diff --git a/.decisions/4-Fido-Extension.md b/.decisions/4-Fido-Extension.md new file mode 100644 index 0000000..78a0bf0 --- /dev/null +++ b/.decisions/4-Fido-Extension.md @@ -0,0 +1,51 @@ +# Overview + +Deprecate ARC-31/Arbitrary Auth Message in favor of custom FIDO2 extension + +## Decisions + +- Remove connect module and endpoints +- Use FIDO2 Attestation/Assertions for device linking + +## Implementation + +```mermaid +sequenceDiagram + participant Website + participant Server + participant Wallet + Note over Website, Wallet: Link devices + Website->>Server: Subscribe to 'wss:link' + Website-->>Website: Display QR Connect Request ID + Wallet->>Website: Scan QR Code + Server-->>Wallet: Get Challenge/Options + Wallet->>Server: POST FIDO2 Credential + Liquid Auth Signature + Server-->>Server: Validate Signatures + Server-->>Website: HTTPOnly Session + Server->>Wallet: Ok Response + HTTPOnly Session + Server->>Website: Emit to `wss:link` client + Note over Website, Wallet: Signaling Channels + Website-->>Server: Subscribe to 'wss:offer-description' + Website-->>Server: Subscribe to 'wss:offer-candidate' + Wallet-->>Server: Subscribe to 'wss:answer-description' + Wallet-->>Server: Subscribe to 'wss:answer-candidate' + + Note over Website, Wallet: Peer Offer + Wallet-->>Wallet: On answer-description, set Remote SDP + Wallet-->>Wallet: On answer-candidate, add ICE Candidate + Wallet-->>Wallet: Create Peer Offer & DataChannel + Wallet-->>Server: Emit `wss:offer-description` + Wallet-->>Server: Emit `wss:offer-candidate` + + Note over Website, Wallet: Peer Answer + Website-->>Website: On offer-description, set Remote SDP and create Answer + Website-->>Website: On offer-candidate, add ICE Candidate + Website-->>Server: Emit `wss:answer-description` + Website-->>Server: Emit `wss:answer-candidate` + + Note over Website, Wallet: Data Channel + Website-->>Wallet: On DataChannel, Emit Messages + +``` + +*Note: It may be possible to handle signaling in a fully decentralized manner in the future. diff --git a/.decisions/README.md b/.decisions/README.md index 9687e1d..b07bf89 100644 --- a/.decisions/README.md +++ b/.decisions/README.md @@ -2,3 +2,5 @@ - [1. Service Authentication](1-Service-Authentication.md) - [2. Bidirectional-Communications](2-Bidirectional-Communication.md) +- [3. Peer-to-Peer-Signaling](3-Peer-to-Peer-Signaling.md) +- [4. Fido-Extension](4-Fido-Extension.md) diff --git a/.dockerignore b/.dockerignore index 3c3629e..9fea4e7 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1 +1,3 @@ node_modules +android +clients/liquid-auth-client-kt diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index e00b40c..b7816b2 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -13,6 +13,7 @@ jobs: uses: actions/setup-node@v1 with: node-version: ${{ matrix.node-version }} + cache: 'npm' - name: Install Dependencies run: npm install - name: Run Build diff --git a/.github/workflows/docker-release.yml b/.github/workflows/docker-release.yml new file mode 100644 index 0000000..f0bbf42 --- /dev/null +++ b/.github/workflows/docker-release.yml @@ -0,0 +1,57 @@ +# See: https://docs.docker.com/build/ci/github-actions/manage-tags-labels/ +name: Docker Image CI + +on: + push: + branches: ["main", "develop"] + tags: + - "v*.*.*" +env: + # Use docker.io for Docker Hub if empty + REGISTRY: ghcr.io + # github.repository as / + IMAGE_NAME: ${{ github.repository }} +jobs: + build: + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + steps: + - # Checkout the repo + name: Checkout + uses: actions/checkout@v3 + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + - # This can be Docker Hub, ECR, or any other registry. Using GHCR for now. + name: Container Registry Login + if: github.event_name != 'pull_request' + uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.repository_owner }} + password: ${{ secrets.GITHUB_TOKEN }} + - # Tag and name the image + name: Docker meta + id: meta + uses: docker/metadata-action@v5 + with: + # list of Docker images to use as base name for tags + images: | + ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + # generate Docker tags based on the following events/attributes + tags: | + type=ref,event=branch + type=semver,pattern={{version}} + - # Build and push + name: Build and push + uses: docker/build-push-action@v5 + with: + context: . + push: ${{ github.event_name != 'pull_request' }} + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=gha + cache-to: type=gha diff --git a/.gitignore b/.gitignore index 08b11ce..91811f2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,25 @@ +# Project Files +docker-compose.override.yml swagger-codegen-cli.jar ngrok.yml - .data -.idea + +# Kotlin +*.iml +.gradle +/local.properties +/.idea/caches +/.idea/libraries +/.idea/modules.xml +/.idea/workspace.xml +/.idea/navEditor.xml +/.idea/assetWizardSettings.xml +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties # Logs logs diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..a9d7db9 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,10 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml +# GitHub Copilot persisted chat sessions +/copilot/chatSessions diff --git a/.idea/.name b/.idea/.name new file mode 100644 index 0000000..8181024 --- /dev/null +++ b/.idea/.name @@ -0,0 +1 @@ +foundation.algorand.liquid \ No newline at end of file diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml new file mode 100644 index 0000000..7dea630 --- /dev/null +++ b/.idea/codeStyles/Project.xml @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml new file mode 100644 index 0000000..79ee123 --- /dev/null +++ b/.idea/codeStyles/codeStyleConfig.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..c8f004d --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..1cd60d3 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 6422067..780b20d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -15,11 +15,7 @@ COPY --from=BUILDER ./package-lock.json ./package-lock.json # Client Files COPY --from=BUILDER ./clients ./clients # Service Files -COPY --from=BUILDER ./services/liquid-auth-api-js/assetlinks.json ./services/liquid-auth-api-js/assetlinks.json -COPY --from=BUILDER ./services/liquid-auth-api-js/dist ./services/liquid-auth-api-js/dist -COPY --from=BUILDER ./services/liquid-auth-api-js/bin ./services/liquid-auth-api-js/bin -COPY --from=BUILDER ./services/liquid-auth-api-js/.env.template ./services/liquid-auth-api-js/.env.template -COPY --from=BUILDER ./services/liquid-auth-api-js/package.json ./services/liquid-auth-api-js/package.json +COPY --from=BUILDER ./services/liquid-auth-api-js/ ./services/liquid-auth-api-js/ RUN npm ci --production diff --git a/README.md b/README.md index acd4cee..bcafea6 100644 --- a/README.md +++ b/README.md @@ -7,8 +7,8 @@ # Overview -This project holds the standard FIDO2 api endpoints and the Proof of Knowledge for Algorand specific private keys. -The api is a stateful session-based architecture with endpoint guards. +This project holds the standard FIDO2 api endpoints and the Proof of Knowledge for Algorand specific private keys. +The api is a stateful session-based architecture with endpoint guards. A user must prove ownership of a private key to associate PublicKeyCredentials ## Getting started @@ -64,6 +64,8 @@ tunnels: #### Update the Service's .docker.env file +Update the [.docekr.env](.env.docker) file with the following keys with the values from ngrok: + ```bash HOSTNAME= ORIGIN=https:// @@ -82,7 +84,7 @@ Navigate to the ngrok URL in your browser to test the FIDO2 feature. ## Using the app -#### Install the [Android client](https://github.com/awesome-algorand/android-authentication-client) to your device. +#### Install the [Android client](https://github.com/awesome-algorand/android-authentication-client/releases) to your device. ![Step-1.png](.docs%2FStep-1.png) diff --git a/client-gen.sh b/client-gen.sh deleted file mode 100755 index d32586d..0000000 --- a/client-gen.sh +++ /dev/null @@ -1,12 +0,0 @@ - - -CODEGEN=swagger-codegen-cli.jar -if [ -f $CODEGEN ]; then - echo "Codegen already exists" -else - echo "Downloading codegen" - wget https://repo1.maven.org/maven2/io/swagger/codegen/v3/swagger-codegen-cli/3.0.52/swagger-codegen-cli-3.0.52.jar -O swagger-codegen-cli.jar -fi - -java -jar swagger-codegen-cli.jar generate -i http://localhost:3000/api-json -l typescript-fetch -o clients/liquid-auth-client-js/src/client -java -jar swagger-codegen-cli.jar generate -i http://localhost:3000/api-json -l kotlin-client -o clients/liquid-auth-client-kotlin diff --git a/clients/liquid-auth-client-js/package.json b/clients/liquid-auth-client-js/package.json index cd5ab60..ff67089 100644 --- a/clients/liquid-auth-client-js/package.json +++ b/clients/liquid-auth-client-js/package.json @@ -33,23 +33,28 @@ "scripts": { "dev": "tsc --watch", "build": "tsc", - "build:docs": "typedoc --plugin typedoc-plugin-markdown --out docs src", + "build:docs": "typedoc --plugin typedoc-plugin-markdown --out docs src src/client", "lint": "eslint --fix src", + "test:ts": "node --import tsx --test ./src/client/*.spec.ts", "test": "tsc && node --test ./tests/*.spec.js", "test:cov": "tsc && c8 node --test ./tests/*.spec.js" }, "author": "", "license": "MIT", "devDependencies": { + "@swc/register": "^0.1.10", + "@types/chai": "^4.3.14", "@types/qrcode": "^1.5.5", "@typescript-eslint/eslint-plugin": "^6.21.0", "@typescript-eslint/parser": "^7.6.0", "algosdk": "^2.7.0", "c8": "^9.1.0", + "chai": "^5.1.0", "eslint": "^8.57.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-prettier": "^5.1.3", "eslint-plugin-tsdoc": "^0.2.17", + "tsx": "^4.7.2", "typedoc": "^0.25.13", "typedoc-plugin-markdown": "^4.0.0-next.55", "typescript": "^5.4.5" @@ -57,6 +62,7 @@ "dependencies": { "@liquid/core": "^1.0.0", "eventemitter3": "^5.0.1", + "isomorphic-fetch": "^3.0.0", "qr-code-styling": "^1.6.0-rc.1", "tweetnacl": "^1.0.3" } diff --git a/clients/liquid-auth-client-js/src/signal.ts b/clients/liquid-auth-client-js/src/signal.ts index 2324472..fb54b0a 100644 --- a/clients/liquid-auth-client-js/src/signal.ts +++ b/clients/liquid-auth-client-js/src/signal.ts @@ -165,19 +165,17 @@ export class SignalClient extends EventEmitter { throw new Error(REQUEST_IN_PROCESS_MESSAGE); return new Promise(async (resolve) => { + let candidatesBuffer = []; // Create Peer Connection this.peerClient = new RTCPeerConnection(config); globalThis.peerClient = this.peerClient; this.type = type === 'offer' ? 'answer' : 'offer'; // Wait for a link message await this.link(requestId); - this.socket.disconnect(); - this.socket.connect(); - console.log('linked!'); // Listen for Local Candidates this.peerClient.onicecandidate = (event) => { if (event.candidate) { - console.log(event.candidate); + this.emit(`${this.type}-candidate`, event.candidate.toJSON()); this.socket.emit(`${this.type}-candidate`, event.candidate.toJSON()); } }; @@ -185,16 +183,20 @@ export class SignalClient extends EventEmitter { this.socket.on( `${type}-candidate`, async (candidate: RTCIceCandidateInit) => { - await this.peerClient.addIceCandidate(new RTCIceCandidate(candidate)); + if ( + this.peerClient.remoteDescription && + this.peerClient.remoteDescription + ) { + this.emit(`${type}-candidate`, candidate); + await this.peerClient.addIceCandidate( + new RTCIceCandidate(candidate), + ); + } else { + candidatesBuffer.push(candidate); + } }, ); - this.peerClient.onicecandidate = (event) => { - if (event.candidate) { - this.socket.emit(`${this.type}-candidate`, event.candidate.toJSON()); - } - }; - // Listen for Remote DataChannel and Resolve this.peerClient.ondatachannel = (event) => { console.log(event); @@ -208,6 +210,18 @@ export class SignalClient extends EventEmitter { await this.peerClient.setRemoteDescription(sdp); const answer = await this.peerClient.createAnswer(); await this.peerClient.setLocalDescription(answer); + if (candidatesBuffer.length > 0) { + await Promise.all( + candidatesBuffer.map(async (candidate) => { + this.emit(`${type}-candidate`, candidate); + await this.peerClient.addIceCandidate( + new RTCIceCandidate(candidate), + ); + }), + ); + candidatesBuffer = []; + } + this.emit(`${this.type}-description`, answer.sdp); this.socket.emit(`${this.type}-description`, answer.sdp); } else { const localSdp = await this.peerClient.createOffer(); diff --git a/clients/liquid-auth-client-js/tests/connect.spec.js b/clients/liquid-auth-client-js/tests/connect.spec.js index 5dbd731..e3cf1e6 100644 --- a/clients/liquid-auth-client-js/tests/connect.spec.js +++ b/clients/liquid-auth-client-js/tests/connect.spec.js @@ -4,7 +4,7 @@ import algosdk from 'algosdk'; import nacl from "tweetnacl"; import { Message } from '../lib/connect.js'; -import { fromBase64Url } from "@liquid/core"; +import { fromBase64Url } from "@liquid/core/encoding"; const encoder = new TextEncoder; test("create instance", async () => { const msg = new Message("hello", "1234", 1234); diff --git a/package-lock.json b/package-lock.json index 0932abe..612bf4f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,33 +21,24 @@ "dependencies": { "@liquid/core": "^1.0.0", "eventemitter3": "^5.0.1", + "isomorphic-fetch": "^3.0.0", "qr-code-styling": "^1.6.0-rc.1", "tweetnacl": "^1.0.3" }, "devDependencies": { + "@swc/register": "^0.1.10", + "@types/chai": "^4.3.14", "@types/qrcode": "^1.5.5", "@typescript-eslint/eslint-plugin": "^6.21.0", "@typescript-eslint/parser": "^7.6.0", "algosdk": "^2.7.0", "c8": "^9.1.0", + "chai": "^5.1.0", "eslint": "^8.57.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-prettier": "^5.1.3", "eslint-plugin-tsdoc": "^0.2.17", - "typedoc": "^0.25.13", - "typedoc-plugin-markdown": "^4.0.0-next.55", - "typescript": "^5.4.5" - } - }, - "clients/liquid-auth-client-js/docs": { - "version": "0.0.1", - "extraneous": true, - "dependencies": { - "@astrojs/check": "^0.5.10", - "@astrojs/starlight": "^0.21.5", - "astro": "^4.3.5", - "sharp": "^0.32.5", - "starlight-typedoc": "^0.11.0", + "tsx": "^4.7.2", "typedoc": "^0.25.13", "typedoc-plugin-markdown": "^4.0.0-next.55", "typescript": "^5.4.5" @@ -55,8 +46,9 @@ }, "clients/liquid-auth-client-js/node_modules/@typescript-eslint/parser": { "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.6.0.tgz", + "integrity": "sha512-usPMPHcwX3ZoPWnBnhhorc14NJw9J4HpSXQX4urF2TPKG0au0XhJoZyX62fmvdHONUkmyUe74Hzm1//XA+BoYg==", "dev": true, - "license": "BSD-2-Clause", "dependencies": { "@typescript-eslint/scope-manager": "7.6.0", "@typescript-eslint/types": "7.6.0", @@ -82,8 +74,9 @@ }, "clients/liquid-auth-client-js/node_modules/@typescript-eslint/scope-manager": { "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.6.0.tgz", + "integrity": "sha512-ngttyfExA5PsHSx0rdFgnADMYQi+Zkeiv4/ZxGYUWd0nLs63Ha0ksmp8VMxAIC0wtCFxMos7Lt3PszJssG/E6w==", "dev": true, - "license": "MIT", "dependencies": { "@typescript-eslint/types": "7.6.0", "@typescript-eslint/visitor-keys": "7.6.0" @@ -98,8 +91,9 @@ }, "clients/liquid-auth-client-js/node_modules/@typescript-eslint/types": { "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.6.0.tgz", + "integrity": "sha512-h02rYQn8J+MureCvHVVzhl69/GAfQGPQZmOMjG1KfCl7o3HtMSlPaPUAPu6lLctXI5ySRGIYk94clD/AUMCUgQ==", "dev": true, - "license": "MIT", "engines": { "node": "^18.18.0 || >=20.0.0" }, @@ -110,8 +104,9 @@ }, "clients/liquid-auth-client-js/node_modules/@typescript-eslint/typescript-estree": { "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.6.0.tgz", + "integrity": "sha512-+7Y/GP9VuYibecrCQWSKgl3GvUM5cILRttpWtnAu8GNL9j11e4tbuGZmZjJ8ejnKYyBRb2ddGQ3rEFCq3QjMJw==", "dev": true, - "license": "BSD-2-Clause", "dependencies": { "@typescript-eslint/types": "7.6.0", "@typescript-eslint/visitor-keys": "7.6.0", @@ -137,8 +132,9 @@ }, "clients/liquid-auth-client-js/node_modules/@typescript-eslint/visitor-keys": { "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.6.0.tgz", + "integrity": "sha512-4eLB7t+LlNUmXzfOu1VAIAdkjbu5xNSerURS9X/S5TUKWFRpXRQZbmtPqgKmYx8bj3J0irtQXSiWAOY82v+cgw==", "dev": true, - "license": "MIT", "dependencies": { "@typescript-eslint/types": "7.6.0", "eslint-visitor-keys": "^3.4.3" @@ -153,16 +149,18 @@ }, "clients/liquid-auth-client-js/node_modules/brace-expansion": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, - "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } }, "clients/liquid-auth-client-js/node_modules/minimatch": { "version": "9.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", + "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", "dev": true, - "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, @@ -195,8 +193,9 @@ }, "clients/liquid-auth-core/node_modules/@typescript-eslint/parser": { "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.6.0.tgz", + "integrity": "sha512-usPMPHcwX3ZoPWnBnhhorc14NJw9J4HpSXQX4urF2TPKG0au0XhJoZyX62fmvdHONUkmyUe74Hzm1//XA+BoYg==", "dev": true, - "license": "BSD-2-Clause", "dependencies": { "@typescript-eslint/scope-manager": "7.6.0", "@typescript-eslint/types": "7.6.0", @@ -222,8 +221,9 @@ }, "clients/liquid-auth-core/node_modules/@typescript-eslint/scope-manager": { "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.6.0.tgz", + "integrity": "sha512-ngttyfExA5PsHSx0rdFgnADMYQi+Zkeiv4/ZxGYUWd0nLs63Ha0ksmp8VMxAIC0wtCFxMos7Lt3PszJssG/E6w==", "dev": true, - "license": "MIT", "dependencies": { "@typescript-eslint/types": "7.6.0", "@typescript-eslint/visitor-keys": "7.6.0" @@ -238,8 +238,9 @@ }, "clients/liquid-auth-core/node_modules/@typescript-eslint/types": { "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.6.0.tgz", + "integrity": "sha512-h02rYQn8J+MureCvHVVzhl69/GAfQGPQZmOMjG1KfCl7o3HtMSlPaPUAPu6lLctXI5ySRGIYk94clD/AUMCUgQ==", "dev": true, - "license": "MIT", "engines": { "node": "^18.18.0 || >=20.0.0" }, @@ -250,8 +251,9 @@ }, "clients/liquid-auth-core/node_modules/@typescript-eslint/typescript-estree": { "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.6.0.tgz", + "integrity": "sha512-+7Y/GP9VuYibecrCQWSKgl3GvUM5cILRttpWtnAu8GNL9j11e4tbuGZmZjJ8ejnKYyBRb2ddGQ3rEFCq3QjMJw==", "dev": true, - "license": "BSD-2-Clause", "dependencies": { "@typescript-eslint/types": "7.6.0", "@typescript-eslint/visitor-keys": "7.6.0", @@ -277,8 +279,9 @@ }, "clients/liquid-auth-core/node_modules/@typescript-eslint/visitor-keys": { "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.6.0.tgz", + "integrity": "sha512-4eLB7t+LlNUmXzfOu1VAIAdkjbu5xNSerURS9X/S5TUKWFRpXRQZbmtPqgKmYx8bj3J0irtQXSiWAOY82v+cgw==", "dev": true, - "license": "MIT", "dependencies": { "@typescript-eslint/types": "7.6.0", "eslint-visitor-keys": "^3.4.3" @@ -293,16 +296,18 @@ }, "clients/liquid-auth-core/node_modules/brace-expansion": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, - "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } }, "clients/liquid-auth-core/node_modules/minimatch": { "version": "9.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", + "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", "dev": true, - "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, @@ -440,8 +445,9 @@ }, "node_modules/@apideck/better-ajv-errors": { "version": "0.3.6", + "resolved": "https://registry.npmjs.org/@apideck/better-ajv-errors/-/better-ajv-errors-0.3.6.tgz", + "integrity": "sha512-P+ZygBLZtkp0qqOAJJVX4oX/sFo5JR3eBWwwuqHHhK0GIgQOKWrAfiAaWX0aArHkRWHMuggFEgAZNxVPwPZYaA==", "dev": true, - "license": "MIT", "dependencies": { "json-schema": "^0.4.0", "jsonpointer": "^5.0.0", @@ -455,40 +461,98 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.24.2", + "version": "7.22.13", "license": "MIT", "dependencies": { - "@babel/highlight": "^7.24.2", - "picocolors": "^1.0.0" + "@babel/highlight": "^7.22.13", + "chalk": "^2.4.2" }, "engines": { "node": ">=6.9.0" } }, + "node_modules/@babel/code-frame/node_modules/ansi-styles": { + "version": "3.2.1", + "license": "MIT", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/chalk": { + "version": "2.4.2", + "license": "MIT", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/color-convert": { + "version": "1.9.3", + "license": "MIT", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/code-frame/node_modules/color-name": { + "version": "1.1.3", + "license": "MIT" + }, + "node_modules/@babel/code-frame/node_modules/escape-string-regexp": { + "version": "1.0.5", + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@babel/code-frame/node_modules/has-flag": { + "version": "3.0.0", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/supports-color": { + "version": "5.5.0", + "license": "MIT", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/@babel/compat-data": { "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.5.tgz", + "integrity": "sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw==", "dev": true, - "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.24.4", + "version": "7.22.17", "dev": true, "license": "MIT", "dependencies": { "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.24.2", - "@babel/generator": "^7.24.4", - "@babel/helper-compilation-targets": "^7.23.6", - "@babel/helper-module-transforms": "^7.23.3", - "@babel/helpers": "^7.24.4", - "@babel/parser": "^7.24.4", - "@babel/template": "^7.24.0", - "@babel/traverse": "^7.24.1", - "@babel/types": "^7.24.0", - "convert-source-map": "^2.0.0", + "@babel/code-frame": "^7.22.13", + "@babel/generator": "^7.22.15", + "@babel/helper-compilation-targets": "^7.22.15", + "@babel/helper-module-transforms": "^7.22.17", + "@babel/helpers": "^7.22.15", + "@babel/parser": "^7.22.16", + "@babel/template": "^7.22.15", + "@babel/traverse": "^7.22.17", + "@babel/types": "^7.22.17", + "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", "json5": "^2.2.3", @@ -502,6 +566,11 @@ "url": "https://opencollective.com/babel" } }, + "node_modules/@babel/core/node_modules/convert-source-map": { + "version": "1.9.0", + "dev": true, + "license": "MIT" + }, "node_modules/@babel/core/node_modules/semver": { "version": "6.3.1", "dev": true, @@ -511,13 +580,13 @@ } }, "node_modules/@babel/generator": { - "version": "7.24.4", + "version": "7.23.0", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.24.0", - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25", + "@babel/types": "^7.23.0", + "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", "jsesc": "^2.5.1" }, "engines": { @@ -526,8 +595,9 @@ }, "node_modules/@babel/helper-annotate-as-pure": { "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz", + "integrity": "sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==", "dev": true, - "license": "MIT", "dependencies": { "@babel/types": "^7.22.5" }, @@ -537,8 +607,9 @@ }, "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.22.15.tgz", + "integrity": "sha512-QkBXwGgaoC2GtGZRoma6kv7Szfv06khvhFav67ZExau2RaXzy8MpHSMO2PNoP2XtmQphJQRHFfg77Bq731Yizw==", "dev": true, - "license": "MIT", "dependencies": { "@babel/types": "^7.22.15" }, @@ -548,8 +619,9 @@ }, "node_modules/@babel/helper-compilation-targets": { "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz", + "integrity": "sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==", "dev": true, - "license": "MIT", "dependencies": { "@babel/compat-data": "^7.23.5", "@babel/helper-validator-option": "^7.23.5", @@ -571,8 +643,9 @@ }, "node_modules/@babel/helper-create-class-features-plugin": { "version": "7.23.10", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.23.10.tgz", + "integrity": "sha512-2XpP2XhkXzgxecPNEEK8Vz8Asj9aRxt08oKOqtiZoqV2UGZ5T+EkyP9sXQ9nwMxBIG34a7jmasVqoMop7VdPUw==", "dev": true, - "license": "MIT", "dependencies": { "@babel/helper-annotate-as-pure": "^7.22.5", "@babel/helper-environment-visitor": "^7.22.20", @@ -593,16 +666,18 @@ }, "node_modules/@babel/helper-create-class-features-plugin/node_modules/semver": { "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, - "license": "ISC", "bin": { "semver": "bin/semver.js" } }, "node_modules/@babel/helper-create-regexp-features-plugin": { "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.22.15.tgz", + "integrity": "sha512-29FkPLFjn4TPEa3RE7GpW+qbE8tlsu3jntNYNfcGsc49LphF1PQIiD+vMZ1z1xVOKt+93khA9tc2JBs3kBjA7w==", "dev": true, - "license": "MIT", "dependencies": { "@babel/helper-annotate-as-pure": "^7.22.5", "regexpu-core": "^5.3.1", @@ -617,16 +692,18 @@ }, "node_modules/@babel/helper-create-regexp-features-plugin/node_modules/semver": { "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, - "license": "ISC", "bin": { "semver": "bin/semver.js" } }, "node_modules/@babel/helper-define-polyfill-provider": { "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.5.0.tgz", + "integrity": "sha512-NovQquuQLAQ5HuyjCz7WQP9MjRj7dx++yspwiyUiGl9ZyadHRSql1HZh5ogRd8W8w6YM6EQ/NTB8rgjLt5W65Q==", "dev": true, - "license": "MIT", "dependencies": { "@babel/helper-compilation-targets": "^7.22.6", "@babel/helper-plugin-utils": "^7.22.5", @@ -671,8 +748,9 @@ }, "node_modules/@babel/helper-member-expression-to-functions": { "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.23.0.tgz", + "integrity": "sha512-6gfrPwh7OuT6gZyJZvd6WbTfrqAo7vm4xCzAXOusKqq/vWdKXphTpj5klHKNmRUU6/QRGlBsyU9mAIPaWHlqJA==", "dev": true, - "license": "MIT", "dependencies": { "@babel/types": "^7.23.0" }, @@ -692,8 +770,9 @@ }, "node_modules/@babel/helper-module-transforms": { "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz", + "integrity": "sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==", "dev": true, - "license": "MIT", "dependencies": { "@babel/helper-environment-visitor": "^7.22.20", "@babel/helper-module-imports": "^7.22.15", @@ -710,8 +789,9 @@ }, "node_modules/@babel/helper-optimise-call-expression": { "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.22.5.tgz", + "integrity": "sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw==", "dev": true, - "license": "MIT", "dependencies": { "@babel/types": "^7.22.5" }, @@ -720,7 +800,7 @@ } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.24.0", + "version": "7.22.5", "dev": true, "license": "MIT", "engines": { @@ -729,8 +809,9 @@ }, "node_modules/@babel/helper-remap-async-to-generator": { "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.22.20.tgz", + "integrity": "sha512-pBGyV4uBqOns+0UvhsTO8qgl8hO89PmiDYv+/COyp1aeMcmfrfruz+/nCMFiYyFF/Knn0yfrC85ZzNFjembFTw==", "dev": true, - "license": "MIT", "dependencies": { "@babel/helper-annotate-as-pure": "^7.22.5", "@babel/helper-environment-visitor": "^7.22.20", @@ -745,8 +826,9 @@ }, "node_modules/@babel/helper-replace-supers": { "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.22.20.tgz", + "integrity": "sha512-qsW0In3dbwQUbK8kejJ4R7IHVGwHJlV6lpG6UA7a9hSa2YEiAib+N1T2kr6PEeUT+Fl7najmSOS6SmAwCHK6Tw==", "dev": true, - "license": "MIT", "dependencies": { "@babel/helper-environment-visitor": "^7.22.20", "@babel/helper-member-expression-to-functions": "^7.22.15", @@ -772,8 +854,9 @@ }, "node_modules/@babel/helper-skip-transparent-expression-wrappers": { "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.22.5.tgz", + "integrity": "sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q==", "dev": true, - "license": "MIT", "dependencies": { "@babel/types": "^7.22.5" }, @@ -793,7 +876,7 @@ } }, "node_modules/@babel/helper-string-parser": { - "version": "7.24.1", + "version": "7.22.5", "license": "MIT", "engines": { "node": ">=6.9.0" @@ -808,16 +891,18 @@ }, "node_modules/@babel/helper-validator-option": { "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz", + "integrity": "sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==", "dev": true, - "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-wrap-function": { "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.22.20.tgz", + "integrity": "sha512-pms/UwkOpnQe/PDAEdV/d7dVCoBbB+R4FvYoHGZz+4VPcg7RtYy2KP7S2lbuWM6FCSgob5wshfGESbC/hzNXZw==", "dev": true, - "license": "MIT", "dependencies": { "@babel/helper-function-name": "^7.22.5", "@babel/template": "^7.22.15", @@ -828,26 +913,25 @@ } }, "node_modules/@babel/helpers": { - "version": "7.24.4", + "version": "7.22.15", "dev": true, "license": "MIT", "dependencies": { - "@babel/template": "^7.24.0", - "@babel/traverse": "^7.24.1", - "@babel/types": "^7.24.0" + "@babel/template": "^7.22.15", + "@babel/traverse": "^7.22.15", + "@babel/types": "^7.22.15" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/highlight": { - "version": "7.24.2", + "version": "7.22.13", "license": "MIT", "dependencies": { - "@babel/helper-validator-identifier": "^7.22.20", + "@babel/helper-validator-identifier": "^7.22.5", "chalk": "^2.4.2", - "js-tokens": "^4.0.0", - "picocolors": "^1.0.0" + "js-tokens": "^4.0.0" }, "engines": { "node": ">=6.9.0" @@ -911,7 +995,7 @@ } }, "node_modules/@babel/parser": { - "version": "7.24.4", + "version": "7.23.0", "dev": true, "license": "MIT", "bin": { @@ -923,8 +1007,9 @@ }, "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.23.3.tgz", + "integrity": "sha512-iRkKcCqb7iGnq9+3G6rZ+Ciz5VywC4XNRHe57lKM+jOeYAoR0lVqdeeDRfh0tQcTfw/+vBhHn926FmQhLtlFLQ==", "dev": true, - "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" }, @@ -937,8 +1022,9 @@ }, "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.23.3.tgz", + "integrity": "sha512-WwlxbfMNdVEpQjZmK5mhm7oSwD3dS6eU+Iwsi4Knl9wAletWem7kaRsGOG+8UEbRyqxY4SS5zvtfXwX+jMxUwQ==", "dev": true, - "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5", "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", @@ -953,8 +1039,9 @@ }, "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { "version": "7.23.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.23.7.tgz", + "integrity": "sha512-LlRT7HgaifEpQA1ZgLVOIJZZFVPWN5iReq/7/JixwBtwcoeVGDBD53ZV28rrsLYOZs1Y/EHhA8N/Z6aazHR8cw==", "dev": true, - "license": "MIT", "dependencies": { "@babel/helper-environment-visitor": "^7.22.20", "@babel/helper-plugin-utils": "^7.22.5" @@ -968,8 +1055,9 @@ }, "node_modules/@babel/plugin-proposal-private-property-in-object": { "version": "7.21.0-placeholder-for-preset-env.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", + "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", "dev": true, - "license": "MIT", "engines": { "node": ">=6.9.0" }, @@ -1012,8 +1100,9 @@ }, "node_modules/@babel/plugin-syntax-class-static-block": { "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", "dev": true, - "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.14.5" }, @@ -1026,8 +1115,9 @@ }, "node_modules/@babel/plugin-syntax-dynamic-import": { "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", + "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", "dev": true, - "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -1037,8 +1127,9 @@ }, "node_modules/@babel/plugin-syntax-export-namespace-from": { "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", + "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", "dev": true, - "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.8.3" }, @@ -1048,8 +1139,9 @@ }, "node_modules/@babel/plugin-syntax-import-assertions": { "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.23.3.tgz", + "integrity": "sha512-lPgDSU+SJLK3xmFDTV2ZRQAiM7UuUjGidwBywFavObCiZc1BeAAcMtHJKUya92hPHO+at63JJPLygilZard8jw==", "dev": true, - "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" }, @@ -1062,8 +1154,9 @@ }, "node_modules/@babel/plugin-syntax-import-attributes": { "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.23.3.tgz", + "integrity": "sha512-pawnE0P9g10xgoP7yKr6CK63K2FMsTE+FZidZO/1PwRdzmAPVs+HS1mAURUsgaoxammTJvULUdIkEK0gOcU2tA==", "dev": true, - "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" }, @@ -1097,11 +1190,11 @@ } }, "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.24.1", + "version": "7.22.5", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0" + "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { "node": ">=6.9.0" @@ -1178,8 +1271,9 @@ }, "node_modules/@babel/plugin-syntax-private-property-in-object": { "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", "dev": true, - "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.14.5" }, @@ -1220,8 +1314,9 @@ }, "node_modules/@babel/plugin-syntax-unicode-sets-regex": { "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", + "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", "dev": true, - "license": "MIT", "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.18.6", "@babel/helper-plugin-utils": "^7.18.6" @@ -1235,8 +1330,9 @@ }, "node_modules/@babel/plugin-transform-arrow-functions": { "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.23.3.tgz", + "integrity": "sha512-NzQcQrzaQPkaEwoTm4Mhyl8jI1huEL/WWIEvudjTCMJ9aBZNpsJbMASx7EQECtQQPS/DcnFpo0FIh3LvEO9cxQ==", "dev": true, - "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" }, @@ -1249,8 +1345,9 @@ }, "node_modules/@babel/plugin-transform-async-generator-functions": { "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.23.9.tgz", + "integrity": "sha512-8Q3veQEDGe14dTYuwagbRtwxQDnytyg1JFu4/HwEMETeofocrB0U0ejBJIXoeG/t2oXZ8kzCyI0ZZfbT80VFNQ==", "dev": true, - "license": "MIT", "dependencies": { "@babel/helper-environment-visitor": "^7.22.20", "@babel/helper-plugin-utils": "^7.22.5", @@ -1266,8 +1363,9 @@ }, "node_modules/@babel/plugin-transform-async-to-generator": { "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.23.3.tgz", + "integrity": "sha512-A7LFsKi4U4fomjqXJlZg/u0ft/n8/7n7lpffUP/ZULx/DtV9SGlNKZolHH6PE8Xl1ngCc0M11OaeZptXVkfKSw==", "dev": true, - "license": "MIT", "dependencies": { "@babel/helper-module-imports": "^7.22.15", "@babel/helper-plugin-utils": "^7.22.5", @@ -1282,8 +1380,9 @@ }, "node_modules/@babel/plugin-transform-block-scoped-functions": { "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.23.3.tgz", + "integrity": "sha512-vI+0sIaPIO6CNuM9Kk5VmXcMVRiOpDh7w2zZt9GXzmE/9KD70CUEVhvPR/etAeNK/FAEkhxQtXOzVF3EuRL41A==", "dev": true, - "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" }, @@ -1296,8 +1395,9 @@ }, "node_modules/@babel/plugin-transform-block-scoping": { "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.23.4.tgz", + "integrity": "sha512-0QqbP6B6HOh7/8iNR4CQU2Th/bbRtBp4KS9vcaZd1fZ0wSh5Fyssg0UCIHwxh+ka+pNDREbVLQnHCMHKZfPwfw==", "dev": true, - "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" }, @@ -1310,8 +1410,9 @@ }, "node_modules/@babel/plugin-transform-class-properties": { "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.23.3.tgz", + "integrity": "sha512-uM+AN8yCIjDPccsKGlw271xjJtGii+xQIF/uMPS8H15L12jZTsLfF4o5vNO7d/oUguOyfdikHGc/yi9ge4SGIg==", "dev": true, - "license": "MIT", "dependencies": { "@babel/helper-create-class-features-plugin": "^7.22.15", "@babel/helper-plugin-utils": "^7.22.5" @@ -1325,8 +1426,9 @@ }, "node_modules/@babel/plugin-transform-class-static-block": { "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.23.4.tgz", + "integrity": "sha512-nsWu/1M+ggti1SOALj3hfx5FXzAY06fwPJsUZD4/A5e1bWi46VUIWtD+kOX6/IdhXGsXBWllLFDSnqSCdUNydQ==", "dev": true, - "license": "MIT", "dependencies": { "@babel/helper-create-class-features-plugin": "^7.22.15", "@babel/helper-plugin-utils": "^7.22.5", @@ -1341,8 +1443,9 @@ }, "node_modules/@babel/plugin-transform-classes": { "version": "7.23.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.23.8.tgz", + "integrity": "sha512-yAYslGsY1bX6Knmg46RjiCiNSwJKv2IUC8qOdYKqMMr0491SXFhcHqOdRDeCRohOOIzwN/90C6mQ9qAKgrP7dg==", "dev": true, - "license": "MIT", "dependencies": { "@babel/helper-annotate-as-pure": "^7.22.5", "@babel/helper-compilation-targets": "^7.23.6", @@ -1362,16 +1465,18 @@ }, "node_modules/@babel/plugin-transform-classes/node_modules/globals": { "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", "dev": true, - "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/@babel/plugin-transform-computed-properties": { "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.23.3.tgz", + "integrity": "sha512-dTj83UVTLw/+nbiHqQSFdwO9CbTtwq1DsDqm3CUEtDrZNET5rT5E6bIdTlOftDTDLMYxvxHNEYO4B9SLl8SLZw==", "dev": true, - "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5", "@babel/template": "^7.22.15" @@ -1385,8 +1490,9 @@ }, "node_modules/@babel/plugin-transform-destructuring": { "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.23.3.tgz", + "integrity": "sha512-n225npDqjDIr967cMScVKHXJs7rout1q+tt50inyBCPkyZ8KxeI6d+GIbSBTT/w/9WdlWDOej3V9HE5Lgk57gw==", "dev": true, - "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" }, @@ -1399,8 +1505,9 @@ }, "node_modules/@babel/plugin-transform-dotall-regex": { "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.23.3.tgz", + "integrity": "sha512-vgnFYDHAKzFaTVp+mneDsIEbnJ2Np/9ng9iviHw3P/KVcgONxpNULEW/51Z/BaFojG2GI2GwwXck5uV1+1NOYQ==", "dev": true, - "license": "MIT", "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.22.15", "@babel/helper-plugin-utils": "^7.22.5" @@ -1414,8 +1521,9 @@ }, "node_modules/@babel/plugin-transform-duplicate-keys": { "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.23.3.tgz", + "integrity": "sha512-RrqQ+BQmU3Oyav3J+7/myfvRCq7Tbz+kKLLshUmMwNlDHExbGL7ARhajvoBJEvc+fCguPPu887N+3RRXBVKZUA==", "dev": true, - "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" }, @@ -1428,8 +1536,9 @@ }, "node_modules/@babel/plugin-transform-dynamic-import": { "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.23.4.tgz", + "integrity": "sha512-V6jIbLhdJK86MaLh4Jpghi8ho5fGzt3imHOBu/x0jlBaPYqDoWz4RDXjmMOfnh+JWNaQleEAByZLV0QzBT4YQQ==", "dev": true, - "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5", "@babel/plugin-syntax-dynamic-import": "^7.8.3" @@ -1443,8 +1552,9 @@ }, "node_modules/@babel/plugin-transform-exponentiation-operator": { "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.23.3.tgz", + "integrity": "sha512-5fhCsl1odX96u7ILKHBj4/Y8vipoqwsJMh4csSA8qFfxrZDEA4Ssku2DyNvMJSmZNOEBT750LfFPbtrnTP90BQ==", "dev": true, - "license": "MIT", "dependencies": { "@babel/helper-builder-binary-assignment-operator-visitor": "^7.22.15", "@babel/helper-plugin-utils": "^7.22.5" @@ -1458,8 +1568,9 @@ }, "node_modules/@babel/plugin-transform-export-namespace-from": { "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.23.4.tgz", + "integrity": "sha512-GzuSBcKkx62dGzZI1WVgTWvkkz84FZO5TC5T8dl/Tht/rAla6Dg/Mz9Yhypg+ezVACf/rgDuQt3kbWEv7LdUDQ==", "dev": true, - "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5", "@babel/plugin-syntax-export-namespace-from": "^7.8.3" @@ -1473,8 +1584,9 @@ }, "node_modules/@babel/plugin-transform-for-of": { "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.23.6.tgz", + "integrity": "sha512-aYH4ytZ0qSuBbpfhuofbg/e96oQ7U2w1Aw/UQmKT+1l39uEhUPoFS3fHevDc1G0OvewyDudfMKY1OulczHzWIw==", "dev": true, - "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5", "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5" @@ -1488,8 +1600,9 @@ }, "node_modules/@babel/plugin-transform-function-name": { "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.23.3.tgz", + "integrity": "sha512-I1QXp1LxIvt8yLaib49dRW5Okt7Q4oaxao6tFVKS/anCdEOMtYwWVKoiOA1p34GOWIZjUK0E+zCp7+l1pfQyiw==", "dev": true, - "license": "MIT", "dependencies": { "@babel/helper-compilation-targets": "^7.22.15", "@babel/helper-function-name": "^7.23.0", @@ -1504,8 +1617,9 @@ }, "node_modules/@babel/plugin-transform-json-strings": { "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.23.4.tgz", + "integrity": "sha512-81nTOqM1dMwZ/aRXQ59zVubN9wHGqk6UtqRK+/q+ciXmRy8fSolhGVvG09HHRGo4l6fr/c4ZhXUQH0uFW7PZbg==", "dev": true, - "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5", "@babel/plugin-syntax-json-strings": "^7.8.3" @@ -1519,8 +1633,9 @@ }, "node_modules/@babel/plugin-transform-literals": { "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.23.3.tgz", + "integrity": "sha512-wZ0PIXRxnwZvl9AYpqNUxpZ5BiTGrYt7kueGQ+N5FiQ7RCOD4cm8iShd6S6ggfVIWaJf2EMk8eRzAh52RfP4rQ==", "dev": true, - "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" }, @@ -1533,8 +1648,9 @@ }, "node_modules/@babel/plugin-transform-logical-assignment-operators": { "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.23.4.tgz", + "integrity": "sha512-Mc/ALf1rmZTP4JKKEhUwiORU+vcfarFVLfcFiolKUo6sewoxSEgl36ak5t+4WamRsNr6nzjZXQjM35WsU+9vbg==", "dev": true, - "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5", "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" @@ -1548,8 +1664,9 @@ }, "node_modules/@babel/plugin-transform-member-expression-literals": { "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.23.3.tgz", + "integrity": "sha512-sC3LdDBDi5x96LA+Ytekz2ZPk8i/Ck+DEuDbRAll5rknJ5XRTSaPKEYwomLcs1AA8wg9b3KjIQRsnApj+q51Ag==", "dev": true, - "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" }, @@ -1562,8 +1679,9 @@ }, "node_modules/@babel/plugin-transform-modules-amd": { "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.23.3.tgz", + "integrity": "sha512-vJYQGxeKM4t8hYCKVBlZX/gtIY2I7mRGFNcm85sgXGMTBcoV3QdVtdpbcWEbzbfUIUZKwvgFT82mRvaQIebZzw==", "dev": true, - "license": "MIT", "dependencies": { "@babel/helper-module-transforms": "^7.23.3", "@babel/helper-plugin-utils": "^7.22.5" @@ -1577,8 +1695,9 @@ }, "node_modules/@babel/plugin-transform-modules-commonjs": { "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.23.3.tgz", + "integrity": "sha512-aVS0F65LKsdNOtcz6FRCpE4OgsP2OFnW46qNxNIX9h3wuzaNcSQsJysuMwqSibC98HPrf2vCgtxKNwS0DAlgcA==", "dev": true, - "license": "MIT", "dependencies": { "@babel/helper-module-transforms": "^7.23.3", "@babel/helper-plugin-utils": "^7.22.5", @@ -1593,8 +1712,9 @@ }, "node_modules/@babel/plugin-transform-modules-systemjs": { "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.23.9.tgz", + "integrity": "sha512-KDlPRM6sLo4o1FkiSlXoAa8edLXFsKKIda779fbLrvmeuc3itnjCtaO6RrtoaANsIJANj+Vk1zqbZIMhkCAHVw==", "dev": true, - "license": "MIT", "dependencies": { "@babel/helper-hoist-variables": "^7.22.5", "@babel/helper-module-transforms": "^7.23.3", @@ -1610,8 +1730,9 @@ }, "node_modules/@babel/plugin-transform-modules-umd": { "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.23.3.tgz", + "integrity": "sha512-zHsy9iXX2nIsCBFPud3jKn1IRPWg3Ing1qOZgeKV39m1ZgIdpJqvlWVeiHBZC6ITRG0MfskhYe9cLgntfSFPIg==", "dev": true, - "license": "MIT", "dependencies": { "@babel/helper-module-transforms": "^7.23.3", "@babel/helper-plugin-utils": "^7.22.5" @@ -1625,8 +1746,9 @@ }, "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.22.5.tgz", + "integrity": "sha512-YgLLKmS3aUBhHaxp5hi1WJTgOUb/NCuDHzGT9z9WTt3YG+CPRhJs6nprbStx6DnWM4dh6gt7SU3sZodbZ08adQ==", "dev": true, - "license": "MIT", "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.22.5", "@babel/helper-plugin-utils": "^7.22.5" @@ -1640,8 +1762,9 @@ }, "node_modules/@babel/plugin-transform-new-target": { "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.23.3.tgz", + "integrity": "sha512-YJ3xKqtJMAT5/TIZnpAR3I+K+WaDowYbN3xyxI8zxx/Gsypwf9B9h0VB+1Nh6ACAAPRS5NSRje0uVv5i79HYGQ==", "dev": true, - "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" }, @@ -1654,8 +1777,9 @@ }, "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.23.4.tgz", + "integrity": "sha512-jHE9EVVqHKAQx+VePv5LLGHjmHSJR76vawFPTdlxR/LVJPfOEGxREQwQfjuZEOPTwG92X3LINSh3M40Rv4zpVA==", "dev": true, - "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5", "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" @@ -1669,8 +1793,9 @@ }, "node_modules/@babel/plugin-transform-numeric-separator": { "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.23.4.tgz", + "integrity": "sha512-mps6auzgwjRrwKEZA05cOwuDc9FAzoyFS4ZsG/8F43bTLf/TgkJg7QXOrPO1JO599iA3qgK9MXdMGOEC8O1h6Q==", "dev": true, - "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5", "@babel/plugin-syntax-numeric-separator": "^7.10.4" @@ -1684,8 +1809,9 @@ }, "node_modules/@babel/plugin-transform-object-rest-spread": { "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.23.4.tgz", + "integrity": "sha512-9x9K1YyeQVw0iOXJlIzwm8ltobIIv7j2iLyP2jIhEbqPRQ7ScNgwQufU2I0Gq11VjyG4gI4yMXt2VFags+1N3g==", "dev": true, - "license": "MIT", "dependencies": { "@babel/compat-data": "^7.23.3", "@babel/helper-compilation-targets": "^7.22.15", @@ -1702,8 +1828,9 @@ }, "node_modules/@babel/plugin-transform-object-super": { "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.23.3.tgz", + "integrity": "sha512-BwQ8q0x2JG+3lxCVFohg+KbQM7plfpBwThdW9A6TMtWwLsbDA01Ek2Zb/AgDN39BiZsExm4qrXxjk+P1/fzGrA==", "dev": true, - "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5", "@babel/helper-replace-supers": "^7.22.20" @@ -1717,8 +1844,9 @@ }, "node_modules/@babel/plugin-transform-optional-catch-binding": { "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.23.4.tgz", + "integrity": "sha512-XIq8t0rJPHf6Wvmbn9nFxU6ao4c7WhghTR5WyV8SrJfUFzyxhCm4nhC+iAp3HFhbAKLfYpgzhJ6t4XCtVwqO5A==", "dev": true, - "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5", "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" @@ -1732,8 +1860,9 @@ }, "node_modules/@babel/plugin-transform-optional-chaining": { "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.23.4.tgz", + "integrity": "sha512-ZU8y5zWOfjM5vZ+asjgAPwDaBjJzgufjES89Rs4Lpq63O300R/kOz30WCLo6BxxX6QVEilwSlpClnG5cZaikTA==", "dev": true, - "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5", "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", @@ -1748,8 +1877,9 @@ }, "node_modules/@babel/plugin-transform-parameters": { "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.23.3.tgz", + "integrity": "sha512-09lMt6UsUb3/34BbECKVbVwrT9bO6lILWln237z7sLaWnMsTi7Yc9fhX5DLpkJzAGfaReXI22wP41SZmnAA3Vw==", "dev": true, - "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" }, @@ -1762,8 +1892,9 @@ }, "node_modules/@babel/plugin-transform-private-methods": { "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.23.3.tgz", + "integrity": "sha512-UzqRcRtWsDMTLrRWFvUBDwmw06tCQH9Rl1uAjfh6ijMSmGYQ+fpdB+cnqRC8EMh5tuuxSv0/TejGL+7vyj+50g==", "dev": true, - "license": "MIT", "dependencies": { "@babel/helper-create-class-features-plugin": "^7.22.15", "@babel/helper-plugin-utils": "^7.22.5" @@ -1777,8 +1908,9 @@ }, "node_modules/@babel/plugin-transform-private-property-in-object": { "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.23.4.tgz", + "integrity": "sha512-9G3K1YqTq3F4Vt88Djx1UZ79PDyj+yKRnUy7cZGSMe+a7jkwD259uKKuUzQlPkGam7R+8RJwh5z4xO27fA1o2A==", "dev": true, - "license": "MIT", "dependencies": { "@babel/helper-annotate-as-pure": "^7.22.5", "@babel/helper-create-class-features-plugin": "^7.22.15", @@ -1794,8 +1926,9 @@ }, "node_modules/@babel/plugin-transform-property-literals": { "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.23.3.tgz", + "integrity": "sha512-jR3Jn3y7cZp4oEWPFAlRsSWjxKe4PZILGBSd4nis1TsC5qeSpb+nrtihJuDhNI7QHiVbUaiXa0X2RZY3/TI6Nw==", "dev": true, - "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" }, @@ -1808,8 +1941,9 @@ }, "node_modules/@babel/plugin-transform-regenerator": { "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.23.3.tgz", + "integrity": "sha512-KP+75h0KghBMcVpuKisx3XTu9Ncut8Q8TuvGO4IhY+9D5DFEckQefOuIsB/gQ2tG71lCke4NMrtIPS8pOj18BQ==", "dev": true, - "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5", "regenerator-transform": "^0.15.2" @@ -1823,8 +1957,9 @@ }, "node_modules/@babel/plugin-transform-reserved-words": { "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.23.3.tgz", + "integrity": "sha512-QnNTazY54YqgGxwIexMZva9gqbPa15t/x9VS+0fsEFWplwVpXYZivtgl43Z1vMpc1bdPP2PP8siFeVcnFvA3Cg==", "dev": true, - "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" }, @@ -1837,8 +1972,9 @@ }, "node_modules/@babel/plugin-transform-shorthand-properties": { "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.23.3.tgz", + "integrity": "sha512-ED2fgqZLmexWiN+YNFX26fx4gh5qHDhn1O2gvEhreLW2iI63Sqm4llRLCXALKrCnbN4Jy0VcMQZl/SAzqug/jg==", "dev": true, - "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" }, @@ -1851,8 +1987,9 @@ }, "node_modules/@babel/plugin-transform-spread": { "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.23.3.tgz", + "integrity": "sha512-VvfVYlrlBVu+77xVTOAoxQ6mZbnIq5FM0aGBSFEcIh03qHf+zNqA4DC/3XMUozTg7bZV3e3mZQ0i13VB6v5yUg==", "dev": true, - "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5", "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5" @@ -1866,8 +2003,9 @@ }, "node_modules/@babel/plugin-transform-sticky-regex": { "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.23.3.tgz", + "integrity": "sha512-HZOyN9g+rtvnOU3Yh7kSxXrKbzgrm5X4GncPY1QOquu7epga5MxKHVpYu2hvQnry/H+JjckSYRb93iNfsioAGg==", "dev": true, - "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" }, @@ -1880,8 +2018,9 @@ }, "node_modules/@babel/plugin-transform-template-literals": { "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.23.3.tgz", + "integrity": "sha512-Flok06AYNp7GV2oJPZZcP9vZdszev6vPBkHLwxwSpaIqx75wn6mUd3UFWsSsA0l8nXAKkyCmL/sR02m8RYGeHg==", "dev": true, - "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" }, @@ -1894,8 +2033,9 @@ }, "node_modules/@babel/plugin-transform-typeof-symbol": { "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.23.3.tgz", + "integrity": "sha512-4t15ViVnaFdrPC74be1gXBSMzXk3B4Us9lP7uLRQHTFpV5Dvt33pn+2MyyNxmN3VTTm3oTrZVMUmuw3oBnQ2oQ==", "dev": true, - "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" }, @@ -1908,8 +2048,9 @@ }, "node_modules/@babel/plugin-transform-unicode-escapes": { "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.23.3.tgz", + "integrity": "sha512-OMCUx/bU6ChE3r4+ZdylEqAjaQgHAgipgW8nsCfu5pGqDcFytVd91AwRvUJSBZDz0exPGgnjoqhgRYLRjFZc9Q==", "dev": true, - "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" }, @@ -1922,8 +2063,9 @@ }, "node_modules/@babel/plugin-transform-unicode-property-regex": { "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.23.3.tgz", + "integrity": "sha512-KcLIm+pDZkWZQAFJ9pdfmh89EwVfmNovFBcXko8szpBeF8z68kWIPeKlmSOkT9BXJxs2C0uk+5LxoxIv62MROA==", "dev": true, - "license": "MIT", "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.22.15", "@babel/helper-plugin-utils": "^7.22.5" @@ -1937,8 +2079,9 @@ }, "node_modules/@babel/plugin-transform-unicode-regex": { "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.23.3.tgz", + "integrity": "sha512-wMHpNA4x2cIA32b/ci3AfwNgheiva2W0WUKWTK7vBHBhDKfPsc5cFGNWm69WBqpwd86u1qwZ9PWevKqm1A3yAw==", "dev": true, - "license": "MIT", "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.22.15", "@babel/helper-plugin-utils": "^7.22.5" @@ -1952,8 +2095,9 @@ }, "node_modules/@babel/plugin-transform-unicode-sets-regex": { "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.23.3.tgz", + "integrity": "sha512-W7lliA/v9bNR83Qc3q1ip9CQMZ09CcHDbHfbLRDNuAhn1Mvkr1ZNF7hPmztMQvtTGVLJ9m8IZqWsTkXOml8dbw==", "dev": true, - "license": "MIT", "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.22.15", "@babel/helper-plugin-utils": "^7.22.5" @@ -1967,8 +2111,9 @@ }, "node_modules/@babel/preset-env": { "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.23.9.tgz", + "integrity": "sha512-3kBGTNBBk9DQiPoXYS0g0BYlwTQYUTifqgKTjxUwEUkduRT2QOa0FPGBJ+NROQhGyYO5BuTJwGvBnqKDykac6A==", "dev": true, - "license": "MIT", "dependencies": { "@babel/compat-data": "^7.23.5", "@babel/helper-compilation-targets": "^7.23.6", @@ -2060,16 +2205,18 @@ }, "node_modules/@babel/preset-env/node_modules/semver": { "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, - "license": "ISC", "bin": { "semver": "bin/semver.js" } }, "node_modules/@babel/preset-modules": { "version": "0.1.6-no-external-plugins", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz", + "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", "dev": true, - "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.0.0", "@babel/types": "^7.4.4", @@ -2081,12 +2228,14 @@ }, "node_modules/@babel/regjsgen": { "version": "0.8.0", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz", + "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==", + "dev": true }, "node_modules/@babel/runtime": { "version": "7.23.9", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.9.tgz", + "integrity": "sha512-0CX6F+BI2s9dkUqr08KFrAIZgNFj75rdBU/DjCyYLIaV/quFjkk6T+EJ2LkZHyZTbEV4L5p97mNkUsHl2wLFAw==", "dependencies": { "regenerator-runtime": "^0.14.0" }, @@ -2095,32 +2244,32 @@ } }, "node_modules/@babel/template": { - "version": "7.24.0", + "version": "7.22.15", "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.23.5", - "@babel/parser": "^7.24.0", - "@babel/types": "^7.24.0" + "@babel/code-frame": "^7.22.13", + "@babel/parser": "^7.22.15", + "@babel/types": "^7.22.15" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.24.1", + "version": "7.23.2", "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.24.1", - "@babel/generator": "^7.24.1", + "@babel/code-frame": "^7.22.13", + "@babel/generator": "^7.23.0", "@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.1", - "@babel/types": "^7.24.0", - "debug": "^4.3.1", + "@babel/parser": "^7.23.0", + "@babel/types": "^7.23.0", + "debug": "^4.1.0", "globals": "^11.1.0" }, "engines": { @@ -2136,10 +2285,10 @@ } }, "node_modules/@babel/types": { - "version": "7.24.0", + "version": "7.23.0", "license": "MIT", "dependencies": { - "@babel/helper-string-parser": "^7.23.4", + "@babel/helper-string-parser": "^7.22.5", "@babel/helper-validator-identifier": "^7.22.20", "to-fast-properties": "^2.0.0" }, @@ -2181,9 +2330,20 @@ "@jridgewell/sourcemap-codec": "^1.4.10" } }, + "node_modules/@emnapi/runtime": { + "version": "0.45.0", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-0.45.0.tgz", + "integrity": "sha512-Txumi3td7J4A/xTTwlssKieHKTGl3j4A1tglBx72auZ49YK7ePY6XZricgIg9mnZT4xPfA+UPCUdnhRuEFDL+w==", + "dev": true, + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, "node_modules/@emotion/babel-plugin": { "version": "11.11.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.11.0.tgz", + "integrity": "sha512-m4HEDZleaaCH+XgDDsPF15Ht6wTLsgDTeR3WYj9Q/k76JtWhrJjcP4+/XlG8LGT/Rol9qUfOIztXeA84ATpqPQ==", "dependencies": { "@babel/helper-module-imports": "^7.16.7", "@babel/runtime": "^7.18.3", @@ -2200,18 +2360,21 @@ }, "node_modules/@emotion/babel-plugin/node_modules/convert-source-map": { "version": "1.9.0", - "license": "MIT" + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==" }, "node_modules/@emotion/babel-plugin/node_modules/source-map": { "version": "0.5.7", - "license": "BSD-3-Clause", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", "engines": { "node": ">=0.10.0" } }, "node_modules/@emotion/cache": { "version": "11.11.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.11.0.tgz", + "integrity": "sha512-P34z9ssTCBi3e9EI1ZsWpNHcfY1r09ZO0rZbRO2ob3ZQMnFI35jB536qoXbkdesr5EUhYi22anuEJuyxifaqAQ==", "dependencies": { "@emotion/memoize": "^0.8.1", "@emotion/sheet": "^1.2.2", @@ -2222,22 +2385,26 @@ }, "node_modules/@emotion/hash": { "version": "0.9.1", - "license": "MIT" + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.1.tgz", + "integrity": "sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ==" }, "node_modules/@emotion/is-prop-valid": { "version": "1.2.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.1.tgz", + "integrity": "sha512-61Mf7Ufx4aDxx1xlDeOm8aFFigGHE4z+0sKCa+IHCeZKiyP9RLD0Mmx7m8b9/Cf37f7NAvQOOJAbQQGVr5uERw==", "dependencies": { "@emotion/memoize": "^0.8.1" } }, "node_modules/@emotion/memoize": { "version": "0.8.1", - "license": "MIT" + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz", + "integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==" }, "node_modules/@emotion/react": { "version": "11.11.3", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.11.3.tgz", + "integrity": "sha512-Cnn0kuq4DoONOMcnoVsTOR8E+AdnKFf//6kUWc4LCdnxj31pZWn7rIULd6Y7/Js1PiPHzn7SKCM9vB/jBni8eA==", "dependencies": { "@babel/runtime": "^7.18.3", "@emotion/babel-plugin": "^11.11.0", @@ -2259,7 +2426,8 @@ }, "node_modules/@emotion/serialize": { "version": "1.1.3", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.1.3.tgz", + "integrity": "sha512-iD4D6QVZFDhcbH0RAG1uVu1CwVLMWUkCvAqqlewO/rxf8+87yIBAlt4+AxMiiKPLs5hFc0owNk/sLLAOROw3cA==", "dependencies": { "@emotion/hash": "^0.9.1", "@emotion/memoize": "^0.8.1", @@ -2270,7 +2438,8 @@ }, "node_modules/@emotion/server": { "version": "11.11.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@emotion/server/-/server-11.11.0.tgz", + "integrity": "sha512-6q89fj2z8VBTx9w93kJ5n51hsmtYuFPtZgnc1L8VzRx9ti4EU6EyvF6Nn1H1x3vcCQCF7u2dB2lY4AYJwUW4PA==", "dependencies": { "@emotion/utils": "^1.2.1", "html-tokenize": "^2.0.0", @@ -2288,11 +2457,13 @@ }, "node_modules/@emotion/sheet": { "version": "1.2.2", - "license": "MIT" + "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.2.2.tgz", + "integrity": "sha512-0QBtGvaqtWi+nx6doRwDdBIzhNdZrXUppvTM4dtZZWEGTXL/XE/yJxLMGlDT1Gt+UHH5IX1n+jkXyytE/av7OA==" }, "node_modules/@emotion/styled": { "version": "11.11.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.11.0.tgz", + "integrity": "sha512-hM5Nnvu9P3midq5aaXj4I+lnSfNi7Pmd4EWk1fOZ3pxookaQTNew6bp4JaCBYM4HVFZF9g7UjJmsUmC2JlxOng==", "dependencies": { "@babel/runtime": "^7.18.3", "@emotion/babel-plugin": "^11.11.0", @@ -2313,60 +2484,433 @@ }, "node_modules/@emotion/unitless": { "version": "0.8.1", - "license": "MIT" + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.1.tgz", + "integrity": "sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ==" }, "node_modules/@emotion/use-insertion-effect-with-fallbacks": { "version": "1.0.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.0.1.tgz", + "integrity": "sha512-jT/qyKZ9rzLErtrjGgdkMBn2OP8wl0G3sQlBb3YPryvKHsjvINUhVaPFfP+fpBcOkmrVOVEEHQFJ7nbj2TH2gw==", "peerDependencies": { "react": ">=16.8.0" } }, "node_modules/@emotion/utils": { "version": "1.2.1", - "license": "MIT" + "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.2.1.tgz", + "integrity": "sha512-Y2tGf3I+XVnajdItskUCn6LX+VUDmP6lTL4fcqsXAv43dnlbZiuW4MWQW38rW/BVWSE7Q/7+XQocmpnRYILUmg==" }, "node_modules/@emotion/weak-memoize": { "version": "0.3.1", - "license": "MIT" + "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.3.1.tgz", + "integrity": "sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww==" }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.4.0", + "node_modules/@esbuild/aix-ppc64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.19.12.tgz", + "integrity": "sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA==", + "cpu": [ + "ppc64" + ], "dev": true, - "license": "MIT", - "dependencies": { - "eslint-visitor-keys": "^3.3.0" - }, + "optional": true, + "os": [ + "aix" + ], "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + "node": ">=12" } }, - "node_modules/@eslint-community/regexpp": { - "version": "4.8.0", + "node_modules/@esbuild/android-arm": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.12.tgz", + "integrity": "sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w==", + "cpu": [ + "arm" + ], "dev": true, - "license": "MIT", + "optional": true, + "os": [ + "android" + ], "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + "node": ">=12" } }, - "node_modules/@eslint/eslintrc": { - "version": "2.1.4", + "node_modules/@esbuild/android-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.12.tgz", + "integrity": "sha512-P0UVNGIienjZv3f5zq0DP3Nt2IE/3plFzuaS96vihvD0Hd6H/q4WXUGpCxD/E8YrSXfNyRPbpTq+T8ZQioSuPA==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "MIT", - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.12.tgz", + "integrity": "sha512-3k7ZoUW6Q6YqhdhIaq/WZ7HwBpnFBlW905Fa4s4qWJyiNOgT1dOqDiVAQFwBH7gBRZr17gLrlFCRzF6jFh7Kew==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.12.tgz", + "integrity": "sha512-B6IeSgZgtEzGC42jsI+YYu9Z3HKRxp8ZT3cqhvliEHovq8HSX2YX8lNocDn79gCKJXOSaEot9MVYky7AKjCs8g==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.12.tgz", + "integrity": "sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.12.tgz", + "integrity": "sha512-4aRvFIXmwAcDBw9AueDQ2YnGmz5L6obe5kmPT8Vd+/+x/JMVKCgdcRwH6APrbpNXsPz+K653Qg8HB/oXvXVukA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.12.tgz", + "integrity": "sha512-EYoXZ4d8xtBoVN7CEwWY2IN4ho76xjYXqSXMNccFSx2lgqOG/1TBPW0yPx1bJZk94qu3tX0fycJeeQsKovA8gg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.12.tgz", + "integrity": "sha512-J5jPms//KhSNv+LO1S1TX1UWp1ucM6N6XuL6ITdKWElCu8wXP72l9MM0zDTzzeikVyqFE6U8YAV9/tFyj0ti+w==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.12.tgz", + "integrity": "sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.12.tgz", + "integrity": "sha512-Thsa42rrP1+UIGaWz47uydHSBOgTUnwBwNq59khgIwktK6x60Hivfbux9iNR0eHCHzOLjLMLfUMLCypBkZXMHA==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.12.tgz", + "integrity": "sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.12.tgz", + "integrity": "sha512-fEnAuj5VGTanfJ07ff0gOA6IPsvrVHLVb6Lyd1g2/ed67oU1eFzL0r9WL7ZzscD+/N6i3dWumGE1Un4f7Amf+w==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.12.tgz", + "integrity": "sha512-nYJA2/QPimDQOh1rKWedNOe3Gfc8PabU7HT3iXWtNUbRzXS9+vgB0Fjaqr//XNbd82mCxHzik2qotuI89cfixg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.12.tgz", + "integrity": "sha512-2MueBrlPQCw5dVJJpQdUYgeqIzDQgw3QtiAHUC4RBz9FXPrskyyU3VI1hw7C0BSKB9OduwSJ79FTCqtGMWqJHg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.12.tgz", + "integrity": "sha512-+Pil1Nv3Umes4m3AZKqA2anfhJiVmNCYkPchwFJNEJN5QxmTs1uzyy4TvmDrCRNT2ApwSari7ZIgrPeUx4UZDg==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.12.tgz", + "integrity": "sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.12.tgz", + "integrity": "sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.12.tgz", + "integrity": "sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.12.tgz", + "integrity": "sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.12.tgz", + "integrity": "sha512-URgtR1dJnmGvX864pn1B2YUYNzjmXkuJOIqG2HdU62MVS4EHpU2946OZoTMnRUHklGtJdJZ33QfzdjGACXhn1A==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.12.tgz", + "integrity": "sha512-+ZOE6pUkMOJfmxmBZElNOx72NKpIa/HFOMGzu8fqzQJ5kgf6aTGrcJaFsNiVMH4JKpMipyK+7k0n2UXN7a8YKQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.12.tgz", + "integrity": "sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.8.0", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -2376,8 +2920,9 @@ }, "node_modules/@eslint/eslintrc/node_modules/ajv": { "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, - "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -2391,27 +2936,47 @@ }, "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { "version": "0.4.1", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true }, "node_modules/@eslint/js": { "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", + "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", "dev": true, - "license": "MIT", "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, + "node_modules/@faker-js/faker": { + "version": "8.4.1", + "resolved": "https://registry.npmjs.org/@faker-js/faker/-/faker-8.4.1.tgz", + "integrity": "sha512-XQ3cU+Q8Uqmrbf2e0cIC/QN43sTBSC8KF12u29Mb47tWrt2hAgBXSgpZMj4Ao8Uk0iJcU99QsOCaIL8934obCg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/fakerjs" + } + ], + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0", + "npm": ">=6.14.13" + } + }, "node_modules/@floating-ui/core": { "version": "1.6.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.0.tgz", + "integrity": "sha512-PcF++MykgmTj3CIyOQbKA/hDzOAiqI3mhuoN44WRCopIs1sgoDoU4oty4Jtqaj/y3oDU6fnVSm4QG0a3t5i0+g==", "dependencies": { "@floating-ui/utils": "^0.2.1" } }, "node_modules/@floating-ui/dom": { "version": "1.6.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.1.tgz", + "integrity": "sha512-iA8qE43/H5iGozC3W0YSnVSW42Vh522yyM1gj+BqRwVsTNOyr231PsXDaV04yT39PsO0QL2QpbI/M0ZaLUQgRQ==", "dependencies": { "@floating-ui/core": "^1.6.0", "@floating-ui/utils": "^0.2.1" @@ -2419,7 +2984,8 @@ }, "node_modules/@floating-ui/react-dom": { "version": "2.0.8", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.0.8.tgz", + "integrity": "sha512-HOdqOt3R3OGeTKidaLvJKcgg75S6tibQ3Tif4eyd91QnIJWr0NLvoXFpJA/j8HqkFSL68GDca9AuyWEHlhyClw==", "dependencies": { "@floating-ui/dom": "^1.6.1" }, @@ -2430,87 +2996,355 @@ }, "node_modules/@floating-ui/utils": { "version": "0.2.1", - "license": "MIT" + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.1.tgz", + "integrity": "sha512-9TANp6GPoMtYzQdt54kfAyMmz1+osLlXdg2ENroU7zzrtflTLrrC/lgrIfaSe+Wu0b89GKccT7vxXA0MoAIO+Q==" }, "node_modules/@humanwhocodes/config-array": { "version": "0.11.14", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", + "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", "dev": true, - "license": "Apache-2.0", "dependencies": { "@humanwhocodes/object-schema": "^2.0.2", "debug": "^4.3.1", "minimatch": "^3.0.5" }, "engines": { - "node": ">=10.10.0" + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz", + "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==", + "dev": true + }, + "node_modules/@img/sharp-darwin-arm64": { + "version": "0.33.2", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.33.2.tgz", + "integrity": "sha512-itHBs1rPmsmGF9p4qRe++CzCgd+kFYktnsoR1sbIAfsRMrJZau0Tt1AH9KVnufc2/tU02Gf6Ibujx+15qRE03w==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "glibc": ">=2.26", + "node": "^18.17.0 || ^20.3.0 || >=21.0.0", + "npm": ">=9.6.5", + "pnpm": ">=7.1.0", + "yarn": ">=3.2.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-arm64": "1.0.1" + } + }, + "node_modules/@img/sharp-darwin-x64": { + "version": "0.33.2", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.33.2.tgz", + "integrity": "sha512-/rK/69Rrp9x5kaWBjVN07KixZanRr+W1OiyKdXcbjQD6KbW+obaTeBBtLUAtbBsnlTTmWthw99xqoOS7SsySDg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "glibc": ">=2.26", + "node": "^18.17.0 || ^20.3.0 || >=21.0.0", + "npm": ">=9.6.5", + "pnpm": ">=7.1.0", + "yarn": ">=3.2.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-x64": "1.0.1" + } + }, + "node_modules/@img/sharp-libvips-darwin-arm64": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.0.1.tgz", + "integrity": "sha512-kQyrSNd6lmBV7O0BUiyu/OEw9yeNGFbQhbxswS1i6rMDwBBSX+e+rPzu3S+MwAiGU3HdLze3PanQ4Xkfemgzcw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "macos": ">=11", + "npm": ">=9.6.5", + "pnpm": ">=7.1.0", + "yarn": ">=3.2.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-darwin-x64": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.0.1.tgz", + "integrity": "sha512-eVU/JYLPVjhhrd8Tk6gosl5pVlvsqiFlt50wotCvdkFGf+mDNBJxMh+bvav+Wt3EBnNZWq8Sp2I7XfSjm8siog==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "macos": ">=10.13", + "npm": ">=9.6.5", + "pnpm": ">=7.1.0", + "yarn": ">=3.2.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.0.1.tgz", + "integrity": "sha512-FtdMvR4R99FTsD53IA3LxYGghQ82t3yt0ZQ93WMZ2xV3dqrb0E8zq4VHaTOuLEAuA83oDawHV3fd+BsAPadHIQ==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "glibc": ">=2.28", + "npm": ">=9.6.5", + "pnpm": ">=7.1.0", + "yarn": ">=3.2.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm64": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.0.1.tgz", + "integrity": "sha512-bnGG+MJjdX70mAQcSLxgeJco11G+MxTz+ebxlz8Y3dxyeb3Nkl7LgLI0mXupoO+u1wRNx/iRj5yHtzA4sde1yA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "glibc": ">=2.26", + "npm": ">=9.6.5", + "pnpm": ">=7.1.0", + "yarn": ">=3.2.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-s390x": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.0.1.tgz", + "integrity": "sha512-3+rzfAR1YpMOeA2zZNp+aYEzGNWK4zF3+sdMxuCS3ey9HhDbJ66w6hDSHDMoap32DueFwhhs3vwooAB2MaK4XQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "glibc": ">=2.28", + "npm": ">=9.6.5", + "pnpm": ">=7.1.0", + "yarn": ">=3.2.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-x64": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.0.1.tgz", + "integrity": "sha512-3NR1mxFsaSgMMzz1bAnnKbSAI+lHXVTqAHgc1bgzjHuXjo4hlscpUxc0vFSAPKI3yuzdzcZOkq7nDPrP2F8Jgw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "glibc": ">=2.26", + "npm": ">=9.6.5", + "pnpm": ">=7.1.0", + "yarn": ">=3.2.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-arm64": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.0.1.tgz", + "integrity": "sha512-5aBRcjHDG/T6jwC3Edl3lP8nl9U2Yo8+oTl5drd1dh9Z1EBfzUKAJFUDTDisDjUwc7N4AjnPGfCA3jl3hY8uDg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "musl": ">=1.2.2", + "npm": ">=9.6.5", + "pnpm": ">=7.1.0", + "yarn": ">=3.2.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@humanwhocodes/module-importer": { + "node_modules/@img/sharp-libvips-linuxmusl-x64": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.0.1.tgz", + "integrity": "sha512-dcT7inI9DBFK6ovfeWRe3hG30h51cBAP5JXlZfx6pzc/Mnf9HFCQDLtYf4MCBjxaaTfjCCjkBxcy3XzOAo5txw==", + "cpu": [ + "x64" + ], "dev": true, - "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=12.22" + "musl": ">=1.2.2", + "npm": ">=9.6.5", + "pnpm": ">=7.1.0", + "yarn": ">=3.2.0" }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" + "url": "https://opencollective.com/libvips" } }, - "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.2", + "node_modules/@img/sharp-linux-arm": { + "version": "0.33.2", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.33.2.tgz", + "integrity": "sha512-Fndk/4Zq3vAc4G/qyfXASbS3HBZbKrlnKZLEJzPLrXoJuipFNNwTes71+Ki1hwYW5lch26niRYoZFAtZVf3EGA==", + "cpu": [ + "arm" + ], "dev": true, - "license": "BSD-3-Clause" + "optional": true, + "os": [ + "linux" + ], + "engines": { + "glibc": ">=2.28", + "node": "^18.17.0 || ^20.3.0 || >=21.0.0", + "npm": ">=9.6.5", + "pnpm": ">=7.1.0", + "yarn": ">=3.2.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm": "1.0.1" + } }, - "node_modules/@img/sharp-libvips-linux-x64": { - "version": "1.0.1", + "node_modules/@img/sharp-linux-arm64": { + "version": "0.33.2", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.33.2.tgz", + "integrity": "sha512-pz0NNo882vVfqJ0yNInuG9YH71smP4gRSdeL09ukC2YLE6ZyZePAlWKEHgAzJGTiOh8Qkaov6mMIMlEhmLdKew==", "cpu": [ - "x64" + "arm64" ], "dev": true, - "license": "LGPL-3.0-or-later", "optional": true, "os": [ "linux" ], "engines": { "glibc": ">=2.26", + "node": "^18.17.0 || ^20.3.0 || >=21.0.0", "npm": ">=9.6.5", "pnpm": ">=7.1.0", "yarn": ">=3.2.0" }, "funding": { "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm64": "1.0.1" } }, - "node_modules/@img/sharp-libvips-linuxmusl-x64": { - "version": "1.0.1", + "node_modules/@img/sharp-linux-s390x": { + "version": "0.33.2", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.33.2.tgz", + "integrity": "sha512-MBoInDXDppMfhSzbMmOQtGfloVAflS2rP1qPcUIiITMi36Mm5YR7r0ASND99razjQUpHTzjrU1flO76hKvP5RA==", "cpu": [ - "x64" + "s390x" ], "dev": true, - "license": "LGPL-3.0-or-later", "optional": true, "os": [ "linux" ], "engines": { - "musl": ">=1.2.2", + "glibc": ">=2.28", + "node": "^18.17.0 || ^20.3.0 || >=21.0.0", "npm": ">=9.6.5", "pnpm": ">=7.1.0", "yarn": ">=3.2.0" }, "funding": { "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-s390x": "1.0.1" } }, "node_modules/@img/sharp-linux-x64": { "version": "0.33.2", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.33.2.tgz", + "integrity": "sha512-xUT82H5IbXewKkeF5aiooajoO1tQV4PnKfS/OZtb5DDdxS/FCI/uXTVZ35GQ97RZXsycojz/AJ0asoz6p2/H/A==", "cpu": [ "x64" ], "dev": true, - "license": "Apache-2.0", "optional": true, "os": [ "linux" @@ -2529,13 +3363,40 @@ "@img/sharp-libvips-linux-x64": "1.0.1" } }, + "node_modules/@img/sharp-linuxmusl-arm64": { + "version": "0.33.2", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.33.2.tgz", + "integrity": "sha512-F+0z8JCu/UnMzg8IYW1TMeiViIWBVg7IWP6nE0p5S5EPQxlLd76c8jYemG21X99UzFwgkRo5yz2DS+zbrnxZeA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "musl": ">=1.2.2", + "node": "^18.17.0 || ^20.3.0 || >=21.0.0", + "npm": ">=9.6.5", + "pnpm": ">=7.1.0", + "yarn": ">=3.2.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-arm64": "1.0.1" + } + }, "node_modules/@img/sharp-linuxmusl-x64": { "version": "0.33.2", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.33.2.tgz", + "integrity": "sha512-+ZLE3SQmSL+Fn1gmSaM8uFusW5Y3J9VOf+wMGNnTtJUMUxFhv+P4UPaYEYT8tqnyYVaOVGgMN/zsOxn9pSsO2A==", "cpu": [ "x64" ], "dev": true, - "license": "Apache-2.0", "optional": true, "os": [ "linux" @@ -2554,11 +3415,75 @@ "@img/sharp-libvips-linuxmusl-x64": "1.0.1" } }, + "node_modules/@img/sharp-wasm32": { + "version": "0.33.2", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.33.2.tgz", + "integrity": "sha512-fLbTaESVKuQcpm8ffgBD7jLb/CQLcATju/jxtTXR1XCLwbOQt+OL5zPHSDMmp2JZIeq82e18yE0Vv7zh6+6BfQ==", + "cpu": [ + "wasm32" + ], + "dev": true, + "optional": true, + "dependencies": { + "@emnapi/runtime": "^0.45.0" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0", + "npm": ">=9.6.5", + "pnpm": ">=7.1.0", + "yarn": ">=3.2.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-ia32": { + "version": "0.33.2", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.33.2.tgz", + "integrity": "sha512-okBpql96hIGuZ4lN3+nsAjGeggxKm7hIRu9zyec0lnfB8E7Z6p95BuRZzDDXZOl2e8UmR4RhYt631i7mfmKU8g==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0", + "npm": ">=9.6.5", + "pnpm": ">=7.1.0", + "yarn": ">=3.2.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-x64": { + "version": "0.33.2", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.33.2.tgz", + "integrity": "sha512-E4magOks77DK47FwHUIGH0RYWSgRBfGdK56kIHSVeB9uIS4pPFr4N2kIVsXdQQo4LzOsENKV5KAhRlRL7eMAdg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0", + "npm": ">=9.6.5", + "pnpm": ">=7.1.0", + "yarn": ">=3.2.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, "node_modules/@ioredis/commands": { "version": "1.2.0", - "license": "MIT", - "optional": true, - "peer": true + "license": "MIT" }, "node_modules/@isaacs/cliui": { "version": "8.0.2", @@ -3006,13 +3931,13 @@ } }, "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.5", + "version": "0.3.3", "dev": true, "license": "MIT", "dependencies": { - "@jridgewell/set-array": "^1.2.1", + "@jridgewell/set-array": "^1.0.1", "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.24" + "@jridgewell/trace-mapping": "^0.3.9" }, "engines": { "node": ">=6.0.0" @@ -3027,7 +3952,7 @@ } }, "node_modules/@jridgewell/set-array": { - "version": "1.2.1", + "version": "1.1.2", "dev": true, "license": "MIT", "engines": { @@ -3049,7 +3974,7 @@ "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.25", + "version": "0.3.19", "dev": true, "license": "MIT", "dependencies": { @@ -3078,13 +4003,14 @@ }, "node_modules/@microsoft/tsdoc": { "version": "0.14.2", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/@microsoft/tsdoc/-/tsdoc-0.14.2.tgz", + "integrity": "sha512-9b8mPpKrfeGRuhFH5iO1iwCLeIIsV6+H1sRfxbkoGXIyQE2BTsPd9zqSqQJ+pv5sJ/hT5M1zvOFL02MnEezFug==" }, "node_modules/@microsoft/tsdoc-config": { "version": "0.16.2", + "resolved": "https://registry.npmjs.org/@microsoft/tsdoc-config/-/tsdoc-config-0.16.2.tgz", + "integrity": "sha512-OGiIzzoBLgWWR0UdRJX98oYO+XKGf7tiK4Zk6tQ/E4IJqGCe7dvkTvgDZV5cFJUzLGDOjeAXrnZoA6QkVySuxw==", "dev": true, - "license": "MIT", "dependencies": { "@microsoft/tsdoc": "0.14.2", "ajv": "~6.12.6", @@ -3094,8 +4020,9 @@ }, "node_modules/@microsoft/tsdoc-config/node_modules/ajv": { "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, - "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -3109,13 +4036,15 @@ }, "node_modules/@microsoft/tsdoc-config/node_modules/json-schema-traverse": { "version": "0.4.1", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true }, "node_modules/@microsoft/tsdoc-config/node_modules/resolve": { "version": "1.19.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.19.0.tgz", + "integrity": "sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==", "dev": true, - "license": "MIT", "dependencies": { "is-core-module": "^2.1.0", "path-parse": "^1.0.6" @@ -3154,7 +4083,8 @@ }, "node_modules/@mui/base": { "version": "5.0.0-beta.34", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-beta.34.tgz", + "integrity": "sha512-e2mbTGTtReD/y5RFwnhkl1Tgl3XwgJhY040IlfkTVaU9f5LWrVhEnpRsYXu3B1CtLrwiWs4cu7aMHV9yRd4jpw==", "dependencies": { "@babel/runtime": "^7.23.9", "@floating-ui/react-dom": "^2.0.8", @@ -3184,7 +4114,8 @@ }, "node_modules/@mui/core-downloads-tracker": { "version": "5.15.7", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.15.7.tgz", + "integrity": "sha512-AuF+Wo2Mp/edaO6vJnWjg+gj4tzEz5ChMZnAQpc22DXpSvM8ddgGcZvM7D7F99pIBoSv8ub+Iz0viL+yuGVmhg==", "funding": { "type": "opencollective", "url": "https://opencollective.com/mui-org" @@ -3192,7 +4123,8 @@ }, "node_modules/@mui/icons-material": { "version": "5.15.7", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@mui/icons-material/-/icons-material-5.15.7.tgz", + "integrity": "sha512-EDAc8TVJGIA/imAvR3u4nANl2W5h3QeHieu2gK7Ypez/nIA55p08tHjf8UrMXEpxCAvfZO6piY9S9uaxETdicA==", "dependencies": { "@babel/runtime": "^7.23.9" }, @@ -3216,7 +4148,8 @@ }, "node_modules/@mui/material": { "version": "5.15.7", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.15.7.tgz", + "integrity": "sha512-l6+AiKZH3iOJmZCnlpel8ghYQe9Lq0BEuKP8fGj3g5xz4arO9GydqYAtLPMvuHKtArj8lJGNuT2yHYxmejincA==", "dependencies": { "@babel/runtime": "^7.23.9", "@mui/base": "5.0.0-beta.34", @@ -3259,7 +4192,8 @@ }, "node_modules/@mui/private-theming": { "version": "5.15.7", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.15.7.tgz", + "integrity": "sha512-bcEeeXm7GyQCQvN9dwo8htGv8/6tP05p0i02Z7GXm5EoDPlBcqTNGugsjNLoGq6B0SsdyanjJGw0Jw00o1yAOA==", "dependencies": { "@babel/runtime": "^7.23.9", "@mui/utils": "^5.15.7", @@ -3284,7 +4218,8 @@ }, "node_modules/@mui/styled-engine": { "version": "5.15.7", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-5.15.7.tgz", + "integrity": "sha512-ixSdslOjK1kzdGcxqj7O3d14By/LPQ7EWknsViQ8RaeT863EAQemS+zvUJDTcOpkfJh6q6gPnYMIb2TJCs9eWA==", "dependencies": { "@babel/runtime": "^7.23.9", "@emotion/cache": "^11.11.0", @@ -3314,7 +4249,8 @@ }, "node_modules/@mui/system": { "version": "5.15.7", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.15.7.tgz", + "integrity": "sha512-9alZ4/dLxsTwUOdqakgzxiL5YW6ntqj0CfzWImgWnBMTZhgGcPsbYpBLniNkkk7/jptma4/bykWXHwju/ls/pg==", "dependencies": { "@babel/runtime": "^7.23.9", "@mui/private-theming": "^5.15.7", @@ -3352,7 +4288,8 @@ }, "node_modules/@mui/types": { "version": "7.2.13", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.2.13.tgz", + "integrity": "sha512-qP9OgacN62s+l8rdDhSFRe05HWtLLJ5TGclC9I1+tQngbssu0m2dmFZs+Px53AcOs9fD7TbYd4gc9AXzVqO/+g==", "peerDependencies": { "@types/react": "^17.0.0 || ^18.0.0" }, @@ -3364,7 +4301,8 @@ }, "node_modules/@mui/utils": { "version": "5.15.7", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.15.7.tgz", + "integrity": "sha512-8qhsxQRNV6aEOjjSk6YQIYJxkF5klhj8oG1FEEU4z6HV78TjNqRxMP08QGcdsibEbez+nihAaz6vu83b4XqbAg==", "dependencies": { "@babel/runtime": "^7.23.9", "@types/prop-types": "^15.7.11", @@ -3524,6 +4462,25 @@ } } }, + "node_modules/@nestjs/mapped-types": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nestjs/mapped-types/-/mapped-types-2.0.5.tgz", + "integrity": "sha512-bSJv4pd6EY99NX9CjBIyn4TVDoSit82DUZlL4I3bqNfy5Gt+gXTa86i3I/i0iIV9P4hntcGM5GyO+FhZAhxtyg==", + "peerDependencies": { + "@nestjs/common": "^8.0.0 || ^9.0.0 || ^10.0.0", + "class-transformer": "^0.4.0 || ^0.5.0", + "class-validator": "^0.13.0 || ^0.14.0", + "reflect-metadata": "^0.1.12 || ^0.2.0" + }, + "peerDependenciesMeta": { + "class-transformer": { + "optional": true + }, + "class-validator": { + "optional": true + } + } + }, "node_modules/@nestjs/microservices": { "version": "10.2.7", "license": "MIT", @@ -3695,6 +4652,38 @@ "node": ">=12" } }, + "node_modules/@nestjs/swagger": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/@nestjs/swagger/-/swagger-7.3.1.tgz", + "integrity": "sha512-LUC4mr+5oAleEC/a2j8pNRh1S5xhKXJ1Gal5ZdRjt9XebQgbngXCdW7JTA9WOEcwGtFZN9EnKYdquzH971LZfw==", + "dependencies": { + "@microsoft/tsdoc": "^0.14.2", + "@nestjs/mapped-types": "2.0.5", + "js-yaml": "4.1.0", + "lodash": "4.17.21", + "path-to-regexp": "3.2.0", + "swagger-ui-dist": "5.11.2" + }, + "peerDependencies": { + "@fastify/static": "^6.0.0 || ^7.0.0", + "@nestjs/common": "^9.0.0 || ^10.0.0", + "@nestjs/core": "^9.0.0 || ^10.0.0", + "class-transformer": "*", + "class-validator": "*", + "reflect-metadata": "^0.1.12 || ^0.2.0" + }, + "peerDependenciesMeta": { + "@fastify/static": { + "optional": true + }, + "class-transformer": { + "optional": true + }, + "class-validator": { + "optional": true + } + } + }, "node_modules/@nestjs/testing": { "version": "10.2.6", "dev": true, @@ -3846,8 +4835,9 @@ }, "node_modules/@pkgr/core": { "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz", + "integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==", "dev": true, - "license": "MIT", "engines": { "node": "^12.20.0 || ^14.18.0 || >=16.0.0" }, @@ -3857,7 +4847,8 @@ }, "node_modules/@popperjs/core": { "version": "2.11.8", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", + "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==", "funding": { "type": "opencollective", "url": "https://opencollective.com/popperjs" @@ -3916,35 +4907,181 @@ }, "node_modules/@remix-run/router": { "version": "1.15.3", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.15.3.tgz", + "integrity": "sha512-Oy8rmScVrVxWZVOpEF57ovlnhpZ8CCPlnIIumVcV9nFdiSIrus99+Lw78ekXyGvVDlIsFJbSfmSovJUhCWYV3w==", "engines": { "node": ">=14.0.0" } }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.9.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.9.6.tgz", + "integrity": "sha512-MVNXSSYN6QXOulbHpLMKYi60ppyO13W9my1qogeiAqtjb2yR4LSmfU2+POvDkLzhjYLXz9Rf9+9a3zFHW1Lecg==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.9.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.9.6.tgz", + "integrity": "sha512-T14aNLpqJ5wzKNf5jEDpv5zgyIqcpn1MlwCrUXLrwoADr2RkWA0vOWP4XxbO9aiO3dvMCQICZdKeDrFl7UMClw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.9.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.9.6.tgz", + "integrity": "sha512-CqNNAyhRkTbo8VVZ5R85X73H3R5NX9ONnKbXuHisGWC0qRbTTxnF1U4V9NafzJbgGM0sHZpdO83pLPzq8uOZFw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.9.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.9.6.tgz", + "integrity": "sha512-zRDtdJuRvA1dc9Mp6BWYqAsU5oeLixdfUvkTHuiYOHwqYuQ4YgSmi6+/lPvSsqc/I0Omw3DdICx4Tfacdzmhog==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.9.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.9.6.tgz", + "integrity": "sha512-oNk8YXDDnNyG4qlNb6is1ojTOGL/tRhbbKeE/YuccItzerEZT68Z9gHrY3ROh7axDc974+zYAPxK5SH0j/G+QQ==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.9.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.9.6.tgz", + "integrity": "sha512-Z3O60yxPtuCYobrtzjo0wlmvDdx2qZfeAWTyfOjEDqd08kthDKexLpV97KfAeUXPosENKd8uyJMRDfFMxcYkDQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.9.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.9.6.tgz", + "integrity": "sha512-gpiG0qQJNdYEVad+1iAsGAbgAnZ8j07FapmnIAQgODKcOTjLEWM9sRb+MbQyVsYCnA0Im6M6QIq6ax7liws6eQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.9.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.9.6.tgz", + "integrity": "sha512-+uCOcvVmFUYvVDr27aiyun9WgZk0tXe7ThuzoUTAukZJOwS5MrGbmSlNOhx1j80GdpqbOty05XqSl5w4dQvcOA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.14.3", + "version": "4.9.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.9.6.tgz", + "integrity": "sha512-HUNqM32dGzfBKuaDUBqFB7tP6VMN74eLZ33Q9Y1TBqRDn+qDonkAUyKWwF9BR9unV7QUzffLnz9GrnKvMqC/fw==", "cpu": [ "x64" ], "dev": true, - "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.14.3", + "version": "4.9.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.9.6.tgz", + "integrity": "sha512-ch7M+9Tr5R4FK40FHQk8VnML0Szi2KRujUgHXd/HjuH9ifH72GUmw6lStZBo3c3GB82vHa0ZoUfjfcM7JiiMrQ==", "cpu": [ "x64" ], "dev": true, - "license": "MIT", "optional": true, "os": [ "linux" ] }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.9.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.9.6.tgz", + "integrity": "sha512-VD6qnR99dhmTQ1mJhIzXsRcTBvTjbfbGGwKAHcu+52cVl15AC/kplkhxzW/uT0Xl62Y/meBKDZvoJSJN+vTeGA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.9.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.9.6.tgz", + "integrity": "sha512-J9AFDq/xiRI58eR2NIDfyVmTYGyIZmRcvcAoJ48oDld/NTR8wyiPUu2X/v1navJ+N/FGg68LEbX3Ejd6l8B7MQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.9.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.9.6.tgz", + "integrity": "sha512-jqzNLhNDvIZOrt69Ce4UjGRpXJBzhUBzawMwnaDAwyHriki3XollsewxWzOzz+4yOFDkuJHtTsZFwMxhYJWmLQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, "node_modules/@sentry-internal/tracing": { "version": "7.74.1", "license": "MIT", @@ -4118,8 +5255,9 @@ }, "node_modules/@surma/rollup-plugin-off-main-thread": { "version": "2.2.3", + "resolved": "https://registry.npmjs.org/@surma/rollup-plugin-off-main-thread/-/rollup-plugin-off-main-thread-2.2.3.tgz", + "integrity": "sha512-lR8q/9W7hZpMWweNiAKU7NQerBnzQQLvi8qnTDU/fxItPhtZVMbPV3lbCwjhIlNBe9Bbr5V+KHshvWmVSG9cxQ==", "dev": true, - "license": "Apache-2.0", "dependencies": { "ejs": "^3.1.6", "json5": "^2.2.0", @@ -4129,8 +5267,9 @@ }, "node_modules/@surma/rollup-plugin-off-main-thread/node_modules/magic-string": { "version": "0.25.9", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz", + "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==", "dev": true, - "license": "MIT", "dependencies": { "sourcemap-codec": "^1.4.8" } @@ -4179,9 +5318,10 @@ }, "node_modules/@swc/core": { "version": "1.3.107", + "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.3.107.tgz", + "integrity": "sha512-zKhqDyFcTsyLIYK1iEmavljZnf4CCor5pF52UzLAz4B6Nu/4GLU+2LQVAf+oRHjusG39PTPjd2AlRT3f3QWfsQ==", "dev": true, "hasInstallScript": true, - "license": "Apache-2.0", "dependencies": { "@swc/counter": "^0.1.1", "@swc/types": "^0.1.5" @@ -4214,13 +5354,94 @@ } } }, + "node_modules/@swc/core-darwin-arm64": { + "version": "1.3.107", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.3.107.tgz", + "integrity": "sha512-47tD/5vSXWxPd0j/ZllyQUg4bqalbQTsmqSw0J4dDdS82MWqCAwUErUrAZPRjBkjNQ6Kmrf5rpCWaGTtPw+ngw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-darwin-x64": { + "version": "1.3.107", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.3.107.tgz", + "integrity": "sha512-hwiLJ2ulNkBGAh1m1eTfeY1417OAYbRGcb/iGsJ+LuVLvKAhU/itzsl535CvcwAlt2LayeCFfcI8gdeOLeZa9A==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm-gnueabihf": { + "version": "1.3.107", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.3.107.tgz", + "integrity": "sha512-I2wzcC0KXqh0OwymCmYwNRgZ9nxX7DWnOOStJXV3pS0uB83TXAkmqd7wvMBuIl9qu4Hfomi9aDM7IlEEn9tumQ==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm64-gnu": { + "version": "1.3.107", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.3.107.tgz", + "integrity": "sha512-HWgnn7JORYlOYnGsdunpSF8A+BCZKPLzLtEUA27/M/ZuANcMZabKL9Zurt7XQXq888uJFAt98Gy+59PU90aHKg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm64-musl": { + "version": "1.3.107", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.3.107.tgz", + "integrity": "sha512-vfPF74cWfAm8hyhS8yvYI94ucMHIo8xIYU+oFOW9uvDlGQRgnUf/6DEVbLyt/3yfX5723Ln57U8uiMALbX5Pyw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, "node_modules/@swc/core-linux-x64-gnu": { "version": "1.3.107", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.3.107.tgz", + "integrity": "sha512-uBVNhIg0ip8rH9OnOsCARUFZ3Mq3tbPHxtmWk9uAa5u8jQwGWeBx5+nTHpDOVd3YxKb6+5xDEI/edeeLpha/9g==", "cpu": [ "x64" ], "dev": true, - "license": "Apache-2.0 AND MIT", "optional": true, "os": [ "linux" @@ -4231,11 +5452,12 @@ }, "node_modules/@swc/core-linux-x64-musl": { "version": "1.3.107", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.3.107.tgz", + "integrity": "sha512-mvACkUvzSIB12q1H5JtabWATbk3AG+pQgXEN95AmEX2ZA5gbP9+B+mijsg7Sd/3tboHr7ZHLz/q3SHTvdFJrEw==", "cpu": [ "x64" ], "dev": true, - "license": "Apache-2.0 AND MIT", "optional": true, "os": [ "linux" @@ -4244,15 +5466,83 @@ "node": ">=10" } }, + "node_modules/@swc/core-win32-arm64-msvc": { + "version": "1.3.107", + "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.3.107.tgz", + "integrity": "sha512-J3P14Ngy/1qtapzbguEH41kY109t6DFxfbK4Ntz9dOWNuVY3o9/RTB841ctnJk0ZHEG+BjfCJjsD2n8H5HcaOA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-ia32-msvc": { + "version": "1.3.107", + "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.3.107.tgz", + "integrity": "sha512-ZBUtgyjTHlz8TPJh7kfwwwFma+ktr6OccB1oXC8fMSopD0AxVnQasgun3l3099wIsAB9eEsJDQ/3lDkOLs1gBA==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-x64-msvc": { + "version": "1.3.107", + "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.3.107.tgz", + "integrity": "sha512-Eyzo2XRqWOxqhE1gk9h7LWmUf4Bp4Xn2Ttb0ayAXFp6YSTxQIThXcT9kipXZqcpxcmDwoq8iWbbf2P8XL743EA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, "node_modules/@swc/counter": { "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.2.tgz", + "integrity": "sha512-9F4ys4C74eSTEUNndnER3VJ15oru2NumfQxS8geE+f3eB5xvfxpWyqE5XlVnxb/R14uoXi6SLbBwwiDSkv+XEw==", + "dev": true + }, + "node_modules/@swc/register": { + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/@swc/register/-/register-0.1.10.tgz", + "integrity": "sha512-6STwH/q4dc3pitXLVkV7sP0Hiy+zBsU2wOF1aXpXR95pnH3RYHKIsDC+gvesfyB7jxNT9OOZgcqOp9RPxVTx9A==", + "deprecated": "Use @swc-node/register instead", "dev": true, - "license": "Apache-2.0" + "dependencies": { + "lodash.clonedeep": "^4.5.0", + "pirates": "^4.0.1", + "source-map-support": "^0.5.13" + }, + "bin": { + "swc-node": "bin/swc-node" + }, + "peerDependencies": { + "@swc/core": "^1.0.46" + } }, "node_modules/@swc/types": { "version": "0.1.5", - "dev": true, - "license": "Apache-2.0" + "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.5.tgz", + "integrity": "sha512-myfUej5naTBWnqOCc/MdVOLVjXUXtIA+NpDrDBKJtLLg2shUjBu3cZmB/85RyitKc55+lUUyl7oRfLOvkr2hsw==", + "dev": true }, "node_modules/@szmarczak/http-timer": { "version": "4.0.6", @@ -4269,7 +5559,8 @@ }, "node_modules/@tanstack/query-core": { "version": "5.20.5", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.20.5.tgz", + "integrity": "sha512-T1W28gGgWn0A++tH3lxj3ZuUVZZorsiKcv+R50RwmPYz62YoDEkG4/aXHZELGkRp4DfrW07dyq2K5dvJ4Wl1aA==", "funding": { "type": "github", "url": "https://github.com/sponsors/tannerlinsley" @@ -4277,7 +5568,8 @@ }, "node_modules/@tanstack/query-devtools": { "version": "5.20.2", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@tanstack/query-devtools/-/query-devtools-5.20.2.tgz", + "integrity": "sha512-BZfSjhk/NGPbqte5E3Vc1Zbj28uWt///4I0DgzAdWrOtMVvdl0WlUXK23K2daLsbcyfoDR4jRI4f2Z5z/mMzuw==", "funding": { "type": "github", "url": "https://github.com/sponsors/tannerlinsley" @@ -4285,7 +5577,8 @@ }, "node_modules/@tanstack/react-query": { "version": "5.20.5", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.20.5.tgz", + "integrity": "sha512-6MHwJ8G9cnOC/XKrwt56QMc91vN7hLlAQNUA0ubP7h9Jj3a/CmkUwT6ALdFbnVP+PsYdhW3WONa8WQ4VcTaSLQ==", "dependencies": { "@tanstack/query-core": "5.20.5" }, @@ -4299,7 +5592,8 @@ }, "node_modules/@tanstack/react-query-devtools": { "version": "5.20.5", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@tanstack/react-query-devtools/-/react-query-devtools-5.20.5.tgz", + "integrity": "sha512-Wl7IzNuKCb4h41a5iH/YXNwalHItqJPCAr4r8+0iUYOLHNOf3E9P0G4kzZ9sqDoWKxY04qst6Vrij9bwPzLQRQ==", "dependencies": { "@tanstack/query-devtools": "5.20.2" }, @@ -4328,8 +5622,9 @@ }, "node_modules/@trysound/sax": { "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", + "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", "dev": true, - "license": "ISC", "engines": { "node": ">=10.13.0" } @@ -4355,7 +5650,7 @@ "license": "MIT" }, "node_modules/@types/babel__core": { - "version": "7.20.5", + "version": "7.20.1", "dev": true, "license": "MIT", "dependencies": { @@ -4413,6 +5708,12 @@ "@types/responselike": "^1.0.0" } }, + "node_modules/@types/chai": { + "version": "4.3.14", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.14.tgz", + "integrity": "sha512-Wj71sXE4Q4AkGdG9Tvq1u/fquNz9EdG4LIJMwVVII7ashjD/8cf8fyIfJAjRr6YcsXnSE8cOGQPq1gqeR8z+3w==", + "dev": true + }, "node_modules/@types/connect": { "version": "3.4.36", "dev": true, @@ -4465,8 +5766,9 @@ }, "node_modules/@types/estree": { "version": "1.0.5", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", + "dev": true }, "node_modules/@types/express": { "version": "4.17.18", @@ -4518,8 +5820,9 @@ }, "node_modules/@types/hbs": { "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/hbs/-/hbs-4.0.4.tgz", + "integrity": "sha512-GH3SIb2tzDBnTByUSOIVcD6AcLufnydBllTuFAIAGMhqPNbz8GL4tLryVdNqhq0NQEb5mVpu2FJOrUeqwJrPtg==", "dev": true, - "license": "MIT", "dependencies": { "handlebars": "^4.1.0" } @@ -4596,7 +5899,8 @@ }, "node_modules/@types/prop-types": { "version": "15.7.11", - "license": "MIT" + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.11.tgz", + "integrity": "sha512-ga8y9v9uyeiLdpKddhxYQkxNDrfvuPrlFb0N1qnZZByvcElJaXthF1UhvCh9TLWJBEHeNtdnbysW7Y6Uq8CVng==" }, "node_modules/@types/qrcode": { "version": "1.5.5", @@ -4618,7 +5922,8 @@ }, "node_modules/@types/react": { "version": "18.2.48", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.48.tgz", + "integrity": "sha512-qboRCl6Ie70DQQG9hhNREz81jqC1cs9EVNcjQ1AU+jH6NFfSAhVVbrrY/+nSF+Bsk4AOwm9Qa61InvMCyV+H3w==", "dependencies": { "@types/prop-types": "*", "@types/scheduler": "*", @@ -4627,23 +5932,26 @@ }, "node_modules/@types/react-dom": { "version": "18.2.18", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.18.tgz", + "integrity": "sha512-TJxDm6OfAX2KJWJdMEVTwWke5Sc/E/RlnPGvGfS0W7+6ocy2xhDVQVh/KvC2Uf7kACs+gDytdusDSdWfWkaNzw==", "dev": true, - "license": "MIT", "dependencies": { "@types/react": "*" } }, "node_modules/@types/react-transition-group": { "version": "4.4.10", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.10.tgz", + "integrity": "sha512-hT/+s0VQs2ojCX823m60m5f0sL5idt9SO6Tj6Dg+rdphGPIeJbJ6CxvBYkgkGKrYeDjvIpKTR38UzmtHJOGW3Q==", "dependencies": { "@types/react": "*" } }, "node_modules/@types/resolve": { "version": "1.17.1", + "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz", + "integrity": "sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==", "dev": true, - "license": "MIT", "dependencies": { "@types/node": "*" } @@ -4660,12 +5968,14 @@ }, "node_modules/@types/scheduler": { "version": "0.16.8", - "license": "MIT" + "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.8.tgz", + "integrity": "sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A==" }, "node_modules/@types/semver": { "version": "7.5.8", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", + "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==", + "dev": true }, "node_modules/@types/send": { "version": "0.17.1", @@ -4728,8 +6038,9 @@ }, "node_modules/@types/trusted-types": { "version": "2.0.7", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", + "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==", + "dev": true }, "node_modules/@types/ua-parser-js": { "version": "0.7.37", @@ -4763,8 +6074,9 @@ }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.21.0.tgz", + "integrity": "sha512-oy9+hTPCUFpngkEZUSzbf9MxI65wbKFoQYsgPdILTfbUldp5ovUuphZVe4i30emU9M/kP+T64Di0mxl7dSw3MA==", "dev": true, - "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.5.1", "@typescript-eslint/scope-manager": "6.21.0", @@ -4797,8 +6109,9 @@ }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/scope-manager": { "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz", + "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==", "dev": true, - "license": "MIT", "dependencies": { "@typescript-eslint/types": "6.21.0", "@typescript-eslint/visitor-keys": "6.21.0" @@ -4813,8 +6126,9 @@ }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types": { "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz", + "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==", "dev": true, - "license": "MIT", "engines": { "node": "^16.0.0 || >=18.0.0" }, @@ -4825,8 +6139,9 @@ }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/visitor-keys": { "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz", + "integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==", "dev": true, - "license": "MIT", "dependencies": { "@typescript-eslint/types": "6.21.0", "eslint-visitor-keys": "^3.4.1" @@ -4841,8 +6156,9 @@ }, "node_modules/@typescript-eslint/parser": { "version": "6.20.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.20.0.tgz", + "integrity": "sha512-bYerPDF/H5v6V76MdMYhjwmwgMA+jlPVqjSDq2cRqMi8bP5sR3Z+RLOiOMad3nsnmDVmn2gAFCyNgh/dIrfP/w==", "dev": true, - "license": "BSD-2-Clause", "dependencies": { "@typescript-eslint/scope-manager": "6.20.0", "@typescript-eslint/types": "6.20.0", @@ -4868,8 +6184,9 @@ }, "node_modules/@typescript-eslint/scope-manager": { "version": "6.20.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.20.0.tgz", + "integrity": "sha512-p4rvHQRDTI1tGGMDFQm+GtxP1ZHyAh64WANVoyEcNMpaTFn3ox/3CcgtIlELnRfKzSs/DwYlDccJEtr3O6qBvA==", "dev": true, - "license": "MIT", "dependencies": { "@typescript-eslint/types": "6.20.0", "@typescript-eslint/visitor-keys": "6.20.0" @@ -4884,8 +6201,9 @@ }, "node_modules/@typescript-eslint/type-utils": { "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.21.0.tgz", + "integrity": "sha512-rZQI7wHfao8qMX3Rd3xqeYSMCL3SoiSQLBATSiVKARdFGCYSRvmViieZjqc58jKgs8Y8i9YvVVhRbHSTA4VBag==", "dev": true, - "license": "MIT", "dependencies": { "@typescript-eslint/typescript-estree": "6.21.0", "@typescript-eslint/utils": "6.21.0", @@ -4910,8 +6228,9 @@ }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types": { "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz", + "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==", "dev": true, - "license": "MIT", "engines": { "node": "^16.0.0 || >=18.0.0" }, @@ -4922,8 +6241,9 @@ }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree": { "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz", + "integrity": "sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==", "dev": true, - "license": "BSD-2-Clause", "dependencies": { "@typescript-eslint/types": "6.21.0", "@typescript-eslint/visitor-keys": "6.21.0", @@ -4949,8 +6269,9 @@ }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/visitor-keys": { "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz", + "integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==", "dev": true, - "license": "MIT", "dependencies": { "@typescript-eslint/types": "6.21.0", "eslint-visitor-keys": "^3.4.1" @@ -4965,16 +6286,18 @@ }, "node_modules/@typescript-eslint/type-utils/node_modules/brace-expansion": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, - "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } }, "node_modules/@typescript-eslint/type-utils/node_modules/minimatch": { "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", "dev": true, - "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, @@ -4987,8 +6310,9 @@ }, "node_modules/@typescript-eslint/types": { "version": "6.20.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.20.0.tgz", + "integrity": "sha512-MM9mfZMAhiN4cOEcUOEx+0HmuaW3WBfukBZPCfwSqFnQy0grXYtngKCqpQN339X3RrwtzspWJrpbrupKYUSBXQ==", "dev": true, - "license": "MIT", "engines": { "node": "^16.0.0 || >=18.0.0" }, @@ -4999,8 +6323,9 @@ }, "node_modules/@typescript-eslint/typescript-estree": { "version": "6.20.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.20.0.tgz", + "integrity": "sha512-RnRya9q5m6YYSpBN7IzKu9FmLcYtErkDkc8/dKv81I9QiLLtVBHrjz+Ev/crAqgMNW2FCsoZF4g2QUylMnJz+g==", "dev": true, - "license": "BSD-2-Clause", "dependencies": { "@typescript-eslint/types": "6.20.0", "@typescript-eslint/visitor-keys": "6.20.0", @@ -5026,16 +6351,18 @@ }, "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, - "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } }, "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", "dev": true, - "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, @@ -5048,8 +6375,9 @@ }, "node_modules/@typescript-eslint/utils": { "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.21.0.tgz", + "integrity": "sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==", "dev": true, - "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", @@ -5072,8 +6400,9 @@ }, "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/scope-manager": { "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz", + "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==", "dev": true, - "license": "MIT", "dependencies": { "@typescript-eslint/types": "6.21.0", "@typescript-eslint/visitor-keys": "6.21.0" @@ -5088,8 +6417,9 @@ }, "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/types": { "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz", + "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==", "dev": true, - "license": "MIT", "engines": { "node": "^16.0.0 || >=18.0.0" }, @@ -5100,8 +6430,9 @@ }, "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/typescript-estree": { "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz", + "integrity": "sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==", "dev": true, - "license": "BSD-2-Clause", "dependencies": { "@typescript-eslint/types": "6.21.0", "@typescript-eslint/visitor-keys": "6.21.0", @@ -5127,8 +6458,9 @@ }, "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/visitor-keys": { "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz", + "integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==", "dev": true, - "license": "MIT", "dependencies": { "@typescript-eslint/types": "6.21.0", "eslint-visitor-keys": "^3.4.1" @@ -5143,16 +6475,18 @@ }, "node_modules/@typescript-eslint/utils/node_modules/brace-expansion": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, - "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } }, "node_modules/@typescript-eslint/utils/node_modules/minimatch": { "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", "dev": true, - "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, @@ -5165,8 +6499,9 @@ }, "node_modules/@typescript-eslint/visitor-keys": { "version": "6.20.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.20.0.tgz", + "integrity": "sha512-E8Cp98kRe4gKHjJD4NExXKz/zOJ1A2hhZc+IMVD6i7w4yjIvh6VyuRI0gRtxAsXtoC35uGMaQ9rjI2zJaXDEAw==", "dev": true, - "license": "MIT", "dependencies": { "@typescript-eslint/types": "6.20.0", "eslint-visitor-keys": "^3.4.1" @@ -5181,13 +6516,15 @@ }, "node_modules/@ungap/structured-clone": { "version": "1.2.0", - "dev": true, - "license": "ISC" + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "dev": true }, "node_modules/@vitejs/plugin-react-swc": { "version": "3.6.0", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react-swc/-/plugin-react-swc-3.6.0.tgz", + "integrity": "sha512-XFRbsGgpGxGzEV5i5+vRiro1bwcIaZDIdBRP16qwm+jP68ue/S8FJTBEgOeojtVDYrbSua3XFp71kC8VJE6v+g==", "dev": true, - "license": "MIT", "dependencies": { "@swc/core": "^1.3.107" }, @@ -5352,7 +6689,7 @@ } }, "node_modules/acorn": { - "version": "8.11.3", + "version": "8.10.0", "dev": true, "license": "MIT", "bin": { @@ -5372,8 +6709,9 @@ }, "node_modules/acorn-jsx": { "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", "dev": true, - "license": "MIT", "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } @@ -5457,8 +6795,7 @@ }, "node_modules/algosdk": { "version": "2.7.0", - "resolved": "https://registry.npmjs.org/algosdk/-/algosdk-2.7.0.tgz", - "integrity": "sha512-sBE9lpV7bup3rZ+q2j3JQaFAE9JwZvjWKX00vPlG8e9txctXbgLL56jZhSWZndqhDI9oI+0P4NldkuQIWdrUyg==", + "license": "MIT", "dependencies": { "algo-msgpack-with-bigint": "^2.1.1", "buffer": "^6.0.3", @@ -5626,13 +6963,14 @@ }, "node_modules/argparse": { "version": "2.0.1", - "dev": true, - "license": "Python-2.0" + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" }, "node_modules/array-buffer-byte-length": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", + "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", "dev": true, - "license": "MIT", "dependencies": { "call-bind": "^1.0.5", "is-array-buffer": "^3.0.4" @@ -5655,16 +6993,18 @@ }, "node_modules/array-union": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", "dev": true, - "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/arraybuffer.prototype.slice": { "version": "1.0.3", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", + "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", "dev": true, - "license": "MIT", "dependencies": { "array-buffer-byte-length": "^1.0.1", "call-bind": "^1.0.5", @@ -5716,10 +7056,20 @@ "node": ">=12.0.0" } }, + "node_modules/assertion-error": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", + "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", + "dev": true, + "engines": { + "node": ">=12" + } + }, "node_modules/async": { "version": "3.2.5", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz", + "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==", + "dev": true }, "node_modules/asynckit": { "version": "0.4.0", @@ -5728,16 +7078,18 @@ }, "node_modules/at-least-node": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", "dev": true, - "license": "ISC", "engines": { "node": ">= 4.0.0" } }, "node_modules/available-typed-arrays": { "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", "dev": true, - "license": "MIT", "dependencies": { "possible-typed-array-names": "^1.0.0" }, @@ -5822,7 +7174,8 @@ }, "node_modules/babel-plugin-macros": { "version": "3.1.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", + "integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==", "dependencies": { "@babel/runtime": "^7.12.5", "cosmiconfig": "^7.0.0", @@ -5835,8 +7188,9 @@ }, "node_modules/babel-plugin-polyfill-corejs2": { "version": "0.4.8", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.8.tgz", + "integrity": "sha512-OtIuQfafSzpo/LhnJaykc0R/MMnuLSSVjVYy9mHArIZ9qTCSZ6TpWCuEKZYVoN//t8HqBNScHrOtCrIK5IaGLg==", "dev": true, - "license": "MIT", "dependencies": { "@babel/compat-data": "^7.22.6", "@babel/helper-define-polyfill-provider": "^0.5.0", @@ -5848,16 +7202,18 @@ }, "node_modules/babel-plugin-polyfill-corejs2/node_modules/semver": { "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, - "license": "ISC", "bin": { "semver": "bin/semver.js" } }, "node_modules/babel-plugin-polyfill-corejs3": { "version": "0.9.0", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.9.0.tgz", + "integrity": "sha512-7nZPG1uzK2Ymhy/NbaOWTg3uibM2BmGASS4vHS4szRZAIR8R6GwA/xAujpdrXU5iyklrimWnLWU+BLF9suPTqg==", "dev": true, - "license": "MIT", "dependencies": { "@babel/helper-define-polyfill-provider": "^0.5.0", "core-js-compat": "^3.34.0" @@ -5868,8 +7224,9 @@ }, "node_modules/babel-plugin-polyfill-regenerator": { "version": "0.5.5", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.5.5.tgz", + "integrity": "sha512-OJGYZlhLqBh2DDHeqAxWB1XIvr49CxiJ2gIt61/PU55CQK4Z58OzMqjDe1zwQdQk+rBYsRc+1rJmdajM3gimHg==", "dev": true, - "license": "MIT", "dependencies": { "@babel/helper-define-polyfill-provider": "^0.5.0" }, @@ -6204,8 +7561,9 @@ }, "node_modules/boolbase": { "version": "1.0.0", - "dev": true, - "license": "ISC" + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "dev": true }, "node_modules/brace-expansion": { "version": "1.1.11", @@ -6232,6 +7590,8 @@ }, "node_modules/browserslist": { "version": "4.23.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz", + "integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==", "dev": true, "funding": [ { @@ -6247,7 +7607,6 @@ "url": "https://github.com/sponsors/ai" } ], - "license": "MIT", "dependencies": { "caniuse-lite": "^1.0.30001587", "electron-to-chromium": "^1.4.668", @@ -6315,8 +7674,9 @@ }, "node_modules/builtin-modules": { "version": "3.3.0", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz", + "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==", "dev": true, - "license": "MIT", "engines": { "node": ">=6" }, @@ -6486,7 +7846,8 @@ }, "node_modules/call-bind": { "version": "1.0.7", - "license": "MIT", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", "dependencies": { "es-define-property": "^1.0.0", "es-errors": "^1.3.0", @@ -6518,6 +7879,8 @@ }, "node_modules/caniuse-lite": { "version": "1.0.30001587", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001587.tgz", + "integrity": "sha512-HMFNotUmLXn71BQxg8cijvqxnIAofforZOwGsxyXJ0qugTdspUF4sPSJ2vhgprHCB996tIDzEq1ubumPDV8ULA==", "dev": true, "funding": [ { @@ -6532,8 +7895,7 @@ "type": "github", "url": "https://github.com/sponsors/ai" } - ], - "license": "CC-BY-4.0" + ] }, "node_modules/cbor": { "version": "5.2.0", @@ -6546,6 +7908,22 @@ "node": ">=6.0.0" } }, + "node_modules/chai": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/chai/-/chai-5.1.0.tgz", + "integrity": "sha512-kDZ7MZyM6Q1DhR9jy7dalKohXQ2yrlXkk59CR52aRKxJrobmlBNqnFQxX9xOX8w+4mz8SYlKJa/7D7ddltFXCw==", + "dev": true, + "dependencies": { + "assertion-error": "^2.0.1", + "check-error": "^2.0.0", + "deep-eql": "^5.0.1", + "loupe": "^3.1.0", + "pathval": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/chalk": { "version": "4.1.2", "license": "MIT", @@ -6573,6 +7951,15 @@ "dev": true, "license": "MIT" }, + "node_modules/check-error": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.0.0.tgz", + "integrity": "sha512-tjLAOBHKVxtPoHe/SA7kNOMvhCRdCJ3vETdeY0RuAc9popf+hyaSV6ZEg9hr4cpWF7jmo/JSWEnLDrnijS9Tog==", + "dev": true, + "engines": { + "node": ">= 16" + } + }, "node_modules/chokidar": { "version": "3.5.3", "dev": true, @@ -6736,7 +8123,8 @@ }, "node_modules/clsx": { "version": "2.1.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.0.tgz", + "integrity": "sha512-m3iNNWpd9rl3jvvcBnu70ylMdrXt8Vlq4HYadnU5fwcOtvkSQWPmj7amUcDT2qYI7risszBjI5AUIUox9D16pg==", "engines": { "node": ">=6" } @@ -6764,8 +8152,9 @@ }, "node_modules/color": { "version": "4.2.3", + "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", + "integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==", "dev": true, - "license": "MIT", "dependencies": { "color-convert": "^2.0.1", "color-string": "^1.9.0" @@ -6790,8 +8179,9 @@ }, "node_modules/color-string": { "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", + "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", "dev": true, - "license": "MIT", "dependencies": { "color-name": "^1.0.0", "simple-swizzle": "^0.2.2" @@ -6840,8 +8230,9 @@ }, "node_modules/common-tags": { "version": "1.8.2", + "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.2.tgz", + "integrity": "sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==", "dev": true, - "license": "MIT", "engines": { "node": ">=4.0.0" } @@ -6870,8 +8261,9 @@ }, "node_modules/concurrently": { "version": "8.2.2", + "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-8.2.2.tgz", + "integrity": "sha512-1dP4gpXFhei8IOtlXRE/T/4H88ElHgTiUzh71YUmtjTEHMSRS2Z/fgOxHSxxusGHogsRfxNq1vyAwxSC+EVyDg==", "dev": true, - "license": "MIT", "dependencies": { "chalk": "^4.1.2", "date-fns": "^2.30.0", @@ -6896,8 +8288,9 @@ }, "node_modules/concurrently/node_modules/supports-color": { "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, - "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -6989,8 +8382,9 @@ }, "node_modules/core-js-compat": { "version": "3.36.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.36.0.tgz", + "integrity": "sha512-iV9Pd/PsgjNWBXeq8XRtWVSgz2tKAfhfvBs7qxYty+RlRd+OCksaWmOnc4JKrTc1cToXL1N0s3l/vwlxPtdElw==", "dev": true, - "license": "MIT", "dependencies": { "browserslist": "^4.22.3" }, @@ -7091,16 +8485,18 @@ }, "node_modules/crypto-random-string": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", + "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", "dev": true, - "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/css-select": { "version": "5.1.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", + "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", "dev": true, - "license": "BSD-2-Clause", "dependencies": { "boolbase": "^1.0.0", "css-what": "^6.1.0", @@ -7114,8 +8510,9 @@ }, "node_modules/css-tree": { "version": "2.3.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz", + "integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==", "dev": true, - "license": "MIT", "dependencies": { "mdn-data": "2.0.30", "source-map-js": "^1.0.1" @@ -7126,8 +8523,9 @@ }, "node_modules/css-what": { "version": "6.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", "dev": true, - "license": "BSD-2-Clause", "engines": { "node": ">= 6" }, @@ -7137,8 +8535,9 @@ }, "node_modules/csso": { "version": "5.0.5", + "resolved": "https://registry.npmjs.org/csso/-/csso-5.0.5.tgz", + "integrity": "sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==", "dev": true, - "license": "MIT", "dependencies": { "css-tree": "~2.2.0" }, @@ -7149,8 +8548,9 @@ }, "node_modules/csso/node_modules/css-tree": { "version": "2.2.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.2.1.tgz", + "integrity": "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==", "dev": true, - "license": "MIT", "dependencies": { "mdn-data": "2.0.28", "source-map-js": "^1.0.1" @@ -7162,12 +8562,14 @@ }, "node_modules/csso/node_modules/mdn-data": { "version": "2.0.28", - "dev": true, - "license": "CC0-1.0" + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.28.tgz", + "integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==", + "dev": true }, "node_modules/csstype": { "version": "3.1.3", - "license": "MIT" + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" }, "node_modules/dapp-ui": { "resolved": "sites/dapp-ui", @@ -7175,8 +8577,9 @@ }, "node_modules/data-view-buffer": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", + "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", "dev": true, - "license": "MIT", "dependencies": { "call-bind": "^1.0.6", "es-errors": "^1.3.0", @@ -7191,8 +8594,9 @@ }, "node_modules/data-view-byte-length": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", + "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", "dev": true, - "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "es-errors": "^1.3.0", @@ -7207,8 +8611,9 @@ }, "node_modules/data-view-byte-offset": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", + "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", "dev": true, - "license": "MIT", "dependencies": { "call-bind": "^1.0.6", "es-errors": "^1.3.0", @@ -7223,8 +8628,9 @@ }, "node_modules/date-fns": { "version": "2.30.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz", + "integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==", "dev": true, - "license": "MIT", "dependencies": { "@babel/runtime": "^7.21.0" }, @@ -7293,6 +8699,15 @@ } } }, + "node_modules/deep-eql": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.1.tgz", + "integrity": "sha512-nwQCf6ne2gez3o1MxWifqkciwt0zhl0LO1/UwVu4uMBuPmflWM4oQ70XMqHqnBJA+nhzncaqL9HVL6KkHJ28lw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/deep-is": { "version": "0.1.4", "dev": true, @@ -7329,7 +8744,8 @@ }, "node_modules/define-data-property": { "version": "1.1.4", - "license": "MIT", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", "dependencies": { "es-define-property": "^1.0.0", "es-errors": "^1.3.0", @@ -7344,8 +8760,9 @@ }, "node_modules/define-properties": { "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", "dev": true, - "license": "MIT", "dependencies": { "define-data-property": "^1.0.1", "has-property-descriptors": "^1.0.0", @@ -7360,8 +8777,9 @@ }, "node_modules/define-properties/node_modules/object-keys": { "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", "dev": true, - "license": "MIT", "engines": { "node": ">= 0.4" } @@ -7381,8 +8799,6 @@ "node_modules/denque": { "version": "2.1.0", "license": "Apache-2.0", - "optional": true, - "peer": true, "engines": { "node": ">=0.10" } @@ -7444,8 +8860,9 @@ }, "node_modules/dir-glob": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", "dev": true, - "license": "MIT", "dependencies": { "path-type": "^4.0.0" }, @@ -7466,7 +8883,8 @@ }, "node_modules/dom-helpers": { "version": "5.2.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz", + "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==", "dependencies": { "@babel/runtime": "^7.8.7", "csstype": "^3.0.2" @@ -7474,8 +8892,9 @@ }, "node_modules/dom-serializer": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", "dev": true, - "license": "MIT", "dependencies": { "domelementtype": "^2.3.0", "domhandler": "^5.0.2", @@ -7487,19 +8906,21 @@ }, "node_modules/domelementtype": { "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", "dev": true, "funding": [ { "type": "github", "url": "https://github.com/sponsors/fb55" } - ], - "license": "BSD-2-Clause" + ] }, "node_modules/domhandler": { "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", "dev": true, - "license": "BSD-2-Clause", "dependencies": { "domelementtype": "^2.3.0" }, @@ -7512,8 +8933,9 @@ }, "node_modules/domutils": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz", + "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==", "dev": true, - "license": "BSD-2-Clause", "dependencies": { "dom-serializer": "^2.0.0", "domelementtype": "^2.3.0", @@ -7542,7 +8964,8 @@ }, "node_modules/duplexer2": { "version": "0.1.4", - "license": "BSD-3-Clause", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", + "integrity": "sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA==", "dependencies": { "readable-stream": "^2.0.2" } @@ -7557,8 +8980,9 @@ }, "node_modules/ejs": { "version": "3.1.9", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.9.tgz", + "integrity": "sha512-rC+QVNMJWv+MtPgkt0y+0rVEIdbtxVADApW9JXrUVlzHetgcyczP/E7DJmWJ4fJCZF2cPcBk0laWO9ZHMG3DmQ==", "dev": true, - "license": "Apache-2.0", "dependencies": { "jake": "^10.8.5" }, @@ -7571,8 +8995,9 @@ }, "node_modules/electron-to-chromium": { "version": "1.4.670", - "dev": true, - "license": "ISC" + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.670.tgz", + "integrity": "sha512-hcijYOWjOtjKrKPtNA6tuLlA/bTLO3heFG8pQA6mLpq7dRydSWicXova5lyxDzp1iVJaYhK7J2OQlGE52KYn7A==", + "dev": true }, "node_modules/elliptic": { "version": "6.5.4", @@ -7657,7 +9082,8 @@ }, "node_modules/engine.io-client": { "version": "6.5.3", - "license": "MIT", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.5.3.tgz", + "integrity": "sha512-9Z0qLB0NIisTRt1DZ/8U2k12RJn8yls/nXMZLn+/N8hANT3TcYjKFKcwbw5zFQiN4NTde3TSY9zb79e1ij6j9Q==", "dependencies": { "@socket.io/component-emitter": "~3.1.0", "debug": "~4.3.1", @@ -7694,8 +9120,9 @@ }, "node_modules/entities": { "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", "dev": true, - "license": "BSD-2-Clause", "engines": { "node": ">=0.12" }, @@ -7723,8 +9150,9 @@ }, "node_modules/es-abstract": { "version": "1.23.3", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz", + "integrity": "sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==", "dev": true, - "license": "MIT", "dependencies": { "array-buffer-byte-length": "^1.0.1", "arraybuffer.prototype.slice": "^1.0.3", @@ -7782,15 +9210,17 @@ }, "node_modules/es-abstract/node_modules/object-keys": { "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", "dev": true, - "license": "MIT", "engines": { "node": ">= 0.4" } }, "node_modules/es-define-property": { "version": "1.0.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", "dependencies": { "get-intrinsic": "^1.2.4" }, @@ -7800,20 +9230,22 @@ }, "node_modules/es-errors": { "version": "1.3.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", "engines": { "node": ">= 0.4" } }, "node_modules/es-module-lexer": { - "version": "1.5.0", + "version": "1.3.1", "dev": true, "license": "MIT" }, "node_modules/es-object-atoms": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", + "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", "dev": true, - "license": "MIT", "dependencies": { "es-errors": "^1.3.0" }, @@ -7823,8 +9255,9 @@ }, "node_modules/es-set-tostringtag": { "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", + "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", "dev": true, - "license": "MIT", "dependencies": { "get-intrinsic": "^1.2.4", "has-tostringtag": "^1.0.2", @@ -7836,8 +9269,9 @@ }, "node_modules/es-to-primitive": { "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", "dev": true, - "license": "MIT", "dependencies": { "is-callable": "^1.1.4", "is-date-object": "^1.0.1", @@ -7850,6 +9284,44 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/esbuild": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.12.tgz", + "integrity": "sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.19.12", + "@esbuild/android-arm": "0.19.12", + "@esbuild/android-arm64": "0.19.12", + "@esbuild/android-x64": "0.19.12", + "@esbuild/darwin-arm64": "0.19.12", + "@esbuild/darwin-x64": "0.19.12", + "@esbuild/freebsd-arm64": "0.19.12", + "@esbuild/freebsd-x64": "0.19.12", + "@esbuild/linux-arm": "0.19.12", + "@esbuild/linux-arm64": "0.19.12", + "@esbuild/linux-ia32": "0.19.12", + "@esbuild/linux-loong64": "0.19.12", + "@esbuild/linux-mips64el": "0.19.12", + "@esbuild/linux-ppc64": "0.19.12", + "@esbuild/linux-riscv64": "0.19.12", + "@esbuild/linux-s390x": "0.19.12", + "@esbuild/linux-x64": "0.19.12", + "@esbuild/netbsd-x64": "0.19.12", + "@esbuild/openbsd-x64": "0.19.12", + "@esbuild/sunos-x64": "0.19.12", + "@esbuild/win32-arm64": "0.19.12", + "@esbuild/win32-ia32": "0.19.12", + "@esbuild/win32-x64": "0.19.12" + } + }, "node_modules/escalade": { "version": "3.1.1", "dev": true, @@ -7874,8 +9346,9 @@ }, "node_modules/eslint": { "version": "8.57.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", + "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", "dev": true, - "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", @@ -7928,8 +9401,9 @@ }, "node_modules/eslint-config-prettier": { "version": "9.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", + "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", "dev": true, - "license": "MIT", "bin": { "eslint-config-prettier": "bin/cli.js" }, @@ -7939,8 +9413,9 @@ }, "node_modules/eslint-plugin-prettier": { "version": "5.1.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.1.3.tgz", + "integrity": "sha512-C9GCVAs4Eq7ZC/XFQHITLiHJxQngdtraXaM+LoUFoFp/lHNl2Zn8f3WQbe9HvTBBQ9YnKFB0/2Ajdqwo5D1EAw==", "dev": true, - "license": "MIT", "dependencies": { "prettier-linter-helpers": "^1.0.0", "synckit": "^0.8.6" @@ -7968,8 +9443,9 @@ }, "node_modules/eslint-plugin-react-hooks": { "version": "4.6.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz", + "integrity": "sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==", "dev": true, - "license": "MIT", "engines": { "node": ">=10" }, @@ -7979,8 +9455,9 @@ }, "node_modules/eslint-plugin-react-refresh": { "version": "0.4.5", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.5.tgz", + "integrity": "sha512-D53FYKJa+fDmZMtriODxvhwrO+IOqrxoEo21gMA0sjHdU6dPVH4OhyFip9ypl8HOF5RV5KdTo+rBQLvnY2cO8w==", "dev": true, - "license": "MIT", "peerDependencies": { "eslint": ">=7" } @@ -8054,8 +9531,9 @@ }, "node_modules/espree": { "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", "dev": true, - "license": "BSD-2-Clause", "dependencies": { "acorn": "^8.9.0", "acorn-jsx": "^5.3.2", @@ -8112,8 +9590,9 @@ }, "node_modules/estree-walker": { "version": "1.0.1", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz", + "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==", + "dev": true }, "node_modules/esutils": { "version": "2.0.3", @@ -8132,7 +9611,8 @@ }, "node_modules/eventemitter3": { "version": "5.0.1", - "license": "MIT" + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==" }, "node_modules/events": { "version": "3.3.0", @@ -8400,8 +9880,9 @@ }, "node_modules/fast-glob": { "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", "dev": true, - "license": "MIT", "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", @@ -8496,24 +9977,27 @@ }, "node_modules/filelist": { "version": "1.0.4", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", + "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", "dev": true, - "license": "Apache-2.0", "dependencies": { "minimatch": "^5.0.1" } }, "node_modules/filelist/node_modules/brace-expansion": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, - "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } }, "node_modules/filelist/node_modules/minimatch": { "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", "dev": true, - "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, @@ -8592,7 +10076,8 @@ }, "node_modules/find-root": { "version": "1.1.0", - "license": "MIT" + "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", + "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==" }, "node_modules/find-up": { "version": "5.0.0", @@ -8659,8 +10144,9 @@ }, "node_modules/for-each": { "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", "dev": true, - "license": "MIT", "dependencies": { "is-callable": "^1.1.3" } @@ -8796,17 +10282,33 @@ "version": "1.0.0", "license": "ISC" }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, "node_modules/function-bind": { "version": "1.1.2", - "license": "MIT", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/function.prototype.name": { "version": "1.1.6", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", + "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", "dev": true, - "license": "MIT", "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.2.0", @@ -8822,8 +10324,9 @@ }, "node_modules/functions-have-names": { "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", "dev": true, - "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -8868,9 +10371,19 @@ "node": "6.* || 8.* || >= 10.*" } }, + "node_modules/get-func-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", + "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", + "dev": true, + "engines": { + "node": "*" + } + }, "node_modules/get-intrinsic": { "version": "1.2.4", - "license": "MIT", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2", @@ -8887,8 +10400,9 @@ }, "node_modules/get-own-enumerable-property-symbols": { "version": "3.0.2", - "dev": true, - "license": "ISC" + "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz", + "integrity": "sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==", + "dev": true }, "node_modules/get-package-type": { "version": "0.1.0", @@ -8911,8 +10425,9 @@ }, "node_modules/get-symbol-description": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", + "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", "dev": true, - "license": "MIT", "dependencies": { "call-bind": "^1.0.5", "es-errors": "^1.3.0", @@ -8925,6 +10440,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/get-tsconfig": { + "version": "4.7.3", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.3.tgz", + "integrity": "sha512-ZvkrzoUA0PQZM6fy6+/Hce561s+faD1rsNwhnO5FelNjyy7EMGJ3Rz1AQ8GYDWjhRs/7dBLOEJvhK8MiEJOAFg==", + "dev": true, + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, "node_modules/glob": { "version": "7.2.3", "license": "ISC", @@ -8961,8 +10488,9 @@ }, "node_modules/globals": { "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", "dev": true, - "license": "MIT", "dependencies": { "type-fest": "^0.20.2" }, @@ -8975,8 +10503,9 @@ }, "node_modules/globalthis": { "version": "1.0.3", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", + "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", "dev": true, - "license": "MIT", "dependencies": { "define-properties": "^1.1.3" }, @@ -8989,8 +10518,9 @@ }, "node_modules/globby": { "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", "dev": true, - "license": "MIT", "dependencies": { "array-union": "^2.1.0", "dir-glob": "^3.0.1", @@ -9008,7 +10538,8 @@ }, "node_modules/gopd": { "version": "1.0.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", "dependencies": { "get-intrinsic": "^1.1.3" }, @@ -9053,8 +10584,9 @@ }, "node_modules/handlebars": { "version": "4.7.7", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", + "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==", "dev": true, - "license": "MIT", "dependencies": { "minimist": "^1.2.5", "neo-async": "^2.6.0", @@ -9073,16 +10605,18 @@ }, "node_modules/handlebars/node_modules/source-map": { "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, - "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" } }, "node_modules/has-bigints": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", "dev": true, - "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -9104,7 +10638,8 @@ }, "node_modules/has-property-descriptors": { "version": "1.0.2", - "license": "MIT", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", "dependencies": { "es-define-property": "^1.0.0" }, @@ -9114,7 +10649,8 @@ }, "node_modules/has-proto": { "version": "1.0.3", - "license": "MIT", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", "engines": { "node": ">= 0.4" }, @@ -9134,8 +10670,9 @@ }, "node_modules/has-tostringtag": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", "dev": true, - "license": "MIT", "dependencies": { "has-symbols": "^1.0.3" }, @@ -9160,7 +10697,8 @@ }, "node_modules/hasown": { "version": "2.0.2", - "license": "MIT", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", "dependencies": { "function-bind": "^1.1.2" }, @@ -9178,7 +10716,8 @@ }, "node_modules/hi-base32": { "version": "0.5.1", - "license": "MIT" + "resolved": "https://registry.npmjs.org/hi-base32/-/hi-base32-0.5.1.tgz", + "integrity": "sha512-EmBBpvdYh/4XxsnUybsPag6VikPYnN30td+vQk+GI3qpahVEG9+gTkG0aXVxTjBqQ5T6ijbWIu77O+C5WFWsnA==" }, "node_modules/hmac-drbg": { "version": "1.0.1", @@ -9191,14 +10730,16 @@ }, "node_modules/hoist-non-react-statics": { "version": "3.3.2", - "license": "BSD-3-Clause", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", "dependencies": { "react-is": "^16.7.0" } }, "node_modules/hoist-non-react-statics/node_modules/react-is": { "version": "16.13.1", - "license": "MIT" + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, "node_modules/html-escaper": { "version": "2.0.2", @@ -9207,7 +10748,8 @@ }, "node_modules/html-tokenize": { "version": "2.0.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/html-tokenize/-/html-tokenize-2.0.1.tgz", + "integrity": "sha512-QY6S+hZ0f5m1WT8WffYN+Hg+xm/w5I8XeUcAq/ZYP5wVC8xbKi4Whhru3FtrAebD5EhBW8rmFzkDI6eCAuFe2w==", "dependencies": { "buffer-from": "~0.1.1", "inherits": "~2.0.1", @@ -9221,15 +10763,18 @@ }, "node_modules/html-tokenize/node_modules/buffer-from": { "version": "0.1.2", - "license": "MIT" + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-0.1.2.tgz", + "integrity": "sha512-RiWIenusJsmI2KcvqQABB83tLxCByE3upSP8QU3rJDMVFGPWLvPQJt/O1Su9moRWeH7d+Q2HYb68f6+v+tw2vg==" }, "node_modules/html-tokenize/node_modules/isarray": { "version": "0.0.1", - "license": "MIT" + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==" }, "node_modules/html-tokenize/node_modules/readable-stream": { "version": "1.0.34", - "license": "MIT", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha512-ok1qVCJuRkNmvebYikljxJA/UEsKwLl2nI1OmaqAu4/UE+h0wKCHok4XkL/gvi39OacXvw59RJUOFUkDib2rHg==", "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.1", @@ -9239,7 +10784,8 @@ }, "node_modules/html-tokenize/node_modules/string_decoder": { "version": "0.10.31", - "license": "MIT" + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==" }, "node_modules/http-cache-semantics": { "version": "4.1.1", @@ -9323,8 +10869,9 @@ }, "node_modules/idb": { "version": "7.1.1", - "dev": true, - "license": "ISC" + "resolved": "https://registry.npmjs.org/idb/-/idb-7.1.1.tgz", + "integrity": "sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ==", + "dev": true }, "node_modules/ieee754": { "version": "1.2.1", @@ -9437,8 +10984,9 @@ }, "node_modules/internal-slot": { "version": "1.0.7", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", + "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", "dev": true, - "license": "MIT", "dependencies": { "es-errors": "^1.3.0", "hasown": "^2.0.0", @@ -9457,10 +11005,9 @@ } }, "node_modules/ioredis": { - "version": "5.3.2", - "license": "MIT", - "optional": true, - "peer": true, + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-5.4.1.tgz", + "integrity": "sha512-2YZsvl7jopIa1gaePkeMtd9rAcSjOOjPtpcLlOeusyO+XH2SK5ZcT+UCrElPP+WVIInh2TzeI4XW9ENaSLVVHA==", "dependencies": { "@ioredis/commands": "^1.1.1", "cluster-key-slot": "^1.1.0", @@ -9493,8 +11040,9 @@ }, "node_modules/is-array-buffer": { "version": "3.0.4", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", + "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", "dev": true, - "license": "MIT", "dependencies": { "call-bind": "^1.0.2", "get-intrinsic": "^1.2.1" @@ -9512,8 +11060,9 @@ }, "node_modules/is-bigint": { "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", "dev": true, - "license": "MIT", "dependencies": { "has-bigints": "^1.0.1" }, @@ -9534,8 +11083,9 @@ }, "node_modules/is-boolean-object": { "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", "dev": true, - "license": "MIT", "dependencies": { "call-bind": "^1.0.2", "has-tostringtag": "^1.0.0" @@ -9549,8 +11099,9 @@ }, "node_modules/is-callable": { "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", "dev": true, - "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -9560,7 +11111,8 @@ }, "node_modules/is-core-module": { "version": "2.13.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", + "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", "dependencies": { "hasown": "^2.0.0" }, @@ -9570,8 +11122,9 @@ }, "node_modules/is-data-view": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz", + "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==", "dev": true, - "license": "MIT", "dependencies": { "is-typed-array": "^1.1.13" }, @@ -9584,8 +11137,9 @@ }, "node_modules/is-date-object": { "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", "dev": true, - "license": "MIT", "dependencies": { "has-tostringtag": "^1.0.0" }, @@ -9644,13 +11198,15 @@ }, "node_modules/is-module": { "version": "1.0.0", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", + "integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==", + "dev": true }, "node_modules/is-negative-zero": { "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", "dev": true, - "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -9668,8 +11224,9 @@ }, "node_modules/is-number-object": { "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", "dev": true, - "license": "MIT", "dependencies": { "has-tostringtag": "^1.0.0" }, @@ -9682,8 +11239,9 @@ }, "node_modules/is-obj": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", + "integrity": "sha512-l4RyHgRqGN4Y3+9JHVrNqO+tN0rV5My76uW5/nuO4K1b6vw5G8d/cmFjP9tRfEsdhZNt0IFdZuK/c2Vr4Nb+Qg==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -9708,8 +11266,9 @@ }, "node_modules/is-regex": { "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", "dev": true, - "license": "MIT", "dependencies": { "call-bind": "^1.0.2", "has-tostringtag": "^1.0.0" @@ -9723,16 +11282,18 @@ }, "node_modules/is-regexp": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz", + "integrity": "sha512-7zjFAPO4/gwyQAAgRRmqeEeyIICSdmCqa3tsVHMdBzaXXRiqopZL4Cyghg/XulGWrtABTpbnYYzzIRffLkP4oA==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/is-shared-array-buffer": { "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", + "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", "dev": true, - "license": "MIT", "dependencies": { "call-bind": "^1.0.7" }, @@ -9756,8 +11317,9 @@ }, "node_modules/is-string": { "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", "dev": true, - "license": "MIT", "dependencies": { "has-tostringtag": "^1.0.0" }, @@ -9770,8 +11332,9 @@ }, "node_modules/is-symbol": { "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", "dev": true, - "license": "MIT", "dependencies": { "has-symbols": "^1.0.2" }, @@ -9784,8 +11347,9 @@ }, "node_modules/is-typed-array": { "version": "1.1.13", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", + "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", "dev": true, - "license": "MIT", "dependencies": { "which-typed-array": "^1.1.14" }, @@ -9809,8 +11373,9 @@ }, "node_modules/is-weakref": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", "dev": true, - "license": "MIT", "dependencies": { "call-bind": "^1.0.2" }, @@ -9826,6 +11391,15 @@ "version": "2.0.0", "license": "ISC" }, + "node_modules/isomorphic-fetch": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-3.0.0.tgz", + "integrity": "sha512-qvUtwJ3j6qwsF3jLxkZ72qCgjMysPzDfeV240JHiGZsANBYd+EEuu35v7dfrJ9Up0Ak07D7GGSkGhCHTqg/5wA==", + "dependencies": { + "node-fetch": "^2.6.1", + "whatwg-fetch": "^3.4.1" + } + }, "node_modules/istanbul-lib-coverage": { "version": "3.2.0", "dev": true, @@ -9920,8 +11494,9 @@ }, "node_modules/jake": { "version": "10.8.7", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.7.tgz", + "integrity": "sha512-ZDi3aP+fG/LchyBzUM804VjddnwfSfsdeYkwt8NcbKRvo4rFkjhs456iLFn3k2ZUWvNe4i48WACDbza8fhq2+w==", "dev": true, - "license": "Apache-2.0", "dependencies": { "async": "^3.2.3", "chalk": "^4.0.2", @@ -10481,8 +12056,9 @@ }, "node_modules/jju": { "version": "1.4.0", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/jju/-/jju-1.4.0.tgz", + "integrity": "sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==", + "dev": true }, "node_modules/js-sha256": { "version": "0.9.0", @@ -10502,8 +12078,8 @@ }, "node_modules/js-yaml": { "version": "4.1.0", - "dev": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dependencies": { "argparse": "^2.0.1" }, @@ -10540,8 +12116,9 @@ }, "node_modules/json-schema": { "version": "0.4.0", - "dev": true, - "license": "(AFL-2.1 OR BSD-3-Clause)" + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", + "dev": true }, "node_modules/json-schema-traverse": { "version": "1.0.0", @@ -10582,8 +12159,9 @@ }, "node_modules/jsonpointer": { "version": "5.0.1", + "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-5.0.1.tgz", + "integrity": "sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -10687,22 +12265,25 @@ "version": "4.17.21", "license": "MIT" }, + "node_modules/lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==", + "dev": true + }, "node_modules/lodash.debounce": { "version": "4.0.8", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", + "dev": true }, "node_modules/lodash.defaults": { "version": "4.2.0", - "license": "MIT", - "optional": true, - "peer": true + "license": "MIT" }, "node_modules/lodash.isarguments": { "version": "3.1.0", - "license": "MIT", - "optional": true, - "peer": true + "license": "MIT" }, "node_modules/lodash.memoize": { "version": "4.1.2", @@ -10716,8 +12297,9 @@ }, "node_modules/lodash.sortby": { "version": "4.7.0", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", + "integrity": "sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==", + "dev": true }, "node_modules/log-symbols": { "version": "4.1.0", @@ -10736,7 +12318,8 @@ }, "node_modules/loose-envify": { "version": "1.4.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", "dependencies": { "js-tokens": "^3.0.0 || ^4.0.0" }, @@ -10744,6 +12327,15 @@ "loose-envify": "cli.js" } }, + "node_modules/loupe": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.0.tgz", + "integrity": "sha512-qKl+FrLXUhFuHUoDJG7f8P8gEMHq9NFS0c6ghXG1J0rldmZFQZoNVv/vyirE9qwCIhWZDsvEFd1sbFu3GvRQFg==", + "dev": true, + "dependencies": { + "get-func-name": "^2.0.1" + } + }, "node_modules/lowercase-keys": { "version": "2.0.0", "dev": true, @@ -10873,8 +12465,9 @@ }, "node_modules/mdn-data": { "version": "2.0.30", - "dev": true, - "license": "CC0-1.0" + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz", + "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==", + "dev": true }, "node_modules/media-typer": { "version": "0.3.0", @@ -11304,7 +12897,8 @@ }, "node_modules/multipipe": { "version": "1.0.2", - "license": "MIT", + "resolved": "https://registry.npmjs.org/multipipe/-/multipipe-1.0.2.tgz", + "integrity": "sha512-6uiC9OvY71vzSGX8lZvSqscE7ft9nPupJ8fMjrCNRAUy2LREUW42UL+V/NTrogr6rFgRydUrCX4ZitfpSNkSCQ==", "dependencies": { "duplexer2": "^0.1.2", "object-assign": "^4.1.0" @@ -11317,6 +12911,8 @@ }, "node_modules/nanoid": { "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", "dev": true, "funding": [ { @@ -11324,7 +12920,6 @@ "url": "https://github.com/sponsors/ai" } ], - "license": "MIT", "bin": { "nanoid": "bin/nanoid.cjs" }, @@ -11433,8 +13028,9 @@ }, "node_modules/node-releases": { "version": "2.0.14", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", + "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", + "dev": true }, "node_modules/node-rsa": { "version": "1.1.1", @@ -11514,8 +13110,9 @@ }, "node_modules/nth-check": { "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", "dev": true, - "license": "BSD-2-Clause", "dependencies": { "boolbase": "^1.0.0" }, @@ -11539,19 +13136,22 @@ }, "node_modules/object-inspect": { "version": "1.13.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", + "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/object-keys": { "version": "0.4.0", - "license": "MIT" + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz", + "integrity": "sha512-ncrLw+X55z7bkl5PnUvHwFK9FcGuFYo9gtjws2XtSzL+aZ8tm830P60WJ0dSmFVaSalWieW5MD7kEdnXda9yJw==" }, "node_modules/object.assign": { "version": "4.1.5", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", + "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", "dev": true, - "license": "MIT", "dependencies": { "call-bind": "^1.0.5", "define-properties": "^1.2.1", @@ -11567,8 +13167,9 @@ }, "node_modules/object.assign/node_modules/object-keys": { "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", "dev": true, - "license": "MIT", "engines": { "node": ">= 0.4" } @@ -11854,8 +13455,18 @@ }, "node_modules/pathe": { "version": "1.1.2", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz", + "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==", + "dev": true + }, + "node_modules/pathval": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.0.tgz", + "integrity": "sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==", "dev": true, - "license": "MIT" + "engines": { + "node": ">= 14.16" + } }, "node_modules/peek-readable": { "version": "5.0.0", @@ -11873,6 +13484,7 @@ }, "node_modules/picocolors": { "version": "1.0.0", + "dev": true, "license": "ISC" }, "node_modules/picomatch": { @@ -11973,14 +13585,17 @@ }, "node_modules/possible-typed-array-names": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", + "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", "dev": true, - "license": "MIT", "engines": { "node": ">= 0.4" } }, "node_modules/postcss": { - "version": "8.4.38", + "version": "8.4.33", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.33.tgz", + "integrity": "sha512-Kkpbhhdjw2qQs2O2DGX+8m5OVqEcbB9HRBvuYM9pgrjEFUg30A9LmXNlTAUj4S9kgtGyrMbTzVjH7E+s5Re2yg==", "dev": true, "funding": [ { @@ -11996,11 +13611,10 @@ "url": "https://github.com/sponsors/ai" } ], - "license": "MIT", "dependencies": { "nanoid": "^3.3.7", "picocolors": "^1.0.0", - "source-map-js": "^1.2.0" + "source-map-js": "^1.0.2" }, "engines": { "node": "^10 || ^12 || >=14" @@ -12041,8 +13655,9 @@ }, "node_modules/pretty-bytes": { "version": "6.1.1", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-6.1.1.tgz", + "integrity": "sha512-mQUvGU6aUFQ+rNvTIAcZuWGRT9a6f6Yrg9bHs4ImKF+HZCEK+plBvnAZYSIQztknZF2qnzNtr6F8s0+IuptdlQ==", "dev": true, - "license": "MIT", "engines": { "node": "^14.13.1 || >=16.0.0" }, @@ -12103,7 +13718,8 @@ }, "node_modules/prop-types": { "version": "15.8.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", "dependencies": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", @@ -12112,7 +13728,8 @@ }, "node_modules/prop-types/node_modules/react-is": { "version": "16.13.1", - "license": "MIT" + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, "node_modules/proxy-addr": { "version": "2.0.7", @@ -12179,14 +13796,16 @@ }, "node_modules/qr-code-styling": { "version": "1.6.0-rc.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/qr-code-styling/-/qr-code-styling-1.6.0-rc.1.tgz", + "integrity": "sha512-ModRIiW6oUnsP18QzrRYZSc/CFKFKIdj7pUs57AEVH20ajlglRpN3HukjHk0UbNMTlKGuaYl7Gt6/O5Gg2NU2Q==", "dependencies": { "qrcode-generator": "^1.4.3" } }, "node_modules/qrcode-generator": { "version": "1.4.4", - "license": "MIT" + "resolved": "https://registry.npmjs.org/qrcode-generator/-/qrcode-generator-1.4.4.tgz", + "integrity": "sha512-HM7yY8O2ilqhmULxGMpcHSF1EhJJ9yBj8gvDEuZ6M+KGJ0YY2hKpnXvRD+hZPLrDVck3ExIGhmPtSdcjC+guuw==" }, "node_modules/qs": { "version": "6.11.0", @@ -12270,7 +13889,8 @@ }, "node_modules/react": { "version": "18.2.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", + "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", "dependencies": { "loose-envify": "^1.1.0" }, @@ -12280,7 +13900,8 @@ }, "node_modules/react-dom": { "version": "18.2.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", + "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==", "dependencies": { "loose-envify": "^1.1.0", "scheduler": "^0.23.0" @@ -12295,7 +13916,8 @@ }, "node_modules/react-router": { "version": "6.22.3", - "license": "MIT", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.22.3.tgz", + "integrity": "sha512-dr2eb3Mj5zK2YISHK++foM9w4eBnO23eKnZEDs7c880P6oKbrjz/Svg9+nxqtHQK+oMW4OtjZca0RqPglXxguQ==", "dependencies": { "@remix-run/router": "1.15.3" }, @@ -12308,7 +13930,8 @@ }, "node_modules/react-router-dom": { "version": "6.22.3", - "license": "MIT", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.22.3.tgz", + "integrity": "sha512-7ZILI7HjcE+p31oQvwbokjk6OA/bnFxrhJ19n82Ex9Ph8fNAq+Hm/7KchpMGlTgWhUxRHMMCut+vEtNpWpowKw==", "dependencies": { "@remix-run/router": "1.15.3", "react-router": "6.22.3" @@ -12323,7 +13946,8 @@ }, "node_modules/react-transition-group": { "version": "4.4.5", - "license": "BSD-3-Clause", + "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", + "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==", "dependencies": { "@babel/runtime": "^7.5.5", "dom-helpers": "^5.0.1", @@ -12423,8 +14047,6 @@ "node_modules/redis-errors": { "version": "1.2.0", "license": "MIT", - "optional": true, - "peer": true, "engines": { "node": ">=4" } @@ -12432,8 +14054,6 @@ "node_modules/redis-parser": { "version": "3.0.0", "license": "MIT", - "optional": true, - "peer": true, "dependencies": { "redis-errors": "^1.0.0" }, @@ -12447,13 +14067,15 @@ }, "node_modules/regenerate": { "version": "1.4.2", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", + "dev": true }, "node_modules/regenerate-unicode-properties": { "version": "10.1.1", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.1.tgz", + "integrity": "sha512-X007RyZLsCJVVrjgEFVpLUTZwyOZk3oiL75ZcuYjlIWd6rNJtOjkBwQc5AsRrpbKVkxN6sklw/k/9m2jJYOf8Q==", "dev": true, - "license": "MIT", "dependencies": { "regenerate": "^1.4.2" }, @@ -12463,20 +14085,23 @@ }, "node_modules/regenerator-runtime": { "version": "0.14.1", - "license": "MIT" + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" }, "node_modules/regenerator-transform": { "version": "0.15.2", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz", + "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==", "dev": true, - "license": "MIT", "dependencies": { "@babel/runtime": "^7.8.4" } }, "node_modules/regexp.prototype.flags": { "version": "1.5.2", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", + "integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==", "dev": true, - "license": "MIT", "dependencies": { "call-bind": "^1.0.6", "define-properties": "^1.2.1", @@ -12492,8 +14117,9 @@ }, "node_modules/regexpu-core": { "version": "5.3.2", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.2.tgz", + "integrity": "sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==", "dev": true, - "license": "MIT", "dependencies": { "@babel/regjsgen": "^0.8.0", "regenerate": "^1.4.2", @@ -12508,8 +14134,9 @@ }, "node_modules/regjsparser": { "version": "0.9.1", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz", + "integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==", "dev": true, - "license": "BSD-2-Clause", "dependencies": { "jsesc": "~0.5.0" }, @@ -12519,6 +14146,8 @@ }, "node_modules/regjsparser/node_modules/jsesc": { "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", "dev": true, "bin": { "jsesc": "bin/jsesc" @@ -12596,6 +14225,15 @@ "node": ">=4" } }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true, + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, "node_modules/resolve.exports": { "version": "2.0.2", "dev": true, @@ -12702,9 +14340,10 @@ } }, "node_modules/rollup": { - "version": "4.14.3", + "version": "4.9.6", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.9.6.tgz", + "integrity": "sha512-05lzkCS2uASX0CiLFybYfVkwNbKZG5NFQ6Go0VWyogFTXXbR039UVsegViTntkk4OglHBdF54ccApXRRuXRbsg==", "dev": true, - "license": "MIT", "dependencies": { "@types/estree": "1.0.5" }, @@ -12716,22 +14355,19 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.14.3", - "@rollup/rollup-android-arm64": "4.14.3", - "@rollup/rollup-darwin-arm64": "4.14.3", - "@rollup/rollup-darwin-x64": "4.14.3", - "@rollup/rollup-linux-arm-gnueabihf": "4.14.3", - "@rollup/rollup-linux-arm-musleabihf": "4.14.3", - "@rollup/rollup-linux-arm64-gnu": "4.14.3", - "@rollup/rollup-linux-arm64-musl": "4.14.3", - "@rollup/rollup-linux-powerpc64le-gnu": "4.14.3", - "@rollup/rollup-linux-riscv64-gnu": "4.14.3", - "@rollup/rollup-linux-s390x-gnu": "4.14.3", - "@rollup/rollup-linux-x64-gnu": "4.14.3", - "@rollup/rollup-linux-x64-musl": "4.14.3", - "@rollup/rollup-win32-arm64-msvc": "4.14.3", - "@rollup/rollup-win32-ia32-msvc": "4.14.3", - "@rollup/rollup-win32-x64-msvc": "4.14.3", + "@rollup/rollup-android-arm-eabi": "4.9.6", + "@rollup/rollup-android-arm64": "4.9.6", + "@rollup/rollup-darwin-arm64": "4.9.6", + "@rollup/rollup-darwin-x64": "4.9.6", + "@rollup/rollup-linux-arm-gnueabihf": "4.9.6", + "@rollup/rollup-linux-arm64-gnu": "4.9.6", + "@rollup/rollup-linux-arm64-musl": "4.9.6", + "@rollup/rollup-linux-riscv64-gnu": "4.9.6", + "@rollup/rollup-linux-x64-gnu": "4.9.6", + "@rollup/rollup-linux-x64-musl": "4.9.6", + "@rollup/rollup-win32-arm64-msvc": "4.9.6", + "@rollup/rollup-win32-ia32-msvc": "4.9.6", + "@rollup/rollup-win32-x64-msvc": "4.9.6", "fsevents": "~2.3.2" } }, @@ -12774,8 +14410,9 @@ }, "node_modules/safe-array-concat": { "version": "1.1.2", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", + "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==", "dev": true, - "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "get-intrinsic": "^1.2.4", @@ -12791,8 +14428,9 @@ }, "node_modules/safe-array-concat/node_modules/isarray": { "version": "2.0.5", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true }, "node_modules/safe-buffer": { "version": "5.2.1", @@ -12814,8 +14452,9 @@ }, "node_modules/safe-regex-test": { "version": "1.0.3", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", + "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", "dev": true, - "license": "MIT", "dependencies": { "call-bind": "^1.0.6", "es-errors": "^1.3.0", @@ -12834,7 +14473,8 @@ }, "node_modules/scheduler": { "version": "0.23.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz", + "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==", "dependencies": { "loose-envify": "^1.1.0" } @@ -12886,7 +14526,8 @@ }, "node_modules/semver": { "version": "7.6.0", - "license": "ISC", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", "dependencies": { "lru-cache": "^6.0.0" }, @@ -13004,7 +14645,8 @@ }, "node_modules/set-function-length": { "version": "1.2.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.1.tgz", + "integrity": "sha512-j4t6ccc+VsKwYHso+kElc5neZpjtq9EnRICFZtWyBsLojhmeF/ZBd/elqm22WJh/BziDe/SBiOeAt0m2mfLD0g==", "dependencies": { "define-data-property": "^1.1.2", "es-errors": "^1.3.0", @@ -13019,8 +14661,9 @@ }, "node_modules/set-function-name": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.1.tgz", + "integrity": "sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==", "dev": true, - "license": "MIT", "dependencies": { "define-data-property": "^1.0.1", "functions-have-names": "^1.2.3", @@ -13036,9 +14679,10 @@ }, "node_modules/sharp": { "version": "0.33.2", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.33.2.tgz", + "integrity": "sha512-WlYOPyyPDiiM07j/UO+E720ju6gtNtHjEGg5vovUk1Lgxyjm2LFO+37Nt/UI3MMh2l6hxTWQWi7qk3cXJTutcQ==", "dev": true, "hasInstallScript": true, - "license": "Apache-2.0", "dependencies": { "color": "^4.2.3", "detect-libc": "^2.0.2", @@ -13092,8 +14736,9 @@ }, "node_modules/shell-quote": { "version": "1.8.1", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz", + "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==", "dev": true, - "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -13114,6 +14759,18 @@ "node": ">=4" } }, + "node_modules/shiki": { + "version": "0.14.7", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.14.7.tgz", + "integrity": "sha512-dNPAPrxSc87ua2sKJ3H5dQ/6ZaY8RNnaAqK+t0eG7p0Soi2ydiqbGOTaZCqaYvA/uZYfS1LJnemt3Q+mSfcPCg==", + "dev": true, + "dependencies": { + "ansi-sequence-parser": "^1.1.0", + "jsonc-parser": "^3.2.0", + "vscode-oniguruma": "^1.7.0", + "vscode-textmate": "^8.0.0" + } + }, "node_modules/side-channel": { "version": "1.0.4", "license": "MIT", @@ -13136,16 +14793,18 @@ }, "node_modules/simple-swizzle": { "version": "0.2.2", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==", "dev": true, - "license": "MIT", "dependencies": { "is-arrayish": "^0.3.1" } }, "node_modules/simple-swizzle/node_modules/is-arrayish": { "version": "0.3.2", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==", + "dev": true }, "node_modules/sisteransi": { "version": "1.0.5", @@ -13192,8 +14851,9 @@ } }, "node_modules/socket.io-client": { - "version": "4.7.5", - "license": "MIT", + "version": "4.7.4", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.7.4.tgz", + "integrity": "sha512-wh+OkeF0rAVCrABWQBaEjLfb7DVPotMbu0cgWgyR0v6eA4EoVnAwcIeIbcdTE3GT/H3kbdLl7OoH2+asoDRIIg==", "dependencies": { "@socket.io/component-emitter": "~3.1.0", "debug": "~4.3.2", @@ -13274,9 +14934,10 @@ } }, "node_modules/source-map-js": { - "version": "1.2.0", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", "dev": true, - "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" } @@ -13300,8 +14961,10 @@ }, "node_modules/sourcemap-codec": { "version": "1.4.8", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", + "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", + "deprecated": "Please use @jridgewell/sourcemap-codec instead", + "dev": true }, "node_modules/sparse-bitfield": { "version": "3.0.3", @@ -13313,6 +14976,8 @@ }, "node_modules/spawn-command": { "version": "0.0.2", + "resolved": "https://registry.npmjs.org/spawn-command/-/spawn-command-0.0.2.tgz", + "integrity": "sha512-zC8zGoGkmc8J9ndvml8Xksr1Amk9qBujgbF0JAIWO7kXr43w0h/0GJNM/Vustixu+YE8N/MTrQ7N31FvHUACxQ==", "dev": true }, "node_modules/sprintf-js": { @@ -13358,9 +15023,7 @@ }, "node_modules/standard-as-callback": { "version": "2.1.0", - "license": "MIT", - "optional": true, - "peer": true + "license": "MIT" }, "node_modules/statuses": { "version": "2.0.1", @@ -13425,8 +15088,9 @@ }, "node_modules/string.prototype.matchall": { "version": "4.0.10", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.10.tgz", + "integrity": "sha512-rGXbGmOEosIQi6Qva94HUjgPs9vKW+dkG7Y8Q5O2OYkWL6wFaTRZO8zM4mhP94uX55wgyrXzfS2aGtGzUL7EJQ==", "dev": true, - "license": "MIT", "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.2.0", @@ -13444,8 +15108,9 @@ }, "node_modules/string.prototype.trim": { "version": "1.2.9", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", + "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", "dev": true, - "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -13461,8 +15126,9 @@ }, "node_modules/string.prototype.trimend": { "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz", + "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", "dev": true, - "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -13474,8 +15140,9 @@ }, "node_modules/string.prototype.trimstart": { "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", "dev": true, - "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -13490,8 +15157,9 @@ }, "node_modules/stringify-object": { "version": "3.3.0", + "resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-3.3.0.tgz", + "integrity": "sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==", "dev": true, - "license": "BSD-2-Clause", "dependencies": { "get-own-enumerable-property-symbols": "^3.0.0", "is-obj": "^1.0.1", @@ -13532,8 +15200,9 @@ }, "node_modules/strip-comments": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-comments/-/strip-comments-2.0.1.tgz", + "integrity": "sha512-ZprKx+bBLXv067WTCALv8SSz5l2+XhpYCsVtSqlMnkAXMWDq+/ekVbl1ghqP9rUHTzv6sm/DwCOiYutU/yp1fw==", "dev": true, - "license": "MIT", "engines": { "node": ">=10" } @@ -13600,7 +15269,8 @@ }, "node_modules/stylis": { "version": "4.2.0", - "license": "MIT" + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz", + "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==" }, "node_modules/superagent": { "version": "8.1.2", @@ -13667,8 +15337,9 @@ }, "node_modules/svgo": { "version": "3.2.0", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-3.2.0.tgz", + "integrity": "sha512-4PP6CMW/V7l/GmKRKzsLR8xxjdHTV4IMvhTnpuHwwBazSIlw5W/5SmPjN8Dwyt7lKbSJrRDgp4t9ph0HgChFBQ==", "dev": true, - "license": "MIT", "dependencies": { "@trysound/sax": "0.2.0", "commander": "^7.2.0", @@ -13691,12 +15362,18 @@ }, "node_modules/svgo/node_modules/commander": { "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", "dev": true, - "license": "MIT", "engines": { "node": ">= 10" } }, + "node_modules/swagger-ui-dist": { + "version": "5.11.2", + "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.11.2.tgz", + "integrity": "sha512-jQG0cRgJNMZ7aCoiFofnoojeSaa/+KgWaDlfgs8QN+BXoGMpxeMVY5OEnjq4OlNvF3yjftO8c9GRAgcHlO+u7A==" + }, "node_modules/symbol-observable": { "version": "4.0.0", "dev": true, @@ -13707,8 +15384,9 @@ }, "node_modules/synckit": { "version": "0.8.8", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.8.tgz", + "integrity": "sha512-HwOKAP7Wc5aRGYdKH+dw0PRRpbO841v2DENBtjnR5HFWoiNByAl7vrx3p0G/rCyYXQsrxqtX48TImFtPcIHSpQ==", "dev": true, - "license": "MIT", "dependencies": { "@pkgr/core": "^0.1.0", "tslib": "^2.6.2" @@ -13786,16 +15464,18 @@ }, "node_modules/temp-dir": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-2.0.0.tgz", + "integrity": "sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==", "dev": true, - "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/tempy": { "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tempy/-/tempy-0.6.0.tgz", + "integrity": "sha512-G13vtMYPT/J8A4X2SjdtBTphZlrp1gKv6hZiOjw14RCWg6GbHuQBGtjlx75xLbYV/wEc0D7G5K4rxKP/cXk8Bw==", "dev": true, - "license": "MIT", "dependencies": { "is-stream": "^2.0.0", "temp-dir": "^2.0.0", @@ -13811,8 +15491,9 @@ }, "node_modules/tempy/node_modules/type-fest": { "version": "0.16.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.16.0.tgz", + "integrity": "sha512-eaBzG6MxNzEn9kiwvtre90cXaNLkmadMWa1zQMs3XORCXNbsH/OewwbxC5ia9dCxIxnTAsSxXJaa/p5y8DlvJg==", "dev": true, - "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=10" }, @@ -13926,7 +15607,8 @@ }, "node_modules/through2": { "version": "0.4.2", - "license": "MIT", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.4.2.tgz", + "integrity": "sha512-45Llu+EwHKtAZYTPPVn3XZHBgakWMN3rokhEv5hu596XP+cNgplMg+Gj+1nmAvj+L0K7+N49zBKx5rah5u0QIQ==", "dependencies": { "readable-stream": "~1.0.17", "xtend": "~2.1.1" @@ -13934,11 +15616,13 @@ }, "node_modules/through2/node_modules/isarray": { "version": "0.0.1", - "license": "MIT" + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==" }, "node_modules/through2/node_modules/readable-stream": { "version": "1.0.34", - "license": "MIT", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha512-ok1qVCJuRkNmvebYikljxJA/UEsKwLl2nI1OmaqAu4/UE+h0wKCHok4XkL/gvi39OacXvw59RJUOFUkDib2rHg==", "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.1", @@ -13948,10 +15632,13 @@ }, "node_modules/through2/node_modules/string_decoder": { "version": "0.10.31", - "license": "MIT" + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==" }, "node_modules/through2/node_modules/xtend": { "version": "2.1.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz", + "integrity": "sha512-vMNKzr2rHP9Dp/e1NQFnLQlwlhp9L/LfvnsVdHxN1f+uggyVI3i08uD14GPvCToPkdsRfyPqIyYGmIk58V98ZQ==", "dependencies": { "object-keys": "~0.4.0" }, @@ -14058,8 +15745,9 @@ }, "node_modules/ts-api-utils": { "version": "1.3.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", + "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", "dev": true, - "license": "MIT", "engines": { "node": ">=16" }, @@ -14207,9 +15895,29 @@ "version": "2.6.2", "license": "0BSD" }, + "node_modules/tsx": { + "version": "4.7.2", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.7.2.tgz", + "integrity": "sha512-BCNd4kz6fz12fyrgCTEdZHGJ9fWTGeUzXmQysh0RVocDY3h4frk05ZNCXSy4kIenF7y/QnrdiVpTsyNRn6vlAw==", + "dev": true, + "dependencies": { + "esbuild": "~0.19.10", + "get-tsconfig": "^4.7.2" + }, + "bin": { + "tsx": "dist/cli.mjs" + }, + "engines": { + "node": ">=18.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + } + }, "node_modules/tweetnacl": { "version": "1.0.3", - "license": "Unlicense" + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz", + "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==" }, "node_modules/type-check": { "version": "0.4.0", @@ -14232,8 +15940,9 @@ }, "node_modules/type-fest": { "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", "dev": true, - "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=10" }, @@ -14254,8 +15963,9 @@ }, "node_modules/typed-array-buffer": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", + "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", "dev": true, - "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "es-errors": "^1.3.0", @@ -14267,8 +15977,9 @@ }, "node_modules/typed-array-byte-length": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", + "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", "dev": true, - "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "for-each": "^0.3.3", @@ -14285,8 +15996,9 @@ }, "node_modules/typed-array-byte-offset": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", + "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", "dev": true, - "license": "MIT", "dependencies": { "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.7", @@ -14304,8 +16016,9 @@ }, "node_modules/typed-array-length": { "version": "1.0.6", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.6.tgz", + "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==", "dev": true, - "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "for-each": "^0.3.3", @@ -14347,9 +16060,9 @@ } }, "node_modules/typedoc-plugin-markdown": { - "version": "4.0.0-next.55", - "resolved": "https://registry.npmjs.org/typedoc-plugin-markdown/-/typedoc-plugin-markdown-4.0.0-next.55.tgz", - "integrity": "sha512-bwEEBkAP0kHnjE10QzPBXAri5yHYmgb+vZP+xn9GirBLCk3lt7SMUiUx0fj7lEtTmbgIH0rv20f3xP+JWxCPHg==", + "version": "4.0.0-next.58", + "resolved": "https://registry.npmjs.org/typedoc-plugin-markdown/-/typedoc-plugin-markdown-4.0.0-next.58.tgz", + "integrity": "sha512-qIpinPrmz75gkKcveXNcCIxtKeNM+u/LGx+L9Cp2qOv0vCR3Vi5ONWVFq3P5XIAkoRFnLZXx6NaLcey+GuQuUA==", "dev": true, "peerDependencies": { "typedoc": "0.25.x" @@ -14379,22 +16092,11 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/typedoc/node_modules/shiki": { - "version": "0.14.7", - "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.14.7.tgz", - "integrity": "sha512-dNPAPrxSc87ua2sKJ3H5dQ/6ZaY8RNnaAqK+t0eG7p0Soi2ydiqbGOTaZCqaYvA/uZYfS1LJnemt3Q+mSfcPCg==", - "dev": true, - "dependencies": { - "ansi-sequence-parser": "^1.1.0", - "jsonc-parser": "^3.2.0", - "vscode-oniguruma": "^1.7.0", - "vscode-textmate": "^8.0.0" - } - }, "node_modules/typescript": { "version": "5.4.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", + "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", "dev": true, - "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -14426,8 +16128,9 @@ }, "node_modules/uglify-js": { "version": "3.17.4", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz", + "integrity": "sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==", "dev": true, - "license": "BSD-2-Clause", "optional": true, "bin": { "uglifyjs": "bin/uglifyjs" @@ -14465,8 +16168,9 @@ }, "node_modules/unbox-primitive": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", "dev": true, - "license": "MIT", "dependencies": { "call-bind": "^1.0.2", "has-bigints": "^1.0.2", @@ -14479,16 +16183,18 @@ }, "node_modules/unicode-canonical-property-names-ecmascript": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", + "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", "dev": true, - "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/unicode-match-property-ecmascript": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", + "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", "dev": true, - "license": "MIT", "dependencies": { "unicode-canonical-property-names-ecmascript": "^2.0.0", "unicode-property-aliases-ecmascript": "^2.0.0" @@ -14499,16 +16205,18 @@ }, "node_modules/unicode-match-property-value-ecmascript": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz", + "integrity": "sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==", "dev": true, - "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/unicode-property-aliases-ecmascript": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", + "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", "dev": true, - "license": "MIT", "engines": { "node": ">=4" } @@ -14535,8 +16243,9 @@ }, "node_modules/unique-string": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", + "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", "dev": true, - "license": "MIT", "dependencies": { "crypto-random-string": "^2.0.0" }, @@ -14561,8 +16270,9 @@ }, "node_modules/upath": { "version": "1.2.0", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", + "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", "dev": true, - "license": "MIT", "engines": { "node": ">=4", "yarn": "*" @@ -14570,6 +16280,8 @@ }, "node_modules/update-browserslist-db": { "version": "1.0.13", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", + "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", "dev": true, "funding": [ { @@ -14585,7 +16297,6 @@ "url": "https://github.com/sponsors/ai" } ], - "license": "MIT", "dependencies": { "escalade": "^3.1.1", "picocolors": "^1.0.0" @@ -14607,7 +16318,8 @@ }, "node_modules/use-sync-external-store": { "version": "1.2.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz", + "integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==", "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0" } @@ -14661,13 +16373,14 @@ } }, "node_modules/vite": { - "version": "5.2.9", + "version": "5.0.12", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.0.12.tgz", + "integrity": "sha512-4hsnEkG3q0N4Tzf1+t6NdN9dg/L3BM+q8SWgbSPnJvrgH2kgdyzfVJwbR1ic69/4uMJJ/3dqDZZE5/WwqW8U1w==", "dev": true, - "license": "MIT", "dependencies": { - "esbuild": "^0.20.1", - "postcss": "^8.4.38", - "rollup": "^4.13.0" + "esbuild": "^0.19.3", + "postcss": "^8.4.32", + "rollup": "^4.2.0" }, "bin": { "vite": "bin/vite.js" @@ -14716,8 +16429,9 @@ }, "node_modules/vite-plugin-image-optimizer": { "version": "1.1.7", + "resolved": "https://registry.npmjs.org/vite-plugin-image-optimizer/-/vite-plugin-image-optimizer-1.1.7.tgz", + "integrity": "sha512-KPJWndwqVi7Z2hYCudzKeNDw5U7w1DxAc266bqDBKV8taG8W3EtripFuUM4Y05IlFC19yBQndJCFA8+NJymH+w==", "dev": true, - "license": "MIT", "dependencies": { "ansi-colors": "^4.1.3", "pathe": "^1.1.1" @@ -14731,8 +16445,9 @@ }, "node_modules/vite-plugin-pwa": { "version": "0.18.1", + "resolved": "https://registry.npmjs.org/vite-plugin-pwa/-/vite-plugin-pwa-0.18.1.tgz", + "integrity": "sha512-2A3BF52l9F8hCkdPy/VP2C+hA+fmBvzJGynCZc9XS6mHTcMvo9046FKc2NqlnkKwTOGtQEwXLEIduML/+eYtdw==", "dev": true, - "license": "MIT", "dependencies": { "debug": "^4.3.4", "fast-glob": "^3.3.2", @@ -14752,58 +16467,6 @@ "workbox-window": "^7.0.0" } }, - "node_modules/vite/node_modules/@esbuild/linux-x64": { - "version": "0.20.2", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/esbuild": { - "version": "0.20.2", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=12" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.20.2", - "@esbuild/android-arm": "0.20.2", - "@esbuild/android-arm64": "0.20.2", - "@esbuild/android-x64": "0.20.2", - "@esbuild/darwin-arm64": "0.20.2", - "@esbuild/darwin-x64": "0.20.2", - "@esbuild/freebsd-arm64": "0.20.2", - "@esbuild/freebsd-x64": "0.20.2", - "@esbuild/linux-arm": "0.20.2", - "@esbuild/linux-arm64": "0.20.2", - "@esbuild/linux-ia32": "0.20.2", - "@esbuild/linux-loong64": "0.20.2", - "@esbuild/linux-mips64el": "0.20.2", - "@esbuild/linux-ppc64": "0.20.2", - "@esbuild/linux-riscv64": "0.20.2", - "@esbuild/linux-s390x": "0.20.2", - "@esbuild/linux-x64": "0.20.2", - "@esbuild/netbsd-x64": "0.20.2", - "@esbuild/openbsd-x64": "0.20.2", - "@esbuild/sunos-x64": "0.20.2", - "@esbuild/win32-arm64": "0.20.2", - "@esbuild/win32-ia32": "0.20.2", - "@esbuild/win32-x64": "0.20.2" - } - }, "node_modules/vlq": { "version": "2.0.4", "license": "MIT" @@ -14934,6 +16597,11 @@ "node": ">=4.0" } }, + "node_modules/whatwg-fetch": { + "version": "3.6.20", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.20.tgz", + "integrity": "sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg==" + }, "node_modules/whatwg-url": { "version": "5.0.0", "license": "MIT", @@ -14957,8 +16625,9 @@ }, "node_modules/which-boxed-primitive": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", "dev": true, - "license": "MIT", "dependencies": { "is-bigint": "^1.0.1", "is-boolean-object": "^1.1.0", @@ -14972,8 +16641,9 @@ }, "node_modules/which-typed-array": { "version": "1.1.15", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", + "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", "dev": true, - "license": "MIT", "dependencies": { "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.7", @@ -15055,13 +16725,15 @@ }, "node_modules/wordwrap": { "version": "1.0.0", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", + "dev": true }, "node_modules/workbox-background-sync": { "version": "7.0.0", + "resolved": "https://registry.npmjs.org/workbox-background-sync/-/workbox-background-sync-7.0.0.tgz", + "integrity": "sha512-S+m1+84gjdueM+jIKZ+I0Lx0BDHkk5Nu6a3kTVxP4fdj3gKouRNmhO8H290ybnJTOPfBDtTMXSQA/QLTvr7PeA==", "dev": true, - "license": "MIT", "dependencies": { "idb": "^7.0.1", "workbox-core": "7.0.0" @@ -15069,16 +16741,18 @@ }, "node_modules/workbox-broadcast-update": { "version": "7.0.0", + "resolved": "https://registry.npmjs.org/workbox-broadcast-update/-/workbox-broadcast-update-7.0.0.tgz", + "integrity": "sha512-oUuh4jzZrLySOo0tC0WoKiSg90bVAcnE98uW7F8GFiSOXnhogfNDGZelPJa+6KpGBO5+Qelv04Hqx2UD+BJqNQ==", "dev": true, - "license": "MIT", "dependencies": { "workbox-core": "7.0.0" } }, "node_modules/workbox-build": { "version": "7.0.0", + "resolved": "https://registry.npmjs.org/workbox-build/-/workbox-build-7.0.0.tgz", + "integrity": "sha512-CttE7WCYW9sZC+nUYhQg3WzzGPr4IHmrPnjKiu3AMXsiNQKx+l4hHl63WTrnicLmKEKHScWDH8xsGBdrYgtBzg==", "dev": true, - "license": "MIT", "dependencies": { "@apideck/better-ajv-errors": "^0.3.1", "@babel/core": "^7.11.1", @@ -15124,8 +16798,9 @@ }, "node_modules/workbox-build/node_modules/@rollup/plugin-babel": { "version": "5.3.1", + "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz", + "integrity": "sha512-WFfdLWU/xVWKeRQnKmIAQULUI7Il0gZnBIH/ZFO069wYIfPu+8zrfp/KMW0atmELoRDq8FbiP3VCss9MhCut7Q==", "dev": true, - "license": "MIT", "dependencies": { "@babel/helper-module-imports": "^7.10.4", "@rollup/pluginutils": "^3.1.0" @@ -15146,8 +16821,9 @@ }, "node_modules/workbox-build/node_modules/@rollup/plugin-node-resolve": { "version": "11.2.1", + "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-11.2.1.tgz", + "integrity": "sha512-yc2n43jcqVyGE2sqV5/YCmocy9ArjVAP/BeXyTtADTBBX6V0e5UMqwO8CdQ0kzjb6zu5P1qMzsScCMRvE9OlVg==", "dev": true, - "license": "MIT", "dependencies": { "@rollup/pluginutils": "^3.1.0", "@types/resolve": "1.17.1", @@ -15165,8 +16841,9 @@ }, "node_modules/workbox-build/node_modules/@rollup/plugin-replace": { "version": "2.4.2", + "resolved": "https://registry.npmjs.org/@rollup/plugin-replace/-/plugin-replace-2.4.2.tgz", + "integrity": "sha512-IGcu+cydlUMZ5En85jxHH4qj2hta/11BHq95iHEyb2sbgiN0eCdzvUcHw5gt9pBL5lTi4JDYJ1acCoMGpTvEZg==", "dev": true, - "license": "MIT", "dependencies": { "@rollup/pluginutils": "^3.1.0", "magic-string": "^0.25.7" @@ -15177,8 +16854,9 @@ }, "node_modules/workbox-build/node_modules/@rollup/pluginutils": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz", + "integrity": "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==", "dev": true, - "license": "MIT", "dependencies": { "@types/estree": "0.0.39", "estree-walker": "^1.0.1", @@ -15193,13 +16871,15 @@ }, "node_modules/workbox-build/node_modules/@types/estree": { "version": "0.0.39", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", + "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==", + "dev": true }, "node_modules/workbox-build/node_modules/fs-extra": { "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", "dev": true, - "license": "MIT", "dependencies": { "at-least-node": "^1.0.0", "graceful-fs": "^4.2.0", @@ -15212,8 +16892,9 @@ }, "node_modules/workbox-build/node_modules/jest-worker": { "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz", + "integrity": "sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==", "dev": true, - "license": "MIT", "dependencies": { "@types/node": "*", "merge-stream": "^2.0.0", @@ -15225,16 +16906,18 @@ }, "node_modules/workbox-build/node_modules/magic-string": { "version": "0.25.9", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz", + "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==", "dev": true, - "license": "MIT", "dependencies": { "sourcemap-codec": "^1.4.8" } }, "node_modules/workbox-build/node_modules/pretty-bytes": { "version": "5.6.0", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz", + "integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==", "dev": true, - "license": "MIT", "engines": { "node": ">=6" }, @@ -15244,8 +16927,9 @@ }, "node_modules/workbox-build/node_modules/rollup": { "version": "2.79.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.1.tgz", + "integrity": "sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==", "dev": true, - "license": "MIT", "bin": { "rollup": "dist/bin/rollup" }, @@ -15258,8 +16942,10 @@ }, "node_modules/workbox-build/node_modules/rollup-plugin-terser": { "version": "7.0.2", + "resolved": "https://registry.npmjs.org/rollup-plugin-terser/-/rollup-plugin-terser-7.0.2.tgz", + "integrity": "sha512-w3iIaU4OxcF52UUXiZNsNeuXIMDvFrr+ZXK6bFZ0Q60qyVfq4uLptoS4bbq3paG3x216eQllFZX7zt6TIImguQ==", + "deprecated": "This package has been deprecated and is no longer maintained. Please use @rollup/plugin-terser", "dev": true, - "license": "MIT", "dependencies": { "@babel/code-frame": "^7.10.4", "jest-worker": "^26.2.1", @@ -15272,16 +16958,18 @@ }, "node_modules/workbox-build/node_modules/serialize-javascript": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", + "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", "dev": true, - "license": "BSD-3-Clause", "dependencies": { "randombytes": "^2.1.0" } }, "node_modules/workbox-build/node_modules/source-map": { "version": "0.8.0-beta.0", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.8.0-beta.0.tgz", + "integrity": "sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==", "dev": true, - "license": "BSD-3-Clause", "dependencies": { "whatwg-url": "^7.0.0" }, @@ -15291,21 +16979,24 @@ }, "node_modules/workbox-build/node_modules/tr46": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", + "integrity": "sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==", "dev": true, - "license": "MIT", "dependencies": { "punycode": "^2.1.0" } }, "node_modules/workbox-build/node_modules/webidl-conversions": { "version": "4.0.2", - "dev": true, - "license": "BSD-2-Clause" + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", + "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==", + "dev": true }, "node_modules/workbox-build/node_modules/whatwg-url": { "version": "7.1.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", + "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==", "dev": true, - "license": "MIT", "dependencies": { "lodash.sortby": "^4.7.0", "tr46": "^1.0.1", @@ -15314,21 +17005,24 @@ }, "node_modules/workbox-cacheable-response": { "version": "7.0.0", + "resolved": "https://registry.npmjs.org/workbox-cacheable-response/-/workbox-cacheable-response-7.0.0.tgz", + "integrity": "sha512-0lrtyGHn/LH8kKAJVOQfSu3/80WDc9Ma8ng0p2i/5HuUndGttH+mGMSvOskjOdFImLs2XZIimErp7tSOPmu/6g==", "dev": true, - "license": "MIT", "dependencies": { "workbox-core": "7.0.0" } }, "node_modules/workbox-core": { "version": "7.0.0", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/workbox-core/-/workbox-core-7.0.0.tgz", + "integrity": "sha512-81JkAAZtfVP8darBpfRTovHg8DGAVrKFgHpOArZbdFd78VqHr5Iw65f2guwjE2NlCFbPFDoez3D3/6ZvhI/rwQ==", + "dev": true }, "node_modules/workbox-expiration": { "version": "7.0.0", + "resolved": "https://registry.npmjs.org/workbox-expiration/-/workbox-expiration-7.0.0.tgz", + "integrity": "sha512-MLK+fogW+pC3IWU9SFE+FRStvDVutwJMR5if1g7oBJx3qwmO69BNoJQVaMXq41R0gg3MzxVfwOGKx3i9P6sOLQ==", "dev": true, - "license": "MIT", "dependencies": { "idb": "^7.0.1", "workbox-core": "7.0.0" @@ -15336,8 +17030,10 @@ }, "node_modules/workbox-google-analytics": { "version": "7.0.0", + "resolved": "https://registry.npmjs.org/workbox-google-analytics/-/workbox-google-analytics-7.0.0.tgz", + "integrity": "sha512-MEYM1JTn/qiC3DbpvP2BVhyIH+dV/5BjHk756u9VbwuAhu0QHyKscTnisQuz21lfRpOwiS9z4XdqeVAKol0bzg==", + "deprecated": "It is not compatible with newer versions of GA starting with v4, as long as you are using GAv3 it should be ok, but the package is not longer being maintained", "dev": true, - "license": "MIT", "dependencies": { "workbox-background-sync": "7.0.0", "workbox-core": "7.0.0", @@ -15347,16 +17043,18 @@ }, "node_modules/workbox-navigation-preload": { "version": "7.0.0", + "resolved": "https://registry.npmjs.org/workbox-navigation-preload/-/workbox-navigation-preload-7.0.0.tgz", + "integrity": "sha512-juWCSrxo/fiMz3RsvDspeSLGmbgC0U9tKqcUPZBCf35s64wlaLXyn2KdHHXVQrb2cqF7I0Hc9siQalainmnXJA==", "dev": true, - "license": "MIT", "dependencies": { "workbox-core": "7.0.0" } }, "node_modules/workbox-precaching": { "version": "7.0.0", + "resolved": "https://registry.npmjs.org/workbox-precaching/-/workbox-precaching-7.0.0.tgz", + "integrity": "sha512-EC0vol623LJqTJo1mkhD9DZmMP604vHqni3EohhQVwhJlTgyKyOkMrZNy5/QHfOby+39xqC01gv4LjOm4HSfnA==", "dev": true, - "license": "MIT", "dependencies": { "workbox-core": "7.0.0", "workbox-routing": "7.0.0", @@ -15365,16 +17063,18 @@ }, "node_modules/workbox-range-requests": { "version": "7.0.0", + "resolved": "https://registry.npmjs.org/workbox-range-requests/-/workbox-range-requests-7.0.0.tgz", + "integrity": "sha512-SxAzoVl9j/zRU9OT5+IQs7pbJBOUOlriB8Gn9YMvi38BNZRbM+RvkujHMo8FOe9IWrqqwYgDFBfv6sk76I1yaQ==", "dev": true, - "license": "MIT", "dependencies": { "workbox-core": "7.0.0" } }, "node_modules/workbox-recipes": { "version": "7.0.0", + "resolved": "https://registry.npmjs.org/workbox-recipes/-/workbox-recipes-7.0.0.tgz", + "integrity": "sha512-DntcK9wuG3rYQOONWC0PejxYYIDHyWWZB/ueTbOUDQgefaeIj1kJ7pdP3LZV2lfrj8XXXBWt+JDRSw1lLLOnww==", "dev": true, - "license": "MIT", "dependencies": { "workbox-cacheable-response": "7.0.0", "workbox-core": "7.0.0", @@ -15386,24 +17086,27 @@ }, "node_modules/workbox-routing": { "version": "7.0.0", + "resolved": "https://registry.npmjs.org/workbox-routing/-/workbox-routing-7.0.0.tgz", + "integrity": "sha512-8YxLr3xvqidnbVeGyRGkaV4YdlKkn5qZ1LfEePW3dq+ydE73hUUJJuLmGEykW3fMX8x8mNdL0XrWgotcuZjIvA==", "dev": true, - "license": "MIT", "dependencies": { "workbox-core": "7.0.0" } }, "node_modules/workbox-strategies": { "version": "7.0.0", + "resolved": "https://registry.npmjs.org/workbox-strategies/-/workbox-strategies-7.0.0.tgz", + "integrity": "sha512-dg3qJU7tR/Gcd/XXOOo7x9QoCI9nk74JopaJaYAQ+ugLi57gPsXycVdBnYbayVj34m6Y8ppPwIuecrzkpBVwbA==", "dev": true, - "license": "MIT", "dependencies": { "workbox-core": "7.0.0" } }, "node_modules/workbox-streams": { "version": "7.0.0", + "resolved": "https://registry.npmjs.org/workbox-streams/-/workbox-streams-7.0.0.tgz", + "integrity": "sha512-moVsh+5to//l6IERWceYKGiftc+prNnqOp2sgALJJFbnNVpTXzKISlTIsrWY+ogMqt+x1oMazIdHj25kBSq/HQ==", "dev": true, - "license": "MIT", "dependencies": { "workbox-core": "7.0.0", "workbox-routing": "7.0.0" @@ -15411,13 +17114,15 @@ }, "node_modules/workbox-sw": { "version": "7.0.0", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/workbox-sw/-/workbox-sw-7.0.0.tgz", + "integrity": "sha512-SWfEouQfjRiZ7GNABzHUKUyj8pCoe+RwjfOIajcx6J5mtgKkN+t8UToHnpaJL5UVVOf5YhJh+OHhbVNIHe+LVA==", + "dev": true }, "node_modules/workbox-window": { "version": "7.0.0", + "resolved": "https://registry.npmjs.org/workbox-window/-/workbox-window-7.0.0.tgz", + "integrity": "sha512-j7P/bsAWE/a7sxqTzXo3P2ALb1reTfZdvVp6OJ/uLr/C2kZAMvjeWGm8V4htQhor7DOvYg0sSbFN2+flT5U0qA==", "dev": true, - "license": "MIT", "dependencies": { "@types/trusted-types": "^2.0.2", "workbox-core": "7.0.0" @@ -15489,6 +17194,8 @@ }, "node_modules/xmlhttprequest-ssl": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.0.0.tgz", + "integrity": "sha512-QKxVRxiRACQcVuQEYFsI1hhkrMlrXHPegbbd1yn9UHOmRxY+si12nQYzri3vbzt8VdTTRviqcKxcyllFas5z2A==", "engines": { "node": ">=0.4.0" } @@ -15566,7 +17273,8 @@ }, "node_modules/zustand": { "version": "4.5.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/zustand/-/zustand-4.5.0.tgz", + "integrity": "sha512-zlVFqS5TQ21nwijjhJlx4f9iGrXSL0o/+Dpy4txAP22miJ8Ti6c1Ol1RLNN98BMib83lmDH/2KmLwaNXpjrO1A==", "dependencies": { "use-sync-external-store": "1.2.0" }, @@ -15590,6 +17298,123 @@ } } }, + "packages/avicennia-api": { + "name": "@algorandfoundation/avicennia-js", + "version": "1.0.0-beta.1", + "extraneous": true, + "license": "UNLICENSED", + "workspaces": [ + "./packages/**" + ], + "dependencies": { + "@nestjs/common": "^10.2.6", + "@nestjs/config": "^3.1.1", + "@nestjs/core": "^10.2.6", + "@nestjs/microservices": "^10.2.7", + "@nestjs/mongoose": "^10.0.1", + "@nestjs/platform-express": "^10.2.6", + "@nestjs/platform-socket.io": "^10.2.7", + "@nestjs/websockets": "^10.2.7", + "@sentry/node": "^7.74.1", + "@sentry/profiling-node": "^1.2.1", + "@simplewebauthn/server": "^0.10.3", + "@socket.io/redis-adapter": "^8.2.1", + "base64url": "^3.0.1", + "bull": "^4.11.4", + "connect-mongo": "^5.0.0", + "express-session": "^1.17.3", + "express-socket.io-session": "^1.3.5", + "hbs": "^4.2.0", + "mongoose": "^7.6.3", + "redis": "^4.6.10", + "reflect-metadata": "^0.1.13", + "rxjs": "^7.8.1", + "ua-parser-js": "^1.0.36" + }, + "devDependencies": { + "@nestjs/cli": "^10.1.18", + "@nestjs/schematics": "^10.0.2", + "@nestjs/testing": "^10.2.6", + "@types/express": "^4.17.18", + "@types/express-session": "^1.17.8", + "@types/express-socket.io-session": "^1.3.7", + "@types/hbs": "^4.0.2", + "@types/jest": "^29.5.5", + "@types/node": "^20.7.0", + "@types/supertest": "^2.0.13", + "@types/ua-parser-js": "^0.7.37", + "@typescript-eslint/eslint-plugin": "^6.7.3", + "@typescript-eslint/parser": "^6.7.3", + "algosdk": "^2.6.0", + "cross-env": "^7.0.3", + "eslint": "^8.50.0", + "eslint-config-prettier": "^9.0.0", + "eslint-plugin-prettier": "^5.0.0", + "jest": "^29.7.0", + "prettier": "^3.0.3", + "source-map-support": "^0.5.21", + "supertest": "^6.3.3", + "ts-jest": "^29.1.1", + "ts-loader": "^9.4.4", + "ts-node": "^10.9.1", + "tsconfig-paths": "^4.2.0", + "typescript": "^5.3.3" + }, + "engines": { + "node": ">=18.0.0 <21.0.0" + } + }, + "packages/dapp-ui": { + "version": "0.0.1", + "extraneous": true, + "license": "UNLICENSED", + "dependencies": { + "@algorandfoundation/propagule-js": "^1.0.0", + "@emotion/react": "^11.11.3", + "@emotion/server": "^11.11.0", + "@emotion/styled": "^11.11.0", + "@mui/icons-material": "^5.15.4", + "@mui/material": "^5.15.4", + "@tanstack/react-query": "^5.17.15", + "qr-code-styling": "^1.6.0-rc.1", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "reflect-metadata": "^0.1.13", + "socket.io-client": "^4.7.4", + "zustand": "^4.4.7" + }, + "devDependencies": { + "@types/react": "^18.2.43", + "@types/react-dom": "^18.2.17", + "@typescript-eslint/eslint-plugin": "^6.14.0", + "@typescript-eslint/parser": "^6.14.0", + "@vitejs/plugin-react-swc": "^3.5.0", + "eslint": "^8.55.0", + "eslint-plugin-react-hooks": "^4.6.0", + "eslint-plugin-react-refresh": "^0.4.5", + "mkdirp": "^3.0.1", + "typescript": "^5.2.2", + "vite": "^5.0.8" + } + }, + "packages/propagule-js": { + "name": "@algorandfoundation/propagule-js", + "version": "1.0.0", + "extraneous": true, + "license": "MIT", + "dependencies": { + "qrcode": "^1.5.3" + }, + "devDependencies": { + "@types/qrcode": "^1.5.5", + "c8": "^9.1.0", + "typescript": "^5.3.3" + }, + "peerDependencies": { + "algosdk": "^2.7.0", + "tweetnacl": "^1.0.3" + } + }, "services/liquid-auth-api-js": { "name": "@liquid/auth-api", "version": "1.0.0-beta.1", @@ -15604,6 +17429,7 @@ "@nestjs/mongoose": "^10.0.1", "@nestjs/platform-express": "^10.2.6", "@nestjs/platform-socket.io": "^10.2.7", + "@nestjs/swagger": "^7.3.1", "@nestjs/websockets": "^10.2.7", "@sentry/node": "^7.74.1", "@sentry/profiling-node": "^1.2.1", @@ -15614,14 +17440,16 @@ "connect-mongo": "^5.0.0", "express-session": "^1.17.3", "express-socket.io-session": "^1.3.5", - "hi-base32": "^0.5.1", + "ioredis": "^5.4.1", "mongoose": "^7.6.3", "redis": "^4.6.10", "reflect-metadata": "^0.1.13", "rxjs": "^7.8.1", + "tweetnacl": "^1.0.3", "ua-parser-js": "^1.0.36" }, "devDependencies": { + "@faker-js/faker": "^8.4.1", "@nestjs/cli": "^10.1.18", "@nestjs/schematics": "^10.0.2", "@nestjs/testing": "^10.2.6", @@ -15695,8 +17523,9 @@ }, "sites/dapp-ui/node_modules/mkdirp": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz", + "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==", "dev": true, - "license": "MIT", "bin": { "mkdirp": "dist/cjs/src/bin.js" }, @@ -15706,17 +17535,6 @@ "funding": { "url": "https://github.com/sponsors/isaacs" } - }, - "sites/major-zero": { - "version": "0.0.1", - "extraneous": true, - "dependencies": { - "@astrojs/check": "^0.5.10", - "@astrojs/starlight": "^0.21.5", - "astro": "^4.3.5", - "sharp": "^0.32.5", - "typescript": "^5.4.5" - } } } } diff --git a/services/liquid-auth-api-js/package.json b/services/liquid-auth-api-js/package.json index ceae1fb..eb97b12 100644 --- a/services/liquid-auth-api-js/package.json +++ b/services/liquid-auth-api-js/package.json @@ -6,6 +6,9 @@ "private": true, "type": "module", "license": "MIT", + "files": [ + "./src/**/*.md" + ], "scripts": { "build": "nest build", "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"", @@ -31,6 +34,7 @@ "@nestjs/mongoose": "^10.0.1", "@nestjs/platform-express": "^10.2.6", "@nestjs/platform-socket.io": "^10.2.7", + "@nestjs/swagger": "^7.3.1", "@nestjs/websockets": "^10.2.7", "@sentry/node": "^7.74.1", "@sentry/profiling-node": "^1.2.1", @@ -41,14 +45,16 @@ "connect-mongo": "^5.0.0", "express-session": "^1.17.3", "express-socket.io-session": "^1.3.5", - "hi-base32": "^0.5.1", + "ioredis": "^5.4.1", "mongoose": "^7.6.3", "redis": "^4.6.10", "reflect-metadata": "^0.1.13", "rxjs": "^7.8.1", + "tweetnacl": "^1.0.3", "ua-parser-js": "^1.0.36" }, "devDependencies": { + "@faker-js/faker": "^8.4.1", "@nestjs/cli": "^10.1.18", "@nestjs/schematics": "^10.0.2", "@nestjs/testing": "^10.2.6", @@ -80,6 +86,7 @@ "node": ">=18.0.0" }, "jest": { + "testTimeout": 10000, "extensionsToTreatAsEsm": [ ".ts" ], @@ -103,7 +110,8 @@ "/node_modules/", "/test/", "/dist/", - "/src/main.ts" + "/src/main.ts", + "/src/adapters/redis-io.adapter.ts" ], "coverageDirectory": "../coverage", "testEnvironment": "node" diff --git a/services/liquid-auth-api-js/src/__fixtures__/configuration.database.fixtures.json b/services/liquid-auth-api-js/src/__fixtures__/configuration.database.fixtures.json new file mode 100644 index 0000000..508dbc2 --- /dev/null +++ b/services/liquid-auth-api-js/src/__fixtures__/configuration.database.fixtures.json @@ -0,0 +1,72 @@ +[ + { + "host": "spherical-concert.info", + "username": "Bettie46", + "password": "SET3G_E_wN2RCUi", + "name": "fido", + "atlas": true + }, + { + "host": "agile-roadway.name", + "username": "Imogene47", + "password": "mRSk9RafA428kE5", + "name": "fido", + "atlas": false + }, + { + "host": "ashamed-meet.biz", + "username": "Gerhard.Pfeffer", + "password": "hFOZJ6TxzKm9GrL", + "name": "fido", + "atlas": true + }, + { + "host": "surprised-expedition.org", + "username": "Josianne27", + "password": "W92QTLOKMb_OHux", + "name": "fido", + "atlas": true + }, + { + "host": "impassioned-medication.net", + "username": "Delfina_Russel98", + "password": "E7LY35i6Cq4avMK", + "name": "fido", + "atlas": false + }, + { + "host": "decent-bidet.biz", + "username": "Catherine6", + "password": "E1FyEmYV0lKK8bk", + "name": "fido", + "atlas": true + }, + { + "host": "double-populist.biz", + "username": "Delpha38", + "password": "qDUq4GAPBUglSwE", + "name": "fido", + "atlas": false + }, + { + "host": "innocent-convenience.name", + "username": "Ryley56", + "password": "vX_n8D8og7hw447", + "name": "fido", + "atlas": true + }, + { + "host": "unique-crocodile.net", + "username": "Elyssa.Schmitt47", + "password": "LtPPTU2A4a0osH3", + "name": "fido", + "atlas": false + }, + { + "host": "untidy-peen.org", + "username": "Ella_Harber", + "password": "hypZR4cXyMzwio3", + "name": "fido", + "atlas": true + } +] \ No newline at end of file diff --git a/services/liquid-auth-api-js/src/__fixtures__/configuration.fixture.json b/services/liquid-auth-api-js/src/__fixtures__/configuration.fixture.json new file mode 100644 index 0000000..32c82d2 --- /dev/null +++ b/services/liquid-auth-api-js/src/__fixtures__/configuration.fixture.json @@ -0,0 +1,25 @@ +{ + "env": "test", + "timeout": 1800000, + "rpName": "Algorand Foundation FIDO2 Server", + "hostname": "catfish-pro-wolf.ngrok-free.app", + "origin": "http://catfish-pro-wolf.ngrok-free.app", + "socket": { + "host": "localhost", + "port": 6379, + "username": "default", + "password": "" + }, + "database": { + "host": "localhost:27017", + "username": "algorand", + "password": "algorand", + "name": "fido", + "atlas": false + }, + "algod": { + "token": "", + "server": "https://testnet-api.algonode.cloud", + "port": "443" + } +} diff --git a/services/liquid-auth-api-js/src/__fixtures__/configuration.socket.fixtures.json b/services/liquid-auth-api-js/src/__fixtures__/configuration.socket.fixtures.json new file mode 100644 index 0000000..6cb9963 --- /dev/null +++ b/services/liquid-auth-api-js/src/__fixtures__/configuration.socket.fixtures.json @@ -0,0 +1,62 @@ +[ + { + "host": "heavenly-elf.info", + "port": 19320, + "username": "Eddie_Dicki72", + "password": "F3CaIQALF8mTpAY" + }, + { + "host": "shameless-invitation.biz", + "port": 20406, + "username": "Patrick_Wintheiser", + "password": "2yMX1wBaNcEeO7T" + }, + { + "host": "stylish-eggnog.biz", + "port": 23600, + "username": "Keara_Wehner4", + "password": "5cQxltW8aW87Ues" + }, + { + "host": "gripping-liability.com", + "port": 50540, + "username": "Stuart_Quigley", + "password": "1dTAqnFJ8rTqMF0" + }, + { + "host": "frightened-prayer.info", + "port": 47241, + "username": "Amelie62", + "password": "9hFUWtwGFtpPS9u" + }, + { + "host": "burdensome-patient.biz", + "port": 15465, + "username": "Richie.Kuvalis", + "password": "POLZ6WqAdD0AUj5" + }, + { + "host": "impeccable-spud.biz", + "port": 30766, + "username": "Jonathan_Schmeler", + "password": "vzHA0KmDciSwJQW" + }, + { + "host": "uneven-setback.org", + "port": 35502, + "username": "Eudora_Hessel", + "password": "p0xu15J36EoNPd_" + }, + { + "host": "masculine-privilege.com", + "port": 51039, + "username": "Kianna_Windler50", + "password": "qq3rvVHA12IeJLb" + }, + { + "host": "weepy-veil.net", + "port": 57820, + "username": "Tiara73", + "password": "1ZYukEvrqWigbHg" + } +] \ No newline at end of file diff --git a/services/liquid-auth-api-js/src/__fixtures__/user-agent.android.fixtures.json b/services/liquid-auth-api-js/src/__fixtures__/user-agent.android.fixtures.json new file mode 100644 index 0000000..8deb802 --- /dev/null +++ b/services/liquid-auth-api-js/src/__fixtures__/user-agent.android.fixtures.json @@ -0,0 +1,3 @@ +[ + "foundation.algorand.demo/1.0 (Android 14; Pixel 8 Pro; google)" +] diff --git a/services/liquid-auth-api-js/src/__fixtures__/user-agent.chrome.fixtures.json b/services/liquid-auth-api-js/src/__fixtures__/user-agent.chrome.fixtures.json new file mode 100644 index 0000000..5165178 --- /dev/null +++ b/services/liquid-auth-api-js/src/__fixtures__/user-agent.chrome.fixtures.json @@ -0,0 +1,80 @@ +[ +"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36", +"Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36", +"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.157 Safari/537.36", +"Mozilla/5.0 (Windows NT 5.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36", +"Mozilla/5.0 (Windows NT 6.2; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36", +"Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36", +"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36", +"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36", +"Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36", +"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36", +"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.84 Safari/537.36", +"Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36", +"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.80 Safari/537.36", +"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.106 Safari/537.36", +"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.109 Safari/537.36", +"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36", +"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.89 Safari/537.36", +"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.63 Safari/537.36", +"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36", +"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36", +"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.65 Safari/537.36", +"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36", +"Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36", +"Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.112 Safari/537.36", +"Mozilla/5.0 (Windows NT 6.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36", +"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36", +"Mozilla/5.0 (Windows NT 6.2; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36", +"Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.89 Safari/537.36", +"Mozilla/5.0 (Windows NT 5.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36", +"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36", +"Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36", +"Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.80 Safari/537.36", +"Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.104 Safari/537.36", +"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36", +"Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36", +"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36", +"Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36", +"Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36", +"Mozilla/5.0 (Windows NT 6.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36", +"Mozilla/5.0 (Windows NT 6.2; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36", +"Mozilla/5.0 (Windows NT 6.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36", +"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36", +"Mozilla/5.0 (Linux; Android 6.0.1; vivo 1603 Build/MMB29M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.83 Mobile Safari/537.36", +"Mozilla/5.0 (Windows NT 5.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36", +"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36", +"Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.106 Safari/537.36", +"Mozilla/5.0 (Unknown; Linux) AppleWebKit/538.1 (KHTML, like Gecko) Chrome/v1.0.0 Safari/538.1", +"Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36", +"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36", +"Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.109 Safari/537.36", +"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36", +"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.79 Safari/537.36", +"Mozilla/5.0 (Linux; Android 6.0; vivo 1713 Build/MRA58K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.124 Mobile Safari/537.36", +"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36", +"Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36", +"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36", +"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.94 Safari/537.36", +"Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.63 Safari/537.36", +"Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36", +"Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36", +"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36", +"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.93 Safari/537.36", +"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36", +"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36", +"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.118 Safari/537.36", +"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36", +"Mozilla/5.0 (Linux; Android 6.0; vivo 1610 Build/MMB29M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.124 Mobile Safari/537.36", +"Mozilla/5.0 (Linux; Android 6.0.1; SM-G532G Build/MMB29T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.83 Mobile Safari/537.36", +"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36", +"Mozilla/5.0 (Linux; Android 5.1.1; vivo X7 Build/LMY47V; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/48.0.2564.116 Mobile Safari/537.36 baiduboxapp/8.6.5 (Baidu; P1 5.1.1)", +"Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36", +"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.101 Safari/537.36", +"Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.65 Safari/537.36", +"Mozilla/5.0 (Windows NT 6.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.112 Safari/537.36", +"Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36", +"Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.80 Safari/537.36", +"Mozilla/5.0 (Windows NT 6.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.80 Safari/537.36", +"Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.106 Safari/537.36" +] diff --git a/services/liquid-auth-api-js/src/__mocks__/assertion.service.mock.ts b/services/liquid-auth-api-js/src/__mocks__/assertion.service.mock.ts deleted file mode 100644 index d59ef3e..0000000 --- a/services/liquid-auth-api-js/src/__mocks__/assertion.service.mock.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { dummyUsers, dummyOptions } from '../../tests/constants.js'; - -export const mockAssertionService = { - request: jest.fn().mockReturnValue(dummyOptions), - response: jest.fn().mockReturnValue(dummyUsers[0]), -}; diff --git a/services/liquid-auth-api-js/src/__mocks__/attestation.service.mock.ts b/services/liquid-auth-api-js/src/__mocks__/attestation.service.mock.ts deleted file mode 100644 index ab062ee..0000000 --- a/services/liquid-auth-api-js/src/__mocks__/attestation.service.mock.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { dummyAttestationOptions } from '../../tests/constants.js'; - -export const mockAttestationService = { - request: jest.fn().mockReturnValue(dummyAttestationOptions), - response: jest.fn().mockReturnValue({}), -}; diff --git a/services/liquid-auth-api-js/src/adapters/redis-io.adapter.spec.ts b/services/liquid-auth-api-js/src/adapters/redis-io.adapter.spec.ts new file mode 100644 index 0000000..03ece02 --- /dev/null +++ b/services/liquid-auth-api-js/src/adapters/redis-io.adapter.spec.ts @@ -0,0 +1,7 @@ +import { RedisIoAdapter } from './redis-io.adapter.js'; +describe('RedisIoAdapter', () => { + it('should create an instance', () => { + const adapter = new RedisIoAdapter(null, null); + expect(adapter).toBeInstanceOf(RedisIoAdapter); + }); +}); diff --git a/services/liquid-auth-api-js/src/algod/algod.service.spec.ts b/services/liquid-auth-api-js/src/algod/algod.service.spec.ts new file mode 100644 index 0000000..18e1fdb --- /dev/null +++ b/services/liquid-auth-api-js/src/algod/algod.service.spec.ts @@ -0,0 +1,27 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { AlgodService } from './algod.service.js'; +import { ConfigModule, ConfigService } from '@nestjs/config'; + +import configurationFixture from '../__fixtures__/configuration.fixture.json'; + +describe('AlgodService', () => { + let provider: AlgodService; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + imports: [ + ConfigModule.forRoot({ + isGlobal: true, + load: [() => configurationFixture], + }), + ], + providers: [ConfigService, AlgodService], + }).compile(); + + provider = module.get(AlgodService); + }); + + it('should be defined', () => { + expect(provider).toBeDefined(); + }); +}); diff --git a/services/liquid-auth-api-js/src/android/android.controller.spec.ts b/services/liquid-auth-api-js/src/android/android.controller.spec.ts index 88a47f5..5099d9f 100644 --- a/services/liquid-auth-api-js/src/android/android.controller.spec.ts +++ b/services/liquid-auth-api-js/src/android/android.controller.spec.ts @@ -1,9 +1,13 @@ import { Test, TestingModule } from '@nestjs/testing'; import { AndroidController } from './android.controller.js'; +import assetLinksInstance from '../../assetlinks.json'; +import uaChromeFixtures from '../__fixtures__/user-agent.chrome.fixtures.json'; + +const assetLinks = [...assetLinksInstance]; + describe('AndroidController', () => { let controller: AndroidController; - beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ controllers: [AndroidController], @@ -15,4 +19,66 @@ describe('AndroidController', () => { it('should be defined', () => { expect(controller).toBeDefined(); }); + + it('should return asset links', () => { + uaChromeFixtures.forEach((ua) => { + expect( + controller.assetLinks({ + headers: { 'user-agent': ua } as unknown as Headers, + } as Request), + ).toEqual(assetLinks); + }); + }); + it('should return developer web links', () => { + process.env.NODE_ENV = 'development'; + process.env.ORIGIN = 'http://unkown.site'; + expect( + controller.assetLinks({ + headers: { 'user-agent': uaChromeFixtures[0] } as unknown as Headers, + } as Request), + ).toEqual([ + ...assetLinks, + { + relation: [ + 'delegate_permission/common.handle_all_urls', + 'delegate_permission/common.get_login_creds', + ], + target: { + namespace: 'web', + site: 'http://unkown.site', + }, + }, + ]); + process.env.NODE_ENV = 'test'; + delete process.env.ORIGIN; + }); + it('should return developer android links', () => { + process.env.NODE_ENV = 'development'; + process.env.ANDROID_PACKAGENAME = 'com.example'; + process.env.ANDROID_SHA256HASH = + 'AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA'; + expect( + controller.assetLinks({ + headers: { 'user-agent': uaChromeFixtures[0] } as unknown as Headers, + } as Request), + ).toEqual([ + ...assetLinks, + { + relation: [ + 'delegate_permission/common.handle_all_urls', + 'delegate_permission/common.get_login_creds', + ], + target: { + namespace: 'android_app', + package_name: 'com.example', + sha256_cert_fingerprints: [ + 'AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA', + ], + }, + }, + ]); + process.env.NODE_ENV = 'test'; + delete process.env.ANDROID_PACKAGENAME; + delete process.env.ANDROID_SHA256HASH; + }); }); diff --git a/services/liquid-auth-api-js/src/android/android.controller.ts b/services/liquid-auth-api-js/src/android/android.controller.ts index 172350a..759f9e3 100644 --- a/services/liquid-auth-api-js/src/android/android.controller.ts +++ b/services/liquid-auth-api-js/src/android/android.controller.ts @@ -1,8 +1,9 @@ -import { Controller, Get, Logger, Req, Res } from '@nestjs/common'; -import type { Response } from 'express'; +import { Controller, Get, Logger, Req } from '@nestjs/common'; //@ts-ignore, required for jest import assetLinks from '../../assetlinks.json' assert { type: 'json' }; +import { ApiOperation, ApiTags } from '@nestjs/swagger'; @Controller('.well-known') +@ApiTags('.well-known') export class AndroidController { private readonly logger = new Logger(AndroidController.name); @@ -11,14 +12,15 @@ export class AndroidController { * * @see https://developer.android.com/training/app-links/verify-android-applinks * @param req - * @param res * */ + @ApiOperation({ summary: 'Asset Links' }) @Get('/assetlinks.json') - assetLinks(@Req() req: Request, @Res() res: Response) { + assetLinks(@Req() req: Request) { this.logger.debug( `GET /.well-known/assetlinks.json ${req.headers['user-agent']}`, ); + const additionalEntries = []; // In Development, allow for overriding the asset links if (process.env.NODE_ENV === 'development') { const relation = [ @@ -26,7 +28,7 @@ export class AndroidController { 'delegate_permission/common.get_login_creds', ]; if (!assetLinks.some((al) => al.target.site === process.env.ORIGIN)) { - assetLinks.push({ + additionalEntries.push({ relation, target: { namespace: 'web', @@ -42,7 +44,7 @@ export class AndroidController { (al) => al.target.package_name === process.env.ANDROID_PACKAGENAME, ) ) { - assetLinks.push({ + additionalEntries.push({ relation, target: { namespace: 'android_app', @@ -52,6 +54,6 @@ export class AndroidController { }); } } - res.json(assetLinks); + return [...assetLinks, ...additionalEntries]; } } diff --git a/services/liquid-auth-api-js/src/app.controller.ts b/services/liquid-auth-api-js/src/app.controller.ts deleted file mode 100644 index 866b9cd..0000000 --- a/services/liquid-auth-api-js/src/app.controller.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { Controller, Get, Logger, Req, Res, Session } from '@nestjs/common'; -import type { Response } from 'express'; - -@Controller() -export class AppController { - private readonly logger = new Logger(AppController.name); - - /** - * Serve the SPA - * - * @param req - Express request - * @param res - Express Response - * @param session - Express Session - */ - @Get('/') - root( - @Req() req: Request, - @Res() res: Response, - @Session() session: Record, - ) { - session.active = true; - this.logger.log( - `GET / Render for Session: ${session.id} UA: ${req.headers['user-agent']}`, - ); - res.render('index'); - } -} diff --git a/services/liquid-auth-api-js/src/app.module.spec.ts b/services/liquid-auth-api-js/src/app.module.spec.ts new file mode 100644 index 0000000..a10125a --- /dev/null +++ b/services/liquid-auth-api-js/src/app.module.spec.ts @@ -0,0 +1,19 @@ +import { mongooseModuleFactory } from './app.module.js'; + +import databaseConfigFixtures from './__fixtures__/configuration.database.fixtures.json'; +import { ConfigService } from '@nestjs/config'; + +describe('AppModule', () => { + it('should create the module with atlas configuration', async () => { + databaseConfigFixtures.forEach((fixture) => { + const mockConfigService = { + get: jest.fn().mockReturnValue(fixture), + } as unknown as ConfigService; + const { name, host, username, password, atlas } = fixture; + const prefix = atlas ? 'mongodb+srv' : 'mongodb'; + expect(mongooseModuleFactory(mockConfigService)).toEqual({ + uri: `${prefix}://${username}:${password}@${host}/${name}?authSource=admin&retryWrites=true&w=majority`, + }); + }); + }); +}); diff --git a/services/liquid-auth-api-js/src/app.module.ts b/services/liquid-auth-api-js/src/app.module.ts index d21f66c..65a87ad 100644 --- a/services/liquid-auth-api-js/src/app.module.ts +++ b/services/liquid-auth-api-js/src/app.module.ts @@ -13,34 +13,33 @@ import { AndroidController } from './android/android.controller.js'; // User Endpoints import { AuthModule } from './auth/auth.module.js'; -// Connect/Signals -import { ConnectModule } from './connect/connect.module.js'; +// Signals import { SignalsModule } from './signals/signals.module.js'; -import { AppController } from './app.controller.js'; + +export function mongooseModuleFactory(configService: ConfigService) { + const database = configService.get('database'); + const { host, username, password, name, atlas: isAtlas } = database; + const uri = `mongodb${ + isAtlas ? '+srv' : '' + }://${username}:${password}@${host}/${name}?authSource=admin&retryWrites=true&w=majority`; + return { + uri, + }; +} @Module({ imports: [ ConfigModule.forRoot({ isGlobal: true, load: [configuration] }), MongooseModule.forRootAsync({ imports: [ConfigModule], - useFactory: async (configService: ConfigService) => { - const database = configService.get('database'); - const { host, username, password, name, atlas: isAtlas } = database; - const uri = `mongodb${ - isAtlas ? '+srv' : '' - }://${username}:${password}@${host}/${name}?authSource=admin&retryWrites=true&w=majority`; - return { - uri, - }; - }, + useFactory: mongooseModuleFactory, inject: [ConfigService], }), AuthModule, AttestationModule, AssertionModule, - ConnectModule, SignalsModule, ], - controllers: [AndroidController, AppController], + controllers: [AndroidController], }) export class AppModule {} diff --git a/services/liquid-auth-api-js/src/app.service.spec.ts b/services/liquid-auth-api-js/src/app.service.spec.ts new file mode 100644 index 0000000..e4b0fd6 --- /dev/null +++ b/services/liquid-auth-api-js/src/app.service.spec.ts @@ -0,0 +1,73 @@ +import { Test, TestingModule } from '@nestjs/testing'; + +import uaChromeFixtures from './__fixtures__/user-agent.chrome.fixtures.json'; +import uaAndroidFixtures from './__fixtures__/user-agent.android.fixtures.json'; +import configurationFixture from './__fixtures__/configuration.fixture.json'; + +import { AppService } from './app.service.js'; +import { ConfigModule, ConfigService } from '@nestjs/config'; + +jest.mock( + '../assetlinks.json', + () => { + return [ + { + relation: [ + 'delegate_permission/common.handle_all_urls', + 'delegate_permission/common.get_login_creds', + ], + target: { + namespace: 'web', + site: 'https://nest-authentication-api.onrender.com', + }, + }, + ...uaAndroidFixtures.map((ua) => { + return { + relation: [ + 'delegate_permission/common.handle_all_urls', + 'delegate_permission/common.get_login_creds', + ], + target: { + namespace: 'android_app', + package_name: ua.split('/')[0], + sha256_cert_fingerprints: [ + 'AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA', + ], + }, + }; + }), + ]; + }, + { virtual: true }, +); + +describe('AppService', () => { + let provider: AppService; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + imports: [ + ConfigModule.forRoot({ + isGlobal: true, + load: [() => configurationFixture], + }), + ], + providers: [ConfigService, AppService], + }).compile(); + + provider = module.get(AppService); + }); + + it('should return the configured origin when it is from chrome', () => { + uaChromeFixtures.forEach((ua) => { + expect(provider.getOrigin(ua)).toEqual(configurationFixture.origin); + }); + }); + it('should return an android origin when it is from an app', () => { + uaAndroidFixtures.forEach((ua) => { + expect(provider.getOrigin(ua)).toEqual( + 'android:apk-key-hash:qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqo', + ); + }); + }); +}); diff --git a/services/liquid-auth-api-js/src/app.service.ts b/services/liquid-auth-api-js/src/app.service.ts index dc1526f..f66f084 100644 --- a/services/liquid-auth-api-js/src/app.service.ts +++ b/services/liquid-auth-api-js/src/app.service.ts @@ -19,7 +19,6 @@ export class AppService { typeof parser.getBrowser().name !== 'string' ) { const pkgName = ua.split('/')[0]; - console.log(pkgName); const statement = assetLinks.filter( (al) => al?.target?.package_name === pkgName, ); diff --git a/services/liquid-auth-api-js/src/assertion/__fixtures__/assertion.request.body.fixtures.json b/services/liquid-auth-api-js/src/assertion/__fixtures__/assertion.request.body.fixtures.json new file mode 100644 index 0000000..5d8c015 --- /dev/null +++ b/services/liquid-auth-api-js/src/assertion/__fixtures__/assertion.request.body.fixtures.json @@ -0,0 +1,8 @@ +[ + {}, + {}, + {}, + {}, + {}, + {} +] \ No newline at end of file diff --git a/services/liquid-auth-api-js/src/assertion/__fixtures__/assertion.request.param.fixtures.json b/services/liquid-auth-api-js/src/assertion/__fixtures__/assertion.request.param.fixtures.json new file mode 100644 index 0000000..9d4ee5d --- /dev/null +++ b/services/liquid-auth-api-js/src/assertion/__fixtures__/assertion.request.param.fixtures.json @@ -0,0 +1,8 @@ +[ + "AYMPi2Rbhcnu2gSHOO1TNvzDJ38iU00rrlCqyH874XCIEoIotRc7eVRFpx0TvsQurg7BAnXy5KnWdKC8LeWs0k0", + "ASk2I69zskHtkQLgnI_zHCAS9n7AwYoGSN8TEfE2D2IrVjETxVJADCdlYAu5lqhigqWvjGq8M0cfHcludnSD-3I", + "AbqTh-5GQBr6NoOMkL_bTOpCDOVBF7_yHvi084BjrlLy8LYLoCJ3Uknichga4FDPY9vq6r3tdGPWS8a9s_Kkpco", + "Af6bB9Z_zx0PmRlncq9IbzRzTuxPS-yvEwOrtojHy7eOOVnhGxxHICrKQfoiXv8sINQjs_3AX9TEejK7VOvav-c", + "AVl7TsljN83pJD7_FfyXNoGubqbs37t41TGV9Y7V4jtgb30BnpqqlUwsQiB-a2h5ovTpkoJg5ChnQEmMlC6L0Sw", + "AYvDA1VZ-qkvCPmf7Re7_GVDY4AwzmUFbI1Njsl3kDcI9BFKTqTd0YUC47IK-peJbf3weNCUdqmB2_QDEPy7iR4" +] \ No newline at end of file diff --git a/services/liquid-auth-api-js/src/assertion/__fixtures__/assertion.request.response.fixtures.json b/services/liquid-auth-api-js/src/assertion/__fixtures__/assertion.request.response.fixtures.json new file mode 100644 index 0000000..9fdc5bf --- /dev/null +++ b/services/liquid-auth-api-js/src/assertion/__fixtures__/assertion.request.response.fixtures.json @@ -0,0 +1,74 @@ +[ + { + "challenge": "0TXu4G4iu3sbAQopheoPe_CpnLJOB-QlIUvwFBC317Q", + "allowCredentials": [ + { + "id": "AYMPi2Rbhcnu2gSHOO1TNvzDJ38iU00rrlCqyH874XCIEoIotRc7eVRFpx0TvsQurg7BAnXy5KnWdKC8LeWs0k0", + "type": "public-key" + } + ], + "timeout": 1800000, + "userVerification": "required", + "rpId": "catfish-pro-wolf.ngrok-free.app" + }, + { + "challenge": "h8upgZHta6ZifR3ApK83Jjpb7SC0IhOK_j839UuLOSo", + "allowCredentials": [ + { + "id": "ASk2I69zskHtkQLgnI_zHCAS9n7AwYoGSN8TEfE2D2IrVjETxVJADCdlYAu5lqhigqWvjGq8M0cfHcludnSD-3I", + "type": "public-key" + } + ], + "timeout": 1800000, + "userVerification": "required", + "rpId": "catfish-pro-wolf.ngrok-free.app" + }, + { + "challenge": "zWFuwmsM9mYVoSYgOzhcBU0R2kyvNANTQiSwPM4emmo", + "allowCredentials": [ + { + "id": "AbqTh-5GQBr6NoOMkL_bTOpCDOVBF7_yHvi084BjrlLy8LYLoCJ3Uknichga4FDPY9vq6r3tdGPWS8a9s_Kkpco", + "type": "public-key" + } + ], + "timeout": 1800000, + "userVerification": "required", + "rpId": "catfish-pro-wolf.ngrok-free.app" + }, + { + "challenge": "coubA_4RNRJE-oQJQk82i1yZoCZ6kb_NrzsW4DxU2Xo", + "allowCredentials": [ + { + "id": "Af6bB9Z_zx0PmRlncq9IbzRzTuxPS-yvEwOrtojHy7eOOVnhGxxHICrKQfoiXv8sINQjs_3AX9TEejK7VOvav-c", + "type": "public-key" + } + ], + "timeout": 1800000, + "userVerification": "required", + "rpId": "catfish-pro-wolf.ngrok-free.app" + }, + { + "challenge": "s4UTa1JBoSkqjNpHb8i6xepK0Gc9esz7sRSygiY1lf4", + "allowCredentials": [ + { + "id": "AVl7TsljN83pJD7_FfyXNoGubqbs37t41TGV9Y7V4jtgb30BnpqqlUwsQiB-a2h5ovTpkoJg5ChnQEmMlC6L0Sw", + "type": "public-key" + } + ], + "timeout": 1800000, + "userVerification": "required", + "rpId": "catfish-pro-wolf.ngrok-free.app" + }, + { + "challenge": "Gkc9Cqhn8TEprdIjRT9l8R6mI2H5q8pe64VRRSBaDWE", + "allowCredentials": [ + { + "id": "AYvDA1VZ-qkvCPmf7Re7_GVDY4AwzmUFbI1Njsl3kDcI9BFKTqTd0YUC47IK-peJbf3weNCUdqmB2_QDEPy7iR4", + "type": "public-key" + } + ], + "timeout": 1800000, + "userVerification": "required", + "rpId": "catfish-pro-wolf.ngrok-free.app" + } +] \ No newline at end of file diff --git a/services/liquid-auth-api-js/src/assertion/__fixtures__/assertion.response.body.fixtures.json b/services/liquid-auth-api-js/src/assertion/__fixtures__/assertion.response.body.fixtures.json new file mode 100644 index 0000000..0d0285b --- /dev/null +++ b/services/liquid-auth-api-js/src/assertion/__fixtures__/assertion.response.body.fixtures.json @@ -0,0 +1,92 @@ +[ + { + "id": "AYMPi2Rbhcnu2gSHOO1TNvzDJ38iU00rrlCqyH874XCIEoIotRc7eVRFpx0TvsQurg7BAnXy5KnWdKC8LeWs0k0", + "type": "public-key", + "rawId": "AYMPi2Rbhcnu2gSHOO1TNvzDJ38iU00rrlCqyH874XCIEoIotRc7eVRFpx0TvsQurg7BAnXy5KnWdKC8LeWs0k0", + "clientExtensionResults": { + "liquid": { + "requestId": 0.4352672418598509 + } + }, + "response": { + "clientDataJSON": "eyJ0eXBlIjoid2ViYXV0aG4uZ2V0IiwiY2hhbGxlbmdlIjoiMFRYdTRHNGl1M3NiQVFvcGhlb1BlX0NwbkxKT0ItUWxJVXZ3RkJDMzE3USIsIm9yaWdpbiI6ImFuZHJvaWQ6YXBrLWtleS1oYXNoOlI4eE83cmxRV2FXTDRCbEZ5Z3B0V1JiNXFjS1dkZmp6WklhU1JpdDlYVnciLCJhbmRyb2lkUGFja2FnZU5hbWUiOiJmb3VuZGF0aW9uLmFsZ29yYW5kLmRlbW8ifQ", + "authenticatorData": "lpPmT7RcYTDeFJdKhDtiKwzb05n-ojlcqqYw5SomXZAFAAAAAQ", + "signature": "MEUCIQDcV2y6ub3Qh8pyTCCLdWKRH_cmR2xlFuNy1Fn1QsSUygIgTZh9b6mB77C-aQrBj7Evb8u3S4j3vjlnSPAKcR7Kld4" + } + }, + { + "id": "ASk2I69zskHtkQLgnI_zHCAS9n7AwYoGSN8TEfE2D2IrVjETxVJADCdlYAu5lqhigqWvjGq8M0cfHcludnSD-3I", + "type": "public-key", + "rawId": "ASk2I69zskHtkQLgnI_zHCAS9n7AwYoGSN8TEfE2D2IrVjETxVJADCdlYAu5lqhigqWvjGq8M0cfHcludnSD-3I", + "clientExtensionResults": { + "liquid": { + "requestId": 0.6811027920177524 + } + }, + "response": { + "clientDataJSON": "eyJ0eXBlIjoid2ViYXV0aG4uZ2V0IiwiY2hhbGxlbmdlIjoiaDh1cGdaSHRhNlppZlIzQXBLODNKanBiN1NDMEloT0tfajgzOVV1TE9TbyIsIm9yaWdpbiI6ImFuZHJvaWQ6YXBrLWtleS1oYXNoOlI4eE83cmxRV2FXTDRCbEZ5Z3B0V1JiNXFjS1dkZmp6WklhU1JpdDlYVnciLCJhbmRyb2lkUGFja2FnZU5hbWUiOiJmb3VuZGF0aW9uLmFsZ29yYW5kLmRlbW8ifQ", + "authenticatorData": "lpPmT7RcYTDeFJdKhDtiKwzb05n-ojlcqqYw5SomXZAFAAAAAQ", + "signature": "MEUCIQDVXDxGBJj-YnSxZ1masei8Yt4baukaHUetGq7nqSJNaAIgbxE5GlJJW-_FgrzNQi9zjKgLyuINEufkTq3Pv6K2P6w" + } + }, + { + "id": "AbqTh-5GQBr6NoOMkL_bTOpCDOVBF7_yHvi084BjrlLy8LYLoCJ3Uknichga4FDPY9vq6r3tdGPWS8a9s_Kkpco", + "type": "public-key", + "rawId": "AbqTh-5GQBr6NoOMkL_bTOpCDOVBF7_yHvi084BjrlLy8LYLoCJ3Uknichga4FDPY9vq6r3tdGPWS8a9s_Kkpco", + "clientExtensionResults": { + "liquid": { + "requestId": 0.45568228623762996 + } + }, + "response": { + "clientDataJSON": "eyJ0eXBlIjoid2ViYXV0aG4uZ2V0IiwiY2hhbGxlbmdlIjoieldGdXdtc005bVlWb1NZZ096aGNCVTBSMmt5dk5BTlRRaVN3UE00ZW1tbyIsIm9yaWdpbiI6ImFuZHJvaWQ6YXBrLWtleS1oYXNoOlI4eE83cmxRV2FXTDRCbEZ5Z3B0V1JiNXFjS1dkZmp6WklhU1JpdDlYVnciLCJhbmRyb2lkUGFja2FnZU5hbWUiOiJmb3VuZGF0aW9uLmFsZ29yYW5kLmRlbW8ifQ", + "authenticatorData": "lpPmT7RcYTDeFJdKhDtiKwzb05n-ojlcqqYw5SomXZAFAAAAAQ", + "signature": "MEUCIAo4HIAQCM_uFhutnDdxFqBpqBPGuHsQBKtWPl4dn98UAiEAsQMo71P1PSn4onOZUzhHDL0Tuyw5Yqdlfj_MJ9zbo3M" + } + }, + { + "id": "Af6bB9Z_zx0PmRlncq9IbzRzTuxPS-yvEwOrtojHy7eOOVnhGxxHICrKQfoiXv8sINQjs_3AX9TEejK7VOvav-c", + "type": "public-key", + "rawId": "Af6bB9Z_zx0PmRlncq9IbzRzTuxPS-yvEwOrtojHy7eOOVnhGxxHICrKQfoiXv8sINQjs_3AX9TEejK7VOvav-c", + "clientExtensionResults": { + "liquid": { + "requestId": 0.22356418742804784 + } + }, + "response": { + "clientDataJSON": "eyJ0eXBlIjoid2ViYXV0aG4uZ2V0IiwiY2hhbGxlbmdlIjoiY291YkFfNFJOUkpFLW9RSlFrODJpMXlab0NaNmtiX05yenNXNER4VTJYbyIsIm9yaWdpbiI6ImFuZHJvaWQ6YXBrLWtleS1oYXNoOlI4eE83cmxRV2FXTDRCbEZ5Z3B0V1JiNXFjS1dkZmp6WklhU1JpdDlYVnciLCJhbmRyb2lkUGFja2FnZU5hbWUiOiJmb3VuZGF0aW9uLmFsZ29yYW5kLmRlbW8ifQ", + "authenticatorData": "lpPmT7RcYTDeFJdKhDtiKwzb05n-ojlcqqYw5SomXZAFAAAAAQ", + "signature": "MEQCIFbl78zFs3Bbw9pmCA5doG-50g9pQ4SvDm-90y-g4W-3AiA5gt7YP-amW52GmlheQd_Q60gPc60VXvDNq_wuVo7FoQ" + } + }, + { + "id": "AVl7TsljN83pJD7_FfyXNoGubqbs37t41TGV9Y7V4jtgb30BnpqqlUwsQiB-a2h5ovTpkoJg5ChnQEmMlC6L0Sw", + "type": "public-key", + "rawId": "AVl7TsljN83pJD7_FfyXNoGubqbs37t41TGV9Y7V4jtgb30BnpqqlUwsQiB-a2h5ovTpkoJg5ChnQEmMlC6L0Sw", + "clientExtensionResults": { + "liquid": { + "requestId": 0.3868176416671725 + } + }, + "response": { + "clientDataJSON": "eyJ0eXBlIjoid2ViYXV0aG4uZ2V0IiwiY2hhbGxlbmdlIjoiczRVVGExSkJvU2txak5wSGI4aTZ4ZXBLMEdjOWVzejdzUlN5Z2lZMWxmNCIsIm9yaWdpbiI6ImFuZHJvaWQ6YXBrLWtleS1oYXNoOlI4eE83cmxRV2FXTDRCbEZ5Z3B0V1JiNXFjS1dkZmp6WklhU1JpdDlYVnciLCJhbmRyb2lkUGFja2FnZU5hbWUiOiJmb3VuZGF0aW9uLmFsZ29yYW5kLmRlbW8ifQ", + "authenticatorData": "lpPmT7RcYTDeFJdKhDtiKwzb05n-ojlcqqYw5SomXZAFAAAAAQ", + "signature": "MEUCIQCoo3153aPecLbQbOM7Na46KZHA602dZ7EaGdilmoyZaAIgUIHl5A7mD64NtwyIy-29O68DErWAzRN9P2rjUBQLTUw" + } + }, + { + "id": "AYvDA1VZ-qkvCPmf7Re7_GVDY4AwzmUFbI1Njsl3kDcI9BFKTqTd0YUC47IK-peJbf3weNCUdqmB2_QDEPy7iR4", + "type": "public-key", + "rawId": "AYvDA1VZ-qkvCPmf7Re7_GVDY4AwzmUFbI1Njsl3kDcI9BFKTqTd0YUC47IK-peJbf3weNCUdqmB2_QDEPy7iR4", + "clientExtensionResults": { + "liquid": { + "requestId": 0.05638003353723975 + } + }, + "response": { + "clientDataJSON": "eyJ0eXBlIjoid2ViYXV0aG4uZ2V0IiwiY2hhbGxlbmdlIjoiR2tjOUNxaG44VEVwcmRJalJUOWw4UjZtSTJINXE4cGU2NFZSUlNCYURXRSIsIm9yaWdpbiI6ImFuZHJvaWQ6YXBrLWtleS1oYXNoOlI4eE83cmxRV2FXTDRCbEZ5Z3B0V1JiNXFjS1dkZmp6WklhU1JpdDlYVnciLCJhbmRyb2lkUGFja2FnZU5hbWUiOiJmb3VuZGF0aW9uLmFsZ29yYW5kLmRlbW8ifQ", + "authenticatorData": "lpPmT7RcYTDeFJdKhDtiKwzb05n-ojlcqqYw5SomXZAFAAAAAQ", + "signature": "MEUCIBqQutY1l53mnXSSNtcE15QgudAhtoPw7DI8oiqGh6yrAiEA7-NBpwF4Zjh9frKzA_qOTNWIQjANbfDXmWV6oItgydE" + } + } +] \ No newline at end of file diff --git a/services/liquid-auth-api-js/src/assertion/__fixtures__/assertion.response.response.fixtures.json b/services/liquid-auth-api-js/src/assertion/__fixtures__/assertion.response.response.fixtures.json new file mode 100644 index 0000000..f4d92c9 --- /dev/null +++ b/services/liquid-auth-api-js/src/assertion/__fixtures__/assertion.response.response.fixtures.json @@ -0,0 +1,86 @@ +[ + { + "_id": "662c2ca47c56f26fbd619624", + "id": "M6RT4iT5FkNDM2i57MXzBhLDt9zl2CrLt2p4Ar03t2Q", + "wallet": "2SPDE6XLJNXFTOO7OIGNRNKSEDOHJWVD3HBSEAPHONZQ4IQEYOGYTP6LXA", + "credentials": [ + { + "device": "Pixel 8 Pro", + "publicKey": "pQECAyYgASFYIB2dcp3wanhReRhgRIpJCUfRSwkCvyE9OdvEL_NlncSJIlggkSIz7h7O5nrAXGJrkCOmeolChSc09eHzniCFLFxaKH0", + "credId": "AYMPi2Rbhcnu2gSHOO1TNvzDJ38iU00rrlCqyH874XCIEoIotRc7eVRFpx0TvsQurg7BAnXy5KnWdKC8LeWs0k0", + "prevCounter": 1 + } + ], + "__v": 0 + }, + { + "_id": "662c2cbe7c56f26fbd619639", + "id": "w0Me3F2XfcK_wVdMejk6Xl98gHmOtqxcN-WKjLydDA0", + "wallet": "KH4XYQ4ZYKARWZAYVIVAY6WPWXNU3FWU2QC6HF2666KKM6CH4APTUIOQHU", + "credentials": [ + { + "device": "Pixel 8 Pro", + "publicKey": "pQECAyYgASFYIIYtbWsD526npX6pWVda473yek0mi8uLWbpQPAv5pJQTIlgg1j0emgrGTJoujIqn27cBBatDEegpRsKwDvzYw7GTuMM", + "credId": "ASk2I69zskHtkQLgnI_zHCAS9n7AwYoGSN8TEfE2D2IrVjETxVJADCdlYAu5lqhigqWvjGq8M0cfHcludnSD-3I", + "prevCounter": 1 + } + ], + "__v": 0 + }, + { + "_id": "662c2cdc7c56f26fbd61964f", + "id": "mvpgdpIfho5IPdU3QquBDDmnnuUD6DittFevmJCMZmA", + "wallet": "6P3TIK6KEPUNVHM77UXVG7ZIZRCCJX6IKZ5FA3WMXKRBHIXW4SAQ3OSEY4", + "credentials": [ + { + "device": "Pixel 8 Pro", + "publicKey": "pQECAyYgASFYIMJO5NYWM6zT5iCx-dSK8xqXkDiebkZtHpjX7FKwZ_L9IlggM02BH4IpsxBww-avE70ZYHbtFv6wCFbTOFGVJ8jmBYA", + "credId": "AbqTh-5GQBr6NoOMkL_bTOpCDOVBF7_yHvi084BjrlLy8LYLoCJ3Uknichga4FDPY9vq6r3tdGPWS8a9s_Kkpco", + "prevCounter": 1 + } + ], + "__v": 0 + }, + { + "_id": "662c2cf77c56f26fbd619664", + "id": "iIet1pMIMOIPmfws0m2aTenDOI1xhux775w09SlNhXM", + "wallet": "2W5VGV43VOKJTVFZXCEZ6L647XCQEXCDNZGDVFROWAR4FZJJCOWHVXLFOE", + "credentials": [ + { + "device": "Pixel 8 Pro", + "publicKey": "pQECAyYgASFYIL8k0vHupVfbe8EQSsRFkGHfjKf_6ZWv63QsqHrxWCWgIlggfy32BhGoicWESUFJ6XhlZUZckPKuGkBacEnLP5pDOPY", + "credId": "Af6bB9Z_zx0PmRlncq9IbzRzTuxPS-yvEwOrtojHy7eOOVnhGxxHICrKQfoiXv8sINQjs_3AX9TEejK7VOvav-c", + "prevCounter": 1 + } + ], + "__v": 0 + }, + { + "_id": "662c2d127c56f26fbd61967a", + "id": "0Xb1BYjal05QzGSe2kUN5BRoBPjR4seyssK1GJKgxhE", + "wallet": "L72CSGO2C7K6QJZHVC2AYCLZ5GY3IMN7GJVKVNXU5WDDKLENPKSBZ7GE7U", + "credentials": [ + { + "device": "Pixel 8 Pro", + "publicKey": "pQECAyYgASFYIJ2cwWQ49K-Sr7ldYkfUCI8hl42qvcFrfDxyquE-7mOiIlggDOxVoZzESas5nboQLMrsL4mHnbdA1zRmnTvqm7qb1s8", + "credId": "AVl7TsljN83pJD7_FfyXNoGubqbs37t41TGV9Y7V4jtgb30BnpqqlUwsQiB-a2h5ovTpkoJg5ChnQEmMlC6L0Sw", + "prevCounter": 1 + } + ], + "__v": 0 + }, + { + "_id": "662c2d2c7c56f26fbd61968f", + "id": "hoQk-DlJOXqyuV2IDKtBHEE2DYr7K2_DTgAyiFcgGpE", + "wallet": "OXOACNIWZ7VDJXJXJHQ53BMNFQTSPPW524RU5JVAFLHSSGGQZCTII65ZII", + "credentials": [ + { + "device": "Pixel 8 Pro", + "publicKey": "pQECAyYgASFYIF5hkHAZkg76PAXB5DGb0IcJJXlxYqT6HSIequIL6DYyIlggaRfQcwy7w-hx-AcLgEZ57oq1n3nCcL8QodheQcLcbto", + "credId": "AYvDA1VZ-qkvCPmf7Re7_GVDY4AwzmUFbI1Njsl3kDcI9BFKTqTd0YUC47IK-peJbf3weNCUdqmB2_QDEPy7iR4", + "prevCounter": 1 + } + ], + "__v": 0 + } +] \ No newline at end of file diff --git a/services/liquid-auth-api-js/src/assertion/assertion.controller.post.request.md b/services/liquid-auth-api-js/src/assertion/assertion.controller.post.request.md new file mode 100644 index 0000000..53fad4d --- /dev/null +++ b/services/liquid-auth-api-js/src/assertion/assertion.controller.post.request.md @@ -0,0 +1,3 @@ +# POST Assertion Request + +This endpoint is used to request assertion options from the FIDO2 service. diff --git a/services/liquid-auth-api-js/src/assertion/assertion.controller.post.response.md b/services/liquid-auth-api-js/src/assertion/assertion.controller.post.response.md new file mode 100644 index 0000000..698d2ec --- /dev/null +++ b/services/liquid-auth-api-js/src/assertion/assertion.controller.post.response.md @@ -0,0 +1,3 @@ +# POST Assertion Response + +This endpoint is used to request assertion options from the FIDO2 service. diff --git a/services/liquid-auth-api-js/src/assertion/assertion.controller.spec.ts b/services/liquid-auth-api-js/src/assertion/assertion.controller.spec.ts new file mode 100644 index 0000000..df8d5df --- /dev/null +++ b/services/liquid-auth-api-js/src/assertion/assertion.controller.spec.ts @@ -0,0 +1,220 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { AuthService } from '../auth/auth.service.js'; +import { Session } from '../auth/session.schema.js'; +import mongoose, { Model } from 'mongoose'; +import { User, UserSchema } from '../auth/auth.schema.js'; +import { getModelToken } from '@nestjs/mongoose'; +import { Request } from 'express'; +import { AssertionController } from './assertion.controller.js'; +import { AssertionService } from './assertion.service.js'; +import { mockAuthService } from '../__mocks__/auth.service.mock.js'; +import { mockAccountLinkService } from '../__mocks__/account-link.service.mock.js'; +import { AppService } from '../app.service.js'; +import { ConfigModule, ConfigService } from '@nestjs/config'; + +import assertionRequestBodyFixtures from './__fixtures__/assertion.request.body.fixtures.json'; +import assertionRequestParamFixtures from './__fixtures__/assertion.request.param.fixtures.json'; +import assertionRequestResponseFixtures from './__fixtures__/assertion.request.response.fixtures.json'; +import assertionResponseBodyFixtures from './__fixtures__/assertion.response.body.fixtures.json'; +import assertionResponseResponseFixtures from './__fixtures__/assertion.response.response.fixtures.json'; + +import { UnauthorizedException } from '@nestjs/common'; +import { + PublicKeyCredentialRequestOptions, + LiquidAssertionCredentialJSON, + AssertionCredentialJSON, +} from './assertion.dto.js'; +import configurationFixture from '../__fixtures__/configuration.fixture.json'; +import androidUserAgentFixtures from '../__fixtures__/user-agent.android.fixtures.json'; + +// AssertionCredentialJSON +const dummyAssertionCredentialJSON = { + id: '', + type: '', + rawId: 'mreh', + response: { + authenticatorData: '', + clientDataJSON: '', + signature: '', + }, +} as LiquidAssertionCredentialJSON; + +describe('AssertionController', () => { + let assertionController: AssertionController; + let authService: AuthService; + let userModel: Model; + + beforeEach(async () => { + userModel = mongoose.model('User', UserSchema); + + const moduleRef: TestingModule = await Test.createTestingModule({ + imports: [ + ConfigModule.forRoot({ + isGlobal: true, + load: [() => configurationFixture], + }), + ], + controllers: [AssertionController], + providers: [ + ConfigService, + { + provide: AuthService, + useValue: { ...mockAuthService }, + }, + AppService, + AssertionService, + { + provide: 'ACCOUNT_LINK_SERVICE', + useValue: { ...mockAccountLinkService }, + }, + { + provide: getModelToken(User.name), + useValue: userModel, + }, + ], + }).compile(); + + authService = moduleRef.get(AuthService); + assertionController = + moduleRef.get(AssertionController); + }); + + it('should be defined', () => { + expect(assertionController).toBeDefined(); + }); + + describe('POST /request/:credId', () => { + it('should create a valid assertion request', async () => { + await Promise.all( + assertionRequestBodyFixtures.map(async (fixture, i) => { + const setChallengeSpy = jest.fn(); + authService.search = jest + .fn() + .mockResolvedValue(assertionResponseResponseFixtures[i]); + const credId = assertionRequestParamFixtures[i]; + const body = fixture as PublicKeyCredentialRequestOptions; + const response = await assertionController.request( + { + set challenge(str: string) { + setChallengeSpy(str); + }, + }, + credId, + body, + ); + expect(response).toEqual({ + ...assertionRequestResponseFixtures[i], + challenge: response.challenge, + }); + expect(setChallengeSpy).toHaveBeenCalledWith(response.challenge); + }), + ); + }); + it('should fail if it cannot find the user', async () => { + await Promise.all( + assertionRequestBodyFixtures.map(async (fixture, i) => { + authService.search = jest.fn().mockResolvedValue(null); + const credId = assertionRequestParamFixtures[i]; + const body = fixture as PublicKeyCredentialRequestOptions; + expect(assertionController.request({}, credId, body)).rejects.toThrow( + UnauthorizedException, + ); + }), + ); + }); + }); + + describe('POST /response', () => { + it('should verify the assertion from the client', async () => { + await Promise.all( + assertionResponseBodyFixtures.map(async (fixture, i) => { + authService.search = jest + .fn() + .mockResolvedValue(assertionResponseResponseFixtures[i]); + + const session = { + challenge: assertionRequestResponseFixtures[i].challenge, + }; + const headers = { 'user-agent': androidUserAgentFixtures[0] }; + const body = fixture as unknown as AssertionCredentialJSON & { + clientExtensionResults: { liquid: { requestId: string } }; + }; + await expect( + assertionController.response(session, headers, body), + ).resolves.toBe(assertionResponseResponseFixtures[i]); + }), + ); + }); + it('should fail if the user is not found', async () => { + await Promise.all( + assertionResponseBodyFixtures.map(async (fixture, i) => { + authService.search = jest.fn().mockResolvedValue(null); + + const session = { + challenge: assertionRequestResponseFixtures[i].challenge, + }; + const headers = { 'user-agent': androidUserAgentFixtures[0] }; + const body = fixture as unknown as AssertionCredentialJSON & { + clientExtensionResults: { liquid: { requestId: string } }; + }; + await expect( + assertionController.response(session, headers, body), + ).rejects.toThrow(UnauthorizedException); + }), + ); + }); + it('should fail if the signature is invalid', async () => { + await Promise.all( + assertionResponseBodyFixtures.map(async (fixture, i) => { + authService.search = jest + .fn() + .mockResolvedValue(assertionResponseResponseFixtures[i]); + + const session = { + challenge: assertionRequestResponseFixtures[i].challenge, + }; + const headers = { 'user-agent': androidUserAgentFixtures[0] }; + const body = fixture as unknown as AssertionCredentialJSON & { + clientExtensionResults: { liquid: { requestId: string } }; + }; + body.response.signature = 'INVALIDSIGNATURE'; + await expect( + assertionController.response(session, headers, body), + ).rejects.toThrow(UnauthorizedException); + }), + ); + }); + it('should fail if the credential is not found', async () => { + await Promise.all( + assertionResponseBodyFixtures.map(async (fixture, i) => { + authService.search = jest.fn().mockResolvedValue({ + ...assertionResponseResponseFixtures[i], + credentials: [], + }); + + const session = { + challenge: assertionRequestResponseFixtures[i].challenge, + }; + const headers = { 'user-agent': androidUserAgentFixtures[0] }; + const body = fixture as unknown as AssertionCredentialJSON & { + clientExtensionResults: { liquid: { requestId: string } }; + }; + await expect( + assertionController.response(session, headers, body), + ).rejects.toThrow(UnauthorizedException); + }), + ); + }); + it('should fail if the challenge is not a string', async () => { + const session: Record = new Session(); + session.challenge = 0; + + const req = {} as any as Request; + const body = dummyAssertionCredentialJSON; + + await expect( + assertionController.response(session, req, body), + ).rejects.toThrow(UnauthorizedException); + }); + }); +}); diff --git a/services/liquid-auth-api-js/src/assertion/assertion.controller.ts b/services/liquid-auth-api-js/src/assertion/assertion.controller.ts index 584c81a..c4865b1 100644 --- a/services/liquid-auth-api-js/src/assertion/assertion.controller.ts +++ b/services/liquid-auth-api-js/src/assertion/assertion.controller.ts @@ -1,25 +1,52 @@ import { Body, Controller, - Get, + Headers, Inject, Logger, + Param, Post, - Req, - Res, Session, + UnauthorizedException, } from '@nestjs/common'; -import type { Request, Response } from 'express'; -import type { + +import { AssertionCredentialJSON, PublicKeyCredentialRequestOptions, -} from '@simplewebauthn/typescript-types'; - +} from './assertion.dto.js'; import { AuthService } from '../auth/auth.service.js'; import { AssertionService } from './assertion.service.js'; import { ClientProxy } from '@nestjs/microservices'; +import { readFileSync } from 'node:fs'; +import { join } from 'node:path'; +import { + ApiBody, + ApiForbiddenResponse, + ApiOperation, + ApiParam, + ApiTags, + ApiResponse, + ApiUnauthorizedResponse, +} from '@nestjs/swagger'; +import { User } from '../auth/auth.schema.js'; +// TODO: Make doc loader utility +const filePath = join(process.cwd(), './src/assertion'); +const requestDescription = readFileSync( + join(filePath, 'assertion.controller.post.request.md'), +).toString(); +const responseDescription = readFileSync( + join(filePath, 'assertion.controller.post.response.md'), +).toString(); + +/** + * Assertion Controller + * + * Handles assertion requests and responses from previously registered PublicKeyCredentials + * + */ @Controller('assertion') +@ApiTags('assertion') export class AssertionController { private readonly logger = new Logger(AssertionController.name); constructor( @@ -28,36 +55,6 @@ export class AssertionController { private authService: AuthService, ) {} - /** - * Hard Coded Request Assertion Options for demo - */ - @Get('/request/:credId') - async assertionDemoRequest( - @Session() session: Record, - @Req() req: Request, - @Res() res: Response, - @Body() body?: PublicKeyCredentialRequestOptions, - ) { - this.logger.log( - `GET /request/${req.params.credId} for Session: ${session.id}`, - ); - const user = await this.authService.search({ - 'credentials.credId': req.params.credId, - }); - - if (!user) { - res.status(404).json({ reason: 'not_found', error: 'User not found.' }); - return; - } - - // Get options, save challenge and respond - const options = this.assertionService.request( - user, - req.params.credId, - body, - ); - res.json(options); - } /** * Request Assertion * @@ -68,38 +65,47 @@ export class AssertionController { * route. * * @param session - Express Session - * @param req - Express Request - * @param res - Express Response + * @param credId - Credential ID to Lookup * @param [body] - Standard Public Key Request Options */ @Post('/request/:credId') - async assertionRequest( + @ApiOperation({ + summary: 'Assertion Request', + description: requestDescription, + }) + @ApiParam({ name: 'credId', description: 'Credential ID', required: true }) + @ApiBody({ type: PublicKeyCredentialRequestOptions }) + @ApiResponse({ + status: 201, + description: 'Successfully created options', + type: PublicKeyCredentialRequestOptions, + }) + @ApiResponse({ status: 404, description: 'Not Found' }) + async request( @Session() session: Record, - @Req() req: Request, - @Res() res: Response, + @Param('credId') credId: string, @Body() body?: PublicKeyCredentialRequestOptions, ) { - this.logger.log( - `POST /request/${req.params.credId} for Session: ${session.id}`, - ); + this.logger.log(`POST /request/${credId} for Session: ${session.id}`); + this.logger.debug('Request Body', body); + const user = await this.authService.search({ - 'credentials.credId': req.params.credId, + 'credentials.credId': credId, }); - if (!user) { - res.status(404).json({ reason: 'not_found', error: 'User not found.' }); - return; + throw new UnauthorizedException({ + reason: 'not_found', + error: 'User not found.', + }); } // Get options, save challenge and respond - const options = this.assertionService.request( - user, - req.params.credId, - body, - ); + const options = this.assertionService.request(user, credId, body); session.challenge = options.challenge; - res.json(options); + + this.logger.debug('Assertion Options', options); + return options; } /** @@ -111,53 +117,81 @@ export class AssertionController { * must have a valid challenge in the session. * * @param session - Express Session - * @param req - Express Request - * @param res - Express Response + * @param headers - Request Headers * @param body - Assertion Credential JSON */ @Post('/response') - async assertionResponse( - @Session() session: Record, - @Req() req: Request, - @Res() res: Response, - @Body() body: AssertionCredentialJSON, + @ApiOperation({ + summary: 'Assertion Response', + description: responseDescription, + }) + @ApiBody({ type: AssertionCredentialJSON }) + @ApiResponse({ + status: 201, + description: 'Successfully attested public key', + type: User, + }) + @ApiUnauthorizedResponse({ description: 'Unauthorized' }) + @ApiForbiddenResponse({ description: 'Forbidden' }) + async response( + @Session() + session: Record, + @Headers() + headers: Record, + @Body() + body: AssertionCredentialJSON & { + clientExtensionResults: { liquid: { requestId: string } }; + }, ) { this.logger.log(`POST /response for Session: ${session.id}`); + this.logger.debug('Authenticator Response', body); const expectedChallenge = session.challenge; if (typeof expectedChallenge !== 'string') { - res - .status(401) - .json({ reason: 'unauthorized', error: 'Challenge not found.' }); - return; + throw new UnauthorizedException({ + reason: 'unauthorized', + error: 'Challenge not found.', + }); } const savedUser = await this.authService.search({ 'credentials.credId': body.id, }); if (!savedUser) { - res - .status(403) - .json({ reason: 'not_found', error: 'Credential not found.' }); - return; + throw new UnauthorizedException({ + reason: 'not_found', + error: 'Credential not found.', + }); + } + let user: User; + try { + user = this.assertionService.response( + savedUser, + body, + expectedChallenge, + headers['user-agent'], + ); + } catch (e) { + this.logger.error(e); + throw new UnauthorizedException({ + reason: 'unauthorized', + error: 'User verification failed.', + }); } - - const user = this.assertionService.response( - savedUser, - body, - expectedChallenge, - req.get('User-Agent'), - ); await this.authService.update(user); - const credential = await this.authService.findCredential(body.id); - console.log(credential); + delete session.challenge; session.wallet = user.wallet; - - this.client.emit('auth-interaction', { - wallet: user.wallet, - credential, - }); - - res.json(user); + // Emit the signin event for the given request id + if ( + typeof body?.clientExtensionResults?.liquid?.requestId !== 'undefined' + ) { + this.client.emit('auth', { + requestId: body.clientExtensionResults.liquid.requestId, + wallet: user.wallet, + credId: body.id, + }); + } + this.logger.debug('User', user); + return user; } } diff --git a/services/liquid-auth-api-js/src/assertion/assertion.dto.spec.ts b/services/liquid-auth-api-js/src/assertion/assertion.dto.spec.ts new file mode 100644 index 0000000..d4f9a31 --- /dev/null +++ b/services/liquid-auth-api-js/src/assertion/assertion.dto.spec.ts @@ -0,0 +1,11 @@ +import { PublicKeyCredentialRequestOptionsJSON } from './assertion.dto.js'; + +describe('AssertionDto', () => { + it('should be defined', () => { + const dto = new PublicKeyCredentialRequestOptionsJSON({ + challenge: 'hello world', + }); + expect(dto).toBeDefined(); + expect(dto.challenge).toEqual('hello world'); + }); +}); diff --git a/services/liquid-auth-api-js/src/assertion/assertion.dto.ts b/services/liquid-auth-api-js/src/assertion/assertion.dto.ts new file mode 100644 index 0000000..cfea766 --- /dev/null +++ b/services/liquid-auth-api-js/src/assertion/assertion.dto.ts @@ -0,0 +1,101 @@ +import { + PublicKeyCredentialRequestOptionsJSON as PublicKeyCredentialRequestOptionsJSONType, + PublicKeyCredentialDescriptorJSON as PublicKeyCredentialDescriptorJSONType, + AssertionCredentialJSON as AssertionCredentialJSONType, + AuthenticatorAssertionResponseJSON as AuthenticatorAssertionResponseJSONType, + PublicKeyCredentialRequestOptions as PublicKeyCredentialRequestOptionsType, +} from '@simplewebauthn/typescript-types'; +import { ApiProperty } from '@nestjs/swagger'; + +type AuthenticatorTransport = 'usb' | 'nfc' | 'ble' | 'internal'; +// Native Types +export class PublicKeyCredentialDescriptor { + @ApiProperty() + id: BufferSource; + @ApiProperty() + transports: AuthenticatorTransport[]; + @ApiProperty() + type: PublicKeyCredentialType; +} +export class AuthenticationExtensionsClientInputs { + @ApiProperty() + appid?: string; + @ApiProperty() + appidExclude?: string; + @ApiProperty() + uvm?: boolean; + @ApiProperty() + credProps?: boolean; + @ApiProperty() + hmacCreateSecret?: boolean; + @ApiProperty() + liquid?: boolean; +} + +// Wrapped Implementations +export class PublicKeyCredentialRequestOptions + implements PublicKeyCredentialRequestOptionsType +{ + @ApiProperty() + allowCredentials: PublicKeyCredentialDescriptor[]; + @ApiProperty() + challenge: BufferSource; + @ApiProperty() + extensions: AuthenticationExtensionsClientInputs; + @ApiProperty() + rpId: string; + @ApiProperty() + timeout: number; + @ApiProperty() + userVerification: UserVerificationRequirement; +} + +export class AuthenticatorAssertionResponseJSON + implements AuthenticatorAssertionResponseJSONType +{ + @ApiProperty() + authenticatorData: string; + @ApiProperty() + clientDataJSON: string; + @ApiProperty() + signature: string; + @ApiProperty() + userHandle: string; +} + +export class AssertionCredentialJSON implements AssertionCredentialJSONType { + @ApiProperty() + readonly id: string; + @ApiProperty() + rawId: string; + @ApiProperty({ type: AuthenticatorAssertionResponseJSON }) + response: AuthenticatorAssertionResponseJSON; + @ApiProperty() + readonly type: string; +} +export type LiquidAssertionCredentialJSON = AssertionCredentialJSON & { + clientExtensionResults: { liquid: { requestId: string } }; +}; + +/** + * JSON representation of PublicKeyCredentialRequestOptions + */ +export class PublicKeyCredentialRequestOptionsJSON + implements PublicKeyCredentialRequestOptionsJSONType +{ + @ApiProperty() + challenge: string; + @ApiProperty() + allowCredentials: PublicKeyCredentialDescriptorJSONType[]; + @ApiProperty() + userVerification: UserVerificationRequirement; + @ApiProperty() + timeout: number; + @ApiProperty() + rpId: string; + @ApiProperty() + extensions: AuthenticationExtensionsClientInputs; + constructor(partial: Partial) { + Object.assign(this, partial); + } +} diff --git a/services/liquid-auth-api-js/src/assertion/assertion.service.ts b/services/liquid-auth-api-js/src/assertion/assertion.service.ts index 9ff0930..51e720b 100644 --- a/services/liquid-auth-api-js/src/assertion/assertion.service.ts +++ b/services/liquid-auth-api-js/src/assertion/assertion.service.ts @@ -1,5 +1,5 @@ import { Injectable } from '@nestjs/common'; -import fido2 from '@simplewebauthn/server'; +import * as fido2 from '@simplewebauthn/server'; import { User } from '../auth/auth.schema.js'; import { AssertionCredentialJSON, diff --git a/services/liquid-auth-api-js/src/attestation/__fixtures__/attestation.request.body.fixtures.json b/services/liquid-auth-api-js/src/attestation/__fixtures__/attestation.request.body.fixtures.json new file mode 100644 index 0000000..ed8897c --- /dev/null +++ b/services/liquid-auth-api-js/src/attestation/__fixtures__/attestation.request.body.fixtures.json @@ -0,0 +1,62 @@ +[ + { + "username": "2SPDE6XLJNXFTOO7OIGNRNKSEDOHJWVD3HBSEAPHONZQ4IQEYOGYTP6LXA", + "displayName": "Liquid Auth User", + "authenticatorSelection": { + "userVerification": "required" + }, + "extensions": { + "liquid": true + } + }, + { + "username": "KH4XYQ4ZYKARWZAYVIVAY6WPWXNU3FWU2QC6HF2666KKM6CH4APTUIOQHU", + "displayName": "Liquid Auth User", + "authenticatorSelection": { + "userVerification": "required" + }, + "extensions": { + "liquid": true + } + }, + { + "username": "6P3TIK6KEPUNVHM77UXVG7ZIZRCCJX6IKZ5FA3WMXKRBHIXW4SAQ3OSEY4", + "displayName": "Liquid Auth User", + "authenticatorSelection": { + "userVerification": "required" + }, + "extensions": { + "liquid": true + } + }, + { + "username": "2W5VGV43VOKJTVFZXCEZ6L647XCQEXCDNZGDVFROWAR4FZJJCOWHVXLFOE", + "displayName": "Liquid Auth User", + "authenticatorSelection": { + "userVerification": "required" + }, + "extensions": { + "liquid": true + } + }, + { + "username": "L72CSGO2C7K6QJZHVC2AYCLZ5GY3IMN7GJVKVNXU5WDDKLENPKSBZ7GE7U", + "displayName": "Liquid Auth User", + "authenticatorSelection": { + "userVerification": "required" + }, + "extensions": { + "liquid": true + } + }, + { + "username": "OXOACNIWZ7VDJXJXJHQ53BMNFQTSPPW524RU5JVAFLHSSGGQZCTII65ZII", + "displayName": "Liquid Auth User", + "authenticatorSelection": { + "userVerification": "required" + }, + "extensions": { + "liquid": true + } + } +] \ No newline at end of file diff --git a/services/liquid-auth-api-js/src/attestation/__fixtures__/attestation.request.response.fixtures.json b/services/liquid-auth-api-js/src/attestation/__fixtures__/attestation.request.response.fixtures.json new file mode 100644 index 0000000..0d16ea2 --- /dev/null +++ b/services/liquid-auth-api-js/src/attestation/__fixtures__/attestation.request.response.fixtures.json @@ -0,0 +1,188 @@ +[ + { + "challenge": "35JYpoXGnM4s8IICakWSLllcXy3Z_lc3AaLSl872qXM", + "rp": { + "name": "Algorand Foundation FIDO2 Server", + "id": "catfish-pro-wolf.ngrok-free.app" + }, + "user": { + "id": "2SPDE6XLJNXFTOO7OIGNRNKSEDOHJWVD3HBSEAPHONZQ4IQEYOGYTP6LXA", + "name": "2SPDE6XLJNXFTOO7OIGNRNKSEDOHJWVD3HBSEAPHONZQ4IQEYOGYTP6LXA", + "displayName": "2SPDE6XLJNXFTOO7OIGNRNKSEDOHJWVD3HBSEAPHONZQ4IQEYOGYTP6LXA" + }, + "pubKeyCredParams": [ + { + "type": "public-key", + "alg": -7 + }, + { + "type": "public-key", + "alg": -257 + } + ], + "timeout": 1800000, + "attestation": "none", + "excludeCredentials": [], + "authenticatorSelection": { + "userVerification": "required" + }, + "extensions": { + "liquid": true + } + }, + { + "challenge": "WcYzyZl1bthPcyhHiY1eFJhs4qkgzbT2yiRBuX7puqc", + "rp": { + "name": "Algorand Foundation FIDO2 Server", + "id": "catfish-pro-wolf.ngrok-free.app" + }, + "user": { + "id": "KH4XYQ4ZYKARWZAYVIVAY6WPWXNU3FWU2QC6HF2666KKM6CH4APTUIOQHU", + "name": "KH4XYQ4ZYKARWZAYVIVAY6WPWXNU3FWU2QC6HF2666KKM6CH4APTUIOQHU", + "displayName": "KH4XYQ4ZYKARWZAYVIVAY6WPWXNU3FWU2QC6HF2666KKM6CH4APTUIOQHU" + }, + "pubKeyCredParams": [ + { + "type": "public-key", + "alg": -7 + }, + { + "type": "public-key", + "alg": -257 + } + ], + "timeout": 1800000, + "attestation": "none", + "excludeCredentials": [], + "authenticatorSelection": { + "userVerification": "required" + }, + "extensions": { + "liquid": true + } + }, + { + "challenge": "GZB_ZBgz_J5svZSrnyfYOYihBeImMRh8CjoV7e-Hij4", + "rp": { + "name": "Algorand Foundation FIDO2 Server", + "id": "catfish-pro-wolf.ngrok-free.app" + }, + "user": { + "id": "6P3TIK6KEPUNVHM77UXVG7ZIZRCCJX6IKZ5FA3WMXKRBHIXW4SAQ3OSEY4", + "name": "6P3TIK6KEPUNVHM77UXVG7ZIZRCCJX6IKZ5FA3WMXKRBHIXW4SAQ3OSEY4", + "displayName": "6P3TIK6KEPUNVHM77UXVG7ZIZRCCJX6IKZ5FA3WMXKRBHIXW4SAQ3OSEY4" + }, + "pubKeyCredParams": [ + { + "type": "public-key", + "alg": -7 + }, + { + "type": "public-key", + "alg": -257 + } + ], + "timeout": 1800000, + "attestation": "none", + "excludeCredentials": [], + "authenticatorSelection": { + "userVerification": "required" + }, + "extensions": { + "liquid": true + } + }, + { + "challenge": "bBvYbdv3MMiBV8085yKqOX1IVFybTjsBrpaYvpTzaBs", + "rp": { + "name": "Algorand Foundation FIDO2 Server", + "id": "catfish-pro-wolf.ngrok-free.app" + }, + "user": { + "id": "2W5VGV43VOKJTVFZXCEZ6L647XCQEXCDNZGDVFROWAR4FZJJCOWHVXLFOE", + "name": "2W5VGV43VOKJTVFZXCEZ6L647XCQEXCDNZGDVFROWAR4FZJJCOWHVXLFOE", + "displayName": "2W5VGV43VOKJTVFZXCEZ6L647XCQEXCDNZGDVFROWAR4FZJJCOWHVXLFOE" + }, + "pubKeyCredParams": [ + { + "type": "public-key", + "alg": -7 + }, + { + "type": "public-key", + "alg": -257 + } + ], + "timeout": 1800000, + "attestation": "none", + "excludeCredentials": [], + "authenticatorSelection": { + "userVerification": "required" + }, + "extensions": { + "liquid": true + } + }, + { + "challenge": "O6CNBPTewHc4ZztGZy5DBkkFP39Ub61uGUHuzL0ZeAw", + "rp": { + "name": "Algorand Foundation FIDO2 Server", + "id": "catfish-pro-wolf.ngrok-free.app" + }, + "user": { + "id": "L72CSGO2C7K6QJZHVC2AYCLZ5GY3IMN7GJVKVNXU5WDDKLENPKSBZ7GE7U", + "name": "L72CSGO2C7K6QJZHVC2AYCLZ5GY3IMN7GJVKVNXU5WDDKLENPKSBZ7GE7U", + "displayName": "L72CSGO2C7K6QJZHVC2AYCLZ5GY3IMN7GJVKVNXU5WDDKLENPKSBZ7GE7U" + }, + "pubKeyCredParams": [ + { + "type": "public-key", + "alg": -7 + }, + { + "type": "public-key", + "alg": -257 + } + ], + "timeout": 1800000, + "attestation": "none", + "excludeCredentials": [], + "authenticatorSelection": { + "userVerification": "required" + }, + "extensions": { + "liquid": true + } + }, + { + "challenge": "aTPfrbLZkQfBEncQ1u0qm-lTHy0N4JX9uZWEDyYk7cg", + "rp": { + "name": "Algorand Foundation FIDO2 Server", + "id": "catfish-pro-wolf.ngrok-free.app" + }, + "user": { + "id": "OXOACNIWZ7VDJXJXJHQ53BMNFQTSPPW524RU5JVAFLHSSGGQZCTII65ZII", + "name": "OXOACNIWZ7VDJXJXJHQ53BMNFQTSPPW524RU5JVAFLHSSGGQZCTII65ZII", + "displayName": "OXOACNIWZ7VDJXJXJHQ53BMNFQTSPPW524RU5JVAFLHSSGGQZCTII65ZII" + }, + "pubKeyCredParams": [ + { + "type": "public-key", + "alg": -7 + }, + { + "type": "public-key", + "alg": -257 + } + ], + "timeout": 1800000, + "attestation": "none", + "excludeCredentials": [], + "authenticatorSelection": { + "userVerification": "required" + }, + "extensions": { + "liquid": true + } + } +] \ No newline at end of file diff --git a/services/liquid-auth-api-js/src/attestation/__fixtures__/attestation.response.body.fixtures.json b/services/liquid-auth-api-js/src/attestation/__fixtures__/attestation.response.body.fixtures.json new file mode 100644 index 0000000..0ab04ef --- /dev/null +++ b/services/liquid-auth-api-js/src/attestation/__fixtures__/attestation.response.body.fixtures.json @@ -0,0 +1,116 @@ +[ + { + "id": "AYMPi2Rbhcnu2gSHOO1TNvzDJ38iU00rrlCqyH874XCIEoIotRc7eVRFpx0TvsQurg7BAnXy5KnWdKC8LeWs0k0", + "type": "public-key", + "rawId": "AYMPi2Rbhcnu2gSHOO1TNvzDJ38iU00rrlCqyH874XCIEoIotRc7eVRFpx0TvsQurg7BAnXy5KnWdKC8LeWs0k0", + "clientExtensionResults": { + "liquid": { + "type": "algorand", + "requestId": 0.6050027432326752, + "address": "2SPDE6XLJNXFTOO7OIGNRNKSEDOHJWVD3HBSEAPHONZQ4IQEYOGYTP6LXA", + "signature": "QY31mdH8AwpJ9p4pCXBO2iA5WdU-BjG52xEtJNuSJNHJIaJ10uzqk3FdR0fvYVfb_rzXTuWn4k1PFFeg-vpEDw", + "device": "Pixel 8 Pro" + } + }, + "response": { + "clientDataJSON": "eyJ0eXBlIjoid2ViYXV0aG4uY3JlYXRlIiwiY2hhbGxlbmdlIjoiMzVKWXBvWEduTTRzOElJQ2FrV1NMbGxjWHkzWl9sYzNBYUxTbDg3MnFYTSIsIm9yaWdpbiI6ImFuZHJvaWQ6YXBrLWtleS1oYXNoOlI4eE83cmxRV2FXTDRCbEZ5Z3B0V1JiNXFjS1dkZmp6WklhU1JpdDlYVnciLCJhbmRyb2lkUGFja2FnZU5hbWUiOiJmb3VuZGF0aW9uLmFsZ29yYW5kLmRlbW8ifQ", + "attestationObject": "o2NmbXRkbm9uZWdhdHRTdG10oGhhdXRoRGF0YVjFlpPmT7RcYTDeFJdKhDtiKwzb05n-ojlcqqYw5SomXZBFAAAAAAAAAAAAAAAAAAAAAAAAAAAAQQGDD4tkW4XJ7toEhzjtUzb8wyd_IlNNK65Qqsh_O-FwiBKCKLUXO3lURacdE77ELq4OwQJ18uSp1nSgvC3lrNJNpQECAyYgASFYIB2dcp3wanhReRhgRIpJCUfRSwkCvyE9OdvEL_NlncSJIlggkSIz7h7O5nrAXGJrkCOmeolChSc09eHzniCFLFxaKH0" + }, + "device": "Pixel 8 Pro" + }, + { + "id": "ASk2I69zskHtkQLgnI_zHCAS9n7AwYoGSN8TEfE2D2IrVjETxVJADCdlYAu5lqhigqWvjGq8M0cfHcludnSD-3I", + "type": "public-key", + "rawId": "ASk2I69zskHtkQLgnI_zHCAS9n7AwYoGSN8TEfE2D2IrVjETxVJADCdlYAu5lqhigqWvjGq8M0cfHcludnSD-3I", + "clientExtensionResults": { + "liquid": { + "type": "algorand", + "requestId": 0.1824949283001871, + "address": "KH4XYQ4ZYKARWZAYVIVAY6WPWXNU3FWU2QC6HF2666KKM6CH4APTUIOQHU", + "signature": "f0KUNI-Q5H54aSurcxCYwhCuQP8UtuHn2Ne5RhxeXfribsH1plCgbNVI4gwn183WxW8aSA-2JhxqLSe2J7ApCA", + "device": "Pixel 8 Pro" + } + }, + "response": { + "clientDataJSON": "eyJ0eXBlIjoid2ViYXV0aG4uY3JlYXRlIiwiY2hhbGxlbmdlIjoiV2NZenlabDFidGhQY3loSGlZMWVGSmhzNHFrZ3piVDJ5aVJCdVg3cHVxYyIsIm9yaWdpbiI6ImFuZHJvaWQ6YXBrLWtleS1oYXNoOlI4eE83cmxRV2FXTDRCbEZ5Z3B0V1JiNXFjS1dkZmp6WklhU1JpdDlYVnciLCJhbmRyb2lkUGFja2FnZU5hbWUiOiJmb3VuZGF0aW9uLmFsZ29yYW5kLmRlbW8ifQ", + "attestationObject": "o2NmbXRkbm9uZWdhdHRTdG10oGhhdXRoRGF0YVjFlpPmT7RcYTDeFJdKhDtiKwzb05n-ojlcqqYw5SomXZBFAAAAAAAAAAAAAAAAAAAAAAAAAAAAQQEpNiOvc7JB7ZEC4JyP8xwgEvZ-wMGKBkjfExHxNg9iK1YxE8VSQAwnZWALuZaoYoKlr4xqvDNHHx3JbnZ0g_typQECAyYgASFYIIYtbWsD526npX6pWVda473yek0mi8uLWbpQPAv5pJQTIlgg1j0emgrGTJoujIqn27cBBatDEegpRsKwDvzYw7GTuMM" + }, + "device": "Pixel 8 Pro" + }, + { + "id": "AbqTh-5GQBr6NoOMkL_bTOpCDOVBF7_yHvi084BjrlLy8LYLoCJ3Uknichga4FDPY9vq6r3tdGPWS8a9s_Kkpco", + "type": "public-key", + "rawId": "AbqTh-5GQBr6NoOMkL_bTOpCDOVBF7_yHvi084BjrlLy8LYLoCJ3Uknichga4FDPY9vq6r3tdGPWS8a9s_Kkpco", + "clientExtensionResults": { + "liquid": { + "type": "algorand", + "requestId": 0.1294004256903012, + "address": "6P3TIK6KEPUNVHM77UXVG7ZIZRCCJX6IKZ5FA3WMXKRBHIXW4SAQ3OSEY4", + "signature": "t6LqTuixeQ7WG1M-XxhSJvKBydY5YBEXCZi2BU_W9zJf2qWBGIbVlnMSfQnfc0ApYjsOO-bKnnoJtJdbh0lACQ", + "device": "Pixel 8 Pro" + } + }, + "response": { + "clientDataJSON": "eyJ0eXBlIjoid2ViYXV0aG4uY3JlYXRlIiwiY2hhbGxlbmdlIjoiR1pCX1pCZ3pfSjVzdlpTcm55ZllPWWloQmVJbU1SaDhDam9WN2UtSGlqNCIsIm9yaWdpbiI6ImFuZHJvaWQ6YXBrLWtleS1oYXNoOlI4eE83cmxRV2FXTDRCbEZ5Z3B0V1JiNXFjS1dkZmp6WklhU1JpdDlYVnciLCJhbmRyb2lkUGFja2FnZU5hbWUiOiJmb3VuZGF0aW9uLmFsZ29yYW5kLmRlbW8ifQ", + "attestationObject": "o2NmbXRkbm9uZWdhdHRTdG10oGhhdXRoRGF0YVjFlpPmT7RcYTDeFJdKhDtiKwzb05n-ojlcqqYw5SomXZBFAAAAAAAAAAAAAAAAAAAAAAAAAAAAQQG6k4fuRkAa-jaDjJC_20zqQgzlQRe_8h74tPOAY65S8vC2C6Aid1JJ4nIYGuBQz2Pb6uq97XRj1kvGvbPypKXKpQECAyYgASFYIMJO5NYWM6zT5iCx-dSK8xqXkDiebkZtHpjX7FKwZ_L9IlggM02BH4IpsxBww-avE70ZYHbtFv6wCFbTOFGVJ8jmBYA" + }, + "device": "Pixel 8 Pro" + }, + { + "id": "Af6bB9Z_zx0PmRlncq9IbzRzTuxPS-yvEwOrtojHy7eOOVnhGxxHICrKQfoiXv8sINQjs_3AX9TEejK7VOvav-c", + "type": "public-key", + "rawId": "Af6bB9Z_zx0PmRlncq9IbzRzTuxPS-yvEwOrtojHy7eOOVnhGxxHICrKQfoiXv8sINQjs_3AX9TEejK7VOvav-c", + "clientExtensionResults": { + "liquid": { + "type": "algorand", + "requestId": 0.5687522830110388, + "address": "2W5VGV43VOKJTVFZXCEZ6L647XCQEXCDNZGDVFROWAR4FZJJCOWHVXLFOE", + "signature": "QL0e1z24j1K5ZErHtwhpJPBBb7z-tdSb8IOuAuGVzL8KvxMQdAQihWM3-us-Vl3DkQD1GuXMlwB8BpZijvLyDw", + "device": "Pixel 8 Pro" + } + }, + "response": { + "clientDataJSON": "eyJ0eXBlIjoid2ViYXV0aG4uY3JlYXRlIiwiY2hhbGxlbmdlIjoiYkJ2WWJkdjNNTWlCVjgwODV5S3FPWDFJVkZ5YlRqc0JycGFZdnBUemFCcyIsIm9yaWdpbiI6ImFuZHJvaWQ6YXBrLWtleS1oYXNoOlI4eE83cmxRV2FXTDRCbEZ5Z3B0V1JiNXFjS1dkZmp6WklhU1JpdDlYVnciLCJhbmRyb2lkUGFja2FnZU5hbWUiOiJmb3VuZGF0aW9uLmFsZ29yYW5kLmRlbW8ifQ", + "attestationObject": "o2NmbXRkbm9uZWdhdHRTdG10oGhhdXRoRGF0YVjFlpPmT7RcYTDeFJdKhDtiKwzb05n-ojlcqqYw5SomXZBFAAAAAAAAAAAAAAAAAAAAAAAAAAAAQQH-mwfWf88dD5kZZ3KvSG80c07sT0vsrxMDq7aIx8u3jjlZ4RscRyAqykH6Il7_LCDUI7P9wF_UxHoyu1Tr2r_npQECAyYgASFYIL8k0vHupVfbe8EQSsRFkGHfjKf_6ZWv63QsqHrxWCWgIlggfy32BhGoicWESUFJ6XhlZUZckPKuGkBacEnLP5pDOPY" + }, + "device": "Pixel 8 Pro" + }, + { + "id": "AVl7TsljN83pJD7_FfyXNoGubqbs37t41TGV9Y7V4jtgb30BnpqqlUwsQiB-a2h5ovTpkoJg5ChnQEmMlC6L0Sw", + "type": "public-key", + "rawId": "AVl7TsljN83pJD7_FfyXNoGubqbs37t41TGV9Y7V4jtgb30BnpqqlUwsQiB-a2h5ovTpkoJg5ChnQEmMlC6L0Sw", + "clientExtensionResults": { + "liquid": { + "type": "algorand", + "requestId": 0.7699192258303749, + "address": "L72CSGO2C7K6QJZHVC2AYCLZ5GY3IMN7GJVKVNXU5WDDKLENPKSBZ7GE7U", + "signature": "RX-r27Alz0i4IF9wRaEy2kp6na29mTTOYSYzHwBWfwv5wNHkPwvIT2spDFdsvaxlt_M16OKo0PVqOUOAuhhGAQ", + "device": "Pixel 8 Pro" + } + }, + "response": { + "clientDataJSON": "eyJ0eXBlIjoid2ViYXV0aG4uY3JlYXRlIiwiY2hhbGxlbmdlIjoiTzZDTkJQVGV3SGM0Wnp0R1p5NURCa2tGUDM5VWI2MXVHVUh1ekwwWmVBdyIsIm9yaWdpbiI6ImFuZHJvaWQ6YXBrLWtleS1oYXNoOlI4eE83cmxRV2FXTDRCbEZ5Z3B0V1JiNXFjS1dkZmp6WklhU1JpdDlYVnciLCJhbmRyb2lkUGFja2FnZU5hbWUiOiJmb3VuZGF0aW9uLmFsZ29yYW5kLmRlbW8ifQ", + "attestationObject": "o2NmbXRkbm9uZWdhdHRTdG10oGhhdXRoRGF0YVjFlpPmT7RcYTDeFJdKhDtiKwzb05n-ojlcqqYw5SomXZBFAAAAAAAAAAAAAAAAAAAAAAAAAAAAQQFZe07JYzfN6SQ-_xX8lzaBrm6m7N-7eNUxlfWO1eI7YG99AZ6aqpVMLEIgfmtoeaL06ZKCYOQoZ0BJjJQui9EspQECAyYgASFYIJ2cwWQ49K-Sr7ldYkfUCI8hl42qvcFrfDxyquE-7mOiIlggDOxVoZzESas5nboQLMrsL4mHnbdA1zRmnTvqm7qb1s8" + }, + "device": "Pixel 8 Pro" + }, + { + "id": "AYvDA1VZ-qkvCPmf7Re7_GVDY4AwzmUFbI1Njsl3kDcI9BFKTqTd0YUC47IK-peJbf3weNCUdqmB2_QDEPy7iR4", + "type": "public-key", + "rawId": "AYvDA1VZ-qkvCPmf7Re7_GVDY4AwzmUFbI1Njsl3kDcI9BFKTqTd0YUC47IK-peJbf3weNCUdqmB2_QDEPy7iR4", + "clientExtensionResults": { + "liquid": { + "type": "algorand", + "requestId": 0.07304218671956053, + "address": "OXOACNIWZ7VDJXJXJHQ53BMNFQTSPPW524RU5JVAFLHSSGGQZCTII65ZII", + "signature": "Fy7gb4f5PSrLOPRRFtQwB-f6kDuapV_T_MDtDY6TwT2ha9D1Km01KBmdFCgHN5VF9G__ae4bTRzC2VtOx37YAQ", + "device": "Pixel 8 Pro" + } + }, + "response": { + "clientDataJSON": "eyJ0eXBlIjoid2ViYXV0aG4uY3JlYXRlIiwiY2hhbGxlbmdlIjoiYVRQZnJiTFprUWZCRW5jUTF1MHFtLWxUSHkwTjRKWDl1WldFRHlZazdjZyIsIm9yaWdpbiI6ImFuZHJvaWQ6YXBrLWtleS1oYXNoOlI4eE83cmxRV2FXTDRCbEZ5Z3B0V1JiNXFjS1dkZmp6WklhU1JpdDlYVnciLCJhbmRyb2lkUGFja2FnZU5hbWUiOiJmb3VuZGF0aW9uLmFsZ29yYW5kLmRlbW8ifQ", + "attestationObject": "o2NmbXRkbm9uZWdhdHRTdG10oGhhdXRoRGF0YVjFlpPmT7RcYTDeFJdKhDtiKwzb05n-ojlcqqYw5SomXZBFAAAAAAAAAAAAAAAAAAAAAAAAAAAAQQGLwwNVWfqpLwj5n-0Xu_xlQ2OAMM5lBWyNTY7Jd5A3CPQRSk6k3dGFAuOyCvqXiW398HjQlHapgdv0AxD8u4kepQECAyYgASFYIF5hkHAZkg76PAXB5DGb0IcJJXlxYqT6HSIequIL6DYyIlggaRfQcwy7w-hx-AcLgEZ57oq1n3nCcL8QodheQcLcbto" + }, + "device": "Pixel 8 Pro" + } +] \ No newline at end of file diff --git a/services/liquid-auth-api-js/src/attestation/__fixtures__/attestation.response.response.fixtures.json b/services/liquid-auth-api-js/src/attestation/__fixtures__/attestation.response.response.fixtures.json new file mode 100644 index 0000000..b108224 --- /dev/null +++ b/services/liquid-auth-api-js/src/attestation/__fixtures__/attestation.response.response.fixtures.json @@ -0,0 +1,86 @@ +[ + { + "_id": "662c2ca47c56f26fbd619624", + "id": "M6RT4iT5FkNDM2i57MXzBhLDt9zl2CrLt2p4Ar03t2Q", + "wallet": "2SPDE6XLJNXFTOO7OIGNRNKSEDOHJWVD3HBSEAPHONZQ4IQEYOGYTP6LXA", + "credentials": [ + { + "device": "Pixel 8 Pro", + "publicKey": "pQECAyYgASFYIB2dcp3wanhReRhgRIpJCUfRSwkCvyE9OdvEL_NlncSJIlggkSIz7h7O5nrAXGJrkCOmeolChSc09eHzniCFLFxaKH0", + "credId": "AYMPi2Rbhcnu2gSHOO1TNvzDJ38iU00rrlCqyH874XCIEoIotRc7eVRFpx0TvsQurg7BAnXy5KnWdKC8LeWs0k0", + "prevCounter": 0 + } + ], + "__v": 0 + }, + { + "_id": "662c2cbe7c56f26fbd619639", + "id": "w0Me3F2XfcK_wVdMejk6Xl98gHmOtqxcN-WKjLydDA0", + "wallet": "KH4XYQ4ZYKARWZAYVIVAY6WPWXNU3FWU2QC6HF2666KKM6CH4APTUIOQHU", + "credentials": [ + { + "device": "Pixel 8 Pro", + "publicKey": "pQECAyYgASFYIIYtbWsD526npX6pWVda473yek0mi8uLWbpQPAv5pJQTIlgg1j0emgrGTJoujIqn27cBBatDEegpRsKwDvzYw7GTuMM", + "credId": "ASk2I69zskHtkQLgnI_zHCAS9n7AwYoGSN8TEfE2D2IrVjETxVJADCdlYAu5lqhigqWvjGq8M0cfHcludnSD-3I", + "prevCounter": 0 + } + ], + "__v": 0 + }, + { + "_id": "662c2cdc7c56f26fbd61964f", + "id": "mvpgdpIfho5IPdU3QquBDDmnnuUD6DittFevmJCMZmA", + "wallet": "6P3TIK6KEPUNVHM77UXVG7ZIZRCCJX6IKZ5FA3WMXKRBHIXW4SAQ3OSEY4", + "credentials": [ + { + "device": "Pixel 8 Pro", + "publicKey": "pQECAyYgASFYIMJO5NYWM6zT5iCx-dSK8xqXkDiebkZtHpjX7FKwZ_L9IlggM02BH4IpsxBww-avE70ZYHbtFv6wCFbTOFGVJ8jmBYA", + "credId": "AbqTh-5GQBr6NoOMkL_bTOpCDOVBF7_yHvi084BjrlLy8LYLoCJ3Uknichga4FDPY9vq6r3tdGPWS8a9s_Kkpco", + "prevCounter": 0 + } + ], + "__v": 0 + }, + { + "_id": "662c2cf77c56f26fbd619664", + "id": "iIet1pMIMOIPmfws0m2aTenDOI1xhux775w09SlNhXM", + "wallet": "2W5VGV43VOKJTVFZXCEZ6L647XCQEXCDNZGDVFROWAR4FZJJCOWHVXLFOE", + "credentials": [ + { + "device": "Pixel 8 Pro", + "publicKey": "pQECAyYgASFYIL8k0vHupVfbe8EQSsRFkGHfjKf_6ZWv63QsqHrxWCWgIlggfy32BhGoicWESUFJ6XhlZUZckPKuGkBacEnLP5pDOPY", + "credId": "Af6bB9Z_zx0PmRlncq9IbzRzTuxPS-yvEwOrtojHy7eOOVnhGxxHICrKQfoiXv8sINQjs_3AX9TEejK7VOvav-c", + "prevCounter": 0 + } + ], + "__v": 0 + }, + { + "_id": "662c2d127c56f26fbd61967a", + "id": "0Xb1BYjal05QzGSe2kUN5BRoBPjR4seyssK1GJKgxhE", + "wallet": "L72CSGO2C7K6QJZHVC2AYCLZ5GY3IMN7GJVKVNXU5WDDKLENPKSBZ7GE7U", + "credentials": [ + { + "device": "Pixel 8 Pro", + "publicKey": "pQECAyYgASFYIJ2cwWQ49K-Sr7ldYkfUCI8hl42qvcFrfDxyquE-7mOiIlggDOxVoZzESas5nboQLMrsL4mHnbdA1zRmnTvqm7qb1s8", + "credId": "AVl7TsljN83pJD7_FfyXNoGubqbs37t41TGV9Y7V4jtgb30BnpqqlUwsQiB-a2h5ovTpkoJg5ChnQEmMlC6L0Sw", + "prevCounter": 0 + } + ], + "__v": 0 + }, + { + "_id": "662c2d2c7c56f26fbd61968f", + "id": "hoQk-DlJOXqyuV2IDKtBHEE2DYr7K2_DTgAyiFcgGpE", + "wallet": "OXOACNIWZ7VDJXJXJHQ53BMNFQTSPPW524RU5JVAFLHSSGGQZCTII65ZII", + "credentials": [ + { + "device": "Pixel 8 Pro", + "publicKey": "pQECAyYgASFYIF5hkHAZkg76PAXB5DGb0IcJJXlxYqT6HSIequIL6DYyIlggaRfQcwy7w-hx-AcLgEZ57oq1n3nCcL8QodheQcLcbto", + "credId": "AYvDA1VZ-qkvCPmf7Re7_GVDY4AwzmUFbI1Njsl3kDcI9BFKTqTd0YUC47IK-peJbf3weNCUdqmB2_QDEPy7iR4", + "prevCounter": 0 + } + ], + "__v": 0 + } +] \ No newline at end of file diff --git a/services/liquid-auth-api-js/src/attestation/attestation.controller.post.request.md b/services/liquid-auth-api-js/src/attestation/attestation.controller.post.request.md new file mode 100644 index 0000000..54ac958 --- /dev/null +++ b/services/liquid-auth-api-js/src/attestation/attestation.controller.post.request.md @@ -0,0 +1 @@ +# TITLE diff --git a/services/liquid-auth-api-js/src/attestation/attestation.controller.spec.ts b/services/liquid-auth-api-js/src/attestation/attestation.controller.spec.ts new file mode 100644 index 0000000..71894bd --- /dev/null +++ b/services/liquid-auth-api-js/src/attestation/attestation.controller.spec.ts @@ -0,0 +1,233 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { AuthService } from '../auth/auth.service.js'; +import { Session } from '../auth/session.schema.js'; +import mongoose, { Model } from 'mongoose'; +import { User, UserSchema } from '../auth/auth.schema.js'; +import { getModelToken } from '@nestjs/mongoose'; +import { AttestationController } from './attestation.controller.js'; +import { mockAuthService } from '../__mocks__/auth.service.mock.js'; +import { mockAccountLinkService } from '../__mocks__/account-link.service.mock.js'; +import { AppService } from '../app.service.js'; +import { ConfigModule, ConfigService } from '@nestjs/config'; +import { AttestationService } from './attestation.service.js'; +import { NotImplementedException, UnauthorizedException } from '@nestjs/common'; +import { + AttestationCredentialJSONDto, + AttestationSelectorDto, +} from './attestation.dto.js'; +import { AlgodService } from '../algod/algod.service.js'; +import configurationFixture from '../__fixtures__/configuration.fixture.json'; +import androidUserAgentFixtures from '../__fixtures__/user-agent.android.fixtures.json'; +import attestationRequestResponseFixtures from './__fixtures__/attestation.request.response.fixtures.json'; +import attestationRequestBodyFixtures from './__fixtures__/attestation.request.body.fixtures.json'; +import attestationResponseBodyFixtures from './__fixtures__/attestation.response.body.fixtures.json'; +import attestationResponseResponseFixtures from './__fixtures__/attestation.response.response.fixtures.json'; +describe('AttestationController', () => { + let attestationController: AttestationController; + let userModel: Model; + let authService: AuthService; + beforeEach(async () => { + userModel = mongoose.model('User', UserSchema); + + const moduleRef: TestingModule = await Test.createTestingModule({ + imports: [ + ConfigModule.forRoot({ + isGlobal: true, + load: [() => configurationFixture], + }), + ], + controllers: [AttestationController], + providers: [ + ConfigService, + AlgodService, + { + provide: AuthService, + useValue: { ...mockAuthService }, + }, + AppService, + AttestationService, + { + provide: 'ACCOUNT_LINK_SERVICE', + useValue: mockAccountLinkService, + }, + { + provide: getModelToken(User.name), + useValue: userModel, + }, + ], + }).compile(); + authService = moduleRef.get(AuthService); + attestationController = moduleRef.get( + AttestationController, + ); + }); + + it('should be defined', () => { + expect(attestationController).toBeDefined(); + }); + + describe('POST /request', () => { + it('should create PublicKeyCredentialCreationOptions', () => { + attestationRequestBodyFixtures.forEach((fixture, i) => { + const setChallengeSpy = jest.fn(); + const setLiquidExtensionSpy = jest.fn(); + const response = attestationController.request( + { + set challenge(str: string) { + setChallengeSpy(str); + }, + set liquidExtension(val: boolean) { + setLiquidExtensionSpy(val); + }, + }, + fixture as AttestationSelectorDto, + ); + expect(response).toEqual({ + ...attestationRequestResponseFixtures[i], + challenge: response.challenge, + }); + expect(setChallengeSpy).toHaveBeenCalledWith(response.challenge); + expect(setLiquidExtensionSpy).toHaveBeenCalledWith(true); + }); + }); + it('should fail if liquid extension is not enabled', async () => { + attestationRequestBodyFixtures.forEach((fixture) => { + expect(() => + attestationController.request({}, { + ...fixture, + extensions: {}, + } as AttestationSelectorDto), + ).toThrow(NotImplementedException); + }); + }); + }); + + describe('POST /response', () => { + it('should register a key and emit to connected clients', async () => { + const session: Record = new Session(); + authService.addCredential = jest + .fn() + .mockResolvedValue(attestationResponseResponseFixtures[0]); + session.challenge = attestationRequestResponseFixtures[0].challenge; + session.liquidExtension = true; + const body = + attestationResponseBodyFixtures[0] as AttestationCredentialJSONDto; + const headers = { 'user-agent': androidUserAgentFixtures[0] }; + await expect( + attestationController.response(session, headers, body), + ).resolves.toBe(attestationResponseResponseFixtures[0]); + expect(session.challenge).toBeUndefined(); + expect(session.liquidExtension).toBeUndefined(); + expect(session.wallet).toEqual( + attestationResponseResponseFixtures[0].wallet, + ); + expect(mockAccountLinkService.emit).toHaveBeenCalledWith('auth', { + requestId: body.clientExtensionResults.liquid.requestId, + wallet: body.clientExtensionResults.liquid.address, + credId: body.id, + }); + }); + it('should set a default device if empty', async () => { + const session: Record = new Session(); + authService.addCredential = jest + .fn() + .mockResolvedValue(attestationResponseResponseFixtures[0]); + session.challenge = attestationRequestResponseFixtures[0].challenge; + session.liquidExtension = true; + const body = { + ...attestationResponseBodyFixtures[0], + clientExtensionResults: { + liquid: { + ...attestationResponseBodyFixtures[0].clientExtensionResults.liquid, + device: null, + }, + }, + } as AttestationCredentialJSONDto; + const headers = { 'user-agent': androidUserAgentFixtures[0] }; + await expect( + attestationController.response(session, headers, body), + ).resolves.toBe(attestationResponseResponseFixtures[0]); + expect(session.challenge).toBeUndefined(); + expect(session.liquidExtension).toBeUndefined(); + expect(mockAccountLinkService.emit).toHaveBeenCalledWith('auth', { + requestId: body.clientExtensionResults.liquid.requestId, + wallet: body.clientExtensionResults.liquid.address, + credId: body.id, + }); + }); + it('should fail if the challenge is not a string', async () => { + await Promise.all( + attestationResponseBodyFixtures.map(async (fixture) => { + const body = fixture as AttestationCredentialJSONDto; + const headers = { 'user-agent': androidUserAgentFixtures[0] }; + + await expect(() => + attestationController.response( + { + challenge: null, + }, + headers, + body, + ), + ).rejects.toThrow(UnauthorizedException); + }), + ); + }); + it(`should fail when liquid is not enabled`, async () => { + await Promise.all( + attestationResponseBodyFixtures.map(async (fixture, i) => { + const body = fixture as AttestationCredentialJSONDto; + const headers = { 'user-agent': androidUserAgentFixtures[0] }; + const session = { + challenge: attestationRequestResponseFixtures[i].challenge, + }; + await expect( + attestationController.response(session, headers, body), + ).rejects.toThrow(NotImplementedException); + }), + ); + }); + it(`should fail when liquid is enabled without client extension results`, async () => { + await Promise.all( + attestationResponseBodyFixtures.map(async (fixture, i) => { + const body = { + ...fixture, + clientExtensionResults: {}, + } as unknown as AttestationCredentialJSONDto; + const headers = { 'user-agent': androidUserAgentFixtures[0] }; + const session = { + challenge: attestationRequestResponseFixtures[i].challenge, + liquidExtension: true, + }; + await expect( + attestationController.response(session, headers, body), + ).rejects.toThrow(UnauthorizedException); + }), + ); + }); + it(`should fail when the extension data is invalid`, async () => { + await Promise.all( + attestationResponseBodyFixtures.map(async (fixture, i) => { + const body = { + ...fixture, + clientExtensionResults: { + liquid: { + ...fixture.clientExtensionResults.liquid, + signature: + 'zM0bKHTntG3VtAp_1nAgsxK2F__bv5FukQAB6W-SMEkcvGPPkXbAmahudJB9M0HTBCcwymH7rjvnO2qR73F7AA', + }, + }, + } as AttestationCredentialJSONDto; + const headers = { 'user-agent': androidUserAgentFixtures[0] }; + const session = { + challenge: attestationRequestResponseFixtures[i].challenge, + liquidExtension: true, + }; + await expect(() => + attestationController.response(session, headers, body), + ).rejects.toThrow(UnauthorizedException); + }), + ); + }); + }); +}); diff --git a/services/liquid-auth-api-js/src/attestation/attestation.controller.ts b/services/liquid-auth-api-js/src/attestation/attestation.controller.ts index 80d3743..3ea4b8d 100644 --- a/services/liquid-auth-api-js/src/attestation/attestation.controller.ts +++ b/services/liquid-auth-api-js/src/attestation/attestation.controller.ts @@ -1,27 +1,26 @@ import { Body, Controller, - Get, Inject, Logger, Post, - Req, - Res, + Headers, Session, - UseGuards, + UnauthorizedException, + NotImplementedException, } from '@nestjs/common'; -import type { AttestationCredentialJSON } from '@simplewebauthn/typescript-types'; -import type { Request, Response } from 'express'; +import { ClientProxy } from '@nestjs/microservices'; +import { ApiOperation, ApiTags } from '@nestjs/swagger'; import { AuthService } from '../auth/auth.service.js'; - import { AttestationService } from './attestation.service.js'; -import type { AttestationSelectorDto } from './attestation.dto.js'; -import { AuthGuard } from '../auth/auth.guard.js'; -import { ClientProxy } from '@nestjs/microservices'; +import { + AttestationCredentialJSONDto, + AttestationSelectorDto, +} from './attestation.dto.js'; @Controller('attestation') -@UseGuards(AuthGuard) +@ApiTags('attestation') export class AttestationController { private readonly logger = new Logger(AttestationController.name); constructor( @@ -29,132 +28,122 @@ export class AttestationController { private attestationService: AttestationService, private authService: AuthService, ) {} - /** - * Hard Coded Request Attestation Options - * - * for demonstrations - * @deprecated - */ - @Get('/request/:walletId') - async demoRequest( - @Session() session: Record, - @Req() req: Request, - @Res() res: Response, - ) { - this.logger.log( - `GET /attestation/request/${req.params.walletId} for Session: ${session.id}`, - ); - try { - const wallet = req.params.walletId; - - const user = await this.authService.find(wallet); - if (!user) { - res.redirect(307, '/'); - } else { - const attestationOptions = this.attestationService.request(user, { - attestationType: 'none', - authenticatorSelection: { - authenticatorAttachment: 'platform', - userVerification: 'required', - requireResidentKey: false, - }, - }); - - res.json(attestationOptions); - } - } catch (e) { - res.status(500).json({ error: e.message }); - } - } /** * Request Attestation Options * * Creates a challenge and returns the options for the * authentication client to create an attestation * - * @param session - Express Session - * @param options - Attestation Selector DTO - * @param req - Express Request - * @param res - Express Response + * @param {Session} session - Express Session + * @param {AttestationSelectorDto} options - Attestation Selector DTO */ @Post('/request') - async request( + @ApiOperation({ summary: 'Attestation Request' }) + request( @Session() session: Record, - @Body() options: AttestationSelectorDto, // TODO: Update to use internal Options - @Req() req: Request, - @Res() res: Response, + @Body() options: AttestationSelectorDto, ) { this.logger.log( - `POST /attestation/request for Session: ${session.id} and Wallet: ${session.wallet}`, + `POST /attestation/request for Session: ${session.id} and Address: ${session.wallet}`, ); - try { - const wallet = session.wallet; - if (!wallet) { - res - .status(401) - .json({ reason: 'unauthorized', error: 'Wallet not connected' }); - return; - } - - const user = await this.authService.find(wallet); - if (!user) { - res - .status(403) - .json({ reason: 'not_found', error: 'Wallet not found.' }); - return; - } - - const attestationOptions = this.attestationService.request(user, options); - - session.challenge = attestationOptions.challenge; - this.logger.debug(attestationOptions); - res.json(attestationOptions); - } catch (e) { - res.status(500).json({ error: e.message }); + this.logger.debug('Attestation Selector', options); + // Enforce the liquid extension + if (typeof options?.extensions?.liquid === 'undefined') { + throw new NotImplementedException({ + reason: 'not_implemented', + error: 'Liquid extension is required', + }); } + session.liquidExtension = true; + // Request Attestation Options + const attestationOptions = this.attestationService.request(options); + // This challenge is used to verify the response + session.challenge = attestationOptions.challenge; + // Return the Attestation Options + this.logger.debug('Attestation Options', attestationOptions); + return attestationOptions; } /** - * Register a Key + * Validate Attestation Response + * + * Validates the attestation response from the authenticator and adds the credential to the user. + * + * @param {Session} session - Express Session + * @param {Headers} headers - Express Request + * @param {AttestationCredentialJSONDto} body - Attestation Credential JSON DTO + * */ @Post('/response') - async attestationResponse( + @ApiOperation({ summary: 'Attestation Response' }) + async response( @Session() session: Record, - @Body() body: AttestationCredentialJSON & { device?: string }, - @Req() req: Request, - @Res() res: Response, + @Headers() headers: Record, + @Body() + body: AttestationCredentialJSONDto, ) { this.logger.log(`POST /attestation/response for Session: ${session.id}`); - try { - const username = session.wallet; - const expectedChallenge = session.challenge; - if (typeof expectedChallenge !== 'string') { - res - .status(404) - .json({ reason: 'not_found', error: 'Challenge not found.' }); - return; - } - this.logger.debug( - `Username: ${username} Challenge: ${expectedChallenge}`, - ); - console.log(body); - const credential = await this.attestationService.response( - expectedChallenge, - req.get('User-Agent'), - body, - ); - this.logger.debug(credential); - const user = await this.authService.addCredential(username, credential); + this.logger.debug(`Authenticator Response`, body); + // Session state + const isLiquid = session.liquidExtension || false; + const expectedChallenge = session.challenge; + // This request should only be called after a request + if (typeof expectedChallenge !== 'string') { + throw new UnauthorizedException({ + reason: 'unauthorized', + error: 'Challenge not found', + }); + } + // If the liquid extension is enabled, the client must send the liquid extension + if ( + isLiquid && + typeof body?.clientExtensionResults?.liquid === 'undefined' + ) { + throw new UnauthorizedException({ + reason: 'unauthorized', + error: 'Liquid extension not found', + }); + } + // Service only supports liquid extension + if (!isLiquid) { + throw new NotImplementedException({ + reason: 'not_implemented', + error: 'Liquid extension is required', + }); + } + // Verify the Credential and Liquid Extension + const credential = await this.attestationService + .response(expectedChallenge, headers['user-agent'], body) + .catch((e) => { + this.logger.error(e); + throw new UnauthorizedException({ + reason: 'unauthorized', + error: 'User verification failed', + }); + }); - delete session.challenge; - this.client.emit('auth-interaction', { + const username = body.clientExtensionResults.liquid.address; + // Initialize a new user if it doesn't exist + await this.authService.init(username); + // Add the new credential to the user + const user = await this.authService.addCredential(username, credential); + // Cleanup Session + delete session.liquidExtension; + delete session.challenge; + // Authorize user with a wallet session + session.wallet = username; + // Handle Liquid Extension + if ( + typeof body?.clientExtensionResults?.liquid?.requestId !== 'undefined' + ) { + this.client.emit('auth', { + requestId: body.clientExtensionResults.liquid.requestId, wallet: user.wallet, - credential, + credId: credential.credId, }); - res.json(user); - } catch (e) { - this.logger.error(e.message, e.stack); - res.status(500).json({ error: e.message }); } + + this.logger.debug('User', user); + return user; } } diff --git a/services/liquid-auth-api-js/src/attestation/attestation.dto.ts b/services/liquid-auth-api-js/src/attestation/attestation.dto.ts index af8c91e..011eced 100644 --- a/services/liquid-auth-api-js/src/attestation/attestation.dto.ts +++ b/services/liquid-auth-api-js/src/attestation/attestation.dto.ts @@ -1,4 +1,27 @@ +import type { AttestationCredentialJSON } from '@simplewebauthn/typescript-types'; + export type AttestationSelectorDto = { + username: string; + displayName: string; authenticatorSelection: AuthenticatorSelectionCriteria; attestationType?: AttestationConveyancePreference; + extensions?: LiquidAttestationExtensionsClientInput; }; +export type AttestationCredentialJSONDto = AttestationCredentialJSON & { + clientExtensionResults: LiquidAuthClientExtensionResults; +}; + +export type LiquidAuthClientExtensionResults = { + liquid: { + type: 'algorand'; + signature: string; + address: string; + + device?: string; + requestId?: string | number; + }; +}; +export type LiquidAttestationExtensionsClientInput = + AuthenticationExtensionsClientInputs & { + liquid: boolean; + }; diff --git a/services/liquid-auth-api-js/src/attestation/attestation.module.ts b/services/liquid-auth-api-js/src/attestation/attestation.module.ts index 785c3ad..7c86ad0 100644 --- a/services/liquid-auth-api-js/src/attestation/attestation.module.ts +++ b/services/liquid-auth-api-js/src/attestation/attestation.module.ts @@ -8,6 +8,7 @@ import { MongooseModule } from '@nestjs/mongoose'; import { User, UserSchema } from '../auth/auth.schema.js'; import { ClientsModule, Transport } from '@nestjs/microservices'; import { Session, SessionSchema } from '../auth/session.schema.js'; +import { AlgodService } from '../algod/algod.service.js'; @Module({ imports: [ @@ -30,6 +31,6 @@ import { Session, SessionSchema } from '../auth/session.schema.js'; ]), ], controllers: [AttestationController], - providers: [AppService, AuthService, AttestationService], + providers: [AppService, AlgodService, AuthService, AttestationService], }) export class AttestationModule {} diff --git a/services/liquid-auth-api-js/src/attestation/attestation.service.spec.ts b/services/liquid-auth-api-js/src/attestation/attestation.service.spec.ts new file mode 100644 index 0000000..8aad592 --- /dev/null +++ b/services/liquid-auth-api-js/src/attestation/attestation.service.spec.ts @@ -0,0 +1,94 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { AttestationService } from './attestation.service.js'; +import { ConfigModule, ConfigService } from '@nestjs/config'; +import { AppService } from '../app.service.js'; + +import { AlgodService } from '../algod/algod.service.js'; +import configurationFixture from '../__fixtures__/configuration.fixture.json'; + +import attestationRequestResponseFixtures from './__fixtures__/attestation.request.response.fixtures.json'; +import attestationResponseBodyFixtures from './__fixtures__/attestation.response.body.fixtures.json'; + +describe('AttestationService', () => { + let provider: AttestationService; + const algodServiceMockFactory = (addr: string) => + ({ + exclude: jest.fn().mockReturnThis(), + do: jest.fn(async () => ({ 'auth-addr': addr })), + accountInformation: jest.fn().mockReturnThis(), + }) as unknown as AlgodService; + let currentMock = algodServiceMockFactory( + '24FEVK3D3VPVHP2MHVTZZSP6PINKW7PGPYTFHLO6X6LV4VNFWDTM6AQI7U', + ); + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + imports: [ + ConfigModule.forRoot({ + isGlobal: true, + load: [() => configurationFixture], + }), + ], + providers: [ + ConfigService, + { + provide: AlgodService, + useValue: currentMock, + }, + AppService, + AttestationService, + ], + }).compile(); + provider = module.get(AttestationService); + }); + it('should be defined', () => { + expect(provider).toBeDefined(); + }); + + it('should validate a signature', () => { + attestationResponseBodyFixtures.forEach((fixture, i) => { + const liquid = fixture.clientExtensionResults.liquid; + expect( + provider.verify( + currentMock, + liquid.type, + attestationRequestResponseFixtures[i].challenge, + liquid.signature, + liquid.address, + ), + ).resolves.toEqual(true); + }); + }); + it('should validate a rekeyed address', () => { + attestationResponseBodyFixtures.forEach((fixture, i) => { + const rekeyAddress = + '24FEVK3D3VPVHP2MHVTZZSP6PINKW7PGPYTFHLO6X6LV4VNFWDTM6AQI7U'; + const liquid = fixture.clientExtensionResults.liquid; + currentMock = algodServiceMockFactory(liquid.address); + expect( + provider.verify( + currentMock, + liquid.type, + attestationRequestResponseFixtures[i].challenge, + liquid.signature, + rekeyAddress, + ), + ).resolves.toEqual(true); + }); + }); + it('should fail to validate unsupported signatures', () => { + attestationResponseBodyFixtures.forEach((fixture, i) => { + const liquid = fixture.clientExtensionResults.liquid; + currentMock = algodServiceMockFactory(liquid.address); + expect( + provider.verify( + currentMock, + 'unknown', + attestationRequestResponseFixtures[i].challenge, + liquid.signature, + liquid.address, + ), + ).resolves.toEqual(false); + }); + }); +}); diff --git a/services/liquid-auth-api-js/src/attestation/attestation.service.ts b/services/liquid-auth-api-js/src/attestation/attestation.service.ts index 8191bc5..ca131b8 100644 --- a/services/liquid-auth-api-js/src/attestation/attestation.service.ts +++ b/services/liquid-auth-api-js/src/attestation/attestation.service.ts @@ -1,17 +1,62 @@ import { Injectable } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; import { AppService } from '../app.service.js'; -import fido2 from '@simplewebauthn/server'; +import * as fido2 from '@simplewebauthn/server'; import { AttestationSelectorDto } from './attestation.dto.js'; -import { User } from '../auth/auth.schema.js'; import type { AttestationCredentialJSON } from '@simplewebauthn/typescript-types'; +import { decodeAddress, fromBase64Url } from '@liquid/core'; +import nacl from 'tweetnacl'; +import { AlgodService } from '../algod/algod.service.js'; @Injectable() export class AttestationService { constructor( private appService: AppService, + private algodService: AlgodService, private configService: ConfigService, ) {} - request(user: User, options: AttestationSelectorDto) { + async verify( + algod: AlgodService, + type: string, + challenge: string, + signature: string, + address: string, + ) { + if (type === 'algorand') { + // Decode + const publicKeyBytes = decodeAddress(address); + const signatureBytes = fromBase64Url(signature); + const challengeBytes = fromBase64Url(challenge); + const valid = nacl.sign.detached.verify( + challengeBytes, + signatureBytes, + publicKeyBytes, + ); + if (valid) return true; + if (!valid) { + // signature check failed, check if its rekeyed + // if it is, verify against that public key instead + const accountInfo = await algod + .accountInformation(address) + .exclude('all') + .do(); + + if (!accountInfo['auth-addr']) { + return false; + } + + const authPublicKey = decodeAddress(accountInfo['auth-addr']); + + // Validate Auth Address Signature + return nacl.sign.detached.verify( + challengeBytes, + signatureBytes, + authPublicKey, + ); + } + } + return false; + } + request(options: AttestationSelectorDto) { //https://www.iana.org/assignments/cose/cose.xhtml#algorithms // EdDSA is -8 const pubKeyCredParams = []; @@ -22,22 +67,12 @@ export class AttestationService { } // TOOD: Investigate fido2 simple server to breakdown what it is doing const attestationOptions = fido2.generateAttestationOptions({ + ...options, rpName: this.configService.get('rpName'), rpID: this.configService.get('hostname'), - userID: user.id, - userName: user.wallet, + userID: options.username, + userName: options.username, timeout: this.configService.get('timeout'), - // Prompt users for additional information about the authenticator. - attestationType: options.attestationType || 'none', - // Prevent users from re-registering existing authenticators - excludeCredentials: user.credentials.map((cred) => { - return { - id: cred.credId, - type: 'public-key', - transports: ['internal'], - }; - }), - // authenticatorSelection: options.authenticatorSelection, }); // Temporary hack until SimpleWebAuthn supports `pubKeyCredParams` @@ -60,26 +95,53 @@ export class AttestationService { async response( expectedChallenge: string, ua: string, - credential: AttestationCredentialJSON & { device?: string }, + credential: AttestationCredentialJSON & { + clientExtensionResults?: { + liquid: { + type: string; + signature: string; + address: string; + device?: string; + }; + }; + }, ) { const expectedOrigin = this.appService.getOrigin(ua); - console.log(expectedOrigin); const expectedRPID = this.configService.get('hostname'); + + // Validate the passkey const verifiedAttestation = await fido2.verifyAttestationResponse({ credential, expectedChallenge, expectedOrigin, expectedRPID, }); + const { authenticatorInfo } = verifiedAttestation; + let { verified } = verifiedAttestation; - const { verified, authenticatorInfo } = verifiedAttestation; + // Handle Liquid Extension + const isLiquid = + typeof credential.clientExtensionResults !== 'undefined' && + typeof credential.clientExtensionResults.liquid !== 'undefined'; + // Check for extension results + if (isLiquid && verified) { + // Verify the signature + verified = await this.verify( + this.algodService, + credential.clientExtensionResults.liquid.type, + expectedChallenge, + credential.clientExtensionResults.liquid.signature, + credential.clientExtensionResults.liquid.address, + ); + } if (!verified) { throw 'User verification failed.'; } return { - device: credential.device || 'Unknown Device', + device: + credential?.clientExtensionResults?.liquid?.device || 'Unknown Device', publicKey: authenticatorInfo.base64PublicKey, credId: authenticatorInfo.base64CredentialID, prevCounter: authenticatorInfo.counter, diff --git a/services/liquid-auth-api-js/src/auth/auth.controller.get.user.md b/services/liquid-auth-api-js/src/auth/auth.controller.get.user.md new file mode 100644 index 0000000..e69de29 diff --git a/services/liquid-auth-api-js/src/auth/auth.controller.spec.ts b/services/liquid-auth-api-js/src/auth/auth.controller.spec.ts new file mode 100644 index 0000000..cfd180d --- /dev/null +++ b/services/liquid-auth-api-js/src/auth/auth.controller.spec.ts @@ -0,0 +1,137 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { AuthController } from './auth.controller.js'; +import { AuthService } from './auth.service.js'; +import { Session } from './session.schema.js'; +import mongoose, { Error, Model } from 'mongoose'; +import { User, UserSchema } from './auth.schema.js'; +import { getModelToken } from '@nestjs/mongoose'; +import { Response } from 'express'; +import { dummyUsers } from '../../tests/constants.js'; +import { mockAuthService } from '../__mocks__/auth.service.mock.js'; +import sessionFixtures from '../__fixtures__/session.fixtures.json'; +import { + InternalServerErrorException, + NotFoundException, +} from '@nestjs/common'; + +describe('AuthController', () => { + let authController: AuthController; + let authService: AuthService; + let userModel: Model; + + beforeEach(async () => { + userModel = mongoose.model('User', UserSchema); + + const moduleRef: TestingModule = await Test.createTestingModule({ + controllers: [AuthController], + providers: [ + { + provide: AuthService, + useValue: { ...mockAuthService }, + }, + { + provide: getModelToken(User.name), + useValue: userModel, + }, + ], + }).compile(); + + authService = moduleRef.get(AuthService); + authController = moduleRef.get(AuthController); + }); + + it('should be defined', () => { + expect(authController).toBeDefined(); + }); + + describe('Get /keys', () => { + it('(OK) should return a user from their session', async () => { + const dummyUser = dummyUsers[0]; + const user = await authController.keys(sessionFixtures.authorized); + + expect(user).toBe(dummyUser); + }); + + it('(FAIL) should fail when mongo db throws an error', async () => { + authService.find = jest + .fn() + .mockRejectedValue(new Error('failed to retrieve user')); + + const session = new Session(); + + await expect(authController.keys(session)).rejects.toThrow(); + }); + }); + + describe('Delete /keys/:id', () => { + it('(OK) should return success: true when removeCredential succeeds', async () => { + const session = new Session(); + await expect(authController.remove(session, `1`)).resolves.toEqual({ + success: true, + }); + }); + + it('(FAIL) should fail if it cannot find the user', async () => { + authService.find = jest.fn().mockResolvedValue(undefined); + + const session = {} as Record; + await expect(authController.remove(session, `1`)).rejects.toThrow( + NotFoundException, + ); + }); + + it('(FAIL) should fail when mongo db throws an error', async () => { + authService.find = jest + .fn() + .mockRejectedValue(new Error('failed to find user')); + + const session = new Session(); + await expect(authController.remove(session, `1`)).rejects.toThrow( + InternalServerErrorException, + ); + }); + + it('(FAIL) should fail if it cannot remove the credential', async () => { + authService.removeCredential = jest + .fn() + .mockRejectedValue(new Error('failed to update user')); + + const session = new Session(); + + await expect(authController.remove(session, `1`)).rejects.toThrow( + InternalServerErrorException, + ); + }); + }); + + describe('Get /logout', () => { + it('(OK) should log the user out (removing their session)', async () => { + const session = new Session(); + const res = { + status: jest.fn().mockReturnValue(200), + json: jest.fn().mockReturnValue('{ meh }'), + redirect: jest.fn(), + } as any as Response; + + expect(authController.logout(session, res)).toBe(undefined); + }); + }); + + describe('Get /session', () => { + it('(OK) should fetch a session', async () => { + const dummyUser = dummyUsers[0]; + const user = await authController.read(sessionFixtures.authorized); + await expect(user).toStrictEqual({ + user: dummyUser, + session: sessionFixtures.authorized, + }); + }); + + it('(OK) should return an empty object if the user is not found', async () => { + authService.find = jest.fn().mockResolvedValue(null); + await expect( + authController.read(sessionFixtures.authorized), + ).resolves.toEqual({ session: sessionFixtures.authorized, user: null }); + }); + }); +}); diff --git a/services/liquid-auth-api-js/src/auth/auth.controller.ts b/services/liquid-auth-api-js/src/auth/auth.controller.ts index 96ac704..47ae49f 100644 --- a/services/liquid-auth-api-js/src/auth/auth.controller.ts +++ b/services/liquid-auth-api-js/src/auth/auth.controller.ts @@ -2,71 +2,86 @@ import { Controller, Delete, Get, - Req, + HttpException, + InternalServerErrorException, + NotFoundException, + Param, Res, Session, UseGuards, } from '@nestjs/common'; -import type { Request, Response } from 'express'; +import type { Response } from 'express'; import { AuthService } from './auth.service.js'; import { AuthGuard } from './auth.guard.js'; +import { + ApiCookieAuth, + ApiForbiddenResponse, + ApiOperation, + ApiResponse, + ApiTags, +} from '@nestjs/swagger'; +import { User } from './auth.schema.js'; @Controller('auth') +@ApiTags('auth') export class AuthController { constructor(private authService: AuthService) {} - /** - * Debugging Route that shows all Users - * @param res - */ - @Get('/all') - async all(@Res() res: Response) { - res.json(await this.authService.all()); - } /** * Display user keys * * @param session - * @param res */ - @Get('/keys') + @Get('/user') + @ApiOperation({ summary: 'Get User' }) + @ApiResponse({ status: 200, description: 'Get the current user', type: User }) + @ApiForbiddenResponse({ description: 'Forbidden' }) + @ApiCookieAuth() @UseGuards(AuthGuard) - async keys(@Session() session: Record, @Res() res: Response) { + async keys(@Session() session: Record) { const wallet = session.wallet; - const user = await this.authService.find(wallet); - res.json(user || {}); + return await this.authService.find(wallet); } /** * Delete Credential * * @param session - Express Session - * @param req - Express Request - * @param res - Express Response + * @param id */ @Delete('/keys/:id') @UseGuards(AuthGuard) + @ApiOperation({ summary: 'Delete Credential' }) + @ApiForbiddenResponse({ description: 'Forbidden' }) + @ApiCookieAuth() async remove( @Session() session: Record, - @Req() req: Request, - @Res() res: Response, + @Param('id') id: string, ) { - const user = await this.authService.find(session.wallet); + try { + const user = await this.authService.find(session.wallet); - if (!user) { - res.status(404).json({ error: 'User not found' }); - } else { - this.authService - .removeCredential(user, req.params.id) - .then(() => { - res.json({ success: true }); - }) - .catch((e) => { - res.status(500).json({ error: e.message }); + if (!user) { + throw new NotFoundException({ + error: 'User not found', }); + } + + await this.authService.removeCredential(user, id); + + return { success: true }; + } catch (e) { + if (e instanceof HttpException) { + throw e; + } + + throw new InternalServerErrorException({ + error: e.message, + }); } } @Get('/logout') + @ApiOperation({ summary: 'Log Out' }) logout(@Session() session: Record, @Res() res: Response) { delete session.wallet; delete session.active; @@ -79,19 +94,18 @@ export class AuthController { * @param session */ @Get('/session') + @ApiOperation({ summary: 'Get Session' }) async read(@Session() session: Record) { const user = await this.authService.find(session.wallet); - return ( - { - user: user - ? { - id: user.id, - wallet: user.wallet, - credentials: user.credentials, - } - : null, - session, - } || {} - ); + return { + user: user + ? { + id: user.id, + wallet: user.wallet, + credentials: user.credentials, + } + : null, + session, + }; } } diff --git a/services/liquid-auth-api-js/src/auth/auth.guard.spec.ts b/services/liquid-auth-api-js/src/auth/auth.guard.spec.ts new file mode 100644 index 0000000..e788a68 --- /dev/null +++ b/services/liquid-auth-api-js/src/auth/auth.guard.spec.ts @@ -0,0 +1,27 @@ +import { AuthGuard } from './auth.guard.js'; +import { ExecutionContext } from '@nestjs/common'; +import sessionFixtures from '../__fixtures__/session.fixtures.json'; +describe('AuthGuard', () => { + const mockExecutionContext: Partial< + Record< + jest.FunctionPropertyNames, + jest.MockedFunction + > + > = { + switchToHttp: jest.fn().mockReturnValue({ + getRequest: jest + .fn() + .mockReturnValue({ session: sessionFixtures.authorized }), + getResponse: jest.fn().mockReturnThis(), + }), + }; + it('should be defined', () => { + expect(new AuthGuard()).toBeDefined(); + }); + it('should guard a route', () => { + const guard = new AuthGuard(); + expect(guard.canActivate(mockExecutionContext as ExecutionContext)).toBe( + true, + ); + }); +}); diff --git a/services/liquid-auth-api-js/src/auth/auth.guard.ts b/services/liquid-auth-api-js/src/auth/auth.guard.ts index b29a387..384e698 100644 --- a/services/liquid-auth-api-js/src/auth/auth.guard.ts +++ b/services/liquid-auth-api-js/src/auth/auth.guard.ts @@ -7,7 +7,7 @@ export class AuthGuard implements CanActivate { context: ExecutionContext, ): boolean | Promise | Observable { const request = context.switchToHttp().getRequest(); - const session = request.session || request.handshake.session; + const session = request.session; return ( typeof session !== 'undefined' && typeof session.wallet === 'string' && diff --git a/services/liquid-auth-api-js/src/auth/auth.schema.ts b/services/liquid-auth-api-js/src/auth/auth.schema.ts index 072d79a..e8fe91e 100644 --- a/services/liquid-auth-api-js/src/auth/auth.schema.ts +++ b/services/liquid-auth-api-js/src/auth/auth.schema.ts @@ -1,21 +1,35 @@ import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose'; import { HydratedDocument } from 'mongoose'; +import { ApiProperty } from '@nestjs/swagger'; export type UserDocument = HydratedDocument; -export type Credential = { +export type CredentialType = { device?: string; publicKey: string; //base64PublicKey, credId: string; //base64CredentialID, prevCounter: number; //counter, }; +export class Credential implements CredentialType { + @ApiProperty() + device?: string; + @ApiProperty() + publicKey: string; //base64PublicKey, + @ApiProperty() + credId: string; //base64CredentialID, + @ApiProperty() + prevCounter: number; //counter +} @Schema() export class User { + @ApiProperty() @Prop({ required: true }) id: string; + @ApiProperty() @Prop({ required: true }) wallet: string; + @ApiProperty({ type: [Credential] }) @Prop({ required: true }) credentials: Credential[]; } diff --git a/services/liquid-auth-api-js/src/auth/auth.service.spec.ts b/services/liquid-auth-api-js/src/auth/auth.service.spec.ts new file mode 100644 index 0000000..24790c1 --- /dev/null +++ b/services/liquid-auth-api-js/src/auth/auth.service.spec.ts @@ -0,0 +1,130 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { getModelToken } from '@nestjs/mongoose'; +import { Model } from 'mongoose'; +import { AuthService } from './auth.service.js'; +import { User } from './auth.schema.js'; +import { Session } from './session.schema.js'; + +describe('AuthService', () => { + const mockUser = { + wallet: '2SPDE6XLJNXFTOO7OIGNRNKSEDOHJWVD3HBSEAPHONZQ4IQEYOGYTP6LXA', + credentials: [], + }; + const mockCredential = { + device: 'Pixel 8 Pro', + publicKey: + 'pQECAyYgASFYIB2dcp3wanhReRhgRIpJCUfRSwkCvyE9OdvEL_NlncSJIlggkSIz7h7O5nrAXGJrkCOmeolChSc09eHzniCFLFxaKH0', + credId: + 'AYMPi2Rbhcnu2gSHOO1TNvzDJ38iU00rrlCqyH874XCIEoIotRc7eVRFpx0TvsQurg7BAnXy5KnWdKC8LeWs0k0', + prevCounter: 0, + }; + const mockSession = { + _id: '60b3b3b3b3b3b3b3b3b3b3b3', + expires: new Date(), + session: JSON.stringify({ wallet: mockUser.wallet }), + }; + let service: AuthService; + let userModel; + let mockUserModel; + let mockSessionModel; + beforeEach(async () => { + mockUserModel = jest.fn(() => ({ + save: jest.fn().mockResolvedValue(mockUser), + toObject: jest.fn().mockReturnValue({}), + })) as unknown as Model; + mockUserModel.findOne = jest.fn().mockReturnValue({ + exec: jest.fn().mockResolvedValue(mockUser), + }); + mockUserModel.findOneAndUpdate = jest.fn().mockReturnValue({ + exec: jest.fn().mockResolvedValue(mockUser), + }); + mockSessionModel = jest.fn(() => ({ + save: jest.fn().mockResolvedValue(mockSession), + toObject: jest.fn().mockReturnValue({}), + })) as unknown as Model; + mockSessionModel.findOne = jest.fn().mockReturnValue({ + exec: jest.fn().mockResolvedValue(mockSession), + }); + mockSessionModel.findOneAndUpdate = jest.fn().mockReturnValue({ + exec: jest.fn().mockResolvedValue(mockSession), + }); + const module: TestingModule = await Test.createTestingModule({ + providers: [ + { + provide: getModelToken(User.name), + useValue: mockUserModel, + }, + { + provide: getModelToken(Session.name), + useValue: mockSessionModel, + }, + AuthService, + ], + }).compile(); + userModel = module.get>(getModelToken(User.name)); + service = module.get(AuthService); + }); + + it('should be defined', () => { + expect(service).toBeDefined(); + }); + it('should initialize a new user', async () => { + userModel.findOne = jest.fn().mockReturnValue({ + exec: jest.fn().mockResolvedValue(null), + }); + const user = await service.init(mockUser.wallet); + expect(user).toEqual(mockUser); + }); + it('should fail to create invalid user', async () => { + await expect(service.init('&$@#%')).rejects.toThrow(TypeError); + }); + it('should search for a user', async () => { + const user = await service.search({ wallet: mockUser.wallet }); + expect(user).toEqual(mockUser); + }); + it('should update a user', async () => { + const user = await service.update(mockUser as User); + expect(user).toEqual(mockUser); + }); + it('should find a credential', async () => { + userModel.findOne = jest.fn().mockReturnValue({ + exec: jest + .fn() + .mockResolvedValue({ ...mockUser, credentials: [mockCredential] }), + }); + const credential = await service.findCredential(mockCredential.credId); + expect(credential).toEqual(mockCredential); + }); + it('should add a credential to a user', async () => { + const user = await service.addCredential(mockUser.wallet, mockCredential); + expect(user).toEqual({ ...mockUser, credentials: [mockCredential] }); + }); + it('should not add duplicate credentials', async () => { + userModel.findOne = jest.fn().mockReturnValue({ + exec: jest + .fn() + .mockResolvedValue({ ...mockUser, credentials: [mockCredential] }), + }); + const user = await service.addCredential(mockUser.wallet, mockCredential); + expect(user).toEqual({ ...mockUser, credentials: [mockCredential] }); + }); + it('should remove a credential from a user', async () => { + const user = await service.removeCredential( + { ...mockUser, credentials: [mockCredential] } as User, + mockCredential.credId, + ); + expect(user).toEqual(mockUser); + }); + + it('should find a session', async () => { + const session = await service.findSession(mockSession._id); + expect(session).toEqual(mockSession); + }); + it('should update a session', async () => { + const session = await service.updateSessionWallet( + mockSession, + mockUser.wallet, + ); + expect(session).toEqual(mockSession); + }); +}); diff --git a/services/liquid-auth-api-js/src/auth/auth.service.ts b/services/liquid-auth-api-js/src/auth/auth.service.ts index fafccad..2113e9f 100644 --- a/services/liquid-auth-api-js/src/auth/auth.service.ts +++ b/services/liquid-auth-api-js/src/auth/auth.service.ts @@ -95,10 +95,6 @@ export class AuthService { return this.update(user); } - async all() { - return this.userModel.find({}).exec(); - } - /** * Find a Session by ID * diff --git a/services/liquid-auth-api-js/src/config/configuration.spec.ts b/services/liquid-auth-api-js/src/config/configuration.spec.ts new file mode 100644 index 0000000..4858a0e --- /dev/null +++ b/services/liquid-auth-api-js/src/config/configuration.spec.ts @@ -0,0 +1,14 @@ +import configFactory from './configuration.js'; +import configFixture from '../__fixtures__/configuration.fixture.json'; +describe('configuration', () => { + it('should return the configuration', () => { + delete process.env.NODE_ENV; + expect(configFactory()).toEqual({ + ...configFixture, + env: 'development', + hostname: 'localhost', + origin: 'http://localhost', + }); + process.env.NODE_ENV = 'test'; + }); +}); diff --git a/services/liquid-auth-api-js/src/config/configuration.ts b/services/liquid-auth-api-js/src/config/configuration.ts index f73c327..2170ecc 100644 --- a/services/liquid-auth-api-js/src/config/configuration.ts +++ b/services/liquid-auth-api-js/src/config/configuration.ts @@ -2,8 +2,8 @@ export default () => ({ env: process.env.NODE_ENV || 'development', timeout: 30 * 1000 * 60, rpName: process.env.RP_NAME || 'Algorand Foundation FIDO2 Server', - hostname: process.env.HOSTNAME, - origin: process.env.ORIGIN, + hostname: process.env.HOSTNAME || 'localhost', + origin: process.env.ORIGIN || 'http://localhost', socket: { host: process.env.REDIS_HOST || 'localhost', port: parseInt(process.env.REDIS_PORT, 10) || 6379, diff --git a/services/liquid-auth-api-js/src/connect/connect.controller.spec.ts b/services/liquid-auth-api-js/src/connect/connect.controller.spec.ts deleted file mode 100644 index 0608e06..0000000 --- a/services/liquid-auth-api-js/src/connect/connect.controller.spec.ts +++ /dev/null @@ -1,100 +0,0 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { AlgodService } from '../algod/algod.service.js'; -import { ConnectController } from './connect.controller.js'; -import { AuthService } from '../auth/auth.service.js'; -import { Session } from '../auth/session.schema.js'; -import { accFixture } from '../../tests/constants.js'; -import { mockAuthService } from '../__mocks__/auth.service.mock.js'; -import { mockAccountLinkService } from '../__mocks__/account-link.service.mock.js'; - -describe('ConnectController', () => { - let connectController: ConnectController; - - beforeEach(async () => { - const moduleRef: TestingModule = await Test.createTestingModule({ - controllers: [ConnectController], - providers: [ - { - provide: AuthService, - useValue: { ...mockAuthService }, - }, - { - provide: 'ACCOUNT_LINK_SERVICE', - useValue: { ...mockAccountLinkService }, - }, - { - provide: AlgodService, - useValue: { - accountInformation: jest.fn().mockReturnThis(), - exclude: jest.fn().mockReturnThis(), - do: jest.fn().mockResolvedValue({ - 'auth-addr': accFixture.accs[1].addr, - }), - }, - }, - ], - }).compile(); - - connectController = moduleRef.get(ConnectController); - }); - - it('should be defined', () => { - expect(connectController).toBeDefined(); - }); - - describe('connect response', () => { - it('(CREATED) should return undefined when a valid account & signature requests to connect', async () => { - const session = new Session(); - - const linkResponseDTO = { - requestId: 0, - wallet: accFixture.accs[0].addr, - challenge: accFixture.challenge, - signature: accFixture.accs[0].signature, - credId: '', - }; - - const response = await connectController.linkWalletResponse( - session, - linkResponseDTO, - ); - - expect(response).toBe(undefined); - }); - - it("(FAIL) should throw an error when the signature doesn't match the account", async () => { - const session = new Session(); - - const linkResponseDTO = { - requestId: 0, - wallet: accFixture.accs[0].addr, - challenge: accFixture.challenge, - signature: accFixture.accs[2].signature, - credId: '', - }; - - await expect( - connectController.linkWalletResponse(session, linkResponseDTO), - ).rejects.toThrowError(); - }); - - it('(CREATED) should return undefined when a valid account & auth address signature requests to connect', async () => { - const session = new Session(); - - const linkResponseDTO = { - requestId: 0, - wallet: accFixture.accs[0].addr, - challenge: accFixture.challenge, - signature: accFixture.accs[1].signature, - credId: '', - }; - - const response = await connectController.linkWalletResponse( - session, - linkResponseDTO, - ); - - expect(response).toBe(undefined); - }); - }); -}); diff --git a/services/liquid-auth-api-js/src/connect/connect.controller.ts b/services/liquid-auth-api-js/src/connect/connect.controller.ts deleted file mode 100644 index 2625fd3..0000000 --- a/services/liquid-auth-api-js/src/connect/connect.controller.ts +++ /dev/null @@ -1,126 +0,0 @@ -import { - Body, - Controller, - Post, - Session, - Inject, - Logger, - HttpException, - HttpStatus, -} from '@nestjs/common'; -import { ClientProxy } from '@nestjs/microservices'; -import { AuthService } from '../auth/auth.service.js'; -import { AlgodService } from '../algod/algod.service.js'; -import nacl from 'tweetnacl'; -import { decodeAddress, fromBase64Url } from '@liquid/core/encoding'; - -type LinkResponseDTO = { - credId?: string; - requestId: string | number; - wallet: string; - challenge: string; - signature: string; -}; - -@Controller('connect') -export class ConnectController { - private readonly logger = new Logger(ConnectController.name); - - constructor( - private authService: AuthService, - private algodService: AlgodService, - @Inject('ACCOUNT_LINK_SERVICE') private client: ClientProxy, - ) {} - - /** - * Submit a response from a ConnectQR Scan - * and login to service - * - * @param res - * @param session - * @param requestId - * @param wallet - */ - @Post('response') - async linkWalletResponse( - @Session() session: Record, - @Body() - { requestId, wallet, challenge, signature, credId }: LinkResponseDTO, - ) { - this.logger.log( - `POST /connect/response for RequestId: ${requestId} Session: ${session.id} with Wallet: ${wallet}`, - ); - // Decode Address - const publicKey = decodeAddress(wallet); - - // Decode signature - const uint8Signature = fromBase64Url(signature); - - // Validate Signature - const encoder = new TextEncoder(); - const encodedChallenge = encoder.encode(challenge); - - if ( - !nacl.sign.detached.verify(encodedChallenge, uint8Signature, publicKey) - ) { - // signature check failed, check if its rekeyed - // if it is, verify against that public key instead - let accountInfo; - try { - accountInfo = await this.algodService - .accountInformation(wallet) - .exclude('all') - .do(); - } catch (e) { - throw new HttpException( - 'Failed to fetch Account Info', - HttpStatus.INTERNAL_SERVER_ERROR, - ); - } - - if (!accountInfo['auth-addr']) { - throw new HttpException('Invalid signature', HttpStatus.FORBIDDEN); - } - - const authPublicKey = decodeAddress(accountInfo['auth-addr']); - - // Validate Auth Address Signature - if ( - !nacl.sign.detached.verify( - encodedChallenge, - uint8Signature, - authPublicKey, - ) - ) { - throw new HttpException('Invalid signature', HttpStatus.FORBIDDEN); - } - } - - this.logger.log('AUTH Wallet is attested'); - // Authenticated user - try { - await this.authService.init(wallet); - } catch (e) { - throw new HttpException( - 'Failed to initialize wallet', - HttpStatus.INTERNAL_SERVER_ERROR, - ); - } - - const parsedRequest = - typeof requestId === 'string' ? parseFloat(requestId) : requestId; - - console.log('Request Forwarding', parsedRequest); - - session.wallet = wallet; - session.active = true; - - this.client.emit('auth', { - requestId, - wallet, - credId, - }); - - return; - } -} diff --git a/services/liquid-auth-api-js/src/connect/connect.dto.ts b/services/liquid-auth-api-js/src/connect/connect.dto.ts deleted file mode 100644 index 0c10c2f..0000000 --- a/services/liquid-auth-api-js/src/connect/connect.dto.ts +++ /dev/null @@ -1,15 +0,0 @@ -export type RTCIceCandidateDto = { - address: string; - candidate: string; - component: string; - foundation: string; - port: number; - priority: number; - protocol: string; - relatedAddress: string; - relatedPort: number; - sdpMid: string; - sdpMLineIndex: number; - tcpType: string; - usernameFragment?: string; -}; diff --git a/services/liquid-auth-api-js/src/connect/connect.gateway.ts b/services/liquid-auth-api-js/src/connect/connect.gateway.ts deleted file mode 100644 index 060cb80..0000000 --- a/services/liquid-auth-api-js/src/connect/connect.gateway.ts +++ /dev/null @@ -1,155 +0,0 @@ -import type { Server, Socket } from 'socket.io'; -import { Observable } from 'rxjs'; -import { map } from 'rxjs/operators'; -import { - ConnectedSocket, - MessageBody, - OnGatewayConnection, - OnGatewayDisconnect, - OnGatewayInit, - SubscribeMessage, - WebSocketGateway, -} from '@nestjs/websockets'; - -import { Logger } from '@nestjs/common'; -import { AuthService } from '../auth/auth.service.js'; -import { RedisIoAdapter } from '../adapters/redis-io.adapter.js'; -@WebSocketGateway({ - cors: { - origin: '*', - }, -}) -export class ConnectGateway - implements OnGatewayInit, OnGatewayConnection, OnGatewayDisconnect -{ - private timers = new Map(); - private ioAdapter: RedisIoAdapter; - private readonly logger = new Logger(ConnectGateway.name); - constructor(private authService: AuthService) {} - - /** - * Initialize the Gateway - * - * Pulls the RedisIoAdapter instance from the server - * - * @param server - */ - afterInit(server: Server) { - this.ioAdapter = server.sockets.adapter as unknown as RedisIoAdapter; - } - - /** - * Handle Connection - * - * Automatically join the client to the public key's room - * - * @param client - */ - async handleConnection(socket: Socket) { - const request = socket.request as Record; - const session = request.session as Record; - - const timer = setInterval(() => { - session.reload((err) => { - // console.log('Reloaded session') - if (err) { - // forces the client to reconnect - socket.conn.close(); - // you can also use socket.disconnect(), but in that case the client - // will not try to reconnect - } else { - if ( - typeof session.wallet === 'string' && - socket.rooms.has(session.wallet) === false - ) { - this.logger.debug(`(*) Client Joining Room ${session.wallet}`); - socket.join(session.wallet); - } - } - }); - }, 200); - - if (this.timers.has(request.sessionID)) { - clearInterval(this.timers.get(request.sessionID)); - } - - this.timers.set(request.sessionID, timer); - - this.logger.debug( - `(*) Client Connected with Session: ${request.sessionID}${ - session.wallet ? ` and PublicKey: ${session.wallet}` : '' - }`, - ); - if (typeof session.wallet === 'string') { - this.logger.debug(`(*) Client Joining Room ${session.wallet}`); - await socket.join(session.wallet); - } - } - - handleDisconnect(socket: Socket) { - const request = socket.request as Record; - this.logger.debug( - `(*) Client Disconnected with Session: ${request.sessionID}`, - ); - if (this.timers.has(request.sessionID)) { - clearInterval(this.timers.get(request.sessionID)); - } - } - - /** - * On Link Connection, wait for the wallet to connect - * @param client - * @param body - */ - @SubscribeMessage('link') - async linkAccount( - @ConnectedSocket() client: Socket, - @MessageBody() body: { requestId: string | number }, - ): Promise< - Observable<{ data: { requestId: string | number; wallet: string } }> - > { - const request = client.request as Record; - this.logger.debug( - `(link): link for Session: ${request.sessionID} with RequestId: ${body.requestId}`, - ); - - // Find the stored session - const session = await this.authService.findSession(request.sessionID); - console.log('Session', session); - if (session) { - console.log('Listening to auth messages'); - await this.ioAdapter.subClient.subscribe('auth'); - - // Handle messages - const obs$: Observable = new Observable((observer) => { - const handleAuthMessage = async (channel, eventMessage) => { - console.log('Link->Message', channel, eventMessage); - const { data } = JSON.parse(eventMessage); - console.log(body.requestId, data.requestId, data, body); - if (body.requestId === data.requestId) { - this.logger.debug( - `(*) Linking Wallet: ${data.wallet} to Session: ${request.sessionID}`, - ); - await this.authService.updateSessionWallet(session, data.wallet); - this.logger.debug(`(*) Joining Room: ${data.wallet}`); - await client.join(data.wallet); - observer.next(data); - this.ioAdapter.subClient.off('message', handleAuthMessage); - observer.complete(); - } - }; - - this.ioAdapter.subClient.on('message', handleAuthMessage); - }); - return obs$.pipe( - map((obs$) => ({ - data: { - credId: obs$.credId, - requestId: obs$.requestId, - wallet: obs$.wallet, - }, - })), - ); - } - } -} diff --git a/services/liquid-auth-api-js/src/connect/connect.module.ts b/services/liquid-auth-api-js/src/connect/connect.module.ts deleted file mode 100644 index 49f7556..0000000 --- a/services/liquid-auth-api-js/src/connect/connect.module.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { Module } from '@nestjs/common'; -import { ClientsModule, Transport } from '@nestjs/microservices'; -import { MongooseModule } from '@nestjs/mongoose'; - -// Connect -import { ConnectController } from './connect.controller.js'; -import { ConnectGateway } from './connect.gateway.js'; -// Auth -import { AuthService } from '../auth/auth.service.js'; -import { Session, SessionSchema } from '../auth/session.schema.js'; -import { User, UserSchema } from '../auth/auth.schema.js'; -import { AlgodService } from '../algod/algod.service.js'; - -@Module({ - imports: [ - MongooseModule.forFeature([ - { name: Session.name, schema: SessionSchema }, - { name: User.name, schema: UserSchema }, - ]), - // TODO: inject configuration - ClientsModule.register([ - { - name: 'ACCOUNT_LINK_SERVICE', - transport: Transport.REDIS, - options: { - host: process.env.REDIS_HOST || 'localhost', - port: parseInt(process.env.REDIS_PORT, 10) || 6379, - username: process.env.REDIS_USERNAME || 'default', - password: process.env.REDIS_PASSWORD || '', - }, - }, - ]), - ], - controllers: [ConnectController], - providers: [AuthService, ConnectGateway, AlgodService], -}) -export class ConnectModule {} diff --git a/services/liquid-auth-api-js/src/main.ts b/services/liquid-auth-api-js/src/main.ts index 1d08066..a20c284 100644 --- a/services/liquid-auth-api-js/src/main.ts +++ b/services/liquid-auth-api-js/src/main.ts @@ -15,6 +15,7 @@ import MongoStore from 'connect-mongo'; import * as Sentry from '@sentry/node'; import { ProfilingIntegration } from '@sentry/profiling-node'; import { SentryFilter } from './sentry.filter.js'; +import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger'; async function bootstrap() { const app = await NestFactory.create(AppModule, { @@ -40,6 +41,14 @@ async function bootstrap() { const { httpAdapter } = app.get(HttpAdapterHost); app.useGlobalFilters(new SentryFilter(httpAdapter)); } + const swaggerConfig = new DocumentBuilder() + .setTitle('Liquid Auth API') + .setDescription('Authentication API') + .setVersion('1.0') + .addCookieAuth('connect.sid') + .build(); + const document = SwaggerModule.createDocument(app, swaggerConfig); + SwaggerModule.setup('docs', app, document); const username = config.get('database.username'); const host = config.get('database.host'); const password = config.get('database.password'); @@ -57,7 +66,7 @@ async function bootstrap() { const sessionHandler = session({ secret: 'my-secret', saveUninitialized: true, - resave: false, + resave: true, cookie: { httpOnly: true, secure: false, // TODO: Secure the cookie diff --git a/services/liquid-auth-api-js/src/sentry.filter.spec.ts b/services/liquid-auth-api-js/src/sentry.filter.spec.ts new file mode 100644 index 0000000..25eb905 --- /dev/null +++ b/services/liquid-auth-api-js/src/sentry.filter.spec.ts @@ -0,0 +1,24 @@ +const captureException = jest.fn(); +const catchFn = jest.fn(); +import { SentryFilter } from './sentry.filter.js'; +import { ArgumentsHost } from '@nestjs/common'; +import { BaseExceptionFilter } from '@nestjs/core'; + +jest.mock('@sentry/node', () => ({ + captureException, +})); + +BaseExceptionFilter.prototype.catch = catchFn; + +describe('SentryFilter', () => { + it('should catch exceptions', () => { + const sentryFilter = new SentryFilter(); + const exception = new Error('test error'); + const host = {} as unknown as ArgumentsHost; + expect(() => { + sentryFilter.catch(exception, host); + }).not.toThrow(); + expect(captureException).toHaveBeenCalledWith(exception); + expect(catchFn).toHaveBeenCalledWith(exception, host); + }); +}); diff --git a/services/liquid-auth-api-js/src/signals/signals.gateway.spec.ts b/services/liquid-auth-api-js/src/signals/signals.gateway.spec.ts index 4d069db..eda108b 100644 --- a/services/liquid-auth-api-js/src/signals/signals.gateway.spec.ts +++ b/services/liquid-auth-api-js/src/signals/signals.gateway.spec.ts @@ -1,26 +1,43 @@ import { Test, TestingModule } from '@nestjs/testing'; -import { SignalsGateway } from './signals.gateway.js'; +import { SignalsGateway, reloadSession } from './signals.gateway.js'; import { Server, Socket } from 'socket.io'; +import mongoose, { Model } from 'mongoose'; +import { User, UserSchema } from '../auth/auth.schema.js'; +import { AuthService } from '../auth/auth.service.js'; +import { getModelToken } from '@nestjs/mongoose'; +import { mockAuthService } from '../__mocks__/auth.service.mock.js'; -// eslint-disable-next-line @typescript-eslint/no-var-requires -const candidateFixture = require('./__fixtures__/candidate.fixture.json'); -// eslint-disable-next-line @typescript-eslint/no-var-requires -const sdpFixtures = require('./__fixtures__/sdp.fixtures.json'); -// eslint-disable-next-line @typescript-eslint/no-var-requires -const sessionFixtures = require('../__fixtures__/session.fixtures.json'); +import candidateFixture from './__fixtures__/candidate.fixture.json'; +import sdpFixtures from './__fixtures__/sdp.fixtures.json'; +import sessionFixtures from '../__fixtures__/session.fixtures.json'; +import { Session } from 'express-session'; -const clientFixture = { +const clientMock = { request: { session: sessionFixtures.authorized, }, + rooms: new Set(), + join: jest.fn(), } as unknown as Socket; - +let linkEventFn: any; +const ioAdapterMock = { + subClient: { + on: jest.fn((name: string, fn) => { + linkEventFn = fn; + }), + off: jest.fn(), + subscribe: jest.fn(), + }, +}; jest.mock('socket.io', () => { return { Server: jest.fn().mockImplementation(() => { return { emit: jest.fn(), in: jest.fn().mockReturnThis(), + sockets: { + adapter: ioAdapterMock, + }, }; }), }; @@ -28,53 +45,138 @@ jest.mock('socket.io', () => { describe('SignalsGateway', () => { let gateway: SignalsGateway; - + let userModel: Model; beforeEach(async () => { + userModel = mongoose.model('User', UserSchema); + Object.keys(sessionFixtures).forEach((key) => { + sessionFixtures[key].reload = jest.fn(async (fn) => fn(null)); + }); + const module: TestingModule = await Test.createTestingModule({ - providers: [SignalsGateway], + providers: [ + { + provide: getModelToken(User.name), + useValue: userModel, + }, + { + provide: AuthService, + useValue: { + ...mockAuthService, + findSession: jest + .fn() + .mockResolvedValue(sessionFixtures.authorized), + updateSessionWallet: jest + .fn() + .mockResolvedValue(sessionFixtures.authorized), + }, + }, + SignalsGateway, + ], }).compile(); gateway = module.get(SignalsGateway); gateway.server = new Server(); + // @ts-expect-error, testing purposes + gateway.logger.debug = jest.fn(); + // @ts-expect-error, testing purposes + gateway.ioAdapter = ioAdapterMock; + }); + it('should be defined', () => { + expect(gateway).toBeDefined(); }); - it('should signal a offer-description', () => { - gateway.onCallDescription(sdpFixtures.call, clientFixture); + it('should add the ioAdapter after init', () => { + gateway.afterInit(gateway.server); + // @ts-expect-error, testing purposes + expect(gateway.ioAdapter).toBeInstanceOf(Object); + }); + it('should handle a authenticated connection', async () => { + await gateway.handleConnection(clientMock); + expect(clientMock.join).toHaveBeenCalledWith( + sessionFixtures.authorized.wallet, + ); + }); + it('should handle a unauthenticated connection', async () => { + await gateway.handleConnection({ + request: { + session: sessionFixtures.unauthorized, + }, + } as unknown as Socket); + // @ts-expect-error, testing purposes + expect(gateway.logger.debug).toHaveBeenCalled(); + }); + it('should log a disconnect', async () => { + gateway.handleDisconnect(clientMock); + // @ts-expect-error, testing purposes + expect(gateway.logger.debug).toHaveBeenCalled(); + }); + it('should handle a link event', async () => { + await gateway.link({ requestId: 0.1 }, clientMock); + expect(clientMock.join).toHaveBeenCalledWith( + sessionFixtures.authorized.wallet, + ); + expect(globalThis.handleObserver).toBeInstanceOf(Function); + expect( + globalThis.handleObserver({ next: jest.fn(), complete: jest.fn() }), + ).toBeUndefined(); + expect( + linkEventFn(null, JSON.stringify({ data: { requestId: 0.1 } })), + ).resolves.toBeUndefined(); + expect(globalThis.handleObserverMap).toBeInstanceOf(Function); + expect( + globalThis.handleObserverMap({ + credId: '0.1', + requestId: 0.1, + wallet: '0.1', + }), + ).toStrictEqual({ data: { credId: '0.1', requestId: 0.1, wallet: '0.1' } }); + }); + it('should signal a offer-description', async () => { + await gateway.onOfferDescription(sdpFixtures.call, clientMock); expect(gateway.server.in).toHaveBeenCalledWith( - (clientFixture.request as any).session.wallet, + (clientMock.request as any).session.wallet, ); expect(gateway.server.emit).toHaveBeenCalledWith( 'offer-description', sdpFixtures.call, ); }); - it('should signal a offer-candidate', () => { - gateway.onCallCandidate(candidateFixture, clientFixture); + it('should signal a offer-candidate', async () => { + await gateway.onOfferCandidate(candidateFixture, clientMock); expect(gateway.server.in).toHaveBeenCalledWith( - (clientFixture.request as any).session.wallet, + (clientMock.request as any).session.wallet, ); expect(gateway.server.emit).toHaveBeenCalledWith( 'offer-candidate', candidateFixture, ); }); - it('should signal a answer-description', () => { - gateway.onAnswerDescription(sdpFixtures.answer, clientFixture); + it('should signal a answer-description', async () => { + await gateway.onAnswerDescription(sdpFixtures.answer, clientMock); expect(gateway.server.in).toHaveBeenCalledWith( - (clientFixture.request as any).session.wallet, + (clientMock.request as any).session.wallet, ); expect(gateway.server.emit).toHaveBeenCalledWith( 'answer-description', sdpFixtures.answer, ); }); - it('should signal a answer-candidate', () => { - gateway.onAnswerCandidate(candidateFixture, clientFixture); + it('should signal a answer-candidate', async () => { + await gateway.onAnswerCandidate(candidateFixture, clientMock); expect(gateway.server.in).toHaveBeenCalledWith( - (clientFixture.request as any).session.wallet, + (clientMock.request as any).session.wallet, ); expect(gateway.server.emit).toHaveBeenCalledWith( 'answer-candidate', candidateFixture, ); }); + it('should reject a failed session reload', async () => { + //@ts-expect-error, testing purposes + sessionFixtures.authorized.reload = jest.fn(async (fn) => + fn(new Error('failed')), + ); + await expect( + reloadSession(sessionFixtures.authorized as unknown as Session), + ).rejects.toThrowError('failed'); + }); }); diff --git a/services/liquid-auth-api-js/src/signals/signals.gateway.ts b/services/liquid-auth-api-js/src/signals/signals.gateway.ts index 8eb13b2..4c5f67b 100644 --- a/services/liquid-auth-api-js/src/signals/signals.gateway.ts +++ b/services/liquid-auth-api-js/src/signals/signals.gateway.ts @@ -1,65 +1,217 @@ import { ConnectedSocket, MessageBody, + OnGatewayConnection, + OnGatewayDisconnect, + OnGatewayInit, SubscribeMessage, WebSocketGateway, WebSocketServer, } from '@nestjs/websockets'; -import { Logger, UseInterceptors } from '@nestjs/common'; +import { Logger } from '@nestjs/common'; import type { Server, Socket } from 'socket.io'; -import { SignalsInterceptor } from './signals.interceptor.js'; +import { Session as SessionType } from 'express-session'; +import { Observable, Subscriber } from 'rxjs'; +import { map } from 'rxjs/operators'; +import { RedisIoAdapter } from '../adapters/redis-io.adapter.js'; +import { AuthService } from '../auth/auth.service.js'; +import { Session } from '../auth/session.schema.js'; +export async function reloadSession(session: SessionType) { + return new Promise((resolve, reject) => { + session.reload((err) => { + if (err) { + reject(err); + } + resolve(session); + }); + }); +} -@WebSocketGateway() -@UseInterceptors(SignalsInterceptor) -export class SignalsGateway { +@WebSocketGateway({ + cors: { + origin: '*', + }, +}) +export class SignalsGateway + implements OnGatewayInit, OnGatewayConnection, OnGatewayDisconnect +{ @WebSocketServer() server: Server; + private ioAdapter: RedisIoAdapter; private readonly logger = new Logger(SignalsGateway.name); + constructor(private authService: AuthService) {} + /** + * Initialize the Gateway + * + * Pulls the RedisIoAdapter instance from the server + * + * @param server + */ + afterInit(server: Server) { + this.ioAdapter = server.sockets.adapter as unknown as RedisIoAdapter; + } + /** + * Handle Connection + * + * Automatically join the client to the public key's room + * + * @param socket + */ + async handleConnection(socket: Socket) { + const request = socket.request as Record; + await reloadSession(request.session); + const session = request.session as Record; + + this.logger.debug( + `(*) Client Connected with Session: ${request.sessionID}${ + session.wallet ? ` and PublicKey: ${session.wallet}` : '' + }`, + ); + if ( + typeof session.wallet === 'string' && + !socket.rooms.has(session.wallet) + ) { + this.logger.debug( + `(*) Client Joining Room ${session.wallet} with Session: ${request.sessionID}`, + ); + await socket.join(session.wallet); + } + } + + handleDisconnect(socket: Socket) { + const request = socket.request as Record; + this.logger.debug( + `(*) Client Disconnected with Session: ${request.sessionID}`, + ); + } + + /** + * On Link Connection, wait for the wallet to connect + * @param client + * @param body + */ + @SubscribeMessage('link') + async link( + @MessageBody() body: { requestId: string | number }, + @ConnectedSocket() client: Socket, + ): Promise< + Observable<{ data: { requestId: string | number; wallet: string } }> + > { + const request = client.request as Record; + this.logger.debug( + `(link): link for Session: ${request.sessionID} with RequestId: ${body.requestId}`, + ); + // Find the stored session + const session = await this.authService.findSession(request.sessionID); + if (session) { + await this.ioAdapter.subClient.subscribe('auth'); + const handleObserver = (observer: Subscriber) => { + const handleAuthMessage = async (_: any, eventMessage: string) => { + const { data } = JSON.parse(eventMessage); + if (body.requestId === data.requestId) { + this.logger.debug( + `(*) Linking Wallet: ${data.wallet} to Session: ${request.sessionID}`, + ); + await this.authService.updateSessionWallet(session, data.wallet); + this.logger.debug( + `(*) Joining Room: ${data.wallet} with Session: ${request.sessionID}`, + ); + await client.join(data.wallet); + observer.next(data); + this.ioAdapter.subClient.off('message', handleAuthMessage); + observer.complete(); + } + }; + + this.ioAdapter.subClient.on('message', handleAuthMessage); + }; + if (process.env.NODE_ENV === 'test') { + globalThis.handleObserver = handleObserver; + } + // Handle messages + const obs$: Observable = new Observable(handleObserver); + const handleObserverMap = (_obs$: any) => ({ + data: { + credId: _obs$.credId, + requestId: _obs$.requestId, + wallet: _obs$.wallet, + }, + }); + if (process.env.NODE_ENV === 'test') { + globalThis.handleObserverMap = handleObserverMap; + } + return obs$.pipe(map(handleObserverMap)); + } + } @SubscribeMessage('offer-candidate') - onCallCandidate( + async onOfferCandidate( @MessageBody() data: { candidate: string; sdpMid: string; sdpMLineIndex: number }, @ConnectedSocket() client: Socket, ) { this.logger.debug(`(offer-candidate): ${JSON.stringify(data)}`); const request = client.request as Record; - const session = request.session as Record; - this.server.in(session.wallet).emit('offer-candidate', data); + await reloadSession(request.session); + const session = request.session as Session & Record; + if (typeof session.wallet === 'string') { + this.server.in(session.wallet).emit('offer-candidate', data); + } } + @SubscribeMessage('offer-description') - onCallDescription( + async onOfferDescription( @MessageBody() data: string, @ConnectedSocket() client: Socket, ) { this.logger.log(`(offer-description): ${data}`); - // Session from the initial Handshake const request = client.request as Record; + await reloadSession(request.session); const session = request.session as Record; - // Send description to all clients in the public key's room - this.server.in(session.wallet).emit('offer-description', data); + if (typeof session.wallet === 'string') { + if (!client.rooms.has(session.wallet)) { + client.join(session.wallet); + } + // Send description to all clients in the public key's room + this.server.in(session.wallet).emit('offer-description', data); + } } @SubscribeMessage('answer-description') - onAnswerDescription( + async onAnswerDescription( @MessageBody() data: string, @ConnectedSocket() client: Socket, ) { this.logger.log(`(answer-description): ${data}`); const request = client.request as Record; + await reloadSession(request.session); + const session = request.session as Record; - this.server.in(session.wallet).emit('answer-description', data); + if (typeof session.wallet === 'string') { + if (!client.rooms.has(session.wallet)) { + client.join(session.wallet); + } + this.server.in(session.wallet).emit('answer-description', data); + } } @SubscribeMessage('answer-candidate') - onAnswerCandidate( + async onAnswerCandidate( @MessageBody() data: { candidate: string; sdpMid: string; sdpMLineIndex: number }, @ConnectedSocket() client: Socket, ) { this.logger.debug(`(answer-candidate): ${JSON.stringify(data)}`); const request = client.request as Record; + await reloadSession(request.session); + const session = request.session as Record; - this.server.in(session.wallet).emit('answer-candidate', data); + if (typeof session.wallet === 'string') { + if (!client.rooms.has(session.wallet)) { + client.join(session.wallet); + } + this.logger.debug(`Sending (answer-candidate): ${JSON.stringify(data)}`); + this.server.in(session.wallet).emit('answer-candidate', data); + } } } diff --git a/services/liquid-auth-api-js/src/signals/signals.interceptor.spec.ts b/services/liquid-auth-api-js/src/signals/signals.interceptor.spec.ts deleted file mode 100644 index 96a904c..0000000 --- a/services/liquid-auth-api-js/src/signals/signals.interceptor.spec.ts +++ /dev/null @@ -1,83 +0,0 @@ -import { SignalsInterceptor } from './signals.interceptor'; -import { ExecutionContext } from '@nestjs/common'; -import { of } from 'rxjs'; - -function createExecutionContextMock(sessionFixture = {}): { - executionContext: ExecutionContext; - disconnect: jest.Mock; -} { - const disconnect = jest.fn(); - return { - executionContext: { - getArgByIndex: jest.fn().mockReturnThis(), - getArgs: jest.fn().mockReturnThis(), - getType: jest.fn().mockReturnThis(), - switchToWs: jest.fn().mockReturnValue({ - getClient: jest.fn().mockReturnValue({ - disconnect, - request: { session: sessionFixture }, - }), - }), - switchToHttp: jest.fn().mockReturnThis(), - switchToRpc: jest.fn().mockReturnThis(), - getClass: () => - ({ - name: 'something', - }) as any, - getHandler: () => - ({ - name: 'something', - }) as any, - }, - disconnect, - }; -} - -const next = { - handle: jest.fn(() => of()), -}; -describe('ConnectInterceptor', () => { - let interceptor: SignalsInterceptor; - - beforeEach(() => { - interceptor = new SignalsInterceptor(); - }); - it('should disconnect a invalid session', (done) => { - expect(interceptor).toBeDefined(); - const { executionContext, disconnect } = createExecutionContextMock({}); - const response = interceptor.intercept(executionContext, next); - - response.subscribe({ - next: () => { - expect(disconnect).toHaveBeenCalled(); - }, - error: (error) => { - throw error; - }, - complete: () => { - expect(disconnect).toBeCalledTimes(1); - done(); - }, - }); - }); - it('should continue with a valid session', (done) => { - expect(interceptor).toBeDefined(); - const { executionContext, disconnect } = createExecutionContextMock({ - wallet: 'AVALIDWALLETADDRESS', - }); - const response = interceptor.intercept(executionContext, next); - - response.subscribe({ - next: () => { - expect(disconnect).not.toHaveBeenCalled(); - }, - error: (error) => { - throw error; - }, - complete: () => { - expect(disconnect).toBeCalledTimes(0); - done(); - }, - }); - }); -}); diff --git a/services/liquid-auth-api-js/src/signals/signals.interceptor.ts b/services/liquid-auth-api-js/src/signals/signals.interceptor.ts deleted file mode 100644 index 38141a1..0000000 --- a/services/liquid-auth-api-js/src/signals/signals.interceptor.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { - CallHandler, - ExecutionContext, - Injectable, - Logger, - NestInterceptor, -} from '@nestjs/common'; -import { Observable } from 'rxjs'; -import { Socket } from 'socket.io'; - -@Injectable() -export class SignalsInterceptor implements NestInterceptor { - private readonly logger = new Logger(SignalsInterceptor.name); - intercept(context: ExecutionContext, next: CallHandler): Observable { - const client = context.switchToWs().getClient() as Socket; - const request = client.request as Record; - const session = request.session as Record; - - if (typeof session.wallet !== 'string') { - this.logger.error(`(*) Client ${request.sessionID} is not authenticated`); - client.disconnect(); - return next.handle(); - } else { - return next.handle(); - } - } -} diff --git a/services/liquid-auth-api-js/src/signals/signals.module.spec.ts b/services/liquid-auth-api-js/src/signals/signals.module.spec.ts deleted file mode 100644 index 5309d9b..0000000 --- a/services/liquid-auth-api-js/src/signals/signals.module.spec.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { SignalsModule } from './signals.module'; -import { SignalsGateway } from './signals.gateway'; -import { Test } from '@nestjs/testing'; - -describe('SignalsModule', () => { - it('should create the module', async () => { - const module = await Test.createTestingModule({ - imports: [SignalsModule], - }).compile(); - - expect(module).toBeDefined(); - expect(module.get(SignalsGateway)).toBeInstanceOf(SignalsGateway); - }); -}); diff --git a/services/liquid-auth-api-js/src/signals/signals.module.ts b/services/liquid-auth-api-js/src/signals/signals.module.ts index 36d094e..d2c7882 100644 --- a/services/liquid-auth-api-js/src/signals/signals.module.ts +++ b/services/liquid-auth-api-js/src/signals/signals.module.ts @@ -1,7 +1,17 @@ import { Module } from '@nestjs/common'; import { SignalsGateway } from './signals.gateway.js'; +import { MongooseModule } from '@nestjs/mongoose'; +import { Session, SessionSchema } from '../auth/session.schema.js'; +import { User, UserSchema } from '../auth/auth.schema.js'; +import { AuthService } from '../auth/auth.service.js'; @Module({ - providers: [SignalsGateway], + imports: [ + MongooseModule.forFeature([ + { name: Session.name, schema: SessionSchema }, + { name: User.name, schema: UserSchema }, + ]), + ], + providers: [AuthService, SignalsGateway], }) export class SignalsModule {} diff --git a/services/liquid-auth-api-js/tests/constants.ts b/services/liquid-auth-api-js/tests/constants.ts index 5c86529..0e5daa7 100644 --- a/services/liquid-auth-api-js/tests/constants.ts +++ b/services/liquid-auth-api-js/tests/constants.ts @@ -1,7 +1,8 @@ import { decodeAddress } from '@liquid/core/encoding'; +import * as crypto from 'node:crypto'; export const accFixture = { - challenge: '1234', + challenge: crypto.randomBytes(32).toString('base64url'), accs: [ { addr: 'B7WYCZ6HRBGCH452D24TYAK7BXKNCHEXY2X7S7FWZXMHDVTDOARAOURJEU', @@ -47,5 +48,5 @@ export const dummyOptions = { }; export const dummyAttestationOptions = { - challenge: 'meh', + challenge: crypto.randomBytes(32).toString('base64url'), }; diff --git a/services/liquid-auth-api-js/tests/fixtures/generate.configuration.database.fixtures.js b/services/liquid-auth-api-js/tests/fixtures/generate.configuration.database.fixtures.js new file mode 100644 index 0000000..a27e9fd --- /dev/null +++ b/services/liquid-auth-api-js/tests/fixtures/generate.configuration.database.fixtures.js @@ -0,0 +1,18 @@ +import {writeFileSync} from 'node:fs' +import {faker} from '@faker-js/faker' + +const count = 10 + +const fixtures = [] + +for(let i = 0; i < count; i++) { + fixtures.push({ + host: faker.internet.url({protocol: 'http', appendSlash: false}).replace('http://', ''), + username: faker.internet.userName(), + password: faker.internet.password(), + name: 'fido', + atlas: faker.datatype.boolean(), + }) +} + +writeFileSync('configuration.database.fixtures.json', JSON.stringify(fixtures, null, 2)) diff --git a/services/liquid-auth-api-js/tests/fixtures/generate.configuration.socket.fixtures.js b/services/liquid-auth-api-js/tests/fixtures/generate.configuration.socket.fixtures.js new file mode 100644 index 0000000..2410b83 --- /dev/null +++ b/services/liquid-auth-api-js/tests/fixtures/generate.configuration.socket.fixtures.js @@ -0,0 +1,20 @@ +import {writeFileSync} from 'node:fs' +import {faker} from '@faker-js/faker' + +const count = 10 + +const fixtures = [] +// host: process.env.REDIS_HOST || 'localhost', +// port: parseInt(process.env.REDIS_PORT, 10) || 6379, +// username: process.env.REDIS_USERNAME || 'default', +// password: process.env.REDIS_PASSWORD || '', +for(let i = 0; i < count; i++) { + fixtures.push({ + host: faker.internet.url({protocol: 'http', appendSlash: false}).replace('http://', ''), + port: faker.datatype.number({min: 1024, max: 65535}), + username: faker.internet.userName(), + password: faker.internet.password() + }) +} + +writeFileSync('configuration.socket.fixtures.json', JSON.stringify(fixtures, null, 2)) diff --git a/services/liquid-auth-api-js/tests/fixtures/writeFixture.ts b/services/liquid-auth-api-js/tests/fixtures/writeFixture.ts new file mode 100644 index 0000000..fffa774 --- /dev/null +++ b/services/liquid-auth-api-js/tests/fixtures/writeFixture.ts @@ -0,0 +1,21 @@ +import { join } from "node:path"; +import { writeFileSync } from "node:fs"; +const filePath = join(process.cwd(), './src'); +let fixtures = {} +export function writeFixture(name: string, content: string) { + if(typeof fixtures[name] === 'undefined') { + fixtures[name] = [] + } + let fixture + try{ + fixture = JSON.parse(content) + } catch (e) { + fixture = content + } + fixtures[name].push(fixture) + const namePath = name.split('.')[0] + const fixturePath = join(filePath, `./${namePath}/__fixtures__`); + if(process.env.NODE_ENV !== 'test') { + writeFileSync(join(fixturePath, name), JSON.stringify(fixtures[name],null, 2)); + } +} diff --git a/services/liquid-auth-api-js/tsconfig.json b/services/liquid-auth-api-js/tsconfig.json index e8f4d91..bc05d65 100644 --- a/services/liquid-auth-api-js/tsconfig.json +++ b/services/liquid-auth-api-js/tsconfig.json @@ -2,7 +2,7 @@ "compilerOptions": { "module": "NodeNext", "declaration": true, - "removeComments": true, + "removeComments": false, "emitDecoratorMetadata": true, "experimentalDecorators": true, "allowSyntheticDefaultImports": true, diff --git a/sites/dapp-ui/src/App.tsx b/sites/dapp-ui/src/App.tsx index f324aa2..0f51e13 100644 --- a/sites/dapp-ui/src/App.tsx +++ b/sites/dapp-ui/src/App.tsx @@ -14,6 +14,7 @@ import { Algodv2 } from 'algosdk'; import { AlgodContext } from '@/hooks'; import { SignalClientContext } from '@/hooks/useSignalClient.ts'; import { LinkMessage, SignalClient } from '@liquid/auth-client/signal'; +import { useAddressStore } from '@/store'; const queryClient = new QueryClient(); const algod = new Algodv2( @@ -42,7 +43,7 @@ const router = createHashRouter([ ]); export default function ProviderApp() { const [dataChannel, setDataChannel] = useState(null); - + const setAddress = useAddressStore((state) => state.setAddress); const [mode, setMode] = useState<'light' | 'dark'>( window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)') ? 'dark' @@ -84,6 +85,19 @@ export default function ProviderApp() { console.log('SignalClient datachannel', dc); setDataChannel(dc); } + client.on('offer-description', (description) => { + console.log({ 'offer-description': description }); + }); + client.on('offer-candidate', (candidate) => { + console.log({ 'offer-candidate': candidate }); + }); + + client.on('answer-description', (description) => { + console.log({ 'answer-description': description }); + }); + client.on('answer-candidate', (candidate) => { + console.log({ 'answer-candidate': candidate }); + }); client.on('data-channel', handleDataChannel); function handleSocketConnect() { console.log('Socket Connect'); @@ -91,7 +105,8 @@ export default function ProviderApp() { } client.on('connect', handleSocketConnect); function handleLinkMessage(msg: LinkMessage) { - window.localStorage.setItem('wallet', JSON.stringify(msg.wallet)); + console.log('LinkMessage', msg); + setAddress(msg.wallet); } client.on('link-message', handleLinkMessage); diff --git a/sites/dapp-ui/src/Layout.tsx b/sites/dapp-ui/src/Layout.tsx index a8fb89a..2fd4c6e 100644 --- a/sites/dapp-ui/src/Layout.tsx +++ b/sites/dapp-ui/src/Layout.tsx @@ -26,7 +26,7 @@ export default function Layout({ children }: PropsWithChildren) { }; const breadcrumbs = ['/', '/connected']; const index = breadcrumbs.indexOf(location.pathname); - console.log(index); + return ( <> { - if (typeof address === 'undefined') { - return; - } - return fetch( - `https://api.nf.domains/nfd/lookup?address=${address}&view=tiny&allowUnverified=true`, - ).then(async (r) => { - if (r.ok) { - const data = await r.json(); - return data[address].name; - } else { - if (r.status === 404) { - return greaterThanMid - ? address - : `${address.slice(0, 5)}...${address.slice(-5)}`; - } - throw new Error('Failed to fetch address'); - } - }); - }, - }); -} diff --git a/sites/dapp-ui/src/pages/connected.tsx b/sites/dapp-ui/src/pages/connected.tsx index 618db43..cf48daf 100644 --- a/sites/dapp-ui/src/pages/connected.tsx +++ b/sites/dapp-ui/src/pages/connected.tsx @@ -13,14 +13,13 @@ import { useAccountInfo } from '@/hooks/useAccountInfo.ts'; import FormControl from '@mui/material/FormControl'; import { Box, CircularProgress, Input, Slider } from '@mui/material'; import Typography from '@mui/material/Typography'; -import { useMessageStore } from '../store.ts'; +import { useAddressStore, useMessageStore } from '../store.ts'; import { useNavigate } from 'react-router-dom'; export function ConnectedPage() { const navigate = useNavigate(); const algod = useAlgod(); - const walletStr = window.localStorage.getItem('wallet'); - const wallet = walletStr ? JSON.parse(walletStr) : null; + const wallet = useAddressStore((state) => state.address); const [txn, setTxn] = useState(null); // const datachannel = useDataChannel('remote', peerConnection); const accountInfo = useAccountInfo(wallet, 3000); @@ -45,6 +44,7 @@ export function ConnectedPage() { async function handleMessage() { if (!txn) return; const message = JSON.parse(event.data); + if (message.type === 'credential') localStorage['credId'] = message.id; if (message.type !== 'transaction-signature') return; if (txn.txID() !== message.txId) throw new Error('Invalid txId'); @@ -80,8 +80,8 @@ export function ConnectedPage() { }, [txn, datachannel, isWaitingForSignature]); useEffect(() => { - if (!datachannel) navigate('/'); - }, [datachannel]); + if (!datachannel || wallet === '') navigate('/'); + }, [datachannel, wallet]); if (accountInfo.data && accountInfo.data.amount === 0) { return ( diff --git a/sites/dapp-ui/src/pages/home.tsx b/sites/dapp-ui/src/pages/home.tsx index c11dff3..ec49c5f 100644 --- a/sites/dapp-ui/src/pages/home.tsx +++ b/sites/dapp-ui/src/pages/home.tsx @@ -5,13 +5,15 @@ import CardActions from '@mui/material/CardActions'; import Card from '@mui/material/Card'; import Button from '@mui/material/Button'; -import { useNavigate } from 'react-router-dom'; import { ConnectModal } from '@/components/ConnectModal'; import { assertion } from '@liquid/auth-client/assertion'; +import { useState } from 'react'; export function HomePage() { const credId = window.localStorage.getItem('credId'); - const navigate = useNavigate(); + const [showLogin, setShowLogin] = useState( + typeof credId === 'string' || false, + ); return ( - {credId && ( + {showLogin && credId && (