From cdb5ae5743dfded83e567ae7e1065f212bbebdfd Mon Sep 17 00:00:00 2001 From: AJ Danelz Date: Fri, 21 Apr 2023 18:34:55 -0400 Subject: [PATCH 1/3] Feature/vuepress rewrite (#23) * Convert gitbook format to vuepress - update a zilla.yaml reference page with more details and quick links - configure the necessary nav links and frontmatter - Polish the build-todo-app page; convert img, hint, code blocks - Add vuepress structure and hope theme - Deploy to github pages for prod and netlify for staging - Remove i18n sample * New Docs framework and multi version build - build and deploy next version from develop - build all versions based on deploy-versions.json - check cache hit and use correct build * Restructure docs * add link checker * correct page edit links * remove contributors, extra back tics and reset ref section names * deploy to cloudflare and github pages depending on repo owner (#15) * Update build-deploy-docs.yml (#19) * Update README.md (#20) * #13 clean out markup (#1) (#22) * outline individual yaml objects and explain each * Update frontmatter and json to yaml * check for broken anchor tag links * rework the nesting and object definition * reorganize files into headings * add yaml samples * add ToCs * runt markdown linter * fix page descriptions (#24) * add Google Analytics (#25) --- .editorconfig | 10 + .github/workflows/build-deploy-docs.yml | 172 + .github/workflows/links-build.yml | 41 + .github/workflows/links-push.yml | 18 + .gitignore | 5 + .linkcheckerrc | 5 + .markdownlint-cli2.jsonc | 4 + README.md | 4 +- SUMMARY.md | 51 - configure-kafka-proxies/README.md | 5 - connect-your-kafka/redpanda.md | 84 - deploy-versions.json | 1 + get-started/README.md | 17 - package.json | 22 + pnpm-lock.yaml | 6033 +++++++++++++++++ reference/zilla.yaml/README.md | 18 - reference/zilla.yaml/binding-amqp.md | 65 - reference/zilla.yaml/binding-echo.md | 31 - reference/zilla.yaml/binding-fan.md | 34 - reference/zilla.yaml/binding-filesystem.md | 48 - .../zilla.yaml/binding-http-filesystem.md | 83 - reference/zilla.yaml/binding-http-kafka.md | 249 - reference/zilla.yaml/binding-http.md | 186 - reference/zilla.yaml/binding-kafka.md | 141 - reference/zilla.yaml/binding-mqtt.md | 70 - reference/zilla.yaml/binding-proxy.md | 89 - reference/zilla.yaml/binding-sse-kafka.md | 119 - reference/zilla.yaml/binding-sse.md | 68 - reference/zilla.yaml/binding-tcp.md | 77 - reference/zilla.yaml/binding-tls.md | 113 - reference/zilla.yaml/binding-ws.md | 103 - reference/zilla.yaml/binding.md | 32 - reference/zilla.yaml/guard-jwt.md | 85 - reference/zilla.yaml/vault-filesystem.md | 70 - reference/zilla.yaml/vault.md | 27 - src/.vuepress/config.ts | 25 + src/.vuepress/env.ts | 41 + src/.vuepress/navbar/en.ts | 25 + src/.vuepress/navbar/index.ts | 1 + .../assets/BuildZillaFromSourceTask.png | Bin .../.vuepress/public}/assets/EditTask.png | Bin .../.vuepress/public}/assets/EmptyTasks.png | Bin .../assets/JoinZillaSlackCommunityTask.png | Bin .../assets/JoinZillaSlackCommunityTask400.png | Bin .../Screen Shot 2022-05-22 at 9.11.25 PM.png | Bin .../Screen Shot 2022-05-24 at 11.00.10 PM.png | Bin ...reen Shot 2022-07-08 at 9.49.37 AM (1).png | Bin .../Screen Shot 2022-07-08 at 9.49.37 AM.png | Bin ...een Shot 2022-07-26 at 12.53.28 PM (1).png | Bin .../Screen Shot 2022-07-26 at 12.53.28 PM.png | Bin ...een Shot 2022-07-26 at 12.53.37 PM (1).png | Bin .../Screen Shot 2022-07-26 at 12.53.37 PM.png | Bin .../public}/assets/SecureTodoAppLoggedIn.png | Bin .../assets/SecureTodoAppNotLoggedIn.png | Bin .../public}/assets/TodoAppTopology.png | Bin .../public}/assets/TryZillaExamplesTask.png | Bin .../public}/assets/bootstrap-server-names.png | Bin .../.vuepress/public}/assets/pca-ca-cert.png | Bin .../.vuepress/public}/assets/todo (1).png | Bin .../todo-app-architecture-secured@2x.png | Bin .../public}/assets/todo-app-architecture.svg | 0 .../assets/todo-app-architecture@2x.png | Bin .../assets/todo-app-architecture@3x.png | Bin .../public}/assets/todo.drawio (1).png | Bin .../public}/assets/todo.drawio (2).png | Bin .../.vuepress/public}/assets/todo.drawio.png | Bin .../.vuepress/public}/assets/todo.png | Bin .../.vuepress/public}/assets/topology.png | Bin .../public}/assets/zilla-studio@2x.png | Bin src/.vuepress/public/cloudflare/_redirects | 2 + src/.vuepress/public/favicon.ico | Bin 0 -> 15406 bytes src/.vuepress/public/logo-dark.png | Bin 0 -> 16519 bytes src/.vuepress/public/logo.png | Bin 0 -> 15867 bytes .../.vuepress/public/logo.svg | 0 src/.vuepress/sidebar/en.ts | 11 + src/.vuepress/sidebar/index.ts | 1 + src/.vuepress/styles/config.scss | 3 + src/.vuepress/styles/index.scss | 17 + src/.vuepress/styles/palette.scss | 2 + src/.vuepress/theme.ts | 58 + src/.vuepress/versions.json | 4 + src/README.md | 80 + src/examples/README.md | 11 + .../todo-app/SecureTodoAppLoggedIn.png | Bin 0 -> 191714 bytes .../todo-app/SecureTodoAppNotLoggedIn.png | Bin 0 -> 158864 bytes .../examples/todo-app}/TodoAppNotLoggedIn.png | Bin .../examples/todo-app/build.md | 244 +- .../examples/todo-app/delete-tasks.png | Bin .../examples/todo-app/get-tasks.png | Bin .../examples/todo-app/post-tasks.png | Bin .../examples/todo-app/put-tasks.png | Bin .../examples/todo-app/secure.md | 67 +- .../examples/todo-app/topology.png | Bin src/get-started/README.md | 11 + .../connecting-to-kafka}/README.md | 71 +- .../get-started/connecting-to-kafka}/aiven.md | 42 +- .../aivien-connection-information.png | Bin .../connecting-to-kafka}/amazon-msk.md | 55 +- .../connecting-to-kafka}/confluent-cloud.md | 15 +- .../connecting-to-kafka/redpanda-zilla.yaml | 86 + .../connecting-to-kafka/redpanda.md | 33 + .../connecting-to-kafka/zilla.yaml | 86 + src/get-started/install/README.md | 9 + src/guides/README.md | 5 + .../guides/kafka-proxies}/rest-proxy.md | 93 +- .../guides/kafka-proxies}/sse-proxy.md | 3 +- {reference => src/reference}/README.md | 6 + {reference => src/reference}/security.json.md | 0 {reference => src/reference}/settings.json.md | 2 +- src/reference/zilla.yaml/README.md | 38 + src/reference/zilla.yaml/binding-amqp.md | 128 + src/reference/zilla.yaml/binding-echo.md | 50 + src/reference/zilla.yaml/binding-fan.md | 62 + .../zilla.yaml/binding-filesystem.md | 83 + .../zilla.yaml/binding-http-filesystem.md | 146 + .../zilla.yaml/binding-http-kafka.md | 422 ++ src/reference/zilla.yaml/binding-http.md | 324 + src/reference/zilla.yaml/binding-kafka.md | 220 + src/reference/zilla.yaml/binding-mqtt.md | 127 + src/reference/zilla.yaml/binding-proxy.md | 176 + src/reference/zilla.yaml/binding-sse-kafka.md | 195 + src/reference/zilla.yaml/binding-sse.md | 144 + src/reference/zilla.yaml/binding-tcp.md | 136 + src/reference/zilla.yaml/binding-tls.md | 238 + src/reference/zilla.yaml/binding-ws.md | 195 + src/reference/zilla.yaml/binding.md | 80 + src/reference/zilla.yaml/guard-jwt.md | 166 + .../reference}/zilla.yaml/guard.md | 35 +- src/reference/zilla.yaml/vault-filesystem.md | 153 + src/reference/zilla.yaml/vault.md | 42 + {reference => src/reference}/zilla/README.md | 9 +- {reference => src/reference}/zilla/clean.md | 6 +- {reference => src/reference}/zilla/load.md | 6 +- {reference => src/reference}/zilla/start.md | 8 +- {reference => src/reference}/zilla/stop.md | 10 +- {reference => src/reference}/zilla/tune.md | 12 +- {reference => src/reference}/zpm.json.md | 6 +- {reference => src/reference}/zpm/README.md | 6 +- {reference => src/reference}/zpm/clean-1.md | 10 +- {reference => src/reference}/zpm/clean.md | 6 +- {reference => src/reference}/zpm/encrypt.md | 4 +- {reference => src/reference}/zpm/install.md | 8 +- {reference => src/reference}/zpm/wrap.md | 8 +- 143 files changed, 10346 insertions(+), 2202 deletions(-) create mode 100644 .editorconfig create mode 100644 .github/workflows/build-deploy-docs.yml create mode 100644 .github/workflows/links-build.yml create mode 100644 .github/workflows/links-push.yml create mode 100644 .gitignore create mode 100644 .linkcheckerrc create mode 100644 .markdownlint-cli2.jsonc delete mode 100644 SUMMARY.md delete mode 100644 configure-kafka-proxies/README.md delete mode 100644 connect-your-kafka/redpanda.md create mode 100644 deploy-versions.json delete mode 100644 get-started/README.md create mode 100644 package.json create mode 100644 pnpm-lock.yaml delete mode 100644 reference/zilla.yaml/README.md delete mode 100644 reference/zilla.yaml/binding-amqp.md delete mode 100644 reference/zilla.yaml/binding-echo.md delete mode 100644 reference/zilla.yaml/binding-fan.md delete mode 100644 reference/zilla.yaml/binding-filesystem.md delete mode 100644 reference/zilla.yaml/binding-http-filesystem.md delete mode 100644 reference/zilla.yaml/binding-http-kafka.md delete mode 100644 reference/zilla.yaml/binding-http.md delete mode 100644 reference/zilla.yaml/binding-kafka.md delete mode 100644 reference/zilla.yaml/binding-mqtt.md delete mode 100644 reference/zilla.yaml/binding-proxy.md delete mode 100644 reference/zilla.yaml/binding-sse-kafka.md delete mode 100644 reference/zilla.yaml/binding-sse.md delete mode 100644 reference/zilla.yaml/binding-tcp.md delete mode 100644 reference/zilla.yaml/binding-tls.md delete mode 100644 reference/zilla.yaml/binding-ws.md delete mode 100644 reference/zilla.yaml/binding.md delete mode 100644 reference/zilla.yaml/guard-jwt.md delete mode 100644 reference/zilla.yaml/vault-filesystem.md delete mode 100644 reference/zilla.yaml/vault.md create mode 100644 src/.vuepress/config.ts create mode 100644 src/.vuepress/env.ts create mode 100644 src/.vuepress/navbar/en.ts create mode 100644 src/.vuepress/navbar/index.ts rename {.gitbook => src/.vuepress/public}/assets/BuildZillaFromSourceTask.png (100%) rename {.gitbook => src/.vuepress/public}/assets/EditTask.png (100%) rename {.gitbook => src/.vuepress/public}/assets/EmptyTasks.png (100%) rename {.gitbook => src/.vuepress/public}/assets/JoinZillaSlackCommunityTask.png (100%) rename {.gitbook => src/.vuepress/public}/assets/JoinZillaSlackCommunityTask400.png (100%) rename {.gitbook => src/.vuepress/public}/assets/Screen Shot 2022-05-22 at 9.11.25 PM.png (100%) rename {.gitbook => src/.vuepress/public}/assets/Screen Shot 2022-05-24 at 11.00.10 PM.png (100%) rename {.gitbook => src/.vuepress/public}/assets/Screen Shot 2022-07-08 at 9.49.37 AM (1).png (100%) rename {.gitbook => src/.vuepress/public}/assets/Screen Shot 2022-07-08 at 9.49.37 AM.png (100%) rename {.gitbook => src/.vuepress/public}/assets/Screen Shot 2022-07-26 at 12.53.28 PM (1).png (100%) rename {.gitbook => src/.vuepress/public}/assets/Screen Shot 2022-07-26 at 12.53.28 PM.png (100%) rename {.gitbook => src/.vuepress/public}/assets/Screen Shot 2022-07-26 at 12.53.37 PM (1).png (100%) rename {.gitbook => src/.vuepress/public}/assets/Screen Shot 2022-07-26 at 12.53.37 PM.png (100%) rename {.gitbook => src/.vuepress/public}/assets/SecureTodoAppLoggedIn.png (100%) rename {.gitbook => src/.vuepress/public}/assets/SecureTodoAppNotLoggedIn.png (100%) rename {.gitbook => src/.vuepress/public}/assets/TodoAppTopology.png (100%) rename {.gitbook => src/.vuepress/public}/assets/TryZillaExamplesTask.png (100%) rename {.gitbook => src/.vuepress/public}/assets/bootstrap-server-names.png (100%) rename {.gitbook => src/.vuepress/public}/assets/pca-ca-cert.png (100%) rename {.gitbook => src/.vuepress/public}/assets/todo (1).png (100%) rename {.gitbook => src/.vuepress/public}/assets/todo-app-architecture-secured@2x.png (100%) rename {.gitbook => src/.vuepress/public}/assets/todo-app-architecture.svg (100%) rename {.gitbook => src/.vuepress/public}/assets/todo-app-architecture@2x.png (100%) rename {.gitbook => src/.vuepress/public}/assets/todo-app-architecture@3x.png (100%) rename {.gitbook => src/.vuepress/public}/assets/todo.drawio (1).png (100%) rename {.gitbook => src/.vuepress/public}/assets/todo.drawio (2).png (100%) rename {.gitbook => src/.vuepress/public}/assets/todo.drawio.png (100%) rename {.gitbook => src/.vuepress/public}/assets/todo.png (100%) rename {.gitbook => src/.vuepress/public}/assets/topology.png (100%) rename {.gitbook => src/.vuepress/public}/assets/zilla-studio@2x.png (100%) create mode 100644 src/.vuepress/public/cloudflare/_redirects create mode 100644 src/.vuepress/public/favicon.ico create mode 100644 src/.vuepress/public/logo-dark.png create mode 100644 src/.vuepress/public/logo.png rename .gitbook/assets/zilla-logo.svg => src/.vuepress/public/logo.svg (100%) create mode 100644 src/.vuepress/sidebar/en.ts create mode 100644 src/.vuepress/sidebar/index.ts create mode 100644 src/.vuepress/styles/config.scss create mode 100644 src/.vuepress/styles/index.scss create mode 100644 src/.vuepress/styles/palette.scss create mode 100644 src/.vuepress/theme.ts create mode 100644 src/.vuepress/versions.json create mode 100644 src/README.md create mode 100644 src/examples/README.md create mode 100644 src/examples/todo-app/SecureTodoAppLoggedIn.png create mode 100644 src/examples/todo-app/SecureTodoAppNotLoggedIn.png rename {.gitbook/assets => src/examples/todo-app}/TodoAppNotLoggedIn.png (100%) rename get-started/build-todo-app.md => src/examples/todo-app/build.md (75%) rename .gitbook/assets/Screen Shot 2022-05-23 at 11.05.49 AM.png => src/examples/todo-app/delete-tasks.png (100%) rename .gitbook/assets/Screen Shot 2022-05-23 at 11.12.06 AM.png => src/examples/todo-app/get-tasks.png (100%) rename .gitbook/assets/Screen Shot 2022-05-23 at 10.34.46 AM.png => src/examples/todo-app/post-tasks.png (100%) rename .gitbook/assets/Screen Shot 2022-05-23 at 10.58.56 AM.png => src/examples/todo-app/put-tasks.png (100%) rename get-started/secure-todo-app.md => src/examples/todo-app/secure.md (91%) rename .gitbook/assets/topology (1).png => src/examples/todo-app/topology.png (100%) create mode 100644 src/get-started/README.md rename {connect-your-kafka => src/get-started/connecting-to-kafka}/README.md (92%) rename {connect-your-kafka => src/get-started/connecting-to-kafka}/aiven.md (84%) rename .gitbook/assets/Screen Shot 2022-07-08 at 9.49.37 AM (2).png => src/get-started/connecting-to-kafka/aivien-connection-information.png (100%) rename {connect-your-kafka => src/get-started/connecting-to-kafka}/amazon-msk.md (89%) rename {connect-your-kafka => src/get-started/connecting-to-kafka}/confluent-cloud.md (94%) create mode 100644 src/get-started/connecting-to-kafka/redpanda-zilla.yaml create mode 100644 src/get-started/connecting-to-kafka/redpanda.md create mode 100644 src/get-started/connecting-to-kafka/zilla.yaml create mode 100644 src/get-started/install/README.md create mode 100644 src/guides/README.md rename {configure-kafka-proxies => src/guides/kafka-proxies}/rest-proxy.md (82%) rename {configure-kafka-proxies => src/guides/kafka-proxies}/sse-proxy.md (87%) rename {reference => src/reference}/README.md (85%) rename {reference => src/reference}/security.json.md (100%) rename {reference => src/reference}/settings.json.md (88%) create mode 100644 src/reference/zilla.yaml/README.md create mode 100644 src/reference/zilla.yaml/binding-amqp.md create mode 100644 src/reference/zilla.yaml/binding-echo.md create mode 100644 src/reference/zilla.yaml/binding-fan.md create mode 100644 src/reference/zilla.yaml/binding-filesystem.md create mode 100644 src/reference/zilla.yaml/binding-http-filesystem.md create mode 100644 src/reference/zilla.yaml/binding-http-kafka.md create mode 100644 src/reference/zilla.yaml/binding-http.md create mode 100644 src/reference/zilla.yaml/binding-kafka.md create mode 100644 src/reference/zilla.yaml/binding-mqtt.md create mode 100644 src/reference/zilla.yaml/binding-proxy.md create mode 100644 src/reference/zilla.yaml/binding-sse-kafka.md create mode 100644 src/reference/zilla.yaml/binding-sse.md create mode 100644 src/reference/zilla.yaml/binding-tcp.md create mode 100644 src/reference/zilla.yaml/binding-tls.md create mode 100644 src/reference/zilla.yaml/binding-ws.md create mode 100644 src/reference/zilla.yaml/binding.md create mode 100644 src/reference/zilla.yaml/guard-jwt.md rename {reference => src/reference}/zilla.yaml/guard.md (53%) create mode 100644 src/reference/zilla.yaml/vault-filesystem.md create mode 100644 src/reference/zilla.yaml/vault.md rename {reference => src/reference}/zilla/README.md (80%) rename {reference => src/reference}/zilla/clean.md (79%) rename {reference => src/reference}/zilla/load.md (84%) rename {reference => src/reference}/zilla/start.md (81%) rename {reference => src/reference}/zilla/stop.md (56%) rename {reference => src/reference}/zilla/tune.md (67%) rename {reference => src/reference}/zpm.json.md (62%) rename {reference => src/reference}/zpm/README.md (92%) rename {reference => src/reference}/zpm/clean-1.md (76%) rename {reference => src/reference}/zpm/clean.md (79%) rename {reference => src/reference}/zpm/encrypt.md (93%) rename {reference => src/reference}/zpm/install.md (78%) rename {reference => src/reference}/zpm/wrap.md (78%) diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000..185bd9e1 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,10 @@ +# EditorConfig is awesome: https://EditorConfig.org +root = true + +[*] +end_of_line = lf +insert_final_newline = true + +[{package.json,*.yml,*.md}] +indent_style = space +indent_size = 2 diff --git a/.github/workflows/build-deploy-docs.yml b/.github/workflows/build-deploy-docs.yml new file mode 100644 index 00000000..7c76954d --- /dev/null +++ b/.github/workflows/build-deploy-docs.yml @@ -0,0 +1,172 @@ +name: Site versioned build & deploy + +on: + push: + branches: [develop, feature/vuepress-rewrite] + workflow_dispatch: + +permissions: + contents: read + deployments: write + pages: write + id-token: write + +concurrency: + group: "pages" + cancel-in-progress: true + +env: + DistDir: dist + BuildDir: build + SITE_BASE: ${{ vars.SITE_BASE }} + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + + - name: Restore cached Docs + id: dist-cache + uses: actions/cache/restore@v3 + with: + path: ${{ env.DistDir }} + key: ${{ env.DistDir }}-${{ hashFiles('deploy-versions.json') }} + + - name: Setup pnpm + uses: pnpm/action-setup@v2 + with: + version: 8 + run_install: true + + - name: Setup Node.js + uses: actions/setup-node@v3 + with: + node-version: 18 + cache: pnpm + + - name: build versions.json + run: jq -rc '. + input' "src/.vuepress/versions.json" deploy-versions.json > versions.json; + + - if: ${{ steps.dist-cache.outputs.cache-hit != 'true' }} + name: Pull versions + run: | + for row in $(jq -rc '.[]' deploy-versions.json); do + key=$(echo ${row} | jq -r '.key'); + tag=$(echo ${row} | jq -r '.tag'); + + gh release download "$tag" --archive=tar.gz --output "$tag.tar.gz" --skip-existing; + mkdir -p "$BuildDir/$key"; + tar -xvf "$tag.tar.gz" -C "$BuildDir/$key" --strip-components 1; + + cp versions.json "$BuildDir/$key/src/.vuepress/versions.json"; + done + + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - if: ${{ steps.dist-cache.outputs.cache-hit != 'true' }} + name: Build versions + env: + NODE_OPTIONS: "--max_old_space_size=4096" + run: | + wrkdir=$(pwd); + for row in $(jq -rc '.[]' deploy-versions.json); do + key=$(echo ${row} | jq -r '.key'); + + export DIST_DIR="$wrkdir/$DistDir"; + export SITE_VERSION_KEY="$key"; + mkdir -p "$DIST_DIR"; + + cd "$BuildDir/$key"; + pnpm install && pnpm build; + + cd $wrkdir; + done + + - name: Build VuePress site + env: + NODE_OPTIONS: "--max_old_space_size=4096" + SITE_VERSION_KEY: next + run: | + cp versions.json "src/.vuepress/versions.json"; + + export DIST_DIR="$(pwd)/$DistDir"; + pnpm build + + - if: ${{ steps.dist-cache.outputs.cache-hit != 'true' }} + name: Save Docs + uses: actions/cache/save@v3 + with: + path: ${{ env.DistDir }} + key: ${{ env.DistDir }}-${{ hashFiles('deploy-versions.json') }} + + - name: Upload cloudflare-pages artifact + if: github.repository_owner == 'aklivity' + uses: actions/upload-artifact@v3 + with: + name: cloudflare-pages + path: ${{ env.DistDir }} + + - name: Upload github-pages artifact + if: github.repository_owner != 'aklivity' + uses: actions/upload-pages-artifact@v1 + with: + path: ${{ env.DistDir }} + + deployCloudflarePages: + if: github.repository_owner == 'aklivity' + runs-on: ubuntu-latest + needs: build + permissions: + contents: read + deployments: write + + environment: + name: cloudflare-pages + url: ${{ steps.cloudflare-deployment.outputs.url }} + + steps: + - name: Download cloudflare-pages artifact + uses: actions/download-artifact@v3 + with: + name: cloudflare-pages + path: ${{ env.DistDir }} + + - name: Move cloudflare files to root + run: mv ${{ env.DistDir }}/next/cloudflare/* ${{ env.DistDir }} + + - name: Update folder structure + if: env.SITE_BASE != '' + run: | + mkdir -p ${{ env.SITE_BASE }} + mv -v ${{ env.DistDir }}/*/ ${{ env.SITE_BASE }} + mv ${{ env.SITE_BASE }} ${{ env.DistDir }}/ + + - name: Publish to Cloudflare Pages + id: cloudflare-deployment + uses: cloudflare/pages-action@v1 + with: + apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }} + accountId: 65fb75109b09718cddae9ab7c68e2e3c + projectName: zilla-docs + directory: ${{ env.DistDir }} + gitHubToken: ${{ secrets.GITHUB_TOKEN }} + + + deployGithubPages: + if: github.repository_owner != 'aklivity' + runs-on: ubuntu-latest + needs: build + permissions: + pages: write + id-token: write + + environment: + name: github-pages + url: ${{ steps.github-deployment.outputs.page_url }}next + + steps: + - name: Deploy to GitHub Pages + id: github-deployment + uses: actions/deploy-pages@v1 diff --git a/.github/workflows/links-build.yml b/.github/workflows/links-build.yml new file mode 100644 index 00000000..da9ffc6d --- /dev/null +++ b/.github/workflows/links-build.yml @@ -0,0 +1,41 @@ +name: Links check build + +on: + pull_request: + +jobs: + linkChecker: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + + - name: Setup pnpm + uses: pnpm/action-setup@v2 + with: + version: 8 + run_install: true + + - name: Setup Node.js + uses: actions/setup-node@v3 + with: + node-version: 18 + cache: pnpm + + - name: Build VuePress site + env: + NODE_OPTIONS: "--max_old_space_size=4096" + run: | + pnpm build + + - name: Anchor tag Checker + run: | + pnpm install -g link-checker + link-checker src/.vuepress/dist + + - name: Link Checker + uses: lycheeverse/lychee-action@v1.6.1 + with: + fail: true + args: -E --exclude "github.com/aklivity/zilla-docs" --exclude "docs.aklivity.io" --exclude-mail src/.vuepress/dist + env: + GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} diff --git a/.github/workflows/links-push.yml b/.github/workflows/links-push.yml new file mode 100644 index 00000000..87ce3fe2 --- /dev/null +++ b/.github/workflows/links-push.yml @@ -0,0 +1,18 @@ +name: Links check src + +on: + push: + +jobs: + linkChecker: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + + - name: Link Checker + uses: lycheeverse/lychee-action@v1.6.1 + with: + fail: true + args: --offline src + env: + GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..c01fc18b --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ + +node_modules/ +dist +src/.vuepress/.cache/ +src/.vuepress/.temp/ diff --git a/.linkcheckerrc b/.linkcheckerrc new file mode 100644 index 00000000..37ac7597 --- /dev/null +++ b/.linkcheckerrc @@ -0,0 +1,5 @@ +{ + "allow-hash-href": true, + "disable-external": true, + "url-ignore": [".+zilla-docs\/.+"] +} diff --git a/.markdownlint-cli2.jsonc b/.markdownlint-cli2.jsonc new file mode 100644 index 00000000..151809d3 --- /dev/null +++ b/.markdownlint-cli2.jsonc @@ -0,0 +1,4 @@ +{ + "MD013": false, + "MD051": false +} diff --git a/README.md b/README.md index 371e303d..01fbaf36 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ description: API Gateway for event-driven microservices # What is Zilla? -![](.gitbook/assets/zilla-logo.svg) +![](/assets/zilla-logo.svg) **Zilla** is open source software connecting web and mobile applications to event-driven microservices using standard protocols, such as HTTP, Server-Sent Events and Kafka. @@ -23,3 +23,5 @@ For example, when deployed in front of a Kafka cluster, Zilla can be configured As a developer, you can focus on writing and testing your event-driven microservices with technologies such as Kafka consumers and producers, you can define your web and mobile APIs using Zilla, and then you can deploy securely at global scale. Learn more about Zilla in the [Get Started](get-started/) guide! + +* Table of Contents are generated by the [VSCode Markdown](https://github.com/yzhang-gh/vscode-markdown#table-of-contents) extension using the `markdown.extension.toc.slugifyMode`:`gitea` diff --git a/SUMMARY.md b/SUMMARY.md deleted file mode 100644 index 4f476787..00000000 --- a/SUMMARY.md +++ /dev/null @@ -1,51 +0,0 @@ -# Table of contents - -* [What is Zilla?](README.md) -* [Get Started](get-started/README.md) - * [Build the Todo Application](get-started/build-todo-app.md) - * [Secure the Todo Application](get-started/secure-todo-app.md) -* [Connect your Kafka](connect-your-kafka/README.md) - * [Aiven](connect-your-kafka/aiven.md) - * [Amazon MSK](connect-your-kafka/amazon-msk.md) - * [Confluent Cloud](connect-your-kafka/confluent-cloud.md) - * [Redpanda](connect-your-kafka/redpanda.md) -* [Configure Kafka Proxies](configure-kafka-proxies/README.md) - * [REST Proxy](configure-kafka-proxies/rest-proxy.md) - * [SSE Proxy](configure-kafka-proxies/sse-proxy.md) -* [Reference](reference/README.md) - * [Zilla Manager CLI (zpm)](reference/zpm/README.md) - * [zpm help](reference/zpm/clean.md) - * [zpm clean](reference/zpm/clean-1.md) - * [zpm encrypt](reference/zpm/encrypt.md) - * [zpm install](reference/zpm/install.md) - * [zpm wrap](reference/zpm/wrap.md) - * [Zilla Manager Configuration](reference/zpm.json.md) - * [Zilla Manager Settings](reference/settings.json.md) - * [Zilla Manager Security](reference/security.json.md) - * [Zilla Runtime CLI (zilla)](reference/zilla/README.md) - * [zilla help](reference/zilla/clean.md) - * [zilla load 🚧](reference/zilla/load.md) - * [zilla start](reference/zilla/start.md) - * [zilla stop](reference/zilla/stop.md) - * [zilla tune 🚧](reference/zilla/tune.md) - * [Zilla Runtime Configuration](reference/zilla.yaml/README.md) - * [binding](reference/zilla.yaml/binding.md) - * [binding (amqp) 🚧](reference/zilla.yaml/binding-amqp.md) - * [binding (echo)](reference/zilla.yaml/binding-echo.md) - * [binding (fan)](reference/zilla.yaml/binding-fan.md) - * [binding (filesystem)](reference/zilla.yaml/binding-filesystem.md) - * [binding (http)](reference/zilla.yaml/binding-http.md) - * [binding (http-filesystem)](reference/zilla.yaml/binding-http-filesystem.md) - * [binding (http-kafka)](reference/zilla.yaml/binding-http-kafka.md) - * [binding (kafka)](reference/zilla.yaml/binding-kafka.md) - * [binding (mqtt) 🚧](reference/zilla.yaml/binding-mqtt.md) - * [binding (proxy)](reference/zilla.yaml/binding-proxy.md) - * [binding (sse)](reference/zilla.yaml/binding-sse.md) - * [binding (sse-kafka)](reference/zilla.yaml/binding-sse-kafka.md) - * [binding (tcp)](reference/zilla.yaml/binding-tcp.md) - * [binding (tls)](reference/zilla.yaml/binding-tls.md) - * [binding (ws)](reference/zilla.yaml/binding-ws.md) - * [guard](reference/zilla.yaml/guard.md) - * [guard (jwt)](reference/zilla.yaml/guard-jwt.md) - * [vault](reference/zilla.yaml/vault.md) - * [vault (filesystem)](reference/zilla.yaml/vault-filesystem.md) diff --git a/configure-kafka-proxies/README.md b/configure-kafka-proxies/README.md deleted file mode 100644 index a13432ea..00000000 --- a/configure-kafka-proxies/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# Configure Kafka Proxies - -### Introduction - -In this guide, you will explore how to design/configure your API Endpoints such as REST API, SSE and etc. diff --git a/connect-your-kafka/redpanda.md b/connect-your-kafka/redpanda.md deleted file mode 100644 index d6ec1da3..00000000 --- a/connect-your-kafka/redpanda.md +++ /dev/null @@ -1,84 +0,0 @@ -# Redpanda - -## Introduction - -In this guide, you will learn how to connect to Redpanda from Zilla. You can get started with a fully working config [example](https://github.com/aklivity/zilla-examples/tree/main/http.redpanda.sasl.scram). - -## Redpanda Parameters - -A brief explanation of replaceable values from the config examples below: - -| Value | Description | -| --------------------------- | ------------------------------ | -| `SASL_USERNAME` | The SASL username for Redpanda | -| `SASL_PASSWORD` | The SASL password for Redpanda | -| `BOOTSTRAP_SERVER_HOSTNAME` | Target Redpanda hostname | -| `BOOTSTRAP_SERVER_PORT` | Target Redpanda port number | - -## Configure Zilla - -Let's configure `zilla.json`. - -{% code title="zilla.json" %} -```json -{ - "bindings": - { - ... - "kafka_client0": - { - "type" : "kafka", - "kind": "client", - "options": - { - "sasl": - { - "mechanism": "scram-sha-256", - "username": "SASL_USERNAME", - "password": "SASL_PASSWORD" - } - }, - "exit": "tls_client0" - }, - "tls_client0": - { - "type" : "tls", - "kind": "client", - "options": - { - "trustcacerts": true, - "sni": ["BOOTSTRAP_SERVER_HOSTNAME"] - }, - "exit": "tcp_client0" - }, - "tcp_client0": - { - "type" : "tcp", - "kind": "client", - "options": - { - "host": "BOOTSTRAP_SERVER_HOSTNAME", - "port": BOOTSTRAP_SERVER_PORT - }, - "routes": - [ - { - "when": - [ - { - "cidr": "0.0.0.0/0" - } - ] - } - ] - } - } -} -``` -{% endcode %} - -{% hint style="info" %} -SNI adds the domain name to the TLS handshake process so that the Zilla process reaches the right domain name and receives the correct SSL certificate. -{% endhint %} - -To test the above SASL config you can follow instructions in the README from the [example](https://github.com/aklivity/zilla-examples/tree/main/http.redpanda.sasl.scram). diff --git a/deploy-versions.json b/deploy-versions.json new file mode 100644 index 00000000..0637a088 --- /dev/null +++ b/deploy-versions.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/get-started/README.md b/get-started/README.md deleted file mode 100644 index 9225cbd8..00000000 --- a/get-started/README.md +++ /dev/null @@ -1,17 +0,0 @@ -# Get Started - -### Welcome to Zilla! - -The Get Started guides below will walk you through the steps to build and secure a Todo application using Apache Kafka with the Zilla engine. - -### Build the Todo Application - -Our [Build the Todo Application](build-todo-app.md) guide shows you how to create your first application with Zilla, using Apache Kafka with Kafka Streams to implement the Tasks service that maintains a shared Todo List of tasks. - -### Secure the Todo Application - -Our [Secure the Todo Application](secure-todo-app.md) guide shows you how to secure the Tasks API using JWT access tokens to allow read and write access only to authorized clients. - -### Connect your Kafka - -Our [Connect your Kafka](../connect-your-kafka/) guide shows you how to change the Zilla configuration to use your own Kafka cluster instead of using a local Kafka deployment in a docker stack. diff --git a/package.json b/package.json new file mode 100644 index 00000000..3615df94 --- /dev/null +++ b/package.json @@ -0,0 +1,22 @@ +{ + "name": "zilla-docs", + "version": "0.0.1", + "description": "The official documentation for the aklivity/zilla open-source project", + "keywords": [], + "author": "aklivity.io", + "license": "ISC", + "scripts": { + "info": "vuepress info", + "build": "vuepress build src", + "clean-dev": "vuepress dev src --clean-cache --debug", + "dev": "vuepress dev src", + "update-package": "pnpm dlx vp-update" + }, + "devDependencies": { + "@vuepress/client": "2.0.0-beta.61", + "@vuepress/plugin-google-analytics": "2.0.0-beta.61", + "vue": "^3.2.47", + "vuepress": "2.0.0-beta.61", + "vuepress-theme-hope": "2.0.0-beta.200" + } +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 00000000..edbcd125 --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,6033 @@ +lockfileVersion: '6.0' + +devDependencies: + '@vuepress/client': + specifier: 2.0.0-beta.61 + version: 2.0.0-beta.61 + '@vuepress/plugin-google-analytics': + specifier: 2.0.0-beta.61 + version: 2.0.0-beta.61 + vue: + specifier: ^3.2.47 + version: 3.2.47 + vuepress: + specifier: 2.0.0-beta.61 + version: 2.0.0-beta.61(@vuepress/client@2.0.0-beta.61)(vue@3.2.47) + vuepress-theme-hope: + specifier: 2.0.0-beta.200 + version: 2.0.0-beta.200(vuepress@2.0.0-beta.61) + +packages: + + /@ampproject/remapping@2.2.0: + resolution: {integrity: sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==} + engines: {node: '>=6.0.0'} + dependencies: + '@jridgewell/gen-mapping': 0.1.1 + '@jridgewell/trace-mapping': 0.3.17 + dev: true + + /@apideck/better-ajv-errors@0.3.6(ajv@8.12.0): + resolution: {integrity: sha512-P+ZygBLZtkp0qqOAJJVX4oX/sFo5JR3eBWwwuqHHhK0GIgQOKWrAfiAaWX0aArHkRWHMuggFEgAZNxVPwPZYaA==} + engines: {node: '>=10'} + peerDependencies: + ajv: '>=8' + dependencies: + ajv: 8.12.0 + json-schema: 0.4.0 + jsonpointer: 5.0.1 + leven: 3.1.0 + dev: true + + /@babel/code-frame@7.18.6: + resolution: {integrity: sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/highlight': 7.18.6 + dev: true + + /@babel/compat-data@7.21.0: + resolution: {integrity: sha512-gMuZsmsgxk/ENC3O/fRw5QY8A9/uxQbbCEypnLIiYYc/qVJtEV7ouxC3EllIIwNzMqAQee5tanFabWsUOutS7g==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/core@7.21.3: + resolution: {integrity: sha512-qIJONzoa/qiHghnm0l1n4i/6IIziDpzqc36FBs4pzMhDUraHqponwJLiAKm1hGLP3OSB/TVNz6rMwVGpwxxySw==} + engines: {node: '>=6.9.0'} + dependencies: + '@ampproject/remapping': 2.2.0 + '@babel/code-frame': 7.18.6 + '@babel/generator': 7.21.3 + '@babel/helper-compilation-targets': 7.20.7(@babel/core@7.21.3) + '@babel/helper-module-transforms': 7.21.2 + '@babel/helpers': 7.21.0 + '@babel/parser': 7.21.3 + '@babel/template': 7.20.7 + '@babel/traverse': 7.21.3 + '@babel/types': 7.21.3 + convert-source-map: 1.9.0 + debug: 4.3.4 + gensync: 1.0.0-beta.2 + json5: 2.2.3 + semver: 6.3.0 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/generator@7.21.3: + resolution: {integrity: sha512-QS3iR1GYC/YGUnW7IdggFeN5c1poPUurnGttOV/bZgPGV+izC/D8HnD6DLwod0fsatNyVn1G3EVWMYIF0nHbeA==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.21.3 + '@jridgewell/gen-mapping': 0.3.2 + '@jridgewell/trace-mapping': 0.3.17 + jsesc: 2.5.2 + dev: true + + /@babel/helper-annotate-as-pure@7.18.6: + resolution: {integrity: sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.21.3 + dev: true + + /@babel/helper-builder-binary-assignment-operator-visitor@7.18.9: + resolution: {integrity: sha512-yFQ0YCHoIqarl8BCRwBL8ulYUaZpz3bNsA7oFepAzee+8/+ImtADXNOmO5vJvsPff3qi+hvpkY/NYBTrBQgdNw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-explode-assignable-expression': 7.18.6 + '@babel/types': 7.21.3 + dev: true + + /@babel/helper-compilation-targets@7.20.7(@babel/core@7.21.3): + resolution: {integrity: sha512-4tGORmfQcrc+bvrjb5y3dG9Mx1IOZjsHqQVUz7XCNHO+iTmqxWnVg3KRygjGmpRLJGdQSKuvFinbIb0CnZwHAQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/compat-data': 7.21.0 + '@babel/core': 7.21.3 + '@babel/helper-validator-option': 7.21.0 + browserslist: 4.21.5 + lru-cache: 5.1.1 + semver: 6.3.0 + dev: true + + /@babel/helper-create-class-features-plugin@7.21.0(@babel/core@7.21.3): + resolution: {integrity: sha512-Q8wNiMIdwsv5la5SPxNYzzkPnjgC0Sy0i7jLkVOCdllu/xcVNkr3TeZzbHBJrj+XXRqzX5uCyCoV9eu6xUG7KQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.21.3 + '@babel/helper-annotate-as-pure': 7.18.6 + '@babel/helper-environment-visitor': 7.18.9 + '@babel/helper-function-name': 7.21.0 + '@babel/helper-member-expression-to-functions': 7.21.0 + '@babel/helper-optimise-call-expression': 7.18.6 + '@babel/helper-replace-supers': 7.20.7 + '@babel/helper-skip-transparent-expression-wrappers': 7.20.0 + '@babel/helper-split-export-declaration': 7.18.6 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/helper-create-regexp-features-plugin@7.21.0(@babel/core@7.21.3): + resolution: {integrity: sha512-N+LaFW/auRSWdx7SHD/HiARwXQju1vXTW4fKr4u5SgBUTm51OKEjKgj+cs00ggW3kEvNqwErnlwuq7Y3xBe4eg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.21.3 + '@babel/helper-annotate-as-pure': 7.18.6 + regexpu-core: 5.3.2 + dev: true + + /@babel/helper-define-polyfill-provider@0.3.3(@babel/core@7.21.3): + resolution: {integrity: sha512-z5aQKU4IzbqCC1XH0nAqfsFLMVSo22SBKUc0BxGrLkolTdPTructy0ToNnlO2zA4j9Q/7pjMZf0DSY+DSTYzww==} + peerDependencies: + '@babel/core': ^7.4.0-0 + dependencies: + '@babel/core': 7.21.3 + '@babel/helper-compilation-targets': 7.20.7(@babel/core@7.21.3) + '@babel/helper-plugin-utils': 7.20.2 + debug: 4.3.4 + lodash.debounce: 4.0.8 + resolve: 1.22.1 + semver: 6.3.0 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/helper-environment-visitor@7.18.9: + resolution: {integrity: sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/helper-explode-assignable-expression@7.18.6: + resolution: {integrity: sha512-eyAYAsQmB80jNfg4baAtLeWAQHfHFiR483rzFK+BhETlGZaQC9bsfrugfXDCbRHLQbIA7U5NxhhOxN7p/dWIcg==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.21.3 + dev: true + + /@babel/helper-function-name@7.21.0: + resolution: {integrity: sha512-HfK1aMRanKHpxemaY2gqBmL04iAPOPRj7DxtNbiDOrJK+gdwkiNRVpCpUJYbUT+aZyemKN8brqTOxzCaG6ExRg==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/template': 7.20.7 + '@babel/types': 7.21.3 + dev: true + + /@babel/helper-hoist-variables@7.18.6: + resolution: {integrity: sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.21.3 + dev: true + + /@babel/helper-member-expression-to-functions@7.21.0: + resolution: {integrity: sha512-Muu8cdZwNN6mRRNG6lAYErJ5X3bRevgYR2O8wN0yn7jJSnGDu6eG59RfT29JHxGUovyfrh6Pj0XzmR7drNVL3Q==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.21.3 + dev: true + + /@babel/helper-module-imports@7.18.6: + resolution: {integrity: sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.21.3 + dev: true + + /@babel/helper-module-transforms@7.21.2: + resolution: {integrity: sha512-79yj2AR4U/Oqq/WOV7Lx6hUjau1Zfo4cI+JLAVYeMV5XIlbOhmjEk5ulbTc9fMpmlojzZHkUUxAiK+UKn+hNQQ==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-environment-visitor': 7.18.9 + '@babel/helper-module-imports': 7.18.6 + '@babel/helper-simple-access': 7.20.2 + '@babel/helper-split-export-declaration': 7.18.6 + '@babel/helper-validator-identifier': 7.19.1 + '@babel/template': 7.20.7 + '@babel/traverse': 7.21.3 + '@babel/types': 7.21.3 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/helper-optimise-call-expression@7.18.6: + resolution: {integrity: sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.21.3 + dev: true + + /@babel/helper-plugin-utils@7.20.2: + resolution: {integrity: sha512-8RvlJG2mj4huQ4pZ+rU9lqKi9ZKiRmuvGuM2HlWmkmgOhbs6zEAw6IEiJ5cQqGbDzGZOhwuOQNtZMi/ENLjZoQ==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/helper-remap-async-to-generator@7.18.9(@babel/core@7.21.3): + resolution: {integrity: sha512-dI7q50YKd8BAv3VEfgg7PS7yD3Rtbi2J1XMXaalXO0W0164hYLnh8zpjRS0mte9MfVp/tltvr/cfdXPvJr1opA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.21.3 + '@babel/helper-annotate-as-pure': 7.18.6 + '@babel/helper-environment-visitor': 7.18.9 + '@babel/helper-wrap-function': 7.20.5 + '@babel/types': 7.21.3 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/helper-replace-supers@7.20.7: + resolution: {integrity: sha512-vujDMtB6LVfNW13jhlCrp48QNslK6JXi7lQG736HVbHz/mbf4Dc7tIRh1Xf5C0rF7BP8iiSxGMCmY6Ci1ven3A==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-environment-visitor': 7.18.9 + '@babel/helper-member-expression-to-functions': 7.21.0 + '@babel/helper-optimise-call-expression': 7.18.6 + '@babel/template': 7.20.7 + '@babel/traverse': 7.21.3 + '@babel/types': 7.21.3 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/helper-simple-access@7.20.2: + resolution: {integrity: sha512-+0woI/WPq59IrqDYbVGfshjT5Dmk/nnbdpcF8SnMhhXObpTq2KNBdLFRFrkVdbDOyUmHBCxzm5FHV1rACIkIbA==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.21.3 + dev: true + + /@babel/helper-skip-transparent-expression-wrappers@7.20.0: + resolution: {integrity: sha512-5y1JYeNKfvnT8sZcK9DVRtpTbGiomYIHviSP3OQWmDPU3DeH4a1ZlT/N2lyQ5P8egjcRaT/Y9aNqUxK0WsnIIg==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.21.3 + dev: true + + /@babel/helper-split-export-declaration@7.18.6: + resolution: {integrity: sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.21.3 + dev: true + + /@babel/helper-string-parser@7.19.4: + resolution: {integrity: sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/helper-validator-identifier@7.19.1: + resolution: {integrity: sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/helper-validator-option@7.21.0: + resolution: {integrity: sha512-rmL/B8/f0mKS2baE9ZpyTcTavvEuWhTTW8amjzXNvYG4AwBsqTLikfXsEofsJEfKHf+HQVQbFOHy6o+4cnC/fQ==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/helper-wrap-function@7.20.5: + resolution: {integrity: sha512-bYMxIWK5mh+TgXGVqAtnu5Yn1un+v8DDZtqyzKRLUzrh70Eal2O3aZ7aPYiMADO4uKlkzOiRiZ6GX5q3qxvW9Q==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-function-name': 7.21.0 + '@babel/template': 7.20.7 + '@babel/traverse': 7.21.3 + '@babel/types': 7.21.3 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/helpers@7.21.0: + resolution: {integrity: sha512-XXve0CBtOW0pd7MRzzmoyuSj0e3SEzj8pgyFxnTT1NJZL38BD1MK7yYrm8yefRPIDvNNe14xR4FdbHwpInD4rA==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/template': 7.20.7 + '@babel/traverse': 7.21.3 + '@babel/types': 7.21.3 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/highlight@7.18.6: + resolution: {integrity: sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-validator-identifier': 7.19.1 + chalk: 2.4.2 + js-tokens: 4.0.0 + dev: true + + /@babel/parser@7.21.3: + resolution: {integrity: sha512-lobG0d7aOfQRXh8AyklEAgZGvA4FShxo6xQbUrrT/cNBPUdIDojlokwJsQyCC/eKia7ifqM0yP+2DRZ4WKw2RQ==} + engines: {node: '>=6.0.0'} + dependencies: + '@babel/types': 7.21.3 + dev: true + + /@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.18.6(@babel/core@7.21.3): + resolution: {integrity: sha512-Dgxsyg54Fx1d4Nge8UnvTrED63vrwOdPmyvPzlNN/boaliRP54pm3pGzZD1SJUwrBA+Cs/xdG8kXX6Mn/RfISQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.21.3 + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.20.7(@babel/core@7.21.3): + resolution: {integrity: sha512-sbr9+wNE5aXMBBFBICk01tt7sBf2Oc9ikRFEcem/ZORup9IMUdNhW7/wVLEbbtlWOsEubJet46mHAL2C8+2jKQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.13.0 + dependencies: + '@babel/core': 7.21.3 + '@babel/helper-plugin-utils': 7.20.2 + '@babel/helper-skip-transparent-expression-wrappers': 7.20.0 + '@babel/plugin-proposal-optional-chaining': 7.21.0(@babel/core@7.21.3) + dev: true + + /@babel/plugin-proposal-async-generator-functions@7.20.7(@babel/core@7.21.3): + resolution: {integrity: sha512-xMbiLsn/8RK7Wq7VeVytytS2L6qE69bXPB10YCmMdDZbKF4okCqY74pI/jJQ/8U0b/F6NrT2+14b8/P9/3AMGA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.3 + '@babel/helper-environment-visitor': 7.18.9 + '@babel/helper-plugin-utils': 7.20.2 + '@babel/helper-remap-async-to-generator': 7.18.9(@babel/core@7.21.3) + '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.21.3) + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/plugin-proposal-class-properties@7.18.6(@babel/core@7.21.3): + resolution: {integrity: sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.3 + '@babel/helper-create-class-features-plugin': 7.21.0(@babel/core@7.21.3) + '@babel/helper-plugin-utils': 7.20.2 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/plugin-proposal-class-static-block@7.21.0(@babel/core@7.21.3): + resolution: {integrity: sha512-XP5G9MWNUskFuP30IfFSEFB0Z6HzLIUcjYM4bYOPHXl7eiJ9HFv8tWj6TXTN5QODiEhDZAeI4hLok2iHFFV4hw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.12.0 + dependencies: + '@babel/core': 7.21.3 + '@babel/helper-create-class-features-plugin': 7.21.0(@babel/core@7.21.3) + '@babel/helper-plugin-utils': 7.20.2 + '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.21.3) + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/plugin-proposal-dynamic-import@7.18.6(@babel/core@7.21.3): + resolution: {integrity: sha512-1auuwmK+Rz13SJj36R+jqFPMJWyKEDd7lLSdOj4oJK0UTgGueSAtkrCvz9ewmgyU/P941Rv2fQwZJN8s6QruXw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.3 + '@babel/helper-plugin-utils': 7.20.2 + '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.21.3) + dev: true + + /@babel/plugin-proposal-export-namespace-from@7.18.9(@babel/core@7.21.3): + resolution: {integrity: sha512-k1NtHyOMvlDDFeb9G5PhUXuGj8m/wiwojgQVEhJ/fsVsMCpLyOP4h0uGEjYJKrRI+EVPlb5Jk+Gt9P97lOGwtA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.3 + '@babel/helper-plugin-utils': 7.20.2 + '@babel/plugin-syntax-export-namespace-from': 7.8.3(@babel/core@7.21.3) + dev: true + + /@babel/plugin-proposal-json-strings@7.18.6(@babel/core@7.21.3): + resolution: {integrity: sha512-lr1peyn9kOdbYc0xr0OdHTZ5FMqS6Di+H0Fz2I/JwMzGmzJETNeOFq2pBySw6X/KFL5EWDjlJuMsUGRFb8fQgQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.3 + '@babel/helper-plugin-utils': 7.20.2 + '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.21.3) + dev: true + + /@babel/plugin-proposal-logical-assignment-operators@7.20.7(@babel/core@7.21.3): + resolution: {integrity: sha512-y7C7cZgpMIjWlKE5T7eJwp+tnRYM89HmRvWM5EQuB5BoHEONjmQ8lSNmBUwOyy/GFRsohJED51YBF79hE1djug==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.3 + '@babel/helper-plugin-utils': 7.20.2 + '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.21.3) + dev: true + + /@babel/plugin-proposal-nullish-coalescing-operator@7.18.6(@babel/core@7.21.3): + resolution: {integrity: sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.3 + '@babel/helper-plugin-utils': 7.20.2 + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.21.3) + dev: true + + /@babel/plugin-proposal-numeric-separator@7.18.6(@babel/core@7.21.3): + resolution: {integrity: sha512-ozlZFogPqoLm8WBr5Z8UckIoE4YQ5KESVcNudyXOR8uqIkliTEgJ3RoketfG6pmzLdeZF0H/wjE9/cCEitBl7Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.3 + '@babel/helper-plugin-utils': 7.20.2 + '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.21.3) + dev: true + + /@babel/plugin-proposal-object-rest-spread@7.20.7(@babel/core@7.21.3): + resolution: {integrity: sha512-d2S98yCiLxDVmBmE8UjGcfPvNEUbA1U5q5WxaWFUGRzJSVAZqm5W6MbPct0jxnegUZ0niLeNX+IOzEs7wYg9Dg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/compat-data': 7.21.0 + '@babel/core': 7.21.3 + '@babel/helper-compilation-targets': 7.20.7(@babel/core@7.21.3) + '@babel/helper-plugin-utils': 7.20.2 + '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.21.3) + '@babel/plugin-transform-parameters': 7.21.3(@babel/core@7.21.3) + dev: true + + /@babel/plugin-proposal-optional-catch-binding@7.18.6(@babel/core@7.21.3): + resolution: {integrity: sha512-Q40HEhs9DJQyaZfUjjn6vE8Cv4GmMHCYuMGIWUnlxH6400VGxOuwWsPt4FxXxJkC/5eOzgn0z21M9gMT4MOhbw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.3 + '@babel/helper-plugin-utils': 7.20.2 + '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.21.3) + dev: true + + /@babel/plugin-proposal-optional-chaining@7.21.0(@babel/core@7.21.3): + resolution: {integrity: sha512-p4zeefM72gpmEe2fkUr/OnOXpWEf8nAgk7ZYVqqfFiyIG7oFfVZcCrU64hWn5xp4tQ9LkV4bTIa5rD0KANpKNA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.3 + '@babel/helper-plugin-utils': 7.20.2 + '@babel/helper-skip-transparent-expression-wrappers': 7.20.0 + '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.21.3) + dev: true + + /@babel/plugin-proposal-private-methods@7.18.6(@babel/core@7.21.3): + resolution: {integrity: sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.3 + '@babel/helper-create-class-features-plugin': 7.21.0(@babel/core@7.21.3) + '@babel/helper-plugin-utils': 7.20.2 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/plugin-proposal-private-property-in-object@7.21.0(@babel/core@7.21.3): + resolution: {integrity: sha512-ha4zfehbJjc5MmXBlHec1igel5TJXXLDDRbuJ4+XT2TJcyD9/V1919BA8gMvsdHcNMBy4WBUBiRb3nw/EQUtBw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.3 + '@babel/helper-annotate-as-pure': 7.18.6 + '@babel/helper-create-class-features-plugin': 7.21.0(@babel/core@7.21.3) + '@babel/helper-plugin-utils': 7.20.2 + '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.21.3) + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/plugin-proposal-unicode-property-regex@7.18.6(@babel/core@7.21.3): + resolution: {integrity: sha512-2BShG/d5yoZyXZfVePH91urL5wTG6ASZU9M4o03lKK8u8UW1y08OMttBSOADTcJrnPMpvDXRG3G8fyLh4ovs8w==} + engines: {node: '>=4'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.3 + '@babel/helper-create-regexp-features-plugin': 7.21.0(@babel/core@7.21.3) + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.21.3): + resolution: {integrity: sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.3 + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.21.3): + resolution: {integrity: sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.3 + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.21.3): + resolution: {integrity: sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.3 + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-syntax-dynamic-import@7.8.3(@babel/core@7.21.3): + resolution: {integrity: sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.3 + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-syntax-export-namespace-from@7.8.3(@babel/core@7.21.3): + resolution: {integrity: sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.3 + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-syntax-import-assertions@7.20.0(@babel/core@7.21.3): + resolution: {integrity: sha512-IUh1vakzNoWalR8ch/areW7qFopR2AEw03JlG7BbrDqmQ4X3q9uuipQwSGrUn7oGiemKjtSLDhNtQHzMHr1JdQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.3 + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.21.3): + resolution: {integrity: sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.3 + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.21.3): + resolution: {integrity: sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.3 + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.21.3): + resolution: {integrity: sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.3 + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.21.3): + resolution: {integrity: sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.3 + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.21.3): + resolution: {integrity: sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.3 + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.21.3): + resolution: {integrity: sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.3 + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.21.3): + resolution: {integrity: sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.3 + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.21.3): + resolution: {integrity: sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.3 + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.21.3): + resolution: {integrity: sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.3 + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-transform-arrow-functions@7.20.7(@babel/core@7.21.3): + resolution: {integrity: sha512-3poA5E7dzDomxj9WXWwuD6A5F3kc7VXwIJO+E+J8qtDtS+pXPAhrgEyh+9GBwBgPq1Z+bB+/JD60lp5jsN7JPQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.3 + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-transform-async-to-generator@7.20.7(@babel/core@7.21.3): + resolution: {integrity: sha512-Uo5gwHPT9vgnSXQxqGtpdufUiWp96gk7yiP4Mp5bm1QMkEmLXBO7PAGYbKoJ6DhAwiNkcHFBol/x5zZZkL/t0Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.3 + '@babel/helper-module-imports': 7.18.6 + '@babel/helper-plugin-utils': 7.20.2 + '@babel/helper-remap-async-to-generator': 7.18.9(@babel/core@7.21.3) + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/plugin-transform-block-scoped-functions@7.18.6(@babel/core@7.21.3): + resolution: {integrity: sha512-ExUcOqpPWnliRcPqves5HJcJOvHvIIWfuS4sroBUenPuMdmW+SMHDakmtS7qOo13sVppmUijqeTv7qqGsvURpQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.3 + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-transform-block-scoping@7.21.0(@babel/core@7.21.3): + resolution: {integrity: sha512-Mdrbunoh9SxwFZapeHVrwFmri16+oYotcZysSzhNIVDwIAb1UV+kvnxULSYq9J3/q5MDG+4X6w8QVgD1zhBXNQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.3 + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-transform-classes@7.21.0(@babel/core@7.21.3): + resolution: {integrity: sha512-RZhbYTCEUAe6ntPehC4hlslPWosNHDox+vAs4On/mCLRLfoDVHf6hVEd7kuxr1RnHwJmxFfUM3cZiZRmPxJPXQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.3 + '@babel/helper-annotate-as-pure': 7.18.6 + '@babel/helper-compilation-targets': 7.20.7(@babel/core@7.21.3) + '@babel/helper-environment-visitor': 7.18.9 + '@babel/helper-function-name': 7.21.0 + '@babel/helper-optimise-call-expression': 7.18.6 + '@babel/helper-plugin-utils': 7.20.2 + '@babel/helper-replace-supers': 7.20.7 + '@babel/helper-split-export-declaration': 7.18.6 + globals: 11.12.0 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/plugin-transform-computed-properties@7.20.7(@babel/core@7.21.3): + resolution: {integrity: sha512-Lz7MvBK6DTjElHAmfu6bfANzKcxpyNPeYBGEafyA6E5HtRpjpZwU+u7Qrgz/2OR0z+5TvKYbPdphfSaAcZBrYQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.3 + '@babel/helper-plugin-utils': 7.20.2 + '@babel/template': 7.20.7 + dev: true + + /@babel/plugin-transform-destructuring@7.21.3(@babel/core@7.21.3): + resolution: {integrity: sha512-bp6hwMFzuiE4HqYEyoGJ/V2LeIWn+hLVKc4pnj++E5XQptwhtcGmSayM029d/j2X1bPKGTlsyPwAubuU22KhMA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.3 + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-transform-dotall-regex@7.18.6(@babel/core@7.21.3): + resolution: {integrity: sha512-6S3jpun1eEbAxq7TdjLotAsl4WpQI9DxfkycRcKrjhQYzU87qpXdknpBg/e+TdcMehqGnLFi7tnFUBR02Vq6wg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.3 + '@babel/helper-create-regexp-features-plugin': 7.21.0(@babel/core@7.21.3) + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-transform-duplicate-keys@7.18.9(@babel/core@7.21.3): + resolution: {integrity: sha512-d2bmXCtZXYc59/0SanQKbiWINadaJXqtvIQIzd4+hNwkWBgyCd5F/2t1kXoUdvPMrxzPvhK6EMQRROxsue+mfw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.3 + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-transform-exponentiation-operator@7.18.6(@babel/core@7.21.3): + resolution: {integrity: sha512-wzEtc0+2c88FVR34aQmiz56dxEkxr2g8DQb/KfaFa1JYXOFVsbhvAonFN6PwVWj++fKmku8NP80plJ5Et4wqHw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.3 + '@babel/helper-builder-binary-assignment-operator-visitor': 7.18.9 + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-transform-for-of@7.21.0(@babel/core@7.21.3): + resolution: {integrity: sha512-LlUYlydgDkKpIY7mcBWvyPPmMcOphEyYA27Ef4xpbh1IiDNLr0kZsos2nf92vz3IccvJI25QUwp86Eo5s6HmBQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.3 + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-transform-function-name@7.18.9(@babel/core@7.21.3): + resolution: {integrity: sha512-WvIBoRPaJQ5yVHzcnJFor7oS5Ls0PYixlTYE63lCj2RtdQEl15M68FXQlxnG6wdraJIXRdR7KI+hQ7q/9QjrCQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.3 + '@babel/helper-compilation-targets': 7.20.7(@babel/core@7.21.3) + '@babel/helper-function-name': 7.21.0 + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-transform-literals@7.18.9(@babel/core@7.21.3): + resolution: {integrity: sha512-IFQDSRoTPnrAIrI5zoZv73IFeZu2dhu6irxQjY9rNjTT53VmKg9fenjvoiOWOkJ6mm4jKVPtdMzBY98Fp4Z4cg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.3 + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-transform-member-expression-literals@7.18.6(@babel/core@7.21.3): + resolution: {integrity: sha512-qSF1ihLGO3q+/g48k85tUjD033C29TNTVB2paCwZPVmOsjn9pClvYYrM2VeJpBY2bcNkuny0YUyTNRyRxJ54KA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.3 + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-transform-modules-amd@7.20.11(@babel/core@7.21.3): + resolution: {integrity: sha512-NuzCt5IIYOW0O30UvqktzHYR2ud5bOWbY0yaxWZ6G+aFzOMJvrs5YHNikrbdaT15+KNO31nPOy5Fim3ku6Zb5g==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.3 + '@babel/helper-module-transforms': 7.21.2 + '@babel/helper-plugin-utils': 7.20.2 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/plugin-transform-modules-commonjs@7.21.2(@babel/core@7.21.3): + resolution: {integrity: sha512-Cln+Yy04Gxua7iPdj6nOV96smLGjpElir5YwzF0LBPKoPlLDNJePNlrGGaybAJkd0zKRnOVXOgizSqPYMNYkzA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.3 + '@babel/helper-module-transforms': 7.21.2 + '@babel/helper-plugin-utils': 7.20.2 + '@babel/helper-simple-access': 7.20.2 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/plugin-transform-modules-systemjs@7.20.11(@babel/core@7.21.3): + resolution: {integrity: sha512-vVu5g9BPQKSFEmvt2TA4Da5N+QVS66EX21d8uoOihC+OCpUoGvzVsXeqFdtAEfVa5BILAeFt+U7yVmLbQnAJmw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.3 + '@babel/helper-hoist-variables': 7.18.6 + '@babel/helper-module-transforms': 7.21.2 + '@babel/helper-plugin-utils': 7.20.2 + '@babel/helper-validator-identifier': 7.19.1 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/plugin-transform-modules-umd@7.18.6(@babel/core@7.21.3): + resolution: {integrity: sha512-dcegErExVeXcRqNtkRU/z8WlBLnvD4MRnHgNs3MytRO1Mn1sHRyhbcpYbVMGclAqOjdW+9cfkdZno9dFdfKLfQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.3 + '@babel/helper-module-transforms': 7.21.2 + '@babel/helper-plugin-utils': 7.20.2 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/plugin-transform-named-capturing-groups-regex@7.20.5(@babel/core@7.21.3): + resolution: {integrity: sha512-mOW4tTzi5iTLnw+78iEq3gr8Aoq4WNRGpmSlrogqaiCBoR1HFhpU4JkpQFOHfeYx3ReVIFWOQJS4aZBRvuZ6mA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.21.3 + '@babel/helper-create-regexp-features-plugin': 7.21.0(@babel/core@7.21.3) + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-transform-new-target@7.18.6(@babel/core@7.21.3): + resolution: {integrity: sha512-DjwFA/9Iu3Z+vrAn+8pBUGcjhxKguSMlsFqeCKbhb9BAV756v0krzVK04CRDi/4aqmk8BsHb4a/gFcaA5joXRw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.3 + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-transform-object-super@7.18.6(@babel/core@7.21.3): + resolution: {integrity: sha512-uvGz6zk+pZoS1aTZrOvrbj6Pp/kK2mp45t2B+bTDre2UgsZZ8EZLSJtUg7m/no0zOJUWgFONpB7Zv9W2tSaFlA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.3 + '@babel/helper-plugin-utils': 7.20.2 + '@babel/helper-replace-supers': 7.20.7 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/plugin-transform-parameters@7.21.3(@babel/core@7.21.3): + resolution: {integrity: sha512-Wxc+TvppQG9xWFYatvCGPvZ6+SIUxQ2ZdiBP+PHYMIjnPXD+uThCshaz4NZOnODAtBjjcVQQ/3OKs9LW28purQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.3 + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-transform-property-literals@7.18.6(@babel/core@7.21.3): + resolution: {integrity: sha512-cYcs6qlgafTud3PAzrrRNbQtfpQ8+y/+M5tKmksS9+M1ckbH6kzY8MrexEM9mcA6JDsukE19iIRvAyYl463sMg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.3 + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-transform-regenerator@7.20.5(@babel/core@7.21.3): + resolution: {integrity: sha512-kW/oO7HPBtntbsahzQ0qSE3tFvkFwnbozz3NWFhLGqH75vLEg+sCGngLlhVkePlCs3Jv0dBBHDzCHxNiFAQKCQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.3 + '@babel/helper-plugin-utils': 7.20.2 + regenerator-transform: 0.15.1 + dev: true + + /@babel/plugin-transform-reserved-words@7.18.6(@babel/core@7.21.3): + resolution: {integrity: sha512-oX/4MyMoypzHjFrT1CdivfKZ+XvIPMFXwwxHp/r0Ddy2Vuomt4HDFGmft1TAY2yiTKiNSsh3kjBAzcM8kSdsjA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.3 + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-transform-shorthand-properties@7.18.6(@babel/core@7.21.3): + resolution: {integrity: sha512-eCLXXJqv8okzg86ywZJbRn19YJHU4XUa55oz2wbHhaQVn/MM+XhukiT7SYqp/7o00dg52Rj51Ny+Ecw4oyoygw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.3 + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-transform-spread@7.20.7(@babel/core@7.21.3): + resolution: {integrity: sha512-ewBbHQ+1U/VnH1fxltbJqDeWBU1oNLG8Dj11uIv3xVf7nrQu0bPGe5Rf716r7K5Qz+SqtAOVswoVunoiBtGhxw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.3 + '@babel/helper-plugin-utils': 7.20.2 + '@babel/helper-skip-transparent-expression-wrappers': 7.20.0 + dev: true + + /@babel/plugin-transform-sticky-regex@7.18.6(@babel/core@7.21.3): + resolution: {integrity: sha512-kfiDrDQ+PBsQDO85yj1icueWMfGfJFKN1KCkndygtu/C9+XUfydLC8Iv5UYJqRwy4zk8EcplRxEOeLyjq1gm6Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.3 + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-transform-template-literals@7.18.9(@babel/core@7.21.3): + resolution: {integrity: sha512-S8cOWfT82gTezpYOiVaGHrCbhlHgKhQt8XH5ES46P2XWmX92yisoZywf5km75wv5sYcXDUCLMmMxOLCtthDgMA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.3 + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-transform-typeof-symbol@7.18.9(@babel/core@7.21.3): + resolution: {integrity: sha512-SRfwTtF11G2aemAZWivL7PD+C9z52v9EvMqH9BuYbabyPuKUvSWks3oCg6041pT925L4zVFqaVBeECwsmlguEw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.3 + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-transform-unicode-escapes@7.18.10(@babel/core@7.21.3): + resolution: {integrity: sha512-kKAdAI+YzPgGY/ftStBFXTI1LZFju38rYThnfMykS+IXy8BVx+res7s2fxf1l8I35DV2T97ezo6+SGrXz6B3iQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.3 + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-transform-unicode-regex@7.18.6(@babel/core@7.21.3): + resolution: {integrity: sha512-gE7A6Lt7YLnNOL3Pb9BNeZvi+d8l7tcRrG4+pwJjK9hD2xX4mEvjlQW60G9EEmfXVYRPv9VRQcyegIVHCql/AA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.3 + '@babel/helper-create-regexp-features-plugin': 7.21.0(@babel/core@7.21.3) + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/preset-env@7.20.2(@babel/core@7.21.3): + resolution: {integrity: sha512-1G0efQEWR1EHkKvKHqbG+IN/QdgwfByUpM5V5QroDzGV2t3S/WXNQd693cHiHTlCFMpr9B6FkPFXDA2lQcKoDg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/compat-data': 7.21.0 + '@babel/core': 7.21.3 + '@babel/helper-compilation-targets': 7.20.7(@babel/core@7.21.3) + '@babel/helper-plugin-utils': 7.20.2 + '@babel/helper-validator-option': 7.21.0 + '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.18.6(@babel/core@7.21.3) + '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.20.7(@babel/core@7.21.3) + '@babel/plugin-proposal-async-generator-functions': 7.20.7(@babel/core@7.21.3) + '@babel/plugin-proposal-class-properties': 7.18.6(@babel/core@7.21.3) + '@babel/plugin-proposal-class-static-block': 7.21.0(@babel/core@7.21.3) + '@babel/plugin-proposal-dynamic-import': 7.18.6(@babel/core@7.21.3) + '@babel/plugin-proposal-export-namespace-from': 7.18.9(@babel/core@7.21.3) + '@babel/plugin-proposal-json-strings': 7.18.6(@babel/core@7.21.3) + '@babel/plugin-proposal-logical-assignment-operators': 7.20.7(@babel/core@7.21.3) + '@babel/plugin-proposal-nullish-coalescing-operator': 7.18.6(@babel/core@7.21.3) + '@babel/plugin-proposal-numeric-separator': 7.18.6(@babel/core@7.21.3) + '@babel/plugin-proposal-object-rest-spread': 7.20.7(@babel/core@7.21.3) + '@babel/plugin-proposal-optional-catch-binding': 7.18.6(@babel/core@7.21.3) + '@babel/plugin-proposal-optional-chaining': 7.21.0(@babel/core@7.21.3) + '@babel/plugin-proposal-private-methods': 7.18.6(@babel/core@7.21.3) + '@babel/plugin-proposal-private-property-in-object': 7.21.0(@babel/core@7.21.3) + '@babel/plugin-proposal-unicode-property-regex': 7.18.6(@babel/core@7.21.3) + '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.21.3) + '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.21.3) + '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.21.3) + '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.21.3) + '@babel/plugin-syntax-export-namespace-from': 7.8.3(@babel/core@7.21.3) + '@babel/plugin-syntax-import-assertions': 7.20.0(@babel/core@7.21.3) + '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.21.3) + '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.21.3) + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.21.3) + '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.21.3) + '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.21.3) + '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.21.3) + '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.21.3) + '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.21.3) + '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.21.3) + '@babel/plugin-transform-arrow-functions': 7.20.7(@babel/core@7.21.3) + '@babel/plugin-transform-async-to-generator': 7.20.7(@babel/core@7.21.3) + '@babel/plugin-transform-block-scoped-functions': 7.18.6(@babel/core@7.21.3) + '@babel/plugin-transform-block-scoping': 7.21.0(@babel/core@7.21.3) + '@babel/plugin-transform-classes': 7.21.0(@babel/core@7.21.3) + '@babel/plugin-transform-computed-properties': 7.20.7(@babel/core@7.21.3) + '@babel/plugin-transform-destructuring': 7.21.3(@babel/core@7.21.3) + '@babel/plugin-transform-dotall-regex': 7.18.6(@babel/core@7.21.3) + '@babel/plugin-transform-duplicate-keys': 7.18.9(@babel/core@7.21.3) + '@babel/plugin-transform-exponentiation-operator': 7.18.6(@babel/core@7.21.3) + '@babel/plugin-transform-for-of': 7.21.0(@babel/core@7.21.3) + '@babel/plugin-transform-function-name': 7.18.9(@babel/core@7.21.3) + '@babel/plugin-transform-literals': 7.18.9(@babel/core@7.21.3) + '@babel/plugin-transform-member-expression-literals': 7.18.6(@babel/core@7.21.3) + '@babel/plugin-transform-modules-amd': 7.20.11(@babel/core@7.21.3) + '@babel/plugin-transform-modules-commonjs': 7.21.2(@babel/core@7.21.3) + '@babel/plugin-transform-modules-systemjs': 7.20.11(@babel/core@7.21.3) + '@babel/plugin-transform-modules-umd': 7.18.6(@babel/core@7.21.3) + '@babel/plugin-transform-named-capturing-groups-regex': 7.20.5(@babel/core@7.21.3) + '@babel/plugin-transform-new-target': 7.18.6(@babel/core@7.21.3) + '@babel/plugin-transform-object-super': 7.18.6(@babel/core@7.21.3) + '@babel/plugin-transform-parameters': 7.21.3(@babel/core@7.21.3) + '@babel/plugin-transform-property-literals': 7.18.6(@babel/core@7.21.3) + '@babel/plugin-transform-regenerator': 7.20.5(@babel/core@7.21.3) + '@babel/plugin-transform-reserved-words': 7.18.6(@babel/core@7.21.3) + '@babel/plugin-transform-shorthand-properties': 7.18.6(@babel/core@7.21.3) + '@babel/plugin-transform-spread': 7.20.7(@babel/core@7.21.3) + '@babel/plugin-transform-sticky-regex': 7.18.6(@babel/core@7.21.3) + '@babel/plugin-transform-template-literals': 7.18.9(@babel/core@7.21.3) + '@babel/plugin-transform-typeof-symbol': 7.18.9(@babel/core@7.21.3) + '@babel/plugin-transform-unicode-escapes': 7.18.10(@babel/core@7.21.3) + '@babel/plugin-transform-unicode-regex': 7.18.6(@babel/core@7.21.3) + '@babel/preset-modules': 0.1.5(@babel/core@7.21.3) + '@babel/types': 7.21.3 + babel-plugin-polyfill-corejs2: 0.3.3(@babel/core@7.21.3) + babel-plugin-polyfill-corejs3: 0.6.0(@babel/core@7.21.3) + babel-plugin-polyfill-regenerator: 0.4.1(@babel/core@7.21.3) + core-js-compat: 3.29.1 + semver: 6.3.0 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/preset-modules@0.1.5(@babel/core@7.21.3): + resolution: {integrity: sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.3 + '@babel/helper-plugin-utils': 7.20.2 + '@babel/plugin-proposal-unicode-property-regex': 7.18.6(@babel/core@7.21.3) + '@babel/plugin-transform-dotall-regex': 7.18.6(@babel/core@7.21.3) + '@babel/types': 7.21.3 + esutils: 2.0.3 + dev: true + + /@babel/regjsgen@0.8.0: + resolution: {integrity: sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==} + dev: true + + /@babel/runtime@7.21.0: + resolution: {integrity: sha512-xwII0//EObnq89Ji5AKYQaRYiW/nZ3llSv29d49IuxPhKbtJoLP+9QUUZ4nVragQVtaVGeZrpB+ZtG/Pdy/POw==} + engines: {node: '>=6.9.0'} + dependencies: + regenerator-runtime: 0.13.11 + dev: true + + /@babel/template@7.20.7: + resolution: {integrity: sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/code-frame': 7.18.6 + '@babel/parser': 7.21.3 + '@babel/types': 7.21.3 + dev: true + + /@babel/traverse@7.21.3: + resolution: {integrity: sha512-XLyopNeaTancVitYZe2MlUEvgKb6YVVPXzofHgqHijCImG33b/uTurMS488ht/Hbsb2XK3U2BnSTxKVNGV3nGQ==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/code-frame': 7.18.6 + '@babel/generator': 7.21.3 + '@babel/helper-environment-visitor': 7.18.9 + '@babel/helper-function-name': 7.21.0 + '@babel/helper-hoist-variables': 7.18.6 + '@babel/helper-split-export-declaration': 7.18.6 + '@babel/parser': 7.21.3 + '@babel/types': 7.21.3 + debug: 4.3.4 + globals: 11.12.0 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/types@7.21.3: + resolution: {integrity: sha512-sBGdETxC+/M4o/zKC0sl6sjWv62WFR/uzxrJ6uYyMLZOUlPnwzw0tKgVHOXxaAd5l2g8pEDM5RZ495GPQI77kg==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-string-parser': 7.19.4 + '@babel/helper-validator-identifier': 7.19.1 + to-fast-properties: 2.0.0 + dev: true + + /@braintree/sanitize-url@6.0.2: + resolution: {integrity: sha512-Tbsj02wXCbqGmzdnXNk0SOF19ChhRU70BsroIi4Pm6Ehp56in6vch94mfbdQ17DozxkL3BAVjbZ4Qc1a0HFRAg==} + dev: true + + /@esbuild/android-arm64@0.16.17: + resolution: {integrity: sha512-MIGl6p5sc3RDTLLkYL1MyL8BMRN4tLMRCn+yRJJmEDvYZ2M7tmAf80hx1kbNEUX2KJ50RRtxZ4JHLvCfuB6kBg==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/android-arm@0.16.17: + resolution: {integrity: sha512-N9x1CMXVhtWEAMS7pNNONyA14f71VPQN9Cnavj1XQh6T7bskqiLLrSca4O0Vr8Wdcga943eThxnVp3JLnBMYtw==} + engines: {node: '>=12'} + cpu: [arm] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/android-x64@0.16.17: + resolution: {integrity: sha512-a3kTv3m0Ghh4z1DaFEuEDfz3OLONKuFvI4Xqczqx4BqLyuFaFkuaG4j2MtA6fuWEFeC5x9IvqnX7drmRq/fyAQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/darwin-arm64@0.16.17: + resolution: {integrity: sha512-/2agbUEfmxWHi9ARTX6OQ/KgXnOWfsNlTeLcoV7HSuSTv63E4DqtAc+2XqGw1KHxKMHGZgbVCZge7HXWX9Vn+w==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@esbuild/darwin-x64@0.16.17: + resolution: {integrity: sha512-2By45OBHulkd9Svy5IOCZt376Aa2oOkiE9QWUK9fe6Tb+WDr8hXL3dpqi+DeLiMed8tVXspzsTAvd0jUl96wmg==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@esbuild/freebsd-arm64@0.16.17: + resolution: {integrity: sha512-mt+cxZe1tVx489VTb4mBAOo2aKSnJ33L9fr25JXpqQqzbUIw/yzIzi+NHwAXK2qYV1lEFp4OoVeThGjUbmWmdw==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/freebsd-x64@0.16.17: + resolution: {integrity: sha512-8ScTdNJl5idAKjH8zGAsN7RuWcyHG3BAvMNpKOBaqqR7EbUhhVHOqXRdL7oZvz8WNHL2pr5+eIT5c65kA6NHug==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-arm64@0.16.17: + resolution: {integrity: sha512-7S8gJnSlqKGVJunnMCrXHU9Q8Q/tQIxk/xL8BqAP64wchPCTzuM6W3Ra8cIa1HIflAvDnNOt2jaL17vaW+1V0g==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-arm@0.16.17: + resolution: {integrity: sha512-iihzrWbD4gIT7j3caMzKb/RsFFHCwqqbrbH9SqUSRrdXkXaygSZCZg1FybsZz57Ju7N/SHEgPyaR0LZ8Zbe9gQ==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-ia32@0.16.17: + resolution: {integrity: sha512-kiX69+wcPAdgl3Lonh1VI7MBr16nktEvOfViszBSxygRQqSpzv7BffMKRPMFwzeJGPxcio0pdD3kYQGpqQ2SSg==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-loong64@0.16.17: + resolution: {integrity: sha512-dTzNnQwembNDhd654cA4QhbS9uDdXC3TKqMJjgOWsC0yNCbpzfWoXdZvp0mY7HU6nzk5E0zpRGGx3qoQg8T2DQ==} + engines: {node: '>=12'} + cpu: [loong64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-mips64el@0.16.17: + resolution: {integrity: sha512-ezbDkp2nDl0PfIUn0CsQ30kxfcLTlcx4Foz2kYv8qdC6ia2oX5Q3E/8m6lq84Dj/6b0FrkgD582fJMIfHhJfSw==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-ppc64@0.16.17: + resolution: {integrity: sha512-dzS678gYD1lJsW73zrFhDApLVdM3cUF2MvAa1D8K8KtcSKdLBPP4zZSLy6LFZ0jYqQdQ29bjAHJDgz0rVbLB3g==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-riscv64@0.16.17: + resolution: {integrity: sha512-ylNlVsxuFjZK8DQtNUwiMskh6nT0vI7kYl/4fZgV1llP5d6+HIeL/vmmm3jpuoo8+NuXjQVZxmKuhDApK0/cKw==} + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-s390x@0.16.17: + resolution: {integrity: sha512-gzy7nUTO4UA4oZ2wAMXPNBGTzZFP7mss3aKR2hH+/4UUkCOyqmjXiKpzGrY2TlEUhbbejzXVKKGazYcQTZWA/w==} + engines: {node: '>=12'} + cpu: [s390x] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-x64@0.16.17: + resolution: {integrity: sha512-mdPjPxfnmoqhgpiEArqi4egmBAMYvaObgn4poorpUaqmvzzbvqbowRllQ+ZgzGVMGKaPkqUmPDOOFQRUFDmeUw==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/netbsd-x64@0.16.17: + resolution: {integrity: sha512-/PzmzD/zyAeTUsduZa32bn0ORug+Jd1EGGAUJvqfeixoEISYpGnAezN6lnJoskauoai0Jrs+XSyvDhppCPoKOA==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/openbsd-x64@0.16.17: + resolution: {integrity: sha512-2yaWJhvxGEz2RiftSk0UObqJa/b+rIAjnODJgv2GbGGpRwAfpgzyrg1WLK8rqA24mfZa9GvpjLcBBg8JHkoodg==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/sunos-x64@0.16.17: + resolution: {integrity: sha512-xtVUiev38tN0R3g8VhRfN7Zl42YCJvyBhRKw1RJjwE1d2emWTVToPLNEQj/5Qxc6lVFATDiy6LjVHYhIPrLxzw==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + requiresBuild: true + dev: true + optional: true + + /@esbuild/win32-arm64@0.16.17: + resolution: {integrity: sha512-ga8+JqBDHY4b6fQAmOgtJJue36scANy4l/rL97W+0wYmijhxKetzZdKOJI7olaBaMhWt8Pac2McJdZLxXWUEQw==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@esbuild/win32-ia32@0.16.17: + resolution: {integrity: sha512-WnsKaf46uSSF/sZhwnqE4L/F89AYNMiD4YtEcYekBt9Q7nj0DiId2XH2Ng2PHM54qi5oPrQ8luuzGszqi/veig==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@esbuild/win32-x64@0.16.17: + resolution: {integrity: sha512-y+EHuSchhL7FjHgvQL/0fnnFmO4T1bhvWANX6gcnqTjtnKWbTvUMCpGnv2+t+31d7RzyEAYAd4u2fnIhHL6N/Q==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@jridgewell/gen-mapping@0.1.1: + resolution: {integrity: sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==} + engines: {node: '>=6.0.0'} + dependencies: + '@jridgewell/set-array': 1.1.2 + '@jridgewell/sourcemap-codec': 1.4.14 + dev: true + + /@jridgewell/gen-mapping@0.3.2: + resolution: {integrity: sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==} + engines: {node: '>=6.0.0'} + dependencies: + '@jridgewell/set-array': 1.1.2 + '@jridgewell/sourcemap-codec': 1.4.14 + '@jridgewell/trace-mapping': 0.3.17 + dev: true + + /@jridgewell/resolve-uri@3.1.0: + resolution: {integrity: sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==} + engines: {node: '>=6.0.0'} + dev: true + + /@jridgewell/set-array@1.1.2: + resolution: {integrity: sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==} + engines: {node: '>=6.0.0'} + dev: true + + /@jridgewell/source-map@0.3.2: + resolution: {integrity: sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==} + dependencies: + '@jridgewell/gen-mapping': 0.3.2 + '@jridgewell/trace-mapping': 0.3.17 + dev: true + + /@jridgewell/sourcemap-codec@1.4.14: + resolution: {integrity: sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==} + dev: true + + /@jridgewell/trace-mapping@0.3.17: + resolution: {integrity: sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==} + dependencies: + '@jridgewell/resolve-uri': 3.1.0 + '@jridgewell/sourcemap-codec': 1.4.14 + dev: true + + /@kurkle/color@0.3.2: + resolution: {integrity: sha512-fuscdXJ9G1qb7W8VdHi+IwRqij3lBkosAm4ydQtEmbY58OzHXqQhvlxqEkoz0yssNVn38bcpRWgA9PP+OGoisw==} + dev: true + + /@lit-labs/ssr-dom-shim@1.1.0: + resolution: {integrity: sha512-92uQ5ARf7UXYrzaFcAX3T2rTvaS9Z1//ukV+DqjACM4c8s0ZBQd7ayJU5Dh2AFLD/Ayuyz4uMmxQec8q3U4Ong==} + dev: true + + /@lit/reactive-element@1.6.1: + resolution: {integrity: sha512-va15kYZr7KZNNPZdxONGQzpUr+4sxVu7V/VG7a8mRfPPXUyhEYj5RzXCQmGrlP3tAh0L3HHm5AjBMFYRqlM9SA==} + dependencies: + '@lit-labs/ssr-dom-shim': 1.1.0 + dev: true + + /@mdit-vue/plugin-component@0.12.0: + resolution: {integrity: sha512-LrwV3f0Y6H7b7m/w1Y3bkGuR3HOiBK4QiHHW3HuRMza6MZodDQbj8Baik5/V5GiSg1/ltijS1CymVcycd1EfTw==} + dependencies: + '@types/markdown-it': 12.2.3 + markdown-it: 13.0.1 + dev: true + + /@mdit-vue/plugin-frontmatter@0.12.0: + resolution: {integrity: sha512-26Y3JktjGgNoCVH7NLqi5RcdAauAqxepTt2qXueRcRHtGpiRQV2/M1FveIhCOTCtHSuG5bBOHUxGaV6vRK3Vbw==} + dependencies: + '@mdit-vue/types': 0.12.0 + '@types/markdown-it': 12.2.3 + gray-matter: 4.0.3 + markdown-it: 13.0.1 + dev: true + + /@mdit-vue/plugin-headers@0.12.0: + resolution: {integrity: sha512-7qR63J2uc/rXbjHT77WoYBm9imwzx1tVESmRK+Uth6kqFvSWAXAFPcm4PBatGEE8TgzhklPs5BTcQtQhmmsyaw==} + dependencies: + '@mdit-vue/shared': 0.12.0 + '@mdit-vue/types': 0.12.0 + '@types/markdown-it': 12.2.3 + markdown-it: 13.0.1 + dev: true + + /@mdit-vue/plugin-sfc@0.12.0: + resolution: {integrity: sha512-mH+rHsERzDxGucAQJILspRiD723AIWMmtMhp7lDKdkCIbIhYfupFv/CkSeX+LAx5UY5greWvUTPGYVKn4gw/5Q==} + dependencies: + '@mdit-vue/types': 0.12.0 + '@types/markdown-it': 12.2.3 + markdown-it: 13.0.1 + dev: true + + /@mdit-vue/plugin-title@0.12.0: + resolution: {integrity: sha512-XrQcior1EmPgsDG88KsoF4LUSQw/RS1Nyfn5xNWGiurO70a2hml4kCe0XzT4sLKUAPG0HNbIY6b92ezNezqWTg==} + dependencies: + '@mdit-vue/shared': 0.12.0 + '@mdit-vue/types': 0.12.0 + '@types/markdown-it': 12.2.3 + markdown-it: 13.0.1 + dev: true + + /@mdit-vue/plugin-toc@0.12.0: + resolution: {integrity: sha512-tT985CqvLp17DFWHrSvmmJbh7qcy0Rl0dBbYN//Fn952a04dbr1mb2LqW0B1oStSAQj2q24HpK4ZPgYOt7Z1Jg==} + dependencies: + '@mdit-vue/shared': 0.12.0 + '@mdit-vue/types': 0.12.0 + '@types/markdown-it': 12.2.3 + markdown-it: 13.0.1 + dev: true + + /@mdit-vue/shared@0.12.0: + resolution: {integrity: sha512-E+sGSubhvnp+Gmb2hJXFDxdLwwQD1H52EVbA4yrxxI5q/cwtnPIN2eJU3zlZB9KcvzXYDFFwt/x2mfhK8RZKBg==} + dependencies: + '@mdit-vue/types': 0.12.0 + '@types/markdown-it': 12.2.3 + markdown-it: 13.0.1 + dev: true + + /@mdit-vue/types@0.12.0: + resolution: {integrity: sha512-mrC4y8n88BYvgcgzq9bvTlDgFyi2zuvzmPilRvRc3Uz1iIvq8mDhxJ0rHKFUNzPEScpDvJdIujqiDrulMqiudA==} + dev: true + + /@mdit/plugin-align@0.4.1: + resolution: {integrity: sha512-46DaKYsov6o7laFqcUTWpjT0TmW8f7EgZ0GeAoZ785vtYMpIWR2ewhevYDRs7r00NMT768/wHypWinCyXlwvuw==} + engines: {node: '>= 14'} + dependencies: + '@mdit/plugin-container': 0.4.1 + '@types/markdown-it': 12.2.3 + markdown-it: 13.0.1 + dev: true + + /@mdit/plugin-attrs@0.4.1: + resolution: {integrity: sha512-C4eNiord5P5njo0mkkB/XS/dhwf3A7nJd2NF3Bz264rWeY1pyJebryLllzFBeTtKjL9kRNZSUt4XnEkhKRpTEg==} + engines: {node: '>= 14'} + dependencies: + '@types/markdown-it': 12.2.3 + markdown-it: 13.0.1 + dev: true + + /@mdit/plugin-container@0.4.1: + resolution: {integrity: sha512-CTawSHXWJpFd1IJqMKdifNK1srqwcbOThtexKs2cdcTmM/+YC74e5cZ1nCxQ4Y3h+2Lxw0EvL+4H3SAPbUXpow==} + engines: {node: '>= 14'} + dependencies: + '@types/markdown-it': 12.2.3 + markdown-it: 13.0.1 + dev: true + + /@mdit/plugin-figure@0.4.1: + resolution: {integrity: sha512-Nh287T6PGmrB2u85edtCd2kQc8y4rMxBOymXrCvR7uqU9XTwGPPdkPANUcAfEZ5X5xd5PSYyFoOJVivoKVCkZQ==} + engines: {node: '>= 14'} + dependencies: + '@types/markdown-it': 12.2.3 + markdown-it: 13.0.1 + dev: true + + /@mdit/plugin-footnote@0.4.1: + resolution: {integrity: sha512-51DPmYu/mmmSeXwIcHncJB+CtRqhGrEppRwmV7FQ1NoJeJFQ/4167i9euvGhI7ITyjQdYzINDO9qlk/hfmhNqg==} + engines: {node: '>= 14'} + dependencies: + '@types/markdown-it': 12.2.3 + markdown-it: 13.0.1 + dev: true + + /@mdit/plugin-img-lazyload@0.4.1: + resolution: {integrity: sha512-cnJLGOyi7QQ6VgG+Lb0O0s+1+ByOuhSdlyzDOQYAua8S7WWzn3s+dPWvailk/2oti8ag1Zi19EE/RwXBHLlVsw==} + engines: {node: '>= 14'} + dependencies: + '@types/markdown-it': 12.2.3 + markdown-it: 13.0.1 + dev: true + + /@mdit/plugin-img-mark@0.4.1: + resolution: {integrity: sha512-X7uJsBpDfU/omEy33F4e4Foopr/Q/8ZQjqjgYuOpB1rx8GA0WNL1/U7GWlnnsA3y3VwGGf1EJfuvFm821Qdq+A==} + engines: {node: '>= 14'} + dependencies: + '@types/markdown-it': 12.2.3 + markdown-it: 13.0.1 + dev: true + + /@mdit/plugin-img-size@0.4.1: + resolution: {integrity: sha512-/mBCpoK9Uvy0iXT45NP1G/OkvlxdbWXVmGwKiuAJHcOzZ9sRsSnnrdBQBQGuhj3Pl0NIdZL9HeZH4YYGIhaMpg==} + engines: {node: '>= 14'} + dependencies: + '@types/markdown-it': 12.2.3 + markdown-it: 13.0.1 + dev: true + + /@mdit/plugin-include@0.4.1: + resolution: {integrity: sha512-XMVyFKNNUwNZbPC9koxHSE+gKqlR/JycvKEuRLGbPaXz+i7lricc59wDmlHJ7oOCCVLGnxsj9MslERcjQQXCrA==} + dependencies: + '@types/markdown-it': 12.2.3 + markdown-it: 13.0.1 + upath: 2.0.1 + dev: true + + /@mdit/plugin-katex@0.4.1: + resolution: {integrity: sha512-0Nk3GdOV5h8LyqvuWWabKNBjWRip0PLMmFktaOQeUghK2hWMaQJJuPc9IqjBfbei0IWyU34KMFSx9GuwMznhXw==} + engines: {node: '>= 14'} + dependencies: + '@mdit/plugin-tex': 0.4.1 + '@types/katex': 0.16.0 + '@types/markdown-it': 12.2.3 + katex: 0.16.4 + markdown-it: 13.0.1 + dev: true + + /@mdit/plugin-mark@0.4.1: + resolution: {integrity: sha512-rfMten6lQpGw/xlxaxtSIqBikfqxw/nIPr8Dt51SdWlaejjXohXoaldGDH8D2XuLxXw+Lquvf0O/q8/RfdEQTA==} + engines: {node: '>= 14'} + dependencies: + '@types/markdown-it': 12.2.3 + markdown-it: 13.0.1 + dev: true + + /@mdit/plugin-mathjax@0.4.1: + resolution: {integrity: sha512-eZrvcwx7OMHjm9V388AINWU+O4TgOMd3sgXtVtODgYtK3XzU+F9Aq8ExX5pxccSNrzjsENCYtv5kEG2j0+7yxA==} + engines: {node: '>= 14'} + dependencies: + '@mdit/plugin-tex': 0.4.1 + '@types/markdown-it': 12.2.3 + markdown-it: 13.0.1 + mathjax-full: 3.2.2 + upath: 2.0.1 + dev: true + + /@mdit/plugin-stylize@0.4.1: + resolution: {integrity: sha512-C72BuR0gSwTYBpUYnXbafrDXyOYV13lHlZdxFg7J7/d+cTasBYgCnNPSiTPDkLi7vas586kxhrE9uhQEQh51kA==} + engines: {node: '>= 14'} + dependencies: + '@types/markdown-it': 12.2.3 + markdown-it: 13.0.1 + dev: true + + /@mdit/plugin-sub@0.4.1: + resolution: {integrity: sha512-pIiWhKNONw1FJ8+fDR+BGE2xLUkhp2v8FKvDmAAX+IZBiGktmQc0b+eA4YQPlLyt2MWSZpJE8yyDylyRoc3Gew==} + engines: {node: '>= 14'} + dependencies: + '@types/markdown-it': 12.2.3 + markdown-it: 13.0.1 + dev: true + + /@mdit/plugin-sup@0.4.1: + resolution: {integrity: sha512-PQhAp4E9XVTxqYDJKuxPF2AiwBbuwS9R82bWjXVCFYJTcpCqSIBRjN3IOCsVe3g2GXQ/KsvkJFFMDtrprJoS/Q==} + engines: {node: '>= 14'} + dependencies: + '@types/markdown-it': 12.2.3 + markdown-it: 13.0.1 + dev: true + + /@mdit/plugin-tab@0.4.1: + resolution: {integrity: sha512-TNGjRI96LS4+WBy38kVOR2KR4VV/e07jzCG2Ql+P1yIBhW0L74UgwrW3D+NiUk9gLIZ8u94NFlhH3djmaNKXIA==} + dependencies: + '@types/markdown-it': 12.2.3 + markdown-it: 13.0.1 + dev: true + + /@mdit/plugin-tasklist@0.4.1: + resolution: {integrity: sha512-ImK7PNeJvFlsZD8DcbQc+b9+b95eNahPuBQDM/hmQs637Od+PpLl1zxi+8e3wNaMjH1+rhVEeVFsts/p5LPXZA==} + engines: {node: '>= 14'} + dependencies: + '@types/markdown-it': 12.2.3 + markdown-it: 13.0.1 + dev: true + + /@mdit/plugin-tex@0.4.1: + resolution: {integrity: sha512-djpDGCIQoMVzydaQ34C+hCQUdJesG0QBQcQeWz+YqrGckvBgCG6NcpuNschCh4D4f0bNQEKVqt4dZ2mWsHqFtg==} + engines: {node: '>= 14'} + dependencies: + '@types/markdown-it': 12.2.3 + markdown-it: 13.0.1 + dev: true + + /@mdit/plugin-uml@0.4.1: + resolution: {integrity: sha512-THy+SgT9bVDmkN3OqU3v7reK2e1gyH/N9J0eHo4GYrxZo6b7DACvEQQ4kgwpOph8U41TxjWyV6VzDYPMPKGo4Q==} + engines: {node: '>= 14'} + dependencies: + '@types/markdown-it': 12.2.3 + markdown-it: 13.0.1 + dev: true + + /@nodelib/fs.scandir@2.1.5: + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 + dev: true + + /@nodelib/fs.stat@2.0.5: + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + dev: true + + /@nodelib/fs.walk@1.2.8: + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.15.0 + dev: true + + /@rollup/plugin-babel@5.3.1(@babel/core@7.21.3)(rollup@2.79.1): + resolution: {integrity: sha512-WFfdLWU/xVWKeRQnKmIAQULUI7Il0gZnBIH/ZFO069wYIfPu+8zrfp/KMW0atmELoRDq8FbiP3VCss9MhCut7Q==} + engines: {node: '>= 10.0.0'} + peerDependencies: + '@babel/core': ^7.0.0 + '@types/babel__core': ^7.1.9 + rollup: ^1.20.0||^2.0.0 + peerDependenciesMeta: + '@types/babel__core': + optional: true + dependencies: + '@babel/core': 7.21.3 + '@babel/helper-module-imports': 7.18.6 + '@rollup/pluginutils': 3.1.0(rollup@2.79.1) + rollup: 2.79.1 + dev: true + + /@rollup/plugin-node-resolve@11.2.1(rollup@2.79.1): + resolution: {integrity: sha512-yc2n43jcqVyGE2sqV5/YCmocy9ArjVAP/BeXyTtADTBBX6V0e5UMqwO8CdQ0kzjb6zu5P1qMzsScCMRvE9OlVg==} + engines: {node: '>= 10.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0 + dependencies: + '@rollup/pluginutils': 3.1.0(rollup@2.79.1) + '@types/resolve': 1.17.1 + builtin-modules: 3.3.0 + deepmerge: 4.3.1 + is-module: 1.0.0 + resolve: 1.22.1 + rollup: 2.79.1 + dev: true + + /@rollup/plugin-replace@2.4.2(rollup@2.79.1): + resolution: {integrity: sha512-IGcu+cydlUMZ5En85jxHH4qj2hta/11BHq95iHEyb2sbgiN0eCdzvUcHw5gt9pBL5lTi4JDYJ1acCoMGpTvEZg==} + peerDependencies: + rollup: ^1.20.0 || ^2.0.0 + dependencies: + '@rollup/pluginutils': 3.1.0(rollup@2.79.1) + magic-string: 0.25.9 + rollup: 2.79.1 + dev: true + + /@rollup/pluginutils@3.1.0(rollup@2.79.1): + resolution: {integrity: sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==} + engines: {node: '>= 8.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0 + dependencies: + '@types/estree': 0.0.39 + estree-walker: 1.0.1 + picomatch: 2.3.1 + rollup: 2.79.1 + dev: true + + /@stackblitz/sdk@1.8.2: + resolution: {integrity: sha512-3aTg0Tb9dNs1huPkpdYxPEX/yc8A28eZneUMOEJzOLi7EJwl5onr9gCAVjIOkN4WLYu1iBSiJiGBYT629bZIJQ==} + dev: true + + /@surma/rollup-plugin-off-main-thread@2.2.3: + resolution: {integrity: sha512-lR8q/9W7hZpMWweNiAKU7NQerBnzQQLvi8qnTDU/fxItPhtZVMbPV3lbCwjhIlNBe9Bbr5V+KHshvWmVSG9cxQ==} + dependencies: + ejs: 3.1.9 + json5: 2.2.3 + magic-string: 0.25.9 + string.prototype.matchall: 4.0.8 + dev: true + + /@types/debug@4.1.7: + resolution: {integrity: sha512-9AonUzyTjXXhEOa0DnqpzZi6VHlqKMswga9EXjpXnnqxwLtdvPPtlO8evrI5D9S6asFRCQ6v+wpiUKbw+vKqyg==} + dependencies: + '@types/ms': 0.7.31 + dev: true + + /@types/estree@0.0.39: + resolution: {integrity: sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==} + dev: true + + /@types/fs-extra@11.0.1: + resolution: {integrity: sha512-MxObHvNl4A69ofaTRU8DFqvgzzv8s9yRtaPPm5gud9HDNvpB3GPQFvNuTWAI59B9huVGV5jXYJwbCsmBsOGYWA==} + dependencies: + '@types/jsonfile': 6.1.1 + '@types/node': 18.15.11 + dev: true + + /@types/hash-sum@1.0.0: + resolution: {integrity: sha512-FdLBT93h3kcZ586Aee66HPCVJ6qvxVjBlDWNmxSGSbCZe9hTsjRKdSsl4y1T+3zfujxo9auykQMnFsfyHWD7wg==} + dev: true + + /@types/jsonfile@6.1.1: + resolution: {integrity: sha512-GSgiRCVeapDN+3pqA35IkQwasaCh/0YFH5dEF6S88iDvEn901DjOeH3/QPY+XYP1DFzDZPvIvfeEgk+7br5png==} + dependencies: + '@types/node': 18.15.11 + dev: true + + /@types/katex@0.16.0: + resolution: {integrity: sha512-hz+S3nV6Mym5xPbT9fnO8dDhBFQguMYpY0Ipxv06JMi1ORgnEM4M1ymWDUhUNer3ElLmT583opRo4RzxKmh9jw==} + dev: true + + /@types/linkify-it@3.0.2: + resolution: {integrity: sha512-HZQYqbiFVWufzCwexrvh694SOim8z2d+xJl5UNamcvQFejLY/2YUtzXHYi3cHdI7PMlS8ejH2slRAOJQ32aNbA==} + dev: true + + /@types/markdown-it-emoji@2.0.2: + resolution: {integrity: sha512-2ln8Wjbcj/0oRi/6VnuMeWEHHuK8uapFttvcLmDIe1GKCsFBLOLBX+D+xhDa9oWOQV0IpvxwrSfKKssAqqroog==} + dependencies: + '@types/markdown-it': 12.2.3 + dev: true + + /@types/markdown-it@12.2.3: + resolution: {integrity: sha512-GKMHFfv3458yYy+v/N8gjufHO6MSZKCOXpZc5GXIWWy8uldwfmPn98vp81gZ5f9SVw8YYBctgfJ22a2d7AOMeQ==} + dependencies: + '@types/linkify-it': 3.0.2 + '@types/mdurl': 1.0.2 + dev: true + + /@types/mdurl@1.0.2: + resolution: {integrity: sha512-eC4U9MlIcu2q0KQmXszyn5Akca/0jrQmwDRgpAMJai7qBWq4amIQhZyNau4VYGtCeALvW1/NtjzJJ567aZxfKA==} + dev: true + + /@types/ms@0.7.31: + resolution: {integrity: sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==} + dev: true + + /@types/node@17.0.45: + resolution: {integrity: sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==} + dev: true + + /@types/node@18.15.11: + resolution: {integrity: sha512-E5Kwq2n4SbMzQOn6wnmBjuK9ouqlURrcZDVfbo9ftDDTFt3nk7ZKK4GMOzoYgnpQJKcxwQw+lGaBvvlMo0qN/Q==} + dev: true + + /@types/raphael@2.3.3: + resolution: {integrity: sha512-Rhvq0q6wzyvipejki/9w87/pgapyE+s3gO66tdl1oD3qDrow+ek+4vVYAbRkeL58HCCK9EOZKwyjqYJ/TFkmtQ==} + dev: true + + /@types/resolve@1.17.1: + resolution: {integrity: sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==} + dependencies: + '@types/node': 18.15.11 + dev: true + + /@types/sax@1.2.4: + resolution: {integrity: sha512-pSAff4IAxJjfAXUG6tFkO7dsSbTmf8CtUpfhhZ5VhkRpC4628tJhh3+V6H1E+/Gs9piSzYKT5yzHO5M4GG9jkw==} + dependencies: + '@types/node': 18.15.11 + dev: true + + /@types/trusted-types@2.0.3: + resolution: {integrity: sha512-NfQ4gyz38SL8sDNrSixxU2Os1a5xcdFxipAFxYEuLUlvU2uDwS4NUpsImcf1//SlWItCVMMLiylsxbmNMToV/g==} + dev: true + + /@types/web-bluetooth@0.0.16: + resolution: {integrity: sha512-oh8q2Zc32S6gd/j50GowEjKLoOVOwHP/bWVjKJInBwQqdOYMdPrf1oVlelTlyfFK3CKxL1uahMDAr+vy8T7yMQ==} + dev: true + + /@vitejs/plugin-vue@4.1.0(vite@4.1.4)(vue@3.2.47): + resolution: {integrity: sha512-++9JOAFdcXI3lyer9UKUV4rfoQ3T1RN8yDqoCLar86s0xQct5yblxAE+yWgRnU5/0FOlVCpTZpYSBV/bGWrSrQ==} + engines: {node: ^14.18.0 || >=16.0.0} + peerDependencies: + vite: ^4.0.0 + vue: ^3.2.25 + dependencies: + vite: 4.1.4 + vue: 3.2.47 + dev: true + + /@vue/compiler-core@3.2.47: + resolution: {integrity: sha512-p4D7FDnQb7+YJmO2iPEv0SQNeNzcbHdGByJDsT4lynf63AFkOTFN07HsiRSvjGo0QrxR/o3d0hUyNCUnBU2Tig==} + dependencies: + '@babel/parser': 7.21.3 + '@vue/shared': 3.2.47 + estree-walker: 2.0.2 + source-map: 0.6.1 + dev: true + + /@vue/compiler-dom@3.2.47: + resolution: {integrity: sha512-dBBnEHEPoftUiS03a4ggEig74J2YBZ2UIeyfpcRM2tavgMWo4bsEfgCGsu+uJIL/vax9S+JztH8NmQerUo7shQ==} + dependencies: + '@vue/compiler-core': 3.2.47 + '@vue/shared': 3.2.47 + dev: true + + /@vue/compiler-sfc@3.2.47: + resolution: {integrity: sha512-rog05W+2IFfxjMcFw10tM9+f7i/+FFpZJJ5XHX72NP9eC2uRD+42M3pYcQqDXVYoj74kHMSEdQ/WmCjt8JFksQ==} + dependencies: + '@babel/parser': 7.21.3 + '@vue/compiler-core': 3.2.47 + '@vue/compiler-dom': 3.2.47 + '@vue/compiler-ssr': 3.2.47 + '@vue/reactivity-transform': 3.2.47 + '@vue/shared': 3.2.47 + estree-walker: 2.0.2 + magic-string: 0.25.9 + postcss: 8.4.21 + source-map: 0.6.1 + dev: true + + /@vue/compiler-ssr@3.2.47: + resolution: {integrity: sha512-wVXC+gszhulcMD8wpxMsqSOpvDZ6xKXSVWkf50Guf/S+28hTAXPDYRTbLQ3EDkOP5Xz/+SY37YiwDquKbJOgZw==} + dependencies: + '@vue/compiler-dom': 3.2.47 + '@vue/shared': 3.2.47 + dev: true + + /@vue/devtools-api@6.5.0: + resolution: {integrity: sha512-o9KfBeaBmCKl10usN4crU53fYtC1r7jJwdGKjPT24t348rHxgfpZ0xL3Xm/gLUYnc0oTp8LAmrxOeLyu6tbk2Q==} + dev: true + + /@vue/reactivity-transform@3.2.47: + resolution: {integrity: sha512-m8lGXw8rdnPVVIdIFhf0LeQ/ixyHkH5plYuS83yop5n7ggVJU+z5v0zecwEnX7fa7HNLBhh2qngJJkxpwEEmYA==} + dependencies: + '@babel/parser': 7.21.3 + '@vue/compiler-core': 3.2.47 + '@vue/shared': 3.2.47 + estree-walker: 2.0.2 + magic-string: 0.25.9 + dev: true + + /@vue/reactivity@3.2.47: + resolution: {integrity: sha512-7khqQ/75oyyg+N/e+iwV6lpy1f5wq759NdlS1fpAhFXa8VeAIKGgk2E/C4VF59lx5b+Ezs5fpp/5WsRYXQiKxQ==} + dependencies: + '@vue/shared': 3.2.47 + dev: true + + /@vue/repl@1.3.3(vue@3.2.47): + resolution: {integrity: sha512-mrN3Gd4CIaiIiRdi7/pAOH9rPud8q8I5svLurSoyxLhxFXs9WdfaKZlirExSJIuecHYFiAAozTBtb8XQPNhCHw==} + peerDependencies: + vue: ^3.2.13 + dependencies: + vue: 3.2.47 + dev: true + + /@vue/runtime-core@3.2.47: + resolution: {integrity: sha512-RZxbLQIRB/K0ev0K9FXhNbBzT32H9iRtYbaXb0ZIz2usLms/D55dJR2t6cIEUn6vyhS3ALNvNthI+Q95C+NOpA==} + dependencies: + '@vue/reactivity': 3.2.47 + '@vue/shared': 3.2.47 + dev: true + + /@vue/runtime-dom@3.2.47: + resolution: {integrity: sha512-ArXrFTjS6TsDei4qwNvgrdmHtD930KgSKGhS5M+j8QxXrDJYLqYw4RRcDy1bz1m1wMmb6j+zGLifdVHtkXA7gA==} + dependencies: + '@vue/runtime-core': 3.2.47 + '@vue/shared': 3.2.47 + csstype: 2.6.21 + dev: true + + /@vue/server-renderer@3.2.47(vue@3.2.47): + resolution: {integrity: sha512-dN9gc1i8EvmP9RCzvneONXsKfBRgqFeFZLurmHOveL7oH6HiFXJw5OGu294n1nHc/HMgTy6LulU/tv5/A7f/LA==} + peerDependencies: + vue: 3.2.47 + dependencies: + '@vue/compiler-ssr': 3.2.47 + '@vue/shared': 3.2.47 + vue: 3.2.47 + dev: true + + /@vue/shared@3.2.47: + resolution: {integrity: sha512-BHGyyGN3Q97EZx0taMQ+OLNuZcW3d37ZEVmEAyeoA9ERdGvm9Irc/0Fua8SNyOtV1w6BS4q25wbMzJujO9HIfQ==} + dev: true + + /@vuepress/bundler-vite@2.0.0-beta.61: + resolution: {integrity: sha512-J9/DGfsqr9rGJT+0osL9uL+jrrGHeAsWuZoCCbQIDbe0rEO2whvou51PJpwko3R0vvCTWsolh6rXYeb0N0+yFg==} + dependencies: + '@vitejs/plugin-vue': 4.1.0(vite@4.1.4)(vue@3.2.47) + '@vuepress/client': 2.0.0-beta.61 + '@vuepress/core': 2.0.0-beta.61 + '@vuepress/shared': 2.0.0-beta.61 + '@vuepress/utils': 2.0.0-beta.61 + autoprefixer: 10.4.14(postcss@8.4.21) + connect-history-api-fallback: 2.0.0 + postcss: 8.4.21 + postcss-load-config: 4.0.1(postcss@8.4.21) + rollup: 3.20.2 + vite: 4.1.4 + vue: 3.2.47 + vue-router: 4.1.6(vue@3.2.47) + transitivePeerDependencies: + - '@types/node' + - less + - sass + - stylus + - sugarss + - supports-color + - terser + - ts-node + dev: true + + /@vuepress/cli@2.0.0-beta.61: + resolution: {integrity: sha512-0CWc82c75987mVZwBOGBaCDke74NwlS6L3n1ybWrrqaFeueZSonwdm+qvaNvM/AJC10chqOJtpO/O3P+/YkBHQ==} + dependencies: + '@vuepress/core': 2.0.0-beta.61 + '@vuepress/shared': 2.0.0-beta.61 + '@vuepress/utils': 2.0.0-beta.61 + cac: 6.7.14 + chokidar: 3.5.3 + envinfo: 7.8.1 + esbuild: 0.16.17 + transitivePeerDependencies: + - supports-color + dev: true + + /@vuepress/client@2.0.0-beta.61: + resolution: {integrity: sha512-C5QbdQkPsurEsKUkLclVucUAKMzBph9kHMUvfKHJqBaAsiXKYVLa61AICTJeyDkhTYF0faOjmpqmaElfMt1S9w==} + dependencies: + '@vue/devtools-api': 6.5.0 + '@vuepress/shared': 2.0.0-beta.61 + vue: 3.2.47 + vue-router: 4.1.6(vue@3.2.47) + dev: true + + /@vuepress/core@2.0.0-beta.61: + resolution: {integrity: sha512-jPr60d/uadgBmEQhXCRLNOm2M4Ym65lvZhGf/wyZCo14kpacp2YoO7RR8bzp/NEpWe7ndr/U8O/VDjFYTsz80g==} + dependencies: + '@vuepress/client': 2.0.0-beta.61 + '@vuepress/markdown': 2.0.0-beta.61 + '@vuepress/shared': 2.0.0-beta.61 + '@vuepress/utils': 2.0.0-beta.61 + vue: 3.2.47 + transitivePeerDependencies: + - supports-color + dev: true + + /@vuepress/markdown@2.0.0-beta.61: + resolution: {integrity: sha512-vzj933XxsfE9B+1kdMXncYtYU7TGTLjWP+qeikVsy5imq2BXa/n3OFVGyGkkdOYmu05hkm82+07dOvtGA+iMBQ==} + dependencies: + '@mdit-vue/plugin-component': 0.12.0 + '@mdit-vue/plugin-frontmatter': 0.12.0 + '@mdit-vue/plugin-headers': 0.12.0 + '@mdit-vue/plugin-sfc': 0.12.0 + '@mdit-vue/plugin-title': 0.12.0 + '@mdit-vue/plugin-toc': 0.12.0 + '@mdit-vue/shared': 0.12.0 + '@mdit-vue/types': 0.12.0 + '@types/markdown-it': 12.2.3 + '@types/markdown-it-emoji': 2.0.2 + '@vuepress/shared': 2.0.0-beta.61 + '@vuepress/utils': 2.0.0-beta.61 + markdown-it: 13.0.1 + markdown-it-anchor: 8.6.7(@types/markdown-it@12.2.3)(markdown-it@13.0.1) + markdown-it-emoji: 2.0.2 + mdurl: 1.0.1 + transitivePeerDependencies: + - supports-color + dev: true + + /@vuepress/plugin-active-header-links@2.0.0-beta.61: + resolution: {integrity: sha512-+bbzb4YqnuTOANvSmJq8hbp60Tl3jLMiaZdkHKxKK9lDODGfTB8uAlH+KvuvxxuLm+Za186r+2PtBwJby773fA==} + dependencies: + '@vuepress/client': 2.0.0-beta.61 + '@vuepress/core': 2.0.0-beta.61 + '@vuepress/utils': 2.0.0-beta.61 + ts-debounce: 4.0.0 + vue: 3.2.47 + vue-router: 4.1.6(vue@3.2.47) + transitivePeerDependencies: + - supports-color + dev: true + + /@vuepress/plugin-back-to-top@2.0.0-beta.61: + resolution: {integrity: sha512-2KX83rdc00FSs38o8/P2Hp0ifKVtRbO+4kXW5ilzY27v0UMY8H//KxmoE/+PZDS9iyeXF1O/YUm3VtoMN5Y/9g==} + dependencies: + '@vuepress/client': 2.0.0-beta.61 + '@vuepress/core': 2.0.0-beta.61 + '@vuepress/utils': 2.0.0-beta.61 + ts-debounce: 4.0.0 + vue: 3.2.47 + transitivePeerDependencies: + - supports-color + dev: true + + /@vuepress/plugin-container@2.0.0-beta.61: + resolution: {integrity: sha512-XVIhMpTSv0F8tsmCKFHzFtsJzD2SeiKX60jHaEGCym+shNvr9euECWY7ygEB5Ob6oQUIDZNS1dDb1RcYsksZ8A==} + dependencies: + '@types/markdown-it': 12.2.3 + '@vuepress/core': 2.0.0-beta.61 + '@vuepress/markdown': 2.0.0-beta.61 + '@vuepress/shared': 2.0.0-beta.61 + '@vuepress/utils': 2.0.0-beta.61 + markdown-it: 13.0.1 + markdown-it-container: 3.0.0 + transitivePeerDependencies: + - supports-color + dev: true + + /@vuepress/plugin-external-link-icon@2.0.0-beta.61: + resolution: {integrity: sha512-Jyp/QdqIvybfocD2K8otKIeHrKMeOamt74tlstsZxrtveKhWE3Js1/n2MP/bJlGkcHrAb6lQQr/JFhpT5jtHVg==} + dependencies: + '@vuepress/client': 2.0.0-beta.61 + '@vuepress/core': 2.0.0-beta.61 + '@vuepress/markdown': 2.0.0-beta.61 + '@vuepress/shared': 2.0.0-beta.61 + '@vuepress/utils': 2.0.0-beta.61 + vue: 3.2.47 + transitivePeerDependencies: + - supports-color + dev: true + + /@vuepress/plugin-git@2.0.0-beta.61: + resolution: {integrity: sha512-ozoxZ+x57yGiHDs5tXJvbyoZTiYpfb7QQaS5mgxn0+XZqfg7/cZnT7DmJtxVqk+VFmz73WHgN+4pGRjkuTOLqQ==} + dependencies: + '@vuepress/core': 2.0.0-beta.61 + '@vuepress/utils': 2.0.0-beta.61 + execa: 7.1.1 + transitivePeerDependencies: + - supports-color + dev: true + + /@vuepress/plugin-google-analytics@2.0.0-beta.61: + resolution: {integrity: sha512-UwjDVtNpqkfEz7S5TPl703Jwhg0V1Xfvz8y5c4y5nQLNRky0/3bOKx8u7e5J3AATtwz0XwI2cmhXtuHFs6IiDA==} + dependencies: + '@vuepress/client': 2.0.0-beta.61 + '@vuepress/core': 2.0.0-beta.61 + '@vuepress/utils': 2.0.0-beta.61 + transitivePeerDependencies: + - supports-color + dev: true + + /@vuepress/plugin-medium-zoom@2.0.0-beta.61: + resolution: {integrity: sha512-mFY2vHXeqC8dizFVlFO7HIzirb79Z8sudKWPVfZmq0Qmlttyhxlns8GjrsPQl1mnz2NlYUY1ztUasikPwsYjAw==} + dependencies: + '@vuepress/client': 2.0.0-beta.61 + '@vuepress/core': 2.0.0-beta.61 + '@vuepress/utils': 2.0.0-beta.61 + medium-zoom: 1.0.8 + vue: 3.2.47 + transitivePeerDependencies: + - supports-color + dev: true + + /@vuepress/plugin-nprogress@2.0.0-beta.61: + resolution: {integrity: sha512-d36NEy8hkZaAuqMZec9VTEjozPkj9Wvimyx+AgJYpYN8JDBrWB58r9Gu9xHf8/PVeEnKayggD2xJYpGKtQ2lrw==} + dependencies: + '@vuepress/client': 2.0.0-beta.61 + '@vuepress/core': 2.0.0-beta.61 + '@vuepress/utils': 2.0.0-beta.61 + vue: 3.2.47 + vue-router: 4.1.6(vue@3.2.47) + transitivePeerDependencies: + - supports-color + dev: true + + /@vuepress/plugin-palette@2.0.0-beta.61: + resolution: {integrity: sha512-mQE/2dxwOZfkc7wwkwR6byaeMJYTqQV7WmfQ4YQ3zAOr4nDP8Bx/zZVRyV3NjAcMwuif/CURpAYJo+WkFM+fpQ==} + dependencies: + '@vuepress/core': 2.0.0-beta.61 + '@vuepress/utils': 2.0.0-beta.61 + chokidar: 3.5.3 + transitivePeerDependencies: + - supports-color + dev: true + + /@vuepress/plugin-prismjs@2.0.0-beta.61: + resolution: {integrity: sha512-B6TRmttJuPs1OMJXE2Stul7zhMUKCPy2YSXEmVWwlJ90jWti85o5nhTT9/OhxBVn3EZ89b+YroPDbB/g1uUc1w==} + dependencies: + '@vuepress/core': 2.0.0-beta.61 + prismjs: 1.29.0 + transitivePeerDependencies: + - supports-color + dev: true + + /@vuepress/plugin-theme-data@2.0.0-beta.61: + resolution: {integrity: sha512-drPLGbaXqXnHsuFHn6FolbqdRIxJzla1+10b3cKnsslatRbSPjKWos4Eri3xzgzEIC5TotPwTeT25gDRMpW8Sw==} + dependencies: + '@vue/devtools-api': 6.5.0 + '@vuepress/client': 2.0.0-beta.61 + '@vuepress/core': 2.0.0-beta.61 + '@vuepress/shared': 2.0.0-beta.61 + '@vuepress/utils': 2.0.0-beta.61 + vue: 3.2.47 + transitivePeerDependencies: + - supports-color + dev: true + + /@vuepress/shared@2.0.0-beta.61: + resolution: {integrity: sha512-NhOQ1FDr5lDSu5IinNlNNzrF+jGOZ+bMFUyAlCxlTvK9oY6aRBCNwV8dWme+yoh3/zviKHGu62Xp7J2hKAHNZA==} + dependencies: + '@mdit-vue/types': 0.12.0 + '@vue/shared': 3.2.47 + dev: true + + /@vuepress/theme-default@2.0.0-beta.61: + resolution: {integrity: sha512-ajjxaGqrSy5LXf+7sslHV1fbUzggMYjITcXxBYa3gT4zVu1tsytAAcmtYxnQKblL1Eo2Wo7inujl/NUwaWDjDQ==} + peerDependencies: + sass-loader: ^13.2.0 + peerDependenciesMeta: + sass-loader: + optional: true + dependencies: + '@vuepress/client': 2.0.0-beta.61 + '@vuepress/core': 2.0.0-beta.61 + '@vuepress/plugin-active-header-links': 2.0.0-beta.61 + '@vuepress/plugin-back-to-top': 2.0.0-beta.61 + '@vuepress/plugin-container': 2.0.0-beta.61 + '@vuepress/plugin-external-link-icon': 2.0.0-beta.61 + '@vuepress/plugin-git': 2.0.0-beta.61 + '@vuepress/plugin-medium-zoom': 2.0.0-beta.61 + '@vuepress/plugin-nprogress': 2.0.0-beta.61 + '@vuepress/plugin-palette': 2.0.0-beta.61 + '@vuepress/plugin-prismjs': 2.0.0-beta.61 + '@vuepress/plugin-theme-data': 2.0.0-beta.61 + '@vuepress/shared': 2.0.0-beta.61 + '@vuepress/utils': 2.0.0-beta.61 + '@vueuse/core': 9.13.0(vue@3.2.47) + sass: 1.60.0 + vue: 3.2.47 + vue-router: 4.1.6(vue@3.2.47) + transitivePeerDependencies: + - '@vue/composition-api' + - supports-color + dev: true + + /@vuepress/utils@2.0.0-beta.61: + resolution: {integrity: sha512-W7g6xjrdyOW5E1V1ouyTm5d4+kgSd4KcM80D7K0NNScrhLIW6gpOggVVOVyTH3q2K1GQhzPlUcUe04ZNSo0ilQ==} + dependencies: + '@types/debug': 4.1.7 + '@types/fs-extra': 11.0.1 + '@types/hash-sum': 1.0.0 + '@vuepress/shared': 2.0.0-beta.61 + debug: 4.3.4 + fs-extra: 11.1.1 + globby: 13.1.3 + hash-sum: 2.0.0 + ora: 6.3.0 + picocolors: 1.0.0 + upath: 2.0.1 + transitivePeerDependencies: + - supports-color + dev: true + + /@vueuse/core@9.13.0(vue@3.2.47): + resolution: {integrity: sha512-pujnclbeHWxxPRqXWmdkKV5OX4Wk4YeK7wusHqRwU0Q7EFusHoqNA/aPhB6KCh9hEqJkLAJo7bb0Lh9b+OIVzw==} + dependencies: + '@types/web-bluetooth': 0.0.16 + '@vueuse/metadata': 9.13.0 + '@vueuse/shared': 9.13.0(vue@3.2.47) + vue-demi: 0.13.11(vue@3.2.47) + transitivePeerDependencies: + - '@vue/composition-api' + - vue + dev: true + + /@vueuse/metadata@9.13.0: + resolution: {integrity: sha512-gdU7TKNAUVlXXLbaF+ZCfte8BjRJQWPCa2J55+7/h+yDtzw3vOoGQDRXzI6pyKyo6bXFT5/QoPE4hAknExjRLQ==} + dev: true + + /@vueuse/shared@9.13.0(vue@3.2.47): + resolution: {integrity: sha512-UrnhU+Cnufu4S6JLCPZnkWh0WwZGUp72ktOF2DFptMlOs3TOdVv8xJN53zhHGARmVOsz5KqOls09+J1NR6sBKw==} + dependencies: + vue-demi: 0.13.11(vue@3.2.47) + transitivePeerDependencies: + - '@vue/composition-api' + - vue + dev: true + + /@waline/client@2.14.9: + resolution: {integrity: sha512-j156AgwKskRNtlBWeFj8niN4j6lwS4xg8BKo1A09p1j78rcGhNxf5S9gmzqW/8oDUbnSILOHtweydiRgWEqBag==} + engines: {node: '>=14'} + dependencies: + '@vueuse/core': 9.13.0(vue@3.2.47) + autosize: 6.0.1 + marked: 4.3.0 + vue: 3.2.47 + transitivePeerDependencies: + - '@vue/composition-api' + dev: true + + /abortcontroller-polyfill@1.7.5: + resolution: {integrity: sha512-JMJ5soJWP18htbbxJjG7bG6yuI6pRhgJ0scHHTfkUjf6wjP912xZWvM+A4sJK3gqd9E8fcPbDnOefbA9Th/FIQ==} + dev: true + + /acorn@8.8.2: + resolution: {integrity: sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==} + engines: {node: '>=0.4.0'} + dev: true + + /ajv@8.12.0: + resolution: {integrity: sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==} + dependencies: + fast-deep-equal: 3.1.3 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + uri-js: 4.4.1 + dev: true + + /ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + dev: true + + /ansi-regex@6.0.1: + resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==} + engines: {node: '>=12'} + dev: true + + /ansi-styles@3.2.1: + resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} + engines: {node: '>=4'} + dependencies: + color-convert: 1.9.3 + dev: true + + /ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + dependencies: + color-convert: 2.0.1 + dev: true + + /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 + + /arg@5.0.2: + resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} + dev: true + + /argparse@1.0.10: + resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} + dependencies: + sprintf-js: 1.0.3 + dev: true + + /argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + dev: true + + /array-buffer-byte-length@1.0.0: + resolution: {integrity: sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==} + dependencies: + call-bind: 1.0.2 + is-array-buffer: 3.0.2 + dev: true + + /artalk@2.5.2: + resolution: {integrity: sha512-qwAtSCRIBadaXyLsVps8DDlawis7KQNQpDfEj2h8xbA8LYv1nTUR4tazb4oVRBOwGSpo1cir8WIT3pq/MkiTLg==} + dependencies: + abortcontroller-polyfill: 1.7.5 + hanabi: 0.4.0 + insane: 2.6.2 + marked: 4.3.0 + dev: true + + /artplayer@4.6.2: + resolution: {integrity: sha512-9RMfFFy2wGgHUCnrwk+M2Z5OiLWQcBL+YzkSBwSi6IuJG6oM+TlfJJZt09RL2iag6DNQ+AUYtB879WUHxbqfIQ==} + dependencies: + option-validator: 2.0.6 + dev: true + + /assignment@2.0.0: + resolution: {integrity: sha512-naMULXjtgCs9SVUEtyvJNt68aF18em7/W+dhbR59kbz9cXWPEvUkCun2tqlgqRPSqZaKPpqLc5ZnwL8jVmJRvw==} + dev: true + + /async@3.2.4: + resolution: {integrity: sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==} + dev: true + + /at-least-node@1.0.0: + resolution: {integrity: sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==} + engines: {node: '>= 4.0.0'} + dev: true + + /autoprefixer@10.4.14(postcss@8.4.21): + resolution: {integrity: sha512-FQzyfOsTlwVzjHxKEqRIAdJx9niO6VCBCoEwax/VLSoQF29ggECcPuBqUMZ+u8jCZOPSy8b8/8KnuFbp0SaFZQ==} + engines: {node: ^10 || ^12 || >=14} + hasBin: true + peerDependencies: + postcss: ^8.1.0 + dependencies: + browserslist: 4.21.5 + caniuse-lite: 1.0.30001472 + fraction.js: 4.2.0 + normalize-range: 0.1.2 + picocolors: 1.0.0 + postcss: 8.4.21 + postcss-value-parser: 4.2.0 + dev: true + + /autosize@6.0.1: + resolution: {integrity: sha512-f86EjiUKE6Xvczc4ioP1JBlWG7FKrE13qe/DxBCpe8GCipCq2nFw73aO8QEBKHfSbYGDN5eB9jXWKen7tspDqQ==} + dev: true + + /available-typed-arrays@1.0.5: + resolution: {integrity: sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==} + engines: {node: '>= 0.4'} + dev: true + + /babel-plugin-polyfill-corejs2@0.3.3(@babel/core@7.21.3): + resolution: {integrity: sha512-8hOdmFYFSZhqg2C/JgLUQ+t52o5nirNwaWM2B9LWteozwIvM14VSwdsCAUET10qT+kmySAlseadmfeeSWFCy+Q==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/compat-data': 7.21.0 + '@babel/core': 7.21.3 + '@babel/helper-define-polyfill-provider': 0.3.3(@babel/core@7.21.3) + semver: 6.3.0 + transitivePeerDependencies: + - supports-color + dev: true + + /babel-plugin-polyfill-corejs3@0.6.0(@babel/core@7.21.3): + resolution: {integrity: sha512-+eHqR6OPcBhJOGgsIar7xoAB1GcSwVUA3XjAd7HJNzOXT4wv6/H7KIdA/Nc60cvUlDbKApmqNvD1B1bzOt4nyA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.3 + '@babel/helper-define-polyfill-provider': 0.3.3(@babel/core@7.21.3) + core-js-compat: 3.29.1 + transitivePeerDependencies: + - supports-color + dev: true + + /babel-plugin-polyfill-regenerator@0.4.1(@babel/core@7.21.3): + resolution: {integrity: sha512-NtQGmyQDXjQqQ+IzRkBVwEOz9lQ4zxAQZgoAYEtU9dJjnl1Oc98qnN7jcp+bE7O7aYzVpavXE3/VKXNzUbh7aw==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.3 + '@babel/helper-define-polyfill-provider': 0.3.3(@babel/core@7.21.3) + transitivePeerDependencies: + - supports-color + dev: true + + /balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + dev: true + + /balloon-css@1.2.0: + resolution: {integrity: sha512-urXwkHgwp6GsXVF+it01485Z2Cj4pnW02ICnM0TemOlkKmCNnDLmyy+ZZiRXBpwldUXO+aRNr7Hdia4CBvXJ5A==} + dev: true + + /base64-js@1.5.1: + resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + dev: true + + /bcp-47-match@1.0.3: + resolution: {integrity: sha512-LggQ4YTdjWQSKELZF5JwchnBa1u0pIQSZf5lSdOHEdbVP55h0qICA/FUp3+W99q0xqxYa1ZQizTUH87gecII5w==} + dev: true + + /bcp-47-normalize@1.1.1: + resolution: {integrity: sha512-jWZ1Jdu3cs0EZdfCkS0UE9Gg01PtxnChjEBySeB+Zo6nkqtFfnvtoQQgP1qU1Oo4qgJgxhTI6Sf9y/pZIhPs0A==} + dependencies: + bcp-47: 1.0.8 + bcp-47-match: 1.0.3 + dev: true + + /bcp-47@1.0.8: + resolution: {integrity: sha512-Y9y1QNBBtYtv7hcmoX0tR+tUNSFZGZ6OL6vKPObq8BbOhkCoyayF6ogfLTgAli/KuAEbsYHYUNq2AQuY6IuLag==} + dependencies: + is-alphabetical: 1.0.4 + is-alphanumerical: 1.0.4 + is-decimal: 1.0.4 + dev: true + + /bcrypt-ts@3.0.0: + resolution: {integrity: sha512-z4pqdPaAuuvBsHCwb77bisxT9qo5hRSbn78FXNhhTywHabqMzcIosDxjnKUrkPQbMyz2curUT+fJRith57rIvg==} + dev: true + + /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 + dev: true + + /boolbase@1.0.0: + resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} + dev: true + + /brace-expansion@1.1.11: + resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + dev: true + + /brace-expansion@2.0.1: + resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} + dependencies: + balanced-match: 1.0.2 + dev: true + + /braces@3.0.2: + resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} + engines: {node: '>=8'} + dependencies: + fill-range: 7.0.1 + dev: true + + /browserslist@4.21.5: + resolution: {integrity: sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + dependencies: + caniuse-lite: 1.0.30001472 + electron-to-chromium: 1.4.342 + node-releases: 2.0.10 + update-browserslist-db: 1.0.10(browserslist@4.21.5) + 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 + dev: true + + /builtin-modules@3.3.0: + resolution: {integrity: sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==} + engines: {node: '>=6'} + dev: true + + /cac@6.7.14: + resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} + engines: {node: '>=8'} + dev: true + + /call-bind@1.0.2: + resolution: {integrity: sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==} + dependencies: + function-bind: 1.1.1 + get-intrinsic: 1.2.0 + dev: true + + /camelcase@5.3.1: + resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} + engines: {node: '>=6'} + dev: true + + /caniuse-lite@1.0.30001472: + resolution: {integrity: sha512-xWC/0+hHHQgj3/vrKYY0AAzeIUgr7L9wlELIcAvZdDUHlhL/kNxMdnQLOSOQfP8R51ZzPhmHdyMkI0MMpmxCfg==} + dev: true + + /chalk@2.4.2: + resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} + engines: {node: '>=4'} + dependencies: + ansi-styles: 3.2.1 + escape-string-regexp: 1.0.5 + supports-color: 5.5.0 + dev: true + + /chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + dev: true + + /chalk@5.2.0: + resolution: {integrity: sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA==} + engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + dev: true + + /chart.js@4.2.1: + resolution: {integrity: sha512-6YbpQ0nt3NovAgOzbkSSeeAQu/3za1319dPUQTXn9WcOpywM8rGKxJHrhS8V8xEkAlk8YhEfjbuAPfUyp6jIsw==} + engines: {pnpm: ^7.0.0} + dependencies: + '@kurkle/color': 0.3.2 + dev: true + + /cheerio-select@2.1.0: + resolution: {integrity: sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==} + dependencies: + boolbase: 1.0.0 + css-select: 5.1.0 + css-what: 6.1.0 + domelementtype: 2.3.0 + domhandler: 5.0.3 + domutils: 3.0.1 + dev: true + + /cheerio@1.0.0-rc.12: + resolution: {integrity: sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q==} + engines: {node: '>= 6'} + dependencies: + cheerio-select: 2.1.0 + dom-serializer: 2.0.0 + domhandler: 5.0.3 + domutils: 3.0.1 + htmlparser2: 8.0.2 + parse5: 7.1.2 + parse5-htmlparser2-tree-adapter: 7.0.0 + dev: true + + /chokidar@3.5.3: + resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==} + engines: {node: '>= 8.10.0'} + dependencies: + anymatch: 3.1.3 + braces: 3.0.2 + glob-parent: 5.1.2 + is-binary-path: 2.1.0 + is-glob: 4.0.3 + normalize-path: 3.0.0 + readdirp: 3.6.0 + optionalDependencies: + fsevents: 2.3.2 + 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.7.0: + resolution: {integrity: sha512-qu3pN8Y3qHNgE2AFweciB1IfMnmZ/fsNTEE+NOFjmGB2F/7rLhnhzppvpCnN4FovtP26k8lHyy9ptEbNwWFLzw==} + engines: {node: '>=6'} + dev: true + + /cliui@6.0.0: + resolution: {integrity: sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==} + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 6.2.0 + dev: true + + /clone@1.0.4: + resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} + engines: {node: '>=0.8'} + dev: true + + /codem-isoboxer@0.3.6: + resolution: {integrity: sha512-LuO8/7LW6XuR5ERn1yavXAfodGRhuY2yP60JTZIw5yNYMCE5lUVbk3NFUCJxjnphQH+Xemp5hOGb1LgUXm00Xw==} + dev: true + + /color-convert@1.9.3: + resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} + dependencies: + color-name: 1.1.3 + dev: true + + /color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + dependencies: + color-name: 1.1.4 + dev: true + + /color-name@1.1.3: + resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} + dev: true + + /color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + dev: true + + /commander@2.20.3: + resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} + dev: true + + /commander@7.2.0: + resolution: {integrity: sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==} + engines: {node: '>= 10'} + dev: true + + /commander@8.3.0: + resolution: {integrity: sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==} + engines: {node: '>= 12'} + dev: true + + /commander@9.2.0: + resolution: {integrity: sha512-e2i4wANQiSXgnrBlIatyHtP1odfUp0BbV5Y5nEGbxtIrStkEOAAzCUirvLBNXHLr7kwLvJl6V+4V3XV9x7Wd9w==} + engines: {node: ^12.20.0 || >=14} + dev: true + + /comment-regex@1.0.1: + resolution: {integrity: sha512-IWlN//Yfby92tOIje7J18HkNmWRR7JESA/BK8W7wqY/akITpU5B0JQWnbTjCfdChSrDNb0DrdA9jfAxiiBXyiQ==} + engines: {node: '>=0.10.0'} + dev: true + + /common-tags@1.8.2: + resolution: {integrity: sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==} + engines: {node: '>=4.0.0'} + dev: true + + /concat-map@0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + dev: true + + /connect-history-api-fallback@2.0.0: + resolution: {integrity: sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==} + engines: {node: '>=0.8'} + dev: true + + /convert-source-map@1.9.0: + resolution: {integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==} + dev: true + + /core-js-compat@3.29.1: + resolution: {integrity: sha512-QmchCua884D8wWskMX8tW5ydINzd8oSJVx38lx/pVkFGqztxt73GYre3pm/hyYq8bPf+MW5In4I/uRShFDsbrA==} + dependencies: + browserslist: 4.21.5 + dev: true + + /core-js@3.29.1: + resolution: {integrity: sha512-+jwgnhg6cQxKYIIjGtAHq2nwUOolo9eoFZ4sHfUH09BLXBgxnH4gA0zEd+t+BO2cNB8idaBtZFcFTRjQJRJmAw==} + requiresBuild: true + dev: true + + /cose-base@1.0.3: + resolution: {integrity: sha512-s9whTXInMSgAp/NVXVNuVxVKzGH2qck3aQlVHxDCdAEPgtMKwc4Wq6/QKhgdEdgbLSi9rBTAcPoRa6JpiG4ksg==} + dependencies: + layout-base: 1.0.2 + dev: true + + /cose-base@2.2.0: + resolution: {integrity: sha512-AzlgcsCbUMymkADOJtQm3wO9S3ltPfYOFD5033keQn9NJzIbtnZj+UdBJe7DYml/8TdbtHJW3j58SOnKhWY/5g==} + dependencies: + layout-base: 2.0.1 + dev: true + + /cross-spawn@7.0.3: + resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} + engines: {node: '>= 8'} + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + dev: true + + /crypto-random-string@2.0.0: + resolution: {integrity: sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==} + engines: {node: '>=8'} + dev: true + + /css-select@5.1.0: + resolution: {integrity: sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==} + dependencies: + boolbase: 1.0.0 + css-what: 6.1.0 + domhandler: 5.0.3 + domutils: 3.0.1 + nth-check: 2.1.1 + dev: true + + /css-what@6.1.0: + resolution: {integrity: sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==} + engines: {node: '>= 6'} + dev: true + + /csstype@2.6.21: + resolution: {integrity: sha512-Z1PhmomIfypOpoMjRQB70jfvy/wxT50qW08YXO5lMIJkrdq4yOTR+AW7FqutScmB9NkLwxo+jU+kZLbofZZq/w==} + dev: true + + /custom-event-polyfill@1.0.7: + resolution: {integrity: sha512-TDDkd5DkaZxZFM8p+1I3yAlvM3rSr1wbrOliG4yJiwinMZN8z/iGL7BTlDkrJcYTmgUSb4ywVCc3ZaUtOtC76w==} + dev: true + + /cytoscape-cose-bilkent@4.1.0(cytoscape@3.23.0): + resolution: {integrity: sha512-wgQlVIUJF13Quxiv5e1gstZ08rnZj2XaLHGoFMYXz7SkNfCDOOteKBE6SYRfA9WxxI/iBc3ajfDoc6hb/MRAHQ==} + peerDependencies: + cytoscape: ^3.2.0 + dependencies: + cose-base: 1.0.3 + cytoscape: 3.23.0 + dev: true + + /cytoscape-fcose@2.2.0(cytoscape@3.23.0): + resolution: {integrity: sha512-ki1/VuRIHFCzxWNrsshHYPs6L7TvLu3DL+TyIGEsRcvVERmxokbf5Gdk7mFxZnTdiGtnA4cfSmjZJMviqSuZrQ==} + peerDependencies: + cytoscape: ^3.2.0 + dependencies: + cose-base: 2.2.0 + cytoscape: 3.23.0 + dev: true + + /cytoscape@3.23.0: + resolution: {integrity: sha512-gRZqJj/1kiAVPkrVFvz/GccxsXhF3Qwpptl32gKKypO4IlqnKBjTOu+HbXtEggSGzC5KCaHp3/F7GgENrtsFkA==} + engines: {node: '>=0.10'} + dependencies: + heap: 0.2.7 + lodash: 4.17.21 + dev: true + + /d3-array@3.2.3: + resolution: {integrity: sha512-JRHwbQQ84XuAESWhvIPaUV4/1UYTBOLiOPGWqgFDHZS1D5QN9c57FbH3QpEnQMYiOXNzKUQyGTZf+EVO7RT5TQ==} + engines: {node: '>=12'} + dependencies: + internmap: 2.0.3 + dev: true + + /d3-axis@3.0.0: + resolution: {integrity: sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw==} + engines: {node: '>=12'} + dev: true + + /d3-brush@3.0.0: + resolution: {integrity: sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ==} + engines: {node: '>=12'} + dependencies: + d3-dispatch: 3.0.1 + d3-drag: 3.0.0 + d3-interpolate: 3.0.1 + d3-selection: 3.0.0 + d3-transition: 3.0.1(d3-selection@3.0.0) + dev: true + + /d3-chord@3.0.1: + resolution: {integrity: sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g==} + engines: {node: '>=12'} + dependencies: + d3-path: 3.1.0 + dev: true + + /d3-color@3.1.0: + resolution: {integrity: sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==} + engines: {node: '>=12'} + dev: true + + /d3-contour@4.0.2: + resolution: {integrity: sha512-4EzFTRIikzs47RGmdxbeUvLWtGedDUNkTcmzoeyg4sP/dvCexO47AaQL7VKy/gul85TOxw+IBgA8US2xwbToNA==} + engines: {node: '>=12'} + dependencies: + d3-array: 3.2.3 + dev: true + + /d3-delaunay@6.0.3: + resolution: {integrity: sha512-1gPbiMuikAgU/rFcT6WMu17zx0aelw9Hh80go7/TwZQ+/uq8DqqmiNYy+EqPEvTSp/BkJFIpQxjac4Gk/w0zOg==} + engines: {node: '>=12'} + dependencies: + delaunator: 5.0.0 + dev: true + + /d3-dispatch@3.0.1: + resolution: {integrity: sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==} + engines: {node: '>=12'} + dev: true + + /d3-drag@3.0.0: + resolution: {integrity: sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==} + engines: {node: '>=12'} + dependencies: + d3-dispatch: 3.0.1 + d3-selection: 3.0.0 + dev: true + + /d3-dsv@3.0.1: + resolution: {integrity: sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q==} + engines: {node: '>=12'} + dependencies: + commander: 7.2.0 + iconv-lite: 0.6.3 + rw: 1.3.3 + dev: true + + /d3-ease@3.0.1: + resolution: {integrity: sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==} + engines: {node: '>=12'} + dev: true + + /d3-fetch@3.0.1: + resolution: {integrity: sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw==} + engines: {node: '>=12'} + dependencies: + d3-dsv: 3.0.1 + dev: true + + /d3-force@3.0.0: + resolution: {integrity: sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==} + engines: {node: '>=12'} + dependencies: + d3-dispatch: 3.0.1 + d3-quadtree: 3.0.1 + d3-timer: 3.0.1 + dev: true + + /d3-format@3.1.0: + resolution: {integrity: sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==} + engines: {node: '>=12'} + dev: true + + /d3-geo@3.1.0: + resolution: {integrity: sha512-JEo5HxXDdDYXCaWdwLRt79y7giK8SbhZJbFWXqbRTolCHFI5jRqteLzCsq51NKbUoX0PjBVSohxrx+NoOUujYA==} + engines: {node: '>=12'} + dependencies: + d3-array: 3.2.3 + dev: true + + /d3-hierarchy@3.1.2: + resolution: {integrity: sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA==} + engines: {node: '>=12'} + dev: true + + /d3-interpolate@3.0.1: + resolution: {integrity: sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==} + engines: {node: '>=12'} + dependencies: + d3-color: 3.1.0 + dev: true + + /d3-path@3.1.0: + resolution: {integrity: sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==} + engines: {node: '>=12'} + dev: true + + /d3-polygon@3.0.1: + resolution: {integrity: sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg==} + engines: {node: '>=12'} + dev: true + + /d3-quadtree@3.0.1: + resolution: {integrity: sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==} + engines: {node: '>=12'} + dev: true + + /d3-random@3.0.1: + resolution: {integrity: sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ==} + engines: {node: '>=12'} + dev: true + + /d3-scale-chromatic@3.0.0: + resolution: {integrity: sha512-Lx9thtxAKrO2Pq6OO2Ua474opeziKr279P/TKZsMAhYyNDD3EnCffdbgeSYN5O7m2ByQsxtuP2CSDczNUIZ22g==} + engines: {node: '>=12'} + dependencies: + d3-color: 3.1.0 + d3-interpolate: 3.0.1 + dev: true + + /d3-scale@4.0.2: + resolution: {integrity: sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==} + engines: {node: '>=12'} + dependencies: + d3-array: 3.2.3 + d3-format: 3.1.0 + d3-interpolate: 3.0.1 + d3-time: 3.1.0 + d3-time-format: 4.1.0 + dev: true + + /d3-selection@3.0.0: + resolution: {integrity: sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==} + engines: {node: '>=12'} + dev: true + + /d3-shape@3.2.0: + resolution: {integrity: sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==} + engines: {node: '>=12'} + dependencies: + d3-path: 3.1.0 + dev: true + + /d3-time-format@4.1.0: + resolution: {integrity: sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==} + engines: {node: '>=12'} + dependencies: + d3-time: 3.1.0 + dev: true + + /d3-time@3.1.0: + resolution: {integrity: sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==} + engines: {node: '>=12'} + dependencies: + d3-array: 3.2.3 + dev: true + + /d3-timer@3.0.1: + resolution: {integrity: sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==} + engines: {node: '>=12'} + dev: true + + /d3-transition@3.0.1(d3-selection@3.0.0): + resolution: {integrity: sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==} + engines: {node: '>=12'} + peerDependencies: + d3-selection: 2 - 3 + dependencies: + d3-color: 3.1.0 + d3-dispatch: 3.0.1 + d3-ease: 3.0.1 + d3-interpolate: 3.0.1 + d3-selection: 3.0.0 + d3-timer: 3.0.1 + dev: true + + /d3-zoom@3.0.0: + resolution: {integrity: sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==} + engines: {node: '>=12'} + dependencies: + d3-dispatch: 3.0.1 + d3-drag: 3.0.0 + d3-interpolate: 3.0.1 + d3-selection: 3.0.0 + d3-transition: 3.0.1(d3-selection@3.0.0) + dev: true + + /d3@7.8.3: + resolution: {integrity: sha512-cAa866AkPXtt4IzRx6nzGf50uerq6VYks7p/tTH94be4QfhUkyTfJfaxXGPOB5ZRVUZmUV1wcM1dism/Ua0lCw==} + engines: {node: '>=12'} + dependencies: + d3-array: 3.2.3 + d3-axis: 3.0.0 + d3-brush: 3.0.0 + d3-chord: 3.0.1 + d3-color: 3.1.0 + d3-contour: 4.0.2 + d3-delaunay: 6.0.3 + d3-dispatch: 3.0.1 + d3-drag: 3.0.0 + d3-dsv: 3.0.1 + d3-ease: 3.0.1 + d3-fetch: 3.0.1 + d3-force: 3.0.0 + d3-format: 3.1.0 + d3-geo: 3.1.0 + d3-hierarchy: 3.1.2 + d3-interpolate: 3.0.1 + d3-path: 3.1.0 + d3-polygon: 3.0.1 + d3-quadtree: 3.0.1 + d3-random: 3.0.1 + d3-scale: 4.0.2 + d3-scale-chromatic: 3.0.0 + d3-selection: 3.0.0 + d3-shape: 3.2.0 + d3-time: 3.1.0 + d3-time-format: 4.1.0 + d3-timer: 3.0.1 + d3-transition: 3.0.1(d3-selection@3.0.0) + d3-zoom: 3.0.0 + dev: true + + /dagre-d3-es@7.0.9: + resolution: {integrity: sha512-rYR4QfVmy+sR44IBDvVtcAmOReGBvRCWDpO2QjYwqgh9yijw6eSHBqaPG/LIOEy7aBsniLvtMW6pg19qJhq60w==} + dependencies: + d3: 7.8.3 + lodash-es: 4.17.21 + dev: true + + /dashjs@4.6.0: + resolution: {integrity: sha512-0PDoSBM9PXb+Io0pRnw2CmO7aV9W8FC/BqBRNhLxzM3/e5Kfj7BLy0OWkkSB58ULg6Md6r+6jkGOTUhut/35rg==} + dependencies: + bcp-47-match: 1.0.3 + bcp-47-normalize: 1.1.1 + codem-isoboxer: 0.3.6 + es6-promise: 4.2.8 + fast-deep-equal: 2.0.1 + html-entities: 1.4.0 + imsc: 1.1.3 + localforage: 1.10.0 + path-browserify: 1.0.1 + ua-parser-js: 1.0.34 + dev: true + + /dayjs@1.11.7: + resolution: {integrity: sha512-+Yw9U6YO5TQohxLcIkrXBeY73WP3ejHWVvx8XCk3gxvQDCTEmS48ZrSZCKciI7Bhl/uCMyxYtE9UqRILmFphkQ==} + dev: true + + /debug@4.3.4: + resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.1.2 + dev: true + + /decamelize@1.2.0: + resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==} + engines: {node: '>=0.10.0'} + dev: true + + /deepmerge@4.3.1: + resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} + engines: {node: '>=0.10.0'} + dev: true + + /defaults@1.0.4: + resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==} + dependencies: + clone: 1.0.4 + dev: true + + /define-properties@1.2.0: + resolution: {integrity: sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==} + engines: {node: '>= 0.4'} + dependencies: + has-property-descriptors: 1.0.0 + object-keys: 1.1.1 + dev: true + + /delaunator@5.0.0: + resolution: {integrity: sha512-AyLvtyJdbv/U1GkiS6gUUzclRoAY4Gs75qkMygJJhU75LW4DNuSF2RMzpxs9jw9Oz1BobHjTdkG3zdP55VxAqw==} + dependencies: + robust-predicates: 3.0.1 + dev: true + + /dijkstrajs@1.0.2: + resolution: {integrity: sha512-QV6PMaHTCNmKSeP6QoXhVTw9snc9VD8MulTT0Bd99Pacp4SS1cjcrYPgBPmibqKVtMJJfqC6XvOXgPMEEPH/fg==} + dev: true + + /dir-glob@3.0.1: + resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} + engines: {node: '>=8'} + dependencies: + path-type: 4.0.0 + dev: true + + /dom-serializer@2.0.0: + resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==} + dependencies: + domelementtype: 2.3.0 + domhandler: 5.0.3 + entities: 4.4.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 + + /dompurify@2.4.3: + resolution: {integrity: sha512-q6QaLcakcRjebxjg8/+NP+h0rPfatOgOzc46Fst9VAA3jF2ApfKBNKMzdP4DYTqtUMXSCd5pRS/8Po/OmoCHZQ==} + dev: true + + /domutils@3.0.1: + resolution: {integrity: sha512-z08c1l761iKhDFtfXO04C7kTdPBLi41zwOZl00WS8b5eiaebNpY00HKbztwBq+e3vyqWNwWF3mP9YLUeqIrF+Q==} + dependencies: + dom-serializer: 2.0.0 + domelementtype: 2.3.0 + domhandler: 5.0.3 + dev: true + + /echarts@5.4.2: + resolution: {integrity: sha512-2W3vw3oI2tWJdyAz+b8DuWS0nfXtSDqlDmqgin/lfzbkB01cuMEN66KWBlmur3YMp5nEDEEt5s23pllnAzB4EA==} + dependencies: + tslib: 2.3.0 + zrender: 5.4.3 + dev: true + + /ejs@3.1.9: + resolution: {integrity: sha512-rC+QVNMJWv+MtPgkt0y+0rVEIdbtxVADApW9JXrUVlzHetgcyczP/E7DJmWJ4fJCZF2cPcBk0laWO9ZHMG3DmQ==} + engines: {node: '>=0.10.0'} + dependencies: + jake: 10.8.5 + dev: true + + /electron-to-chromium@1.4.342: + resolution: {integrity: sha512-dTei3VResi5bINDENswBxhL+N0Mw5YnfWyTqO75KGsVldurEkhC9+CelJVAse8jycWyP8pv3VSj4BSyP8wTWJA==} + dev: true + + /elkjs@0.8.2: + resolution: {integrity: sha512-L6uRgvZTH+4OF5NE/MBbzQx/WYpru1xCBE9respNj6qznEewGUIfhzmm7horWWxbNO2M0WckQypGctR8lH79xQ==} + dev: true + + /emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + dev: true + + /encode-utf8@1.0.3: + resolution: {integrity: sha512-ucAnuBEhUK4boH2HjVYG5Q2mQyPorvv0u/ocS+zhdw0S8AlHYY+GOFhP1Gio5z4icpP2ivFSvhtFjQi8+T9ppw==} + dev: true + + /entities@3.0.1: + resolution: {integrity: sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==} + engines: {node: '>=0.12'} + dev: true + + /entities@4.4.0: + resolution: {integrity: sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA==} + engines: {node: '>=0.12'} + dev: true + + /envinfo@7.8.1: + resolution: {integrity: sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw==} + engines: {node: '>=4'} + dev: true + + /es-abstract@1.21.2: + resolution: {integrity: sha512-y/B5POM2iBnIxCiernH1G7rC9qQoM77lLIMQLuob0zhp8C56Po81+2Nj0WFKnd0pNReDTnkYryc+zhOzpEIROg==} + engines: {node: '>= 0.4'} + dependencies: + array-buffer-byte-length: 1.0.0 + available-typed-arrays: 1.0.5 + call-bind: 1.0.2 + es-set-tostringtag: 2.0.1 + es-to-primitive: 1.2.1 + function.prototype.name: 1.1.5 + get-intrinsic: 1.2.0 + get-symbol-description: 1.0.0 + globalthis: 1.0.3 + gopd: 1.0.1 + has: 1.0.3 + has-property-descriptors: 1.0.0 + has-proto: 1.0.1 + has-symbols: 1.0.3 + internal-slot: 1.0.5 + is-array-buffer: 3.0.2 + is-callable: 1.2.7 + is-negative-zero: 2.0.2 + is-regex: 1.1.4 + is-shared-array-buffer: 1.0.2 + is-string: 1.0.7 + is-typed-array: 1.1.10 + is-weakref: 1.0.2 + object-inspect: 1.12.3 + object-keys: 1.1.1 + object.assign: 4.1.4 + regexp.prototype.flags: 1.4.3 + safe-regex-test: 1.0.0 + string.prototype.trim: 1.2.7 + string.prototype.trimend: 1.0.6 + string.prototype.trimstart: 1.0.6 + typed-array-length: 1.0.4 + unbox-primitive: 1.0.2 + which-typed-array: 1.1.9 + dev: true + + /es-set-tostringtag@2.0.1: + resolution: {integrity: sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==} + engines: {node: '>= 0.4'} + dependencies: + get-intrinsic: 1.2.0 + has: 1.0.3 + has-tostringtag: 1.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 + + /es6-promise@4.2.8: + resolution: {integrity: sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==} + dev: true + + /esbuild@0.16.17: + resolution: {integrity: sha512-G8LEkV0XzDMNwXKgM0Jwu3nY3lSTwSGY6XbxM9cr9+s0T/qSV1q1JVPBGzm3dcjhCic9+emZDmMffkwgPeOeLg==} + engines: {node: '>=12'} + requiresBuild: true + optionalDependencies: + '@esbuild/android-arm': 0.16.17 + '@esbuild/android-arm64': 0.16.17 + '@esbuild/android-x64': 0.16.17 + '@esbuild/darwin-arm64': 0.16.17 + '@esbuild/darwin-x64': 0.16.17 + '@esbuild/freebsd-arm64': 0.16.17 + '@esbuild/freebsd-x64': 0.16.17 + '@esbuild/linux-arm': 0.16.17 + '@esbuild/linux-arm64': 0.16.17 + '@esbuild/linux-ia32': 0.16.17 + '@esbuild/linux-loong64': 0.16.17 + '@esbuild/linux-mips64el': 0.16.17 + '@esbuild/linux-ppc64': 0.16.17 + '@esbuild/linux-riscv64': 0.16.17 + '@esbuild/linux-s390x': 0.16.17 + '@esbuild/linux-x64': 0.16.17 + '@esbuild/netbsd-x64': 0.16.17 + '@esbuild/openbsd-x64': 0.16.17 + '@esbuild/sunos-x64': 0.16.17 + '@esbuild/win32-arm64': 0.16.17 + '@esbuild/win32-ia32': 0.16.17 + '@esbuild/win32-x64': 0.16.17 + 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 + + /esm@3.2.25: + resolution: {integrity: sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA==} + engines: {node: '>=6'} + dev: true + + /esprima@4.0.1: + resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} + engines: {node: '>=4'} + dev: true + + /estree-walker@1.0.1: + resolution: {integrity: sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==} + 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 + + /eve-raphael@0.5.0: + resolution: {integrity: sha512-jrxnPsCGqng1UZuEp9DecX/AuSyAszATSjf4oEcRxvfxa1Oux4KkIPKBAAWWnpdwfARtr+Q0o9aPYWjsROD7ug==} + dev: true + + /execa@7.1.1: + resolution: {integrity: sha512-wH0eMf/UXckdUYnO21+HDztteVv05rq2GXksxT4fCGeHkBhw1DROXh40wcjMcRqDOWE7iPJ4n3M7e2+YFP+76Q==} + engines: {node: ^14.18.0 || ^16.14.0 || >=18.0.0} + dependencies: + cross-spawn: 7.0.3 + get-stream: 6.0.1 + human-signals: 4.3.1 + is-stream: 3.0.0 + merge-stream: 2.0.0 + npm-run-path: 5.1.0 + onetime: 6.0.0 + signal-exit: 3.0.7 + strip-final-newline: 3.0.0 + dev: true + + /extend-shallow@2.0.1: + resolution: {integrity: sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==} + engines: {node: '>=0.10.0'} + dependencies: + is-extendable: 0.1.1 + dev: true + + /fast-deep-equal@2.0.1: + resolution: {integrity: sha512-bCK/2Z4zLidyB4ReuIsvALH6w31YfAQDmXMqMx6FyfHqvBxtjC0eRumeSu4Bs3XtXwpyIywtSTrVT99BxY1f9w==} + dev: true + + /fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + dev: true + + /fast-glob@3.2.12: + resolution: {integrity: sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==} + engines: {node: '>=8.6.0'} + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.5 + dev: true + + /fast-json-stable-stringify@2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + dev: true + + /fastq@1.15.0: + resolution: {integrity: sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==} + dependencies: + reusify: 1.0.4 + dev: true + + /fflate@0.7.4: + resolution: {integrity: sha512-5u2V/CDW15QM1XbbgS+0DfPxVB+jUKhWEKuuFuHncbk3tEEqzmoXL+2KyOFuKGqOnmdIy0/davWF1CkuwtibCw==} + dev: true + + /filelist@1.0.4: + resolution: {integrity: sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==} + dependencies: + minimatch: 5.1.6 + dev: true + + /fill-range@7.0.1: + resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} + engines: {node: '>=8'} + dependencies: + to-regex-range: 5.0.1 + dev: true + + /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 + + /flowchart.ts@0.1.2: + resolution: {integrity: sha512-4N8U2gXTkWUYh57SkCYwnSBM2B9Djia+JjClx/rLA13m0xz2S5BZht/9DvTZH5yXGZkmk7NGxGB15tnbUSI6mg==} + dependencies: + '@types/raphael': 2.3.3 + raphael: 2.3.0 + tslib: 2.4.1 + dev: true + + /for-each@0.3.3: + resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} + dependencies: + is-callable: 1.2.7 + dev: true + + /fraction.js@4.2.0: + resolution: {integrity: sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==} + dev: true + + /fs-extra@11.1.1: + resolution: {integrity: sha512-MGIE4HOvQCeUCzmlHs0vXpih4ysz4wg9qiSAu6cd42lVwPbTM1TjV7RusoyQqMmk/95gdQZX72u+YW+c3eEpFQ==} + engines: {node: '>=14.14'} + dependencies: + graceful-fs: 4.2.11 + jsonfile: 6.1.0 + universalify: 2.0.0 + dev: true + + /fs-extra@9.1.0: + resolution: {integrity: sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==} + engines: {node: '>=10'} + dependencies: + at-least-node: 1.0.0 + graceful-fs: 4.2.11 + jsonfile: 6.1.0 + universalify: 2.0.0 + dev: true + + /fs.realpath@1.0.0: + resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + dev: true + + /fsevents@2.3.2: + resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /function-bind@1.1.1: + resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==} + dev: true + + /function.prototype.name@1.1.5: + resolution: {integrity: sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + define-properties: 1.2.0 + es-abstract: 1.21.2 + 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.0: + resolution: {integrity: sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==} + dependencies: + function-bind: 1.1.1 + has: 1.0.3 + has-symbols: 1.0.3 + dev: true + + /get-own-enumerable-property-symbols@3.0.2: + resolution: {integrity: sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==} + dev: true + + /get-stream@6.0.1: + resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} + engines: {node: '>=10'} + dev: true + + /get-symbol-description@1.0.0: + resolution: {integrity: sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + get-intrinsic: 1.2.0 + dev: true + + /giscus@1.2.8: + resolution: {integrity: sha512-pufrgQYt1W+4ztiWp/PilLPN8NdyKvpbQ8jNqbAa1g84t6qqyevXHfkOYCi4x4d+y191vJAUc6seL1Dq74yUeA==} + dependencies: + lit: 2.7.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@7.2.3: + resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.2 + once: 1.4.0 + path-is-absolute: 1.0.1 + dev: true + + /globals@11.12.0: + resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} + engines: {node: '>=4'} + dev: true + + /globalthis@1.0.3: + resolution: {integrity: sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==} + engines: {node: '>= 0.4'} + dependencies: + define-properties: 1.2.0 + dev: true + + /globby@13.1.3: + resolution: {integrity: sha512-8krCNHXvlCgHDpegPzleMq07yMYTO2sXKASmZmquEYWEmCx6J5UTRbp5RwMJkTJGtcQ44YpiUYUiN0b9mzy8Bw==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + dir-glob: 3.0.1 + fast-glob: 3.2.12 + ignore: 5.2.4 + merge2: 1.4.1 + slash: 4.0.0 + dev: true + + /gopd@1.0.1: + resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} + dependencies: + get-intrinsic: 1.2.0 + dev: true + + /graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + dev: true + + /gray-matter@4.0.3: + resolution: {integrity: sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==} + engines: {node: '>=6.0'} + dependencies: + js-yaml: 3.14.1 + kind-of: 6.0.3 + section-matter: 1.0.0 + strip-bom-string: 1.0.0 + dev: true + + /hanabi@0.4.0: + resolution: {integrity: sha512-ixJH94fwmmVzUSdxl7TMkVZJmsq4d2JKrxedpM5V1V+91iVHL0q6NnJi4xiDahK6Vo00xT17H8H6b4F6RVbsOg==} + dependencies: + comment-regex: 1.0.1 + dev: true + + /has-bigints@1.0.2: + resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} + dev: true + + /has-flag@3.0.0: + resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} + engines: {node: '>=4'} + dev: true + + /has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + dev: true + + /has-property-descriptors@1.0.0: + resolution: {integrity: sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==} + dependencies: + get-intrinsic: 1.2.0 + dev: true + + /has-proto@1.0.1: + resolution: {integrity: sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==} + engines: {node: '>= 0.4'} + dev: true + + /has-symbols@1.0.3: + resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} + engines: {node: '>= 0.4'} + dev: true + + /has-tostringtag@1.0.0: + resolution: {integrity: sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==} + engines: {node: '>= 0.4'} + dependencies: + has-symbols: 1.0.3 + dev: true + + /has@1.0.3: + resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==} + engines: {node: '>= 0.4.0'} + dependencies: + function-bind: 1.1.1 + dev: true + + /hash-sum@2.0.0: + resolution: {integrity: sha512-WdZTbAByD+pHfl/g9QSsBIIwy8IT+EsPiKDs0KNX+zSHhdDLFKdZu0BQHljvO+0QI/BasbMSUa8wYNCZTvhslg==} + dev: true + + /he@0.5.0: + resolution: {integrity: sha512-DoufbNNOFzwRPy8uecq+j+VCPQ+JyDelHTmSgygrA5TsR8Cbw4Qcir5sGtWiusB4BdT89nmlaVDhSJOqC/33vw==} + dev: true + + /heap@0.2.7: + resolution: {integrity: sha512-2bsegYkkHO+h/9MGbn6KWcE45cHZgPANo5LXF7EvWdT0yT2EguSVO1nDgU5c8+ZOPwp2vMNa7YFsJhVcDR9Sdg==} + dev: true + + /hls.js@1.3.5: + resolution: {integrity: sha512-uybAvKS6uDe0MnWNEPnO0krWVr+8m2R0hJ/viql8H3MVK+itq8gGQuIYoFHL3rECkIpNH98Lw8YuuWMKZxp3Ew==} + dev: true + + /html-entities@1.4.0: + resolution: {integrity: sha512-8nxjcBcd8wovbeKx7h3wTji4e6+rhaVuPNpMqwWgnHh+N9ToqsCs6XztWRBPQ+UtzsoMAdKZtUENoVzU/EMtZA==} + dev: true + + /htmlparser2@8.0.2: + resolution: {integrity: sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==} + dependencies: + domelementtype: 2.3.0 + domhandler: 5.0.3 + domutils: 3.0.1 + entities: 4.4.0 + dev: true + + /human-signals@4.3.1: + resolution: {integrity: sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==} + engines: {node: '>=14.18.0'} + dev: true + + /iconv-lite@0.6.3: + resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} + engines: {node: '>=0.10.0'} + dependencies: + safer-buffer: 2.1.2 + dev: true + + /idb@7.1.1: + resolution: {integrity: sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ==} + dev: true + + /ieee754@1.2.1: + resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} + dev: true + + /ignore@5.2.4: + resolution: {integrity: sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==} + engines: {node: '>= 4'} + dev: true + + /immediate@3.0.6: + resolution: {integrity: sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==} + dev: true + + /immutable@4.3.0: + resolution: {integrity: sha512-0AOCmOip+xgJwEVTQj1EfiDDOkPmuyllDuTuEX+DDXUgapLAsBIfkg3sxCYyCEA8mQqZrrxPUGjcOQ2JS3WLkg==} + dev: true + + /imsc@1.1.3: + resolution: {integrity: sha512-IY0hMkVTNoqoYwKEp5UvNNKp/A5jeJUOrIO7judgOyhHT+xC6PA4VBOMAOhdtAYbMRHx9DTgI8p6Z6jhYQPFDA==} + dependencies: + sax: 1.2.1 + dev: true + + /inflight@1.0.6: + resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + dependencies: + once: 1.4.0 + wrappy: 1.0.2 + dev: true + + /inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + dev: true + + /insane@2.6.2: + resolution: {integrity: sha512-BqEL1CJsjJi+/C/zKZxv31zs3r6zkLH5Nz1WMFb7UBX2KHY2yXDpbFTSEmNHzomBbGDysIfkTX55A0mQZ2CQiw==} + dependencies: + assignment: 2.0.0 + he: 0.5.0 + dev: true + + /internal-slot@1.0.5: + resolution: {integrity: sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==} + engines: {node: '>= 0.4'} + dependencies: + get-intrinsic: 1.2.0 + has: 1.0.3 + side-channel: 1.0.4 + dev: true + + /internmap@2.0.3: + resolution: {integrity: sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==} + engines: {node: '>=12'} + dev: true + + /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-array-buffer@3.0.2: + resolution: {integrity: sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==} + dependencies: + call-bind: 1.0.2 + get-intrinsic: 1.2.0 + is-typed-array: 1.1.10 + dev: true + + /is-bigint@1.0.4: + resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==} + dependencies: + has-bigints: 1.0.2 + dev: true + + /is-binary-path@2.1.0: + resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} + engines: {node: '>=8'} + dependencies: + binary-extensions: 2.2.0 + dev: true + + /is-boolean-object@1.1.2: + resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + has-tostringtag: 1.0.0 + dev: true + + /is-callable@1.2.7: + resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} + engines: {node: '>= 0.4'} + dev: true + + /is-core-module@2.11.0: + resolution: {integrity: sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==} + dependencies: + has: 1.0.3 + 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-extendable@0.1.1: + resolution: {integrity: sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==} + engines: {node: '>=0.10.0'} + dev: true + + /is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + dev: true + + /is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + dev: true + + /is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + dependencies: + is-extglob: 2.1.1 + dev: true + + /is-interactive@2.0.0: + resolution: {integrity: sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==} + engines: {node: '>=12'} + dev: true + + /is-module@1.0.0: + resolution: {integrity: sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==} + dev: true + + /is-negative-zero@2.0.2: + resolution: {integrity: sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==} + engines: {node: '>= 0.4'} + dev: true + + /is-number-object@1.0.7: + resolution: {integrity: sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==} + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: 1.0.0 + dev: true + + /is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + dev: true + + /is-obj@1.0.1: + resolution: {integrity: sha512-l4RyHgRqGN4Y3+9JHVrNqO+tN0rV5My76uW5/nuO4K1b6vw5G8d/cmFjP9tRfEsdhZNt0IFdZuK/c2Vr4Nb+Qg==} + engines: {node: '>=0.10.0'} + dev: true + + /is-regex@1.1.4: + resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + has-tostringtag: 1.0.0 + dev: true + + /is-regexp@1.0.0: + resolution: {integrity: sha512-7zjFAPO4/gwyQAAgRRmqeEeyIICSdmCqa3tsVHMdBzaXXRiqopZL4Cyghg/XulGWrtABTpbnYYzzIRffLkP4oA==} + engines: {node: '>=0.10.0'} + dev: true + + /is-shared-array-buffer@1.0.2: + resolution: {integrity: sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==} + dependencies: + call-bind: 1.0.2 + dev: true + + /is-stream@2.0.1: + resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} + engines: {node: '>=8'} + dev: true + + /is-stream@3.0.0: + resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dev: true + + /is-string@1.0.7: + resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==} + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: 1.0.0 + dev: true + + /is-symbol@1.0.4: + resolution: {integrity: sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==} + engines: {node: '>= 0.4'} + dependencies: + has-symbols: 1.0.3 + dev: true + + /is-typed-array@1.1.10: + resolution: {integrity: sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==} + engines: {node: '>= 0.4'} + dependencies: + available-typed-arrays: 1.0.5 + call-bind: 1.0.2 + for-each: 0.3.3 + gopd: 1.0.1 + has-tostringtag: 1.0.0 + dev: true + + /is-unicode-supported@1.3.0: + resolution: {integrity: sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==} + engines: {node: '>=12'} + dev: true + + /is-weakref@1.0.2: + resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==} + dependencies: + call-bind: 1.0.2 + dev: true + + /isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + dev: true + + /jake@10.8.5: + resolution: {integrity: sha512-sVpxYeuAhWt0OTWITwT98oyV0GsXyMlXCF+3L1SuafBVUIr/uILGRB+NqwkzhgXKvoJpDIpQvqkUALgdmQsQxw==} + engines: {node: '>=10'} + dependencies: + async: 3.2.4 + chalk: 4.1.2 + filelist: 1.0.4 + minimatch: 3.1.2 + dev: true + + /jest-worker@26.6.2: + resolution: {integrity: sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==} + engines: {node: '>= 10.13.0'} + dependencies: + '@types/node': 18.15.11 + merge-stream: 2.0.0 + supports-color: 7.2.0 + 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==} + dependencies: + argparse: 1.0.10 + esprima: 4.0.1 + dev: true + + /jsesc@0.5.0: + resolution: {integrity: sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==} + dev: true + + /jsesc@2.5.2: + resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==} + engines: {node: '>=4'} + dev: true + + /json-schema-traverse@1.0.0: + resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} + dev: true + + /json-schema@0.4.0: + resolution: {integrity: sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==} + dev: true + + /json5@2.2.3: + resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} + engines: {node: '>=6'} + dev: true + + /jsonfile@6.1.0: + resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} + dependencies: + universalify: 2.0.0 + optionalDependencies: + graceful-fs: 4.2.11 + dev: true + + /jsonpointer@5.0.1: + resolution: {integrity: sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==} + engines: {node: '>=0.10.0'} + dev: true + + /katex@0.16.4: + resolution: {integrity: sha512-WudRKUj8yyBeVDI4aYMNxhx5Vhh2PjpzQw1GRu/LVGqL4m1AxwD1GcUp0IMbdJaf5zsjtj8ghP0DOQRYhroNkw==} + dependencies: + commander: 8.3.0 + dev: true + + /khroma@2.0.0: + resolution: {integrity: sha512-2J8rDNlQWbtiNYThZRvmMv5yt44ZakX+Tz5ZIp/mN1pt4snn+m030Va5Z4v8xA0cQFDXBwO/8i42xL4QPsVk3g==} + dev: true + + /kind-of@6.0.3: + resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} + engines: {node: '>=0.10.0'} + dev: true + + /layout-base@1.0.2: + resolution: {integrity: sha512-8h2oVEZNktL4BH2JCOI90iD1yXwL6iNW7KcCKT2QZgQJR2vbqDsldCTPRU9NifTCqHZci57XvQQ15YTu+sTYPg==} + dev: true + + /layout-base@2.0.1: + resolution: {integrity: sha512-dp3s92+uNI1hWIpPGH3jK2kxE2lMjdXdr+DH8ynZHpd6PUlH6x6cbuXnoMmiNumznqaNO31xu9e79F0uuZ0JFg==} + dev: true + + /leven@3.1.0: + resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==} + engines: {node: '>=6'} + dev: true + + /lie@3.1.1: + resolution: {integrity: sha512-RiNhHysUjhrDQntfYSfY4MU24coXXdEOgw9WGcKHNeEwffDYbF//u87M1EWaMGzuFoSbqW0C9C6lEEhDOAswfw==} + dependencies: + immediate: 3.0.6 + dev: true + + /lilconfig@2.1.0: + resolution: {integrity: sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==} + engines: {node: '>=10'} + dev: true + + /linkify-it@4.0.1: + resolution: {integrity: sha512-C7bfi1UZmoj8+PQx22XyeXCuBlokoyWQL5pWSP+EI6nzRylyThouddufc2c1NDIcP9k5agmN9fLpA7VNJfIiqw==} + dependencies: + uc.micro: 1.0.6 + dev: true + + /lit-element@3.3.0: + resolution: {integrity: sha512-M3OIoblNS7LZdRxOIk8g0wyLEA/lRw/UGJ1TX+767OpkuDsRdSoxBIvewpWqCo7sMd9xt1XedUNZIr9jUO1X3g==} + dependencies: + '@lit-labs/ssr-dom-shim': 1.1.0 + '@lit/reactive-element': 1.6.1 + lit-html: 2.7.0 + dev: true + + /lit-html@2.7.0: + resolution: {integrity: sha512-/zPOl8EfeB3HHpTzINSpnWgvgQ8N07g/j272EOAIyB0Ys2RzBqTVT23i+JZuUlNbB2WHHeSsTCFi92NtWrtpqQ==} + dependencies: + '@types/trusted-types': 2.0.3 + dev: true + + /lit@2.7.0: + resolution: {integrity: sha512-qSy2BAVA+OiWtNptP404egcC/izDdNRw6iHGIbUmkZtbMJvPKfNsaoKrNs8Zmsbjmv5ZX2tur1l9TfzkSWWT4g==} + dependencies: + '@lit/reactive-element': 1.6.1 + lit-element: 3.3.0 + lit-html: 2.7.0 + dev: true + + /loadjs@4.2.0: + resolution: {integrity: sha512-AgQGZisAlTPbTEzrHPb6q+NYBMD+DP9uvGSIjSUM5uG+0jG15cb8axWpxuOIqrmQjn6scaaH8JwloiP27b2KXA==} + dev: true + + /localforage@1.10.0: + resolution: {integrity: sha512-14/H1aX7hzBBmmh7sGPd+AOMkkIrHM3Z1PAyGgZigA1H1p5O5ANnMyWzvpAETtG68/dC4pC0ncy3+PPGzXZHPg==} + dependencies: + lie: 3.1.1 + dev: true + + /locate-path@5.0.0: + resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} + engines: {node: '>=8'} + dependencies: + p-locate: 4.1.0 + dev: true + + /lodash-es@4.17.21: + resolution: {integrity: sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==} + dev: true + + /lodash.debounce@4.0.8: + resolution: {integrity: sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==} + dev: true + + /lodash.sortby@4.7.0: + resolution: {integrity: sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==} + dev: true + + /lodash@4.17.21: + resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + dev: true + + /log-symbols@5.1.0: + resolution: {integrity: sha512-l0x2DvrW294C9uDCoQe1VSU4gf529FkSZ6leBl4TiqZH/e+0R7hSfHQBNut2mNygDgHwvYHfFLn6Oxb3VWj2rA==} + engines: {node: '>=12'} + dependencies: + chalk: 5.2.0 + is-unicode-supported: 1.3.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 + + /magic-string@0.25.9: + resolution: {integrity: sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==} + dependencies: + sourcemap-codec: 1.4.8 + dev: true + + /markdown-it-anchor@8.6.7(@types/markdown-it@12.2.3)(markdown-it@13.0.1): + resolution: {integrity: sha512-FlCHFwNnutLgVTflOYHPW2pPcl2AACqVzExlkGQNsi4CJgqOHN7YTgDd4LuhgN1BFO3TS0vLAruV1Td6dwWPJA==} + peerDependencies: + '@types/markdown-it': '*' + markdown-it: '*' + dependencies: + '@types/markdown-it': 12.2.3 + markdown-it: 13.0.1 + dev: true + + /markdown-it-container@3.0.0: + resolution: {integrity: sha512-y6oKTq4BB9OQuY/KLfk/O3ysFhB3IMYoIWhGJEidXt1NQFocFK2sA2t0NYZAMyMShAGL6x5OPIbrmXPIqaN9rw==} + dev: true + + /markdown-it-emoji@2.0.2: + resolution: {integrity: sha512-zLftSaNrKuYl0kR5zm4gxXjHaOI3FAOEaloKmRA5hijmJZvSjmxcokOLlzycb/HXlUFWzXqpIEoyEMCE4i9MvQ==} + dev: true + + /markdown-it@13.0.1: + resolution: {integrity: sha512-lTlxriVoy2criHP0JKRhO2VDG9c2ypWCsT237eDiLqi09rmbKoUetyGHq2uOIRoRS//kfoJckS0eUzzkDR+k2Q==} + dependencies: + argparse: 2.0.1 + entities: 3.0.1 + linkify-it: 4.0.1 + mdurl: 1.0.1 + uc.micro: 1.0.6 + dev: true + + /marked@4.3.0: + resolution: {integrity: sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==} + engines: {node: '>= 12'} + dev: true + + /mathjax-full@3.2.2: + resolution: {integrity: sha512-+LfG9Fik+OuI8SLwsiR02IVdjcnRCy5MufYLi0C3TdMT56L/pjB0alMVGgoWJF8pN9Rc7FESycZB9BMNWIid5w==} + dependencies: + esm: 3.2.25 + mhchemparser: 4.1.1 + mj-context-menu: 0.6.1 + speech-rule-engine: 4.0.7 + dev: true + + /mdurl@1.0.1: + resolution: {integrity: sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==} + dev: true + + /medium-zoom@1.0.8: + resolution: {integrity: sha512-CjFVuFq/IfrdqesAXfg+hzlDKu6A2n80ZIq0Kl9kWjoHh9j1N9Uvk5X0/MmN0hOfm5F9YBswlClhcwnmtwz7gA==} + 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 + + /mermaid@10.0.2: + resolution: {integrity: sha512-slwoB9WdNUT+/W9VhxLYRLZ0Ey12fIE+cAZjm3FmHTD+0F1uoJETfsNbVS1POnvQZhFYzfT6/z6hJZXgecqVBA==} + dependencies: + '@braintree/sanitize-url': 6.0.2 + cytoscape: 3.23.0 + cytoscape-cose-bilkent: 4.1.0(cytoscape@3.23.0) + cytoscape-fcose: 2.2.0(cytoscape@3.23.0) + d3: 7.8.3 + dagre-d3-es: 7.0.9 + dayjs: 1.11.7 + dompurify: 2.4.3 + elkjs: 0.8.2 + khroma: 2.0.0 + lodash-es: 4.17.21 + non-layered-tidy-tree-layout: 2.0.2 + stylis: 4.1.3 + ts-dedent: 2.2.0 + uuid: 9.0.0 + web-worker: 1.2.0 + dev: true + + /mhchemparser@4.1.1: + resolution: {integrity: sha512-R75CUN6O6e1t8bgailrF1qPq+HhVeFTM3XQ0uzI+mXTybmphy3b6h4NbLOYhemViQ3lUs+6CKRkC3Ws1TlYREA==} + 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 + + /minimatch@3.1.2: + resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + dependencies: + brace-expansion: 1.1.11 + dev: true + + /minimatch@5.1.6: + resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} + engines: {node: '>=10'} + dependencies: + brace-expansion: 2.0.1 + dev: true + + /mitt@3.0.0: + resolution: {integrity: sha512-7dX2/10ITVyqh4aOSVI9gdape+t9l2/8QxHrFmUXu4EEUpdlxl6RudZUPZoc+zuY2hk1j7XxVroIVIan/pD/SQ==} + dev: true + + /mj-context-menu@0.6.1: + resolution: {integrity: sha512-7NO5s6n10TIV96d4g2uDpG7ZDpIhMh0QNfGdJw/W47JswFcosz457wqz/b5sAKvl12sxINGFCn80NZHKwxQEXA==} + dev: true + + /mpegts.js@1.7.2: + resolution: {integrity: sha512-qQ1ELBDC4IAqpULFuFzp3hoQeKwD5BCR3UM9Lk2+kj9jCWcXl19spF7PdzX0ZljghPHAj/VL2ajBbGyMWk2fgA==} + dependencies: + es6-promise: 4.2.8 + webworkify-webpack: 2.1.5 + dev: true + + /ms@2.1.2: + resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} + dev: true + + /nanoid@3.3.6: + resolution: {integrity: sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + dev: true + + /node-releases@2.0.10: + resolution: {integrity: sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w==} + dev: true + + /non-layered-tidy-tree-layout@2.0.2: + resolution: {integrity: sha512-gkXMxRzUH+PB0ax9dUN0yYF0S25BqeAYqhgMaLUFmpXLEk7Fcu8f4emJuOAY0V8kjDICxROIKsTAKsV/v355xw==} + dev: true + + /normalize-path@3.0.0: + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} + dev: true + + /normalize-range@0.1.2: + resolution: {integrity: sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==} + engines: {node: '>=0.10.0'} + dev: true + + /npm-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 + + /nth-check@2.1.1: + resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} + dependencies: + boolbase: 1.0.0 + dev: true + + /object-inspect@1.12.3: + resolution: {integrity: sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==} + dev: true + + /object-keys@1.1.1: + resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} + engines: {node: '>= 0.4'} + dev: true + + /object.assign@4.1.4: + resolution: {integrity: sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + define-properties: 1.2.0 + has-symbols: 1.0.3 + object-keys: 1.1.1 + dev: true + + /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 + + /option-validator@2.0.6: + resolution: {integrity: sha512-tmZDan2LRIRQyhUGvkff68/O0R8UmF+Btmiiz0SmSw2ng3CfPZB9wJlIjHpe/MKUZqyIZkVIXCrwr1tIN+0Dzg==} + dependencies: + kind-of: 6.0.3 + dev: true + + /ora@6.3.0: + resolution: {integrity: sha512-1/D8uRFY0ay2kgBpmAwmSA404w4OoPVhHMqRqtjvrcK/dnzcEZxMJ+V4DUbyICu8IIVRclHcOf5wlD1tMY4GUQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + chalk: 5.2.0 + cli-cursor: 4.0.0 + cli-spinners: 2.7.0 + is-interactive: 2.0.0 + is-unicode-supported: 1.3.0 + log-symbols: 5.1.0 + stdin-discarder: 0.1.0 + strip-ansi: 7.0.1 + wcwidth: 1.0.1 + dev: true + + /p-limit@2.3.0: + resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} + engines: {node: '>=6'} + dependencies: + p-try: 2.2.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-try@2.2.0: + resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} + engines: {node: '>=6'} + dev: true + + /parse5-htmlparser2-tree-adapter@7.0.0: + resolution: {integrity: sha512-B77tOZrqqfUfnVcOrUvfdLbz4pu4RopLD/4vmu3HUPswwTA8OH0EMW9BlWR2B0RCoiZRAHEUu7IxeP1Pd1UU+g==} + dependencies: + domhandler: 5.0.3 + parse5: 7.1.2 + dev: true + + /parse5@7.1.2: + resolution: {integrity: sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==} + dependencies: + entities: 4.4.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 + + /photoswipe@5.3.7: + resolution: {integrity: sha512-zsyLsTTLFrj0XR1m4/hO7qNooboFKUrDy+Zt5i2d6qjFPAtBjzaj/Xtydso4uxzcXpcqbTmyxDibb3BcSISseg==} + engines: {node: '>= 0.12.0'} + 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 + + /plyr@3.7.8: + resolution: {integrity: sha512-yG/EHDobwbB/uP+4Bm6eUpJ93f8xxHjjk2dYcD1Oqpe1EcuQl5tzzw9Oq+uVAzd2lkM11qZfydSiyIpiB8pgdA==} + dependencies: + core-js: 3.29.1 + custom-event-polyfill: 1.0.7 + loadjs: 4.2.0 + rangetouch: 2.0.1 + url-polyfill: 1.1.12 + dev: true + + /pngjs@5.0.0: + resolution: {integrity: sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==} + engines: {node: '>=10.13.0'} + dev: true + + /postcss-load-config@4.0.1(postcss@8.4.21): + resolution: {integrity: sha512-vEJIc8RdiBRu3oRAI0ymerOn+7rPuMvRXslTvZUKZonDHFIczxztIyJ1urxM1x9JXEikvpWWTUUqal5j/8QgvA==} + engines: {node: '>= 14'} + peerDependencies: + postcss: '>=8.0.9' + ts-node: '>=9.0.0' + peerDependenciesMeta: + postcss: + optional: true + ts-node: + optional: true + dependencies: + lilconfig: 2.1.0 + postcss: 8.4.21 + yaml: 2.2.1 + dev: true + + /postcss-value-parser@4.2.0: + resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} + dev: true + + /postcss@8.4.21: + resolution: {integrity: sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg==} + engines: {node: ^10 || ^12 || >=14} + dependencies: + nanoid: 3.3.6 + picocolors: 1.0.0 + source-map-js: 1.0.2 + dev: true + + /pretty-bytes@5.6.0: + resolution: {integrity: sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==} + engines: {node: '>=6'} + dev: true + + /prismjs@1.29.0: + resolution: {integrity: sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q==} + engines: {node: '>=6'} + dev: true + + /punycode@2.3.0: + resolution: {integrity: sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==} + engines: {node: '>=6'} + dev: true + + /qrcode@1.5.1: + resolution: {integrity: sha512-nS8NJ1Z3md8uTjKtP+SGGhfqmTCs5flU/xR623oI0JX+Wepz9R8UrRVCTBTJm3qGw3rH6jJ6MUHjkDx15cxSSg==} + engines: {node: '>=10.13.0'} + dependencies: + dijkstrajs: 1.0.2 + encode-utf8: 1.0.3 + pngjs: 5.0.0 + yargs: 15.4.1 + dev: true + + /queue-microtask@1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + dev: true + + /randombytes@2.1.0: + resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} + dependencies: + safe-buffer: 5.2.1 + dev: true + + /rangetouch@2.0.1: + resolution: {integrity: sha512-sln+pNSc8NGaHoLzwNBssFSf/rSYkqeBXzX1AtJlkJiUaVSJSbRAWJk+4omsXkN+EJalzkZhWQ3th1m0FpR5xA==} + dev: true + + /raphael@2.3.0: + resolution: {integrity: sha512-w2yIenZAQnp257XUWGni4bLMVxpUpcIl7qgxEgDIXtmSypYtlNxfXWpOBxs7LBTps5sDwhRnrToJrMUrivqNTQ==} + dependencies: + eve-raphael: 0.5.0 + dev: true + + /readable-stream@3.6.2: + resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} + engines: {node: '>= 6'} + dependencies: + inherits: 2.0.4 + string_decoder: 1.3.0 + util-deprecate: 1.0.2 + dev: true + + /readdirp@3.6.0: + resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} + engines: {node: '>=8.10.0'} + dependencies: + picomatch: 2.3.1 + dev: true + + /regenerate-unicode-properties@10.1.0: + resolution: {integrity: sha512-d1VudCLoIGitcU/hEg2QqvyGZQmdC0Lf8BqdOMXGFSvJP4bNV1+XqbPQeHHLD51Jh4QJJ225dlIFvY4Ly6MXmQ==} + engines: {node: '>=4'} + dependencies: + regenerate: 1.4.2 + dev: true + + /regenerate@1.4.2: + resolution: {integrity: sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==} + dev: true + + /regenerator-runtime@0.13.11: + resolution: {integrity: sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==} + dev: true + + /regenerator-transform@0.15.1: + resolution: {integrity: sha512-knzmNAcuyxV+gQCufkYcvOqX/qIIfHLv0u5x79kRxuGojfYVky1f15TzZEu2Avte8QGepvUNTnLskf8E6X6Vyg==} + dependencies: + '@babel/runtime': 7.21.0 + dev: true + + /regexp.prototype.flags@1.4.3: + resolution: {integrity: sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + define-properties: 1.2.0 + functions-have-names: 1.2.3 + dev: true + + /regexpu-core@5.3.2: + resolution: {integrity: sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==} + engines: {node: '>=4'} + dependencies: + '@babel/regjsgen': 0.8.0 + regenerate: 1.4.2 + regenerate-unicode-properties: 10.1.0 + regjsparser: 0.9.1 + unicode-match-property-ecmascript: 2.0.0 + unicode-match-property-value-ecmascript: 2.1.0 + dev: true + + /register-service-worker@1.7.2: + resolution: {integrity: sha512-CiD3ZSanZqcMPRhtfct5K9f7i3OLCcBBWsJjLh1gW9RO/nS94sVzY59iS+fgYBOBqaBpf4EzfqUF3j9IG+xo8A==} + dev: true + + /regjsparser@0.9.1: + resolution: {integrity: sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==} + dependencies: + jsesc: 0.5.0 + dev: true + + /require-directory@2.1.1: + resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} + engines: {node: '>=0.10.0'} + dev: true + + /require-from-string@2.0.2: + resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} + engines: {node: '>=0.10.0'} + dev: true + + /require-main-filename@2.0.0: + resolution: {integrity: sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==} + dev: true + + /resolve@1.22.1: + resolution: {integrity: sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==} + dependencies: + is-core-module: 2.11.0 + 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 + + /reveal.js@4.4.0: + resolution: {integrity: sha512-jIV6C9V2NEUjGzU8L6dUFGpk1KJmq7/EzP2fOW67ggc2c0Cp/PdprWxZ9Qgp46F0T2ZWDCjQ1p3Ytzy5jA6a2w==} + engines: {node: '>=10.0.0'} + dev: true + + /robust-predicates@3.0.1: + resolution: {integrity: sha512-ndEIpszUHiG4HtDsQLeIuMvRsDnn8c8rYStabochtUeCvfuvNptb5TUbVD68LRAILPX7p9nqQGh4xJgn3EHS/g==} + dev: true + + /rollup-plugin-terser@7.0.2(rollup@2.79.1): + resolution: {integrity: sha512-w3iIaU4OxcF52UUXiZNsNeuXIMDvFrr+ZXK6bFZ0Q60qyVfq4uLptoS4bbq3paG3x216eQllFZX7zt6TIImguQ==} + peerDependencies: + rollup: ^2.0.0 + dependencies: + '@babel/code-frame': 7.18.6 + jest-worker: 26.6.2 + rollup: 2.79.1 + serialize-javascript: 4.0.0 + terser: 5.16.8 + dev: true + + /rollup@2.79.1: + resolution: {integrity: sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==} + engines: {node: '>=10.0.0'} + optionalDependencies: + fsevents: 2.3.2 + dev: true + + /rollup@3.20.2: + resolution: {integrity: sha512-3zwkBQl7Ai7MFYQE0y1MeQ15+9jsi7XxfrqwTb/9EK8D9C9+//EBR4M+CuA1KODRaNbFez/lWxA5vhEGZp4MUg==} + engines: {node: '>=14.18.0', npm: '>=8.0.0'} + optionalDependencies: + fsevents: 2.3.2 + dev: true + + /run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + dependencies: + queue-microtask: 1.2.3 + dev: true + + /rw@1.3.3: + resolution: {integrity: sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==} + dev: true + + /safe-buffer@5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + dev: true + + /safe-regex-test@1.0.0: + resolution: {integrity: sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==} + dependencies: + call-bind: 1.0.2 + get-intrinsic: 1.2.0 + is-regex: 1.1.4 + dev: true + + /safer-buffer@2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + dev: true + + /sass@1.60.0: + resolution: {integrity: sha512-updbwW6fNb5gGm8qMXzVO7V4sWf7LMXnMly/JEyfbfERbVH46Fn6q02BX7/eHTdKpE7d+oTkMMQpFWNUMfFbgQ==} + engines: {node: '>=12.0.0'} + dependencies: + chokidar: 3.5.3 + immutable: 4.3.0 + source-map-js: 1.0.2 + dev: true + + /sax@1.2.1: + resolution: {integrity: sha512-8I2a3LovHTOpm7NV5yOyO8IHqgVsfK4+UuySrXU8YXkSRX7k6hCV9b3HrkKCr3nMpgj+0bmocaJJWpvp1oc7ZA==} + dev: true + + /sax@1.2.4: + resolution: {integrity: sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==} + dev: true + + /section-matter@1.0.0: + resolution: {integrity: sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==} + engines: {node: '>=4'} + dependencies: + extend-shallow: 2.0.1 + kind-of: 6.0.3 + dev: true + + /semver@6.3.0: + resolution: {integrity: sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==} + dev: true + + /semver@7.3.8: + resolution: {integrity: sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==} + engines: {node: '>=10'} + dependencies: + lru-cache: 6.0.0 + dev: true + + /serialize-javascript@4.0.0: + resolution: {integrity: sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==} + dependencies: + randombytes: 2.1.0 + dev: true + + /set-blocking@2.0.0: + resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==} + dev: true + + /shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + dependencies: + shebang-regex: 3.0.0 + dev: true + + /shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + dev: true + + /side-channel@1.0.4: + resolution: {integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==} + dependencies: + call-bind: 1.0.2 + get-intrinsic: 1.2.0 + object-inspect: 1.12.3 + dev: true + + /signal-exit@3.0.7: + resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} + dev: true + + /sitemap@7.1.1: + resolution: {integrity: sha512-mK3aFtjz4VdJN0igpIJrinf3EO8U8mxOPsTBzSsy06UtjZQJ3YY3o3Xa7zSc5nMqcMrRwlChHZ18Kxg0caiPBg==} + engines: {node: '>=12.0.0', npm: '>=5.6.0'} + dependencies: + '@types/node': 17.0.45 + '@types/sax': 1.2.4 + arg: 5.0.2 + sax: 1.2.4 + dev: true + + /slash@4.0.0: + resolution: {integrity: sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==} + engines: {node: '>=12'} + dev: true + + /source-map-js@1.0.2: + resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==} + engines: {node: '>=0.10.0'} + dev: true + + /source-map-support@0.5.21: + resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} + dependencies: + buffer-from: 1.1.2 + source-map: 0.6.1 + dev: true + + /source-map@0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + dev: true + + /source-map@0.8.0-beta.0: + resolution: {integrity: sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==} + engines: {node: '>= 8'} + dependencies: + whatwg-url: 7.1.0 + dev: true + + /sourcemap-codec@1.4.8: + resolution: {integrity: sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==} + dev: true + + /speech-rule-engine@4.0.7: + resolution: {integrity: sha512-sJrL3/wHzNwJRLBdf6CjJWIlxC04iYKkyXvYSVsWVOiC2DSkHmxsqOhEeMsBA9XK+CHuNcsdkbFDnoUfAsmp9g==} + dependencies: + commander: 9.2.0 + wicked-good-xpath: 1.3.0 + xmldom-sre: 0.1.31 + 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 + + /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.prototype.matchall@4.0.8: + resolution: {integrity: sha512-6zOCOcJ+RJAQshcTvXPHoxoQGONa3e/Lqx90wUA+wEzX78sg5Bo+1tQo4N0pohS0erG9qtCqJDjNCQBjeWVxyg==} + dependencies: + call-bind: 1.0.2 + define-properties: 1.2.0 + es-abstract: 1.21.2 + get-intrinsic: 1.2.0 + has-symbols: 1.0.3 + internal-slot: 1.0.5 + regexp.prototype.flags: 1.4.3 + side-channel: 1.0.4 + dev: true + + /string.prototype.trim@1.2.7: + resolution: {integrity: sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + define-properties: 1.2.0 + es-abstract: 1.21.2 + dev: true + + /string.prototype.trimend@1.0.6: + resolution: {integrity: sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==} + dependencies: + call-bind: 1.0.2 + define-properties: 1.2.0 + es-abstract: 1.21.2 + dev: true + + /string.prototype.trimstart@1.0.6: + resolution: {integrity: sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==} + dependencies: + call-bind: 1.0.2 + define-properties: 1.2.0 + es-abstract: 1.21.2 + dev: true + + /string_decoder@1.3.0: + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + dependencies: + safe-buffer: 5.2.1 + dev: true + + /stringify-object@3.3.0: + resolution: {integrity: sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==} + engines: {node: '>=4'} + dependencies: + get-own-enumerable-property-symbols: 3.0.2 + is-obj: 1.0.1 + is-regexp: 1.0.0 + dev: true + + /strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + dependencies: + ansi-regex: 5.0.1 + dev: true + + /strip-ansi@7.0.1: + resolution: {integrity: sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==} + engines: {node: '>=12'} + dependencies: + ansi-regex: 6.0.1 + dev: true + + /strip-bom-string@1.0.0: + resolution: {integrity: sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g==} + engines: {node: '>=0.10.0'} + dev: true + + /strip-comments@2.0.1: + resolution: {integrity: sha512-ZprKx+bBLXv067WTCALv8SSz5l2+XhpYCsVtSqlMnkAXMWDq+/ekVbl1ghqP9rUHTzv6sm/DwCOiYutU/yp1fw==} + engines: {node: '>=10'} + dev: true + + /strip-final-newline@3.0.0: + resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==} + engines: {node: '>=12'} + dev: true + + /striptags@3.2.0: + resolution: {integrity: sha512-g45ZOGzHDMe2bdYMdIvdAfCQkCTDMGBazSw1ypMowwGIee7ZQ5dU0rBJ8Jqgl+jAKIv4dbeE1jscZq9wid1Tkw==} + dev: true + + /stylis@4.1.3: + resolution: {integrity: sha512-GP6WDNWf+o403jrEp9c5jibKavrtLW+/qYGhFxFrG8maXhwTBI7gLLhiBb0o7uFccWN+EOS9aMO6cGHWAO07OA==} + dev: true + + /supports-color@5.5.0: + resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} + engines: {node: '>=4'} + dependencies: + has-flag: 3.0.0 + dev: true + + /supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + dependencies: + has-flag: 4.0.0 + dev: true + + /supports-preserve-symlinks-flag@1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + dev: true + + /temp-dir@2.0.0: + resolution: {integrity: sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==} + engines: {node: '>=8'} + dev: true + + /tempy@0.6.0: + resolution: {integrity: sha512-G13vtMYPT/J8A4X2SjdtBTphZlrp1gKv6hZiOjw14RCWg6GbHuQBGtjlx75xLbYV/wEc0D7G5K4rxKP/cXk8Bw==} + engines: {node: '>=10'} + dependencies: + is-stream: 2.0.1 + temp-dir: 2.0.0 + type-fest: 0.16.0 + unique-string: 2.0.0 + dev: true + + /terser@5.16.8: + resolution: {integrity: sha512-QI5g1E/ef7d+PsDifb+a6nnVgC4F22Bg6T0xrBrz6iloVB4PUkkunp6V8nzoOOZJIzjWVdAGqCdlKlhLq/TbIA==} + engines: {node: '>=10'} + dependencies: + '@jridgewell/source-map': 0.3.2 + acorn: 8.8.2 + commander: 2.20.3 + source-map-support: 0.5.21 + dev: true + + /to-fast-properties@2.0.0: + resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} + engines: {node: '>=4'} + dev: true + + /to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + dependencies: + is-number: 7.0.0 + dev: true + + /tr46@1.0.1: + resolution: {integrity: sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==} + dependencies: + punycode: 2.3.0 + dev: true + + /ts-debounce@4.0.0: + resolution: {integrity: sha512-+1iDGY6NmOGidq7i7xZGA4cm8DAa6fqdYcvO5Z6yBevH++Bdo9Qt/mN0TzHUgcCcKv1gmh9+W5dHqz8pMWbCbg==} + dev: true + + /ts-dedent@2.2.0: + resolution: {integrity: sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==} + engines: {node: '>=6.10'} + dev: true + + /tslib@2.3.0: + resolution: {integrity: sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==} + dev: true + + /tslib@2.4.1: + resolution: {integrity: sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==} + dev: true + + /twikoo@1.6.11: + resolution: {integrity: sha512-/d0MJFDrtgOHtKh9QN8KDT58h2odtZOFli7CLK83hu1BB9VqIi5jE9PqU9UggZD89vhXrYRXMkEFATMoMSbBSw==} + dev: true + + /type-fest@0.16.0: + resolution: {integrity: sha512-eaBzG6MxNzEn9kiwvtre90cXaNLkmadMWa1zQMs3XORCXNbsH/OewwbxC5ia9dCxIxnTAsSxXJaa/p5y8DlvJg==} + engines: {node: '>=10'} + dev: true + + /typed-array-length@1.0.4: + resolution: {integrity: sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==} + dependencies: + call-bind: 1.0.2 + for-each: 0.3.3 + is-typed-array: 1.1.10 + dev: true + + /ua-parser-js@1.0.34: + resolution: {integrity: sha512-K9mwJm/DaB6mRLZfw6q8IMXipcrmuT6yfhYmwhAkuh+81sChuYstYA+znlgaflUPaYUa3odxKPKGw6Vw/lANew==} + dev: true + + /uc.micro@1.0.6: + resolution: {integrity: sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==} + dev: true + + /unbox-primitive@1.0.2: + resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} + dependencies: + call-bind: 1.0.2 + has-bigints: 1.0.2 + has-symbols: 1.0.3 + which-boxed-primitive: 1.0.2 + dev: true + + /unicode-canonical-property-names-ecmascript@2.0.0: + resolution: {integrity: sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==} + engines: {node: '>=4'} + dev: true + + /unicode-match-property-ecmascript@2.0.0: + resolution: {integrity: sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==} + engines: {node: '>=4'} + dependencies: + unicode-canonical-property-names-ecmascript: 2.0.0 + unicode-property-aliases-ecmascript: 2.1.0 + dev: true + + /unicode-match-property-value-ecmascript@2.1.0: + resolution: {integrity: sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==} + engines: {node: '>=4'} + dev: true + + /unicode-property-aliases-ecmascript@2.1.0: + resolution: {integrity: sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==} + engines: {node: '>=4'} + dev: true + + /unique-string@2.0.0: + resolution: {integrity: sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==} + engines: {node: '>=8'} + dependencies: + crypto-random-string: 2.0.0 + dev: true + + /universalify@2.0.0: + resolution: {integrity: sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==} + engines: {node: '>= 10.0.0'} + dev: true + + /upath@1.2.0: + resolution: {integrity: sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==} + engines: {node: '>=4'} + dev: true + + /upath@2.0.1: + resolution: {integrity: sha512-1uEe95xksV1O0CYKXo8vQvN1JEbtJp7lb7C5U9HMsIp6IVwntkH/oNUzyVNQSd4S1sYk2FpSSW44FqMc8qee5w==} + engines: {node: '>=4'} + dev: true + + /update-browserslist-db@1.0.10(browserslist@4.21.5): + resolution: {integrity: sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + dependencies: + browserslist: 4.21.5 + 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 + + /url-polyfill@1.1.12: + resolution: {integrity: sha512-mYFmBHCapZjtcNHW0MDq9967t+z4Dmg5CJ0KqysK3+ZbyoNOWQHksGCTWwDhxGXllkWlOc10Xfko6v4a3ucM6A==} + dev: true + + /util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + dev: true + + /uuid@9.0.0: + resolution: {integrity: sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==} + dev: true + + /vite@4.1.4: + resolution: {integrity: sha512-3knk/HsbSTKEin43zHu7jTwYWv81f8kgAL99G5NWBcA1LKvtvcVAC4JjBH1arBunO9kQka+1oGbrMKOjk4ZrBg==} + engines: {node: ^14.18.0 || >=16.0.0} + hasBin: true + peerDependencies: + '@types/node': '>= 14' + less: '*' + sass: '*' + stylus: '*' + sugarss: '*' + terser: ^5.4.0 + peerDependenciesMeta: + '@types/node': + optional: true + less: + optional: true + sass: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + dependencies: + esbuild: 0.16.17 + postcss: 8.4.21 + resolve: 1.22.1 + rollup: 3.20.2 + optionalDependencies: + fsevents: 2.3.2 + dev: true + + /vue-demi@0.13.11(vue@3.2.47): + resolution: {integrity: sha512-IR8HoEEGM65YY3ZJYAjMlKygDQn25D5ajNFNoKh9RSDMQtlzCxtfQjdQgv9jjK+m3377SsJXY8ysq8kLCZL25A==} + engines: {node: '>=12'} + hasBin: true + requiresBuild: true + peerDependencies: + '@vue/composition-api': ^1.0.0-rc.1 + vue: ^3.0.0-0 || ^2.6.0 + peerDependenciesMeta: + '@vue/composition-api': + optional: true + dependencies: + vue: 3.2.47 + dev: true + + /vue-router@4.1.6(vue@3.2.47): + resolution: {integrity: sha512-DYWYwsG6xNPmLq/FmZn8Ip+qrhFEzA14EI12MsMgVxvHFDYvlr4NXpVF5hrRH1wVcDP8fGi5F4rxuJSl8/r+EQ==} + peerDependencies: + vue: ^3.2.0 + dependencies: + '@vue/devtools-api': 6.5.0 + vue: 3.2.47 + dev: true + + /vue@3.2.47: + resolution: {integrity: sha512-60188y/9Dc9WVrAZeUVSDxRQOZ+z+y5nO2ts9jWXSTkMvayiWxCWOWtBQoYjLeccfXkiiPZWAHcV+WTPhkqJHQ==} + dependencies: + '@vue/compiler-dom': 3.2.47 + '@vue/compiler-sfc': 3.2.47 + '@vue/runtime-dom': 3.2.47 + '@vue/server-renderer': 3.2.47(vue@3.2.47) + '@vue/shared': 3.2.47 + dev: true + + /vuepress-plugin-auto-catalog@2.0.0-beta.200(vuepress@2.0.0-beta.61): + resolution: {integrity: sha512-9au5xgrLfLTNi3c4Z370XKhR1SQLZgYHp+NrHr+gMj4OGWxzq7v18qYAkcyqpeYf/mGL5qgl7T4wbtU3tPDZTg==} + engines: {node: ^14.18.0 || >=16.0.0, npm: '>=8', pnpm: '>=7'} + peerDependencies: + sass-loader: ^13.2.0 + vuepress: 2.0.0-beta.61 + vuepress-vite: 2.0.0-beta.61 + vuepress-webpack: 2.0.0-beta.61 + peerDependenciesMeta: + sass-loader: + optional: true + vuepress: + optional: true + vuepress-vite: + optional: true + vuepress-webpack: + optional: true + dependencies: + '@vuepress/client': 2.0.0-beta.61 + '@vuepress/core': 2.0.0-beta.61 + '@vuepress/shared': 2.0.0-beta.61 + '@vuepress/utils': 2.0.0-beta.61 + vue: 3.2.47 + vue-router: 4.1.6(vue@3.2.47) + vuepress: 2.0.0-beta.61(@vuepress/client@2.0.0-beta.61)(vue@3.2.47) + vuepress-plugin-components: 2.0.0-beta.200(vuepress@2.0.0-beta.61) + vuepress-plugin-sass-palette: 2.0.0-beta.200(vuepress@2.0.0-beta.61) + vuepress-shared: 2.0.0-beta.200(vuepress@2.0.0-beta.61) + transitivePeerDependencies: + - '@vue/composition-api' + - supports-color + dev: true + + /vuepress-plugin-blog2@2.0.0-beta.200(vuepress@2.0.0-beta.61): + resolution: {integrity: sha512-Xrdqj5fuXggCscC1BKxdYNEn7S/b/eK9bsw3DaYH31T7b66bg6UNSJ7j9KiLq2RAfhKiCdFjx9BN+WEZGJpB6A==} + engines: {node: ^14.18.0 || >=16.0.0, npm: '>=8', pnpm: '>=7'} + peerDependencies: + vuepress: 2.0.0-beta.61 + vuepress-vite: 2.0.0-beta.61 + vuepress-webpack: 2.0.0-beta.61 + peerDependenciesMeta: + vuepress: + optional: true + vuepress-vite: + optional: true + vuepress-webpack: + optional: true + dependencies: + '@vuepress/client': 2.0.0-beta.61 + '@vuepress/core': 2.0.0-beta.61 + '@vuepress/shared': 2.0.0-beta.61 + '@vuepress/utils': 2.0.0-beta.61 + chokidar: 3.5.3 + vue: 3.2.47 + vue-router: 4.1.6(vue@3.2.47) + vuepress: 2.0.0-beta.61(@vuepress/client@2.0.0-beta.61)(vue@3.2.47) + vuepress-shared: 2.0.0-beta.200(vuepress@2.0.0-beta.61) + transitivePeerDependencies: + - '@vue/composition-api' + - supports-color + dev: true + + /vuepress-plugin-comment2@2.0.0-beta.200(vuepress@2.0.0-beta.61): + resolution: {integrity: sha512-JHUxUuFu1Yc7ZgkMdFz+s57WbFizjtXhEVBocs+cQnSZBZSpCkb+pOzU49hAP5EjbWwwj3vLweyEupD6os/cJQ==} + engines: {node: ^14.18.0 || >=16.0.0, npm: '>=8', pnpm: '>=7'} + peerDependencies: + sass-loader: ^13.2.0 + vuepress: 2.0.0-beta.61 + vuepress-vite: 2.0.0-beta.61 + vuepress-webpack: 2.0.0-beta.61 + peerDependenciesMeta: + sass-loader: + optional: true + vuepress: + optional: true + vuepress-vite: + optional: true + vuepress-webpack: + optional: true + dependencies: + '@vuepress/client': 2.0.0-beta.61 + '@vuepress/shared': 2.0.0-beta.61 + '@vuepress/utils': 2.0.0-beta.61 + '@waline/client': 2.14.9 + artalk: 2.5.2 + giscus: 1.2.8 + twikoo: 1.6.11 + vue: 3.2.47 + vue-router: 4.1.6(vue@3.2.47) + vuepress: 2.0.0-beta.61(@vuepress/client@2.0.0-beta.61)(vue@3.2.47) + vuepress-plugin-sass-palette: 2.0.0-beta.200(vuepress@2.0.0-beta.61) + vuepress-shared: 2.0.0-beta.200(vuepress@2.0.0-beta.61) + transitivePeerDependencies: + - '@vue/composition-api' + - supports-color + dev: true + + /vuepress-plugin-components@2.0.0-beta.200(vuepress@2.0.0-beta.61): + resolution: {integrity: sha512-n+EGMshISwiegSpiav1JEeYSxGqByngIFocYYIgEQstjieNRVrf5FRdr41EW+HhIrpaq2ktwmU+YcLS/ZADVDA==} + engines: {node: ^14.18.0 || >=16.0.0, npm: '>=8', pnpm: '>=7'} + peerDependencies: + sass-loader: ^13.2.0 + vuepress: 2.0.0-beta.61 + vuepress-vite: 2.0.0-beta.61 + vuepress-webpack: 2.0.0-beta.61 + peerDependenciesMeta: + sass-loader: + optional: true + vuepress: + optional: true + vuepress-vite: + optional: true + vuepress-webpack: + optional: true + dependencies: + '@stackblitz/sdk': 1.8.2 + '@vuepress/client': 2.0.0-beta.61 + '@vuepress/shared': 2.0.0-beta.61 + '@vuepress/utils': 2.0.0-beta.61 + '@vueuse/core': 9.13.0(vue@3.2.47) + artplayer: 4.6.2 + balloon-css: 1.2.0 + dashjs: 4.6.0 + hls.js: 1.3.5 + mpegts.js: 1.7.2 + plyr: 3.7.8 + qrcode: 1.5.1 + vue: 3.2.47 + vue-router: 4.1.6(vue@3.2.47) + vuepress: 2.0.0-beta.61(@vuepress/client@2.0.0-beta.61)(vue@3.2.47) + vuepress-plugin-reading-time2: 2.0.0-beta.200(vuepress@2.0.0-beta.61) + vuepress-plugin-sass-palette: 2.0.0-beta.200(vuepress@2.0.0-beta.61) + vuepress-shared: 2.0.0-beta.200(vuepress@2.0.0-beta.61) + transitivePeerDependencies: + - '@vue/composition-api' + - supports-color + dev: true + + /vuepress-plugin-copy-code2@2.0.0-beta.200(vuepress@2.0.0-beta.61): + resolution: {integrity: sha512-SPOGaSsUd3uFd1cdc27Y1PLtlJQ9yxOmgyFRLOBGGZ4HV0rUNbkCw1nv9ncfYAQxmyQRtbZSWwRKXXwi/tsltQ==} + engines: {node: ^14.18.0 || >=16.0.0, npm: '>=8', pnpm: '>=7'} + peerDependencies: + sass-loader: ^13.2.0 + vuepress: 2.0.0-beta.61 + vuepress-vite: 2.0.0-beta.61 + vuepress-webpack: 2.0.0-beta.61 + peerDependenciesMeta: + sass-loader: + optional: true + vuepress: + optional: true + vuepress-vite: + optional: true + vuepress-webpack: + optional: true + dependencies: + '@vuepress/client': 2.0.0-beta.61 + '@vuepress/shared': 2.0.0-beta.61 + '@vuepress/utils': 2.0.0-beta.61 + '@vueuse/core': 9.13.0(vue@3.2.47) + balloon-css: 1.2.0 + vue: 3.2.47 + vue-router: 4.1.6(vue@3.2.47) + vuepress: 2.0.0-beta.61(@vuepress/client@2.0.0-beta.61)(vue@3.2.47) + vuepress-plugin-sass-palette: 2.0.0-beta.200(vuepress@2.0.0-beta.61) + vuepress-shared: 2.0.0-beta.200(vuepress@2.0.0-beta.61) + transitivePeerDependencies: + - '@vue/composition-api' + - supports-color + dev: true + + /vuepress-plugin-copyright2@2.0.0-beta.200(vuepress@2.0.0-beta.61): + resolution: {integrity: sha512-CYq6qY74ScQAOMgJOZnic3bgwCt15Bo/xQTaV893MMFL75qN6gnGG6jqFsgAiR1hvnJ2kwpbXhvIv9XND5Mxgg==} + engines: {node: ^14.18.0 || >=16.0.0, npm: '>=8', pnpm: '>=7'} + peerDependencies: + vuepress: 2.0.0-beta.61 + vuepress-vite: 2.0.0-beta.61 + vuepress-webpack: 2.0.0-beta.61 + peerDependenciesMeta: + vuepress: + optional: true + vuepress-vite: + optional: true + vuepress-webpack: + optional: true + dependencies: + '@vuepress/client': 2.0.0-beta.61 + '@vuepress/shared': 2.0.0-beta.61 + '@vuepress/utils': 2.0.0-beta.61 + '@vueuse/core': 9.13.0(vue@3.2.47) + vue: 3.2.47 + vue-router: 4.1.6(vue@3.2.47) + vuepress: 2.0.0-beta.61(@vuepress/client@2.0.0-beta.61)(vue@3.2.47) + vuepress-shared: 2.0.0-beta.200(vuepress@2.0.0-beta.61) + transitivePeerDependencies: + - '@vue/composition-api' + - supports-color + dev: true + + /vuepress-plugin-feed2@2.0.0-beta.200(vuepress@2.0.0-beta.61): + resolution: {integrity: sha512-LlnMJXuvPf2pWWN9m0gdJReQ1A+iKOoFHMiA36m3kHBp5G0YrECKdDN8yl9N2z/sb4EC9VxvnaYa5by7V+PPAA==} + engines: {node: ^14.18.0 || >=16.0.0, npm: '>=8', pnpm: '>=7'} + peerDependencies: + vuepress: 2.0.0-beta.61 + vuepress-vite: 2.0.0-beta.61 + vuepress-webpack: 2.0.0-beta.61 + peerDependenciesMeta: + vuepress: + optional: true + vuepress-vite: + optional: true + vuepress-webpack: + optional: true + dependencies: + '@vuepress/shared': 2.0.0-beta.61 + '@vuepress/utils': 2.0.0-beta.61 + cheerio: 1.0.0-rc.12 + vuepress: 2.0.0-beta.61(@vuepress/client@2.0.0-beta.61)(vue@3.2.47) + vuepress-shared: 2.0.0-beta.200(vuepress@2.0.0-beta.61) + xml-js: 1.6.11 + transitivePeerDependencies: + - '@vue/composition-api' + - supports-color + dev: true + + /vuepress-plugin-md-enhance@2.0.0-beta.200(vuepress@2.0.0-beta.61): + resolution: {integrity: sha512-KbBopiIe4N1LUdb6KI0Ndh9VXiHCtrqQ+HC03IWHHNBAoXun/CFpAKTtaOOuxBnPF8hIG4v6eLzs/xfAjuYRBg==} + engines: {node: ^14.18.0 || >=16.0.0, npm: '>=8', pnpm: '>=7'} + peerDependencies: + sass-loader: ^13.2.0 + vuepress: 2.0.0-beta.61 + vuepress-vite: 2.0.0-beta.61 + vuepress-webpack: 2.0.0-beta.61 + peerDependenciesMeta: + sass-loader: + optional: true + vuepress: + optional: true + vuepress-vite: + optional: true + vuepress-webpack: + optional: true + dependencies: + '@babel/core': 7.21.3 + '@mdit/plugin-align': 0.4.1 + '@mdit/plugin-attrs': 0.4.1 + '@mdit/plugin-container': 0.4.1 + '@mdit/plugin-figure': 0.4.1 + '@mdit/plugin-footnote': 0.4.1 + '@mdit/plugin-img-lazyload': 0.4.1 + '@mdit/plugin-img-mark': 0.4.1 + '@mdit/plugin-img-size': 0.4.1 + '@mdit/plugin-include': 0.4.1 + '@mdit/plugin-katex': 0.4.1 + '@mdit/plugin-mark': 0.4.1 + '@mdit/plugin-mathjax': 0.4.1 + '@mdit/plugin-stylize': 0.4.1 + '@mdit/plugin-sub': 0.4.1 + '@mdit/plugin-sup': 0.4.1 + '@mdit/plugin-tab': 0.4.1 + '@mdit/plugin-tasklist': 0.4.1 + '@mdit/plugin-tex': 0.4.1 + '@mdit/plugin-uml': 0.4.1 + '@types/markdown-it': 12.2.3 + '@vue/repl': 1.3.3(vue@3.2.47) + '@vuepress/client': 2.0.0-beta.61 + '@vuepress/shared': 2.0.0-beta.61 + '@vuepress/utils': 2.0.0-beta.61 + '@vueuse/core': 9.13.0(vue@3.2.47) + balloon-css: 1.2.0 + chart.js: 4.2.1 + echarts: 5.4.2 + flowchart.ts: 0.1.2 + katex: 0.16.4 + markdown-it: 13.0.1 + mermaid: 10.0.2 + reveal.js: 4.4.0 + vue: 3.2.47 + vue-router: 4.1.6(vue@3.2.47) + vuepress: 2.0.0-beta.61(@vuepress/client@2.0.0-beta.61)(vue@3.2.47) + vuepress-plugin-sass-palette: 2.0.0-beta.200(vuepress@2.0.0-beta.61) + vuepress-shared: 2.0.0-beta.200(vuepress@2.0.0-beta.61) + transitivePeerDependencies: + - '@vue/composition-api' + - supports-color + dev: true + + /vuepress-plugin-photo-swipe@2.0.0-beta.200(vuepress@2.0.0-beta.61): + resolution: {integrity: sha512-g7EvdNWdR6MmobbEmOBg+BduutG3YvHv+JGdquFbdRPn/bf3VhzNAxgNhv0E+Vzjq2quVNdmjVLcYLSuAKVwRw==} + engines: {node: ^14.18.0 || >=16.0.0, npm: '>=8', pnpm: '>=7'} + peerDependencies: + sass-loader: ^13.2.0 + vuepress: 2.0.0-beta.61 + vuepress-vite: 2.0.0-beta.61 + vuepress-webpack: 2.0.0-beta.61 + peerDependenciesMeta: + sass-loader: + optional: true + vuepress: + optional: true + vuepress-vite: + optional: true + vuepress-webpack: + optional: true + dependencies: + '@vuepress/client': 2.0.0-beta.61 + '@vuepress/shared': 2.0.0-beta.61 + '@vuepress/utils': 2.0.0-beta.61 + '@vueuse/core': 9.13.0(vue@3.2.47) + photoswipe: 5.3.7 + vue: 3.2.47 + vue-router: 4.1.6(vue@3.2.47) + vuepress: 2.0.0-beta.61(@vuepress/client@2.0.0-beta.61)(vue@3.2.47) + vuepress-plugin-sass-palette: 2.0.0-beta.200(vuepress@2.0.0-beta.61) + vuepress-shared: 2.0.0-beta.200(vuepress@2.0.0-beta.61) + transitivePeerDependencies: + - '@vue/composition-api' + - supports-color + dev: true + + /vuepress-plugin-pwa2@2.0.0-beta.200(vuepress@2.0.0-beta.61): + resolution: {integrity: sha512-pAe3bxzDne9IqvuHmnd0HFZNR6K/oXkkOhdiice0h2EEFwTz2azQRdO8Rl7+r8KDptiY1J08VKDeLuvbqKu2Yw==} + engines: {node: ^14.18.0 || >=16.0.0, npm: '>=8', pnpm: '>=7'} + peerDependencies: + sass-loader: ^13.2.0 + vuepress: 2.0.0-beta.61 + vuepress-vite: 2.0.0-beta.61 + vuepress-webpack: 2.0.0-beta.61 + peerDependenciesMeta: + sass-loader: + optional: true + vuepress: + optional: true + vuepress-vite: + optional: true + vuepress-webpack: + optional: true + dependencies: + '@vuepress/client': 2.0.0-beta.61 + '@vuepress/shared': 2.0.0-beta.61 + '@vuepress/utils': 2.0.0-beta.61 + '@vueuse/core': 9.13.0(vue@3.2.47) + mitt: 3.0.0 + register-service-worker: 1.7.2 + vue: 3.2.47 + vue-router: 4.1.6(vue@3.2.47) + vuepress: 2.0.0-beta.61(@vuepress/client@2.0.0-beta.61)(vue@3.2.47) + vuepress-plugin-sass-palette: 2.0.0-beta.200(vuepress@2.0.0-beta.61) + vuepress-shared: 2.0.0-beta.200(vuepress@2.0.0-beta.61) + workbox-build: 6.5.4 + transitivePeerDependencies: + - '@types/babel__core' + - '@vue/composition-api' + - supports-color + dev: true + + /vuepress-plugin-reading-time2@2.0.0-beta.200(vuepress@2.0.0-beta.61): + resolution: {integrity: sha512-4svs6BowtlSCQcEgRGZmLucsy+DLl25MrSRojuG8rDL8a5UK54XMy5gxUbfPQtoZyJl8vpT7ab86snKQje0V3Q==} + engines: {node: ^14.18.0 || >=16.0.0, npm: '>=8', pnpm: '>=7'} + peerDependencies: + vuepress: 2.0.0-beta.61 + vuepress-vite: 2.0.0-beta.61 + vuepress-webpack: 2.0.0-beta.61 + peerDependenciesMeta: + vuepress: + optional: true + vuepress-vite: + optional: true + vuepress-webpack: + optional: true + dependencies: + vuepress: 2.0.0-beta.61(@vuepress/client@2.0.0-beta.61)(vue@3.2.47) + vuepress-shared: 2.0.0-beta.200(vuepress@2.0.0-beta.61) + transitivePeerDependencies: + - '@vue/composition-api' + - supports-color + dev: true + + /vuepress-plugin-rtl@2.0.0-beta.200(vuepress@2.0.0-beta.61): + resolution: {integrity: sha512-w2qckAlgEW11CtZUvrSaanKL9MQT88SVuNe5FOdiZFK+QRSA3Vsfo8xdLV+JXzEmwnaAnCChvUnOnPrsiFDSGQ==} + engines: {node: ^14.18.0 || >=16.0.0, npm: '>=8', pnpm: '>=7'} + peerDependencies: + vuepress: 2.0.0-beta.61 + vuepress-vite: 2.0.0-beta.61 + vuepress-webpack: 2.0.0-beta.61 + peerDependenciesMeta: + vuepress: + optional: true + vuepress-vite: + optional: true + vuepress-webpack: + optional: true + dependencies: + '@vuepress/client': 2.0.0-beta.61 + '@vuepress/shared': 2.0.0-beta.61 + '@vuepress/utils': 2.0.0-beta.61 + vue: 3.2.47 + vuepress: 2.0.0-beta.61(@vuepress/client@2.0.0-beta.61)(vue@3.2.47) + vuepress-shared: 2.0.0-beta.200(vuepress@2.0.0-beta.61) + transitivePeerDependencies: + - '@vue/composition-api' + - supports-color + dev: true + + /vuepress-plugin-sass-palette@2.0.0-beta.200(vuepress@2.0.0-beta.61): + resolution: {integrity: sha512-yhcm3hvmkj4PlK0bAg1Yebx3RwpOygrOIe1EazqA6phuqUIDcLyHI9x9AUmvEvZ7YHC1B0hiExYdb96UFkYl3w==} + engines: {node: ^14.18.0 || >=16.0.0, npm: '>=8', pnpm: '>=7'} + peerDependencies: + sass-loader: ^13.2.0 + vuepress: 2.0.0-beta.61 + vuepress-vite: 2.0.0-beta.61 + vuepress-webpack: 2.0.0-beta.61 + peerDependenciesMeta: + sass-loader: + optional: true + vuepress: + optional: true + vuepress-vite: + optional: true + vuepress-webpack: + optional: true + dependencies: + '@vuepress/shared': 2.0.0-beta.61 + '@vuepress/utils': 2.0.0-beta.61 + chokidar: 3.5.3 + sass: 1.60.0 + vuepress: 2.0.0-beta.61(@vuepress/client@2.0.0-beta.61)(vue@3.2.47) + vuepress-shared: 2.0.0-beta.200(vuepress@2.0.0-beta.61) + transitivePeerDependencies: + - '@vue/composition-api' + - supports-color + dev: true + + /vuepress-plugin-seo2@2.0.0-beta.200(vuepress@2.0.0-beta.61): + resolution: {integrity: sha512-CC2fCeJT1pTVH+/du7mju8q73aqDOB3JHPjF5QVwamLoWlmQFivgGInFaGtifWMcLNzzeeL5Fgk4OLp+XgGXBw==} + engines: {node: ^14.18.0 || >=16.0.0, npm: '>=8', pnpm: '>=7'} + peerDependencies: + vuepress: 2.0.0-beta.61 + vuepress-vite: 2.0.0-beta.61 + vuepress-webpack: 2.0.0-beta.61 + peerDependenciesMeta: + vuepress: + optional: true + vuepress-vite: + optional: true + vuepress-webpack: + optional: true + dependencies: + '@vuepress/shared': 2.0.0-beta.61 + '@vuepress/utils': 2.0.0-beta.61 + vuepress: 2.0.0-beta.61(@vuepress/client@2.0.0-beta.61)(vue@3.2.47) + vuepress-shared: 2.0.0-beta.200(vuepress@2.0.0-beta.61) + transitivePeerDependencies: + - '@vue/composition-api' + - supports-color + dev: true + + /vuepress-plugin-sitemap2@2.0.0-beta.200(vuepress@2.0.0-beta.61): + resolution: {integrity: sha512-Nbc1w/Ekp8qQdrd08aJqgU2ddQqI/B5+bjO6pdwKfst/c7POteNJYtYgqGVJ8GAxXBqq2xP5W8DgZvuTU7gvPg==} + engines: {node: ^14.18.0 || >=16.0.0, npm: '>=8', pnpm: '>=7'} + peerDependencies: + vuepress: 2.0.0-beta.61 + vuepress-vite: 2.0.0-beta.61 + vuepress-webpack: 2.0.0-beta.61 + peerDependenciesMeta: + vuepress: + optional: true + vuepress-vite: + optional: true + vuepress-webpack: + optional: true + dependencies: + '@vuepress/shared': 2.0.0-beta.61 + '@vuepress/utils': 2.0.0-beta.61 + sitemap: 7.1.1 + vuepress: 2.0.0-beta.61(@vuepress/client@2.0.0-beta.61)(vue@3.2.47) + vuepress-shared: 2.0.0-beta.200(vuepress@2.0.0-beta.61) + transitivePeerDependencies: + - '@vue/composition-api' + - supports-color + dev: true + + /vuepress-shared@2.0.0-beta.200(vuepress@2.0.0-beta.61): + resolution: {integrity: sha512-H4TqjpfMR3MkTlStlSvaun1ZpNdhxgX57zVnatSRk9kSr1+VFcRAqLTvDuaSYlMC7i2DDAPKNReQw18h/OBfDw==} + engines: {node: ^14.18.0 || >=16.0.0, npm: '>=8', pnpm: '>=7'} + peerDependencies: + vuepress: 2.0.0-beta.61 + vuepress-vite: 2.0.0-beta.61 + vuepress-webpack: 2.0.0-beta.61 + peerDependenciesMeta: + vuepress: + optional: true + vuepress-vite: + optional: true + vuepress-webpack: + optional: true + dependencies: + '@vuepress/client': 2.0.0-beta.61 + '@vuepress/shared': 2.0.0-beta.61 + '@vuepress/utils': 2.0.0-beta.61 + '@vueuse/core': 9.13.0(vue@3.2.47) + cheerio: 1.0.0-rc.12 + dayjs: 1.11.7 + execa: 7.1.1 + fflate: 0.7.4 + gray-matter: 4.0.3 + semver: 7.3.8 + striptags: 3.2.0 + vue: 3.2.47 + vue-router: 4.1.6(vue@3.2.47) + vuepress: 2.0.0-beta.61(@vuepress/client@2.0.0-beta.61)(vue@3.2.47) + transitivePeerDependencies: + - '@vue/composition-api' + - supports-color + dev: true + + /vuepress-theme-hope@2.0.0-beta.200(vuepress@2.0.0-beta.61): + resolution: {integrity: sha512-3pg7Ts7JcBqkGFpqT0WnUxgwK1SUWt4NZ/yDPev2P+Vn8RHq7ZRcZxomxN9OgRsOKJSH271IbpSlifmpUyAhSQ==} + engines: {node: ^14.18.0 || >=16.0.0, npm: '>=8', pnpm: '>=7'} + peerDependencies: + sass-loader: ^13.2.0 + vuepress: 2.0.0-beta.61 + vuepress-vite: 2.0.0-beta.61 + vuepress-webpack: 2.0.0-beta.61 + peerDependenciesMeta: + sass-loader: + optional: true + vuepress: + optional: true + vuepress-vite: + optional: true + vuepress-webpack: + optional: true + dependencies: + '@vuepress/cli': 2.0.0-beta.61 + '@vuepress/client': 2.0.0-beta.61 + '@vuepress/core': 2.0.0-beta.61 + '@vuepress/plugin-active-header-links': 2.0.0-beta.61 + '@vuepress/plugin-container': 2.0.0-beta.61 + '@vuepress/plugin-external-link-icon': 2.0.0-beta.61 + '@vuepress/plugin-git': 2.0.0-beta.61 + '@vuepress/plugin-nprogress': 2.0.0-beta.61 + '@vuepress/plugin-palette': 2.0.0-beta.61 + '@vuepress/plugin-prismjs': 2.0.0-beta.61 + '@vuepress/plugin-theme-data': 2.0.0-beta.61 + '@vuepress/shared': 2.0.0-beta.61 + '@vuepress/utils': 2.0.0-beta.61 + '@vueuse/core': 9.13.0(vue@3.2.47) + balloon-css: 1.2.0 + bcrypt-ts: 3.0.0 + cheerio: 1.0.0-rc.12 + chokidar: 3.5.3 + gray-matter: 4.0.3 + vue: 3.2.47 + vue-router: 4.1.6(vue@3.2.47) + vuepress: 2.0.0-beta.61(@vuepress/client@2.0.0-beta.61)(vue@3.2.47) + vuepress-plugin-auto-catalog: 2.0.0-beta.200(vuepress@2.0.0-beta.61) + vuepress-plugin-blog2: 2.0.0-beta.200(vuepress@2.0.0-beta.61) + vuepress-plugin-comment2: 2.0.0-beta.200(vuepress@2.0.0-beta.61) + vuepress-plugin-components: 2.0.0-beta.200(vuepress@2.0.0-beta.61) + vuepress-plugin-copy-code2: 2.0.0-beta.200(vuepress@2.0.0-beta.61) + vuepress-plugin-copyright2: 2.0.0-beta.200(vuepress@2.0.0-beta.61) + vuepress-plugin-feed2: 2.0.0-beta.200(vuepress@2.0.0-beta.61) + vuepress-plugin-md-enhance: 2.0.0-beta.200(vuepress@2.0.0-beta.61) + vuepress-plugin-photo-swipe: 2.0.0-beta.200(vuepress@2.0.0-beta.61) + vuepress-plugin-pwa2: 2.0.0-beta.200(vuepress@2.0.0-beta.61) + vuepress-plugin-reading-time2: 2.0.0-beta.200(vuepress@2.0.0-beta.61) + vuepress-plugin-rtl: 2.0.0-beta.200(vuepress@2.0.0-beta.61) + vuepress-plugin-sass-palette: 2.0.0-beta.200(vuepress@2.0.0-beta.61) + vuepress-plugin-seo2: 2.0.0-beta.200(vuepress@2.0.0-beta.61) + vuepress-plugin-sitemap2: 2.0.0-beta.200(vuepress@2.0.0-beta.61) + vuepress-shared: 2.0.0-beta.200(vuepress@2.0.0-beta.61) + transitivePeerDependencies: + - '@types/babel__core' + - '@vue/composition-api' + - supports-color + dev: true + + /vuepress-vite@2.0.0-beta.61(@vuepress/client@2.0.0-beta.61)(vue@3.2.47): + resolution: {integrity: sha512-4mcR8XSY5b36CYkPqF80WvoeGAEjTw6Cr9bMPHrPVSjG4qqyfVpdSdyRtXD+/5aLJB7r/L60J7PI1pKTci1+3w==} + hasBin: true + peerDependencies: + '@vuepress/client': 2.0.0-beta.61 + vue: ^3.2.47 + dependencies: + '@vuepress/bundler-vite': 2.0.0-beta.61 + '@vuepress/cli': 2.0.0-beta.61 + '@vuepress/client': 2.0.0-beta.61 + '@vuepress/core': 2.0.0-beta.61 + '@vuepress/theme-default': 2.0.0-beta.61 + vue: 3.2.47 + transitivePeerDependencies: + - '@types/node' + - '@vue/composition-api' + - less + - sass + - sass-loader + - stylus + - sugarss + - supports-color + - terser + - ts-node + dev: true + + /vuepress@2.0.0-beta.61(@vuepress/client@2.0.0-beta.61)(vue@3.2.47): + resolution: {integrity: sha512-gpttL0x5ZvI9eTyR/pexBknIAcgrdjAWoiJc7OYd4bIVfwlXAb4GO4A2EwRSX+pIaNOWdcd+sfZA86EMEbrtNg==} + dependencies: + vuepress-vite: 2.0.0-beta.61(@vuepress/client@2.0.0-beta.61)(vue@3.2.47) + transitivePeerDependencies: + - '@types/node' + - '@vue/composition-api' + - '@vuepress/client' + - less + - sass + - sass-loader + - stylus + - sugarss + - supports-color + - terser + - ts-node + - vue + dev: true + + /wcwidth@1.0.1: + resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} + dependencies: + defaults: 1.0.4 + dev: true + + /web-worker@1.2.0: + resolution: {integrity: sha512-PgF341avzqyx60neE9DD+XS26MMNMoUQRz9NOZwW32nPQrF6p77f1htcnjBSEV8BGMKZ16choqUG4hyI0Hx7mA==} + dev: true + + /webidl-conversions@4.0.2: + resolution: {integrity: sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==} + dev: true + + /webworkify-webpack@2.1.5: + resolution: {integrity: sha512-2akF8FIyUvbiBBdD+RoHpoTbHMQF2HwjcxfDvgztAX5YwbZNyrtfUMgvfgFVsgDhDPVTlkbb5vyasqDHfIDPQw==} + dev: true + + /whatwg-url@7.1.0: + resolution: {integrity: sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==} + dependencies: + lodash.sortby: 4.7.0 + tr46: 1.0.1 + webidl-conversions: 4.0.2 + dev: true + + /which-boxed-primitive@1.0.2: + resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} + dependencies: + is-bigint: 1.0.4 + is-boolean-object: 1.1.2 + is-number-object: 1.0.7 + is-string: 1.0.7 + is-symbol: 1.0.4 + dev: true + + /which-module@2.0.0: + resolution: {integrity: sha512-B+enWhmw6cjfVC7kS8Pj9pCrKSc5txArRyaYGe088shv/FGWH+0Rjx/xPgtsWfsUtS27FkP697E4DDhgrgoc0Q==} + dev: true + + /which-typed-array@1.1.9: + resolution: {integrity: sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==} + engines: {node: '>= 0.4'} + dependencies: + available-typed-arrays: 1.0.5 + call-bind: 1.0.2 + for-each: 0.3.3 + gopd: 1.0.1 + has-tostringtag: 1.0.0 + is-typed-array: 1.1.10 + dev: true + + /which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + dependencies: + isexe: 2.0.0 + dev: true + + /wicked-good-xpath@1.3.0: + resolution: {integrity: sha512-Gd9+TUn5nXdwj/hFsPVx5cuHHiF5Bwuc30jZ4+ronF1qHK5O7HD0sgmXWSEgwKquT3ClLoKPVbO6qGwVwLzvAw==} + dev: true + + /workbox-background-sync@6.5.4: + resolution: {integrity: sha512-0r4INQZMyPky/lj4Ou98qxcThrETucOde+7mRGJl13MPJugQNKeZQOdIJe/1AchOP23cTqHcN/YVpD6r8E6I8g==} + dependencies: + idb: 7.1.1 + workbox-core: 6.5.4 + dev: true + + /workbox-broadcast-update@6.5.4: + resolution: {integrity: sha512-I/lBERoH1u3zyBosnpPEtcAVe5lwykx9Yg1k6f8/BGEPGaMMgZrwVrqL1uA9QZ1NGGFoyE6t9i7lBjOlDhFEEw==} + dependencies: + workbox-core: 6.5.4 + dev: true + + /workbox-build@6.5.4: + resolution: {integrity: sha512-kgRevLXEYvUW9WS4XoziYqZ8Q9j/2ziJYEtTrjdz5/L/cTUa2XfyMP2i7c3p34lgqJ03+mTiz13SdFef2POwbA==} + engines: {node: '>=10.0.0'} + dependencies: + '@apideck/better-ajv-errors': 0.3.6(ajv@8.12.0) + '@babel/core': 7.21.3 + '@babel/preset-env': 7.20.2(@babel/core@7.21.3) + '@babel/runtime': 7.21.0 + '@rollup/plugin-babel': 5.3.1(@babel/core@7.21.3)(rollup@2.79.1) + '@rollup/plugin-node-resolve': 11.2.1(rollup@2.79.1) + '@rollup/plugin-replace': 2.4.2(rollup@2.79.1) + '@surma/rollup-plugin-off-main-thread': 2.2.3 + ajv: 8.12.0 + common-tags: 1.8.2 + fast-json-stable-stringify: 2.1.0 + fs-extra: 9.1.0 + glob: 7.2.3 + lodash: 4.17.21 + pretty-bytes: 5.6.0 + rollup: 2.79.1 + rollup-plugin-terser: 7.0.2(rollup@2.79.1) + source-map: 0.8.0-beta.0 + stringify-object: 3.3.0 + strip-comments: 2.0.1 + tempy: 0.6.0 + upath: 1.2.0 + workbox-background-sync: 6.5.4 + workbox-broadcast-update: 6.5.4 + workbox-cacheable-response: 6.5.4 + workbox-core: 6.5.4 + workbox-expiration: 6.5.4 + workbox-google-analytics: 6.5.4 + workbox-navigation-preload: 6.5.4 + workbox-precaching: 6.5.4 + workbox-range-requests: 6.5.4 + workbox-recipes: 6.5.4 + workbox-routing: 6.5.4 + workbox-strategies: 6.5.4 + workbox-streams: 6.5.4 + workbox-sw: 6.5.4 + workbox-window: 6.5.4 + transitivePeerDependencies: + - '@types/babel__core' + - supports-color + dev: true + + /workbox-cacheable-response@6.5.4: + resolution: {integrity: sha512-DCR9uD0Fqj8oB2TSWQEm1hbFs/85hXXoayVwFKLVuIuxwJaihBsLsp4y7J9bvZbqtPJ1KlCkmYVGQKrBU4KAug==} + dependencies: + workbox-core: 6.5.4 + dev: true + + /workbox-core@6.5.4: + resolution: {integrity: sha512-OXYb+m9wZm8GrORlV2vBbE5EC1FKu71GGp0H4rjmxmF4/HLbMCoTFws87M3dFwgpmg0v00K++PImpNQ6J5NQ6Q==} + dev: true + + /workbox-expiration@6.5.4: + resolution: {integrity: sha512-jUP5qPOpH1nXtjGGh1fRBa1wJL2QlIb5mGpct3NzepjGG2uFFBn4iiEBiI9GUmfAFR2ApuRhDydjcRmYXddiEQ==} + dependencies: + idb: 7.1.1 + workbox-core: 6.5.4 + dev: true + + /workbox-google-analytics@6.5.4: + resolution: {integrity: sha512-8AU1WuaXsD49249Wq0B2zn4a/vvFfHkpcFfqAFHNHwln3jK9QUYmzdkKXGIZl9wyKNP+RRX30vcgcyWMcZ9VAg==} + dependencies: + workbox-background-sync: 6.5.4 + workbox-core: 6.5.4 + workbox-routing: 6.5.4 + workbox-strategies: 6.5.4 + dev: true + + /workbox-navigation-preload@6.5.4: + resolution: {integrity: sha512-IIwf80eO3cr8h6XSQJF+Hxj26rg2RPFVUmJLUlM0+A2GzB4HFbQyKkrgD5y2d84g2IbJzP4B4j5dPBRzamHrng==} + dependencies: + workbox-core: 6.5.4 + dev: true + + /workbox-precaching@6.5.4: + resolution: {integrity: sha512-hSMezMsW6btKnxHB4bFy2Qfwey/8SYdGWvVIKFaUm8vJ4E53JAY+U2JwLTRD8wbLWoP6OVUdFlXsTdKu9yoLTg==} + dependencies: + workbox-core: 6.5.4 + workbox-routing: 6.5.4 + workbox-strategies: 6.5.4 + dev: true + + /workbox-range-requests@6.5.4: + resolution: {integrity: sha512-Je2qR1NXCFC8xVJ/Lux6saH6IrQGhMpDrPXWZWWS8n/RD+WZfKa6dSZwU+/QksfEadJEr/NfY+aP/CXFFK5JFg==} + dependencies: + workbox-core: 6.5.4 + dev: true + + /workbox-recipes@6.5.4: + resolution: {integrity: sha512-QZNO8Ez708NNwzLNEXTG4QYSKQ1ochzEtRLGaq+mr2PyoEIC1xFW7MrWxrONUxBFOByksds9Z4//lKAX8tHyUA==} + dependencies: + workbox-cacheable-response: 6.5.4 + workbox-core: 6.5.4 + workbox-expiration: 6.5.4 + workbox-precaching: 6.5.4 + workbox-routing: 6.5.4 + workbox-strategies: 6.5.4 + dev: true + + /workbox-routing@6.5.4: + resolution: {integrity: sha512-apQswLsbrrOsBUWtr9Lf80F+P1sHnQdYodRo32SjiByYi36IDyL2r7BH1lJtFX8fwNHDa1QOVY74WKLLS6o5Pg==} + dependencies: + workbox-core: 6.5.4 + dev: true + + /workbox-strategies@6.5.4: + resolution: {integrity: sha512-DEtsxhx0LIYWkJBTQolRxG4EI0setTJkqR4m7r4YpBdxtWJH1Mbg01Cj8ZjNOO8etqfA3IZaOPHUxCs8cBsKLw==} + dependencies: + workbox-core: 6.5.4 + dev: true + + /workbox-streams@6.5.4: + resolution: {integrity: sha512-FXKVh87d2RFXkliAIheBojBELIPnWbQdyDvsH3t74Cwhg0fDheL1T8BqSM86hZvC0ZESLsznSYWw+Va+KVbUzg==} + dependencies: + workbox-core: 6.5.4 + workbox-routing: 6.5.4 + dev: true + + /workbox-sw@6.5.4: + resolution: {integrity: sha512-vo2RQo7DILVRoH5LjGqw3nphavEjK4Qk+FenXeUsknKn14eCNedHOXWbmnvP4ipKhlE35pvJ4yl4YYf6YsJArA==} + dev: true + + /workbox-window@6.5.4: + resolution: {integrity: sha512-HnLZJDwYBE+hpG25AQBO8RUWBJRaCsI9ksQJEp3aCOFCaG5kqaToAYXFRAHxzRluM2cQbGzdQF5rjKPWPA1fug==} + dependencies: + '@types/trusted-types': 2.0.3 + workbox-core: 6.5.4 + dev: true + + /wrap-ansi@6.2.0: + resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} + engines: {node: '>=8'} + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + dev: true + + /wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + dev: true + + /xml-js@1.6.11: + resolution: {integrity: sha512-7rVi2KMfwfWFl+GpPg6m80IVMWXLRjO+PxTq7V2CDhoGak0wzYzFgUY2m4XJ47OGdXd8eLE8EmwfAmdjw7lC1g==} + dependencies: + sax: 1.2.4 + dev: true + + /xmldom-sre@0.1.31: + resolution: {integrity: sha512-f9s+fUkX04BxQf+7mMWAp5zk61pciie+fFLC9hX9UVvCeJQfNHRHXpeo5MPcR0EUf57PYLdt+ZO4f3Ipk2oZUw==} + engines: {node: '>=0.1'} + dev: true + + /y18n@4.0.3: + resolution: {integrity: sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==} + dev: true + + /yallist@3.1.1: + resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} + dev: true + + /yallist@4.0.0: + resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} + dev: true + + /yaml@2.2.1: + resolution: {integrity: sha512-e0WHiYql7+9wr4cWMx3TVQrNwejKaEe7/rHNmQmqRjazfOP5W8PB6Jpebb5o6fIapbz9o9+2ipcaTM2ZwDI6lw==} + engines: {node: '>= 14'} + dev: true + + /yargs-parser@18.1.3: + resolution: {integrity: sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==} + engines: {node: '>=6'} + dependencies: + camelcase: 5.3.1 + decamelize: 1.2.0 + dev: true + + /yargs@15.4.1: + resolution: {integrity: sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==} + engines: {node: '>=8'} + dependencies: + cliui: 6.0.0 + decamelize: 1.2.0 + find-up: 4.1.0 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + require-main-filename: 2.0.0 + set-blocking: 2.0.0 + string-width: 4.2.3 + which-module: 2.0.0 + y18n: 4.0.3 + yargs-parser: 18.1.3 + dev: true + + /zrender@5.4.3: + resolution: {integrity: sha512-DRUM4ZLnoaT0PBVvGBDO9oWIDBKFdAVieNWxWwK0niYzJCMwGchRk21/hsE+RKkIveH3XHCyvXcJDkgLVvfizQ==} + dependencies: + tslib: 2.3.0 + dev: true diff --git a/reference/zilla.yaml/README.md b/reference/zilla.yaml/README.md deleted file mode 100644 index 2a03ab61..00000000 --- a/reference/zilla.yaml/README.md +++ /dev/null @@ -1,18 +0,0 @@ ---- -description: Defines the Zilla runtime engine configuration in zilla.yaml ---- - -# Zilla Runtime Configuration - -The Zilla runtime configuration defines the `bindings`, `guards` and `vaults` used by the Zilla runtime engine. The values of properties in the configuration can be literals, or expressions of the form `${{env.VARIABLE}}` to resolve a local environment variable value instead. - -### Configuration - -#### Properties - -| Name | Type | Description | -| ---------- | ----------------------------------------------------------- | --------------------- | -| `name` | `string` | Namespace name | -| `bindings` | `object` as map of named [`binding`](binding.md) properties | Map of named bindings | -| `guards` | `object` as map of named [`guard`](guard.md) properties | Map of named guards | -| `vaults` | `object` as map of named [vault](vault.md) properties | Map of named vaults | diff --git a/reference/zilla.yaml/binding-amqp.md b/reference/zilla.yaml/binding-amqp.md deleted file mode 100644 index d3a902bc..00000000 --- a/reference/zilla.yaml/binding-amqp.md +++ /dev/null @@ -1,65 +0,0 @@ ---- -description: Zilla runtime amqp binding (incubator) ---- - -# binding (amqp) 🚧 - -Defines a binding with `amqp 1.0` protocol support, with `server` behavior. - -The `server` kind `amqp` binding decodes `amqp 1.0` protocol on the inbound network stream, producing higher level application streams for each `send` or `receive` `link`. - -Conditional routes based on the `link` `address` are used to route these application streams to an `exit` binding. - -## Example - -``` -"amqp_server0": -{ - "type" : "amqp", - "kind": "server", - "routes": - [ - { - "when": - [ - { - "address": "echo", - "capabilities": "send_and_receive" - } - ], - "exit": "echo_server0" - } - ] -} -``` - -## Configuration - -Binding with support for `amqp 1.0` protocol. - -#### Properties - -
Name (* = required)TypeDescriptionRequired
type*const "amqp"Support amqp 1.0 protocoltrue
kind*enum [ "server" ]Behave as an amqp 1.0 servertrue
routesarray of routeConditional amqp-specific routesfalse
exitstringDefault exit binding when no conditional routes are viablefalse
- -### route - -Routes for `amqp 1.0` protocol. - -#### Properties - -| Name (\* = required) | Type | Description | -| -------------------- | ----------------------------------------------------- | ------------------------------------------------------------------ | -| `guarded` | `object` as named map of `string` `array` | List of roles required by each named guard to authorize this route | -| `when` | `array` of [`condition`](binding-amqp.md#condition)`` | List of conditions (any match) to match this route | -| `exit`\* | `string` | Next binding when following this route | - -### condition - -Conditions to match routes for `amqp 1.0` protocol. - -#### Properties - -| Name (\* = required) | Type | Description | -| -------------------- | ------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------ | -| `address` | `string` | Link address | -| `capabilities` |

enum [
"send_only",
"receive_only",
"send_and_receive" ]

|

Send or receive, or both.
Defaults to send_and_receive.

| diff --git a/reference/zilla.yaml/binding-echo.md b/reference/zilla.yaml/binding-echo.md deleted file mode 100644 index 8bcb0cdc..00000000 --- a/reference/zilla.yaml/binding-echo.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -description: Zilla runtime echo binding ---- - -# binding (echo) - -Defines a binding with `echo` protocol support, with `server` behavior. - -The `server` kind `echo` binding reads inbound writes it back to the sender. - -## Example - -``` -"echo_server0": -{ - "type" : "echo", - "kind": "server" -} -``` - -## Configuration - -Binding with support for `echo` protocol. - -#### Properties - -| Name (\* = required) | Type | Description | -| -------------------- | ------------------- | ---------------------------- | -| `type`\* | `const "echo"` | Support `echo` protocol | -| `kind`\* | `enum [ "server" ]` | Behave as an `echo` `server` | - diff --git a/reference/zilla.yaml/binding-fan.md b/reference/zilla.yaml/binding-fan.md deleted file mode 100644 index 1a167d99..00000000 --- a/reference/zilla.yaml/binding-fan.md +++ /dev/null @@ -1,34 +0,0 @@ ---- -description: Zilla runtime fan binding ---- - -# binding (fan) - -Defines a binding with `fan-in` and `fan-out` support, with `server` behavior. - -The `server` kind `fan` binding performs fan-in of data on all inbound network streams, grouping them into a single application stream. Then data received from the application stream is fanned-out to all network streams in the group. - -When the `exit` is an `echo` server binding, the combination reflects all inbound data from each client to all clients. - -## Example - -``` -"fan_server0": -{ - "type" : "fan", - "kind": "server", - "exit": "echo_server0" -} -``` - -## Configuration - -Binding with support for `fan-in` and `fan-out`. - -#### Properties - -| Name (\* = required) | Type | Description | -| -------------------- | ------------------- | -------------------------------------------- | -| `type`\* | `const "fan"` | Support `fan-in` and `fan-out`. | -| `kind`\* | `enum [ "server" ]` | Behave as an `fan-in` and `fan-out` `server` | -| `exit`\* | `string` | Default exit binding | diff --git a/reference/zilla.yaml/binding-filesystem.md b/reference/zilla.yaml/binding-filesystem.md deleted file mode 100644 index 63507e7b..00000000 --- a/reference/zilla.yaml/binding-filesystem.md +++ /dev/null @@ -1,48 +0,0 @@ ---- -description: Zilla runtime filesystem binding ---- - -# binding (filesystem) - -Defines a binding with `filesystem` support, with `server` behavior. - -The `server` kind `filesystem` binding provides access to files and directories on the local filesystem, optionally following symbolic links. - -Behaves as a web server when combined with `tcp,` `tls`, `http` and `http-filesystem` bindings. - -## Example - -``` -"filesystem_server0": -{ - "type" : "filesystem", - "kind": "server", - "options": - { - "location": "web/" - } -} -``` - -## Configuration - -Binding with support for `filesystem`. - -#### Properties - -| Name (\* = required) | Type | Description | -| ------------------------------------------ | -------------------- | ------------------------------------------------ | -| `type`\* | `const "filesystem"` | Support `filesystem` accessfiles and directories | -| `kind`\* | `enum [ "server" ]` | Behave as a `filesystem` `server` | -| [`options`](binding-filesystem.md#options) | `object` | `filesystem`-specifc options | - -### options - -Options for `filesystem` access. - -#### Properties - -| Name (\* = required) | Type | Description | -| -------------------- | ---------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------- | -| `location` | `string` | File system URI or directory name with trailing slash. | -| `symlinks` |

enum [
follow ,
ignore ]

|

How to treat symbolic links.
Defaults to ignore.

| diff --git a/reference/zilla.yaml/binding-http-filesystem.md b/reference/zilla.yaml/binding-http-filesystem.md deleted file mode 100644 index a53440c3..00000000 --- a/reference/zilla.yaml/binding-http-filesystem.md +++ /dev/null @@ -1,83 +0,0 @@ ---- -description: Zilla runtime http-filesystem binding ---- - -# binding (http-filesystem) - -Defines a binding with `http-filesystem` support, with `proxy` behavior. - -The `proxy` kind `http-filesystem` binding adapts `http` data streams into `filesystem` data streams by mapping the path from an inbound `http` `GET` request into a filesystem relative path. - -Behaves as a web server when combined with `tcp,` `tls`, `http` and `filesystem` bindings. - -## Example - -``` -"http_filesystem_proxy0": -{ - "type" : "http-filesystem", - "kind": "proxy", - "routes": - [ - { - "when": - [ - { - "path": "/{path}" - } - ], - "exit": "filesystem_server0", - "with": - { - "path": "${params.path}" - } - } - ] -} -``` - -## Configuration - -Binding with support for adapting `http` data streams into `filesystem` data streams. - -#### Properties - -| Name (\* = required) | Type | Description | -| -------------------- | -------------------------------------------------------- | ---------------------------------------------------------- | -| `type`\* | `const "http-filesystem"` | Adapt `http` data streams into `filesystem` data streams | -| `kind`\* | `enum [ "proxy" ]` | Behave as an `http-filesystem` `proxy` | -| `routes` | `array` of [`route`](binding-http-filesystem.md#route)`` | Conditional `http-kafka`-specific routes | -| `exit` | `string` | Default exit binding when no conditional routes are viable | - -### route - -Routes for adapting `http` data streams into `filesystem` data streams. - -#### Properties - -| Name (\* = required) | Type | Description | -| -------------------- | -------------------------------------------------------------- | ------------------------------------------------------------------ | -| `guarded` | `object` as named map of `string` `array` | List of roles required by each named guard to authorize this route | -| `when` | `array` of [`condition`](binding-http-filesystem.md#condition) | List of conditions (any match) to match this route | -| `exit`\* | `string` | Next binding when following this route | -| `with` | [`with`](binding-http-filesystem.md#with) | Filesystem parameters used when following this route | - -### condition - -HTTP conditions to match routes when adapting `http` data streams into `filesystem` data streams. - -#### Properties - -| Name (\* = required) | Type | Description | -| -------------------- | -------- | -------------------------------------------------------------- | -| `path`\* | `string` | Path with optional embedded parameter names, such as `/{path}` | - -### with - -Filesystem parameters from matched route when adapting `http` data streams into `filesystem` data streams. - -#### Properties - -| Name (\* = required) | Type | Description | -| -------------------- | -------- | -------------------------------------------------------------------------- | -| `path`\* | `string` | Topic name, optionally referencing path parameter such as `${params.path}` | diff --git a/reference/zilla.yaml/binding-http-kafka.md b/reference/zilla.yaml/binding-http-kafka.md deleted file mode 100644 index 0e0bae88..00000000 --- a/reference/zilla.yaml/binding-http-kafka.md +++ /dev/null @@ -1,249 +0,0 @@ ---- -description: Zilla runtime http-kafka binding ---- - -# binding (http-kafka) - -Defines a binding with `http-kafka` support, with `proxy` behavior. - -The `proxy` kind `http-kafka` binding adapts `http` request-response streams to `kafka` topic streams. - -#### Fetch capability - -Routes with `fetch` capability map `http` `GET` requests to a `kafka` log-compacted topic, supporting filtered retrieval of messages with a specific key, or unfiltered retrieval of all messages with distinct keys in the topic merged into a unified response. - -Filtering can be performed by `kafka` message key, message headers, or a combination of both message key and headers, extracting the parameter values from the inbound `http` request path. - -Status `200` `http` responses include an `etag` header that can be used with `if-none-match` for subsequent conditional `GET` requests to check for updates. Rather than polling, `http` requests can also include the `prefer: wait=N` header to wait a maximum of `N` seconds before responding with `304` if not modified. When a new message arrives in the topic that would modify the response, then all `prefer: wait=N` clients receive the response immediately. - -#### Produce capability - -Routes with `produce` capability map any `http` request-response to a correlated pair of `kafka` messages. The `http` request message is sent to a `requests` topic, with a `zilla:correlation-id` header. When the request message received and processed by the `kafka` `requests` topic consumer, it produces a response message to the `responses` topic, with the same `zilla:correlation-id` header to correlate the response. - -Requests including an `idempotency-key` `http` header can be replayed and safely receive the same response. This requires the `kafka` consumer to detect and ignore the duplicate request with the same `idempotency-key` and `zilla:correlation-id`. - -Specifying `async` allows clients to include a `prefer: respond-async` header in the `http` request to receive `202 Accepted` response with `location` response header. - -A corresponding `route` `condition` with matching `GET` method and `location` path is also required for follow up `GET` requests to return the same response as would have been returned if `prefer: respond-async` request header had been omitted. - -## Example - -``` -"http_kafka_proxy0": -{ - "type" : "http-kafka", - "kind": "proxy", - "routes": - [ - { - "when": - [ - { - "method": "GET", - "path": "/items" - } - ], - "exit": "kafka_cache_client0", - "with": - { - "capability": "fetch", - "topic": "items-snapshots", - "merge": - { - "content-type": "application/json" - } - } - }, - { - "exit": "kafka_cache_client0", - "when": - [ - { - "method": "GET", - "path": "/items/{id}" - } - ], - "with": - { - "capability": "fetch", - "topic": "items-snapshots", - "filters": - [ - { - "key": "${params.id}" - } - ] - } - }, - { - "when": - [ - { - "path": "/items/{id}" - }, - { - "method": "GET", - "path": "/items/{id};{correlationId}" - }, - ], - "exit": "kafka_cache_client0", - "with": - { - "capability": "produce", - "topic": "items-requests", - "acks": "leader_only", - "key": "${params.id}", - "reply-to": "items-responses", - "async": - { - "location": "/items/${params.id};${correlationId}" - } - } - } - ] -} -``` - -## Configuration - -Binding with support for adapting `http` request-response streams to `kafka` topic streams. - -#### Properties - -| Name (\* = required) | Type | Description | -| ------------------------------------------ | ------------------------------------------------- | -------------------------------------------------------------- | -| `type`\* | `const "http-kafka"` | Adapt `http` request-response streams to `kafka` topic streams | -| `kind`\* | `enum [ "proxy" ]` | Behave as an `http-kafka` `proxy` | -| [`options`](binding-http-kafka.md#options) | `object` | `http-kafka`-specific options | -| `routes` | `array` of [`route`](binding-http-kafka.md#route) | Conditional `http-kafka`-specific routes | -| `exit` | `string` | Default exit binding when no conditional routes are viable | - -### options - -Options for adapting `http` request-response streams to `kafka` topic streams. - -#### Properties - -| Name (\* = required) | Type | Description | -| -------------------------------------------------- | -------- | -------------------------------- | -| [`idempotency`](binding-http-kafka.md#idempotency) | `object` | Idempotency key | -| [`correlation`](binding-http-kafka.md#correlation) | `object` | Correlate requests and responses | - -### idempotency - -HTTP request header used to specify the idempotency key when adapting `http` request-response streams to `kafka` topic streams. - -#### Properties - -| Name (\* = required) | Type | Description | -| -------------------- | -------- | ----------------------------------------------------------------------------------------------------- | -| `header` | `string` |

HTTP request header name for idempotency key

Defaults to "idempotency-key"

| - -### correlation - -Kafka request message headers injected when adapting `http` request-response streams to `kafka` topic streams. - -#### Properties - -| Name (\* = required) | Type | Description | -| ------------------------------------------ | -------- | ------------------- | -| [`headers`](binding-http-kafka.md#headers) | `object` | Correlation headers | - -### headers - -Kafka request message reply to and correlation id header names injected when adapting `http` request-response streams to `kafka` topic streams. - -#### Properties - -| Name (\* = required) | Type | Description | -| -------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------- | -| `reply-to` | `string` |

Kafka header name for reply-to topic.
Defaults to "zilla:reply-to".

| -| `correlation-id` | `string` |

Kafka header name for request-response correlation identifier.
Defaults to "zilla:correlation-id".

| - -### route - -Routes for adapting `http` request-response streams to `kafka` topic streams. - -#### Properties - -| Name (\* = required) | Type | Description | -| -------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------- | -| `guarded` | `object` as named map of `string` `array` | Roles required by named guard | -| `when` | `array` of [`condition`](binding-http-kafka.md#condition)`` |

List of conditions
(any match)

| -| `exit`\* | `string` | List of conditions (any match) to match this route | -| `with` |

with (fetch) |
with (produce)

| Kafka parameters used when following this route | - -### condition - -Conditions to match routes for adapting `http` request-response streams to `kafka` topic streams. - -#### Properties - -| Name (\* = required) | Type | Description | -| -------------------- | -------- | --------------------------------------------------------------- | -| `method` | `string` | Method, such as `GET`. | -| `path` | `string` | Path with optional embedded parameter names, such as `/{topic}` | - -### with (fetch) - -Kafka parameters for matched route when adapting `http` request-response streams to `kafka` topic fetch streams. - -#### Properties - -| Name (\* = required) | Type | Description | -| -------------------------------------- | --------------------------------------------------- | --------------------------------------------------------------------------- | -| `capability` | `const "fetch"` | Fetch capability | -| `topic` | `string` | Topic name, optionally referencing path parameter such as `${params.topic}` | -| `filters` | `array` of [`filter`](binding-http-kafka.md#filter) | List of criteria (any match) | -| [`merge`](binding-http-kafka.md#merge) | `object` | Merge multiple Kafka messages into a unified HTTP response. | - -### filter - -Kafka filters for matched route when adapting `http` request-response streams to `kafka` topic fetch streams. - -All specified headers and key must match for the combined criteria to match. - -#### Properties - -| Name (\* = required) | Type | Description | -| -------------------- | -------- | --------------------------------------------------------------------------------------------- | -| `key` | `string` | Message key, optionally referencing path parameter such as `${params.key}` | -| `headers` | `object` | Message headers, with value optionally referencing path parameter such as `${params.headerX}` | - -### merge - -Kafka merge configuration for matched route when adapting `http` request-response streams to `kafka` topic streams where all messages are fetched and must be merged into a unified `http` response. - -#### Properties - -| Name (\* = required) | Type | Description | -| ------------------------------------------------------- | -------------------------- | ------------------------------------------------------------------------------------------------------------ | -| `content-type` | `const "application/json"` | Content type of merged HTTP response. | -| [`patch`](binding-http-kafka.md#patch-application-json) | `object` | Describes how to patch initial HTTP response to include one or more Kafka messages in unified HTTP response. | - -### patch (application/json) - -Kafka merge patch configuration for matched route when adapting `http` request-response streams to `kafka` topic streams where all messages are fetched and must be merged into a unified `http` response. - -#### Properties - -| Name (\* = required) | Type | Description | -| -------------------- | -------------------------------------------------------- | ----------------------------------------------------------------------- | -| `initial` |

string

const "[]"

| Initial JSON value. | -| `path` |

string
const "/-"

| JSON Patch path to include each Kafka message in unified HTTP response. | - -### with (produce) - -Kafka parameters from matched route when adapting `http` request-response streams to `kafka` topic produce streams. - -#### Properties - -| Name (\* = required) | Type | Description | -| -------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------- | -| `capability` | `const "produce"` | Produce capability. | -| `topic` | `string` | Kafka topic name, optionally referencing path parameter such as `${params.topic}` | -| `acks` |

enum [
"none" ,
"leader_only" ,
"in_sync_replicas" ]

|

Kafka acknowledgement mode

Defaults to in_sync_replicas.

| -| `key` | `string` | Kafka message key, optionally referencing path parameter such as `${params.id}` | -| `overrides` | `object` | Kafka message headers, with values optionally referencing path parameter. | -| `reply-to` | `string` | Kafka reply-to topic name. | -| `async` | `object` | HTTP response headers, with values optionally referencing path parameter or `${correlationId}` | diff --git a/reference/zilla.yaml/binding-http.md b/reference/zilla.yaml/binding-http.md deleted file mode 100644 index 2f02f597..00000000 --- a/reference/zilla.yaml/binding-http.md +++ /dev/null @@ -1,186 +0,0 @@ ---- -description: Zilla runtime http binding ---- - -# binding (http) - -Defines a binding with `http` protocol support, with `server` or `client` behavior. - -#### Server behavior - -The `server` kind `http` binding decodes `HTTP/1.1` protocol or `HTTP/2` protocol on the inbound network stream, producing higher level application streams for each request. - -Cross-Origin Resource Sharing (CORS) is supported by specifying an access control policy of `cross-origin`. Further configuration allows for finer-grained access control including specific request origins, methods and headers allowed, and specific response headers exposed. - -Authorization is enforced by a [`guard`](guard.md) and the credentials can be extracted from a cookie, header or query parameter. - -Conditional routes based on `http` request headers are used to route these application streams to an `exit` binding. - -#### Client behavior - -The `client` kind `http` binding receives inbound application streams and encodes each request as a network stream via `HTTP/1.1` protocol. Note that the same network stream can be reused to encode multiple `HTTP/1.1` requests. - -Conditional routes based on `http` request headers are used to route these network streams to an `exit` binding. - -## Example - -``` -"http_server0": -{ - "type" : "http", - "kind": "server", - "options": - { - "access-control": - { - "policy": "cross-origin" - }, - "authorization": - { - "jwt0": - { - "credentials": - { - "headers": - { - "authorization": "Bearer {credentials}" - } - } - } - } - }, - "routes": - [ - { - "when": - [ - { - "headers": - { - ":scheme": "https", - ":authority": "example.com:443" - } - } - ], - "exit": "echo_server0" - } - ] -} -``` - -## Configuration - -Binding with support for `http` protocol. - -#### Properties - -| Name (\* = required) | Type | Description | -| ------------------------------------ | ----------------------------------------------------------------------------------------- | ---------------------------------------------------------- | -| `type`\* | `const "http"` | Support `http` protocol | -| `kind`\* |

enum [

"server",

"client" ]

| Behave as an `http` `server` or `client` | -| [`options`](binding-http.md#options) | `object` | `http`-specifc options | -| `routes` | `array` of [`route`](binding-http.md#route) | Conditional `http`-specific routes | -| `exit` | `string` | Default exit binding when no conditional routes are viable | - -### options - -Options for `HTTP` protocol. - -#### Properties - -| Name (\* = required) | Type | Description | -| -------------------------------------------------- | ------------------------------------------------------------------------------------------------------- | --------------------------- | -| `versions` |

array of enum [
"http/1.1",
"h2" ]

| Supported protocol versions | -| [`access-control`](binding-http.md#access-control) | `object` | Access control policy | -| `authorization` | `object` as map of named [`authorization`](binding-http.md#authorization) properties | Authorization by guard | -| `overrides` | `object` of name-value header overrides | Request header overrides | - -### access-control - -Access control for `HTTP` protocol. - -#### Properties - -| Name (\* = required) | Type | Description | -| -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------- | -| `policy`\* |

enum [
"same-origin" ,
"cross-origin" ]

| Supported access control policies | - -### access-control (cross-origin) - -Cross Origin Resource Sharing (CORS) access control for `HTTP` protocol. - -#### Properties - -| Name (\* = required) | Type | Description | -| -------------------------------------- | ---------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `policy`\* | `const "cross-origin"` | Support cross-origin access control policy | -| ``[`allow`](binding-http.md#allow)`` | `object` |

Allowed cross-origin request origins, methods, headers and credentials.

Defaults to all origins, methods and headers, without credentials.

| -| `max-age` | `number` | Maximum cache age (in seconds) for allowed headers and methods. | -| ``[`expose`](binding-http.md#expose)`` | `object` |

Exposed cross-origin response headers.

Defaults to all response headers.

| - -### allow - -CORS allowed request origins, methods, headers and credentials for `HTTP` protocol. - -#### Properties - -| Name (\* = required) | Type | Description | -| -------------------- | ----------------- | ------------------------------------------- | -| `origins` | `array of string` | Allowed request origins. | -| `methods` | `array of string` | Allowed request methods. | -| `headers` | `array of string` | Allowed request headers | -| `credentials` | `boolean` | Support `fetch` credentials mode `include`. | - -### expose - -CORS exposed response headers for `HTTP` protocol. - -#### Properties - -| Name (\* = required) | Type | Description | -| -------------------- | ----------------- | ------------------------ | -| `headers` | `array of string` | Exposed response headers | - -### authorization - -Authorization for `HTTP/1.1` and `HTTP/2` protocols. - -#### Properties - -| Name (\* = required) | Type | Description | -| -------------------------------------------- | -------- | --------------------------------------------------------- | -| [`credentials`](binding-http.md#credentials) | `object` | Defines how to extract credentials from the HTTP request. | - -### credentials - -Credentials for `HTTP` protocol. - -#### Properties - -| Name (\* = required) | Type | Description | -| -------------------- | --------------------------- | -------------------------------------------------------------------------------- | -| `cookies` | `object` as map of `string` | Named cookie value pattern with `{credentials}` | -| `headers` | `object` as map of `string` | Named header value pattern with `{credentials}`, e.g. `"Bearer` `{credentials}"` | -| `query` | `object` as map of `string` | Named query parameter value pattern with `{credentials}` | - -### route - -Routes for `HTTP` protocol. - -#### Properties - -| Name (\* = required) | Type | Description | -| -------------------- | ----------------------------------------------------- | ------------------------------------------------------------------ | -| `guarded` | `object` as named map of `string` `array` | List of roles required by each named guard to authorize this route | -| `when` | `array` of [`condition`](binding-http.md#condition)`` | List of conditions (any match) to match this route | -| `exit`\* | `string` | Next binding when following this route | - -### condition - -Conditions to match routes for `HTTP` protocol. - -#### Properties - -| Name (\* = required) | Type | Description | -| -------------------- | ------------------------------ | --------------------------------------------- | -| `headers` | `object` of name-value headers |

Header name value pairs
(all match)

| diff --git a/reference/zilla.yaml/binding-kafka.md b/reference/zilla.yaml/binding-kafka.md deleted file mode 100644 index 1719d5cf..00000000 --- a/reference/zilla.yaml/binding-kafka.md +++ /dev/null @@ -1,141 +0,0 @@ ---- -description: Zilla runtime kafka binding ---- - -# binding (kafka) - -Defines a binding with `kafka` protocol support, with `cache_client`, `cache_server` or `client` behavior. - -#### Cache behavior - -The `cache_client` and `cache_server` kinds combine to provide a persistent cache of `kafka` messages per `topic` `partition` honoring the `kafka` `topic` configuration for message expiration and compaction. Messages ordering is guaranteed per `partition` and messages are merged into a unified stream for the `topic` spanning all `partitions`. - -The `cache_server` kind supports proactive `fetch` of messages to keep the cache fresh in preparation for new consumers. This is enabled by configuring a list of `bootstrap` topics for the binding. - -The `cache_client` kind supports filtering by `kafka` message key, headers or a combination of key and headers. - -Message conflation occurs implicitly for `compacted` `kafka` topics, where a slower consumer that is not keeping up with the latest messages can safely skip over each older message that has effectively been replaced by a newer message with the same key. - -When a new consumer arrives, the latest messages in the compacted topic are immediately delivered to that consumer, followed by any additional messages as they are produced to the `kafka` `topic`. - -When the `kafka` `topic` is not compacted, then the binding can be configured to either replay historical messages first, or start with upcoming live messages instead. - -The `cache_client` and `cache_server` also combine to provide a staging area when producing new messages as `kafka` requires exact message length up front when producing new messages and `kafka` does not support producing multiple messages in parallel over the same network connection. - -#### Client behavior - -The `client` kind `kafka` binding receives inbound application streams and encodes each as a network stream via `kafka` request-response protocol. Note that the same network stream can be reused to encode multiple `kafka` requests, including both `fetch` and `produce` requests. - -Conditional routes based on `kafka` `topic` names are used to route these network streams to an `exit` binding that ultimately reaches a `kafka` broker. - -## Example - -``` -"kafka_cache_client0": -{ - "type" : "kafka", - "kind": "cache_client", - "options": - { - "merged": - [ - "items-requests", - "items-responses" - ] - }, - "exit": "kafka_cache_server0" -}, - -"kafka_cache_server0": -{ - "type" : "kafka", - "kind": "cache_server", - "options": - { - "bootstrap": - [ - "items-responses" - ] - }, - "exit": "kafka_client0" -}, - -"kafka_client0": -{ - "type" : "kafka", - "kind": "client", - "exit": "tcp_client0" -} -``` - -## Configuration - -Binding with support for `kafka` protocol. - -#### Properties - -| Name (\* = required) | Type | Description | -| ------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------- | -| `type`\* | `const "kafka"` | Support `kafka` protocol | -| `kind`\* |

enum [
"cache_client",
"cache_server",
"client" ]

| Behave as a `kafka` `cache_client`, `cache_server` or `client` | -| [`options`](binding-kafka.md#options) | `object` | `kafka`-specific options | -| `routes` | `array` of [`route`](binding-kafka.md#route) | Conditional `kafka`-specific routes | -| `exit` | `string` | Default exit binding when no conditional routes are viable | - -### options - -Options for `kafka` protocol. - -#### Properties - -| Name (\* = required) | Type | Description | -| ------------------------------- | -------------------------------------------- | -------------------------------------------------------- | -| `bootstrap` | `array` of `string` | Topics to bootstrap in cache server even when no clients | -| `topics` | `array` of [`topic`](binding-kafka.md#topic) | Topic configuration | -| [`sasl`](binding-kafka.md#sasl) | `object` | SASL credentials | - -### topic - -Topic-specific configuration when supporting `kafka` protocol. - -#### Properties - -| Name (\* = required) | Type | Description | -| -------------------- | ------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------- | -| `name`\* | `string` | Topic name | -| `defaultOffset` |

enum [
"live",
"historical" ]

|

Fetch offset to use for new consumers

Defaults to "historical"

| - -### sasl - -SASL credentials to use when connecting to `kafka` brokers. - -#### Properties - -| Name (\* = required) | Type | Description | -| -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------ | -| `name` | `string` | Mechanism name | -| `mechanism`\* |

enum [
"plain",
"scram-sha-1",
"scram-sha-256",
"scram-sha-512" ]

|

SASL mechanism

Supports plain and scram mechanisms

| -| `username` | `string` | SASL username | -| `password` | `string` | SASL password | - -### route - -Routes for `kafka` protocol. - -#### Properties - -| Name (\* = required) | Type | Description | -| -------------------- | ------------------------------------------------------ | ------------------------------------------------------------------ | -| `guarded` | `object` as named map of `string` `array` | List of roles required by each named guard to authorize this route | -| `when` | `array` of [`condition`](binding-kafka.md#condition)`` | List of conditions (any match) to match this route | -| `exit`\* | `string` | Next binding when following this route | - -### condition - -Conditions to match routes for `kafka` protocol. - -#### Properties - -| Name (\* = required) | Type | Description | -| -------------------- | -------- | ------------------ | -| `topic`\* | `string` | Topic name pattern | diff --git a/reference/zilla.yaml/binding-mqtt.md b/reference/zilla.yaml/binding-mqtt.md deleted file mode 100644 index 15045b40..00000000 --- a/reference/zilla.yaml/binding-mqtt.md +++ /dev/null @@ -1,70 +0,0 @@ ---- -description: Zilla runtime mqtt binding (incubator) ---- - -# binding (mqtt) 🚧 - -Defines a binding with `mqtt 5.0` protocol support, with `server` behavior. - -The `server` kind `mqtt` binding decodes `mqtt 5.0` protocol on the inbound network stream, producing higher level application streams for each `publish` or `subscribe` `topic`. - -Conditional routes based on the `topic` `name` are used to route these application streams to an `exit` binding. - -## Example - -``` -"mqtt_server0": -{ - "type" : "mqtt", - "kind": "server", - "routes": - [ - { - "when": - [ - { - "topic": "echo", - "capabilities": "publish_and_subscribe" - } - ], - "exit": "echo_server0" - } - ] -} -``` - -## Configuration - -Binding with support for `mqtt 5.0` protocol. - -#### Properties - -| Name (\* = required) | Type | Description | -| -------------------- | ------------------------------------------- | ---------------------------------------------------------- | -| `type`\* | `const "mqtt"` | Support `mqtt 5.0` protocol | -| `kind`\* | `enum [ "server" ]` | Behave as a `mqtt` `server` | -| `routes` | `array` of [`route`](binding-mqtt.md#route) | Conditional `mqtt`-specific routes | -| `exit` | `string` | Default exit binding when no conditional routes are viable | - -### route - -Routes for `mqtt 5.0` protocol. - -#### Properties - -| Name (\* = required) | Type | Description | -| -------------------- | ----------------------------------------------------- | ------------------------------------------------------------------ | -| `guarded` | `object` as named map of `string` `array` | List of roles required by each named guard to authorize this route | -| `when` | `array` of [`condition`](binding-mqtt.md#condition)`` | List of conditions (any match) to match this route | -| `exit`\* | `string` | Next binding when following this route | - -### condition - -Conditions to match routes for `mqtt 5.0` protocol. - -#### Properties - -| Name (\* = required) | Type | Description | -| -------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------- | -| `topic`\* | `string` | Topic name | -| `capabilities` |

enum [
"publish_only",
"subscribe_only",
"publish_and_subscribe" ]

|

Publish or subscribe, or both.
Defaults to publish_and_subscribe.

| diff --git a/reference/zilla.yaml/binding-proxy.md b/reference/zilla.yaml/binding-proxy.md deleted file mode 100644 index 53910021..00000000 --- a/reference/zilla.yaml/binding-proxy.md +++ /dev/null @@ -1,89 +0,0 @@ ---- -description: Zilla runtime proxy binding ---- - -# binding (proxy) - -Defines a binding with `proxy` protocol support, with `server` or `client` behavior. - -The `server` kind `proxy` binding decodes `Proxy v2` protocol on the inbound network stream, producing higher level application streams for each request. - -The `client` kind `proxy` binding receives inbound application streams and encodes each as a network stream via `Proxy v2` protocol. - -Conditional routes based on the network transport type or network addresses are used to route these streams to an `exit` binding. - -## Example - -``` -"proxy_server0": -{ - "type" : "proxy", - "kind": "server", - "routes": - [ - { - "when": - [ - { - "transport": "stream", - "family": "inet4", - "destination": - { - "port": 443 - } - } - ], - "exit": "tls_server0" - } - ] -} -``` - -## Configuration - -Binding with support for `proxy` protocol. - -#### Properties - -| Name (\* = required) | Type | Description | -| -------------------- | ----------------------------------------------------------------------------------- | ---------------------------------------------------------- | -| `type`\* | `const "proxy"` | Support `proxy` protocol. | -| `kind`\* |

enum [
"client",
"server" ]

| Behave as `proxy` `client` or `server` | -| `routes` | `array` of [`route`](binding-proxy.md#route) | Conditional `proxy`-specific routes | -| `exit` | `string` | Default exit binding when no conditional routes are viable | - -### route - -Routes for `proxy` protocol. - -#### Properties - -| Name | Type | Description | -| --------- | ------------------------------------------------------ | ------------------------------------------------------------------ | -| `guarded` | `object` as named map of `string` `array` | List of roles required by each named guard to authorize this route | -| `when` | `array` of [`condition`](binding-proxy.md#condition)`` | List of conditions (any match) to match this route | -| `exit`\* | `string` | Next binding when following this route | - -### condition - -Conditions to match routes for `proxy` protocol. - -#### Properties - -| Name | Type | Description | -| ------------- | ---------------------------------------------------------------------------------------------------------------------------------------- | ------------------- | -| `transport` |

enum [
"stream",
"datagram" ]

| Transport type | -| `family` |

enum [
"inet",
"inet4",
"inet6",
"unix" ]

| Address family | -| `source` | [`address`](binding-proxy.md#address) | Source address | -| `destination` | [`address`](binding-proxy.md#address) | Destination address | - -### address - -Address for `proxy` protocol. - -#### Properties - -| Name | Type | Description | -| ------ | --------- | ---------------------- | -| `host` | `string` | Hostname or IP address | -| `port` | `integer` | Port number | diff --git a/reference/zilla.yaml/binding-sse-kafka.md b/reference/zilla.yaml/binding-sse-kafka.md deleted file mode 100644 index 72d41d1d..00000000 --- a/reference/zilla.yaml/binding-sse-kafka.md +++ /dev/null @@ -1,119 +0,0 @@ ---- -description: Zilla runtime sse-kafka binding ---- - -# binding (sse-kafka) - -Defines a binding with `sse-kafka` support, with `proxy` behavior. - -The `proxy` kind `sse-kafka` binding adapts `sse` data streams into `kafka` data streams, so that `kafka` messages can be delivered to `sse` clients. - -Filtering can be performed by `kafka` message key, message headers, or a combination of both message key and headers, extracting the parameter values from the inbound `sse` path. - -Progress across `kafka` topic partitions is conveyed to the `sse` client via event `id` and when the stream is implicitly paused during `sse` client reconnect, the `last-event-id` header in the `sse` reconnect request contains the last received event `id` value, allowing the `sse` stream to resume reliable message delivery automatically. - -The event `id` can be configured to include the message `key` and `etag` of each message, avoiding the need to duplicate the key in the message body and making it suitable for integration with `http-kafka` binding's use of `etag` for conditional `if-match` operations. - -When a `kafka` tombstone (`null` value) message is received by the `sse-kafka` binding, it delivers a `delete` event to the `sse` client. This informs the client which specific message has been deleted by observing the message key from the `sse` `delete` event `id`. - -## Example - -``` -"sse_kafka_proxy0": -{ - "type" : "sse-kafka", - "kind": "proxy", - "routes": - [ - { - "when": - [ - { - "path": "/items" - } - ], - "exit": "kafka_cache_client0", - "with": - { - "topic": "items-snapshots", - "event": - { - "id": "[\"${base64(key)}\",\"${etag}\"]" - } - } - } - ] -} -``` - -## Configuration - -Binding with support for adapting `sse` data streams to `kafka` data streams. - -#### Properties - -| Name (\* = required) | Type | Description | -| -------------------- | ------------------------------------------------ | ---------------------------------------------------------- | -| `type`\* | `const "sse-kafka"` | Adapt `sse` data streams to `kafka` data streams | -| `kind`\* | `enum [ "proxy" ]` | Behave as a `sse-kafka` `proxy` | -| `routes` | `array` of [`route`](binding-sse-kafka.md#route) | Conditional `sse-kafka`-specific routes | -| `exit` | `string` | Default exit binding when no conditional routes are viable | - -### route - -Routes for adapting `sse` data streams to `kafka` data streams. - -#### Properties - -| Name (\* = required) | Type | Description | -| -------------------- | ---------------------------------------------------------- | ------------------------------------------------------------------ | -| `guarded` | `object` as named map of `string` `array` | List of roles required by each named guard to authorize this route | -| `when` | `array` of [`condition`](binding-sse-kafka.md#condition)`` | List of conditions (any match) to match this route | -| `exit`\* | `string` | Next binding when following this route | -| `with` | [`with`](binding-sse-kafka.md#with) | Kafka parameters used when following this route | - -### condition - -Conditions to match routes for adapting `sse` data streams to `kafka` data streams. - -#### Properties - -| Name (\* = required) | Type | Description | -| -------------------- | -------- | --------------------------------------------------------------- | -| `path`\* | `string` | Path with optional embedded parameter names, such as `/{topic}` | - -### with - -Kafka parameters for matched route when adapting `sse` data streams to `kafka` data streams. - -#### Properties - -| Name (\* = required) | Type | Description | -| ----------------------------------------- | -------------------------------------------------- | --------------------------------------------------------------------------- | -| `topic`\* | `string` | Topic name, optionally referencing path parameter such as `${params.topic}` | -| `filters` | `array` of [`filter`](binding-sse-kafka.md#filter) | List of criteria (any match) | -| ``[`event`](binding-sse-kafka.md#event)`` | `object` | Defines the syntax of the `event` `id` | - -### filter - -Kafka filters for matched route when adapting `sse` data streams to `kafka` data streams. - -All specified headers and key must match for the combined criteria to match. - -#### Properties - -| Name (\* = required) | Type | Description | -| -------------------- | -------- | --------------------------------------------------------------------------------------------- | -| `key` | `string` | Message key, optionally referencing path parameter such as `${params.key}` | -| `headers` | `object` | Message headers, with value optionally referencing path parameter such as `${params.headerX}` | - -### event - -SSE event syntax used when delivering Kafka messages to SSE clients. - -#### Properties - -| Name (\* = required) | Type | Description | -| -------------------- | ------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------- | -| `id`\* |

enum [
"${etag}",
"[\"${base64(key)}\",\"${etag}\"]"
]

|

Format of id field in sse event

Defaults to "${etag}"

| - diff --git a/reference/zilla.yaml/binding-sse.md b/reference/zilla.yaml/binding-sse.md deleted file mode 100644 index 8d84e78b..00000000 --- a/reference/zilla.yaml/binding-sse.md +++ /dev/null @@ -1,68 +0,0 @@ ---- -description: Zilla runtime sse binding ---- - -# binding (sse) - -Defines a binding with `Server Sent Events (sse)` protocol support, with `server` behavior. - -The `server` kind `sse` binding converts inbound `http` request-response streams into `sse` request-response streams, with optionally configured `retry` delay. - -Messages received on the `sse` response stream are encoded using `Server Sent Events` protocol, including support for custom `event` types and last event `id`. - -## Example - -``` -"sse_server0": -{ - "type" : "sse", - "kind": "server", - "exit": "sse_kafka_proxy0" -} -``` - -## Configuration - -Binding with support for `sse` protocol. - -#### Properties - -| Name (\* = required) | Type | Description | -| ----------------------------------- | ----------------------------------------------------------------------------------- | ---------------------------------------------------------- | -| `type`\* | `const "sse"` | Support `sse` protocol | -| `kind`\* |

enum [
"client",
"server" ]

| Behave as a `sse` `client` or `server` | -| [`options`](binding-sse.md#options) | `object` | `sse`-specific options | -| `routes` | `array` of [`route`](binding-sse.md#route) | Conditional `sse`-specific routes | -| `exit` | `string` | Default exit binding when no conditional routes are viable | - -### options - -Options for `sse` protocol. - -#### Properties - -| Name (\* = required) | Type | Description | -| -------------------- | --------- | ------------------------------------------------------------ | -| `retry` | `integer` |

Retry delay (ms)

Defaults to 2000

| - -### route - -Routes for `sse` protocol. - -#### Properties - -| Name (\* = required) | Type | Description | -| -------------------- | ---------------------------------------------------- | ------------------------------------------------------------------ | -| `guarded` | `object` as named map of `string` `array` | List of roles required by each named guard to authorize this route | -| `when` | `array` of [`condition`](binding-sse.md#condition)`` | List of conditions (any match) to match this route | -| `exit`\* | `string` | Next binding when following this route | - -### condition - -Conditions to match routes for `sse` protocol. - -#### Properties - -| Name (\* = required) | Type | Description | -| -------------------- | -------- | ------------ | -| `path`\* | `string` | Path pattern | diff --git a/reference/zilla.yaml/binding-tcp.md b/reference/zilla.yaml/binding-tcp.md deleted file mode 100644 index 6410d616..00000000 --- a/reference/zilla.yaml/binding-tcp.md +++ /dev/null @@ -1,77 +0,0 @@ ---- -description: Zilla runtime tcp binding ---- - -# binding (tcp) - -Defines a binding with `tcp` protocol support, with `server` or `client` behavior. - -The `server` kind `tcp` binding listens for inbound socket connections, producing higher level application streams for each remote `tcp` client. - -The `client` kind `tcp` binding receives inbound application streams and initiates outbound `tcp` network connections to a remote `tcp` server address. - -Conditional routes based on the hostname authority and network address mask are used to route these streams to an `exit` binding. - -## Example - -``` -"tcp_server0": -{ - "type" : "tcp", - "kind": "server", - "options": - { - "host": "0.0.0.0", - "port": 12345 - }, - "exit": "echo_server0" -} -``` - -## Configuration - -Binding with support for `tcp` protocol. - -#### Properties - -| Name (\* = required) | Type | Description | -| ----------------------------------- | ----------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------- | -| `type`\* | `const "tcp"` | Support `tcp` protocol | -| `kind`\* |

enum [
"client",
"server" ]

| Behave as a `tcp` `client` or `server` | -| [`options`](binding-tcp.md#options) | `object` | `tcp`-specific options | -| `routes` | `array` of [`route`](binding-tcp.md#route) | Conditional `tcp`-specific routes | -| `exit` | `string` | Default exit binding when no conditional routes are viable, for kind `server` only | - -### options - -Options for `tcp` protocol. - -#### Properties - -| Name (\* = required) | Type | Description | -| -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------- | -| `host` | `string` | Hostname or IP address | -| `port` |

integer |
string |
array of integer |
array of string

| Port number(s), including port number ranges. | - -### route - -Routes for `tcp` protocol. - -#### Properties - -| Name (\* = required) | Type | Description | -| -------------------- | ---------------------------------------------------- | ------------------------------------------------------------------ | -| `guarded` | `object` as named map of `string` `array` | List of roles required by each named guard to authorize this route | -| `when` | `array` of [`condition`](binding-tcp.md#condition)`` | List of conditions (any match) to match this route | -| `exit`\* | `string` | Next binding when following this route, for kind `server` only | - -### condition - -Conditions to match routes for `tcp` protocol. - -#### Properties - -| Name (\* = required) | Type | Description | -| -------------------- | -------- | -------------------- | -| `authority` | `string` | Associated authority | -| `cidr` | `string` | CIDR mask | diff --git a/reference/zilla.yaml/binding-tls.md b/reference/zilla.yaml/binding-tls.md deleted file mode 100644 index 37bb4e7e..00000000 --- a/reference/zilla.yaml/binding-tls.md +++ /dev/null @@ -1,113 +0,0 @@ ---- -description: Zilla runtime tls binding ---- - -# binding (tls) - -Defines a binding with `tls` protocol support, with `server`, `client` or `proxy` behavior. - -#### Server behavior - -The `server` kind tls binding decodes encrypted `TLS` protocol protocol on the inbound network stream, producing higher level cleartext application streams for each request. - -Certificates and keys required to complete the `TLS` handshake are provided by a `vault` referenced in the binding configuration. - -Conditional routes based on `tls` hostname authority or negotiated ALPN protocol are used to route these streams to an `exit` binding. - -#### Client behavior - -The `client` kind `tls` binding receives inbound application streams and encodes each as an encrypted network stream via `TLS` protocol. - -Certificates and keys required to complete the `TLS` handshake are provided by a `vault` referenced in the binding configuration. - -Conditional routes based on `tls` hostname authority or negotiated ALPN protocol are used to route these streams to an `exit` binding. - -#### Proxy behavior - -The `proxy` kind `tls` binding detects `ClientHello` `server_name` extension to provide TLS virtual hosting by routing based on server name. - -A `vault` is not required to proxy `TLS` protocol as the handshake is only observed read-only as it routes through the `tls` `proxy` binding. - -## Example - -``` -"tls_server0": -{ - "type" : "tls", - "kind": "server", - "vault": "server", - "options": - { - "keys": [ "localhost" ], - "sni": [ "localhost" ], - "alpn": [ "echo" ] - }, - "routes": - [ - { - "when": - [ - { - "alpn": "echo" - } - ], - "exit": "echo_server0" - } - ] -} -``` - -## Configuration - -Binding with support for `tls` protocol. - -#### Properties - -| Name (\* = required) | Type | Description | -| ----------------------------------- | -------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------- | -| `type`\* | `const "tls"` | Support `tls` protocol | -| `kind`\* |

enum [
"client",
"server",
"proxy" ]

| Behave as a `tls` `client`, `server` or `proxy` | -| `vault` | `string` | Vault name | -| [`options`](binding-tls.md#options) | `object` | `tls`-specific options | -| `routes` | `array` of [`route`](binding-tls.md#route) | Conditional `tls`-specific routes | -| `exit` | `string` | Default exit binding when no conditional routes are viable | - -### options - -Options for `tls` protocol. - -#### Properties - -| Name (\* = required) | Type | Description | -| -------------------- | ---------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------- | -| `version` | `string` | Protocol version | -| `keys` | `array` of `string` | Vault key refs | -| `trust` | `array` of `string` | Vault certificate refs | -| `signers` | `array` of `string` | Vault signer certificate refs | -| `trustcacerts` | `boolean` | Trust CA certificates | -| `sni`\* | `array` of `string` | Server names | -| `alpn` | `array` of `string` | Application protocols | -| `mutual` |

enum [
"required",
"requested",
"none"
]

|

Mutual authentication

Defaults to none

| - -### route - -Routes for `tls` protocol. - -#### Properties - -| Name (\* = required) | Type | Description | -| -------------------- | ---------------------------------------------------- | ------------------------------------------------------------------ | -| `guarded` | `object` as named map of `string` `array` | List of roles required by each named guard to authorize this route | -| `when` | `array` of [`condition`](binding-tls.md#condition)`` | List of conditions (any match) to match this route | -| `exit`\* | `string` | Next binding when following this route | - -### condition - -Conditions to match routes for `tls` protocol. - -#### Properties - -| Name | Type | Description | -| ----------- | -------- | -------------------- | -| `authority` | `string` | Associated authority | -| `alpn` | `string` | Application protocol | diff --git a/reference/zilla.yaml/binding-ws.md b/reference/zilla.yaml/binding-ws.md deleted file mode 100644 index 7bc3ce2e..00000000 --- a/reference/zilla.yaml/binding-ws.md +++ /dev/null @@ -1,103 +0,0 @@ ---- -description: Zilla runtime ws binding ---- - -# binding (ws) - -Defines a binding with `WebSockets` protocol support, with `server` or `client` behavior. - -#### Server behavior - -The `server` kind `ws` binding converts inbound `http` request-response streams into `ws` full-duplex streams. - -Conditional routes based on `ws` scheme, authority, path or negotiated subprotocol are used to route these streams to an `exit` binding. - -#### Client behavior - -The `client` kind `ws` binding converts inbound `ws` full duplex streams into `http` request-response streams. - -Conditional routes based on `ws` scheme, authority, path or negotiated subprotocol are used to route these streams to an `exit` binding. - -## Example - -``` -"ws_server0": -{ - "type" : "ws", - "kind": "server", - "routes": - [ - { - "when": - [ - { - "protocol": "echo" - } - ], - "exit": "echo_server0" - } - ] -} -``` - -## Configuration - -Binding with support for `ws` protocol. - -#### Properties - -| Name (\* = required) | Type | Description | -| ---------------------------------- | ----------------------------------------------------------------------------------- | ---------------------------------------------------------- | -| `type`\* | `const "ws"` | Support `ws` protocol | -| `kind`\* |

enum [
"client",
"server" ]

| Behave as a `ws` `client` or `server` | -| [`options`](binding-ws.md#options) | `object` | `ws`-specific options | -| `routes` | `array` of [`route`](binding-ws.md#route) | Conditional `ws`-specific routes | -| `exit` | `string` | Default exit binding when no conditional routes are viable | - -### options - -Options for `ws` protocol. - -#### Properties - -| Name (\* = required) | Type | Description | -| ------------------------------------ | -------- | ----------- | -| [`defaults`](binding-ws.md#defaults) | `object` | Defaults | - -### defaults - -Defaults option for `ws` protocol. - -#### Properties - -| Name (\* = required) | Type | Description | -| -------------------- | -------- | ----------- | -| `protocol` | `string` | Subprotocol | -| `scheme` | `string` | Scheme | -| `authority` | `string` | Authority | -| `path` | `string` | Path | - -### route - -Routes for `ws` protocol. - -#### Properties - -| Name (\* = required) | Type | Description | -| -------------------- | ------------------------------------------------- | ------------------------------------------------------------------ | -| `guarded` | `object` as named map of `string` `array` | List of roles required by each named guard to authorize this route | -| `when` | `array` of [`condition`](binding-ws.md#condition) | List of conditions (any match) to match this route | -| `exit`\* | `string` | Next binding when following this route | - -### condition - -Conditions to match routes for `ws` protocol. - -#### Properties - -| Name (\* = required) | Type | Description | -| -------------------- | -------- | ------------------- | -| `protocol` | `string` | Subprotocol pattern | -| `scheme` | `string` | Scheme pattern | -| `authority` | `string` | Authority pattern | -| `path` | `string` | Path pattern | diff --git a/reference/zilla.yaml/binding.md b/reference/zilla.yaml/binding.md deleted file mode 100644 index f17305fc..00000000 --- a/reference/zilla.yaml/binding.md +++ /dev/null @@ -1,32 +0,0 @@ ---- -description: Zilla runtime bindings ---- - -# binding - -Each configured `binding` represents a step in the pipeline as data streams are decoded, translated or encoded according to a specific protocol `type`. - -A `binding` also has a `kind`, indicating how it should behave, such as `server`, `proxy` or `client`. - -As each incoming data stream arrives, the binding follows its configured `routes` to reach an `exit` binding, or rejects the stream if no routes are viable. Route matching conditions are defined in terms specific to each `binding` type. - -See each of the specific `binding` types linked below for more detailed examples. - -### Configuration - -Each runtime `binding` has a behavioral type supporting either encoding and decoding for a specific protocol or translation between protocols. - -#### Properties (generic) - -| Name | Type | Description | -| ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- | -| `type` |

enum [
"amqp" ,
"echo" ,
"fan" ,
"filesystem" ,
"http" ,

"http-filesystem" ,
"http-kafka" ,

"kafka" ,
"mqtt" ,
"proxy" ,
"sse" ,

"sse-kafka" ,
"tcp" ,
"tls" ,
"ws" ]

| Behavioral type supporting either encoding and decoding for a specific protocol or translation between protocols | - -#### Properties (type-specific) - -| Name | Type | Description | -| --------- | ------------------ | --------------------------------------------------------------------------------------------- | -| `kind` | `string` | Behavioral kind such as `server`, `client` or `proxy` | -| `options` | `object` | Type-specific options to configure the binding | -| `routes` | `array` of `route` | Type-specific conditional routing rules to reach an `exit` binding | -| `exit` | `string` | Unconditional `exit` binding acting as a default if none of the conditional routes are viable | diff --git a/reference/zilla.yaml/guard-jwt.md b/reference/zilla.yaml/guard-jwt.md deleted file mode 100644 index 7e0a898a..00000000 --- a/reference/zilla.yaml/guard-jwt.md +++ /dev/null @@ -1,85 +0,0 @@ ---- -description: Zilla runtime jwt guard ---- - -# guard (jwt) - -Defines a guard with `JSON Web Token (JWT)` support. - -The `jwt` guard uses public keys to verify the integrity of `JWT` access tokens when identifying authorized subjects and their associated roles scope. The token issuer and audience can also be constrained to prevent access tokens from other applications from being reused inappropriately. - -Each verified JWT access token has an expiration time, and an optional challenge window prior to the expiration time that can be used by specific protocol bindings to send a challenge to renew the access token before it expires. - -## Example - -``` -"jwt0": -{ - "type": "jwt", - "options": - { - "issuer": "https://auth.example.com", - "audience": "https://api.example.com", - "keys": - [ - { - "kty":"EC", - "crv":"P-256", - "x":"MKBCTNIcKUSDii11ySs3526iDZ8AiTo7Tu6KPAqv7D4", - "y":"4Etl6SRW2YiLUrN5vfvVHuhp7x8PxltmWWlbbM4IFyM", - "use":"enc", - "kid":"1" - }, - { - "kty":"RSA", - "n": "0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFbWhM78LhWx4cbbfAAtVT86zwu1RK7aPFFxuhDR1L6tSoc_BJECPebWKRXjBZCiFV4n3oknjhMstn64tZ_2W-5JsGY4Hc5n9yBXArwl93lqt7_RN5w6Cf0h4QyQ5v-65YGjQR0_FDW2QvzqY368QQMicAtaSqzs8KJZgnYb9c7d0zgdAZHzu6qMQvRL5hajrn1n91CbOpbISD08qNLyrdkt-bFTWhAI4vMQFh6WeZu0fM4lFd2NcRwr3XPksINHaQ-G_xBniIqbw0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw", - "e":"AQAB", - "alg":"RS256", - "kid":"2011-04-29" - } - ], - "challenge": 30 - } -} -``` - -## Configuration - -Guard with support for `jwt`. - -#### Properties - -| Name (\* = required) | Type | Description | -| --------------------------------- | ------------- | ---------------------- | -| `type`\* | `const "jwt"` | Support `jwt` | -| [`options`](guard-jwt.md#options) | `object` | `jwt`-specific options | - -### options - -Options for `jwt`. - -#### Properties - -| Name | Type | Description | -| ----------- | ------------------------- | -------------------------- | -| `issuer` | `string` | Issuer claim | -| `audience` | `string` | Audience claim | -| `keys`\* | [`key`](guard-jwt.md#key) | Signature public keys | -| `challenge` | `number` | Challenge period (seconds) | - -### key - -Key option for `jwt`. - -#### Properties - -| Name | Type | Description | -| ------- | -------- | ----------------------------- | -| `kty`\* | `string` | Key type, e.g. `RSA` , `EC` | -| `kid`\* | `string` | Key ID | -| `n` | `string` | `RSA` `modulus` | -| `e` | `string` | `RSA` `exponent` | -| `alg` | `string` | `RSA` algorithm, e.g. `RS256` | -| `crv` | `string` | `EC` curve name | -| `x` | `string` | `EC` point `x` coordinate | -| `y` | `string` | `EC` point `y` coordinate | diff --git a/reference/zilla.yaml/vault-filesystem.md b/reference/zilla.yaml/vault-filesystem.md deleted file mode 100644 index ef92ebf2..00000000 --- a/reference/zilla.yaml/vault-filesystem.md +++ /dev/null @@ -1,70 +0,0 @@ ---- -description: Zilla runtime filesystem vault ---- - -# vault (filesystem) - -Defines a vault stored on the local filesystem. - -The `filesystem` vault uses `PKCS12` format to store signed certificates and keys. - -The `keys` option is used to identify the local peer in a `TLS` handshake. - -The `trust` option is used to verify identity of the remote peer in a `TLS` handshake. - -The `signers` option is used to challenge for mutual authentication in a `TLS` handshake. - -## Example - -``` -"server": -{ - "type": "filesystem", - "options": - { - "keys": - { - "store": "localhost.p12", - "type": "pkcs12", - "password": "{{env.KEYS_PASSWORD}}" - } - } -} -``` - -Note that use of `{{env.*}}` syntax to read an environment variable currently requires setting `zilla.engine.config.syntax.mustache=true` in `.zilla/zilla.properties`. - -## Configuration - -Guard with support for local `filesystem`. - -#### Properties - -| Name (\* = required) | Type | Description | -| ---------------------------------------- | -------------------- | ----------------------------- | -| `type`\* | `const "filesystem"` | Support `filesystem` | -| [`options`](vault-filesystem.md#options) | `object` | `filesystem`-specific options | - -### options - -Options for local `filesystem`. - -#### Properties - -| Name (\* = required) | Type | Description | -| -------------------- | ------------------------------------ | ------------------- | -| `keys` | [`store`](vault-filesystem.md#store) | Private keys | -| `trust` | [`store`](vault-filesystem.md#store) | Trust certificates | -| `signers` | [`store`](vault-filesystem.md#store) | Signer certificates | - -### store - -Store option for local `filesystem`. - -#### Properties - -| Name (\* = required) | Type | Description | -| -------------------- | -------- | ---------------------------------------------------------- | -| `store`\* | `string` | Relative path to keystore | -| `type` | `string` |

Keystore type,
defaults to "pkcs12"

| -| `password` | `string` | Keystore password | diff --git a/reference/zilla.yaml/vault.md b/reference/zilla.yaml/vault.md deleted file mode 100644 index d1675c35..00000000 --- a/reference/zilla.yaml/vault.md +++ /dev/null @@ -1,27 +0,0 @@ ---- -description: Zilla runtime vault type ---- - -# vault - -Each configured `vault` represents a container for digital keys and certificates based on a specific implementation `type`. - -Vaults can be used by specific protocol bindings, such as `tls`, to negotiate shared encryption keys. - -See each of the specific `vault` types linked below for more detailed examples. - -### Configuration - -Each runtime `vault` has a behavioral type supporting a specific implementation strategy. - -#### Properties (generic) - -| Name | Type | Description | -| ------ | ------------------------------------------------------------------------------------------------------------- | --------------- | -| `type` |

enum [
"filesystem"
]

| Behavioral type | - -#### Properties (type-specific) - -| Name | Type | Description | -| --------- | -------- | ------------------ | -| `options` | `object` | Behavioral options | diff --git a/src/.vuepress/config.ts b/src/.vuepress/config.ts new file mode 100644 index 00000000..882f2e6e --- /dev/null +++ b/src/.vuepress/config.ts @@ -0,0 +1,25 @@ +import { defineUserConfig } from "vuepress"; +import { googleAnalyticsPlugin } from '@vuepress/plugin-google-analytics' +import theme from "./theme.js"; +import { base, dest } from "./env.js"; + +export default defineUserConfig({ + base: `/${base}/`, + dest, + + locales: { + "/": { + lang: "en-US", + title: "Zilla Docs", + description: "The official documentation for the aklivity/zilla open-source project", + }, + }, + + theme, + + plugins: [ + googleAnalyticsPlugin({ + id: 'G-Q2XWKQS14L', + }), + ], +}); diff --git a/src/.vuepress/env.ts b/src/.vuepress/env.ts new file mode 100644 index 00000000..b14b72d7 --- /dev/null +++ b/src/.vuepress/env.ts @@ -0,0 +1,41 @@ + +export const siteBase = process.env.SITE_BASE || "zilla-docs"; +export const dist = process.env.DIST_DIR || "src/.vuepress/dist"; +export const hostnameSEO = process.env.SITE_URL || `https://docs.aklivity.io`; +export const versionKey = process.env.SITE_VERSION_KEY || "next"; +export const base = `${siteBase}/${versionKey}`; +export const dest = `${dist}/${versionKey}`; + +export const docsRepo = process.env.GITHUB_REPOSITORY || "aklivity/zilla-docs"; +var repoTree; +switch (versionKey) { + case "next": + repoTree = "develop" + break; + default: + repoTree = "main" +} +export const docsBranch = repoTree; + + +console.log("Configured env variables:", { + siteBase, + dist, + hostnameSEO, + base, + versionKey, + dest, + docsRepo, + docsBranch, + }); + +export default { + siteBase, + dist, + hostnameSEO, + base, + versionKey, + dest, + docsRepo, + docsBranch, +}; \ No newline at end of file diff --git a/src/.vuepress/navbar/en.ts b/src/.vuepress/navbar/en.ts new file mode 100644 index 00000000..1e471827 --- /dev/null +++ b/src/.vuepress/navbar/en.ts @@ -0,0 +1,25 @@ +import { navbar } from "vuepress-theme-hope"; +import { hostnameSEO, siteBase } from "../env.js"; +import versions from '../versions.json' assert { type: "json" }; +const versionLinks = <{ text: string; link: string; }[]>versions.map(o => ({ text: o.text, link: o.key?`${hostnameSEO}/${siteBase}/${o.key}`:o.link })); + +export const enNavbar = navbar([ + { text: "Get Started", icon: "clock", link: "/get-started/", }, + { text: "Guides", icon: "bars-staggered", link: "/guides/", }, + { text: "Examples", icon: "diagram-project", link: "/examples/", }, + { + text: "Reference", + icon: "book", + prefix: "/reference/", + children: [ + "zilla.yaml/", + "zilla/", + "zpm/", + ], + }, + { text: "Blog", icon: "blog", link: "https://www.aklivity.io/blog", }, + // todo: remove and uncomment the below once there is multiple versions of the blogs to host + // and add necessary items ({ "text": "v0.1", "key": "v0.1", "tag": "v0.1" }) to deploy-versions.json + { "text": "Changelog", icon: "tag", "link": "https://github.com/orgs/aklivity/projects/4", }, + // { text: "version", icon: "list-ol", children: versionLinks }, +]); diff --git a/src/.vuepress/navbar/index.ts b/src/.vuepress/navbar/index.ts new file mode 100644 index 00000000..850f6d62 --- /dev/null +++ b/src/.vuepress/navbar/index.ts @@ -0,0 +1 @@ +export * from "./en.js"; diff --git a/.gitbook/assets/BuildZillaFromSourceTask.png b/src/.vuepress/public/assets/BuildZillaFromSourceTask.png similarity index 100% rename from .gitbook/assets/BuildZillaFromSourceTask.png rename to src/.vuepress/public/assets/BuildZillaFromSourceTask.png diff --git a/.gitbook/assets/EditTask.png b/src/.vuepress/public/assets/EditTask.png similarity index 100% rename from .gitbook/assets/EditTask.png rename to src/.vuepress/public/assets/EditTask.png diff --git a/.gitbook/assets/EmptyTasks.png b/src/.vuepress/public/assets/EmptyTasks.png similarity index 100% rename from .gitbook/assets/EmptyTasks.png rename to src/.vuepress/public/assets/EmptyTasks.png diff --git a/.gitbook/assets/JoinZillaSlackCommunityTask.png b/src/.vuepress/public/assets/JoinZillaSlackCommunityTask.png similarity index 100% rename from .gitbook/assets/JoinZillaSlackCommunityTask.png rename to src/.vuepress/public/assets/JoinZillaSlackCommunityTask.png diff --git a/.gitbook/assets/JoinZillaSlackCommunityTask400.png b/src/.vuepress/public/assets/JoinZillaSlackCommunityTask400.png similarity index 100% rename from .gitbook/assets/JoinZillaSlackCommunityTask400.png rename to src/.vuepress/public/assets/JoinZillaSlackCommunityTask400.png diff --git a/.gitbook/assets/Screen Shot 2022-05-22 at 9.11.25 PM.png b/src/.vuepress/public/assets/Screen Shot 2022-05-22 at 9.11.25 PM.png similarity index 100% rename from .gitbook/assets/Screen Shot 2022-05-22 at 9.11.25 PM.png rename to src/.vuepress/public/assets/Screen Shot 2022-05-22 at 9.11.25 PM.png diff --git a/.gitbook/assets/Screen Shot 2022-05-24 at 11.00.10 PM.png b/src/.vuepress/public/assets/Screen Shot 2022-05-24 at 11.00.10 PM.png similarity index 100% rename from .gitbook/assets/Screen Shot 2022-05-24 at 11.00.10 PM.png rename to src/.vuepress/public/assets/Screen Shot 2022-05-24 at 11.00.10 PM.png diff --git a/.gitbook/assets/Screen Shot 2022-07-08 at 9.49.37 AM (1).png b/src/.vuepress/public/assets/Screen Shot 2022-07-08 at 9.49.37 AM (1).png similarity index 100% rename from .gitbook/assets/Screen Shot 2022-07-08 at 9.49.37 AM (1).png rename to src/.vuepress/public/assets/Screen Shot 2022-07-08 at 9.49.37 AM (1).png diff --git a/.gitbook/assets/Screen Shot 2022-07-08 at 9.49.37 AM.png b/src/.vuepress/public/assets/Screen Shot 2022-07-08 at 9.49.37 AM.png similarity index 100% rename from .gitbook/assets/Screen Shot 2022-07-08 at 9.49.37 AM.png rename to src/.vuepress/public/assets/Screen Shot 2022-07-08 at 9.49.37 AM.png diff --git a/.gitbook/assets/Screen Shot 2022-07-26 at 12.53.28 PM (1).png b/src/.vuepress/public/assets/Screen Shot 2022-07-26 at 12.53.28 PM (1).png similarity index 100% rename from .gitbook/assets/Screen Shot 2022-07-26 at 12.53.28 PM (1).png rename to src/.vuepress/public/assets/Screen Shot 2022-07-26 at 12.53.28 PM (1).png diff --git a/.gitbook/assets/Screen Shot 2022-07-26 at 12.53.28 PM.png b/src/.vuepress/public/assets/Screen Shot 2022-07-26 at 12.53.28 PM.png similarity index 100% rename from .gitbook/assets/Screen Shot 2022-07-26 at 12.53.28 PM.png rename to src/.vuepress/public/assets/Screen Shot 2022-07-26 at 12.53.28 PM.png diff --git a/.gitbook/assets/Screen Shot 2022-07-26 at 12.53.37 PM (1).png b/src/.vuepress/public/assets/Screen Shot 2022-07-26 at 12.53.37 PM (1).png similarity index 100% rename from .gitbook/assets/Screen Shot 2022-07-26 at 12.53.37 PM (1).png rename to src/.vuepress/public/assets/Screen Shot 2022-07-26 at 12.53.37 PM (1).png diff --git a/.gitbook/assets/Screen Shot 2022-07-26 at 12.53.37 PM.png b/src/.vuepress/public/assets/Screen Shot 2022-07-26 at 12.53.37 PM.png similarity index 100% rename from .gitbook/assets/Screen Shot 2022-07-26 at 12.53.37 PM.png rename to src/.vuepress/public/assets/Screen Shot 2022-07-26 at 12.53.37 PM.png diff --git a/.gitbook/assets/SecureTodoAppLoggedIn.png b/src/.vuepress/public/assets/SecureTodoAppLoggedIn.png similarity index 100% rename from .gitbook/assets/SecureTodoAppLoggedIn.png rename to src/.vuepress/public/assets/SecureTodoAppLoggedIn.png diff --git a/.gitbook/assets/SecureTodoAppNotLoggedIn.png b/src/.vuepress/public/assets/SecureTodoAppNotLoggedIn.png similarity index 100% rename from .gitbook/assets/SecureTodoAppNotLoggedIn.png rename to src/.vuepress/public/assets/SecureTodoAppNotLoggedIn.png diff --git a/.gitbook/assets/TodoAppTopology.png b/src/.vuepress/public/assets/TodoAppTopology.png similarity index 100% rename from .gitbook/assets/TodoAppTopology.png rename to src/.vuepress/public/assets/TodoAppTopology.png diff --git a/.gitbook/assets/TryZillaExamplesTask.png b/src/.vuepress/public/assets/TryZillaExamplesTask.png similarity index 100% rename from .gitbook/assets/TryZillaExamplesTask.png rename to src/.vuepress/public/assets/TryZillaExamplesTask.png diff --git a/.gitbook/assets/bootstrap-server-names.png b/src/.vuepress/public/assets/bootstrap-server-names.png similarity index 100% rename from .gitbook/assets/bootstrap-server-names.png rename to src/.vuepress/public/assets/bootstrap-server-names.png diff --git a/.gitbook/assets/pca-ca-cert.png b/src/.vuepress/public/assets/pca-ca-cert.png similarity index 100% rename from .gitbook/assets/pca-ca-cert.png rename to src/.vuepress/public/assets/pca-ca-cert.png diff --git a/.gitbook/assets/todo (1).png b/src/.vuepress/public/assets/todo (1).png similarity index 100% rename from .gitbook/assets/todo (1).png rename to src/.vuepress/public/assets/todo (1).png diff --git a/.gitbook/assets/todo-app-architecture-secured@2x.png b/src/.vuepress/public/assets/todo-app-architecture-secured@2x.png similarity index 100% rename from .gitbook/assets/todo-app-architecture-secured@2x.png rename to src/.vuepress/public/assets/todo-app-architecture-secured@2x.png diff --git a/.gitbook/assets/todo-app-architecture.svg b/src/.vuepress/public/assets/todo-app-architecture.svg similarity index 100% rename from .gitbook/assets/todo-app-architecture.svg rename to src/.vuepress/public/assets/todo-app-architecture.svg diff --git a/.gitbook/assets/todo-app-architecture@2x.png b/src/.vuepress/public/assets/todo-app-architecture@2x.png similarity index 100% rename from .gitbook/assets/todo-app-architecture@2x.png rename to src/.vuepress/public/assets/todo-app-architecture@2x.png diff --git a/.gitbook/assets/todo-app-architecture@3x.png b/src/.vuepress/public/assets/todo-app-architecture@3x.png similarity index 100% rename from .gitbook/assets/todo-app-architecture@3x.png rename to src/.vuepress/public/assets/todo-app-architecture@3x.png diff --git a/.gitbook/assets/todo.drawio (1).png b/src/.vuepress/public/assets/todo.drawio (1).png similarity index 100% rename from .gitbook/assets/todo.drawio (1).png rename to src/.vuepress/public/assets/todo.drawio (1).png diff --git a/.gitbook/assets/todo.drawio (2).png b/src/.vuepress/public/assets/todo.drawio (2).png similarity index 100% rename from .gitbook/assets/todo.drawio (2).png rename to src/.vuepress/public/assets/todo.drawio (2).png diff --git a/.gitbook/assets/todo.drawio.png b/src/.vuepress/public/assets/todo.drawio.png similarity index 100% rename from .gitbook/assets/todo.drawio.png rename to src/.vuepress/public/assets/todo.drawio.png diff --git a/.gitbook/assets/todo.png b/src/.vuepress/public/assets/todo.png similarity index 100% rename from .gitbook/assets/todo.png rename to src/.vuepress/public/assets/todo.png diff --git a/.gitbook/assets/topology.png b/src/.vuepress/public/assets/topology.png similarity index 100% rename from .gitbook/assets/topology.png rename to src/.vuepress/public/assets/topology.png diff --git a/.gitbook/assets/zilla-studio@2x.png b/src/.vuepress/public/assets/zilla-studio@2x.png similarity index 100% rename from .gitbook/assets/zilla-studio@2x.png rename to src/.vuepress/public/assets/zilla-studio@2x.png diff --git a/src/.vuepress/public/cloudflare/_redirects b/src/.vuepress/public/cloudflare/_redirects new file mode 100644 index 00000000..4974209f --- /dev/null +++ b/src/.vuepress/public/cloudflare/_redirects @@ -0,0 +1,2 @@ +/ /zilla/next 302 +/zilla /zilla/next 302 \ No newline at end of file diff --git a/src/.vuepress/public/favicon.ico b/src/.vuepress/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..5a26df4927c4f4414d3d23ac72e8a760221a6b53 GIT binary patch literal 15406 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 Theme Hope | MIT Licensed, Copyright © Aklivity, Inc. 2023 +--- + + +**Zilla** is open-source software connecting web and mobile applications to event-driven microservices using standard protocols, such as HTTP, Server-Sent Events and Kafka. + +Zilla is designed on the fundamental principle that _every data flow is a stream_, and that streams can be composed together to create efficient protocol transformation pipelines. This concept of a stream holds at both the network level for communication protocols and also at the application level for data processing. + +Zilla's declarative configuration defines a routed graph of protocol decoders, transformers, encoders and caches that combine to provide a secure and stateless API entry point to your event-driven architecture. + +For example, when deployed in front of a Kafka cluster, Zilla can be configured to support: + +* HTTP request-response interaction with Kafka-based microservices +* HTTP event-driven caching populated by messages from a Kafka topic +* reliable message streaming from a Kafka topic via Server-Sent Events +* secure HTTP request-response APIs using JWT access tokens +* secure Server-Sent Events streams using continuous authorization via JWT access tokens + +As a developer, you can focus on writing and testing your event-driven microservices with technologies such as Kafka consumers and producers, you can define your web and mobile APIs using Zilla, and then you can deploy securely at a global scale. diff --git a/src/examples/README.md b/src/examples/README.md new file mode 100644 index 00000000..cd0d1a74 --- /dev/null +++ b/src/examples/README.md @@ -0,0 +1,11 @@ +# Examples + +The examples below will walk you through the steps to build and secure a Todo application using Apache Kafka with the Zilla engine. + +## [Build the Todo Application](todo-app/build.md) + +Our Build the Todo Application guide shows you how to create your first application with Zilla, using Apache Kafka with Kafka Streams to implement the Tasks service that maintains a shared Todo List of tasks. + +## [Secure the Todo Application](todo-app/secure.md) + +Our Secure the Todo Application guide shows you how to secure the Tasks API using JWT access tokens to allow read and write access only to authorized clients. diff --git a/src/examples/todo-app/SecureTodoAppLoggedIn.png b/src/examples/todo-app/SecureTodoAppLoggedIn.png new file mode 100644 index 0000000000000000000000000000000000000000..2d4dac9bf32594e6041997797639a275cf6e17a2 GIT binary patch literal 191714 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 Ad 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 literal 0 HcmV?d00001 diff --git a/src/examples/todo-app/SecureTodoAppNotLoggedIn.png b/src/examples/todo-app/SecureTodoAppNotLoggedIn.png new file mode 100644 index 0000000000000000000000000000000000000000..cbba7bde66990523ed3a996c1912caba8bd65bca GIT binary patch literal 158864 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 literal 0 HcmV?d00001 diff --git a/.gitbook/assets/TodoAppNotLoggedIn.png b/src/examples/todo-app/TodoAppNotLoggedIn.png similarity index 100% rename from .gitbook/assets/TodoAppNotLoggedIn.png rename to src/examples/todo-app/TodoAppNotLoggedIn.png diff --git a/get-started/build-todo-app.md b/src/examples/todo-app/build.md similarity index 75% rename from get-started/build-todo-app.md rename to src/examples/todo-app/build.md index 022f4285..8e48674e 100644 --- a/get-started/build-todo-app.md +++ b/src/examples/todo-app/build.md @@ -2,7 +2,7 @@ In this getting started exercise, you will create a simple Todo application using a CQRS design pattern that's backed by Apache Kafka and Zilla as the event-driven API gateway. Zilla lets you focus on your applications and business logic instead of spending time writing tons of code and this demo helps to ease CQRS complexity. This tutorial gives a basic introduction to Zilla and describes some straightforward capabilities. -![](../.gitbook/assets/todo-app-architecture@2x.png) +![](/assets/todo-app-architecture@2x.png) This Todo Application tutorial has the following goals: @@ -22,16 +22,17 @@ This Todo Application tutorial has the following goals: In this step, you will set up basic infrastructure components for your event-driven architecture. -{% hint style="info" %} +::: info NOTE Run `docker swarm init if you already haven't done to initiate`Swarm orchestrator. -{% endhint %} +::: Let's create `stack.yml` and add `Apache Kafka` (or `Redpanda`). -{% tabs %} -{% tab title="Apache Kafka" %} -{% code title="stack.yml" %} -```yaml +::: code-tabs#shell + +@tab Apache Kafka + +```yaml stack.yml version: "3" networks: @@ -88,12 +89,10 @@ services: /opt/bitnami/kafka/bin/kafka-topics.sh --bootstrap-server kafka.internal.net:29092 --list --topic 'task-.*' " ``` -{% endcode %} -{% endtab %} -{% tab title="Redpanda" %} -{% code title="stack.yml" %} -```yaml +@tab Redpanda + +```yaml stack.yml version: "3" networks: @@ -155,32 +154,38 @@ services: rpk topic list --brokers kafka.internal.net:29092 --regex 'task-.*' " ``` -{% endcode %} -{% endtab %} -{% endtabs %} + +::: Now let's run -```bash +```bash:no-line-numbers docker stack deploy -c stack.yml example --resolve-image never ``` - to spin up `Apache Kafka` (or `Redpanda`) and create the following topics. +to spin up `Apache Kafka` (or `Redpanda`) and create the following topics. -
task-commandsQueues commands to be processed by the Todo service
task-repliesQueues the response from the Todo service after processing each command
task-snapshotsCaptures the latest snapshot of each task entity
+| | | +| ---------------- | -------------------- | +| `task-commands` | Queues commands to be processed by the Todo service | +| `task-replies` | Queues the response from the Todo service after processing each command | +| `task-snapshots` | Captures the latest snapshot of each task entity | Now verify that the Kafka topics have been successfully created. -```bash +```bash:no-line-numbers docker service logs example_init-topics --follow --raw ``` Make sure you see this output at the end of the `example_init-topics` service logs. -{% tabs %} -{% tab title="Apache Kafka" %} -
## Creating the Kafka topics
-Created topic task-commands.
+::: code-tabs#shell
+
+@tab Apache Kafka
+
+```bash:no-line-numbers
+## Creating the Kafka topics
+Created topic task-commands.
 Created topic task-replies.
 Created topic task-snapshots.
 
@@ -188,11 +193,11 @@ Created topic task-snapshots.
 task-commands
 task-replies
 task-snapshots
-
-{% endtab %} +``` -{% tab title="Redpanda" %} -```bash +@tab Redpanda + +```bash:no-line-numbers CLUSTER ======= redpanda.initializing @@ -216,8 +221,8 @@ task-commands 1 1 task-replies 1 1 task-snapshots 1 1 ``` -{% endtab %} -{% endtabs %} + +::: ### Step 2: Todo Service @@ -233,23 +238,25 @@ Commands arrive at the Tasks service via the `task-commands` topic and correlate Implementing the Todo domain using these topics gives us the following Kafka Streams topology. -![](<../.gitbook/assets/topology (1).png>) +![](./topology.png) The `ValidateCommand` Kafka Streams processor implements optimistic locking by ensuring that conditional requests using `if-match` are allowed to proceed only if the latest `etag` for the Task matches, otherwise the command is rejected. Let's checkout and build the service by running the commands below. -
git clone https://github.com/aklivity/todo-service && \
-cd todo-service && \
-./mvnw clean install && \
-cd ..
-
+```bash:no-line-numbers +git clone https://github.com/aklivity/todo-service +cd todo-service +./mvnw clean install +cd .. +``` This will checkout and build `todo-service:latest` image. Open `stack.yml` file and add the Todo service into the stack: -{% code title="stack.yml" %} +### stack.yml + ```yaml ... @@ -264,29 +271,31 @@ Open `stack.yml` file and add the Todo service into the stack: TASK_SNAPSHOTS_TOPIC: task-snapshots TASK_REPLIES_TOPIC: task-replies ``` -{% endcode %} Run the command below to deploy the `todo-service` to your existing stack. -```bash +```bash:no-line-numbers docker stack deploy -c stack.yml example --resolve-image never ``` -{% tabs %} -{% tab title="Apache Kafka" %} -``` +Output: +::: code-tabs#shell + +@tab Apache Kafka + +```bash:no-line-numbers Creating service example_todo-service Updating service example_kafka (id: st4hq1bwjsom5r0jxnc6i9rgr) ``` -{% endtab %} -{% tab title="Redpanda" %} -``` +@tab Redpanda + +```bash:no-line-numbers Creating service example_todo-service Updating service example_redpanda (id: ilmfqpwf35b7ftd6cvzdis8au) ``` -{% endtab %} -{% endtabs %} + +::: Now, you have a running to-do service that can process incoming commands, send a response and take snapshots of the task. @@ -300,13 +309,11 @@ However, Zilla is designed to solve these architectural challenges, requiring on Let's design the Tasks API. You need to define a Tasks API to send commands to the `Todo` service via Kafka and retrieve task queries from Kafka as needed by the Tasks UX. -
- - - -Creates a new Todo Task. +![](./post-tasks.png) +::: details +Creates a new Todo Task. Requires `content-type` `application/json` and request body matching `CreateTask` command domain model. @@ -316,11 +323,11 @@ Include `idempotency-key` of type `uuid` to support idempotent `CreateTask`. **201: Created** - Task created successfully -
+::: -
+![](./put-tasks.png) - +::: details **Rename Task** @@ -342,18 +349,16 @@ id\[String] - Task identifier if-match\[String] - Task etag - - **Responses:** * **204 No Content** - Task renamed successfully * **412 Precondition Failed** - Task rename failed, etag does not match -
+::: -
+![](./delete-tasks.png) - +::: details **Delete Task** @@ -373,18 +378,16 @@ id\[String] - Task identifier if-match\[String] - Task etag - - **Responses:** * **204 No Content** - **** Task deleted successfully * **412 Precondition Failed** - **** Task delete failed, etag does not match -
+::: -
+![](./get-tasks.png) - +::: details **Get Tasks** @@ -396,14 +399,12 @@ Retrieves all tasks, with `etag` representing the **** latest value. if-none-match\[String] - Tasks collection etag - - **Responses:** * **200 OK** - Returns an array of Tasks * **304 Not Modified** - **** If Tasks collection etag matches -
+::: #### Configure Zilla @@ -412,25 +413,23 @@ The Zilla engine configuration defines a flow of named `bindings` representing e Let's configure `Zilla` for the Tasks API to interact with the `Todo` Kafka Streams service via Kafka topics. You will add the following bindings to support the Tasks API as shown `zilla.yaml` below. To understand each binding type in more detail please visit [Zilla Runtime Configuration](https://docs.aklivity.io/zilla/reference/zilla.json). - -| `tcp_server0` |

listens on port 8080

routes to http_server0

| -| --------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `http_server0` |

decodes HTTP protocol

routes Tasks API to http_kafka_proxy0

| -| `http_kafka_proxy0` |

transforms HTTP to Kafka

routes POST, PUT and DELETE Tasks API requests to task-commands topic with task-replies reply-to topic via kafka_cache_client0

routes GET Tasks API requests to task-snapshots topic via kafka_cache_client0

| -| `kafka_cache_client0` |

reads from local Kafka topic message cache

routes to kafka_cache_server0

| -| `kafka_cache_server0` |

writes to local Kafka topic message cache as new messages arrive from Kafka

routes to kafka_client0

| -| `kafka_client0` |

encodes Kafka protocol

routes to kafka_client0

| -| `tcp_client0` | connects to Kafka brokers | +| | | +| --------------------- | -------------------- | +| `tcp_server0` | listens on port 8080 routes to http_server0 | +| `http_server0` | decodes HTTP protocol routes Tasks API to http_kafka_proxy0 | +| `http_kafka_proxy0` | transforms HTTP to Kafka routes POST, PUT and DELETE Tasks API requests to task-commands topic with task-replies reply-to topic via kafka_cache_client0 routes GET Tasks API requests to task-snapshots topic via kafka_cache_client0 | +| `kafka_cache_client0` | reads from local Kafka topic message cache routes to kafka_cache_server0 | +| `kafka_cache_server0` | writes to local Kafka topic message cache as new messages arrive from Kafka routes to kafka_client0 | +| `kafka_client0` | encodes Kafka protocol routes to kafka_client0 | +| `tcp_client0` | connects to Kafka brokers | Using [Zilla Studio](https://zilla-studio.aklivity.io/), select the `Build the Todo App` template from the `Load Template` dropdown and then press `Generate Config` to download the corresponding `zilla.yaml` configuration file. -

Zilla Studio

+![Zilla Studio](/assets/zilla-studio@2x.png) Alternatively, copy the contents of `zilla.yaml` shown below to your local `zilla.yaml` file. -
- -zilla.yaml +::: details zilla.yaml ```yaml --- @@ -547,7 +546,7 @@ bindings: guards: {} ``` -
+::: Now let's add the `zilla` service to the docker stack, mounting the `zilla.yaml` configuration. @@ -569,61 +568,66 @@ Now let's add the `zilla` service to the docker stack, mounting the `zilla.yaml` Run the below command as this will deploy the `zilla` service to the existing stack. -```bash +```bash:no-line-numbers docker stack deploy -c stack.yml example --resolve-image never ``` -{% tabs %} -{% tab title="Apache Kafka" %} -
Updating service example_kafka (id: st4hq1bwjsom5r0jxnc6i9rgr)
-Updating service example_todo-service (id: ojbj2kbuft22egy854xqv8yo8)
+::: code-tabs#shell
+
+@tab Apache Kafka
+
+```bash:no-line-numbers
+Updating service example_kafka (id: st4hq1bwjsom5r0jxnc6i9rgr)
+Updating service example_todo-service (id: ojbj2kbuft22egy854xqv8yo8)
 Creating service example_zilla
-
-{% endtab %} +``` + +@tab Redpanda -{% tab title="Redpanda" %} -
Updating service example_redpanda (id: ilmfqpwf35b7ftd6cvzdis8au)
-Updating service example_todo-service (id: 1tq9nktlvcwxeh3wzhmj02cvd)
+```bash:no-line-numbers
+Updating service example_redpanda (id: ilmfqpwf35b7ftd6cvzdis8au)
+Updating service example_todo-service (id: 1tq9nktlvcwxeh3wzhmj02cvd)
 Creating service example_zilla
-
-{% endtab %} -{% endtabs %} +``` + +::: -{% hint style="info" %} +::: info NOTE Make sure that Zilla is fully started by checking container logs where you see **started** at the end of the log. -{% endhint %} +::: Let's verify the Tasks API using the `curl` `POST` and `GET` commands shown below. -
curl -X POST http://localhost:8080/tasks \
-    -H "Idempotency-Key: 5958F9A2-8319-486B-BD43-2F80FDE87223" \
-    -H "Content-Type: application/json" \
-    -d "{\"name\":\"Read the docs\"}"
-
+```bash:no-line-numbers +curl -X POST http://localhost:8080/tasks \ + -H "Idempotency-Key: 5958F9A2-8319-486B-BD43-2F80FDE87223" \ + -H "Content-Type: application/json" \ + -d "{\"name\":\"Read the docs\"}" +``` -```bash +```bash:no-line-numbers curl http://localhost:8080/tasks ``` -```bash +```bash:no-line-numbers id:["NTk1OEY5QTItODMxOS00ODZCLUJENDMtMkY4MEZERTg3MjIz","AQIAAg==/1"] data:{"name":"Read the docs"} - ``` As you can see, the `GET /tasks` API delivers a continuous stream of tasks starting with the initial tasks as expected. Now create a new Todo task while keeping the `GET /tasks` stream open as shown above. -
curl -X POST http://localhost:8080/tasks \
-    -H "Idempotency-Key: 5C1A90A3-AEB5-496F-BA00-42D1D805B21B" \
-    -H "Content-Type: application/json" \
-    -d "{\"name\":\"Join the Slack community\"}"
-
+```bash:no-line-numbers +curl -X POST http://localhost:8080/tasks \ + -H "Idempotency-Key: 5C1A90A3-AEB5-496F-BA00-42D1D805B21B" \ + -H "Content-Type: application/json" \ + -d "{\"name\":\"Join the Slack community\"}" +``` The `GET /tasks` stream automatically receives the update when the new task is created. -```bash +```bash:no-line-numbers id:["NUMxQTkwQTMtQUVCNS00OTZGLUJBMDAtNDJEMUQ4MDVCMjFC","AQIABA==/1"] data:{"name":"Join the Slack community"} @@ -635,7 +639,7 @@ Each new update arrives automatically, even when changes are made by other clien Next, you will build the `Todo` app that's implemented using [VueJs](https://vuejs.org/) framework. Run the commands below in the root directory. -```bash +```bash:no-line-numbers git clone https://github.com/aklivity/todo-app && \ cd todo-app && \ npm install && \ @@ -647,9 +651,7 @@ This will generate `dist` folder with necessary artifacts. Now you can configure First, add the `http_filesystem_proxy0` and `filesystem_server0` bindings to `zilla.yaml` giving the following updated configuration. -
- -zilla.yaml (updated) +::: details zilla.yaml (updated) ```yaml --- @@ -786,13 +788,14 @@ bindings: guards: {} ``` -
+::: The last step is to mount the `dist` folder into the `Zilla` container. Open `stack.yml` file and add `- ./todo-app/dist:/app/dist:ro` to the `zilla` service `volumes`. -{% code title="stack.yml" %} +#### stack.yml + ```yaml ... @@ -806,22 +809,21 @@ Open `stack.yml` file and add `- ./todo-app/dist:/app/dist:ro` to the `zilla` se ... ``` -{% endcode %} Finally, run -```bash +```bash:no-line-numbers docker stack deploy -c stack.yml example --resolve-image never ``` Make sure that `zilla.yaml` config changes got applied after restarting the `Zilla` service. Check the `example_zilla` service log. -### Step 5: Test Drive! +### Step 5: Test Drive Open the browser and enter [`http://localhost:8080/`](http://localhost:8080/) to see the Todo Application. -![](../.gitbook/assets/TodoAppNotLoggedIn.png) +![](./TodoAppNotLoggedIn.png) Notice that there is no need to `Login` as the Tasks API is initially available to anonymous clients. -Next up: [Secure the Todo Application](secure-todo-app.md) Tasks API with JWT access tokens. +Next up: [Secure the Todo Application](secure.md) Tasks API with JWT access tokens. diff --git a/.gitbook/assets/Screen Shot 2022-05-23 at 11.05.49 AM.png b/src/examples/todo-app/delete-tasks.png similarity index 100% rename from .gitbook/assets/Screen Shot 2022-05-23 at 11.05.49 AM.png rename to src/examples/todo-app/delete-tasks.png diff --git a/.gitbook/assets/Screen Shot 2022-05-23 at 11.12.06 AM.png b/src/examples/todo-app/get-tasks.png similarity index 100% rename from .gitbook/assets/Screen Shot 2022-05-23 at 11.12.06 AM.png rename to src/examples/todo-app/get-tasks.png diff --git a/.gitbook/assets/Screen Shot 2022-05-23 at 10.34.46 AM.png b/src/examples/todo-app/post-tasks.png similarity index 100% rename from .gitbook/assets/Screen Shot 2022-05-23 at 10.34.46 AM.png rename to src/examples/todo-app/post-tasks.png diff --git a/.gitbook/assets/Screen Shot 2022-05-23 at 10.58.56 AM.png b/src/examples/todo-app/put-tasks.png similarity index 100% rename from .gitbook/assets/Screen Shot 2022-05-23 at 10.58.56 AM.png rename to src/examples/todo-app/put-tasks.png diff --git a/get-started/secure-todo-app.md b/src/examples/todo-app/secure.md similarity index 91% rename from get-started/secure-todo-app.md rename to src/examples/todo-app/secure.md index e154548b..52add7f2 100644 --- a/get-started/secure-todo-app.md +++ b/src/examples/todo-app/secure.md @@ -1,12 +1,12 @@ # Secure the Todo Application -In this getting started exercise, you will enhance the [previously built Todo application](build-todo-app.md) to secure the Tasks API using JWT access tokens. +In this getting started exercise, you will enhance the [previously built Todo application](build.md) to secure the Tasks API using JWT access tokens. -![](../.gitbook/assets/todo-app-architecture-secured@2x.png) +![](/assets/todo-app-architecture@2x.png) -Zilla has the concept of a [guard](../reference/zilla.yaml/guard.md) that can be defined to control access to any route in the bindings configuration. +Zilla has the concept of a [guard](../../reference/zilla.yaml/guard.md) that can be defined to control access to any route in the bindings configuration. -In this guide, you will use the [JWT guard](../reference/zilla.yaml/guard-jwt.md) to enforce authorization of the `read:tasks` and `write:tasks` roles when calling the Tasks API. +In this guide, you will use the [JWT guard](../../reference/zilla.yaml/guard-jwt.md) to enforce authorization of the `read:tasks` and `write:tasks` roles when calling the Tasks API. ### Prerequisites @@ -14,19 +14,17 @@ In this guide, you will use the [JWT guard](../reference/zilla.yaml/guard-jwt.md * Git `2.32.0` * npm `8.3.1` and above * jq `1.6` and above -* completed [Build the Todo Application](build-todo-app.md) with docker stack still running +* completed [Build the Todo Application](build.md) with Docker stack still running ### Step 1: Zilla -In [Build a Todo Application](build-todo-app.md#step-3-zilla), you defined a Tasks API to send commands to the `Todo` service via Kafka and retrieve a continuously updated stream of tasks from Kafka as needed by the Tasks UX. +In [Build a Todo Application](build.md#step-3-zilla), you defined a Tasks API to send commands to the `Todo` service via Kafka and retrieve a continuously updated stream of tasks from Kafka as needed by the Tasks UX. -
- - - -Creates a new Todo Task. +![](./post-tasks.png) +::: details +Creates a new Todo Task. Requires `content-type` `application/json` and request body matching `CreateTask` command domain model. @@ -36,11 +34,11 @@ Include `idempotency-key` of type `uuid` to support idempotent `CreateTask`. **201: Created** - Task created successfully -
+::: -
+![](./put-tasks.png) - +::: details **Rename Task** @@ -62,18 +60,16 @@ id\[String] - Task identifier if-match\[String] - Task etag - - **Responses:** * **204 No Content** - Task renamed successfully * **412 Precondition Failed** - Task rename failed, etag does not match -
+::: -
+![](./delete-tasks.png) - +::: details **Delete Task** @@ -93,36 +89,33 @@ id\[String] - Task identifier if-match\[String] - Task etag - - **Responses:** * **204 No Content** - **** Task deleted successfully * **412 Precondition Failed** - **** Task delete failed, etag does not match -
+::: -
+![](./get-tasks.png) - +::: details **Get Tasks** -Retrieves a stream of tasks, with via Server-Sent Events. +Retrieves all tasks, with `etag` representing the **** latest value. **Parameters** **Header:** -last-event-id\[String] - last received task event id - - +if-none-match\[String] - Tasks collection etag **Responses:** -* **200 OK** - Returns a stream of tasks +* **200 OK** - Returns an array of Tasks +* **304 Not Modified** - **** If Tasks collection etag matches -
+::: Now we secure the Tasks API by requiring the caller to have `read:tasks` role for the `GET` request, and `write:tasks` role for the `POST`, `PUT` and `DELETE` requests. @@ -130,7 +123,7 @@ Now we secure the Tasks API by requiring the caller to have `read:tasks` role fo The Zilla engine configuration defines a flow of named `bindings` representing each step in the pipeline as inbound network traffic is decoded and transformed then encoded into outbound network traffic as needed. -In [Build the Todo Application, Step 3: Zilla](build-todo-app.md#step-3-zilla), you created `zilla.yaml` that defined the Tasks API without security. +In [Build the Todo Application, Step 3: Zilla](build.md#step-3-zilla), you created `zilla.yaml` that defined the Tasks API without security. When routing at each binding, Zilla can guard a route to require that specific roles have been granted to the caller. If the caller does not have the required roles, then the route is ignored. If no routes are viable, then the HTTP request fails with `404 Not Found`. @@ -140,7 +133,7 @@ In this example, tokens are issued by [`Auth0`](https://auth0.com/) at `https:// Using [Zilla Studio](https://zilla-studio.aklivity.io/), select the `Secure the Todo App` template from the `Load Template` dropdown and then press `Generate Config` to download the corresponding `zilla.yaml` configuration file. -

Zilla Studio

+![Zilla Studio](/assets/zilla-studio@2x.png) Alternatively, copy the contents of `zilla.yaml` shown below to your local `zilla.yaml` file. @@ -502,18 +495,18 @@ guards: Now run the command below to update the `zilla` service and force a restart. -```bash +```bash:no-line-numbers docker service update --force \ $(docker stack services example -q -f name=example_zilla) ``` Let's verify the Tasks API using `curl` as shown below. -```bash +```bash:no-line-numbers curl -v http://localhost:8080/tasks ``` -```bash +```bash:no-line-numbers > GET /tasks HTTP/1.1 > Host: localhost:8080 > User-Agent: curl/7.79.1 @@ -528,7 +521,7 @@ curl -v http://localhost:8080/tasks As you can see, the `GET /tasks` API is now secured against unauthorized access, _without_ leaking any information about failed security checks. -### Step 2: Test Drive! +### Step 2: Test Drive Open the browser and enter [`http://localhost:8080/`](http://localhost:8080/) to see the secured Todo Application. @@ -540,4 +533,4 @@ For the purposes of this guide, all authorized users are implicitly granted both The Todo Application now behaves as expected, with authorized-only access to the Tasks API. -![](../.gitbook/assets/SecureTodoAppLoggedIn.png) +![](./SecureTodoAppLoggedIn.png) diff --git a/.gitbook/assets/topology (1).png b/src/examples/todo-app/topology.png similarity index 100% rename from .gitbook/assets/topology (1).png rename to src/examples/todo-app/topology.png diff --git a/src/get-started/README.md b/src/get-started/README.md new file mode 100644 index 00000000..deeadf32 --- /dev/null +++ b/src/get-started/README.md @@ -0,0 +1,11 @@ +# Get Started + +The Get Started guides below will walk you through the steps to build and secure a Todo application using Apache Kafka with the Zilla engine. + +## [Installing Zilla](install/) + +on prem or in the cloud + +## [Connecting to Kafka](connecting-to-kafka/) + +Here we show you how to change the Zilla configuration to use your own Kafka cluster instead of using a local Kafka deployment in a docker stack. diff --git a/connect-your-kafka/README.md b/src/get-started/connecting-to-kafka/README.md similarity index 92% rename from connect-your-kafka/README.md rename to src/get-started/connecting-to-kafka/README.md index 248eacee..b96cec90 100644 --- a/connect-your-kafka/README.md +++ b/src/get-started/connecting-to-kafka/README.md @@ -2,7 +2,7 @@ ## Introduction -In this guide, you will explore how to connect to your own Kafka from Zilla. +In this guide, you will explore how to connect to your own Kafka from Zilla. A brief explanation of replaceable values from the config examples below: @@ -24,7 +24,8 @@ A brief explanation of replaceable values from the config examples below: To connect to any Kafka on **PLAINTEXT** protocol is as simple as defining your TCP binding as shown below. -{% code title="zilla.json" %} +#### zilla.json + ```json { "bindings": @@ -60,7 +61,8 @@ To connect to any Kafka on **PLAINTEXT** protocol is as simple as defining your } } ``` -{% endcode %} + +@[code yaml{69-86}](zilla.yaml) As usual, you need to define the host and port and flush the data to the network. For the full working config please take a look at this [example](https://github.com/aklivity/zilla-examples/blob/main/http.kafka.cache/). @@ -70,11 +72,12 @@ By default, Kafka communicates in `PLAINTEXT`, which means that all data is sent If the `Kafka` cluster is secured by a `TLS` server certificate that is provided by a public certificate authority, then configure `Zilla` add a `TLS` client binding as shown below with the `trustcacerts` option to set to `true`. -{% hint style="info" %} +::: info NOTE The `exit` from `kafka_client0` binding now changes to `tls_client0`. -{% endhint %} +::: + +#### zilla.json -{% code title="zilla.json" %} ```json { "bindings": @@ -121,11 +124,11 @@ The `exit` from `kafka_client0` binding now changes to `tls_client0`. } } ``` -{% endcode %} However, if the `Kafka` cluster is secured by a `TLS` server certificate that is signed by a private certificate authority then you need to add a `vault` [config](https://docs.aklivity.io/zilla/reference/zilla.json/vault-filesystem) to provide access to certificates needed by the `TLS` client binding. -{% code title="zilla.json" %} +#### zilla.json + ```json { "vaults": @@ -189,7 +192,13 @@ However, if the `Kafka` cluster is secured by a `TLS` server certificate that is } } ``` -{% endcode %} + +@[code yaml{69-77}](zilla.yaml) +::: + +However, if the `Kafka` cluster is secured by a `TLS` server certificate that is signed by a private certificate authority then you need to add a `vault` [config](https://docs.aklivity.io/zilla/reference/zilla.json/vault-filesystem) to provide access to certificates needed by the `TLS` client binding. + +@[code yaml{3-10}](zilla.yaml) ## Connect to Kafka over `TLS/SSL` using client certificates @@ -204,24 +213,29 @@ Kafka clients connecting to Kafka clusters that are configured for `TLS mutual a You can use the scripts shown below to generate `truststore.p12` and `keystore.p12` files using the three files. -{% code title="truststore.p12" %} -```bash +::: code-tabs#shell + +@tab truststore.p12 + +```bash:no-line-numbers keytool -import -file ca.pem -alias YOUR_KAFKA_SIGNED_CLIENT_CERT_ALIAS \ -keystore truststore.p12 ``` -{% endcode %} -{% code title="keystore.p12" %} -```bash -openssl pkcs12 -export -in service.cert -inkey service.key \ 130 ↵ ──(Tue,May31)─┘ - -out keystore.p12 -name YOUR_KAFKA_CA_CERT_ALIAS \ - -CAfile ca.pem +@tab keystore.p12 + +```bash:no-line-numbers +openssl pkcs12 -export -in service.cert -inkey service.key + -out keystore.p12 -name YOUR_KAFKA_CA_CERT_ALIAS \ + -CAfile ca.pem ``` -{% endcode %} + +::: You also need to configure a `vault` with `truststore` and `keystore`, then reference the vault in the `tls_client0` binding. -{% code title="zilla.json" %} +#### zilla.json + ```json { "vaults": @@ -292,11 +306,12 @@ You also need to configure a `vault` with `truststore` and `keystore`, then ref } } ``` -{% endcode %} -{% hint style="info" %} +@[code yaml{69-86}](zilla.yaml) + +::: info NOTE SNI adds the domain name to the TLS handshake process so that the Zilla process reaches the right domain name and receives the correct SSL certificate. -{% endhint %} +::: ## Connect to Kafka over SASL @@ -311,15 +326,16 @@ Apache Kafka supports the following SASL mechanisms are: * Delegation Tokens * LDAP -{% hint style="info" %} +::: info NOTE Zilla currently supports SASL PLAIN authentication to Kafka. -Please add your feedback to the [SASL enhancement request](https://github.com/aklivity/zilla/issues/12). -{% endhint %} +Please add your feedback to the [SASL enhancement request](https://github.com/aklivity/zilla/issues/12). +::: Let's configure zilla.json. -{% code title="zilla.json" %} +#### zilla.json + ```json { "bindings": @@ -375,6 +391,7 @@ Let's configure zilla.json. } } ``` -{% endcode %} + +@[code yaml{69-86}](zilla.yaml) To test the above config you can follow instructions in the README from the [example](https://github.com/aklivity/zilla-examples/blob/main/http.kafka.cache/). diff --git a/connect-your-kafka/aiven.md b/src/get-started/connecting-to-kafka/aiven.md similarity index 84% rename from connect-your-kafka/aiven.md rename to src/get-started/connecting-to-kafka/aiven.md index f27a173a..614a5b12 100644 --- a/connect-your-kafka/aiven.md +++ b/src/get-started/connecting-to-kafka/aiven.md @@ -1,3 +1,6 @@ +--- +description: Shows help information for commands +--- # Aiven ## Introduction @@ -20,9 +23,9 @@ A brief explanation of replaceable values from the config examples below: ## Aiven Parameters -The Aiven Kafka requires clients to connect via `TLS mutual authentication` and provides the following files `Client Key`, `Client Certificate`, and `CA Certificate` to achieve that. You can download them by going to `Aiven Console` -> `Kafka Cluster` -> `Overview Tab` as shown below. +The Aiven Kafka requires clients to connect via `TLS mutual authentication` and provides the following files `Client Key`, `Client Certificate`, and `CA Certificate` to achieve that. You can download them by going to `Aiven Console` -> `Kafka Cluster` -> `Overview Tab` as shown below. -![](<../.gitbook/assets/Screen Shot 2022-07-08 at 9.49.37 AM (2).png>) +![Connection Info](./aivien-connection-information.png) you should have the following files: @@ -37,26 +40,32 @@ The next step is to generate the truststore and keystore. You can use the scripts shown below to generate `truststore.p12` and `keystore.p12` files using certificates and keys downloaded from `Aiven Kafka Console`. Please replace all caps lock words. -{% code title="truststore.p12" %} -```bash -keytool -import -file ca.pem -alias YOUR_KAFKA_SIGNED_CLIENT_CERT_ALIAS \ - -keystore truststore.p12 +::: code-tabs#shell + +@tab truststore.p12 + +```bash:no-line-numbers +keytool -import -file ca.pem \ + -alias YOUR_KAFKA_SIGNED_CLIENT_CERT_ALIAS \ + -keystore truststore.p12 ``` -{% endcode %} -{% code title="keystore.p12" %} -```bash -openssl pkcs12 -export -in service.cert -inkey service.key \ 130 ↵ ──(Tue,May31)─┘ - -out keystore.p12 -name YOUR_KAFKA_CA_CERT_ALIAS \ - -CAfile ca.pem +@tab keystore.p12 + +```bash:no-line-numbers +openssl pkcs12 -export -in service.cert -inkey service.key \ + -out keystore.p12 -name YOUR_KAFKA_CA_CERT_ALIAS \ + -CAfile ca.pem ``` -{% endcode %} + +::: ## Configure Zilla And the final step is to configure a `vault` with `truststore` and `keystore`, then reference the vault in the `tls_client0` binding. -{% code title="zilla.json" %} +### zilla.json + ```json { "vaults": @@ -127,10 +136,9 @@ And the final step is to configure a `vault` with `truststore` and `keystore`, } } ``` -{% endcode %} -{% hint style="info" %} +::: info NOTE SNI adds the domain name to the TLS handshake process so that the Zilla process reaches the right domain name and receives the correct SSL certificate. -{% endhint %} +::: To test the above config you can follow instructions in the README from the [example](https://github.com/aklivity/zilla-examples/blob/main/http.kafka.cache/). diff --git a/.gitbook/assets/Screen Shot 2022-07-08 at 9.49.37 AM (2).png b/src/get-started/connecting-to-kafka/aivien-connection-information.png similarity index 100% rename from .gitbook/assets/Screen Shot 2022-07-08 at 9.49.37 AM (2).png rename to src/get-started/connecting-to-kafka/aivien-connection-information.png diff --git a/connect-your-kafka/amazon-msk.md b/src/get-started/connecting-to-kafka/amazon-msk.md similarity index 89% rename from connect-your-kafka/amazon-msk.md rename to src/get-started/connecting-to-kafka/amazon-msk.md index edab3b16..e92351fc 100644 --- a/connect-your-kafka/amazon-msk.md +++ b/src/get-started/connecting-to-kafka/amazon-msk.md @@ -1,3 +1,6 @@ +--- +description: Unlike other hosted Kafka services, Amazon MSK is not readily reachable over the internet +--- # Amazon MSK ## Introduction @@ -6,11 +9,11 @@ Unlike other hosted Kafka services, Amazon MSK is not readily reachable over the ### Enable MSK Public Access -"Public Access" can be turned on for MSK clusters running Apache Kafka 2.6.0 or later. Follow the MSK [Public Access Guide ](https://docs.aws.amazon.com/msk/latest/developerguide/public-access.html)to do so. +"Public Access" can be turned on for MSK clusters running Apache Kafka 2.6.0 or later. Follow the MSK [Public Access Guide](https://docs.aws.amazon.com/msk/latest/developerguide/public-access.html)to do so. -{% hint style="warning" %} +::: warning MSK's “Public Access” feature directly exposes your brokers to the internet, which may present additional security concerns. An alternative and more flexible solution is the [**Aklivity Public MSK Proxy**](https://docs.aklivity.io/aws/get-started/public-proxy). The Proxy is deployed via a CloudFormation template, and acts as intermediary that securely routes connectivity between external clients and MSK brokers without having to modify the brokers. -{% endhint %} +::: ## Set up mTLS Authentication between MSK and Zilla @@ -20,26 +23,27 @@ Once your MSK cluster is reachable over the internet, it will rely on Mutual TLS 2. Export the Client Certificate as well as the Certificate Authority (CA) Certificate. 3. Create a PKCS12 KeyStore containing the exported certificates that will be referenced by Zilla to complete the `mTLS` handshake with your MSK cluster. -{% hint style="info" %} +::: info NOTE If you deployed the Aklivity Public MSK Proxy, then you should already have a Client Certificate that Zilla can use and you can go straight to the second step. -{% endhint %} +::: ### Create a Client Certificate -Follow the [Create Client Certificate (ACM) guide](https://docs.aklivity.io/aws/resources/create-client-certificate-acm#issue-the-signed-certificate). Upon completion you will have created a client certificate inside ACM and should have a local `client-1.key.pem` file containing the client certificate's RSA key as well as the `ARN` of the certificate. +Follow the [Create Client Certificate (ACM) guide](https://docs.aklivity.io/aws/resources/create-client-certificate-acm#issue-the-signed-certificate). Upon completion you will have created a client certificate inside ACM and should have a local `client-1.key.pem` file containing the client certificate's RSA key as well as the `ARN` of the certificate. ### Export Client and CA Certificates First**,** you will export the Client Certificate to a local file called `client.cert`. To do this you will need the `ARN` of the client certificate as well as of the [certificate authority](https://docs.aklivity.io/aws/resources/create-certificate-authority-acm) used to issue the certificate, and run the following command: -``` +```bash:no-line-numbers aws acm-pca get-certificate --certificate-authority-arn CERTIFICATE_ATHORITY_ARN \ - --certificate-arn CERTIFICATE_ARN --output text + --certificate-arn CERTIFICATE_ARN --output text ``` -{% code title="output" overflow="wrap" %} -``` ------BEGIN CERTIFICATE----- +#### output + +```bash:no-line-numbers +----BEGIN CERTIFICATE----- MIIEdzCCA1+gAwIBAgIQDLtFK9uDUb6VpObjhusyhTANBgkqhkiG9w0BAQsFADAS ...... -----END CERTIFICATE----- @@ -49,40 +53,39 @@ MIIC8TCCAdmgAwIBAgIRAIxnMlRU8x8CasAlsfpjghQwDQYJKoZIhvcNAQELBQAw ...... -----END CERTIFICATE----- ``` -{% endcode %} Copy first certificate and save it as `client.cert` -{% code title="client.cert" %} -``` ------BEGIN CERTIFICATE----- +#### client.cert + +```bash:no-line-numbers +----BEGIN CERTIFICATE----- MIIEdzCCA1+gAwIBAgIQDLtFK9uDUb6VpObjhusyhTANBgkqhkiG9w0BAQsFADAS ...... -----END CERTIFICATE----- ``` -{% endcode %} -Next, you will export the CA Certificate. +Next, you will export the CA Certificate. Log into your AWS Certificate Manager Private Certificate Authority and under "Additional Information" export the certificate body to a file called `ca.pem` -![Export the CA Certificate](../.gitbook/assets/pca-ca-cert.png) +![Export the CA Certificate](/assets/pca-ca-cert.png) ### Create a PKCS12 KeyStore To create the KeyStore you will need a signed client certificate alias. It is best to use one of your MSK cluster's `bootstrap server names`. -![chose one of the bootstrap server names such as b-1.xxx.xxx.kafka-use-east.amazonaws.com:9094](../.gitbook/assets/bootstrap-server-names.png) +![chose one of the bootstrap server names such as b-1.xxx.xxx.kafka-use-east.amazonaws.com:9094](/assets/bootstrap-server-names.png) With the `bootstrap server name` in hand, run the following command to create the `keystore.p12` file: -{% code title="keystore.p12" %} -```bash +#### keystore.p12 + +```bash:no-line-numbers openssl pkcs12 -export -in client.cert -inkey client-1.key.pem \ -out keystore.p12 -name SIGNED_CLIENT_CERT_ALIES \ -CAfile ca.pem ``` -{% endcode %} ## Configure Zilla @@ -99,7 +102,8 @@ To configure Zilla you will be replacing the following values in the `zilla.json Inside `zilla.json` create a `client_vault` that references your newly created `keystore`. After this, reference the the vault in the `tls_client0` binding. Your `zilla.json` should appear as follows: -{% code title="zilla.json" %} +#### zilla.json + ```json { "vaults": @@ -164,10 +168,9 @@ Inside `zilla.json` create a `client_vault` that references your newly created ` } } ``` -{% endcode %} -{% hint style="info" %} +::: info NOTE SNI adds the domain name to the TLS handshake process so that the Zilla process reaches the right domain name and receives the correct SSL certificate. -{% endhint %} +::: Your Zilla can now connect to your MSK cluster! You can test your configuration by placing it into the `zilla.json` of the following Zilla [example](https://github.com/aklivity/zilla-examples/tree/main/http.kafka.cache) and running it as per the instructions. diff --git a/connect-your-kafka/confluent-cloud.md b/src/get-started/connecting-to-kafka/confluent-cloud.md similarity index 94% rename from connect-your-kafka/confluent-cloud.md rename to src/get-started/connecting-to-kafka/confluent-cloud.md index f6e822af..a08e8967 100644 --- a/connect-your-kafka/confluent-cloud.md +++ b/src/get-started/connecting-to-kafka/confluent-cloud.md @@ -1,3 +1,6 @@ +--- +description: In this guide, you will learn how to connect to Confluent Cloud from Zilla +--- # Confluent Cloud ## Introduction @@ -9,7 +12,7 @@ In this guide, you will learn how to connect to Confluent Cloud from Zilla. You * Cluster Bootstrap server - see [Confluent Cloud Cluster Settings](https://docs.confluent.io/cloud/current/clusters/broker-config.html). * API Keys(Key, Secret) - see [API Keys to Control Access](https://docs.confluent.io/cloud/current/access-management/authenticate/api-keys/api-keys.html). -## Confluent Cloud Parameters +## Confluent Cloud Parameters Confluent Cloud is exposed over `SASL_SSL` authentication protocols and the `Confluent Cloud` cluster is secured by a `TLS` server certificate that is provided by a public certificate authority. @@ -24,7 +27,7 @@ For a better understanding of the `Zilla` config, please use a brief explanation Before we proceed further let's use the below command to verify connectivity to your Kafka. -``` +```bash:no-line-numbers kcat -b BOOTSTRAP_SERVER_HOSTNAME:BOOTSTRAP_SERVER_PORT \ -X security.protocol=sasl_ssl -X sasl.mechanisms=PLAIN \ -X sasl.username=API_KEY_KEY -X sasl.password=API_KEY_SECRET \ @@ -35,7 +38,8 @@ kcat -b BOOTSTRAP_SERVER_HOSTNAME:BOOTSTRAP_SERVER_PORT \ Let's configure `zilla.json`. -{% code title="zilla.json" %} +#### zilla.json + ```json { "bindings": @@ -91,10 +95,9 @@ Let's configure `zilla.json`. } } ``` -{% endcode %} -{% hint style="info" %} +::: info NOTE SNI adds the domain name to the TLS handshake process so that the Zilla process reaches the right domain name and receives the correct SSL certificate. -{% endhint %} +::: To test the above config you can follow instructions in the README from the [example](https://github.com/aklivity/zilla-examples/blob/main/http.kafka.cache/). diff --git a/src/get-started/connecting-to-kafka/redpanda-zilla.yaml b/src/get-started/connecting-to-kafka/redpanda-zilla.yaml new file mode 100644 index 00000000..a8755f87 --- /dev/null +++ b/src/get-started/connecting-to-kafka/redpanda-zilla.yaml @@ -0,0 +1,86 @@ +--- +name: example +vaults: + server: + type: filesystem + options: + keys: + store: tls/localhost.p12 + type: pkcs12 + password: ${{env.KEYSTORE_PASSWORD}} +bindings: + tcp_server0: + type: tcp + kind: server + options: + host: 0.0.0.0 + port: 9090 + exit: tls_server0 + tcp_server1: + type: tcp + kind: server + options: + host: 0.0.0.0 + port: 8080 + exit: http_server0 + tls_server0: + type: tls + kind: server + vault: server + options: + keys: + - localhost + sni: + - localhost + alpn: + - http/1.1 + - h2 + exit: http_server0 + http_server0: + type: http + kind: server + routes: + - when: + - headers: + :scheme: http + :authority: localhost:8080 + - headers: + :scheme: https + :authority: localhost:9090 + exit: http_kafka_proxy0 + http_kafka_proxy0: + type: http-kafka + kind: proxy + routes: + - when: + - path: /events + exit: kafka_cache_client0 + with: + capability: produce + topic: events + kafka_cache_client0: + type: kafka + kind: cache_client + exit: kafka_cache_server0 + kafka_cache_server0: + type: kafka + kind: cache_server + exit: kafka_client0 + kafka_client0: + type: kafka + kind: client + options: + sasl: + mechanism: scram-sha-256 + username: ${{env.SASL_USERNAME}} + password: ${{env.SASL_PASSWORD}} + exit: tcp_client0 + tcp_client0: + type: tcp + kind: client + options: + host: redpanda + port: 29092 + routes: + - when: + - cidr: 0.0.0.0/0 \ No newline at end of file diff --git a/src/get-started/connecting-to-kafka/redpanda.md b/src/get-started/connecting-to-kafka/redpanda.md new file mode 100644 index 00000000..4e5e7a40 --- /dev/null +++ b/src/get-started/connecting-to-kafka/redpanda.md @@ -0,0 +1,33 @@ +--- +description: In this guide, you will learn how to connect to Redpanda from Zilla +--- +# Redpanda + +## Introduction + +In this guide, you will learn how to connect to Redpanda from Zilla. You can get started with a fully working config [example](https://github.com/aklivity/zilla-examples/tree/main/http.redpanda.sasl.scram). + +## Redpanda Parameters + +A brief explanation of replaceable values from the config examples below: + +| Value | Description | +| --------------------------- | ------------------------------ | +| `SASL_USERNAME` | The SASL username for Redpanda | +| `SASL_PASSWORD` | The SASL password for Redpanda | +| `BOOTSTRAP_SERVER_HOSTNAME` | Target Redpanda hostname | +| `BOOTSTRAP_SERVER_PORT` | Target Redpanda port number | + +## Configure Zilla + +Let's configure `zilla.yaml`. + +::: details zilla.yaml +@[code yaml{3-9,69-86}](redpanda-zilla.yaml) +::: + +::: info NOTE +SNI adds the domain name to the TLS handshake process so that the Zilla process reaches the right domain name and receives the correct SSL certificate. +::: + +To test the above SASL config you can follow instructions in the README from the [example](https://github.com/aklivity/zilla-examples/tree/main/http.redpanda.sasl.scram). diff --git a/src/get-started/connecting-to-kafka/zilla.yaml b/src/get-started/connecting-to-kafka/zilla.yaml new file mode 100644 index 00000000..a8755f87 --- /dev/null +++ b/src/get-started/connecting-to-kafka/zilla.yaml @@ -0,0 +1,86 @@ +--- +name: example +vaults: + server: + type: filesystem + options: + keys: + store: tls/localhost.p12 + type: pkcs12 + password: ${{env.KEYSTORE_PASSWORD}} +bindings: + tcp_server0: + type: tcp + kind: server + options: + host: 0.0.0.0 + port: 9090 + exit: tls_server0 + tcp_server1: + type: tcp + kind: server + options: + host: 0.0.0.0 + port: 8080 + exit: http_server0 + tls_server0: + type: tls + kind: server + vault: server + options: + keys: + - localhost + sni: + - localhost + alpn: + - http/1.1 + - h2 + exit: http_server0 + http_server0: + type: http + kind: server + routes: + - when: + - headers: + :scheme: http + :authority: localhost:8080 + - headers: + :scheme: https + :authority: localhost:9090 + exit: http_kafka_proxy0 + http_kafka_proxy0: + type: http-kafka + kind: proxy + routes: + - when: + - path: /events + exit: kafka_cache_client0 + with: + capability: produce + topic: events + kafka_cache_client0: + type: kafka + kind: cache_client + exit: kafka_cache_server0 + kafka_cache_server0: + type: kafka + kind: cache_server + exit: kafka_client0 + kafka_client0: + type: kafka + kind: client + options: + sasl: + mechanism: scram-sha-256 + username: ${{env.SASL_USERNAME}} + password: ${{env.SASL_PASSWORD}} + exit: tcp_client0 + tcp_client0: + type: tcp + kind: client + options: + host: redpanda + port: 29092 + routes: + - when: + - cidr: 0.0.0.0/0 \ No newline at end of file diff --git a/src/get-started/install/README.md b/src/get-started/install/README.md new file mode 100644 index 00000000..ab85638a --- /dev/null +++ b/src/get-started/install/README.md @@ -0,0 +1,9 @@ +# Installing Zilla + +## Docker + +Install via `docker-compose` + +## Kubernetes + +Install via `helm chart` diff --git a/src/guides/README.md b/src/guides/README.md new file mode 100644 index 00000000..c50dac4f --- /dev/null +++ b/src/guides/README.md @@ -0,0 +1,5 @@ +# Guides + +## Configure Kafka Proxies + +In this guide, you will explore how to design/configure your API Endpoints such as [REST](kafka-proxies/rest-proxy.md) API, [SSE](kafka-proxies/sse-proxy.md) and etc. diff --git a/configure-kafka-proxies/rest-proxy.md b/src/guides/kafka-proxies/rest-proxy.md similarity index 82% rename from configure-kafka-proxies/rest-proxy.md rename to src/guides/kafka-proxies/rest-proxy.md index 040c1398..2c0141e9 100644 --- a/configure-kafka-proxies/rest-proxy.md +++ b/src/guides/kafka-proxies/rest-proxy.md @@ -4,7 +4,10 @@ Zilla lets you configure application-centric REST API endpoints that unlock `Apa A brief explanation of replaceable values from the config examples below: -
ENDPOINT_PATHHTTP path for example /tasks
KAFKA_TOPICThe Kafka topic that you want to produce to or fetch from.
KAFKA_REPLY_TO_TOPICThe Kafka topic that you want to send a response with correlation-id
AUTH_URLJWT token provider URL
+- `ENDPOINT_PATH`: HTTP path for example `/tasks` +- `KAFKA_TOPIC`: The Kafka topic that you want to produce to or fetch from. +- `KAFKA_REPLY_TO_TOPIC`: The Kafka topic that you want to send a response with `correlation-id` +- `AUTH_URL`: JWT token provider URL ### Configure Endpoints @@ -12,7 +15,8 @@ Zilla can be configured to map REST APIs to Kafka using the [http-kafka](https:/ Kafka **Produce** capability and HTTP request method types such as `POST`, `PUT`, `DELETE`, and `PATCH` . -{% code title="zilla.json" %} +#### zilla.json + ```json { "bindings": { @@ -43,15 +47,15 @@ Kafka **Produce** capability and HTTP request method types such as `POST`, `PUT` } ``` -{% endcode %} -{% hint style="info" %} -When the POST request is received by Zilla, a message is produced to the requests topic, with HTTP headers delivered as the Kafka message headers and the HTTP payload delivered as the Kafka message value. You have the option to [override headers](https://docs.aklivity.io/zilla/reference/zilla.json/binding-http-kafka#with-produce) as well. -{% endhint %} +::: info NOTE +When the POST request is received by Zilla, a message is produced to the requests topic, with HTTP headers delivered as the Kafka message headers and the HTTP payload delivered as the Kafka message value. You have the option to [override headers](https://docs.aklivity.io/zilla/reference/zilla.json/binding-http-kafka#with-produce) as well. +::: Kafka **Fetch** capability with HTTP request methods such as `GET` : -{% code title="zilla.json" %} +#### zilla.json + ```json { "bindings": { @@ -79,53 +83,53 @@ Kafka **Fetch** capability with HTTP request methods such as `GET` : } } ``` -{% endcode %} ### Dynamic URL parameters It's a common case when you want to work with a specific entity e.g. `/tasks/123`. To make sure the dynamic value `123` is correctly matched and forwarded API endpoint can be configured as in the following example: -{% code title="zilla.json" %} +#### zilla.json + ```json { - "bindings": { - ... - "http_kafka_proxy0": { - "type": "http-kafka", - "kind": "proxy", - "routes": [ + "bindings": { + ... + "http_kafka_proxy0": { + "type": "http-kafka", + "kind": "proxy", + "routes": [ + { + "when": [ { - "when": [ - { - "method": "GET", - "path": "/tasks/{id}" - } - ], - "exit": "kafka_cache_client0", - "with": { - "capability": "fetch", - "topic": "KAFKA_TOPIC" - }, - "filters": - [ - { - "key": "${params.id}" - } - ] + "method": "GET", + "path": "/tasks/{id}" } + ], + "exit": "kafka_cache_client0", + "with": { + "capability": "fetch", + "topic": "KAFKA_TOPIC" + }, + "filters": + [ + { + "key": "${params.id}" + } ] } - ... - } - } + ] + } + ... + } +} ``` -{% endcode %} ### CORS Zilla supports Cross-Origin Resource Sharing (CORS) and allows you to specify fine-grained access control including specific request origins, methods and headers allowed, and specific response headers exposed. Since it acts more like a guard and has no dependency on Apache Kafka configuration, you need to define it in the [http binding](https://docs.aklivity.io/zilla/reference/zilla.json/binding-http). -{% code title="zilla.json" %} +#### zilla.json + ```json "http_server0": { @@ -157,19 +161,19 @@ Zilla supports Cross-Origin Resource Sharing (CORS) and allows you to specify f } ``` -{% endcode %} ### Authorization -Since `Zilla` config is very much modular it has the concept of [`guard`](https://docs.aklivity.io/zilla/reference/zilla.json/guard) where you define your `guard` configuration and reference that `guard` to authorize a specific endpoint. Currently, `Zilla` supports [`JSON Web Token (JWT)`](https://docs.aklivity.io/zilla/reference/zilla.json/guard-jwt) mechanism to authorize the endpoint. +Since `Zilla` config is very much modular it has the concept of [`guard`](https://docs.aklivity.io/zilla/reference/zilla.json/guard) where you define your `guard` configuration and reference that `guard` to authorize a specific endpoint. Currently, `Zilla` supports [`JSON Web Token (JWT)`](https://docs.aklivity.io/zilla/reference/zilla.json/guard-jwt) mechanism to authorize the endpoint. The information about keys and other details such as issuer and audience you can get from `JWT` providers for example in the case of Auth0 you can use the command below. +```bash:no-line-numbers +url -s https://AUTH_URL/.well-known/jwks.json | jq .keys ``` -curl -s https://AUTH_URL/.well-known/jwks.json | jq .keys -``` -{% code title="zilla.json" %} +#### zilla.json + ```json { ... @@ -247,11 +251,10 @@ curl -s https://AUTH_URL/.well-known/jwks.json | jq .keys ] } ... - } + } ... - } +} ``` -{% endcode %} ### More diff --git a/configure-kafka-proxies/sse-proxy.md b/src/guides/kafka-proxies/sse-proxy.md similarity index 87% rename from configure-kafka-proxies/sse-proxy.md rename to src/guides/kafka-proxies/sse-proxy.md index 8ca9af2a..4e6d4a1e 100644 --- a/configure-kafka-proxies/sse-proxy.md +++ b/src/guides/kafka-proxies/sse-proxy.md @@ -4,7 +4,8 @@ There is an increasing rise in integrating the event stream into frontends where A brief explanation of replaceable values from the config examples below: -
ENDPOINT_PATHHTTP path for example /tasks
KAFKA_TOPICThe Kafka topic that you want to stream from
+- `ENDPOINT_PATH`: HTTP path for example `/tasks` +- `KAFKA_TOPIC`: The Kafka topic that you want to stream from ### Configure Endpoint diff --git a/reference/README.md b/src/reference/README.md similarity index 85% rename from reference/README.md rename to src/reference/README.md index 8e8809b9..ca11948d 100644 --- a/reference/README.md +++ b/src/reference/README.md @@ -1,4 +1,10 @@ --- +title: Reference +text: "Reference" +icon: "book" +order: 2 +category: + - Config description: Reference documentation for Zilla's CLIs and configuration formats. --- diff --git a/reference/security.json.md b/src/reference/security.json.md similarity index 100% rename from reference/security.json.md rename to src/reference/security.json.md diff --git a/reference/settings.json.md b/src/reference/settings.json.md similarity index 88% rename from reference/settings.json.md rename to src/reference/settings.json.md index 0e455fc5..3bc82eef 100644 --- a/reference/settings.json.md +++ b/src/reference/settings.json.md @@ -10,7 +10,7 @@ description: Stores the remote repository credentials in ${user.home}/.zpm/setti | Name | Type | Description | | ------------- | -------------------------------------------------------- | ------------------------------ | -| `credentials` | `array` of [`credentials`](settings.json.md#credentials) | List of repository credentials | +| `credentials` | `array` of [`credentials`](#credentials) | List of repository credentials | ### credentials diff --git a/src/reference/zilla.yaml/README.md b/src/reference/zilla.yaml/README.md new file mode 100644 index 00000000..c1037927 --- /dev/null +++ b/src/reference/zilla.yaml/README.md @@ -0,0 +1,38 @@ +--- +title: Zilla Runtime Configuration +icon: "gears" +order: 1 +category: + - config +description: Defines the Zilla runtime engine configuration in zilla.yaml +--- + +# Zilla Runtime Configuration + +The Zilla runtime configuration defines the [`bindings`](binding.md), [`guards`](guard.md) and [`vaults`](vault.md) used by the Zilla runtime engine. The values of properties in the configuration can be literals or expressions of the form `${{env.VARIABLE}}` to resolve a local environment variable value instead. + +## Properties + +### name + +> `string` + +Namespace name. + +### bindings + +> `object` as map of named [`binding`](binding.md) properties + +Map of named bindings. + +### guards + +> `object` as map of named [`guard`](guard.md) properties + +Map of named guards. + +### vaults + +> `object` as map of named [`vault`](vault.md) properties + +Map of named vaults. diff --git a/src/reference/zilla.yaml/binding-amqp.md b/src/reference/zilla.yaml/binding-amqp.md new file mode 100644 index 00000000..42646a02 --- /dev/null +++ b/src/reference/zilla.yaml/binding-amqp.md @@ -0,0 +1,128 @@ +--- +shortTitle: binding (amqp) 🚧 +description: Zilla runtime amqp binding (incubator) +category: + - Binding +tag: + - Server +--- + +# amqp Binding 🚧 + +Zilla runtime amqp binding (incubator). + +```yaml {2} +amqp_server0: + type: amqp + kind: server + routes: + - when: + - address: echo + capabilities: send_and_receive + exit: echo_server0 +``` + +## Summary + +Defines a binding with `amqp 1.0` protocol support, with `server` behavior. + +The `server` kind `amqp` binding decodes `amqp 1.0` protocol on the inbound network stream, producing higher level application streams for each `send` or `receive` `link`. + +Conditional routes based on the `link` `address` are used to route these application streams to an `exit` binding. + +## Configuration + +:::: note Properties + +- [kind\*](#kind) +- [routes](#routes) +- [routes\[\].guarded](#routes-guarded) +- [routes\[\].when](#routes-when) + - [when\[\].address](#when-address) + - [when\[\].capabilities](#when-capabilities) +- [routes\[\].exit\*](#routes-exit) + +::: right +\* required +::: + +:::: + +### kind\* + +> `enum` [ "server" ] + +Behave as an `amqp 1.0` `proxy`. + +```yaml +kind: proxy +``` + +### routes + +> `array` of `object` + +Conditional `amqp`-specific routes for adapting `http` request-response streams to `kafka` topic streams. + +```yaml +routes: + - when: + - address: echo + capabilities: send_and_receive + exit: echo_server0 +``` + +### routes[].guarded + +> `object` as named map of `string:string` `array` + +List of roles required by each named guard to authorize this route. + +```yaml +routes: + - guarded: + test0: + - read:items +``` + +### routes[].when + +> `array` of `object` + +List of conditions (any match) to match this route. + +```yaml +routes: + - when: + - address: echo + capabilities: send_and_receive +``` + +#### when[].address + +> `string` + +Link address. + +#### when[].capabilities + +> `enum` [ "send_only", "receive_only", "send_and_receive" ] + +Send or receive, or both.\ +Defaults to `"send_and_receive"`. + +### routes[].exit\* + +> `string` + +Next binding when following this route. + +```yaml +exit: echo_server0 +``` + +--- + +::: right +\* required +::: diff --git a/src/reference/zilla.yaml/binding-echo.md b/src/reference/zilla.yaml/binding-echo.md new file mode 100644 index 00000000..a011a1a0 --- /dev/null +++ b/src/reference/zilla.yaml/binding-echo.md @@ -0,0 +1,50 @@ +--- +shortTitle: binding (echo) +description: Zilla runtime echo binding +category: + - Binding +tag: + - Server +--- + +# echo binding + +Zilla runtime echo binding. + +```yaml {2} +echo_server0: + type: echo + kind: server +``` + +## Summary + +This binding supports the `echo` protocol and is run with the `server` behavior. It reads inbound messages and writes it back to the sender. + +## Configuration + +:::: note Properties + +- [kind\*](#kind) + +::: right +\* required +::: + +:::: + +### kind\* + +> enum [ "server" ] + +Behaves as an `echo` `server`. + +```yaml +kind: server +``` + +--- + +::: right +\* required +::: diff --git a/src/reference/zilla.yaml/binding-fan.md b/src/reference/zilla.yaml/binding-fan.md new file mode 100644 index 00000000..d44d4038 --- /dev/null +++ b/src/reference/zilla.yaml/binding-fan.md @@ -0,0 +1,62 @@ +--- +shortTitle: binding (fan) +description: Zilla runtime fan binding +category: + - Binding +tag: + - Server +--- + +# fan Binding + +Zilla runtime fan binding. + +```yaml {2} +fan_server0: + type: fan + kind: server + exit: echo_server0 +``` + +## Summary + +Defines a binding with `fan-in` and `fan-out` support, with `server` behavior. + +The `server` kind `fan` binding performs fan-in of data on all inbound network streams, grouping them into a single application stream. Then data received from the application stream is fanned-out to all network streams in the group. + +When the `exit` is an `echo` server binding, the combination reflects all inbound data from each client to all clients. + +## Configuration + +:::: note Properties + +- [kind\*](#kind) +- [exit\*](#exit) + +::: right +\* required +::: + +:::: + +### kind\* + +> `enum` [ "server" ] + +Behave as an `fan-in` and `fan-out` `server`. + +### exit\* + +> `string` + +Default exit binding. + +```yaml +exit: echo_server0 +``` + +--- + +::: right +\* required +::: diff --git a/src/reference/zilla.yaml/binding-filesystem.md b/src/reference/zilla.yaml/binding-filesystem.md new file mode 100644 index 00000000..6e1b57b9 --- /dev/null +++ b/src/reference/zilla.yaml/binding-filesystem.md @@ -0,0 +1,83 @@ +--- +shortTitle: binding (filesystem) +description: Zilla runtime filesystem binding +category: + - Binding +tag: + - Server +--- + +# filesystem Binding + +Zilla runtime filesystem binding. + +```yaml {2} +filesystem_server0: + type: filesystem + kind: server + options: + location: web/ + simlinks: follow +``` + +## Summary + +The `server` kind `filesystem` binding provides access to files and directories on the local filesystem, optionally following symbolic links. + +Behaves as a web server when combined with `tcp,` `tls`, `http` and `http-filesystem` bindings. + +## Configuration + +:::: note Properties + +- [kind\*](#kind) +- [options](#options) + - [options.location](#options-location) + - [options.symlinks](#options-symlinks) + +::: right +\* required +::: + +:::: + +### kind\* + +> `enum` [ "server" ] + +Behave as a `filesystem` `server`. + +```yaml +kind: server +``` + +### options + +> `object` + +`filesystem`-specifc options for `filesystem` access. + +```yaml +options: + location: web/ + simlinks: follow +``` + +#### options.location + +> `string` + +File system URI or directory name with trailing slash. + +#### options.symlinks + +> `enum` [ "follow", "ignore" ] + +How to treat symbolic links.\ +Defaults to `"ignore"`. + +--- + +::: right +\* required +::: diff --git a/src/reference/zilla.yaml/binding-http-filesystem.md b/src/reference/zilla.yaml/binding-http-filesystem.md new file mode 100644 index 00000000..c79ac449 --- /dev/null +++ b/src/reference/zilla.yaml/binding-http-filesystem.md @@ -0,0 +1,146 @@ +--- +shortTitle: binding (http-filesystem) +description: Zilla runtime http-filesystem binding +category: + - Binding +tag: + - Proxy +--- + +# http-filesystem Binding + +Zilla runtime http-filesystem binding. + +```yaml {2} +http_filesystem_proxy0: + type: http-filesystem + kind: proxy + routes: + - when: + - path: "/{path}" + exit: filesystem_server0 + with: + path: "${params.path}" +``` + +## Summary + +Defines a binding with `http-filesystem` support, with `proxy` behavior. + +The `proxy` kind `http-filesystem` binding adapts `http` data streams into `filesystem` data streams by mapping the path from an inbound `http` `GET` request into a filesystem relative path. + +Behaves as a web server when combined with `tcp,` `tls`, `http` and `filesystem` bindings. + +## Configuration + +:::: note Properties + +- [kind\*](#kind) +- [exit](#exit) +- [routes](#routes) +- [routes\[\].guarded](#routes-guarded) +- [routes\[\].when](#routes-when) + - [when\[\].path\*](#when-path) +- [routes\[\].exit\*](#routes-exit) +- [routes\[\].with](#routes-with) + - [with\[\].path\*](#with-path) + +::: right +\* required +::: + +:::: + +### kind\* + +> `enum` [ "proxy" ] + +Behave as an `http-filesystem` `proxy`. + +```yaml +kind: proxy +``` + +### exit + +> `string` + +Default exit binding when no conditional routes are viable. + +```yaml +exit: filesystem_server0 +``` + +### routes + +> `array` of `object` + +Conditional `http-kafka`-specific routes for adapting `http` data streams into `filesystem` data streams. + +```yaml +routes: + - when: + - path: "/{path}" + exit: filesystem_server0 + with: + path: "${params.path}" +``` + +### routes[].guarded + +> `object` as named map of `string:string` `array` + +List of roles required by each named guard to authorize this route. + +```yaml +routes: + - guarded: + test0: + - read:items +``` + +### routes[].when + +> `array` of `object` + +List of conditions (any match) to match this route when adapting `http` data streams into `filesystem` data streams. + +```yaml +routes: + - when: + - path: "/{path}" +``` + +#### when[].path\* + +> `string` + +Path with optional embedded parameter names, such as `/{path}`. + +### routes[].exit\* + +> `string` + +Next binding when following this route. + +```yaml +exit: filesystem_server0 +``` + +### routes[].with + +> `object` + +Filesystem parameters used when adapting `http` data streams into `filesystem` data streams. + +#### with[].path\* + +> `string` + +Topic name, optionally referencing path parameter such as `${params.path}`. + +--- + +::: right +\* required +::: diff --git a/src/reference/zilla.yaml/binding-http-kafka.md b/src/reference/zilla.yaml/binding-http-kafka.md new file mode 100644 index 00000000..b2cbbdbb --- /dev/null +++ b/src/reference/zilla.yaml/binding-http-kafka.md @@ -0,0 +1,422 @@ +--- +shortTitle: binding (http-kafka) +description: Zilla runtime http-kafka binding +category: + - Binding +tag: + - Proxy +--- + +# http-kafka Binding + +Zilla runtime http-kafka binding. + +```yaml {2} +http_kafka_proxy0: + type: http-kafka + kind: proxy + routes: + - when: + - method: GET + path: "/items" + exit: kafka_cache_client0 + with: + capability: fetch + topic: items-snapshots + merge: + content-type: application/json + - when: + - method: GET + path: "/items/{id}" + exit: kafka_cache_client0 + with: + capability: fetch + topic: items-snapshots + filters: + - key: "${params.id}" + - when: + - path: "/items/{id}" + - method: GET + path: "/items/{id};{correlationId}" + exit: kafka_cache_client0 + with: + capability: produce + topic: items-requests + acks: leader_only + key: "${params.id}" + reply-to: items-responses + async: + location: "/items/${params.id};${correlationId}" +``` + +## Summary + +The `proxy` kind `http-kafka` binding adapts `http` request-response streams to `kafka` topic streams. + +## Fetch capability + +Routes with `fetch` capability map `http` `GET` requests to a `kafka` log-compacted topic, supporting filtered retrieval of messages with a specific key, or unfiltered retrieval of all messages with distinct keys in the topic merged into a unified response. + +Filtering can be performed by `kafka` message key, message headers, or a combination of both message key and headers, extracting the parameter values from the inbound `http` request path. + +Status `200` `http` responses include an `etag` header that can be used with `if-none-match` for subsequent conditional `GET` requests to check for updates. Rather than polling, `http` requests can also include the `prefer: wait=N` header to wait a maximum of `N` seconds before responding with `304` if not modified. When a new message arrives in the topic that would modify the response, then all `prefer: wait=N` clients receive the response immediately. + +## Produce capability + +Routes with `produce` capability map any `http` request-response to a correlated pair of `kafka` messages. The `http` request message is sent to a `requests` topic, with a `zilla:correlation-id` header. When the request message received and processed by the `kafka` `requests` topic consumer, it produces a response message to the `responses` topic, with the same `zilla:correlation-id` header to correlate the response. + +Requests including an `idempotency-key` `http` header can be replayed and safely receive the same response. This requires the `kafka` consumer to detect and ignore the duplicate request with the same `idempotency-key` and `zilla:correlation-id`. + +Specifying `async` allows clients to include a `prefer: respond-async` header in the `http` request to receive `202 Accepted` response with `location` response header. + +A corresponding `routes[].when` object with matching `GET` method and `location` path is also required for follow up `GET` requests to return the same response as would have been returned if `prefer: respond-async` request header had been omitted. + +## Configuration + +:::: note Properties + +- [kind\*](#kind) +- [options](#options) + - [options.idempotency](#options-idempotency) + - [idempotency.header](#idempotency-header) + - [options.correlation](#options-correlation) + - [correlation.headers](#correlation-headers) + - [headers.reply-to](#headers-reply-to) + - [headers.correlation-id](#headers-correlation-id) +- [routes](#routes) +- [routes\[\].guarded](#routes-guarded) +- [routes\[\].when](#routes-when) + - [when\[\].method](#when-method) + - [when\[\].path](#when-path) +- [routes\[\].exit\*](#routes-exit) +- [routes\[\].with](#routes-with) +- [with.capability (fetch)](#with-capability-fetch) + - [with.topic](#with-topic) + - [with.filters](#with-filters) + - [filters\[\].key](#filters-key) + - [filters\[\].headers](#filters-headers) + - [with.merge](#with-merge) + - [merge.content-type](#merge-content-type) + - [merge.patch](#merge-patch) + - [patch.initial](#patch-initial) + - [patch.path](#patch-path) +- [with.capability (produce)](#with-capability-produce) + - [with.topic](#with-topic-1) + - [with.acks](#with-acks) + - [with.key](#with-key) + - [with.overrides](#with-overrides) + - [with.reply-to](#with-reply-to) + - [with.async](#with-async) + +::: right +\* required +::: + +:::: + +### kind\* + +> `enum` [ "proxy" ] + +Behave as an `http-kafka` `proxy`. + +```yaml +kind: proxy +``` + +### options + +> `object` + +`http-kafka`-specific options for adapting `http` request-response streams to `kafka` topic streams. + +```yaml +options: + idempotency: + header: idempotency-key + correlation: + headers: + reply-to: zilla:reply-to + correlation-id: zilla:correlation-id +``` + +#### options.idempotency + +> `object` + +HTTP request header used to specify the idempotency key when adapting `http` request-response streams to `kafka` topic streams. + +##### idempotency.header + +> `string` + +HTTP request header name for idempotency key.\ +Defaults to `"idempotency-key"`. + +#### options.correlation + +> `object` + +Kafka request message headers injected when adapting `http` request-response streams to `kafka` topic streams. + +##### correlation.headers + +> `object` + +Kafka request message reply to and correlation id header names injected when adapting `http` request-response streams to `kafka` topic streams. + +##### headers.reply-to + +> `string` + +Kafka header name for reply-to topic.\ +Defaults to `"zilla:reply-to"`. + +##### headers.correlation-id + +> `string` + +Kafka header name for request-response correlation identifier.\ +Defaults to `"zilla:correlation-id"`. + +### routes + +> `array` of `object` + +Conditional `http-kafka`-specific routes for adapting `http` request-response streams to `kafka` topic streams. + +```yaml +routes: + - when: + - method: GET + path: "/items" + exit: kafka_cache_client0 + with: + capability: fetch + topic: items-snapshots + merge: + content-type: application/json + - when: + - method: GET + path: "/items/{id}" + exit: kafka_cache_client0 + with: + capability: fetch + topic: items-snapshots + filters: + - key: "${params.id}" + - when: + - path: "/items/{id}" + - method: GET + path: "/items/{id};{correlationId}" + exit: kafka_cache_client0 + with: + capability: produce + topic: items-requests + acks: leader_only + key: "${params.id}" + reply-to: items-responses +``` + +### routes[].guarded + +> `object` as named map of `string:string` `array` + +Roles required by named guard. + +```yaml +routes: + - guarded: + test0: + - read:items +``` + +### routes[].when + +> `array` of `object` + +List of conditions (any match) to match this route when adapting `http` request-response streams to `kafka` topic streams. + +```yaml +routes: + - when: + - method: GET + path: "/items/{id};{correlationId}" +``` + +#### when[].method + +> `string` + +HTTP Method, such as `GET`, `HEAD`, `POST`, `PUT`, `DELETE`, `CONNECT`, `OPTIONS`, `TRACE`, `PATCH`. + +#### when[].path + +> `string` + +Path with optional embedded parameter names, such as `/{topic}`. + +### routes[].exit\* + +> `string` + +Default exit binding when no conditional routes are viable. + +```yaml +exit: kafka_cache_client0 +``` + +### routes[].with + +> **oneOf**: [Fetch](#with-capability-fetch) | [Produce](#with-capability-produce) + +Defines the route with the Fetch capability. + +```yaml +with: + capability: fetch +``` + +Defines the route with the Produce capability. + +```yaml +with: + capability: produce +``` + +### with.capability (fetch) + +> `object` + +Kafka parameters for matched route when adapting `http` request-response streams to `kafka` topic fetch streams. + +```yaml +with: + capability: fetch + topic: items-snapshots + filters: + - key: "${params.id}" + merge: + content-type: application/json + patch: + initial: "[]" + path: /- +``` + +#### with.topic + +> `string` + +Topic name, optionally referencing path parameter such as `${params.topic}`. + +#### with.filters + +> `array` of `object` + +List of criteria (any match) to this filter. Kafka filters for matched route when adapting `http` request-response streams to `kafka` topic fetch streams. All specified headers and key must match for the combined criteria to match. + +##### filters[].key + +> `string` + +Message key, optionally referencing path parameter such as `${params.key}`. + +##### filters[].headers + +> `object` + +Message headers, with value optionally referencing path parameter such as `${params.headerX}`. + +#### with.merge + +> `object` + +Merge multiple Kafka messages into a unified HTTP response. Kafka merge configuration for matched route when adapting `http` request-response streams to `kafka` topic streams where all messages are fetched and must be merged into a unified `http` response. + +##### merge.content-type + +> `const` "application/json" + +Content type of merged HTTP response. + +##### merge.patch + +> `object` + +Describes how to patch initial HTTP response to include one or more Kafka messages in unified HTTP response. + +- patch (application/json) + + Kafka merge patch configuration for matched route when adapting `http` request-response streams to `kafka` topic streams where all messages are fetched and must be merged into a unified `http` response. + +##### patch.initial + +> `string` + +Initial JSON value. + +##### patch.path + +> `const` "/-" + +JSON Patch path to include each Kafka message in unified HTTP response. + +### with.capability (produce) + +> `object` + +Kafka parameters for matched route when adapting `http` request-response streams to `kafka` topic pruduce streams. + +```yaml +with: + capability: produce + topic: items-requests + acks: leader_only + key: "${params.id}" + reply-to: items-responses + async: + location: "/items/${params.id};${correlationId}" +``` + +#### with.topic + +> `string` + +Kafka topic name, optionally referencing path parameter such as `${params.topic}`. + +#### with.acks + +> `enum` [ "none", "leader_only", "in_sync_replicas" ] + +Kafka acknowledgement mode\ +Defaults to `"in_sync_replicas"`. + +#### with.key + +> `string` + +Kafka message key, optionally referencing path parameter such as `${params.id}`. + +#### with.overrides + +> `object` + +Kafka message headers, with values optionally referencing path parameter. + +#### with.reply-to + +> `string` + +Kafka reply-to topic name. + +#### with.async + +> `object` + +HTTP response headers, with values optionally referencing path parameter or `${correlationId}`. + +--- + +::: right +\* required +::: diff --git a/src/reference/zilla.yaml/binding-http.md b/src/reference/zilla.yaml/binding-http.md new file mode 100644 index 00000000..55c58f96 --- /dev/null +++ b/src/reference/zilla.yaml/binding-http.md @@ -0,0 +1,324 @@ +--- +shortTitle: binding (http) +description: Zilla runtime http binding +category: + - Binding +tag: + - Server +--- + +# http Binding + +Zilla runtime http binding. + +```yaml {2} +http_server0: + type: http + kind: server + options: + access-control: + policy: cross-origin + authorization: + jwt0: + credentials: + headers: + authorization: Bearer {credentials} + routes: + - when: + - headers: + ":scheme": https + ":authority": example.com:443 + exit: echo_server0 +``` + +## Summary + +Defines a binding with `http` protocol support, with `server` or `client` behavior. + +#### Server behavior + +The `server` kind `http` binding decodes `HTTP/1.1` protocol or `HTTP/2` protocol on the inbound network stream, producing higher level application streams for each request. + +Cross-Origin Resource Sharing (CORS) is supported by specifying an access control policy of `cross-origin`. Further configuration allows for finer-grained access control including specific request origins, methods and headers allowed, and specific response headers exposed. + +Authorization is enforced by a [`guard`](guard.md) and the credentials can be extracted from a cookie, header or query parameter. + +Conditional routes based on `http` request headers are used to route these application streams to an `exit` binding. + +#### Client behavior + +The `client` kind `http` binding receives inbound application streams and encodes each request as a network stream via `HTTP/1.1` protocol. Note that the same network stream can be reused to encode multiple `HTTP/1.1` requests. + +Conditional routes based on `http` request headers are used to route these network streams to an `exit` binding. + +## Configuration + +:::: note Properties + +- [kind\*](#kind) +- [options](#options) +- [options.versions](#options-versions) +- [options.access-control](#options-access-control) + - [access-control.policy\*](#access-control-policy) + - [access-control.policy (same-origin)](#access-control-policy-same-origin) + - [access-control.policy (cross-origin)](#access-control-policy-cross-origin) + - [access-control.allow](#access-control-allow) + - [allow.origins](#allow-origins) + - [allow.methods](#allow-methods) + - [allow.headers](#allow-headers) + - [allow.credentials](#allow-credentials) + - [access-control.max-age](#access-control-max-age) + - [access-control.expose](#access-control-expose) + - [expose.headers](#expose-headers) +- [options.authorization](#options-authorization) + - [authorization.credentials](#authorization-credentials) + - [credentials.cookies](#credentials-cookies) + - [credentials.headers](#credentials-headers) + - [credentials.query](#credentials-query) +- [options.overrides](#options-overrides) +- [exit](#exit) +- [routes](#routes) +- [routes\[\].guarded](#routes-guarded) +- [routes\[\].when](#routes-when) + - [when\[\].headers](#when-headers) +- [routes\[\].exit\*](#routes-exit) + +::: right +\* required +::: + +:::: + +### kind\* + +> `enum` [ "server", "client" ] + +Behave as an `http` `server` or `client`. + +### options + +> `object` + +`http`-specifc options. + +```yaml +options: + access-control: + policy: cross-origin + authorization: + jwt0: + credentials: + headers: + authorization: Bearer {credentials} +``` + +### options.versions + +> `array` of `enum` [ "http/1.1", "h2" ] + +Supported protocol versions. + +### options.access-control + +> **oneOf**: [same-origin](#access-control-policy-same-origin) | [cross-origin](#access-control-policy-cross-origin) + +Access control policy for the `HTTP` protocol. + +#### access-control.policy\* + +> `enum` [ "same-origin" , "cross-origin" ] + +Supported access control policies. + +#### access-control.policy (same-origin) + +> `string` + +Extra properties aren't needed when using Same Origin access control for the `HTTP` protocol. + +```yaml +options: + access-control: + policy: same-origin +``` + +#### access-control.policy (cross-origin) + +> `object` + +Additional properties that cover Cross Origin Resource Sharing (CORS) access control for the `HTTP` protocol. + +```yaml +options: + access-control: + policy: cross-origin +``` + +#### access-control.allow + +> `object` + +Allowed cross-origin request origins, methods, headers and credentials.\ +Defaults to all origins, methods and headers, without credentials. +CORS allowed request origins, methods, headers and credentials for the `HTTP` protocol. + +##### allow.origins + +> `array` of `string` + +Allowed request origins. + +##### allow.methods + +> `array` of `string` + +Allowed request methods. + +##### allow.headers + +> `array` of `string` + +Allowed request headers. + +##### allow.credentials + +> `boolean` + +Support `fetch` credentials mode `include`. + +#### access-control.max-age + +> `number` + +Maximum cache age (in seconds) for allowed headers and methods. + +#### access-control.expose + +> `object` + +Exposed cross-origin response headers.\ +Defaults to all response headers. + +##### expose.headers + +> `array` of `string` + +Exposed response headers. + +### options.authorization + +> `object` as map of named properties + +Authorization by guard for the `HTTP/1.1` and `HTTP/2` protocols. + +```yaml +authorization: + jwt0: + credentials: + headers: + authorization: Bearer {credentials} +``` + +#### authorization.credentials + +> `object` + +Defines how to extract credentials from the HTTP request. + +##### credentials.cookies + +> `object` as map of `string` + +Named cookie value pattern with `{credentials}`. + +##### credentials.headers + +> `object` as map of `string` + +Named header value pattern with `{credentials}`, e.g. `"Bearer` `{credentials}"`. + +##### credentials.query + +> `object` as map of `string` + +Named query parameter value pattern with `{credentials}`. + +### options.overrides + +> `object` of name-value header overrides + +Request header overrides. + +### exit + +> `string` + +Default exit binding when no conditional routes are viable. + +```yaml +exit: echo_server0 +``` + +### routes + +> `array` of `object` + +Conditional `http`-specific routes. + +```yaml +routes: + - when: + - headers: + ":scheme": https + ":authority": example.com:443 + exit: echo_server0 +``` + +### routes[].guarded + +> `object` as named map of `string:string` `array` + +List of roles required by each named guard to authorize this route. + +```yaml +routes: + - guarded: + test0: + - read:items +``` + +### routes[].when + +> `array` of `object` + +List of conditions (any match) to match this route. + +```yaml +routes: + - when: + - headers: + ":scheme": https + ":authority": example.com:443 +``` + +#### when[].headers + +> `object` of name-value headers + +Header name value pairs (all match). + +### routes[].exit\* + +> `string` + +Next binding when following this route. + +```yaml +exit: echo_server0 +``` + +--- + +::: right +\* required +::: diff --git a/src/reference/zilla.yaml/binding-kafka.md b/src/reference/zilla.yaml/binding-kafka.md new file mode 100644 index 00000000..9d1bee24 --- /dev/null +++ b/src/reference/zilla.yaml/binding-kafka.md @@ -0,0 +1,220 @@ +--- +shortTitle: binding (kafka) +description: Zilla runtime kafka binding +category: + - Binding +tag: + - Server +--- + +# kafka Binding + +Zilla runtime kafka binding. + +```yaml {2,10,17} +kafka_cache_client0: + type: kafka + kind: cache_client + options: + merged: + - items-requests + - items-responses + exit: kafka_cache_server0 +kafka_cache_server0: + type: kafka + kind: cache_server + options: + bootstrap: + - items-responses + exit: kafka_client0 +kafka_client0: + type: kafka + kind: client + exit: tcp_client0 +``` + +## Summary + +Defines a binding with `kafka` protocol support, with `cache_client`, `cache_server` or `client` behavior. + +#### Cache behavior + +The `cache_client` and `cache_server` kinds combine to provide a persistent cache of `kafka` messages per `topic` `partition` honoring the `kafka` `topic` configuration for message expiration and compaction. Messages ordering is guaranteed per `partition` and messages are merged into a unified stream for the `topic` spanning all `partitions`. + +The `cache_server` kind supports proactive `fetch` of messages to keep the cache fresh in preparation for new consumers. This is enabled by configuring a list of `bootstrap` topics for the binding. + +The `cache_client` kind supports filtering by `kafka` message key, headers or a combination of key and headers. + +Message conflation occurs implicitly for `compacted` `kafka` topics, where a slower consumer that is not keeping up with the latest messages can safely skip over each older message that has effectively been replaced by a newer message with the same key. + +When a new consumer arrives, the latest messages in the compacted topic are immediately delivered to that consumer, followed by any additional messages as they are produced to the `kafka` `topic`. + +When the `kafka` `topic` is not compacted, then the binding can be configured to either replay historical messages first, or start with upcoming live messages instead. + +The `cache_client` and `cache_server` also combine to provide a staging area when producing new messages as `kafka` requires exact message length up front when producing new messages and `kafka` does not support producing multiple messages in parallel over the same network connection. + +#### Client behavior + +The `client` kind `kafka` binding receives inbound application streams and encodes each as a network stream via `kafka` request-response protocol. Note that the same network stream can be reused to encode multiple `kafka` requests, including both `fetch` and `produce` requests. + +Conditional routes based on `kafka` `topic` names are used to route these network streams to an `exit` binding that ultimately reaches a `kafka` broker. + +## Configuration + +:::: note Properties + +- [kind\*](#kind) +- [options](#options) +- [options.bootstrap](#options-bootstrap) +- [options.topics](#options-topics) + - [topics\[\].name\*](#topics-name) + - [topics\[\].defaultOffset](#topics-defaultoffset) +- [options.sasl](#options-sasl) + - [sasl.name](#sasl-name) + - [sasl.mechanism\*](#sasl-mechanism) + - [sasl.username](#sasl-username) + - [sasl.password](#sasl-password) +- [exit](#exit) +- [routes](#routes) +- [routes\[\].guarded](#routes-guarded) +- [routes\[\].when](#routes-when) + - [when\[\].topic\*](#when-topic) +- [routes\[\].exit\*](#routes-exit) + +::: right +\* required +::: + +:::: + +### kind\* + +> `enum` [ "cache_client", "cache_server", "client" ] + +Behave as a `kafka` `cache_client`, `cache_server` or `client`. + +### options + +> `object` + +`kafka`-specific options. + +```yaml +options: + merged: + - items-requests + - items-responses +``` + +### options.bootstrap + +> `array` of `string` + +Topics to bootstrap in cache server even when no clients. + +### options.topics + +> `array` of `object` + +Topic configuration. + +#### topics[].name\* + +> `string` + +Topic name. + +#### topics[].defaultOffset + +> `enum` [ "live", "historical" ] + +Fetch offset to use for new consumers\ +Defaults to `"historical"`. + +### options.sasl + +> `object` + +SASL credentials to use when connecting to `kafka` brokers. + +#### sasl.name + +> `string` + +Mechanism name. + +#### sasl.mechanism\* + +> `enum` [ "plain", "scram-sha-1", "scram-sha-256", "scram-sha-512" ] + +SASL mechanism\ +Supports `plain` and `scram` mechanisms. + +#### sasl.username + +> `string` + +SASL username. + +#### sasl.password + +> `string` + +SASL password. + +### exit + +> `string` + +Default exit binding when no conditional routes are viable. + +```yaml +exit: echo_server0 +``` + +### routes + +> `array` of `object` + +Conditional `kafka`-specific routes. + +### routes[].guarded + +> `object` as named map of `string:string` `array` + +List of roles required by each named guard to authorize this route. + +```yaml +routes: + - guarded: + test0: + - read:items +``` + +### routes[].when + +> `array` of `object` + +List of conditions (any match) to match this route. + +#### when[].topic\* + +> `string` + +Topic name pattern. + +### routes[].exit\* + +> `string` + +Next binding when following this route. + +```yaml +exit: echo_server0 +``` + +--- + +::: right +\* required +::: diff --git a/src/reference/zilla.yaml/binding-mqtt.md b/src/reference/zilla.yaml/binding-mqtt.md new file mode 100644 index 00000000..bc9ba008 --- /dev/null +++ b/src/reference/zilla.yaml/binding-mqtt.md @@ -0,0 +1,127 @@ +--- +shortTitle: binding (mqtt) 🚧 +description: Zilla runtime mqtt binding (incubator) +category: + - Binding +tag: + - Server +--- + +# binding (mqtt) 🚧 + +Zilla runtime mqtt binding (incubator). + +```yaml {2} +mqtt_server0: + type: mqtt + kind: server + routes: + - when: + - topic: echo + capabilities: publish_and_subscribe + exit: echo_server0 +``` + +## Summary + +Defines a binding with `mqtt 5.0` protocol support, with `server` behavior. + +The `server` kind `mqtt` binding decodes `mqtt 5.0` protocol on the inbound network stream, producing higher level application streams for each `publish` or `subscribe` `topic`. + +Conditional routes based on the `topic` `name` are used to route these application streams to an `exit` binding. + +## Configuration + +:::: note Properties + +- [kind\*](#kind) +- [exit](#exit) +- [routes](#routes) +- [routes\[\].guarded](#routes-guarded) +- [routes\[\].when](#routes-when) + - [when\[\].topic\*](#when-topic) + - [when\[\].capabilities](#when-capabilities) +- [routes\[\].exit\*](#routes-exit) + +::: right +\* required +::: + +:::: + +### kind\* + +> `enum` [ "server" ] + +Behave as a `mqtt` `server`. + +### exit + +> `string` + +Default exit binding when no conditional routes are viable. + +```yaml +exit: echo_server0 +``` + +### routes + +> `array` of `object` + +Conditional `mqtt`-specific routes. + +### routes[].guarded + +> `object` as named map of `string:string` `array` + +List of roles required by each named guard to authorize this route. + +```yaml +routes: + - guarded: + test0: + - read:items +``` + +### routes[].when + +> `array` of `object` + +List of conditions (any match) to match this route. + +```yaml +routes: + - when: + - topic: echo + capabilities: publish_and_subscribe +``` + +#### when[].topic\* + +> `string` + +Topic name. + +#### when[].capabilities + +> `enum` [ "publish_only", "subscribe_only", "publish_and_subscribe" ] + +Publish or subscribe, or both.\ +Defaults to `"publish_and_subscribe"`. + +### routes[].exit\* + +> `string` + +Next binding when following this route. + +```yaml +exit: echo_server0 +``` + +--- + +::: right +\* required +::: diff --git a/src/reference/zilla.yaml/binding-proxy.md b/src/reference/zilla.yaml/binding-proxy.md new file mode 100644 index 00000000..ba93b906 --- /dev/null +++ b/src/reference/zilla.yaml/binding-proxy.md @@ -0,0 +1,176 @@ +--- +shortTitle: binding (proxy) +description: Zilla runtime proxy binding +category: + - Binding +tag: + - Proxy + - Server +--- + +# proxy Binding + +Zilla runtime proxy binding. + +```yaml {2} +proxy_server0: + type: proxy + kind: server + routes: + - when: + - transport: stream + family: inet4 + destination: + port: 443 + exit: tls_server0 +``` + +## Summary + +Defines a binding with `proxy` protocol support, with `server` or `client` behavior. + +The `server` kind `proxy` binding decodes `Proxy v2` protocol on the inbound network stream, producing higher level application streams for each request. + +The `client` kind `proxy` binding receives inbound application streams and encodes each as a network stream via `Proxy v2` protocol. + +Conditional routes based on the network transport type or network addresses are used to route these streams to an `exit` binding. + +## Configuration + +:::: note Properties + +- [kind\*](#kind) +- [exit](#exit) +- [routes](#routes) +- [routes\[\].guarded](#routes-guarded) +- [routes\[\].when](#routes-when) + - [when\[\].transport](#when-transport) + - [when\[\].family](#when-family) + - [when\[\].source](#when-source) + - [source.host](#source-host) + - [source.port](#source-port) + - [when\[\].destination](#when-destination) + - [destination.host](#destination-host) + - [destination.port](#destination-port) +- [routes\[\].exit\*](#routes-exit) + +::: right +\* required +::: + +:::: + +### kind\* + +> `enum` [ "client", "server" ] + +Behave as `proxy` `client` or `server`. + +### exit + +> `string` + +Default exit binding when no conditional routes are viable. + +```yaml +exit: echo_server0 +``` + +### routes + +> `array` of `object` + +Conditional `proxy`-specific routes. + +```yaml +routes: + - when: + - transport: stream + family: inet4 + destination: + port: 443 + exit: tls_server0 +``` + +### routes[].guarded + +> `object` as named map of `string:string` `array` + +List of roles required by each named guard to authorize this route. + +```yaml +routes: + - guarded: + test0: + - read:items +``` + +### routes[].when + +> `array` of `object` + +List of conditions (any match) to match this route. + +#### when[].transport + +> `enum` [ "stream", "datagram" ] + +Transport type. + +#### when[].family + +> `enum` [ "inet", "inet4", "inet6", "unix" ] + +Address family. + +#### when[].source + +> `object` + +Source address. + +##### source.host + +> `string` + +Hostname or IP address. + +##### source.port + +> `integer` + +Port number. + +#### when[].destination + +> `object` + +Destination address. + +##### destination.host + +> `string` + +Hostname or IP address. + +##### destination.port + +> `integer` + +Port number. + +### routes[].exit\* + +> `string` + +Next binding when following this route. + +```yaml +exit: echo_server0 +``` + +--- + +::: right +\* required +::: diff --git a/src/reference/zilla.yaml/binding-sse-kafka.md b/src/reference/zilla.yaml/binding-sse-kafka.md new file mode 100644 index 00000000..21e37ea7 --- /dev/null +++ b/src/reference/zilla.yaml/binding-sse-kafka.md @@ -0,0 +1,195 @@ +--- +shortTitle: binding (sse-kafka) +description: Zilla runtime sse-kafka binding +category: + - Binding +tag: + - Proxy +--- + +# sse-kafka Binding + +Zilla runtime sse-kafka binding. + +```yaml {2} +sse_kafka_proxy0: + type: sse-kafka + kind: proxy + routes: + - when: + - path: "/items" + exit: kafka_cache_client0 + with: + topic: items-snapshots + event: + id: '["${base64(key)}","${etag}"]' +``` + +## Summary + +Defines a binding with `sse-kafka` support, with `proxy` behavior. + +The `proxy` kind `sse-kafka` binding adapts `sse` data streams into `kafka` data streams, so that `kafka` messages can be delivered to `sse` clients. + +Filtering can be performed by `kafka` message key, message headers, or a combination of both message key and headers, extracting the parameter values from the inbound `sse` path. + +Progress across `kafka` topic partitions is conveyed to the `sse` client via event `id` and when the stream is implicitly paused during `sse` client reconnect, the `last-event-id` header in the `sse` reconnect request contains the last received event `id` value, allowing the `sse` stream to resume reliable message delivery automatically. + +The event `id` can be configured to include the message `key` and `etag` of each message, avoiding the need to duplicate the key in the message body and making it suitable for integration with `http-kafka` binding's use of `etag` for conditional `if-match` operations. + +When a `kafka` tombstone (`null` value) message is received by the `sse-kafka` binding, it delivers a `delete` event to the `sse` client. This informs the client which specific message has been deleted by observing the message key from the `sse` `delete` event `id`. + +## Configuration + +:::: note Properties + +- [kind\*](#kind) +- [exit](#exit) +- [routes](#routes) +- [routes\[\].guarded](#routes-guarded) +- [routes\[\].when](#routes-when) + - [when\[\].path\*](#when-path) +- [routes\[\].exit\*](#routes-exit) +- [routes\[\].with](#routes-with) + - [with.topic\*](#with-topic) + - [with.filters](#with-filters) + - [filters\[\].key](#filters-key) + - [filters\[\].headers](#filters-headers) + - [filters\[\].event](#filters-event) + - [with.event](#with-event) + - [event.id\*](#event-id) + +::: right +\* required +::: + +:::: + +### kind\* + +> `enum` [ "proxy" ] + +Behave as a `sse-kafka` `proxy`. + +### exit + +> `string` + +Default exit binding when no conditional routes are viable. + +```yaml +exit: kafka_cache_client0 +``` + +### routes + +> `array` of `object` + +Conditional `sse-kafka`-specific routes for adapting `sse` data streams to `kafka` data streams. + +```yaml +routes: + - when: + - path: "/items" + exit: kafka_cache_client0 + with: + topic: items-snapshots + event: + id: '["${base64(key)}","${etag}"]' +``` + +### routes[].guarded + +> `object` as named map of `string:string` `array` + +List of roles required by each named guard to authorize this route. + +```yaml +routes: + - guarded: + test0: + - read:items +``` + +### routes[].when + +> `array` of `object` + +List of conditions (any match) to match this route. + +```yaml +routes: + - when: + - path: "/items" +``` + +#### when[].path\* + +> `string` + +Path with optional embedded parameter names, such as `/{topic}`. + +### routes[].exit\* + +> `string` + +Next binding when following this route. + +```yaml +exit: kafka_cache_client0 +``` + +### routes[].with + +> `object` + +Kafka parameters used when adapting `sse` data streams to `kafka` data streams. + +#### with.topic\* + +> `string` + +Topic name, optionally referencing path parameter such as `${params.topic}`. + +#### with.filters + +> `array` of `object` + +List of criteria (any match)Kafka filters for matched route when adapting `sse` data streams to `kafka` data streams. + +All specified headers and key must match for the combined criteria to match. + +##### filters[].key + +> `string` + +Message key, optionally referencing path parameter such as `${params.key}`. + +##### filters[].headers + +> `object` + +Message headers, with value optionally referencing path parameter such as `${params.headerX}`. + +##### filters[].event + +> `object` + +#### with.event + +> `object` + +Defines the SSE event syntax used when delivering Kafka messages to SSE clients. + +##### event.id\* + +> `enum` [ `"${etag}"`, `"["${base64(key)}","${etag}"]"` ] + +Format of `id` field in `sse` `event`\ +Defaults to `"${etag}"`. + +--- + +::: right +\* required +::: diff --git a/src/reference/zilla.yaml/binding-sse.md b/src/reference/zilla.yaml/binding-sse.md new file mode 100644 index 00000000..cb197d5d --- /dev/null +++ b/src/reference/zilla.yaml/binding-sse.md @@ -0,0 +1,144 @@ +--- +shortTitle: binding (sse) +description: Zilla runtime sse binding +category: + - Binding +tag: + - Server +--- + +# sse Binding + +Zilla runtime sse binding. + +```yaml {2} +sse_server0: + type: sse + kind: server + exit: sse_kafka_proxy0 +``` + +## Summary + +Defines a binding with `Server Sent Events (sse)` protocol support, with `server` behavior. + +The `server` kind `sse` binding converts inbound `http` request-response streams into `sse` request-response streams, with optionally configured `retry` delay. + +Messages received on the `sse` response stream are encoded using `Server Sent Events` protocol, including support for custom `event` types and last event `id`. + +## Configuration + +:::: note Properties + +- [kind\*](#kind) +- [options](#options) +- [options.retry](#options-retry) +- [exit](#exit) +- [routes](#routes) +- [routes\[\].guarded](#routes-guarded) +- [routes\[\].when](#routes-when) + - [when\[\].path\*](#when-path) +- [routes\[\].exit\*](#routes-exit) + +::: right +\* required +::: + +:::: + +### kind\* + +> `enum` [ "client", "server" ] + +Behave as a `sse` `client` or `server`. + +### options + +> `object` + +`sse`-specific options. + +```yaml +options: + retry: 2000 +``` + +### options.retry + +> `integer` + +Retry delay (ms)\ +Defaults to `2000`. + +### exit + +> `string` + +Default exit binding when no conditional routes are viable. + +```yaml +exit: sse_kafka_proxy0 +``` + +### routes + +> `array` of `object` + +Conditional `sse`-specific routes. + +```yaml +routes: + - guarded: + test0: + - read:items + when: + - path: "/items" + exit: sse_kafka_proxy0 +``` + +### routes[].guarded + +> `object` as named map of `string:string` `array` + +List of roles required by each named guard to authorize this route. + +```yaml +routes: + - guarded: + test0: + - read:items +``` + +### routes[].when + +> `array` of `object` + +List of conditions (any match) to match this route. + +```yaml +routes: + - when: + - path: "/items" +``` + +#### when[].path\* + +> `string` + +Path pattern. + +### routes[].exit\* + +> `string` + +Next binding when following this route. + +```yaml +exit: sse_kafka_proxy0 +``` + +--- + +::: right +\* required +::: diff --git a/src/reference/zilla.yaml/binding-tcp.md b/src/reference/zilla.yaml/binding-tcp.md new file mode 100644 index 00000000..18101ece --- /dev/null +++ b/src/reference/zilla.yaml/binding-tcp.md @@ -0,0 +1,136 @@ +--- +shortTitle: binding (tcp) +description: Zilla runtime tcp binding +category: + - Binding +tag: + - Server +--- + +# tcp Binding + +Zilla runtime tcp binding. + +```yaml {2} +tcp_server0: + type: tcp + kind: server + options: + host: 0.0.0.0 + port: 12345 + exit: echo_server0 +``` + +## Summary + +Defines a binding with `tcp` protocol support, with `server` or `client` behavior. + +The `server` kind `tcp` binding listens for inbound socket connections, producing higher level application streams for each remote `tcp` client. + +The `client` kind `tcp` binding receives inbound application streams and initiates outbound `tcp` network connections to a remote `tcp` server address. + +Conditional routes based on the hostname authority and network address mask are used to route these streams to an `exit` binding. + +## Configuration + +:::: note Properties + +- [kind\*](#kind) +- [options](#options) +- [options.host](#options-host) +- [options.port](#options-port) +- [exit](#exit) +- [routes](#routes) +- [routes\[\].guarded](#routes-guarded) +- [routes\[\].when](#routes-when) + - [when\[\].authority](#when-authority) + - [when\[\].cidr](#when-cidr) +- [routes\[\].exit\*](#routes-exit) + +::: right +\* required +::: + +:::: + +### kind\* + +> `enum` [ "client", "server" ] + +Behave as a `tcp` `client` or `server`. + +### options + +> `object` + +`tcp`-specific options. + +```yaml +options: + host: 0.0.0.0 + port: 12345 +``` + +### options.host + +> `string` + +Hostname or IP address. + +### options.port + +> `integer` + +`string` | `array` of `integer` | `array` of `string` | Port number(s), including port number ranges. + +### exit + +> `string` + +Default exit binding when no conditional routes are viable, for kind `server` only. + +```yaml +exit: echo_server0 +``` + +### routes + +> `array` of `object` + +Conditional `tcp`-specific routes. + +### routes[].guarded + +> `object` as named map of `string:string` `array` + +List of roles required by each named guard to authorize this route. + +### routes[].when + +> `array` of `object` + +List of conditions (any match) to match this route. + +#### when[].authority + +> `string` + +Associated authority. + +#### when[].cidr + +> `string` + +CIDR mask. + +### routes[].exit\* + +> `string` + +Next binding when following this route, for kind `server` only. + +--- + +::: right +\* required +::: diff --git a/src/reference/zilla.yaml/binding-tls.md b/src/reference/zilla.yaml/binding-tls.md new file mode 100644 index 00000000..1ffea57f --- /dev/null +++ b/src/reference/zilla.yaml/binding-tls.md @@ -0,0 +1,238 @@ +--- +shortTitle: binding (tls) +description: Zilla runtime tls binding +category: + - Binding +tag: + - Server +--- + +# tls Binding + +Zilla runtime tls binding. + +```yaml {2} +tls_server0: + type: tls + kind: server + vault: server + options: + keys: + - localhost + sni: + - localhost + alpn: + - echo + routes: + - when: + - alpn: echo + exit: echo_server0 +``` + +## Summary + +Defines a binding with `tls` protocol support, with `server`, `client` or `proxy` behavior. + +#### Server behavior + +The `server` kind tls binding decodes encrypted `TLS` protocol protocol on the inbound network stream, producing higher level cleartext application streams for each request. + +Certificates and keys required to complete the `TLS` handshake are provided by a `vault` referenced in the binding configuration. + +Conditional routes based on `tls` hostname authority or negotiated ALPN protocol are used to route these streams to an `exit` binding. + +#### Client behavior + +The `client` kind `tls` binding receives inbound application streams and encodes each as an encrypted network stream via `TLS` protocol. + +Certificates and keys required to complete the `TLS` handshake are provided by a `vault` referenced in the binding configuration. + +Conditional routes based on `tls` hostname authority or negotiated ALPN protocol are used to route these streams to an `exit` binding. + +#### Proxy behavior + +The `proxy` kind `tls` binding detects `ClientHello` `server_name` extension to provide TLS virtual hosting by routing based on server name. + +A `vault` is not required to proxy `TLS` protocol as the handshake is only observed read-only as it routes through the `tls` `proxy` binding. + +## Configuration + +:::: note Properties + +- [kind\*](#kind) +- [vault](#vault) +- [options](#options) +- [options.version](#options-version) +- [options.keys](#options-keys) +- [options.trust](#options-trust) +- [options.signers](#options-signers) +- [options.trustcacerts](#options-trustcacerts) +- [options.sni\*](#options-sni) +- [options.alpn](#options-alpn) +- [options.mutual](#options-mutual) +- [exit](#exit) +- [routes](#routes) +- [routes\[\].guarded](#routes-guarded) +- [routes\[\].when](#routes-when) + - [when\[\].authority](#when-authority) + - [when\[\].alpn](#when-alpn) +- [routes\[\].exit\*](#routes-exit) + +::: right +\* required +::: + +:::: + +### kind\* + +> `enum` [ "client", "server", "proxy" ] + +Behave as a `tls` `client`, `server` or `proxy`. + +### vault + +> `string` + +Vault name. + +### options + +> `object` + +`tls`-specific options. + +```yaml +options: + keys: + - localhost + sni: + - localhost + alpn: + - echo +``` + +### options.version + +> `string` + +Protocol version. + +### options.keys + +> `array` of `string` + +Vault key refs. + +### options.trust + +> `array` of `string` + +Vault certificate refs. + +### options.signers + +> `array` of `string` + +Vault signer certificate refs. + +### options.trustcacerts + +> `boolean` + +Trust CA certificates. + +### options.sni\* + +> `array` of `string` + +Server names. + +### options.alpn + +> `array` of `string` + +Application protocols. + +### options.mutual + +> `enum` [ "required", "requested", "none" ] + +Mutual authentication\ +Defaults to `"none"`. + +### exit + +> `string` + +Default exit binding when no conditional routes are viable. + +```yaml +exit: echo_server0 +``` + +### routes + +> `array` of `object` + +Conditional `tls`-specific routes. + +```yaml +routes: + - when: + - alpn: echo + exit: echo_server0 +``` + +### routes[].guarded + +> `object` as named map of `string:string` `array` + +List of roles required by each named guard to authorize this route. + +```yaml +routes: + - guarded: + test0: + - read:items +``` + +### routes[].when + +> `array` of `object` + +List of conditions (any match) to match this route. + +```yaml +routes: + - when: + - alpn: echo +``` + +#### when[].authority + +> `string` + +Associated authority. + +#### when[].alpn + +> `string` + +Application protocol. + +### routes[].exit\* + +> `string` + +Next binding when following this route. + +```yaml +exit: echo_server0 +``` + +--- + +::: right +\* required +::: diff --git a/src/reference/zilla.yaml/binding-ws.md b/src/reference/zilla.yaml/binding-ws.md new file mode 100644 index 00000000..dee657f0 --- /dev/null +++ b/src/reference/zilla.yaml/binding-ws.md @@ -0,0 +1,195 @@ +--- +shortTitle: binding (ws) +description: Zilla runtime ws binding +category: + - Binding +tag: + - Server +--- + +# ws Binding + +Zilla runtime ws binding. + +```yaml {2} +ws_server0: + type: ws + kind: server + routes: + - when: + - protocol: echo + exit: echo_server0 +``` + +## Summary + +Defines a binding with `WebSockets` protocol support, with `server` or `client` behavior. + +#### Server behavior + +The `server` kind `ws` binding converts inbound `http` request-response streams into `ws` full-duplex streams. + +Conditional routes based on `ws` scheme, authority, path or negotiated subprotocol are used to route these streams to an `exit` binding. + +#### Client behavior + +The `client` kind `ws` binding converts inbound `ws` full duplex streams into `http` request-response streams. + +Conditional routes based on `ws` scheme, authority, path or negotiated subprotocol are used to route these streams to an `exit` binding. + +## Configuration + +:::: note Properties + +- [kind\*](#kind) +- [options](#options) +- [options.defaults](#options-defaults) + - [defaults.protocol](#defaults-protocol) + - [defaults.scheme](#defaults-scheme) + - [defaults.authority](#defaults-authority) + - [defaults.path](#defaults-path) +- [exit](#exit) +- [routes](#routes) +- [routes\[\].guarded](#routes-guarded) +- [routes\[\].when](#routes-when) + - [when\[\].protocol](#when-protocol) + - [when\[\].scheme](#when-scheme) + - [when\[\].authority](#when-authority) + - [when\[\].path](#when-path) +- [routes\[\].exit\*](#routes-exit) + +::: right +\* required +::: + +:::: + +### kind\* + +> `enum` [ "client", "server" ] + +Behave as a `ws` `client` or `server`. + +### options + +> `object` + +`ws`-specific options. + +### options.defaults + +> `object` + +Defaults. + +#### defaults.protocol + +> `string` + +Subprotocol. + +#### defaults.scheme + +> `string` + +Scheme. + +#### defaults.authority + +> `string` + +Authority. + +#### defaults.path + +> `string` + +Path. + +### exit + +> `string` + +Default exit binding when no conditional routes are viable. + +```yaml +exit: echo_server0 +``` + +### routes + +> `array` of `object` + +Conditional `ws`-specific routes. + +```yaml +routes: + - when: + - protocol: echo + exit: echo_server0 +``` + +### routes[].guarded + +> `object` as named map of `string:string` `array` + +List of roles required by each named guard to authorize this route. + +```yaml +routes: + - guarded: + test0: + - read:items +``` + +### routes[].when + +> `array` of `object` + +List of conditions (any match) to match this route. + +```yaml +routes: + - when: + - protocol: echo +``` + +#### when[].protocol + +> `string` + +Subprotocol pattern. + +#### when[].scheme + +> `string` + +Scheme pattern. + +#### when[].authority + +> `string` + +Authority pattern. + +#### when[].path + +> `string` + +Path pattern. + +### routes[].exit\* + +> `string` + +Next binding when following this route. + +```yaml +exit: echo_server0 +``` + +--- + +::: right +\* required +::: diff --git a/src/reference/zilla.yaml/binding.md b/src/reference/zilla.yaml/binding.md new file mode 100644 index 00000000..d293e782 --- /dev/null +++ b/src/reference/zilla.yaml/binding.md @@ -0,0 +1,80 @@ +--- +shortTitle: binding +description: Zilla runtime bindings +category: + - Binding +tag: + - Client + - Proxy + - Server +--- + +# Binding + +Each configured `binding` represents a step in the pipeline as data streams are decoded, translated or encoded according to a specific protocol `type`. + +A `binding` also has a `kind`, indicating how it should behave, such as `server`, `proxy` or `client`. + +As each incoming data stream arrives, the binding follows its configured `routes` to reach an `exit` binding, or rejects the stream if no routes are viable. Route matching conditions are defined in terms specific to each `binding` type. + +See each of the specific `binding` types linked below for more detailed examples. + +## Configuration + +Each runtime `binding` has a behavioral type supporting either encoding and decoding for a specific protocol or translation between protocols. + +### Properties (generic) + +### type + +> `enum` \[\ +> ["amqp"](binding-amqp.md),\ +> ["echo"](binding-echo.md),\ +> ["fan"](binding-fan.md),\ +> ["filesystem"](binding-filesystem.md),\ +> ["http"](binding-http.md),\ +> ["http-filesystem"](binding-http-filesystem.md),\ +> ["http-kafka"](binding-http-kafka.md),\ +> ["kafka"](binding-kafka.md),\ +> ["mqtt"](binding-mqtt.md),\ +> ["proxy"](binding-proxy.md),\ +> ["sse"](binding-sse.md),\ +> ["sse-kafka"](binding-sse-kafka.md),\ +> ["tcp"](binding-tcp.md),\ +> ["tls"](binding-tls.md),\ +> ["ws"](binding-ws.md)\ +> \] + +Behavioral type supporting either encoding and decoding for a specific protocol or translation between protocols. + +### Properties (type-specific) + +### kind + +> `string` + +Behavioral kind such as `server`, `client` or `proxy`. + +### options + +> `object` + +Type-specific options to configure the binding. + +### routes + +> `array` of `object` + +Type-specific conditional routing rules to reach an `exit` binding. + +### routes[].exit + +> `string` + +Unconditional `exit` binding acting as a default if none of the conditional routes are viable. + +--- + +::: right +\* required +::: diff --git a/src/reference/zilla.yaml/guard-jwt.md b/src/reference/zilla.yaml/guard-jwt.md new file mode 100644 index 00000000..a2e37489 --- /dev/null +++ b/src/reference/zilla.yaml/guard-jwt.md @@ -0,0 +1,166 @@ +--- +shortTitle: guard (jwt) +description: Zilla runtime jwt guard +category: + - Binding +tag: + - Server +--- + +# jwt Guard + +Zilla runtime jwt guard. + +```yaml {2} +jwt0: + type: jwt + options: + issuer: https://auth.example.com + audience: https://api.example.com + keys: + - kty: EC + crv: P-256 + x: MKBCTNIcKUSDii11ySs3526iDZ8AiTo7Tu6KPAqv7D4 + y: 4Etl6SRW2YiLUrN5vfvVHuhp7x8PxltmWWlbbM4IFyM + use: enc + kid: '1' + - kty: RSA + n: 0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFbWhM78LhWx4cbbfAAtVT86zwu1RK7aPFFxuhDR1L6tSoc_BJECPebWKRXjBZCiFV4n3oknjhMstn64tZ_2W-5JsGY4Hc5n9yBXArwl93lqt7_RN5w6Cf0h4QyQ5v-65YGjQR0_FDW2QvzqY368QQMicAtaSqzs8KJZgnYb9c7d0zgdAZHzu6qMQvRL5hajrn1n91CbOpbISD08qNLyrdkt-bFTWhAI4vMQFh6WeZu0fM4lFd2NcRwr3XPksINHaQ-G_xBniIqbw0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw + e: AQAB + alg: RS256 + kid: '2011-04-29' + challenge: 30 +``` + +## Summary + +Defines a guard with `JSON Web Token (JWT)` support. + +The `jwt` guard uses public keys to verify the integrity of `JWT` access tokens when identifying authorized subjects and their associated roles scope. The token issuer and audience can also be constrained to prevent access tokens from other applications from being reused inappropriately. + +Each verified JWT access token has an expiration time, and an optional challenge window prior to the expiration time that can be used by specific protocol bindings to send a challenge to renew the access token before it expires. + +## Configuration + +:::: note Properties + +- [options](#options) +- [options.issuer](#options-issuer) +- [options.audience](#options-audience) +- [options.keys\*](#options-keys) +- [keys\[\].kty\*](#keys-kty) +- [keys\[\].kid\*](#keys-kid) +- [keys\[\].n](#keys-n) +- [keys\[\].e](#keys-e) +- [keys\[\].alg](#keys-alg) +- [keys\[\].crv](#keys-crv) +- [keys\[\].x](#keys-x) +- [keys\[\].y](#keys-y) +- [options.challenge](#options-challenge) + +::: right +\* required +::: + +:::: + +### options + +> `object` + +`jwt`-specific options. + +```yaml +options: + issuer: https://auth.example.com + audience: https://api.example.com + keys: + - kty: EC + crv: P-256 + x: MKBCTNIcKUSDii11ySs3526iDZ8AiTo7Tu6KPAqv7D4 + y: 4Etl6SRW2YiLUrN5vfvVHuhp7x8PxltmWWlbbM4IFyM + use: enc + kid: '1' + - kty: RSA + n: 0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFbWhM78LhWx4cbbfAAtVT86zwu1RK7aPFFxuhDR1L6tSoc_BJECPebWKRXjBZCiFV4n3oknjhMstn64tZ_2W-5JsGY4Hc5n9yBXArwl93lqt7_RN5w6Cf0h4QyQ5v-65YGjQR0_FDW2QvzqY368QQMicAtaSqzs8KJZgnYb9c7d0zgdAZHzu6qMQvRL5hajrn1n91CbOpbISD08qNLyrdkt-bFTWhAI4vMQFh6WeZu0fM4lFd2NcRwr3XPksINHaQ-G_xBniIqbw0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw + e: AQAB + alg: RS256 + kid: '2011-04-29' + challenge: 30 +``` + +### options.issuer + +> `string` + +Issuer claim. + +### options.audience + +> `string` + +Audience claim. + +### options.keys\* + +> `array` of `object` + +### keys[].kty\* + +> `string` + +Key type, e.g. `RSA` , `EC`. + +### keys[].kid\* + +> `string` + +Key ID. + +### keys[].n + +> `string` + +`RSA` `modulus`. + +### keys[].e + +> `string` + +`RSA` `exponent`. + +### keys[].alg + +> `string` + +`RSA` algorithm, e.g. `RS256`. + +### keys[].crv + +> `string` + +`EC` curve name. + +### keys[].x + +> `string` + +`EC` point `x` coordinate. + +### keys[].y + +> `string` + +`EC` point `y` coordinate. + +### options.challenge + +> `number` + +Challenge period (seconds). + +--- + +::: right +\* required +::: diff --git a/reference/zilla.yaml/guard.md b/src/reference/zilla.yaml/guard.md similarity index 53% rename from reference/zilla.yaml/guard.md rename to src/reference/zilla.yaml/guard.md index fb93178b..2baee28c 100644 --- a/reference/zilla.yaml/guard.md +++ b/src/reference/zilla.yaml/guard.md @@ -1,8 +1,11 @@ --- +shortTitle: guard description: Zilla runtime guard type +category: + - Guard --- -# guard +# Guard Each configured `guard` represents a security checkpoint for one or more bindings based on a specific implementation `type`. @@ -12,18 +15,30 @@ Associated roles can be enforced during routing by only following routes `guarde See each of the specific `guard` types linked below for more detailed examples. -### Configuration +## Configuration Each runtime `guard` has a behavioral type supporting a specific implementation strategy. -#### Properties (generic) +### Properties (generic) -| Name | Type | Description | -| ------ | ----------------------------------------------------------------------------------------------- | --------------- | -| `type` |
| Behavioral type | +### type -#### Properties (type-specific) +> `enum` \[\ +> ["jwt"](guard-jwt.md)\ +> \] -| Name | Type | Description | -| --------- | -------- | ------------------ | -| `options` | `object` | Behavioral options | +Behavioral type. + +### Properties (type-specific) + +### options + +> `object` + +Behavioral options. + +--- + +::: right +\* required +::: diff --git a/src/reference/zilla.yaml/vault-filesystem.md b/src/reference/zilla.yaml/vault-filesystem.md new file mode 100644 index 00000000..7cc7659d --- /dev/null +++ b/src/reference/zilla.yaml/vault-filesystem.md @@ -0,0 +1,153 @@ +--- +shortTitle: vault (filesystem) +description: Zilla runtime filesystem vault +category: + - Vault +--- + +# filesystem Vault + +Zilla runtime filesystem vault. + +```yaml {2} +server: + type: filesystem + options: + keys: + store: localhost.p12 + type: pkcs12 + password: "{{env.KEYS_PASSWORD}}" +``` + +## Summary + +Defines a vault stored on the local filesystem. + +The `filesystem` vault uses `PKCS12` format to store signed certificates and keys. + +The [keys](#options-keys) option is used to identify the local peer in a `TLS` handshake. + +The [trust](#options-trust) option is used to verify identity of the remote peer in a `TLS` handshake. + +The [signers](#options-signers) option is used to challenge for mutual authentication in a `TLS` handshake. + +Note that use of `{{env.*}}` syntax to read an environment variable currently requires setting `zilla.engine.config.syntax.mustache=true` in `.zilla/zilla.properties`. + +## Configuration + +:::: note Properties + +- [options](#options) +- [options.keys](#options-keys) + - [keys.store\*](#keys-store) + - [keys.type](#keys-type) + - [keys.password](#keys-password) +- [options.trust](#options-trust) + - [trust.store\*](#trust-store) + - [trust.type](#trust-type) + - [trust.password](#trust-password) +- [options.signers](#options-signers) + - [signers.store\*](#signers-store) + - [signers.type](#signers-type) + - [signers.password](#signers-password) + +::: right +\* required +::: + +:::: + +### options + +> `object` + +`filesystem`-specific options. + +```yaml +options: + keys: + store: localhost.p12 + type: pkcs12 + password: "{{env.KEYS_PASSWORD}}" +``` + +### options.keys + +> `object` + +Private keys. + +#### keys.store\* + +> `string` + +Relative path to keystore. + +#### keys.type + +> `string` + +Keystore type,\ +defaults to `"pkcs12"` + +#### keys.password + +> `string` + +Keystore password. + +### options.trust + +> `object` + +Trust certificates. + +#### trust.store\* + +> `string` + +Relative path to keystore. + +#### trust.type + +> `string` + +Keystore type,\ +defaults to `"pkcs12"` + +#### trust.password + +> `string` + +Keystore password. + +### options.signers + +> `object` + +Signer certificates. + +#### signers.store\* + +> `string` + +Relative path to keystore. + +#### signers.type + +> `string` + +Keystore type,\ +defaults to `"pkcs12"` + +#### signers.password + +> `string` + +Keystore password. + +--- + +::: right +\* required +::: diff --git a/src/reference/zilla.yaml/vault.md b/src/reference/zilla.yaml/vault.md new file mode 100644 index 00000000..6fdbbdd5 --- /dev/null +++ b/src/reference/zilla.yaml/vault.md @@ -0,0 +1,42 @@ +--- +shortTitle: vault +description: Zilla runtime vault type +category: + - Vault +--- + +# Vault + +Each configured `vault` represents a container for digital keys and certificates based on a specific implementation `type`. + +Vaults can be used by specific protocol bindings, such as `tls`, to negotiate shared encryption keys. + +See each of the specific `vault` types linked below for more detailed examples. + +## Configuration + +Each runtime `vault` has a behavioral type supporting a specific implementation strategy. + +### Properties (generic) + +### type + +> `enum` \[\ +> ["filesystem"](vault-filesystem.md)\ +> \] + +Behavioral type. + +### Properties (type-specific) + +### options + +> `object` + +Behavioral options. + +--- + +::: right +\* required +::: diff --git a/reference/zilla/README.md b/src/reference/zilla/README.md similarity index 80% rename from reference/zilla/README.md rename to src/reference/zilla/README.md index af964255..72cf9ffe 100644 --- a/reference/zilla/README.md +++ b/src/reference/zilla/README.md @@ -1,12 +1,17 @@ --- +title: Zilla Runtime CLI +icon: "terminal" +order: 2 +category: + - CLI description: The command line interface to control the Zilla runtime. --- # Zilla Runtime CLI (zilla) -The Zilla Runtime command line interface uses the [Zilla Runtime Configuration](../zilla.yaml/) to control and observe the Zilla runtime. +The Zilla Runtime command line interface uses the [Zilla Runtime Configuration](../zilla.yaml/README.md) to control and observe the Zilla runtime. -### Commands +## Commands The Zilla Runtime command line interface supports the following commands. diff --git a/reference/zilla/clean.md b/src/reference/zilla/clean.md similarity index 79% rename from reference/zilla/clean.md rename to src/reference/zilla/clean.md index 69398d24..95154c98 100644 --- a/reference/zilla/clean.md +++ b/src/reference/zilla/clean.md @@ -10,12 +10,12 @@ The `zilla help` command shows help information about available commands, or mor ### Usage -``` +```bash:no-line-numbers zilla help [command] ``` ### Examples -``` +```bash:no-line-numbers ./zilla help start -``` +```bash:no-line-numbers diff --git a/reference/zilla/load.md b/src/reference/zilla/load.md similarity index 84% rename from reference/zilla/load.md rename to src/reference/zilla/load.md index 14454822..6474370d 100644 --- a/reference/zilla/load.md +++ b/src/reference/zilla/load.md @@ -8,7 +8,7 @@ The `zilla load` command provides metrics for each binding in the configuration. ### Usage -```bash +```bash:no-line-numbers zilla load [NAME] ``` @@ -20,10 +20,10 @@ zilla load [NAME] ### Examples -```bash +```bash:no-line-numbers ./zilla load echo0 binding rx.opens rx.closes rx.errors rx.bytes tx.opens tx.closes tx.errors tx.bytes example.echo0 1 1 0 13 1 1 0 13 ``` -See [Zilla examples](https://github.com/aklivity/zilla/tree/develop/examples) on GitHub. +See [Zilla examples](https://github.com/aklivity/zilla-examples) on GitHub. diff --git a/reference/zilla/start.md b/src/reference/zilla/start.md similarity index 81% rename from reference/zilla/start.md rename to src/reference/zilla/start.md index 19b2f51a..f365b4aa 100644 --- a/reference/zilla/start.md +++ b/src/reference/zilla/start.md @@ -8,7 +8,7 @@ The `zilla start` command resolves the [Zilla Runtime Configuration](../zilla.ya ### Usage -```bash +```bash:no-line-numbers zilla start ``` @@ -17,11 +17,11 @@ zilla start | | | | ------------ | -------------------------------------------------------- | | `--verbose` | Show verbose output | -| `--workers` |

Worker count
Defaults to # CPU cores available

| +| `--workers` | Worker count
Defaults to # CPU cores available | ### Examples -```bash +```bash:no-line-numbers ./zilla start --verbose { "name": "example", @@ -48,4 +48,4 @@ zilla start started ``` -See [Zilla examples](https://github.com/aklivity/zilla/tree/develop/examples) on GitHub. +See [Zilla examples](https://github.com/aklivity/zilla-examples) on GitHub. diff --git a/reference/zilla/stop.md b/src/reference/zilla/stop.md similarity index 56% rename from reference/zilla/stop.md rename to src/reference/zilla/stop.md index 7f6eb654..b2762d21 100644 --- a/reference/zilla/stop.md +++ b/src/reference/zilla/stop.md @@ -8,25 +8,25 @@ The `zilla stop` command signals the runtime engine to stop. ### Usage -```bash +```bash:no-line-numbers zilla stop ``` ### Examples -```bash +```bash:no-line-numbers ./zilla start started ... ``` -```bash +```bash:no-line-numbers ./zilla stop ``` -```bash +```bash:no-line-numbers ... stopped ``` -See [Zilla examples](https://github.com/aklivity/zilla/tree/develop/examples) on GitHub. +See [Zilla examples](https://github.com/aklivity/zilla-examples) on GitHub. diff --git a/reference/zilla/tune.md b/src/reference/zilla/tune.md similarity index 67% rename from reference/zilla/tune.md rename to src/reference/zilla/tune.md index 440fb140..f4319704 100644 --- a/reference/zilla/tune.md +++ b/src/reference/zilla/tune.md @@ -8,32 +8,32 @@ The `zilla tune` command tunes the mapping from runtime engine workers to bindin ### Usage -```bash +```bash:no-line-numbers zilla tune [NAME=VALUE] ``` ### Examples -```bash +```bash:no-line-numbers ./zilla start --workers 4 started ``` -```bash +```bash:no-line-numbers ./zilla tune xxxx example.tcp0 xxxx example.echo0 ``` -```bash +```bash:no-line-numbers ./zilla tune example.echo0=2 ..x. example.echo0 ``` -```bash +```bash:no-line-numbers ./zilla tune xxxx example.tcp0 .x.. example.echo0 ``` -See [Zilla examples](https://github.com/aklivity/zilla/tree/develop/examples) on GitHub. +See [Zilla examples](https://github.com/aklivity/zilla-examples) on GitHub. diff --git a/reference/zpm.json.md b/src/reference/zpm.json.md similarity index 62% rename from reference/zpm.json.md rename to src/reference/zpm.json.md index 4a3c0751..baa4caec 100644 --- a/reference/zpm.json.md +++ b/src/reference/zpm.json.md @@ -10,9 +10,9 @@ description: Configures dependencies to be resolved when packaging the Zilla run | Name | Type | Description | | -------------- | -------------------------------------------------- | -------------------------------------------------------- | -| `repositories` | `array` of [`repository`](zpm.json.md#respository) | List of repository URLs | -| `imports` | `array` of [`import`](zpm.json.md#import) | List of Maven BOMs to import managed dependency versions | -| `dependencies` | `array` of [`dependency`](zpm.json.md#dependency) | List of Maven dependencies | +| `repositories` | `array` of [`repository`](#repository) | List of repository URLs | +| `imports` | `array` of [`import`](#import) | List of Maven BOMs to import managed dependency versions | +| `dependencies` | `array` of [`dependency`](#dependency) | List of Maven dependencies | ### repository diff --git a/reference/zpm/README.md b/src/reference/zpm/README.md similarity index 92% rename from reference/zpm/README.md rename to src/reference/zpm/README.md index 2566cc84..ed1c766c 100644 --- a/reference/zpm/README.md +++ b/src/reference/zpm/README.md @@ -1,4 +1,9 @@ --- +title: Zilla Manager CLI +icon: "server" +order: 3 +category: + - CLI description: >- The command line interface to manage Zilla dependencies and package the Zilla runtime. @@ -19,4 +24,3 @@ The Zilla Manager command line interface supports the following commands: | [`zpm encrypt`](encrypt.md) | Encrypt passwords | | [`zpm install`](install.md) | Install dependencies | | [`zpm wrap`](wrap.md) | Generate wrapper | - diff --git a/reference/zpm/clean-1.md b/src/reference/zpm/clean-1.md similarity index 76% rename from reference/zpm/clean-1.md rename to src/reference/zpm/clean-1.md index 19d7ae10..eac730b2 100644 --- a/reference/zpm/clean-1.md +++ b/src/reference/zpm/clean-1.md @@ -8,11 +8,11 @@ description: Cleans up the generated runtime files The `zpm clean` command removes files from its `.zpm/` output directory. -Optionally, only the files necessary to execute the [Zilla Runtime](../zilla/) are kept intact, leaving a minimal installation footprint for deployment. +Optionally, only the files necessary to execute the [Zilla Runtime](../zilla/) are kept intact, leaving a minimal installation footprint for deployment. ### Usage -```bash +```bash:no-line-numbers zpm clean ``` @@ -20,10 +20,10 @@ zpm clean | | | | -------------- | --------------------------------------------------------------------------------- | -| `--keep-image` |

Clean up everything except runtime image
Defaults to false

| +| `--keep-image` | Clean up everything except runtime image
Defaults to `false` | ### Examples -```bash +```bash:no-line-numbers ./zpmw clean --keep-image -``` +```bash:no-line-numbers diff --git a/reference/zpm/clean.md b/src/reference/zpm/clean.md similarity index 79% rename from reference/zpm/clean.md rename to src/reference/zpm/clean.md index 5cf8a8d9..ef0461c1 100644 --- a/reference/zpm/clean.md +++ b/src/reference/zpm/clean.md @@ -10,12 +10,12 @@ The `zpm help` command shows help information about available commands, or more ### Usage -``` +```bash:no-line-numbers zpm help [command] ``` ### Examples -``` +```bash:no-line-numbers ./zpmw help install -``` +```bash:no-line-numbers diff --git a/reference/zpm/encrypt.md b/src/reference/zpm/encrypt.md similarity index 93% rename from reference/zpm/encrypt.md rename to src/reference/zpm/encrypt.md index 0c01513b..5a0d5f34 100644 --- a/reference/zpm/encrypt.md +++ b/src/reference/zpm/encrypt.md @@ -14,13 +14,13 @@ If a master secret does not already exist, it is generated in [Zilla Manager Sec ### Usage -```bash +```bash:no-line-numbers zpm encrypt ``` ### Examples -```bash +```bash:no-line-numbers ./zpmw encrypt ``` diff --git a/reference/zpm/install.md b/src/reference/zpm/install.md similarity index 78% rename from reference/zpm/install.md rename to src/reference/zpm/install.md index 273cc65f..c179d18b 100644 --- a/reference/zpm/install.md +++ b/src/reference/zpm/install.md @@ -10,7 +10,7 @@ The `zpm install` command resolves the [Zilla Manager Configuration](../zpm.json ### Usage -```bash +```bash:no-line-numbers zpm install ``` @@ -18,14 +18,14 @@ zpm install | | | | ------------------------------- | -------------------------------------------------------------------------------- | -| `--debug` |

Link jdk.jdwp.agent module
Defaults to false

| +| `--debug` | Link `jdk.jdwp.agent` module
Defaults to `false` | | `--exclude-local-repository` | Exclude the local Maven repository when resolving dependencies | | `--exclude-remote-repositories` | Exclude remote Maven repositories when resolving dependencies | ### Examples -```bash +```bash:no-line-numbers ./zpmw install ``` -See [Zilla examples](https://github.com/aklivity/zilla/tree/develop/examples) on GitHub. +See [Zilla examples](https://github.com/aklivity/zilla-examples) on GitHub. diff --git a/reference/zpm/wrap.md b/src/reference/zpm/wrap.md similarity index 78% rename from reference/zpm/wrap.md rename to src/reference/zpm/wrap.md index ccaf327f..4a1e4a25 100644 --- a/reference/zpm/wrap.md +++ b/src/reference/zpm/wrap.md @@ -12,7 +12,7 @@ This approach avoids the need to manually install `zpm` and allows greater contr ### Usage -```bash +```bash:no-line-numbers zpm wrap ``` @@ -20,13 +20,13 @@ zpm wrap | | | | ----------------------------------- | ------------------------------------------------------------------------------------------------- | -| `--local-repository ` |

Local Maven repository directory
Defaults to ${user.home}/.m2/repository

| -| `--remote-repository ` |

Remote Maven repository URL
Defaults to https://maven.packages.aklivity.io

| +| `--local-repository ` | Local Maven repository directory
Defaults to `${user.home}/.m2/repository` | +| `--remote-repository ` | Remote Maven repository URL
Defaults to `https://maven.packages.aklivity.io` | | `--version ` | Require `zpm` wrapper to use \ | ### Examples -```bash +```bash:no-line-numbers ./zpmw wrap --version 0.9.8 ``` From 5406671a775bc78841a1bbfb7041260568f2baa3 Mon Sep 17 00:00:00 2001 From: AJ Danelz Date: Sun, 23 Apr 2023 12:16:46 -0400 Subject: [PATCH 2/3] update redirects (#26) --- src/.vuepress/public/cloudflare/_redirects | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/.vuepress/public/cloudflare/_redirects b/src/.vuepress/public/cloudflare/_redirects index 4974209f..745ba348 100644 --- a/src/.vuepress/public/cloudflare/_redirects +++ b/src/.vuepress/public/cloudflare/_redirects @@ -1,2 +1,5 @@ -/ /zilla/next 302 -/zilla /zilla/next 302 \ No newline at end of file +/zilla/next/library /zilla/next 302 +/zilla/next/get-started/build-todo-app /zilla/next/examples/todo-app/build 302 +/zilla/next/get-started/secure-todo-app /zilla/next/examples/todo-app/secure 302 +/zilla/next/configure-kafka-proxies/* /zilla/next/guides/kafka-proxies/:splat +/zilla/next/connect-your-kafka/* /zilla/next/get-started/connecting-to-kafka/:splat From d41f44ae0a1f99d487261a0bfb9cd98b55c47251 Mon Sep 17 00:00:00 2001 From: AJ Danelz Date: Mon, 24 Apr 2023 19:01:22 -0400 Subject: [PATCH 3/3] Addressing feedback (#27) fixing all of the links --- .github/workflows/build-deploy-docs.yml | 13 +- .github/workflows/links-build.yml | 2 +- .github/workflows/links-push.yml | 4 +- src/.vuepress/config.ts | 2 +- src/.vuepress/env.ts | 2 +- src/.vuepress/navbar/en.ts | 2 +- src/.vuepress/sidebar/en.ts | 86 +++- src/.vuepress/theme.ts | 6 +- src/README.md | 21 +- src/examples/README.md | 11 - src/examples/todo-app/build.md | 11 +- src/examples/todo-app/secure.md | 8 +- src/get-started/README.md | 11 - src/get-started/connecting-to-kafka/README.md | 464 +++++++----------- src/get-started/connecting-to-kafka/aiven.md | 119 ++--- .../connecting-to-kafka/amazon-msk.md | 108 ++-- .../connecting-to-kafka/confluent-cloud.md | 93 ++-- .../connecting-to-kafka/redpanda-zilla.yaml | 86 ---- .../connecting-to-kafka/redpanda.md | 37 +- .../connecting-to-kafka/zilla.yaml | 86 ---- src/guides/README.md | 5 - src/guides/kafka-proxies/rest-proxy.md | 366 ++++++-------- src/guides/kafka-proxies/sse-proxy.md | 63 +-- src/reference/zilla.yaml/README.md | 1 - src/reference/zilla/README.md | 3 +- src/reference/zpm/README.md | 1 - 26 files changed, 640 insertions(+), 971 deletions(-) delete mode 100644 src/examples/README.md delete mode 100644 src/get-started/README.md delete mode 100644 src/get-started/connecting-to-kafka/redpanda-zilla.yaml delete mode 100644 src/get-started/connecting-to-kafka/zilla.yaml delete mode 100644 src/guides/README.md diff --git a/.github/workflows/build-deploy-docs.yml b/.github/workflows/build-deploy-docs.yml index 7c76954d..a5708e2f 100644 --- a/.github/workflows/build-deploy-docs.yml +++ b/.github/workflows/build-deploy-docs.yml @@ -112,7 +112,7 @@ jobs: if: github.repository_owner != 'aklivity' uses: actions/upload-pages-artifact@v1 with: - path: ${{ env.DistDir }} + path: ${{ env.DistDir }}/zilla-docs deployCloudflarePages: if: github.repository_owner == 'aklivity' @@ -134,14 +134,7 @@ jobs: path: ${{ env.DistDir }} - name: Move cloudflare files to root - run: mv ${{ env.DistDir }}/next/cloudflare/* ${{ env.DistDir }} - - - name: Update folder structure - if: env.SITE_BASE != '' - run: | - mkdir -p ${{ env.SITE_BASE }} - mv -v ${{ env.DistDir }}/*/ ${{ env.SITE_BASE }} - mv ${{ env.SITE_BASE }} ${{ env.DistDir }}/ + run: mv ${{ env.DistDir }}/${{ env.SITE_BASE }}/next/cloudflare/* ${{ env.DistDir }} - name: Publish to Cloudflare Pages id: cloudflare-deployment @@ -169,4 +162,4 @@ jobs: steps: - name: Deploy to GitHub Pages id: github-deployment - uses: actions/deploy-pages@v1 + uses: actions/deploy-pages@v2 diff --git a/.github/workflows/links-build.yml b/.github/workflows/links-build.yml index da9ffc6d..b7dd47e3 100644 --- a/.github/workflows/links-build.yml +++ b/.github/workflows/links-build.yml @@ -36,6 +36,6 @@ jobs: uses: lycheeverse/lychee-action@v1.6.1 with: fail: true - args: -E --exclude "github.com/aklivity/zilla-docs" --exclude "docs.aklivity.io" --exclude-mail src/.vuepress/dist + args: --exclude="github.com" --exclude="docs.aklivity.io" --exclude-mail --base="src/.vuepress/dist" src/.vuepress/dist env: GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} diff --git a/.github/workflows/links-push.yml b/.github/workflows/links-push.yml index 87ce3fe2..fb0bc1ad 100644 --- a/.github/workflows/links-push.yml +++ b/.github/workflows/links-push.yml @@ -13,6 +13,6 @@ jobs: uses: lycheeverse/lychee-action@v1.6.1 with: fail: true - args: --offline src + args: --exclude-mail src env: - GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} \ No newline at end of file + GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} diff --git a/src/.vuepress/config.ts b/src/.vuepress/config.ts index 882f2e6e..4cce171a 100644 --- a/src/.vuepress/config.ts +++ b/src/.vuepress/config.ts @@ -1,5 +1,5 @@ import { defineUserConfig } from "vuepress"; -import { googleAnalyticsPlugin } from '@vuepress/plugin-google-analytics' +import { googleAnalyticsPlugin } from '@vuepress/plugin-google-analytics'; import theme from "./theme.js"; import { base, dest } from "./env.js"; diff --git a/src/.vuepress/env.ts b/src/.vuepress/env.ts index b14b72d7..c7622ec7 100644 --- a/src/.vuepress/env.ts +++ b/src/.vuepress/env.ts @@ -4,7 +4,7 @@ export const dist = process.env.DIST_DIR || "src/.vuepress/dist"; export const hostnameSEO = process.env.SITE_URL || `https://docs.aklivity.io`; export const versionKey = process.env.SITE_VERSION_KEY || "next"; export const base = `${siteBase}/${versionKey}`; -export const dest = `${dist}/${versionKey}`; +export const dest = `${dist}/${base}`; export const docsRepo = process.env.GITHUB_REPOSITORY || "aklivity/zilla-docs"; var repoTree; diff --git a/src/.vuepress/navbar/en.ts b/src/.vuepress/navbar/en.ts index 1e471827..3b897fe8 100644 --- a/src/.vuepress/navbar/en.ts +++ b/src/.vuepress/navbar/en.ts @@ -17,9 +17,9 @@ export const enNavbar = navbar([ "zpm/", ], }, - { text: "Blog", icon: "blog", link: "https://www.aklivity.io/blog", }, // todo: remove and uncomment the below once there is multiple versions of the blogs to host // and add necessary items ({ "text": "v0.1", "key": "v0.1", "tag": "v0.1" }) to deploy-versions.json { "text": "Changelog", icon: "tag", "link": "https://github.com/orgs/aklivity/projects/4", }, // { text: "version", icon: "list-ol", children: versionLinks }, + { text: "Aklivity", icon: "home", link: "https://www.aklivity.io/", }, ]); diff --git a/src/.vuepress/sidebar/en.ts b/src/.vuepress/sidebar/en.ts index 19aae153..657af437 100644 --- a/src/.vuepress/sidebar/en.ts +++ b/src/.vuepress/sidebar/en.ts @@ -1,11 +1,89 @@ import { sidebar } from "vuepress-theme-hope"; export const enSidebar = sidebar({ - "/get-started/": "structure", - "/guides/": "structure", - "/examples/": "structure", - "/reference/": "structure", + "/reference/": [ + "", + { + text: "Zilla Manager CLI (zpm)", + collapsible: true, + prefix: "zpm/", + link: "zpm/", + children: "structure", + }, + { text: "Zilla Manager Configuration", link: "/reference/zpm.json.md" }, + { text: "Zilla Manager Settings", link: "/reference/settings.json.md" }, + { text: "Zilla Manager Security", link: "/reference/security.json.md" }, + { + text: "Zilla Runtime CLI (zilla)", + collapsible: true, + prefix: "zilla/", + link: "zilla/", + children: "structure", + }, + { + text: "Zilla Runtime Configuration", + collapsible: true, + prefix: "zilla.yaml/", + link: "zilla.yaml/", + children: "structure", + }, + ], "/": [ "", + { + text: "Get Started", + prefix: "get-started/", + link: "get-started/", + children: [ + { + text: "Install", + collapsible: false, + prefix: "install/", + link: "install/", + }, + { + text: "Connecting to Kafka", + collapsible: false, + prefix: "connecting-to-kafka/", + link: "connecting-to-kafka/", + children: [ + "aiven.md", + "amazon-msk.md", + "confluent-cloud.md", + "redpanda.md", + ], + }, + ], + }, + { + text: "Guides", + prefix: "guides/", + children: [ + { + text: "Kafka Proxies", + collapsible: false, + prefix: "kafka-proxies/", + children: "structure", + }, + ], + }, + { + text: "Examples", + prefix: "examples/", + children: [ + { + text: "Todo App", + collapsible: false, + prefix: "todo-app/", + children: "structure", + }, + ], + }, + { + text: "Reference", + prefix: "reference/", + link: "reference/", + children: ["zilla.yaml/", "zilla/", "zpm/"], + }, ], }); diff --git a/src/.vuepress/theme.ts b/src/.vuepress/theme.ts index 5336503b..a0765b41 100644 --- a/src/.vuepress/theme.ts +++ b/src/.vuepress/theme.ts @@ -28,8 +28,6 @@ export default hopeTheme({ navbar: enNavbar, sidebar: enSidebar, - footer: "Default footer", - displayFooter: false, metaLocales: { @@ -39,7 +37,9 @@ export default hopeTheme({ }, plugins: { - + autoCatalog: { + level: 1 + }, // all features are enabled for demo, only preserve features you need here mdEnhance: { align: true, diff --git a/src/README.md b/src/README.md index ec0dbaf3..55e13dd1 100644 --- a/src/README.md +++ b/src/README.md @@ -8,12 +8,12 @@ heroText: APIs for Data-in-Motion tagline: Open source software connecting web and mobile applications to event-driven microservices using standard protocols, such as HTTP, Server-Sent Events and Kafka. actions: - text: " Zilla in Action" - link: examples/todo-app/build.md + link: /examples/todo-app/build.html type: primary icon: code - text: " Install" - link: get-started/install + link: /get-started/install/index.html icon: download features: @@ -21,45 +21,44 @@ features: - title: Bindings icon: arrows-left-right-to-line details: Each configured binding represents a step in the pipeline as data streams are decoded, translated or encoded according to a specific protocol type. - link: reference/zilla.yaml/binding.md + link: /reference/zilla.yaml/binding.html - title: Vaults icon: vault details: Each configured vault represents a container for digital keys and certificates based on a specific implementation type. - link: reference/zilla.yaml/vault.md + link: /reference/zilla.yaml/vault.html - title: Guards icon: shield-halved details: Each configured guard represents a security checkpoint for one or more bindings based on a specific implementation type. - link: reference/zilla.yaml/guard.md + link: /reference/zilla.yaml/guard.html - title: Proxies icon: diagram-project details: Design and configure your API Endpoints such as REST API, SSE and more. - link: guides/kafka-proxies/rest-proxy.md + link: /guides/kafka-proxies/index.html - title: Amazon MSK icon: database details: Learn how to deploy a more secure Amazon MSK with Aklivity Public MSK Proxy. - link: get-started/connecting-to-kafka/amazon-msk.md + link: /get-started/connecting-to-kafka/amazon-msk.html - title: Avian icon: server details: Connect to Aiven Kafka from Zilla. - link: get-started/connecting-to-kafka/aiven.md + link: /get-started/connecting-to-kafka/aiven.html - title: Confluent Cloud icon: cloud details: Connect to Confluent Cloud from Zilla. - link: get-started/connecting-to-kafka/confluent-cloud.md + link: /get-started/connecting-to-kafka/confluent-cloud.html - title: RedPanda icon: bars-staggered details: Connect to Redpanda from Zilla. - link: get-started/connecting-to-kafka/redpanda.md + link: /get-started/connecting-to-kafka/redpanda.html copyright: false -footer: Theme by VuePress Theme Hope | MIT Licensed, Copyright © Aklivity, Inc. 2023 --- diff --git a/src/examples/README.md b/src/examples/README.md deleted file mode 100644 index cd0d1a74..00000000 --- a/src/examples/README.md +++ /dev/null @@ -1,11 +0,0 @@ -# Examples - -The examples below will walk you through the steps to build and secure a Todo application using Apache Kafka with the Zilla engine. - -## [Build the Todo Application](todo-app/build.md) - -Our Build the Todo Application guide shows you how to create your first application with Zilla, using Apache Kafka with Kafka Streams to implement the Tasks service that maintains a shared Todo List of tasks. - -## [Secure the Todo Application](todo-app/secure.md) - -Our Secure the Todo Application guide shows you how to secure the Tasks API using JWT access tokens to allow read and write access only to authorized clients. diff --git a/src/examples/todo-app/build.md b/src/examples/todo-app/build.md index 8e48674e..25d47054 100644 --- a/src/examples/todo-app/build.md +++ b/src/examples/todo-app/build.md @@ -1,3 +1,7 @@ +--- +description: Our Build the Todo Application guide shows you how to create your first application with Zilla, using Apache Kafka with Kafka Streams to implement the Tasks service that maintains a shared Todo List of tasks. +--- + # Build the Todo Application In this getting started exercise, you will create a simple Todo application using a CQRS design pattern that's backed by Apache Kafka and Zilla as the event-driven API gateway. Zilla lets you focus on your applications and business logic instead of spending time writing tons of code and this demo helps to ease CQRS complexity. This tutorial gives a basic introduction to Zilla and describes some straightforward capabilities. @@ -412,7 +416,8 @@ The Zilla engine configuration defines a flow of named `bindings` representing e Let's configure `Zilla` for the Tasks API to interact with the `Todo` Kafka Streams service via Kafka topics. -You will add the following bindings to support the Tasks API as shown `zilla.yaml` below. To understand each binding type in more detail please visit [Zilla Runtime Configuration](https://docs.aklivity.io/zilla/reference/zilla.json). +You will add the following bindings to support the Tasks API as shown `zilla.yaml` below. To understand each binding type in more detail please visit [Zilla Runtime Configuration](../../reference/zilla.yaml/). + | | | | --------------------- | -------------------- | | `tcp_server0` | listens on port 8080 routes to http_server0 | @@ -432,7 +437,6 @@ Alternatively, copy the contents of `zilla.yaml` shown below to your local `zill ::: details zilla.yaml ```yaml ---- name: Example vaults: {} bindings: @@ -654,7 +658,6 @@ First, add the `http_filesystem_proxy0` and `filesystem_server0` bindings to `zi ::: details zilla.yaml (updated) ```yaml ---- name: Example vaults: {} bindings: @@ -820,7 +823,7 @@ Make sure that `zilla.yaml` config changes got applied after restarting the `Zi ### Step 5: Test Drive -Open the browser and enter [`http://localhost:8080/`](http://localhost:8080/) to see the Todo Application. +Open the browser and enter `http://localhost:8080/` to see the Todo Application. ![](./TodoAppNotLoggedIn.png) diff --git a/src/examples/todo-app/secure.md b/src/examples/todo-app/secure.md index 52add7f2..2e9ead67 100644 --- a/src/examples/todo-app/secure.md +++ b/src/examples/todo-app/secure.md @@ -1,3 +1,7 @@ +--- +description: Our Secure the Todo Application guide shows you how to secure the Tasks API using JWT access tokens to allow read and write access only to authorized clients. +--- + # Secure the Todo Application In this getting started exercise, you will enhance the [previously built Todo application](build.md) to secure the Tasks API using JWT access tokens. @@ -142,7 +146,6 @@ Alternatively, copy the contents of `zilla.yaml` shown below to your local `zill zilla.yaml ```yaml ---- name: Example vaults: {} bindings: @@ -314,7 +317,6 @@ Then, add the `http_filesystem_proxy0` and `filesystem_server0` bindings to `zil zilla.yaml (updated) ```yaml ---- name: Example vaults: {} bindings: @@ -523,7 +525,7 @@ As you can see, the `GET /tasks` API is now secured against unauthorized access, ### Step 2: Test Drive -Open the browser and enter [`http://localhost:8080/`](http://localhost:8080/) to see the secured Todo Application. +Open the browser and enter `http://localhost:8080/` to see the secured Todo Application. Initially you will see an error message caused by attempting to list the current tasks as an unauthorized user without the `read:tasks` role. diff --git a/src/get-started/README.md b/src/get-started/README.md deleted file mode 100644 index deeadf32..00000000 --- a/src/get-started/README.md +++ /dev/null @@ -1,11 +0,0 @@ -# Get Started - -The Get Started guides below will walk you through the steps to build and secure a Todo application using Apache Kafka with the Zilla engine. - -## [Installing Zilla](install/) - -on prem or in the cloud - -## [Connecting to Kafka](connecting-to-kafka/) - -Here we show you how to change the Zilla configuration to use your own Kafka cluster instead of using a local Kafka deployment in a docker stack. diff --git a/src/get-started/connecting-to-kafka/README.md b/src/get-started/connecting-to-kafka/README.md index b96cec90..c71c3966 100644 --- a/src/get-started/connecting-to-kafka/README.md +++ b/src/get-started/connecting-to-kafka/README.md @@ -24,45 +24,31 @@ A brief explanation of replaceable values from the config examples below: To connect to any Kafka on **PLAINTEXT** protocol is as simple as defining your TCP binding as shown below. -#### zilla.json - -```json -{ - "bindings": - { - ... - "kafka_client0": - { - "type" : "kafka", - "kind": "client", - "exit": "tcp_client0" - }, - "tcp_client0": - { - "type" : "tcp", - "kind": "client", - "options": - { - "host": "BOOTSTRAP_SERVER_HOSTNAME", - "port": BOOTSTRAP_SERVER_PORT - }, - "routes": - [ - { - "when": - [ - { - "cidr": "0.0.0.0/0" - } - ] - } - ] - } - } -} +### zilla.yaml + +::: code-tabs#yaml + +@tab zilla.yaml + +```yaml +bindings: + kafka_client0: + type: kafka + kind: client + exit: tcp_client0 + tcp_client0: + type: tcp + kind: client + options: + host: BOOTSTRAP_SERVER_HOSTNAME + port: BOOTSTRAP_SERVER_PORT + routes: + - when: + - cidr: 0.0.0.0/0 + ``` -@[code yaml{69-86}](zilla.yaml) +::: As usual, you need to define the host and port and flush the data to the network. For the full working config please take a look at this [example](https://github.com/aklivity/zilla-examples/blob/main/http.kafka.cache/). @@ -76,129 +62,87 @@ If the `Kafka` cluster is secured by a `TLS` server certificate that is provided The `exit` from `kafka_client0` binding now changes to `tls_client0`. ::: -#### zilla.json - -```json -{ - "bindings": - { - ... - "kafka_client0": - { - "type" : "kafka", - "kind": "client", - "exit": "tls_client0" - }, - "tls_client0": - { - "type" : "tls", - "kind": "client", - "options": - { - "trustcacerts": true - "sni": ["BOOTSTRAP_SERVER_HOSTNAME"] - }, - "exit": "tcp_client0" - }, - "tcp_client0": - { - "type" : "tcp", - "kind": "client", - "options": - { - "host": "BOOTSTRAP_SERVER_HOSTNAME", - "port": BOOTSTRAP_SERVER_PORT - }, - "routes": - [ - { - "when": - [ - { - "cidr": "0.0.0.0/0" - } - ] - } - ] - } - } -} -``` +### zilla.yaml + +::: code-tabs#yaml + +@tab zilla.yaml + +```yaml +bindings: + kafka_client0: + type: kafka + kind: client + exit: tls_client0 + tls_client0: + type: tls + kind: client + options: + trustcacerts: true + sni: + - BOOTSTRAP_SERVER_HOSTNAME + exit: tcp_client0 + tcp_client0: + type: tcp + kind: client + options: + host: BOOTSTRAP_SERVER_HOSTNAME + port: BOOTSTRAP_SERVER_PORT + routes: + - when: + - cidr: 0.0.0.0/0 -However, if the `Kafka` cluster is secured by a `TLS` server certificate that is signed by a private certificate authority then you need to add a `vault` [config](https://docs.aklivity.io/zilla/reference/zilla.json/vault-filesystem) to provide access to certificates needed by the `TLS` client binding. - -#### zilla.json - -```json -{ - "vaults": - { - "client_vault": - { - "type": "filesystem", - "options": - { - "trust": - { - "store": "TRUSTORE_PATH", - "type": "STORE_TYPE", - "password": "TRUSTORE_PASSWORD" - } - } - } - }, - "bindings": - { - ... - "kafka_client0": - { - "type" : "kafka", - "kind": "client", - "exit": "tls_client0" - }, - "tls_client0": - { - "type" : "tls", - "kind": "client", - "vault": "client_vault", - "options": - { - "trust": ["CA_CERT_ALIAS"], - "sni": ["BOOTSTRAP_SERVER_HOSTNAME"] - }, - "exit": "tcp_client0" - }, - "tcp_client0": - { - "type" : "tcp", - "kind": "client", - "options": - { - "host": "BOOTSTRAP_SERVER_HOSTNAME", - "port": BOOTSTRAP_SERVER_PORT - }, - "routes": - [ - { - "when": - [ - { - "cidr": "0.0.0.0/0" - } - ] - } - ] - } - } -} ``` -@[code yaml{69-77}](zilla.yaml) ::: -However, if the `Kafka` cluster is secured by a `TLS` server certificate that is signed by a private certificate authority then you need to add a `vault` [config](https://docs.aklivity.io/zilla/reference/zilla.json/vault-filesystem) to provide access to certificates needed by the `TLS` client binding. +However, if the `Kafka` cluster is secured by a `TLS` server certificate that is signed by a private certificate authority then you need to add a `vault` [config](../../reference/zilla.yaml/vault-filesystem.md) to provide access to certificates needed by the `TLS` client binding. + +### zilla.yaml + +::: code-tabs#yaml + +@tab zilla.yaml + +```yaml +vaults: + client_vault: + type: filesystem + options: + trust: + store: TRUSTORE_PATH + type: STORE_TYPE + password: TRUSTORE_PASSWORD +bindings: + kafka_client0: + type: kafka + kind: client + exit: tls_client0 + tls_client0: + type: tls + kind: client + vault: client_vault + options: + trust: + - CA_CERT_ALIAS + sni: + - BOOTSTRAP_SERVER_HOSTNAME + exit: tcp_client0 + tcp_client0: + type: tcp + kind: client + options: + host: BOOTSTRAP_SERVER_HOSTNAME + port: BOOTSTRAP_SERVER_PORT + routes: + - when: + - cidr: 0.0.0.0/0 -@[code yaml{3-10}](zilla.yaml) +``` + +::: + +However, if the `Kafka` cluster is secured by a `TLS` server certificate that is signed by a private certificate authority then you need to add a `vault` [config](../../reference/zilla.yaml/vault-filesystem.md) to provide access to certificates needed by the `TLS` client binding. ## Connect to Kafka over `TLS/SSL` using client certificates @@ -234,80 +178,55 @@ openssl pkcs12 -export -in service.cert -inkey service.key You also need to configure a `vault` with `truststore` and `keystore`, then reference the vault in the `tls_client0` binding. -#### zilla.json - -```json -{ - "vaults": - { - "client_vault": - { - "type": "filesystem", - "options": - { - "trust": - { - "store": "TRUSTORE_PATH", - "type": "STORE_TYPE", - "password": "TRUSTORE_PASSWORD" - }, - "keys": - { - "store": "KEYSTORE_PATH", - "type": "STORE_TYPE", - "password": "KEYSTORE_PASSWORD" - } - } - } - }, - "bindings": - { - ... - "kafka_client0": - { - "type" : "kafka", - "kind": "client", - "exit": "tls_client0" - }, - "tls_client0": - { - "type" : "tls", - "kind": "client", - "vault": "client_vault", - "options": - { - "trust": ["CA_CERT_ALIAS"], - "keys": ["SIGNED_CLIENT_CERT_ALIAS"], - "sni": ["BOOTSTRAP_SERVER_HOSTNAME"] - }, - "exit": "tcp_client0" - }, - "tcp_client0": - { - "type" : "tcp", - "kind": "client", - "options": - { - "host": "BOOTSTRAP_SERVER_HOSTNAME", - "port": BOOTSTRAP_SERVER_PORT - }, - "routes": - [ - { - "when": - [ - { - "cidr": "0.0.0.0/0" - } - ] - } - ] - } - } -} +### zilla.yaml + +::: code-tabs#yaml + +@tab zilla.yaml + +```yaml +vaults: + client_vault: + type: filesystem + options: + trust: + store: TRUSTORE_PATH + type: STORE_TYPE + password: TRUSTORE_PASSWORD + keys: + store: KEYSTORE_PATH + type: STORE_TYPE + password: KEYSTORE_PASSWORD +bindings: + kafka_client0: + type: kafka + kind: client + exit: tls_client0 + tls_client0: + type: tls + kind: client + vault: client_vault + options: + trust: + - CA_CERT_ALIAS + keys: + - SIGNED_CLIENT_CERT_ALIAS + sni: + - BOOTSTRAP_SERVER_HOSTNAME + exit: tcp_client0 + tcp_client0: + type: tcp + kind: client + options: + host: BOOTSTRAP_SERVER_HOSTNAME + port: BOOTSTRAP_SERVER_PORT + routes: + - when: + - cidr: 0.0.0.0/0 + ``` -@[code yaml{69-86}](zilla.yaml) +::: ::: info NOTE SNI adds the domain name to the TLS handshake process so that the Zilla process reaches the right domain name and receives the correct SSL certificate. @@ -334,64 +253,43 @@ Please add your feedback to the [SASL enhancement request](https://github.com/ak Let's configure zilla.json. -#### zilla.json - -```json -{ - "bindings": - { - ... - "kafka_client0": - { - "type" : "kafka", - "kind": "client", - "exit": "tls_client0", - "options": - { - "sasl": - { - "mechanism": "plain", - "username": "SASL_USERNAME", - "password": "SASL_PASSWORD" - } - } - }, - "tls_client0": - { - "type" : "tls", - "kind": "client", - "options": - { - "trustcacerts": true - "sni": ["BOOTSTRAP_SERVER_HOSTNAME"] - }, - "exit": "tcp_client0" - }, - "tcp_client0": - { - "type" : "tcp", - "kind": "client", - "options": - { - "host": "BOOTSTRAP_SERVER_HOSTNAME", - "port": BOOTSTRAP_SERVER_PORT - }, - "routes": - [ - { - "when": - [ - { - "cidr": "0.0.0.0/0" - } - ] - } - ] - } - } -} +### zilla.yaml + +::: code-tabs#yaml + +@tab zilla.yaml + +```yaml +bindings: + kafka_client0: + type: kafka + kind: client + exit: tls_client0 + options: + sasl: + mechanism: plain + username: SASL_USERNAME + password: SASL_PASSWORD + tls_client0: + type: tls + kind: client + options: + trustcacerts: true + sni: + - BOOTSTRAP_SERVER_HOSTNAME + exit: tcp_client0 + tcp_client0: + type: tcp + kind: client + options: + host: BOOTSTRAP_SERVER_HOSTNAME + port: BOOTSTRAP_SERVER_PORT + routes: + - when: + - cidr: 0.0.0.0/0 + ``` -@[code yaml{69-86}](zilla.yaml) +::: To test the above config you can follow instructions in the README from the [example](https://github.com/aklivity/zilla-examples/blob/main/http.kafka.cache/). diff --git a/src/get-started/connecting-to-kafka/aiven.md b/src/get-started/connecting-to-kafka/aiven.md index 614a5b12..4f33d066 100644 --- a/src/get-started/connecting-to-kafka/aiven.md +++ b/src/get-started/connecting-to-kafka/aiven.md @@ -64,79 +64,56 @@ openssl pkcs12 -export -in service.cert -inkey service.key \ And the final step is to configure a `vault` with `truststore` and `keystore`, then reference the vault in the `tls_client0` binding. -### zilla.json - -```json -{ - "vaults": - { - "client_vault": - { - "type": "filesystem", - "options": - { - "trust": - { - "store": "TRUSTORE_PATH", - "type": "STORE_TYPE", - "password": "TRUSTORE_PASSWORD" - }, - "keys": - { - "store": "KEYSTORE_PATH", - "type": "STORE_TYPE", - "password": "KEYSTORE_PASSWORD" - } - } - } - }, - "bindings": - { - ... - "kafka_client0": - { - "type" : "kafka", - "kind": "client", - "exit": "tls_client0" - }, - "tls_client0": - { - "type" : "tls", - "kind": "client", - "vault": "client_vault", - "options": - { - "trust": ["CA_CERT_ALIAS"], - "keys": ["SIGNED_CLIENT_CERT_ALIAS"], - "sni": ["BOOTSTRAP_SERVER_HOSTNAME"] - }, - "exit": "tcp_client0" - }, - "tcp_client0": - { - "type" : "tcp", - "kind": "client", - "options": - { - "host": "BOOTSTRAP_SERVER_HOSTNAME", - "port": BOOTSTRAP_SERVER_PORT - }, - "routes": - [ - { - "when": - [ - { - "cidr": "0.0.0.0/0" - } - ] - } - ] - } - } -} +### zilla.yaml + +::: code-tabs#yaml + +@tab zilla.yaml + +```yaml +vaults: + client_vault: + type: filesystem + options: + trust: + store: TRUSTORE_PATH + type: STORE_TYPE + password: TRUSTORE_PASSWORD + keys: + store: KEYSTORE_PATH + type: STORE_TYPE + password: KEYSTORE_PASSWORD +bindings: + kafka_client0: + type: kafka + kind: client + exit: tls_client0 + tls_client0: + type: tls + kind: client + vault: client_vault + options: + trust: + - CA_CERT_ALIAS + keys: + - SIGNED_CLIENT_CERT_ALIAS + sni: + - BOOTSTRAP_SERVER_HOSTNAME + exit: tcp_client0 + tcp_client0: + type: tcp + kind: client + options: + host: BOOTSTRAP_SERVER_HOSTNAME + port: BOOTSTRAP_SERVER_PORT + routes: + - when: + - cidr: 0.0.0.0/0 + ``` +::: + ::: info NOTE SNI adds the domain name to the TLS handshake process so that the Zilla process reaches the right domain name and receives the correct SSL certificate. ::: diff --git a/src/get-started/connecting-to-kafka/amazon-msk.md b/src/get-started/connecting-to-kafka/amazon-msk.md index e92351fc..9a7a44e4 100644 --- a/src/get-started/connecting-to-kafka/amazon-msk.md +++ b/src/get-started/connecting-to-kafka/amazon-msk.md @@ -102,73 +102,51 @@ To configure Zilla you will be replacing the following values in the `zilla.json Inside `zilla.json` create a `client_vault` that references your newly created `keystore`. After this, reference the the vault in the `tls_client0` binding. Your `zilla.json` should appear as follows: -#### zilla.json - -```json -{ - "vaults": - { - "client_vault": - { - "type": "filesystem", - "options": - { - "keys": - { - "store": "KEYSTORE_PATH", - "type": "STORE_TYPE", - "password": "KEYSTORE_PASSWORD" - } - } - } - }, - "bindings": - { - ... - "kafka_client0": - { - "type" : "kafka", - "kind": "client", - "exit": "tls_client0" - }, - "tls_client0": - { - "type" : "tls", - "kind": "client", - "vault": "client_vault", - "options": - { - "trustcacerts": true, - "keys": ["SIGNED_CLIENT_CERT_ALIAS"], - "sni": ["BOOTSTRAP_SERVER_HOSTNAME"] - }, - "exit": "tcp_client0" - }, - "tcp_client0": - { - "type" : "tcp", - "kind": "client", - "options": - { - "host": "BOOTSTRAP_ SERVER_HOSTNAME", - "port": BOOTSTRAP_SERVER_PORT - }, - "routes": - [ - { - "when": - [ - { - "cidr": "0.0.0.0/0" - } - ] - } - ] - } - } -} +### zilla.yaml + +::: code-tabs#yaml + +@tab zilla.yaml + +```yaml +vaults: + client_vault: + type: filesystem + options: + keys: + store: KEYSTORE_PATH + type: STORE_TYPE + password: KEYSTORE_PASSWORD +bindings: + kafka_client0: + type: kafka + kind: client + exit: tls_client0 + tls_client0: + type: tls + kind: client + vault: client_vault + options: + trustcacerts: true + keys: + - SIGNED_CLIENT_CERT_ALIAS + sni: + - BOOTSTRAP_SERVER_HOSTNAME + exit: tcp_client0 + tcp_client0: + type: tcp + kind: client + options: + host: BOOTSTRAP_ SERVER_HOSTNAME + port: BOOTSTRAP_SERVER_PORT + routes: + - when: + - cidr: 0.0.0.0/0 + ``` +::: + ::: info NOTE SNI adds the domain name to the TLS handshake process so that the Zilla process reaches the right domain name and receives the correct SSL certificate. ::: diff --git a/src/get-started/connecting-to-kafka/confluent-cloud.md b/src/get-started/connecting-to-kafka/confluent-cloud.md index a08e8967..afd87156 100644 --- a/src/get-started/connecting-to-kafka/confluent-cloud.md +++ b/src/get-started/connecting-to-kafka/confluent-cloud.md @@ -38,64 +38,45 @@ kcat -b BOOTSTRAP_SERVER_HOSTNAME:BOOTSTRAP_SERVER_PORT \ Let's configure `zilla.json`. -#### zilla.json - -```json -{ - "bindings": - { - ... - "kafka_client0": - { - "type" : "kafka", - "kind": "client", - "exit": "tls_client0", - "options": - { - "sasl": - { - "mechanism": "plain", - "username": "API_KEY_KEY", - "password": "API_KEY_SECRET" - } - } - }, - "tls_client0": - { - "type" : "tls", - "kind": "client", - "options": - { - "trustcacerts": true - "sni": ["BOOTSTRAP_SERVER_HOSTNAME"] - }, - "exit": "tcp_client0" - }, - "tcp_client0": - { - "type" : "tcp", - "kind": "client", - "options": - { - "host": "BOOTSTRAP_SERVER_HOSTNAME", - "port": BOOTSTRAP_SERVER_PORT - }, - "routes": - [ - { - "when": - [ - { - "cidr": "0.0.0.0/0" - } - ] - } - ] - } - } -} +### zilla.yaml + +::: code-tabs#yaml + +@tab zilla.yaml + +```yaml +bindings: + kafka_client0: + type: kafka + kind: client + exit: tls_client0 + options: + sasl: + mechanism: plain + username: API_KEY_KEY + password: API_KEY_SECRET + tls_client0: + type: tls + kind: client + options: + trustcacerts: true + sni: + - BOOTSTRAP_SERVER_HOSTNAME + exit: tcp_client0 + tcp_client0: + type: tcp + kind: client + options: + host: BOOTSTRAP_SERVER_HOSTNAME + port: BOOTSTRAP_SERVER_PORT + routes: + - when: + - cidr: 0.0.0.0/0 + ``` +::: + ::: info NOTE SNI adds the domain name to the TLS handshake process so that the Zilla process reaches the right domain name and receives the correct SSL certificate. ::: diff --git a/src/get-started/connecting-to-kafka/redpanda-zilla.yaml b/src/get-started/connecting-to-kafka/redpanda-zilla.yaml deleted file mode 100644 index a8755f87..00000000 --- a/src/get-started/connecting-to-kafka/redpanda-zilla.yaml +++ /dev/null @@ -1,86 +0,0 @@ ---- -name: example -vaults: - server: - type: filesystem - options: - keys: - store: tls/localhost.p12 - type: pkcs12 - password: ${{env.KEYSTORE_PASSWORD}} -bindings: - tcp_server0: - type: tcp - kind: server - options: - host: 0.0.0.0 - port: 9090 - exit: tls_server0 - tcp_server1: - type: tcp - kind: server - options: - host: 0.0.0.0 - port: 8080 - exit: http_server0 - tls_server0: - type: tls - kind: server - vault: server - options: - keys: - - localhost - sni: - - localhost - alpn: - - http/1.1 - - h2 - exit: http_server0 - http_server0: - type: http - kind: server - routes: - - when: - - headers: - :scheme: http - :authority: localhost:8080 - - headers: - :scheme: https - :authority: localhost:9090 - exit: http_kafka_proxy0 - http_kafka_proxy0: - type: http-kafka - kind: proxy - routes: - - when: - - path: /events - exit: kafka_cache_client0 - with: - capability: produce - topic: events - kafka_cache_client0: - type: kafka - kind: cache_client - exit: kafka_cache_server0 - kafka_cache_server0: - type: kafka - kind: cache_server - exit: kafka_client0 - kafka_client0: - type: kafka - kind: client - options: - sasl: - mechanism: scram-sha-256 - username: ${{env.SASL_USERNAME}} - password: ${{env.SASL_PASSWORD}} - exit: tcp_client0 - tcp_client0: - type: tcp - kind: client - options: - host: redpanda - port: 29092 - routes: - - when: - - cidr: 0.0.0.0/0 \ No newline at end of file diff --git a/src/get-started/connecting-to-kafka/redpanda.md b/src/get-started/connecting-to-kafka/redpanda.md index 4e5e7a40..488d1720 100644 --- a/src/get-started/connecting-to-kafka/redpanda.md +++ b/src/get-started/connecting-to-kafka/redpanda.md @@ -22,8 +22,41 @@ A brief explanation of replaceable values from the config examples below: Let's configure `zilla.yaml`. -::: details zilla.yaml -@[code yaml{3-9,69-86}](redpanda-zilla.yaml) +::: code-tabs#yaml + +@tab zilla.yaml + +```yaml +bindings: + kafka_client0: + type: kafka + kind: client + options: + sasl: + mechanism: scram-sha-256 + username: SASL_USERNAME + password: SASL_PASSWORD + exit: tls_client0 + tls_client0: + type: tls + kind: client + options: + trustcacerts: true + sni: + - BOOTSTRAP_SERVER_HOSTNAME + exit: tcp_client0 + tcp_client0: + type: tcp + kind: client + options: + host: BOOTSTRAP_SERVER_HOSTNAME + port: "BOOTSTRAP_SERVER_PORT" + routes: + - when: + - cidr: 0.0.0.0/0 + +``` + ::: ::: info NOTE diff --git a/src/get-started/connecting-to-kafka/zilla.yaml b/src/get-started/connecting-to-kafka/zilla.yaml deleted file mode 100644 index a8755f87..00000000 --- a/src/get-started/connecting-to-kafka/zilla.yaml +++ /dev/null @@ -1,86 +0,0 @@ ---- -name: example -vaults: - server: - type: filesystem - options: - keys: - store: tls/localhost.p12 - type: pkcs12 - password: ${{env.KEYSTORE_PASSWORD}} -bindings: - tcp_server0: - type: tcp - kind: server - options: - host: 0.0.0.0 - port: 9090 - exit: tls_server0 - tcp_server1: - type: tcp - kind: server - options: - host: 0.0.0.0 - port: 8080 - exit: http_server0 - tls_server0: - type: tls - kind: server - vault: server - options: - keys: - - localhost - sni: - - localhost - alpn: - - http/1.1 - - h2 - exit: http_server0 - http_server0: - type: http - kind: server - routes: - - when: - - headers: - :scheme: http - :authority: localhost:8080 - - headers: - :scheme: https - :authority: localhost:9090 - exit: http_kafka_proxy0 - http_kafka_proxy0: - type: http-kafka - kind: proxy - routes: - - when: - - path: /events - exit: kafka_cache_client0 - with: - capability: produce - topic: events - kafka_cache_client0: - type: kafka - kind: cache_client - exit: kafka_cache_server0 - kafka_cache_server0: - type: kafka - kind: cache_server - exit: kafka_client0 - kafka_client0: - type: kafka - kind: client - options: - sasl: - mechanism: scram-sha-256 - username: ${{env.SASL_USERNAME}} - password: ${{env.SASL_PASSWORD}} - exit: tcp_client0 - tcp_client0: - type: tcp - kind: client - options: - host: redpanda - port: 29092 - routes: - - when: - - cidr: 0.0.0.0/0 \ No newline at end of file diff --git a/src/guides/README.md b/src/guides/README.md deleted file mode 100644 index c50dac4f..00000000 --- a/src/guides/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# Guides - -## Configure Kafka Proxies - -In this guide, you will explore how to design/configure your API Endpoints such as [REST](kafka-proxies/rest-proxy.md) API, [SSE](kafka-proxies/sse-proxy.md) and etc. diff --git a/src/guides/kafka-proxies/rest-proxy.md b/src/guides/kafka-proxies/rest-proxy.md index 2c0141e9..e703b4fb 100644 --- a/src/guides/kafka-proxies/rest-proxy.md +++ b/src/guides/kafka-proxies/rest-proxy.md @@ -11,160 +11,126 @@ A brief explanation of replaceable values from the config examples below: ### Configure Endpoints -Zilla can be configured to map REST APIs to Kafka using the [http-kafka](https://docs.aklivity.io/zilla/reference/zilla.json/binding-http-kafka) binding in zilla.json. +Zilla can be configured to map REST APIs to Kafka using the [http-kafka](../../reference/zilla.yaml/binding-http-kafka.md) binding in zilla.json. Kafka **Produce** capability and HTTP request method types such as `POST`, `PUT`, `DELETE`, and `PATCH` . -#### zilla.json - -```json - { - "bindings": { - ... - "http_kafka_proxy0": { - "type": "http-kafka", - "kind": "proxy", - "routes": [ - { - "when": [ - { - "method": "POST", - "path": "ENDPOINT_PATH" - } - ], - "exit": "kafka_cache_client0", - "with": { - "capability": "produce", - "topic": "KAFKA_TOPIC", - "key": "${idempotencyKey}", - "reply-to": "KAFKA_REPLY_TO_TOPIC" - } - } - ] - } - ... - } - } - +### zilla.yaml + +::: code-tabs#yaml + +@tab zilla.yaml + +```yaml +bindings: + http_kafka_proxy0: + type: http-kafka + kind: proxy + routes: + - when: + - method: POST + path: ENDPOINT_PATH + exit: kafka_cache_client0 + with: + capability: produce + topic: KAFKA_TOPIC + key: ${idempotencyKey} + reply-to: KAFKA_REPLY_TO_TOPIC ``` +::: + ::: info NOTE -When the POST request is received by Zilla, a message is produced to the requests topic, with HTTP headers delivered as the Kafka message headers and the HTTP payload delivered as the Kafka message value. You have the option to [override headers](https://docs.aklivity.io/zilla/reference/zilla.json/binding-http-kafka#with-produce) as well. +When the POST request is received by Zilla, a message is produced to the requests topic, with HTTP headers delivered as the Kafka message headers and the HTTP payload delivered as the Kafka message value. You have the option to [override headers](../../reference/zilla.yaml/binding-http-kafka.md#with-capability-produce) as well. ::: Kafka **Fetch** capability with HTTP request methods such as `GET` : -#### zilla.json - -```json -{ - "bindings": { - ... - "http_kafka_proxy0": { - "type": "http-kafka", - "kind": "proxy", - "routes": [ - { - "when": [ - { - "method": "GET", - "path": "ENDPOINT_PATH" - } - ], - "exit": "kafka_cache_client0", - "with": { - "capability": "fetch", - "topic": "KAFKA_TOPIC" - } - } - ] - } - ... - } - } +### zilla.yaml + +::: code-tabs#yaml + +@tab zilla.yaml + +```yaml +bindings: + http_kafka_proxy0: + type: http-kafka + kind: proxy + routes: + - when: + - method: GET + path: ENDPOINT_PATH + exit: kafka_cache_client0 + with: + capability: fetch + topic: KAFKA_TOPIC + ``` +::: + ### Dynamic URL parameters It's a common case when you want to work with a specific entity e.g. `/tasks/123`. To make sure the dynamic value `123` is correctly matched and forwarded API endpoint can be configured as in the following example: -#### zilla.json - -```json -{ - "bindings": { - ... - "http_kafka_proxy0": { - "type": "http-kafka", - "kind": "proxy", - "routes": [ - { - "when": [ - { - "method": "GET", - "path": "/tasks/{id}" - } - ], - "exit": "kafka_cache_client0", - "with": { - "capability": "fetch", - "topic": "KAFKA_TOPIC" - }, - "filters": - [ - { - "key": "${params.id}" - } - ] - } - ] - } - ... - } -} +### zilla.yaml + +::: code-tabs#yaml + +@tab zilla.yaml + +```yaml +bindings: + http_kafka_proxy0: + type: http-kafka + kind: proxy + routes: + - when: + - method: GET + path: /tasks/{id} + exit: kafka_cache_client0 + with: + capability: fetch + topic: KAFKA_TOPIC + filters: + - key: ${params.id} + ``` +::: + ### CORS -Zilla supports Cross-Origin Resource Sharing (CORS) and allows you to specify fine-grained access control including specific request origins, methods and headers allowed, and specific response headers exposed. Since it acts more like a guard and has no dependency on Apache Kafka configuration, you need to define it in the [http binding](https://docs.aklivity.io/zilla/reference/zilla.json/binding-http). - -#### zilla.json - -```json -"http_server0": -{ - "type" : "http", - "kind": "server", - "options": - { - "access-control": - { - "policy": "cross-origin" - } - }, - "routes": - [ - { - "when": - [ - { - "headers": - { - ":scheme": "https", - ":authority": "example.com:443" - } - } - ], - "exit": "echo_server0" - } - ] -} +Zilla supports Cross-Origin Resource Sharing (CORS) and allows you to specify fine-grained access control including specific request origins, methods and headers allowed, and specific response headers exposed. Since it acts more like a guard and has no dependency on Apache Kafka configuration, you need to define it in the [http binding](../../reference/zilla.yaml/binding-http.md). + +### zilla.yaml + +::: code-tabs#yaml + +@tab zilla.yaml + +```yaml +http_server0: + type: http + kind: server + options: + access-control: + policy: cross-origin + routes: + - when: + - headers: + ':scheme': https + ':authority': example.com:443 + exit: echo_server0 ``` +::: + ### Authorization -Since `Zilla` config is very much modular it has the concept of [`guard`](https://docs.aklivity.io/zilla/reference/zilla.json/guard) where you define your `guard` configuration and reference that `guard` to authorize a specific endpoint. Currently, `Zilla` supports [`JSON Web Token (JWT)`](https://docs.aklivity.io/zilla/reference/zilla.json/guard-jwt) mechanism to authorize the endpoint. +Since `Zilla` config is very much modular it has the concept of [`guard`](../../reference/zilla.yaml/guard.md) where you define your `guard` configuration and reference that `guard` to authorize a specific endpoint. Currently, `Zilla` supports [`JSON Web Token (JWT)`](../../reference/zilla.yaml/guard-jwt.md) mechanism to authorize the endpoint. The information about keys and other details such as issuer and audience you can get from `JWT` providers for example in the case of Auth0 you can use the command below. @@ -172,90 +138,66 @@ The information about keys and other details such as issuer and audience you can url -s https://AUTH_URL/.well-known/jwks.json | jq .keys ``` -#### zilla.json - -```json -{ - ... - "guards": { - "jwt0": { - "type": "jwt", - "options": { - "issuer": "https://auth.example.com", - "audience": "https://api.example.com", - "keys": [ - { - "kty":"EC", - "crv":"P-256", - "x":"MKBCTNIcKUSDii11ySs3526iDZ8AiTo7Tu6KPAqv7D4", - "y":"4Etl6SRW2YiLUrN5vfvVHuhp7x8PxltmWWlbbM4IFyM", - "use":"enc", - "kid":"1" - }, { - "kty":"RSA", - "n": "0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFbWhM78LhWx4cbbfAAtVT86zwu1RK7aPFFxuhDR1L6tSoc_BJECPebWKRXjBZCiFV4n3oknjhMstn64tZ_2W-5JsGY4Hc5n9yBXArwl93lqt7_RN5w6Cf0h4QyQ5v-65YGjQR0_FDW2QvzqY368QQMicAtaSqzs8KJZgnYb9c7d0zgdAZHzu6qMQvRL5hajrn1n91CbOpbISD08qNLyrdkt-bFTWhAI4vMQFh6WeZu0fM4lFd2NcRwr3XPksINHaQ-G_xBniIqbw0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw", - "e":"AQAB", - "alg":"RS256", - "kid":"2011-04-29" - } - ], - "challenge": 30 - } - } - }, - { - "bindings": { - ... - "http_server0": { - "type": "http", - "kind": "server", - "options": { - ... - "authorization": { - "jwt0": { - "credentials": { - "headers": { - "authorization": "Bearer {credentials}" - }, - "query": { - "access_token": "{credentials}" - } - } - } - } - }, - ... - }, - "http_kafka_proxy0": { - "type": "http-kafka", - "kind": "proxy", - "routes": [ - { - "guarded": { - "jwt0": [ "write:tasks" ] - }, - "when": [ - { - "method": "POST", - "path": "ENDPOINT_PATH" - } - ], - "exit": "kafka_cache_client0", - "with": { - "capability": "produce", - "topic": "KAFKA_TOPIC", - "key": "${idempotencyKey}", - "reply-to": "KAFKA_REPLY_TO_TOPIC" - } - } - ] - } - ... - } - ... -} +### zilla.yaml + +::: code-tabs#yaml + +@tab zilla.yaml + +```yaml +guards: + jwt0: + type: jwt + options: + issuer: https://auth.example.com + audience: https://api.example.com + keys: + - kty: EC + crv: P-256 + x: MKBCTNIcKUSDii11ySs3526iDZ8AiTo7Tu6KPAqv7D4 + 'y': 4Etl6SRW2YiLUrN5vfvVHuhp7x8PxltmWWlbbM4IFyM + use: enc + kid: '1' + - kty: RSA + 'n': >- + 0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFbWhM78LhWx4cbbfAAtVT86zwu1RK7aPFFxuhDR1L6tSoc_BJECPebWKRXjBZCiFV4n3oknjhMstn64tZ_2W-5JsGY4Hc5n9yBXArwl93lqt7_RN5w6Cf0h4QyQ5v-65YGjQR0_FDW2QvzqY368QQMicAtaSqzs8KJZgnYb9c7d0zgdAZHzu6qMQvRL5hajrn1n91CbOpbISD08qNLyrdkt-bFTWhAI4vMQFh6WeZu0fM4lFd2NcRwr3XPksINHaQ-G_xBniIqbw0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw + e: AQAB + alg: RS256 + kid: '2011-04-29' + challenge: 30 +bindings: + http_server0: + type: http + kind: server + options: + authorization: + jwt0: + credentials: + headers: + authorization: Bearer {credentials} + query: + access_token: '{credentials}' + http_kafka_proxy0: + type: http-kafka + kind: proxy + routes: + - guarded: + jwt0: + - write:tasks + when: + - method: POST + path: ENDPOINT_PATH + exit: kafka_cache_client0 + with: + capability: produce + topic: KAFKA_TOPIC + key: ${idempotencyKey} + reply-to: KAFKA_REPLY_TO_TOPIC + ``` +::: + ### More -For a more detailed explanation please check out Zilla Runtime Configuration Reference doc for [HTTP Binding](https://docs.aklivity.io/zilla/reference/zilla.json/binding-http), [HTTP-Kafka Binding](https://docs.aklivity.io/zilla/reference/zilla.json/binding-http-kafka), and [Guard(JWT)](https://docs.aklivity.io/zilla/reference/zilla.json/guard-jwt). +For a more detailed explanation please check out Zilla Runtime Configuration Reference doc for [HTTP Binding](../../reference/zilla.yaml/binding-http.md), [HTTP-Kafka Binding](../../reference/zilla.yaml/binding-http-kafka.md), and [Guard(JWT)](../../reference/zilla.yaml/guard-jwt.md). diff --git a/src/guides/kafka-proxies/sse-proxy.md b/src/guides/kafka-proxies/sse-proxy.md index 4e6d4a1e..11992e95 100644 --- a/src/guides/kafka-proxies/sse-proxy.md +++ b/src/guides/kafka-proxies/sse-proxy.md @@ -11,50 +11,37 @@ A brief explanation of replaceable values from the config examples below: Configuring `Zilla` with SSE endpoint and Kafka binding is as simple as it is shown below: -```json -{ - ... - "sse_server0": - { - "type" : "sse", - "kind": "server", - "exit": "sse_kafka_proxy0" - }, - "sse_kafka_proxy0": - { - "type" : "sse-kafka", - "kind": "proxy", - "routes": - [ - { - "when": - [ - { - "path": "ENDPOINT_PATH" - } - ], - "with": - { - "topic": "KAFKA_TOPIC", - "event": - { - "id": "[\"${base64(key)}\",\"${etag}\"]" - } - }, - "exit": "kafka_cache_client0", - } - ] - } - ... -} +::: code-tabs#yaml + +@tab zilla.yaml + +```yaml +sse_server0: + type: sse + kind: server + exit: sse_kafka_proxy0 +sse_kafka_proxy0: + type: sse-kafka + kind: proxy + routes: + - when: + - path: ENDPOINT_PATH + with: + topic: KAFKA_TOPIC + event: + id: '["${base64(key)}","${etag}"]' + exit: kafka_cache_client0 + ``` +::: + As shown above you can describe your event id in case you want to retrieve the message `key` or `etag`. ### Authorization -Similar to [REST API](https://app.gitbook.com/o/-MgpzCvF5ASmql4KrimM/s/Vm9RaZVq9LSiRtVnjdT5/\~/changes/6egLxlGFQsSCpw1GICR4/configure-apis/rest-api) you can secure the `SSE` endpoints as well which allows you to continuously authorize the stream which unlike `HTTP` request, `SSE` is a long-lived connection. +Similar to [REST Proxy](rest-proxy.md) you can secure the `SSE` endpoints as well which allows you to continuously authorize the stream which unlike `HTTP` request, `SSE` is a long-lived connection. ### More -For the full capability of `SSE` configure you can check out Zilla Runtime Configuration Reference: [SSE Binding](https://docs.aklivity.io/zilla/reference/zilla.json/binding-sse), [SSE-Kafka Binding](https://docs.aklivity.io/zilla/reference/zilla.json/binding-sse-kafka). +For the full capability of `SSE` configure you can check out Zilla Runtime Configuration Reference: [SSE Binding](../../reference/zilla.yaml/binding-sse.md), [SSE-Kafka Binding](../../reference/zilla.yaml/binding-sse-kafka.md). diff --git a/src/reference/zilla.yaml/README.md b/src/reference/zilla.yaml/README.md index c1037927..b25d1e8e 100644 --- a/src/reference/zilla.yaml/README.md +++ b/src/reference/zilla.yaml/README.md @@ -1,6 +1,5 @@ --- title: Zilla Runtime Configuration -icon: "gears" order: 1 category: - config diff --git a/src/reference/zilla/README.md b/src/reference/zilla/README.md index 72cf9ffe..1c37417a 100644 --- a/src/reference/zilla/README.md +++ b/src/reference/zilla/README.md @@ -1,6 +1,5 @@ --- title: Zilla Runtime CLI -icon: "terminal" order: 2 category: - CLI @@ -9,7 +8,7 @@ description: The command line interface to control the Zilla runtime. # Zilla Runtime CLI (zilla) -The Zilla Runtime command line interface uses the [Zilla Runtime Configuration](../zilla.yaml/README.md) to control and observe the Zilla runtime. +The Zilla Runtime command line interface uses the [Zilla Runtime Configuration](../zilla.yaml/) to control and observe the Zilla runtime. ## Commands diff --git a/src/reference/zpm/README.md b/src/reference/zpm/README.md index ed1c766c..a4e744ad 100644 --- a/src/reference/zpm/README.md +++ b/src/reference/zpm/README.md @@ -1,6 +1,5 @@ --- title: Zilla Manager CLI -icon: "server" order: 3 category: - CLI

enum [
"jwt"
]