diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 0000000..4c18324 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,46 @@ +{ + "name": "js", + //https://containers.dev/templates or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile + "image": "mcr.microsoft.com/devcontainers/typescript-node", + // https://containers.dev/features + "features": { + "ghcr.io/devcontainers/features/github-cli:1": { + "installDirectlyFromGitHubRelease": true, + "version": "latest" + }, + "ghcr.io/devcontainers/features/node:1": { + "nodeGypDependencies": true, + "version": "lts" + } + }, + + // 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": "pnpm install", + + "customizations": { + "codespaces": { + "openFiles": ["readme.md"] + }, + "vscode": { + "extensions": [ + "dbaeumer.vscode-eslint", + "esbenp.prettier-vscode", + "yoavbls.pretty-ts-errors" + ], + "settings": { + "javascript.format.enable": false, + "typescript.format.enable": false, + "editor.formatOnPaste": true, + "editor.formatOnType": true, + "editor.formatOnSave": true, + "editor.defaultFormatter": "esbenp.prettier-vscode", + "javascript.preferences.importModuleSpecifierEnding": "js", + "typescript.preferences.importModuleSpecifierEnding": "auto", + "typescript.enablePromptUseWorkspaceTsdk": true + } + } + } +} diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000..e016438 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1 @@ +* @hugomrdias diff --git a/.github/CODE_OF_CONDUCT.md b/.github/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..ced9997 --- /dev/null +++ b/.github/CODE_OF_CONDUCT.md @@ -0,0 +1,108 @@ +# Code of Conduct + +**TL;DR Be kind, inclusive, and considerate.** + +In the interest of fostering an open, inclusive, and welcoming environment, all +members, contributors, and maintainers interacting within our online community +(including Discord, Discourse, etc.), on affiliated projects and repositories +(including issues, pull requests, and discussions on Github), and/or involved +with associated events pledge to accept and observe the following Code of +Conduct. + +As members, contributors, and maintainers, we pledge to make participation in +our projects and community a harassment-free experience, ensuring a safe +environment for all, regardless of background, gender, gender identity and +expression, age, sexual orientation, disability, physical appearance, body size, +race, ethnicity, religion (or lack thereof), or any other dimension of +diversity. + +Sexual language and imagery will not be accepted in any way. Be kind to others. +Do not insult or put down people within the community. Behave professionally. +Remember that harassment and sexist, racist, or exclusionary jokes are not +appropriate in any form. Participants violating these rules may be sanctioned or +expelled from the community and related projects. + +## Spelling it out + +Harassment includes offensive verbal comments or actions related to or involving + +- background +- gender +- gender identity and expression +- age +- sexual orientation +- disability +- physical appearance +- body size +- race +- ethnicity +- religion (or lack thereof) +- economic status +- geographic location +- technology choices +- sexual imagery +- deliberate intimidation +- violence and threats of violence +- stalking +- doxing +- inappropriate or unwelcome physical contact in public spaces +- unwelcomed sexual attention +- influencing unacceptable behavior +- any other dimension of diversity + +## Our Responsibilities + +Maintainers of the community and associated projects are not only subject to the +anti-harassment policy, but also responsible for executing the policy, +moderating related forums, and for taking appropriate and fair corrective action +in response to any instances of unacceptable behavior that breach the policy. + +Maintainers have the right to remove and reject comments, threads, commits, +code, documentation, pull requests, issues, and contributions not aligned with +this Code of Conduct. + +## Scope + +This Code of Conduct applies within all project and community spaces, as well as +in any public spaces where an individual representing the community is involved. +This covers + +- Interactions on the Github repository, including discussions, issues, pull + requests, commits, and wikis +- Interactions on any affiliated Discord, Slack, IRC, or related online + communities and forums like Discourse, etc. +- Any official project emails and social media posts +- Individuals representing the community at public events like meetups, talks, + and presentations + +## Enforcement + +All instances of abusive, harassing, or otherwise unacceptable behavior should +be reported by contacting the project and community maintainers at +[support@fission.codes][support-email]. All complaints will be reviewed and +investigated and will result in a response that is deemed necessary and +appropriate to the circumstances. + +Maintainers of the community and associated projects are obligated to maintain +confidentiality with regard to the reporter of an incident. Further details of +specific enforcement policies may be posted separately. + +Anyone asked to stop abusive, harassing, or otherwise unacceptable behavior are +expected to comply immediately and accept the response decided on by the +maintainers of the community and associated projects. + +## Need help? + +If you are experiencing harassment, witness an incident or have concerns about +content please contact us at [support@fission.codes][support-email]. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant, v2.1][contributor-cov], +among other sources like [!!con’s Code of Conduct][!!con] and +[Mozilla’s Community Participation Guidelines][mozilla]. + +[!!con]: https://bangbangcon.com/conduct.html +[contributor-cov]: https://www.contributor-covenant.org/version/2/1/code_of_conduct/ +[mozilla]: https://www.mozilla.org/en-US/about/governance/policies/participation/ +[support-email]: mailto:support@fission.codes diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md new file mode 100644 index 0000000..d91095a --- /dev/null +++ b/.github/CONTRIBUTING.md @@ -0,0 +1,134 @@ +# Contributing to Template + +Thank you for helping to improve the project! We are so happy that you are contributing! 💖 + +You can contribute to the project at any level. Whether you are new to web development or have been at it for ages doesn't matter. We can use your help! + +**No contribution is too small, and all contributions are valued.** + +This guide will help you to get started. It includes many details, but don't let that turn you away. Consider this a map to help you navigate the process, and please reach out to us with any questions and concerns in the our public [channel] . + +## Conduct + +Please review our [Code of Conduct] which describes the behavior we expect from all contributors. Please be kind, inclusive, and considerate when interacting with contributors and maintainers. + +## Contributing in issues + +You can contribute by [opening an issue][issue] to request a feature or report a bug. We also welcome comments on an issue, bug reproductions, and pull requests if you see how to address an issue. + +If you are still determining the details of a feature request, you can start with a [discussion][discussions] where we can informally discuss what you have on your mind. + +**Anyone can participate in any stage of contribution**. We urge you to +join in the discussion around bugs and comment on pull requests. + +### Asking for help + +If you have reviewed our [documentation][docs] and still have questions or are having problems, ask for help in the our public [channel] or [start a discussion][discussions]. + +### Submitting a bug report + +We provide a template to give you a starting point when submitting a bug report. Please fill this template in with all relevant information, but feel free to delete any sections that do not apply. + +The most important information is describing the problem and how it impacts you. We also invite you to propose a solution, which could be a description of expected behavior. + +We very much appreciate it if you could include a [short, self-contained, correct example][sscce] that demonstrates the issue. + +## Development + +If you have been assigned to fix an issue or develop a new feature, please follow these steps to get started: + +- Fork this repository. +- Install dependencies by running `pnpm install`. + - We use [pnpm](https://pnpm.io/) for package management. + - Make sure you have Node LTS installed in your system. +- Optionally run `npx simple-git-hooks` to install git hooks for linting and formatting. +- Implement your changes to files in the `src/` directory and corresponding test files in the `/test` directory. +- Git stage your required changes and commit (see below commit [guidelines](#how-should-i-write-my-commits)). +- Submit PR for review + +### Codespaces + +This repo has a dev container configuration to enable one click setup of a development environment using Codespaces. + +[![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)][codespaces] + +## Pull requests + +Pull requests are how we make changes. + +Even tiny pull requests to fix typos or improve comments are welcome. Before submitting a significant PR, it is usually best to start by [opening an issue][issue] or [starting a discusssion][discussions]. Taking one of these steps increases the likelihood that your PR will be merged. + +All commits must be signed before a pull request will be accepted. See the GitHub [signing commits][signing] and [telling git about your signing key][telling-git] documentation. We recommend generating a new SSH key for signing if you are setting up signing for the first time. + +We squash and merge all PRs. Orderly, well-written commits will help us during review, but we don't require a pristine commit history. + +### Tests + +If your change alters existing code, please run the test suites: + +```sh +pnpm run lint +pnpm run test + +# node tests can use native watch mode +pnpm test:node -n watch + +# browser tests can enable watch +pnpm test:browser --watch +``` + +If you are adding a new feature, please add tests that prove the code works correctly and reference them when you submit the pull request. + +### Opening a pull request + +We provide a [pull request template][template] to give you a starting point when creating a pull request. Please fill this template in, but feel free to delete any sections that do not apply or that you are unsure about. + +### Discuss and update + +You will likely receive feedback or requests for changes to your pull request. Don't be discouraged! Pull request reviews help us all to collaborate and produce better code. Some reviewers may sign off immediately, and others may have more detailed comments and feedback. It's all part of the process of evaluating whether the changes are correct and necessary. + +**Once the PR is open, do not rebase the commits.** Add more commits to address feedback. We will squash and merge all contributions, and we may clean up the history recorded in the final commit. + +### Merging + +The primary goals for a pull request are to improve the codebase and for the contributor to succeed. Some pull requests may not be merged at the end of the day, but that does not indicate failure. If your pull request is not merged, please know that your efforts are appreciated and will have an impact on how we think about the codebase in the long run. + +## Release Process + +[Release Please](https://github.com/googleapis/release-please) automates CHANGELOG generation, the creation of GitHub releases, +and version bumps for our packages. Release Please does so by parsing your +git history, looking for [Conventional Commit messages](https://www.conventionalcommits.org/), +and creating release PRs. + +### What's a Release PR? + +Rather than continuously releasing what's landed to our default branch, release-please maintains Release PRs: + +These Release PRs are kept up-to-date as additional work is merged. When we're ready to tag a release, we simply merge the release PR. + +When the release PR is merged the release job is triggered to create a new tag, a new github release and run other package specific jobs. Only merge ONE release PR at a time and wait for CI to finish before merging another. + +Release PRs are created individually for each package in the mono repo. + +### How should I write my commits? + +Release Please assumes you are using [Conventional Commit messages](https://www.conventionalcommits.org/). + +The most important prefixes you should have in mind are: + +- `fix:` which represents bug fixes, and correlates to a [SemVer](https://semver.org/) + patch. +- `feat:` which represents a new feature, and correlates to a SemVer minor. +- `feat!:`, or `fix!:`, `refactor!:`, etc., which represent a breaking change + (indicated by the `!`) and will result in a SemVer major. + +[channel]: https://discord.gg/zAQBDEq +[codespaces]: https://codespaces.new/fission-codes/stack +[discussions]: https://github.com/fission-codes/stack/discussions +[issue]: https://github.com/fission-codes/stack/issues +[docs]: https://fission-codes.github.io/stack/ +[sscce]: http://www.sscce.org/ +[signing]: https://docs.github.com/en/authentication/managing-commit-signature-verification/signing-commits +[telling-git]: https://docs.github.com/en/authentication/managing-commit-signature-verification/telling-git-about-your-signing-key +[template]: PULL_REQUEST_TEMPLATE.md +[Code of Conduct]: CODE_OF_CONDUCT.md diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000..e9d48fa --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,24 @@ +--- +name: Bug report +about: Create a report to help us improve +title: '[bug]: ' +labels: bug, help wanted +assignees: 'hugomrdias' +--- + +**Describe the bug** +A clear and concise description of what the bug is. + +**To Reproduce** +Steps to reproduce the behavior: + +1. Go to '...' +2. Click on '....' +3. Scroll down to '....' +4. See error + +**Expected behavior** +A clear and concise description of what you expected to happen. + +**Additional context** +Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000..0dbec0d --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,19 @@ +--- +name: Feature request +about: Suggest an idea for this project +title: '[feature]: ' +labels: enhancement, help wanted +assignees: 'hugomrdias' +--- + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +Add any other context or screenshots about the feature request here. diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..311a193 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,18 @@ +# Description + +Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. List any dependencies that are required for this change. + +## Link to issue + +Please add a link to any relevant issues/tickets + +## Type of change + +Please delete options that are not relevant. + +- [ ] Bug fix (non-breaking change that fixes an issue) +- [ ] New feature (non-breaking change that adds functionality) +- [ ] Refactor (non-breaking change that updates existing functionality) +- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) +- [ ] This change requires a documentation update +- [ ] Comments have been added/updated diff --git a/.github/SECURITY.md b/.github/SECURITY.md new file mode 100644 index 0000000..4157aeb --- /dev/null +++ b/.github/SECURITY.md @@ -0,0 +1,17 @@ +# Security Policy + +## Reporting a Vulnerability + +The project team welcomes security reports and is committed to providing prompt attention to security issues. + +Security issues **SHOULD** be reported privately via [email]. + +Security issues **SHOULD NOT** be reported via the public GitHub Issue tracker. + +## Security advisories + +The project team is committed to transparency in the security issue disclosure +process. Security advisories will be published through Github [Security Advisories][sec-advisories]. + +[email]: mailto:support@fission.codes +[sec-advisories]: https://github.com/fission-codes/stack/security/advisories diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..38e5450 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,12 @@ +version: 2 +updates: + - package-ecosystem: github-actions + directory: / + open-pull-requests-limit: 5 + schedule: + interval: monthly + - package-ecosystem: npm + directory: / + open-pull-requests-limit: 5 + schedule: + interval: weekly diff --git a/.github/release-please-config.json b/.github/release-please-config.json new file mode 100644 index 0000000..dc51bba --- /dev/null +++ b/.github/release-please-config.json @@ -0,0 +1,7 @@ +{ + "separate-pull-requests": true, + "packages": { + "packages/package1": {}, + "packages/package2": {} + } +} diff --git a/.github/release-please-manifest.json b/.github/release-please-manifest.json new file mode 100644 index 0000000..7d06962 --- /dev/null +++ b/.github/release-please-manifest.json @@ -0,0 +1,4 @@ +{ + "packages/package1": "0.0.1", + "packages/package2": "0.0.2" +} diff --git a/.github/workflows/package1.yml b/.github/workflows/package1.yml new file mode 100644 index 0000000..00ea837 --- /dev/null +++ b/.github/workflows/package1.yml @@ -0,0 +1,33 @@ +name: Package1 +env: + CI: true + FORCE_COLOR: 1 +on: + push: + branches: [main] + paths: + - 'packages/package1/**' + - .github/workflows/package1.yml + - pnpm-lock.yaml + pull_request: + paths: + - 'packages/package1/**' + - .github/workflows/package1.yml + - pnpm-lock.yaml +jobs: + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: pnpm/action-setup@v2 + with: + version: latest + - uses: actions/setup-node@v4 + with: + node-version: lts/* + cache: pnpm + - run: pnpm install + - run: pnpm run build + - run: pnpm -r --filter package1 run lint + - run: pnpm -r --filter package1 run test + - run: pnpm -r --filter package1 exec depcheck diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..621ddae --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,61 @@ +name: Release + +permissions: + contents: write + pull-requests: write + pages: write + id-token: write + +env: + CI: true + FORCE_COLOR: 1 +on: + push: + branches: [main] +jobs: + release: + runs-on: ubuntu-latest + outputs: + paths_released: ${{ steps.release.outputs.paths_released }} + steps: + - uses: google-github-actions/release-please-action@v4 + id: release + with: + # needs to be personal token so release PRs can run workflows + token: ${{ secrets.GH_TOKEN }} + command: manifest + config-file: .github/release-please-config.json + manifest-file: .github/release-please-manifest.json + default-branch: main + release-type: node + npm: + needs: release + if: | + contains(fromJson(needs.release.outputs.paths_released), 'packages/package1') || + contains(fromJson(needs.release.outputs.paths_released), 'packages/package2') + runs-on: ubuntu-latest + permissions: + contents: read + id-token: write + steps: + - uses: actions/checkout@v4 + - uses: pnpm/action-setup@v2 + with: + version: latest + - uses: actions/setup-node@v4 + with: + node-version: lts/* + registry-url: 'https://registry.npmjs.org' + cache: pnpm + - run: pnpm install + - run: pnpm run lint + - run: pnpm run build + - run: pnpm -r publish --access=public + env: + NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}} + docs: + needs: release + if: | + contains(fromJson(needs.release.outputs.paths_released), 'packages/package1') || + contains(fromJson(needs.release.outputs.paths_released), 'packages/package2') + uses: ./.github/workflows/reusable-docs.yml diff --git a/.github/workflows/reusable-docs.yml b/.github/workflows/reusable-docs.yml new file mode 100644 index 0000000..e843066 --- /dev/null +++ b/.github/workflows/reusable-docs.yml @@ -0,0 +1,40 @@ +name: Reusable Deploy Docs +on: + workflow_call: + +# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued. +# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete. +concurrency: + group: pages + cancel-in-progress: false +permissions: + contents: read + pages: write + id-token: write + +jobs: + deploy-docs: + runs-on: ubuntu-latest + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + steps: + - uses: actions/checkout@v4 + - uses: pnpm/action-setup@v2 + with: + version: latest + - uses: actions/setup-node@v4 + with: + node-version: lts/* + registry-url: 'https://registry.npmjs.org' + cache: pnpm + - run: pnpm install + - run: pnpm run lint + - run: pnpm run docs + - uses: actions/configure-pages@v4 + - uses: actions/upload-pages-artifact@v2 + with: + path: ./docs + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v3 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0e17055 --- /dev/null +++ b/.gitignore @@ -0,0 +1,32 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +# Build tools and env +node_modules +dist +dist-ssr +*.local +dev-dist +kv-data +.env + +# Editor directories and files +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +!.vscode/*.code-snippets +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..f8ee548 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,8 @@ +{ + "recommendations": [ + "dbaeumer.vscode-eslint", + "esbenp.prettier-vscode", + "github.vscode-pull-request-github", + "yoavbls.pretty-ts-errors" + ] +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..4bb760e --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,27 @@ +{ + "editor.defaultFormatter": "esbenp.prettier-vscode", + "editor.formatOnSave": true, + "editor.codeActionsOnSave": { + "source.fixAll.eslint": true, + "source.organizeImports": false + }, + "eslint.validate": [ + "javascript", + "javascriptreact", + "typescript", + "typescriptreact", + "html", + "nunjucks", + "json", + "jsonc", + "json5", + "markdown", + "yaml", + "github-actions-workflow" + ], + "javascript.format.enable": false, + "javascript.preferences.importModuleSpecifierEnding": "js", + "typescript.format.enable": false, + "typescript.preferences.importModuleSpecifierEnding": "auto", + "typescript.enablePromptUseWorkspaceTsdk": true +} diff --git a/LICENSE-APACHE b/LICENSE-APACHE new file mode 100644 index 0000000..18f9394 --- /dev/null +++ b/LICENSE-APACHE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright 2023 Filecoin Project + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/LICENSE-MIT b/LICENSE-MIT new file mode 100644 index 0000000..cafeb1d --- /dev/null +++ b/LICENSE-MIT @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) Fission + +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/README.md b/README.md new file mode 100644 index 0000000..3c07f9d --- /dev/null +++ b/README.md @@ -0,0 +1,60 @@ +__⚠️ Work in progress!__ + +A layer around the `wnfs` package that provides a `FileSystem` class, transactions, a root tree and some other essentials. + +## Features + +- A file system class that allows for an easy-to-use mutable API. +- A transaction system, rewinding the state if an error occurs. +- Creates a private forest automatically with a RSA modules using the Web Crypto API (supported on multiple platforms) + +## Packages + +- [package1](https://github.com/fission-codes/js-template/tree/master/packages/package1) - description +- [package2](https://github.com/fission-codes/js-template/tree/master/packages/package2) - description + +## Examples + +- [`demo`](https://github.com/fission-codes/js-template/tree/master/examples/demo) - description + +### Checkout examples + +You can use Codesandbox and start hacking right away. + +To clone it locally: + +```bash +npx tiged fission-codes/js-template/examples/demo demo +cd demo +pnpm install +pnpm dev +``` + +You can try any of the examples by replacing `demo` with the name of the example you want to try. + +## Contributing + +Read contributing guidelines [here](.github/CONTRIBUTING.md). + +[![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/hd-template/examples) + +## License + +This project is licensed under either of + +- Apache License, Version 2.0, ([LICENSE-APACHE](./LICENSE-APACHE) or + [http://www.apache.org/licenses/LICENSE-2.0][apache]) +- MIT license ([LICENSE-MIT](./LICENSE-MIT) or + [http://opensource.org/licenses/MIT][mit]) + +at your option. + +### Contribution + +Unless you explicitly state otherwise, any contribution intentionally +submitted for inclusion in the work by you, as defined in the Apache-2.0 +license, shall be dual licensed as above, without any additional terms or +conditions. + +[apache]: https://www.apache.org/licenses/LICENSE-2.0 +[mit]: http://opensource.org/licenses/MIT diff --git a/assets/logo.png b/assets/logo.png new file mode 100644 index 0000000..f86c0ff Binary files /dev/null and b/assets/logo.png differ diff --git a/examples/demo/.codesandbox/tasks.json b/examples/demo/.codesandbox/tasks.json new file mode 100644 index 0000000..4b697fc --- /dev/null +++ b/examples/demo/.codesandbox/tasks.json @@ -0,0 +1,19 @@ +{ + "$schema": "https://codesandbox.io/schemas/tasks.json", + "setupTasks": ["pnpm install"], + "tasks": { + "install-dependencies": { + "name": "Install Dependencies", + "command": "pnpm install", + "restartOn": { + "files": ["package.json", "pnpm-lock.yaml"], + "branch": true + } + }, + "dev": { + "name": "Run Dev Server", + "command": "pnpm dev", + "runAtStart": true + } + } +} diff --git a/examples/demo/README.md b/examples/demo/README.md new file mode 100644 index 0000000..e4a7d8d --- /dev/null +++ b/examples/demo/README.md @@ -0,0 +1,10 @@ +# demo + +## Run locally + +From this directory: + +```bash +pnpm install +pnpm dev +``` diff --git a/examples/demo/index.html b/examples/demo/index.html new file mode 100644 index 0000000..0ea846b --- /dev/null +++ b/examples/demo/index.html @@ -0,0 +1,15 @@ + + + + + + + + Demo + + + +

Hello

+ + + \ No newline at end of file diff --git a/examples/demo/package.json b/examples/demo/package.json new file mode 100644 index 0000000..5c9649d --- /dev/null +++ b/examples/demo/package.json @@ -0,0 +1,34 @@ +{ + "name": "demo", + "type": "module", + "version": "1.0.0", + "private": true, + "description": "", + "author": "Hugo Dias (hugodias.me)", + "license": "MIT", + "keywords": [], + "main": "src/main.jsx", + "scripts": { + "lint": "tsc --build && eslint . && prettier --check '**/*.{js,jsx,ts,tsx,yml,json,css}' --ignore-path ../../.gitignore", + "build": "vite build --force", + "dev": "vite --force", + "serve": "vite preview --port 3000" + }, + "dependencies": { + "package1": "*" + }, + "devDependencies": { + "@babel/core": "^7.23.5", + "@types/node": "^20.10.4", + "typescript": "5.2.2", + "vite": "^5.0.7" + }, + "eslintConfig": { + "extends": [ + "@fission-codes" + ], + "ignorePatterns": [ + "dist" + ] + } +} diff --git a/examples/demo/src/main.ts b/examples/demo/src/main.ts new file mode 100644 index 0000000..a9e1933 --- /dev/null +++ b/examples/demo/src/main.ts @@ -0,0 +1,4 @@ +import { randomBytes } from 'package1' + +// eslint-disable-next-line no-console +console.log(randomBytes(10)) diff --git a/examples/demo/tsconfig.json b/examples/demo/tsconfig.json new file mode 100644 index 0000000..04257e0 --- /dev/null +++ b/examples/demo/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "types": ["vite/client"], + "outDir": "dist", + "noEmit": true + }, + "include": ["src", "test"], + "exclude": ["node_modules", "dist", "out"] +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..cb58484 --- /dev/null +++ b/package.json @@ -0,0 +1,50 @@ +{ + "name": "js-template", + "version": "0.0.0", + "private": true, + "workspaces": [ + "packages/*", + "examples/*" + ], + "packageManager": "pnpm@8.6.1", + "engines": { + "node": ">=18" + }, + "scripts": { + "format": "prettier --write '**/*.{js,ts,jsx,tsx,yml,json,css}' --ignore-path .gitignore", + "format:check": "prettier --check '**/*.{js,ts,jsx,tsx,yml,json,css}' --ignore-path .gitignore", + "clean": "rm -rf docs node_modules pnpm-lock.yaml packages/*/{pnpm-lock.yaml,coverage,.nyc_output,dist,node_modules} packages/*/{pnpm-lock.yaml,coverage,.nyc_output,dist,node_modules}", + "lint": "pnpm -r --if-present run lint", + "test": "pnpm -r --if-present run test", + "check": "pnpm -r --if-present run check", + "build": "pnpm -r --if-present run build", + "docs": "typedoc --out docs --plugin typedoc-plugin-missing-exports --plugin typedoc-plugin-zod" + }, + "devDependencies": { + "@fission-codes/eslint-config": "^0.0.3", + "depcheck": "^1.4.7", + "lint-staged": "^15.1.0", + "prettier": "3.1.1", + "simple-git-hooks": "^2.9.0", + "typedoc": "^0.25.4", + "typedoc-plugin-missing-exports": "^2.1.0", + "typedoc-plugin-zod": "^1.1.0", + "typescript": "5.2.2" + }, + "simple-git-hooks": { + "pre-commit": "npx lint-staged" + }, + "lint-staged": { + "*.{js,ts,jsx,tsx,yml,json,css}": "prettier --write", + "*": "eslint --fix" + }, + "prettier": "@fission-codes/eslint-config/prettier.config.js", + "eslintConfig": { + "extends": [ + "@fission-codes" + ], + "ignorePatterns": [ + "docs" + ] + } +} diff --git a/packages/nest/.mocharc.json b/packages/nest/.mocharc.json new file mode 100644 index 0000000..e8ecf2c --- /dev/null +++ b/packages/nest/.mocharc.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://json.schemastore.org/mocharc.json", + "require": "tsx" +} diff --git a/packages/nest/package.json b/packages/nest/package.json new file mode 100644 index 0000000..7d83fd5 --- /dev/null +++ b/packages/nest/package.json @@ -0,0 +1,97 @@ +{ + "name": "package1", + "type": "module", + "version": "0.0.1", + "description": "Example package description.", + "author": "Hugo Dias (hugodias.me)", + "license": "(Apache-2.0 AND MIT)", + "homepage": "https://github.com/fission-codes/js-template/tree/main/packages/package1", + "repository": { + "url": "fission-codes/js-template", + "directory": "packages/package1" + }, + "exports": { + ".": { + "types": "./dist/src/index.d.ts", + "default": "./src/index.js" + }, + "./crypto": { + "types": "./dist/src/crypto.d.ts", + "browser": "./src/crypto-browser.js", + "default": "./src/crypto.js" + } + }, + "main": "src/index.js", + "types": "dist/src/index.d.ts", + "browser": { + "crypto": false, + "./src/crypto.js": "./src/crypto-browser.js" + }, + "typesVersions": { + "*": { + "module1": ["dist/src/crypto"] + } + }, + "files": ["src", "dist/src/*.d.ts", "dist/src/*.d.ts.map"], + "scripts": { + "lint": "tsc --build && eslint . && prettier --check '**/*.{js,ts,yml,json}' --ignore-path ../../.gitignore", + "build": "tsc --build", + "test": "pnpm run test:node && pnpm run test:browser", + "test:node": "mocha 'test/**/!(*.browser).test.ts' --bail --timeout 30000", + "test:browser": "playwright-test 'test/**/!(*.node).test.ts' --timeout 30000" + }, + "dependencies": { + "@ipld/dag-cbor": "^9.0.6", + "@ipld/dag-pb": "^4.0.6", + "compare-versions": "^6.1.0", + "debounce": "^2.0.0", + "emittery": "^1.0.1", + "interface-blockstore": "^5.2.7", + "ipfs-unixfs": "^11.1.0", + "ipfs-unixfs-exporter": "^13.2.2", + "ipfs-unixfs-importer": "^15.2.1", + "iso-base": "^2.0.1", + "it-all": "^3.0.4", + "multiformats": "^12.1.3", + "uint8arrays": "^5.0.0", + "wnfs": "^0.1.27" + }, + "devDependencies": { + "@types/assert": "^1.5.9", + "@types/debounce-promise": "^3.1.9", + "@types/mocha": "^10.0.6", + "@types/node": "^20.10.4", + "assert": "^2.1.0", + "blockstore-core": "^4.3.8", + "fast-check": "^3.14.0", + "mocha": "^10.2.0", + "playwright-test": "^14.0.0", + "tsx": "^4.6.2" + }, + "publishConfig": { + "provenance": true + }, + "eslintConfig": { + "extends": ["@fission-codes"], + "reportUnusedDisableDirectives": false, + "env": { + "mocha": true + }, + "ignorePatterns": ["dist"], + "rules": { + "@typescript-eslint/no-unused-vars": [ + "error", + { + "argsIgnorePattern": "^_", + "destructuredArrayIgnorePattern": "^_", + "varsIgnorePattern": "^_" + } + ], + "unicorn/no-array-reduce": ["off"] + } + }, + "depcheck": { + "specials": ["bin"], + "ignores": ["@types/*", "assert"] + } +} diff --git a/packages/nest/readme.md b/packages/nest/readme.md new file mode 100644 index 0000000..f17148c --- /dev/null +++ b/packages/nest/readme.md @@ -0,0 +1,52 @@ +# Package 1 + +[![npm (scoped)](https://img.shields.io/npm/v/%40fission-codes/eslint-config)](https://www.npmjs.com/package/@fission-codes/eslint-config) +[![GitHub Workflow Status (with event)](https://img.shields.io/github/actions/workflow/status/fission-codes/stack/eslint-config.yml)](https://github.com/fission-codes/stack/actions/workflows/eslint-config.yml) +[![Built by FISSION](https://img.shields.io/badge/built_by-⌘_Fission-purple.svg)](https://fission.codes) +[![Discord](https://img.shields.io/discord/478735028319158273?&color=mediumslateblue)](https://discord.gg/zAQBDEq) +[![Discourse users]()](https://talk.fission.codes) + +Fission eslint, ts and prettier config. + +## Installation + +```bash +pnpm install package1 +``` + +## Usage + +```js +import { module } from 'package1' +``` + +## Docs + +Check + +## Contributing + +Read contributing guidelines [here](../../.github/CONTRIBUTING.md). + +[![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/hugomrdias/hd-template) + +## License + +This project is licensed under either of + +- Apache License, Version 2.0, ([LICENSE-APACHE](../../LICENSE-APACHE) or + [http://www.apache.org/licenses/LICENSE-2.0][apache]) +- MIT license ([LICENSE-MIT](../../LICENSE-MIT) or + [http://opensource.org/licenses/MIT][mit]) + +at your option. + +### Contribution + +Unless you explicitly state otherwise, any contribution intentionally +submitted for inclusion in the work by you, as defined in the Apache-2.0 +license, shall be dual licensed as above, without any additional terms or +conditions. + +[apache]: https://www.apache.org/licenses/LICENSE-2.0 +[mit]: http://opensource.org/licenses/MIT diff --git a/packages/nest/src/app-info.ts b/packages/nest/src/app-info.ts new file mode 100644 index 0000000..5bfe74e --- /dev/null +++ b/packages/nest/src/app-info.ts @@ -0,0 +1,9 @@ +/** + * Information about your app. + * + * @group Configuration + */ +export interface AppInfo { + name: string + creator: string +} diff --git a/packages/nest/src/class.ts b/packages/nest/src/class.ts new file mode 100644 index 0000000..4d475f7 --- /dev/null +++ b/packages/nest/src/class.ts @@ -0,0 +1,757 @@ +import type { Blockstore } from 'interface-blockstore' +import type { PublicDirectory, PublicFile } from 'wnfs' + +import { CID } from 'multiformats/cid' +import { AccessKey, PrivateDirectory, PrivateFile, PrivateNode } from 'wnfs' + +import debounce from 'debounce' +import Emittery, { + type EmitteryOncePromise, + type OmnipresentEventData, + type UnsubscribeFunction, +} from 'emittery' + +import type { + AnySupportedDataType, + DataForType, + DataRootChange, + DataType, + DirectoryItem, + DirectoryItemWithKind, + FileSystemChange, + MutationOptions, + MutationResult, + PrivateMutationResult, + PublicMutationResult, +} from './types.js' + +import type { + MountedPrivateNode, + MountedPrivateNodes, +} from './types/internal.js' + +import type { Events, Listener } from './events.js' + +import * as Path from './path.js' +import * as Rng from './rng.js' +import * as Store from './store.js' + +import type { RootTree } from './root-tree.js' +import type { + Partition, + Partitioned, + PartitionedNonEmpty, + Private, + Public, +} from './path.js' + +import { searchLatest } from './common.js' +import { partition as determinePartition, findPrivateNode } from './mounts.js' +import { TransactionContext } from './transaction.js' +import { BasicRootTree } from './root-tree/basic.js' + +// OPTIONS + +export interface Options { + blockstore: Blockstore + rootTreeClass?: typeof RootTree + settleTimeBeforePublish?: number +} + +export class FileSystem { + readonly #blockstore: Blockstore + readonly #debouncedDataRootUpdate: debounce.DebouncedFunction + readonly #eventEmitter: Emittery + readonly #rng: Rng.Rng + + #privateNodes: MountedPrivateNodes = {} + #rootTree: RootTree + + /** @hidden */ + constructor( + blockstore: Blockstore, + rootTree: RootTree, + settleTimeBeforePublish: number + ) { + this.#blockstore = blockstore + this.#eventEmitter = new Emittery() + this.#rng = Rng.makeRngInterface() + this.#rootTree = rootTree + + this.#debouncedDataRootUpdate = debounce( + async (...dataRoots: CID[]): Promise => { + const dataRoot = dataRoots.at(-1) + if (dataRoot !== undefined) { + await this.#eventEmitter.emit('publish', { dataRoot }) + } + }, + settleTimeBeforePublish + ) + } + + // INITIALISATION + // -------------- + + /** + * Creates a file system with an empty public tree & an empty private tree at the root. + */ + static async create(opts: Options): Promise { + const { blockstore, rootTreeClass, settleTimeBeforePublish } = opts + const rootTree = await (rootTreeClass ?? BasicRootTree).create(blockstore) + + return new FileSystem(blockstore, rootTree, settleTimeBeforePublish ?? 2500) + } + + /** + * Loads an existing file system from a CID. + */ + static async fromCID(cid: CID, opts: Options): Promise { + const { blockstore, rootTreeClass, settleTimeBeforePublish } = opts + const rootTree = await (rootTreeClass ?? BasicRootTree).fromCID( + blockstore, + cid + ) + + return new FileSystem(blockstore, rootTree, settleTimeBeforePublish ?? 2500) + } + + // EVENTS + // ------ + + /** + * {@inheritDoc events.EmitterClass.on} + * + * @group Events + */ + on = ( + eventName: Name, + listener: Listener + ): UnsubscribeFunction => this.#eventEmitter.on(eventName, listener) + + /** + * {@inheritDoc events.EmitterClass.onAny} + * + * @group Events + */ + onAny = ( + listener: ( + eventName: keyof Events, + eventData: Events[keyof Events] + ) => void | Promise + ): UnsubscribeFunction => this.#eventEmitter.onAny(listener) + + /** + * {@inheritDoc events.EmitterClass.off} + * + * @group Events + */ + off = ( + eventName: Name, + listener: Listener + ): void => { + this.#eventEmitter.off(eventName, listener) + } + + /** + * {@inheritDoc events.EmitterClass.offAny} + * + * @group Events + */ + offAny = ( + listener: ( + eventName: keyof Events, + eventData: Events[keyof Events] + ) => void | Promise + ): void => { + this.#eventEmitter.offAny(listener) + } + + /** + * {@inheritDoc events.EmitterClass.once} + * + * @group Events + */ + once = ( + eventName: Name + ): EmitteryOncePromise<(Events & OmnipresentEventData)[Name]> => + this.#eventEmitter.once(eventName) + + /** + * {@inheritDoc events.EmitterClass.anyEvent} + * + * @group Events + */ + anyEvent = (): AsyncIterable<[keyof Events, Events[keyof Events]]> => + this.#eventEmitter.anyEvent() + + /** + * {@inheritDoc events.EmitterClass.events} + * + * @group Events + */ + events = ( + eventName: Name + ): AsyncIterable => this.#eventEmitter.events(eventName) + + // MOUNTS + // ------ + + /** + * Mount a private node onto the file system. + * + * @group Mounting + */ + async mountPrivateNode(node: { + path: Path.Distinctive + capsuleKey?: Uint8Array + }): Promise<{ + path: Path.Distinctive + capsuleKey: Uint8Array + }> { + const mounts = await this.mountPrivateNodes([node]) + return mounts[0] + } + + /** + * Mount private nodes onto the file system. + * + * @group Mounting + */ + async mountPrivateNodes( + nodes: Array<{ + path: Path.Distinctive + capsuleKey?: Uint8Array + }> + ): Promise< + Array<{ + path: Path.Distinctive + capsuleKey: Uint8Array + }> + > { + const newNodes = await Promise.all( + nodes.map( + async ({ path, capsuleKey }): Promise<[string, MountedPrivateNode]> => { + let privateNode: PrivateNode + + if (capsuleKey === null || capsuleKey === undefined) { + privateNode = Path.isFile(path) + ? new PrivateFile( + this.#rootTree.privateForest().emptyName(), + new Date(), + this.#rng + ).asNode() + : new PrivateDirectory( + this.#rootTree.privateForest().emptyName(), + new Date(), + this.#rng + ).asNode() + } else { + const accessKey = AccessKey.fromBytes(capsuleKey) + privateNode = await PrivateNode.load( + accessKey, + this.#rootTree.privateForest(), + Store.wnfs(this.#blockstore) + ) + } + + return [ + // Use absolute paths so that you can retrieve the root: privateNodes["/"] + Path.toPosix(path, { absolute: true }), + { node: privateNode, path }, + ] + } + ) + ) + + this.#privateNodes = { + ...this.#privateNodes, + ...Object.fromEntries(newNodes), + } + + return await Promise.all( + newNodes.map(async ([_, n]: [string, MountedPrivateNode]) => { + const storeResult = await n.node.store( + this.#rootTree.privateForest(), + Store.wnfs(this.#blockstore), + this.#rng + ) + const [accessKey, privateForest] = storeResult + + this.#rootTree = await this.#rootTree.replacePrivateForest( + privateForest, + [ + { + path: Path.withPartition('private', n.path), + type: 'added-or-updated', + }, + ] + ) + + return { + path: n.path, + capsuleKey: accessKey.toBytes(), + } + }) + ) + } + + /** + * Unmount a private node from the file system. + * + * @group Mounting + */ + unmountPrivateNode(path: Path.Distinctive): void { + // eslint-disable-next-line @typescript-eslint/no-dynamic-delete + delete this.#privateNodes[Path.toPosix(path)] + } + + // QUERY + // ----- + + /** @group Querying */ + async contentCID( + path: Path.File> + ): Promise { + return await this.#transactionContext().contentCID(path) + } + + /** @group Querying */ + async capsuleCID( + path: Path.Distinctive> + ): Promise { + return await this.#transactionContext().capsuleCID(path) + } + + /** @group Querying */ + async capsuleKey( + path: Path.Distinctive> + ): Promise { + return await this.#transactionContext().capsuleKey(path) + } + + /** @group Querying */ + async exists( + path: Path.Distinctive> + ): Promise { + return await this.#transactionContext().exists(path) + } + + /** @group Querying */ + async listDirectory( + path: Path.Directory>, + listOptions: { withItemKind: true } + ): Promise + async listDirectory( + path: Path.Directory>, + listOptions: { withItemKind: false } + ): Promise + async listDirectory( + path: Path.Directory> + ): Promise + async listDirectory( + path: Path.Directory>, + listOptions?: { withItemKind: boolean } + ): Promise { + return await this.#transactionContext().listDirectory(path, listOptions) + } + + /** @group Querying */ + ls = this.listDirectory + + /** @group Querying */ + async read( + path: + | Path.File> + | { contentCID: CID } + | { capsuleCID: CID } + | { + capsuleKey: Uint8Array + }, + dataType: D, + options?: { offset: number; length: number } + ): Promise> + async read( + path: + | Path.File> + | { contentCID: CID } + | { capsuleCID: CID } + | { + capsuleKey: Uint8Array + }, + dataType: DataType, + options?: { offset: number; length: number } + ): Promise> { + return await this.#transactionContext().read( + path, + dataType, + options + ) + } + + // MUTATIONS + // --------- + + /** @group Mutating */ + async copy( + from: Path.Distinctive>, + to: Path.File> | Path.Directory>, + mutationOptions?: MutationOptions + ): Promise> + async copy( + from: Path.Distinctive>, + to: + | Path.File> + | Path.Directory>, + mutationOptions: MutationOptions = {} + ): Promise | null> { + return await this.#infusedTransaction( + async (t) => { + await t.copy(from, to) + }, + to, + mutationOptions + ) + } + + /** @group Mutating */ + cp = this.copy + + /** @group Mutating */ + async createDirectory

( + path: Path.Directory>, + mutationOptions?: MutationOptions + ): Promise< + MutationResult

& { path: Path.Directory> } + > + async createDirectory( + path: Path.Directory>, + mutationOptions: MutationOptions = {} + ): Promise< + MutationResult & { + path: Path.Directory> + } + > { + let finalPath = path + + const mutationResult = await this.#infusedTransaction( + async (t) => { + const creationResult = await t.createDirectory(path) + finalPath = creationResult.path + }, + path, + mutationOptions + ) + + return { + ...mutationResult, + path: finalPath, + } + } + + /** @group Mutating */ + async createFile

( + path: Path.File>, + dataType: DataType, + data: DataForType, + mutationOptions?: MutationOptions + ): Promise< + MutationResult

& { path: Path.File> } + > + async createFile( + path: Path.File>, + dataType: DataType, + data: DataForType, + mutationOptions: MutationOptions = {} + ): Promise< + MutationResult & { + path: Path.File> + } + > { + let finalPath = path + + const mutationResult = await this.#infusedTransaction( + async (t) => { + const creationResult = await t.createFile(path, dataType, data) + finalPath = creationResult.path + }, + path, + mutationOptions + ) + + return { + ...mutationResult, + path: finalPath, + } + } + + /** @group Mutating */ + async ensureDirectory

( + path: Path.Directory>, + mutationOptions?: MutationOptions + ): Promise> + async ensureDirectory( + path: Path.Directory>, + mutationOptions: MutationOptions = {} + ): Promise> { + return await this.#infusedTransaction( + async (t) => { + await t.ensureDirectory(path) + }, + path, + mutationOptions + ) + } + + /** @group Mutating */ + mkdir = this.ensureDirectory + + /** @group Mutating */ + async move( + from: Path.Distinctive>, + to: Path.File> | Path.Directory>, + mutationOptions?: MutationOptions + ): Promise> + async move( + from: Path.Distinctive>, + to: + | Path.File> + | Path.Directory>, + mutationOptions: MutationOptions = {} + ): Promise> { + return await this.#infusedTransaction( + async (t) => { + await t.move(from, to) + }, + to, + mutationOptions + ) + } + + /** @group Mutating */ + mv = this.move + + /** @group Mutating */ + async remove( + path: Path.Distinctive>, + mutationOptions: MutationOptions = {} + ): Promise { + const transactionResult = await this.transaction(async (t) => { + await t.remove(path) + }, mutationOptions) + + return { + dataRoot: transactionResult.dataRoot, + } + } + + /** @group Mutating */ + rm = this.remove + + /** @group Mutating */ + async rename

( + path: Path.Distinctive>, + newName: string, + mutationOptions?: MutationOptions + ): Promise> + async rename( + path: Path.Distinctive>, + newName: string, + mutationOptions: MutationOptions = {} + ): Promise> { + return await this.#infusedTransaction( + async (t) => { + await t.rename(path, newName) + }, + Path.replaceTerminus(path, newName), + mutationOptions + ) + } + + /** @group Mutating */ + async write

( + path: Path.File>, + dataType: DataType, + data: DataForType, + mutationOptions?: MutationOptions + ): Promise> + async write( + path: Path.File>, + dataType: DataType, + data: DataForType, + mutationOptions: MutationOptions = {} + ): Promise> { + return await this.#infusedTransaction( + async (t) => { + await t.write(path, dataType, data) + }, + path, + mutationOptions + ) + } + + // TRANSACTIONS + // ------------ + + /** @group Transacting */ + async transaction( + handler: (t: TransactionContext) => Promise, + mutationOptions: MutationOptions = {} + ): Promise<{ + changes: FileSystemChange[] + dataRoot: CID + }> { + const context = this.#transactionContext() + + // Execute handler + await handler(context) + + // Commit transaction + const { changes, privateNodes, rootTree } = + await TransactionContext.commit(context) + + this.#privateNodes = privateNodes + this.#rootTree = rootTree + + // Determine data root + const dataRoot = await this.calculateDataRoot() + + // Emit events + for (const change of changes) { + await this.#eventEmitter.emit('local-change', { + dataRoot, + ...change, + }) + } + + // Publish + if ( + mutationOptions.skipPublish === false || + mutationOptions.skipPublish === undefined + ) { + await this.#publish(dataRoot) + } + + // Fin + return { + changes, + dataRoot, + } + } + + // 🛠️ + + /** @group Misc */ + async calculateDataRoot(): Promise { + return await this.#rootTree.store() + } + + // ㊙️ ▒▒ MUTATIONS + + async #infusedTransaction( + handler: (t: TransactionContext) => Promise, + path: Path.Distinctive>, + mutationOptions?: MutationOptions + ): Promise + async #infusedTransaction( + handler: (t: TransactionContext) => Promise, + path: Path.Distinctive>, + mutationOptions?: MutationOptions + ): Promise + async #infusedTransaction( + handler: (t: TransactionContext) => Promise, + path: Path.Distinctive>, + mutationOptions?: MutationOptions + ): Promise> + async #infusedTransaction( + handler: (t: TransactionContext) => Promise, + path: Path.Distinctive>, + mutationOptions: MutationOptions = {} + ): Promise> { + const transactionResult = await this.transaction(handler, mutationOptions) + const partition = determinePartition(path) + + switch (partition.name) { + case 'public': { + const node = + partition.segments.length === 0 + ? this.#rootTree.publicRoot().asNode() + : await this.#rootTree + .publicRoot() + .getNode(partition.segments, Store.wnfs(this.#blockstore)) + if (node === null || node === undefined) + throw new Error('Failed to find needed public node for infusion') + + const fileOrDir: PublicFile | PublicDirectory = + node.isFile() === true ? node.asFile() : node.asDir() + + const capsuleCID = await fileOrDir + .store(Store.wnfs(this.#blockstore)) + .then((a) => CID.decode(a)) + const contentCID = + node.isFile() === true + ? CID.decode(node.asFile().contentCid()) + : capsuleCID + + return { + dataRoot: transactionResult.dataRoot, + capsuleCID, + contentCID, + } + } + + case 'private': { + const priv = findPrivateNode(partition.path, this.#privateNodes) + const accessKey = priv.node.isFile() + ? await priv.node + .asFile() + .store( + this.#rootTree.privateForest(), + Store.wnfs(this.#blockstore), + this.#rng + ) + : await (priv.remainder.length === 0 + ? Promise.resolve(priv.node) + : priv.node + .asDir() + .getNode( + priv.remainder, + searchLatest(), + this.#rootTree.privateForest(), + Store.wnfs(this.#blockstore) + ) + ) + .then((node) => { + if (node === null || node === undefined) + throw new Error( + 'Failed to find needed private node for infusion' + ) + return node.store( + this.#rootTree.privateForest(), + Store.wnfs(this.#blockstore) + ) + }) + .then(([key]) => key) + + return { + dataRoot: transactionResult.dataRoot, + capsuleKey: accessKey.toBytes(), + } + } + } + } + + #transactionContext(): TransactionContext { + return new TransactionContext( + this.#blockstore, + { ...this.#privateNodes }, + this.#rng, + this.#rootTree.clone() + ) + } + + // ㊙️ ▒▒ PUBLISHING + + async #publish(dataRoot: CID): Promise { + await this.#debouncedDataRootUpdate(dataRoot) + } +} diff --git a/packages/nest/src/common.ts b/packages/nest/src/common.ts new file mode 100644 index 0000000..a2eb251 --- /dev/null +++ b/packages/nest/src/common.ts @@ -0,0 +1,40 @@ +import * as Path from './path.js' + +export function addOrIncreaseNameNumber( + path: Path.Directory> +): Path.Directory> +export function addOrIncreaseNameNumber( + path: Path.File> +): Path.File> +export function addOrIncreaseNameNumber( + path: Path.Distinctive> +): Path.Distinctive> { + const regex = Path.isFile(path) ? /( \((\d+)\))?(\.[^$]+)?$/ : /( \((\d+)\))$/ + const terminus = Path.terminus(path) + const suffixMatches = terminus.match(regex) + + return Path.replaceTerminus( + path, + suffixMatches === null + ? `${terminus} (1)` + : terminus.replace( + regex, + ` (${Number.parseInt(suffixMatches[2] ?? '0', 10) + 1})${ + suffixMatches[3] ?? '' + }` + ) + ) +} + +export function pathSegmentsWithoutPartition( + path: Path.Distinctive> +): Path.Segments { + return Path.unwrap(Path.removePartition(path)) +} + +/** + * Which `searchLatest` value to use for the private file system actions. + */ +export function searchLatest(): boolean { + return true +} diff --git a/packages/nest/src/data.ts b/packages/nest/src/data.ts new file mode 100644 index 0000000..448fd77 --- /dev/null +++ b/packages/nest/src/data.ts @@ -0,0 +1,62 @@ +import type { AnySupportedDataType, DataType } from './types.js' + +/** + * Convert Uint8Array to `Data`. + */ +export function dataFromBytes(dataType: 'bytes', bytes: Uint8Array): Uint8Array +export function dataFromBytes( + dataType: 'json', + bytes: Uint8Array +): Record +export function dataFromBytes(dataType: 'utf8', bytes: Uint8Array): string +export function dataFromBytes( + dataType: DataType, + bytes: Uint8Array +): AnySupportedDataType +export function dataFromBytes( + dataType: DataType, + bytes: Uint8Array +): AnySupportedDataType { + switch (dataType) { + case 'bytes': { + return bytes + } + + case 'json': { + return JSON.parse(new TextDecoder().decode(bytes)) + } + + case 'utf8': { + return new TextDecoder().decode(bytes) + } + } +} + +/** + * Convert `Data` to Uint8Array. + */ +export function dataToBytes(dataType: 'bytes', data: Uint8Array): Uint8Array +export function dataToBytes( + dataType: 'json', + data: Record +): Uint8Array +export function dataToBytes(dataType: 'utf8', data: string): Uint8Array +export function dataToBytes( + dataType: DataType, + data: AnySupportedDataType +): Uint8Array +export function dataToBytes(dataType: DataType, data: any): Uint8Array { + switch (dataType) { + case 'bytes': { + return data + } + + case 'json': { + return new TextEncoder().encode(JSON.stringify(data)) + } + + case 'utf8': { + return new TextEncoder().encode(data) + } + } +} diff --git a/packages/nest/src/data/sample.ts b/packages/nest/src/data/sample.ts new file mode 100644 index 0000000..8e56386 --- /dev/null +++ b/packages/nest/src/data/sample.ts @@ -0,0 +1,20 @@ +import * as Path from '../path.js' +import type { FileSystem } from '../class.js' + +/** + * Adds some sample to the file system. + */ +export async function addSampleData(fs: FileSystem): Promise { + await fs.mkdir(Path.directory('private', 'Apps')) + await fs.mkdir(Path.directory('private', 'Audio')) + await fs.mkdir(Path.directory('private', 'Documents')) + await fs.mkdir(Path.directory('private', 'Photos')) + await fs.mkdir(Path.directory('private', 'Video')) + + // Files + await fs.write( + Path.file('private', 'Welcome.txt'), + 'utf8', + 'Welcome to your personal transportable encrypted file system 👋' + ) +} diff --git a/packages/nest/src/errors.ts b/packages/nest/src/errors.ts new file mode 100644 index 0000000..f2281da --- /dev/null +++ b/packages/nest/src/errors.ts @@ -0,0 +1,20 @@ +import * as Path from './path.js' + +export function throwNoAccess( + path: Path.DistinctivePath, + accessType?: string +): never { + throw new Error( + `Expected to have ${ + typeof accessType === 'string' ? accessType + ' ' : '' + }access to the path '${Path.toPosix(path)}'` + ) +} + +export function throwInvalidPartition( + path: Path.Distinctive +): never { + throw new Error( + `Expected either a public or private path, got '${Path.toPosix(path)}'` + ) +} diff --git a/packages/nest/src/events.ts b/packages/nest/src/events.ts new file mode 100644 index 0000000..915168b --- /dev/null +++ b/packages/nest/src/events.ts @@ -0,0 +1,18 @@ +import type { CID } from 'multiformats/cid' +import type { DistinctivePath, Partition, Partitioned } from './path.js' +import type { MutationType } from './types.js' + +// eslint-disable-next-line @typescript-eslint/consistent-type-definitions +export type Events = { + 'local-change': { + dataRoot: CID + path: DistinctivePath> + type: MutationType + } + publish: { dataRoot: CID } +} + +export type Listener< + EventMap extends Record, + Name extends keyof EventMap, +> = (eventData: EventMap[Name]) => void | Promise diff --git a/packages/nest/src/index.ts b/packages/nest/src/index.ts new file mode 100644 index 0000000..67e7d05 --- /dev/null +++ b/packages/nest/src/index.ts @@ -0,0 +1,5 @@ +export * from './app-info.js' +export * from './class.js' +export * from './root-tree.js' +export * from './root-tree/basic.js' +export * from './types.js' diff --git a/packages/nest/src/mounts.ts b/packages/nest/src/mounts.ts new file mode 100644 index 0000000..4a7abe0 --- /dev/null +++ b/packages/nest/src/mounts.ts @@ -0,0 +1,76 @@ +import * as Path from './path.js' + +import type { Partition, Partitioned, PartitionedNonEmpty } from './path.js' +import type { PartitionDiscovery, PartitionDiscoveryNonEmpty } from './types.js' +import type { + MountedPrivateNode, + MountedPrivateNodes, + PrivateNodeQueryResult, +} from './types/internal.js' + +import { throwInvalidPartition, throwNoAccess } from './errors.js' + +/** + * Find a private node based on a given path. + * Throws if it cannot find a node. + * + * This looks in the `privateNodes` record using the POSIX path as the key. + * A directory will end with a forward slash and a file will not. + * + * Starts from the path `/` and works up to given path, + * which could be a file or directory path. + */ +export function findPrivateNode( + path: Path.Distinctive>, + privateNodes: MountedPrivateNodes +): PrivateNodeQueryResult { + const pathKind = Path.kind(path) + const pathWithoutPartition = Path.removePartition(path) + const pathSegments = Path.unwrap(pathWithoutPartition) + + for (let i = 0; i <= pathSegments.length; i++) { + const path = Path.fromKind( + i === pathSegments.length ? pathKind : Path.Kind.Directory, + ...pathSegments.slice(0, i) + ) + + const result: MountedPrivateNode | undefined = + privateNodes[Path.toPosix(path, { absolute: true })] + + if (result !== undefined) { + return { + ...result, + remainder: pathSegments.slice(i), + } + } + } + + throwNoAccess(path) +} + +export function partition

( + path: Path.Distinctive> +): PartitionDiscoveryNonEmpty

+export function partition

( + path: Path.Distinctive> +): PartitionDiscovery

+export function partition(path: Path.Distinctive>): { + name: 'public' | 'private' + path: Path.Distinctive> + segments: Path.Segments +} { + const unwrapped = Path.unwrap(path) + const rest = unwrapped.slice(1) + + switch (unwrapped[0]) { + case 'public': { + return { name: 'public', path: path, segments: rest } + } + case 'private': { + return { name: 'private', path: path, segments: rest } + } + default: { + throwInvalidPartition(path) + } + } +} diff --git a/packages/nest/src/mutations.ts b/packages/nest/src/mutations.ts new file mode 100644 index 0000000..86d0444 --- /dev/null +++ b/packages/nest/src/mutations.ts @@ -0,0 +1,131 @@ +import type { Blockstore } from 'interface-blockstore' + +import type * as Path from './path.js' +import type { Rng } from './rng.js' +import type { RootTree } from './root-tree.js' +import type { MutationType } from './types.js' +import type { + MountedPrivateNodes, + PrivateNodeQueryResult, + WnfsPrivateResult, + WnfsPublicResult, +} from './types/internal.js' + +import * as Store from './store.js' +import * as Unix from './unix.js' + +import { searchLatest } from './common.js' + +// 🏔️ + +export const TYPES: Record = { + ADDED_OR_UPDATED: 'added-or-updated', + REMOVED: 'removed', +} + +// PUBLIC + +export interface PublicParams { + blockstore: Blockstore + pathSegments: Path.Segments + rootTree: RootTree +} + +export type Public = (params: PublicParams) => Promise + +export const publicCreateDirectory = () => { + return async (params: PublicParams): Promise => { + return await params.rootTree + .publicRoot() + .mkdir(params.pathSegments, new Date(), Store.wnfs(params.blockstore)) + } +} + +export const publicRemove = () => { + return async (params: PublicParams): Promise => { + return await params.rootTree + .publicRoot() + .rm(params.pathSegments, Store.wnfs(params.blockstore)) + } +} + +export const publicWrite = (bytes: Uint8Array) => { + return async (params: PublicParams): Promise => { + const cid = await Unix.importFile(bytes, params.blockstore) + + return await params.rootTree + .publicRoot() + .write( + params.pathSegments, + cid.bytes, + new Date(), + Store.wnfs(params.blockstore) + ) + } +} + +// PRIVATE + +export type PrivateParams = { + blockstore: Blockstore + privateNodes: MountedPrivateNodes + rng: Rng + rootTree: RootTree +} & PrivateNodeQueryResult + +export type Private = (params: PrivateParams) => Promise + +export const privateCreateDirectory = () => { + return async (params: PrivateParams): Promise => { + if (params.node.isFile()) + throw new Error('Cannot create a directory inside a file') + + return await params.node + .asDir() + .mkdir( + params.remainder, + searchLatest(), + new Date(), + params.rootTree.privateForest(), + Store.wnfs(params.blockstore), + params.rng + ) + } +} + +export const privateRemove = () => { + return async (params: PrivateParams): Promise => { + if (params.node.isFile()) { + throw new Error('Cannot self-destruct') + } + + return await params.node + .asDir() + .rm( + params.remainder, + searchLatest(), + params.rootTree.privateForest(), + Store.wnfs(params.blockstore) + ) + } +} + +export const privateWrite = (bytes: Uint8Array) => { + return async (params: PrivateParams): Promise => { + if (params.node.isFile()) { + throw new Error('Cannot write into a PrivateFile directly') + } + + return await params.node + .asDir() + .write( + params.remainder, + searchLatest(), + bytes, + new Date(), + params.rootTree.privateForest(), + Store.wnfs(params.blockstore), + params.rng + ) + } +} diff --git a/packages/nest/src/path.ts b/packages/nest/src/path.ts new file mode 100644 index 0000000..38295be --- /dev/null +++ b/packages/nest/src/path.ts @@ -0,0 +1,595 @@ +// 🧩 + +import type { AppInfo } from './app-info.js' + +export enum RootBranch { + Exchange = 'exchange', + Private = 'private', + Public = 'public', + Unix = 'unix', + Version = 'version', +} + +export enum Kind { + Directory = 'directory', + File = 'file', +} + +export type Segment = string +export type Segments = Segment[] +export type SegmentsNonEmpty = [Segment, ...Segments] +export type Partitioned

= [P, ...Segments] +export type PartitionedNonEmpty

= [P, Segment, ...Segments] + +/** + * Private partition + */ +export type Private = 'private' | RootBranch.Private + +/** + * Public partition + */ +export type Public = 'public' | RootBranch.Public + +/** + * `RootBranch`es that are accessible through the POSIX file system interface. + */ +export type Partition = Private | Public + +/** + * A directory path. + */ +export interface DirectoryPath

{ + directory: P +} + +/** + * A file path. + */ +export interface FilePath

{ + file: P +} + +/** + * A file or directory path. + */ +export type DistinctivePath

= DirectoryPath

| FilePath

+ +/** + * Alias for `DirectoryPath` + */ +export type Directory

= DirectoryPath

+ +/** + * Alias for `FilePath` + */ +export type File

= FilePath

+ +/** + * Alias for `DistinctivePath` + */ +export type Distinctive

= DistinctivePath

+ +// CREATION + +/** + * Utility function to create a `DirectoryPath` + */ +export function directory

( + ...args: PartitionedNonEmpty

+): DirectoryPath> +export function directory

( + ...args: Partitioned

+): DirectoryPath> +export function directory( + ...args: SegmentsNonEmpty +): DirectoryPath +export function directory(...args: Segments): DirectoryPath +export function directory(...args: Segments): DirectoryPath { + if (args.some((p) => p.includes('/'))) { + throw new Error('Forward slashes `/` are not allowed') + } + return { directory: args } +} + +/** + * Utility function to create a `FilePath` + */ +export function file

( + ...args: PartitionedNonEmpty

+): FilePath> +export function file(...args: SegmentsNonEmpty): FilePath +export function file(...args: Segments): FilePath +export function file(...args: Segments): FilePath { + if (args.some((p) => p.includes('/'))) { + throw new Error('Forward slashes `/` are not allowed') + } + return { file: args } +} + +/** + * Utility function to create a path based on the given `Kind` + */ +export function fromKind

( + kind: Kind.Directory, + ...args: PartitionedNonEmpty

+): DirectoryPath> +export function fromKind

( + kind: Kind.Directory, + ...args: Partitioned

+): DirectoryPath> +export function fromKind( + kind: Kind.Directory, + ...args: SegmentsNonEmpty +): DirectoryPath +export function fromKind( + kind: Kind.Directory, + ...args: Segments +): DirectoryPath +export function fromKind

( + kind: Kind.File, + ...args: PartitionedNonEmpty

+): FilePath> +export function fromKind( + kind: Kind.File, + ...args: SegmentsNonEmpty +): FilePath +export function fromKind(kind: Kind.File, ...args: Segments): FilePath +export function fromKind

( + kind: Kind, + ...args: PartitionedNonEmpty

+): DistinctivePath> +export function fromKind

( + kind: Kind, + ...args: Partitioned

+): DistinctivePath> +export function fromKind( + kind: Kind, + ...args: SegmentsNonEmpty +): DistinctivePath +export function fromKind( + kind: Kind, + ...args: Segments +): DistinctivePath +export function fromKind( + kind: Kind, + ...args: Segments +): DistinctivePath { + return kind === Kind.Directory ? directory(...args) : file(...args) +} + +/** + * Utility function to create a root `DirectoryPath` + */ +export function root(): DirectoryPath { + return { directory: [] } +} + +/** + * Utility function create an app data path. + */ +export function appData

( + partition: P, + app: AppInfo +): DirectoryPath> +export function appData

( + partition: P, + app: AppInfo, + suffix: FilePath +): FilePath> +export function appData

( + partition: P, + app: AppInfo, + suffix: DirectoryPath +): DirectoryPath> +export function appData

( + partition: P, + app: AppInfo, + suffix: DistinctivePath +): DistinctivePath> +export function appData

( + partition: P, + app: AppInfo, + suffix?: DistinctivePath +): DistinctivePath> { + const appDir = directory(partition, 'Apps', app.creator, app.name) + return suffix === undefined ? appDir : combine(appDir, suffix) +} + +// POSIX + +/** + * Transform a string into a `DistinctivePath`. + * + * Directories should have the format `path/to/dir/` and + * files should have the format `path/to/file`. + * + * Leading forward slashes are removed too, so you can pass absolute paths. + */ +export function fromPosix(path: string): DistinctivePath { + const split = path.replace(/^\/+/, '').split('/') + if (path.endsWith('/')) return { directory: split.slice(0, -1) } + else if (path === '') return root() + return { file: split } +} + +/** + * Transform a `DistinctivePath` into a string. + * + * Directories will have the format `path/to/dir/` and + * files will have the format `path/to/file`. + */ +export function toPosix( + path: DistinctivePath, + options?: { absolute?: boolean } +): string { + const prefix = options?.absolute === true ? '/' : '' + const joinedPath = unwrap(path).join('/') + if (isDirectory(path)) + return prefix + joinedPath + (joinedPath.length > 0 ? '/' : '') + return prefix + joinedPath +} + +// 🛠️ + +/** + * Combine two `DistinctivePath`s. + */ +export function combine

( + a: DirectoryPath>, + b: FilePath +): FilePath> +export function combine

( + a: DirectoryPath>, + b: FilePath +): FilePath> +export function combine

( + a: DirectoryPath>, + b: FilePath +): FilePath> +export function combine( + a: DirectoryPath, + b: FilePath +): FilePath +export function combine( + a: DirectoryPath, + b: FilePath +): FilePath +export function combine

( + a: DirectoryPath>, + b: DirectoryPath +): DirectoryPath> +export function combine

( + a: DirectoryPath>, + b: DirectoryPath +): DirectoryPath> +export function combine

( + a: DirectoryPath>, + b: DirectoryPath +): DirectoryPath> +export function combine( + a: DirectoryPath, + b: DirectoryPath +): DirectoryPath +export function combine( + a: DirectoryPath, + b: DirectoryPath +): DirectoryPath +export function combine

( + a: DirectoryPath>, + b: DistinctivePath +): DistinctivePath> +export function combine

( + a: DirectoryPath>, + b: DistinctivePath +): DistinctivePath> +export function combine

( + a: DirectoryPath>, + b: DistinctivePath +): DistinctivePath> +export function combine( + a: DirectoryPath, + b: DistinctivePath +): DistinctivePath +export function combine( + a: DirectoryPath, + b: DistinctivePath +): DistinctivePath +export function combine( + a: DirectoryPath, + b: DistinctivePath +): DistinctivePath { + return map((p) => [...unwrap(a), ...p], b) +} + +/** + * Is this `DistinctivePath` a directory? + */ +export function isDirectory

( + path: DistinctivePath

+): path is DirectoryPath

{ + return 'directory' in path +} + +/** + * Is this `DistinctivePath` a file? + */ +export function isFile

(path: DistinctivePath

): path is FilePath

{ + return 'file' in path +} + +/** + * Is this `DistinctivePath` on the given `RootBranch`? + */ +export function isOnRootBranch( + rootBranch: RootBranch, + path: DistinctivePath +): boolean { + return unwrap(path)[0] === rootBranch +} + +/** + * Is this `DistinctivePath` of the given `Partition`? + */ +export function isPartition( + partition: Partition, + path: DistinctivePath +): boolean { + return unwrap(path)[0] === partition +} + +/** + * Is this a partitioned `DistinctivePath`? + */ +export function isPartitioned

( + path: DistinctivePath +): path is DistinctivePath> { + const soCalledPartition = unwrap(path)[0] + return [RootBranch.Private, RootBranch.Public, 'private', 'public'].includes( + soCalledPartition + ) +} + +/** + * Is this partitioned `DistinctivePath` non-empty? + */ +export function isPartitionedNonEmpty

( + path: DistinctivePath +): path is DistinctivePath> { + return isPartitioned(path) && length(path) > 1 +} + +/** + * Is this `DirectoryPath` a root directory? + */ +export function isRootDirectory(path: DirectoryPath): boolean { + return path.directory.length === 0 +} + +/** + * Check if two `DistinctivePath` have the same `Partition`. + */ +export function isSamePartition( + a: DistinctivePath, + b: DistinctivePath +): boolean { + return unwrap(a)[0] === unwrap(b)[0] +} + +/** + * Check if two `DistinctivePath` are of the same kind. + */ +export function isSameKind( + a: DistinctivePath, + b: DistinctivePath +): boolean { + if (isDirectory(a) && isDirectory(b)) return true + else if (isFile(a) && isFile(b)) return true + else return false +} + +/** + * What `Kind` of path are we dealing with? + */ +export function kind

(path: DistinctivePath

): Kind { + if (isDirectory(path)) return Kind.Directory + return Kind.File +} + +/** + * What's the length of a path? + */ +export function length(path: DistinctivePath): number { + return unwrap(path).length +} + +/** + * Map a `DistinctivePath`. + */ +export function map( + fn: (p: A) => B, + path: DistinctivePath +): DistinctivePath { + if (isDirectory(path)) return { directory: fn(path.directory) } + else if (isFile(path)) return { file: fn(path.file) } + return path +} + +/** + * Get the parent directory of a `DistinctivePath`. + */ +export function parent( + path: DistinctivePath<[Partition, Segment, Segment, ...Segments]> +): DirectoryPath> +export function parent( + path: DistinctivePath<[Segment, Segment, Segment, ...Segments]> +): DirectoryPath +export function parent( + path: DistinctivePath> +): DirectoryPath> +export function parent( + path: DistinctivePath<[Partition, Segment]> +): DirectoryPath> +export function parent( + path: DistinctivePath> +): DirectoryPath +export function parent( + path: DistinctivePath +): DirectoryPath +export function parent(path: DistinctivePath<[Segment]>): DirectoryPath<[]> +export function parent(path: DistinctivePath<[]>): undefined +export function parent( + path: DistinctivePath +): DirectoryPath | undefined +export function parent( + path: DistinctivePath +): DirectoryPath | undefined { + return isDirectory(path) && isRootDirectory(path) + ? undefined + : directory(...unwrap(path).slice(0, -1)) +} + +/** + * Remove the `Partition` of a `DistinctivePath` (ie. the top-level directory) + */ +export function removePartition( + path: DistinctivePath +): DistinctivePath { + return map((p) => (isDirectory(path) || p.length > 1 ? p.slice(1) : p), path) +} + +export function replaceTerminus( + path: FilePath>, + terminus: string +): FilePath> +export function replaceTerminus( + path: DirectoryPath>, + terminus: string +): DirectoryPath> +export function replaceTerminus( + path: DistinctivePath>, + terminus: string +): DistinctivePath> +export function replaceTerminus( + path: FilePath, + terminus: string +): FilePath +export function replaceTerminus( + path: DirectoryPath, + terminus: string +): DirectoryPath +export function replaceTerminus( + path: DistinctivePath, + terminus: string +): DistinctivePath +export function replaceTerminus( + path: DistinctivePath | DistinctivePath, + terminus: string +): DistinctivePath { + return combine(parent(path), fromKind(kind(path), terminus)) +} + +export function rootBranch( + path: DistinctivePath +): { branch: RootBranch; rest: Segments } | undefined { + const unwrapped = unwrap(path) + const firstSegment = unwrapped[0] + const rest = unwrapped.slice(1) + + switch (firstSegment) { + case RootBranch.Exchange: { + return { branch: RootBranch.Exchange, rest } + } + + case RootBranch.Private: { + return { branch: RootBranch.Private, rest } + } + + case RootBranch.Public: { + return { branch: RootBranch.Public, rest } + } + + case RootBranch.Unix: { + return { branch: RootBranch.Unix, rest } + } + + case RootBranch.Version: { + return { branch: RootBranch.Version, rest } + } + + default: { + return undefined + } + } +} + +/** + * Get the last part of the path. + */ +export function terminus( + path: DistinctivePath> +): string +export function terminus(path: DistinctivePath>): string +export function terminus(path: DistinctivePath): string +export function terminus(path: DistinctivePath): string | undefined +export function terminus(path: DistinctivePath): string | undefined { + const u = unwrap(path) + if (u.length === 0) return undefined + return u.at(-1) +} + +/** + * Unwrap a `DistinctivePath`. + */ +export function unwrap

(path: DistinctivePath

): P { + if (isDirectory(path)) { + return path.directory + } else if (isFile(path)) { + return path.file + } + + throw new Error('Path is neither a directory or a file') +} + +/** + * Utility function to prefix a path with a `Partition`. + */ +export function withPartition

( + partition: P, + path: DirectoryPath +): DirectoryPath> +export function withPartition

( + partition: P, + path: DirectoryPath +): DirectoryPath> +export function withPartition

( + partition: P, + path: FilePath +): FilePath> +export function withPartition

( + partition: P, + path: FilePath +): FilePath> +export function withPartition

( + partition: P, + path: DistinctivePath +): DistinctivePath> +export function withPartition

( + partition: P, + path: DistinctivePath +): DistinctivePath> +export function withPartition

( + partition: P, + path: DistinctivePath +): DistinctivePath> { + return combine(directory(partition), path) +} + +// 🔬 + +/** + * Render a raw `Path` to a string for logging purposes. + */ +export function log(path: Segments): string { + return `[ ${path.join(', ')} ]` +} diff --git a/packages/nest/src/queries.ts b/packages/nest/src/queries.ts new file mode 100644 index 0000000..2cb5d5a --- /dev/null +++ b/packages/nest/src/queries.ts @@ -0,0 +1,302 @@ +import type { Blockstore } from 'interface-blockstore' +import type { + AccessKey, + PrivateDirectory, + PrivateFile, + PublicDirectory, + PublicNode, +} from 'wnfs' + +import { PrivateNode } from 'wnfs' +import { CID } from 'multiformats/cid' + +import * as Store from './store.js' +import * as Path from './path.js' +import * as Unix from './unix.js' + +import type { Partitioned } from './path.js' +import type { Rng } from './rng.js' +import type { RootTree } from './root-tree.js' +import type { DirectoryItem, DirectoryItemWithKind } from './types.js' +import type { + MountedPrivateNodes, + PrivateNodeQueryResult, +} from './types/internal.js' + +import { searchLatest } from './common.js' +import { findPrivateNode } from './mounts.js' + +// PUBLIC + +export interface PublicParams { + blockstore: Blockstore + pathSegments: Path.Segments + rootTree: RootTree +} + +export type Public = (params: PublicParams) => Promise +export type PublicContext = Omit + +export async function publicQuery( + path: Path.Distinctive>, + qry: Public, + context: PublicContext +): Promise { + return await qry({ + blockstore: context.blockstore, + pathSegments: Path.unwrap(Path.removePartition(path)), + rootTree: context.rootTree, + }) +} + +export const publicExists = () => { + return async (params: PublicParams): Promise => { + const result = await params.rootTree + .publicRoot() + .getNode(params.pathSegments, Store.wnfs(params.blockstore)) + + return result !== null && result !== undefined + } +} + +export const publicListDirectory = () => { + return async (params: PublicParams): Promise => { + return await params.rootTree + .publicRoot() + .ls(params.pathSegments, Store.wnfs(params.blockstore)) + } +} + +export const publicListDirectoryWithKind = () => { + return async (params: PublicParams): Promise => { + const dir: PublicDirectory = + params.pathSegments.length === 0 + ? params.rootTree.publicRoot() + : await params.rootTree + .publicRoot() + .getNode(params.pathSegments, Store.wnfs(params.blockstore)) + .then((a) => a.asDir()) + const items: DirectoryItem[] = await dir.ls( + [], + Store.wnfs(params.blockstore) + ) + + const promises = items.map(async (item): Promise => { + const node: PublicNode = await dir.lookupNode( + item.name, + Store.wnfs(params.blockstore) + ) + + const kind = node.isDir() ? Path.Kind.Directory : Path.Kind.File + + return { + ...item, + kind, + path: Path.combine( + Path.directory('public', ...params.pathSegments), + Path.fromKind(kind, item.name) + ), + } + }) + + return await Promise.all(promises) + } +} + +export const publicRead = (options?: { offset: number; length: number }) => { + return async (params: PublicParams): Promise => { + const result = await params.rootTree + .publicRoot() + .read(params.pathSegments, Store.wnfs(params.blockstore)) + + return await publicReadFromCID(CID.decode(result), options)(params) + } +} + +export const publicReadFromCID = ( + cid: CID, + options?: { offset: number; length: number } +) => { + return async (context: PublicContext): Promise => { + return await Unix.exportFile(cid, context.blockstore, options) + } +} + +// PRIVATE + +export type PrivateParams = { + blockstore: Blockstore + privateNodes: MountedPrivateNodes + rng: Rng + rootTree: RootTree +} & PrivateNodeQueryResult + +export type Private = (params: PrivateParams) => Promise +export type PrivateContext = Omit + +export async function privateQuery( + path: Path.Distinctive>, + qry: Private, + context: PrivateContext +): Promise { + const priv = findPrivateNode(path, context.privateNodes) + + // Perform mutation + return await qry({ + ...priv, + blockstore: context.blockstore, + privateNodes: context.privateNodes, + rng: context.rng, + rootTree: context.rootTree, + }) +} + +export const privateExists = () => { + return async (params: PrivateParams): Promise => { + if (params.node.isFile()) return true + + const result = await params.node + .asDir() + .getNode( + params.remainder, + searchLatest(), + params.rootTree.privateForest(), + Store.wnfs(params.blockstore) + ) + + return result !== null && result !== undefined + } +} + +export const privateListDirectory = () => { + return async (params: PrivateParams): Promise => { + if (params.node.isFile()) throw new Error('Cannot list a file') + const { result } = await params.node + .asDir() + .ls( + params.remainder, + searchLatest(), + params.rootTree.privateForest(), + Store.wnfs(params.blockstore) + ) + return result + } +} + +export const privateListDirectoryWithKind = () => { + return async (params: PrivateParams): Promise => { + if (params.node.isFile()) throw new Error('Cannot list a file') + + const dir: PrivateDirectory = + params.remainder.length === 0 + ? params.node.asDir() + : await params.node + .asDir() + .getNode( + params.remainder, + searchLatest(), + params.rootTree.privateForest(), + Store.wnfs(params.blockstore) + ) + .then((a) => a.asDir()) + const items: DirectoryItem[] = await dir + .ls( + [], + searchLatest(), + params.rootTree.privateForest(), + Store.wnfs(params.blockstore) + ) + .then((a) => a.result) + + const parentPath = Path.combine( + Path.directory('private', ...Path.unwrap(params.path)), + Path.directory(...params.remainder) + ) + + if (!Path.isDirectory(parentPath)) { + throw new Error("Didn't expect a file path") + } + + const promises = items.map( + async (item: DirectoryItem): Promise => { + const node: PrivateNode = await dir.lookupNode( + item.name, + searchLatest(), + params.rootTree.privateForest(), + Store.wnfs(params.blockstore) + ) + + const kind = node.isDir() ? Path.Kind.Directory : Path.Kind.File + + return { + ...item, + kind, + path: Path.combine(parentPath, Path.fromKind(kind, item.name)), + } + } + ) + + return await Promise.all(promises) + } +} + +export const privateRead = (_options?: { offset: number; length: number }) => { + return async (params: PrivateParams): Promise => { + // TODO: Respect `offset` and `length` options when private streaming API is exposed in rs-wnfs + // const offset = options?.offset + // const length = options?.length + + let bytes + + if (params.node.isFile()) { + bytes = await params.node + .asFile() + .getContent( + params.rootTree.privateForest(), + Store.wnfs(params.blockstore) + ) + } else { + const { result } = await params.node + .asDir() + .read( + params.remainder, + searchLatest(), + params.rootTree.privateForest(), + Store.wnfs(params.blockstore) + ) + bytes = result + } + + return bytes + } +} + +export const privateReadFromAccessKey = ( + accessKey: AccessKey, + _options?: { offset: number; length: number } +) => { + return async (context: PrivateContext): Promise => { + // TODO: Respect `offset` and `length` options when private streaming API is exposed in rs-wnfs + // const offset = options?.offset + // const length = options?.length + + // Retrieve node + const node = await PrivateNode.load( + accessKey, + context.rootTree.privateForest(), + Store.wnfs(context.blockstore) + ) + + if (node.isFile() === true) { + const file: PrivateFile = node.asFile() + + // TODO: Respect the offset and length options when available in rs-wnfs + return await file.getContent( + context.rootTree.privateForest(), + Store.wnfs(context.blockstore) + ) + } else { + throw new Error('Expected a file, found a directory') + } + } +} diff --git a/packages/nest/src/references.ts b/packages/nest/src/references.ts new file mode 100644 index 0000000..cb01e4b --- /dev/null +++ b/packages/nest/src/references.ts @@ -0,0 +1,46 @@ +import type { Blockstore } from 'interface-blockstore' +import type { PublicNode } from 'wnfs' + +import { CID } from 'multiformats/cid' + +import type * as Path from './path.js' +import type { RootTree } from './root-tree.js' + +import * as Store from './store.js' +import { pathSegmentsWithoutPartition } from './common.js' + +export async function contentCID( + blockstore: Blockstore, + rootTree: RootTree, + path: Path.File> +): Promise { + const wnfsBlockstore = Store.wnfs(blockstore) + const result = await rootTree + .publicRoot() + .getNode(pathSegmentsWithoutPartition(path), wnfsBlockstore) + + const maybeNode: PublicNode | undefined = result ?? undefined + return maybeNode?.isFile() === true + ? CID.decode(maybeNode.asFile().contentCid()) + : undefined +} + +export async function capsuleCID( + blockstore: Blockstore, + rootTree: RootTree, + path: Path.Distinctive> +): Promise { + const wnfsBlockstore = Store.wnfs(blockstore) + const result = await rootTree + .publicRoot() + .getNode(pathSegmentsWithoutPartition(path), wnfsBlockstore) + + const maybeNode: PublicNode | undefined = result ?? undefined + return maybeNode === undefined + ? undefined + : CID.decode( + maybeNode.isFile() + ? await maybeNode.asFile().store(wnfsBlockstore) + : await maybeNode.asDir().store(wnfsBlockstore) + ) +} diff --git a/packages/nest/src/rng.ts b/packages/nest/src/rng.ts new file mode 100644 index 0000000..7fad503 --- /dev/null +++ b/packages/nest/src/rng.ts @@ -0,0 +1,14 @@ +import { webcrypto } from 'iso-base/crypto' + +export interface Rng { + randomBytes: (count: number) => Uint8Array +} + +export function makeRngInterface(): Rng { + return { + /** Returns random bytes of specified length */ + randomBytes(count: number): Uint8Array { + return webcrypto.getRandomValues(new Uint8Array(count)) + }, + } +} diff --git a/packages/nest/src/root-tree.ts b/packages/nest/src/root-tree.ts new file mode 100644 index 0000000..9034073 --- /dev/null +++ b/packages/nest/src/root-tree.ts @@ -0,0 +1,32 @@ +import type { Blockstore } from 'interface-blockstore' +import type { CID } from 'multiformats' +import type { PrivateForest, PublicDirectory } from 'wnfs' + +import type { FileSystemChange } from './types.js' + +/** + * The tree that ties different file systems together. + */ +export abstract class RootTree { + abstract privateForest(): PrivateForest + abstract replacePrivateForest( + forest: PrivateForest, + changes: FileSystemChange[] + ): Promise + abstract publicRoot(): PublicDirectory + abstract replacePublicRoot( + dir: PublicDirectory, + changes: FileSystemChange[] + ): Promise + + abstract clone(): RootTree + abstract store(): Promise + + static async create(_blockstore: Blockstore): Promise { + throw new Error('Not implemented!') + } + + static async fromCID(_blockstore: Blockstore, _cid: CID): Promise { + throw new Error('Not implemented!') + } +} diff --git a/packages/nest/src/root-tree/basic.ts b/packages/nest/src/root-tree/basic.ts new file mode 100644 index 0000000..90a44e2 --- /dev/null +++ b/packages/nest/src/root-tree/basic.ts @@ -0,0 +1,334 @@ +import type { PBLink, PBNode } from '@ipld/dag-pb' +import type { Blockstore } from 'interface-blockstore' + +import * as DagPB from '@ipld/dag-pb' +import * as Raw from 'multiformats/codecs/raw' +import * as Uint8Arrays from 'uint8arrays' + +import { webcrypto } from 'iso-base/crypto' +import { CID } from 'multiformats/cid' +import { PrivateForest, PublicDirectory } from 'wnfs' + +import * as Path from '../path.js' +import * as References from '../references.js' +import * as Store from '../store.js' +import * as Unix from '../unix.js' +import * as Version from '../version.js' + +import type { RootTree } from '../root-tree.js' +import type { FileSystemChange } from '../types.js' + +import { RootBranch } from '../path.js' +import { makeRngInterface } from '../rng.js' + +// CLASS + +export class BasicRootTree implements RootTree { + readonly #blockstore: Blockstore + readonly #exchangeRoot: PublicDirectory + readonly #privateForest: PrivateForest + readonly #publicRoot: PublicDirectory + readonly #unix: PBNode + readonly #version: string + + constructor({ + blockstore, + exchangeRoot, + publicRoot, + privateForest, + unix, + version, + }: { + blockstore: Blockstore + exchangeRoot: PublicDirectory + privateForest: PrivateForest + publicRoot: PublicDirectory + unix: PBNode + version: string + }) { + this.#blockstore = blockstore + this.#exchangeRoot = exchangeRoot + this.#privateForest = privateForest + this.#publicRoot = publicRoot + this.#unix = unix + this.#version = version + } + + /** + * Create a new root tree. + */ + static async create(blockstore: Blockstore): Promise { + const currentTime = new Date() + + return new BasicRootTree({ + blockstore, + + exchangeRoot: new PublicDirectory(currentTime), + publicRoot: new PublicDirectory(currentTime), + privateForest: await createPrivateForest(), + unix: Unix.createDirectory(currentTime), + version: Version.latest, + }) + } + + /** + * Load an existing root tree. + */ + static async fromCID( + blockstore: Blockstore, + cid: CID + ): Promise { + const currentTime = new Date() + const wnfsStore = Store.wnfs(blockstore) + + // Retrieve links + const links = await linksFromCID(cid, blockstore) + + // Retrieve all pieces + async function handleLink( + name: string, + present: (cid: CID) => Promise, + missing: () => T | Promise + ): Promise { + if (links[name] === undefined) { + console.warn( + `Missing '${name}' link in the root tree from '${cid.toString()}'. Creating a new link.` + ) + return await missing() + } + + return await present(links[name]) + } + + const exchangeRoot = await handleLink( + RootBranch.Exchange, + async (cid) => await PublicDirectory.load(cid.bytes, wnfsStore), + () => new PublicDirectory(currentTime) + ) + + const publicRoot = await handleLink( + RootBranch.Public, + async (cid) => await PublicDirectory.load(cid.bytes, wnfsStore), + () => new PublicDirectory(currentTime) + ) + + const privateForest = await handleLink( + RootBranch.Private, + async (cid) => await PrivateForest.load(cid.bytes, wnfsStore), + async () => await createPrivateForest() + ) + + const unix = await handleLink( + RootBranch.Unix, + async (cid) => await Unix.load(cid, blockstore), + () => Unix.createDirectory(currentTime) + ) + + const version = await handleLink( + RootBranch.Version, + async (cid) => { + return new TextDecoder().decode(Raw.decode(await blockstore.get(cid))) + }, + () => Version.latest + ) + + // Compose + return new BasicRootTree({ + blockstore, + + exchangeRoot, + publicRoot, + privateForest, + unix, + version, + }) + } + + privateForest(): PrivateForest { + return this.#privateForest + } + + async replacePrivateForest( + forest: PrivateForest, + _changes: FileSystemChange[] + ): Promise { + return new BasicRootTree({ + blockstore: this.#blockstore, + + exchangeRoot: this.#exchangeRoot, + publicRoot: this.#publicRoot, + privateForest: forest, + unix: this.#unix, + version: this.#version, + }) + } + + publicRoot(): PublicDirectory { + return this.#publicRoot + } + + async replacePublicRoot( + dir: PublicDirectory, + changes: FileSystemChange[] + ): Promise { + const treeWithNewPublicRoot = new BasicRootTree({ + blockstore: this.#blockstore, + + exchangeRoot: this.#exchangeRoot, + publicRoot: dir, + privateForest: this.#privateForest, + unix: this.#unix, + version: this.#version, + }) + + const unixTree = await changes.reduce(async (oldRootPromise, change) => { + const oldRoot = await oldRootPromise + + if (!Path.isPartition('public', change.path)) { + return oldRoot + } + + const path = Path.removePartition(change.path) + + if (change.type === 'removed') { + return await Unix.removeNodeFromTree(oldRoot, path, this.#blockstore) + } + + const contentCID = + Path.isFile(change.path) && + Path.isPartitionedNonEmpty(change.path) + ? await References.contentCID( + this.#blockstore, + treeWithNewPublicRoot, + change.path + ) + : undefined + + return await Unix.insertNodeIntoTree( + oldRoot, + path, + this.#blockstore, + contentCID + ) + }, Promise.resolve(this.#unix)) + + return new BasicRootTree({ + blockstore: this.#blockstore, + + exchangeRoot: this.#exchangeRoot, + publicRoot: dir, + privateForest: this.#privateForest, + unix: unixTree, + version: this.#version, + }) + } + + clone(): RootTree { + return new BasicRootTree({ + blockstore: this.#blockstore, + + exchangeRoot: this.#exchangeRoot, + publicRoot: this.#publicRoot, + privateForest: this.#privateForest, + unix: this.#unix, + version: this.#version, + }) + } + + async store(): Promise { + const wnfsStore = Store.wnfs(this.#blockstore) + + // Store all pieces + const exchangeRoot = await this.#exchangeRoot.store(wnfsStore) + const privateForest = await this.#privateForest.store(wnfsStore) + const publicRoot = await this.#publicRoot.store(wnfsStore) + const unixTree = await Store.store( + DagPB.encode(this.#unix), + DagPB.code, + this.#blockstore + ) + + const version = await Store.store( + Raw.encode(new TextEncoder().encode(this.#version)), + Raw.code, + this.#blockstore + ) + + // Store root tree + const links = [ + { + Name: RootBranch.Exchange, + Hash: CID.decode(exchangeRoot), + }, + { + Name: RootBranch.Private, + Hash: CID.decode(privateForest), + }, + { + Name: RootBranch.Public, + Hash: CID.decode(publicRoot), + }, + { + Name: RootBranch.Unix, + Hash: unixTree, + }, + { + Name: RootBranch.Version, + Hash: version, + }, + ] + + const node = DagPB.createNode(new Uint8Array([8, 1]), links) + + // Fin + return await Store.store(DagPB.encode(node), DagPB.code, this.#blockstore) + } +} + +// ㊙️ + +/** + * Create a new `PrivateForest` + */ +async function createPrivateForest(): Promise { + const rng = makeRngInterface() + + const rsaKey = await webcrypto.subtle.generateKey( + { + name: 'RSASSA-PKCS1-v1_5', + modulusLength: 2048, + publicExponent: new Uint8Array([0x01, 0x00, 0x01]), + hash: { name: 'SHA-256' }, + }, + false, + ['sign', 'verify'] + ) + + const rsaMod = await webcrypto.subtle + .exportKey('jwk', rsaKey.publicKey) + .then((a) => { + if (typeof a.n === 'string') return a.n + else throw new Error('Expected public RSA key to have `n` property') + }) + .then((n) => Uint8Arrays.fromString(n, 'base64url')) + + return new PrivateForest(rng, rsaMod) +} + +/** + * Retrieve the links of a root tree. + */ +export async function linksFromCID( + cid: CID, + blockstore: Blockstore +): Promise> { + // Get the root node, + // which is stored as DAG-PB. + const node = DagPB.decode(await blockstore.get(cid)) + + return node.Links.reduce((acc: Record, link: PBLink) => { + return typeof link.Name === 'string' + ? { ...acc, [link.Name]: link.Hash } + : acc + }, {}) +} diff --git a/packages/nest/src/store.ts b/packages/nest/src/store.ts new file mode 100644 index 0000000..c521d22 --- /dev/null +++ b/packages/nest/src/store.ts @@ -0,0 +1,43 @@ +import type { Blockstore } from 'interface-blockstore' + +import { CID } from 'multiformats/cid' +import { sha256 } from 'multiformats/hashes/sha2' + +// 🧩 + +export interface WnfsBlockStore { + getBlock: (cid: Uint8Array) => Promise + putBlock: (bytes: Uint8Array, code: number) => Promise +} + +// 🛠️ + +export async function cid(bytes: Uint8Array, code: number): Promise { + const multihash = await sha256.digest(bytes) + return CID.createV1(code, multihash) +} + +export function wnfs(blockstore: Blockstore): WnfsBlockStore { + return { + async getBlock(cid: Uint8Array): Promise { + const decodedCid = CID.decode(cid) + return await blockstore.get(decodedCid) + }, + + async putBlock(bytes: Uint8Array, code: number): Promise { + const c = await cid(bytes, code) + await blockstore.put(c, bytes) + return c.bytes + }, + } +} + +export async function store( + bytes: Uint8Array, + code: number, + blockstore: Blockstore +): Promise { + const c = await cid(bytes, code) + await blockstore.put(c, bytes) + return c +} diff --git a/packages/nest/src/transaction.ts b/packages/nest/src/transaction.ts new file mode 100644 index 0000000..a46ac7a --- /dev/null +++ b/packages/nest/src/transaction.ts @@ -0,0 +1,634 @@ +import type { PrivateForest, PrivateNode } from 'wnfs' +import type { Blockstore } from 'interface-blockstore' + +import { CID } from 'multiformats/cid' +import { AccessKey, PublicFile } from 'wnfs' + +import * as Path from './path.js' +import * as Mutations from './mutations.js' +import * as Queries from './queries.js' +import * as References from './references.js' +import * as Store from './store.js' + +import type { + Partition, + Partitioned, + PartitionedNonEmpty, + Private, + Public, +} from './path.js' + +import { addOrIncreaseNameNumber, searchLatest } from './common.js' + +import { dataFromBytes, dataToBytes } from './data.js' +import { partition as determinePartition, findPrivateNode } from './mounts.js' +import type { Rng } from './rng.js' +import type { RootTree } from './root-tree.js' + +import type { + AnySupportedDataType, + DataForType, + DataType, + DirectoryItem, + DirectoryItemWithKind, + MutationType, +} from './types.js' + +import type { + MountedPrivateNodes, + PrivateNodeQueryResult, +} from './types/internal.js' + +// CLASS + +/** @group File System */ +export class TransactionContext { + readonly #blockstore: Blockstore + readonly #rng: Rng + + #privateNodes: MountedPrivateNodes + #rootTree: RootTree + + readonly #changes: Set<{ + type: MutationType + path: Path.Distinctive> + }> + + /** @internal */ + constructor( + blockstore: Blockstore, + privateNodes: MountedPrivateNodes, + rng: Rng, + rootTree: RootTree + ) { + this.#blockstore = blockstore + this.#privateNodes = privateNodes + this.#rng = rng + this.#rootTree = rootTree + + this.#changes = new Set() + } + + /** @internal */ + static async commit(context: TransactionContext): Promise<{ + changes: Array<{ + path: Path.Distinctive> + type: MutationType + }> + privateNodes: MountedPrivateNodes + rootTree: RootTree + }> { + const changes = [...context.#changes] + + // Private forest + const newForest = await changes.reduce( + async (oldForestPromise, change): Promise => { + const oldForest = await oldForestPromise + + if (!Path.isPartition('private', change.path)) { + return oldForest + } + + const maybeNode = findPrivateNode( + change.path as Path.Distinctive>, + context.#privateNodes + ) + + const [_newAccessKey, newForest] = await maybeNode.node.store( + oldForest, + Store.wnfs(context.#blockstore), + context.#rng + ) + return newForest + }, + Promise.resolve(context.#rootTree.privateForest()) + ) + + // Replace forest + const rootTree = await context.#rootTree.replacePrivateForest( + newForest, + changes + ) + + // Fin + return { + changes: changes, + privateNodes: context.#privateNodes, + rootTree: rootTree, + } + } + + // QUERIES + + /** @group Querying */ + async contentCID( + path: Path.File> + ): Promise { + return await References.contentCID(this.#blockstore, this.#rootTree, path) + } + + /** @group Querying */ + async capsuleCID( + path: Path.Distinctive> + ): Promise { + return await References.capsuleCID(this.#blockstore, this.#rootTree, path) + } + + /** @group Querying */ + async capsuleKey( + path: Path.Distinctive> + ): Promise { + let priv: PrivateNodeQueryResult + + try { + priv = findPrivateNode(path, this.#privateNodes) + } catch { + return undefined + } + + return priv.remainder.length === 0 || priv.node.isFile() + ? await priv.node + .store( + this.#rootTree.privateForest(), + Store.wnfs(this.#blockstore), + this.#rng + ) + .then(([accessKey]: [AccessKey, PrivateForest]) => + accessKey.toBytes() + ) + : await priv.node + .asDir() + .getNode( + priv.remainder, + searchLatest(), + this.#rootTree.privateForest(), + Store.wnfs(this.#blockstore) + ) + .then(async (result: PrivateNode | undefined) => { + return result === undefined + ? undefined + : await result + .store( + this.#rootTree.privateForest(), + Store.wnfs(this.#blockstore), + this.#rng + ) + .then(([accessKey]: [AccessKey, PrivateForest]) => + accessKey.toBytes() + ) + }) + } + + /** @group Querying */ + async exists( + path: Path.Distinctive> + ): Promise { + return await this.#query(path, { + public: Queries.publicExists(), + private: Queries.privateExists(), + }) + } + + /** @group Querying */ + async listDirectory( + path: Path.Directory>, + listOptions: { withItemKind: true } + ): Promise + async listDirectory( + path: Path.Directory>, + listOptions: { withItemKind: false } + ): Promise + async listDirectory( + path: Path.Directory> + ): Promise + async listDirectory( + path: Path.Directory>, + listOptions?: { withItemKind: boolean } + ): Promise + async listDirectory( + path: Path.Directory>, + listOptions?: { withItemKind: boolean } + ): Promise { + if (listOptions?.withItemKind === true) { + return await this.#query(path, { + public: Queries.publicListDirectoryWithKind(), + private: Queries.privateListDirectoryWithKind(), + }) + } + + return await this.#query(path, { + public: Queries.publicListDirectory(), + private: Queries.privateListDirectory(), + }) + } + + /** @group Querying */ + ls = this.listDirectory + + /** @group Querying */ + async read( + arg: + | Path.File> + | { contentCID: CID } + | { capsuleCID: CID } + | { + capsuleKey: Uint8Array + }, + dataType: DataType, + options?: { offset: number; length: number } + ): Promise> + async read( + arg: + | Path.File> + | { contentCID: CID } + | { capsuleCID: CID } + | { + capsuleKey: Uint8Array + }, + dataType: DataType, + options?: { offset: number; length: number } + ): Promise> { + let bytes + + if ('contentCID' in arg) { + // Public content from content CID + bytes = await Queries.publicReadFromCID( + arg.contentCID, + options + )(this.#publicContext()) + } else if ('capsuleCID' in arg) { + // Public content from capsule CID + const publicFile: PublicFile = await PublicFile.load( + arg.capsuleCID.bytes, + Store.wnfs(this.#blockstore) + ) + + return await this.read( + { contentCID: CID.decode(publicFile.contentCid()) }, + dataType, + options + ) + } else if ('capsuleKey' in arg) { + // Private content from capsule key + bytes = await Queries.privateReadFromAccessKey( + AccessKey.fromBytes(arg.capsuleKey), + options + )(this.#privateContext()) + } else if ('file' in arg || 'directory' in arg) { + // Public or private from path + bytes = await this.#query(arg, { + public: Queries.publicRead(options), + private: Queries.privateRead(options), + }) + } else { + // ⚠️ + throw new Error('Invalid argument') + } + + return dataFromBytes(dataType, bytes) + } + + // MUTATIONS + + /** @group Mutating */ + async copy( + fromParam: Path.Distinctive>, + toParam: + | Path.File> + | Path.Directory> + ): Promise { + const from = fromParam + let to = toParam + + if (Path.isDirectory(fromParam) && Path.isFile(toParam)) + throw new Error('Cannot copy a directory to a file') + if (Path.isFile(fromParam) && Path.isDirectory(toParam)) + to = Path.combine(toParam, Path.file(Path.terminus(from))) + + if (Path.isFile(from) && Path.isFile(to)) { + await this.#manualCopyFile(from, to) + return + } else if (Path.isDirectory(from) && Path.isDirectory(to)) { + await this.#manualCopyDirectory(from, to) + return + } + + // NOOP + throw new Error( + `Copy no-op, from '${Path.toPosix(from)}' to '${Path.toPosix(to)}'` + ) + } + + /** @group Mutating */ + cp = this.copy + + /** @group Mutating */ + async createDirectory( + path: Path.Directory> + ): Promise<{ path: Path.Directory> }> { + if (await this.exists(path)) { + const newPath = addOrIncreaseNameNumber(path) + return await this.createDirectory(newPath) + } else { + await this.ensureDirectory(path) + return { path: path } + } + } + + /** @group Mutating */ + async createFile( + path: Path.File>, + dataType: DataType, + data: DataForType + ): Promise<{ path: Path.File> }> { + if (await this.exists(path)) { + const newPath = addOrIncreaseNameNumber(path) + return await this.createFile(newPath, dataType, data) + } else { + await this.write(path, dataType, data) + return { path: path } + } + } + + /** @group Mutating */ + async ensureDirectory( + path: Path.Directory> + ): Promise { + const partition = determinePartition(path) + + switch (partition.name) { + case 'public': { + await this.#publicMutation( + partition.path, + Mutations.publicCreateDirectory(), + Mutations.TYPES.ADDED_OR_UPDATED + ) + break + } + + case 'private': { + await this.#privateMutation( + partition.path, + Mutations.privateCreateDirectory(), + Mutations.TYPES.ADDED_OR_UPDATED + ) + break + } + } + } + + mkdir = this.ensureDirectory + + async move( + fromParam: Path.Distinctive>, + toParam: + | Path.File> + | Path.Directory> + ): Promise { + const from = fromParam + let to = toParam + + if (Path.isDirectory(fromParam) && Path.isFile(toParam)) + throw new Error('Cannot move a directory to a file') + if (Path.isFile(fromParam) && Path.isDirectory(toParam)) + to = Path.combine(toParam, Path.file(Path.terminus(from))) + + await this.#manualMove(from, to) + } + + /** @group Mutating */ + mv = this.move + + /** @group Mutating */ + async remove( + path: Path.Distinctive> + ): Promise { + const partition = determinePartition(path) + + switch (partition.name) { + case 'public': { + await this.#publicMutation( + partition.path, + Mutations.publicRemove(), + Mutations.TYPES.REMOVED + ) + break + } + + case 'private': { + await this.#privateMutation( + partition.path, + Mutations.privateRemove(), + Mutations.TYPES.REMOVED + ) + break + } + } + } + + /** @group Mutating */ + rm = this.remove + + /** @group Mutating */ + async rename( + path: Path.Distinctive>, + newName: string + ): Promise { + const fromPath = path + const toPath = Path.replaceTerminus(fromPath, newName) + + await this.move(fromPath, toPath) + } + + /** @group Mutating */ + async write( + path: Path.File>, + dataType: DataType, + data: DataForType + ): Promise { + const bytes = dataToBytes(dataType, data) + const partition = determinePartition(path) + + switch (partition.name) { + case 'public': { + await this.#publicMutation( + partition.path, + Mutations.publicWrite(bytes), + Mutations.TYPES.ADDED_OR_UPDATED + ) + break + } + + case 'private': { + await this.#privateMutation( + partition.path, + Mutations.privateWrite(bytes), + Mutations.TYPES.ADDED_OR_UPDATED + ) + break + } + } + } + + // ㊙️ ▒▒ QUERIES + + async #query( + path: Path.Distinctive>, + queryFunctions: { + public: Queries.Public + private: Queries.Private + } + ): Promise { + const partition = determinePartition(path) + + switch (partition.name) { + case 'public': { + return await Queries.publicQuery( + partition.path, + queryFunctions.public, + this.#publicContext() + ) + } + + case 'private': { + return await Queries.privateQuery( + partition.path, + queryFunctions.private, + this.#privateContext() + ) + } + } + } + + // ㊙️ ▒▒ MUTATIONS + + async #manualCopyFile( + from: Path.File>, + to: Path.File> + ): Promise { + await this.write(to, 'bytes', await this.read(from, 'bytes')) + } + + async #manualCopyDirectory( + from: Path.Directory>, + to: Path.Directory> + ): Promise { + if (Path.isPartitionedNonEmpty(to)) await this.ensureDirectory(to) + + // Copies everything under `fromDir/` to `toDir/` + // eg. `public/docs/fromDir/a/b/c.txt` -> `private/docs/toDir/a/b/c.txt` + const listing = await this.listDirectory(from, { withItemKind: true }) + if (listing.length === 0) return + + await listing.reduce( + async ( + acc: Promise, + item: DirectoryItemWithKind + ): Promise => { + await acc + + item.kind === 'directory' + ? await this.#manualCopyDirectory( + Path.combine(from, Path.directory(item.name)), + Path.combine(to, Path.directory(item.name)) + ) + : await this.#manualCopyFile( + Path.combine(from, Path.file(item.name)), + Path.combine(to, Path.file(item.name)) + ) + }, + Promise.resolve() + ) + } + + async #manualMove( + from: Path.Distinctive>, + to: + | Path.File> + | Path.Directory> + ): Promise { + await this.copy(from, to) + await this.remove(from) + } + + async #publicMutation( + path: Path.Distinctive>, + mut: Mutations.Public, + mutType: MutationType + ): Promise { + const change = { + type: mutType, + path: path, + } + + const result = await mut({ + blockstore: this.#blockstore, + pathSegments: Path.unwrap(Path.removePartition(path)), + rootTree: this.#rootTree, + }) + + // Replace public root + this.#rootTree = await this.#rootTree.replacePublicRoot(result.rootDir, [ + change, + ]) + + // Mark node as changed + this.#changes.add(change) + } + + async #privateMutation( + path: Path.Distinctive>, + mut: Mutations.Private, + mutType: MutationType + ): Promise { + const priv = findPrivateNode(path, this.#privateNodes) + const change = { + type: mutType, + path: path, + } + + // Perform mutation + const result = await mut({ + ...priv, + blockstore: this.#blockstore, + privateNodes: this.#privateNodes, + rng: this.#rng, + rootTree: this.#rootTree, + }) + + // Mark node as changed + this.#changes.add(change) + + // Replace forest + this.#rootTree = await this.#rootTree.replacePrivateForest(result.forest, [ + change, + ]) + + // Replace private node + const nodePosix = Path.toPosix(priv.path, { absolute: true }) + const node = result.rootDir.asNode() + + this.#privateNodes[nodePosix] = { + node, + path: priv.path, + } + } + + // ㊙️ + + #publicContext(): Queries.PublicContext { + return { + blockstore: this.#blockstore, + rootTree: this.#rootTree, + } + } + + #privateContext(): Queries.PrivateContext { + return { + blockstore: this.#blockstore, + privateNodes: this.#privateNodes, + rng: this.#rng, + rootTree: this.#rootTree, + } + } +} diff --git a/packages/nest/src/types.ts b/packages/nest/src/types.ts new file mode 100644 index 0000000..57e9a0a --- /dev/null +++ b/packages/nest/src/types.ts @@ -0,0 +1,86 @@ +import type { CID } from 'multiformats' +import type * as Path from './path.js' + +export type AnySupportedDataType = + | Uint8Array + | Record + | string + +export interface DataRootChange { + dataRoot: CID +} + +export type DataType = 'bytes' | 'json' | 'utf8' + +export type DataForType = D extends 'bytes' + ? Uint8Array + : D extends 'json' + ? Record + : D extends 'utf8' + ? string + : never + +export interface DirectoryItem { + metadata: { created: number; modified: number } + name: string +} + +export type DirectoryItemWithKind = DirectoryItem & { + kind: Path.Kind + path: Path.Distinctive> +} + +export interface FileSystemChange { + path: Path.Distinctive> + type: MutationType +} + +export interface MutationOptions { + skipPublish?: boolean +} + +export type MutationResult

= P extends Path.Public + ? PublicMutationResult + : P extends Path.Private + ? PrivateMutationResult + : never + +export type MutationType = 'added-or-updated' | 'removed' + +export type PartitionDiscovery

= P extends Path.Public + ? { + name: 'public' + path: Path.File> + segments: Path.Segments + } + : P extends Path.Private + ? { + name: 'private' + path: Path.File> + segments: Path.Segments + } + : never + +export type PartitionDiscoveryNonEmpty

= + P extends Path.Public + ? { + name: 'public' + path: Path.File> + segments: Path.Segments + } + : P extends Path.Private + ? { + name: 'private' + path: Path.File> + segments: Path.Segments + } + : never + +export type PublicMutationResult = DataRootChange & { + capsuleCID: CID + contentCID: CID +} + +export type PrivateMutationResult = DataRootChange & { + capsuleKey: Uint8Array +} diff --git a/packages/nest/src/types/internal.ts b/packages/nest/src/types/internal.ts new file mode 100644 index 0000000..8d175b9 --- /dev/null +++ b/packages/nest/src/types/internal.ts @@ -0,0 +1,28 @@ +import type { + PrivateDirectory, + PrivateForest, + PrivateNode, + PublicDirectory, +} from 'wnfs' +import type * as Path from '../path.js' + +// 🧩 + +export type MountedPrivateNodes = Record + +export interface MountedPrivateNode { + node: PrivateNode + path: Path.Distinctive +} + +export type PrivateNodeQueryResult = MountedPrivateNode & { + remainder: Path.Segments +} + +export interface WnfsPrivateResult { + rootDir: PrivateDirectory + forest: PrivateForest +} +export interface WnfsPublicResult { + rootDir: PublicDirectory +} diff --git a/packages/nest/src/unix.ts b/packages/nest/src/unix.ts new file mode 100644 index 0000000..270d52d --- /dev/null +++ b/packages/nest/src/unix.ts @@ -0,0 +1,203 @@ +import type { Blockstore } from 'interface-blockstore' +import type { CID } from 'multiformats' +import type { PBLink, PBNode } from '@ipld/dag-pb' + +import * as DagPB from '@ipld/dag-pb' +import * as Uint8arrays from 'uint8arrays' +import { UnixFS } from 'ipfs-unixfs' +import { exporter } from 'ipfs-unixfs-exporter' +import { importBytes as importer } from 'ipfs-unixfs-importer' +import all from 'it-all' + +import * as Path from './path.js' +import * as Store from './store.js' + +/** + * Create a UnixFS directory. + */ +export function createDirectory( + currentTime: Date, + links: PBLink[] = [] +): PBNode { + const unixDir = new UnixFS({ + type: 'directory', + mtime: { secs: BigInt(Math.round(currentTime.getTime() / 1000)) }, + }) + + return DagPB.createNode(unixDir.marshal(), links) +} + +/** + * Get the bytes of a UnixFS file. + */ +export async function exportFile( + cid: CID, + store: Blockstore, + options?: { offset: number; length: number } +): Promise { + const offset = options?.offset + const length = options?.length + + const fsEntry = await exporter(cid, store) + + if (fsEntry.type === 'file' || fsEntry.type === 'raw') { + return Uint8arrays.concat(await all(fsEntry.content({ offset, length }))) + } else { + throw new Error( + `Expected a file, found a '${fsEntry.type}' (CID: ${cid.toString()})` + ) + } +} + +/** + * Get the CID for some file bytes. + */ +export async function importFile( + bytes: Uint8Array, + store: Blockstore +): Promise { + const { cid } = await importer(bytes, store) + return cid +} + +/** + * Insert a node into UnixFS tree, creating directories when needed + * and overwriting content. + */ +export async function insertNodeIntoTree( + node: PBNode, + path: Path.Distinctive, + store: Blockstore, + fileCID?: CID +): Promise { + const pathKind = Path.kind(path) + const pathParts = Path.unwrap(path) + const name = pathParts[0] + const link = node.Links.find((l) => l.Name === name) + + // Directory + // --------- + if (Path.length(path) > 1) { + const dirNode: PBNode = + link?.Hash === undefined + ? createDirectory(new Date()) + : await load(link.Hash, store) + + const newDirNode = await insertNodeIntoTree( + dirNode, + Path.fromKind(pathKind, ...pathParts.slice(1)), + store, + fileCID + ) + + const dirCID = await Store.store( + DagPB.encode(newDirNode), + DagPB.code, + store + ) + + const links = + link === undefined + ? addLink(node.Links, name, dirCID) + : replaceLinkHash(node.Links, name, dirCID) + + return { ...node, Links: links } + } + + // Last part of path + // ----------------- + // Directory + if (pathKind === 'directory') { + if (link !== undefined) return node + + const dirNode = createDirectory(new Date()) + const dirCID = await Store.store(DagPB.encode(dirNode), DagPB.code, store) + + const links = addLink(node.Links, name, dirCID) + return { ...node, Links: links } + } + + // File + if (fileCID === undefined) + throw new Error('Need a file CID when adding a UnixFS file') + + const links = + link === undefined + ? addLink(node.Links, name, fileCID) + : replaceLinkHash(node.Links, name, fileCID) + + return { ...node, Links: links } +} + +/** + * Load a UnixFS node. + */ +export async function load(cid: CID, store: Blockstore): Promise { + return DagPB.decode(await store.get(cid)) +} + +/** + * Remove a node from a UnixFS tree. + */ +export async function removeNodeFromTree( + node: PBNode, + path: Path.Distinctive, + store: Blockstore +): Promise { + const pathKind = Path.kind(path) + const pathParts = Path.unwrap(path) + const name = pathParts[0] + const link = node.Links.find((l) => l.Name === name) + + // Directory + // --------- + if (Path.length(path) > 1) { + let dirNode: PBNode + + if (link?.Hash === undefined) { + return node + } else { + dirNode = await load(link.Hash, store) + } + + const newDirNode = await removeNodeFromTree( + dirNode, + Path.fromKind(pathKind, ...pathParts.slice(1)), + store + ) + + const dirCID = await Store.store( + DagPB.encode(newDirNode), + DagPB.code, + store + ) + + const links = + link === undefined + ? addLink(node.Links, name, dirCID) + : replaceLinkHash(node.Links, name, dirCID) + + return { ...node, Links: links } + } + + // Last part of path + // ----------------- + if (link === undefined) return node + return { ...node, Links: node.Links.filter((l) => l.Name !== name) } +} + +// ㊙️ + +function addLink(links: PBLink[], name: string, hash: CID): PBLink[] { + return [...links, DagPB.createLink(name, 0, hash)].sort(linkSorter) +} + +function replaceLinkHash(links: PBLink[], name: string, hash: CID): PBLink[] { + return links.map((l) => (l.Name === name ? { ...l, Hash: hash } : l)) +} + +function linkSorter(a: PBLink, b: PBLink): number { + if ((a.Name ?? '') > (b.Name ?? '')) return 1 + if ((a.Name ?? '') < (b.Name ?? '')) return -1 + return 0 +} diff --git a/packages/nest/src/version.ts b/packages/nest/src/version.ts new file mode 100644 index 0000000..de31e9b --- /dev/null +++ b/packages/nest/src/version.ts @@ -0,0 +1,20 @@ +import { compare, satisfies } from 'compare-versions' + +export const isSupported = ( + fsVersion: string +): true | 'too-high' | 'too-low' => { + if (satisfies(fsVersion, `^${latest}`)) { + return true + } else if (compare(fsVersion, latest, '>')) { + return 'too-high' + } + + return 'too-low' +} + +// VERSIONS + +export const v1 = '1.0.0' +export const latest = v1 + +export const supported = [latest] diff --git a/packages/nest/test/class.test.ts b/packages/nest/test/class.test.ts new file mode 100644 index 0000000..d032bf2 --- /dev/null +++ b/packages/nest/test/class.test.ts @@ -0,0 +1,1046 @@ +// eslint-disable @typescript-eslint/no-confusing-void-expression unicorn/no-await-expression-member + +import assert from 'assert' + +import type { Blockstore } from 'interface-blockstore' +import type { CID } from 'multiformats' + +import { MemoryBlockstore } from 'blockstore-core/memory' + +import * as Path from '../src/path.js' +import * as Unix from '../src/unix.js' + +import { FileSystem } from '../src/class.js' + +import { + assertUnixFsDirectory, + assertUnixFsFile, + assertUnixNodeRemoval, +} from './helpers/index.js' + +describe('File System Class', () => { + let blockstore: Blockstore + let fs: FileSystem + let mounts: Array<{ + path: Path.Distinctive + capsuleKey: Uint8Array + }> + + const fsOpts = { + settleTimeBeforePublish: 250, + } + + // HOOKS + // ----- + + beforeEach(async () => { + blockstore = new MemoryBlockstore() + + fs = await FileSystem.create({ + blockstore, + ...fsOpts, + }) + + mounts = await fs.mountPrivateNodes([{ path: Path.root() }]) + }) + + // LOADING + // ------- + + it('loads a file system and capsule keys + content cids', async () => { + const publicPath = Path.file('public', 'nested-public', 'public.txt') + const privatePath = Path.file('private', 'nested-private', 'private.txt') + + const { contentCID } = await fs.write(publicPath, 'utf8', 'public') + const { _capsuleKey, dataRoot } = await fs.write( + privatePath, + 'utf8', + 'private' + ) + + const contentBytes = await Unix.exportFile(contentCID, blockstore) + + assert.equal(new TextDecoder().decode(contentBytes), 'public') + + const loadedFs = await FileSystem.fromCID(dataRoot, { + blockstore, + ...fsOpts, + }) + await loadedFs.mountPrivateNodes([ + // TODO: Needs to be fixed in rs-wnfs + // { path: Path.removePartition(privatePath), capsuleKey }, + { path: Path.root(), capsuleKey: mounts[0].capsuleKey }, + ]) + + assert.equal(await loadedFs.read(publicPath, 'utf8'), 'public') + assert.equal(await loadedFs.read(privatePath, 'utf8'), 'private') + }) + + it('loads a file system and capsule keys + content cids after multiple changes', async () => { + const publicPath = Path.file('public', 'nested-public', 'public.txt') + const privatePath = Path.file('private', 'nested-private', 'private.txt') + + await fs.write(publicPath, 'utf8', 'public') + await fs.write(privatePath, 'utf8', 'private') + + await fs.write(Path.file('public', 'part.two'), 'utf8', 'public-2') + const { dataRoot } = await fs.write( + Path.file('private', 'part.two'), + 'utf8', + 'private-2' + ) + const capsuleKey = await fs.capsuleKey(Path.directory('private')) + + const loadedFs = await FileSystem.fromCID(dataRoot, { + blockstore, + ...fsOpts, + }) + + if (capsuleKey === null || capsuleKey === undefined) { + throw new Error('Expected a capsule key') + } + + await loadedFs.mountPrivateNodes([{ path: Path.root(), capsuleKey }]) + + assert.equal(await loadedFs.read(publicPath, 'utf8'), 'public') + assert.equal(await loadedFs.read(privatePath, 'utf8'), 'private') + }) + + it('loads a private file system given an older capsule key', async () => { + const privatePath = Path.file('private', 'nested-private', 'private.txt') + const oldCapsuleKey = await fs.capsuleKey(Path.directory('private')) + + const { dataRoot } = await fs.write(privatePath, 'utf8', 'private') + + const loadedFs = await FileSystem.fromCID(dataRoot, { + blockstore, + ...fsOpts, + }) + + if (oldCapsuleKey === null || oldCapsuleKey === undefined) { + throw new Error('Expected a capsule key') + } + + await loadedFs.mountPrivateNodes([ + { path: Path.root(), capsuleKey: oldCapsuleKey }, + ]) + + assert.equal(await loadedFs.read(privatePath, 'utf8'), 'private') + + await loadedFs.write(privatePath, 'utf8', 'new content') + + assert.equal(await loadedFs.read(privatePath, 'utf8'), 'new content') + }) + + // READING & WRITING + // ----------------- + + it('writes and reads public files', async () => { + const path = Path.file('public', 'a') + const bytes = new TextEncoder().encode('🚀') + + const { _contentCID } = await fs.write(path, 'bytes', bytes) + + assert.equal(await fs.read(path, 'utf8'), '🚀') + await assertUnixFsFile({ blockstore }, fs, path, bytes) + }) + + it('writes and reads private files', async () => { + const path = Path.file('private', 'a') + + const { _capsuleKey } = await fs.write(path, 'json', { foo: 'bar', a: 1 }) + + assert.deepEqual(await fs.read(path, 'json'), { foo: 'bar', a: 1 }) + }) + + it('writes and reads deeply nested files', async () => { + const pathPublic = Path.file('public', 'a', 'b', 'c.txt') + const pathPrivate = Path.file('private', 'a', 'b', 'c.txt') + + await fs.write(pathPublic, 'utf8', '🌍') + await fs.write(pathPrivate, 'utf8', '🔐') + + assert.equal(await fs.exists(pathPublic), true) + assert.equal(await fs.exists(pathPrivate), true) + + await assertUnixFsFile( + { blockstore }, + fs, + pathPublic, + new TextEncoder().encode('🌍') + ) + }) + + it('creates files', async () => { + await fs.write(Path.file('private', 'File'), 'utf8', '🧞') + await fs.createFile(Path.file('private', 'File'), 'utf8', '🧞') + + assert.equal(await fs.exists(Path.file('private', 'File (1)')), true) + + await fs.createFile(Path.file('private', 'File'), 'utf8', '🧞') + + assert.equal(await fs.exists(Path.file('private', 'File (2)')), true) + + await fs.createFile(Path.file('private', 'File (1)'), 'utf8', '🧞') + + assert.equal(await fs.read(Path.file('private', 'File (3)'), 'utf8'), '🧞') + }) + + it('creates files with extensions', async () => { + await fs.write(Path.file('private', 'File.7z'), 'utf8', '🧞') + await fs.createFile(Path.file('private', 'File.7z'), 'utf8', '🧞') + + assert.equal(await fs.exists(Path.file('private', 'File (1).7z')), true) + + await fs.createFile(Path.file('private', 'File.7z'), 'utf8', '🧞') + + assert.equal(await fs.exists(Path.file('private', 'File (2).7z')), true) + + await fs.createFile(Path.file('private', 'File (1).7z'), 'utf8', '🧞') + + assert.equal( + await fs.read(Path.file('private', 'File (3).7z'), 'utf8'), + '🧞' + ) + }) + + it('retrieves public content using a CID', async () => { + const { contentCID, capsuleCID } = await fs.write( + Path.file('public', 'file'), + 'utf8', + '🌍' + ) + + assert.equal(await fs.read({ contentCID }, 'utf8'), '🌍') + + assert.equal(await fs.read({ capsuleCID }, 'utf8'), '🌍') + }) + + it('retrieves private content using a capsule key', async () => { + const { capsuleKey } = await fs.write( + Path.file('private', 'file'), + 'utf8', + '🔐' + ) + + assert.equal(await fs.read({ capsuleKey }, 'utf8'), '🔐') + }) + + // DIRECTORIES + // ----------- + + it('ensures directories and checks for existence', async () => { + await fs.ensureDirectory(Path.directory('public', 'a')) + await fs.ensureDirectory(Path.directory('public', 'a', 'b')) + await fs.ensureDirectory(Path.directory('public', 'a', 'b', 'c')) + + await fs.ensureDirectory(Path.directory('private', 'a')) + await fs.ensureDirectory(Path.directory('private', 'a', 'b')) + await fs.ensureDirectory(Path.directory('private', 'a', 'b', 'c')) + + assert.equal(await fs.exists(Path.directory('public', 'a')), true) + assert.equal(await fs.exists(Path.directory('public', 'a', 'b')), true) + assert.equal(await fs.exists(Path.directory('public', 'a', 'b', 'c')), true) + + assert.equal(await fs.exists(Path.directory('private', 'a')), true) + assert.equal(await fs.exists(Path.directory('private', 'a', 'b')), true) + assert.equal( + await fs.exists(Path.directory('private', 'a', 'b', 'c')), + true + ) + + // Does not throw for existing dirs + await fs.ensureDirectory(Path.directory('public', 'a')) + await fs.ensureDirectory(Path.directory('public', 'a', 'b')) + + await fs.ensureDirectory(Path.directory('private', 'a')) + await fs.ensureDirectory(Path.directory('private', 'a', 'b')) + + await assertUnixFsDirectory( + { blockstore }, + fs, + Path.directory('public', 'a') + ) + await assertUnixFsDirectory( + { blockstore }, + fs, + Path.directory('public', 'a', 'b') + ) + }) + + it('lists public directories', async () => { + await fs.ensureDirectory(Path.directory('public', 'a')) + await fs.write(Path.file('public', 'a-file'), 'utf8', '🧞') + await fs.ensureDirectory(Path.directory('public', 'a', 'b')) + await fs.write(Path.file('public', 'a', 'b-file'), 'utf8', '💃') + + const a = await fs.listDirectory(Path.directory('public')) + assert.deepEqual( + a.map((i) => i.name), + ['a', 'a-file'] + ) + + const b = await fs.listDirectory(Path.directory('public', 'a')) + assert.deepEqual( + b.map((i) => i.name), + ['b', 'b-file'] + ) + }) + + it('lists public directories with item kind', async () => { + const pathDirA = Path.directory('public', 'a') + const pathFileA = Path.file('public', 'a-file') + const pathDirB = Path.directory('public', 'a', 'b') + const pathFileB = Path.file('public', 'a', 'b-file') + + await fs.ensureDirectory(pathDirA) + await fs.write(pathFileA, 'utf8', '🧞') + await fs.ensureDirectory(pathDirB) + await fs.write(pathFileB, 'utf8', '💃') + + const a = await fs.listDirectory(Path.directory('public'), { + withItemKind: true, + }) + assert.deepEqual( + a.map((i) => i.kind), + [Path.Kind.Directory, Path.Kind.File] + ) + assert.deepEqual( + a.map((i) => i.path), + [pathDirA, pathFileA] + ) + + const b = await fs.listDirectory(Path.directory('public', 'a'), { + withItemKind: true, + }) + assert.deepEqual( + b.map((i) => i.kind), + [Path.Kind.Directory, Path.Kind.File] + ) + assert.deepEqual( + b.map((i) => i.path), + [pathDirB, pathFileB] + ) + }) + + it('lists private directories', async () => { + await fs.ensureDirectory(Path.directory('private', 'a')) + await fs.write(Path.file('private', 'a-file'), 'utf8', '🧞') + await fs.ensureDirectory(Path.directory('private', 'a', 'b')) + await fs.write(Path.file('private', 'a', 'b-file'), 'utf8', '💃') + + const a = await fs.listDirectory(Path.directory('private')) + assert.deepEqual( + a.map((i) => i.name), + ['a', 'a-file'] + ) + + const b = await fs.listDirectory(Path.directory('private', 'a')) + assert.deepEqual( + b.map((i) => i.name), + ['b', 'b-file'] + ) + }) + + it('lists private directories with item kind', async () => { + const pathDirA = Path.directory('private', 'a') + const pathFileA = Path.file('private', 'a-file') + const pathDirB = Path.directory('private', 'a', 'b') + const pathFileB = Path.file('private', 'a', 'b-file') + + await fs.ensureDirectory(pathDirA) + await fs.write(pathFileA, 'utf8', '🧞') + await fs.ensureDirectory(pathDirB) + await fs.write(pathFileB, 'utf8', '💃') + + const a = await fs.listDirectory(Path.directory('private'), { + withItemKind: true, + }) + assert.deepEqual( + a.map((i) => i.kind), + [Path.Kind.Directory, Path.Kind.File] + ) + assert.deepEqual( + a.map((i) => i.path), + [pathDirA, pathFileA] + ) + + const b = await fs.listDirectory(Path.directory('private', 'a'), { + withItemKind: true, + }) + assert.deepEqual( + b.map((i) => i.kind), + [Path.Kind.Directory, Path.Kind.File] + ) + assert.deepEqual( + b.map((i) => i.path), + [pathDirB, pathFileB] + ) + }) + + it('creates directories', async () => { + await fs.ensureDirectory(Path.directory('private', 'Directory')) + await fs.createDirectory(Path.directory('private', 'Directory')) + + assert.equal( + await fs.exists(Path.directory('private', 'Directory (1)')), + true + ) + + await fs.createDirectory(Path.directory('private', 'Directory')) + + assert.equal( + await fs.exists(Path.directory('private', 'Directory (2)')), + true + ) + + await fs.createDirectory(Path.directory('private', 'Directory (1)')) + + assert.equal( + await fs.exists(Path.directory('private', 'Directory (3)')), + true + ) + }) + + it('creates directories with extensions', async () => { + await fs.ensureDirectory(Path.directory('private', 'Directory.7z')) + await fs.createDirectory(Path.directory('private', 'Directory.7z')) + + assert.equal( + await fs.exists(Path.directory('private', 'Directory.7z (1)')), + true + ) + + await fs.createDirectory(Path.directory('private', 'Directory.7z')) + + assert.equal( + await fs.exists(Path.directory('private', 'Directory.7z (2)')), + true + ) + + await fs.createDirectory(Path.directory('private', 'Directory.7z (1)')) + + assert.equal( + await fs.exists(Path.directory('private', 'Directory.7z (3)')), + true + ) + }) + + // CIDS & REFS + // ----------- + + it('can get a content CID for an existing public file', async () => { + const path = Path.file('public', 'a', 'b', 'file') + + const { contentCID } = await fs.write(path, 'utf8', '💃') + const cid = await fs.contentCID(path) + + assert.equal(cid?.toString(), contentCID.toString()) + }) + + it('can get a capsule CID for an existing public file', async () => { + const path = Path.file('public', 'a', 'b', 'file') + + const { capsuleCID } = await fs.write(path, 'utf8', '💃') + const cid = await fs.capsuleCID(path) + + assert.equal(cid?.toString(), capsuleCID.toString()) + }) + + it('can get a capsule CID for an existing public directory', async () => { + const path = Path.directory('public', 'a', 'b', 'directory') + + const { capsuleCID } = await fs.ensureDirectory(path) + const cid = await fs.capsuleCID(path) + + assert.equal(cid?.toString(), capsuleCID.toString()) + }) + + it('can get a capsule key for an existing private file', async () => { + const path = Path.file('private', 'a', 'b', 'file') + + const { capsuleKey } = await fs.write(path, 'utf8', '💃') + const key = await fs.capsuleKey(path) + + assert.equal( + key === undefined ? undefined : JSON.stringify(key), + JSON.stringify(capsuleKey) + ) + }) + + it('can get a capsule CID for an existing private directory', async () => { + const path = Path.directory('private', 'a', 'b', 'directory') + + const { capsuleKey } = await fs.ensureDirectory(path) + const key = await fs.capsuleKey(path) + + assert.equal( + key === undefined ? undefined : JSON.stringify(key), + JSON.stringify(capsuleKey) + ) + }) + + it('can get a capsule CID for a mounted private directory', async () => { + const path = Path.directory('private') + const key = await fs.capsuleKey(path) + + assert.notEqual( + key === undefined ? undefined : JSON.stringify(key), + undefined + ) + }) + + // REMOVE + // ------ + + it('removes public files', async () => { + const path = Path.file('public', 'a', 'b', 'file') + + await fs.write(path, 'utf8', '💃') + await fs.remove(path) + + assert.equal(await fs.exists(path), false) + + await assertUnixNodeRemoval({ blockstore }, fs, path) + }) + + it('removes private files', async () => { + const path = Path.file('private', 'a', 'b', 'file') + + await fs.write(path, 'utf8', '💃') + await fs.remove(path) + + assert.equal(await fs.exists(path), false) + }) + + it('removes public directories', async () => { + const path = Path.directory('public', 'a', 'b', 'directory') + + await fs.ensureDirectory(path) + await fs.remove(path) + + assert.equal(await fs.exists(path), false) + + await assertUnixNodeRemoval({ blockstore }, fs, path) + }) + + it('removes private directories', async () => { + const path = Path.directory('private', 'a', 'b', 'directory') + + await fs.ensureDirectory(path) + await fs.remove(path) + + assert.equal(await fs.exists(path), false) + }) + + // COPYING + // ------- + + it('copies public files', async () => { + const fromPath = Path.file('public', 'a', 'b', 'file') + const toPath = Path.file('public', 'a', 'b', 'c', 'd', 'file') + + await fs.write(fromPath, 'utf8', '💃') + await fs.copy(fromPath, toPath) + + assert.equal(await fs.read(toPath, 'utf8'), '💃') + }) + + it('copies public files into a directory that already exists', async () => { + await fs.ensureDirectory(Path.directory('public', 'a', 'b', 'c', 'd')) + + const fromPath = Path.file('public', 'a', 'b', 'file') + const toPath = Path.file('public', 'a', 'b', 'c', 'd', 'file') + + await fs.write(fromPath, 'utf8', '💃') + await fs.copy(fromPath, toPath) + + assert.equal(await fs.read(toPath, 'utf8'), '💃') + }) + + it('copies private files', async () => { + const fromPath = Path.file('private', 'a', 'b', 'file') + const toPath = Path.file('private', 'a', 'b', 'c', 'd', 'file') + + await fs.write(fromPath, 'utf8', '💃') + await fs.copy(fromPath, toPath) + + assert.equal(await fs.read(toPath, 'utf8'), '💃') + }) + + it('copies private files into a directory that already exists', async () => { + await fs.ensureDirectory(Path.directory('private', 'a', 'b', 'c', 'd')) + + const fromPath = Path.file('private', 'a', 'b', 'file') + const toPath = Path.file('private', 'a', 'b', 'c', 'd', 'file') + + await fs.write(fromPath, 'utf8', '💃') + await fs.copy(fromPath, toPath) + + assert.equal(await fs.read(toPath, 'utf8'), '💃') + }) + + it('copies public directories', async () => { + const fromPath = Path.directory('public', 'b', 'c') + const toPath = Path.directory('public', 'a', 'b', 'c', 'd', 'e') + + await fs.write(Path.combine(fromPath, Path.file('file')), 'utf8', '💃') + await fs.write( + Path.combine(fromPath, Path.file('nested', 'file')), + 'utf8', + '🧞' + ) + await fs.ensureDirectory( + Path.combine(fromPath, Path.directory('nested-empty')) + ) + await fs.ensureDirectory( + Path.combine(fromPath, Path.directory('nested-2', 'deeply-nested')) + ) + + await fs.copy(fromPath, toPath) + + assert.equal( + await fs.read(Path.combine(toPath, Path.file('file')), 'utf8'), + '💃' + ) + + assert.equal( + await fs.read(Path.combine(toPath, Path.file('nested', 'file')), 'utf8'), + '🧞' + ) + + assert.equal( + await fs.exists(Path.combine(toPath, Path.directory('nested-empty'))), + true + ) + + assert.equal( + await fs.exists( + Path.combine(toPath, Path.directory('nested-2', 'deeply-nested')) + ), + true + ) + + await fs.copy(Path.directory('public', 'a', 'b'), Path.directory('public')) + + assert.equal( + await fs.exists( + Path.directory('public', 'b', 'c', 'nested-2', 'deeply-nested') + ), + true + ) + }) + + it('copies private directories', async () => { + const fromPath = Path.directory('private', 'b', 'c') + const toPath = Path.directory('private', 'a', 'b', 'c', 'd', 'e') + + await fs.write(Path.combine(fromPath, Path.file('file')), 'utf8', '💃') + await fs.write( + Path.combine(fromPath, Path.file('nested', 'file')), + 'utf8', + '🧞' + ) + await fs.ensureDirectory( + Path.combine(fromPath, Path.directory('nested-empty')) + ) + await fs.ensureDirectory( + Path.combine(fromPath, Path.directory('nested-2', 'deeply-nested')) + ) + + await fs.copy(fromPath, toPath) + + assert.equal( + await fs.read(Path.combine(toPath, Path.file('file')), 'utf8'), + '💃' + ) + + assert.equal( + await fs.read(Path.combine(toPath, Path.file('nested', 'file')), 'utf8'), + '🧞' + ) + + assert.equal( + await fs.exists(Path.combine(toPath, Path.directory('nested-empty'))), + true + ) + + assert.equal( + await fs.exists( + Path.combine(toPath, Path.directory('nested-2', 'deeply-nested')) + ), + true + ) + + await fs.copy(Path.directory('private', 'a'), Path.directory('private')) + + assert.equal( + await fs.exists( + Path.directory('private', 'b', 'c', 'nested-2', 'deeply-nested') + ), + true + ) + }) + + // MOVING + // ------ + + it('moves public files', async () => { + const fromPath = Path.file('public', 'a', 'b', 'file') + const toPath = Path.file('public', 'a', 'b', 'c', 'd', 'file') + + await fs.write(fromPath, 'utf8', '💃') + await fs.move(fromPath, toPath) + + assert.equal(await fs.read(toPath, 'utf8'), '💃') + assert.equal(await fs.exists(fromPath), false) + }) + + it('moves private files', async () => { + const fromPath = Path.file('private', 'a', 'b', 'file') + const toPath = Path.file('private', 'a', 'b', 'c', 'd', 'file') + + await fs.write(fromPath, 'utf8', '💃') + await fs.move(fromPath, toPath) + + assert.equal(await fs.read(toPath, 'utf8'), '💃') + assert.equal(await fs.exists(fromPath), false) + }) + + it('moves public directories', async () => { + const fromPath = Path.directory('public', 'b', 'c') + const toPath = Path.directory('public', 'a', 'b', 'c', 'd', 'e') + + await fs.write(Path.combine(fromPath, Path.file('file')), 'utf8', '💃') + await fs.write( + Path.combine(fromPath, Path.file('nested', 'file')), + 'utf8', + '🧞' + ) + await fs.ensureDirectory( + Path.combine(fromPath, Path.directory('nested-empty')) + ) + await fs.ensureDirectory( + Path.combine(fromPath, Path.directory('nested-2', 'deeply-nested')) + ) + + await fs.move(fromPath, toPath) + + assert.equal( + await fs.read(Path.combine(toPath, Path.file('file')), 'utf8'), + '💃' + ) + + assert.equal( + await fs.read(Path.combine(toPath, Path.file('nested', 'file')), 'utf8'), + '🧞' + ) + + assert.equal( + await fs.exists(Path.combine(toPath, Path.directory('nested-empty'))), + true + ) + + assert.equal( + await fs.exists( + Path.combine(toPath, Path.directory('nested-2', 'deeply-nested')) + ), + true + ) + + assert.equal(await fs.exists(fromPath), false) + + await fs.move(Path.directory('public', 'a'), Path.directory('public')) + + assert.equal( + await fs.exists( + Path.directory('public', 'b', 'c', 'nested-2', 'deeply-nested') + ), + false + ) + + assert.equal(await fs.exists(Path.directory('public', 'a')), false) + + assert.equal( + await fs.exists( + Path.directory( + 'public', + 'a', + 'b', + 'c', + 'd', + 'e', + 'nested-2', + 'deeply-nested' + ) + ), + false + ) + }) + + it('moves private directories', async () => { + const fromPath = Path.directory('private', 'b', 'c') + const toPath = Path.directory('private', 'a', 'b', 'c', 'd', 'e') + + await fs.write(Path.combine(fromPath, Path.file('file')), 'utf8', '💃') + await fs.write( + Path.combine(fromPath, Path.file('nested', 'file')), + 'utf8', + '🧞' + ) + await fs.ensureDirectory( + Path.combine(fromPath, Path.directory('nested-empty')) + ) + await fs.ensureDirectory( + Path.combine(fromPath, Path.directory('nested-2', 'deeply-nested')) + ) + + await fs.move(fromPath, toPath) + + assert.equal( + await fs.read(Path.combine(toPath, Path.file('file')), 'utf8'), + '💃' + ) + + assert.equal( + await fs.read(Path.combine(toPath, Path.file('nested', 'file')), 'utf8'), + '🧞' + ) + + assert.equal( + await fs.exists(Path.combine(toPath, Path.directory('nested-empty'))), + true + ) + + assert.equal( + await fs.exists( + Path.combine(toPath, Path.directory('nested-2', 'deeply-nested')) + ), + true + ) + + assert.equal(await fs.exists(fromPath), false) + + await fs.move(Path.directory('private', 'a'), Path.directory('private')) + + assert.equal( + await fs.exists( + Path.directory('public', 'b', 'c', 'nested-2', 'deeply-nested') + ), + false + ) + + assert.equal(await fs.exists(Path.directory('public', 'a')), false) + + assert.equal( + await fs.exists( + Path.directory( + 'public', + 'a', + 'b', + 'c', + 'd', + 'e', + 'nested-2', + 'deeply-nested' + ) + ), + false + ) + }) + + it('moves a public file to the private partition', async () => { + const fromPath = Path.file('public', 'a', 'b', 'file') + const toPath = Path.file('private', 'a', 'b', 'c', 'd', 'file') + + const { _capsuleCID } = await fs.write(fromPath, 'utf8', '💃') + const { _capsuleKey } = await fs.move(fromPath, toPath) + + assert.equal(await fs.read(toPath, 'utf8'), '💃') + assert.equal(await fs.exists(fromPath), false) + }) + + it('moves a private file to the public partition', async () => { + const fromPath = Path.file('private', 'a', 'b', 'file') + const toPath = Path.file('public', 'a', 'b', 'c', 'd', 'file') + + const { _capsuleKey } = await fs.write(fromPath, 'utf8', '💃') + const { _capsuleCID } = await fs.move(fromPath, toPath) + + assert.equal(await fs.read(toPath, 'utf8'), '💃') + assert.equal(await fs.exists(fromPath), false) + }) + + // RENAMING + // -------- + + it('renames public files', async () => { + await fs.write(Path.file('public', 'a'), 'bytes', new Uint8Array()) + await fs.rename(Path.file('public', 'a'), 'b') + + assert.equal(await fs.exists(Path.file('public', 'a')), false) + + assert.equal(await fs.exists(Path.file('public', 'b')), true) + }) + + it('renames private files', async () => { + await fs.write(Path.file('private', 'a'), 'bytes', new Uint8Array()) + await fs.rename(Path.file('private', 'a'), 'b') + + assert.equal(await fs.exists(Path.file('private', 'a')), false) + + assert.equal(await fs.exists(Path.file('private', 'b')), true) + }) + + it('renames public directories', async () => { + await fs.ensureDirectory(Path.directory('public', 'a')) + await fs.rename(Path.directory('public', 'a'), 'b') + + assert.equal(await fs.exists(Path.directory('public', 'a')), false) + + assert.equal(await fs.exists(Path.directory('public', 'b')), true) + }) + + it('renames private directories', async () => { + await fs.ensureDirectory(Path.directory('private', 'a')) + await fs.rename(Path.directory('private', 'a'), 'b') + + assert.equal(await fs.exists(Path.directory('private', 'a')), false) + + assert.equal(await fs.exists(Path.directory('private', 'b')), true) + }) + + // PUBLISHING + // ---------- + + it('publishes & debounces by default', async () => { + await new Promise((resolve) => + setTimeout(resolve, fsOpts.settleTimeBeforePublish * 1.5) + ) + + const promise = new Promise((resolve, reject) => { + setTimeout(reject, 10_000) + fs.once('publish') + .then((event) => event.dataRoot) + .then(resolve, reject) + }) + + const a = await fs.write( + Path.file('private', 'a'), + 'bytes', + new Uint8Array() + ) + const b = await fs.write( + Path.file('private', 'b'), + 'bytes', + new Uint8Array() + ) + const c = await fs.write( + Path.file('private', 'c'), + 'bytes', + new Uint8Array() + ) + const d = await fs.write( + Path.file('private', 'd'), + 'bytes', + new Uint8Array() + ) + + assert.equal((await promise).toString(), d.dataRoot.toString()) + }) + + it("doesn't publish when asked not to do so", async () => { + let published = false + + fs.on('publish', () => { + published = true + }) + + await fs.mkdir(Path.directory('private', 'dir'), { skipPublish: true }) + await fs.write(Path.file('public', 'file'), 'bytes', new Uint8Array(), { + skipPublish: true, + }) + await fs.cp(Path.file('public', 'file'), Path.file('private', 'file'), { + skipPublish: true, + }) + await fs.mv( + Path.file('private', 'file'), + Path.file('private', 'dir', 'file'), + { skipPublish: true } + ) + await fs.rename(Path.file('private', 'dir', 'file'), 'renamed', { + skipPublish: true, + }) + await fs.rm(Path.file('private', 'dir', 'renamed'), { skipPublish: true }) + + await new Promise((resolve) => + setTimeout(resolve, fsOpts.settleTimeBeforePublish * 1.5) + ) + + assert.equal(published, false) + }) + + // EVENTS + // ------ + // Other than "publish" + + it('emits an event for a mutation', async () => { + const eventPromise: Promise = new Promise((resolve, reject) => { + setTimeout(reject, 10000) + + fs.on('local-change', ({ dataRoot }) => { + resolve(dataRoot) + }) + }) + + const mutationResult = await fs.write( + Path.file('private', 'file'), + 'bytes', + new Uint8Array() + ) + + assert.equal( + (await eventPromise).toString(), + mutationResult.dataRoot.toString() + ) + }) + + // TRANSACTIONS + // ------------ + + it('commits a transaction', async () => { + await fs.transaction(async (t) => { + await t.write(Path.file('private', 'file'), 'utf8', '💃') + await t.write( + Path.file('public', 'file'), + 'bytes', + await t.read(Path.file('private', 'file'), 'bytes') + ) + }) + + assert.equal(await fs.read(Path.file('public', 'file'), 'utf8'), '💃') + }) + + async function transaction(): Promise { + await fs + .transaction(async (t) => { + await t.write(Path.file('private', 'file'), 'utf8', '💃') + throw new Error('Whoops') + }) + .catch((_error) => {}) + } + + // it("doesn't commit a transaction when an error occurs inside of the transaction", async () => { + // const tracker = new assert.CallTracker() + // const tracked = tracker.calls(transaction, 1) + + // await tracked() + // tracker.verify() + + // try { + // await fs.read(Path.file('private', 'file'), 'utf8') + // } catch (error) { + // assert(error) + // } + // }) +}) diff --git a/packages/nest/test/helpers/index.ts b/packages/nest/test/helpers/index.ts new file mode 100644 index 0000000..b53fcca --- /dev/null +++ b/packages/nest/test/helpers/index.ts @@ -0,0 +1,116 @@ +import assert from 'assert' +import all from 'it-all' + +import * as fc from 'fast-check' +import * as UnixExporter from 'ipfs-unixfs-exporter' +import * as Uint8Arrays from 'uint8arrays' + +import type { FileSystem } from '../../src/class.js' +import { linksFromCID } from '../../src/root-tree/basic.js' +import * as Path from '../../src/path.js' +import type { Blockstore } from 'interface-blockstore' + +// PATHS + +export function arbitraryDirectoryPath

( + partition: P +): fc.Arbitrary>> { + return fc + .array(arbitraryPathSegment(), { minLength: 1, maxLength: 8 }) + .map((array) => { + const path: Path.Directory> = { + directory: [partition, ...array], + } + return path + }) +} + +export function arbitraryFilePath

( + partition: P +): fc.Arbitrary>> { + return fc + .array(arbitraryPathSegment(), { minLength: 1, maxLength: 8 }) + .map((array) => { + const path: Path.File> = { + file: [partition, ...array], + } + return path + }) +} + +export function arbitraryPathSegment(): fc.Arbitrary { + return fc.oneof( + fc.webSegment().filter((segment) => segment.length > 0), + fc.constantFrom('a', 'b', 'c') // to generate more 'collisions' + ) +} + +// UNIX + +export async function assertUnixFsDirectory( + opts: { blockstore: Blockstore }, + fs: FileSystem, + path: Path.Directory> +): Promise { + const dataRoot = await fs.calculateDataRoot() + + const rootTree = await linksFromCID(dataRoot, opts.blockstore) + const unixRoot = rootTree.unix + + const pathString = Path.toPosix(Path.removePartition(path), { + absolute: true, + }) + const entry = await UnixExporter.exporter( + `${unixRoot.toString()}${pathString}`, + opts.blockstore + ) + + assert.equal(entry.type, 'directory') +} + +export async function assertUnixFsFile( + opts: { blockstore: Blockstore }, + fs: FileSystem, + path: Path.File>, + bytes: Uint8Array +): Promise { + const dataRoot = await fs.calculateDataRoot() + + const rootTree = await linksFromCID(dataRoot, opts.blockstore) + const unixRoot = rootTree.unix + + const pathString = Path.toPosix(Path.removePartition(path), { + absolute: true, + }) + const entry = await UnixExporter.exporter( + `${unixRoot.toString()}${pathString}`, + opts.blockstore + ) + const unixBytes = Uint8Arrays.concat(await all(entry.content())) + + assert.equal(Uint8Arrays.equals(unixBytes, bytes), true) +} + +export async function assertUnixNodeRemoval( + opts: { blockstore: Blockstore }, + fs: FileSystem, + path: Path.Distinctive> +): Promise { + const dataRoot = await fs.calculateDataRoot() + + const rootTree = await linksFromCID(dataRoot, opts.blockstore) + const unixRoot = rootTree.unix + + const pathString = Path.toPosix(Path.removePartition(path), { + absolute: true, + }) + + try { + const _entry = await UnixExporter.exporter( + `${unixRoot.toString()}${pathString}`, + opts.blockstore + ) + } catch (error) { + assert(error.toString(), 'File does not exist') + } +} diff --git a/packages/nest/test/path.test.ts b/packages/nest/test/path.test.ts new file mode 100644 index 0000000..9969365 --- /dev/null +++ b/packages/nest/test/path.test.ts @@ -0,0 +1,377 @@ +import { strict as assert } from 'assert' +import * as fc from 'fast-check' + +import type { DirectoryPath, FilePath } from '../src/path.js' +import * as Path from '../src/path.js' +import { RootBranch } from '../src/path.js' + +describe('Path functions', () => { + // CREATION + + it('creates directory paths', () => { + fc.assert( + fc.property(fc.array(fc.hexaString()), (data) => { + assert.deepEqual(Path.directory(...data), { directory: data }) + }) + ) + + assert.throws(() => Path.directory('/')) + + // Type testing + const _a: Path.Directory> = + Path.directory('private') + const _b: Path.Directory> = + Path.directory('public', 'a') + const _c: Path.Directory = Path.directory( + 'private', + 'a', + 'b' + ) + }) + + it('creates file paths', () => { + fc.assert( + fc.property(fc.array(fc.hexaString()), (data) => { + assert.deepEqual(Path.file(...data), { file: data }) + }) + ) + + assert.throws(() => Path.file('/')) + + // Type testing + const _a: Path.File> = Path.file( + 'private', + 'a' + ) + const _b: Path.File = Path.file('private', 'a', 'b') + }) + + it('creates directory paths with fromKind', () => { + fc.assert( + fc.property(fc.array(fc.hexaString()), (data) => { + assert.deepEqual(Path.fromKind(Path.Kind.Directory, ...data), { + directory: data, + }) + }) + ) + + // Type testing + const _a: Path.Directory> = Path.fromKind( + Path.Kind.Directory, + 'private' + ) + const _b: Path.Directory> = + Path.fromKind(Path.Kind.Directory, 'public', 'a') + const _c: Path.Directory = Path.fromKind( + Path.Kind.Directory, + 'private', + 'a', + 'b' + ) + }) + + it('creates file paths with fromKind', () => { + fc.assert( + fc.property(fc.array(fc.hexaString()), (data) => { + assert.deepEqual(Path.fromKind(Path.Kind.File, ...data), { file: data }) + }) + ) + + // Type testing + const _a: Path.File> = Path.fromKind( + Path.Kind.File, + 'private', + 'a' + ) + const _b: Path.File = Path.fromKind( + Path.Kind.File, + 'private', + 'a', + 'b' + ) + }) + + // POSIX + + it('creates a path from a POSIX formatted string', () => { + assert.deepEqual(Path.fromPosix('foo/bar/'), { directory: ['foo', 'bar'] }) + + assert.deepEqual(Path.fromPosix('/foo/bar/'), { directory: ['foo', 'bar'] }) + + assert.deepEqual(Path.fromPosix('/'), { directory: [] }) + + assert.deepEqual(Path.fromPosix('foo/bar'), { file: ['foo', 'bar'] }) + + assert.deepEqual(Path.fromPosix('/foo/bar'), { file: ['foo', 'bar'] }) + }) + + it('converts a path to the POSIX format', () => { + assert.equal(Path.toPosix({ directory: ['foo', 'bar'] }), 'foo/bar/') + + assert.equal(Path.toPosix({ directory: [] }), '') + + assert.equal(Path.toPosix({ file: ['foo', 'bar'] }), 'foo/bar') + }) + + // 🛠 + + it('can create app-data paths', () => { + const appInfo = { + name: 'Tests', + creator: 'Fission', + } + + const root: DirectoryPath> = + Path.appData('private', appInfo) + + assert.deepEqual(root, { + directory: [RootBranch.Private, 'Apps', appInfo.creator, appInfo.name], + }) + + const dir: DirectoryPath> = + Path.appData('private', appInfo, Path.directory('a')) + + assert.deepEqual(dir, { + directory: [ + RootBranch.Private, + 'Apps', + appInfo.creator, + appInfo.name, + 'a', + ], + }) + + const file: FilePath> = Path.appData( + 'public', + appInfo, + Path.file('a') + ) + + assert.deepEqual(file, { + file: [RootBranch.Public, 'Apps', appInfo.creator, appInfo.name, 'a'], + }) + }) + + it('can be combined', () => { + const dir: DirectoryPath = Path.combine( + Path.directory('a'), + Path.directory('b') + ) + + assert.deepEqual(dir, { directory: ['a', 'b'] }) + + const file: FilePath = Path.combine( + Path.directory('a'), + Path.file('b') + ) + + assert.deepEqual(file, { file: ['a', 'b'] }) + + // Type testing + const _a: DirectoryPath> = + Path.combine(Path.directory('private'), Path.directory('a')) + + const _aa: FilePath> = Path.combine( + Path.directory('public'), + Path.file('a') + ) + + const _b: DirectoryPath> = Path.combine( + Path.directory('private'), + Path.directory() + ) + + const _bb: FilePath> = Path.combine( + Path.directory('public'), + Path.file() + ) + + const _c: DirectoryPath> = + Path.combine(Path.directory('private'), Path.directory('a')) + + const _cc: FilePath> = Path.combine( + Path.directory('public'), + Path.file('a') + ) + }) + + it('supports isOnRootBranch', () => { + assert.equal( + Path.isOnRootBranch( + RootBranch.Private, + Path.directory(RootBranch.Private, 'a') + ), + true + ) + + assert.equal( + Path.isOnRootBranch( + RootBranch.Public, + Path.directory(RootBranch.Private, 'a') + ), + false + ) + }) + + it('supports isDirectory', () => { + assert.equal(Path.isDirectory(Path.directory(RootBranch.Private)), true) + + assert.equal(Path.isDirectory(Path.file('foo')), false) + }) + + it('supports isFile', () => { + assert.equal(Path.isFile(Path.file('foo')), true) + + assert.equal(Path.isFile(Path.directory(RootBranch.Private)), false) + }) + + it('supports isRootDirectory', () => { + assert.equal(Path.isRootDirectory(Path.root()), true) + + assert.equal(Path.isRootDirectory(Path.directory()), true) + + assert.equal( + Path.isRootDirectory(Path.directory(RootBranch.Private)), + false + ) + }) + + it('supports isSamePartition', () => { + assert.equal( + Path.isSamePartition( + Path.directory(RootBranch.Private), + Path.directory(RootBranch.Private) + ), + true + ) + + assert.equal( + Path.isSamePartition( + Path.directory(RootBranch.Private), + Path.directory(RootBranch.Public) + ), + false + ) + }) + + it('supports isSameKind', () => { + assert.equal(Path.isSameKind(Path.directory(), Path.file()), false) + + assert.equal(Path.isSameKind(Path.file(), Path.directory()), false) + + assert.equal(Path.isSameKind(Path.directory(), Path.directory()), true) + + assert.equal(Path.isSameKind(Path.file(), Path.file()), true) + }) + + it('has kind', () => { + assert.equal(Path.kind(Path.directory()), Path.Kind.Directory) + + assert.equal(Path.kind(Path.file()), Path.Kind.File) + }) + + it('supports map', () => { + assert.deepEqual( + Path.map((p) => [...p, 'bar'], Path.directory('foo')), + { directory: ['foo', 'bar'] } + ) + + assert.deepEqual( + Path.map((p) => [...p, 'bar'], Path.file('foo')), + { file: ['foo', 'bar'] } + ) + }) + + it('supports parent', () => { + assert.deepEqual(Path.parent(Path.directory('foo')), Path.root()) + + assert.deepEqual(Path.parent(Path.file('foo')), Path.root()) + + assert.equal(Path.parent(Path.root()), undefined) + + // Type testing + const _a: DirectoryPath> = + Path.parent({ + directory: ['private', 'a', 'b'], + }) + + const _a_: DirectoryPath = Path.parent({ + directory: ['random', 'a', 'b'], + }) + + const _b: DirectoryPath> = Path.parent({ + directory: ['private', 'a'], + }) + + const _b_: DirectoryPath = Path.parent({ + directory: ['random', 'a'], + }) + + const _c: DirectoryPath = Path.parent({ + directory: ['private'], + }) + + const _c_: DirectoryPath = Path.parent({ + directory: ['random'], + }) + + // const _x: undefined = Path.parent({ + // directory: [], + // }) + }) + + it('supports removePartition', () => { + assert.deepEqual(Path.removePartition(Path.directory('foo')), { + directory: [], + }) + + assert.deepEqual( + Path.removePartition(Path.directory('foo', 'bar')), + Path.directory('bar') + ) + }) + + it('supports replaceTerminus', () => { + assert.deepEqual( + Path.replaceTerminus(Path.file('private', 'a', 'b'), 'c'), + Path.file('private', 'a', 'c') + ) + + // Type testing + const _a: DirectoryPath> = + Path.replaceTerminus( + { + directory: ['private', 'a'], + }, + 'b' + ) + + const _b: FilePath> = + Path.replaceTerminus( + { + file: ['private', 'a'], + }, + 'b' + ) + + const _c: DirectoryPath = Path.replaceTerminus( + { + directory: ['a'], + }, + 'b' + ) + + const _d: FilePath = Path.replaceTerminus( + { + file: ['a'], + }, + 'b' + ) + }) + + it('correctly unwraps', () => { + assert.deepEqual(Path.unwrap(Path.directory('foo')), ['foo']) + + assert.deepEqual(Path.unwrap(Path.file('foo')), ['foo']) + }) +}) diff --git a/packages/nest/tsconfig.json b/packages/nest/tsconfig.json new file mode 100644 index 0000000..dd412b7 --- /dev/null +++ b/packages/nest/tsconfig.json @@ -0,0 +1,26 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "dist", + "module": "NodeNext", + "moduleResolution": "NodeNext" + }, + "include": [ + "src", + "test" + ], + "exclude": [ + "node_modules", + "dist", + "out" + ], + "typedocOptions": { + "entryPoints": [ + "src/index.js", + "src/module1.js" + ], + "includeVersion": true, + "excludeExternals": true, + "internalModule": "" + } +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 0000000..331d856 --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,5983 @@ +lockfileVersion: '6.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + devDependencies: + '@fission-codes/eslint-config': + specifier: ^0.0.3 + version: 0.0.3 + depcheck: + specifier: ^1.4.7 + version: 1.4.7 + lint-staged: + specifier: ^15.1.0 + version: 15.1.0 + prettier: + specifier: 3.1.1 + version: 3.1.1 + simple-git-hooks: + specifier: ^2.9.0 + version: 2.9.0 + typedoc: + specifier: ^0.25.4 + version: 0.25.4(typescript@5.2.2) + typedoc-plugin-missing-exports: + specifier: ^2.1.0 + version: 2.1.0(typedoc@0.25.4) + typedoc-plugin-zod: + specifier: ^1.1.0 + version: 1.1.0(typedoc@0.25.4) + typescript: + specifier: 5.2.2 + version: 5.2.2 + + examples/demo: + dependencies: + package1: + specifier: '*' + version: link:../../packages/nest + devDependencies: + '@babel/core': + specifier: ^7.23.5 + version: 7.23.5 + '@types/node': + specifier: ^20.10.4 + version: 20.10.4 + typescript: + specifier: 5.2.2 + version: 5.2.2 + vite: + specifier: ^5.0.7 + version: 5.0.7(@types/node@20.10.4) + + packages/nest: + dependencies: + '@ipld/dag-cbor': + specifier: ^9.0.6 + version: 9.0.6 + '@ipld/dag-pb': + specifier: ^4.0.6 + version: 4.0.6 + compare-versions: + specifier: ^6.1.0 + version: 6.1.0 + debounce: + specifier: ^2.0.0 + version: 2.0.0 + emittery: + specifier: ^1.0.1 + version: 1.0.1 + interface-blockstore: + specifier: ^5.2.7 + version: 5.2.7 + ipfs-unixfs: + specifier: ^11.1.0 + version: 11.1.0 + ipfs-unixfs-exporter: + specifier: ^13.2.2 + version: 13.2.2 + ipfs-unixfs-importer: + specifier: ^15.2.1 + version: 15.2.1 + iso-base: + specifier: ^2.0.1 + version: 2.0.1 + it-all: + specifier: ^3.0.4 + version: 3.0.4 + multiformats: + specifier: ^12.1.3 + version: 12.1.3 + uint8arrays: + specifier: ^5.0.0 + version: 5.0.0 + wnfs: + specifier: ^0.1.27 + version: 0.1.27 + devDependencies: + '@types/assert': + specifier: ^1.5.9 + version: 1.5.9 + '@types/debounce-promise': + specifier: ^3.1.9 + version: 3.1.9 + '@types/mocha': + specifier: ^10.0.6 + version: 10.0.6 + '@types/node': + specifier: ^20.10.4 + version: 20.10.4 + assert: + specifier: ^2.1.0 + version: 2.1.0 + blockstore-core: + specifier: ^4.3.8 + version: 4.3.8 + fast-check: + specifier: ^3.14.0 + version: 3.14.0 + mocha: + specifier: ^10.2.0 + version: 10.2.0 + playwright-test: + specifier: ^14.0.0 + version: 14.0.0 + tsx: + specifier: ^4.6.2 + version: 4.6.2 + +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 + + /@arr/every@1.0.1: + resolution: {integrity: sha512-UQFQ6SgyJ6LX42W8rHCs8KVc0JS0tzVL9ct4XYedJukskYVWTo49tNiMEK9C2HTyarbNiT/RVIRSY82vH+6sTg==} + engines: {node: '>=4'} + dev: true + + /@assemblyscript/loader@0.9.4: + resolution: {integrity: sha512-HazVq9zwTVwGmqdwYzu7WyQ6FQVZ7SwET0KKQuKm55jD0IfUpZgN0OPIiZG3zV1iSrVYcN0bdwLRXI/VNCYsUA==} + dev: false + + /@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.5: + resolution: {integrity: sha512-Cwc2XjUrG4ilcfOw4wBAK+enbdgwAcAJCfGUItPBKR7Mjw4aEfAFYrLxeRp4jWgtNIKn3n2AlBOfwwafl+42/g==} + engines: {node: '>=6.9.0'} + dependencies: + '@ampproject/remapping': 2.2.1 + '@babel/code-frame': 7.23.5 + '@babel/generator': 7.23.5 + '@babel/helper-compilation-targets': 7.22.15 + '@babel/helper-module-transforms': 7.23.3(@babel/core@7.23.5) + '@babel/helpers': 7.23.5 + '@babel/parser': 7.23.5 + '@babel/template': 7.22.15 + '@babel/traverse': 7.23.5 + '@babel/types': 7.23.5 + convert-source-map: 2.0.0 + debug: 4.3.4(supports-color@8.1.1) + gensync: 1.0.0-beta.2 + json5: 2.2.3 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/generator@7.23.5: + resolution: {integrity: sha512-BPssCHrBD+0YrxviOa3QzpqwhNIXKEtOa2jQrm4FlmkC2apYgRnQcmPWiGZDlGxiNtltnUFolMe8497Esry+jA==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.23.5 + '@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.5 + dev: true + + /@babel/helper-hoist-variables@7.22.5: + resolution: {integrity: sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.23.5 + dev: true + + /@babel/helper-module-imports@7.22.15: + resolution: {integrity: sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.23.5 + dev: true + + /@babel/helper-module-transforms@7.23.3(@babel/core@7.23.5): + resolution: {integrity: sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.23.5 + '@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.5 + dev: true + + /@babel/helper-split-export-declaration@7.22.6: + resolution: {integrity: sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.23.5 + dev: true + + /@babel/helper-string-parser@7.23.4: + resolution: {integrity: sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/helper-validator-identifier@7.22.20: + resolution: {integrity: sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/helper-validator-option@7.22.15: + resolution: {integrity: sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/helpers@7.23.5: + resolution: {integrity: sha512-oO7us8FzTEsG3U6ag9MfdF1iA/7Z6dz+MtFhifZk8C8o453rGJFFWUP1t+ULM9TUIAzC9uxXEiXjOiVMyd7QPg==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/template': 7.22.15 + '@babel/traverse': 7.23.5 + '@babel/types': 7.23.5 + 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.0: + resolution: {integrity: sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==} + engines: {node: '>=6.0.0'} + hasBin: true + dependencies: + '@babel/types': 7.23.5 + dev: true + + /@babel/parser@7.23.5: + resolution: {integrity: sha512-hOOqoiNXrmGdFbhgCzu6GiURxUgM27Xwd/aPuu8RfHEZPBzL1Z54okAHAQjXfcQNwvrlkAmAp4SlRTZ45vlthQ==} + engines: {node: '>=6.0.0'} + hasBin: true + dependencies: + '@babel/types': 7.23.5 + 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.5 + '@babel/types': 7.23.5 + dev: true + + /@babel/traverse@7.23.2: + resolution: {integrity: sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/code-frame': 7.23.5 + '@babel/generator': 7.23.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.22.6 + '@babel/parser': 7.23.5 + '@babel/types': 7.23.5 + debug: 4.3.4(supports-color@8.1.1) + globals: 11.12.0 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/traverse@7.23.5: + resolution: {integrity: sha512-czx7Xy5a6sapWWRx61m1Ke1Ra4vczu1mCTtJam5zRTBOonfdJ+S/B6HYmGYu3fJtr8GGET3si6IhgWVBhJ/m8w==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/code-frame': 7.23.5 + '@babel/generator': 7.23.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.22.6 + '@babel/parser': 7.23.5 + '@babel/types': 7.23.5 + debug: 4.3.4(supports-color@8.1.1) + globals: 11.12.0 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/types@7.23.5: + resolution: {integrity: sha512-ON5kSOJwVO6xXVRTvOI0eOnWe7VdUcIpsovGo9U/Br4Ie4UVFQTboO2cYnDhAGU6Fp+UxSiT+pMft0SMHfuq6w==} + 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 + + /@bcoe/v8-coverage@0.2.3: + resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} + dev: true + + /@chainsafe/is-ip@2.0.2: + resolution: {integrity: sha512-ndGqEMG1W5WkGagaqOZHpPU172AGdxr+LD15sv3WIUvT5oCFUrG1Y0CW/v2Egwj4JXEvSibaIIIqImsm98y1nA==} + dev: true + + /@chainsafe/netmask@2.0.0: + resolution: {integrity: sha512-I3Z+6SWUoaljh3TBzCnCxjlUyN8tA+NAk5L6m9IxvCf1BENQTePzPMis97CoN/iMW1St3WN+AWCCRp+TTBRiDg==} + dependencies: + '@chainsafe/is-ip': 2.0.2 + dev: true + + /@es-joy/jsdoccomment@0.40.1: + resolution: {integrity: sha512-YORCdZSusAlBrFpZ77pJjc5r1bQs5caPWtAu+WWmiSo+8XaUzseapVrfAtiRFbQWnrBxxLLEwF6f6ZG/UgCQCg==} + engines: {node: '>=16'} + dependencies: + comment-parser: 1.4.0 + esquery: 1.5.0 + jsdoc-type-pratt-parser: 4.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-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.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-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.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/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.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-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.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/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.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-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.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/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.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-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.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-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.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-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.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-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.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-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.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-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.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-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.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-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.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/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.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/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.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/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.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/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.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-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.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-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.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 + + /@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.52.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.52.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.2: + resolution: {integrity: sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + ajv: 6.12.6 + debug: 4.3.4(supports-color@8.1.1) + espree: 9.6.1 + globals: 13.23.0 + ignore: 5.2.4 + 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.52.0: + resolution: {integrity: sha512-mjZVbpaeMZludF2fsWLD0Z9gCref1Tk4i9+wddjRvpUNqqcndPkBD09N/Mapey0b3jaXbLm2kICwFv2E64QinA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dev: true + + /@fission-codes/eslint-config@0.0.3: + resolution: {integrity: sha512-yyCd36LKx2K7XKdLDl5jEryUuKIkY3tvgBvfqVSffcRZ+r+lMx7UHJH5uaIj3Z05L899TJ/xkFlHlmlv0Jev3Q==} + dependencies: + '@typescript-eslint/eslint-plugin': 6.9.0(@typescript-eslint/parser@6.9.0)(eslint@8.52.0)(typescript@5.2.2) + '@typescript-eslint/parser': 6.9.0(eslint@8.52.0)(typescript@5.2.2) + eslint: 8.52.0 + eslint-config-prettier: 9.0.0(eslint@8.52.0) + eslint-config-standard: 17.1.0(eslint-plugin-import@2.29.0)(eslint-plugin-n@16.2.0)(eslint-plugin-promise@6.1.1)(eslint@8.52.0) + eslint-config-standard-with-typescript: 39.1.1(@typescript-eslint/eslint-plugin@6.9.0)(eslint-plugin-import@2.29.0)(eslint-plugin-n@16.2.0)(eslint-plugin-promise@6.1.1)(eslint@8.52.0)(typescript@5.2.2) + eslint-plugin-eslint-comments: 3.2.0(eslint@8.52.0) + eslint-plugin-etc: 2.0.3(eslint@8.52.0)(typescript@5.2.2) + eslint-plugin-html: 7.1.0 + eslint-plugin-import: 2.29.0(@typescript-eslint/parser@6.9.0)(eslint@8.52.0) + eslint-plugin-jsdoc: 46.8.2(eslint@8.52.0) + eslint-plugin-jsonc: 2.10.0(eslint@8.52.0) + eslint-plugin-markdown: 3.0.1(eslint@8.52.0) + eslint-plugin-n: 16.2.0(eslint@8.52.0) + eslint-plugin-no-only-tests: 3.1.0 + eslint-plugin-promise: 6.1.1(eslint@8.52.0) + eslint-plugin-react: 7.33.2(eslint@8.52.0) + eslint-plugin-react-hooks: 4.6.0(eslint@8.52.0) + eslint-plugin-unicorn: 48.0.1(eslint@8.52.0) + eslint-plugin-yml: 1.10.0(eslint@8.52.0) + typescript: 5.2.2 + transitivePeerDependencies: + - eslint-import-resolver-typescript + - eslint-import-resolver-webpack + - supports-color + dev: true + + /@humanwhocodes/config-array@0.11.13: + resolution: {integrity: sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==} + engines: {node: '>=10.10.0'} + dependencies: + '@humanwhocodes/object-schema': 2.0.1 + debug: 4.3.4(supports-color@8.1.1) + 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.1: + resolution: {integrity: sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==} + dev: true + + /@ipld/dag-cbor@9.0.6: + resolution: {integrity: sha512-3kNab5xMppgWw6DVYx2BzmFq8t7I56AGWfp5kaU1fIPkwHVpBRglJJTYsGtbVluCi/s/q97HZM3bC+aDW4sxbQ==} + engines: {node: '>=16.0.0', npm: '>=7.0.0'} + dependencies: + cborg: 4.0.5 + multiformats: 12.1.3 + dev: false + + /@ipld/dag-pb@4.0.6: + resolution: {integrity: sha512-wOij3jfDKZsb9yjhQeHp+TQy0pu1vmUkGv324xciFFZ7xGbDfAGTQW03lSA5aJ/7HBBNYgjEE0nvHmNW1Qjfag==} + engines: {node: '>=16.0.0', npm: '>=7.0.0'} + dependencies: + multiformats: 12.1.3 + dev: false + + /@istanbuljs/schema@0.1.3: + resolution: {integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==} + engines: {node: '>=8'} + 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 + + /@libp2p/interface@1.0.2: + resolution: {integrity: sha512-z/3Yyg+7cVyzRXwzdrDkJd7YmNaLE9iZjQaixo5luI/n9uk5OFFjb9ulAsNqpq8V1xylCo2DXIC7f94KClwzVw==} + dependencies: + '@multiformats/multiaddr': 12.1.11 + it-pushable: 3.2.3 + it-stream-types: 2.0.1 + multiformats: 12.1.3 + uint8arraylist: 2.4.7 + transitivePeerDependencies: + - supports-color + dev: true + + /@libp2p/logger@4.0.2: + resolution: {integrity: sha512-J9UMtMU9BKXNp+3c5kcI7HyWOPYg2B2E6sn1gEQckiSexTaz0wKJSlgTZ89f9F8bkC3AaC8ybXYuHbFQhwpTIg==} + dependencies: + '@libp2p/interface': 1.0.2 + '@multiformats/multiaddr': 12.1.11 + debug: 4.3.4(supports-color@8.1.1) + interface-datastore: 8.2.9 + multiformats: 12.1.3 + transitivePeerDependencies: + - supports-color + dev: true + + /@multiformats/multiaddr@12.1.11: + resolution: {integrity: sha512-CWG9kETEGTTMdr1T+/JEuMwFld3r3fHNP8LkLoUcLvHRy6yr8sWdotVGEDNEdDO/vrKhuD7bQBws3xMSMMyylg==} + dependencies: + '@chainsafe/is-ip': 2.0.2 + '@chainsafe/netmask': 2.0.0 + '@libp2p/interface': 1.0.2 + dns-over-http-resolver: 3.0.0 + multiformats: 12.1.3 + uint8-varint: 2.0.2 + uint8arrays: 4.0.9 + transitivePeerDependencies: + - supports-color + dev: true + + /@multiformats/murmur3@2.1.7: + resolution: {integrity: sha512-Yf0UpAaONjed+8PTt5NM/GG4Z4Ai4m1qfT7bqevjnkwRQ12K+0jxtRomirz+VJx4PokpA2St1ZSD1iMkZTqPRQ==} + engines: {node: '>=16.0.0', npm: '>=7.0.0'} + dependencies: + multiformats: 12.1.3 + murmurhash3js-revisited: 3.0.0 + dev: false + + /@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 + + /@phenomnomnominal/tsquery@5.0.1(typescript@5.2.2): + resolution: {integrity: sha512-3nVv+e2FQwsW8Aw6qTU6f+1rfcJ3hrcnvH/mu9i8YhxO+9sqbOfpL8m6PbET5+xKOlz/VSbp0RoYWYCtIsnmuA==} + peerDependencies: + typescript: ^3 || ^4 || ^5 + dependencies: + esquery: 1.5.0 + typescript: 5.2.2 + dev: true + + /@polka/url@0.5.0: + resolution: {integrity: sha512-oZLYFEAzUKyi3SKnXvj32ZCEGH6RDnao7COuCVhDydMS9NrCSVXhM79VaKyP5+Zc33m0QXEd2DN3UkU7OsHcfw==} + dev: true + + /@polka/url@1.0.0-next.23: + resolution: {integrity: sha512-C16M+IYz0rgRhWZdCmK+h58JMv8vijAA61gmz2rspCSwKwzBebpdcsiUmwrtJRdphuY30i6BSLEOP8ppbNLyLg==} + dev: true + + /@rollup/rollup-android-arm-eabi@4.6.1: + resolution: {integrity: sha512-0WQ0ouLejaUCRsL93GD4uft3rOmB8qoQMU05Kb8CmMtMBe7XUDLAltxVZI1q6byNqEtU7N1ZX1Vw5lIpgulLQA==} + cpu: [arm] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-android-arm64@4.6.1: + resolution: {integrity: sha512-1TKm25Rn20vr5aTGGZqo6E4mzPicCUD79k17EgTLAsXc1zysyi4xXKACfUbwyANEPAEIxkzwue6JZ+stYzWUTA==} + cpu: [arm64] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-darwin-arm64@4.6.1: + resolution: {integrity: sha512-cEXJQY/ZqMACb+nxzDeX9IPLAg7S94xouJJCNVE5BJM8JUEP4HeTF+ti3cmxWeSJo+5D+o8Tc0UAWUkfENdeyw==} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-darwin-x64@4.6.1: + resolution: {integrity: sha512-LoSU9Xu56isrkV2jLldcKspJ7sSXmZWkAxg7sW/RfF7GS4F5/v4EiqKSMCFbZtDu2Nc1gxxFdQdKwkKS4rwxNg==} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-linux-arm-gnueabihf@4.6.1: + resolution: {integrity: sha512-EfI3hzYAy5vFNDqpXsNxXcgRDcFHUWSx5nnRSCKwXuQlI5J9dD84g2Usw81n3FLBNsGCegKGwwTVsSKK9cooSQ==} + cpu: [arm] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-linux-arm64-gnu@4.6.1: + resolution: {integrity: sha512-9lhc4UZstsegbNLhH0Zu6TqvDfmhGzuCWtcTFXY10VjLLUe4Mr0Ye2L3rrtHaDd/J5+tFMEuo5LTCSCMXWfUKw==} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-linux-arm64-musl@4.6.1: + resolution: {integrity: sha512-FfoOK1yP5ksX3wwZ4Zk1NgyGHZyuRhf99j64I5oEmirV8EFT7+OhUZEnP+x17lcP/QHJNWGsoJwrz4PJ9fBEXw==} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-linux-x64-gnu@4.6.1: + resolution: {integrity: sha512-DNGZvZDO5YF7jN5fX8ZqmGLjZEXIJRdJEdTFMhiyXqyXubBa0WVLDWSNlQ5JR2PNgDbEV1VQowhVRUh+74D+RA==} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-linux-x64-musl@4.6.1: + resolution: {integrity: sha512-RkJVNVRM+piYy87HrKmhbexCHg3A6Z6MU0W9GHnJwBQNBeyhCJG9KDce4SAMdicQnpURggSvtbGo9xAWOfSvIQ==} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-win32-arm64-msvc@4.6.1: + resolution: {integrity: sha512-v2FVT6xfnnmTe3W9bJXl6r5KwJglMK/iRlkKiIFfO6ysKs0rDgz7Cwwf3tjldxQUrHL9INT/1r4VA0n9L/F1vQ==} + cpu: [arm64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-win32-ia32-msvc@4.6.1: + resolution: {integrity: sha512-YEeOjxRyEjqcWphH9dyLbzgkF8wZSKAKUkldRY6dgNR5oKs2LZazqGB41cWJ4Iqqcy9/zqYgmzBkRoVz3Q9MLw==} + cpu: [ia32] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-win32-x64-msvc@4.6.1: + resolution: {integrity: sha512-0zfTlFAIhgz8V2G8STq8toAjsYYA6eci1hnXuyOTUFnymrtJwnS6uGKiv3v5UrPZkBlamLvrLV2iiaeqCKzb0A==} + cpu: [x64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@sindresorhus/merge-streams@1.0.0: + resolution: {integrity: sha512-rUV5WyJrJLoloD4NDN1V1+LDMDWOa4OTsT4yYJwQNpTU6FWxkxHpL7eu4w+DmiH8x/EAM1otkPE1+LaspIbplw==} + engines: {node: '>=18'} + dev: true + + /@types/assert@1.5.9: + resolution: {integrity: sha512-uQ+/hp0DbfrhnJFgiqHlsrLTGgr8HZGssV7vYN8XunlvyJkzArcyBy/9e5Rey2T7lpL7jVuoNI/8CWCDCwISgg==} + dev: true + + /@types/debounce-promise@3.1.9: + resolution: {integrity: sha512-awNxydYSU+E2vL7EiOAMtiSOfL5gUM5X4YSE2A92qpxDJQ/rXz6oMPYBFDcDywlUmvIDI6zsqgq17cGm5CITQw==} + dev: true + + /@types/istanbul-lib-coverage@2.0.6: + resolution: {integrity: sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==} + dev: true + + /@types/json-schema@7.0.14: + resolution: {integrity: sha512-U3PUjAudAdJBeC2pgN8uTIKgxrb4nlDF3SF0++EldXQvQBGkpFZMSnwQiIoDU77tv45VgNkl/L4ouD+rEomujw==} + dev: true + + /@types/json5@0.0.29: + resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} + dev: true + + /@types/mdast@3.0.14: + resolution: {integrity: sha512-gVZ04PGgw1qLZKsnWnyFv4ORnaJ+DXLdHTVSFbU8yX6xZ34Bjg4Q32yPkmveUP1yItXReKfB0Aknlh/3zxTKAw==} + dependencies: + '@types/unist': 2.0.9 + dev: true + + /@types/minimatch@3.0.5: + resolution: {integrity: sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==} + dev: true + + /@types/mocha@10.0.6: + resolution: {integrity: sha512-dJvrYWxP/UcXm36Qn36fxhUKu8A/xMRXVT2cliFF1Z7UA9liG5Psj3ezNSZw+5puH2czDXRLcXQxf8JbJt0ejg==} + dev: true + + /@types/node@20.10.4: + resolution: {integrity: sha512-D08YG6rr8X90YB56tSIuBaddy/UXAA9RKJoFvrsnogAum/0pmjkgi4+2nx96A330FmioegBWmEYQ+syqCFaveg==} + dependencies: + undici-types: 5.26.5 + dev: true + + /@types/normalize-package-data@2.4.3: + resolution: {integrity: sha512-ehPtgRgaULsFG8x0NeYJvmyH1hmlfsNLujHe9dQEia/7MAJYdzMSi19JtchUHjmBA6XC/75dK55mzZH+RyieSg==} + dev: true + + /@types/parse-json@4.0.1: + resolution: {integrity: sha512-3YmXzzPAdOTVljVMkTMBdBEvlOLg2cDQaDhnnhT3nT9uDbnJzjWhKlzb+desT12Y7tGqaN6d+AbozcKzyL36Ng==} + dev: true + + /@types/semver@7.5.4: + resolution: {integrity: sha512-MMzuxN3GdFwskAnb6fz0orFvhfqi752yjaXylr0Rp4oDg5H0Zn1IuyRhDVvYOwAXoJirx2xuS16I3WjxnAIHiQ==} + dev: true + + /@types/unist@2.0.9: + resolution: {integrity: sha512-zC0iXxAv1C1ERURduJueYzkzZ2zaGyc+P2c95hgkikHPr3z8EdUZOlgEQ5X0DRmwDZn+hekycQnoeiiRVrmilQ==} + dev: true + + /@types/yargs-parser@21.0.2: + resolution: {integrity: sha512-5qcvofLPbfjmBfKaLfj/+f+Sbd6pN4zl7w7VSVI5uz7m9QZTuB2aZAa2uo1wHFBNN2x6g/SoTkXmd8mQnQF2Cw==} + dev: true + + /@types/yargs@17.0.29: + resolution: {integrity: sha512-nacjqA3ee9zRF/++a3FUY1suHTFKZeHba2n8WeDw9cCVdmzmHpIxyzOJBcpHvvEmS8E9KqWlSnWHUkOrkhWcvA==} + dependencies: + '@types/yargs-parser': 21.0.2 + dev: true + + /@typescript-eslint/eslint-plugin@6.9.0(@typescript-eslint/parser@6.9.0)(eslint@8.52.0)(typescript@5.2.2): + resolution: {integrity: sha512-lgX7F0azQwRPB7t7WAyeHWVfW1YJ9NIgd9mvGhfQpRY56X6AVf8mwM8Wol+0z4liE7XX3QOt8MN1rUKCfSjRIA==} + 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.9.0(eslint@8.52.0)(typescript@5.2.2) + '@typescript-eslint/scope-manager': 6.9.0 + '@typescript-eslint/type-utils': 6.9.0(eslint@8.52.0)(typescript@5.2.2) + '@typescript-eslint/utils': 6.9.0(eslint@8.52.0)(typescript@5.2.2) + '@typescript-eslint/visitor-keys': 6.9.0 + debug: 4.3.4(supports-color@8.1.1) + eslint: 8.52.0 + graphemer: 1.4.0 + ignore: 5.2.4 + natural-compare: 1.4.0 + semver: 7.5.4 + ts-api-utils: 1.0.3(typescript@5.2.2) + typescript: 5.2.2 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/experimental-utils@5.62.0(eslint@8.52.0)(typescript@5.2.2): + resolution: {integrity: sha512-RTXpeB3eMkpoclG3ZHft6vG/Z30azNHuqY6wKPBHlVMZFuEvrtlEDe8gMqDb+SO+9hjC/pLekeSCryf9vMZlCw==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + dependencies: + '@typescript-eslint/utils': 5.62.0(eslint@8.52.0)(typescript@5.2.2) + eslint: 8.52.0 + transitivePeerDependencies: + - supports-color + - typescript + dev: true + + /@typescript-eslint/parser@6.9.0(eslint@8.52.0)(typescript@5.2.2): + resolution: {integrity: sha512-GZmjMh4AJ/5gaH4XF2eXA8tMnHWP+Pm1mjQR2QN4Iz+j/zO04b9TOvJYOX2sCNIQHtRStKTxRY1FX7LhpJT4Gw==} + 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.9.0 + '@typescript-eslint/types': 6.9.0 + '@typescript-eslint/typescript-estree': 6.9.0(typescript@5.2.2) + '@typescript-eslint/visitor-keys': 6.9.0 + debug: 4.3.4(supports-color@8.1.1) + eslint: 8.52.0 + typescript: 5.2.2 + 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.9.0: + resolution: {integrity: sha512-1R8A9Mc39n4pCCz9o79qRO31HGNDvC7UhPhv26TovDsWPBDx+Sg3rOZdCELIA3ZmNoWAuxaMOT7aWtGRSYkQxw==} + engines: {node: ^16.0.0 || >=18.0.0} + dependencies: + '@typescript-eslint/types': 6.9.0 + '@typescript-eslint/visitor-keys': 6.9.0 + dev: true + + /@typescript-eslint/type-utils@6.9.0(eslint@8.52.0)(typescript@5.2.2): + resolution: {integrity: sha512-XXeahmfbpuhVbhSOROIzJ+b13krFmgtc4GlEuu1WBT+RpyGPIA4Y/eGnXzjbDj5gZLzpAXO/sj+IF/x2GtTMjQ==} + 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.9.0(typescript@5.2.2) + '@typescript-eslint/utils': 6.9.0(eslint@8.52.0)(typescript@5.2.2) + debug: 4.3.4(supports-color@8.1.1) + eslint: 8.52.0 + ts-api-utils: 1.0.3(typescript@5.2.2) + typescript: 5.2.2 + 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.9.0: + resolution: {integrity: sha512-+KB0lbkpxBkBSiVCuQvduqMJy+I1FyDbdwSpM3IoBS7APl4Bu15lStPjgBIdykdRqQNYqYNMa8Kuidax6phaEw==} + engines: {node: ^16.0.0 || >=18.0.0} + dev: true + + /@typescript-eslint/typescript-estree@5.62.0(typescript@5.2.2): + 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(supports-color@8.1.1) + globby: 11.1.0 + is-glob: 4.0.3 + semver: 7.5.4 + tsutils: 3.21.0(typescript@5.2.2) + typescript: 5.2.2 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/typescript-estree@6.9.0(typescript@5.2.2): + resolution: {integrity: sha512-NJM2BnJFZBEAbCfBP00zONKXvMqihZCrmwCaik0UhLr0vAgb6oguXxLX1k00oQyD+vZZ+CJn3kocvv2yxm4awQ==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/types': 6.9.0 + '@typescript-eslint/visitor-keys': 6.9.0 + debug: 4.3.4(supports-color@8.1.1) + globby: 11.1.0 + is-glob: 4.0.3 + semver: 7.5.4 + ts-api-utils: 1.0.3(typescript@5.2.2) + typescript: 5.2.2 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/utils@5.62.0(eslint@8.52.0)(typescript@5.2.2): + 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.52.0) + '@types/json-schema': 7.0.14 + '@types/semver': 7.5.4 + '@typescript-eslint/scope-manager': 5.62.0 + '@typescript-eslint/types': 5.62.0 + '@typescript-eslint/typescript-estree': 5.62.0(typescript@5.2.2) + eslint: 8.52.0 + eslint-scope: 5.1.1 + semver: 7.5.4 + transitivePeerDependencies: + - supports-color + - typescript + dev: true + + /@typescript-eslint/utils@6.9.0(eslint@8.52.0)(typescript@5.2.2): + resolution: {integrity: sha512-5Wf+Jsqya7WcCO8me504FBigeQKVLAMPmUzYgDbWchINNh1KJbxCgVya3EQ2MjvJMVeXl3pofRmprqX6mfQkjQ==} + 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.52.0) + '@types/json-schema': 7.0.14 + '@types/semver': 7.5.4 + '@typescript-eslint/scope-manager': 6.9.0 + '@typescript-eslint/types': 6.9.0 + '@typescript-eslint/typescript-estree': 6.9.0(typescript@5.2.2) + eslint: 8.52.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.9.0: + resolution: {integrity: sha512-dGtAfqjV6RFOtIP8I0B4ZTBRrlTT8NHHlZZSchQx3qReaoDeXhYM++M4So2AgFK9ZB0emRPA6JI1HkafzA2Ibg==} + engines: {node: ^16.0.0 || >=18.0.0} + dependencies: + '@typescript-eslint/types': 6.9.0 + eslint-visitor-keys: 3.4.3 + dev: true + + /@ungap/structured-clone@1.2.0: + resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} + dev: true + + /@vue/compiler-core@3.3.7: + resolution: {integrity: sha512-pACdY6YnTNVLXsB86YD8OF9ihwpolzhhtdLVHhBL6do/ykr6kKXNYABRtNMGrsQXpEXXyAdwvWWkuTbs4MFtPQ==} + dependencies: + '@babel/parser': 7.23.5 + '@vue/shared': 3.3.7 + estree-walker: 2.0.2 + source-map-js: 1.0.2 + dev: true + + /@vue/compiler-dom@3.3.7: + resolution: {integrity: sha512-0LwkyJjnUPssXv/d1vNJ0PKfBlDoQs7n81CbO6Q0zdL7H1EzqYRrTVXDqdBVqro0aJjo/FOa1qBAPVI4PGSHBw==} + dependencies: + '@vue/compiler-core': 3.3.7 + '@vue/shared': 3.3.7 + dev: true + + /@vue/compiler-sfc@3.3.7: + resolution: {integrity: sha512-7pfldWy/J75U/ZyYIXRVqvLRw3vmfxDo2YLMwVtWVNew8Sm8d6wodM+OYFq4ll/UxfqVr0XKiVwti32PCrruAw==} + dependencies: + '@babel/parser': 7.23.5 + '@vue/compiler-core': 3.3.7 + '@vue/compiler-dom': 3.3.7 + '@vue/compiler-ssr': 3.3.7 + '@vue/reactivity-transform': 3.3.7 + '@vue/shared': 3.3.7 + estree-walker: 2.0.2 + magic-string: 0.30.5 + postcss: 8.4.32 + source-map-js: 1.0.2 + dev: true + + /@vue/compiler-ssr@3.3.7: + resolution: {integrity: sha512-TxOfNVVeH3zgBc82kcUv+emNHo+vKnlRrkv8YvQU5+Y5LJGJwSNzcmLUoxD/dNzv0bhQ/F0s+InlgV0NrApJZg==} + dependencies: + '@vue/compiler-dom': 3.3.7 + '@vue/shared': 3.3.7 + dev: true + + /@vue/reactivity-transform@3.3.7: + resolution: {integrity: sha512-APhRmLVbgE1VPGtoLQoWBJEaQk4V8JUsqrQihImVqKT+8U6Qi3t5ATcg4Y9wGAPb3kIhetpufyZ1RhwbZCIdDA==} + dependencies: + '@babel/parser': 7.23.5 + '@vue/compiler-core': 3.3.7 + '@vue/shared': 3.3.7 + estree-walker: 2.0.2 + magic-string: 0.30.5 + dev: true + + /@vue/shared@3.3.7: + resolution: {integrity: sha512-N/tbkINRUDExgcPTBvxNkvHGu504k8lzlNQRITVnm6YjOjwa4r0nnbd4Jb01sNpur5hAllyRJzSK5PvB9PPwRg==} + dev: true + + /acorn-jsx@5.3.2(acorn@8.11.2): + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + dependencies: + acorn: 8.11.2 + dev: true + + /acorn-loose@8.4.0: + resolution: {integrity: sha512-M0EUka6rb+QC4l9Z3T0nJEzNOO7JcoJlYMrBlyBCiFSXRyxjLKayd4TbQs2FDRWQU1h9FR7QVNHt+PEaoNL5rQ==} + engines: {node: '>=0.4.0'} + dependencies: + acorn: 8.11.2 + dev: true + + /acorn@8.11.2: + resolution: {integrity: sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==} + engines: {node: '>=0.4.0'} + hasBin: true + dev: true + + /aggregate-error@4.0.1: + resolution: {integrity: sha512-0poP0T7el6Vq3rstR8Mn4V/IQrpBLO6POkUSrN7RhyY+GF/InCFShQzsQ39T25gkHhLgSLByyAz+Kjb+c2L98w==} + engines: {node: '>=12'} + dependencies: + clean-stack: 4.2.0 + indent-string: 5.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.1: + resolution: {integrity: sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==} + engines: {node: '>=6'} + dev: true + + /ansi-escapes@5.0.0: + resolution: {integrity: sha512-5GFMVX8HqE/TB+FuBJGuO5XG0WrsA6ptUqoODaT/n9mmUaZFkqnBueB4leqGBCmrUHnCnC4PCZTCd0E7QQ83bA==} + engines: {node: '>=12'} + dependencies: + type-fest: 1.4.0 + 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-sequence-parser@1.1.1: + resolution: {integrity: sha512-vJXt3yiaUL4UU546s3rPXlsry/RnM730G1+HkpKE012AN0sx1eOrxSu95oKDIonskeLTijMgqWZ3uDEe3NFvyg==} + 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 + + /are-docs-informative@0.0.2: + resolution: {integrity: sha512-ixiS0nLNNG5jNQzgZJNoUpBKdo9yTYZMGJ+QgT2jmjR7G7+QHRCc4v6LQ3NgE7EBJq+o0ams3waJwkrlBom8Ig==} + engines: {node: '>=14'} + 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 + + /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-differ@3.0.0: + resolution: {integrity: sha512-THtfYS6KtME/yIAhKjZ2ul7XI96lQGHRputJQHO80LAWQnuGP4iCIN8vdMRboGbIEYBwU33q8Tch1os2+X0kMg==} + engines: {node: '>=8'} + 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.2: + resolution: {integrity: sha512-HuQCHOlk1Weat5jzStICBCd83NxiIMwqDg/dHEsoefabn/hJRj5pVdWcPUSpRrwhwxZOsQassMpgN/xRYFBMIg==} + 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@2.0.1: + resolution: {integrity: sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==} + engines: {node: '>=8'} + dev: true + + /assert@2.1.0: + resolution: {integrity: sha512-eLHpSK/Y4nhMJ07gDaAzoX/XAKS8PSaojml3M0DM4JpV1LAi5JOJ/p6H/XWrl8L+DzVEvVCW1z3vWAaB9oTsQw==} + dependencies: + call-bind: 1.0.5 + is-nan: 1.3.2 + object-is: 1.1.5 + object.assign: 4.1.4 + util: 0.12.5 + 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 + + /balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + dev: true + + /base-x@4.0.0: + resolution: {integrity: sha512-FuwxlW4H5kh37X/oW59pwTzzTKRzfrrQwhmyspRM7swOEZcHtDZSCt45U6oKgtuFE+WYPblePMVIPR4RZrh/hw==} + dev: false + + /base64-js@1.5.1: + resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + + /bigint-mod-arith@3.3.1: + resolution: {integrity: sha512-pX/cYW3dCa87Jrzv6DAr8ivbbJRzEX5yGhdt8IutnX/PCIXfpx+mabWNK/M8qqh+zQ0J3thftUBHW0ByuUlG0w==} + engines: {node: '>=10.4.0'} + dev: false + + /binary-extensions@2.2.0: + resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==} + engines: {node: '>=8'} + dev: true + + /bl@5.1.0: + resolution: {integrity: sha512-tv1ZJHLfTDnXE6tMHv73YgSJaWR2AFuPwMntBe7XL/GBFHnT0CLnsHMogfk5+GzCDC5ZWarSCYaIGATZt9dNsQ==} + dependencies: + buffer: 6.0.3 + inherits: 2.0.4 + readable-stream: 3.6.2 + + /blockstore-core@4.3.8: + resolution: {integrity: sha512-Agunhjw9w0I1OoJn012OpzJwBRm3Nf+v64N2FaZSsF3UGhoQAu4RePLuIBsZrPh4XRqT5Yg1rHoBYJGDhDmkWQ==} + dependencies: + '@libp2p/logger': 4.0.2 + err-code: 3.0.1 + interface-blockstore: 5.2.7 + interface-store: 5.1.5 + it-drain: 3.0.5 + it-filter: 3.0.4 + it-merge: 3.0.3 + it-pushable: 3.2.3 + multiformats: 12.1.3 + uint8arrays: 5.0.0 + transitivePeerDependencies: + - supports-color + 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 + + /browser-stdout@1.3.1: + resolution: {integrity: sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==} + 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-from@1.1.2: + resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + dev: true + + /buffer@6.0.3: + resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} + 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 + + /builtins@5.0.1: + resolution: {integrity: sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==} + dependencies: + semver: 7.5.4 + dev: true + + /c8@8.0.1: + resolution: {integrity: sha512-EINpopxZNH1mETuI0DzRA4MZpAUH+IFiRhnmFD3vFr3vdrgxqi3VfE3KL0AIL+zDq8rC9bZqwM/VDmmoe04y7w==} + engines: {node: '>=12'} + hasBin: true + dependencies: + '@bcoe/v8-coverage': 0.2.3 + '@istanbuljs/schema': 0.1.3 + find-up: 5.0.0 + foreground-child: 2.0.0 + istanbul-lib-coverage: 3.2.2 + istanbul-lib-report: 3.0.1 + istanbul-reports: 3.1.6 + rimraf: 3.0.2 + test-exclude: 6.0.0 + v8-to-istanbul: 9.2.0 + yargs: 17.7.2 + yargs-parser: 21.1.1 + 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 + + /callsite@1.0.0: + resolution: {integrity: sha512-0vdNRFXn5q+dtOqjfFtmtlI9N2eVZ7LMyEV2iKC5mEEFvSg/69Ml6b/WU2qF8W1nLRa0wiSrDT3Y5jOHZCwKPQ==} + 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 + + /camelcase@8.0.0: + resolution: {integrity: sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA==} + engines: {node: '>=16'} + dev: true + + /caniuse-lite@1.0.30001561: + resolution: {integrity: sha512-NTt0DNoKe958Q0BE0j0c1V9jbUzhBxHIEJy7asmGrpE0yG63KTV7PLHPnK2E1O9RsQrQ081I3NLuXGS6zht3cw==} + dev: true + + /cborg@4.0.5: + resolution: {integrity: sha512-q8TAjprr8pn9Fp53rOIGp/UFDdFY6os2Nq62YogPSIzczJD9M6g2b6igxMkpCiZZKJ0kn/KzDLDvG+EqBIEeCg==} + hasBin: true + 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@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 + + /character-entities-legacy@1.1.4: + resolution: {integrity: sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA==} + dev: true + + /character-entities@1.2.4: + resolution: {integrity: sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw==} + dev: true + + /character-reference-invalid@1.1.4: + resolution: {integrity: sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==} + 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 + + /clean-stack@4.2.0: + resolution: {integrity: sha512-LYv6XPxoyODi36Dp976riBtSY27VmFo+MKqEU9QCCWyTrdEPDog+RWA7xQWHi6Vbp61j5c4cdzzX1NidnwtUWg==} + engines: {node: '>=12'} + dependencies: + escape-string-regexp: 5.0.0 + dev: true + + /cli-cursor@4.0.0: + resolution: {integrity: sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + restore-cursor: 4.0.0 + dev: true + + /cli-spinners@2.9.1: + resolution: {integrity: sha512-jHgecW0pxkonBJdrKsqxgRX9AcG+u/5k0Q7WPDfi8AogLAdwxEkyYYNWwZ5GvVFoFx2uiY1eNcSK00fh+1+FyQ==} + engines: {node: '>=6'} + dev: true + + /cli-truncate@3.1.0: + resolution: {integrity: sha512-wfOBkjXteqSnI59oPcJkcPl/ZmwvMMOj340qUIY1SKZCv0B9Cf4D4fAucRkIKQmsIuYK3x1rrgU7MeGRruiuiA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + slice-ansi: 5.0.0 + string-width: 5.1.2 + 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 + + /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 + + /commander@11.1.0: + resolution: {integrity: sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==} + engines: {node: '>=16'} + dev: true + + /comment-parser@1.4.0: + resolution: {integrity: sha512-QLyTNiZ2KDOibvFPlZ6ZngVsZ/0gYnE6uTXi5aoDg8ed3AkJAz4sEje3Y8a29hQ1s6A99MZXe47fLAXQ1rTqaw==} + engines: {node: '>= 12.0.0'} + dev: true + + /compare-versions@6.1.0: + resolution: {integrity: sha512-LNZQXhqUvqUTotpZ00qLSaify3b4VFD588aRr8MKFw4CMUr98ytzCW5wDH5qx/DEY5kCDXcbcRuCqL0szEf2tg==} + dev: false + + /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 + + /copy-file@11.0.0: + resolution: {integrity: sha512-mFsNh/DIANLqFt5VHZoGirdg7bK5+oTWlhnGu6tgRhzBlnEKWaPX2xrFaLltii/6rmhqFMJqffUgknuRdpYlHw==} + engines: {node: '>=18'} + dependencies: + graceful-fs: 4.2.11 + p-event: 6.0.0 + dev: true + + /cosmiconfig@7.1.0: + resolution: {integrity: sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==} + engines: {node: '>=10'} + dependencies: + '@types/parse-json': 4.0.1 + import-fresh: 3.3.0 + parse-json: 5.2.0 + path-type: 4.0.0 + yaml: 1.10.2 + dev: true + + /cpy@11.0.0: + resolution: {integrity: sha512-vA71mFQyIxCrqvP/9JBLCj05UJV/+WpvAxZK2/EiK5ndD090cjuChfJ3ExVVuZXHoTJ/3HLedOPYDWyxnNHjrg==} + engines: {node: '>=18'} + dependencies: + copy-file: 11.0.0 + globby: 13.2.2 + junk: 4.0.1 + micromatch: 4.0.5 + p-filter: 3.0.0 + p-map: 6.0.0 + 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 + + /debounce@2.0.0: + resolution: {integrity: sha512-xRetU6gL1VJbs85Mc4FoEGSjQxzpdxRyFhe3lmWFyy2EzydIcD4xzUvRJMD+NPDfMwKNhxa3PvsIOU32luIWeA==} + engines: {node: '>=18'} + 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.4(supports-color@8.1.1): + resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.1.2 + supports-color: 8.1.1 + + /decamelize@4.0.0: + resolution: {integrity: sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==} + engines: {node: '>=10'} + 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.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-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 + + /depcheck@1.4.7: + resolution: {integrity: sha512-1lklS/bV5chOxwNKA/2XUUk/hPORp8zihZsXflr8x0kLwmcZ9Y9BsS6Hs3ssvA+2wUVbG0U2Ciqvm1SokNjPkA==} + engines: {node: '>=10'} + hasBin: true + dependencies: + '@babel/parser': 7.23.0 + '@babel/traverse': 7.23.2 + '@vue/compiler-sfc': 3.3.7 + callsite: 1.0.0 + camelcase: 6.3.0 + cosmiconfig: 7.1.0 + debug: 4.3.4(supports-color@8.1.1) + deps-regex: 0.2.0 + findup-sync: 5.0.0 + ignore: 5.2.4 + is-core-module: 2.13.1 + js-yaml: 3.14.1 + json5: 2.2.3 + lodash: 4.17.21 + minimatch: 7.4.6 + multimatch: 5.0.0 + please-upgrade-node: 3.2.0 + readdirp: 3.6.0 + require-package-name: 2.0.1 + resolve: 1.22.8 + resolve-from: 5.0.0 + semver: 7.5.4 + yargs: 16.2.0 + transitivePeerDependencies: + - supports-color + dev: true + + /deps-regex@0.2.0: + resolution: {integrity: sha512-PwuBojGMQAYbWkMXOY9Pd/NWCDNHVH12pnS7WHqZkTSeMESe4hwnKKRp0yR87g37113x4JPbo/oIvXY+s/f56Q==} + dev: true + + /detect-file@1.0.0: + resolution: {integrity: sha512-DtCOLG98P007x7wiiOmfI0fi3eIKyWiLTGJ2MDnVi/E04lWGbf+JzrRHMm0rgIIZJGtHpKpbVgLWHrv8xXpc3Q==} + engines: {node: '>=0.10.0'} + dev: true + + /diff@5.0.0: + resolution: {integrity: sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==} + 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 + + /dns-over-http-resolver@3.0.0: + resolution: {integrity: sha512-5+BI+B7n8LKhNaEZBYErr+CBd9t5nYtjunByLhrLGtZ+i3TRgiU8yE87pCjEBu2KOwNsD9ljpSXEbZ4S8xih5g==} + dependencies: + debug: 4.3.4(supports-color@8.1.1) + receptacle: 1.3.2 + transitivePeerDependencies: + - supports-color + 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 + + /eastasianwidth@0.2.0: + resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + dev: true + + /electron-to-chromium@1.4.581: + resolution: {integrity: sha512-6uhqWBIapTJUxgPTCHH9sqdbxIMPt7oXl0VcAL1kOtlU6aECdcMncCrX5Z7sHQ/invtrC9jUQUef7+HhO8vVFw==} + dev: true + + /emittery@1.0.1: + resolution: {integrity: sha512-2ID6FdrMD9KDLldGesP6317G78K7km/kMcwItRtVFva7I/cSEOIaLpewaUb+YLXVwdAp3Ctfxh/V5zIl1sj7dQ==} + engines: {node: '>=14.16'} + dev: false + + /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 + + /entities@4.5.0: + resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} + engines: {node: '>=0.12'} + dev: true + + /err-code@3.0.1: + resolution: {integrity: sha512-GiaH0KJUewYok+eeY05IIgjtAe4Yltygk9Wqp1V5yVWLdhf0hYZchRjNIT9bb0mSwRcIusT3cx7PJUf3zEIfUA==} + + /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.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-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-plugin-wasm@1.1.0: + resolution: {integrity: sha512-0bQ6+1tUbySSnxzn5jnXHMDvYnT0cN/Wd4Syk8g/sqAIJUg7buTIi22svS3Qz6ssx895NT+TgLPb33xi1OkZig==} + engines: {node: '>=0.10.0'} + 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 + + /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 + + /escape-string-regexp@5.0.0: + resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==} + engines: {node: '>=12'} + dev: true + + /eslint-compat-utils@0.1.2(eslint@8.52.0): + resolution: {integrity: sha512-Jia4JDldWnFNIru1Ehx1H5s9/yxiRHY/TimCuUc0jNexew3cF1gI6CYZil1ociakfWO3rRqFjl1mskBblB3RYg==} + engines: {node: '>=12'} + peerDependencies: + eslint: '>=6.0.0' + dependencies: + eslint: 8.52.0 + dev: true + + /eslint-config-prettier@9.0.0(eslint@8.52.0): + resolution: {integrity: sha512-IcJsTkJae2S35pRsRAwoCE+925rJJStOdkKnLVgtE+tEpqU0EVVM7OqrwxqgptKdX29NUwC82I5pXsGFIgSevw==} + hasBin: true + peerDependencies: + eslint: '>=7.0.0' + dependencies: + eslint: 8.52.0 + dev: true + + /eslint-config-standard-with-typescript@39.1.1(@typescript-eslint/eslint-plugin@6.9.0)(eslint-plugin-import@2.29.0)(eslint-plugin-n@16.2.0)(eslint-plugin-promise@6.1.1)(eslint@8.52.0)(typescript@5.2.2): + resolution: {integrity: sha512-t6B5Ep8E4I18uuoYeYxINyqcXb2UbC0SOOTxRtBSt2JUs+EzeXbfe2oaiPs71AIdnoWhXDO2fYOHz8df3kV84A==} + peerDependencies: + '@typescript-eslint/eslint-plugin': ^6.4.0 + 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 + typescript: '*' + dependencies: + '@typescript-eslint/eslint-plugin': 6.9.0(@typescript-eslint/parser@6.9.0)(eslint@8.52.0)(typescript@5.2.2) + '@typescript-eslint/parser': 6.9.0(eslint@8.52.0)(typescript@5.2.2) + eslint: 8.52.0 + eslint-config-standard: 17.1.0(eslint-plugin-import@2.29.0)(eslint-plugin-n@16.2.0)(eslint-plugin-promise@6.1.1)(eslint@8.52.0) + eslint-plugin-import: 2.29.0(@typescript-eslint/parser@6.9.0)(eslint@8.52.0) + eslint-plugin-n: 16.2.0(eslint@8.52.0) + eslint-plugin-promise: 6.1.1(eslint@8.52.0) + typescript: 5.2.2 + transitivePeerDependencies: + - supports-color + dev: true + + /eslint-config-standard@17.1.0(eslint-plugin-import@2.29.0)(eslint-plugin-n@16.2.0)(eslint-plugin-promise@6.1.1)(eslint@8.52.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.52.0 + eslint-plugin-import: 2.29.0(@typescript-eslint/parser@6.9.0)(eslint@8.52.0) + eslint-plugin-n: 16.2.0(eslint@8.52.0) + eslint-plugin-promise: 6.1.1(eslint@8.52.0) + dev: true + + /eslint-etc@5.2.1(eslint@8.52.0)(typescript@5.2.2): + resolution: {integrity: sha512-lFJBSiIURdqQKq9xJhvSJFyPA+VeTh5xvk24e8pxVL7bwLBtGF60C/KRkLTMrvCZ6DA3kbPuYhLWY0TZMlqTsg==} + peerDependencies: + eslint: ^8.0.0 + typescript: '>=4.0.0' + dependencies: + '@typescript-eslint/experimental-utils': 5.62.0(eslint@8.52.0)(typescript@5.2.2) + eslint: 8.52.0 + tsutils: 3.21.0(typescript@5.2.2) + tsutils-etc: 1.4.2(tsutils@3.21.0)(typescript@5.2.2) + typescript: 5.2.2 + transitivePeerDependencies: + - supports-color + 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-module-utils@2.8.0(@typescript-eslint/parser@6.9.0)(eslint-import-resolver-node@0.3.9)(eslint@8.52.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.9.0(eslint@8.52.0)(typescript@5.2.2) + debug: 3.2.7 + eslint: 8.52.0 + eslint-import-resolver-node: 0.3.9 + transitivePeerDependencies: + - supports-color + dev: true + + /eslint-plugin-es-x@7.2.0(eslint@8.52.0): + resolution: {integrity: sha512-9dvv5CcvNjSJPqnS5uZkqb3xmbeqRLnvXKK7iI5+oK/yTusyc46zbBZKENGsOfojm/mKfszyZb+wNqNPAPeGXA==} + engines: {node: ^14.18.0 || >=16.0.0} + peerDependencies: + eslint: '>=8' + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@8.52.0) + '@eslint-community/regexpp': 4.10.0 + eslint: 8.52.0 + dev: true + + /eslint-plugin-eslint-comments@3.2.0(eslint@8.52.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.52.0 + ignore: 5.2.4 + dev: true + + /eslint-plugin-etc@2.0.3(eslint@8.52.0)(typescript@5.2.2): + resolution: {integrity: sha512-o5RS/0YwtjlGKWjhKojgmm82gV1b4NQUuwk9zqjy9/EjxNFKKYCaF+0M7DkYBn44mJ6JYFZw3Ft249dkKuR1ew==} + peerDependencies: + eslint: ^8.0.0 + typescript: '>=4.0.0' + dependencies: + '@phenomnomnominal/tsquery': 5.0.1(typescript@5.2.2) + '@typescript-eslint/experimental-utils': 5.62.0(eslint@8.52.0)(typescript@5.2.2) + eslint: 8.52.0 + eslint-etc: 5.2.1(eslint@8.52.0)(typescript@5.2.2) + requireindex: 1.2.0 + tslib: 2.6.2 + tsutils: 3.21.0(typescript@5.2.2) + typescript: 5.2.2 + transitivePeerDependencies: + - supports-color + dev: true + + /eslint-plugin-html@7.1.0: + resolution: {integrity: sha512-fNLRraV/e6j8e3XYOC9xgND4j+U7b1Rq+OygMlLcMg+wI/IpVbF+ubQa3R78EjKB9njT6TQOlcK5rFKBVVtdfg==} + dependencies: + htmlparser2: 8.0.2 + dev: true + + /eslint-plugin-import@2.29.0(@typescript-eslint/parser@6.9.0)(eslint@8.52.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': 6.9.0(eslint@8.52.0)(typescript@5.2.2) + 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.52.0 + eslint-import-resolver-node: 0.3.9 + eslint-module-utils: 2.8.0(@typescript-eslint/parser@6.9.0)(eslint-import-resolver-node@0.3.9)(eslint@8.52.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-jsdoc@46.8.2(eslint@8.52.0): + resolution: {integrity: sha512-5TSnD018f3tUJNne4s4gDWQflbsgOycIKEUBoCLn6XtBMgNHxQFmV8vVxUtiPxAQq8lrX85OaSG/2gnctxw9uQ==} + engines: {node: '>=16'} + peerDependencies: + eslint: ^7.0.0 || ^8.0.0 + dependencies: + '@es-joy/jsdoccomment': 0.40.1 + are-docs-informative: 0.0.2 + comment-parser: 1.4.0 + debug: 4.3.4(supports-color@8.1.1) + escape-string-regexp: 4.0.0 + eslint: 8.52.0 + esquery: 1.5.0 + is-builtin-module: 3.2.1 + semver: 7.5.4 + spdx-expression-parse: 3.0.1 + transitivePeerDependencies: + - supports-color + dev: true + + /eslint-plugin-jsonc@2.10.0(eslint@8.52.0): + resolution: {integrity: sha512-9d//o6Jyh4s1RxC9fNSt1+MMaFN2ruFdXPG9XZcb/mR2KkfjADYiNL/hbU6W0Cyxfg3tS/XSFuhl5LgtMD8hmw==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: '>=6.0.0' + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@8.52.0) + eslint: 8.52.0 + eslint-compat-utils: 0.1.2(eslint@8.52.0) + jsonc-eslint-parser: 2.4.0 + natural-compare: 1.4.0 + dev: true + + /eslint-plugin-markdown@3.0.1(eslint@8.52.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.52.0 + mdast-util-from-markdown: 0.8.5 + transitivePeerDependencies: + - supports-color + dev: true + + /eslint-plugin-n@16.2.0(eslint@8.52.0): + resolution: {integrity: sha512-AQER2jEyQOt1LG6JkGJCCIFotzmlcCZFur2wdKrp1JX2cNotC7Ae0BcD/4lLv3lUAArM9uNS8z/fsvXTd0L71g==} + engines: {node: '>=16.0.0'} + peerDependencies: + eslint: '>=7.0.0' + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@8.52.0) + builtins: 5.0.1 + eslint: 8.52.0 + eslint-plugin-es-x: 7.2.0(eslint@8.52.0) + get-tsconfig: 4.7.2 + ignore: 5.2.4 + is-core-module: 2.13.1 + minimatch: 3.1.2 + resolve: 1.22.8 + semver: 7.5.4 + dev: true + + /eslint-plugin-no-only-tests@3.1.0: + resolution: {integrity: sha512-Lf4YW/bL6Un1R6A76pRZyE1dl1vr31G/ev8UzIc/geCgFWyrKil8hVjYqWVKGB/UIGmb6Slzs9T0wNezdSVegw==} + engines: {node: '>=5.0.0'} + dev: true + + /eslint-plugin-promise@6.1.1(eslint@8.52.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.52.0 + dev: true + + /eslint-plugin-react-hooks@4.6.0(eslint@8.52.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.52.0 + dev: true + + /eslint-plugin-react@7.33.2(eslint@8.52.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.52.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-unicorn@48.0.1(eslint@8.52.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.52.0) + ci-info: 3.9.0 + clean-regexp: 1.0.0 + eslint: 8.52.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-plugin-yml@1.10.0(eslint@8.52.0): + resolution: {integrity: sha512-53SUwuNDna97lVk38hL/5++WXDuugPM9SUQ1T645R0EHMRCdBIIxGye/oOX2qO3FQ7aImxaUZJU/ju+NMUBrLQ==} + engines: {node: ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: '>=6.0.0' + dependencies: + debug: 4.3.4(supports-color@8.1.1) + eslint: 8.52.0 + eslint-compat-utils: 0.1.2(eslint@8.52.0) + lodash: 4.17.21 + natural-compare: 1.4.0 + yaml-eslint-parser: 1.2.2 + 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-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.52.0: + resolution: {integrity: sha512-zh/JHnaixqHZsolRB/w9/02akBk9EPrOs9JwcTP2ek7yL5bVvXuRariiaAjjoJ5DvuwQ1WAE/HsMz+w17YgBCg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + hasBin: true + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@8.52.0) + '@eslint-community/regexpp': 4.10.0 + '@eslint/eslintrc': 2.1.2 + '@eslint/js': 8.52.0 + '@humanwhocodes/config-array': 0.11.13 + '@humanwhocodes/module-importer': 1.0.1 + '@nodelib/fs.walk': 1.2.8 + '@ungap/structured-clone': 1.2.0 + ajv: 6.12.6 + chalk: 4.1.2 + cross-spawn: 7.0.3 + debug: 4.3.4(supports-color@8.1.1) + 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.23.0 + graphemer: 1.4.0 + ignore: 5.2.4 + 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.2 + acorn-jsx: 5.3.2(acorn@8.11.2) + 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-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 + + /eventemitter3@5.0.1: + resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==} + + /events@3.3.0: + resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} + engines: {node: '>=0.8.x'} + 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 + + /exit-hook@4.0.0: + resolution: {integrity: sha512-Fqs7ChZm72y40wKjOFXBKg7nJZvQJmewP5/7LtePDdnah/+FH9Hp5sgMujSCMPXlxOAW2//1jrW9pnsY7o20vQ==} + engines: {node: '>=18'} + dev: true + + /expand-tilde@2.0.2: + resolution: {integrity: sha512-A5EmesHW6rfnZ9ysHQjPdJRni0SRar0tjtG5MNtm9n5TUvsYU8oozprtRD4AqHxcZWWlVuAmQo2nWKfN9oyjTw==} + engines: {node: '>=0.10.0'} + dependencies: + homedir-polyfill: 1.0.3 + dev: true + + /fast-check@3.14.0: + resolution: {integrity: sha512-9Z0zqASzDNjXBox/ileV/fd+4P+V/f3o4shM6QawvcdLFh8yjPG4h5BrHUZ8yzY6amKGDTAmRMyb/JZqe+dCgw==} + engines: {node: '>=8.0.0'} + dependencies: + pure-rand: 6.0.4 + 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.15.0: + resolution: {integrity: sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==} + 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.1.1 + 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 + + /findup-sync@5.0.0: + resolution: {integrity: sha512-MzwXju70AuyflbgeOhzvQWAvvQdo1XL0A9bVvlXsYcFEBM87WR4OakL4OfZq+QRmr+duJubio+UtNQCPsVESzQ==} + engines: {node: '>= 10.13.0'} + dependencies: + detect-file: 1.0.0 + is-glob: 4.0.3 + micromatch: 4.0.5 + resolve-dir: 1.0.1 + dev: true + + /flat-cache@3.1.1: + resolution: {integrity: sha512-/qM2b3LUIaIgviBQovTLvijfyOQXPtSRnRK26ksj2J7rzPIecePUIpJsZ4T02Qg+xiAEKIs5K8dsHEd+VaKa/Q==} + engines: {node: '>=12.0.0'} + dependencies: + flatted: 3.2.9 + 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.2.9: + resolution: {integrity: sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==} + dev: true + + /for-each@0.3.3: + resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} + dependencies: + is-callable: 1.2.7 + dev: true + + /foreground-child@2.0.0: + resolution: {integrity: sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA==} + engines: {node: '>=8.0.0'} + dependencies: + cross-spawn: 7.0.3 + signal-exit: 3.0.7 + 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-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.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 + + /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@7.2.0: + resolution: {integrity: sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==} + 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 + + /global-modules@1.0.0: + resolution: {integrity: sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==} + engines: {node: '>=0.10.0'} + dependencies: + global-prefix: 1.0.2 + is-windows: 1.0.2 + resolve-dir: 1.0.1 + dev: true + + /global-prefix@1.0.2: + resolution: {integrity: sha512-5lsx1NUDHtSjfg0eHlmYvZKv8/nVqX4ckFbM+FrGcQ+04KWcWFo9P5MxPZYSzUvyzmdTbI7Eix8Q4IbELDqzKg==} + engines: {node: '>=0.10.0'} + dependencies: + expand-tilde: 2.0.2 + homedir-polyfill: 1.0.3 + ini: 1.3.8 + is-windows: 1.0.2 + which: 1.3.1 + dev: true + + /globals@11.12.0: + resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} + engines: {node: '>=4'} + dev: true + + /globals@13.23.0: + resolution: {integrity: sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==} + 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@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.2.4 + 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.2.4 + merge2: 1.4.1 + slash: 4.0.0 + dev: true + + /globby@14.0.0: + resolution: {integrity: sha512-/1WM/LNHRAOH9lZta77uGbq0dAEQM+XjNesWwhlERDVenqothRbnzTrL3/LrIoEPPjeUHC3vrS6TwoyxeHs7MQ==} + engines: {node: '>=18'} + dependencies: + '@sindresorhus/merge-streams': 1.0.0 + fast-glob: 3.3.2 + ignore: 5.2.4 + 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.2 + 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 + + /hamt-sharding@3.0.2: + resolution: {integrity: sha512-f0DzBD2tSmLFdFsLAvOflIBqFPjerbA7BfmwO8mVho/5hXwgyyYhv+ijIzidQf/DpDX3bRjAQvhGoBFj+DBvPw==} + engines: {node: '>=16.0.0', npm: '>=7.0.0'} + dependencies: + sparse-array: 1.3.2 + uint8arrays: 4.0.9 + dev: false + + /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.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 + + /he@1.2.0: + resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} + hasBin: true + dev: true + + /homedir-polyfill@1.0.3: + resolution: {integrity: sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==} + engines: {node: '>=0.10.0'} + dependencies: + parse-passwd: 1.0.0 + dev: true + + /hosted-git-info@2.8.9: + resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==} + 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 + + /human-signals@5.0.0: + resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==} + engines: {node: '>=16.17.0'} + dev: true + + /ieee754@1.2.1: + resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} + + /ignore@5.2.4: + resolution: {integrity: sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==} + 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 + + /indent-string@5.0.0: + resolution: {integrity: sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==} + engines: {node: '>=12'} + 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 + + /interface-blockstore@5.2.7: + resolution: {integrity: sha512-B9UplmgUdQg15f/6xDJEbQYcjMm568cnqJsxSZYbDD0s6eQX5gKh58sd9H3aJEMosIy8T4vz9MwWWZuAOc3hQQ==} + dependencies: + interface-store: 5.1.5 + multiformats: 12.1.3 + + /interface-datastore@8.2.9: + resolution: {integrity: sha512-J/8PN8TnB5xxCRtgu9Vx3zExdOzcTU5/DBF2dlU41deX1GW6/SPpbJo5DRNSnvzfjmwJ7YhUOIFXyccUp8nuAA==} + dependencies: + interface-store: 5.1.5 + uint8arrays: 5.0.0 + dev: true + + /interface-store@5.1.5: + resolution: {integrity: sha512-X0KnJBk3o+YL13MxZBMwa88/b3Mdrpm0yPzkSTKDDVn9BSPH7UK6W+ZtIPO2bxKOQVmq7zqOwAnYnpfqWjb6/g==} + + /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 + + /ipfs-unixfs-exporter@13.2.2: + resolution: {integrity: sha512-poCxSte+SdQzuPc/Sm+gx/86VJu+IEsW6/Cfkq29yEUZDG8QuCvTkvuqAysKAYuN40aR9SjYqwYFRW/hsvspSw==} + engines: {node: '>=16.0.0', npm: '>=7.0.0'} + dependencies: + '@ipld/dag-cbor': 9.0.6 + '@ipld/dag-pb': 4.0.6 + '@multiformats/murmur3': 2.1.7 + err-code: 3.0.1 + hamt-sharding: 3.0.2 + interface-blockstore: 5.2.7 + ipfs-unixfs: 11.1.0 + it-filter: 3.0.4 + it-last: 3.0.4 + it-map: 3.0.5 + it-parallel: 3.0.6 + it-pipe: 3.0.1 + it-pushable: 3.2.3 + multiformats: 12.1.3 + p-queue: 7.4.1 + progress-events: 1.0.0 + uint8arrays: 4.0.9 + dev: false + + /ipfs-unixfs-importer@15.2.1: + resolution: {integrity: sha512-9ArBh7Xfz8gUSe8pq9c9ilBOXd1bbT3L+4xnI6w/usWLwnNT14p8WbFZjDD0MO1/PrD0PTUZuHNDS2l4EO+wPg==} + engines: {node: '>=16.0.0', npm: '>=7.0.0'} + dependencies: + '@ipld/dag-pb': 4.0.6 + '@multiformats/murmur3': 2.1.7 + err-code: 3.0.1 + hamt-sharding: 3.0.2 + interface-blockstore: 5.2.7 + interface-store: 5.1.5 + ipfs-unixfs: 11.1.0 + it-all: 3.0.4 + it-batch: 3.0.4 + it-first: 3.0.4 + it-parallel-batch: 3.0.4 + multiformats: 12.1.3 + progress-events: 1.0.0 + rabin-wasm: 0.1.5 + uint8arraylist: 2.4.7 + uint8arrays: 4.0.9 + transitivePeerDependencies: + - encoding + - supports-color + dev: false + + /ipfs-unixfs@11.1.0: + resolution: {integrity: sha512-Lq37nKLJOpRFjx3rcg3y+ZwUxBX7jluKfIt5UPp6wb1L3dP0sj1yaLR0Yg2CdGYvHWyUpZD1iTnT8upL0ToDOw==} + engines: {node: '>=16.0.0', npm: '>=7.0.0'} + dependencies: + err-code: 3.0.1 + protons-runtime: 5.2.0 + uint8arraylist: 2.4.7 + dev: false + + /is-alphabetical@1.0.4: + resolution: {integrity: sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==} + 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-arguments@1.1.1: + resolution: {integrity: sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + 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.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-decimal@1.0.4: + resolution: {integrity: sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw==} + 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-fullwidth-code-point@4.0.0: + resolution: {integrity: sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==} + engines: {node: '>=12'} + 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-hexadecimal@1.0.4: + resolution: {integrity: sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw==} + dev: true + + /is-interactive@2.0.0: + resolution: {integrity: sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==} + engines: {node: '>=12'} + dev: true + + /is-map@2.0.2: + resolution: {integrity: sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==} + dev: true + + /is-nan@1.3.2: + resolution: {integrity: sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + define-properties: 1.2.1 + dev: 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@2.1.0: + resolution: {integrity: sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==} + engines: {node: '>=8'} + 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@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-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 + + /isarray@2.0.5: + resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} + dev: true + + /isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + dev: true + + /iso-base@2.0.1: + resolution: {integrity: sha512-ip0nUW9oZP+LG6mslSgdJPt9NWZOq1qIOKpoUIdm8sq/87VwY8WZXw9ptCkhdJclY+r4feFbZuu9P/OFDqCvkQ==} + dependencies: + base-x: 4.0.0 + bigint-mod-arith: 3.3.1 + dev: false + + /istanbul-lib-coverage@3.2.2: + resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==} + engines: {node: '>=8'} + 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-reports@3.1.6: + resolution: {integrity: sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg==} + engines: {node: '>=8'} + dependencies: + html-escaper: 2.0.2 + istanbul-lib-report: 3.0.1 + dev: true + + /it-all@3.0.4: + resolution: {integrity: sha512-UMiy0i9DqCHBdWvMbzdYvVGa5/w4t1cc4nchpbnjdLhklglv8mQeEYnii0gvKESJuL1zV32Cqdb33R6/GPfxpQ==} + dev: false + + /it-batch@3.0.4: + resolution: {integrity: sha512-WRu2mqOYIs+T9k7+yxSK9VJdk0UE4R0jKQsWQcti5c6vhb1FhjC2+yCB5XBrctQ9edNfCMU/wVzdDj8qSwimbA==} + dev: false + + /it-drain@3.0.5: + resolution: {integrity: sha512-qYFe4SWdvs9oJGUY5bSjvmiLUMLzFEODNOQUdYdCIkuIgQF+AUB2INhM4yQ09buJ2rhHKDFxvTD/+yUq6qg0XA==} + dev: true + + /it-filter@3.0.4: + resolution: {integrity: sha512-e0sz+st4sudK/zH6GZ/gRTRP8A/ADuJFCYDmRgMbZvR79y5+v4ZXav850bBZk5wL9zXaYZFxS1v/6Qi+Vjwh5g==} + dependencies: + it-peekable: 3.0.3 + + /it-first@3.0.4: + resolution: {integrity: sha512-FtQl84iTNxN5EItP/JgL28V2rzNMkCzTUlNoj41eVdfix2z1DBuLnBqZ0hzYhGGa1rMpbQf0M7CQSA2adlrLJg==} + dev: false + + /it-last@3.0.4: + resolution: {integrity: sha512-Ns+KTsQWhs0KCvfv5X3Ck3lpoYxHcp4zUp4d+AOdmC8cXXqDuoZqAjfWhgCbxJubXyIYWdfE2nRcfWqgvZHP8Q==} + dev: false + + /it-map@3.0.5: + resolution: {integrity: sha512-hB0TDXo/h4KSJJDSRLgAPmDroiXP6Fx1ck4Bzl3US9hHfZweTKsuiP0y4gXuTMcJlS6vj0bb+f70rhkD47ZA3w==} + dependencies: + it-peekable: 3.0.3 + dev: false + + /it-merge@3.0.3: + resolution: {integrity: sha512-FYVU15KC5pb/GQX1Ims+lee8d4pdqGVCpWr0lkNj8o4xuNo7jY71k6GuEiWdP+T7W1bJqewSxX5yoTy5yZpRVA==} + dependencies: + it-pushable: 3.2.3 + + /it-parallel-batch@3.0.4: + resolution: {integrity: sha512-O1omh8ss8+UtXiMjE+8kM5C20DT0Ma4VtKVfrSHOJU0UHZ+iWBXarabzPYEp+WiuQmrv+klDPPlTZ9KaLN9xOA==} + dependencies: + it-batch: 3.0.4 + dev: false + + /it-parallel@3.0.6: + resolution: {integrity: sha512-i7UM7I9LTkDJw3YIqXHFAPZX6CWYzGc+X3irdNrVExI4vPazrJdI7t5OqrSVN8CONXLAunCiqaSV/zZRbQR56A==} + dependencies: + p-defer: 4.0.0 + dev: false + + /it-peekable@3.0.3: + resolution: {integrity: sha512-Wx21JX/rMzTEl9flx3DGHuPV1KQFGOl8uoKfQtmZHgPQtGb89eQ6RyVd82h3HuP9Ghpt0WgBDlmmdWeHXqyx7w==} + + /it-pipe@3.0.1: + resolution: {integrity: sha512-sIoNrQl1qSRg2seYSBH/3QxWhJFn9PKYvOf/bHdtCBF0bnghey44VyASsWzn5dAx0DCDDABq1hZIuzKmtBZmKA==} + engines: {node: '>=16.0.0', npm: '>=7.0.0'} + dependencies: + it-merge: 3.0.3 + it-pushable: 3.2.3 + it-stream-types: 2.0.1 + dev: false + + /it-pushable@3.2.3: + resolution: {integrity: sha512-gzYnXYK8Y5t5b/BnJUr7glfQLO4U5vyb05gPx/TyTw+4Bv1zM9gFk4YsOrnulWefMewlphCjKkakFvj1y99Tcg==} + dependencies: + p-defer: 4.0.0 + + /it-stream-types@2.0.1: + resolution: {integrity: sha512-6DmOs5r7ERDbvS4q8yLKENcj6Yecr7QQTqWApbZdfAUTEC947d+PEha7PCqhm//9oxaLYL7TWRekwhoXl2s6fg==} + engines: {node: '>=16.0.0', npm: '>=7.0.0'} + + /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 + + /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 + + /jsdoc-type-pratt-parser@4.0.0: + resolution: {integrity: sha512-YtOli5Cmzy3q4dP26GraSOeAhqecewG04hoO8DY56CH4KJ9Fvv5qKWUCCo3HZob7esJQHCv6/+bnTy72xZZaVQ==} + engines: {node: '>=12.0.0'} + 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 + + /jsonc-eslint-parser@2.4.0: + resolution: {integrity: sha512-WYDyuc/uFcGp6YtM2H0uKmUwieOuzeE/5YocFJLnLfclZ4inf3mRn8ZVy1s7Hxji7Jxm6Ss8gqpexD/GlKoGgg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + acorn: 8.11.2 + eslint-visitor-keys: 3.4.3 + espree: 9.6.1 + semver: 7.5.4 + dev: true + + /jsonc-parser@3.2.0: + resolution: {integrity: sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==} + 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 + + /junk@4.0.1: + resolution: {integrity: sha512-Qush0uP+G8ZScpGMZvHUiRfI0YBWuB3gVBYlI0v0vvOJt5FLicco+IkP0a50LqTTQhmts/m6tP5SWE+USyIvcQ==} + engines: {node: '>=12.20'} + dev: true + + /keyv@4.5.4: + resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + dependencies: + json-buffer: 3.0.1 + dev: true + + /kleur@4.1.5: + resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==} + 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@2.1.0: + resolution: {integrity: sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==} + engines: {node: '>=10'} + 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 + + /lint-staged@15.1.0: + resolution: {integrity: sha512-ZPKXWHVlL7uwVpy8OZ7YQjYDAuO5X4kMh0XgZvPNxLcCCngd0PO5jKQyy3+s4TL2EnHoIXIzP1422f/l3nZKMw==} + engines: {node: '>=18.12.0'} + hasBin: true + dependencies: + chalk: 5.3.0 + commander: 11.1.0 + debug: 4.3.4(supports-color@8.1.1) + execa: 8.0.1 + lilconfig: 2.1.0 + listr2: 7.0.2 + micromatch: 4.0.5 + pidtree: 0.6.0 + string-argv: 0.3.2 + yaml: 2.3.4 + transitivePeerDependencies: + - supports-color + dev: true + + /listr2@7.0.2: + resolution: {integrity: sha512-rJysbR9GKIalhTbVL2tYbF2hVyDnrf7pFUZBwjPaMIdadYHmeT+EVi/Bu3qd7ETQPahTotg2WRCatXwRBW554g==} + engines: {node: '>=16.0.0'} + dependencies: + cli-truncate: 3.1.0 + colorette: 2.0.20 + eventemitter3: 5.0.1 + log-update: 5.0.1 + rfdc: 1.3.0 + wrap-ansi: 8.1.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@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 + + /log-symbols@5.1.0: + resolution: {integrity: sha512-l0x2DvrW294C9uDCoQe1VSU4gf529FkSZ6leBl4TiqZH/e+0R7hSfHQBNut2mNygDgHwvYHfFLn6Oxb3VWj2rA==} + engines: {node: '>=12'} + dependencies: + chalk: 5.3.0 + is-unicode-supported: 1.3.0 + dev: true + + /log-update@5.0.1: + resolution: {integrity: sha512-5UtUDQ/6edw4ofyljDNcOVJQ4c7OjDro4h3y8e1GQL5iYElYclVHJ3zeWchylvMaKnDbDilC8irOVyexnA/Slw==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + ansi-escapes: 5.0.0 + cli-cursor: 4.0.0 + slice-ansi: 5.0.0 + strip-ansi: 7.1.0 + wrap-ansi: 8.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 + 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 + + /lunr@2.3.9: + resolution: {integrity: sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==} + 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 + + /marked@4.3.0: + resolution: {integrity: sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==} + engines: {node: '>= 12'} + hasBin: true + dev: true + + /matchit@1.1.0: + resolution: {integrity: sha512-+nGYoOlfHmxe5BW5tE0EMJppXEwdSf8uBA1GTZC7Q77kbT35+VKLYJMzVNWCHSsga1ps1tPYFtFyvxvKzWVmMA==} + engines: {node: '>=6'} + dependencies: + '@arr/every': 1.0.1 + dev: true + + /mdast-util-from-markdown@0.8.5: + resolution: {integrity: sha512-2hkTXtYYnr+NubD/g6KGBS/0mFmBcifAsI0yIWRiRo0PjVs6SSOSOdtzbp6kSGnShDN6G5aWZpKQ2lWRy27mWQ==} + dependencies: + '@types/mdast': 3.0.14 + 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-to-string@2.0.0: + resolution: {integrity: sha512-AW4DRS3QbBayY/jJmD8437V1Gombjf8RSOUCMFBuo5iHi58AGEgVCKQ+ezHkZZDpAQS75hcBMpLqjpJTjtUL7w==} + dev: true + + /merge-options@3.0.4: + resolution: {integrity: sha512-2Sug1+knBjkaMsMgf1ctR1Ujx+Ayku4EdJN4Z+C2+JzoeF7A3OZ9KM2GY0CpQS51NR61LTurMJrRKPhSs3ZRTQ==} + engines: {node: '>=10'} + dependencies: + is-plain-obj: 2.1.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 + + /micromark@2.11.4: + resolution: {integrity: sha512-+WoovN/ppKolQOFIAajxi7Lu9kInbPxFuTBVEavFcL8eAfVstoc5MocPmqBeAdBOJV00uaVjegzH4+MA0DN/uA==} + dependencies: + debug: 4.3.4(supports-color@8.1.1) + parse-entities: 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 + + /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.0.1: + resolution: {integrity: sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==} + engines: {node: '>=10'} + dependencies: + brace-expansion: 2.0.1 + dev: true + + /minimatch@7.4.6: + resolution: {integrity: sha512-sBz8G/YjVniEz6lKPNpKxXwazJe4c19fEfV2GDMX6AjFz+MX9uDWIZW8XreVhkFW3fkIdTv/gxWr/Kks5FFAVw==} + 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==} + + /mocha@10.2.0: + resolution: {integrity: sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg==} + engines: {node: '>= 14.0.0'} + hasBin: true + dependencies: + ansi-colors: 4.1.1 + browser-stdout: 1.3.1 + chokidar: 3.5.3 + debug: 4.3.4(supports-color@8.1.1) + diff: 5.0.0 + escape-string-regexp: 4.0.0 + find-up: 5.0.0 + glob: 7.2.0 + he: 1.2.0 + js-yaml: 4.1.0 + log-symbols: 4.1.0 + minimatch: 5.0.1 + ms: 2.1.3 + nanoid: 3.3.3 + serialize-javascript: 6.0.0 + strip-json-comments: 3.1.1 + supports-color: 8.1.1 + workerpool: 6.2.1 + yargs: 16.2.0 + yargs-parser: 20.2.4 + yargs-unparser: 2.0.0 + 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.1.2: + resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} + + /ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + dev: true + + /multiformats@12.1.3: + resolution: {integrity: sha512-eajQ/ZH7qXZQR2AgtfpmSMizQzmyYVmCql7pdhldPuYQi4atACekbJaQplk6dWyIi10jCaFnd6pqvcEFXjbaJw==} + engines: {node: '>=16.0.0', npm: '>=7.0.0'} + + /multimatch@5.0.0: + resolution: {integrity: sha512-ypMKuglUrZUD99Tk2bUQ+xNQj43lPEfAeX2o9cTteAmShXy2VHDJpuwu1o0xqoKCt9jLVAvwyFKdLTPXKAfJyA==} + engines: {node: '>=10'} + dependencies: + '@types/minimatch': 3.0.5 + array-differ: 3.0.0 + array-union: 2.1.0 + arrify: 2.0.1 + minimatch: 3.1.2 + dev: true + + /murmurhash3js-revisited@3.0.0: + resolution: {integrity: sha512-/sF3ee6zvScXMb1XFJ8gDsSnY+X8PbOyjIuBhtgis10W2Jx4ZjIhikUCIF9c4gpJxVnQIsPAFrSwTCuAjicP6g==} + engines: {node: '>=8.0.0'} + dev: false + + /nanoid@3.3.3: + resolution: {integrity: sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + 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@5.0.3: + resolution: {integrity: sha512-I7X2b22cxA4LIHXPSqbBCEQSL+1wv8TuoefejsX4HFWyC6jc5JG7CEaxOltiKjc1M+YCS2YkrZZcj4+dytw9GA==} + engines: {node: ^18 || >=20} + hasBin: true + dev: true + + /natural-compare@1.4.0: + resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + 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: 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@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 + + /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-is@1.1.5: + resolution: {integrity: sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + 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.4: + resolution: {integrity: sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==} + 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.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.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 + + /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.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@7.0.1: + resolution: {integrity: sha512-0TUxTiFJWv+JnjWm4o9yvuskpEJLXTcng8MJuKd+SzAzp2o+OP3HWqNhB4OdJRt1Vsd9/mR0oyaEYlOnL7XIRw==} + engines: {node: '>=16'} + dependencies: + chalk: 5.3.0 + cli-cursor: 4.0.0 + cli-spinners: 2.9.1 + is-interactive: 2.0.0 + is-unicode-supported: 1.3.0 + log-symbols: 5.1.0 + stdin-discarder: 0.1.0 + string-width: 6.1.0 + strip-ansi: 7.1.0 + dev: true + + /p-defer@4.0.0: + resolution: {integrity: sha512-Vb3QRvQ0Y5XnF40ZUWW7JfLogicVh/EnA5gBIvKDJoYpeI82+1E3AlB9yOcKFS0AhHrWVnAQO39fbR0G99IVEQ==} + engines: {node: '>=12'} + + /p-event@6.0.0: + resolution: {integrity: sha512-Xbfxd0CfZmHLGKXH32k1JKjQYX6Rkv0UtQdaFJ8OyNcf+c0oWCeXHc1C4CX/IESZLmcvfPa5aFIO/vCr5gqtag==} + engines: {node: '>=16.17'} + dependencies: + p-timeout: 6.1.2 + dev: true + + /p-filter@3.0.0: + resolution: {integrity: sha512-QtoWLjXAW++uTX67HZQz1dbTpqBfiidsB6VtQUC9iR85S120+s0T5sO6s+B5MLzFcZkrEd/DGMmCjR+f2Qpxwg==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + p-map: 5.5.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@5.5.0: + resolution: {integrity: sha512-VFqfGDHlx87K66yZrNdI4YGtD70IRyd+zSvgks6mzHPRNkoKy+9EKP4SFC77/vTTQYmRmti7dvqC+m5jBrBAcg==} + engines: {node: '>=12'} + dependencies: + aggregate-error: 4.0.1 + dev: true + + /p-map@6.0.0: + resolution: {integrity: sha512-T8BatKGY+k5rU+Q/GTYgrEf2r4xRMevAN5mtXc2aPc4rS1j3s+vWTaO2Wag94neXuCAUAs8cxBL9EeB5EA6diw==} + engines: {node: '>=16'} + dev: true + + /p-queue@7.4.1: + resolution: {integrity: sha512-vRpMXmIkYF2/1hLBKisKeVYJZ8S2tZ0zEAmIJgdVKP2nq0nh4qCdf8bgw+ZgKrkh71AOCaqzwbJJk1WtdcF3VA==} + engines: {node: '>=12'} + dependencies: + eventemitter3: 5.0.1 + p-timeout: 5.1.0 + dev: false + + /p-timeout@5.1.0: + resolution: {integrity: sha512-auFDyzzzGZZZdHz3BtET9VEz0SE/uMEAx7uWfGPucfzEwwe/xH0iVeZibQmANYE/hp9T2+UUZT5m+BKyrDp3Ew==} + engines: {node: '>=12'} + dev: false + + /p-timeout@6.1.2: + resolution: {integrity: sha512-UbD77BuZ9Bc9aABo74gfXhNvzC9Tx7SxtHSh1fxvx3jTLLYvmVhiQZZrJzqqU0jKbN32kb5VOKiLEQI/3bIjgQ==} + engines: {node: '>=14.16'} + 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-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-passwd@1.0.0: + resolution: {integrity: sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q==} + engines: {node: '>=0.10.0'} + 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-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 + + /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 + + /pidtree@0.6.0: + resolution: {integrity: sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==} + engines: {node: '>=0.10'} + hasBin: true + dev: true + + /playwright-core@1.40.0: + resolution: {integrity: sha512-fvKewVJpGeca8t0ipM56jkVSU6Eo0RmFvQ/MaCQNDYm+sdvKkMBBWTE1FdeMqIdumRaXXjZChWHvIzCGM/tA/Q==} + engines: {node: '>=16'} + hasBin: true + dev: true + + /playwright-test@14.0.0: + resolution: {integrity: sha512-noWhbTO+naQmzrW1/GMbsf2MK3fbiyFbKcBEPt4xTfMxWQ7Je3gkTJ9EU8ryQ/2VL3twe0F2BfG3rizf/i5KvQ==} + engines: {node: '>=16.0.0'} + hasBin: true + dependencies: + acorn-loose: 8.4.0 + assert: 2.1.0 + buffer: 6.0.3 + c8: 8.0.1 + camelcase: 8.0.0 + chokidar: 3.5.3 + cpy: 11.0.0 + esbuild: 0.19.7 + esbuild-plugin-wasm: 1.1.0 + events: 3.3.0 + execa: 8.0.1 + exit-hook: 4.0.0 + globby: 14.0.0 + kleur: 4.1.5 + lilconfig: 3.0.0 + lodash: 4.17.21 + merge-options: 3.0.4 + nanoid: 5.0.3 + ora: 7.0.1 + p-timeout: 6.1.2 + path-browserify: 1.0.1 + playwright-core: 1.40.0 + polka: 0.5.2 + premove: 4.0.0 + process: 0.11.10 + sade: 1.8.1 + sirv: 2.0.3 + source-map: 0.6.1 + source-map-support: 0.5.21 + stream-browserify: 3.0.0 + tempy: 3.1.0 + test-exclude: 6.0.0 + util: 0.12.5 + v8-to-istanbul: 9.2.0 + dev: true + + /please-upgrade-node@3.2.0: + resolution: {integrity: sha512-gQR3WpIgNIKwBMVLkpMUeR3e1/E1y42bqDQZfql+kDeXd8COYfM8PQA4X6y7a8u9Ua9FHmsrrmirW2vHs45hWg==} + dependencies: + semver-compare: 1.0.0 + dev: true + + /pluralize@8.0.0: + resolution: {integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==} + engines: {node: '>=4'} + dev: true + + /polka@0.5.2: + resolution: {integrity: sha512-FVg3vDmCqP80tOrs+OeNlgXYmFppTXdjD5E7I4ET1NjvtNmQrb1/mJibybKkb/d4NA7YWAr1ojxuhpL3FHqdlw==} + dependencies: + '@polka/url': 0.5.0 + trouter: 2.0.1 + dev: true + + /postcss@8.4.32: + resolution: {integrity: sha512-D/kj5JNu6oo2EIy+XL/26JEDTlIbB8hw85G8StOE6L74RQAVVP5rej6wxCNqyMbR4RkPfqvezVbPw81Ngd6Kcw==} + 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'} + dev: true + + /premove@4.0.0: + resolution: {integrity: sha512-zim/Hr4+FVdCIM7zL9b9Z0Wfd5Ya3mnKtiuDv7L5lzYzanSq6cOcVJ7EFcgK4I0pt28l8H0jX/x3nyog380XgQ==} + engines: {node: '>=6'} + hasBin: true + dev: true + + /prettier@3.1.1: + resolution: {integrity: sha512-22UbSzg8luF4UuZtzgiUOfcGM8s4tjBv6dJRT7j275NXsy2jb4aJa4NNveul5x4eqlF1wuhuR2RElK71RvmVaw==} + engines: {node: '>=14'} + hasBin: true + dev: true + + /process@0.11.10: + resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==} + engines: {node: '>= 0.6.0'} + dev: true + + /progress-events@1.0.0: + resolution: {integrity: sha512-zIB6QDrSbPfRg+33FZalluFIowkbV5Xh1xSuetjG+rlC5he6u2dc6VQJ0TbMdlN3R1RHdpOqxEFMKTnQ+itUwA==} + engines: {node: '>=16.0.0', npm: '>=7.0.0'} + dev: false + + /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 + + /protons-runtime@5.2.0: + resolution: {integrity: sha512-jL3VSbXllgm17zurKQ/z+Ath0w+4BknJ+l/NLocfjAB8hbeASOZTNtb7zK3nDsKq2pHK9YFumNQvpkZ6gFfWhA==} + dependencies: + uint8arraylist: 2.4.7 + uint8arrays: 4.0.9 + dev: false + + /punycode@2.3.0: + resolution: {integrity: sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==} + engines: {node: '>=6'} + dev: true + + /pure-rand@6.0.4: + resolution: {integrity: sha512-LA0Y9kxMYv47GIPJy6MI84fqTd2HmYZI83W/kM/SkKfDlajnZYfmXFTxkbY+xSBPkLJxltMa9hIkmdc29eguMA==} + dev: true + + /queue-microtask@1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + dev: true + + /rabin-wasm@0.1.5: + resolution: {integrity: sha512-uWgQTo7pim1Rnj5TuWcCewRDTf0PEFTSlaUjWP4eY9EbLV9em08v89oCz/WO+wRxpYuO36XEHp4wgYQnAgOHzA==} + hasBin: true + dependencies: + '@assemblyscript/loader': 0.9.4 + bl: 5.1.0 + debug: 4.3.4(supports-color@8.1.1) + minimist: 1.2.8 + node-fetch: 2.7.0 + readable-stream: 3.6.2 + transitivePeerDependencies: + - encoding + - supports-color + dev: false + + /randombytes@2.1.0: + resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} + dependencies: + safe-buffer: 5.2.1 + dev: true + + /react-is@16.13.1: + resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} + 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.3 + 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 + + /readdirp@3.6.0: + resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} + engines: {node: '>=8.10.0'} + dependencies: + picomatch: 2.3.1 + dev: true + + /receptacle@1.3.2: + resolution: {integrity: sha512-HrsFvqZZheusncQRiEE7GatOAETrARKV/lnfYicIm8lbvp/JQOdADOfhjBd2DajvoszEyxSM6RlAAIZgEoeu/A==} + dependencies: + ms: 2.1.3 + 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 + + /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-package-name@2.0.1: + resolution: {integrity: sha512-uuoJ1hU/k6M0779t3VMVIYpb2VMJk05cehCaABFhXaibcbvfgR8wKiozLjVFSzJPmQMRqIcO0HMyTFqfV09V6Q==} + dev: true + + /requireindex@1.2.0: + resolution: {integrity: sha512-L9jEkOi3ASd9PYit2cwRfyppc9NoABujTP8/5gFcbERmo5jUoAKovIC3fsF17pkTnGsrByysqX+Kxd2OTNI1ww==} + engines: {node: '>=0.10.5'} + dev: true + + /resolve-dir@1.0.1: + resolution: {integrity: sha512-R7uiTjECzvOsWSfdM0QKFNBVFcK27aHOUwdvK53BcW8zqnGdYp0Fbj82cy54+2A4P2tFM22J5kRfe1R+lM/1yg==} + engines: {node: '>=0.10.0'} + dependencies: + expand-tilde: 2.0.2 + global-modules: 1.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@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@4.0.0: + resolution: {integrity: sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + 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 + + /rfdc@1.3.0: + resolution: {integrity: sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==} + dev: true + + /rimraf@3.0.2: + resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} + hasBin: true + dependencies: + glob: 7.2.3 + dev: true + + /rollup@4.6.1: + resolution: {integrity: sha512-jZHaZotEHQaHLgKr8JnQiDT1rmatjgKlMekyksz+yk9jt/8z9quNjnKNRoaM0wd9DC2QKXjmWWuDYtM3jfF8pQ==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} + hasBin: true + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.6.1 + '@rollup/rollup-android-arm64': 4.6.1 + '@rollup/rollup-darwin-arm64': 4.6.1 + '@rollup/rollup-darwin-x64': 4.6.1 + '@rollup/rollup-linux-arm-gnueabihf': 4.6.1 + '@rollup/rollup-linux-arm64-gnu': 4.6.1 + '@rollup/rollup-linux-arm64-musl': 4.6.1 + '@rollup/rollup-linux-x64-gnu': 4.6.1 + '@rollup/rollup-linux-x64-musl': 4.6.1 + '@rollup/rollup-win32-arm64-msvc': 4.6.1 + '@rollup/rollup-win32-ia32-msvc': 4.6.1 + '@rollup/rollup-win32-x64-msvc': 4.6.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 + + /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.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-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.5 + get-intrinsic: 1.2.2 + is-regex: 1.1.4 + dev: true + + /semver-compare@1.0.0: + resolution: {integrity: sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==} + 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.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 + + /serialize-javascript@6.0.0: + resolution: {integrity: sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==} + dependencies: + randombytes: 2.1.0 + 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@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 + + /shiki@0.14.5: + resolution: {integrity: sha512-1gCAYOcmCFONmErGTrS1fjzJLA7MGZmKzrBNX7apqSwhyITJg2O102uFzXUeBxNnEkDA9vHIKLyeKq0V083vIw==} + dependencies: + ansi-sequence-parser: 1.1.1 + jsonc-parser: 3.2.0 + vscode-oniguruma: 1.7.0 + vscode-textmate: 8.0.0 + 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 + + /simple-git-hooks@2.9.0: + resolution: {integrity: sha512-waSQ5paUQtyGC0ZxlHmcMmD9I1rRXauikBwX31bX58l5vTOhCEcBC5Bi+ZDkPXTjDnZAF8TbCqKBY+9+sVPScw==} + hasBin: true + requiresBuild: true + 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 + + /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 + + /slice-ansi@5.0.0: + resolution: {integrity: sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==} + engines: {node: '>=12'} + dependencies: + ansi-styles: 6.2.1 + is-fullwidth-code-point: 4.0.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 + + /sparse-array@1.3.2: + resolution: {integrity: sha512-ZT711fePGn3+kQyLuv1fpd3rNSkNF8vd5Kv2D+qnOANeyKs3fx6bUMGWRPvgTTcYV64QMqZKZwcuaQSP3AZ0tg==} + dev: false + + /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 + + /stdin-discarder@0.1.0: + resolution: {integrity: sha512-xhV7w8S+bUwlPTb4bAOUQhv8/cSS5offJuX8GQGq32ONF0ZtDWKfkdomM3HMRA+LhX6um/FZ0COqlwsjD53LeQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + bl: 5.1.0 + dev: true + + /stream-browserify@3.0.0: + resolution: {integrity: sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==} + dependencies: + inherits: 2.0.4 + readable-stream: 3.6.2 + dev: true + + /string-argv@0.3.2: + resolution: {integrity: sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==} + engines: {node: '>=0.6.19'} + 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.10: + resolution: {integrity: sha512-rGXbGmOEosIQi6Qva94HUjgPs9vKW+dkG7Y8Q5O2OYkWL6wFaTRZO8zM4mhP94uX55wgyrXzfS2aGtGzUL7EJQ==} + 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 + set-function-name: 2.0.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 + + /string_decoder@1.3.0: + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + dependencies: + safe-buffer: 5.2.1 + + /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@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 + + /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 + + /supports-preserve-symlinks-flag@1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + dev: true + + /temp-dir@3.0.0: + resolution: {integrity: sha512-nHc6S/bwIilKHNRgK/3jlhDoIHcp45YgyiwcAk46Tr0LfEqGBVpmiAyuiuxeVE44m3mXnEeVhaipLOEWmH+Njw==} + engines: {node: '>=14.16'} + 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 + + /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 + + /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 + + /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: false + + /trouter@2.0.1: + resolution: {integrity: sha512-kr8SKKw94OI+xTGOkfsvwZQ8mWoikZDd2n8XZHjJVZUARZT+4/VV6cacRS6CLsH9bNm+HFIPU1Zx4CnNnb4qlQ==} + engines: {node: '>=6'} + dependencies: + matchit: 1.1.0 + dev: true + + /ts-api-utils@1.0.3(typescript@5.2.2): + resolution: {integrity: sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg==} + engines: {node: '>=16.13.0'} + peerDependencies: + typescript: '>=4.2.0' + dependencies: + typescript: 5.2.2 + 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.6.2: + resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} + dev: true + + /tsutils-etc@1.4.2(tsutils@3.21.0)(typescript@5.2.2): + resolution: {integrity: sha512-2Dn5SxTDOu6YWDNKcx1xu2YUy6PUeKrWZB/x2cQ8vY2+iz3JRembKn/iZ0JLT1ZudGNwQQvtFX9AwvRHbXuPUg==} + hasBin: true + peerDependencies: + tsutils: ^3.0.0 + typescript: '>=4.0.0' + dependencies: + '@types/yargs': 17.0.29 + tsutils: 3.21.0(typescript@5.2.2) + typescript: 5.2.2 + yargs: 17.7.2 + dev: true + + /tsutils@3.21.0(typescript@5.2.2): + 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.2.2 + dev: true + + /tsx@4.6.2: + resolution: {integrity: sha512-QPpBdJo+ZDtqZgAnq86iY/PD2KYCUPSUGIunHdGwyII99GKH+f3z3FZ8XNFLSGQIA4I365ui8wnQpl8OKLqcsg==} + engines: {node: '>=18.0.0'} + hasBin: true + dependencies: + esbuild: 0.18.20 + get-tsconfig: 4.7.2 + optionalDependencies: + fsevents: 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.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 + + /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 + + /typedoc-plugin-missing-exports@2.1.0(typedoc@0.25.4): + resolution: {integrity: sha512-+1DhqZCEu7Vu5APnrqpPwl31D+hXpt1fV0Le9ycCRL1eLVdatdl6KVt4SEVwPxnEpKwgOn2dNX6I9+0F1aO2aA==} + peerDependencies: + typedoc: 0.24.x || 0.25.x + dependencies: + typedoc: 0.25.4(typescript@5.2.2) + dev: true + + /typedoc-plugin-zod@1.1.0(typedoc@0.25.4): + resolution: {integrity: sha512-LaQdkYyVVL8CX+4R0GJuOyDa1meiG3M85FiBTPvlikCGaRkTNGSEBZTbx3gQHAsNQ5NWJpLvYJQB6gMhcO8bWw==} + peerDependencies: + typedoc: 0.23.x || 0.24.x || 0.25.x + dependencies: + typedoc: 0.25.4(typescript@5.2.2) + dev: true + + /typedoc@0.25.4(typescript@5.2.2): + resolution: {integrity: sha512-Du9ImmpBCw54bX275yJrxPVnjdIyJO/84co0/L9mwe0R3G4FSR6rQ09AlXVRvZEGMUg09+z/usc8mgygQ1aidA==} + engines: {node: '>= 16'} + hasBin: true + peerDependencies: + typescript: 4.6.x || 4.7.x || 4.8.x || 4.9.x || 5.0.x || 5.1.x || 5.2.x || 5.3.x + dependencies: + lunr: 2.3.9 + marked: 4.3.0 + minimatch: 9.0.3 + shiki: 0.14.5 + typescript: 5.2.2 + dev: true + + /typescript@5.2.2: + resolution: {integrity: sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==} + engines: {node: '>=14.17'} + hasBin: true + dev: true + + /uint8-varint@2.0.2: + resolution: {integrity: sha512-LZXmBT0jiHR7J4oKM1GUhtdLFW1yPauzI8NjJlotXn92TprO9u8VMvEVR4QMk8xhUVUd+2fqfU2/kGbVHYSSWw==} + dependencies: + uint8arraylist: 2.4.7 + uint8arrays: 4.0.9 + dev: true + + /uint8arraylist@2.4.7: + resolution: {integrity: sha512-ohRElqR6C5dd60vRFLq40MCiSnUe1AzkpHvbCEMCGGP6zMoFYECsjdhL6bR1kTK37ONNRDuHQ3RIpScRYcYYIg==} + dependencies: + uint8arrays: 4.0.9 + + /uint8arrays@4.0.9: + resolution: {integrity: sha512-iHU8XJJnfeijILZWzV7RgILdPHqe0mjJvyzY4mO8aUUtHsDbPa2Gc8/02Kc4zeokp2W6Qq8z9Ap1xkQ1HfbKwg==} + dependencies: + multiformats: 12.1.3 + + /uint8arrays@5.0.0: + resolution: {integrity: sha512-RWO7gR4x6syxnKDfZO8mDCsaaYs1/BqZCxlHgrcRge50E9GTnLmtoA4kwFSGIL4s3dQkryeTkvtG6oEFEya3yg==} + dependencies: + multiformats: 12.1.3 + + /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 + + /unicorn-magic@0.1.0: + resolution: {integrity: sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==} + engines: {node: '>=18'} + 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-stringify-position@2.0.3: + resolution: {integrity: sha512-3faScn5I+hy9VleOq/qNbAd6pAx7iH5jYBMS9I1HgQVijz/4mv5Bvw5iw1sC/90CODiKo81G/ps8AJrISn687g==} + dependencies: + '@types/unist': 2.0.9 + 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.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.1.1 + is-generator-function: 1.0.10 + is-typed-array: 1.1.12 + which-typed-array: 1.1.13 + 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.20 + '@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 + + /vite@5.0.7(@types/node@20.10.4): + resolution: {integrity: sha512-B4T4rJCDPihrQo2B+h1MbeGL/k/GMAHzhQ8S0LjQ142s6/+l3hHTT095ORvsshj4QCkoWu3Xtmob5mazvakaOw==} + 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.10.4 + esbuild: 0.19.5 + postcss: 8.4.32 + rollup: 4.6.1 + optionalDependencies: + fsevents: 2.3.3 + dev: true + + /vscode-oniguruma@1.7.0: + resolution: {integrity: sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==} + dev: true + + /vscode-textmate@8.0.0: + resolution: {integrity: sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg==} + dev: true + + /webidl-conversions@3.0.1: + resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} + dev: false + + /whatwg-url@5.0.0: + resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} + dependencies: + tr46: 0.0.3 + webidl-conversions: 3.0.1 + dev: false + + /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.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 + + /wnfs@0.1.27: + resolution: {integrity: sha512-9cC53nL3Nd303gykf6WNLYoxBsGkR9sgG2PMLMRcaMD3Ygzd6Q9sUFz7dPhYNWUPIH9VUGLM58MA16c03HrX0Q==} + dev: false + + /workerpool@6.2.1: + resolution: {integrity: sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==} + 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@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-eslint-parser@1.2.2: + resolution: {integrity: sha512-pEwzfsKbTrB8G3xc/sN7aw1v6A6c/pKxLAkjclnAyo5g5qOh6eL9WGu0o3cSDQZKrTNk4KL4lQSwZW+nBkANEg==} + engines: {node: ^14.17.0 || >=16.0.0} + dependencies: + eslint-visitor-keys: 3.4.3 + lodash: 4.17.21 + yaml: 2.3.4 + dev: true + + /yaml@1.10.2: + resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==} + engines: {node: '>= 6'} + dev: true + + /yaml@2.3.4: + resolution: {integrity: sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==} + engines: {node: '>= 14'} + dev: true + + /yargs-parser@20.2.4: + resolution: {integrity: sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==} + engines: {node: '>=10'} + 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-unparser@2.0.0: + resolution: {integrity: sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==} + engines: {node: '>=10'} + dependencies: + camelcase: 6.3.0 + decamelize: 4.0.0 + flat: 5.0.2 + is-plain-obj: 2.1.0 + dev: true + + /yargs@16.2.0: + resolution: {integrity: sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==} + engines: {node: '>=10'} + dependencies: + cliui: 7.0.4 + 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: 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.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/pnpm-workspace.yaml b/pnpm-workspace.yaml new file mode 100644 index 0000000..1598933 --- /dev/null +++ b/pnpm-workspace.yaml @@ -0,0 +1,3 @@ +packages: + - 'packages/*' + - 'examples/*' diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..3883f91 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,13 @@ +{ + "extends": "@fission-codes/eslint-config/tsconfig.json", + "typedocOptions": { + "entryPointStrategy": "packages", + "entryPoints": ["packages/package1"], + "excludeExternals": true, + "darkHighlightTheme": "github-dark", + "sourceLinkExternal": true, + "navigationLinks": { + "Github": "https://github.com/fission-code/js-template" + } + } +}