diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 00000000..8b717fab --- /dev/null +++ b/.dockerignore @@ -0,0 +1,7 @@ +.git/ +.github/ +lib/ +target/ +common/target/ +codegen/target/ +tests/ diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 01419f35..4ae2b853 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,6 +19,11 @@ jobs: - name: Checkout Sources uses: actions/checkout@v4 + - name: Install Protoc + uses: arduino/setup-protoc@v3 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + - name: Setup cache uses: Swatinem/rust-cache@v2 @@ -46,6 +51,11 @@ jobs: - name: Checkout Sources uses: actions/checkout@v4 + - name: Install Protoc + uses: arduino/setup-protoc@v3 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + - name: Setup cache uses: Swatinem/rust-cache@v2 @@ -59,7 +69,6 @@ jobs: run: cargo make clippy test: - needs: [ clippy, check ] name: tests runs-on: ubuntu-latest steps: @@ -73,34 +82,10 @@ jobs: - name: Checkout Sources uses: actions/checkout@v4 - - name: Setup cache - uses: Swatinem/rust-cache@v2 - - - name: Install cargo-make - uses: actions-rs/cargo@v1 - with: - command: install - args: cargo-make - - - name: Tests - run: cargo make test - - docs: - name: docs - runs-on: ubuntu-latest - steps: - - uses: pnpm/action-setup@v2 - with: - version: 8 - - - name: Install toolchain - uses: actions-rs/toolchain@v1 + - name: Install Protoc + uses: arduino/setup-protoc@v3 with: - toolchain: nightly - override: true - - - name: Checkout Sources - uses: actions/checkout@v4 + repo-token: ${{ secrets.GITHUB_TOKEN }} - name: Setup cache uses: Swatinem/rust-cache@v2 @@ -111,8 +96,5 @@ jobs: command: install args: cargo-make - - name: Run docs lint - uses: actions-rs/cargo@v1 - with: - command: make - args: docs_lint + - name: Tests + run: cargo make test diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 1aa10f0b..4ee1605c 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -20,6 +20,11 @@ jobs: - name: Checkout Sources uses: actions/checkout@v4 + - name: Install Protoc + uses: arduino/setup-protoc@v3 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + - name: Setup cache uses: Swatinem/rust-cache@v2 @@ -47,6 +52,11 @@ jobs: - name: Checkout Sources uses: actions/checkout@v4 + - name: Install Protoc + uses: arduino/setup-protoc@v3 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + - name: Setup cache uses: Swatinem/rust-cache@v2 @@ -60,7 +70,6 @@ jobs: run: cargo make clippy test: - needs: [ clippy, check ] name: tests runs-on: ubuntu-latest steps: @@ -74,34 +83,10 @@ jobs: - name: Checkout Sources uses: actions/checkout@v4 - - name: Setup cache - uses: Swatinem/rust-cache@v2 - - - name: Install cargo-make - uses: actions-rs/cargo@v1 - with: - command: install - args: cargo-make - - - name: Tests - run: cargo make test - - docs-lint: - name: lint docs - runs-on: ubuntu-latest - steps: - - uses: pnpm/action-setup@v2 - with: - version: 8 - - - name: Install toolchain - uses: actions-rs/toolchain@v1 + - name: Install Protoc + uses: arduino/setup-protoc@v3 with: - toolchain: nightly - override: true - - - name: Checkout Sources - uses: actions/checkout@v4 + repo-token: ${{ secrets.GITHUB_TOKEN }} - name: Setup cache uses: Swatinem/rust-cache@v2 @@ -112,97 +97,94 @@ jobs: command: install args: cargo-make - - name: Run docs lint - uses: actions-rs/cargo@v1 - with: - command: make - args: docs_lint - - build-docs: - needs: [ docs-lint ] - name: build docs - runs-on: ubuntu-latest - steps: - - uses: pnpm/action-setup@v2 - with: - version: 8 - - - name: Install toolchain - uses: actions-rs/toolchain@v1 - with: - toolchain: nightly - override: true - - - name: Checkout Sources - uses: actions/checkout@v4 - - - name: Setup cache - uses: Swatinem/rust-cache@v2 - - - name: Install cargo-make - uses: actions-rs/cargo@v1 - with: - command: install - args: cargo-make - - - name: Determine current pages artifact - id: determine_pages_artifact - uses: actions/github-script@v7 - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - script: | - const { data } = await github.rest.actions.listWorkflowRunsForRepo({ - owner: context.repo.owner, - repo: context.repo.repo, - branch: "main", - status: "success", - per_page: 1 - }); - - core.setOutput("last_run", data.workflow_runs[0].id); - - - name: Download current pages artifact - uses: actions/download-artifact@v4 - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - run-id: ${{ steps.determine_pages_artifact.outputs.last_run }} - name: github-pages - path: ./ - - - name: Extract pages artifact - run: mkdir pages/ && tar -xvf artifact.tar -C pages/ - - - name: Build docs - uses: actions-rs/cargo@v1 - with: - command: make - args: docs_build - - - name: Prefix docs - run: rm -Rf pages/nightly/ && mkdir -p pages/nightly/ && mv -f target/docs/ pages/nightly/docs/ - - - name: Fix permissions - run: | - chmod -c -R +rX "pages/" | while read line; do - echo "::warning title=Invalid file permissions automatically fixed::$line" - done + - name: Tests + run: cargo make test - - name: Upload pages artifact - uses: actions/upload-pages-artifact@v3 - with: - path: pages/ - retention-days: 3 + # build-docs: + # needs: [ docs-lint ] + # name: build docs + # runs-on: ubuntu-latest + # steps: + # - uses: pnpm/action-setup@v2 + # with: + # version: 8 + # + # - name: Install toolchain + # uses: actions-rs/toolchain@v1 + # with: + # toolchain: nightly + # override: true + # + # - name: Checkout Sources + # uses: actions/checkout@v4 + # + # - name: Setup cache + # uses: Swatinem/rust-cache@v2 + # + # - name: Install cargo-make + # uses: actions-rs/cargo@v1 + # with: + # command: install + # args: cargo-make + # + # - name: Determine current pages artifact + # id: determine_pages_artifact + # uses: actions/github-script@v7 + # with: + # github-token: ${{ secrets.GITHUB_TOKEN }} + # script: | + # const { data } = await github.rest.actions.listWorkflowRunsForRepo({ + # owner: context.repo.owner, + # repo: context.repo.repo, + # branch: "main", + # status: "success", + # per_page: 1 + # }); + # + # core.setOutput("last_run", data.workflow_runs[0].id); + # + # - name: Download current pages artifact + # uses: actions/download-artifact@v4 + # with: + # github-token: ${{ secrets.GITHUB_TOKEN }} + # run-id: ${{ steps.determine_pages_artifact.outputs.last_run }} + # name: github-pages + # path: ./ + # + # - name: Extract pages artifact + # run: mkdir pages/ && tar -xvf artifact.tar -C pages/ + # + # - name: Build docs + # uses: actions-rs/cargo@v1 + # with: + # command: make + # args: docs_build + # + # - name: Prefix docs + # run: rm -Rf pages/nightly/ && mkdir -p pages/nightly/ && mv -f target/docs/ pages/nightly/docs/ + # + # - name: Fix permissions + # run: | + # chmod -c -R +rX "pages/" | while read line; do + # echo "::warning title=Invalid file permissions automatically fixed::$line" + # done + # + # - name: Upload pages artifact + # uses: actions/upload-pages-artifact@v3 + # with: + # path: pages/ + # retention-days: 3 - deploy-pages: - needs: [ build-docs, test ] - runs-on: ubuntu-latest - permissions: - pages: write - id-token: write - environment: - name: github-pages - url: ${{ steps.deployment.outputs.page_url }} - steps: - - name: Deploy to pages - id: deployment - uses: actions/deploy-pages@v4 + # deploy-pages: + # needs: [ build-docs, test ] + # runs-on: ubuntu-latest + # permissions: + # pages: write + # id-token: write + # environment: + # name: github-pages + # url: ${{ steps.deployment.outputs.page_url }} + # steps: + # - name: Deploy to pages + # id: deployment + # uses: actions/deploy-pages@v4 diff --git a/.redocly.lint-ignore.yaml b/.redocly.lint-ignore.yaml deleted file mode 100644 index 1f611238..00000000 --- a/.redocly.lint-ignore.yaml +++ /dev/null @@ -1,6 +0,0 @@ -# This file instructs Redocly's linter to ignore the rules contained for specific parts of your API. -# See https://redoc.ly/docs/cli/ for more information. -target/openapi.yaml: - spec: - - >- - #/components/schemas/PutFeedbackPromptFieldRequest/properties/options/nullable diff --git a/Cargo.toml b/Cargo.toml index a4543393..4e22647c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,28 +3,17 @@ name = "feedback-fusion" version = "0.1.0" edition = "2021" license = "MIT" -default-run = "main" - -[[bin]] -name = "main" -path = "src/main.rs" - -[[bin]] -name = "docs" -path = "src/docs.rs" - -[[bin]] -name = "bindings" -path = "src/bindings.rs" [dependencies] +feedback_fusion_common = { path = "./common" } +feedback_fusion_codegen = { path = "./codegen" } + aliri = "0.6.3" -aliri_axum = "0.4.0" aliri_clock = "0.1.4" aliri_oauth2 = "0.10.1" -aliri_tower = "0.6.0" +aliri_tower = "=0.5.0" +aliri_traits = "0.1.1" async-trait = "0.1.80" -axum = "0.7.5" chrono = { version = "0.4.38", features = ["serde"] } derivative = "2.2.0" envy = "0.4.2" @@ -34,6 +23,7 @@ lazy_static = "1.4.0" nanoid = "0.4.0" openidconnect = "3.5.0" paste = "1.0.14" +prost-types = "0.12.4" rbatis = "4.5.21" rbdc-pg = { version = "4.5.6", optional = true } rbdc-mysql = { version = "4.5.7", optional = true } @@ -41,18 +31,21 @@ rbs = "4.5.13" serde = { version = "1.0.197", features = ["derive"] } serde_json = "1.0.115" thiserror = "1.0.58" +tonic = "0.11.0" +tonic-health = "0.11.0" +tonic-reflection = "0.11.0" +tonic-web = "0.11.0" tokio = { version = "1.37.0", features = ["full"] } -tower = { version = "0.4.13", features = ["limit", "buffer"] } -tower-http = { version = "0.5.2", features = ["trace"] } +tower = "0.4.13" +tower-http = { version = "=0.4.4", features = ["trace", "validate-request"] } tracing = "0.1.39" tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } -ts-rs = { version = "7.1.1", optional = true } typed-builder = "0.18.1" -utoipa = { version = "4.2.0", features = ["yaml", "chrono"] } validator = { version = "0.18", features = ["derive"] } version-compare = "0.2.0" [dev-dependencies] +paste = "1.0.14" rand = "0.8.5" reqwest = { version = "0.12.3", features = ["json"] } test-log = "0.2.15" @@ -65,6 +58,3 @@ postgres = ["rbdc-pg"] mysql = ["rbdc-mysql"] test = [] -docs = [] -bindings = ["ts-rs"] - diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..c6a12baf --- /dev/null +++ b/Dockerfile @@ -0,0 +1,24 @@ +FROM rust:slim as build + +ARG features=all-databases + +RUN apt-get update +RUN apt-get install libssl-dev protobuf-compiler -y + +# set toolchain +RUN rustup default nightly + +COPY ./Cargo.toml . +COPY ./Cargo.lock . +COPY ./proto ./proto +COPY ./common ./common +COPY ./codegen ./codegen +COPY ./src ./src + +RUN cargo build --release --features $features + +FROM gcr.io/distroless/cc-debian12 + +COPY --from=build ./target/release/feedback-fusion . + +ENTRYPOINT ["./feedback-fusion"] diff --git a/Makefile.toml b/Makefile.toml index 064dc290..c53e86e0 100644 --- a/Makefile.toml +++ b/Makefile.toml @@ -3,37 +3,27 @@ [config] skip_core_tasks = true -[tasks.docs_init] -command = "pnpm" -args = ["i"] - -# openapi docs - -[tasks.docs_generate] -dependencies = ["docs_init"] -command = "cargo" -args = ["run", "--bin", "docs", "--features", "docs"] +# lib dev -[tasks.docs_preview] -dependencies = ["docs_generate"] +[tasks.core_generate] +cwd = "./lib/core/src/" command = "npx" -args = ["redocly", "preview-docs", "target/openapi.yaml"] - -# lib dev +args = ["protoc", "--ts_out", ".", "--ts_opt", "server_none", "--proto_path", "../../../proto", "../../../proto/feedback-fusion-v1.proto"] -[tasks.core_build] +[tasks.core] +dependencies = ["core_generate"] cwd = "./lib/core/" command = "pnpm" args = ["run", "tsc"] [tasks.vue] -dependencies = ["core_build"] +dependencies = ["core"] cwd = "./lib/vue/" command = "pnpm" args = ["run", "docs:dev"] [tasks.vue_build] -dependencies = ["core_build"] +dependencies = ["core"] cwd = "./lib/vue/" command = "pnpm" args = ["run", "build"] @@ -42,35 +32,27 @@ args = ["run", "build"] [tasks.check] command = "cargo" -args = ["check", "--bin", "main"] +args = ["check", "--features", "all-databases"] [tasks.clippy] command = "cargo" -args = [ - "clippy", - "--bin", - "main", - "--features", - "postgres", - "--", - "-D", - "warnings", -] +args = ["clippy", "--features", "all-databases", "--", "-D", "warnings"] # run oidc server for integration tests [tasks.oidc-server-mock] -script = "docker compose -f tests/_common/oidc-mock/docker-compose.yaml up -d" +script = "docker compose -f tests/_common/oidc-mock/docker-compose.yaml up -d && sleep 5 && curl -s -o /dev/null http://localhost:5151/.well-known/openid-configuration" # Postgres [tasks.postgres_database] script = "docker run --name postgres -e POSTGRES_PASSWORD=password -e POSTGRES_USERNAME=postgres -p 5150:5432 -d postgres && sleep 1" [tasks.postgres_tests] -env = { DATABASE = "POSTGRES", POSTGRES_USERNAME = "postgres", POSTGRES_PASSWORD = "password", POSTGRES_ENDPOINT = "localhost:5150", POSTGRES_DATABASE = "postgres", "OIDC_DISCOVERY_URL" = "http://localhost:5151", OIDC_CLIENT_ID = "client", OIDC_CLIENT_SECRET = "secret", OIDC_SCOPE = "api:feedback-fusion", RUST_LOG = "INFO" } +env = { DATABASE = "POSTGRES", POSTGRES_USERNAME = "postgres", POSTGRES_PASSWORD = "password", POSTGRES_ENDPOINT = "localhost:5150", POSTGRES_DATABASE = "postgres", "OIDC_DISCOVERY_URL" = "http://localhost:5151", OIDC_CLIENT_ID = "client", OIDC_CLIENT_SECRET = "secret", RUST_LOG = "INFO" } command = "cargo" args = [ "test", + "--no-fail-fast", "--no-default-features", "--features", "postgres,test", @@ -87,46 +69,9 @@ run_task = { name = [ ], fork = true, cleanup_task = "postgres_cleanup" } [tasks.postgres_cleanup] -script = "docker kill postgres;docker rm postgres;docker kill oidc-server-mock;docker rm oidc-server-mock" +script = "docker rm -f postgres;docker rm -f oidc-server-mock" # run all tests [tasks.test] run_task = { name = ["postgres"] } - -# OpenAPI build - -[tasks.docs_lint] -dependencies = ["docs_generate"] -command = "npx" -args = [ - "redocly", - "lint", - "--skip-rule=no-empty-servers", - "--skip-rule=info-license-url", - "target/openapi.yaml", -] - -[tasks.docs_build] -dependencies = ["docs_lint"] -command = "npx" -args = ["redocly", "build-docs", "target/openapi.yaml", "-o", "target/docs/http/index.html"] - -# bindings - -[tasks.generate_bindings] -command = "cargo" -args = [ - "run", - "--bin", - "bindings", - "--no-default-features", - "--features", - "bindings,postgres", -] - -[tasks.export_bindings] -script = '''for f in bindings/*.ts; do [ "$f" != "bindings/index.ts" ] && echo "export * from './$(basename "$f" .ts)';" ; done > bindings/index.ts''' - -[tasks.bindings] -run_task = { name = ["generate_bindings", "export_bindings"] } diff --git a/bindings/CheckboxOptions.ts b/bindings/CheckboxOptions.ts deleted file mode 100644 index abfab5a2..00000000 --- a/bindings/CheckboxOptions.ts +++ /dev/null @@ -1,4 +0,0 @@ -// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. -import type { CheckboxStyle } from "./CheckboxStyle"; - -export interface CheckboxOptions { defaultState: boolean, style: CheckboxStyle, } \ No newline at end of file diff --git a/bindings/CheckboxResponse.ts b/bindings/CheckboxResponse.ts deleted file mode 100644 index 3d651636..00000000 --- a/bindings/CheckboxResponse.ts +++ /dev/null @@ -1,3 +0,0 @@ -// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. - -export interface CheckboxResponse { checked: boolean, } \ No newline at end of file diff --git a/bindings/CheckboxStyle.ts b/bindings/CheckboxStyle.ts deleted file mode 100644 index fbc006d7..00000000 --- a/bindings/CheckboxStyle.ts +++ /dev/null @@ -1,3 +0,0 @@ -// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. - -export type CheckboxStyle = "switch" | "checkbox"; \ No newline at end of file diff --git a/bindings/CreateFeedbackPromptFieldRequest.ts b/bindings/CreateFeedbackPromptFieldRequest.ts deleted file mode 100644 index e190762c..00000000 --- a/bindings/CreateFeedbackPromptFieldRequest.ts +++ /dev/null @@ -1,5 +0,0 @@ -// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. -import type { FeedbackPromptInputOptions } from "./FeedbackPromptInputOptions"; -import type { FeedbackPromptInputType } from "./FeedbackPromptInputType"; - -export interface CreateFeedbackPromptFieldRequest { title: string, description: string | null, type: FeedbackPromptInputType, options: FeedbackPromptInputOptions, } \ No newline at end of file diff --git a/bindings/CreateFeedbackPromptRequest.ts b/bindings/CreateFeedbackPromptRequest.ts deleted file mode 100644 index c9df6d2e..00000000 --- a/bindings/CreateFeedbackPromptRequest.ts +++ /dev/null @@ -1,3 +0,0 @@ -// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. - -export interface CreateFeedbackPromptRequest { title: string, active: boolean, description: string, } \ No newline at end of file diff --git a/bindings/CreateFeedbackTargetRequest.ts b/bindings/CreateFeedbackTargetRequest.ts deleted file mode 100644 index 91fe6703..00000000 --- a/bindings/CreateFeedbackTargetRequest.ts +++ /dev/null @@ -1,3 +0,0 @@ -// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. - -export interface CreateFeedbackTargetRequest { name: string, description: string | null, } \ No newline at end of file diff --git a/bindings/FeedbackPrompt.ts b/bindings/FeedbackPrompt.ts deleted file mode 100644 index 89666928..00000000 --- a/bindings/FeedbackPrompt.ts +++ /dev/null @@ -1,3 +0,0 @@ -// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. - -export interface FeedbackPrompt { id: string, title: string, description: string, target: string, active: boolean, updated_at: Date, created_at: Date, } \ No newline at end of file diff --git a/bindings/FeedbackPromptField.ts b/bindings/FeedbackPromptField.ts deleted file mode 100644 index 8710ca0f..00000000 --- a/bindings/FeedbackPromptField.ts +++ /dev/null @@ -1,5 +0,0 @@ -// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. -import type { FeedbackPromptInputOptions } from "./FeedbackPromptInputOptions"; -import type { FeedbackPromptInputType } from "./FeedbackPromptInputType"; - -export interface FeedbackPromptField { id: string, title: string, description: string | null, prompt: string, type: FeedbackPromptInputType, options: FeedbackPromptInputOptions, updated_at: Date, created_at: Date, } \ No newline at end of file diff --git a/bindings/FeedbackPromptFieldData.ts b/bindings/FeedbackPromptFieldData.ts deleted file mode 100644 index ce0f5dfb..00000000 --- a/bindings/FeedbackPromptFieldData.ts +++ /dev/null @@ -1,9 +0,0 @@ -// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. -import type { CheckboxResponse } from "./CheckboxResponse"; -import type { NumberResponse } from "./NumberResponse"; -import type { RangeResponse } from "./RangeResponse"; -import type { RatingResponse } from "./RatingResponse"; -import type { SelectionResponse } from "./SelectionResponse"; -import type { TextResponse } from "./TextResponse"; - -export type FeedbackPromptFieldData = { "type": "text" } & TextResponse | { "type": "rating" } & RatingResponse | { "type": "checkbox" } & CheckboxResponse | { "type": "selection" } & SelectionResponse | { "type": "range" } & RangeResponse | { "type": "number" } & NumberResponse; \ No newline at end of file diff --git a/bindings/FeedbackPromptFieldResponse.ts b/bindings/FeedbackPromptFieldResponse.ts deleted file mode 100644 index 873b63f7..00000000 --- a/bindings/FeedbackPromptFieldResponse.ts +++ /dev/null @@ -1,4 +0,0 @@ -// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. -import type { FeedbackPromptFieldData } from "./FeedbackPromptFieldData"; - -export interface FeedbackPromptFieldResponse { id: string, response: string, field: string, data: FeedbackPromptFieldData, } \ No newline at end of file diff --git a/bindings/FeedbackPromptInputOptions.ts b/bindings/FeedbackPromptInputOptions.ts deleted file mode 100644 index a5ac83a8..00000000 --- a/bindings/FeedbackPromptInputOptions.ts +++ /dev/null @@ -1,9 +0,0 @@ -// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. -import type { CheckboxOptions } from "./CheckboxOptions"; -import type { NumberOptions } from "./NumberOptions"; -import type { RangeOptions } from "./RangeOptions"; -import type { RatingOptions } from "./RatingOptions"; -import type { SelectionOptions } from "./SelectionOptions"; -import type { TextOptions } from "./TextOptions"; - -export type FeedbackPromptInputOptions = { "type": "text" } & TextOptions | { "type": "rating" } & RatingOptions | { "type": "checkbox" } & CheckboxOptions | { "type": "selection" } & SelectionOptions | { "type": "range" } & RangeOptions | { "type": "number" } & NumberOptions; \ No newline at end of file diff --git a/bindings/FeedbackPromptInputType.ts b/bindings/FeedbackPromptInputType.ts deleted file mode 100644 index bca96737..00000000 --- a/bindings/FeedbackPromptInputType.ts +++ /dev/null @@ -1,3 +0,0 @@ -// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. - -export type FeedbackPromptInputType = "text" | "rating" | "checkbox" | "selection" | "range" | "number"; \ No newline at end of file diff --git a/bindings/FeedbackPromptResponse.ts b/bindings/FeedbackPromptResponse.ts deleted file mode 100644 index 20ff4821..00000000 --- a/bindings/FeedbackPromptResponse.ts +++ /dev/null @@ -1,3 +0,0 @@ -// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. - -export interface FeedbackPromptResponse { id: string, prompt: string, created_at: Date, } \ No newline at end of file diff --git a/bindings/FeedbackTarget.ts b/bindings/FeedbackTarget.ts deleted file mode 100644 index 4c4e7db6..00000000 --- a/bindings/FeedbackTarget.ts +++ /dev/null @@ -1,3 +0,0 @@ -// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. - -export interface FeedbackTarget { id: string, name: string, description: string | null, updated_at: Date, created_at: Date, } \ No newline at end of file diff --git a/bindings/GetFeedbackPromptResponsesResponseWrapper.ts b/bindings/GetFeedbackPromptResponsesResponseWrapper.ts deleted file mode 100644 index 7b119d1f..00000000 --- a/bindings/GetFeedbackPromptResponsesResponseWrapper.ts +++ /dev/null @@ -1,4 +0,0 @@ -// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. -import type { FeedbackPromptFieldResponse } from "./FeedbackPromptFieldResponse"; - -export type GetFeedbackPromptResponsesResponseWrapper = Record>; \ No newline at end of file diff --git a/bindings/NumberOptions.ts b/bindings/NumberOptions.ts deleted file mode 100644 index b2afa209..00000000 --- a/bindings/NumberOptions.ts +++ /dev/null @@ -1,3 +0,0 @@ -// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. - -export interface NumberOptions { min: number, max: number, placeholder: string, } \ No newline at end of file diff --git a/bindings/NumberResponse.ts b/bindings/NumberResponse.ts deleted file mode 100644 index e2a48c2d..00000000 --- a/bindings/NumberResponse.ts +++ /dev/null @@ -1,3 +0,0 @@ -// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. - -export interface NumberResponse { number: number, } \ No newline at end of file diff --git a/bindings/Page.ts b/bindings/Page.ts deleted file mode 100644 index 200d55e4..00000000 --- a/bindings/Page.ts +++ /dev/null @@ -1,4 +0,0 @@ -// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. -import type { FeedbackPromptField } from "./FeedbackPromptField"; - -export interface Page { records: Array, total: number, page_no: number, } \ No newline at end of file diff --git a/bindings/PutFeedbackPromptFieldRequest.ts b/bindings/PutFeedbackPromptFieldRequest.ts deleted file mode 100644 index bbe80555..00000000 --- a/bindings/PutFeedbackPromptFieldRequest.ts +++ /dev/null @@ -1,4 +0,0 @@ -// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. -import type { FeedbackPromptInputOptions } from "./FeedbackPromptInputOptions"; - -export interface PutFeedbackPromptFieldRequest { title: string | null, options: FeedbackPromptInputOptions | null, } \ No newline at end of file diff --git a/bindings/PutFeedbackPromptRequest.ts b/bindings/PutFeedbackPromptRequest.ts deleted file mode 100644 index f401b179..00000000 --- a/bindings/PutFeedbackPromptRequest.ts +++ /dev/null @@ -1,3 +0,0 @@ -// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. - -export interface PutFeedbackPromptRequest { title: string | null, active: boolean | null, } \ No newline at end of file diff --git a/bindings/PutFeedbackTargetRequest.ts b/bindings/PutFeedbackTargetRequest.ts deleted file mode 100644 index 15247839..00000000 --- a/bindings/PutFeedbackTargetRequest.ts +++ /dev/null @@ -1,3 +0,0 @@ -// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. - -export interface PutFeedbackTargetRequest { name: string | null, description: string | null, } \ No newline at end of file diff --git a/bindings/RangeOptions.ts b/bindings/RangeOptions.ts deleted file mode 100644 index e7b73bab..00000000 --- a/bindings/RangeOptions.ts +++ /dev/null @@ -1,3 +0,0 @@ -// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. - -export interface RangeOptions { min: number, max: number, } \ No newline at end of file diff --git a/bindings/RangeResponse.ts b/bindings/RangeResponse.ts deleted file mode 100644 index f587e36e..00000000 --- a/bindings/RangeResponse.ts +++ /dev/null @@ -1,3 +0,0 @@ -// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. - -export interface RangeResponse { start: number, end: number, } \ No newline at end of file diff --git a/bindings/RatingOptions.ts b/bindings/RatingOptions.ts deleted file mode 100644 index 80ba9b16..00000000 --- a/bindings/RatingOptions.ts +++ /dev/null @@ -1,3 +0,0 @@ -// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. - -export interface RatingOptions { max: number, } \ No newline at end of file diff --git a/bindings/RatingResponse.ts b/bindings/RatingResponse.ts deleted file mode 100644 index 23556200..00000000 --- a/bindings/RatingResponse.ts +++ /dev/null @@ -1,3 +0,0 @@ -// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. - -export interface RatingResponse { rating: number, } \ No newline at end of file diff --git a/bindings/SelectionOptions.ts b/bindings/SelectionOptions.ts deleted file mode 100644 index 34297764..00000000 --- a/bindings/SelectionOptions.ts +++ /dev/null @@ -1,3 +0,0 @@ -// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. - -export interface SelectionOptions { values: Array, multiple: boolean, combobox: boolean, } \ No newline at end of file diff --git a/bindings/SelectionResponse.ts b/bindings/SelectionResponse.ts deleted file mode 100644 index b7e1087e..00000000 --- a/bindings/SelectionResponse.ts +++ /dev/null @@ -1,3 +0,0 @@ -// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. - -export interface SelectionResponse { values: Array, } \ No newline at end of file diff --git a/bindings/SubmitFeedbackPromptResponseRequest.ts b/bindings/SubmitFeedbackPromptResponseRequest.ts deleted file mode 100644 index 79e02bfd..00000000 --- a/bindings/SubmitFeedbackPromptResponseRequest.ts +++ /dev/null @@ -1,4 +0,0 @@ -// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. -import type { FeedbackPromptFieldData } from "./FeedbackPromptFieldData"; - -export interface SubmitFeedbackPromptResponseRequest { responses: Record, } \ No newline at end of file diff --git a/bindings/TextOptions.ts b/bindings/TextOptions.ts deleted file mode 100644 index 160bf360..00000000 --- a/bindings/TextOptions.ts +++ /dev/null @@ -1,3 +0,0 @@ -// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. - -export interface TextOptions { placeholder: string, lines: number, } \ No newline at end of file diff --git a/bindings/TextResponse.ts b/bindings/TextResponse.ts deleted file mode 100644 index 4e1ca371..00000000 --- a/bindings/TextResponse.ts +++ /dev/null @@ -1,3 +0,0 @@ -// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. - -export interface TextResponse { text: string, } \ No newline at end of file diff --git a/bindings/index.ts b/bindings/index.ts deleted file mode 100644 index c10bebe2..00000000 --- a/bindings/index.ts +++ /dev/null @@ -1,30 +0,0 @@ -export * from './CheckboxOptions'; -export * from './CheckboxResponse'; -export * from './CheckboxStyle'; -export * from './CreateFeedbackPromptFieldRequest'; -export * from './CreateFeedbackPromptRequest'; -export * from './CreateFeedbackTargetRequest'; -export * from './FeedbackPrompt'; -export * from './FeedbackPromptField'; -export * from './FeedbackPromptFieldData'; -export * from './FeedbackPromptFieldResponse'; -export * from './FeedbackPromptInputOptions'; -export * from './FeedbackPromptInputType'; -export * from './FeedbackPromptResponse'; -export * from './FeedbackTarget'; -export * from './GetFeedbackPromptResponsesResponseWrapper'; -export * from './NumberOptions'; -export * from './NumberResponse'; -export * from './Page'; -export * from './PutFeedbackPromptFieldRequest'; -export * from './PutFeedbackPromptRequest'; -export * from './PutFeedbackTargetRequest'; -export * from './RangeOptions'; -export * from './RangeResponse'; -export * from './RatingOptions'; -export * from './RatingResponse'; -export * from './SelectionOptions'; -export * from './SelectionResponse'; -export * from './SubmitFeedbackPromptResponseRequest'; -export * from './TextOptions'; -export * from './TextResponse'; diff --git a/codegen/Cargo.toml b/codegen/Cargo.toml new file mode 100644 index 00000000..2805638e --- /dev/null +++ b/codegen/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "feedback_fusion_codegen" +version = "0.1.0" +edition = "2021" + +[lib] +proc-macro = true + +[dependencies] +syn = "2.0.60" +quote = "1.0.36" diff --git a/src/prelude.rs b/codegen/src/lib.rs similarity index 59% rename from src/prelude.rs rename to codegen/src/lib.rs index 8e4a41d4..3f5f529d 100644 --- a/src/prelude.rs +++ b/codegen/src/lib.rs @@ -20,33 +20,24 @@ //DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -pub use crate::{ - config::*, - database::{DatabaseConfiguration, DatabaseConnection}, - database_request, - error::*, - impl_select_page_wrapper, - routes::{oidc::*, *}, - state::FeedbackFusionState, -}; -pub use axum::{ - extract::{Json, Query, State}, - routing::*, - Router, -}; -pub use derivative::Derivative; -pub use getset::{Getters, MutGetters, Setters}; -pub use lazy_static::lazy_static; -pub use paste::paste; -pub use rbatis::{ - crud, impl_insert, impl_select, impl_select_page, impled, plugin::page::Page, py_sql, - rbdc::JsonV, IPageRequest, -}; -pub use serde::{Deserialize, Serialize}; -pub use tracing::{debug, error, info, info_span, warn}; -pub use typed_builder::TypedBuilder; -pub use utoipa::{IntoParams, ToSchema}; -pub use validator::Validate; - -#[cfg(feature = "bindings")] -pub use ts_rs::TS; +use proc_macro::TokenStream; +use syn::{parse_macro_input, DeriveInput}; + +#[proc_macro_derive(IntoPageRequest)] +pub fn into_page_request_derive(input: TokenStream) -> TokenStream { + let input: DeriveInput = parse_macro_input!(input as DeriveInput); + let ident = &input.ident; + + let expanded = quote::quote! { + impl crate::IntoPageRequest for #ident { + fn into_page_request(&self) -> rbatis::plugin::page::PageRequest { + let page_size = if self.page_size > 0 { self.page_size as u64 } else { 20 }; + let page = if self.page_token > 0 { self.page_token as u64 } else { 1 }; + + rbatis::plugin::page::PageRequest::new(page, page_size) + } + } + }; + + expanded.into() +} diff --git a/common/Cargo.toml b/common/Cargo.toml new file mode 100644 index 00000000..1ded16f4 --- /dev/null +++ b/common/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "feedback_fusion_common" +version = "0.1.0" +edition = "2021" + +[dependencies] +feedback_fusion_codegen = { path = "../codegen" } + +rbatis = "4.5.21" +tonic = "0.11.0" +prost = "0.12.4" +prost-types = "0.12.4" +validator = { version = "0.18.1", features = ["derive"] } + +[build-dependencies] +tonic-build = "0.11.0" diff --git a/common/build.rs b/common/build.rs new file mode 100644 index 00000000..cb7ec61b --- /dev/null +++ b/common/build.rs @@ -0,0 +1,81 @@ +//SPDX-FileCopyrightText: 2024 OneLiteFeatherNet +//SPDX-License-Identifier: MIT + +//MIT License + +// Copyright (c) 2024 OneLiteFeatherNet + +//Permission is hereby granted, free of charge, to any person obtaining a copy of this software and +//associated documentation files (the "Software"), to deal in the Software without restriction, +//including without limitation the rights to use, copy, modify, merge, publish, distribute, +//sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +//furnished to do so, subject to the following conditions: + +//The above copyright notice and this permission notice (including the next paragraph) shall be +//included in all copies or substantial portions of the Software. + +//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT +//NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +//NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +//DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +use std::path::PathBuf; + +fn main() -> Result<(), Box> { + let out_dir = PathBuf::from(std::env::var("OUT_DIR").unwrap()); + + tonic_build::configure() + .type_attribute("CreateTargetRequest", "#[derive(validator::Validate)]") + .field_attribute("CreateTargetRequest.name", "#[validate(length(max = 255))]") + .type_attribute("UpdateTargetRequest", "#[derive(validator::Validate)]") + .field_attribute("UpdateTargetRequest.name", "#[validate(length(max = 255))]") + .field_attribute( + "UpdateTargetRequest.description", + "#[validate(length(max = 255))]", + ) + .type_attribute("CreatePromptRequest", "#[derive(validator::Validate)]") + .field_attribute("CreatePromptRequest.title", "#[validate(length(max = 32))]") + .field_attribute( + "UpdatePromptRequest.description", + "#[validate(length(max = 255))]", + ) + .type_attribute("UpdatePromptRequest", "#[derive(validator::Validate)]") + .field_attribute("UpdatePromptRequest.title", "#[validate(length(max = 32))]") + .field_attribute( + "CreatePromptRequest.description", + "#[validate(length(max = 255))]", + ) + .type_attribute("CreateFieldRequest", "#[derive(validator::Validate)]") + .field_attribute("CreateFieldRequest.title", "#[validate(length(max = 32))]") + .field_attribute( + "CreateFieldRequest.description", + "#[validate(length(max = 255))]", + ) + .type_attribute("UpdateFieldRequest", "#[derive(validator::Validate)]") + .field_attribute("UpdateFieldRequest.title", "#[validate(length(max = 32))]") + .field_attribute( + "UpdateFieldRequest.description", + "#[validate(length(max = 255))]", + ) + .type_attribute( + "GetTargetsRequest", + "#[derive(feedback_fusion_codegen::IntoPageRequest)]", + ) + .type_attribute( + "GetPromptsRequest", + "#[derive(feedback_fusion_codegen::IntoPageRequest)]", + ) + .type_attribute( + "GetFieldsRequest", + "#[derive(feedback_fusion_codegen::IntoPageRequest)]", + ) + .type_attribute( + "GetResponsesRequest", + "#[derive(feedback_fusion_codegen::IntoPageRequest)]", + ) + .file_descriptor_set_path(out_dir.join("feedback-fusion-v1-descriptor.bin")) + .compile(&["../proto/feedback-fusion-v1.proto"], &["../proto"]) + .unwrap(); + Ok(()) +} diff --git a/common/src/lib.rs b/common/src/lib.rs new file mode 100644 index 00000000..c2191361 --- /dev/null +++ b/common/src/lib.rs @@ -0,0 +1,31 @@ +//SPDX-FileCopyrightText: 2024 OneLiteFeatherNet +//SPDX-License-Identifier: MIT + +//MIT License + +// Copyright (c) 2024 OneLiteFeatherNet + +//Permission is hereby granted, free of charge, to any person obtaining a copy of this software and +//associated documentation files (the "Software"), to deal in the Software without restriction, +//including without limitation the rights to use, copy, modify, merge, publish, distribute, +//sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +//furnished to do so, subject to the following conditions: + +//The above copyright notice and this permission notice (including the next paragraph) shall be +//included in all copies or substantial portions of the Software. + +//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT +//NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +//NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +//DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +pub mod proto { + tonic::include_proto!("feedback_fusion_v1"); + pub const FILE_DESCRIPTOR_SET: &[u8] = + tonic::include_file_descriptor_set!("feedback-fusion-v1-descriptor"); +} + +pub trait IntoPageRequest { + fn into_page_request(&self) -> rbatis::plugin::page::PageRequest; +} diff --git a/lib/core/.gitignore b/lib/core/.gitignore index a9180ed0..e1efa34a 100644 --- a/lib/core/.gitignore +++ b/lib/core/.gitignore @@ -130,3 +130,6 @@ dist .pnp. dist/ +src/google/ +src/feedback-fusion-v1.ts +src/feedback-fusion-v1.client.ts diff --git a/lib/core/package.json b/lib/core/package.json index a4552102..f9d9f9fb 100644 --- a/lib/core/package.json +++ b/lib/core/package.json @@ -2,8 +2,8 @@ "name": "@onelitefeathernet/feedback-fusion-core", "version": "0.0.0", "description": "Core lib containing the http client in order to interact with the feedback-fusion backend", - "main": "dist/lib/core/src/index.js", - "types": "dist/lib/core/src/index.d.ts", + "main": "dist/index.js", + "types": "dist/index.d.ts", "scripts": { "tsc": "tsc" }, @@ -12,12 +12,16 @@ ], "exports": { ".": { - "types": "./dist/lib/core/src/index.d.ts", - "default": "./dist/lib/core/src/index.js" + "types": "./dist/index.d.ts", + "default": "./dist/index.js" }, "./locales/*": { - "types": "./dist/lib/core/src/locales/*.d.ts", - "default": "./dist/lib/core/src/locales/*.js" + "types": "./dist/locales/*.d.ts", + "default": "./dist/locales/*.js" + }, + "./dist/google/protobuf/*": { + "types": "./dist/google/protobuf/*.d.ts", + "default": "./dist/google/protobuf/*.js" } }, "repository": { @@ -31,6 +35,11 @@ }, "homepage": "https://github.com/OneLiteFeatherNET/feedback-fusion#readme", "devDependencies": { + "@protobuf-ts/plugin": "^2.9.4", "typescript": "^5.3.3" + }, + "dependencies": { + "@protobuf-ts/runtime": "^2.9.4", + "@protobuf-ts/runtime-rpc": "^2.9.4" } } diff --git a/lib/core/pnpm-lock.yaml b/lib/core/pnpm-lock.yaml index 529952b9..e26ade2b 100644 --- a/lib/core/pnpm-lock.yaml +++ b/lib/core/pnpm-lock.yaml @@ -4,13 +4,61 @@ settings: autoInstallPeers: true excludeLinksFromLockfile: false +dependencies: + '@protobuf-ts/runtime': + specifier: ^2.9.4 + version: 2.9.4 + '@protobuf-ts/runtime-rpc': + specifier: ^2.9.4 + version: 2.9.4 + devDependencies: + '@protobuf-ts/plugin': + specifier: ^2.9.4 + version: 2.9.4 typescript: specifier: ^5.3.3 version: 5.4.5 packages: + /@protobuf-ts/plugin-framework@2.9.4: + resolution: {integrity: sha512-9nuX1kjdMliv+Pes8dQCKyVhjKgNNfwxVHg+tx3fLXSfZZRcUHMc1PMwB9/vTvc6gBKt9QGz5ERqSqZc0++E9A==} + dependencies: + '@protobuf-ts/runtime': 2.9.4 + typescript: 3.9.10 + dev: true + + /@protobuf-ts/plugin@2.9.4: + resolution: {integrity: sha512-Db5Laq5T3mc6ERZvhIhkj1rn57/p8gbWiCKxQWbZBBl20wMuqKoHbRw4tuD7FyXi+IkwTToaNVXymv5CY3E8Rw==} + hasBin: true + dependencies: + '@protobuf-ts/plugin-framework': 2.9.4 + '@protobuf-ts/protoc': 2.9.4 + '@protobuf-ts/runtime': 2.9.4 + '@protobuf-ts/runtime-rpc': 2.9.4 + typescript: 3.9.10 + dev: true + + /@protobuf-ts/protoc@2.9.4: + resolution: {integrity: sha512-hQX+nOhFtrA+YdAXsXEDrLoGJqXHpgv4+BueYF0S9hy/Jq0VRTVlJS1Etmf4qlMt/WdigEes5LOd/LDzui4GIQ==} + hasBin: true + dev: true + + /@protobuf-ts/runtime-rpc@2.9.4: + resolution: {integrity: sha512-y9L9JgnZxXFqH5vD4d7j9duWvIJ7AShyBRoNKJGhu9Q27qIbchfzli66H9RvrQNIFk5ER7z1Twe059WZGqERcA==} + dependencies: + '@protobuf-ts/runtime': 2.9.4 + + /@protobuf-ts/runtime@2.9.4: + resolution: {integrity: sha512-vHRFWtJJB/SiogWDF0ypoKfRIZ41Kq+G9cEFj6Qm1eQaAhJ1LDFvgZ7Ja4tb3iLOQhz0PaoPnnOijF1qmEqTxg==} + + /typescript@3.9.10: + resolution: {integrity: sha512-w6fIxVE/H1PkLKcCPsFqKE7Kv7QUwhU8qQY2MueZXWx5cPZdwFupLgKK3vntcK98BtNHZtAF4LA/yl2a7k8R6Q==} + engines: {node: '>=4.2.0'} + hasBin: true + dev: true + /typescript@5.4.5: resolution: {integrity: sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==} engines: {node: '>=14.17'} diff --git a/lib/core/src/config.ts b/lib/core/src/config.ts index 2647b85d..13cf8bc3 100644 --- a/lib/core/src/config.ts +++ b/lib/core/src/config.ts @@ -20,14 +20,9 @@ * SOFTWARE. */ -import { FeedbackFusionClient } from "./"; +import { PublicFeedbackFusionV1Client } from "./"; import en from "./locales/en"; -interface BaseConfig { - baseURL: string; - target: string; -} - interface LocaleData { locale: string; translation: Object[]; @@ -45,14 +40,16 @@ interface ThemeOptions { }; } -export interface FeedbackFusionConfigurationOptions extends BaseConfig { +export interface FeedbackFusionConfigurationOptions { + endpoint: string; locales?: LocaleData[]; defaultLocale?: string; defaultTheme?: string; themes?: ThemeOptions; } -export interface FeedbackFusionConfig extends BaseConfig { +export interface FeedbackFusionConfig { + endpoint: string; locales: { [key: string]: { translation: Object } }; defaultLocale: string; defaultTheme: string; @@ -102,5 +99,5 @@ export function patchConfig( export interface FeedbackFusionState { config: FeedbackFusionConfig; - client: FeedbackFusionClient; + client: PublicFeedbackFusionV1Client; } diff --git a/lib/core/src/index.ts b/lib/core/src/index.ts index 3d58a0de..556e746a 100644 --- a/lib/core/src/index.ts +++ b/lib/core/src/index.ts @@ -20,58 +20,6 @@ * SOFTWARE. */ -import { - FeedbackPromptResponse, - SubmitFeedbackPromptResponseRequest, - FeedbackPromptField, - Page, - FeedbackPrompt, -} from "../../../bindings"; - -export class FeedbackFusionClient { - public baseURL: string; - - public constructor(baseURL: string, target: String) { - this.baseURL = `${baseURL}/v1/target/${target}`; - } - - /** - * Submit a new response to the prompt - */ - public async submitResponse( - prompt: String, - responses: SubmitFeedbackPromptResponseRequest, - ): Promise { - return await fetch(`${this.baseURL}/prompt/${prompt}/response`, { - method: "POST", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify(responses), - }) - .then((response) => response.json() as Promise) - .then((response: FeedbackPromptResponse) => response); - // TODO: handle errors - } - - /** - * Fetch a specific prompt - */ - public async getPrompt(prompt: string): Promise { - return await fetch(`${this.baseURL}/prompt/${prompt}`) - .then((response) => response.json() as Promise) - .then((response: FeedbackPrompt) => response) - } - - /** - * Fetch a page of fields - */ - public async getFields(prompt: string, page = 1, page_size = 20): Promise> { - return await fetch(`${this.baseURL}/prompt/${prompt}/fetch?page=${page}&page_size=${page_size}`) - .then((response) => response.json() as Promise>) - .then((response: Page) => response) - } -} - +export * from "./feedback-fusion-v1"; +export * from "./feedback-fusion-v1.client"; export * from "./config"; - -// export bindings generated via ts-rs -export * from "../../../bindings"; diff --git a/lib/vue/docs/.vitepress/theme/index.ts b/lib/vue/docs/.vitepress/theme/index.ts index 68ecc8ce..55cf8a8c 100644 --- a/lib/vue/docs/.vitepress/theme/index.ts +++ b/lib/vue/docs/.vitepress/theme/index.ts @@ -1,177 +1,280 @@ import DefaultTheme from "vitepress/theme"; import { FeedbackFusion } from "../../../src/"; -import fetchMock from "fetch-mock"; import en from "@onelitefeathernet/feedback-fusion-core/locales/en"; +import { http, HttpResponse } from "msw"; +import { setupWorker } from "msw/browser"; +import { + CheckboxStyle, + FieldPage, + FieldType, + Prompt, +} from "@onelitefeathernet/feedback-fusion-core"; +import { Timestamp } from "@onelitefeathernet/feedback-fusion-core/dist/google/protobuf/timestamp"; +import { + BinaryWriteOptions, + BinaryWriter, + IBinaryWriter, +} from "@protobuf-ts/runtime"; -fetchMock - .get("http://mock/v1/target/target/prompt/prompt", { +// https://lucas-levin.com/code/blog/mocking-grpc-web-requests-for-integration-testing +function createGrpcResponse( + data: Message, + encode: ( + message: Message, + writer: IBinaryWriter, + options: BinaryWriteOptions, + ) => IBinaryWriter, +) { + const encoded = encode(data, new BinaryWriter(), { + writeUnknownFields: false, + writerFactory: () => new BinaryWriter(), + }).finish(); + // create the data length bytes - there is probably a more concise way, but this works + const dataLengthBytes = new Uint8Array( + // @ts-ignore + new Uint32Array([encoded.byteLength]).buffer, + ); + dataLengthBytes.reverse(); + // @ts-ignore + const dataFrame = new Uint8Array(encoded.byteLength + 5); + dataFrame.set([0x00], 0); // set the magic byte 0x00 to identify the data frame + dataFrame.set(dataLengthBytes, 1); // set the length bytes + dataFrame.set(encoded, 5); // set the actual data + + // you can add mock errors by tweaking the trailers string with different status codes/messages + const trailersString = `grpc-status: 0\r\ngrpc-message: `; + const encoder = new TextEncoder(); + const trailers = encoder.encode(trailersString); + const trailersLengthBytes = new Uint8Array( + new Uint32Array([trailers.byteLength]).buffer, + ); + trailersLengthBytes.reverse(); + const trailersFrame = new Uint8Array(trailers.byteLength + 5); + trailersFrame.set([0x80], 0); // magic byte for trailers is 0x80 + trailersFrame.set(trailersLengthBytes, 1); + trailersFrame.set(trailers, 5); + + // create the final body by combining the data frame and trailers frame + const body = new Uint8Array(dataFrame.byteLength + trailersFrame.byteLength); + body.set(dataFrame, 0); + body.set(trailersFrame, dataFrame.byteLength); + + return HttpResponse.arrayBuffer(body.buffer, { status: 200, headers: { - "Content-Type": "application/json", + "content-type": "application/grpc-web+proto", }, - body: JSON.stringify({ - "id": "prompt", - "target": "target", - "title": "Mocked Prompt", - "active": true, - "updated_at": new Date(), - "created_at": new Date(), - }), }); +} -fetchMock - .get("begin:http://mock/v1/target/target/prompt/prompt/fetch", { - status: 200, - headers: { - "Content-Type": "application/json", +const handlers = [ + http.post( + "http://mock.mock/feedback_fusion_v1.PublicFeedbackFusionV1/GetPrompt", + () => { + return createGrpcResponse( + { + id: "prompt", + target: "target", + description: "Description", + title: "Mocked Prompt", + active: true, + updatedAt: Timestamp.now(), + createdAt: Timestamp.now(), + }, + Prompt.internalBinaryWrite, + ); }, - body: JSON.stringify( - { - "page_no": 1, - "total": 3, - "records": [ - { - "id": "text1", - "prompt": "prompt", - "title": "Text1", - "type": "text", - "description": "description", - "options": { - "placeholder": "placeholder", - "lines": 1 + ), + + http.post( + "http://mock.mock/feedback_fusion_v1.PublicFeedbackFusionV1/GetActiveFields", + () => { + return createGrpcResponse( + { + "pageToken": 1, + "pageSize": 10, + "nextPageToken": 2, + "total": 3, + "fields": [ + { + "id": "text1", + "prompt": "prompt", + "title": "Text1", + "fieldType": FieldType.TEXT, + "description": "description", + "options": { + "oneofKind": "text", + "text": { + "placeholder": "placeholder", + "lines": 1, + }, + }, + "updatedAt": Timestamp.now(), + "createdAt": Timestamp.now(), }, - "updated_at": new Date(), - "created_at": new Date(), - }, - { - "id": "textarea", - "prompt": "prompt", - "title": "Textarea", - "type": "text", - "description": "description", - "options": { - "placeholder": "placeholder", - "lines": 3, + { + "id": "textarea", + "prompt": "prompt", + "title": "Textarea", + "fieldType": FieldType.TEXT, + "description": "description", + "options": { + "oneofKind": "text", + "text": { + "placeholder": "placeholder", + "lines": 3, + }, + }, + "updatedAt": Timestamp.now(), + "createdAt": Timestamp.now(), }, - "updated_at": new Date(), - "created_at": new Date(), - }, - { - "id": "rating1", - "prompt": "prompt", - "title": "Rating1", - "type": "rating", - "description": "description", - "options": { - "max": 5, + { + "id": "rating1", + "prompt": "prompt", + "title": "Rating1", + "fieldType": FieldType.RATING, + "description": "description", + "options": { + "oneofKind": "rating", + "rating": { + "max": 5, + }, + }, + "updatedAt": Timestamp.now(), + "createdAt": Timestamp.now(), }, - "updated_at": new Date(), - "created_at": new Date(), - }, - { - "id": "text2", - "prompt": "prompt", - "title": "Text2", - "type": "text", - "description": "description", - "options": { - "placeholder": "placeholder", - "lines": 1, + { + "id": "text2", + "prompt": "prompt", + "title": "Text2", + "fieldType": FieldType.TEXT, + "description": "description", + "options": { + "oneofKind": "text", + "text": { + "placeholder": "placeholder", + "lines": 1, + }, + }, + "updatedAt": Timestamp.now(), + "createdAt": Timestamp.now(), }, - "updated_at": new Date(), - "created_at": new Date(), - }, - { - "id": "checkbox", - "prompt": "prompt", - "type": "checkbox", - "title": "Checkbox", - "description": "description", - "options": { - "defaultState": true, - "style": "checkbox", + { + "id": "checkbox", + "prompt": "prompt", + "fieldType": FieldType.CHECKBOX, + "title": "Checkbox", + "description": "description", + "options": { + "oneofKind": "checkbox", + checkbox: { + "defaultState": true, + "style": CheckboxStyle.NORMAL, + }, + }, + "updatedAt": Timestamp.now(), + "createdAt": Timestamp.now(), }, - "updated_at": new Date(), - "created_at": new Date(), - }, - { - "id": "switch", - "prompt": "prompt", - "type": "checkbox", - "title": "Switch", - "description": "description", - "options": { - "defaultState": false, - "style": "switch", + { + "id": "switch", + "prompt": "prompt", + "fieldType": FieldType.CHECKBOX, + "title": "Switch", + "description": "description", + "options": { + "oneofKind": "checkbox", + checkbox: { + "defaultState": true, + "style": CheckboxStyle.SWITCH, + }, + }, + "updatedAt": Timestamp.now(), + "createdAt": Timestamp.now(), }, - "updated_at": new Date(), - "created_at": new Date(), - }, - { - "id": "selection", - "prompt": "prompt", - "title": "Selection", - "type": "selection", - "description": "description", - "options": { - "values": ["foo", "bar"], - "combobox": false, + { + "id": "selection", + "prompt": "prompt", + "title": "Selection", + "fieldType": FieldType.SELECTION, + "description": "description", + "options": { + "oneofKind": "selection", + "selection": { + "values": ["foo", "bar"], + "combobox": false, + "multiple": true, + }, + }, + "updatedAt": Timestamp.now(), + "createdAt": Timestamp.now(), }, - "updated_at": new Date(), - "created_at": new Date(), - }, - { - "id": "combobox", - "title": "Combobox", - "prompt": "prompt", - "type": "selection", - "description": "description", - "options": { - "values": ["foo", "bar"], - "combobox": true, + { + "id": "combobox", + "title": "Combobox", + "prompt": "prompt", + "fieldType": FieldType.SELECTION, + "description": "description", + "options": { + "oneofKind": "selection", + "selection": { + "values": ["foo", "bar"], + "combobox": true, + "multiple": true, + }, + }, + "updatedAt": Timestamp.now(), + "createdAt": Timestamp.now(), }, - "updated_at": new Date(), - "created_at": new Date(), - }, - { - "id": "range", - "title": "Range", - "prompt": "prompt", - "type": "range", - "options": { - "min": 1, - "max": 10, + { + "id": "range", + "title": "Range", + "prompt": "prompt", + "fieldType": FieldType.RANGE, + "options": { + "oneofKind": "range", + "range": { + "min": 1, + "max": 10, + }, + }, + "updatedAt": Timestamp.now(), + "createdAt": Timestamp.now(), }, - "updated_at": new Date(), - "created_at": new Date(), - }, - { - "id": "number", - "prompt": "prompt", - "title": "Number", - "type": "number", - "description": "description", - "options": { - "min": 1, - "max": 10, - "placeholder": "placeholder", + { + "id": "number", + "prompt": "prompt", + "title": "Number", + "fieldType": FieldType.NUMBER, + "description": "description", + "options": { + "oneofKind": "number", + "number": { + "min": 1, + "max": 10, + "placeholder": "placeholder", + }, + }, + "updatedAt": Timestamp.now(), + "createdAt": Timestamp.now(), }, - "updated_at": new Date(), - "created_at": new Date(), - }, - ], - }, - ), - }); + ], + }, + FieldPage.internalBinaryWrite, + ); + }, + ), +]; +const worker = setupWorker(...handlers); +await worker.start(); export default { ...DefaultTheme, enhanceApp({ app }) { app.use(FeedbackFusion, { locales: [en], - baseURL: "http://mock", + endpoint: "http://mock.mock", target: "target", }); }, diff --git a/lib/vue/docs/mockServiceWorker.js b/lib/vue/docs/mockServiceWorker.js new file mode 100644 index 00000000..e891a685 --- /dev/null +++ b/lib/vue/docs/mockServiceWorker.js @@ -0,0 +1,284 @@ +/* eslint-disable */ +/* tslint:disable */ + +/** + * Mock Service Worker. + * @see https://github.com/mswjs/msw + * - Please do NOT modify this file. + * - Please do NOT serve this file on production. + */ + +const PACKAGE_VERSION = '2.2.14' +const INTEGRITY_CHECKSUM = '26357c79639bfa20d64c0efca2a87423' +const IS_MOCKED_RESPONSE = Symbol('isMockedResponse') +const activeClientIds = new Set() + +self.addEventListener('install', function () { + self.skipWaiting() +}) + +self.addEventListener('activate', function (event) { + event.waitUntil(self.clients.claim()) +}) + +self.addEventListener('message', async function (event) { + const clientId = event.source.id + + if (!clientId || !self.clients) { + return + } + + const client = await self.clients.get(clientId) + + if (!client) { + return + } + + const allClients = await self.clients.matchAll({ + type: 'window', + }) + + switch (event.data) { + case 'KEEPALIVE_REQUEST': { + sendToClient(client, { + type: 'KEEPALIVE_RESPONSE', + }) + break + } + + case 'INTEGRITY_CHECK_REQUEST': { + sendToClient(client, { + type: 'INTEGRITY_CHECK_RESPONSE', + payload: { + packageVersion: PACKAGE_VERSION, + checksum: INTEGRITY_CHECKSUM, + }, + }) + break + } + + case 'MOCK_ACTIVATE': { + activeClientIds.add(clientId) + + sendToClient(client, { + type: 'MOCKING_ENABLED', + payload: true, + }) + break + } + + case 'MOCK_DEACTIVATE': { + activeClientIds.delete(clientId) + break + } + + case 'CLIENT_CLOSED': { + activeClientIds.delete(clientId) + + const remainingClients = allClients.filter((client) => { + return client.id !== clientId + }) + + // Unregister itself when there are no more clients + if (remainingClients.length === 0) { + self.registration.unregister() + } + + break + } + } +}) + +self.addEventListener('fetch', function (event) { + const { request } = event + + // Bypass navigation requests. + if (request.mode === 'navigate') { + return + } + + // Opening the DevTools triggers the "only-if-cached" request + // that cannot be handled by the worker. Bypass such requests. + if (request.cache === 'only-if-cached' && request.mode !== 'same-origin') { + return + } + + // Bypass all requests when there are no active clients. + // Prevents the self-unregistered worked from handling requests + // after it's been deleted (still remains active until the next reload). + if (activeClientIds.size === 0) { + return + } + + // Generate unique request ID. + const requestId = crypto.randomUUID() + event.respondWith(handleRequest(event, requestId)) +}) + +async function handleRequest(event, requestId) { + const client = await resolveMainClient(event) + const response = await getResponse(event, client, requestId) + + // Send back the response clone for the "response:*" life-cycle events. + // Ensure MSW is active and ready to handle the message, otherwise + // this message will pend indefinitely. + if (client && activeClientIds.has(client.id)) { + ;(async function () { + const responseClone = response.clone() + + sendToClient( + client, + { + type: 'RESPONSE', + payload: { + requestId, + isMockedResponse: IS_MOCKED_RESPONSE in response, + type: responseClone.type, + status: responseClone.status, + statusText: responseClone.statusText, + body: responseClone.body, + headers: Object.fromEntries(responseClone.headers.entries()), + }, + }, + [responseClone.body], + ) + })() + } + + return response +} + +// Resolve the main client for the given event. +// Client that issues a request doesn't necessarily equal the client +// that registered the worker. It's with the latter the worker should +// communicate with during the response resolving phase. +async function resolveMainClient(event) { + const client = await self.clients.get(event.clientId) + + if (client?.frameType === 'top-level') { + return client + } + + const allClients = await self.clients.matchAll({ + type: 'window', + }) + + return allClients + .filter((client) => { + // Get only those clients that are currently visible. + return client.visibilityState === 'visible' + }) + .find((client) => { + // Find the client ID that's recorded in the + // set of clients that have registered the worker. + return activeClientIds.has(client.id) + }) +} + +async function getResponse(event, client, requestId) { + const { request } = event + + // Clone the request because it might've been already used + // (i.e. its body has been read and sent to the client). + const requestClone = request.clone() + + function passthrough() { + const headers = Object.fromEntries(requestClone.headers.entries()) + + // Remove internal MSW request header so the passthrough request + // complies with any potential CORS preflight checks on the server. + // Some servers forbid unknown request headers. + delete headers['x-msw-intention'] + + return fetch(requestClone, { headers }) + } + + // Bypass mocking when the client is not active. + if (!client) { + return passthrough() + } + + // Bypass initial page load requests (i.e. static assets). + // The absence of the immediate/parent client in the map of the active clients + // means that MSW hasn't dispatched the "MOCK_ACTIVATE" event yet + // and is not ready to handle requests. + if (!activeClientIds.has(client.id)) { + return passthrough() + } + + // Notify the client that a request has been intercepted. + const requestBuffer = await request.arrayBuffer() + const clientMessage = await sendToClient( + client, + { + type: 'REQUEST', + payload: { + id: requestId, + url: request.url, + mode: request.mode, + method: request.method, + headers: Object.fromEntries(request.headers.entries()), + cache: request.cache, + credentials: request.credentials, + destination: request.destination, + integrity: request.integrity, + redirect: request.redirect, + referrer: request.referrer, + referrerPolicy: request.referrerPolicy, + body: requestBuffer, + keepalive: request.keepalive, + }, + }, + [requestBuffer], + ) + + switch (clientMessage.type) { + case 'MOCK_RESPONSE': { + return respondWithMock(clientMessage.data) + } + + case 'PASSTHROUGH': { + return passthrough() + } + } + + return passthrough() +} + +function sendToClient(client, message, transferrables = []) { + return new Promise((resolve, reject) => { + const channel = new MessageChannel() + + channel.port1.onmessage = (event) => { + if (event.data && event.data.error) { + return reject(event.data.error) + } + + resolve(event.data) + } + + client.postMessage( + message, + [channel.port2].concat(transferrables.filter(Boolean)), + ) + }) +} + +async function respondWithMock(response) { + // Setting response status code to 0 is a no-op. + // However, when responding with a "Response.error()", the produced Response + // instance will have status code set to 0. Since it's not possible to create + // a Response instance with status code 0, handle that use-case separately. + if (response.status === 0) { + return Response.error() + } + + const mockedResponse = new Response(response.body, response) + + Reflect.defineProperty(mockedResponse, IS_MOCKED_RESPONSE, { + value: true, + enumerable: true, + }) + + return mockedResponse +} diff --git a/lib/vue/package.json b/lib/vue/package.json index 4a8f7337..7eba22e1 100644 --- a/lib/vue/package.json +++ b/lib/vue/package.json @@ -10,17 +10,24 @@ }, "dependencies": { "@onelitefeathernet/feedback-fusion-core": "../core", + "@protobuf-ts/grpcweb-transport": "^2.9.4", + "@protobuf-ts/runtime": "^2.9.4", "i18next": "^23.10.1", + "msw": "^2.2.14", "vue": "^3.3.11" }, "devDependencies": { "@types/node": "^20.11.25", "@vitejs/plugin-vue": "^4.5.2", - "fetch-mock": "^9.11.0", "sass": "^1.71.1", "typescript": "^5.2.2", "vite": "^5.0.8", "vitepress": "1.1.0", "vue-tsc": "^1.8.25" + }, + "msw": { + "workerDirectory": [ + "docs" + ] } -} +} \ No newline at end of file diff --git a/lib/vue/pnpm-lock.yaml b/lib/vue/pnpm-lock.yaml index 768ce12a..742b961f 100644 --- a/lib/vue/pnpm-lock.yaml +++ b/lib/vue/pnpm-lock.yaml @@ -8,9 +8,18 @@ dependencies: '@onelitefeathernet/feedback-fusion-core': specifier: ../core version: link:../core + '@protobuf-ts/grpcweb-transport': + specifier: ^2.9.4 + version: 2.9.4 + '@protobuf-ts/runtime': + specifier: ^2.9.4 + version: 2.9.4 i18next: specifier: ^23.10.1 version: 23.11.2 + msw: + specifier: ^2.2.14 + version: 2.2.14(typescript@5.4.5) vue: specifier: ^3.3.11 version: 3.4.22(typescript@5.4.5) @@ -22,9 +31,6 @@ devDependencies: '@vitejs/plugin-vue': specifier: ^4.5.2 version: 4.6.2(vite@5.2.8)(vue@3.4.22) - fetch-mock: - specifier: ^9.11.0 - version: 9.11.0 sass: specifier: ^1.71.1 version: 1.75.0 @@ -212,126 +218,6 @@ packages: '@algolia/requester-common': 4.23.3 dev: true - /@ampproject/remapping@2.3.0: - resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} - engines: {node: '>=6.0.0'} - dependencies: - '@jridgewell/gen-mapping': 0.3.5 - '@jridgewell/trace-mapping': 0.3.25 - dev: true - - /@babel/code-frame@7.23.5: - resolution: {integrity: sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/highlight': 7.23.4 - chalk: 2.4.2 - dev: true - - /@babel/compat-data@7.23.5: - resolution: {integrity: sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw==} - engines: {node: '>=6.9.0'} - dev: true - - /@babel/core@7.24.0: - resolution: {integrity: sha512-fQfkg0Gjkza3nf0c7/w6Xf34BW4YvzNfACRLmmb7XRLa6XHdR+K9AlJlxneFfWYf6uhOzuzZVTjF/8KfndZANw==} - engines: {node: '>=6.9.0'} - dependencies: - '@ampproject/remapping': 2.3.0 - '@babel/code-frame': 7.23.5 - '@babel/generator': 7.23.6 - '@babel/helper-compilation-targets': 7.23.6 - '@babel/helper-module-transforms': 7.23.3(@babel/core@7.24.0) - '@babel/helpers': 7.24.0 - '@babel/parser': 7.24.0 - '@babel/template': 7.24.0 - '@babel/traverse': 7.24.0 - '@babel/types': 7.24.0 - convert-source-map: 2.0.0 - debug: 4.3.4 - gensync: 1.0.0-beta.2 - json5: 2.2.3 - semver: 6.3.1 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/generator@7.23.6: - resolution: {integrity: sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.24.0 - '@jridgewell/gen-mapping': 0.3.5 - '@jridgewell/trace-mapping': 0.3.25 - jsesc: 2.5.2 - dev: true - - /@babel/helper-compilation-targets@7.23.6: - resolution: {integrity: sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/compat-data': 7.23.5 - '@babel/helper-validator-option': 7.23.5 - browserslist: 4.23.0 - lru-cache: 5.1.1 - semver: 6.3.1 - dev: true - - /@babel/helper-environment-visitor@7.22.20: - resolution: {integrity: sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==} - engines: {node: '>=6.9.0'} - dev: true - - /@babel/helper-function-name@7.23.0: - resolution: {integrity: sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/template': 7.24.0 - '@babel/types': 7.24.0 - dev: true - - /@babel/helper-hoist-variables@7.22.5: - resolution: {integrity: sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.24.0 - dev: true - - /@babel/helper-module-imports@7.22.15: - resolution: {integrity: sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.24.0 - dev: true - - /@babel/helper-module-transforms@7.23.3(@babel/core@7.24.0): - resolution: {integrity: sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.24.0 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-module-imports': 7.22.15 - '@babel/helper-simple-access': 7.22.5 - '@babel/helper-split-export-declaration': 7.22.6 - '@babel/helper-validator-identifier': 7.22.20 - dev: true - - /@babel/helper-simple-access@7.22.5: - resolution: {integrity: sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.24.0 - dev: true - - /@babel/helper-split-export-declaration@7.22.6: - resolution: {integrity: sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.24.0 - dev: true - /@babel/helper-string-parser@7.24.1: resolution: {integrity: sha512-2ofRCjnnA9y+wk8b9IAREroeUP02KHp431N2mhKniy2yKIDKpbrHv9eXwm8cBeWQYcJmzv5qKCu65P47eCF7CQ==} engines: {node: '>=6.9.0'} @@ -340,39 +226,6 @@ packages: resolution: {integrity: sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==} engines: {node: '>=6.9.0'} - /@babel/helper-validator-option@7.23.5: - resolution: {integrity: sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==} - engines: {node: '>=6.9.0'} - dev: true - - /@babel/helpers@7.24.0: - resolution: {integrity: sha512-ulDZdc0Aj5uLc5nETsa7EPx2L7rM0YJM8r7ck7U73AXi7qOV44IHHRAYZHY6iU1rr3C5N4NtTmMRUJP6kwCWeA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/template': 7.24.0 - '@babel/traverse': 7.24.0 - '@babel/types': 7.24.0 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/highlight@7.23.4: - resolution: {integrity: sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-validator-identifier': 7.22.20 - chalk: 2.4.2 - js-tokens: 4.0.0 - dev: true - - /@babel/parser@7.24.0: - resolution: {integrity: sha512-QuP/FxEAzMSjXygs8v4N9dvdXzEHN4W1oF3PxuWAtPo08UdM17u89RDMgjLn/mlc56iM0HlLmVkO/wgR+rDgHg==} - engines: {node: '>=6.0.0'} - hasBin: true - dependencies: - '@babel/types': 7.24.0 - dev: true - /@babel/parser@7.24.4: resolution: {integrity: sha512-zTvEBcghmeBma9QIGunWevvBAp4/Qu9Bdq+2k0Ot4fVMD6v3dsC9WOcRSKk7tRRyBM/53yKMJko9xOatGQAwSg==} engines: {node: '>=6.0.0'} @@ -380,13 +233,6 @@ packages: dependencies: '@babel/types': 7.24.0 - /@babel/runtime@7.24.0: - resolution: {integrity: sha512-Chk32uHMg6TnQdvw2e9IlqPpFX/6NLuK0Ys2PqLb7/gL5uFn9mXvK715FGLlOLQrcO4qIkNHkvPGktzzXexsFw==} - engines: {node: '>=6.9.0'} - dependencies: - regenerator-runtime: 0.14.1 - dev: true - /@babel/runtime@7.24.4: resolution: {integrity: sha512-dkxf7+hn8mFBwKjs9bvBlArzLVxVbS8usaPUDd5p2a9JCL9tB8OaOVN1isD4+Xyk4ns89/xeOmbQvgdK7IIVdA==} engines: {node: '>=6.9.0'} @@ -394,33 +240,6 @@ packages: regenerator-runtime: 0.14.1 dev: false - /@babel/template@7.24.0: - resolution: {integrity: sha512-Bkf2q8lMB0AFpX0NFEqSbx1OkTHf0f+0j82mkw+ZpzBnkk7e9Ql0891vlfgi+kHwOk8tQjiQHpqh4LaSa0fKEA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/code-frame': 7.23.5 - '@babel/parser': 7.24.0 - '@babel/types': 7.24.0 - dev: true - - /@babel/traverse@7.24.0: - resolution: {integrity: sha512-HfuJlI8qq3dEDmNU5ChzzpZRWq+oxCZQyMzIMEqLho+AQnhMnKQUzH6ydo3RBl/YjPCuk68Y6s0Gx0AeyULiWw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/code-frame': 7.23.5 - '@babel/generator': 7.23.6 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-function-name': 7.23.0 - '@babel/helper-hoist-variables': 7.22.5 - '@babel/helper-split-export-declaration': 7.22.6 - '@babel/parser': 7.24.0 - '@babel/types': 7.24.0 - debug: 4.3.4 - globals: 11.12.0 - transitivePeerDependencies: - - supports-color - dev: true - /@babel/types@7.24.0: resolution: {integrity: sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w==} engines: {node: '>=6.9.0'} @@ -429,6 +248,18 @@ packages: '@babel/helper-validator-identifier': 7.22.20 to-fast-properties: 2.0.0 + /@bundled-es-modules/cookie@2.0.0: + resolution: {integrity: sha512-Or6YHg/kamKHpxULAdSqhGqnWFneIXu1NKvvfBBzKGwpVsYuFIQ5aBPHDnnoR3ghW1nvSkALd+EF9iMtY7Vjxw==} + dependencies: + cookie: 0.5.0 + dev: false + + /@bundled-es-modules/statuses@1.0.1: + resolution: {integrity: sha512-yn7BklA5acgcBr+7w064fGV+SGIFySjCKpqjcWgBAIfrAkY+4GQTJJHQMeT3V/sgz23VTEVV8TtOmkvJAhFVfg==} + dependencies: + statuses: 2.0.1 + dev: false + /@docsearch/css@3.6.0: resolution: {integrity: sha512-+sbxb71sWre+PwDK7X2T8+bhS6clcVMLwBPznX45Qu6opJcgRjAp7gYSDzVFp187J+feSj5dNBN1mJoi6ckkUQ==} dev: true @@ -679,34 +510,94 @@ packages: dev: true optional: true - /@jridgewell/gen-mapping@0.3.5: - resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==} - engines: {node: '>=6.0.0'} + /@inquirer/confirm@3.1.6: + resolution: {integrity: sha512-Mj4TU29g6Uy+37UtpA8UpEOI2icBfpCwSW1QDtfx60wRhUy90s/kHPif2OXSSvuwDQT1lhAYRWUfkNf9Tecxvg==} + engines: {node: '>=18'} dependencies: - '@jridgewell/set-array': 1.2.1 - '@jridgewell/sourcemap-codec': 1.4.15 - '@jridgewell/trace-mapping': 0.3.25 - dev: true + '@inquirer/core': 8.1.0 + '@inquirer/type': 1.3.1 + dev: false - /@jridgewell/resolve-uri@3.1.2: - resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} - engines: {node: '>=6.0.0'} - dev: true + /@inquirer/core@8.1.0: + resolution: {integrity: sha512-kfx0SU9nWgGe1f03ao/uXc85SFH1v2w3vQVH7QDGjKxdtJz+7vPitFtG++BTyJMYyYgH8MpXigutcXJeiQwVRw==} + engines: {node: '>=18'} + dependencies: + '@inquirer/figures': 1.0.1 + '@inquirer/type': 1.3.1 + '@types/mute-stream': 0.0.4 + '@types/node': 20.12.7 + '@types/wrap-ansi': 3.0.0 + ansi-escapes: 4.3.2 + chalk: 4.1.2 + cli-spinners: 2.9.2 + cli-width: 4.1.0 + mute-stream: 1.0.0 + signal-exit: 4.1.0 + strip-ansi: 6.0.1 + wrap-ansi: 6.2.0 + dev: false - /@jridgewell/set-array@1.2.1: - resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} - engines: {node: '>=6.0.0'} - dev: true + /@inquirer/figures@1.0.1: + resolution: {integrity: sha512-mtup3wVKia3ZwULPHcbs4Mor8Voi+iIXEWD7wCNbIO6lYR62oPCTQyrddi5OMYVXHzeCSoneZwJuS8sBvlEwDw==} + engines: {node: '>=18'} + dev: false + + /@inquirer/type@1.3.1: + resolution: {integrity: sha512-Pe3PFccjPVJV1vtlfVvm9OnlbxqdnP5QcscFEFEnK5quChf1ufZtM0r8mR5ToWHMxZOh0s8o/qp9ANGRTo/DAw==} + engines: {node: '>=18'} + dev: false /@jridgewell/sourcemap-codec@1.4.15: resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} - /@jridgewell/trace-mapping@0.3.25: - resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} + /@mswjs/cookies@1.1.0: + resolution: {integrity: sha512-0ZcCVQxifZmhwNBoQIrystCb+2sWBY2Zw8lpfJBPCHGCA/HWqehITeCRVIv4VMy8MPlaHo2w2pTHFV2pFfqKPw==} + engines: {node: '>=18'} + dev: false + + /@mswjs/interceptors@0.26.15: + resolution: {integrity: sha512-HM47Lu1YFmnYHKMBynFfjCp0U/yRskHj/8QEJW0CBEPOlw8Gkmjfll+S9b8M7V5CNDw2/ciRxjjnWeaCiblSIQ==} + engines: {node: '>=18'} dependencies: - '@jridgewell/resolve-uri': 3.1.2 - '@jridgewell/sourcemap-codec': 1.4.15 - dev: true + '@open-draft/deferred-promise': 2.2.0 + '@open-draft/logger': 0.3.0 + '@open-draft/until': 2.1.0 + is-node-process: 1.2.0 + outvariant: 1.4.2 + strict-event-emitter: 0.5.1 + dev: false + + /@open-draft/deferred-promise@2.2.0: + resolution: {integrity: sha512-CecwLWx3rhxVQF6V4bAgPS5t+So2sTbPgAzafKkVizyi7tlwpcFpdFqq+wqF2OwNBmqFuu6tOyouTuxgpMfzmA==} + dev: false + + /@open-draft/logger@0.3.0: + resolution: {integrity: sha512-X2g45fzhxH238HKO4xbSr7+wBS8Fvw6ixhTDuvLd5mqh6bJJCFAPwU9mPDxbcrRtfxv4u5IHCEH77BmxvXmmxQ==} + dependencies: + is-node-process: 1.2.0 + outvariant: 1.4.2 + dev: false + + /@open-draft/until@2.1.0: + resolution: {integrity: sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg==} + dev: false + + /@protobuf-ts/grpcweb-transport@2.9.4: + resolution: {integrity: sha512-6aQgwPTgX6FkqWqmNts3uk8T/C5coJoH7U87zgaZY/Wo2EVa9SId5bXTM8uo4WR+CN8j9W4c9ij1yG13Hc3xUw==} + dependencies: + '@protobuf-ts/runtime': 2.9.4 + '@protobuf-ts/runtime-rpc': 2.9.4 + dev: false + + /@protobuf-ts/runtime-rpc@2.9.4: + resolution: {integrity: sha512-y9L9JgnZxXFqH5vD4d7j9duWvIJ7AShyBRoNKJGhu9Q27qIbchfzli66H9RvrQNIFk5ER7z1Twe059WZGqERcA==} + dependencies: + '@protobuf-ts/runtime': 2.9.4 + dev: false + + /@protobuf-ts/runtime@2.9.4: + resolution: {integrity: sha512-vHRFWtJJB/SiogWDF0ypoKfRIZ41Kq+G9cEFj6Qm1eQaAhJ1LDFvgZ7Ja4tb3iLOQhz0PaoPnnOijF1qmEqTxg==} + dev: false /@rollup/rollup-android-arm-eabi@4.14.3: resolution: {integrity: sha512-X9alQ3XM6I9IlSlmC8ddAvMSyG1WuHk5oUnXGw+yUBs3BFoTizmG1La/Gr8fVJvDWAq+zlYTZ9DBgrlKRVY06g==} @@ -846,6 +737,10 @@ packages: shiki: 1.3.0 dev: true + /@types/cookie@0.6.0: + resolution: {integrity: sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==} + dev: false + /@types/estree@1.0.5: resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} dev: true @@ -865,16 +760,29 @@ packages: resolution: {integrity: sha512-6L6VymKTzYSrEf4Nev4Xa1LCHKrlTlYCBMTlQKFuddo1CvQcE52I0mwfOJayueUC7MJuXOeHTcIU683lzd0cUA==} dev: true + /@types/mute-stream@0.0.4: + resolution: {integrity: sha512-CPM9nzrCPPJHQNA9keH9CVkVI+WR5kMa+7XEs5jcGQ0VoAGnLv242w8lIVgwAEfmE4oufJRaTc9PNLQl0ioAow==} + dependencies: + '@types/node': 20.12.7 + dev: false + /@types/node@20.12.7: resolution: {integrity: sha512-wq0cICSkRLVaf3UGLMGItu/PtdY7oaXaI/RVU+xliKVOtRna3PRY57ZDfztpDL0n11vfymMUnXv8QwYCO7L1wg==} dependencies: undici-types: 5.26.5 - dev: true + + /@types/statuses@2.0.5: + resolution: {integrity: sha512-jmIUGWrAiwu3dZpxntxieC+1n/5c3mjrImkmOSQ2NC5uP6cYO4aAZDdSmRcI5C1oiTmqlZGHC+/NmJrKogbP5A==} + dev: false /@types/web-bluetooth@0.0.20: resolution: {integrity: sha512-g9gZnnXVq7gM7v3tJCWV/qw7w+KeOlSHAhgF9RytFyifW6AF61hdT2ucrYhPq9hLs5JIryeupHV3qGk95dH9ow==} dev: true + /@types/wrap-ansi@3.0.0: + resolution: {integrity: sha512-ltIpx+kM7g/MLRZfkbL7EsCEjfzCcScLpkg37eXEtx5kmrAKBkTJwd1GIAjDSL8wTpM6Hzn5YO4pSb91BEwu1g==} + dev: false + /@vitejs/plugin-vue@4.6.2(vite@5.2.8)(vue@3.4.22): resolution: {integrity: sha512-kqf7SGFoG+80aZG6Pf+gsZIVvGSCKE98JbiWqcCV9cThtg91Jav0yvYFC9Zb+jKetNGF6ZKeoaxgZfND21fWKw==} engines: {node: ^14.18.0 || >=16.0.0} @@ -1121,12 +1029,24 @@ packages: '@algolia/transporter': 4.22.1 dev: true - /ansi-styles@3.2.1: - resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} - engines: {node: '>=4'} + /ansi-escapes@4.3.2: + resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} + engines: {node: '>=8'} dependencies: - color-convert: 1.9.3 - dev: true + type-fest: 0.21.3 + dev: false + + /ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + dev: false + + /ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + dependencies: + color-convert: 2.0.1 + dev: false /anymatch@3.1.3: resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} @@ -1158,29 +1078,13 @@ packages: fill-range: 7.0.1 dev: true - /browserslist@4.23.0: - resolution: {integrity: sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==} - engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} - hasBin: true - dependencies: - caniuse-lite: 1.0.30001596 - electron-to-chromium: 1.4.699 - node-releases: 2.0.14 - update-browserslist-db: 1.0.13(browserslist@4.23.0) - dev: true - - /caniuse-lite@1.0.30001596: - resolution: {integrity: sha512-zpkZ+kEr6We7w63ORkoJ2pOfBwBkY/bJrG/UZ90qNb45Isblu8wzDgevEOrRL1r9dWayHjYiiyCMEXPn4DweGQ==} - dev: true - - /chalk@2.4.2: - resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} - engines: {node: '>=4'} + /chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} dependencies: - ansi-styles: 3.2.1 - escape-string-regexp: 1.0.5 - supports-color: 5.5.0 - dev: true + ansi-styles: 4.3.0 + supports-color: 7.2.0 + dev: false /chokidar@3.6.0: resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} @@ -1197,28 +1101,44 @@ packages: fsevents: 2.3.3 dev: true - /color-convert@1.9.3: - resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} + /cli-spinners@2.9.2: + resolution: {integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==} + engines: {node: '>=6'} + dev: false + + /cli-width@4.1.0: + resolution: {integrity: sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==} + engines: {node: '>= 12'} + dev: false + + /cliui@8.0.1: + resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} + engines: {node: '>=12'} dependencies: - color-name: 1.1.3 - dev: true + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + dev: false - /color-name@1.1.3: - resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} - 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: false + + /color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + dev: false /computeds@0.0.1: resolution: {integrity: sha512-7CEBgcMjVmitjYo5q8JTJVra6X5mQ20uTThdK+0kR7UEaDrAWEQcRiBtWJzga4eRpP6afNwwLsX2SET2JhVB1Q==} dev: true - /convert-source-map@2.0.0: - resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} - dev: true - - /core-js@3.36.0: - resolution: {integrity: sha512-mt7+TUBbTFg5+GngsAxeKBTl5/VS0guFeJacYge9OmHb+m058UwwIm41SE9T4Den7ClatV57B6TYTuJ0CX1MAw==} - requiresBuild: true - dev: true + /cookie@0.5.0: + resolution: {integrity: sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==} + engines: {node: '>= 0.6'} + dev: false /csstype@3.1.3: resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} @@ -1227,21 +1147,9 @@ packages: resolution: {integrity: sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==} 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 - - /electron-to-chromium@1.4.699: - resolution: {integrity: sha512-I7q3BbQi6e4tJJN5CRcyvxhK0iJb34TV8eJQcgh+fR2fQ8miMgZcEInckCo1U9exDHbfz7DLDnFn8oqH/VcRKw==} - dev: true + /emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + dev: false /entities@4.5.0: resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} @@ -1281,39 +1189,11 @@ packages: /escalade@3.1.2: resolution: {integrity: sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==} engines: {node: '>=6'} - dev: true - - /escape-string-regexp@1.0.5: - resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} - engines: {node: '>=0.8.0'} - dev: true + dev: false /estree-walker@2.0.2: resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} - /fetch-mock@9.11.0: - resolution: {integrity: sha512-PG1XUv+x7iag5p/iNHD4/jdpxL9FtVSqRMUQhPab4hVDt80T1MH5ehzVrL2IdXO9Q2iBggArFvPqjUbHFuI58Q==} - engines: {node: '>=4.0.0'} - peerDependencies: - node-fetch: '*' - peerDependenciesMeta: - node-fetch: - optional: true - dependencies: - '@babel/core': 7.24.0 - '@babel/runtime': 7.24.0 - core-js: 3.36.0 - debug: 4.3.4 - glob-to-regexp: 0.4.1 - is-subset: 0.1.1 - lodash.isequal: 4.5.0 - path-to-regexp: 2.4.0 - querystring: 0.2.1 - whatwg-url: 6.5.0 - transitivePeerDependencies: - - supports-color - dev: true - /fill-range@7.0.1: resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} engines: {node: '>=8'} @@ -1335,10 +1215,10 @@ packages: dev: true optional: true - /gensync@1.0.0-beta.2: - resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} - engines: {node: '>=6.9.0'} - dev: true + /get-caller-file@2.0.5: + resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} + engines: {node: 6.* || 8.* || >= 10.*} + dev: false /glob-parent@5.1.2: resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} @@ -1347,25 +1227,25 @@ packages: is-glob: 4.0.3 dev: true - /glob-to-regexp@0.4.1: - resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==} - dev: true - - /globals@11.12.0: - resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} - engines: {node: '>=4'} - dev: true + /graphql@16.8.1: + resolution: {integrity: sha512-59LZHPdGZVh695Ud9lRzPBVTtlX9ZCV150Er2W43ro37wVof0ctenSaskPPjN7lVTIN8mSZt8PHUNKZuNQUuxw==} + engines: {node: ^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0} + dev: false - /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: false /he@1.2.0: resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} hasBin: true dev: true + /headers-polyfill@4.0.3: + resolution: {integrity: sha512-IScLbePpkvO846sIwOtOTDjutRMWdXdJmXdMvk6gCBHxFO8d+QKOQedyZSxFTTFYRSmlgSTDtXqqq4pcenBXLQ==} + dev: false + /hookable@5.5.3: resolution: {integrity: sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==} dev: true @@ -1392,6 +1272,11 @@ packages: 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: false + /is-glob@4.0.3: resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} engines: {node: '>=0.10.0'} @@ -1399,45 +1284,15 @@ packages: is-extglob: 2.1.1 dev: true + /is-node-process@1.2.0: + resolution: {integrity: sha512-Vg4o6/fqPxIjtxgUH5QLJhwZ7gW5diGCVlXpuUfELC62CuxM1iHcRe51f2W1FDy04Ai4KJkagKjx3XaqyfRKXw==} + dev: false + /is-number@7.0.0: resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} engines: {node: '>=0.12.0'} dev: true - /is-subset@0.1.1: - resolution: {integrity: sha512-6Ybun0IkarhmEqxXCNw/C0bna6Zb/TkfUX9UbwJtK6ObwAVCxmAP308WWTHviM/zAqXk05cdhYsUsZeGQh99iw==} - dev: true - - /js-tokens@4.0.0: - resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} - dev: true - - /jsesc@2.5.2: - resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==} - engines: {node: '>=4'} - hasBin: true - dev: true - - /json5@2.2.3: - resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} - engines: {node: '>=6'} - hasBin: true - dev: true - - /lodash.isequal@4.5.0: - resolution: {integrity: sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==} - dev: true - - /lodash.sortby@4.7.0: - resolution: {integrity: sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==} - 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'} @@ -1470,35 +1325,67 @@ packages: resolution: {integrity: sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==} dev: true - /ms@2.1.2: - resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} - dev: true + /msw@2.2.14(typescript@5.4.5): + resolution: {integrity: sha512-64i8rNCa1xzDK8ZYsTrVMli05D687jty8+Th+PU5VTbJ2/4P7fkQFVyDQ6ZFT5FrNR8z2BHhbY47fKNvfHrumA==} + engines: {node: '>=18'} + hasBin: true + requiresBuild: true + peerDependencies: + typescript: '>= 4.7.x' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@bundled-es-modules/cookie': 2.0.0 + '@bundled-es-modules/statuses': 1.0.1 + '@inquirer/confirm': 3.1.6 + '@mswjs/cookies': 1.1.0 + '@mswjs/interceptors': 0.26.15 + '@open-draft/until': 2.1.0 + '@types/cookie': 0.6.0 + '@types/statuses': 2.0.5 + chalk: 4.1.2 + graphql: 16.8.1 + headers-polyfill: 4.0.3 + is-node-process: 1.2.0 + outvariant: 1.4.2 + path-to-regexp: 6.2.2 + strict-event-emitter: 0.5.1 + type-fest: 4.17.0 + typescript: 5.4.5 + yargs: 17.7.2 + dev: false /muggle-string@0.3.1: resolution: {integrity: sha512-ckmWDJjphvd/FvZawgygcUeQCxzvohjFO5RxTjj4eq8kw359gFF3E1brjfI+viLMxss5JrHTDRHZvu2/tuy0Qg==} dev: true + /mute-stream@1.0.0: + resolution: {integrity: sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + dev: false + /nanoid@3.3.7: resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true - /node-releases@2.0.14: - resolution: {integrity: sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==} - dev: true - /normalize-path@3.0.0: resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} engines: {node: '>=0.10.0'} dev: true + /outvariant@1.4.2: + resolution: {integrity: sha512-Ou3dJ6bA/UJ5GVHxah4LnqDwZRwAmWxrG3wtrHrbGnP4RnLCtA64A4F+ae7Y8ww660JaddSoArUR5HjipWSHAQ==} + dev: false + /path-browserify@1.0.1: resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==} dev: true - /path-to-regexp@2.4.0: - resolution: {integrity: sha512-G6zHoVqC6GGTQkZwF4lkuEyMbVOjoBKAEybQUypI1WTkqinCOrq2x6U2+phkJ1XsEMTy4LjtwPI7HW+NVrRR2w==} - dev: true + /path-to-regexp@6.2.2: + resolution: {integrity: sha512-GQX3SSMokngb36+whdpRXE+3f9V8UzyAorlYvOGx87ufGHehNTn5lCxrKtLyZ4Yl/wEKnNnr98ZzOwwDZV5ogw==} + dev: false /perfect-debounce@1.0.0: resolution: {integrity: sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==} @@ -1524,17 +1411,6 @@ packages: resolution: {integrity: sha512-gympg+T2Z1fG1unB8NH29yHJwnEaCH37Z32diPDku316OTnRPeMbiRV9kTrfZpocXjdfnWuFUl/Mj4BHaf6gnw==} dev: true - /punycode@2.3.1: - resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} - engines: {node: '>=6'} - dev: true - - /querystring@0.2.1: - resolution: {integrity: sha512-wkvS7mL/JMugcup3/rMitHmd9ecIGd2lhFhK9N3UUQ450h66d1r3Y9nvXzQAW1Lq+wyx61k/1pfKS5KuKiyEbg==} - engines: {node: '>=0.4.x'} - deprecated: The querystring API is considered Legacy. new code should use the URLSearchParams API instead. - dev: true - /readdirp@3.6.0: resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} engines: {node: '>=8.10.0'} @@ -1544,6 +1420,12 @@ packages: /regenerator-runtime@0.14.1: resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==} + dev: false + + /require-directory@2.1.1: + resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} + engines: {node: '>=0.10.0'} + dev: false /rfdc@1.3.1: resolution: {integrity: sha512-r5a3l5HzYlIC68TpmYKlxWjmOP6wiPJ1vWv2HeLhNsRZMrCkxeqxiHlQ21oXmQ4F3SiryXBHhAD7JZqvOJjFmg==} @@ -1589,11 +1471,6 @@ packages: resolution: {integrity: sha512-Orrsjf9trHHxFRuo9/rzm0KIWmgzE8RMlZMzuhZOJ01Rnz3D0YBAe+V6473t6/H6c7irs6Lt48brULAiRWb3Vw==} dev: true - /semver@6.3.1: - resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} - hasBin: true - dev: true - /semver@7.5.4: resolution: {integrity: sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==} engines: {node: '>=10'} @@ -1608,6 +1485,11 @@ packages: '@shikijs/core': 1.3.0 dev: true + /signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} + dev: false + /source-map-js@1.2.0: resolution: {integrity: sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==} engines: {node: '>=0.10.0'} @@ -1617,12 +1499,37 @@ packages: engines: {node: '>=0.10.0'} dev: true - /supports-color@5.5.0: - resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} - engines: {node: '>=4'} + /statuses@2.0.1: + resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} + engines: {node: '>= 0.8'} + dev: false + + /strict-event-emitter@0.5.1: + resolution: {integrity: sha512-vMgjE/GGEPEFnhFub6pa4FmJBRBVOLpIII2hvCZ8Kzb7K0hlHo7mQv6xYrBvCL2LtAIBwFUK8wvuJgTVSQ5MFQ==} + dev: false + + /string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} dependencies: - has-flag: 3.0.0 - dev: true + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + dev: false + + /strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + dependencies: + ansi-regex: 5.0.1 + dev: false + + /supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + dependencies: + has-flag: 4.0.0 + dev: false /tabbable@6.2.0: resolution: {integrity: sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==} @@ -1639,11 +1546,15 @@ packages: is-number: 7.0.0 dev: true - /tr46@1.0.1: - resolution: {integrity: sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==} - dependencies: - punycode: 2.3.1 - dev: true + /type-fest@0.21.3: + resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} + engines: {node: '>=10'} + dev: false + + /type-fest@4.17.0: + resolution: {integrity: sha512-9flrz1zkfLRH3jO3bLflmTxryzKMxVa7841VeMgBaNQGY6vH4RCcpN/sQLB7mQQYh1GZ5utT2deypMuCy4yicw==} + engines: {node: '>=16'} + dev: false /typescript@5.4.5: resolution: {integrity: sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==} @@ -1652,18 +1563,6 @@ packages: /undici-types@5.26.5: resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} - dev: true - - /update-browserslist-db@1.0.13(browserslist@4.23.0): - resolution: {integrity: sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==} - hasBin: true - peerDependencies: - browserslist: '>= 4.21.0' - dependencies: - browserslist: 4.23.0 - escalade: 3.1.2 - picocolors: 1.0.0 - dev: true /vite@5.2.8(@types/node@20.12.7)(sass@1.75.0): resolution: {integrity: sha512-OyZR+c1CE8yeHw5V5t59aXsUPPVTHMDjEZz8MgguLL/Q7NblxhZUlTu9xSPqlsUO/y+X7dlU05jdhvyycD55DA==} @@ -1806,22 +1705,47 @@ packages: '@vue/shared': 3.4.22 typescript: 5.4.5 - /webidl-conversions@4.0.2: - resolution: {integrity: sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==} - 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: false - /whatwg-url@6.5.0: - resolution: {integrity: sha512-rhRZRqx/TLJQWUpQ6bmrt2UV4f0HCQ463yQuONJqC6fO2VoEb1pTYddbe59SkYq87aoM5A3bdhMZiUiVws+fzQ==} + /wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} dependencies: - lodash.sortby: 4.7.0 - tr46: 1.0.1 - webidl-conversions: 4.0.2 - dev: true + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + dev: false - /yallist@3.1.1: - resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} - dev: true + /y18n@5.0.8: + resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} + engines: {node: '>=10'} + dev: false /yallist@4.0.0: resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} dev: true + + /yargs-parser@21.1.1: + resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} + engines: {node: '>=12'} + dev: false + + /yargs@17.7.2: + resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} + engines: {node: '>=12'} + dependencies: + cliui: 8.0.1 + escalade: 3.1.2 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 21.1.1 + dev: false diff --git a/lib/vue/src/components/Field.vue b/lib/vue/src/components/Field.vue index 0cf43452..53042d35 100644 --- a/lib/vue/src/components/Field.vue +++ b/lib/vue/src/components/Field.vue @@ -4,13 +4,13 @@ {{ props.title }} -