Merge branch 'staging' into feat/reverse-trials-fresh
This commit is contained in:
302
.github/workflows/test.yml
vendored
302
.github/workflows/test.yml
vendored
@@ -1,173 +1,173 @@
|
||||
name: Run Autumn Tests
|
||||
# name: Run Autumn Tests
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
env:
|
||||
DATABASE_URL: ${{ secrets.SUPABASE_URL }}
|
||||
UNIT_TEST_AUTUMN_SECRET_KEY: ${{ secrets.AUTUMN_KEY }}
|
||||
REDIS_URL: redis://localhost:6379
|
||||
ENCRYPTION_IV: ${{ secrets.ENCRYPTION_IV }}
|
||||
ENCRYPTION_PASSWORD: ${{ secrets.ENCRYPTION_PASSWORD }}
|
||||
TESTS_ORG: ${{ secrets.TESTS_ORG }}
|
||||
TESTS_ORG_ID: ${{ secrets.TESTS_ORG_ID }}
|
||||
LOCALTUNNEL_RESERVED_KEY: ${{ secrets.LOCALTUNNEL_RESERVED_KEY }}
|
||||
STRIPE_WEBHOOK_URL: ${{ secrets.STRIPE_WEBHOOK_URL }}
|
||||
BETTER_AUTH_SECRET: ${{ secrets.BETTER_AUTH_SECRET }}
|
||||
HYPERBROWSER_API_KEY: ${{ secrets.HYPERBROWSER_API_KEY }}
|
||||
STRIPE_TEST_KEY: ${{ secrets.STRIPE_TEST_KEY }}
|
||||
# on:
|
||||
# workflow_dispatch:
|
||||
# push:
|
||||
# branches:
|
||||
# - main
|
||||
# env:
|
||||
# DATABASE_URL: ${{ secrets.SUPABASE_URL }}
|
||||
# UNIT_TEST_AUTUMN_SECRET_KEY: ${{ secrets.AUTUMN_KEY }}
|
||||
# REDIS_URL: redis://localhost:6379
|
||||
# ENCRYPTION_IV: ${{ secrets.ENCRYPTION_IV }}
|
||||
# ENCRYPTION_PASSWORD: ${{ secrets.ENCRYPTION_PASSWORD }}
|
||||
# TESTS_ORG: ${{ secrets.TESTS_ORG }}
|
||||
# TESTS_ORG_ID: ${{ secrets.TESTS_ORG_ID }}
|
||||
# LOCALTUNNEL_RESERVED_KEY: ${{ secrets.LOCALTUNNEL_RESERVED_KEY }}
|
||||
# STRIPE_WEBHOOK_URL: ${{ secrets.STRIPE_WEBHOOK_URL }}
|
||||
# BETTER_AUTH_SECRET: ${{ secrets.BETTER_AUTH_SECRET }}
|
||||
# HYPERBROWSER_API_KEY: ${{ secrets.HYPERBROWSER_API_KEY }}
|
||||
# STRIPE_TEST_KEY: ${{ secrets.STRIPE_TEST_KEY }}
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: blacksmith-4vcpu-ubuntu-2404
|
||||
# runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4.2.2
|
||||
# jobs:
|
||||
# test:
|
||||
# runs-on: blacksmith-4vcpu-ubuntu-2404
|
||||
# # runs-on: ubuntu-latest
|
||||
# steps:
|
||||
# - name: Checkout
|
||||
# uses: actions/checkout@v4.2.2
|
||||
|
||||
- name: Set up bun
|
||||
uses: oven-sh/setup-bun@v2
|
||||
# - name: Set up bun
|
||||
# uses: oven-sh/setup-bun@v2
|
||||
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '22'
|
||||
# - name: Set up Node.js
|
||||
# uses: actions/setup-node@v4
|
||||
# with:
|
||||
# node-version: '22'
|
||||
|
||||
- name: Install dependencies
|
||||
# run: bun install --no-frozen-lockfile
|
||||
run: bun install
|
||||
# - name: Install dependencies
|
||||
# # run: bun install --no-frozen-lockfile
|
||||
# run: bun install
|
||||
|
||||
- name: Setup CI
|
||||
run: bun run setupci
|
||||
# - name: Setup CI
|
||||
# run: bun run setupci
|
||||
|
||||
# - name: Install Chrome Dependencies
|
||||
# run: |
|
||||
# sudo apt-get update
|
||||
# sudo apt-get install -y \
|
||||
# ca-certificates \
|
||||
# fonts-liberation \
|
||||
# libasound2 \
|
||||
# libatk-bridge2.0-0 \
|
||||
# libatk1.0-0 \
|
||||
# libc6 \
|
||||
# libcairo2 \
|
||||
# libcups2 \
|
||||
# libdbus-1-3 \
|
||||
# libexpat1 \
|
||||
# libfontconfig1 \
|
||||
# libgbm1 \
|
||||
# libgcc1 \
|
||||
# libgdk-pixbuf2.0-0 \
|
||||
# libglib2.0-0 \
|
||||
# libgtk-3-0 \
|
||||
# libnspr4 \
|
||||
# libnss3 \
|
||||
# libpango-1.0-0 \
|
||||
# libpangocairo-1.0-0 \
|
||||
# libstdc++6 \
|
||||
# libx11-6 \
|
||||
# libx11-xcb1 \
|
||||
# libxcb1 \
|
||||
# libxcomposite1 \
|
||||
# libxcursor1 \
|
||||
# libxdamage1 \
|
||||
# libxext6 \
|
||||
# libxfixes3 \
|
||||
# libxi6 \
|
||||
# libxrandr2 \
|
||||
# libxrender1 \
|
||||
# libxss1 \
|
||||
# libxtst6 \
|
||||
# lsb-release \
|
||||
# wget \
|
||||
# xdg-utils
|
||||
# # - name: Install Chrome Dependencies
|
||||
# # run: |
|
||||
# # sudo apt-get update
|
||||
# # sudo apt-get install -y \
|
||||
# # ca-certificates \
|
||||
# # fonts-liberation \
|
||||
# # libasound2 \
|
||||
# # libatk-bridge2.0-0 \
|
||||
# # libatk1.0-0 \
|
||||
# # libc6 \
|
||||
# # libcairo2 \
|
||||
# # libcups2 \
|
||||
# # libdbus-1-3 \
|
||||
# # libexpat1 \
|
||||
# # libfontconfig1 \
|
||||
# # libgbm1 \
|
||||
# # libgcc1 \
|
||||
# # libgdk-pixbuf2.0-0 \
|
||||
# # libglib2.0-0 \
|
||||
# # libgtk-3-0 \
|
||||
# # libnspr4 \
|
||||
# # libnss3 \
|
||||
# # libpango-1.0-0 \
|
||||
# # libpangocairo-1.0-0 \
|
||||
# # libstdc++6 \
|
||||
# # libx11-6 \
|
||||
# # libx11-xcb1 \
|
||||
# # libxcb1 \
|
||||
# # libxcomposite1 \
|
||||
# # libxcursor1 \
|
||||
# # libxdamage1 \
|
||||
# # libxext6 \
|
||||
# # libxfixes3 \
|
||||
# # libxi6 \
|
||||
# # libxrandr2 \
|
||||
# # libxrender1 \
|
||||
# # libxss1 \
|
||||
# # libxtst6 \
|
||||
# # lsb-release \
|
||||
# # wget \
|
||||
# # xdg-utils
|
||||
|
||||
# - name: Install Chrome
|
||||
# run: |
|
||||
# cd server/
|
||||
# npx puppeteer browsers install chrome
|
||||
# # - name: Install Chrome
|
||||
# # run: |
|
||||
# # cd server/
|
||||
# # npx puppeteer browsers install chrome
|
||||
|
||||
- name: Create .env file
|
||||
run: |
|
||||
echo "Creating .env file..."
|
||||
echo "DATABASE_URL=${{ env.DATABASE_URL }}" >> .env
|
||||
echo "UNIT_TEST_AUTUMN_SECRET_KEY=${{ env.UNIT_TEST_AUTUMN_SECRET_KEY }}" >> .env
|
||||
echo "REDIS_URL=${{ env.REDIS_URL }}" >> .env
|
||||
echo "ENCRYPTION_IV=${{ env.ENCRYPTION_IV }}" >> .env
|
||||
echo "ENCRYPTION_PASSWORD=${{ env.ENCRYPTION_PASSWORD }}" >> .env
|
||||
echo "TESTS_ORG=${{ env.TESTS_ORG }}" >> .env
|
||||
echo "TESTS_ORG_ID=${{ env.TESTS_ORG_ID }}" >> .env
|
||||
echo "LOCALTUNNEL_RESERVED_KEY=${{ env.LOCALTUNNEL_RESERVED_KEY }}" >> .env
|
||||
echo "BETTER_AUTH_SECRET=${{ env.BETTER_AUTH_SECRET }}" >> .env
|
||||
echo "HYPERBROWSER_API_KEY=${{ env.HYPERBROWSER_API_KEY }}" >> .env
|
||||
echo "STRIPE_TEST_KEY=${{ env.STRIPE_TEST_KEY }}" >> .env
|
||||
echo "STRIPE_WEBHOOK_URL=${{ env.STRIPE_WEBHOOK_URL }}" >> .env
|
||||
cat .env
|
||||
# - name: Create .env file
|
||||
# run: |
|
||||
# echo "Creating .env file..."
|
||||
# echo "DATABASE_URL=${{ env.DATABASE_URL }}" >> .env
|
||||
# echo "UNIT_TEST_AUTUMN_SECRET_KEY=${{ env.UNIT_TEST_AUTUMN_SECRET_KEY }}" >> .env
|
||||
# echo "REDIS_URL=${{ env.REDIS_URL }}" >> .env
|
||||
# echo "ENCRYPTION_IV=${{ env.ENCRYPTION_IV }}" >> .env
|
||||
# echo "ENCRYPTION_PASSWORD=${{ env.ENCRYPTION_PASSWORD }}" >> .env
|
||||
# echo "TESTS_ORG=${{ env.TESTS_ORG }}" >> .env
|
||||
# echo "TESTS_ORG_ID=${{ env.TESTS_ORG_ID }}" >> .env
|
||||
# echo "LOCALTUNNEL_RESERVED_KEY=${{ env.LOCALTUNNEL_RESERVED_KEY }}" >> .env
|
||||
# echo "BETTER_AUTH_SECRET=${{ env.BETTER_AUTH_SECRET }}" >> .env
|
||||
# echo "HYPERBROWSER_API_KEY=${{ env.HYPERBROWSER_API_KEY }}" >> .env
|
||||
# echo "STRIPE_TEST_KEY=${{ env.STRIPE_TEST_KEY }}" >> .env
|
||||
# echo "STRIPE_WEBHOOK_URL=${{ env.STRIPE_WEBHOOK_URL }}" >> .env
|
||||
# cat .env
|
||||
|
||||
- name: Build shared
|
||||
run: |
|
||||
cd shared
|
||||
bun run build
|
||||
# - name: Build shared
|
||||
# run: |
|
||||
# cd shared
|
||||
# bun run build
|
||||
|
||||
- name: Startup server
|
||||
run: sudo docker compose -f docker-compose.ci.yml up --detach
|
||||
# - name: Startup server
|
||||
# run: sudo docker compose -f docker-compose.ci.yml up --detach
|
||||
|
||||
- name: Wait for server to be ready
|
||||
run: |
|
||||
echo "Waiting for server to start..."
|
||||
timeout 120s bash -c 'until curl -s --fail http://localhost:8080; do echo "Waiting..."; sleep 2; done'
|
||||
echo "Server is up!"
|
||||
# - name: Wait for server to be ready
|
||||
# run: |
|
||||
# echo "Waiting for server to start..."
|
||||
# timeout 120s bash -c 'until curl -s --fail http://localhost:8080; do echo "Waiting..."; sleep 2; done'
|
||||
# echo "Server is up!"
|
||||
|
||||
- name: Ping Local Tunnel
|
||||
run: |
|
||||
echo "Pinging Local Tunnel..."
|
||||
curl https://askjdnaslkjdalkjen.loca.lt
|
||||
echo "Local Tunnel pinged!"
|
||||
# - name: Ping Local Tunnel
|
||||
# run: |
|
||||
# echo "Pinging Local Tunnel..."
|
||||
# curl https://askjdnaslkjdalkjen.loca.lt
|
||||
# echo "Local Tunnel pinged!"
|
||||
|
||||
|
||||
- name: Run G2 tests
|
||||
run: |
|
||||
cd server/
|
||||
chmod +x ./shell/g2.sh
|
||||
./shell/g2.sh setup
|
||||
# - name: Run G2 tests
|
||||
# run: |
|
||||
# cd server/
|
||||
# chmod +x ./shell/g2.sh
|
||||
# ./shell/g2.sh setup
|
||||
|
||||
- name: Run G3 tests
|
||||
run: |
|
||||
cd server/
|
||||
chmod +x ./shell/g3.sh
|
||||
./shell/g3.sh
|
||||
# - name: Run G3 tests
|
||||
# run: |
|
||||
# cd server/
|
||||
# chmod +x ./shell/g3.sh
|
||||
# ./shell/g3.sh
|
||||
|
||||
- name: Run G4 tests
|
||||
run: |
|
||||
cd server/
|
||||
chmod +x ./shell/g4.sh
|
||||
./shell/g4.sh
|
||||
# - name: Run G4 tests
|
||||
# run: |
|
||||
# cd server/
|
||||
# chmod +x ./shell/g4.sh
|
||||
# ./shell/g4.sh
|
||||
|
||||
- name: Run G5 tests
|
||||
run: |
|
||||
cd server/
|
||||
chmod +x ./shell/g5.sh
|
||||
./shell/g4.sh
|
||||
# - name: Run G5 tests
|
||||
# run: |
|
||||
# cd server/
|
||||
# chmod +x ./shell/g5.sh
|
||||
# ./shell/g4.sh
|
||||
|
||||
# - name: Run G4 tests
|
||||
# run: |
|
||||
# cd server/
|
||||
# chmod +x ./shell/g4.sh
|
||||
# ./shell/g4.sh
|
||||
# # - name: Run G4 tests
|
||||
# # run: |
|
||||
# # cd server/
|
||||
# # chmod +x ./shell/g4.sh
|
||||
# # ./shell/g4.sh
|
||||
|
||||
# - name: Message
|
||||
# run:
|
||||
# echo "We're all setup!"
|
||||
# # - name: Message
|
||||
# # run:
|
||||
# # echo "We're all setup!"
|
||||
|
||||
# - name: Check logs
|
||||
# if: always()
|
||||
# run: sudo docker compose -f docker-compose.ci.yml logs server
|
||||
- name: Check logs
|
||||
if: always()
|
||||
run: sudo docker compose -f docker-compose.ci.yml logs localtunnel
|
||||
# # - name: Check logs
|
||||
# # if: always()
|
||||
# # run: sudo docker compose -f docker-compose.ci.yml logs server
|
||||
# - name: Check logs
|
||||
# if: always()
|
||||
# run: sudo docker compose -f docker-compose.ci.yml logs localtunnel
|
||||
|
||||
- name: Close Docker Containers
|
||||
if: always()
|
||||
run: sudo docker compose -f docker-compose.ci.yml down
|
||||
# - name: Close Docker Containers
|
||||
# if: always()
|
||||
# run: sudo docker compose -f docker-compose.ci.yml down
|
||||
352
bun.lock
352
bun.lock
@@ -47,7 +47,7 @@
|
||||
"@supabase/supabase-js": "^2.46.2",
|
||||
"@upstash/redis": "^1.35.1",
|
||||
"ai": "^4.3.10",
|
||||
"autumn-js": "^0.1.4",
|
||||
"autumn-js": "^0.1.8",
|
||||
"axios": "^1.8.3",
|
||||
"better-auth": "^1.2.9",
|
||||
"body-parser": "^1.20.3",
|
||||
@@ -253,15 +253,15 @@
|
||||
|
||||
"@babel/compat-data": ["@babel/compat-data@7.28.0", "", {}, "sha512-60X7qkglvrap8mn1lh2ebxXdZYtUcpd7gsmy9kLaBJ4i/WdY8PqTSdxyA8qraikqKQK5C1KRBKXqznrVapyNaw=="],
|
||||
|
||||
"@babel/core": ["@babel/core@7.28.0", "", { "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.28.0", "@babel/helper-compilation-targets": "^7.27.2", "@babel/helper-module-transforms": "^7.27.3", "@babel/helpers": "^7.27.6", "@babel/parser": "^7.28.0", "@babel/template": "^7.27.2", "@babel/traverse": "^7.28.0", "@babel/types": "^7.28.0", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", "json5": "^2.2.3", "semver": "^6.3.1" } }, "sha512-UlLAnTPrFdNGoFtbSXwcGFQBtQZJCNjaN6hQNP3UPvuNXT1i82N26KL3dZeIpNalWywr9IuQuncaAfUaS1g6sQ=="],
|
||||
"@babel/core": ["@babel/core@7.28.3", "", { "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.28.3", "@babel/helper-compilation-targets": "^7.27.2", "@babel/helper-module-transforms": "^7.28.3", "@babel/helpers": "^7.28.3", "@babel/parser": "^7.28.3", "@babel/template": "^7.27.2", "@babel/traverse": "^7.28.3", "@babel/types": "^7.28.2", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", "json5": "^2.2.3", "semver": "^6.3.1" } }, "sha512-yDBHV9kQNcr2/sUr9jghVyz9C3Y5G2zUM2H2lo+9mKv4sFgbA8s8Z9t8D1jiTkGoO/NoIfKMyKWr4s6CN23ZwQ=="],
|
||||
|
||||
"@babel/generator": ["@babel/generator@7.28.0", "", { "dependencies": { "@babel/parser": "^7.28.0", "@babel/types": "^7.28.0", "@jridgewell/gen-mapping": "^0.3.12", "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" } }, "sha512-lJjzvrbEeWrhB4P3QBsH7tey117PjLZnDbLiQEKjQ/fNJTjuq4HSqgFA+UNSwZT8D7dxxbnuSBMsa1lrWzKlQg=="],
|
||||
"@babel/generator": ["@babel/generator@7.28.3", "", { "dependencies": { "@babel/parser": "^7.28.3", "@babel/types": "^7.28.2", "@jridgewell/gen-mapping": "^0.3.12", "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" } }, "sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw=="],
|
||||
|
||||
"@babel/helper-annotate-as-pure": ["@babel/helper-annotate-as-pure@7.27.3", "", { "dependencies": { "@babel/types": "^7.27.3" } }, "sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg=="],
|
||||
|
||||
"@babel/helper-compilation-targets": ["@babel/helper-compilation-targets@7.27.2", "", { "dependencies": { "@babel/compat-data": "^7.27.2", "@babel/helper-validator-option": "^7.27.1", "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" } }, "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ=="],
|
||||
|
||||
"@babel/helper-create-class-features-plugin": ["@babel/helper-create-class-features-plugin@7.27.1", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.1", "@babel/helper-member-expression-to-functions": "^7.27.1", "@babel/helper-optimise-call-expression": "^7.27.1", "@babel/helper-replace-supers": "^7.27.1", "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", "@babel/traverse": "^7.27.1", "semver": "^6.3.1" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-QwGAmuvM17btKU5VqXfb+Giw4JcN0hjuufz3DYnpeVDvZLAObloM77bhMXiqry3Iio+Ai4phVRDwl6WU10+r5A=="],
|
||||
"@babel/helper-create-class-features-plugin": ["@babel/helper-create-class-features-plugin@7.28.3", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.3", "@babel/helper-member-expression-to-functions": "^7.27.1", "@babel/helper-optimise-call-expression": "^7.27.1", "@babel/helper-replace-supers": "^7.27.1", "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", "@babel/traverse": "^7.28.3", "semver": "^6.3.1" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-V9f6ZFIYSLNEbuGA/92uOvYsGCJNsuA8ESZ4ldc09bWk/j8H8TKiPw8Mk1eG6olpnO0ALHJmYfZvF4MEE4gajg=="],
|
||||
|
||||
"@babel/helper-globals": ["@babel/helper-globals@7.28.0", "", {}, "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw=="],
|
||||
|
||||
@@ -269,7 +269,7 @@
|
||||
|
||||
"@babel/helper-module-imports": ["@babel/helper-module-imports@7.27.1", "", { "dependencies": { "@babel/traverse": "^7.27.1", "@babel/types": "^7.27.1" } }, "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w=="],
|
||||
|
||||
"@babel/helper-module-transforms": ["@babel/helper-module-transforms@7.27.3", "", { "dependencies": { "@babel/helper-module-imports": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1", "@babel/traverse": "^7.27.3" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-dSOvYwvyLsWBeIRyOeHXp5vPj5l1I011r52FM1+r1jCERv+aFXYk4whgQccYEGYxK2H3ZAIA8nuPkQ0HaUo3qg=="],
|
||||
"@babel/helper-module-transforms": ["@babel/helper-module-transforms@7.28.3", "", { "dependencies": { "@babel/helper-module-imports": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1", "@babel/traverse": "^7.28.3" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw=="],
|
||||
|
||||
"@babel/helper-optimise-call-expression": ["@babel/helper-optimise-call-expression@7.27.1", "", { "dependencies": { "@babel/types": "^7.27.1" } }, "sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw=="],
|
||||
|
||||
@@ -285,9 +285,9 @@
|
||||
|
||||
"@babel/helper-validator-option": ["@babel/helper-validator-option@7.27.1", "", {}, "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg=="],
|
||||
|
||||
"@babel/helpers": ["@babel/helpers@7.28.2", "", { "dependencies": { "@babel/template": "^7.27.2", "@babel/types": "^7.28.2" } }, "sha512-/V9771t+EgXz62aCcyofnQhGM8DQACbRhvzKFsXKC9QM+5MadF8ZmIm0crDMaz3+o0h0zXfJnd4EhbYbxsrcFw=="],
|
||||
"@babel/helpers": ["@babel/helpers@7.28.3", "", { "dependencies": { "@babel/template": "^7.27.2", "@babel/types": "^7.28.2" } }, "sha512-PTNtvUQihsAsDHMOP5pfobP8C6CM4JWXmP8DrEIt46c3r2bf87Ua1zoqevsMo9g+tWDwgWrFP5EIxuBx5RudAw=="],
|
||||
|
||||
"@babel/parser": ["@babel/parser@7.28.0", "", { "dependencies": { "@babel/types": "^7.28.0" }, "bin": "./bin/babel-parser.js" }, "sha512-jVZGvOxOuNSsuQuLRTh13nU0AogFlw32w/MT+LV6D3sP5WdbW61E77RnkbaO2dUvmPAYrBDJXGn5gGS6tH4j8g=="],
|
||||
"@babel/parser": ["@babel/parser@7.28.3", "", { "dependencies": { "@babel/types": "^7.28.2" }, "bin": "./bin/babel-parser.js" }, "sha512-7+Ey1mAgYqFAx2h0RuoxcQT5+MlG3GTV0TQrgr7/ZliKsm/MNDxVVutlWaziMq7wJNAz8MTqz55XLpWvva6StA=="],
|
||||
|
||||
"@babel/plugin-proposal-private-property-in-object": ["@babel/plugin-proposal-private-property-in-object@7.21.11", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.18.6", "@babel/helper-create-class-features-plugin": "^7.21.0", "@babel/helper-plugin-utils": "^7.20.2", "@babel/plugin-syntax-private-property-in-object": "^7.14.5" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-0QZ8qP/3RLDVBwBFoWAwCtgcDZJVwA5LUJRZU8x2YFfKNuFq161wK3cuGrALu5yiPu+vzwTAg/sMWVNeWeNyaw=="],
|
||||
|
||||
@@ -297,41 +297,41 @@
|
||||
|
||||
"@babel/plugin-transform-react-jsx-source": ["@babel/plugin-transform-react-jsx-source@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw=="],
|
||||
|
||||
"@babel/runtime": ["@babel/runtime@7.28.2", "", {}, "sha512-KHp2IflsnGywDjBWDkR9iEqiWSpc8GIi0lgTT3mOElT0PP1tG26P4tmFI2YvAdzgq9RGyoHZQEIEdZy6Ec5xCA=="],
|
||||
"@babel/runtime": ["@babel/runtime@7.28.3", "", {}, "sha512-9uIQ10o0WGdpP6GDhXcdOJPJuDgFtIDtN/9+ArJQ2NAfAmiuhTQdzkaTGR33v43GYS2UrSA0eX2pPPHoFVvpxA=="],
|
||||
|
||||
"@babel/template": ["@babel/template@7.27.2", "", { "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/parser": "^7.27.2", "@babel/types": "^7.27.1" } }, "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw=="],
|
||||
|
||||
"@babel/traverse": ["@babel/traverse@7.28.0", "", { "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.28.0", "@babel/helper-globals": "^7.28.0", "@babel/parser": "^7.28.0", "@babel/template": "^7.27.2", "@babel/types": "^7.28.0", "debug": "^4.3.1" } }, "sha512-mGe7UK5wWyh0bKRfupsUchrQGqvDbZDbKJw+kcRGSmdHVYrv+ltd0pnpDTVpiTqnaBru9iEvA8pz8W46v0Amwg=="],
|
||||
"@babel/traverse": ["@babel/traverse@7.28.3", "", { "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.28.3", "@babel/helper-globals": "^7.28.0", "@babel/parser": "^7.28.3", "@babel/template": "^7.27.2", "@babel/types": "^7.28.2", "debug": "^4.3.1" } }, "sha512-7w4kZYHneL3A6NP2nxzHvT3HCZ7puDZZjFMqDpBPECub79sTtSO5CGXDkKrTQq8ksAwfD/XI2MRFX23njdDaIQ=="],
|
||||
|
||||
"@babel/types": ["@babel/types@7.28.2", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" } }, "sha512-ruv7Ae4J5dUYULmeXw1gmb7rYRz57OWCPM57pHojnLq/3Z1CK2lNSLTCVjxVk1F/TZHwOZZrOWi0ur95BbLxNQ=="],
|
||||
|
||||
"@better-auth/stripe": ["@better-auth/stripe@1.3.4", "", { "dependencies": { "better-auth": "^1.3.4", "zod": "^4.0.0" } }, "sha512-sFHEOvLDwKe0ZYxqNTlfoshekiXkomnAcOEH7ARq0r7XImpPjpUR+GHc9+0CGTXTCn3LYljmBt0paTX1rhRNjw=="],
|
||||
"@better-auth/stripe": ["@better-auth/stripe@1.3.6", "", { "dependencies": { "better-auth": "^1.3.6" }, "peerDependencies": { "zod": "^3.25.0 || ^4.0.0" } }, "sha512-f4tsO5DLEOS1FhzpEE5QxtYjgxaAluy9ut9QsBp5uXx3dh38iFUOfrUuJTwxo2EdoqsEiRyIcFxH9ikMuzPrpQ=="],
|
||||
|
||||
"@better-auth/utils": ["@better-auth/utils@0.2.5", "", { "dependencies": { "typescript": "^5.8.2", "uncrypto": "^0.1.3" } }, "sha512-uI2+/8h/zVsH8RrYdG8eUErbuGBk16rZKQfz8CjxQOyCE6v7BqFYEbFwvOkvl1KbUdxhqOnXp78+uE5h8qVEgQ=="],
|
||||
"@better-auth/utils": ["@better-auth/utils@0.2.6", "", { "dependencies": { "uncrypto": "^0.1.3" } }, "sha512-3y/vaL5Ox33dBwgJ6ub3OPkVqr6B5xL2kgxNHG8eHZuryLyG/4JSPGqjbdRSgjuy9kALUZYDFl+ORIAxlWMSuA=="],
|
||||
|
||||
"@better-fetch/fetch": ["@better-fetch/fetch@1.1.18", "", {}, "sha512-rEFOE1MYIsBmoMJtQbl32PGHHXuG2hDxvEd7rUHE0vCBoFQVSDqaVs9hkZEtHCxRoY+CljXKFCOuJ8uxqw1LcA=="],
|
||||
|
||||
"@browserbasehq/sdk": ["@browserbasehq/sdk@2.6.0", "", { "dependencies": { "@types/node": "^18.11.18", "@types/node-fetch": "^2.6.4", "abort-controller": "^3.0.0", "agentkeepalive": "^4.2.1", "form-data-encoder": "1.7.2", "formdata-node": "^4.3.2", "node-fetch": "^2.6.7" } }, "sha512-83iXP5D7xMm8Wyn66TUaUrgoByCmAJuoMoZQI3sGg3JAiMlTfnCIMqyVBoNSaItaPIkaCnrsj6LiusmXV2X9YA=="],
|
||||
|
||||
"@clerk/backend": ["@clerk/backend@2.6.3", "", { "dependencies": { "@clerk/shared": "^3.18.0", "@clerk/types": "^4.73.0", "cookie": "1.0.2", "standardwebhooks": "^1.0.0", "tslib": "2.8.1" } }, "sha512-x73eu/zDMc1E2YvvW+KW55B6BOfiUrgFhSJngBsZJ6+W5hWZph+XeCS7oEcZfhvQyUcb9M6tqM2R1w7htNgh1Q=="],
|
||||
"@clerk/backend": ["@clerk/backend@2.9.1", "", { "dependencies": { "@clerk/shared": "^3.21.0", "@clerk/types": "^4.78.0", "cookie": "1.0.2", "standardwebhooks": "^1.0.0", "tslib": "2.8.1" } }, "sha512-ZRvy4cHpCrOORtyB3xixifek5/Tsc+X5pkC4vVBrZyqntcRsqhO58eSwb4O4rba6gE9UpVhTYnP1+DVLLiyTJw=="],
|
||||
|
||||
"@clerk/clerk-react": ["@clerk/clerk-react@5.39.0", "", { "dependencies": { "@clerk/shared": "^3.18.0", "@clerk/types": "^4.73.0", "tslib": "2.8.1" }, "peerDependencies": { "react": "^18.0.0 || ^19.0.0 || ^19.0.0-0", "react-dom": "^18.0.0 || ^19.0.0 || ^19.0.0-0" } }, "sha512-c1GJMj8wrzFrT3BbvZ4JwYY91BAY1M4yMypaAs3UNvtU0dDze7bmUVs02eW+z0GgaEQbGBVO4f5ru/pBXCGSKA=="],
|
||||
"@clerk/clerk-react": ["@clerk/clerk-react@5.42.1", "", { "dependencies": { "@clerk/shared": "^3.21.0", "@clerk/types": "^4.78.0", "tslib": "2.8.1" }, "peerDependencies": { "react": "^18.0.0 || ^19.0.0 || ^19.0.0-0", "react-dom": "^18.0.0 || ^19.0.0 || ^19.0.0-0" } }, "sha512-6CuOY0QttPU2uimzTTVEEeH0mKo4xQVhaUN8Iqe+Z6nIwYLOTa2w4Lk8wAqEQHWbd1WBOAkP3b+7c/QToWTH7A=="],
|
||||
|
||||
"@clerk/express": ["@clerk/express@1.7.16", "", { "dependencies": { "@clerk/backend": "^2.6.3", "@clerk/shared": "^3.18.0", "@clerk/types": "^4.73.0", "tslib": "2.8.1" }, "peerDependencies": { "express": "^4.17.0 || ^5.0.0" } }, "sha512-T+Gw0vjRl9gRG1aEFfJVf3EQ9r6jfHtvOq9NU4q64GrsgvCZmvhjsx514sx3mqKfXM5CzFnT5biUpNwY27aAwQ=="],
|
||||
"@clerk/express": ["@clerk/express@1.7.21", "", { "dependencies": { "@clerk/backend": "^2.9.1", "@clerk/shared": "^3.21.0", "@clerk/types": "^4.78.0", "tslib": "2.8.1" }, "peerDependencies": { "express": "^4.17.0 || ^5.0.0" } }, "sha512-ALtBBhaYU+gfRoJp25hC3OntbNNgcrvLSyIYVShSCQ8gmyFjrJe/u6wb2PJalKtiE0SJUZPCAPCr8QpWSXEIsg=="],
|
||||
|
||||
"@clerk/shared": ["@clerk/shared@3.18.0", "", { "dependencies": { "@clerk/types": "^4.73.0", "dequal": "2.0.3", "glob-to-regexp": "0.4.1", "js-cookie": "3.0.5", "std-env": "^3.9.0", "swr": "2.3.4" }, "peerDependencies": { "react": "^18.0.0 || ^19.0.0 || ^19.0.0-0", "react-dom": "^18.0.0 || ^19.0.0 || ^19.0.0-0" }, "optionalPeers": ["react", "react-dom"] }, "sha512-QGYbtPfJEp66AgaI0JtiRX04ejoUI8SmqUqqbAm3UXAeUAsKOyXoNbghNal97X7qeq1vPRRiDugK5B9WYN69uA=="],
|
||||
"@clerk/shared": ["@clerk/shared@3.21.0", "", { "dependencies": { "@clerk/types": "^4.78.0", "dequal": "2.0.3", "glob-to-regexp": "0.4.1", "js-cookie": "3.0.5", "std-env": "^3.9.0", "swr": "2.3.4" }, "peerDependencies": { "react": "^18.0.0 || ^19.0.0 || ^19.0.0-0", "react-dom": "^18.0.0 || ^19.0.0 || ^19.0.0-0" }, "optionalPeers": ["react", "react-dom"] }, "sha512-BlIjPLsw2ral0V2sDDTNxoSK3SLLT6tfKiTJG2I3vQILnrGPEwkiEaMY1+bJtOze7EHdpP2KSsTzzjFTP1UDOg=="],
|
||||
|
||||
"@clerk/types": ["@clerk/types@4.73.0", "", { "dependencies": { "csstype": "3.1.3" } }, "sha512-SFM29RFVqs0KyTds3F7s7DBYNoqeBDSZiWuso/WCgfQVI4H3j0gI+0BdBEiqwCILXr4jKBG2srDmzP5FVvx8Hg=="],
|
||||
"@clerk/types": ["@clerk/types@4.78.0", "", { "dependencies": { "csstype": "3.1.3" } }, "sha512-wj52aLAH8RrZmHSNTNJIvxwyCuBMNRP2THOshFwpt0Vg62GQi6NtMLRqNH3Pc5y+zrg42SzLiO31PTNZh3ddpQ=="],
|
||||
|
||||
"@clickhouse/client": ["@clickhouse/client@1.12.0", "", { "dependencies": { "@clickhouse/client-common": "1.12.0" } }, "sha512-vJUSX8THhTzlVn0WxPukVjOgNRaSoY02ubQkB0LpqNoHFxXuF5jQZZAYvGZWpBGbYQ/4gfPrqu8g4TX5UKeNxA=="],
|
||||
"@clickhouse/client": ["@clickhouse/client@1.12.1", "", { "dependencies": { "@clickhouse/client-common": "1.12.1" } }, "sha512-7ORY85rphRazqHzImNXMrh4vsaPrpetFoTWpZYueCO2bbO6PXYDXp/GQ4DgxnGIqbWB/Di1Ai+Xuwq2o7DJ36A=="],
|
||||
|
||||
"@clickhouse/client-common": ["@clickhouse/client-common@1.12.0", "", {}, "sha512-cyI4n7u9jK30d9q1q0ceQ7IwJ/MtTs5HxoQfc8yHpN+ok5wqaU2jAtq5hpa1z7C7sS1pDy/ZOFmOzg1v1F683g=="],
|
||||
"@clickhouse/client-common": ["@clickhouse/client-common@1.12.1", "", {}, "sha512-ccw1N6hB4+MyaAHIaWBwGZ6O2GgMlO99FlMj0B0UEGfjxM9v5dYVYql6FpP19rMwrVAroYs/IgX2vyZEBvzQLg=="],
|
||||
|
||||
"@colors/colors": ["@colors/colors@1.6.0", "", {}, "sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA=="],
|
||||
|
||||
"@cspotcode/source-map-support": ["@cspotcode/source-map-support@0.8.1", "", { "dependencies": { "@jridgewell/trace-mapping": "0.3.9" } }, "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw=="],
|
||||
|
||||
"@date-fns/tz": ["@date-fns/tz@1.3.1", "", {}, "sha512-LnBOyuj+piItX/D5BWBSckBsuZyOt7Jg2obGNiObq7qjl1A2/8F+i4RS8/MmkSdnw6hOe6afrJLCWrUWZw5Mlw=="],
|
||||
"@date-fns/tz": ["@date-fns/tz@1.4.1", "", {}, "sha512-P5LUNhtbj6YfI3iJjw5EL9eUAG6OitD0W3fWQcpQjDRc/QIsL0tRNuO1PcDvPccWL1fSTXXdE1ds+l95DV/OFA=="],
|
||||
|
||||
"@date-fns/utc": ["@date-fns/utc@2.1.1", "", {}, "sha512-SlJDfG6RPeEX8wEVv6ZB3kak4MmbtyiI2qX/5zuKdordbrhB/iaJ58GVMZgJ6P1sJaM1gMgENFYYeg1JWrCFrA=="],
|
||||
|
||||
@@ -347,57 +347,57 @@
|
||||
|
||||
"@esbuild-kit/esm-loader": ["@esbuild-kit/esm-loader@2.6.5", "", { "dependencies": { "@esbuild-kit/core-utils": "^3.3.2", "get-tsconfig": "^4.7.0" } }, "sha512-FxEMIkJKnodyA1OaCUoEvbYRkoZlLZ4d/eXFu9Fh8CbBBgP5EmZxrfTRyN0qpXZ4vOvqnE5YdRdcrmUUXuU+dA=="],
|
||||
|
||||
"@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.8", "", { "os": "aix", "cpu": "ppc64" }, "sha512-urAvrUedIqEiFR3FYSLTWQgLu5tb+m0qZw0NBEasUeo6wuqatkMDaRT+1uABiGXEu5vqgPd7FGE1BhsAIy9QVA=="],
|
||||
"@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.9", "", { "os": "aix", "cpu": "ppc64" }, "sha512-OaGtL73Jck6pBKjNIe24BnFE6agGl+6KxDtTfHhy1HmhthfKouEcOhqpSL64K4/0WCtbKFLOdzD/44cJ4k9opA=="],
|
||||
|
||||
"@esbuild/android-arm": ["@esbuild/android-arm@0.25.8", "", { "os": "android", "cpu": "arm" }, "sha512-RONsAvGCz5oWyePVnLdZY/HHwA++nxYWIX1atInlaW6SEkwq6XkP3+cb825EUcRs5Vss/lGh/2YxAb5xqc07Uw=="],
|
||||
"@esbuild/android-arm": ["@esbuild/android-arm@0.25.9", "", { "os": "android", "cpu": "arm" }, "sha512-5WNI1DaMtxQ7t7B6xa572XMXpHAaI/9Hnhk8lcxF4zVN4xstUgTlvuGDorBguKEnZO70qwEcLpfifMLoxiPqHQ=="],
|
||||
|
||||
"@esbuild/android-arm64": ["@esbuild/android-arm64@0.25.8", "", { "os": "android", "cpu": "arm64" }, "sha512-OD3p7LYzWpLhZEyATcTSJ67qB5D+20vbtr6vHlHWSQYhKtzUYrETuWThmzFpZtFsBIxRvhO07+UgVA9m0i/O1w=="],
|
||||
"@esbuild/android-arm64": ["@esbuild/android-arm64@0.25.9", "", { "os": "android", "cpu": "arm64" }, "sha512-IDrddSmpSv51ftWslJMvl3Q2ZT98fUSL2/rlUXuVqRXHCs5EUF1/f+jbjF5+NG9UffUDMCiTyh8iec7u8RlTLg=="],
|
||||
|
||||
"@esbuild/android-x64": ["@esbuild/android-x64@0.25.8", "", { "os": "android", "cpu": "x64" }, "sha512-yJAVPklM5+4+9dTeKwHOaA+LQkmrKFX96BM0A/2zQrbS6ENCmxc4OVoBs5dPkCCak2roAD+jKCdnmOqKszPkjA=="],
|
||||
"@esbuild/android-x64": ["@esbuild/android-x64@0.25.9", "", { "os": "android", "cpu": "x64" }, "sha512-I853iMZ1hWZdNllhVZKm34f4wErd4lMyeV7BLzEExGEIZYsOzqDWDf+y082izYUE8gtJnYHdeDpN/6tUdwvfiw=="],
|
||||
|
||||
"@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.25.8", "", { "os": "darwin", "cpu": "arm64" }, "sha512-Jw0mxgIaYX6R8ODrdkLLPwBqHTtYHJSmzzd+QeytSugzQ0Vg4c5rDky5VgkoowbZQahCbsv1rT1KW72MPIkevw=="],
|
||||
"@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.25.9", "", { "os": "darwin", "cpu": "arm64" }, "sha512-XIpIDMAjOELi/9PB30vEbVMs3GV1v2zkkPnuyRRURbhqjyzIINwj+nbQATh4H9GxUgH1kFsEyQMxwiLFKUS6Rg=="],
|
||||
|
||||
"@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.25.8", "", { "os": "darwin", "cpu": "x64" }, "sha512-Vh2gLxxHnuoQ+GjPNvDSDRpoBCUzY4Pu0kBqMBDlK4fuWbKgGtmDIeEC081xi26PPjn+1tct+Bh8FjyLlw1Zlg=="],
|
||||
"@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.25.9", "", { "os": "darwin", "cpu": "x64" }, "sha512-jhHfBzjYTA1IQu8VyrjCX4ApJDnH+ez+IYVEoJHeqJm9VhG9Dh2BYaJritkYK3vMaXrf7Ogr/0MQ8/MeIefsPQ=="],
|
||||
|
||||
"@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.25.8", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-YPJ7hDQ9DnNe5vxOm6jaie9QsTwcKedPvizTVlqWG9GBSq+BuyWEDazlGaDTC5NGU4QJd666V0yqCBL2oWKPfA=="],
|
||||
"@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.25.9", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-z93DmbnY6fX9+KdD4Ue/H6sYs+bhFQJNCPZsi4XWJoYblUqT06MQUdBCpcSfuiN72AbqeBFu5LVQTjfXDE2A6Q=="],
|
||||
|
||||
"@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.25.8", "", { "os": "freebsd", "cpu": "x64" }, "sha512-MmaEXxQRdXNFsRN/KcIimLnSJrk2r5H8v+WVafRWz5xdSVmWLoITZQXcgehI2ZE6gioE6HirAEToM/RvFBeuhw=="],
|
||||
"@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.25.9", "", { "os": "freebsd", "cpu": "x64" }, "sha512-mrKX6H/vOyo5v71YfXWJxLVxgy1kyt1MQaD8wZJgJfG4gq4DpQGpgTB74e5yBeQdyMTbgxp0YtNj7NuHN0PoZg=="],
|
||||
|
||||
"@esbuild/linux-arm": ["@esbuild/linux-arm@0.25.8", "", { "os": "linux", "cpu": "arm" }, "sha512-FuzEP9BixzZohl1kLf76KEVOsxtIBFwCaLupVuk4eFVnOZfU+Wsn+x5Ryam7nILV2pkq2TqQM9EZPsOBuMC+kg=="],
|
||||
"@esbuild/linux-arm": ["@esbuild/linux-arm@0.25.9", "", { "os": "linux", "cpu": "arm" }, "sha512-HBU2Xv78SMgaydBmdor38lg8YDnFKSARg1Q6AT0/y2ezUAKiZvc211RDFHlEZRFNRVhcMamiToo7bDx3VEOYQw=="],
|
||||
|
||||
"@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.25.8", "", { "os": "linux", "cpu": "arm64" }, "sha512-WIgg00ARWv/uYLU7lsuDK00d/hHSfES5BzdWAdAig1ioV5kaFNrtK8EqGcUBJhYqotlUByUKz5Qo6u8tt7iD/w=="],
|
||||
"@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.25.9", "", { "os": "linux", "cpu": "arm64" }, "sha512-BlB7bIcLT3G26urh5Dmse7fiLmLXnRlopw4s8DalgZ8ef79Jj4aUcYbk90g8iCa2467HX8SAIidbL7gsqXHdRw=="],
|
||||
|
||||
"@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.25.8", "", { "os": "linux", "cpu": "ia32" }, "sha512-A1D9YzRX1i+1AJZuFFUMP1E9fMaYY+GnSQil9Tlw05utlE86EKTUA7RjwHDkEitmLYiFsRd9HwKBPEftNdBfjg=="],
|
||||
"@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.25.9", "", { "os": "linux", "cpu": "ia32" }, "sha512-e7S3MOJPZGp2QW6AK6+Ly81rC7oOSerQ+P8L0ta4FhVi+/j/v2yZzx5CqqDaWjtPFfYz21Vi1S0auHrap3Ma3A=="],
|
||||
|
||||
"@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.25.8", "", { "os": "linux", "cpu": "none" }, "sha512-O7k1J/dwHkY1RMVvglFHl1HzutGEFFZ3kNiDMSOyUrB7WcoHGf96Sh+64nTRT26l3GMbCW01Ekh/ThKM5iI7hQ=="],
|
||||
"@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.25.9", "", { "os": "linux", "cpu": "none" }, "sha512-Sbe10Bnn0oUAB2AalYztvGcK+o6YFFA/9829PhOCUS9vkJElXGdphz0A3DbMdP8gmKkqPmPcMJmJOrI3VYB1JQ=="],
|
||||
|
||||
"@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.25.8", "", { "os": "linux", "cpu": "none" }, "sha512-uv+dqfRazte3BzfMp8PAQXmdGHQt2oC/y2ovwpTteqrMx2lwaksiFZ/bdkXJC19ttTvNXBuWH53zy/aTj1FgGw=="],
|
||||
"@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.25.9", "", { "os": "linux", "cpu": "none" }, "sha512-YcM5br0mVyZw2jcQeLIkhWtKPeVfAerES5PvOzaDxVtIyZ2NUBZKNLjC5z3/fUlDgT6w89VsxP2qzNipOaaDyA=="],
|
||||
|
||||
"@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.25.8", "", { "os": "linux", "cpu": "ppc64" }, "sha512-GyG0KcMi1GBavP5JgAkkstMGyMholMDybAf8wF5A70CALlDM2p/f7YFE7H92eDeH/VBtFJA5MT4nRPDGg4JuzQ=="],
|
||||
"@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.25.9", "", { "os": "linux", "cpu": "ppc64" }, "sha512-++0HQvasdo20JytyDpFvQtNrEsAgNG2CY1CLMwGXfFTKGBGQT3bOeLSYE2l1fYdvML5KUuwn9Z8L1EWe2tzs1w=="],
|
||||
|
||||
"@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.25.8", "", { "os": "linux", "cpu": "none" }, "sha512-rAqDYFv3yzMrq7GIcen3XP7TUEG/4LK86LUPMIz6RT8A6pRIDn0sDcvjudVZBiiTcZCY9y2SgYX2lgK3AF+1eg=="],
|
||||
"@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.25.9", "", { "os": "linux", "cpu": "none" }, "sha512-uNIBa279Y3fkjV+2cUjx36xkx7eSjb8IvnL01eXUKXez/CBHNRw5ekCGMPM0BcmqBxBcdgUWuUXmVWwm4CH9kg=="],
|
||||
|
||||
"@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.25.8", "", { "os": "linux", "cpu": "s390x" }, "sha512-Xutvh6VjlbcHpsIIbwY8GVRbwoviWT19tFhgdA7DlenLGC/mbc3lBoVb7jxj9Z+eyGqvcnSyIltYUrkKzWqSvg=="],
|
||||
"@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.25.9", "", { "os": "linux", "cpu": "s390x" }, "sha512-Mfiphvp3MjC/lctb+7D287Xw1DGzqJPb/J2aHHcHxflUo+8tmN/6d4k6I2yFR7BVo5/g7x2Monq4+Yew0EHRIA=="],
|
||||
|
||||
"@esbuild/linux-x64": ["@esbuild/linux-x64@0.25.8", "", { "os": "linux", "cpu": "x64" }, "sha512-ASFQhgY4ElXh3nDcOMTkQero4b1lgubskNlhIfJrsH5OKZXDpUAKBlNS0Kx81jwOBp+HCeZqmoJuihTv57/jvQ=="],
|
||||
"@esbuild/linux-x64": ["@esbuild/linux-x64@0.25.9", "", { "os": "linux", "cpu": "x64" }, "sha512-iSwByxzRe48YVkmpbgoxVzn76BXjlYFXC7NvLYq+b+kDjyyk30J0JY47DIn8z1MO3K0oSl9fZoRmZPQI4Hklzg=="],
|
||||
|
||||
"@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.25.8", "", { "os": "none", "cpu": "arm64" }, "sha512-d1KfruIeohqAi6SA+gENMuObDbEjn22olAR7egqnkCD9DGBG0wsEARotkLgXDu6c4ncgWTZJtN5vcgxzWRMzcw=="],
|
||||
"@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.25.9", "", { "os": "none", "cpu": "arm64" }, "sha512-9jNJl6FqaUG+COdQMjSCGW4QiMHH88xWbvZ+kRVblZsWrkXlABuGdFJ1E9L7HK+T0Yqd4akKNa/lO0+jDxQD4Q=="],
|
||||
|
||||
"@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.25.8", "", { "os": "none", "cpu": "x64" }, "sha512-nVDCkrvx2ua+XQNyfrujIG38+YGyuy2Ru9kKVNyh5jAys6n+l44tTtToqHjino2My8VAY6Lw9H7RI73XFi66Cg=="],
|
||||
"@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.25.9", "", { "os": "none", "cpu": "x64" }, "sha512-RLLdkflmqRG8KanPGOU7Rpg829ZHu8nFy5Pqdi9U01VYtG9Y0zOG6Vr2z4/S+/3zIyOxiK6cCeYNWOFR9QP87g=="],
|
||||
|
||||
"@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.25.8", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-j8HgrDuSJFAujkivSMSfPQSAa5Fxbvk4rgNAS5i3K+r8s1X0p1uOO2Hl2xNsGFppOeHOLAVgYwDVlmxhq5h+SQ=="],
|
||||
"@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.25.9", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-YaFBlPGeDasft5IIM+CQAhJAqS3St3nJzDEgsgFixcfZeyGPCd6eJBWzke5piZuZ7CtL656eOSYKk4Ls2C0FRQ=="],
|
||||
|
||||
"@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.25.8", "", { "os": "openbsd", "cpu": "x64" }, "sha512-1h8MUAwa0VhNCDp6Af0HToI2TJFAn1uqT9Al6DJVzdIBAd21m/G0Yfc77KDM3uF3T/YaOgQq3qTJHPbTOInaIQ=="],
|
||||
"@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.25.9", "", { "os": "openbsd", "cpu": "x64" }, "sha512-1MkgTCuvMGWuqVtAvkpkXFmtL8XhWy+j4jaSO2wxfJtilVCi0ZE37b8uOdMItIHz4I6z1bWWtEX4CJwcKYLcuA=="],
|
||||
|
||||
"@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.25.8", "", { "os": "none", "cpu": "arm64" }, "sha512-r2nVa5SIK9tSWd0kJd9HCffnDHKchTGikb//9c7HX+r+wHYCpQrSgxhlY6KWV1nFo1l4KFbsMlHk+L6fekLsUg=="],
|
||||
"@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.25.9", "", { "os": "none", "cpu": "arm64" }, "sha512-4Xd0xNiMVXKh6Fa7HEJQbrpP3m3DDn43jKxMjxLLRjWnRsfxjORYJlXPO4JNcXtOyfajXorRKY9NkOpTHptErg=="],
|
||||
|
||||
"@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.25.8", "", { "os": "sunos", "cpu": "x64" }, "sha512-zUlaP2S12YhQ2UzUfcCuMDHQFJyKABkAjvO5YSndMiIkMimPmxA+BYSBikWgsRpvyxuRnow4nS5NPnf9fpv41w=="],
|
||||
"@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.25.9", "", { "os": "sunos", "cpu": "x64" }, "sha512-WjH4s6hzo00nNezhp3wFIAfmGZ8U7KtrJNlFMRKxiI9mxEK1scOMAaa9i4crUtu+tBr+0IN6JCuAcSBJZfnphw=="],
|
||||
|
||||
"@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.25.8", "", { "os": "win32", "cpu": "arm64" }, "sha512-YEGFFWESlPva8hGL+zvj2z/SaK+pH0SwOM0Nc/d+rVnW7GSTFlLBGzZkuSU9kFIGIo8q9X3ucpZhu8PDN5A2sQ=="],
|
||||
"@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.25.9", "", { "os": "win32", "cpu": "arm64" }, "sha512-mGFrVJHmZiRqmP8xFOc6b84/7xa5y5YvR1x8djzXpJBSv/UsNK6aqec+6JDjConTgvvQefdGhFDAs2DLAds6gQ=="],
|
||||
|
||||
"@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.25.8", "", { "os": "win32", "cpu": "ia32" }, "sha512-hiGgGC6KZ5LZz58OL/+qVVoZiuZlUYlYHNAmczOm7bs2oE1XriPFi5ZHHrS8ACpV5EjySrnoCKmcbQMN+ojnHg=="],
|
||||
"@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.25.9", "", { "os": "win32", "cpu": "ia32" }, "sha512-b33gLVU2k11nVx1OhX3C8QQP6UHQK4ZtN56oFWvVXvz2VkDoe6fbG8TOgHFxEvqeqohmRnIHe5A1+HADk4OQww=="],
|
||||
|
||||
"@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.8", "", { "os": "win32", "cpu": "x64" }, "sha512-cn3Yr7+OaaZq1c+2pe+8yxC8E144SReCQjN6/2ynubzYjvyqZjTXfQJpAcQpsdJq3My7XADANiYGHoFC69pLQw=="],
|
||||
"@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.9", "", { "os": "win32", "cpu": "x64" }, "sha512-PPOl1mi6lpLNQxnGoyAfschAodRFYXJ+9fs6WHXz7CSWKbOqiMZsubC+BQsVKuul+3vKLuwTHsS2c2y9EoKwxQ=="],
|
||||
|
||||
"@eslint-community/eslint-utils": ["@eslint-community/eslint-utils@4.7.0", "", { "dependencies": { "eslint-visitor-keys": "^3.4.3" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw=="],
|
||||
|
||||
@@ -405,17 +405,17 @@
|
||||
|
||||
"@eslint/config-array": ["@eslint/config-array@0.21.0", "", { "dependencies": { "@eslint/object-schema": "^2.1.6", "debug": "^4.3.1", "minimatch": "^3.1.2" } }, "sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ=="],
|
||||
|
||||
"@eslint/config-helpers": ["@eslint/config-helpers@0.3.0", "", {}, "sha512-ViuymvFmcJi04qdZeDc2whTHryouGcDlaxPqarTD0ZE10ISpxGUVZGZDx4w01upyIynL3iu6IXH2bS1NhclQMw=="],
|
||||
"@eslint/config-helpers": ["@eslint/config-helpers@0.3.1", "", {}, "sha512-xR93k9WhrDYpXHORXpxVL5oHj3Era7wo6k/Wd8/IsQNnZUTzkGS29lyn3nAT05v6ltUuTFVCCYDEGfy2Or/sPA=="],
|
||||
|
||||
"@eslint/core": ["@eslint/core@0.15.1", "", { "dependencies": { "@types/json-schema": "^7.0.15" } }, "sha512-bkOp+iumZCCbt1K1CmWf0R9pM5yKpDv+ZXtvSyQpudrI9kuFLp+bM2WOPXImuD/ceQuaa8f5pj93Y7zyECIGNA=="],
|
||||
"@eslint/core": ["@eslint/core@0.15.2", "", { "dependencies": { "@types/json-schema": "^7.0.15" } }, "sha512-78Md3/Rrxh83gCxoUc0EiciuOHsIITzLy53m3d9UyiW8y9Dj2D29FeETqyKA+BRK76tnTp6RXWb3pCay8Oyomg=="],
|
||||
|
||||
"@eslint/eslintrc": ["@eslint/eslintrc@3.3.1", "", { "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", "espree": "^10.0.1", "globals": "^14.0.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" } }, "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ=="],
|
||||
|
||||
"@eslint/js": ["@eslint/js@9.32.0", "", {}, "sha512-BBpRFZK3eX6uMLKz8WxFOBIFFcGFJ/g8XuwjTHCqHROSIsopI+ddn/d5Cfh36+7+e5edVS8dbSHnBNhrLEX0zg=="],
|
||||
"@eslint/js": ["@eslint/js@9.33.0", "", {}, "sha512-5K1/mKhWaMfreBGJTwval43JJmkip0RmM+3+IuqupeSKNC/Th2Kc7ucaq5ovTSra/OOKB9c58CGSz3QMVbWt0A=="],
|
||||
|
||||
"@eslint/object-schema": ["@eslint/object-schema@2.1.6", "", {}, "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA=="],
|
||||
|
||||
"@eslint/plugin-kit": ["@eslint/plugin-kit@0.3.4", "", { "dependencies": { "@eslint/core": "^0.15.1", "levn": "^0.4.1" } }, "sha512-Ul5l+lHEcw3L5+k8POx6r74mxEYKG5kOb6Xpy2gCRW6zweT6TEhAf8vhxGgjhqrd/VO/Dirhsb+1hNpD1ue9hw=="],
|
||||
"@eslint/plugin-kit": ["@eslint/plugin-kit@0.3.5", "", { "dependencies": { "@eslint/core": "^0.15.2", "levn": "^0.4.1" } }, "sha512-Z5kJ+wU3oA7MMIqVR9tyZRtjYPr4OC004Q4Rw7pgOKUOKkJfZ3O24nz3WYfGRpMDNmcOi3TwQOmgm7B7Tpii0w=="],
|
||||
|
||||
"@floating-ui/core": ["@floating-ui/core@1.7.3", "", { "dependencies": { "@floating-ui/utils": "^0.2.10" } }, "sha512-sGnvb5dmrJaKEZ+LDIpguvdX3bDlEllmv4/ClQ9awcmCZrlx5jQyyMWFM5kBI+EyNOCDDiKk8il0zeuX3Zlg/w=="],
|
||||
|
||||
@@ -499,16 +499,18 @@
|
||||
|
||||
"@img/sharp-win32-x64": ["@img/sharp-win32-x64@0.34.3", "", { "os": "win32", "cpu": "x64" }, "sha512-OWwz05d++TxzLEv4VnsTz5CmZ6mI6S05sfQGEMrNrQcOEERbX46332IvE7pO/EUiw7jUrrS40z/M7kPyjfl04g=="],
|
||||
|
||||
"@inquirer/checkbox": ["@inquirer/checkbox@4.2.0", "", { "dependencies": { "@inquirer/core": "^10.1.15", "@inquirer/figures": "^1.0.13", "@inquirer/type": "^3.0.8", "ansi-escapes": "^4.3.2", "yoctocolors-cjs": "^2.1.2" }, "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-fdSw07FLJEU5vbpOPzXo5c6xmMGDzbZE2+niuDHX5N6mc6V0Ebso/q3xiHra4D73+PMsC8MJmcaZKuAAoaQsSA=="],
|
||||
"@inquirer/checkbox": ["@inquirer/checkbox@4.2.1", "", { "dependencies": { "@inquirer/core": "^10.1.15", "@inquirer/figures": "^1.0.13", "@inquirer/type": "^3.0.8", "ansi-escapes": "^4.3.2", "yoctocolors-cjs": "^2.1.2" }, "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-bevKGO6kX1eM/N+pdh9leS5L7TBF4ICrzi9a+cbWkrxeAeIcwlo/7OfWGCDERdRCI2/Q6tjltX4bt07ALHDwFw=="],
|
||||
|
||||
"@inquirer/confirm": ["@inquirer/confirm@5.1.14", "", { "dependencies": { "@inquirer/core": "^10.1.15", "@inquirer/type": "^3.0.8" }, "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-5yR4IBfe0kXe59r1YCTG8WXkUbl7Z35HK87Sw+WUyGD8wNUx7JvY7laahzeytyE1oLn74bQnL7hstctQxisQ8Q=="],
|
||||
|
||||
"@inquirer/core": ["@inquirer/core@10.1.15", "", { "dependencies": { "@inquirer/figures": "^1.0.13", "@inquirer/type": "^3.0.8", "ansi-escapes": "^4.3.2", "cli-width": "^4.1.0", "mute-stream": "^2.0.0", "signal-exit": "^4.1.0", "wrap-ansi": "^6.2.0", "yoctocolors-cjs": "^2.1.2" }, "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-8xrp836RZvKkpNbVvgWUlxjT4CraKk2q+I3Ksy+seI2zkcE+y6wNs1BVhgcv8VyImFecUhdQrYLdW32pAjwBdA=="],
|
||||
|
||||
"@inquirer/editor": ["@inquirer/editor@4.2.15", "", { "dependencies": { "@inquirer/core": "^10.1.15", "@inquirer/type": "^3.0.8", "external-editor": "^3.1.0" }, "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-wst31XT8DnGOSS4nNJDIklGKnf+8shuauVrWzgKegWUe28zfCftcWZ2vktGdzJgcylWSS2SrDnYUb6alZcwnCQ=="],
|
||||
"@inquirer/editor": ["@inquirer/editor@4.2.17", "", { "dependencies": { "@inquirer/core": "^10.1.15", "@inquirer/external-editor": "^1.0.1", "@inquirer/type": "^3.0.8" }, "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-r6bQLsyPSzbWrZZ9ufoWL+CztkSatnJ6uSxqd6N+o41EZC51sQeWOzI6s5jLb+xxTWxl7PlUppqm8/sow241gg=="],
|
||||
|
||||
"@inquirer/expand": ["@inquirer/expand@4.0.17", "", { "dependencies": { "@inquirer/core": "^10.1.15", "@inquirer/type": "^3.0.8", "yoctocolors-cjs": "^2.1.2" }, "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-PSqy9VmJx/VbE3CT453yOfNa+PykpKg/0SYP7odez1/NWBGuDXgPhp4AeGYYKjhLn5lUUavVS/JbeYMPdH50Mw=="],
|
||||
|
||||
"@inquirer/external-editor": ["@inquirer/external-editor@1.0.1", "", { "dependencies": { "chardet": "^2.1.0", "iconv-lite": "^0.6.3" }, "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-Oau4yL24d2B5IL4ma4UpbQigkVhzPDXLoqy1ggK4gnHg/stmkffJE4oOXHXF3uz0UEpywG68KcyXsyYpA1Re/Q=="],
|
||||
|
||||
"@inquirer/figures": ["@inquirer/figures@1.0.13", "", {}, "sha512-lGPVU3yO9ZNqA7vTYz26jny41lE7yoQansmqdMLBEfqaGsmdg7V3W9mK9Pvb5IL4EVZ9GnSDGMO/cJXud5dMaw=="],
|
||||
|
||||
"@inquirer/input": ["@inquirer/input@4.2.1", "", { "dependencies": { "@inquirer/core": "^10.1.15", "@inquirer/type": "^3.0.8" }, "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-tVC+O1rBl0lJpoUZv4xY+WGWY8V5b0zxU1XDsMsIHYregdh7bN5X5QnIONNBAl0K765FYlAfNHS2Bhn7SSOVow=="],
|
||||
@@ -517,7 +519,7 @@
|
||||
|
||||
"@inquirer/password": ["@inquirer/password@4.0.17", "", { "dependencies": { "@inquirer/core": "^10.1.15", "@inquirer/type": "^3.0.8", "ansi-escapes": "^4.3.2" }, "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-DJolTnNeZ00E1+1TW+8614F7rOJJCM4y4BAGQ3Gq6kQIG+OJ4zr3GLjIjVVJCbKsk2jmkmv6v2kQuN/vriHdZA=="],
|
||||
|
||||
"@inquirer/prompts": ["@inquirer/prompts@7.8.0", "", { "dependencies": { "@inquirer/checkbox": "^4.2.0", "@inquirer/confirm": "^5.1.14", "@inquirer/editor": "^4.2.15", "@inquirer/expand": "^4.0.17", "@inquirer/input": "^4.2.1", "@inquirer/number": "^3.0.17", "@inquirer/password": "^4.0.17", "@inquirer/rawlist": "^4.1.5", "@inquirer/search": "^3.1.0", "@inquirer/select": "^4.3.1" }, "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-JHwGbQ6wjf1dxxnalDYpZwZxUEosT+6CPGD9Zh4sm9WXdtUp9XODCQD3NjSTmu+0OAyxWXNOqf0spjIymJa2Tw=="],
|
||||
"@inquirer/prompts": ["@inquirer/prompts@7.8.2", "", { "dependencies": { "@inquirer/checkbox": "^4.2.1", "@inquirer/confirm": "^5.1.14", "@inquirer/editor": "^4.2.17", "@inquirer/expand": "^4.0.17", "@inquirer/input": "^4.2.1", "@inquirer/number": "^3.0.17", "@inquirer/password": "^4.0.17", "@inquirer/rawlist": "^4.1.5", "@inquirer/search": "^3.1.0", "@inquirer/select": "^4.3.1" }, "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-nqhDw2ZcAUrKNPwhjinJny903bRhI0rQhiDz1LksjeRxqa36i3l75+4iXbOy0rlDpLJGxqtgoPavQjmmyS5UJw=="],
|
||||
|
||||
"@inquirer/rawlist": ["@inquirer/rawlist@4.1.5", "", { "dependencies": { "@inquirer/core": "^10.1.15", "@inquirer/type": "^3.0.8", "yoctocolors-cjs": "^2.1.2" }, "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-R5qMyGJqtDdi4Ht521iAkNqyB6p2UPuZUbMifakg1sWtu24gc2Z8CJuw8rP081OckNDMgtDCuLe42Q2Kr3BolA=="],
|
||||
|
||||
@@ -537,11 +539,13 @@
|
||||
|
||||
"@isaacs/fs-minipass": ["@isaacs/fs-minipass@4.0.1", "", { "dependencies": { "minipass": "^7.0.4" } }, "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w=="],
|
||||
|
||||
"@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.12", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-OuLGC46TjB5BbN1dH8JULVVZY4WTdkF7tV9Ys6wLL1rubZnCMstOhNHueU5bLCrnRuDhKPDM4g6sw4Bel5Gzqg=="],
|
||||
"@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.13", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA=="],
|
||||
|
||||
"@jridgewell/remapping": ["@jridgewell/remapping@2.3.5", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ=="],
|
||||
|
||||
"@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.2", "", {}, "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="],
|
||||
|
||||
"@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.4", "", {}, "sha512-VT2+G1VQs/9oz078bLrYbecdZKs912zQlkelYpuf+SXF+QvZDYJlbx/LSx+meSAwdDFnF8FVXW92AVjjkVmgFw=="],
|
||||
"@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.5", "", {}, "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og=="],
|
||||
|
||||
"@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.9", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.0.3", "@jridgewell/sourcemap-codec": "^1.4.10" } }, "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ=="],
|
||||
|
||||
@@ -795,15 +799,15 @@
|
||||
|
||||
"@radix-ui/number": ["@radix-ui/number@1.1.1", "", {}, "sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g=="],
|
||||
|
||||
"@radix-ui/primitive": ["@radix-ui/primitive@1.1.2", "", {}, "sha512-XnbHrrprsNqZKQhStrSwgRUQzoCI1glLzdw79xiZPoofhGICeZRSQ3dIxAKH1gb3OHfNf4d6f+vAv3kil2eggA=="],
|
||||
"@radix-ui/primitive": ["@radix-ui/primitive@1.1.3", "", {}, "sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg=="],
|
||||
|
||||
"@radix-ui/react-accordion": ["@radix-ui/react-accordion@1.2.11", "", { "dependencies": { "@radix-ui/primitive": "1.1.2", "@radix-ui/react-collapsible": "1.1.11", "@radix-ui/react-collection": "1.1.7", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-l3W5D54emV2ues7jjeG1xcyN7S3jnK3zE2zHqgn0CmMsy9lNJwmgcrmaxS+7ipw15FAivzKNzH3d5EcGoFKw0A=="],
|
||||
"@radix-ui/react-accordion": ["@radix-ui/react-accordion@1.2.12", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-collapsible": "1.1.12", "@radix-ui/react-collection": "1.1.7", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-T4nygeh9YE9dLRPhAHSeOZi7HBXo+0kYIPJXayZfvWOWA0+n3dESrZbjfDPUABkUNym6Hd+f2IR113To8D2GPA=="],
|
||||
|
||||
"@radix-ui/react-arrow": ["@radix-ui/react-arrow@1.1.7", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w=="],
|
||||
|
||||
"@radix-ui/react-checkbox": ["@radix-ui/react-checkbox@1.3.2", "", { "dependencies": { "@radix-ui/primitive": "1.1.2", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-presence": "1.1.4", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-controllable-state": "1.2.2", "@radix-ui/react-use-previous": "1.1.1", "@radix-ui/react-use-size": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-yd+dI56KZqawxKZrJ31eENUwqc1QSqg4OZ15rybGjF2ZNwMO+wCyHzAVLRp9qoYJf7kYy0YpZ2b0JCzJ42HZpA=="],
|
||||
"@radix-ui/react-checkbox": ["@radix-ui/react-checkbox@1.3.3", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-presence": "1.1.5", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-controllable-state": "1.2.2", "@radix-ui/react-use-previous": "1.1.1", "@radix-ui/react-use-size": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-wBbpv+NQftHDdG86Qc0pIyXk5IR3tM8Vd0nWLKDcX8nNn4nXFOFwsKuqw2okA/1D/mpaAkmuyndrPJTYDNZtFw=="],
|
||||
|
||||
"@radix-ui/react-collapsible": ["@radix-ui/react-collapsible@1.1.11", "", { "dependencies": { "@radix-ui/primitive": "1.1.2", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-presence": "1.1.4", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-controllable-state": "1.2.2", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-2qrRsVGSCYasSz1RFOorXwl0H7g7J1frQtgpQgYrt+MOidtPAINHn9CPovQXb83r8ahapdx3Tu0fa/pdFFSdPg=="],
|
||||
"@radix-ui/react-collapsible": ["@radix-ui/react-collapsible@1.1.12", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-presence": "1.1.5", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-controllable-state": "1.2.2", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-Uu+mSh4agx2ib1uIGPP4/CKNULyajb3p92LsVXmH2EHVMTfZWpll88XJ0j4W0z3f8NK1eYl1+Mf/szHPmcHzyA=="],
|
||||
|
||||
"@radix-ui/react-collection": ["@radix-ui/react-collection@1.1.7", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw=="],
|
||||
|
||||
@@ -811,47 +815,47 @@
|
||||
|
||||
"@radix-ui/react-context": ["@radix-ui/react-context@1.1.2", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA=="],
|
||||
|
||||
"@radix-ui/react-dialog": ["@radix-ui/react-dialog@1.1.14", "", { "dependencies": { "@radix-ui/primitive": "1.1.2", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-dismissable-layer": "1.1.10", "@radix-ui/react-focus-guards": "1.1.2", "@radix-ui/react-focus-scope": "1.1.7", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-portal": "1.1.9", "@radix-ui/react-presence": "1.1.4", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-slot": "1.2.3", "@radix-ui/react-use-controllable-state": "1.2.2", "aria-hidden": "^1.2.4", "react-remove-scroll": "^2.6.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-+CpweKjqpzTmwRwcYECQcNYbI8V9VSQt0SNFKeEBLgfucbsLssU6Ppq7wUdNXEGb573bMjFhVjKVll8rmV6zMw=="],
|
||||
"@radix-ui/react-dialog": ["@radix-ui/react-dialog@1.1.15", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-dismissable-layer": "1.1.11", "@radix-ui/react-focus-guards": "1.1.3", "@radix-ui/react-focus-scope": "1.1.7", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-portal": "1.1.9", "@radix-ui/react-presence": "1.1.5", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-slot": "1.2.3", "@radix-ui/react-use-controllable-state": "1.2.2", "aria-hidden": "^1.2.4", "react-remove-scroll": "^2.6.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-TCglVRtzlffRNxRMEyR36DGBLJpeusFcgMVD9PZEzAKnUs1lKCgX5u9BmC2Yg+LL9MgZDugFFs1Vl+Jp4t/PGw=="],
|
||||
|
||||
"@radix-ui/react-direction": ["@radix-ui/react-direction@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw=="],
|
||||
|
||||
"@radix-ui/react-dismissable-layer": ["@radix-ui/react-dismissable-layer@1.1.10", "", { "dependencies": { "@radix-ui/primitive": "1.1.2", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-escape-keydown": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-IM1zzRV4W3HtVgftdQiiOmA0AdJlCtMLe00FXaHwgt3rAnNsIyDqshvkIW3hj/iu5hu8ERP7KIYki6NkqDxAwQ=="],
|
||||
"@radix-ui/react-dismissable-layer": ["@radix-ui/react-dismissable-layer@1.1.11", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-escape-keydown": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-Nqcp+t5cTB8BinFkZgXiMJniQH0PsUt2k51FUhbdfeKvc4ACcG2uQniY/8+h1Yv6Kza4Q7lD7PQV0z0oicE0Mg=="],
|
||||
|
||||
"@radix-ui/react-dropdown-menu": ["@radix-ui/react-dropdown-menu@2.1.15", "", { "dependencies": { "@radix-ui/primitive": "1.1.2", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-menu": "2.1.15", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-mIBnOjgwo9AH3FyKaSWoSu/dYj6VdhJ7frEPiGTeXCdUFHjl9h3mFh2wwhEtINOmYXWhdpf1rY2minFsmaNgVQ=="],
|
||||
"@radix-ui/react-dropdown-menu": ["@radix-ui/react-dropdown-menu@2.1.16", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-menu": "2.1.16", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-1PLGQEynI/3OX/ftV54COn+3Sud/Mn8vALg2rWnBLnRaGtJDduNW/22XjlGgPdpcIbiQxjKtb7BkcjP00nqfJw=="],
|
||||
|
||||
"@radix-ui/react-focus-guards": ["@radix-ui/react-focus-guards@1.1.2", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-fyjAACV62oPV925xFCrH8DR5xWhg9KYtJT4s3u54jxp+L/hbpTY2kIeEFFbFe+a/HCE94zGQMZLIpVTPVZDhaA=="],
|
||||
"@radix-ui/react-focus-guards": ["@radix-ui/react-focus-guards@1.1.3", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-0rFg/Rj2Q62NCm62jZw0QX7a3sz6QCQU0LpZdNrJX8byRGaGVTqbrW9jAoIAHyMQqsNpeZ81YgSizOt5WXq0Pw=="],
|
||||
|
||||
"@radix-ui/react-focus-scope": ["@radix-ui/react-focus-scope@1.1.7", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-t2ODlkXBQyn7jkl6TNaw/MtVEVvIGelJDCG41Okq/KwUsJBwQ4XVZsHAVUkK4mBv3ewiAS3PGuUWuY2BoK4ZUw=="],
|
||||
|
||||
"@radix-ui/react-id": ["@radix-ui/react-id@1.1.1", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg=="],
|
||||
|
||||
"@radix-ui/react-menu": ["@radix-ui/react-menu@2.1.15", "", { "dependencies": { "@radix-ui/primitive": "1.1.2", "@radix-ui/react-collection": "1.1.7", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-dismissable-layer": "1.1.10", "@radix-ui/react-focus-guards": "1.1.2", "@radix-ui/react-focus-scope": "1.1.7", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-popper": "1.2.7", "@radix-ui/react-portal": "1.1.9", "@radix-ui/react-presence": "1.1.4", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-roving-focus": "1.1.10", "@radix-ui/react-slot": "1.2.3", "@radix-ui/react-use-callback-ref": "1.1.1", "aria-hidden": "^1.2.4", "react-remove-scroll": "^2.6.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-tVlmA3Vb9n8SZSd+YSbuFR66l87Wiy4du+YE+0hzKQEANA+7cWKH1WgqcEX4pXqxUFQKrWQGHdvEfw00TjFiew=="],
|
||||
"@radix-ui/react-menu": ["@radix-ui/react-menu@2.1.16", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-collection": "1.1.7", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-dismissable-layer": "1.1.11", "@radix-ui/react-focus-guards": "1.1.3", "@radix-ui/react-focus-scope": "1.1.7", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-popper": "1.2.8", "@radix-ui/react-portal": "1.1.9", "@radix-ui/react-presence": "1.1.5", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-roving-focus": "1.1.11", "@radix-ui/react-slot": "1.2.3", "@radix-ui/react-use-callback-ref": "1.1.1", "aria-hidden": "^1.2.4", "react-remove-scroll": "^2.6.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-72F2T+PLlphrqLcAotYPp0uJMr5SjP5SL01wfEspJbru5Zs5vQaSHb4VB3ZMJPimgHHCHG7gMOeOB9H3Hdmtxg=="],
|
||||
|
||||
"@radix-ui/react-popover": ["@radix-ui/react-popover@1.1.14", "", { "dependencies": { "@radix-ui/primitive": "1.1.2", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-dismissable-layer": "1.1.10", "@radix-ui/react-focus-guards": "1.1.2", "@radix-ui/react-focus-scope": "1.1.7", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-popper": "1.2.7", "@radix-ui/react-portal": "1.1.9", "@radix-ui/react-presence": "1.1.4", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-slot": "1.2.3", "@radix-ui/react-use-controllable-state": "1.2.2", "aria-hidden": "^1.2.4", "react-remove-scroll": "^2.6.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-ODz16+1iIbGUfFEfKx2HTPKizg2MN39uIOV8MXeHnmdd3i/N9Wt7vU46wbHsqA0xoaQyXVcs0KIlBdOA2Y95bw=="],
|
||||
"@radix-ui/react-popover": ["@radix-ui/react-popover@1.1.15", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-dismissable-layer": "1.1.11", "@radix-ui/react-focus-guards": "1.1.3", "@radix-ui/react-focus-scope": "1.1.7", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-popper": "1.2.8", "@radix-ui/react-portal": "1.1.9", "@radix-ui/react-presence": "1.1.5", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-slot": "1.2.3", "@radix-ui/react-use-controllable-state": "1.2.2", "aria-hidden": "^1.2.4", "react-remove-scroll": "^2.6.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-kr0X2+6Yy/vJzLYJUPCZEc8SfQcf+1COFoAqauJm74umQhta9M7lNJHP7QQS3vkvcGLQUbWpMzwrXYwrYztHKA=="],
|
||||
|
||||
"@radix-ui/react-popper": ["@radix-ui/react-popper@1.2.7", "", { "dependencies": { "@floating-ui/react-dom": "^2.0.0", "@radix-ui/react-arrow": "1.1.7", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-layout-effect": "1.1.1", "@radix-ui/react-use-rect": "1.1.1", "@radix-ui/react-use-size": "1.1.1", "@radix-ui/rect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-IUFAccz1JyKcf/RjB552PlWwxjeCJB8/4KxT7EhBHOJM+mN7LdW+B3kacJXILm32xawcMMjb2i0cIZpo+f9kiQ=="],
|
||||
"@radix-ui/react-popper": ["@radix-ui/react-popper@1.2.8", "", { "dependencies": { "@floating-ui/react-dom": "^2.0.0", "@radix-ui/react-arrow": "1.1.7", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-layout-effect": "1.1.1", "@radix-ui/react-use-rect": "1.1.1", "@radix-ui/react-use-size": "1.1.1", "@radix-ui/rect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-0NJQ4LFFUuWkE7Oxf0htBKS6zLkkjBH+hM1uk7Ng705ReR8m/uelduy1DBo0PyBXPKVnBA6YBlU94MBGXrSBCw=="],
|
||||
|
||||
"@radix-ui/react-portal": ["@radix-ui/react-portal@1.1.9", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ=="],
|
||||
|
||||
"@radix-ui/react-presence": ["@radix-ui/react-presence@1.1.4", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-ueDqRbdc4/bkaQT3GIpLQssRlFgWaL/U2z/S31qRwwLWoxHLgry3SIfCwhxeQNbirEUXFa+lq3RL3oBYXtcmIA=="],
|
||||
"@radix-ui/react-presence": ["@radix-ui/react-presence@1.1.5", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-/jfEwNDdQVBCNvjkGit4h6pMOzq8bHkopq458dPt2lMjx+eBQUohZNG9A7DtO/O5ukSbxuaNGXMjHicgwy6rQQ=="],
|
||||
|
||||
"@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="],
|
||||
|
||||
"@radix-ui/react-roving-focus": ["@radix-ui/react-roving-focus@1.1.10", "", { "dependencies": { "@radix-ui/primitive": "1.1.2", "@radix-ui/react-collection": "1.1.7", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-dT9aOXUen9JSsxnMPv/0VqySQf5eDQ6LCk5Sw28kamz8wSOW2bJdlX2Bg5VUIIcV+6XlHpWTIuTPCf/UNIyq8Q=="],
|
||||
"@radix-ui/react-roving-focus": ["@radix-ui/react-roving-focus@1.1.11", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-collection": "1.1.7", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-7A6S9jSgm/S+7MdtNDSb+IU859vQqJ/QAtcYQcfFC6W8RS4IxIZDldLR0xqCFZ6DCyrQLjLPsxtTNch5jVA4lA=="],
|
||||
|
||||
"@radix-ui/react-scroll-area": ["@radix-ui/react-scroll-area@1.2.9", "", { "dependencies": { "@radix-ui/number": "1.1.1", "@radix-ui/primitive": "1.1.2", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-presence": "1.1.4", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-YSjEfBXnhUELsO2VzjdtYYD4CfQjvao+lhhrX5XsHD7/cyUNzljF1FHEbgTPN7LH2MClfwRMIsYlqTYpKTTe2A=="],
|
||||
"@radix-ui/react-scroll-area": ["@radix-ui/react-scroll-area@1.2.10", "", { "dependencies": { "@radix-ui/number": "1.1.1", "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-presence": "1.1.5", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-tAXIa1g3sM5CGpVT0uIbUx/U3Gs5N8T52IICuCtObaos1S8fzsrPXG5WObkQN3S6NVl6wKgPhAIiBGbWnvc97A=="],
|
||||
|
||||
"@radix-ui/react-select": ["@radix-ui/react-select@2.2.5", "", { "dependencies": { "@radix-ui/number": "1.1.1", "@radix-ui/primitive": "1.1.2", "@radix-ui/react-collection": "1.1.7", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-dismissable-layer": "1.1.10", "@radix-ui/react-focus-guards": "1.1.2", "@radix-ui/react-focus-scope": "1.1.7", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-popper": "1.2.7", "@radix-ui/react-portal": "1.1.9", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-slot": "1.2.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-controllable-state": "1.2.2", "@radix-ui/react-use-layout-effect": "1.1.1", "@radix-ui/react-use-previous": "1.1.1", "@radix-ui/react-visually-hidden": "1.2.3", "aria-hidden": "^1.2.4", "react-remove-scroll": "^2.6.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-HnMTdXEVuuyzx63ME0ut4+sEMYW6oouHWNGUZc7ddvUWIcfCva/AMoqEW/3wnEllriMWBa0RHspCYnfCWJQYmA=="],
|
||||
"@radix-ui/react-select": ["@radix-ui/react-select@2.2.6", "", { "dependencies": { "@radix-ui/number": "1.1.1", "@radix-ui/primitive": "1.1.3", "@radix-ui/react-collection": "1.1.7", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-dismissable-layer": "1.1.11", "@radix-ui/react-focus-guards": "1.1.3", "@radix-ui/react-focus-scope": "1.1.7", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-popper": "1.2.8", "@radix-ui/react-portal": "1.1.9", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-slot": "1.2.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-controllable-state": "1.2.2", "@radix-ui/react-use-layout-effect": "1.1.1", "@radix-ui/react-use-previous": "1.1.1", "@radix-ui/react-visually-hidden": "1.2.3", "aria-hidden": "^1.2.4", "react-remove-scroll": "^2.6.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-I30RydO+bnn2PQztvo25tswPH+wFBjehVGtmagkU78yMdwTwVf12wnAOF+AeP8S2N8xD+5UPbGhkUfPyvT+mwQ=="],
|
||||
|
||||
"@radix-ui/react-separator": ["@radix-ui/react-separator@1.1.7", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-0HEb8R9E8A+jZjvmFCy/J4xhbXy3TV+9XSnGJ3KvTtjlIUy/YQ/p6UYZvi7YbeoeXdyU9+Y3scizK6hkY37baA=="],
|
||||
|
||||
"@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.3", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A=="],
|
||||
|
||||
"@radix-ui/react-switch": ["@radix-ui/react-switch@1.2.5", "", { "dependencies": { "@radix-ui/primitive": "1.1.2", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-controllable-state": "1.2.2", "@radix-ui/react-use-previous": "1.1.1", "@radix-ui/react-use-size": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-5ijLkak6ZMylXsaImpZ8u4Rlf5grRmoc0p0QeX9VJtlrM4f5m3nCTX8tWga/zOA8PZYIR/t0p2Mnvd7InrJ6yQ=="],
|
||||
"@radix-ui/react-switch": ["@radix-ui/react-switch@1.2.6", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-controllable-state": "1.2.2", "@radix-ui/react-use-previous": "1.1.1", "@radix-ui/react-use-size": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-bByzr1+ep1zk4VubeEVViV592vu2lHE2BZY5OnzehZqOOgogN80+mNtCqPkhn2gklJqOpxWgPoYTSnhBCqpOXQ=="],
|
||||
|
||||
"@radix-ui/react-tabs": ["@radix-ui/react-tabs@1.1.12", "", { "dependencies": { "@radix-ui/primitive": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-presence": "1.1.4", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-roving-focus": "1.1.10", "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-GTVAlRVrQrSw3cEARM0nAx73ixrWDPNZAruETn3oHCNP6SbZ/hNxdxp+u7VkIEv3/sFoLq1PfcHrl7Pnp0CDpw=="],
|
||||
"@radix-ui/react-tabs": ["@radix-ui/react-tabs@1.1.13", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-presence": "1.1.5", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-roving-focus": "1.1.11", "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-7xdcatg7/U+7+Udyoj2zodtI9H/IIopqo+YOIcZOq1nJwXWBZ9p8xiu5llXlekDbZkca79a/fozEYQXIA4sW6A=="],
|
||||
|
||||
"@radix-ui/react-tooltip": ["@radix-ui/react-tooltip@1.2.7", "", { "dependencies": { "@radix-ui/primitive": "1.1.2", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-dismissable-layer": "1.1.10", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-popper": "1.2.7", "@radix-ui/react-portal": "1.1.9", "@radix-ui/react-presence": "1.1.4", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-slot": "1.2.3", "@radix-ui/react-use-controllable-state": "1.2.2", "@radix-ui/react-visually-hidden": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-Ap+fNYwKTYJ9pzqW+Xe2HtMRbQ/EeWkj2qykZ6SuEV4iS/o1bZI5ssJbk4D2r8XuDuOBVz/tIx2JObtuqU+5Zw=="],
|
||||
"@radix-ui/react-tooltip": ["@radix-ui/react-tooltip@1.2.8", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-dismissable-layer": "1.1.11", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-popper": "1.2.8", "@radix-ui/react-portal": "1.1.9", "@radix-ui/react-presence": "1.1.5", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-slot": "1.2.3", "@radix-ui/react-use-controllable-state": "1.2.2", "@radix-ui/react-visually-hidden": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-tY7sVt1yL9ozIxvmbtN5qtmH2krXcBCfjEiCgKGLqunJHvgvZG2Pcl2oQ3kbcZARb1BGEHdkLzcYGO8ynVlieg=="],
|
||||
|
||||
"@radix-ui/react-use-callback-ref": ["@radix-ui/react-use-callback-ref@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg=="],
|
||||
|
||||
@@ -961,13 +965,13 @@
|
||||
|
||||
"@selderee/plugin-htmlparser2": ["@selderee/plugin-htmlparser2@0.11.0", "", { "dependencies": { "domhandler": "^5.0.3", "selderee": "^0.11.0" } }, "sha512-P33hHGdldxGabLFjPPpaTxVolMrzrcegejx+0GxjrIb9Zv48D8yAIA/QTDR2dFl7Uz7urX8aX6+5bCZslr+gWQ=="],
|
||||
|
||||
"@sentry/core": ["@sentry/core@9.44.2", "", {}, "sha512-4wduCY9vz+VRMZXTT1dzk08L2nReeR+lzpY8hCcc+Wu100BoJR+TNlrSn1rG5iIo98NDW860JsRA7SVDUDOiNQ=="],
|
||||
"@sentry/core": ["@sentry/core@9.46.0", "", {}, "sha512-it7JMFqxVproAgEtbLgCVBYtQ9fIb+Bu0JD+cEplTN/Ukpe6GaolyYib5geZqslVxhp2sQgT+58aGvfd/k0N8Q=="],
|
||||
|
||||
"@sentry/node": ["@sentry/node@9.44.2", "", { "dependencies": { "@opentelemetry/api": "^1.9.0", "@opentelemetry/context-async-hooks": "^1.30.1", "@opentelemetry/core": "^1.30.1", "@opentelemetry/instrumentation": "^0.57.2", "@opentelemetry/instrumentation-amqplib": "^0.46.1", "@opentelemetry/instrumentation-connect": "0.43.1", "@opentelemetry/instrumentation-dataloader": "0.16.1", "@opentelemetry/instrumentation-express": "0.47.1", "@opentelemetry/instrumentation-fs": "0.19.1", "@opentelemetry/instrumentation-generic-pool": "0.43.1", "@opentelemetry/instrumentation-graphql": "0.47.1", "@opentelemetry/instrumentation-hapi": "0.45.2", "@opentelemetry/instrumentation-http": "0.57.2", "@opentelemetry/instrumentation-ioredis": "0.47.1", "@opentelemetry/instrumentation-kafkajs": "0.7.1", "@opentelemetry/instrumentation-knex": "0.44.1", "@opentelemetry/instrumentation-koa": "0.47.1", "@opentelemetry/instrumentation-lru-memoizer": "0.44.1", "@opentelemetry/instrumentation-mongodb": "0.52.0", "@opentelemetry/instrumentation-mongoose": "0.46.1", "@opentelemetry/instrumentation-mysql": "0.45.1", "@opentelemetry/instrumentation-mysql2": "0.45.2", "@opentelemetry/instrumentation-pg": "0.51.1", "@opentelemetry/instrumentation-redis-4": "0.46.1", "@opentelemetry/instrumentation-tedious": "0.18.1", "@opentelemetry/instrumentation-undici": "0.10.1", "@opentelemetry/resources": "^1.30.1", "@opentelemetry/sdk-trace-base": "^1.30.1", "@opentelemetry/semantic-conventions": "^1.34.0", "@prisma/instrumentation": "6.11.1", "@sentry/core": "9.44.2", "@sentry/node-core": "9.44.2", "@sentry/opentelemetry": "9.44.2", "import-in-the-middle": "^1.14.2", "minimatch": "^9.0.0" } }, "sha512-HTUDD73Tdr4GvvcNGQunkqEKeijHb4WYq/NX4YZP5VOeOsKsgIUsv55EgWk1BSHAFGTW6bfeMSoqaNVWiRHn0w=="],
|
||||
"@sentry/node": ["@sentry/node@9.46.0", "", { "dependencies": { "@opentelemetry/api": "^1.9.0", "@opentelemetry/context-async-hooks": "^1.30.1", "@opentelemetry/core": "^1.30.1", "@opentelemetry/instrumentation": "^0.57.2", "@opentelemetry/instrumentation-amqplib": "^0.46.1", "@opentelemetry/instrumentation-connect": "0.43.1", "@opentelemetry/instrumentation-dataloader": "0.16.1", "@opentelemetry/instrumentation-express": "0.47.1", "@opentelemetry/instrumentation-fs": "0.19.1", "@opentelemetry/instrumentation-generic-pool": "0.43.1", "@opentelemetry/instrumentation-graphql": "0.47.1", "@opentelemetry/instrumentation-hapi": "0.45.2", "@opentelemetry/instrumentation-http": "0.57.2", "@opentelemetry/instrumentation-ioredis": "0.47.1", "@opentelemetry/instrumentation-kafkajs": "0.7.1", "@opentelemetry/instrumentation-knex": "0.44.1", "@opentelemetry/instrumentation-koa": "0.47.1", "@opentelemetry/instrumentation-lru-memoizer": "0.44.1", "@opentelemetry/instrumentation-mongodb": "0.52.0", "@opentelemetry/instrumentation-mongoose": "0.46.1", "@opentelemetry/instrumentation-mysql": "0.45.1", "@opentelemetry/instrumentation-mysql2": "0.45.2", "@opentelemetry/instrumentation-pg": "0.51.1", "@opentelemetry/instrumentation-redis-4": "0.46.1", "@opentelemetry/instrumentation-tedious": "0.18.1", "@opentelemetry/instrumentation-undici": "0.10.1", "@opentelemetry/resources": "^1.30.1", "@opentelemetry/sdk-trace-base": "^1.30.1", "@opentelemetry/semantic-conventions": "^1.34.0", "@prisma/instrumentation": "6.11.1", "@sentry/core": "9.46.0", "@sentry/node-core": "9.46.0", "@sentry/opentelemetry": "9.46.0", "import-in-the-middle": "^1.14.2", "minimatch": "^9.0.0" } }, "sha512-pRLqAcd7GTGvN8gex5FtkQR5Mcol8gOy1WlyZZFq4rBbVtMbqKOQRhohwqnb+YrnmtFpj7IZ7KNDo077MvNeOQ=="],
|
||||
|
||||
"@sentry/node-core": ["@sentry/node-core@9.44.2", "", { "dependencies": { "@sentry/core": "9.44.2", "@sentry/opentelemetry": "9.44.2", "import-in-the-middle": "^1.14.2" }, "peerDependencies": { "@opentelemetry/api": "^1.9.0", "@opentelemetry/context-async-hooks": "^1.30.1 || ^2.0.0", "@opentelemetry/core": "^1.30.1 || ^2.0.0", "@opentelemetry/instrumentation": ">=0.57.1 <1", "@opentelemetry/resources": "^1.30.1 || ^2.0.0", "@opentelemetry/sdk-trace-base": "^1.30.1 || ^2.0.0", "@opentelemetry/semantic-conventions": "^1.34.0" } }, "sha512-TnyKZQ4FOCA+mkLLaOzFPePUBRBf0FU62hnNMscJviwb0UloOvHXx4Ub1DudfFFdnIeVSSMU96ou8vW1zR/1Uw=="],
|
||||
"@sentry/node-core": ["@sentry/node-core@9.46.0", "", { "dependencies": { "@sentry/core": "9.46.0", "@sentry/opentelemetry": "9.46.0", "import-in-the-middle": "^1.14.2" }, "peerDependencies": { "@opentelemetry/api": "^1.9.0", "@opentelemetry/context-async-hooks": "^1.30.1 || ^2.0.0", "@opentelemetry/core": "^1.30.1 || ^2.0.0", "@opentelemetry/instrumentation": ">=0.57.1 <1", "@opentelemetry/resources": "^1.30.1 || ^2.0.0", "@opentelemetry/sdk-trace-base": "^1.30.1 || ^2.0.0", "@opentelemetry/semantic-conventions": "^1.34.0" } }, "sha512-XRVu5pqoklZeh4wqhxCLZkz/ipoKhitctgEFXX9Yh1e1BoHM2pIxT52wf+W6hHM676TFmFXW3uKBjsmRM3AjgA=="],
|
||||
|
||||
"@sentry/opentelemetry": ["@sentry/opentelemetry@9.44.2", "", { "dependencies": { "@sentry/core": "9.44.2" }, "peerDependencies": { "@opentelemetry/api": "^1.9.0", "@opentelemetry/context-async-hooks": "^1.30.1 || ^2.0.0", "@opentelemetry/core": "^1.30.1 || ^2.0.0", "@opentelemetry/sdk-trace-base": "^1.30.1 || ^2.0.0", "@opentelemetry/semantic-conventions": "^1.34.0" } }, "sha512-KeW5MPXyq9Q8ieYUHO0PuzNNYEYizmTH6x02PG400GwmoeNxnT59Afa4TuPcrXN0QUmK76HJuPfC+7CTuCgoKA=="],
|
||||
"@sentry/opentelemetry": ["@sentry/opentelemetry@9.46.0", "", { "dependencies": { "@sentry/core": "9.46.0" }, "peerDependencies": { "@opentelemetry/api": "^1.9.0", "@opentelemetry/context-async-hooks": "^1.30.1 || ^2.0.0", "@opentelemetry/core": "^1.30.1 || ^2.0.0", "@opentelemetry/sdk-trace-base": "^1.30.1 || ^2.0.0", "@opentelemetry/semantic-conventions": "^1.34.0" } }, "sha512-w2zTxqrdmwRok0cXBoh+ksXdGRUHUZhlpfL/H2kfTodOL+Mk8rW72qUmfqQceXoqgbz8UyK8YgJbyt+XS5H4Qg=="],
|
||||
|
||||
"@sentry/types": ["@sentry/types@8.55.0", "", { "dependencies": { "@sentry/core": "8.55.0" } }, "sha512-6LRT0+r6NWQ+RtllrUW2yQfodST0cJnkOmdpHA75vONgBUhpKwiJ4H7AmgfoTET8w29pU6AnntaGOe0LJbOmog=="],
|
||||
|
||||
@@ -993,45 +997,45 @@
|
||||
|
||||
"@supabase/postgrest-js": ["@supabase/postgrest-js@1.19.4", "", { "dependencies": { "@supabase/node-fetch": "^2.6.14" } }, "sha512-O4soKqKtZIW3olqmbXXbKugUtByD2jPa8kL2m2c1oozAO11uCcGrRhkZL0kVxjBLrXHE0mdSkFsMj7jDSfyNpw=="],
|
||||
|
||||
"@supabase/realtime-js": ["@supabase/realtime-js@2.11.15", "", { "dependencies": { "@supabase/node-fetch": "^2.6.13", "@types/phoenix": "^1.6.6", "@types/ws": "^8.18.1", "isows": "^1.0.7", "ws": "^8.18.2" } }, "sha512-HQKRnwAqdVqJW/P9TjKVK+/ETpW4yQ8tyDPPtRMKOH4Uh3vQD74vmj353CYs8+YwVBKubeUOOEpI9CT8mT4obw=="],
|
||||
"@supabase/realtime-js": ["@supabase/realtime-js@2.15.1", "", { "dependencies": { "@supabase/node-fetch": "^2.6.13", "@types/phoenix": "^1.6.6", "@types/ws": "^8.18.1", "ws": "^8.18.2" } }, "sha512-edRFa2IrQw50kNntvUyS38hsL7t2d/psah6om6aNTLLcWem0R6bOUq7sk7DsGeSlNfuwEwWn57FdYSva6VddYw=="],
|
||||
|
||||
"@supabase/ssr": ["@supabase/ssr@0.5.2", "", { "dependencies": { "@types/cookie": "^0.6.0", "cookie": "^0.7.0" }, "peerDependencies": { "@supabase/supabase-js": "^2.43.4" } }, "sha512-n3plRhr2Bs8Xun1o4S3k1CDv17iH5QY9YcoEvXX3bxV1/5XSasA0mNXYycFmADIdtdE6BG9MRjP5CGIs8qxC8A=="],
|
||||
|
||||
"@supabase/storage-js": ["@supabase/storage-js@2.10.4", "", { "dependencies": { "@supabase/node-fetch": "^2.6.14" } }, "sha512-cvL02GarJVFcNoWe36VBybQqTVRq6wQSOCvTS64C+eyuxOruFIm1utZAY0xi2qKtHJO3EjKaj8iWJKySusDmAQ=="],
|
||||
"@supabase/storage-js": ["@supabase/storage-js@2.11.0", "", { "dependencies": { "@supabase/node-fetch": "^2.6.14" } }, "sha512-Y+kx/wDgd4oasAgoAq0bsbQojwQ+ejIif8uczZ9qufRHWFLMU5cODT+ApHsSrDufqUcVKt+eyxtOXSkeh2v9ww=="],
|
||||
|
||||
"@supabase/supabase-js": ["@supabase/supabase-js@2.53.0", "", { "dependencies": { "@supabase/auth-js": "2.71.1", "@supabase/functions-js": "2.4.5", "@supabase/node-fetch": "2.6.15", "@supabase/postgrest-js": "1.19.4", "@supabase/realtime-js": "2.11.15", "@supabase/storage-js": "^2.10.4" } }, "sha512-Vg9sl0oFn55cCPaEOsDsRDbxOVccxRrK/cikjL1XbywHEOfyA5SOOEypidMvQLwgoAfnC2S4D9BQwJDcZs7/TQ=="],
|
||||
"@supabase/supabase-js": ["@supabase/supabase-js@2.55.0", "", { "dependencies": { "@supabase/auth-js": "2.71.1", "@supabase/functions-js": "2.4.5", "@supabase/node-fetch": "2.6.15", "@supabase/postgrest-js": "1.19.4", "@supabase/realtime-js": "2.15.1", "@supabase/storage-js": "^2.10.4" } }, "sha512-Y1uV4nEMjQV1x83DGn7+Z9LOisVVRlY1geSARrUHbXWgbyKLZ6/08dvc0Us1r6AJ4tcKpwpCZWG9yDQYo1JgHg=="],
|
||||
|
||||
"@swc/helpers": ["@swc/helpers@0.5.15", "", { "dependencies": { "tslib": "^2.8.0" } }, "sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g=="],
|
||||
|
||||
"@tailwindcss/node": ["@tailwindcss/node@4.1.11", "", { "dependencies": { "@ampproject/remapping": "^2.3.0", "enhanced-resolve": "^5.18.1", "jiti": "^2.4.2", "lightningcss": "1.30.1", "magic-string": "^0.30.17", "source-map-js": "^1.2.1", "tailwindcss": "4.1.11" } }, "sha512-yzhzuGRmv5QyU9qLNg4GTlYI6STedBWRE7NjxP45CsFYYq9taI0zJXZBMqIC/c8fViNLhmrbpSFS57EoxUmD6Q=="],
|
||||
"@tailwindcss/node": ["@tailwindcss/node@4.1.12", "", { "dependencies": { "@jridgewell/remapping": "^2.3.4", "enhanced-resolve": "^5.18.3", "jiti": "^2.5.1", "lightningcss": "1.30.1", "magic-string": "^0.30.17", "source-map-js": "^1.2.1", "tailwindcss": "4.1.12" } }, "sha512-3hm9brwvQkZFe++SBt+oLjo4OLDtkvlE8q2WalaD/7QWaeM7KEJbAiY/LJZUaCs7Xa8aUu4xy3uoyX4q54UVdQ=="],
|
||||
|
||||
"@tailwindcss/oxide": ["@tailwindcss/oxide@4.1.11", "", { "dependencies": { "detect-libc": "^2.0.4", "tar": "^7.4.3" }, "optionalDependencies": { "@tailwindcss/oxide-android-arm64": "4.1.11", "@tailwindcss/oxide-darwin-arm64": "4.1.11", "@tailwindcss/oxide-darwin-x64": "4.1.11", "@tailwindcss/oxide-freebsd-x64": "4.1.11", "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.11", "@tailwindcss/oxide-linux-arm64-gnu": "4.1.11", "@tailwindcss/oxide-linux-arm64-musl": "4.1.11", "@tailwindcss/oxide-linux-x64-gnu": "4.1.11", "@tailwindcss/oxide-linux-x64-musl": "4.1.11", "@tailwindcss/oxide-wasm32-wasi": "4.1.11", "@tailwindcss/oxide-win32-arm64-msvc": "4.1.11", "@tailwindcss/oxide-win32-x64-msvc": "4.1.11" } }, "sha512-Q69XzrtAhuyfHo+5/HMgr1lAiPP/G40OMFAnws7xcFEYqcypZmdW8eGXaOUIeOl1dzPJBPENXgbjsOyhg2nkrg=="],
|
||||
"@tailwindcss/oxide": ["@tailwindcss/oxide@4.1.12", "", { "dependencies": { "detect-libc": "^2.0.4", "tar": "^7.4.3" }, "optionalDependencies": { "@tailwindcss/oxide-android-arm64": "4.1.12", "@tailwindcss/oxide-darwin-arm64": "4.1.12", "@tailwindcss/oxide-darwin-x64": "4.1.12", "@tailwindcss/oxide-freebsd-x64": "4.1.12", "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.12", "@tailwindcss/oxide-linux-arm64-gnu": "4.1.12", "@tailwindcss/oxide-linux-arm64-musl": "4.1.12", "@tailwindcss/oxide-linux-x64-gnu": "4.1.12", "@tailwindcss/oxide-linux-x64-musl": "4.1.12", "@tailwindcss/oxide-wasm32-wasi": "4.1.12", "@tailwindcss/oxide-win32-arm64-msvc": "4.1.12", "@tailwindcss/oxide-win32-x64-msvc": "4.1.12" } }, "sha512-gM5EoKHW/ukmlEtphNwaGx45fGoEmP10v51t9unv55voWh6WrOL19hfuIdo2FjxIaZzw776/BUQg7Pck++cIVw=="],
|
||||
|
||||
"@tailwindcss/oxide-android-arm64": ["@tailwindcss/oxide-android-arm64@4.1.11", "", { "os": "android", "cpu": "arm64" }, "sha512-3IfFuATVRUMZZprEIx9OGDjG3Ou3jG4xQzNTvjDoKmU9JdmoCohQJ83MYd0GPnQIu89YoJqvMM0G3uqLRFtetg=="],
|
||||
"@tailwindcss/oxide-android-arm64": ["@tailwindcss/oxide-android-arm64@4.1.12", "", { "os": "android", "cpu": "arm64" }, "sha512-oNY5pq+1gc4T6QVTsZKwZaGpBb2N1H1fsc1GD4o7yinFySqIuRZ2E4NvGasWc6PhYJwGK2+5YT1f9Tp80zUQZQ=="],
|
||||
|
||||
"@tailwindcss/oxide-darwin-arm64": ["@tailwindcss/oxide-darwin-arm64@4.1.11", "", { "os": "darwin", "cpu": "arm64" }, "sha512-ESgStEOEsyg8J5YcMb1xl8WFOXfeBmrhAwGsFxxB2CxY9evy63+AtpbDLAyRkJnxLy2WsD1qF13E97uQyP1lfQ=="],
|
||||
"@tailwindcss/oxide-darwin-arm64": ["@tailwindcss/oxide-darwin-arm64@4.1.12", "", { "os": "darwin", "cpu": "arm64" }, "sha512-cq1qmq2HEtDV9HvZlTtrj671mCdGB93bVY6J29mwCyaMYCP/JaUBXxrQQQm7Qn33AXXASPUb2HFZlWiiHWFytw=="],
|
||||
|
||||
"@tailwindcss/oxide-darwin-x64": ["@tailwindcss/oxide-darwin-x64@4.1.11", "", { "os": "darwin", "cpu": "x64" }, "sha512-EgnK8kRchgmgzG6jE10UQNaH9Mwi2n+yw1jWmof9Vyg2lpKNX2ioe7CJdf9M5f8V9uaQxInenZkOxnTVL3fhAw=="],
|
||||
"@tailwindcss/oxide-darwin-x64": ["@tailwindcss/oxide-darwin-x64@4.1.12", "", { "os": "darwin", "cpu": "x64" }, "sha512-6UCsIeFUcBfpangqlXay9Ffty9XhFH1QuUFn0WV83W8lGdX8cD5/+2ONLluALJD5+yJ7k8mVtwy3zMZmzEfbLg=="],
|
||||
|
||||
"@tailwindcss/oxide-freebsd-x64": ["@tailwindcss/oxide-freebsd-x64@4.1.11", "", { "os": "freebsd", "cpu": "x64" }, "sha512-xdqKtbpHs7pQhIKmqVpxStnY1skuNh4CtbcyOHeX1YBE0hArj2romsFGb6yUmzkq/6M24nkxDqU8GYrKrz+UcA=="],
|
||||
"@tailwindcss/oxide-freebsd-x64": ["@tailwindcss/oxide-freebsd-x64@4.1.12", "", { "os": "freebsd", "cpu": "x64" }, "sha512-JOH/f7j6+nYXIrHobRYCtoArJdMJh5zy5lr0FV0Qu47MID/vqJAY3r/OElPzx1C/wdT1uS7cPq+xdYYelny1ww=="],
|
||||
|
||||
"@tailwindcss/oxide-linux-arm-gnueabihf": ["@tailwindcss/oxide-linux-arm-gnueabihf@4.1.11", "", { "os": "linux", "cpu": "arm" }, "sha512-ryHQK2eyDYYMwB5wZL46uoxz2zzDZsFBwfjssgB7pzytAeCCa6glsiJGjhTEddq/4OsIjsLNMAiMlHNYnkEEeg=="],
|
||||
"@tailwindcss/oxide-linux-arm-gnueabihf": ["@tailwindcss/oxide-linux-arm-gnueabihf@4.1.12", "", { "os": "linux", "cpu": "arm" }, "sha512-v4Ghvi9AU1SYgGr3/j38PD8PEe6bRfTnNSUE3YCMIRrrNigCFtHZ2TCm8142X8fcSqHBZBceDx+JlFJEfNg5zQ=="],
|
||||
|
||||
"@tailwindcss/oxide-linux-arm64-gnu": ["@tailwindcss/oxide-linux-arm64-gnu@4.1.11", "", { "os": "linux", "cpu": "arm64" }, "sha512-mYwqheq4BXF83j/w75ewkPJmPZIqqP1nhoghS9D57CLjsh3Nfq0m4ftTotRYtGnZd3eCztgbSPJ9QhfC91gDZQ=="],
|
||||
"@tailwindcss/oxide-linux-arm64-gnu": ["@tailwindcss/oxide-linux-arm64-gnu@4.1.12", "", { "os": "linux", "cpu": "arm64" }, "sha512-YP5s1LmetL9UsvVAKusHSyPlzSRqYyRB0f+Kl/xcYQSPLEw/BvGfxzbH+ihUciePDjiXwHh+p+qbSP3SlJw+6g=="],
|
||||
|
||||
"@tailwindcss/oxide-linux-arm64-musl": ["@tailwindcss/oxide-linux-arm64-musl@4.1.11", "", { "os": "linux", "cpu": "arm64" }, "sha512-m/NVRFNGlEHJrNVk3O6I9ggVuNjXHIPoD6bqay/pubtYC9QIdAMpS+cswZQPBLvVvEF6GtSNONbDkZrjWZXYNQ=="],
|
||||
"@tailwindcss/oxide-linux-arm64-musl": ["@tailwindcss/oxide-linux-arm64-musl@4.1.12", "", { "os": "linux", "cpu": "arm64" }, "sha512-V8pAM3s8gsrXcCv6kCHSuwyb/gPsd863iT+v1PGXC4fSL/OJqsKhfK//v8P+w9ThKIoqNbEnsZqNy+WDnwQqCA=="],
|
||||
|
||||
"@tailwindcss/oxide-linux-x64-gnu": ["@tailwindcss/oxide-linux-x64-gnu@4.1.11", "", { "os": "linux", "cpu": "x64" }, "sha512-YW6sblI7xukSD2TdbbaeQVDysIm/UPJtObHJHKxDEcW2exAtY47j52f8jZXkqE1krdnkhCMGqP3dbniu1Te2Fg=="],
|
||||
"@tailwindcss/oxide-linux-x64-gnu": ["@tailwindcss/oxide-linux-x64-gnu@4.1.12", "", { "os": "linux", "cpu": "x64" }, "sha512-xYfqYLjvm2UQ3TZggTGrwxjYaLB62b1Wiysw/YE3Yqbh86sOMoTn0feF98PonP7LtjsWOWcXEbGqDL7zv0uW8Q=="],
|
||||
|
||||
"@tailwindcss/oxide-linux-x64-musl": ["@tailwindcss/oxide-linux-x64-musl@4.1.11", "", { "os": "linux", "cpu": "x64" }, "sha512-e3C/RRhGunWYNC3aSF7exsQkdXzQ/M+aYuZHKnw4U7KQwTJotnWsGOIVih0s2qQzmEzOFIJ3+xt7iq67K/p56Q=="],
|
||||
"@tailwindcss/oxide-linux-x64-musl": ["@tailwindcss/oxide-linux-x64-musl@4.1.12", "", { "os": "linux", "cpu": "x64" }, "sha512-ha0pHPamN+fWZY7GCzz5rKunlv9L5R8kdh+YNvP5awe3LtuXb5nRi/H27GeL2U+TdhDOptU7T6Is7mdwh5Ar3A=="],
|
||||
|
||||
"@tailwindcss/oxide-wasm32-wasi": ["@tailwindcss/oxide-wasm32-wasi@4.1.11", "", { "dependencies": { "@emnapi/core": "^1.4.3", "@emnapi/runtime": "^1.4.3", "@emnapi/wasi-threads": "^1.0.2", "@napi-rs/wasm-runtime": "^0.2.11", "@tybys/wasm-util": "^0.9.0", "tslib": "^2.8.0" }, "cpu": "none" }, "sha512-Xo1+/GU0JEN/C/dvcammKHzeM6NqKovG+6921MR6oadee5XPBaKOumrJCXvopJ/Qb5TH7LX/UAywbqrP4lax0g=="],
|
||||
"@tailwindcss/oxide-wasm32-wasi": ["@tailwindcss/oxide-wasm32-wasi@4.1.12", "", { "dependencies": { "@emnapi/core": "^1.4.5", "@emnapi/runtime": "^1.4.5", "@emnapi/wasi-threads": "^1.0.4", "@napi-rs/wasm-runtime": "^0.2.12", "@tybys/wasm-util": "^0.10.0", "tslib": "^2.8.0" }, "cpu": "none" }, "sha512-4tSyu3dW+ktzdEpuk6g49KdEangu3eCYoqPhWNsZgUhyegEda3M9rG0/j1GV/JjVVsj+lG7jWAyrTlLzd/WEBg=="],
|
||||
|
||||
"@tailwindcss/oxide-win32-arm64-msvc": ["@tailwindcss/oxide-win32-arm64-msvc@4.1.11", "", { "os": "win32", "cpu": "arm64" }, "sha512-UgKYx5PwEKrac3GPNPf6HVMNhUIGuUh4wlDFR2jYYdkX6pL/rn73zTq/4pzUm8fOjAn5L8zDeHp9iXmUGOXZ+w=="],
|
||||
"@tailwindcss/oxide-win32-arm64-msvc": ["@tailwindcss/oxide-win32-arm64-msvc@4.1.12", "", { "os": "win32", "cpu": "arm64" }, "sha512-iGLyD/cVP724+FGtMWslhcFyg4xyYyM+5F4hGvKA7eifPkXHRAUDFaimu53fpNg9X8dfP75pXx/zFt/jlNF+lg=="],
|
||||
|
||||
"@tailwindcss/oxide-win32-x64-msvc": ["@tailwindcss/oxide-win32-x64-msvc@4.1.11", "", { "os": "win32", "cpu": "x64" }, "sha512-YfHoggn1j0LK7wR82TOucWc5LDCguHnoS879idHekmmiR7g9HUtMw9MI0NHatS28u/Xlkfi9w5RJWgz2Dl+5Qg=="],
|
||||
"@tailwindcss/oxide-win32-x64-msvc": ["@tailwindcss/oxide-win32-x64-msvc@4.1.12", "", { "os": "win32", "cpu": "x64" }, "sha512-NKIh5rzw6CpEodv/++r0hGLlfgT/gFN+5WNdZtvh6wpU2BpGNgdjvj6H2oFc8nCM839QM1YOhjpgbAONUb4IxA=="],
|
||||
|
||||
"@tailwindcss/vite": ["@tailwindcss/vite@4.1.11", "", { "dependencies": { "@tailwindcss/node": "4.1.11", "@tailwindcss/oxide": "4.1.11", "tailwindcss": "4.1.11" }, "peerDependencies": { "vite": "^5.2.0 || ^6 || ^7" } }, "sha512-RHYhrR3hku0MJFRV+fN2gNbDNEh3dwKvY8XJvTxCSXeMOsCRSr+uKvDWQcbizrHgjML6ZmTE5OwMrl5wKcujCw=="],
|
||||
"@tailwindcss/vite": ["@tailwindcss/vite@4.1.12", "", { "dependencies": { "@tailwindcss/node": "4.1.12", "@tailwindcss/oxide": "4.1.12", "tailwindcss": "4.1.12" }, "peerDependencies": { "vite": "^5.2.0 || ^6 || ^7" } }, "sha512-4pt0AMFDx7gzIrAOIYgYP0KCBuKWqyW8ayrdiLEjoJTT4pKTjrzG/e4uzWtTLDziC+66R9wbUqZBccJalSE5vQ=="],
|
||||
|
||||
"@tanstack/react-table": ["@tanstack/react-table@8.21.3", "", { "dependencies": { "@tanstack/table-core": "8.21.3" }, "peerDependencies": { "react": ">=16.8", "react-dom": ">=16.8" } }, "sha512-5nNMTSETP4ykGegmVkhjcS8tTLW6Vl4axfEGQN3v0zdHYbK4UfoqfPChclTrJ4EoK9QynqAu9oUf8VEmrpZ5Ww=="],
|
||||
|
||||
@@ -1059,7 +1063,7 @@
|
||||
|
||||
"@types/body-parser": ["@types/body-parser@1.19.6", "", { "dependencies": { "@types/connect": "*", "@types/node": "*" } }, "sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g=="],
|
||||
|
||||
"@types/bun": ["@types/bun@1.2.19", "", { "dependencies": { "bun-types": "1.2.19" } }, "sha512-d9ZCmrH3CJ2uYKXQIUuZ/pUnTqIvLDS0SK7pFmbx8ma+ziH/FRMoAq5bYpRG7y+w1gl+HgyNZbtqgMq4W4e2Lg=="],
|
||||
"@types/bun": ["@types/bun@1.2.20", "", { "dependencies": { "bun-types": "1.2.20" } }, "sha512-dX3RGzQ8+KgmMw7CsW4xT5ITBSCrSbfHc36SNT31EOUg/LA9JWq0VDdEXDRSe1InVWpd2yLUM1FUF/kEOyTzYA=="],
|
||||
|
||||
"@types/bunyan": ["@types/bunyan@1.8.11", "", { "dependencies": { "@types/node": "*" } }, "sha512-758fRH7umIMk5qt5ELmRMff4mLDlN+xyYzC+dkPTdKwbSkJFvz6xwyScrytPU0QIBbRRwbiE8/BIg8bpajerNQ=="],
|
||||
|
||||
@@ -1129,7 +1133,7 @@
|
||||
|
||||
"@types/mysql": ["@types/mysql@2.15.27", "", { "dependencies": { "@types/node": "*" } }, "sha512-YfWiV16IY0OeBfBCk8+hXKmdTKrKlwKN1MNKAPBu5JYxLwBEZl7QzeEpGnlZb3VMGJrrGmB84gXiH+ofs/TezA=="],
|
||||
|
||||
"@types/node": ["@types/node@24.2.0", "", { "dependencies": { "undici-types": "~7.10.0" } }, "sha512-3xyG3pMCq3oYCNg7/ZP+E1ooTaGB4cG8JWRsqqOYQdbWNY4zbaV0Ennrd7stjiJEFZCaybcIgpTjJWHRfBSIDw=="],
|
||||
"@types/node": ["@types/node@24.3.0", "", { "dependencies": { "undici-types": "~7.10.0" } }, "sha512-aPTXCrfwnDLj4VvXrm+UUCQjNEvJgNA8s5F1cvwQU+3KNltTOkBm1j30uNLyqqPNe7gE3KFzImYoZEfLhp4Yow=="],
|
||||
|
||||
"@types/node-fetch": ["@types/node-fetch@2.6.13", "", { "dependencies": { "@types/node": "*", "form-data": "^4.0.4" } }, "sha512-QGpRVpzSaUs30JBSGPjOg4Uveu384erbHBoT1zeONvyCfwQxIkUshLAOqN/k9EjGviPRmWTTe6aH2qySWKTVSw=="],
|
||||
|
||||
@@ -1181,41 +1185,41 @@
|
||||
|
||||
"@types/yauzl": ["@types/yauzl@2.10.3", "", { "dependencies": { "@types/node": "*" } }, "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q=="],
|
||||
|
||||
"@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.39.0", "", { "dependencies": { "@eslint-community/regexpp": "^4.10.0", "@typescript-eslint/scope-manager": "8.39.0", "@typescript-eslint/type-utils": "8.39.0", "@typescript-eslint/utils": "8.39.0", "@typescript-eslint/visitor-keys": "8.39.0", "graphemer": "^1.4.0", "ignore": "^7.0.0", "natural-compare": "^1.4.0", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "@typescript-eslint/parser": "^8.39.0", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-bhEz6OZeUR+O/6yx9Jk6ohX6H9JSFTaiY0v9/PuKT3oGK0rn0jNplLmyFUGV+a9gfYnVNwGDwS/UkLIuXNb2Rw=="],
|
||||
"@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.39.1", "", { "dependencies": { "@eslint-community/regexpp": "^4.10.0", "@typescript-eslint/scope-manager": "8.39.1", "@typescript-eslint/type-utils": "8.39.1", "@typescript-eslint/utils": "8.39.1", "@typescript-eslint/visitor-keys": "8.39.1", "graphemer": "^1.4.0", "ignore": "^7.0.0", "natural-compare": "^1.4.0", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "@typescript-eslint/parser": "^8.39.1", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-yYegZ5n3Yr6eOcqgj2nJH8cH/ZZgF+l0YIdKILSDjYFRjgYQMgv/lRjV5Z7Up04b9VYUondt8EPMqg7kTWgJ2g=="],
|
||||
|
||||
"@typescript-eslint/parser": ["@typescript-eslint/parser@8.39.0", "", { "dependencies": { "@typescript-eslint/scope-manager": "8.39.0", "@typescript-eslint/types": "8.39.0", "@typescript-eslint/typescript-estree": "8.39.0", "@typescript-eslint/visitor-keys": "8.39.0", "debug": "^4.3.4" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-g3WpVQHngx0aLXn6kfIYCZxM6rRJlWzEkVpqEFLT3SgEDsp9cpCbxxgwnE504q4H+ruSDh/VGS6nqZIDynP+vg=="],
|
||||
"@typescript-eslint/parser": ["@typescript-eslint/parser@8.39.1", "", { "dependencies": { "@typescript-eslint/scope-manager": "8.39.1", "@typescript-eslint/types": "8.39.1", "@typescript-eslint/typescript-estree": "8.39.1", "@typescript-eslint/visitor-keys": "8.39.1", "debug": "^4.3.4" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-pUXGCuHnnKw6PyYq93lLRiZm3vjuslIy7tus1lIQTYVK9bL8XBgJnCWm8a0KcTtHC84Yya1Q6rtll+duSMj0dg=="],
|
||||
|
||||
"@typescript-eslint/project-service": ["@typescript-eslint/project-service@8.39.0", "", { "dependencies": { "@typescript-eslint/tsconfig-utils": "^8.39.0", "@typescript-eslint/types": "^8.39.0", "debug": "^4.3.4" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-CTzJqaSq30V/Z2Og9jogzZt8lJRR5TKlAdXmWgdu4hgcC9Kww5flQ+xFvMxIBWVNdxJO7OifgdOK4PokMIWPew=="],
|
||||
"@typescript-eslint/project-service": ["@typescript-eslint/project-service@8.39.1", "", { "dependencies": { "@typescript-eslint/tsconfig-utils": "^8.39.1", "@typescript-eslint/types": "^8.39.1", "debug": "^4.3.4" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-8fZxek3ONTwBu9ptw5nCKqZOSkXshZB7uAxuFF0J/wTMkKydjXCzqqga7MlFMpHi9DoG4BadhmTkITBcg8Aybw=="],
|
||||
|
||||
"@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.39.0", "", { "dependencies": { "@typescript-eslint/types": "8.39.0", "@typescript-eslint/visitor-keys": "8.39.0" } }, "sha512-8QOzff9UKxOh6npZQ/4FQu4mjdOCGSdO3p44ww0hk8Vu+IGbg0tB/H1LcTARRDzGCC8pDGbh2rissBuuoPgH8A=="],
|
||||
"@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.39.1", "", { "dependencies": { "@typescript-eslint/types": "8.39.1", "@typescript-eslint/visitor-keys": "8.39.1" } }, "sha512-RkBKGBrjgskFGWuyUGz/EtD8AF/GW49S21J8dvMzpJitOF1slLEbbHnNEtAHtnDAnx8qDEdRrULRnWVx27wGBw=="],
|
||||
|
||||
"@typescript-eslint/tsconfig-utils": ["@typescript-eslint/tsconfig-utils@8.39.0", "", { "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-Fd3/QjmFV2sKmvv3Mrj8r6N8CryYiCS8Wdb/6/rgOXAWGcFuc+VkQuG28uk/4kVNVZBQuuDHEDUpo/pQ32zsIQ=="],
|
||||
"@typescript-eslint/tsconfig-utils": ["@typescript-eslint/tsconfig-utils@8.39.1", "", { "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-ePUPGVtTMR8XMU2Hee8kD0Pu4NDE1CN9Q1sxGSGd/mbOtGZDM7pnhXNJnzW63zk/q+Z54zVzj44HtwXln5CvHA=="],
|
||||
|
||||
"@typescript-eslint/type-utils": ["@typescript-eslint/type-utils@8.39.0", "", { "dependencies": { "@typescript-eslint/types": "8.39.0", "@typescript-eslint/typescript-estree": "8.39.0", "@typescript-eslint/utils": "8.39.0", "debug": "^4.3.4", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-6B3z0c1DXVT2vYA9+z9axjtc09rqKUPRmijD5m9iv8iQpHBRYRMBcgxSiKTZKm6FwWw1/cI4v6em35OsKCiN5Q=="],
|
||||
"@typescript-eslint/type-utils": ["@typescript-eslint/type-utils@8.39.1", "", { "dependencies": { "@typescript-eslint/types": "8.39.1", "@typescript-eslint/typescript-estree": "8.39.1", "@typescript-eslint/utils": "8.39.1", "debug": "^4.3.4", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-gu9/ahyatyAdQbKeHnhT4R+y3YLtqqHyvkfDxaBYk97EcbfChSJXyaJnIL3ygUv7OuZatePHmQvuH5ru0lnVeA=="],
|
||||
|
||||
"@typescript-eslint/types": ["@typescript-eslint/types@8.39.0", "", {}, "sha512-ArDdaOllnCj3yn/lzKn9s0pBQYmmyme/v1HbGIGB0GB/knFI3fWMHloC+oYTJW46tVbYnGKTMDK4ah1sC2v0Kg=="],
|
||||
"@typescript-eslint/types": ["@typescript-eslint/types@8.39.1", "", {}, "sha512-7sPDKQQp+S11laqTrhHqeAbsCfMkwJMrV7oTDvtDds4mEofJYir414bYKUEb8YPUm9QL3U+8f6L6YExSoAGdQw=="],
|
||||
|
||||
"@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.39.0", "", { "dependencies": { "@typescript-eslint/project-service": "8.39.0", "@typescript-eslint/tsconfig-utils": "8.39.0", "@typescript-eslint/types": "8.39.0", "@typescript-eslint/visitor-keys": "8.39.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", "minimatch": "^9.0.4", "semver": "^7.6.0", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-ndWdiflRMvfIgQRpckQQLiB5qAKQ7w++V4LlCHwp62eym1HLB/kw7D9f2e8ytONls/jt89TEasgvb+VwnRprsw=="],
|
||||
"@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.39.1", "", { "dependencies": { "@typescript-eslint/project-service": "8.39.1", "@typescript-eslint/tsconfig-utils": "8.39.1", "@typescript-eslint/types": "8.39.1", "@typescript-eslint/visitor-keys": "8.39.1", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", "minimatch": "^9.0.4", "semver": "^7.6.0", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-EKkpcPuIux48dddVDXyQBlKdeTPMmALqBUbEk38McWv0qVEZwOpVJBi7ugK5qVNgeuYjGNQxrrnoM/5+TI/BPw=="],
|
||||
|
||||
"@typescript-eslint/utils": ["@typescript-eslint/utils@8.39.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.7.0", "@typescript-eslint/scope-manager": "8.39.0", "@typescript-eslint/types": "8.39.0", "@typescript-eslint/typescript-estree": "8.39.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-4GVSvNA0Vx1Ktwvf4sFE+exxJ3QGUorQG1/A5mRfRNZtkBT2xrA/BCO2H0eALx/PnvCS6/vmYwRdDA41EoffkQ=="],
|
||||
"@typescript-eslint/utils": ["@typescript-eslint/utils@8.39.1", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.7.0", "@typescript-eslint/scope-manager": "8.39.1", "@typescript-eslint/types": "8.39.1", "@typescript-eslint/typescript-estree": "8.39.1" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-VF5tZ2XnUSTuiqZFXCZfZs1cgkdd3O/sSYmdo2EpSyDlC86UM/8YytTmKnehOW3TGAlivqTDT6bS87B/GQ/jyg=="],
|
||||
|
||||
"@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.39.0", "", { "dependencies": { "@typescript-eslint/types": "8.39.0", "eslint-visitor-keys": "^4.2.1" } }, "sha512-ldgiJ+VAhQCfIjeOgu8Kj5nSxds0ktPOSO9p4+0VDH2R2pLvQraaM5Oen2d7NxzMCm+Sn/vJT+mv2H5u6b/3fA=="],
|
||||
"@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.39.1", "", { "dependencies": { "@typescript-eslint/types": "8.39.1", "eslint-visitor-keys": "^4.2.1" } }, "sha512-W8FQi6kEh2e8zVhQ0eeRnxdvIoOkAp/CPAahcNio6nO9dsIwb9b34z90KOlheoyuVf6LSOEdjlkxSkapNEc+4A=="],
|
||||
|
||||
"@typescript/native-preview": ["@typescript/native-preview@7.0.0-dev.20250806.1", "", { "optionalDependencies": { "@typescript/native-preview-darwin-arm64": "7.0.0-dev.20250806.1", "@typescript/native-preview-darwin-x64": "7.0.0-dev.20250806.1", "@typescript/native-preview-linux-arm": "7.0.0-dev.20250806.1", "@typescript/native-preview-linux-arm64": "7.0.0-dev.20250806.1", "@typescript/native-preview-linux-x64": "7.0.0-dev.20250806.1", "@typescript/native-preview-win32-arm64": "7.0.0-dev.20250806.1", "@typescript/native-preview-win32-x64": "7.0.0-dev.20250806.1" }, "bin": { "tsgo": "bin/tsgo.js" } }, "sha512-dQWOle1t2QJHiGK+ILB5SCz1Q6VfGtkrZybT4FPSaddkskYN1djY6voxza8hd8yl1Yw0PmBmbqk3E4vTKyibig=="],
|
||||
"@typescript/native-preview": ["@typescript/native-preview@7.0.0-dev.20250816.1", "", { "optionalDependencies": { "@typescript/native-preview-darwin-arm64": "7.0.0-dev.20250816.1", "@typescript/native-preview-darwin-x64": "7.0.0-dev.20250816.1", "@typescript/native-preview-linux-arm": "7.0.0-dev.20250816.1", "@typescript/native-preview-linux-arm64": "7.0.0-dev.20250816.1", "@typescript/native-preview-linux-x64": "7.0.0-dev.20250816.1", "@typescript/native-preview-win32-arm64": "7.0.0-dev.20250816.1", "@typescript/native-preview-win32-x64": "7.0.0-dev.20250816.1" }, "bin": { "tsgo": "bin/tsgo.js" } }, "sha512-du/e72VqzVXFQqbKuEc7W+W9pWvIgKg0SwydHxzvzQ6TiccBAP/Ar7FUBEuYkFGQ2rbo7pYLj/zkoUCy08QW5w=="],
|
||||
|
||||
"@typescript/native-preview-darwin-arm64": ["@typescript/native-preview-darwin-arm64@7.0.0-dev.20250806.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-rRlWJEkaNCJmd5Ph4NQAJK4NMVwhWuycMKeGxRw8Lj68kNymZTVsNi/TDYN3I1InBj7Fg2kwzygessHHzZTb8A=="],
|
||||
"@typescript/native-preview-darwin-arm64": ["@typescript/native-preview-darwin-arm64@7.0.0-dev.20250816.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-JM+b5qXA1M9G/NFmytUatwEFQSKz1JQDZBsHCLxHbWaGazbg+yJPTzsxKfSz+DW72hyGTldiQqeIdJKwg3G5uQ=="],
|
||||
|
||||
"@typescript/native-preview-darwin-x64": ["@typescript/native-preview-darwin-x64@7.0.0-dev.20250806.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-n2RRV0+SHR6QnaTlJoTX6Q4M7T/P0GtWfOGiKa7QUzQFRQQNdZpTv6P2KAB38b/cfCfX7PRb6mhCWK9FMHwB3w=="],
|
||||
"@typescript/native-preview-darwin-x64": ["@typescript/native-preview-darwin-x64@7.0.0-dev.20250816.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-jwhb6osHxniK+gv23uSjalfTN2XoMiF7X8eIslIRKQ6ICqxf5k8XtOJY0v2lf/t3HxIQQdG962kDVwiGaN3K6w=="],
|
||||
|
||||
"@typescript/native-preview-linux-arm": ["@typescript/native-preview-linux-arm@7.0.0-dev.20250806.1", "", { "os": "linux", "cpu": "arm" }, "sha512-uriaW4phv1E6YkGTacGq8YzdZ11F1lgH1kfRjwDpzNB+UDV4ONqihU0mN1y0JRHhlqqhtKhBL6UnSqd4mbu6zA=="],
|
||||
"@typescript/native-preview-linux-arm": ["@typescript/native-preview-linux-arm@7.0.0-dev.20250816.1", "", { "os": "linux", "cpu": "arm" }, "sha512-syEtVN8E5oOlTOm7CrE3vgoVveBPRKvBbkfShqzwlmq1mw51MWunwO3yDNB3tk9GC1w1VoISoYpe8xm/hUKqIQ=="],
|
||||
|
||||
"@typescript/native-preview-linux-arm64": ["@typescript/native-preview-linux-arm64@7.0.0-dev.20250806.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-fwRhKF3t4OCp4ClfNrXIXwS5G+02AymnmgFGrhvnF0Wg5II8ReVVu9mvazVcfrTN9RtJo4xVofstSF2EbgQ0Sg=="],
|
||||
"@typescript/native-preview-linux-arm64": ["@typescript/native-preview-linux-arm64@7.0.0-dev.20250816.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-e9YXa8QJ2kxBE/eIIci0n906crKxw+C9exAoWysjEsShIsXghIyP3BedMMVRhp2ZigjAPD6pa2ibE1R637C60g=="],
|
||||
|
||||
"@typescript/native-preview-linux-x64": ["@typescript/native-preview-linux-x64@7.0.0-dev.20250806.1", "", { "os": "linux", "cpu": "x64" }, "sha512-EJ5/obfzrDse9KYXzZBpwzdpPad7+y/R+atXApAekIdULHLjYZ/5j/tZ9UMEnMWkCmZaFK6JpfHOG1jOGy71nA=="],
|
||||
"@typescript/native-preview-linux-x64": ["@typescript/native-preview-linux-x64@7.0.0-dev.20250816.1", "", { "os": "linux", "cpu": "x64" }, "sha512-C1pGpcbR2KwAacOQ9e0pAEZeOIZOZ7+GGxQjFQBYxnFdZfT/AvrCP8rKbZhWUx0ghntskl4BejqhGGC3kTc8Cg=="],
|
||||
|
||||
"@typescript/native-preview-win32-arm64": ["@typescript/native-preview-win32-arm64@7.0.0-dev.20250806.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-hHY/4xBsV9SWqb2nAmd9J9FQfsbte5Q4WMB2JVXSbjni0EUdDJmQgdmQ+V7v5teMaaTYhpnRrdsO95jPiR3JAA=="],
|
||||
"@typescript/native-preview-win32-arm64": ["@typescript/native-preview-win32-arm64@7.0.0-dev.20250816.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-tHiD2c4/GQQeSl5kbnNMcjFx0JaC3blbKA9oPMH11hrio/eRnHVrvmatLe5Mo4KOuCS5EHgNUhUvhI43TD0lfw=="],
|
||||
|
||||
"@typescript/native-preview-win32-x64": ["@typescript/native-preview-win32-x64@7.0.0-dev.20250806.1", "", { "os": "win32", "cpu": "x64" }, "sha512-CFFcMz1CwZPL4TKaR10h/sZuRzGE0kLNfXq1zDDgsL1aO8gcOSDuVKrYDdwYGdedLUCINSort7kyv9nIFUKSqQ=="],
|
||||
"@typescript/native-preview-win32-x64": ["@typescript/native-preview-win32-x64@7.0.0-dev.20250816.1", "", { "os": "win32", "cpu": "x64" }, "sha512-4Gm8x1fjnPU441faBu9Mgf9xUWC/DTetulu1bXNcdcrmSkRCFNiIQFtM/IBz47ghDaec4+XiHlrYxkzcaN/avw=="],
|
||||
|
||||
"@ungap/structured-clone": ["@ungap/structured-clone@1.3.0", "", {}, "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g=="],
|
||||
|
||||
@@ -1293,7 +1297,7 @@
|
||||
|
||||
"attr-accept": ["attr-accept@2.2.5", "", {}, "sha512-0bDNnY/u6pPwHDMoF0FieU354oBi0a8rD9FcsLwzcGWbc8KS8KPIi7y+s13OlVY+gMWc/9xEMUgNE6Qm8ZllYQ=="],
|
||||
|
||||
"autumn-js": ["autumn-js@0.1.8", "", { "dependencies": { "rou3": "^0.6.1", "swr": "^2.3.3", "zod": "^3.24.1" }, "peerDependencies": { "better-auth": "^1.2.12", "better-call": "^1.0.12" }, "optionalPeers": ["better-auth", "better-call"] }, "sha512-tayOSj4hFYUvfaIkmjwDyMMnKZ4duTMzuLCOXBT1HZSgO/3guAqEmaz3OQupdw/JbhpnsOEVsQfrFV2dFUU2Mw=="],
|
||||
"autumn-js": ["autumn-js@0.1.12", "", { "dependencies": { "rou3": "^0.6.1", "swr": "^2.3.3", "zod": "^4.0.0" }, "peerDependencies": { "better-auth": "^1.2.12", "better-call": "^1.0.12" }, "optionalPeers": ["better-auth", "better-call"] }, "sha512-FvWM5txsOjal+GHmMlC+pA/+bUQQYNDXQOvwA620UzD3oxpU/25SCDeJDj+Fyzn6pqNdLjeUaUQ/XNPPks23Ug=="],
|
||||
|
||||
"axios": ["axios@1.11.0", "", { "dependencies": { "follow-redirects": "^1.15.6", "form-data": "^4.0.4", "proxy-from-env": "^1.1.0" } }, "sha512-1Lx3WLFQWm3ooKDYZD1eXmoGO9fxYQjrycfHFC8P0sCfQVXyROp0p9PFWBehewBOdCwHc+f/b8I0fMto5eSfwA=="],
|
||||
|
||||
@@ -1301,15 +1305,15 @@
|
||||
|
||||
"balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="],
|
||||
|
||||
"bare-events": ["bare-events@2.6.0", "", {}, "sha512-EKZ5BTXYExaNqi3I3f9RtEsaI/xBSGjE0XZCZilPzFAV/goswFHuPd9jEZlPIZ/iNZJwDSao9qRiScySz7MbQg=="],
|
||||
"bare-events": ["bare-events@2.6.1", "", {}, "sha512-AuTJkq9XmE6Vk0FJVNq5QxETrSA/vKHarWVBG5l/JbdCL1prJemiyJqUS0jrlXO0MftuPq4m3YVYhoNc5+aE/g=="],
|
||||
|
||||
"bare-fs": ["bare-fs@4.1.6", "", { "dependencies": { "bare-events": "^2.5.4", "bare-path": "^3.0.0", "bare-stream": "^2.6.4" }, "peerDependencies": { "bare-buffer": "*" }, "optionalPeers": ["bare-buffer"] }, "sha512-25RsLF33BqooOEFNdMcEhMpJy8EoR88zSMrnOQOaM3USnOK2VmaJ1uaQEwPA6AQjrv1lXChScosN6CzbwbO9OQ=="],
|
||||
"bare-fs": ["bare-fs@4.2.0", "", { "dependencies": { "bare-events": "^2.5.4", "bare-path": "^3.0.0", "bare-stream": "^2.6.4" }, "peerDependencies": { "bare-buffer": "*" }, "optionalPeers": ["bare-buffer"] }, "sha512-oRfrw7gwwBVAWx9S5zPMo2iiOjxyiZE12DmblmMQREgcogbNO0AFaZ+QBxxkEXiPspcpvO/Qtqn8LabUx4uYXg=="],
|
||||
|
||||
"bare-os": ["bare-os@3.6.1", "", {}, "sha512-uaIjxokhFidJP+bmmvKSgiMzj2sV5GPHaZVAIktcxcpCyBFFWO+YlikVAdhmUo2vYFvFhOXIAlldqV29L8126g=="],
|
||||
|
||||
"bare-path": ["bare-path@3.0.0", "", { "dependencies": { "bare-os": "^3.0.1" } }, "sha512-tyfW2cQcB5NN8Saijrhqn0Zh7AnFNsnczRcuWODH0eYAXBsJ5gVxAUuNr7tsHSC6IZ77cA0SitzT+s47kot8Mw=="],
|
||||
|
||||
"bare-stream": ["bare-stream@2.6.5", "", { "dependencies": { "streamx": "^2.21.0" }, "peerDependencies": { "bare-buffer": "*", "bare-events": "*" }, "optionalPeers": ["bare-buffer", "bare-events"] }, "sha512-jSmxKJNJmHySi6hC42zlZnq00rga4jjxcgNZjY9N5WlOe/iOoGRtdwGsHzQv2RlH2KOYMwGUXhf2zXd32BA9RA=="],
|
||||
"bare-stream": ["bare-stream@2.7.0", "", { "dependencies": { "streamx": "^2.21.0" }, "peerDependencies": { "bare-buffer": "*", "bare-events": "*" }, "optionalPeers": ["bare-buffer", "bare-events"] }, "sha512-oyXQNicV1y8nc2aKffH+BUHFRXmx6VrPzlnaEvMhram0nPBrKcEdcyBg5r08D0i8VxngHFAiVyn1QKXpSG0B8A=="],
|
||||
|
||||
"base-convert-int-array": ["base-convert-int-array@1.0.1", "", {}, "sha512-NWqzaoXx8L/SS32R+WmKqnQkVXVYl2PwNJ68QV3RAlRRL1uV+yxJT66abXI1cAvqCXQTyXr7/9NN4Af90/zDVw=="],
|
||||
|
||||
@@ -1319,7 +1323,7 @@
|
||||
|
||||
"basic-ftp": ["basic-ftp@5.0.5", "", {}, "sha512-4Bcg1P8xhUuqcii/S0Z9wiHIrQVPMermM1any+MX5GeGD7faD3/msQUDGLol9wOcz4/jbg/WJnGqoJF6LiBdtg=="],
|
||||
|
||||
"better-auth": ["better-auth@1.3.4", "", { "dependencies": { "@better-auth/utils": "0.2.5", "@better-fetch/fetch": "^1.1.18", "@noble/ciphers": "^0.6.0", "@noble/hashes": "^1.8.0", "@simplewebauthn/browser": "^13.0.0", "@simplewebauthn/server": "^13.0.0", "better-call": "^1.0.12", "defu": "^6.1.4", "jose": "^5.9.6", "kysely": "^0.28.1", "nanostores": "^0.11.3", "zod": "^4.0.5" }, "peerDependencies": { "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0" }, "optionalPeers": ["react", "react-dom"] }, "sha512-JbZYam6Cs3Eu5CSoMK120zSshfaKvrCftSo/+v7524H1RvhryQ7UtMbzagBcXj0Digjj8hZtVkkR4tTZD/wK2g=="],
|
||||
"better-auth": ["better-auth@1.3.6", "", { "dependencies": { "@better-auth/utils": "0.2.6", "@better-fetch/fetch": "^1.1.18", "@noble/ciphers": "^0.6.0", "@noble/hashes": "^1.8.0", "@simplewebauthn/browser": "^13.1.2", "@simplewebauthn/server": "^13.1.2", "better-call": "^1.0.13", "defu": "^6.1.4", "jose": "^5.10.0", "kysely": "^0.28.5", "nanostores": "^0.11.4" }, "peerDependencies": { "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0", "zod": "^3.25.0 || ^4.0.0" }, "optionalPeers": ["react", "react-dom"] }, "sha512-zjwbz9GpgGt3LuvJ8ZXfQeowSRpzdGojVvkhxvXjhCLwGOaOrZmFiNdEVyIKWTraN4oBtgNimcxUIQTGs6OKYg=="],
|
||||
|
||||
"better-call": ["better-call@1.0.13", "", { "dependencies": { "@better-fetch/fetch": "^1.1.4", "rou3": "^0.5.1", "set-cookie-parser": "^2.7.1", "uncrypto": "^0.1.3" } }, "sha512-auqdP9lnNOli9tKpZIiv0nEIwmmyaD/RotM3Mucql+Ef88etoZi/t7Ph5LjlmZt/hiSahhNTt6YVnx6++rziXA=="],
|
||||
|
||||
@@ -1337,7 +1341,7 @@
|
||||
|
||||
"browser-stdout": ["browser-stdout@1.3.1", "", {}, "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw=="],
|
||||
|
||||
"browserslist": ["browserslist@4.25.1", "", { "dependencies": { "caniuse-lite": "^1.0.30001726", "electron-to-chromium": "^1.5.173", "node-releases": "^2.0.19", "update-browserslist-db": "^1.1.3" }, "bin": { "browserslist": "cli.js" } }, "sha512-KGj0KoOMXLpSNkkEI6Z6mShmQy0bc1I+T7K9N81k4WWMrfz+6fQ6es80B/YLAeRoKvjYE1YSHHOW1qe9xIVzHw=="],
|
||||
"browserslist": ["browserslist@4.25.2", "", { "dependencies": { "caniuse-lite": "^1.0.30001733", "electron-to-chromium": "^1.5.199", "node-releases": "^2.0.19", "update-browserslist-db": "^1.1.3" }, "bin": { "browserslist": "cli.js" } }, "sha512-0si2SJK3ooGzIawRu61ZdPCO1IncZwS8IzuX73sPZsXW6EQ/w/DAfPyKI8l1ETTCr2MnvqWitmlCUxgdul45jA=="],
|
||||
|
||||
"buffer": ["buffer@6.0.3", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.2.1" } }, "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA=="],
|
||||
|
||||
@@ -1345,9 +1349,9 @@
|
||||
|
||||
"buffer-from": ["buffer-from@1.1.2", "", {}, "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="],
|
||||
|
||||
"bullmq": ["bullmq@5.56.9", "", { "dependencies": { "cron-parser": "^4.9.0", "ioredis": "^5.4.1", "msgpackr": "^1.11.2", "node-abort-controller": "^3.1.1", "semver": "^7.5.4", "tslib": "^2.0.0", "uuid": "^9.0.0" } }, "sha512-SL7OZG0x9sh/PC6ZVKqibSmPsbjViBaiFAyr3ujJRxb6nlZefb1hU0biJuvfI8/hQa4HtEG9sCHRMiz905B2eg=="],
|
||||
"bullmq": ["bullmq@5.58.0", "", { "dependencies": { "cron-parser": "^4.9.0", "ioredis": "^5.4.1", "msgpackr": "^1.11.2", "node-abort-controller": "^3.1.1", "semver": "^7.5.4", "tslib": "^2.0.0", "uuid": "^9.0.0" } }, "sha512-WIjvoSQ9jprId2gAZaPMQu3jaAkRCN8Wjj/pR39knwjULB7asB6XoSTqvnSbOsfyHMKln8el0MRvRJVY9VdmFA=="],
|
||||
|
||||
"bun-types": ["bun-types@1.2.19", "", { "dependencies": { "@types/node": "*" }, "peerDependencies": { "@types/react": "^19" } }, "sha512-uAOTaZSPuYsWIXRpj7o56Let0g/wjihKCkeRqUBhlLVM/Bt+Fj9xTo+LhC1OV1XDaGkz4hNC80et5xgy+9KTHQ=="],
|
||||
"bun-types": ["bun-types@1.2.20", "", { "dependencies": { "@types/node": "*" }, "peerDependencies": { "@types/react": "^19" } }, "sha512-pxTnQYOrKvdOwyiyd/7sMt9yFOenN004Y6O4lCcCUoKVej48FS5cvTw9geRaEcB9TsDZaJKAxPTVvi8tFsVuXA=="],
|
||||
|
||||
"bytes": ["bytes@3.1.2", "", {}, "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg=="],
|
||||
|
||||
@@ -1359,7 +1363,7 @@
|
||||
|
||||
"camelcase": ["camelcase@6.3.0", "", {}, "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA=="],
|
||||
|
||||
"caniuse-lite": ["caniuse-lite@1.0.30001731", "", {}, "sha512-lDdp2/wrOmTRWuoB5DpfNkC0rJDU8DqRa6nYL6HK6sytw70QMopt/NIc/9SM7ylItlBWfACXk0tEn37UWM/+mg=="],
|
||||
"caniuse-lite": ["caniuse-lite@1.0.30001735", "", {}, "sha512-EV/laoX7Wq2J9TQlyIXRxTJqIw4sxfXS4OYgudGxBYRuTv0q7AM6yMEpU/Vo1I94thg9U6EZ2NfZx9GJq83u7w=="],
|
||||
|
||||
"ccount": ["ccount@2.0.1", "", {}, "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg=="],
|
||||
|
||||
@@ -1373,7 +1377,7 @@
|
||||
|
||||
"character-entities-legacy": ["character-entities-legacy@3.0.0", "", {}, "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ=="],
|
||||
|
||||
"chardet": ["chardet@0.7.0", "", {}, "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA=="],
|
||||
"chardet": ["chardet@2.1.0", "", {}, "sha512-bNFETTG/pM5ryzQ9Ad0lJOTa6HWD/YsScAR3EnCPZRPlQh77JocYktSHOUHelyhm8IARL+o4c4F1bP5KVOjiRA=="],
|
||||
|
||||
"charset": ["charset@1.0.1", "", {}, "sha512-6dVyOOYjpfFcL1Y4qChrAoQLRHvj2ziyhcm0QJlhOcAhykL/k1kTUPbeo+87MNRTRdk2OIIsIXbuF3x2wi5EXg=="],
|
||||
|
||||
@@ -1383,7 +1387,7 @@
|
||||
|
||||
"chownr": ["chownr@3.0.0", "", {}, "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g=="],
|
||||
|
||||
"chromium-bidi": ["chromium-bidi@7.2.0", "", { "dependencies": { "mitt": "^3.0.1", "zod": "^3.24.1" }, "peerDependencies": { "devtools-protocol": "*" } }, "sha512-gREyhyBstermK+0RbcJLbFhcQctg92AGgDe/h/taMJEOLRdtSswBAO9KmvltFSQWgM2LrwWu5SIuEUbdm3JsyQ=="],
|
||||
"chromium-bidi": ["chromium-bidi@7.3.1", "", { "dependencies": { "mitt": "^3.0.1", "zod": "^3.24.1" }, "peerDependencies": { "devtools-protocol": "*" } }, "sha512-i+BMGluhZZc4Jic9L1aHJBTfaopxmCqQxGklyMcqFx4fvF3nI4BJ3bCe1ad474nvYRIo/ZN/VrdA4eOaRZua4Q=="],
|
||||
|
||||
"cjs-module-lexer": ["cjs-module-lexer@1.4.3", "", {}, "sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q=="],
|
||||
|
||||
@@ -1575,7 +1579,7 @@
|
||||
|
||||
"ee-first": ["ee-first@1.1.1", "", {}, "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="],
|
||||
|
||||
"electron-to-chromium": ["electron-to-chromium@1.5.197", "", {}, "sha512-m1xWB3g7vJ6asIFz+2pBUbq3uGmfmln1M9SSvBe4QIFWYrRHylP73zL/3nMjDmwz8V+1xAXQDfBd6+HPW0WvDQ=="],
|
||||
"electron-to-chromium": ["electron-to-chromium@1.5.203", "", {}, "sha512-uz4i0vLhfm6dLZWbz/iH88KNDV+ivj5+2SA+utpgjKaj9Q0iDLuwk6Idhe9BTxciHudyx6IvTvijhkPvFGUQ0g=="],
|
||||
|
||||
"emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="],
|
||||
|
||||
@@ -1599,11 +1603,11 @@
|
||||
|
||||
"es-set-tostringtag": ["es-set-tostringtag@2.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6", "has-tostringtag": "^1.0.2", "hasown": "^2.0.2" } }, "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA=="],
|
||||
|
||||
"es-toolkit": ["es-toolkit@1.39.8", "", {}, "sha512-A8QO9TfF+rltS8BXpdu8OS+rpGgEdnRhqIVxO/ZmNvnXBYgOdSsxukT55ELyP94gZIntWJ+Li9QRrT2u1Kitpg=="],
|
||||
"es-toolkit": ["es-toolkit@1.39.9", "", {}, "sha512-9OtbkZmTA2Qc9groyA1PUNeb6knVTkvB2RSdr/LcJXDL8IdEakaxwXLHXa7VX/Wj0GmdMJPR3WhnPGhiP3E+qg=="],
|
||||
|
||||
"es6-promise": ["es6-promise@4.2.8", "", {}, "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w=="],
|
||||
|
||||
"esbuild": ["esbuild@0.25.8", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.8", "@esbuild/android-arm": "0.25.8", "@esbuild/android-arm64": "0.25.8", "@esbuild/android-x64": "0.25.8", "@esbuild/darwin-arm64": "0.25.8", "@esbuild/darwin-x64": "0.25.8", "@esbuild/freebsd-arm64": "0.25.8", "@esbuild/freebsd-x64": "0.25.8", "@esbuild/linux-arm": "0.25.8", "@esbuild/linux-arm64": "0.25.8", "@esbuild/linux-ia32": "0.25.8", "@esbuild/linux-loong64": "0.25.8", "@esbuild/linux-mips64el": "0.25.8", "@esbuild/linux-ppc64": "0.25.8", "@esbuild/linux-riscv64": "0.25.8", "@esbuild/linux-s390x": "0.25.8", "@esbuild/linux-x64": "0.25.8", "@esbuild/netbsd-arm64": "0.25.8", "@esbuild/netbsd-x64": "0.25.8", "@esbuild/openbsd-arm64": "0.25.8", "@esbuild/openbsd-x64": "0.25.8", "@esbuild/openharmony-arm64": "0.25.8", "@esbuild/sunos-x64": "0.25.8", "@esbuild/win32-arm64": "0.25.8", "@esbuild/win32-ia32": "0.25.8", "@esbuild/win32-x64": "0.25.8" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-vVC0USHGtMi8+R4Kz8rt6JhEWLxsv9Rnu/lGYbPR8u47B+DCBksq9JarW0zOO7bs37hyOK1l2/oqtbciutL5+Q=="],
|
||||
"esbuild": ["esbuild@0.25.9", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.9", "@esbuild/android-arm": "0.25.9", "@esbuild/android-arm64": "0.25.9", "@esbuild/android-x64": "0.25.9", "@esbuild/darwin-arm64": "0.25.9", "@esbuild/darwin-x64": "0.25.9", "@esbuild/freebsd-arm64": "0.25.9", "@esbuild/freebsd-x64": "0.25.9", "@esbuild/linux-arm": "0.25.9", "@esbuild/linux-arm64": "0.25.9", "@esbuild/linux-ia32": "0.25.9", "@esbuild/linux-loong64": "0.25.9", "@esbuild/linux-mips64el": "0.25.9", "@esbuild/linux-ppc64": "0.25.9", "@esbuild/linux-riscv64": "0.25.9", "@esbuild/linux-s390x": "0.25.9", "@esbuild/linux-x64": "0.25.9", "@esbuild/netbsd-arm64": "0.25.9", "@esbuild/netbsd-x64": "0.25.9", "@esbuild/openbsd-arm64": "0.25.9", "@esbuild/openbsd-x64": "0.25.9", "@esbuild/openharmony-arm64": "0.25.9", "@esbuild/sunos-x64": "0.25.9", "@esbuild/win32-arm64": "0.25.9", "@esbuild/win32-ia32": "0.25.9", "@esbuild/win32-x64": "0.25.9" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-CRbODhYyQx3qp7ZEwzxOk4JBqmD/seJrzPa/cGjY1VtIn5E09Oi9/dB4JwctnfZ8Q8iT7rioVv5k/FNT/uf54g=="],
|
||||
|
||||
"esbuild-register": ["esbuild-register@3.6.0", "", { "dependencies": { "debug": "^4.3.4" }, "peerDependencies": { "esbuild": ">=0.12 <1" } }, "sha512-H2/S7Pm8a9CL1uhp9OvjwrBh5Pvx0H8qVOxNu8Wed9Y7qv56MPtq+GGM8RJpq6glYJn9Wspr8uw7l55uyinNeg=="],
|
||||
|
||||
@@ -1615,7 +1619,7 @@
|
||||
|
||||
"escodegen": ["escodegen@2.1.0", "", { "dependencies": { "esprima": "^4.0.1", "estraverse": "^5.2.0", "esutils": "^2.0.2" }, "optionalDependencies": { "source-map": "~0.6.1" }, "bin": { "esgenerate": "bin/esgenerate.js", "escodegen": "bin/escodegen.js" } }, "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w=="],
|
||||
|
||||
"eslint": ["eslint@9.32.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.21.0", "@eslint/config-helpers": "^0.3.0", "@eslint/core": "^0.15.0", "@eslint/eslintrc": "^3.3.1", "@eslint/js": "9.32.0", "@eslint/plugin-kit": "^0.3.4", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", "eslint-scope": "^8.4.0", "eslint-visitor-keys": "^4.2.1", "espree": "^10.4.0", "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "json-stable-stringify-without-jsonify": "^1.0.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", "optionator": "^0.9.3" }, "peerDependencies": { "jiti": "*" }, "optionalPeers": ["jiti"], "bin": { "eslint": "bin/eslint.js" } }, "sha512-LSehfdpgMeWcTZkWZVIJl+tkZ2nuSkyyB9C27MZqFWXuph7DvaowgcTvKqxvpLW1JZIk8PN7hFY3Rj9LQ7m7lg=="],
|
||||
"eslint": ["eslint@9.33.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.21.0", "@eslint/config-helpers": "^0.3.1", "@eslint/core": "^0.15.2", "@eslint/eslintrc": "^3.3.1", "@eslint/js": "9.33.0", "@eslint/plugin-kit": "^0.3.5", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", "eslint-scope": "^8.4.0", "eslint-visitor-keys": "^4.2.1", "espree": "^10.4.0", "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "json-stable-stringify-without-jsonify": "^1.0.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", "optionator": "^0.9.3" }, "peerDependencies": { "jiti": "*" }, "optionalPeers": ["jiti"], "bin": { "eslint": "bin/eslint.js" } }, "sha512-TS9bTNIryDzStCpJN93aC5VRSW3uTx9sClUn4B87pwiCaJh220otoI0X8mJKr+VcPtniMdN8GKjlwgWGUv5ZKA=="],
|
||||
|
||||
"eslint-plugin-react-hooks": ["eslint-plugin-react-hooks@5.2.0", "", { "peerDependencies": { "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0" } }, "sha512-+f15FfK64YQwZdJNELETdn5ibXEUQmW1DZL6KXhNnc2heoy/sg9VJJeT7n8TlMWouzWqSWavFkIhHyIbIAEapg=="],
|
||||
|
||||
@@ -1651,8 +1655,6 @@
|
||||
|
||||
"extend": ["extend@3.0.2", "", {}, "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="],
|
||||
|
||||
"external-editor": ["external-editor@3.1.0", "", { "dependencies": { "chardet": "^0.7.0", "iconv-lite": "^0.4.24", "tmp": "^0.0.33" } }, "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew=="],
|
||||
|
||||
"extract-zip": ["extract-zip@2.0.1", "", { "dependencies": { "debug": "^4.1.1", "get-stream": "^5.1.0", "yauzl": "^2.10.0" }, "optionalDependencies": { "@types/yauzl": "^2.9.1" }, "bin": { "extract-zip": "cli.js" } }, "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg=="],
|
||||
|
||||
"fast-copy": ["fast-copy@3.0.2", "", {}, "sha512-dl0O9Vhju8IrcLndv2eU4ldt1ftXMqqfgN4H1cpmGV7P6jeB9FwpN9a2c8DPGE1Ys88rNUJVYDHq73CGAGOPfQ=="],
|
||||
@@ -1677,7 +1679,7 @@
|
||||
|
||||
"fd-slicer": ["fd-slicer@1.1.0", "", { "dependencies": { "pend": "~1.2.0" } }, "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g=="],
|
||||
|
||||
"fdir": ["fdir@6.4.6", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w=="],
|
||||
"fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="],
|
||||
|
||||
"fecha": ["fecha@4.2.3", "", {}, "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw=="],
|
||||
|
||||
@@ -1833,13 +1835,13 @@
|
||||
|
||||
"input-otp": ["input-otp@1.4.2", "", { "peerDependencies": { "react": "^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc" } }, "sha512-l3jWwYNvrEa6NTCt7BECfCm48GvwuZzkoeG3gBL2w4CHeOXW3eKFmf9UNYkNfYc3mxMrthMnxjIE07MT0zLBQA=="],
|
||||
|
||||
"inquirer": ["inquirer@12.9.0", "", { "dependencies": { "@inquirer/core": "^10.1.15", "@inquirer/prompts": "^7.8.0", "@inquirer/type": "^3.0.8", "ansi-escapes": "^4.3.2", "mute-stream": "^2.0.0", "run-async": "^4.0.5", "rxjs": "^7.8.2" }, "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-LlFVmvWVCun7uEgPB3vups9NzBrjJn48kRNtFGw3xU1H5UXExTEz/oF1JGLaB0fvlkUB+W6JfgLcSEaSdH7RPA=="],
|
||||
"inquirer": ["inquirer@12.9.2", "", { "dependencies": { "@inquirer/core": "^10.1.15", "@inquirer/prompts": "^7.8.2", "@inquirer/type": "^3.0.8", "ansi-escapes": "^4.3.2", "mute-stream": "^2.0.0", "run-async": "^4.0.5", "rxjs": "^7.8.2" }, "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-XPukbomHpZc3GAajQdAcuqa5NCIFhUcLMcXXSpJLM2RW/u/5JHLxjLF206GNTJARib8XBBRqyMbaNrDzXROdoA=="],
|
||||
|
||||
"internmap": ["internmap@2.0.3", "", {}, "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg=="],
|
||||
|
||||
"ioredis": ["ioredis@5.7.0", "", { "dependencies": { "@ioredis/commands": "^1.3.0", "cluster-key-slot": "^1.1.0", "debug": "^4.3.4", "denque": "^2.1.0", "lodash.defaults": "^4.2.0", "lodash.isarguments": "^3.1.0", "redis-errors": "^1.2.0", "redis-parser": "^3.0.0", "standard-as-callback": "^2.1.0" } }, "sha512-NUcA93i1lukyXU+riqEyPtSEkyFq8tX90uL659J+qpCZ3rEdViB/APC58oAhIh3+bJln2hzdlZbBZsGNrlsR8g=="],
|
||||
|
||||
"ip-address": ["ip-address@9.0.5", "", { "dependencies": { "jsbn": "1.1.0", "sprintf-js": "^1.1.3" } }, "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g=="],
|
||||
"ip-address": ["ip-address@10.0.1", "", {}, "sha512-NWv9YLW4PoW2B7xtzaS3NCot75m6nK7Icdv0o3lfMceJVRfSoQwqD4wEH5rLwoKJwUiZ/rfpiVBhnaF0FK4HoA=="],
|
||||
|
||||
"ip-regex": ["ip-regex@5.0.0", "", {}, "sha512-fOCG6lhoKKakwv+C6KdsOnGvgXnmgfmp0myi3bcNwj3qfwPAxRKWEuFhvEFF7ceYIz6+1jRZ+yguLFAmUNPEfw=="],
|
||||
|
||||
@@ -1879,8 +1881,6 @@
|
||||
|
||||
"isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="],
|
||||
|
||||
"isows": ["isows@1.0.7", "", { "peerDependencies": { "ws": "*" } }, "sha512-I1fSfDCZL5P0v33sVqeTDSpcstAg/N+wF5HS033mogOVIp4B+oHC7oOCsA3axAbBSGTJ8QubbNmnIRN/h8U7hg=="],
|
||||
|
||||
"jackspeak": ["jackspeak@3.4.3", "", { "dependencies": { "@isaacs/cliui": "^8.0.2" }, "optionalDependencies": { "@pkgjs/parseargs": "^0.11.0" } }, "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw=="],
|
||||
|
||||
"jiti": ["jiti@2.5.1", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-twQoecYPiVA5K/h6SxtORw/Bs3ar+mLUtoPSc7iMXzQzK8d7eJ/R09wmTwAjiamETn1cXYPGfNnu7DMoHgu12w=="],
|
||||
@@ -1895,8 +1895,6 @@
|
||||
|
||||
"js-yaml": ["js-yaml@4.1.0", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA=="],
|
||||
|
||||
"jsbn": ["jsbn@1.1.0", "", {}, "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A=="],
|
||||
|
||||
"jsesc": ["jsesc@3.1.0", "", { "bin": { "jsesc": "bin/jsesc" } }, "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA=="],
|
||||
|
||||
"json-bigint": ["json-bigint@1.0.0", "", { "dependencies": { "bignumber.js": "^9.0.0" } }, "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ=="],
|
||||
@@ -1947,7 +1945,7 @@
|
||||
|
||||
"ksuid": ["ksuid@3.0.0", "", { "dependencies": { "base-convert-int-array": "^1.0.1" } }, "sha512-81CkBGn/06ZVAjGvFZi6fVG8VcPeMH0JpJ4V1Z9VwrMMaGIeAjY4jrVdrIcxhL9I2ZUU6t5uiyswcmkk+KZegA=="],
|
||||
|
||||
"kysely": ["kysely@0.28.4", "", {}, "sha512-pfQj8/Bo3KSzC1HIZB5MeeYRWcDmx1ZZv8H25LsyeygqXE+gfsbUAgPT1GSYZFctB1cdOVlv+OifuCls2mQSnw=="],
|
||||
"kysely": ["kysely@0.28.5", "", {}, "sha512-rlB0I/c6FBDWPcQoDtkxi9zIvpmnV5xoIalfCMSMCa7nuA6VGA3F54TW9mEgX4DVf10sXAWCF5fDbamI/5ZpKA=="],
|
||||
|
||||
"leac": ["leac@0.6.0", "", {}, "sha512-y+SqErxb8h7nE/fiEX07jsbuhrpO9lL8eca7/Y1nuWV2moNlXhyd59iDGcRf6moVyDMbmTNzL40SUyrFU/yDpg=="],
|
||||
|
||||
@@ -2139,8 +2137,6 @@
|
||||
|
||||
"ora": ["ora@8.2.0", "", { "dependencies": { "chalk": "^5.3.0", "cli-cursor": "^5.0.0", "cli-spinners": "^2.9.2", "is-interactive": "^2.0.0", "is-unicode-supported": "^2.0.0", "log-symbols": "^6.0.0", "stdin-discarder": "^0.2.2", "string-width": "^7.2.0", "strip-ansi": "^7.1.0" } }, "sha512-weP+BZ8MVNnlCm8c0Qdc1WSWq4Qn7I+9CJGm7Qali6g44e/PUzbjNqJX5NJ9ljlNMosfJvg1fKEGILklK9cwnw=="],
|
||||
|
||||
"os-tmpdir": ["os-tmpdir@1.0.2", "", {}, "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g=="],
|
||||
|
||||
"p-limit": ["p-limit@3.1.0", "", { "dependencies": { "yocto-queue": "^0.1.0" } }, "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ=="],
|
||||
|
||||
"p-locate": ["p-locate@5.0.0", "", { "dependencies": { "p-limit": "^3.0.2" } }, "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw=="],
|
||||
@@ -2195,7 +2191,7 @@
|
||||
|
||||
"picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="],
|
||||
|
||||
"pino": ["pino@9.7.0", "", { "dependencies": { "atomic-sleep": "^1.0.0", "fast-redact": "^3.1.1", "on-exit-leak-free": "^2.1.0", "pino-abstract-transport": "^2.0.0", "pino-std-serializers": "^7.0.0", "process-warning": "^5.0.0", "quick-format-unescaped": "^4.0.3", "real-require": "^0.2.0", "safe-stable-stringify": "^2.3.1", "sonic-boom": "^4.0.1", "thread-stream": "^3.0.0" }, "bin": { "pino": "bin.js" } }, "sha512-vnMCM6xZTb1WDmLvtG2lE/2p+t9hDEIvTWJsu6FejkE62vB7gDhvzrpFR4Cw2to+9JNQxVnkAKVPA1KPB98vWg=="],
|
||||
"pino": ["pino@9.9.0", "", { "dependencies": { "atomic-sleep": "^1.0.0", "fast-redact": "^3.1.1", "on-exit-leak-free": "^2.1.0", "pino-abstract-transport": "^2.0.0", "pino-std-serializers": "^7.0.0", "process-warning": "^5.0.0", "quick-format-unescaped": "^4.0.3", "real-require": "^0.2.0", "safe-stable-stringify": "^2.3.1", "sonic-boom": "^4.0.1", "thread-stream": "^3.0.0" }, "bin": { "pino": "bin.js" } }, "sha512-zxsRIQG9HzG+jEljmvmZupOMDUQ0Jpj0yAgE28jQvvrdYTlEaiGwelJpdndMl/MBuRr70heIj83QyqJUWaU8mQ=="],
|
||||
|
||||
"pino-abstract-transport": ["pino-abstract-transport@1.2.0", "", { "dependencies": { "readable-stream": "^4.0.0", "split2": "^4.0.0" } }, "sha512-Guhh8EZfPCfH+PMXAb6rKOjGQEoy0xlAIn+irODG5kgfYV+BQ0rGYYWTIel3P5mmyXqkYkPmdIkywsn6QKUR1Q=="],
|
||||
|
||||
@@ -2217,7 +2213,7 @@
|
||||
|
||||
"postgres-interval": ["postgres-interval@1.2.0", "", { "dependencies": { "xtend": "^4.0.0" } }, "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ=="],
|
||||
|
||||
"posthog-js": ["posthog-js@1.258.6", "", { "dependencies": { "core-js": "^3.38.1", "fflate": "^0.4.8", "preact": "^10.19.3", "web-vitals": "^4.2.4" }, "peerDependencies": { "@rrweb/types": "2.0.0-alpha.17", "rrweb-snapshot": "2.0.0-alpha.17" }, "optionalPeers": ["@rrweb/types", "rrweb-snapshot"] }, "sha512-vL5AGG+rOoRg3LGquMfBPO55jD4bGl0CiV44SHdHAoBnOVDDAqxczRGDqMdxor+VLx3/ofTFOJ2FNprfAHp70Q=="],
|
||||
"posthog-js": ["posthog-js@1.260.1", "", { "dependencies": { "core-js": "^3.38.1", "fflate": "^0.4.8", "preact": "^10.19.3", "web-vitals": "^4.2.4" }, "peerDependencies": { "@rrweb/types": "2.0.0-alpha.17", "rrweb-snapshot": "2.0.0-alpha.17" }, "optionalPeers": ["@rrweb/types", "rrweb-snapshot"] }, "sha512-DD8ZSRpdScacMqtqUIvMFme8lmOWkOvExG8VvjONE7Cm3xpRH5xXpfrwMJE4bayTGWKMx4ij6SfphK6dm/o2ug=="],
|
||||
|
||||
"posthog-node": ["posthog-node@4.18.0", "", { "dependencies": { "axios": "^1.8.2" } }, "sha512-XROs1h+DNatgKh/AlIlCtDxWzwrKdYDb2mOs58n4yN8BkGN9ewqeQwG5ApS4/IzwCb7HPttUkOVulkYatd2PIw=="],
|
||||
|
||||
@@ -2241,7 +2237,7 @@
|
||||
|
||||
"property-information": ["property-information@7.1.0", "", {}, "sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ=="],
|
||||
|
||||
"protobufjs": ["protobufjs@7.5.3", "", { "dependencies": { "@protobufjs/aspromise": "^1.1.2", "@protobufjs/base64": "^1.1.2", "@protobufjs/codegen": "^2.0.4", "@protobufjs/eventemitter": "^1.1.0", "@protobufjs/fetch": "^1.1.0", "@protobufjs/float": "^1.0.2", "@protobufjs/inquire": "^1.1.0", "@protobufjs/path": "^1.1.2", "@protobufjs/pool": "^1.1.0", "@protobufjs/utf8": "^1.1.0", "@types/node": ">=13.7.0", "long": "^5.0.0" } }, "sha512-sildjKwVqOI2kmFDiXQ6aEB0fjYTafpEvIBs8tOR8qI4spuL9OPROLVu2qZqi/xgCfsHIwVqlaF8JBjWFHnKbw=="],
|
||||
"protobufjs": ["protobufjs@7.5.4", "", { "dependencies": { "@protobufjs/aspromise": "^1.1.2", "@protobufjs/base64": "^1.1.2", "@protobufjs/codegen": "^2.0.4", "@protobufjs/eventemitter": "^1.1.0", "@protobufjs/fetch": "^1.1.0", "@protobufjs/float": "^1.0.2", "@protobufjs/inquire": "^1.1.0", "@protobufjs/path": "^1.1.2", "@protobufjs/pool": "^1.1.0", "@protobufjs/utf8": "^1.1.0", "@types/node": ">=13.7.0", "long": "^5.0.0" } }, "sha512-CvexbZtbov6jW2eXAvLukXjXUW1TzFaivC46BpWc/3BpcCysb5Vffu+B3XHMm8lVEuy2Mm4XGex8hBSg1yapPg=="],
|
||||
|
||||
"proxy-addr": ["proxy-addr@2.0.7", "", { "dependencies": { "forwarded": "0.2.0", "ipaddr.js": "1.9.1" } }, "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg=="],
|
||||
|
||||
@@ -2255,7 +2251,7 @@
|
||||
|
||||
"punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="],
|
||||
|
||||
"puppeteer-core": ["puppeteer-core@24.16.0", "", { "dependencies": { "@puppeteer/browsers": "2.10.6", "chromium-bidi": "7.2.0", "debug": "^4.4.1", "devtools-protocol": "0.0.1475386", "typed-query-selector": "^2.12.0", "ws": "^8.18.3" } }, "sha512-tZ0tJiOYaDGTRzzr2giDpf8O/55JsoqkrafS1Xu4H6S8oP4eeL6RbZzY9OzjShSf5EQvx/zAc55QKpDqzXos/Q=="],
|
||||
"puppeteer-core": ["puppeteer-core@24.16.2", "", { "dependencies": { "@puppeteer/browsers": "2.10.6", "chromium-bidi": "7.3.1", "debug": "^4.4.1", "devtools-protocol": "0.0.1475386", "typed-query-selector": "^2.12.0", "ws": "^8.18.3" } }, "sha512-areKSSQzpoHa5nCk3uD/o504yjrW5ws0N6jZfdFZ3a4H+Q7NBgvuDydjN5P87jN4Rj+eIpLcK3ELOThTtYuuxg=="],
|
||||
|
||||
"pvtsutils": ["pvtsutils@1.3.6", "", { "dependencies": { "tslib": "^2.8.1" } }, "sha512-PLgQXQ6H2FWCaeRak8vvk1GW462lMxB5s3Jm673N82zI4vqtVUPuZdffdZbPDFRoU8kAhItWFtPCWiPpp4/EDg=="],
|
||||
|
||||
@@ -2291,7 +2287,7 @@
|
||||
|
||||
"react-email": ["react-email@4.0.16", "", { "dependencies": { "@babel/parser": "^7.27.0", "@babel/traverse": "^7.27.0", "chalk": "^5.0.0", "chokidar": "^4.0.3", "commander": "^13.0.0", "debounce": "^2.0.0", "esbuild": "^0.25.0", "glob": "^11.0.0", "log-symbols": "^7.0.0", "mime-types": "^3.0.0", "next": "^15.3.1", "normalize-path": "^3.0.0", "ora": "^8.0.0", "socket.io": "^4.8.1" }, "bin": { "email": "dist/cli/index.mjs" } }, "sha512-auhFU+nQxAkKkP6lQhPyGsa9exwfUEzp2BwZnjHokCwphZlg30tu4t1LgdKRwGPYsi7XNGy6asbVLAUhOVpzzg=="],
|
||||
|
||||
"react-hot-toast": ["react-hot-toast@2.5.2", "", { "dependencies": { "csstype": "^3.1.3", "goober": "^2.1.16" }, "peerDependencies": { "react": ">=16", "react-dom": ">=16" } }, "sha512-Tun3BbCxzmXXM7C+NI4qiv6lT0uwGh4oAfeJyNOjYUejTsm35mK9iCaYLGv8cBz9L5YxZLx/2ii7zsIwPtPUdw=="],
|
||||
"react-hot-toast": ["react-hot-toast@2.6.0", "", { "dependencies": { "csstype": "^3.1.3", "goober": "^2.1.16" }, "peerDependencies": { "react": ">=16", "react-dom": ">=16" } }, "sha512-bH+2EBMZ4sdyou/DPrfgIouFpcRLCJ+HoCA32UoAYHn6T3Ur5yfcDCeSr5mwldl6pFOsiocmrXMuoCJ1vV8bWg=="],
|
||||
|
||||
"react-hotkeys-hook": ["react-hotkeys-hook@4.6.2", "", { "peerDependencies": { "react": ">=16.8.1", "react-dom": ">=16.8.1" } }, "sha512-FmP+ZriY3EG59Ug/lxNfrObCnW9xQShgk7Nb83+CkpfkcCpfS95ydv+E9JuXA5cp8KtskU7LGlIARpkc92X22Q=="],
|
||||
|
||||
@@ -2309,9 +2305,9 @@
|
||||
|
||||
"react-remove-scroll-bar": ["react-remove-scroll-bar@2.3.8", "", { "dependencies": { "react-style-singleton": "^2.2.2", "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" }, "optionalPeers": ["@types/react"] }, "sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q=="],
|
||||
|
||||
"react-router": ["react-router@7.7.1", "", { "dependencies": { "cookie": "^1.0.1", "set-cookie-parser": "^2.6.0" }, "peerDependencies": { "react": ">=18", "react-dom": ">=18" }, "optionalPeers": ["react-dom"] }, "sha512-jVKHXoWRIsD/qS6lvGveckwb862EekvapdHJN/cGmzw40KnJH5gg53ujOJ4qX6EKIK9LSBfFed/xiQ5yeXNrUA=="],
|
||||
"react-router": ["react-router@7.8.1", "", { "dependencies": { "cookie": "^1.0.1", "set-cookie-parser": "^2.6.0" }, "peerDependencies": { "react": ">=18", "react-dom": ">=18" }, "optionalPeers": ["react-dom"] }, "sha512-5cy/M8DHcG51/KUIka1nfZ2QeylS4PJRs6TT8I4PF5axVsI5JUxp0hC0NZ/AEEj8Vw7xsEoD7L/6FY+zoYaOGA=="],
|
||||
|
||||
"react-router-dom": ["react-router-dom@7.7.1", "", { "dependencies": { "react-router": "7.7.1" }, "peerDependencies": { "react": ">=18", "react-dom": ">=18" } }, "sha512-bavdk2BA5r3MYalGKZ01u8PGuDBloQmzpBZVhDLrOOv1N943Wq6dcM9GhB3x8b7AbqPMEezauv4PeGkAJfy7FQ=="],
|
||||
"react-router-dom": ["react-router-dom@7.8.1", "", { "dependencies": { "react-router": "7.8.1" }, "peerDependencies": { "react": ">=18", "react-dom": ">=18" } }, "sha512-NkgBCF3sVgCiAWIlSt89GR2PLaksMpoo3HDCorpRfnCEfdtRPLiuTf+CNXvqZMI5SJLZCLpVCvcZrTdtGW64xQ=="],
|
||||
|
||||
"react-style-singleton": ["react-style-singleton@2.2.3", "", { "dependencies": { "get-nonce": "^1.0.0", "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ=="],
|
||||
|
||||
@@ -2357,7 +2353,7 @@
|
||||
|
||||
"rou3": ["rou3@0.6.3", "", {}, "sha512-1HSG1ENTj7Kkm5muMnXuzzfdDOf7CFnbSYFA+H3Fp/rB9lOCxCPgy1jlZxTKyFoC5jJay8Mmc+VbPLYRjzYLrA=="],
|
||||
|
||||
"run-async": ["run-async@4.0.5", "", {}, "sha512-oN9GTgxUNDBumHTTDmQ8dep6VIJbgj9S3dPP+9XylVLIK4xB9XTXtKWROd5pnhdXR9k0EgO1JRcNh0T+Ny2FsA=="],
|
||||
"run-async": ["run-async@4.0.6", "", {}, "sha512-IoDlSLTs3Yq593mb3ZoKWKXMNu3UpObxhgA/Xuid5p4bbfi2jdY1Hj0m1K+0/tEuQTxIGMhQDqGjKb7RuxGpAQ=="],
|
||||
|
||||
"run-parallel": ["run-parallel@1.2.0", "", { "dependencies": { "queue-microtask": "^1.2.2" } }, "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA=="],
|
||||
|
||||
@@ -2425,7 +2421,7 @@
|
||||
|
||||
"socket.io-parser": ["socket.io-parser@4.2.4", "", { "dependencies": { "@socket.io/component-emitter": "~3.1.0", "debug": "~4.3.1" } }, "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew=="],
|
||||
|
||||
"socks": ["socks@2.8.6", "", { "dependencies": { "ip-address": "^9.0.5", "smart-buffer": "^4.2.0" } }, "sha512-pe4Y2yzru68lXCb38aAqRf5gvN8YdjP1lok5o0J7BOHljkyCGKVz7H3vpVIXKD27rj2giOJ7DwVyk/GWrPHDWA=="],
|
||||
"socks": ["socks@2.8.7", "", { "dependencies": { "ip-address": "^10.0.1", "smart-buffer": "^4.2.0" } }, "sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A=="],
|
||||
|
||||
"socks-proxy-agent": ["socks-proxy-agent@8.0.5", "", { "dependencies": { "agent-base": "^7.1.2", "debug": "^4.3.4", "socks": "^2.8.3" } }, "sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw=="],
|
||||
|
||||
@@ -2443,8 +2439,6 @@
|
||||
|
||||
"split2": ["split2@4.2.0", "", {}, "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg=="],
|
||||
|
||||
"sprintf-js": ["sprintf-js@1.1.3", "", {}, "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA=="],
|
||||
|
||||
"stack-trace": ["stack-trace@0.0.10", "", {}, "sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg=="],
|
||||
|
||||
"standard-as-callback": ["standard-as-callback@2.1.0", "", {}, "sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A=="],
|
||||
@@ -2487,13 +2481,11 @@
|
||||
|
||||
"supports-preserve-symlinks-flag": ["supports-preserve-symlinks-flag@1.0.0", "", {}, "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w=="],
|
||||
|
||||
"svix": ["svix@1.70.1", "", { "dependencies": { "@stablelib/base64": "^1.0.0", "@types/node": "^22.7.5", "es6-promise": "^4.2.8", "fast-sha256": "^1.3.0", "svix-fetch": "^3.0.0", "url-parse": "^1.5.10", "uuid": "^10.0.0" } }, "sha512-UDO8VBNyfZcqRjQQLanrOanGK+nCaMhBT7LJyXQBhPLEUcoDzRUhKujFdivl2OrleUVNknmuuz7CnYZ+4Axugg=="],
|
||||
|
||||
"svix-fetch": ["svix-fetch@3.0.0", "", { "dependencies": { "node-fetch": "^2.6.1", "whatwg-fetch": "^3.4.1" } }, "sha512-rcADxEFhSqHbraZIsjyZNh4TF6V+koloX1OzZ+AQuObX9mZ2LIMhm1buZeuc5BIZPftZpJCMBsSiBaeszo9tRw=="],
|
||||
"svix": ["svix@1.73.0", "", { "dependencies": { "@stablelib/base64": "^1.0.0", "@types/node": "^22.7.5", "es6-promise": "^4.2.8", "fast-sha256": "^1.3.0", "url-parse": "^1.5.10", "uuid": "^10.0.0" } }, "sha512-EqaQcuJezFxJBWvtjfRhhDtVYcrYdzLiVqc2Naw3aGwd3FrCzqLUwLHEWo8LE2MoPEUGm/2xSt8b9W7NLQr25w=="],
|
||||
|
||||
"svix-react": ["svix-react@1.13.5", "", { "dependencies": { "iframe-resizer-react": "^1.1.0" }, "peerDependencies": { "react": ">=16", "react-dom": ">=16", "svix": ">=1.26.0" } }, "sha512-2UnpYFvr5yCZuvpaYA4F1A/zv8NGyXHas8xBeR6ozJ1MOLKvdf0anqNE3ZTyUr+ngr7Sd3tcQgiJt1vpFU35xQ=="],
|
||||
|
||||
"swr": ["swr@2.3.4", "", { "dependencies": { "dequal": "^2.0.3", "use-sync-external-store": "^1.4.0" }, "peerDependencies": { "react": "^16.11.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-bYd2lrhc+VarcpkgWclcUi92wYCpOgMws9Sd1hG1ntAu0NEy+14CbotuFjshBU2kt9rYj9TSmDcybpxpeTU1fg=="],
|
||||
"swr": ["swr@2.3.6", "", { "dependencies": { "dequal": "^2.0.3", "use-sync-external-store": "^1.4.0" }, "peerDependencies": { "react": "^16.11.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-wfHRmHWk/isGNMwlLGlZX5Gzz/uTgo0o2IRuTMcf4CPuPFJZlq0rDaKUx+ozB5nBOReNV1kiOyzMfj+MBMikLw=="],
|
||||
|
||||
"symbol-observable": ["symbol-observable@1.2.0", "", {}, "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ=="],
|
||||
|
||||
@@ -2501,7 +2493,7 @@
|
||||
|
||||
"tailwind-scrollbar-hide": ["tailwind-scrollbar-hide@4.0.0", "", { "peerDependencies": { "tailwindcss": ">=3.0.0 || >= 4.0.0 || >= 4.0.0-beta.8 || >= 4.0.0-alpha.20" } }, "sha512-gobtvVcThB2Dxhy0EeYSS1RKQJ5baDFkamkhwBvzvevwX6L4XQfpZ3me9s25Ss1ecFVT5jPYJ50n+7xTBJG9WQ=="],
|
||||
|
||||
"tailwindcss": ["tailwindcss@4.1.11", "", {}, "sha512-2E9TBm6MDD/xKYe+dvJZAmg3yxIEDNRc0jwlNyDg/4Fil2QcSLjFKGVff0lAf1jjeaArlG/M75Ey/EYr/OJtBA=="],
|
||||
"tailwindcss": ["tailwindcss@4.1.12", "", {}, "sha512-DzFtxOi+7NsFf7DBtI3BJsynR+0Yp6etH+nRPTbpWnS2pZBaSksv/JGctNwSWzbFjp0vxSqknaUylseZqMDGrA=="],
|
||||
|
||||
"tailwindcss-animate": ["tailwindcss-animate@1.0.7", "", { "peerDependencies": { "tailwindcss": ">=3.0.0 || insiders" } }, "sha512-bl6mpH3T7I3UFxuvDEXLxy/VuFxBk5bbzplh7tXI68mwMokNYd1t9qPBHlnyTwfa4JGC4zP516I1hYYtQ/vspA=="],
|
||||
|
||||
@@ -2529,8 +2521,6 @@
|
||||
|
||||
"tinyglobby": ["tinyglobby@0.2.14", "", { "dependencies": { "fdir": "^6.4.4", "picomatch": "^4.0.2" } }, "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ=="],
|
||||
|
||||
"tmp": ["tmp@0.0.33", "", { "dependencies": { "os-tmpdir": "~1.0.2" } }, "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw=="],
|
||||
|
||||
"to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="],
|
||||
|
||||
"toidentifier": ["toidentifier@1.0.1", "", {}, "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA=="],
|
||||
@@ -2555,7 +2545,7 @@
|
||||
|
||||
"tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
|
||||
|
||||
"tsx": ["tsx@4.20.3", "", { "dependencies": { "esbuild": "~0.25.0", "get-tsconfig": "^4.7.5" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "bin": { "tsx": "dist/cli.mjs" } }, "sha512-qjbnuR9Tr+FJOMBqJCW5ehvIo/buZq7vH7qD7JziU98h6l3qGy0a/yPFjwO+y0/T7GFpNgNAvEcPPVfyT8rrPQ=="],
|
||||
"tsx": ["tsx@4.20.4", "", { "dependencies": { "esbuild": "~0.25.0", "get-tsconfig": "^4.7.5" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "bin": { "tsx": "dist/cli.mjs" } }, "sha512-yyxBKfORQ7LuRt/BQKBXrpcq59ZvSW0XxwfjAt3w2/8PmdxaFzijtMhTawprSHhpzeM5BgU2hXHG3lklIERZXg=="],
|
||||
|
||||
"type-check": ["type-check@0.4.0", "", { "dependencies": { "prelude-ls": "^1.2.1" } }, "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew=="],
|
||||
|
||||
@@ -2567,7 +2557,7 @@
|
||||
|
||||
"typescript": ["typescript@5.9.2", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A=="],
|
||||
|
||||
"typescript-eslint": ["typescript-eslint@8.39.0", "", { "dependencies": { "@typescript-eslint/eslint-plugin": "8.39.0", "@typescript-eslint/parser": "8.39.0", "@typescript-eslint/typescript-estree": "8.39.0", "@typescript-eslint/utils": "8.39.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-lH8FvtdtzcHJCkMOKnN73LIn6SLTpoojgJqDAxPm1jCR14eWSGPX8ul/gggBdPMk/d5+u9V854vTYQ8T5jF/1Q=="],
|
||||
"typescript-eslint": ["typescript-eslint@8.39.1", "", { "dependencies": { "@typescript-eslint/eslint-plugin": "8.39.1", "@typescript-eslint/parser": "8.39.1", "@typescript-eslint/typescript-estree": "8.39.1", "@typescript-eslint/utils": "8.39.1" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-GDUv6/NDYngUlNvwaHM1RamYftxf782IyEDbdj3SeaIHHv8fNQVRC++fITT7kUJV/5rIA/tkoRSSskt6osEfqg=="],
|
||||
|
||||
"uncrypto": ["uncrypto@0.1.3", "", {}, "sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q=="],
|
||||
|
||||
@@ -2633,8 +2623,6 @@
|
||||
|
||||
"webidl-conversions": ["webidl-conversions@3.0.1", "", {}, "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="],
|
||||
|
||||
"whatwg-fetch": ["whatwg-fetch@3.6.20", "", {}, "sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg=="],
|
||||
|
||||
"whatwg-url": ["whatwg-url@5.0.0", "", { "dependencies": { "tr46": "~0.0.3", "webidl-conversions": "^3.0.0" } }, "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw=="],
|
||||
|
||||
"which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="],
|
||||
@@ -2685,13 +2673,13 @@
|
||||
|
||||
"@ai-sdk/provider-utils/secure-json-parse": ["secure-json-parse@2.7.0", "", {}, "sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw=="],
|
||||
|
||||
"@ampproject/remapping/@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.29", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ=="],
|
||||
"@ampproject/remapping/@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.30", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-GQ7Nw5G2lTu/BtHTKfXhKHok2WGetd4XYcVKGx00SjAk8GMwgJM3zr6zORiPGuOE+/vkc90KtTosSSvaCjKb2Q=="],
|
||||
|
||||
"@anthropic-ai/sdk/@types/node": ["@types/node@18.19.121", "", { "dependencies": { "undici-types": "~5.26.4" } }, "sha512-bHOrbyztmyYIi4f1R0s17QsPs1uyyYnGcXeZoGEd227oZjry0q6XQBQxd82X1I57zEfwO8h9Xo+Kl5gX1d9MwQ=="],
|
||||
"@anthropic-ai/sdk/@types/node": ["@types/node@18.19.123", "", { "dependencies": { "undici-types": "~5.26.4" } }, "sha512-K7DIaHnh0mzVxreCR9qwgNxp3MH9dltPNIEddW9MYUlcKAzm+3grKNSTe2vCJHI1FaLpvpL5JGJrz1UZDKYvDg=="],
|
||||
|
||||
"@autumn/server/@types/node": ["@types/node@22.17.0", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-bbAKTCqX5aNVryi7qXVMi+OkB3w/OyblodicMbvE38blyAz7GxXf6XYhklokijuPwwVg9sDLKRxt0ZHXQwZVfQ=="],
|
||||
"@autumn/server/@types/node": ["@types/node@22.17.2", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-gL6z5N9Jm9mhY+U2KXZpteb+09zyffliRkZyZOHODGATyC5B1Jt/7TzuuiLkFsSUMLbS1OLmlj/E+/3KF4Q/4w=="],
|
||||
|
||||
"@autumn/vite/@types/node": ["@types/node@22.17.0", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-bbAKTCqX5aNVryi7qXVMi+OkB3w/OyblodicMbvE38blyAz7GxXf6XYhklokijuPwwVg9sDLKRxt0ZHXQwZVfQ=="],
|
||||
"@autumn/vite/@types/node": ["@types/node@22.17.2", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-gL6z5N9Jm9mhY+U2KXZpteb+09zyffliRkZyZOHODGATyC5B1Jt/7TzuuiLkFsSUMLbS1OLmlj/E+/3KF4Q/4w=="],
|
||||
|
||||
"@autumn/vite/date-fns": ["date-fns@3.6.0", "", {}, "sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww=="],
|
||||
|
||||
@@ -2703,7 +2691,7 @@
|
||||
|
||||
"@babel/core/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
|
||||
|
||||
"@babel/generator/@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.29", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ=="],
|
||||
"@babel/generator/@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.30", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-GQ7Nw5G2lTu/BtHTKfXhKHok2WGetd4XYcVKGx00SjAk8GMwgJM3zr6zORiPGuOE+/vkc90KtTosSSvaCjKb2Q=="],
|
||||
|
||||
"@babel/helper-compilation-targets/lru-cache": ["lru-cache@5.1.1", "", { "dependencies": { "yallist": "^3.0.2" } }, "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w=="],
|
||||
|
||||
@@ -2711,12 +2699,12 @@
|
||||
|
||||
"@babel/helper-create-class-features-plugin/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
|
||||
|
||||
"@better-auth/stripe/zod": ["zod@4.0.15", "", {}, "sha512-2IVHb9h4Mt6+UXkyMs0XbfICUh1eUrlJJAOupBHUhLRnKkruawyDddYRCs0Eizt900ntIMk9/4RksYl+FgSpcQ=="],
|
||||
|
||||
"@browserbasehq/sdk/@types/node": ["@types/node@18.19.121", "", { "dependencies": { "undici-types": "~5.26.4" } }, "sha512-bHOrbyztmyYIi4f1R0s17QsPs1uyyYnGcXeZoGEd227oZjry0q6XQBQxd82X1I57zEfwO8h9Xo+Kl5gX1d9MwQ=="],
|
||||
"@browserbasehq/sdk/@types/node": ["@types/node@18.19.123", "", { "dependencies": { "undici-types": "~5.26.4" } }, "sha512-K7DIaHnh0mzVxreCR9qwgNxp3MH9dltPNIEddW9MYUlcKAzm+3grKNSTe2vCJHI1FaLpvpL5JGJrz1UZDKYvDg=="],
|
||||
|
||||
"@clerk/backend/cookie": ["cookie@1.0.2", "", {}, "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA=="],
|
||||
|
||||
"@clerk/shared/swr": ["swr@2.3.4", "", { "dependencies": { "dequal": "^2.0.3", "use-sync-external-store": "^1.4.0" }, "peerDependencies": { "react": "^16.11.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-bYd2lrhc+VarcpkgWclcUi92wYCpOgMws9Sd1hG1ntAu0NEy+14CbotuFjshBU2kt9rYj9TSmDcybpxpeTU1fg=="],
|
||||
|
||||
"@esbuild-kit/core-utils/esbuild": ["esbuild@0.18.20", "", { "optionalDependencies": { "@esbuild/android-arm": "0.18.20", "@esbuild/android-arm64": "0.18.20", "@esbuild/android-x64": "0.18.20", "@esbuild/darwin-arm64": "0.18.20", "@esbuild/darwin-x64": "0.18.20", "@esbuild/freebsd-arm64": "0.18.20", "@esbuild/freebsd-x64": "0.18.20", "@esbuild/linux-arm": "0.18.20", "@esbuild/linux-arm64": "0.18.20", "@esbuild/linux-ia32": "0.18.20", "@esbuild/linux-loong64": "0.18.20", "@esbuild/linux-mips64el": "0.18.20", "@esbuild/linux-ppc64": "0.18.20", "@esbuild/linux-riscv64": "0.18.20", "@esbuild/linux-s390x": "0.18.20", "@esbuild/linux-x64": "0.18.20", "@esbuild/netbsd-x64": "0.18.20", "@esbuild/openbsd-x64": "0.18.20", "@esbuild/sunos-x64": "0.18.20", "@esbuild/win32-arm64": "0.18.20", "@esbuild/win32-ia32": "0.18.20", "@esbuild/win32-x64": "0.18.20" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA=="],
|
||||
|
||||
"@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="],
|
||||
@@ -2751,11 +2739,15 @@
|
||||
|
||||
"@hyperdx/node-opentelemetry/ora": ["ora@5.4.1", "", { "dependencies": { "bl": "^4.1.0", "chalk": "^4.1.0", "cli-cursor": "^3.1.0", "cli-spinners": "^2.5.0", "is-interactive": "^1.0.0", "is-unicode-supported": "^0.1.0", "log-symbols": "^4.1.0", "strip-ansi": "^6.0.0", "wcwidth": "^1.0.1" } }, "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ=="],
|
||||
|
||||
"@inquirer/external-editor/iconv-lite": ["iconv-lite@0.6.3", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw=="],
|
||||
|
||||
"@isaacs/cliui/string-width": ["string-width@5.1.2", "", { "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", "strip-ansi": "^7.0.1" } }, "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA=="],
|
||||
|
||||
"@isaacs/cliui/wrap-ansi": ["wrap-ansi@8.1.0", "", { "dependencies": { "ansi-styles": "^6.1.0", "string-width": "^5.0.1", "strip-ansi": "^7.0.1" } }, "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ=="],
|
||||
|
||||
"@jridgewell/gen-mapping/@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.29", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ=="],
|
||||
"@jridgewell/gen-mapping/@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.30", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-GQ7Nw5G2lTu/BtHTKfXhKHok2WGetd4XYcVKGx00SjAk8GMwgJM3zr6zORiPGuOE+/vkc90KtTosSSvaCjKb2Q=="],
|
||||
|
||||
"@jridgewell/remapping/@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.30", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-GQ7Nw5G2lTu/BtHTKfXhKHok2WGetd4XYcVKGx00SjAk8GMwgJM3zr6zORiPGuOE+/vkc90KtTosSSvaCjKb2Q=="],
|
||||
|
||||
"@opentelemetry/auto-instrumentations-node/@opentelemetry/core": ["@opentelemetry/core@2.0.1", "", { "dependencies": { "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, "sha512-MaZk9SJIDgo1peKevlbhP6+IwIiNPNmswNL4AF0WaQJLbHXjr9SrZMgS12+iqr9ToV4ZVosCcc0f8Rg67LXjxw=="],
|
||||
|
||||
@@ -3031,7 +3023,7 @@
|
||||
|
||||
"@tailwindcss/oxide-wasm32-wasi/@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@0.2.12", "", { "dependencies": { "@emnapi/core": "^1.4.3", "@emnapi/runtime": "^1.4.3", "@tybys/wasm-util": "^0.10.0" }, "bundled": true }, "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ=="],
|
||||
|
||||
"@tailwindcss/oxide-wasm32-wasi/@tybys/wasm-util": ["@tybys/wasm-util@0.9.0", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-6+7nlbMVX/PVDCwaIQ8nTOPveOcFLSt8GcXdx8hD0bt39uWxYT88uXzqTd4fTvqta7oeUJqudepapKNt2DYJFw=="],
|
||||
"@tailwindcss/oxide-wasm32-wasi/@tybys/wasm-util": ["@tybys/wasm-util@0.10.0", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-VyyPYFlOMNylG45GoAe0xDoLwWuowvf92F9kySqzYh8vmYm7D2u4iUJKa1tOUpS70Ku13ASrOkS4ScXFsTaCNQ=="],
|
||||
|
||||
"@tailwindcss/oxide-wasm32-wasi/tslib": ["tslib@2.8.1", "", { "bundled": true }, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
|
||||
|
||||
@@ -3041,7 +3033,7 @@
|
||||
|
||||
"anymatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
|
||||
|
||||
"better-auth/zod": ["zod@4.0.15", "", {}, "sha512-2IVHb9h4Mt6+UXkyMs0XbfICUh1eUrlJJAOupBHUhLRnKkruawyDddYRCs0Eizt900ntIMk9/4RksYl+FgSpcQ=="],
|
||||
"autumn-js/zod": ["zod@4.0.17", "", {}, "sha512-1PHjlYRevNxxdy2JZ8JcNAw7rX8V9P1AKkP+x/xZfxB0K5FYfuV+Ug6P/6NVSR2jHQ+FzDDoDHS04nYUsOIyLQ=="],
|
||||
|
||||
"better-call/rou3": ["rou3@0.5.1", "", {}, "sha512-OXMmJ3zRk2xeXFGfA3K+EOPHC5u7RDFG7lIOx0X1pdnhUkI8MdVrbV+sNsD80ElpUZ+MRHdyxPnFthq9VHs8uQ=="],
|
||||
|
||||
@@ -3057,7 +3049,7 @@
|
||||
|
||||
"cliui/wrap-ansi": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="],
|
||||
|
||||
"cloudflare/@types/node": ["@types/node@18.19.121", "", { "dependencies": { "undici-types": "~5.26.4" } }, "sha512-bHOrbyztmyYIi4f1R0s17QsPs1uyyYnGcXeZoGEd227oZjry0q6XQBQxd82X1I57zEfwO8h9Xo+Kl5gX1d9MwQ=="],
|
||||
"cloudflare/@types/node": ["@types/node@18.19.123", "", { "dependencies": { "undici-types": "~5.26.4" } }, "sha512-K7DIaHnh0mzVxreCR9qwgNxp3MH9dltPNIEddW9MYUlcKAzm+3grKNSTe2vCJHI1FaLpvpL5JGJrz1UZDKYvDg=="],
|
||||
|
||||
"concurrently/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="],
|
||||
|
||||
@@ -3093,7 +3085,7 @@
|
||||
|
||||
"nodemon/supports-color": ["supports-color@5.5.0", "", { "dependencies": { "has-flag": "^3.0.0" } }, "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow=="],
|
||||
|
||||
"openai/@types/node": ["@types/node@18.19.121", "", { "dependencies": { "undici-types": "~5.26.4" } }, "sha512-bHOrbyztmyYIi4f1R0s17QsPs1uyyYnGcXeZoGEd227oZjry0q6XQBQxd82X1I57zEfwO8h9Xo+Kl5gX1d9MwQ=="],
|
||||
"openai/@types/node": ["@types/node@18.19.123", "", { "dependencies": { "undici-types": "~5.26.4" } }, "sha512-K7DIaHnh0mzVxreCR9qwgNxp3MH9dltPNIEddW9MYUlcKAzm+3grKNSTe2vCJHI1FaLpvpL5JGJrz1UZDKYvDg=="],
|
||||
|
||||
"ora/is-unicode-supported": ["is-unicode-supported@2.1.0", "", {}, "sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ=="],
|
||||
|
||||
@@ -3105,7 +3097,7 @@
|
||||
|
||||
"pino-pretty/pino-abstract-transport": ["pino-abstract-transport@2.0.0", "", { "dependencies": { "split2": "^4.0.0" } }, "sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw=="],
|
||||
|
||||
"pino-pretty/strip-json-comments": ["strip-json-comments@5.0.2", "", {}, "sha512-4X2FR3UwhNUE9G49aIsJW5hRRR3GXGTBTZRMfv568O60ojM8HcWjV/VxAxCDW3SUND33O6ZY66ZuRcdkj73q2g=="],
|
||||
"pino-pretty/strip-json-comments": ["strip-json-comments@5.0.3", "", {}, "sha512-1tB5mhVo7U+ETBKNf92xT4hrQa3pm0MZ0PQvuDnWgAAGHDsfp4lPSpiS6psrSiet87wyGPh9ft6wmhOMQ0hDiw=="],
|
||||
|
||||
"postcss/nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="],
|
||||
|
||||
@@ -3121,7 +3113,7 @@
|
||||
|
||||
"react-router/cookie": ["cookie@1.0.2", "", {}, "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA=="],
|
||||
|
||||
"recaseai/@types/node": ["@types/node@22.17.0", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-bbAKTCqX5aNVryi7qXVMi+OkB3w/OyblodicMbvE38blyAz7GxXf6XYhklokijuPwwVg9sDLKRxt0ZHXQwZVfQ=="],
|
||||
"recaseai/@types/node": ["@types/node@22.17.2", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-gL6z5N9Jm9mhY+U2KXZpteb+09zyffliRkZyZOHODGATyC5B1Jt/7TzuuiLkFsSUMLbS1OLmlj/E+/3KF4Q/4w=="],
|
||||
|
||||
"recaseai/commander": ["commander@12.1.0", "", {}, "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA=="],
|
||||
|
||||
@@ -3151,7 +3143,7 @@
|
||||
|
||||
"superagent/qs": ["qs@6.14.0", "", { "dependencies": { "side-channel": "^1.1.0" } }, "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w=="],
|
||||
|
||||
"svix/@types/node": ["@types/node@22.17.0", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-bbAKTCqX5aNVryi7qXVMi+OkB3w/OyblodicMbvE38blyAz7GxXf6XYhklokijuPwwVg9sDLKRxt0ZHXQwZVfQ=="],
|
||||
"svix/@types/node": ["@types/node@22.17.2", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-gL6z5N9Jm9mhY+U2KXZpteb+09zyffliRkZyZOHODGATyC5B1Jt/7TzuuiLkFsSUMLbS1OLmlj/E+/3KF4Q/4w=="],
|
||||
|
||||
"svix/uuid": ["uuid@10.0.0", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ=="],
|
||||
|
||||
@@ -3467,8 +3459,6 @@
|
||||
|
||||
"@sentry/node/@opentelemetry/sdk-trace-base/@opentelemetry/semantic-conventions": ["@opentelemetry/semantic-conventions@1.28.0", "", {}, "sha512-lp4qAiMTD4sNWW4DbKLBkfiMZ4jbAboJIGOQr5DvciMRI494OapieI9qiODpOt0XBr1LjIDy1xAGAnVs5supTA=="],
|
||||
|
||||
"@tailwindcss/oxide-wasm32-wasi/@napi-rs/wasm-runtime/@tybys/wasm-util": ["@tybys/wasm-util@0.10.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-VyyPYFlOMNylG45GoAe0xDoLwWuowvf92F9kySqzYh8vmYm7D2u4iUJKa1tOUpS70Ku13ASrOkS4ScXFsTaCNQ=="],
|
||||
|
||||
"accepts/mime-types/mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="],
|
||||
|
||||
"body-parser/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="],
|
||||
|
||||
@@ -27,14 +27,3 @@ else
|
||||
NODE_ENV=development bun "$filename"
|
||||
fi
|
||||
|
||||
|
||||
# # If filename ends with .sh, then run it
|
||||
# if [ "${filename##*.}" = "sh" ]; then
|
||||
# ./$filename
|
||||
# else if [ "${filename##*.}" = "ts" ]; then
|
||||
# npx tsx $filename
|
||||
# else
|
||||
# echo "Invalid file extension"
|
||||
# fi
|
||||
|
||||
# # npm run test
|
||||
@@ -5,18 +5,19 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
source "$SCRIPT_DIR/config.sh"
|
||||
|
||||
# If contains setup then run $MOCHA_SETUP
|
||||
if [[ "$2" == *"setup"* ]]; then
|
||||
MOCHA_PARALLEL=true $MOCHA_SETUP
|
||||
if [[ "$1" == *"setup"* ]]; then
|
||||
MOCHA_PARALLEL=true $MOCHA_SETUP
|
||||
fi
|
||||
|
||||
$MOCHA_CMD \
|
||||
'tests/attach/basic/*.ts' \
|
||||
'tests/attach/upgrade/*.ts' \
|
||||
'tests/attach/downgrade/*.ts' \
|
||||
'tests/attach/checkout/*.ts'
|
||||
'tests/attach/addOn/*.ts'
|
||||
|
||||
$MOCHA_CMD \
|
||||
'tests/attach/checkout/*.ts' \
|
||||
'tests/attach/entities/*.ts' \
|
||||
'tests/attach/free/*.ts'
|
||||
'tests/attach/free/*.ts'\
|
||||
|
||||
# 'tests/attach/basic/basic2.ts' \
|
||||
@@ -17,15 +17,15 @@ $MOCHA_CMD 'tests/contUse/track/*.ts'
|
||||
|
||||
$MOCHA_CMD 'tests/contUse/roles/*.ts'
|
||||
|
||||
# G4
|
||||
$MOCHA_CMD 'tests/advanced/multiFeature/*.ts' \
|
||||
'tests/advanced/coupons/*.ts' \
|
||||
'tests/attach/updateQuantity/*.ts' \
|
||||
'tests/advanced/referrals/*.ts' \
|
||||
'tests/advanced/rollovers/*.ts' \
|
||||
'tests/advanced/customInterval/*.ts'
|
||||
# # G4
|
||||
# $MOCHA_CMD 'tests/advanced/multiFeature/*.ts' \
|
||||
# 'tests/advanced/coupons/*.ts' \
|
||||
# 'tests/attach/updateQuantity/*.ts' \
|
||||
# 'tests/advanced/referrals/*.ts' \
|
||||
# 'tests/advanced/rollovers/*.ts' \
|
||||
# 'tests/advanced/customInterval/*.ts'
|
||||
|
||||
$MOCHA_CMD 'tests/attach/multiProduct/*.ts' \
|
||||
'tests/advanced/usageLimit/*.ts'
|
||||
# $MOCHA_CMD 'tests/attach/multiProduct/*.ts' \
|
||||
# 'tests/advanced/usageLimit/*.ts'
|
||||
|
||||
$MOCHA_CMD 'tests/advanced/usage/*.ts'
|
||||
# $MOCHA_CMD 'tests/advanced/usage/*.ts'
|
||||
4
server/src/external/autumn/autumnCli.ts
vendored
4
server/src/external/autumn/autumnCli.ts
vendored
@@ -170,7 +170,9 @@ export class AutumnInt {
|
||||
|
||||
return data;
|
||||
}
|
||||
async checkout(params: CheckoutParams) {
|
||||
async checkout(
|
||||
params: CheckoutParams & { invoice?: boolean; force_checkout?: boolean }
|
||||
) {
|
||||
// const data = await this.post(`/attach`, {
|
||||
// customer_id: customerId,
|
||||
// product_id: productId,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { getPriceForOverage } from "@/internal/products/prices/priceUtils.js";
|
||||
import { nullish } from "@/utils/genUtils.js";
|
||||
import { notNullish, nullish } from "@/utils/genUtils.js";
|
||||
import { FeatureOptions, Organization, UsagePriceConfig } from "@autumn/shared";
|
||||
import { EntitlementWithFeature } from "@autumn/shared";
|
||||
import { Price } from "@autumn/shared";
|
||||
@@ -29,7 +29,7 @@ export const priceToOneOffAndTiered = ({
|
||||
const amount = getPriceForOverage(price, overage);
|
||||
if (!config.stripe_product_id) {
|
||||
console.log(
|
||||
`WARNING: One off & tiered in advance price has no stripe product id: ${price.id}, ${relatedEnt.feature.name}`,
|
||||
`WARNING: One off & tiered in advance price has no stripe product id: ${price.id}, ${relatedEnt.feature.name}`
|
||||
);
|
||||
}
|
||||
return {
|
||||
@@ -61,7 +61,7 @@ export const priceToUsageInAdvance = ({
|
||||
let finalQuantity = optionsQuantity;
|
||||
|
||||
// 1. If adjustable quantity is set, use that, else if quantity is undefined, adjustable is true, else false
|
||||
let adjustable = !nullish(options?.adjustable_quantity)
|
||||
let adjustable = notNullish(options?.adjustable_quantity)
|
||||
? options!.adjustable_quantity
|
||||
: nullish(optionsQuantity)
|
||||
? true
|
||||
|
||||
@@ -42,6 +42,7 @@ export const createWebhookEndpoint = async (
|
||||
"invoice.upcoming",
|
||||
"invoice.created",
|
||||
"invoice.finalized",
|
||||
"invoice.updated",
|
||||
"subscription_schedule.canceled",
|
||||
"customer.discount.deleted",
|
||||
],
|
||||
|
||||
@@ -11,7 +11,11 @@ import {
|
||||
import Stripe from "stripe";
|
||||
import { getCusPaymentMethod } from "../stripeCusUtils.js";
|
||||
import { SubService } from "@/internal/subscriptions/SubService.js";
|
||||
import { formatUnixToDateTime, generateId, notNullish } from "@/utils/genUtils.js";
|
||||
import {
|
||||
formatUnixToDateTime,
|
||||
generateId,
|
||||
notNullish,
|
||||
} from "@/utils/genUtils.js";
|
||||
import { ItemSet } from "@/utils/models/ItemSet.js";
|
||||
import { DrizzleCli } from "@/db/initDrizzle.js";
|
||||
import { getAlignedIntervalUnix } from "@/internal/products/prices/billingIntervalUtils.js";
|
||||
@@ -46,7 +50,8 @@ export const createStripeSub = async ({
|
||||
let paymentMethod = await getCusPaymentMethod({
|
||||
stripeCli,
|
||||
stripeId: customer.processor.id,
|
||||
errorIfNone: !invoiceOnly && (notNullish(freeTrial) && freeTrial?.card_required), // throw error if no payment method and invoiceOnly is false OR if its a free trial and card is required but no payment method
|
||||
errorIfNone:
|
||||
!invoiceOnly && notNullish(freeTrial) && freeTrial?.card_required, // throw error if no payment method and invoiceOnly is false OR if its a free trial and card is required but no payment method
|
||||
});
|
||||
|
||||
let paymentMethodData = {};
|
||||
@@ -85,7 +90,11 @@ export const createStripeSub = async ({
|
||||
trial_end: freeTrialToStripeTimestamp({ freeTrial, now }),
|
||||
payment_behavior: "error_if_incomplete",
|
||||
add_invoice_items: invoiceItems,
|
||||
collection_method: freeTrial ? undefined : invoiceOnly ? "send_invoice" : "charge_automatically",
|
||||
collection_method: freeTrial
|
||||
? undefined
|
||||
: invoiceOnly
|
||||
? "send_invoice"
|
||||
: "charge_automatically",
|
||||
days_until_due: freeTrial ? undefined : invoiceOnly ? 30 : undefined,
|
||||
billing_cycle_anchor: billingCycleAnchorUnix
|
||||
? Math.floor(billingCycleAnchorUnix / 1000)
|
||||
@@ -93,16 +102,24 @@ export const createStripeSub = async ({
|
||||
|
||||
coupon: reward ? reward.id : undefined,
|
||||
|
||||
trial_settings: freeTrial && !freeTrial.card_required ? {
|
||||
end_behavior: {
|
||||
missing_payment_method: "cancel",
|
||||
},
|
||||
} : undefined,
|
||||
trial_settings:
|
||||
freeTrial && !freeTrial.card_required
|
||||
? {
|
||||
end_behavior: {
|
||||
missing_payment_method: "cancel",
|
||||
},
|
||||
}
|
||||
: undefined,
|
||||
expand: ["latest_invoice"],
|
||||
});
|
||||
|
||||
if (invoiceOnly && finalizeInvoice) {
|
||||
await stripeCli.invoices.finalizeInvoice(
|
||||
subscription.latest_invoice as string
|
||||
if (
|
||||
invoiceOnly &&
|
||||
finalizeInvoice &&
|
||||
(subscription.latest_invoice as Stripe.Invoice).status === "draft"
|
||||
) {
|
||||
subscription.latest_invoice = await stripeCli.invoices.finalizeInvoice(
|
||||
(subscription.latest_invoice as Stripe.Invoice).id
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
10
server/src/external/stripe/stripeWebhooks.ts
vendored
10
server/src/external/stripe/stripeWebhooks.ts
vendored
@@ -21,6 +21,7 @@ import { createStripeCli } from "./utils.js";
|
||||
import { deleteCusCache } from "@/internal/customers/cusCache/updateCachedCus.js";
|
||||
import { CusService } from "@/internal/customers/CusService.js";
|
||||
import { DrizzleCli } from "@/db/initDrizzle.js";
|
||||
import { handleInvoiceUpdated } from "./webhookHandlers/handleInvoiceUpdated.js";
|
||||
|
||||
export const stripeWebhookRouter: Router = express.Router();
|
||||
|
||||
@@ -183,6 +184,15 @@ stripeWebhookRouter.post(
|
||||
});
|
||||
break;
|
||||
|
||||
case "invoice.updated":
|
||||
await handleInvoiceUpdated({
|
||||
stripeCli,
|
||||
env,
|
||||
event,
|
||||
req: request,
|
||||
});
|
||||
break;
|
||||
|
||||
case "invoice.created":
|
||||
const createdInvoice = event.data.object;
|
||||
await handleInvoiceCreated({
|
||||
|
||||
@@ -101,7 +101,8 @@ export const handleRemainingSets = async ({
|
||||
})) as Stripe.Subscription;
|
||||
|
||||
subs.push(subscription);
|
||||
invoiceIds.push(subscription.latest_invoice as string);
|
||||
const latestInvoice = subscription.latest_invoice as Stripe.Invoice;
|
||||
invoiceIds.push(latestInvoice.id);
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
@@ -22,6 +22,7 @@ import { DrizzleCli } from "@/db/initDrizzle.js";
|
||||
import { InvoiceService } from "@/internal/invoices/InvoiceService.js";
|
||||
import { getInvoiceItems } from "@/internal/invoices/invoiceUtils.js";
|
||||
import { handleInvoicePaidDiscount } from "./handleInvoicePaidDiscount.js";
|
||||
import { handleInvoiceCheckoutPaid } from "@/internal/customers/attach/attachFunctions/invoiceCheckoutPaid/handleInvoiceCheckoutPaid.js";
|
||||
|
||||
const handleOneOffInvoicePaid = async ({
|
||||
db,
|
||||
@@ -92,12 +93,12 @@ const convertToChargeAutomatically = async ({
|
||||
logger.info(`Converting to charge automatically`);
|
||||
// 1. Get payment intent
|
||||
const paymentIntent = await stripeCli.paymentIntents.retrieve(
|
||||
invoice.payment_intent as string,
|
||||
invoice.payment_intent as string
|
||||
);
|
||||
|
||||
// 2. Get payment method
|
||||
const paymentMethod = await stripeCli.paymentMethods.retrieve(
|
||||
paymentIntent.payment_method as string,
|
||||
paymentIntent.payment_method as string
|
||||
);
|
||||
|
||||
await stripeCli.paymentMethods.attach(paymentMethod.id, {
|
||||
@@ -113,7 +114,7 @@ const convertToChargeAutomatically = async ({
|
||||
});
|
||||
} catch (error) {
|
||||
logger.warn(
|
||||
`Convert to charge automatically: error updating subscription ${sub.id}`,
|
||||
`Convert to charge automatically: error updating subscription ${sub.id}`
|
||||
);
|
||||
logger.warn(error);
|
||||
}
|
||||
@@ -153,6 +154,17 @@ export const handleInvoicePaid = async ({
|
||||
stripeId: invoiceData.id,
|
||||
});
|
||||
|
||||
if (invoice.metadata?.autumn_metadata_id) {
|
||||
await handleInvoiceCheckoutPaid({
|
||||
req,
|
||||
org,
|
||||
env,
|
||||
db,
|
||||
stripeCli,
|
||||
invoice,
|
||||
});
|
||||
}
|
||||
|
||||
await handleInvoicePaidDiscount({
|
||||
db,
|
||||
expandedInvoice: invoice,
|
||||
@@ -174,7 +186,7 @@ export const handleInvoicePaid = async ({
|
||||
// TODO: Send alert
|
||||
if (invoice.livemode) {
|
||||
logger.warn(
|
||||
`invoice.paid: customer product not found for invoice ${invoice.id}`,
|
||||
`invoice.paid: customer product not found for invoice ${invoice.id}`
|
||||
);
|
||||
}
|
||||
return;
|
||||
@@ -199,7 +211,7 @@ export const handleInvoicePaid = async ({
|
||||
let invoiceItems = await getInvoiceItems({
|
||||
stripeInvoice: invoice,
|
||||
prices: activeCusProducts.flatMap((p) =>
|
||||
p.customer_prices.map((cpr: FullCustomerPrice) => cpr.price),
|
||||
p.customer_prices.map((cpr: FullCustomerPrice) => cpr.price)
|
||||
),
|
||||
logger,
|
||||
});
|
||||
|
||||
39
server/src/external/stripe/webhookHandlers/handleInvoiceUpdated.ts
vendored
Normal file
39
server/src/external/stripe/webhookHandlers/handleInvoiceUpdated.ts
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
import { AppEnv, InvoiceStatus } from "@autumn/shared";
|
||||
import Stripe from "stripe";
|
||||
import { getFullStripeInvoice } from "../stripeInvoiceUtils.js";
|
||||
import { InvoiceService } from "@/internal/invoices/InvoiceService.js";
|
||||
|
||||
export const handleInvoiceUpdated = async ({
|
||||
env,
|
||||
event,
|
||||
stripeCli,
|
||||
req,
|
||||
}: {
|
||||
env: AppEnv;
|
||||
event: Stripe.Event;
|
||||
stripeCli: Stripe;
|
||||
req: any;
|
||||
}) => {
|
||||
const invoiceObject = event.data.object as Stripe.Invoice;
|
||||
const invoice = await getFullStripeInvoice({
|
||||
stripeCli,
|
||||
stripeId: invoiceObject.id,
|
||||
});
|
||||
|
||||
const prevAttributes = event.data.previous_attributes as any;
|
||||
const invoiceVoided =
|
||||
prevAttributes?.status !== "void" && invoice.status === "void";
|
||||
|
||||
const { logger } = req;
|
||||
|
||||
if (invoiceVoided) {
|
||||
logger.info(`Invoice has been voided!`);
|
||||
await InvoiceService.updateByStripeId({
|
||||
db: req.db,
|
||||
stripeId: invoiceObject.id,
|
||||
updates: {
|
||||
status: InvoiceStatus.Void,
|
||||
},
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -202,6 +202,12 @@ export const handleUsageEvent = async ({
|
||||
entityId: entity_id,
|
||||
};
|
||||
|
||||
// console.log("Customer:", customer);
|
||||
// console.log(
|
||||
// "Is paid continuous use:",
|
||||
// isPaidContinuousUse({ feature, fullCus: customer })
|
||||
// );
|
||||
|
||||
if (isPaidContinuousUse({ feature, fullCus: customer })) {
|
||||
console.log(`Running update usage task synchronously`);
|
||||
await runUpdateUsageTask({
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
import RecaseError from "@/utils/errorUtils.js";
|
||||
import {
|
||||
AttachParams,
|
||||
AttachResultSchema,
|
||||
} from "../cusProducts/AttachParams.js";
|
||||
import { createStripeCli } from "@/external/stripe/utils.js";
|
||||
import { createCheckoutMetadata } from "@/internal/metadata/metadataUtils.js";
|
||||
import { getStripeSubItems } from "@/external/stripe/stripeSubUtils/getStripeSubItems.js";
|
||||
import { ErrCode } from "@/errors/errCodes.js";
|
||||
import { getNextStartOfMonthUnix } from "@/internal/products/prices/billingIntervalUtils.js";
|
||||
import { isOneOff } from "@/internal/products/productUtils.js";
|
||||
import { attachParamsToProduct } from "../attach/attachUtils/convertAttachParams.js";
|
||||
import { handlePaidProduct } from "../attach/attachFunctions/addProductFlow/handlePaidProduct.js";
|
||||
import {
|
||||
AttachBranch,
|
||||
AttachConfig,
|
||||
ProrationBehavior,
|
||||
SuccessCode,
|
||||
} from "@autumn/shared";
|
||||
import Stripe from "stripe";
|
||||
import { handleOneOffFunction } from "../attach/attachFunctions/addProductFlow/handleOneOffFunction.js";
|
||||
|
||||
export const handleCreateInvoiceCheckout = async ({
|
||||
req,
|
||||
res,
|
||||
attachParams,
|
||||
config,
|
||||
}: {
|
||||
req: any;
|
||||
res?: any;
|
||||
attachParams: AttachParams;
|
||||
config: AttachConfig;
|
||||
}) => {
|
||||
// if one off
|
||||
const { stripeCli } = attachParams;
|
||||
|
||||
let invoiceResult;
|
||||
if (isOneOff(attachParams.prices)) {
|
||||
invoiceResult = await handleOneOffFunction({
|
||||
req,
|
||||
res,
|
||||
attachParams,
|
||||
config,
|
||||
});
|
||||
} else {
|
||||
invoiceResult = await handlePaidProduct({
|
||||
req,
|
||||
res,
|
||||
attachParams,
|
||||
config,
|
||||
});
|
||||
}
|
||||
|
||||
const { invoices, anchorToUnix, subs }: any = invoiceResult;
|
||||
|
||||
const metadataId = await createCheckoutMetadata({
|
||||
db: req.db,
|
||||
attachParams: {
|
||||
...attachParams,
|
||||
anchorToUnix,
|
||||
subIds: subs.map((s: Stripe.Subscription) => s.id),
|
||||
config,
|
||||
} as any,
|
||||
});
|
||||
|
||||
for (const invoice of invoices) {
|
||||
await stripeCli.invoices.update(invoice.id, {
|
||||
metadata: {
|
||||
autumn_metadata_id: metadataId,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// AttachResultSchema.parse({
|
||||
// checkout_url: checkout.url,
|
||||
// code: SuccessCode.CheckoutCreated,
|
||||
// message: `Successfully created checkout for customer ${
|
||||
// customer.id || customer.internal_id
|
||||
// }, product(s) ${attachParams.products.map((p) => p.name).join(", ")}`,
|
||||
// product_ids: attachParams.products.map((p) => p.id),
|
||||
// customer_id: customer.id || customer.internal_id,
|
||||
// });
|
||||
if (res) {
|
||||
res.status(200).json(
|
||||
AttachResultSchema.parse({
|
||||
checkout_url: invoices[0].hosted_invoice_url,
|
||||
code: SuccessCode.CheckoutCreated,
|
||||
message: `Successfully created invoice checkout for customer ${
|
||||
attachParams.customer.id || attachParams.customer.internal_id
|
||||
}, product(s) ${attachParams.products.map((p) => p.name).join(", ")}`,
|
||||
product_ids: attachParams.products.map((p) => p.id),
|
||||
customer_id:
|
||||
attachParams.customer.id || attachParams.customer.internal_id,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
return { invoices };
|
||||
};
|
||||
@@ -106,7 +106,7 @@ export const handleOneOffFunction = async ({
|
||||
|
||||
// Create invoice
|
||||
logger.info("1. Creating invoice");
|
||||
const stripeInvoice = await stripeCli.invoices.create({
|
||||
let stripeInvoice = await stripeCli.invoices.create({
|
||||
customer: customer.processor.id!,
|
||||
auto_advance: false,
|
||||
currency: org.default_currency!,
|
||||
@@ -117,6 +117,8 @@ export const handleOneOffFunction = async ({
|
||||
},
|
||||
]
|
||||
: undefined,
|
||||
collection_method: attachParams.invoiceOnly ? "send_invoice" : undefined,
|
||||
days_until_due: attachParams.invoiceOnly ? 30 : undefined,
|
||||
});
|
||||
|
||||
logger.info("2. Creating invoice items");
|
||||
@@ -128,6 +130,23 @@ export const handleOneOffFunction = async ({
|
||||
} as any);
|
||||
}
|
||||
|
||||
if (config.invoiceCheckout) {
|
||||
if (stripeInvoice.status === "draft") {
|
||||
stripeInvoice = await stripeCli.invoices.finalizeInvoice(
|
||||
stripeInvoice.id
|
||||
);
|
||||
}
|
||||
|
||||
await insertInvoiceFromAttach({
|
||||
db: req.db,
|
||||
attachParams,
|
||||
invoiceId: stripeInvoice.id,
|
||||
logger,
|
||||
});
|
||||
|
||||
return { invoices: [stripeInvoice], subs: [], anchorToUnix: undefined };
|
||||
}
|
||||
|
||||
// Create invoice items
|
||||
if (!invoiceOnly) {
|
||||
await stripeCli.invoices.finalizeInvoice(stripeInvoice.id);
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import RecaseError from "@/utils/errorUtils.js";
|
||||
|
||||
import { getStripeSubs } from "@/external/stripe/stripeSubUtils.js";
|
||||
import { createStripeSub } from "@/external/stripe/stripeSubUtils/createStripeSub.js";
|
||||
import { getStripeSubItems } from "@/external/stripe/stripeSubUtils/getStripeSubItems.js";
|
||||
@@ -14,8 +16,6 @@ import {
|
||||
} from "@/internal/invoices/invoiceUtils.js";
|
||||
import { getNextStartOfMonthUnix } from "@/internal/products/prices/billingIntervalUtils.js";
|
||||
import { attachToInsertParams } from "@/internal/products/productUtils.js";
|
||||
import RecaseError from "@/utils/errorUtils.js";
|
||||
import { formatUnixToDateTime } from "@/utils/genUtils.js";
|
||||
import { ExtendedRequest } from "@/utils/models/Request.js";
|
||||
import {
|
||||
APIVersion,
|
||||
@@ -122,7 +122,7 @@ export const handlePaidProduct = async ({
|
||||
freeTrial,
|
||||
invoiceOnly,
|
||||
itemSet,
|
||||
finalizeInvoice: attachParams.finalizeInvoice,
|
||||
finalizeInvoice: config.invoiceCheckout,
|
||||
anchorToUnix: billingCycleAnchorUnix,
|
||||
reward: i == 0 ? reward : undefined,
|
||||
now: attachParams.now,
|
||||
@@ -148,9 +148,6 @@ export const handlePaidProduct = async ({
|
||||
}
|
||||
}
|
||||
|
||||
// Add product and entitlements to customer
|
||||
const batchInsert = [];
|
||||
|
||||
const anchorToUnix =
|
||||
subscriptions.length > 0
|
||||
? subscriptions[0].current_period_end * 1000
|
||||
@@ -158,6 +155,32 @@ export const handlePaidProduct = async ({
|
||||
? mergeSubs[0].current_period_end * 1000
|
||||
: undefined;
|
||||
|
||||
const batchInsertInvoice: any = [];
|
||||
for (const sub of subscriptions) {
|
||||
batchInsertInvoice.push(
|
||||
insertInvoiceFromAttach({
|
||||
db: req.db,
|
||||
// invoiceId: sub.latest_invoice as string,
|
||||
stripeInvoice: sub.latest_invoice as Stripe.Invoice,
|
||||
attachParams,
|
||||
logger,
|
||||
})
|
||||
);
|
||||
}
|
||||
const invoices = await Promise.all(batchInsertInvoice);
|
||||
|
||||
if (config.invoiceCheckout) {
|
||||
return {
|
||||
invoices: subscriptions.map((s) => s.latest_invoice as Stripe.Invoice),
|
||||
subs: subscriptions,
|
||||
anchorToUnix,
|
||||
config,
|
||||
};
|
||||
}
|
||||
|
||||
// Add product and entitlements to customer
|
||||
const batchInsert = [];
|
||||
|
||||
for (const product of products) {
|
||||
batchInsert.push(
|
||||
createFullCusProduct({
|
||||
@@ -173,19 +196,6 @@ export const handlePaidProduct = async ({
|
||||
}
|
||||
await Promise.all(batchInsert);
|
||||
|
||||
const batchInsertInvoice: any = [];
|
||||
for (const sub of subscriptions) {
|
||||
batchInsertInvoice.push(
|
||||
insertInvoiceFromAttach({
|
||||
db: req.db,
|
||||
invoiceId: sub.latest_invoice as string,
|
||||
attachParams,
|
||||
logger,
|
||||
})
|
||||
);
|
||||
}
|
||||
const invoices = await Promise.all(batchInsertInvoice);
|
||||
|
||||
if (res) {
|
||||
let apiVersion = attachParams.apiVersion || APIVersion.v1;
|
||||
const productNames = products.map((p) => p.name).join(", ");
|
||||
|
||||
@@ -8,10 +8,14 @@ export const addSubItemsToRemove = async ({
|
||||
cusProduct,
|
||||
itemSet,
|
||||
}: {
|
||||
sub: Stripe.Subscription;
|
||||
sub?: Stripe.Subscription | null;
|
||||
cusProduct: FullCusProduct;
|
||||
itemSet: ItemSet;
|
||||
}) => {
|
||||
if (!sub) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (const item of sub.items.data) {
|
||||
let shouldRemove = subItemInCusProduct({
|
||||
cusProduct,
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
import { DrizzleCli } from "@/db/initDrizzle.js";
|
||||
import { createFullCusProduct } from "@/internal/customers/add-product/createFullCusProduct.js";
|
||||
import { AttachParams } from "@/internal/customers/cusProducts/AttachParams.js";
|
||||
import { MetadataService } from "@/internal/metadata/MetadataService.js";
|
||||
import { attachToInsertParams } from "@/internal/products/productUtils.js";
|
||||
import { ExtendedRequest } from "@/utils/models/Request.js";
|
||||
import { AppEnv, AttachScenario, Organization } from "@autumn/shared";
|
||||
import Stripe from "stripe";
|
||||
|
||||
export const handleInvoiceCheckoutPaid = async ({
|
||||
req,
|
||||
org,
|
||||
env,
|
||||
db,
|
||||
stripeCli,
|
||||
invoice,
|
||||
}: {
|
||||
req: ExtendedRequest;
|
||||
org: Organization;
|
||||
env: AppEnv;
|
||||
db: DrizzleCli;
|
||||
stripeCli: Stripe;
|
||||
invoice: Stripe.Invoice;
|
||||
}) => {
|
||||
const metadataId = invoice.metadata?.autumn_metadata_id!;
|
||||
|
||||
const metadata = await MetadataService.get({
|
||||
db,
|
||||
id: metadataId,
|
||||
});
|
||||
|
||||
const { subIds, anchorToUnix, config, ...rest } = metadata?.data;
|
||||
const attachParams = rest as AttachParams;
|
||||
|
||||
if (!attachParams) {
|
||||
return;
|
||||
}
|
||||
|
||||
const reqMatch =
|
||||
attachParams.org.id === org.id && attachParams.customer.env === env;
|
||||
|
||||
if (!reqMatch) return;
|
||||
|
||||
const batchInsert = [];
|
||||
for (const product of attachParams.products) {
|
||||
batchInsert.push(
|
||||
createFullCusProduct({
|
||||
db,
|
||||
attachParams: attachToInsertParams(attachParams, product),
|
||||
subscriptionIds: subIds,
|
||||
anchorToUnix,
|
||||
carryExistingUsages: config.carryUsage,
|
||||
scenario: AttachScenario.New,
|
||||
logger: req.logger,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
await Promise.all(batchInsert);
|
||||
|
||||
req.logger.info(
|
||||
`✅ invoice.paid, successfully inserted cus products: ${attachParams.products.map((p) => p.id).join(", ")}`
|
||||
);
|
||||
};
|
||||
@@ -23,6 +23,7 @@ import {
|
||||
insertInvoiceFromAttach,
|
||||
} from "@/internal/invoices/invoiceUtils.js";
|
||||
import { updateSubsDiffInt } from "./updateSubsDiffInt.js";
|
||||
import { attachParamsToCurCusProduct } from "../../attachUtils/convertAttachParams.js";
|
||||
|
||||
export const handleUpgradeDiffInterval = async ({
|
||||
req,
|
||||
@@ -41,12 +42,12 @@ export const handleUpgradeDiffInterval = async ({
|
||||
|
||||
const product = products[0];
|
||||
|
||||
let { curMainProduct: curCusProduct } = getExistingCusProducts({
|
||||
product,
|
||||
cusProducts: cusProducts || [],
|
||||
internalEntityId: attachParams.internalEntityId,
|
||||
});
|
||||
|
||||
// let { curMainProduct: curCusProduct } = getExistingCusProducts({
|
||||
// product,
|
||||
// cusProducts: cusProducts || [],
|
||||
// internalEntityId: attachParams.internalEntityId,
|
||||
// });
|
||||
let curCusProduct = attachParamsToCurCusProduct({ attachParams });
|
||||
curCusProduct = curCusProduct!;
|
||||
|
||||
const stripeSubs = await getStripeSubs({
|
||||
|
||||
@@ -39,8 +39,8 @@ export const updateSubsDiffInt = async ({
|
||||
carryExistingUsages: config.carryUsage,
|
||||
});
|
||||
|
||||
const firstSub = stripeSubs[0];
|
||||
const firstItemSet = itemSets[0];
|
||||
const firstSub = stripeSubs?.[0];
|
||||
const firstItemSet = itemSets?.[0];
|
||||
|
||||
await addSubItemsToRemove({
|
||||
sub: firstSub,
|
||||
@@ -127,7 +127,8 @@ export const updateSubsDiffInt = async ({
|
||||
});
|
||||
|
||||
newSubs.push(newSub);
|
||||
newInvoiceIds.push(newSub.latest_invoice as string);
|
||||
const latestInvoice = newSub.latest_invoice as Stripe.Invoice;
|
||||
newInvoiceIds.push(latestInvoice.id);
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
@@ -2,7 +2,10 @@ import {
|
||||
AttachParams,
|
||||
AttachResultSchema,
|
||||
} from "@/internal/customers/cusProducts/AttachParams.js";
|
||||
import { attachParamToCusProducts } from "../../attachUtils/convertAttachParams.js";
|
||||
import {
|
||||
attachParamsToCurCusProduct,
|
||||
attachParamToCusProducts,
|
||||
} from "../../attachUtils/convertAttachParams.js";
|
||||
import { CusProductService } from "@/internal/customers/cusProducts/CusProductService.js";
|
||||
import { createFullCusProduct } from "@/internal/customers/add-product/createFullCusProduct.js";
|
||||
import { attachToInsertParams } from "@/internal/products/productUtils.js";
|
||||
@@ -24,13 +27,11 @@ export const handleUpgradeSameInterval = async ({
|
||||
attachParams: AttachParams;
|
||||
config: AttachConfig;
|
||||
}) => {
|
||||
const { curMainProduct: curCusProduct } = attachParamToCusProducts({
|
||||
attachParams,
|
||||
});
|
||||
const curCusProduct = attachParamsToCurCusProduct({ attachParams });
|
||||
|
||||
const stripeSubs = await getStripeSubs({
|
||||
stripeCli: attachParams.stripeCli,
|
||||
subIds: curCusProduct!.subscription_ids || [],
|
||||
subIds: curCusProduct?.subscription_ids || [],
|
||||
expand: ["items.data.price.tiers"],
|
||||
});
|
||||
|
||||
|
||||
@@ -39,25 +39,11 @@ export const updateSubsByInt = async ({
|
||||
|
||||
attachParams.replaceables = replaceables;
|
||||
|
||||
// logger.info(`Cont use items`);
|
||||
// logger.info(
|
||||
// `New items: `,
|
||||
// newItems.map(
|
||||
// (item) => `${item.description} | Amount: ${item.amount || item.price}`,
|
||||
// ),
|
||||
// );
|
||||
// logger.info(
|
||||
// "Replaceables: ",
|
||||
// replaceables.map((r) => `${r.ent.feature_id}`),
|
||||
// );
|
||||
|
||||
const itemSets = await getStripeSubItems({ attachParams });
|
||||
|
||||
const invoices: Stripe.Invoice[] = [];
|
||||
|
||||
// const replaceables: Replaceable[] = [];
|
||||
for (const sub of stripeSubs) {
|
||||
// let interval = subToAutumnInterval(sub);
|
||||
|
||||
let subInterval = subToAutumnInterval(sub);
|
||||
let itemSet = itemSets.find((itemSet) => {
|
||||
return intervalsSame({
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
import { Router } from "express";
|
||||
import RecaseError from "@/utils/errorUtils.js";
|
||||
import { APIVersion, BillingType, FullCusProduct } from "@autumn/shared";
|
||||
import {
|
||||
APIVersion,
|
||||
AttachConfig,
|
||||
BillingType,
|
||||
FullCusProduct,
|
||||
} from "@autumn/shared";
|
||||
import { ErrCode } from "@/errors/errCodes.js";
|
||||
import { getCusPaymentMethod } from "@/external/stripe/stripeCusUtils.js";
|
||||
|
||||
@@ -22,6 +27,7 @@ import { createStripePriceIFNotExist } from "@/external/stripe/createStripePrice
|
||||
import {
|
||||
notNullish,
|
||||
notNullOrUndefined,
|
||||
nullish,
|
||||
nullOrUndefined,
|
||||
} from "@/utils/genUtils.js";
|
||||
import { CusService } from "@/internal/customers/CusService.js";
|
||||
@@ -35,14 +41,17 @@ import { handleAttachPreview } from "./handleAttachPreview/handleAttachPreview.j
|
||||
import { handleAttach } from "./handleAttach.js";
|
||||
import { handleCheckout } from "./checkout/handleCheckout.js";
|
||||
import { createStripeCusIfNotExists } from "@/external/stripe/stripeCusUtils.js";
|
||||
import { attachParamsToCurCusProduct } from "./attachUtils/convertAttachParams.js";
|
||||
|
||||
export const attachRouter: Router = Router();
|
||||
|
||||
export const handlePrepaidErrors = async ({
|
||||
attachParams,
|
||||
config,
|
||||
useCheckout = false,
|
||||
}: {
|
||||
attachParams: AttachParams;
|
||||
config: AttachConfig;
|
||||
useCheckout?: boolean;
|
||||
}) => {
|
||||
const { prices, entitlements, optionsList } = attachParams;
|
||||
@@ -57,7 +66,8 @@ export const handlePrepaidErrors = async ({
|
||||
let options = getEntOptions(optionsList, priceEnt);
|
||||
|
||||
// 1. If not checkout, quantity should be defined
|
||||
if (!useCheckout && nullOrUndefined(options?.quantity)) {
|
||||
const regularCheckout = useCheckout && !config.invoiceCheckout;
|
||||
if (!regularCheckout && nullOrUndefined(options?.quantity)) {
|
||||
throw new RecaseError({
|
||||
message: `Pass in 'quantity' for feature ${priceEnt.feature_id} in options`,
|
||||
code: ErrCode.InvalidOptions,
|
||||
@@ -161,6 +171,7 @@ export const checkStripeConnections = async ({
|
||||
}
|
||||
|
||||
const batchProductUpdates = [];
|
||||
|
||||
if (createCus) {
|
||||
batchProductUpdates.push(
|
||||
createStripeCusIfNotExists({
|
||||
@@ -172,6 +183,7 @@ export const checkStripeConnections = async ({
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
for (const product of products) {
|
||||
batchProductUpdates.push(
|
||||
checkStripeProductExists({
|
||||
@@ -207,6 +219,9 @@ export const createStripePrices = async ({
|
||||
const { prices, entitlements, products, org, stripeCli } = attachParams;
|
||||
|
||||
const batchPriceUpdates = [];
|
||||
|
||||
// const curCusProduct = attachParamsToCurCusProduct({ attachParams });
|
||||
|
||||
for (const price of prices) {
|
||||
let product = getProductForPrice(price, products);
|
||||
|
||||
|
||||
@@ -77,13 +77,6 @@ export const checkToAttachParams = async ({
|
||||
|
||||
// Others
|
||||
apiVersion,
|
||||
// successUrl: attachBody.success_url,
|
||||
// invoiceOnly: attachBody.invoice_only,
|
||||
// billingAnchor: attachBody.billing_cycle_anchor,
|
||||
// metadata: attachBody.metadata,
|
||||
// disableFreeTrial: attachBody.free_trial === false || false,
|
||||
// checkoutSessionParams: attachBody.checkout_session_params,
|
||||
// isCustom: attachBody.is_custom,
|
||||
};
|
||||
|
||||
return attachParams;
|
||||
|
||||
@@ -66,8 +66,9 @@ export const getAttachParams = async ({
|
||||
// Others
|
||||
apiVersion,
|
||||
successUrl: attachBody.success_url,
|
||||
invoiceOnly: attachBody.invoice_only || attachBody.invoice,
|
||||
finalizeInvoice: attachBody.invoice,
|
||||
invoiceOnly: attachBody.invoice,
|
||||
// || attachBody.invoice_only
|
||||
|
||||
billingAnchor: attachBody.billing_cycle_anchor,
|
||||
metadata: attachBody.metadata,
|
||||
disableFreeTrial: attachBody.free_trial === false || false,
|
||||
|
||||
@@ -10,7 +10,7 @@ export const attachParamsToCurCusProduct = ({
|
||||
const { curMainProduct, curSameProduct, curScheduledProduct } =
|
||||
attachParamToCusProducts({ attachParams });
|
||||
|
||||
return curMainProduct || curSameProduct;
|
||||
return curSameProduct || curMainProduct;
|
||||
};
|
||||
|
||||
export const attachParamToCusProducts = ({
|
||||
|
||||
@@ -135,9 +135,6 @@ const checkSameCustom = async ({
|
||||
features: attachParams.features,
|
||||
});
|
||||
|
||||
// console.log("Attach params free trial:", attachParams.freeTrial);
|
||||
// console.log("Cur same product free trial:", curSameProduct.free_trial);
|
||||
|
||||
if (itemsSame && freeTrialsSame) {
|
||||
throw new RecaseError({
|
||||
message: `Items specified for ${product.name} are the same as the existing product, can't attach again`,
|
||||
@@ -145,6 +142,11 @@ const checkSameCustom = async ({
|
||||
});
|
||||
}
|
||||
|
||||
// const curPrices = cusProductToPrices({ cusProduct: curSameProduct });
|
||||
// if (isFreeProduct(curPrices) && !isFreeProduct(attachParams.prices)) {
|
||||
// return AttachBranch.MainIsFree;
|
||||
// }
|
||||
|
||||
if (onlyEntsChanged) {
|
||||
return AttachBranch.SameCustomEnts;
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ export const intervalsAreSame = ({
|
||||
attachParams,
|
||||
});
|
||||
|
||||
let curCusProduct = curMainProduct || curSameProduct;
|
||||
let curCusProduct = curSameProduct || curMainProduct;
|
||||
|
||||
if (!curCusProduct) {
|
||||
return false;
|
||||
@@ -147,8 +147,17 @@ export const getAttachConfig = async ({
|
||||
branch == AttachBranch.MainIsTrial ||
|
||||
org.config.merge_billing_cycles === false;
|
||||
|
||||
const invoiceAndEnable =
|
||||
attachParams.invoiceOnly && attachBody.enable_product_immediately;
|
||||
|
||||
const invoiceCheckout =
|
||||
attachParams.invoiceOnly === true && !attachBody.enable_product_immediately;
|
||||
|
||||
const checkoutFlow =
|
||||
isPublic || forceCheckout || (noPaymentMethod && !invoiceOnly);
|
||||
isPublic ||
|
||||
forceCheckout ||
|
||||
invoiceCheckout ||
|
||||
(noPaymentMethod && !invoiceAndEnable);
|
||||
|
||||
const onlyCheckout = !isFree && checkoutFlow && !freeTrialWithoutCardRequired;
|
||||
|
||||
@@ -159,6 +168,7 @@ export const getAttachConfig = async ({
|
||||
proration,
|
||||
disableTrial,
|
||||
invoiceOnly: flags.invoiceOnly,
|
||||
invoiceCheckout,
|
||||
disableMerge,
|
||||
sameIntervals,
|
||||
carryTrial,
|
||||
@@ -178,6 +188,7 @@ export const getDefaultAttachConfig = () => {
|
||||
disableMerge: false,
|
||||
sameIntervals: false,
|
||||
carryTrial: false,
|
||||
invoiceCheckout: false,
|
||||
};
|
||||
|
||||
return config;
|
||||
|
||||
@@ -25,6 +25,7 @@ import { deleteCurrentScheduledProduct } from "./deleteCurrentScheduledProduct.j
|
||||
import { handleOneOffFunction } from "../attachFunctions/addProductFlow/handleOneOffFunction.js";
|
||||
import { handleUpgradeSameInterval } from "../attachFunctions/upgradeSameIntFlow/handleUpgradeSameInt.js";
|
||||
import { CusProductService } from "../../cusProducts/CusProductService.js";
|
||||
import { handleCreateInvoiceCheckout } from "../../add-product/handleCreateInvoiceCheckout.js";
|
||||
|
||||
/*
|
||||
1. If from new version, free trial should just carry over
|
||||
@@ -217,6 +218,14 @@ export const runAttachFunction = async ({
|
||||
}
|
||||
|
||||
if (attachFunction == AttachFunction.CreateCheckout) {
|
||||
if (config.invoiceCheckout) {
|
||||
return await handleCreateInvoiceCheckout({
|
||||
req,
|
||||
res,
|
||||
attachParams,
|
||||
config,
|
||||
});
|
||||
}
|
||||
return await handleCreateCheckout({
|
||||
req,
|
||||
res,
|
||||
|
||||
@@ -2,9 +2,15 @@ import RecaseError from "@/utils/errorUtils.js";
|
||||
import { ErrCode } from "@/errors/errCodes.js";
|
||||
import { StatusCodes } from "http-status-codes";
|
||||
import { AttachParams } from "../../cusProducts/AttachParams.js";
|
||||
import { AttachBranch, AttachErrCode, UsagePriceConfig } from "@autumn/shared";
|
||||
import {
|
||||
AttachBranch,
|
||||
AttachConfig,
|
||||
AttachErrCode,
|
||||
UsagePriceConfig,
|
||||
} from "@autumn/shared";
|
||||
import { AttachBody } from "@autumn/shared";
|
||||
import { AttachConfig, AttachFlags } from "../models/AttachFlags.js";
|
||||
import { AttachFlags } from "../models/AttachFlags.js";
|
||||
|
||||
import {
|
||||
getEntOptions,
|
||||
priceIsOneOffAndTiered,
|
||||
@@ -25,8 +31,10 @@ import { Decimal } from "decimal.js";
|
||||
const handleNonCheckoutErrors = ({
|
||||
flags,
|
||||
action,
|
||||
config,
|
||||
}: {
|
||||
flags: AttachFlags;
|
||||
config: AttachConfig;
|
||||
action: string;
|
||||
}) => {
|
||||
const { isPublic, forceCheckout, noPaymentMethod } = flags;
|
||||
@@ -47,14 +55,22 @@ const handleNonCheckoutErrors = ({
|
||||
message: `Not allowed to ${action} because customer has no payment method on file`,
|
||||
code: ErrCode.InvalidRequest,
|
||||
});
|
||||
} else if (config.invoiceCheckout) {
|
||||
throw new RecaseError({
|
||||
message: `Not allowed to ${action} when using 'invoice': true`,
|
||||
code: ErrCode.InvalidRequest,
|
||||
statusCode: StatusCodes.BAD_REQUEST,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const handlePrepaidErrors = async ({
|
||||
attachParams,
|
||||
config,
|
||||
useCheckout = false,
|
||||
}: {
|
||||
attachParams: AttachParams;
|
||||
config: AttachConfig;
|
||||
useCheckout?: boolean;
|
||||
}) => {
|
||||
const { prices, entitlements, optionsList } = attachParams;
|
||||
@@ -69,7 +85,10 @@ const handlePrepaidErrors = async ({
|
||||
let options = getEntOptions(optionsList, priceEnt);
|
||||
|
||||
// 1. If not checkout, quantity should be defined
|
||||
if (!useCheckout && nullOrUndefined(options?.quantity)) {
|
||||
|
||||
const regularCheckout = useCheckout && !config.invoiceCheckout;
|
||||
|
||||
if (!regularCheckout && nullOrUndefined(options?.quantity)) {
|
||||
throw new RecaseError({
|
||||
message: `Pass in 'quantity' for feature ${priceEnt.feature_id} in options`,
|
||||
code: ErrCode.InvalidOptions,
|
||||
@@ -197,6 +216,8 @@ export const handleAttachErrors = async ({
|
||||
}) => {
|
||||
const { onlyCheckout } = config;
|
||||
|
||||
// Invoice no payment enabled: onlyCheckout
|
||||
|
||||
if (onlyCheckout || flags.isPublic) {
|
||||
let upgradeDowngradeFlows = [
|
||||
AttachBranch.Upgrade,
|
||||
@@ -206,6 +227,7 @@ export const handleAttachErrors = async ({
|
||||
if (upgradeDowngradeFlows.includes(branch)) {
|
||||
handleNonCheckoutErrors({
|
||||
flags,
|
||||
config,
|
||||
action: "perform upgrade or downgrade",
|
||||
});
|
||||
}
|
||||
@@ -218,6 +240,7 @@ export const handleAttachErrors = async ({
|
||||
handleNonCheckoutErrors({
|
||||
flags,
|
||||
action: "update current product",
|
||||
config,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -236,6 +259,7 @@ export const handleAttachErrors = async ({
|
||||
|
||||
await handlePrepaidErrors({
|
||||
attachParams,
|
||||
config,
|
||||
useCheckout: onlyCheckout,
|
||||
});
|
||||
|
||||
|
||||
@@ -14,7 +14,10 @@ import { getAttachBranch } from "../attachUtils/getAttachBranch.js";
|
||||
import { getAttachConfig } from "../attachUtils/getAttachConfig.js";
|
||||
import { getAttachFunction } from "../attachUtils/getAttachFunction.js";
|
||||
import { handleCreateCheckout } from "../../add-product/handleCreateCheckout.js";
|
||||
import { checkStripeConnections } from "../attachRouter.js";
|
||||
import {
|
||||
checkStripeConnections,
|
||||
handlePrepaidErrors,
|
||||
} from "../attachRouter.js";
|
||||
import { attachParamsToPreview } from "../handleAttachPreview/attachParamsToPreview.js";
|
||||
import { previewToCheckoutRes } from "./previewToCheckoutRes.js";
|
||||
import { getProductResponse } from "@/internal/products/productUtils/productResponseUtils/getProductResponse.js";
|
||||
@@ -24,6 +27,7 @@ import { isPrepaidPrice } from "@/internal/products/prices/priceUtils/usagePrice
|
||||
import { priceToFeature } from "@/internal/products/prices/priceUtils/convertPrice.js";
|
||||
import { getPriceOptions } from "@/internal/products/prices/priceUtils.js";
|
||||
import { getHasProrations } from "./getHasProrations.js";
|
||||
import { handleCreateInvoiceCheckout } from "../../add-product/handleCreateInvoiceCheckout.js";
|
||||
|
||||
const getAttachVars = async ({
|
||||
req,
|
||||
@@ -108,17 +112,13 @@ export const handleCheckout = (req: any, res: any) =>
|
||||
const { logger, features } = req;
|
||||
const attachBody = AttachBodySchema.parse(req.body);
|
||||
|
||||
const { attachParams, branch, func } = await getAttachVars({
|
||||
const { attachParams, branch, func, config } = await getAttachVars({
|
||||
req,
|
||||
attachBody,
|
||||
});
|
||||
|
||||
await getCheckoutOptions({
|
||||
req,
|
||||
attachParams,
|
||||
});
|
||||
|
||||
let checkoutUrl = null;
|
||||
|
||||
if (func == AttachFunction.CreateCheckout) {
|
||||
await checkStripeConnections({
|
||||
req,
|
||||
@@ -127,33 +127,37 @@ export const handleCheckout = (req: any, res: any) =>
|
||||
useCheckout: true,
|
||||
});
|
||||
|
||||
const checkout = await handleCreateCheckout({
|
||||
req,
|
||||
res,
|
||||
attachParams,
|
||||
returnCheckout: true,
|
||||
});
|
||||
if (config.invoiceCheckout) {
|
||||
await handlePrepaidErrors({
|
||||
attachParams,
|
||||
config,
|
||||
useCheckout: config.onlyCheckout,
|
||||
});
|
||||
|
||||
checkoutUrl = checkout?.url;
|
||||
const result = await handleCreateInvoiceCheckout({
|
||||
req,
|
||||
attachParams,
|
||||
config,
|
||||
});
|
||||
|
||||
// const customer = attachParams.customer;
|
||||
// res.status(200).json(
|
||||
// CheckoutResponseSchema.parse({
|
||||
// url: checkout?.url,
|
||||
// customer_id: customer.id || customer.internal_id,
|
||||
// scenario: AttachScenario.New,
|
||||
// lines: [],
|
||||
// product: await getProductResponse({
|
||||
// product: attachParams.products[0],
|
||||
// features: features,
|
||||
// withDisplay: false,
|
||||
// options: attachParams.optionsList,
|
||||
// }),
|
||||
// })
|
||||
// );
|
||||
// return;
|
||||
checkoutUrl = result?.invoices?.[0]?.hosted_invoice_url;
|
||||
} else {
|
||||
const checkout = await handleCreateCheckout({
|
||||
req,
|
||||
res,
|
||||
attachParams,
|
||||
returnCheckout: true,
|
||||
});
|
||||
|
||||
checkoutUrl = checkout?.url;
|
||||
}
|
||||
}
|
||||
|
||||
await getCheckoutOptions({
|
||||
req,
|
||||
attachParams,
|
||||
});
|
||||
|
||||
const preview = await attachParamsToPreview({
|
||||
req,
|
||||
attachParams,
|
||||
|
||||
@@ -64,7 +64,10 @@ export const getNewProductPreview = async ({
|
||||
|
||||
let dueNextCycle = null;
|
||||
|
||||
if (freeTrial || notNullish(anchorToUnix)) {
|
||||
if (
|
||||
(freeTrial || notNullish(anchorToUnix)) &&
|
||||
branch != AttachBranch.OneOff
|
||||
) {
|
||||
let nextCycleItems = await getItemsForNewProduct({
|
||||
newProduct,
|
||||
attachParams,
|
||||
|
||||
@@ -30,6 +30,9 @@ export const handleAttachPreview = (req: any, res: any) =>
|
||||
logger,
|
||||
});
|
||||
|
||||
console.log("Branch:", attachPreview.branch);
|
||||
console.log("Func:", attachPreview.func);
|
||||
|
||||
res.status(200).json(attachPreview);
|
||||
|
||||
return;
|
||||
|
||||
@@ -58,9 +58,7 @@ export const getCusWithCache = async ({
|
||||
|
||||
if (!skipCache && !skipGet) {
|
||||
try {
|
||||
const start = Date.now();
|
||||
const cached = await upstash!.get(cacheKey);
|
||||
const end = Date.now();
|
||||
if (cached) {
|
||||
return cached as FullCustomer;
|
||||
} else {
|
||||
@@ -88,8 +86,9 @@ export const getCusWithCache = async ({
|
||||
|
||||
if (!skipCache && notNullish(customer)) {
|
||||
try {
|
||||
await upstash!.set(cacheKey, customer);
|
||||
await upstash!.expire(cacheKey, 300); // Expire after 5 minutes...
|
||||
await upstash!.set(cacheKey, customer, {
|
||||
ex: 300,
|
||||
});
|
||||
} catch (error) {
|
||||
logger.error(`Failed to set cache: ${cacheKey}`, { error });
|
||||
}
|
||||
|
||||
@@ -16,10 +16,11 @@ import {
|
||||
import Stripe from "stripe";
|
||||
import { DrizzleCli } from "@/db/initDrizzle.js";
|
||||
import { getBillingType } from "@/internal/products/prices/priceUtils.js";
|
||||
import { ACTIVE_STATUSES } from "../CusProductService.js";
|
||||
|
||||
export const cusProductsToCusPrices = ({
|
||||
cusProducts,
|
||||
inStatuses = [CusProductStatus.Active],
|
||||
inStatuses,
|
||||
billingType,
|
||||
}: {
|
||||
cusProducts: FullCusProduct[];
|
||||
@@ -29,7 +30,7 @@ export const cusProductsToCusPrices = ({
|
||||
const cusPrices: FullCustomerPrice[] = [];
|
||||
|
||||
for (const cusProduct of cusProducts) {
|
||||
if (!inStatuses.includes(cusProduct.status)) {
|
||||
if (inStatuses && !inStatuses.includes(cusProduct.status)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ import {
|
||||
cusProductsToCusPrices,
|
||||
} from "../../cusProducts/cusProductUtils/convertCusProduct.js";
|
||||
import { getCusBalances } from "./getCusBalances.js";
|
||||
import { ACTIVE_STATUSES } from "../../cusProducts/CusProductService.js";
|
||||
|
||||
export const getCusFeaturesResponse = async ({
|
||||
cusProducts,
|
||||
@@ -26,7 +27,9 @@ export const getCusFeaturesResponse = async ({
|
||||
|
||||
const balances = await getCusBalances({
|
||||
cusEntsWithCusProduct: cusEnts,
|
||||
cusPrices: cusProductsToCusPrices({ cusProducts }),
|
||||
cusPrices: cusProductsToCusPrices({
|
||||
cusProducts,
|
||||
}),
|
||||
org,
|
||||
entity,
|
||||
apiVersion,
|
||||
|
||||
@@ -96,6 +96,7 @@ export const getOrCreateCustomer = async ({
|
||||
email: customerData?.email,
|
||||
fingerprint: customerData?.fingerprint,
|
||||
metadata: customerData?.metadata || {},
|
||||
stripe_id: customerData?.stripe_id,
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@ export const initStripeCusAndProducts = async ({
|
||||
env,
|
||||
logger,
|
||||
product,
|
||||
}),
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
@@ -90,7 +90,7 @@ const handleIdIsNull = async ({
|
||||
for (const existingCustomer of existingCustomers) {
|
||||
if (existingCustomer.id === null) {
|
||||
logger.info(
|
||||
`Create customer by email: ${newCus.email} already exists, skipping...`,
|
||||
`Create customer by email: ${newCus.email} already exists, skipping...`
|
||||
);
|
||||
return existingCustomer;
|
||||
}
|
||||
@@ -134,7 +134,7 @@ export const handleCreateCustomerWithId = async ({
|
||||
|
||||
if (existingCustomer) {
|
||||
logger.info(
|
||||
`Customer already exists, skipping creation: ${existingCustomer.id}`,
|
||||
`Customer already exists, skipping creation: ${existingCustomer.id}`
|
||||
);
|
||||
return existingCustomer;
|
||||
}
|
||||
@@ -150,7 +150,7 @@ export const handleCreateCustomerWithId = async ({
|
||||
|
||||
if (cusWithEmail.length === 1 && cusWithEmail[0].id === null) {
|
||||
logger.info(
|
||||
`POST /customers, email ${newCus.email} and ID null found, updating ID to ${newCus.id} (org: ${org.slug})`,
|
||||
`POST /customers, email ${newCus.email} and ID null found, updating ID to ${newCus.id} (org: ${org.slug})`
|
||||
);
|
||||
|
||||
let updatedCustomer = await CusService.update({
|
||||
@@ -185,6 +185,7 @@ export const handleCreateCustomer = async ({
|
||||
createDefaultProducts?: boolean;
|
||||
}) => {
|
||||
const newCus = CreateCustomerSchema.parse(cusData);
|
||||
console.log("newCus", newCus);
|
||||
|
||||
// 1. If no ID and email is not NULL
|
||||
let createdCustomer;
|
||||
|
||||
@@ -11,6 +11,7 @@ export const handlePostCustomerRequest = async (req: any, res: any) => {
|
||||
const logger = req.logtail;
|
||||
try {
|
||||
const data = req.body;
|
||||
|
||||
const expand = parseCusExpand(req.query.expand);
|
||||
const { db, org, features } = req;
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import { OrgService } from "@/internal/orgs/OrgService.js";
|
||||
import RecaseError from "@/utils/errorUtils.js";
|
||||
import { notNullish } from "@/utils/genUtils.js";
|
||||
import { routeHandler } from "@/utils/routerUtils.js";
|
||||
import { CreateCustomerSchema, ErrCode } from "@autumn/shared";
|
||||
import { CreateCustomerSchema, ErrCode, ProcessorType } from "@autumn/shared";
|
||||
import { StatusCodes } from "http-status-codes";
|
||||
import { getCustomerDetails } from "../cusUtils/getCustomerDetails.js";
|
||||
import { parseCusExpand } from "../cusUtils/cusUtils.js";
|
||||
@@ -69,6 +69,20 @@ export const handleUpdateCustomer = async (req: any, res: any) =>
|
||||
delete newCusData.id;
|
||||
}
|
||||
|
||||
// Try to update stripe ID
|
||||
let stripeId = originalCustomer.processor?.id;
|
||||
let newStripeId = newCusData.stripe_id;
|
||||
|
||||
if (notNullish(newStripeId) && stripeId !== newStripeId) {
|
||||
const stripeCli = createStripeCli({ org, env: req.env });
|
||||
await stripeCli.customers.retrieve(newStripeId);
|
||||
|
||||
stripeId = newCusData.stripe_id;
|
||||
req.logger.info(
|
||||
`Updating customer's Stripe ID from ${originalCustomer.processor?.id} to ${stripeId}`
|
||||
);
|
||||
}
|
||||
|
||||
// 2. Check if customer email is being changed
|
||||
let oldMetadata = originalCustomer.metadata || {};
|
||||
let newMetadata = newCusData.metadata || {};
|
||||
@@ -90,15 +104,9 @@ export const handleUpdateCustomer = async (req: any, res: any) =>
|
||||
: undefined,
|
||||
};
|
||||
|
||||
if (
|
||||
Object.keys(stripeUpdate).length > 0 &&
|
||||
originalCustomer.processor?.id
|
||||
) {
|
||||
if (Object.keys(stripeUpdate).length > 0 && stripeId) {
|
||||
const stripeCli = createStripeCli({ org, env: req.env });
|
||||
await stripeCli.customers.update(
|
||||
originalCustomer.processor.id,
|
||||
stripeUpdate as any
|
||||
);
|
||||
await stripeCli.customers.update(stripeId, stripeUpdate as any);
|
||||
}
|
||||
|
||||
await CusService.update({
|
||||
@@ -106,6 +114,9 @@ export const handleUpdateCustomer = async (req: any, res: any) =>
|
||||
internalCusId: originalCustomer.internal_id,
|
||||
update: {
|
||||
...newCusData,
|
||||
processor: newStripeId
|
||||
? { id: newStripeId, type: ProcessorType.Stripe }
|
||||
: undefined,
|
||||
metadata: {
|
||||
...oldMetadata,
|
||||
...newMetadata,
|
||||
|
||||
@@ -23,6 +23,7 @@ import {
|
||||
cusProductToPrices,
|
||||
} from "../customers/cusProducts/cusProductUtils/convertCusProduct.js";
|
||||
import { priceToFeature } from "../products/prices/priceUtils/convertPrice.js";
|
||||
import { ACTIVE_STATUSES } from "../customers/cusProducts/CusProductService.js";
|
||||
|
||||
export const validateFeatureId = (featureId: string) => {
|
||||
if (!featureId.match(/^[a-zA-Z0-9_-]+$/)) {
|
||||
@@ -227,7 +228,9 @@ export const isPaidContinuousUse = ({
|
||||
|
||||
let cusPrices = cusProductsToCusPrices({
|
||||
cusProducts: fullCus.customer_products,
|
||||
inStatuses: ACTIVE_STATUSES,
|
||||
});
|
||||
|
||||
let hasPaid = cusPrices.some((cp) => {
|
||||
let config = cp.price.config as UsagePriceConfig;
|
||||
if (config.internal_feature_id == feature.internal_id) {
|
||||
|
||||
@@ -53,7 +53,7 @@ export const getItemsForCurProduct = async ({
|
||||
const curPrices = cusProductToPrices({ cusProduct: curCusProduct });
|
||||
|
||||
let items: PreviewLineItem[] = [];
|
||||
let onTrial = isTrialing(curMainProduct!);
|
||||
let onTrial = isTrialing(curCusProduct);
|
||||
|
||||
for (const sub of stripeSubs) {
|
||||
for (const item of sub.items.data) {
|
||||
|
||||
@@ -36,7 +36,7 @@ export const createCheckoutMetadata = async ({
|
||||
|
||||
export const getMetadataFromCheckoutSession = async (
|
||||
checkoutSession: Stripe.Checkout.Session,
|
||||
db: DrizzleCli,
|
||||
db: DrizzleCli
|
||||
) => {
|
||||
const metadataId = checkoutSession.metadata?.autumn_metadata_id;
|
||||
|
||||
|
||||
@@ -60,13 +60,6 @@ export const migrationToAttachParams = async ({
|
||||
|
||||
// Others
|
||||
apiVersion,
|
||||
// successUrl: attachBody.success_url,
|
||||
// invoiceOnly: attachBody.invoice_only,
|
||||
// billingAnchor: attachBody.billing_cycle_anchor,
|
||||
// metadata: attachBody.metadata,
|
||||
// disableFreeTrial: attachBody.free_trial === false || false,
|
||||
// checkoutSessionParams: attachBody.checkout_session_params,
|
||||
// isCustom: attachBody.is_custom,
|
||||
};
|
||||
|
||||
return attachParams;
|
||||
|
||||
@@ -19,6 +19,7 @@ import { z } from "zod";
|
||||
import { createKey } from "../dev/api-keys/apiKeyUtils.js";
|
||||
import { afterOrgCreated } from "@/utils/authUtils/afterOrgCreated.js";
|
||||
import { Autumn } from "autumn-js";
|
||||
import { organizationSchema } from "better-auth/plugins";
|
||||
|
||||
const platformRouter = Router();
|
||||
|
||||
@@ -63,6 +64,14 @@ const platformAuthMiddleware = async (
|
||||
platformRouter.use(platformAuthMiddleware);
|
||||
|
||||
const ExchangeSchema = z.object({
|
||||
// organization_name: z.string().nullish(),
|
||||
// organization_slug: z.string().nullish(),
|
||||
organization: z
|
||||
.object({
|
||||
name: z.string().nonempty(),
|
||||
slug: z.string().nonempty(),
|
||||
})
|
||||
.nullish(),
|
||||
email: z.string().regex(/^[^\s@]+@[^\s@]+\.[^\s@]+$/),
|
||||
stripe_test_key: z.string().nonempty().optional(),
|
||||
stripe_live_key: z.string().nonempty().optional(),
|
||||
@@ -121,9 +130,36 @@ platformRouter.post("/exchange", (req: any, res: any) =>
|
||||
|
||||
let org: Organization;
|
||||
|
||||
let membership = await db.query.member.findFirst({
|
||||
where: and(eq(member.userId, user.id!), eq(member.role, "owner")),
|
||||
});
|
||||
// let membership = await db.query.member.findFirst({
|
||||
// with: {
|
||||
// organization: true,
|
||||
// },
|
||||
// where: and(
|
||||
// eq(member.userId, user.id!),
|
||||
// eq(member.role, "owner"),
|
||||
// organization_slug
|
||||
// ? eq(organizations.slug, organization_slug)
|
||||
// : undefined,
|
||||
// eq(organizations.created_by, req.org.id)
|
||||
// ),
|
||||
// });
|
||||
const orgSlug = organization?.slug
|
||||
? `${organization.slug}_${req.org.id}`
|
||||
: undefined;
|
||||
const data = await db
|
||||
.select()
|
||||
.from(member)
|
||||
.innerJoin(organizations, eq(member.organizationId, organizations.id))
|
||||
.where(
|
||||
and(
|
||||
eq(member.userId, user.id!),
|
||||
eq(member.role, "owner"),
|
||||
orgSlug ? eq(organizations.slug, orgSlug) : undefined,
|
||||
eq(organizations.created_by, req.org.id)
|
||||
)
|
||||
);
|
||||
|
||||
let membership = data.length > 0 ? data[0] : null;
|
||||
|
||||
if (!membership) {
|
||||
logger.info(`Connected to Stripe`);
|
||||
@@ -135,8 +171,11 @@ platformRouter.post("/exchange", (req: any, res: any) =>
|
||||
.insert(organizations)
|
||||
.values({
|
||||
id: orgId,
|
||||
slug: `platform_org_${Math.floor(10000000 + Math.random() * 90000000)}`,
|
||||
name: `Platform Org`,
|
||||
slug: orgSlug
|
||||
? orgSlug
|
||||
: `platform_org_${Math.floor(10000000 + Math.random() * 90000000)}`,
|
||||
|
||||
name: organization?.name || `Platform Org (${req.org.id})`,
|
||||
logo: "",
|
||||
createdAt: new Date(),
|
||||
metadata: "",
|
||||
@@ -154,9 +193,10 @@ platformRouter.post("/exchange", (req: any, res: any) =>
|
||||
|
||||
await afterOrgCreated({ org });
|
||||
} else {
|
||||
org = (await db.query.organizations.findFirst({
|
||||
where: eq(organizations.id, membership.organizationId),
|
||||
})) as Organization;
|
||||
// org = (await db.query.organizations.findFirst({
|
||||
// where: eq(organizations.id, membership.organizationId),
|
||||
// })) as Organization;
|
||||
org = membership.organizations as Organization;
|
||||
}
|
||||
|
||||
let sandboxKey, prodKey;
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import Stripe from "stripe";
|
||||
import { constructPrice } from "../priceUtils.js";
|
||||
import { FullProduct, PriceType } from "@autumn/shared";
|
||||
import { generateId } from "@/utils/genUtils.js";
|
||||
import { subItemToAutumnInterval } from "tests/utils/stripeUtils.js";
|
||||
import { subItemToAutumnInterval } from "@/external/stripe/utils.js";
|
||||
|
||||
export const subItemToFixedPrice = ({
|
||||
subItem,
|
||||
|
||||
@@ -60,40 +60,9 @@ const validateProductItem = ({
|
||||
});
|
||||
}
|
||||
|
||||
// 3. If tiers are set, final tier must be infinite, and amount must be > 0
|
||||
if (notNullish(item.tiers)) {
|
||||
for (let i = 0; i < item.tiers!.length; i++) {
|
||||
let tier = item.tiers![i];
|
||||
if (tier.amount < 0) {
|
||||
throw new RecaseError({
|
||||
message: `Tier amount must be >= 0`,
|
||||
code: ErrCode.InvalidProductItem,
|
||||
statusCode: StatusCodes.BAD_REQUEST,
|
||||
});
|
||||
}
|
||||
|
||||
if (i > 0 && tier.to <= item.tiers![i - 1].to) {
|
||||
throw new RecaseError({
|
||||
message: `Tier ${i + 1} should have a greater 'to' than tier ${i}`,
|
||||
code: ErrCode.InvalidProductItem,
|
||||
statusCode: StatusCodes.BAD_REQUEST,
|
||||
});
|
||||
}
|
||||
|
||||
if (i == item.tiers!.length - 1 && tier.to != TierInfinite) {
|
||||
throw new RecaseError({
|
||||
message: `Final tier must be infinite${
|
||||
item.feature_id ? ` (feature: ${item.feature_id})` : ""
|
||||
}`,
|
||||
code: ErrCode.InvalidProductItem,
|
||||
statusCode: StatusCodes.BAD_REQUEST,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 4. One off prices / fixed prices can have at most 2 decimal places
|
||||
if ((isFeaturePriceItem(item) && !item.interval) || isPriceItem(item)) {
|
||||
// (isFeaturePriceItem(item) && !item.interval && isOneOff) ||
|
||||
if (isPriceItem(item)) {
|
||||
// One off price..., can't have more than 2 DP
|
||||
if (item.price && item.price.toString().split(".")[1]?.length > 2) {
|
||||
throw new RecaseError({
|
||||
@@ -103,17 +72,17 @@ const validateProductItem = ({
|
||||
});
|
||||
}
|
||||
|
||||
if (item.tiers) {
|
||||
item.tiers.forEach((tier) => {
|
||||
if (tier.amount.toString().split(".")[1]?.length > 2) {
|
||||
throw new RecaseError({
|
||||
message: `One off prices can have at most 2 decimal places`,
|
||||
code: ErrCode.InvalidInputs,
|
||||
statusCode: StatusCodes.BAD_REQUEST,
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
// if (item.tiers) {
|
||||
// item.tiers.forEach((tier) => {
|
||||
// if (tier.amount.toString().split(".")[1]?.length > 2) {
|
||||
// throw new RecaseError({
|
||||
// message: `One off prices can have at most 2 decimal places`,
|
||||
// code: ErrCode.InvalidInputs,
|
||||
// statusCode: StatusCodes.BAD_REQUEST,
|
||||
// });
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
}
|
||||
|
||||
// 4. If it's a feature item, it should have included usage as number or inf
|
||||
@@ -169,6 +138,7 @@ const validateProductItem = ({
|
||||
// }
|
||||
// }
|
||||
};
|
||||
|
||||
export const validateProductItems = ({
|
||||
newItems,
|
||||
features,
|
||||
@@ -189,6 +159,13 @@ export const validateProductItems = ({
|
||||
|
||||
features = allFeatures;
|
||||
|
||||
// const isOneOff =
|
||||
// newItems.every((item) => {
|
||||
// if (isFeatureItem(item)) return true;
|
||||
// return nullish(item.interval);
|
||||
// }) &&
|
||||
// newItems.some((item) => isFeaturePriceItem(item) || isPriceItem(item));
|
||||
|
||||
// 1. Check values
|
||||
for (let index = 0; index < newItems.length; index++) {
|
||||
validateProductItem({ item: newItems[index], features });
|
||||
@@ -251,10 +228,23 @@ export const validateProductItems = ({
|
||||
continue;
|
||||
}
|
||||
|
||||
if (
|
||||
isFeatureItem(otherItem) ||
|
||||
(item.usage_model && item.usage_model == otherItem?.usage_model)
|
||||
) {
|
||||
if (isFeatureItem(otherItem) && isFeatureItem(item)) {
|
||||
throw new RecaseError({
|
||||
message: `You're trying to create two items for the same feature (${item.feature_id}) with the same interval. Please make them into one item.`,
|
||||
code: ErrCode.InvalidInputs,
|
||||
statusCode: StatusCodes.BAD_REQUEST,
|
||||
});
|
||||
}
|
||||
|
||||
if (isFeatureItem(otherItem)) {
|
||||
throw new RecaseError({
|
||||
message: `You have a usage-based price for for this feature (${item.feature_id}). If you're looking to create an overage item (eg. 100 free, then $0.5 thereafter), you should add it to the existing item.`,
|
||||
code: ErrCode.InvalidInputs,
|
||||
statusCode: StatusCodes.BAD_REQUEST,
|
||||
});
|
||||
}
|
||||
|
||||
if (item.usage_model && item.usage_model == otherItem?.usage_model) {
|
||||
throw new RecaseError({
|
||||
message: `You're trying to add the same feature (${item.feature_id}), with the same reset interval. You should either change the reset interval of one of the items, or make one of them a prepaid quantity`,
|
||||
code: ErrCode.InvalidInputs,
|
||||
|
||||
@@ -47,6 +47,7 @@ export const formatTiers = ({
|
||||
return formatAmount({
|
||||
currency,
|
||||
amount: tiers[0].amount,
|
||||
maxFractionDigits: 10,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -56,9 +57,11 @@ export const formatTiers = ({
|
||||
return `${formatAmount({
|
||||
currency,
|
||||
amount: firstPrice,
|
||||
maxFractionDigits: 10,
|
||||
})} - ${formatAmount({
|
||||
currency,
|
||||
amount: lastPrice,
|
||||
maxFractionDigits: 10,
|
||||
})}`;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -696,6 +696,7 @@ export const runUpdateBalanceTask = async ({
|
||||
entityId,
|
||||
});
|
||||
|
||||
// console.time("refreshCusCache");
|
||||
await refreshCusCache({
|
||||
db,
|
||||
customerId,
|
||||
@@ -703,6 +704,7 @@ export const runUpdateBalanceTask = async ({
|
||||
env,
|
||||
entityId,
|
||||
});
|
||||
// console.timeEnd("refreshCusCache");
|
||||
|
||||
if (!cusEnts || cusEnts.length === 0) {
|
||||
return;
|
||||
|
||||
@@ -10,7 +10,11 @@ export const getActiveCusProductStatuses = () => [
|
||||
|
||||
export const ADMIN_USER_IDs =
|
||||
process.env.ENV == "production" || process.env.NODE_ENV == "production"
|
||||
? ["user_2tMgAiPsQzX8JTHjZZh9m0VdvUv", "user_2sB3tBXsnVVLlTKliQIqvvM2xfB"]
|
||||
? [
|
||||
"user_2tMgAiPsQzX8JTHjZZh9m0VdvUv", // a
|
||||
"user_2sB3tBXsnVVLlTKliQIqvvM2xfB", // j
|
||||
"ZsDswIXyOGMP9y1V1At4dAZNaiggClSs", // t
|
||||
]
|
||||
: ["user_2rypooIKyMQx81vMS8FFGx24UHU"];
|
||||
|
||||
export const dashboardOrigins = [
|
||||
|
||||
@@ -143,8 +143,8 @@ export const handleRequestError = ({
|
||||
);
|
||||
|
||||
res.status(400).json({
|
||||
message: error.message,
|
||||
code: ErrCode.InvalidInputs,
|
||||
message: `(Stripe Error) ${error.message}`,
|
||||
code: `stripe_error`,
|
||||
});
|
||||
} else if (error instanceof ZodError) {
|
||||
logger.error(
|
||||
|
||||
@@ -56,9 +56,9 @@ export const addProductFromSubs = async ({
|
||||
|
||||
if (mainCusProduct && !force) {
|
||||
let prices = mainCusProduct.customer_prices.map((cp) => cp.price);
|
||||
let isFree = isFreeProduct(prices);
|
||||
// let isFree = isFreeProduct(prices);
|
||||
|
||||
if (!isFree) {
|
||||
if (mainCusProduct) {
|
||||
logger.info(
|
||||
`Customer ${
|
||||
autumnCus.id || autumnCus.email
|
||||
@@ -71,10 +71,12 @@ export const addProductFromSubs = async ({
|
||||
}
|
||||
|
||||
// Handle if trialing
|
||||
let trialEndsAt = stripeSubs[0].trial_end
|
||||
let trialEndsAt = stripeSubs?.[0]?.trial_end
|
||||
? stripeSubs[0].trial_end * 1000
|
||||
: null;
|
||||
|
||||
// throw new Error("test");
|
||||
|
||||
// 1. Insert custom prices...
|
||||
let customPrices = prices?.filter((p) => p.is_custom);
|
||||
if (customPrices && customPrices.length > 0) {
|
||||
@@ -107,17 +109,17 @@ export const addProductFromSubs = async ({
|
||||
logger,
|
||||
trialEndsAt: trialEndsAt || undefined,
|
||||
subscriptionIds: stripeSubs.map((s) => s.id),
|
||||
anchorToUnix: anchorToUnix || stripeSubs[0].current_period_end * 1000,
|
||||
anchorToUnix: anchorToUnix || stripeSubs?.[0]?.current_period_end * 1000,
|
||||
|
||||
subscriptionStatus: stripeToAutumnSubStatus(
|
||||
stripeSubs[0].status
|
||||
) as CusProductStatus,
|
||||
subscriptionStatus: stripeSubs?.[0]?.status
|
||||
? (stripeToAutumnSubStatus(stripeSubs[0].status) as CusProductStatus)
|
||||
: undefined,
|
||||
|
||||
canceledAt: stripeSubs[0].canceled_at
|
||||
canceledAt: stripeSubs?.[0]?.canceled_at
|
||||
? stripeSubs[0].canceled_at * 1000
|
||||
: null,
|
||||
|
||||
createdAt: stripeSubs[0].created * 1000,
|
||||
createdAt: stripeSubs?.[0]?.created ? stripeSubs[0].created * 1000 : null,
|
||||
sendWebhook: false,
|
||||
});
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import {
|
||||
FullProduct,
|
||||
UsagePriceConfig,
|
||||
FullCusProduct,
|
||||
BillingInterval,
|
||||
} from "@autumn/shared";
|
||||
import Stripe from "stripe";
|
||||
import { ExtendedRequest } from "../models/Request.js";
|
||||
@@ -26,11 +27,15 @@ export const addContUsePricesToSub = async ({
|
||||
quantity: number;
|
||||
logger: any;
|
||||
}) => {
|
||||
const usagePrices = filterByBillingType({
|
||||
let usagePrices = filterByBillingType({
|
||||
prices: autumnProduct.prices,
|
||||
billingType: BillingType.InArrearProrated,
|
||||
});
|
||||
|
||||
usagePrices = usagePrices.filter(
|
||||
(p) => p.config.interval !== BillingInterval.OneOff
|
||||
);
|
||||
|
||||
logger.info(`Adding ${usagePrices.length} cont use prices to sub`);
|
||||
|
||||
for (const usagePrice of usagePrices) {
|
||||
@@ -100,12 +105,12 @@ export const addUsagePricesToSub = async ({
|
||||
|
||||
logger.info(`Adding ${config.feature_id} to sub ${stripeSub.id}`);
|
||||
let stripePrice = await stripeCli.prices.retrieve(
|
||||
price.config.stripe_price_id!,
|
||||
price.config.stripe_price_id!
|
||||
);
|
||||
|
||||
if (stripePrice.recurring?.usage_type !== "metered") {
|
||||
logger.info(
|
||||
`Skipping ${config.feature_id} because it's not a metered price`,
|
||||
`Skipping ${config.feature_id} because it's not a metered price`
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
import { FeatureOptions } from "@autumn/shared";
|
||||
import csvParser from "csv-parser";
|
||||
import fs from "fs";
|
||||
|
||||
export interface ImportCustomer {
|
||||
id: string;
|
||||
name: string;
|
||||
email?: string;
|
||||
stripe_id: string;
|
||||
product_id: string;
|
||||
base_price?: number;
|
||||
options?: FeatureOptions[];
|
||||
// business_id;name;email;active_pass_count;Stripe id;Base price;free_trial_end
|
||||
}
|
||||
export const parseCsv = ({
|
||||
slug,
|
||||
filename,
|
||||
}: {
|
||||
slug: string;
|
||||
filename?: string;
|
||||
}): Promise<any[]> => {
|
||||
const path = `scripts/customers/${slug}/${filename || "data.csv"}`;
|
||||
const results: ImportCustomer[] = [];
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
const stream = fs.createReadStream(path);
|
||||
stream
|
||||
.pipe(csvParser({ separator: ";" }))
|
||||
.on("data", (data) =>
|
||||
results.push({
|
||||
id: data.business_id,
|
||||
name: data.name,
|
||||
email: data.email,
|
||||
stripe_id: data["Stripe id"],
|
||||
// base_price: data["Base price"],
|
||||
product_id: "standard_subscription",
|
||||
base_price: data["Base price"],
|
||||
options: [
|
||||
{
|
||||
feature_id: "active_passes",
|
||||
quantity: data["active_pass_count"],
|
||||
},
|
||||
],
|
||||
}),
|
||||
)
|
||||
.on("end", () => resolve(results))
|
||||
.on("error", (error) => reject(error));
|
||||
});
|
||||
};
|
||||
@@ -8,7 +8,7 @@ import {
|
||||
} from "@autumn/shared";
|
||||
import { and, eq, inArray } from "drizzle-orm";
|
||||
|
||||
const clearCustomersInBatches = async ({
|
||||
export const clearCustomersInBatches = async ({
|
||||
db,
|
||||
org,
|
||||
batchSize = 450,
|
||||
@@ -38,6 +38,8 @@ const clearCustomersInBatches = async ({
|
||||
.map((c) => c.internalId)
|
||||
.filter((id) => id !== null);
|
||||
|
||||
console.log("Deleting customers:", customerIds);
|
||||
|
||||
await db
|
||||
.delete(customers)
|
||||
.where(inArray(customers.internal_id, customerIds));
|
||||
|
||||
@@ -1,13 +1,19 @@
|
||||
import csv from "csv-parser";
|
||||
import fs from "fs";
|
||||
|
||||
export const parseCsv = (path: string) => {
|
||||
export const parseCsv = ({
|
||||
path,
|
||||
delimiter = ",",
|
||||
}: {
|
||||
path: string;
|
||||
delimiter?: string;
|
||||
}) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const stream = fs.createReadStream(path);
|
||||
const results: any[] = [];
|
||||
let headers: string[] = [];
|
||||
stream
|
||||
.pipe(csv({ separator: "," }))
|
||||
.pipe(csv({ separator: delimiter }))
|
||||
.on("data", (data) => {
|
||||
results.push(data);
|
||||
// if (headers.length === 0) {
|
||||
|
||||
158
server/tests/attach/addOn/addOn1.ts
Normal file
158
server/tests/attach/addOn/addOn1.ts
Normal file
@@ -0,0 +1,158 @@
|
||||
import { AutumnInt } from "@/external/autumn/autumnCli.js";
|
||||
import { initCustomer } from "@/utils/scriptUtils/initCustomer.js";
|
||||
import { APIVersion, AppEnv, Organization } from "@autumn/shared";
|
||||
import chalk from "chalk";
|
||||
import Stripe from "stripe";
|
||||
import { DrizzleCli } from "@/db/initDrizzle.js";
|
||||
import { setupBefore } from "tests/before.js";
|
||||
import { createProducts } from "tests/utils/productUtils.js";
|
||||
import { addPrefixToProducts, replaceItems } from "../utils.js";
|
||||
import {
|
||||
constructProduct,
|
||||
constructRawProduct,
|
||||
} from "@/utils/scriptUtils/createTestProducts.js";
|
||||
import {
|
||||
constructArrearProratedItem,
|
||||
constructFeatureItem,
|
||||
} from "@/utils/scriptUtils/constructItem.js";
|
||||
import { TestFeature } from "tests/setup/v2Features.js";
|
||||
import { attachAndExpectCorrect } from "tests/utils/expectUtils/expectAttach.js";
|
||||
import { expect } from "chai";
|
||||
import { expectProductAttached } from "tests/utils/expectUtils/expectProductAttached.js";
|
||||
|
||||
export let pro = constructProduct({
|
||||
items: [
|
||||
constructFeatureItem({
|
||||
featureId: TestFeature.Messages,
|
||||
includedUsage: 100,
|
||||
}),
|
||||
],
|
||||
type: "pro",
|
||||
});
|
||||
|
||||
export let addOn = constructRawProduct({
|
||||
id: "add_on_1",
|
||||
items: [
|
||||
constructFeatureItem({
|
||||
featureId: TestFeature.Messages,
|
||||
includedUsage: 200,
|
||||
}),
|
||||
],
|
||||
isAddOn: true,
|
||||
});
|
||||
|
||||
const testCase = "addOn1";
|
||||
|
||||
describe(`${chalk.yellowBright(`${testCase}: Testing free add on, and updating free add on`)}`, () => {
|
||||
let customerId = testCase;
|
||||
let autumn: AutumnInt = new AutumnInt({ version: APIVersion.v1_2 });
|
||||
let testClockId: string;
|
||||
let db: DrizzleCli, org: Organization, env: AppEnv;
|
||||
let stripeCli: Stripe;
|
||||
|
||||
let curUnix = new Date().getTime();
|
||||
|
||||
before(async function () {
|
||||
await setupBefore(this);
|
||||
const { autumnJs } = this;
|
||||
db = this.db;
|
||||
org = this.org;
|
||||
env = this.env;
|
||||
|
||||
stripeCli = this.stripeCli;
|
||||
|
||||
addPrefixToProducts({
|
||||
products: [pro, addOn],
|
||||
prefix: testCase,
|
||||
});
|
||||
|
||||
await createProducts({
|
||||
autumn,
|
||||
products: [pro, addOn],
|
||||
customerId,
|
||||
db,
|
||||
orgId: org.id,
|
||||
env,
|
||||
});
|
||||
|
||||
const { testClockId: testClockId1 } = await initCustomer({
|
||||
autumn: autumnJs,
|
||||
customerId,
|
||||
db,
|
||||
org,
|
||||
env,
|
||||
attachPm: "success",
|
||||
});
|
||||
|
||||
testClockId = testClockId1!;
|
||||
});
|
||||
|
||||
it("should should attach pro product, then add on product", async function () {
|
||||
await attachAndExpectCorrect({
|
||||
autumn,
|
||||
db,
|
||||
org,
|
||||
env,
|
||||
stripeCli,
|
||||
customerId,
|
||||
product: pro,
|
||||
});
|
||||
});
|
||||
|
||||
it("should should attach add on product", async function () {
|
||||
const preview = await autumn.attachPreview({
|
||||
customer_id: customerId,
|
||||
product_id: addOn.id,
|
||||
});
|
||||
|
||||
await autumn.attach({
|
||||
customer_id: customerId,
|
||||
product_id: addOn.id,
|
||||
});
|
||||
|
||||
const customer = await autumn.customers.get(customerId);
|
||||
|
||||
expect(customer.products.length).to.equal(3);
|
||||
expectProductAttached({
|
||||
customer,
|
||||
product: addOn,
|
||||
});
|
||||
expectProductAttached({
|
||||
customer,
|
||||
product: pro,
|
||||
});
|
||||
});
|
||||
|
||||
const customItems = replaceItems({
|
||||
items: addOn.items,
|
||||
featureId: TestFeature.Messages,
|
||||
newItem: constructFeatureItem({
|
||||
featureId: TestFeature.Messages,
|
||||
includedUsage: 400,
|
||||
}),
|
||||
});
|
||||
|
||||
it("should update add on product", async function () {
|
||||
const preview = await autumn.attachPreview({
|
||||
customer_id: customerId,
|
||||
product_id: addOn.id,
|
||||
is_custom: true,
|
||||
items: customItems,
|
||||
});
|
||||
|
||||
await autumn.attach({
|
||||
customer_id: customerId,
|
||||
product_id: addOn.id,
|
||||
is_custom: true,
|
||||
items: customItems,
|
||||
});
|
||||
|
||||
const customer = await autumn.customers.get(customerId);
|
||||
|
||||
expect(customer.products.length).to.equal(3);
|
||||
expectProductAttached({
|
||||
customer,
|
||||
product: addOn,
|
||||
});
|
||||
});
|
||||
});
|
||||
118
server/tests/attach/checkout/checkout5.ts
Normal file
118
server/tests/attach/checkout/checkout5.ts
Normal file
@@ -0,0 +1,118 @@
|
||||
import { AutumnInt } from "@/external/autumn/autumnCli.js";
|
||||
import { initCustomer } from "@/utils/scriptUtils/initCustomer.js";
|
||||
import { APIVersion, AppEnv, Organization } from "@autumn/shared";
|
||||
import chalk from "chalk";
|
||||
import Stripe from "stripe";
|
||||
import { DrizzleCli } from "@/db/initDrizzle.js";
|
||||
import { setupBefore } from "tests/before.js";
|
||||
import { createProducts, createReward } from "tests/utils/productUtils.js";
|
||||
import { addPrefixToProducts } from "../utils.js";
|
||||
import {
|
||||
constructCoupon,
|
||||
constructProduct,
|
||||
} from "@/utils/scriptUtils/createTestProducts.js";
|
||||
import { constructFeatureItem } from "@/utils/scriptUtils/constructItem.js";
|
||||
import { TestFeature } from "tests/setup/v2Features.js";
|
||||
import { completeCheckoutForm } from "tests/utils/stripeUtils.js";
|
||||
import { timeout } from "@/utils/genUtils.js";
|
||||
import { expectProductAttached } from "tests/utils/expectUtils/expectProductAttached.js";
|
||||
import { expect } from "chai";
|
||||
import { getBasePrice } from "tests/utils/testProductUtils/testProductUtils.js";
|
||||
import { completeInvoiceCheckout } from "tests/utils/stripeUtils/completeInvoiceCheckout.js";
|
||||
import { expectFeaturesCorrect } from "tests/utils/expectUtils/expectFeaturesCorrect.js";
|
||||
|
||||
export let pro = constructProduct({
|
||||
items: [
|
||||
constructFeatureItem({
|
||||
featureId: TestFeature.Messages,
|
||||
includedUsage: 100,
|
||||
}),
|
||||
],
|
||||
type: "pro",
|
||||
});
|
||||
|
||||
const testCase = "checkout5";
|
||||
describe(`${chalk.yellowBright(`${testCase}: Testing invoice checkout, no product till paid`)}`, () => {
|
||||
let customerId = testCase;
|
||||
let autumn: AutumnInt = new AutumnInt({ version: APIVersion.v1_2 });
|
||||
let testClockId: string;
|
||||
let db: DrizzleCli, org: Organization, env: AppEnv;
|
||||
let stripeCli: Stripe;
|
||||
let curUnix = new Date().getTime();
|
||||
|
||||
before(async function () {
|
||||
await setupBefore(this);
|
||||
const { autumnJs } = this;
|
||||
db = this.db;
|
||||
org = this.org;
|
||||
env = this.env;
|
||||
|
||||
stripeCli = this.stripeCli;
|
||||
|
||||
addPrefixToProducts({
|
||||
products: [pro],
|
||||
prefix: testCase,
|
||||
});
|
||||
|
||||
await createProducts({
|
||||
autumn,
|
||||
products: [pro],
|
||||
customerId,
|
||||
db,
|
||||
orgId: org.id,
|
||||
env,
|
||||
});
|
||||
|
||||
const { testClockId: testClockId1 } = await initCustomer({
|
||||
autumn: autumnJs,
|
||||
customerId,
|
||||
db,
|
||||
org,
|
||||
env,
|
||||
// attachPm: "success",
|
||||
});
|
||||
|
||||
testClockId = testClockId1!;
|
||||
});
|
||||
|
||||
it("should attach pro product", async function () {
|
||||
const res = await autumn.attach({
|
||||
customer_id: customerId,
|
||||
product_id: pro.id,
|
||||
invoice: true,
|
||||
});
|
||||
|
||||
const customer = await autumn.customers.get(customerId);
|
||||
|
||||
const invoice = customer.invoices?.[0];
|
||||
|
||||
expect(invoice).to.exist;
|
||||
expect(invoice.total).to.equal(getBasePrice({ product: pro }));
|
||||
expect(invoice.status).to.equal("open");
|
||||
|
||||
const product = customer.products.find((p) => p.id === pro.id);
|
||||
expect(product).to.not.exist;
|
||||
|
||||
await completeInvoiceCheckout({
|
||||
url: res.checkout_url,
|
||||
});
|
||||
|
||||
const customer2 = await autumn.customers.get(customerId);
|
||||
|
||||
const invoice2 = customer2.invoices?.[0];
|
||||
|
||||
expect(customer2.invoices.length).to.equal(1);
|
||||
expect(invoice2).to.exist;
|
||||
expect(invoice2.status).to.equal("paid");
|
||||
|
||||
expectProductAttached({
|
||||
customer: customer2,
|
||||
product: pro,
|
||||
});
|
||||
|
||||
expectFeaturesCorrect({
|
||||
customer: customer2,
|
||||
product: pro,
|
||||
});
|
||||
});
|
||||
});
|
||||
158
server/tests/attach/checkout/checkout6.ts
Normal file
158
server/tests/attach/checkout/checkout6.ts
Normal file
@@ -0,0 +1,158 @@
|
||||
import chalk from "chalk";
|
||||
import Stripe from "stripe";
|
||||
|
||||
import { AutumnInt } from "@/external/autumn/autumnCli.js";
|
||||
import { initCustomer } from "@/utils/scriptUtils/initCustomer.js";
|
||||
import { APIVersion, AppEnv, Organization } from "@autumn/shared";
|
||||
import { DrizzleCli } from "@/db/initDrizzle.js";
|
||||
import { setupBefore } from "tests/before.js";
|
||||
import { createProducts } from "tests/utils/productUtils.js";
|
||||
import { addPrefixToProducts } from "../utils.js";
|
||||
import { constructProduct } from "@/utils/scriptUtils/createTestProducts.js";
|
||||
import { constructFeatureItem } from "@/utils/scriptUtils/constructItem.js";
|
||||
import { TestFeature } from "tests/setup/v2Features.js";
|
||||
import { completeInvoiceCheckout } from "tests/utils/stripeUtils/completeInvoiceCheckout.js";
|
||||
import { expect } from "chai";
|
||||
import { expectProductAttached } from "tests/utils/expectUtils/expectProductAttached.js";
|
||||
import { expectFeaturesCorrect } from "tests/utils/expectUtils/expectFeaturesCorrect.js";
|
||||
import { expectAutumnError } from "tests/utils/expectUtils/expectErrUtils.js";
|
||||
import { getBasePrice } from "tests/utils/testProductUtils/testProductUtils.js";
|
||||
|
||||
export let pro = constructProduct({
|
||||
items: [
|
||||
constructFeatureItem({
|
||||
featureId: TestFeature.Messages,
|
||||
includedUsage: 100,
|
||||
}),
|
||||
],
|
||||
type: "pro",
|
||||
});
|
||||
|
||||
export let premium = constructProduct({
|
||||
items: [
|
||||
constructFeatureItem({
|
||||
featureId: TestFeature.Messages,
|
||||
includedUsage: 250,
|
||||
}),
|
||||
],
|
||||
type: "premium",
|
||||
});
|
||||
|
||||
const testCase = "checkout6";
|
||||
describe(`${chalk.yellowBright(`${testCase}: Testing invoice checkout via checkout endpoint`)}`, () => {
|
||||
let customerId = testCase;
|
||||
let autumn: AutumnInt = new AutumnInt({ version: APIVersion.v1_2 });
|
||||
let testClockId: string;
|
||||
let db: DrizzleCli, org: Organization, env: AppEnv;
|
||||
let stripeCli: Stripe;
|
||||
let curUnix = new Date().getTime();
|
||||
|
||||
before(async function () {
|
||||
await setupBefore(this);
|
||||
const { autumnJs } = this;
|
||||
db = this.db;
|
||||
org = this.org;
|
||||
env = this.env;
|
||||
|
||||
stripeCli = this.stripeCli;
|
||||
|
||||
addPrefixToProducts({
|
||||
products: [pro, premium],
|
||||
prefix: testCase,
|
||||
});
|
||||
|
||||
await createProducts({
|
||||
autumn,
|
||||
products: [pro, premium],
|
||||
customerId,
|
||||
db,
|
||||
orgId: org.id,
|
||||
env,
|
||||
});
|
||||
|
||||
const { testClockId: testClockId1 } = await initCustomer({
|
||||
autumn: autumnJs,
|
||||
customerId,
|
||||
db,
|
||||
org,
|
||||
env,
|
||||
attachPm: "success",
|
||||
});
|
||||
|
||||
testClockId = testClockId1!;
|
||||
});
|
||||
|
||||
it("should attach pro product via invoice checkout", async function () {
|
||||
const res = await autumn.checkout({
|
||||
customer_id: customerId,
|
||||
product_id: pro.id,
|
||||
invoice: true,
|
||||
});
|
||||
|
||||
expect(res.url).to.exist;
|
||||
|
||||
await completeInvoiceCheckout({
|
||||
url: res.url!,
|
||||
});
|
||||
|
||||
const customer = await autumn.customers.get(customerId);
|
||||
|
||||
expectProductAttached({
|
||||
customer,
|
||||
product: pro,
|
||||
});
|
||||
|
||||
expectFeaturesCorrect({
|
||||
customer,
|
||||
product: pro,
|
||||
});
|
||||
});
|
||||
|
||||
it("should have no URL returned if try to attach premium (with invoice true)", async function () {
|
||||
await expectAutumnError({
|
||||
func: async () => {
|
||||
await autumn.attach({
|
||||
customer_id: customerId,
|
||||
product_id: premium.id,
|
||||
invoice: true,
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
const res = await autumn.checkout({
|
||||
customer_id: customerId,
|
||||
product_id: premium.id,
|
||||
invoice: true,
|
||||
});
|
||||
|
||||
expect(res.url).to.not.exist;
|
||||
});
|
||||
|
||||
it("should attach premium product via invoice enable immediately", async function () {
|
||||
const res = await autumn.attach({
|
||||
customer_id: customerId,
|
||||
product_id: premium.id,
|
||||
invoice: true,
|
||||
enable_product_immediately: true,
|
||||
});
|
||||
|
||||
const customer = await autumn.customers.get(customerId);
|
||||
|
||||
expectProductAttached({
|
||||
customer,
|
||||
product: premium,
|
||||
});
|
||||
|
||||
expectFeaturesCorrect({
|
||||
customer,
|
||||
product: premium,
|
||||
});
|
||||
|
||||
const invoices = customer.invoices;
|
||||
expect(invoices.length).to.equal(2);
|
||||
expect(invoices[0].status).to.equal("draft");
|
||||
expect(invoices[0].total).to.equal(
|
||||
getBasePrice({ product: premium }) - getBasePrice({ product: pro })
|
||||
); // proration...
|
||||
});
|
||||
});
|
||||
141
server/tests/attach/checkout/checkout7.ts
Normal file
141
server/tests/attach/checkout/checkout7.ts
Normal file
@@ -0,0 +1,141 @@
|
||||
import chalk from "chalk";
|
||||
import Stripe from "stripe";
|
||||
|
||||
import { AutumnInt } from "@/external/autumn/autumnCli.js";
|
||||
import { initCustomer } from "@/utils/scriptUtils/initCustomer.js";
|
||||
import { APIVersion, AppEnv, Organization } from "@autumn/shared";
|
||||
import { DrizzleCli } from "@/db/initDrizzle.js";
|
||||
import { setupBefore } from "tests/before.js";
|
||||
import { createProducts } from "tests/utils/productUtils.js";
|
||||
import { addPrefixToProducts } from "../utils.js";
|
||||
import {
|
||||
constructProduct,
|
||||
constructRawProduct,
|
||||
} from "@/utils/scriptUtils/createTestProducts.js";
|
||||
import {
|
||||
constructFeatureItem,
|
||||
constructPrepaidItem,
|
||||
} from "@/utils/scriptUtils/constructItem.js";
|
||||
import { TestFeature } from "tests/setup/v2Features.js";
|
||||
import { completeInvoiceCheckout } from "tests/utils/stripeUtils/completeInvoiceCheckout.js";
|
||||
import { expect } from "chai";
|
||||
import { expectProductAttached } from "tests/utils/expectUtils/expectProductAttached.js";
|
||||
import { expectFeaturesCorrect } from "tests/utils/expectUtils/expectFeaturesCorrect.js";
|
||||
|
||||
export let pro = constructProduct({
|
||||
items: [
|
||||
constructFeatureItem({
|
||||
featureId: TestFeature.Messages,
|
||||
includedUsage: 100,
|
||||
}),
|
||||
],
|
||||
type: "pro",
|
||||
});
|
||||
|
||||
export let addOn = constructRawProduct({
|
||||
id: "addOn",
|
||||
items: [
|
||||
constructPrepaidItem({
|
||||
featureId: TestFeature.Messages,
|
||||
billingUnits: 100,
|
||||
price: 10,
|
||||
isOneOff: true,
|
||||
}),
|
||||
],
|
||||
});
|
||||
|
||||
const testCase = "checkout7";
|
||||
describe(`${chalk.yellowBright(`${testCase}: Testing invoice checkout with one off product`)}`, () => {
|
||||
let customerId = testCase;
|
||||
let autumn: AutumnInt = new AutumnInt({ version: APIVersion.v1_2 });
|
||||
let testClockId: string;
|
||||
let db: DrizzleCli, org: Organization, env: AppEnv;
|
||||
let stripeCli: Stripe;
|
||||
let curUnix = new Date().getTime();
|
||||
|
||||
before(async function () {
|
||||
await setupBefore(this);
|
||||
const { autumnJs } = this;
|
||||
db = this.db;
|
||||
org = this.org;
|
||||
env = this.env;
|
||||
|
||||
stripeCli = this.stripeCli;
|
||||
|
||||
addPrefixToProducts({
|
||||
products: [pro, addOn],
|
||||
prefix: testCase,
|
||||
});
|
||||
|
||||
await createProducts({
|
||||
autumn,
|
||||
products: [pro, addOn],
|
||||
customerId,
|
||||
db,
|
||||
orgId: org.id,
|
||||
env,
|
||||
});
|
||||
|
||||
const { testClockId: testClockId1 } = await initCustomer({
|
||||
autumn: autumnJs,
|
||||
customerId,
|
||||
db,
|
||||
org,
|
||||
env,
|
||||
attachPm: "success",
|
||||
});
|
||||
|
||||
testClockId = testClockId1!;
|
||||
});
|
||||
|
||||
it("should attach pro product, then add on product via invoice checkout", async function () {
|
||||
await autumn.attach({
|
||||
customer_id: customerId,
|
||||
product_id: pro.id,
|
||||
});
|
||||
|
||||
const options = [
|
||||
{
|
||||
quantity: 200,
|
||||
feature_id: TestFeature.Messages,
|
||||
},
|
||||
];
|
||||
|
||||
const res2 = await autumn.checkout({
|
||||
customer_id: customerId,
|
||||
product_id: addOn.id,
|
||||
invoice: true,
|
||||
options,
|
||||
});
|
||||
|
||||
expect(res2.url).to.exist;
|
||||
|
||||
await completeInvoiceCheckout({
|
||||
url: res2.url!,
|
||||
});
|
||||
|
||||
const customer = await autumn.customers.get(customerId);
|
||||
|
||||
expectProductAttached({
|
||||
customer,
|
||||
product: addOn,
|
||||
});
|
||||
|
||||
expectFeaturesCorrect({
|
||||
customer,
|
||||
product: addOn,
|
||||
otherProducts: [pro],
|
||||
options,
|
||||
});
|
||||
});
|
||||
|
||||
// it("should have no URL returned if try to attach add on (with invoice true)", async function () {
|
||||
// const res = await autumn.checkout({
|
||||
// customer_id: customerId,
|
||||
// product_id: addOn.id,
|
||||
// invoice: true,
|
||||
// });
|
||||
|
||||
// expect(res.url).to.not.exist;
|
||||
// });
|
||||
});
|
||||
@@ -12,12 +12,14 @@ const checkEntitledOnProduct = async ({
|
||||
totalAllowance,
|
||||
finish = false,
|
||||
usageBased = false,
|
||||
timeoutMs = 8000,
|
||||
}: {
|
||||
customerId: string;
|
||||
product: any;
|
||||
totalAllowance?: number;
|
||||
finish?: boolean;
|
||||
usageBased?: boolean;
|
||||
timeoutMs?: number;
|
||||
}) => {
|
||||
// 1. Send events
|
||||
const allowance = totalAllowance || product.entitlements.metered1.allowance;
|
||||
@@ -35,7 +37,7 @@ const checkEntitledOnProduct = async ({
|
||||
}
|
||||
|
||||
await Promise.all(batchUpdates);
|
||||
await timeout(8000);
|
||||
await timeout(timeoutMs);
|
||||
let used = randomNum;
|
||||
|
||||
// 2. Check entitled
|
||||
@@ -74,7 +76,7 @@ const checkEntitledOnProduct = async ({
|
||||
);
|
||||
}
|
||||
await Promise.all(batchUpdates2);
|
||||
await timeout(8000);
|
||||
await timeout(timeoutMs);
|
||||
used += allowance - randomNum;
|
||||
|
||||
// 3. Check entitled again
|
||||
@@ -124,13 +126,13 @@ describe(`${chalk.yellowBright(
|
||||
});
|
||||
});
|
||||
|
||||
it("should have correct entitlements (free)", async function () {
|
||||
await checkEntitledOnProduct({
|
||||
customerId: customerId,
|
||||
product: products.free,
|
||||
finish: true,
|
||||
});
|
||||
});
|
||||
// it("should have correct entitlements (free)", async function () {
|
||||
// await checkEntitledOnProduct({
|
||||
// customerId: customerId,
|
||||
// product: products.free,
|
||||
// finish: true,
|
||||
// });
|
||||
// });
|
||||
|
||||
it("should attach pro", async function () {
|
||||
await AutumnCli.attach({
|
||||
@@ -170,6 +172,7 @@ describe(`${chalk.yellowBright(
|
||||
product: products.oneTimeAddOnMetered1,
|
||||
finish: true,
|
||||
totalAllowance: curAllowance + oneTimeQuantity,
|
||||
timeoutMs: 15000,
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -231,7 +234,7 @@ describe(`${chalk.yellowBright(
|
||||
}
|
||||
|
||||
await Promise.all(batchUpdates);
|
||||
await timeout(14000);
|
||||
await timeout(10000);
|
||||
|
||||
const { allowed: allowed2, balanceObj: balanceObj2 }: any =
|
||||
await AutumnCli.entitled(customerId, features.metered1.id, true);
|
||||
|
||||
@@ -93,7 +93,8 @@ describe(`${chalk.yellowBright(`${testCase}: Testing attach with customer ID and
|
||||
customer_id: internalCustomerId,
|
||||
entity_id: internalEntityId,
|
||||
product_id: pro.id,
|
||||
invoice_only: true,
|
||||
invoice: true,
|
||||
enable_product_immediately: true,
|
||||
});
|
||||
|
||||
const customer = await autumn.customers.get(internalCustomerId);
|
||||
|
||||
144
server/tests/utils/stripeUtils/completeInvoiceCheckout.ts
Normal file
144
server/tests/utils/stripeUtils/completeInvoiceCheckout.ts
Normal file
@@ -0,0 +1,144 @@
|
||||
import "dotenv/config";
|
||||
|
||||
import { Stripe } from "stripe";
|
||||
import puppeteer from "puppeteer-core";
|
||||
import Browserbase from "@browserbasehq/sdk";
|
||||
|
||||
import { Hyperbrowser } from "@hyperbrowser/sdk";
|
||||
import { timeout } from "../genUtils.js";
|
||||
|
||||
const client = new Hyperbrowser({
|
||||
apiKey: process.env.HYPERBROWSER_API_KEY,
|
||||
});
|
||||
|
||||
export const completeInvoiceCheckout = async ({
|
||||
url,
|
||||
isLocal = false,
|
||||
}: {
|
||||
url: string;
|
||||
isLocal?: boolean;
|
||||
}) => {
|
||||
let browser;
|
||||
|
||||
if (process.env.NODE_ENV === "development" && !isLocal) {
|
||||
const session = await client.sessions.create();
|
||||
browser = await puppeteer.connect({
|
||||
browserWSEndpoint: session!.wsEndpoint,
|
||||
defaultViewport: null,
|
||||
});
|
||||
} else {
|
||||
browser = await puppeteer.launch({
|
||||
headless: false,
|
||||
executablePath: "/Applications/Chromium.app/Contents/MacOS/Chromium",
|
||||
args: ["--no-sandbox", "--disable-setuid-sandbox"],
|
||||
});
|
||||
}
|
||||
|
||||
try {
|
||||
const page = await browser.newPage();
|
||||
await page.setViewport({ width: 1280, height: 800 }); // Set standard desktop viewport size
|
||||
await page.goto(url);
|
||||
|
||||
// Wait for the payment element to load
|
||||
|
||||
await page.waitForSelector("#payment-element", { timeout: 10000 });
|
||||
|
||||
// Wait a bit more for the iframe to fully load
|
||||
await new Promise((resolve) => setTimeout(resolve, 3000));
|
||||
|
||||
// Try clicking on the payment element container to expand the accordion
|
||||
|
||||
await page.click("#payment-element");
|
||||
|
||||
await new Promise((resolve) => setTimeout(resolve, 3000));
|
||||
|
||||
// Get the iframe containing the Stripe elements
|
||||
const stripeFrame = await page.$("#payment-element iframe");
|
||||
if (!stripeFrame) {
|
||||
throw new Error("Stripe iframe not found");
|
||||
}
|
||||
|
||||
const frame = await stripeFrame.contentFrame();
|
||||
if (!frame) {
|
||||
throw new Error("Could not access iframe content");
|
||||
}
|
||||
|
||||
// Enter card number - try different possible selectors
|
||||
try {
|
||||
await frame.waitForSelector(
|
||||
'input[name="number"], input[data-elements-stable-field-name="cardNumber"], input[placeholder*="1234"], input[aria-label*="Card number"]',
|
||||
{ timeout: 2000 }
|
||||
);
|
||||
const cardNumberInput = await frame.$(
|
||||
'input[name="number"], input[data-elements-stable-field-name="cardNumber"], input[placeholder*="1234"], input[aria-label*="Card number"]'
|
||||
);
|
||||
if (cardNumberInput) {
|
||||
await cardNumberInput.click();
|
||||
await cardNumberInput.type("4242424242424242");
|
||||
}
|
||||
} catch (error) {
|
||||
console.log("Could not find card number input:", error);
|
||||
}
|
||||
|
||||
// Enter expiry date
|
||||
try {
|
||||
await frame.waitForSelector(
|
||||
'input[name="expiry"], input[data-elements-stable-field-name="cardExpiry"], input[placeholder*="MM"], input[aria-label*="expir"]',
|
||||
{ timeout: 2000 }
|
||||
);
|
||||
const expiryInput = await frame.$(
|
||||
'input[name="expiry"], input[data-elements-stable-field-name="cardExpiry"], input[placeholder*="MM"], input[aria-label*="expir"]'
|
||||
);
|
||||
if (expiryInput) {
|
||||
await expiryInput.click();
|
||||
await expiryInput.type("1227");
|
||||
}
|
||||
} catch (error) {
|
||||
console.log("Could not find expiry input:", error);
|
||||
}
|
||||
|
||||
// Enter CVC
|
||||
try {
|
||||
await frame.waitForSelector(
|
||||
'input[name="cvc"], input[data-elements-stable-field-name="cardCvc"], input[placeholder*="CVC"], input[aria-label*="CVC"]',
|
||||
{ timeout: 2000 }
|
||||
);
|
||||
const cvcInput = await frame.$(
|
||||
'input[name="cvc"], input[data-elements-stable-field-name="cardCvc"], input[placeholder*="CVC"], input[aria-label*="CVC"]'
|
||||
);
|
||||
if (cvcInput) {
|
||||
await cvcInput.click();
|
||||
await cvcInput.type("123");
|
||||
}
|
||||
} catch (error) {
|
||||
console.log("Could not find CVC input:", error);
|
||||
}
|
||||
|
||||
// Enter postal code
|
||||
try {
|
||||
await frame.waitForSelector(
|
||||
'input[name="postalCode"], input[data-elements-stable-field-name="postalCode"], input[placeholder*="12345"], input[aria-label*="ZIP"]',
|
||||
{ timeout: 2000 }
|
||||
);
|
||||
const postalInput = await frame.$(
|
||||
'input[name="postalCode"], input[data-elements-stable-field-name="postalCode"], input[placeholder*="12345"], input[aria-label*="ZIP"]'
|
||||
);
|
||||
if (postalInput) {
|
||||
await postalInput.click();
|
||||
await postalInput.type("12345");
|
||||
}
|
||||
} catch (error) {
|
||||
console.log("Could not find postal code input:", error);
|
||||
}
|
||||
|
||||
// Wait a bit for all inputs to be processed
|
||||
await new Promise((resolve) => setTimeout(resolve, 2000));
|
||||
|
||||
const submitButton = await page.$(".SubmitButton-IconContainer");
|
||||
await submitButton?.evaluate((b: any) => (b as HTMLElement).click());
|
||||
await timeout(20000);
|
||||
} finally {
|
||||
// always close browser
|
||||
await browser.close();
|
||||
}
|
||||
};
|
||||
@@ -1,5 +1,12 @@
|
||||
import { relations } from "drizzle-orm";
|
||||
import { user } from "./auth-schema.js";
|
||||
import { member, user } from "./auth-schema.js";
|
||||
import { organizations } from "../models/orgModels/orgTable.js";
|
||||
|
||||
export const userRelations = relations(user, ({ many }) => ({}));
|
||||
|
||||
export const memberRelations = relations(member, ({ one }) => ({
|
||||
organization: one(organizations, {
|
||||
fields: [member.organizationId],
|
||||
references: [organizations.id],
|
||||
}),
|
||||
}));
|
||||
|
||||
@@ -7,6 +7,7 @@ import {
|
||||
foreignKey,
|
||||
} from "drizzle-orm/pg-core";
|
||||
import { organizations } from "./schema.js";
|
||||
import { relations } from "drizzle-orm";
|
||||
|
||||
export const user = pgTable(
|
||||
"user",
|
||||
|
||||
@@ -79,7 +79,7 @@ import {
|
||||
member,
|
||||
invitation,
|
||||
} from "./auth-schema.js";
|
||||
import { userRelations } from "./auth-relations.js";
|
||||
import { userRelations, memberRelations } from "./auth-relations.js";
|
||||
|
||||
export {
|
||||
// Tables
|
||||
@@ -140,4 +140,5 @@ export {
|
||||
rolloverRelations,
|
||||
// Auth Relations
|
||||
userRelations,
|
||||
memberRelations,
|
||||
};
|
||||
|
||||
@@ -44,6 +44,7 @@ export const AttachBodySchema = z
|
||||
checkout_session_params: z.any().optional(),
|
||||
reward: z.string().optional(),
|
||||
invoice: z.boolean().optional(),
|
||||
enable_product_immediately: z.boolean().optional(),
|
||||
})
|
||||
.refine(
|
||||
(data) => {
|
||||
|
||||
@@ -8,6 +8,7 @@ export enum ProrationBehavior {
|
||||
|
||||
export interface AttachConfig {
|
||||
onlyCheckout: boolean;
|
||||
invoiceCheckout: boolean;
|
||||
carryUsage: boolean; // Whether to carry over existing usages
|
||||
branch: AttachBranch;
|
||||
proration: ProrationBehavior;
|
||||
|
||||
@@ -33,6 +33,7 @@ export const CustomerDataSchema = z.object({
|
||||
email: z.string().nullish(),
|
||||
fingerprint: z.string().nullish(),
|
||||
metadata: z.record(z.any()).nullish().default({}),
|
||||
stripe_id: z.string().nullish(),
|
||||
});
|
||||
|
||||
export const CustomerResponseSchema = CustomerSchema.omit({
|
||||
|
||||
@@ -94,8 +94,14 @@ export const LimitedItemSchema = ProductItemSchema.extend({
|
||||
included_usage: z.number(),
|
||||
});
|
||||
|
||||
export const FrontendProductItem = ProductItemSchema.extend({
|
||||
isPrice: z.boolean(),
|
||||
isVariable: z.boolean().nullish(),
|
||||
});
|
||||
|
||||
export type ProductItem = z.infer<typeof ProductItemSchema>;
|
||||
export type LimitedItem = z.infer<typeof LimitedItemSchema>;
|
||||
export type ProductItemConfig = z.infer<typeof ProductItemConfigSchema>;
|
||||
export type PriceTier = z.infer<typeof PriceTierSchema>;
|
||||
export type RolloverConfig = z.infer<typeof RolloverConfigSchema>;
|
||||
export type FrontendProductItem = z.infer<typeof FrontendProductItem>;
|
||||
|
||||
@@ -351,13 +351,15 @@ const PrepaidItem = ({
|
||||
const disableSelection = scenario === "renew";
|
||||
|
||||
return (
|
||||
<div className="flex justify-between">
|
||||
<div className="flex gap-2">
|
||||
<p className="text-muted-foreground">{item.feature?.name}</p>
|
||||
<div className="flex justify-between gap-2">
|
||||
<div className="flex gap-2 items-start">
|
||||
<p className="text-muted-foreground whitespace-nowrap">
|
||||
{item.feature?.name}
|
||||
</p>
|
||||
<Popover open={open} onOpenChange={setOpen}>
|
||||
<PopoverTrigger
|
||||
className={cn(
|
||||
"text-muted-foreground text-xs px-1 py-0.5 rounded-md flex items-center gap-1 bg-accent/80",
|
||||
"text-muted-foreground text-xs px-1 py-0.5 rounded-md flex items-center gap-1 bg-accent/80 shrink-0",
|
||||
disableSelection !== true &&
|
||||
"hover:bg-accent hover:text-foreground"
|
||||
)}
|
||||
@@ -405,7 +407,7 @@ const PrepaidItem = ({
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
</div>
|
||||
<p>
|
||||
<p className="text-end">
|
||||
{item.display?.primary_text} {item.display?.secondary_text}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
42
vite/src/components/general/SelectType.tsx
Normal file
42
vite/src/components/general/SelectType.tsx
Normal file
@@ -0,0 +1,42 @@
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
export const SelectType = ({
|
||||
title,
|
||||
description,
|
||||
icon,
|
||||
isSelected,
|
||||
onClick,
|
||||
disabled = false,
|
||||
}: {
|
||||
title: string;
|
||||
description: string;
|
||||
icon: React.ReactNode;
|
||||
isSelected: boolean;
|
||||
onClick: () => void;
|
||||
disabled?: boolean;
|
||||
}) => {
|
||||
return (
|
||||
<button
|
||||
className={cn(
|
||||
`relative h-full flex flex-col text-start gap-2 text-sm p-3 rounded-xs cursor-pointer `,
|
||||
isSelected
|
||||
? "shadow-inner bg-stone-100 border border-zinc-400 ring-1 ring-zinc-300/50"
|
||||
: "border hover:shadow-sm",
|
||||
disabled && "opacity-50 cursor-default"
|
||||
)}
|
||||
onClick={onClick}
|
||||
disabled={disabled}
|
||||
>
|
||||
<div className="flex items-center gap-1 justify-center">
|
||||
{/* <div className="flex w-4 h-full items-center justify-start text-t2">
|
||||
{icon}
|
||||
</div> */}
|
||||
<span className="w-0 -translate-x-4 text-t2">{icon}</span>
|
||||
<span className="relative text-t2 text-sm font-medium whitespace-nowrap leading-none">
|
||||
{title}
|
||||
</span>
|
||||
</div>
|
||||
<p className="text-t2 text-xs text-center">{description}</p>
|
||||
</button>
|
||||
);
|
||||
};
|
||||
@@ -13,14 +13,16 @@ export const ToggleButton = ({
|
||||
className,
|
||||
disabled,
|
||||
infoContent,
|
||||
switchClassName,
|
||||
}: {
|
||||
value: boolean;
|
||||
setValue: (value: boolean) => void;
|
||||
tooltipContent?: string;
|
||||
buttonText?: string;
|
||||
buttonText?: string | React.ReactNode;
|
||||
className?: string;
|
||||
disabled?: boolean;
|
||||
infoContent?: string;
|
||||
switchClassName?: string;
|
||||
}) => {
|
||||
const MainButton = (
|
||||
<Button
|
||||
@@ -37,12 +39,14 @@ export const ToggleButton = ({
|
||||
)}
|
||||
>
|
||||
{buttonText}
|
||||
{infoContent && <InfoTooltip>{infoContent}</InfoTooltip>}
|
||||
<Switch
|
||||
checked={value}
|
||||
className="h-4 w-7 data-[state=checked]:bg-stone-500"
|
||||
thumbClassName="h-3 w-3 data-[state=checked]:translate-x-3"
|
||||
/>
|
||||
<div className={cn("flex items-center gap-1", switchClassName)}>
|
||||
{infoContent && <InfoTooltip>{infoContent}</InfoTooltip>}
|
||||
<Switch
|
||||
checked={value}
|
||||
className="h-4 w-7 data-[state=checked]:bg-stone-500"
|
||||
thumbClassName="h-3 w-3 data-[state=checked]:translate-x-3"
|
||||
/>
|
||||
</div>
|
||||
</Button>
|
||||
);
|
||||
|
||||
|
||||
@@ -15,8 +15,9 @@ export const CustomDialogContent = ({
|
||||
return (
|
||||
<DialogContent
|
||||
className={cn(
|
||||
"flex flex-col gap-0 !p-0",
|
||||
fromTop && "translate-y-[0%] top-[20%]",
|
||||
"flex flex-col gap-0 !p-0 overflow-y-auto",
|
||||
fromTop &&
|
||||
"translate-y-[0%] top-[20%] max-h-[70vh] overflow-y-hidden duration-0",
|
||||
className
|
||||
)}
|
||||
>
|
||||
|
||||
@@ -8,13 +8,15 @@ import { InfoIcon } from "lucide-react";
|
||||
|
||||
export const InfoTooltip = ({
|
||||
children,
|
||||
className,
|
||||
...props
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
className?: string;
|
||||
} & TooltipContentProps) => {
|
||||
return (
|
||||
<Tooltip>
|
||||
<TooltipTrigger>
|
||||
<TooltipTrigger className={className}>
|
||||
<InfoIcon size={12} className="text-t3/50" />
|
||||
</TooltipTrigger>
|
||||
<TooltipContent sideOffset={10} {...props}>
|
||||
|
||||
@@ -11,10 +11,6 @@ interface InputProps extends React.ComponentProps<"input"> {
|
||||
const Input = React.forwardRef<HTMLInputElement, InputProps>(
|
||||
({ className, type, startContent, endContent, variant, ...props }, ref) => {
|
||||
const hasAdornment = startContent || endContent;
|
||||
const [isFocused, setIsFocused] = React.useState(false);
|
||||
|
||||
const handleFocus = () => setIsFocused(true);
|
||||
const handleBlur = () => setIsFocused(false);
|
||||
|
||||
// const gradientBg =
|
||||
// "bg-[linear-gradient(180deg,white,theme(colors.stone.50))]";
|
||||
@@ -26,15 +22,13 @@ const Input = React.forwardRef<HTMLInputElement, InputProps>(
|
||||
{hasAdornment ? (
|
||||
<div
|
||||
className={cn(
|
||||
`flex w-full rounded-md border border-input ${gradientBg} text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50
|
||||
`flex w-full rounded-md border border-input ${gradientBg} text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50
|
||||
|
||||
h-8 transition-colors duration-100 shadow-sm overflow-hidden
|
||||
`,
|
||||
isFocused &&
|
||||
`transition-colors duration-100 focus-visible:outline-none focus-visible:ring-0
|
||||
border-focus shadow-focus`,
|
||||
|
||||
focus-within:outline-none focus-within:ring-0 focus-within:border-focus focus-within:shadow-focus`,
|
||||
variant === "destructive" &&
|
||||
`focus-visible:border-red-400 focus-visible:shadow-[0_0_2px_1px_rgba(248,113,113,0.25)]`,
|
||||
`focus-within:border-red-400 focus-within:shadow-[0_0_2px_1px_rgba(248,113,113,0.25)]`
|
||||
)}
|
||||
data-disabled={props.disabled}
|
||||
>
|
||||
@@ -46,11 +40,9 @@ const Input = React.forwardRef<HTMLInputElement, InputProps>(
|
||||
|
||||
p-2
|
||||
`,
|
||||
className,
|
||||
className
|
||||
)}
|
||||
ref={ref}
|
||||
onFocus={handleFocus}
|
||||
onBlur={handleBlur}
|
||||
{...props}
|
||||
/>
|
||||
<div className="flex items-center justify-center pr-2">
|
||||
@@ -70,7 +62,7 @@ const Input = React.forwardRef<HTMLInputElement, InputProps>(
|
||||
variant === "destructive"
|
||||
? `focus-visible:border-red-400 focus-visible:shadow-[0_0_2px_1px_rgba(248,113,113,0.25)]`
|
||||
: `focus-visible:shadow-focus`,
|
||||
className,
|
||||
className
|
||||
)}
|
||||
ref={ref}
|
||||
{...props}
|
||||
@@ -78,7 +70,7 @@ const Input = React.forwardRef<HTMLInputElement, InputProps>(
|
||||
)}
|
||||
</>
|
||||
);
|
||||
},
|
||||
}
|
||||
);
|
||||
Input.displayName = "Input";
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ export const isEmptyItem = (item: ProductItem) => {
|
||||
export const isFeatureItem = (item: ProductItem) => {
|
||||
return (
|
||||
// notNullish(item.feature_id) &&
|
||||
(nullish(item.price) || item.price == 0) && nullish(item.tiers)
|
||||
nullish(item.price) && nullish(item.tiers)
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ import { invalidNumber, notNullish, nullish } from "@/utils/genUtils";
|
||||
import {
|
||||
Feature,
|
||||
FeatureUsageType,
|
||||
FrontendProductItem,
|
||||
Infinite,
|
||||
ProductItem,
|
||||
ProductItemInterval,
|
||||
@@ -17,7 +18,7 @@ export const validateProductItem = ({
|
||||
// show,
|
||||
features,
|
||||
}: {
|
||||
item: ProductItem;
|
||||
item: FrontendProductItem;
|
||||
// show: any;
|
||||
features: Feature[];
|
||||
}) => {
|
||||
@@ -31,11 +32,22 @@ export const validateProductItem = ({
|
||||
item.interval = null;
|
||||
}
|
||||
|
||||
if (item.isPrice && item.isVariable && !item.feature_id) {
|
||||
toast.error("Please select a feature");
|
||||
return null;
|
||||
}
|
||||
|
||||
if (notNullish(item.price)) {
|
||||
if (invalidNumber(item.price)) {
|
||||
toast.error("Please enter a valid price amount");
|
||||
return null;
|
||||
}
|
||||
|
||||
if (item.price === 0) {
|
||||
toast.error("Price should be greater than 0");
|
||||
return null;
|
||||
}
|
||||
|
||||
item.price = parseFloat(item.price!.toString());
|
||||
}
|
||||
|
||||
@@ -45,17 +57,51 @@ export const validateProductItem = ({
|
||||
item.included_usage = Number(item.included_usage);
|
||||
}
|
||||
|
||||
if (isFeaturePriceItem(item) && nullish(item.usage_model)) {
|
||||
toast.error("Please select a usage model");
|
||||
return null;
|
||||
}
|
||||
|
||||
//if both item.tiers and item.price are set, set item.price to null
|
||||
if (item.tiers && item.price) {
|
||||
item.price = null;
|
||||
}
|
||||
|
||||
// Usage/Feature item validation (when tiers are set)
|
||||
|
||||
if (item.tiers) {
|
||||
let previousTo = 0;
|
||||
|
||||
for (let i = 0; i < item.tiers.length; i++) {
|
||||
const tier = item.tiers[i];
|
||||
const allFree = item.tiers.every((tier) => tier.amount == 0);
|
||||
|
||||
if (allFree) {
|
||||
if (item.tiers.length == 1) {
|
||||
toast.error("Price should be greater than 0");
|
||||
} else {
|
||||
toast.error("Should have at least one tier with price greater than 0");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
const freeTier =
|
||||
item.tiers.length > 0 && item.tiers[0].amount == 0 ? item.tiers[0] : null;
|
||||
|
||||
// const includedUsage = parseFloat(item.included_usage?.toString() || "0");
|
||||
|
||||
let finalTiers = item.tiers;
|
||||
|
||||
if (freeTier) {
|
||||
finalTiers = finalTiers.slice(1);
|
||||
item.included_usage = parseFloat(freeTier.to.toString() || "0");
|
||||
|
||||
finalTiers = finalTiers.map((tier) => {
|
||||
tier.amount -= freeTier.amount;
|
||||
return tier;
|
||||
});
|
||||
}
|
||||
|
||||
for (let i = 0; i < finalTiers.length; i++) {
|
||||
const tier = finalTiers[i];
|
||||
|
||||
// Check if amount is actually a number
|
||||
if (typeof tier.amount !== "number") {
|
||||
@@ -88,15 +134,24 @@ export const validateProductItem = ({
|
||||
}
|
||||
|
||||
// Ensure tiers are in ascending order
|
||||
if (tier.to <= previousTo) {
|
||||
if (tier.to < previousTo) {
|
||||
toast.error("Tiers must be in ascending order");
|
||||
return null;
|
||||
}
|
||||
|
||||
if (tier.to == previousTo) {
|
||||
toast.error(`tier ${i + 1} should have a greater 'to'`);
|
||||
return null;
|
||||
}
|
||||
|
||||
previousTo = tier.to;
|
||||
}
|
||||
|
||||
item.tiers = finalTiers;
|
||||
}
|
||||
|
||||
console.log("Final tiers:", item.tiers);
|
||||
|
||||
// Validate billing units
|
||||
if (item.billing_units && invalidNumber(item.billing_units)) {
|
||||
toast.error("Please enter valid billing units");
|
||||
|
||||
@@ -100,3 +100,16 @@ export const shouldShowProrationConfig = ({
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
export const itemsHaveSameInterval = ({
|
||||
item1,
|
||||
item2,
|
||||
}: {
|
||||
item1: ProductItem;
|
||||
item2: ProductItem;
|
||||
}) => {
|
||||
return (
|
||||
item1.interval == item2.interval &&
|
||||
(item1.interval_count || 1) == (item2.interval_count || 1)
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
import { DialogFooter } from "@/components/ui/dialog";
|
||||
|
||||
import { getOriginalCouponId } from "@/utils/product/couponUtils";
|
||||
import { getBackendErr } from "@/utils/genUtils";
|
||||
import { getBackendErr, navigateTo } from "@/utils/genUtils";
|
||||
import { Reward, CreateCustomer, Customer } from "@autumn/shared";
|
||||
import { useEffect, useState } from "react";
|
||||
import { toast } from "sonner";
|
||||
@@ -14,6 +12,7 @@ import { useAxiosInstance } from "@/services/useAxiosInstance";
|
||||
import { useEnv } from "@/utils/envUtils";
|
||||
import { CustomerConfig } from "./CustomerConfig";
|
||||
import { CusService } from "@/services/customers/CusService";
|
||||
import { useNavigate } from "react-router";
|
||||
|
||||
const UpdateCustomerDialog = ({
|
||||
selectedCustomer,
|
||||
@@ -30,6 +29,7 @@ const UpdateCustomerDialog = ({
|
||||
const [loading, setLoading] = useState(false);
|
||||
const env = useEnv();
|
||||
const axiosInstance = useAxiosInstance({ env });
|
||||
const navigate = useNavigate();
|
||||
|
||||
useEffect(() => {
|
||||
setCustomer(selectedCustomer);
|
||||
@@ -42,6 +42,7 @@ const UpdateCustomerDialog = ({
|
||||
axios: axiosInstance,
|
||||
customer_id: selectedCustomer.id || selectedCustomer.internal_id,
|
||||
data: {
|
||||
id: customer.id || undefined,
|
||||
name: customer.name || null,
|
||||
email: customer.email || null,
|
||||
fingerprint: customer.fingerprint || null,
|
||||
@@ -51,6 +52,10 @@ const UpdateCustomerDialog = ({
|
||||
toast.success(`Successfully updated customer`);
|
||||
setOpen(false);
|
||||
await cusMutate();
|
||||
|
||||
if (customer.id != selectedCustomer.id) {
|
||||
navigateTo(`/customers/${customer.id}`, navigate, env);
|
||||
}
|
||||
} catch (error) {
|
||||
toast.error(getBackendErr(error, "Failed to update customer"));
|
||||
} finally {
|
||||
|
||||
@@ -32,7 +32,15 @@ export const CustomerDetails = ({
|
||||
{customer.id}
|
||||
</CopyButton>
|
||||
) : (
|
||||
<span className="px-2 text-t3">N/A</span>
|
||||
<Button
|
||||
variant="sidebarItem"
|
||||
onClick={() => {
|
||||
setIsModalOpen(true);
|
||||
setModalType("customer");
|
||||
}}
|
||||
>
|
||||
<span className="truncate text-t3">N/A</span>
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
@@ -103,7 +111,7 @@ export const CustomerDetails = ({
|
||||
>
|
||||
<FontAwesomeIcon
|
||||
icon={faStripe}
|
||||
className="!h-6 text-t2"
|
||||
className="!h-6 !w-6 text-t2"
|
||||
/>
|
||||
<ArrowUpRightFromSquare size={12} className="text-t2" />
|
||||
</Button>
|
||||
|
||||
@@ -31,6 +31,7 @@ import { cn } from "@/lib/utils";
|
||||
import { Separator } from "@/components/ui/separator";
|
||||
import { AttachInfo } from "./attach-preview/AttachInfo";
|
||||
import { getAttachBody } from "./attachProductUtils";
|
||||
import { InvoiceCustomerButton } from "./InvoiceCustomerButton";
|
||||
|
||||
export const AttachModal = ({
|
||||
open,
|
||||
@@ -118,8 +119,15 @@ export const AttachModal = ({
|
||||
return "Charge Customer";
|
||||
};
|
||||
|
||||
const handleAttachClicked = async (useInvoice: boolean) => {
|
||||
const setLoading = useInvoice ? setInvoiceLoading : setCheckoutLoading;
|
||||
const handleAttachClicked = async ({
|
||||
useInvoice,
|
||||
enableProductImmediately,
|
||||
setLoading,
|
||||
}: {
|
||||
useInvoice: boolean;
|
||||
enableProductImmediately?: boolean;
|
||||
setLoading: (loading: boolean) => void;
|
||||
}) => {
|
||||
const cusId = getCusId();
|
||||
|
||||
for (const option of options) {
|
||||
@@ -145,6 +153,7 @@ export const AttachModal = ({
|
||||
optionsInput: options,
|
||||
attachState,
|
||||
useInvoice,
|
||||
enableProductImmediately,
|
||||
successUrl: `${import.meta.env.VITE_FRONTEND_URL}${redirectUrl}`,
|
||||
version: version || product.version,
|
||||
});
|
||||
@@ -155,9 +164,8 @@ export const AttachModal = ({
|
||||
window.open(data.checkout_url, "_blank");
|
||||
} else if (data.invoice) {
|
||||
window.open(getStripeInvoiceLink(data.invoice), "_blank");
|
||||
} else {
|
||||
navigateTo(`/customers/${cusId}`, navigation, env);
|
||||
}
|
||||
navigateTo(`/customers/${cusId}`, navigation, env);
|
||||
|
||||
toast.success(data.message || "Successfully attached product");
|
||||
setOpen(false);
|
||||
@@ -186,7 +194,7 @@ export const AttachModal = ({
|
||||
const mainWidth = "w-lg";
|
||||
return (
|
||||
<Dialog open={open} onOpenChange={setOpen}>
|
||||
<DialogContent className="gap-0 p-0 rounded-xs">
|
||||
<DialogContent className="translate-y-[0%] top-[20%] max-h-[70vh] duration-0 p-0 overflow-y-auto">
|
||||
<div className="flex transition-all duration-300 ease-in-out">
|
||||
<div
|
||||
className={`p-6 pb-2 flex flex-col gap-4 ${mainWidth} rounded-sm`}
|
||||
@@ -234,19 +242,23 @@ export const AttachModal = ({
|
||||
)}
|
||||
>
|
||||
{invoiceAllowed() && (
|
||||
<Button
|
||||
variant="add"
|
||||
className="!h-full text-t2"
|
||||
endIcon={<ArrowUpRightFromSquare size={12} />}
|
||||
disableStartIcon={true}
|
||||
tabIndex={-1}
|
||||
tooltipContent="This will enable the product for the customer immediately, and redirect you to Stripe to finalize the invoice"
|
||||
isLoading={invoiceLoading}
|
||||
disabled={invoiceLoading || checkoutLoading}
|
||||
onClick={() => handleAttachClicked(true)}
|
||||
>
|
||||
Invoice Customer
|
||||
</Button>
|
||||
<InvoiceCustomerButton
|
||||
preview={preview}
|
||||
handleAttachClicked={handleAttachClicked}
|
||||
/>
|
||||
// <Button
|
||||
// variant="add"
|
||||
// className="!h-full text-t2"
|
||||
// endIcon={<ArrowUpRightFromSquare size={12} />}
|
||||
// disableStartIcon={true}
|
||||
// tabIndex={-1}
|
||||
// tooltipContent="This will enable the product for the customer immediately, and redirect you to Stripe to finalize the invoice"
|
||||
// isLoading={invoiceLoading}
|
||||
// disabled={invoiceLoading || checkoutLoading}
|
||||
// onClick={() => handleAttachClicked(true)}
|
||||
// >
|
||||
// Invoice Customer
|
||||
// </Button>
|
||||
)}
|
||||
<Button
|
||||
variant="add"
|
||||
@@ -255,7 +267,12 @@ export const AttachModal = ({
|
||||
endIcon={<ArrowUpRightFromSquare size={12} />}
|
||||
isLoading={checkoutLoading}
|
||||
disabled={invoiceLoading || checkoutLoading}
|
||||
onClick={() => handleAttachClicked(false)}
|
||||
onClick={() =>
|
||||
handleAttachClicked({
|
||||
useInvoice: false,
|
||||
setLoading: setCheckoutLoading,
|
||||
})
|
||||
}
|
||||
>
|
||||
{getButtonText()}
|
||||
</Button>
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
import FieldLabel from "@/components/general/modal-components/FieldLabel";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import {
|
||||
Popover,
|
||||
PopoverContent,
|
||||
PopoverTrigger,
|
||||
} from "@/components/ui/popover";
|
||||
import { AttachBranch, AttachFunction } from "@autumn/shared";
|
||||
import { ArrowUpRightFromSquare } from "lucide-react";
|
||||
import { useState } from "react";
|
||||
|
||||
export const InvoiceCustomerButton = ({
|
||||
handleAttachClicked,
|
||||
preview,
|
||||
}: {
|
||||
handleAttachClicked: any;
|
||||
preview?: any;
|
||||
}) => {
|
||||
const [immediateLoading, setImmediateLoading] = useState(false);
|
||||
const [afterPaymentLoading, setAfterPaymentLoading] = useState(false);
|
||||
const buttonsDisabled = immediateLoading || afterPaymentLoading;
|
||||
|
||||
const allowedBranches = [
|
||||
AttachBranch.New,
|
||||
AttachBranch.MainIsTrial,
|
||||
AttachBranch.MainIsFree,
|
||||
AttachBranch.OneOff,
|
||||
AttachBranch.AddOn,
|
||||
];
|
||||
|
||||
// const immediateDisabled = !allowedBranches.includes(preview?.branch);
|
||||
|
||||
console.log("Preview:", preview);
|
||||
|
||||
return (
|
||||
<Popover>
|
||||
<PopoverTrigger asChild>
|
||||
<Button
|
||||
variant="add"
|
||||
className="!h-full text-t2"
|
||||
endIcon={<ArrowUpRightFromSquare size={12} />}
|
||||
disableStartIcon={true}
|
||||
tabIndex={-1}
|
||||
tooltipContent="This will enable the product for the customer immediately, and redirect you to Stripe to finalize the invoice"
|
||||
>
|
||||
Invoice Customer
|
||||
</Button>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent className="w-fit flex p-0">
|
||||
<div className="w-[300px]">
|
||||
<div className="border-r p-4 text-sm flex flex-col gap-2">
|
||||
<p>Enable Product Immediately</p>
|
||||
<p className="text-t2">
|
||||
This will enable the product for the customer immediately, and
|
||||
redirect you to Stripe to finalize the invoice
|
||||
</p>
|
||||
<Button
|
||||
isLoading={immediateLoading}
|
||||
className="w-fit mt-2"
|
||||
variant="outline"
|
||||
disabled={buttonsDisabled}
|
||||
onClick={() =>
|
||||
handleAttachClicked({
|
||||
useInvoice: true,
|
||||
enableProductImmediately: true,
|
||||
setLoading: setImmediateLoading,
|
||||
})
|
||||
}
|
||||
>
|
||||
Invoice and enable immediately
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
{preview?.func == AttachFunction.CreateCheckout && (
|
||||
<div className="w-[300px]">
|
||||
<div className="p-4 text-sm flex flex-col gap-2">
|
||||
<p>Enable Product After Payment</p>
|
||||
<p className="text-t2">
|
||||
This will generate an invoice link for the customer, and enable
|
||||
the product after they pay the invoice
|
||||
</p>
|
||||
<Button
|
||||
isLoading={afterPaymentLoading}
|
||||
className="w-fit mt-2"
|
||||
variant="outline"
|
||||
disabled={buttonsDisabled}
|
||||
onClick={() =>
|
||||
handleAttachClicked({
|
||||
useInvoice: true,
|
||||
enableProductImmediately: false,
|
||||
setLoading: setAfterPaymentLoading,
|
||||
})
|
||||
}
|
||||
>
|
||||
Invoice and enable after payment
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
);
|
||||
};
|
||||
@@ -13,6 +13,7 @@ export const getAttachBody = ({
|
||||
entityId,
|
||||
optionsInput,
|
||||
useInvoice,
|
||||
enableProductImmediately = true,
|
||||
successUrl,
|
||||
version,
|
||||
}: {
|
||||
@@ -22,6 +23,7 @@ export const getAttachBody = ({
|
||||
entityId: string;
|
||||
optionsInput?: FeatureOptions[];
|
||||
useInvoice?: boolean;
|
||||
enableProductImmediately?: boolean;
|
||||
successUrl?: string;
|
||||
version?: number;
|
||||
}) => {
|
||||
@@ -47,7 +49,14 @@ export const getAttachBody = ({
|
||||
...customData,
|
||||
free_trial: isCustom ? product.free_trial || undefined : undefined,
|
||||
|
||||
invoice_only: useInvoice,
|
||||
invoice: useInvoice,
|
||||
enable_product_immediately: useInvoice
|
||||
? enableProductImmediately
|
||||
: undefined,
|
||||
|
||||
force_checkout:
|
||||
useInvoice && enableProductImmediately === false ? true : undefined,
|
||||
|
||||
success_url: successUrl,
|
||||
version: version ? Number(version) : undefined,
|
||||
};
|
||||
|
||||
@@ -15,8 +15,9 @@ import {
|
||||
TooltipContent,
|
||||
TooltipTrigger,
|
||||
} from "@/components/ui/tooltip";
|
||||
import { SelectFeatureUsageType } from "./SelectFeatureUsageType";
|
||||
import { notNullish, nullish } from "@/utils/genUtils";
|
||||
import { SelectFeatureType } from "./SelectFeatureType";
|
||||
import { notNullish } from "@/utils/genUtils";
|
||||
|
||||
export function FeatureConfig({
|
||||
feature,
|
||||
@@ -69,98 +70,33 @@ export function FeatureConfig({
|
||||
);
|
||||
const [idChanged, setIdChanged] = useState(!!feature.id);
|
||||
|
||||
// useEffect(() => {
|
||||
// setFeature({
|
||||
// ...feature,
|
||||
// name: fields.name,
|
||||
// id: fields.id,
|
||||
// type: null,
|
||||
// config: meteredConfig,
|
||||
// });
|
||||
// }, [meteredConfig, fields]);
|
||||
const showNameAndId = () => {
|
||||
if (nullish(feature.type)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (
|
||||
feature.type === FeatureType.Metered &&
|
||||
nullish(feature.config?.usage_type)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-4 min-w-md max-w-md">
|
||||
{/* <Tabs
|
||||
defaultValue={feature.type}
|
||||
className="w-[400px]"
|
||||
value={featureType}
|
||||
onValueChange={setFeatureType}
|
||||
>
|
||||
<TabsList className="-ml-2">
|
||||
<TabsTrigger value={FeatureType.Metered}>Metered</TabsTrigger>
|
||||
<TabsTrigger value={FeatureType.Boolean}>Boolean</TabsTrigger>
|
||||
</TabsList>
|
||||
<p className="text-t3 text-sm">
|
||||
{featureType == FeatureType.Metered &&
|
||||
"A usage-based feature that you want to track"}
|
||||
{featureType == FeatureType.Boolean &&
|
||||
"A feature flag that can be either enabled or disabled"}
|
||||
</p>
|
||||
</Tabs> */}
|
||||
|
||||
<div className="text-sm text-t2 flex items-center gap-1">
|
||||
Features are the parts of your application that customers get access to
|
||||
when purchasing a product
|
||||
</div>
|
||||
<SelectFeatureType feature={feature} setFeature={setFeature} />
|
||||
{/* {featureType === FeatureType.Metered && (
|
||||
<div className="w-full">
|
||||
<div className="flex flex-col gap-2">
|
||||
<Tabs
|
||||
defaultValue={FeatureUsageType.Single}
|
||||
value={meteredConfig.usage_type}
|
||||
onValueChange={(value) => {
|
||||
setMeteredConfig({
|
||||
...meteredConfig,
|
||||
usage_type: value as FeatureUsageType,
|
||||
});
|
||||
}}
|
||||
>
|
||||
<TabsList className="-mx-2">
|
||||
<TabsTrigger
|
||||
value={FeatureUsageType.Single}
|
||||
className="flex items-center gap-1"
|
||||
>
|
||||
<Zap className="h-3 w-3 text-t3" />
|
||||
<span>Single Use</span>
|
||||
</TabsTrigger>
|
||||
<TabsTrigger
|
||||
value={FeatureUsageType.Continuous}
|
||||
className="flex items-center gap-1"
|
||||
>
|
||||
<Clock className="h-3 w-3 text-t3" />
|
||||
<span>Continuous Use</span>
|
||||
</TabsTrigger>
|
||||
</TabsList>
|
||||
<p className="text-sm text-t3 flex items-center gap-1">
|
||||
{meteredConfig.usage_type === FeatureUsageType.Continuous
|
||||
? "For features used on an ongoing basis, like 'seats' or 'storage'"
|
||||
: "For features that are consumed and refilled like 'credits' or 'API calls'"}
|
||||
<Tooltip delayDuration={400}>
|
||||
<TooltipTrigger asChild>
|
||||
<InfoIcon className="w-3 h-3 text-t3/50" />
|
||||
</TooltipTrigger>
|
||||
<TooltipContent
|
||||
sideOffset={5}
|
||||
side="top"
|
||||
align="start"
|
||||
className="flex flex-col"
|
||||
>
|
||||
<p>
|
||||
Single use features can have a reset period, to refill a
|
||||
balance every month, day etc. Existing usage is also
|
||||
typically reset on upgrades.
|
||||
<br />
|
||||
<br />
|
||||
Continuous use features don't have a reset period. They
|
||||
can be prorated (eg, if a seat is purchased halfway during
|
||||
the month, it'll cost half the price).
|
||||
</p>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</p>
|
||||
</Tabs>
|
||||
</div>
|
||||
</div>
|
||||
)} */}
|
||||
{notNullish(feature.type) && (
|
||||
{feature.type == FeatureType.Metered && (
|
||||
<SelectFeatureUsageType feature={feature} setFeature={setFeature} />
|
||||
)}
|
||||
|
||||
{showNameAndId() && (
|
||||
<>
|
||||
<div className="flex gap-2 w-full">
|
||||
<div className="w-full">
|
||||
@@ -351,3 +287,86 @@ export const FilterInput = ({
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
{
|
||||
/* {featureType === FeatureType.Metered && (
|
||||
<div className="w-full">
|
||||
<div className="flex flex-col gap-2">
|
||||
<Tabs
|
||||
defaultValue={FeatureUsageType.Single}
|
||||
value={meteredConfig.usage_type}
|
||||
onValueChange={(value) => {
|
||||
setMeteredConfig({
|
||||
...meteredConfig,
|
||||
usage_type: value as FeatureUsageType,
|
||||
});
|
||||
}}
|
||||
>
|
||||
<TabsList className="-mx-2">
|
||||
<TabsTrigger
|
||||
value={FeatureUsageType.Single}
|
||||
className="flex items-center gap-1"
|
||||
>
|
||||
<Zap className="h-3 w-3 text-t3" />
|
||||
<span>Single Use</span>
|
||||
</TabsTrigger>
|
||||
<TabsTrigger
|
||||
value={FeatureUsageType.Continuous}
|
||||
className="flex items-center gap-1"
|
||||
>
|
||||
<Clock className="h-3 w-3 text-t3" />
|
||||
<span>Continuous Use</span>
|
||||
</TabsTrigger>
|
||||
</TabsList>
|
||||
<p className="text-sm text-t3 flex items-center gap-1">
|
||||
{meteredConfig.usage_type === FeatureUsageType.Continuous
|
||||
? "For features used on an ongoing basis, like 'seats' or 'storage'"
|
||||
: "For features that are consumed and refilled like 'credits' or 'API calls'"}
|
||||
<Tooltip delayDuration={400}>
|
||||
<TooltipTrigger asChild>
|
||||
<InfoIcon className="w-3 h-3 text-t3/50" />
|
||||
</TooltipTrigger>
|
||||
<TooltipContent
|
||||
sideOffset={5}
|
||||
side="top"
|
||||
align="start"
|
||||
className="flex flex-col"
|
||||
>
|
||||
<p>
|
||||
Single use features can have a reset period, to refill a
|
||||
balance every month, day etc. Existing usage is also
|
||||
typically reset on upgrades.
|
||||
<br />
|
||||
<br />
|
||||
Continuous use features don't have a reset period. They
|
||||
can be prorated (eg, if a seat is purchased halfway during
|
||||
the month, it'll cost half the price).
|
||||
</p>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</p>
|
||||
</Tabs>
|
||||
</div>
|
||||
</div>
|
||||
)} */
|
||||
}
|
||||
|
||||
{
|
||||
/* <Tabs
|
||||
defaultValue={feature.type}
|
||||
className="w-[400px]"
|
||||
value={featureType}
|
||||
onValueChange={setFeatureType}
|
||||
>
|
||||
<TabsList className="-ml-2">
|
||||
<TabsTrigger value={FeatureType.Metered}>Metered</TabsTrigger>
|
||||
<TabsTrigger value={FeatureType.Boolean}>Boolean</TabsTrigger>
|
||||
</TabsList>
|
||||
<p className="text-t3 text-sm">
|
||||
{featureType == FeatureType.Metered &&
|
||||
"A usage-based feature that you want to track"}
|
||||
{featureType == FeatureType.Boolean &&
|
||||
"A feature flag that can be either enabled or disabled"}
|
||||
</p>
|
||||
</Tabs> */
|
||||
}
|
||||
|
||||
@@ -1,46 +1,14 @@
|
||||
import FieldLabel from "@/components/general/modal-components/FieldLabel";
|
||||
import { SelectType } from "@/components/general/SelectType";
|
||||
import {
|
||||
APIFeatureType,
|
||||
CreateFeature,
|
||||
FeatureType,
|
||||
FeatureUsageType,
|
||||
} from "@autumn/shared";
|
||||
import { Clock, ToggleLeft, Zap } from "lucide-react";
|
||||
import { Zap, Clock, ArrowUp01, Flag } from "lucide-react";
|
||||
import { defaultMeteredConfig } from "./defaultFeatureConfig";
|
||||
import FieldLabel from "@/components/general/modal-components/FieldLabel";
|
||||
|
||||
const SelectType = ({
|
||||
title,
|
||||
description,
|
||||
icon,
|
||||
isSelected,
|
||||
onClick,
|
||||
}: {
|
||||
title: string;
|
||||
description: string;
|
||||
icon: React.ReactNode;
|
||||
isSelected: boolean;
|
||||
onClick: () => void;
|
||||
}) => {
|
||||
return (
|
||||
<div
|
||||
key={FeatureUsageType.Single}
|
||||
className={`h-fit flex flex-col gap-2 text-sm p-2 rounded-xs cursor-pointer ${
|
||||
isSelected
|
||||
? "shadow-inner bg-stone-100 border border-zinc-200"
|
||||
: "border"
|
||||
}`}
|
||||
onClick={onClick}
|
||||
>
|
||||
<div className="flex items-center gap-1">
|
||||
<span className="text-t2 text-sm font-medium whitespace-nowrap">
|
||||
{title}
|
||||
</span>
|
||||
<div className="flex w-4 h-full items-center justify-start">{icon}</div>
|
||||
</div>
|
||||
<p className="text-t2 text-xs">{description}</p>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
export const SelectFeatureType = ({
|
||||
feature,
|
||||
setFeature,
|
||||
@@ -69,35 +37,45 @@ export const SelectFeatureType = ({
|
||||
};
|
||||
return (
|
||||
<div className="flex flex-col">
|
||||
<FieldLabel>Select Feature Type</FieldLabel>
|
||||
<div className="grid grid-cols-3 gap-2">
|
||||
<FieldLabel>Feature Type</FieldLabel>
|
||||
<div className="grid grid-cols-2 gap-2">
|
||||
<SelectType
|
||||
title="Single Use"
|
||||
description="Features that are consumed and refilled like 'credits' or 'tokens'"
|
||||
icon={<Zap className="h-3 w-3 text-t3" />}
|
||||
isSelected={
|
||||
featureType === FeatureType.Metered &&
|
||||
usageType === FeatureUsageType.Single
|
||||
}
|
||||
onClick={() => setFeatureType(APIFeatureType.SingleUsage)}
|
||||
/>
|
||||
<SelectType
|
||||
title="Continuous Use"
|
||||
description="Features used on an ongoing basis, like 'seats' or 'storage'"
|
||||
icon={<Clock className="h-3 w-3 text-t3" />}
|
||||
isSelected={
|
||||
featureType === FeatureType.Metered &&
|
||||
usageType === FeatureUsageType.Continuous
|
||||
}
|
||||
onClick={() => setFeatureType(APIFeatureType.ContinuousUse)}
|
||||
title="Metered"
|
||||
description="A usage-based feature that you want to track"
|
||||
icon={<ArrowUp01 className="text-t3" size={13} />}
|
||||
isSelected={featureType === FeatureType.Metered}
|
||||
onClick={() => {
|
||||
const curConfig = feature.config;
|
||||
setFeature({
|
||||
...feature,
|
||||
type: FeatureType.Metered,
|
||||
config: {
|
||||
...defaultMeteredConfig,
|
||||
usage_type: curConfig?.usage_type ?? null,
|
||||
},
|
||||
});
|
||||
}}
|
||||
/>
|
||||
<SelectType
|
||||
title="Boolean"
|
||||
description="Features that are either enabled or disabled, like 'premium models'"
|
||||
icon={<ToggleLeft className="h-3 w-3 text-t3" />}
|
||||
description="A feature flag that can be either enabled or disabled"
|
||||
icon={<Flag className="text-t3" size={12} />}
|
||||
isSelected={featureType === FeatureType.Boolean}
|
||||
onClick={() => setFeatureType(APIFeatureType.Boolean)}
|
||||
onClick={() =>
|
||||
setFeature({
|
||||
...feature,
|
||||
type: FeatureType.Boolean,
|
||||
config: undefined,
|
||||
})
|
||||
}
|
||||
/>
|
||||
{/* <SelectType
|
||||
title="Boolean"
|
||||
description="Features that are either enabled or disabled, like 'premium models'"
|
||||
icon={<ToggleLeft className="h-3 w-3 text-t3" />}
|
||||
isSelected={featureType === FeatureType.Boolean}
|
||||
onClick={() => setFeatureType(APIFeatureType.Boolean)}
|
||||
/> */}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
import {
|
||||
APIFeatureType,
|
||||
CreateFeature,
|
||||
FeatureType,
|
||||
FeatureUsageType,
|
||||
} from "@autumn/shared";
|
||||
import { Clock, ToggleLeft, Zap } from "lucide-react";
|
||||
import { defaultMeteredConfig } from "./defaultFeatureConfig";
|
||||
import FieldLabel from "@/components/general/modal-components/FieldLabel";
|
||||
import { SelectType } from "@/components/general/SelectType";
|
||||
|
||||
export const SelectFeatureUsageType = ({
|
||||
feature,
|
||||
setFeature,
|
||||
}: {
|
||||
feature: CreateFeature;
|
||||
setFeature: any;
|
||||
}) => {
|
||||
const featureType = feature.type;
|
||||
const usageType = feature.config?.usage_type;
|
||||
|
||||
const setFeatureType = (type: APIFeatureType) => {
|
||||
// 1. If type is boolean
|
||||
if (type === APIFeatureType.Boolean) {
|
||||
setFeature({
|
||||
...feature,
|
||||
type: APIFeatureType.Boolean,
|
||||
config: undefined,
|
||||
});
|
||||
} else {
|
||||
setFeature({
|
||||
...feature,
|
||||
type: FeatureType.Metered,
|
||||
config: { ...defaultMeteredConfig, usage_type: type },
|
||||
});
|
||||
}
|
||||
};
|
||||
return (
|
||||
<div className="flex flex-col">
|
||||
<FieldLabel>Usage Type</FieldLabel>
|
||||
<div className="grid grid-cols-2 gap-2">
|
||||
<SelectType
|
||||
title="Single"
|
||||
description="Features that are consumed and refilled like 'credits' or 'tokens'"
|
||||
icon={<Zap className="text-t3" size={12} />}
|
||||
isSelected={
|
||||
featureType === FeatureType.Metered &&
|
||||
usageType === FeatureUsageType.Single
|
||||
}
|
||||
onClick={() => setFeatureType(APIFeatureType.SingleUsage)}
|
||||
/>
|
||||
<SelectType
|
||||
title="Continuous"
|
||||
description="Features used on an ongoing basis, like 'seats' or 'storage'"
|
||||
icon={<Clock className="text-t3" size={12} />}
|
||||
isSelected={
|
||||
featureType === FeatureType.Metered &&
|
||||
usageType === FeatureUsageType.Continuous
|
||||
}
|
||||
onClick={() => setFeatureType(APIFeatureType.ContinuousUse)}
|
||||
/>
|
||||
{/* <SelectType
|
||||
title="Boolean"
|
||||
description="Features that are either enabled or disabled, like 'premium models'"
|
||||
icon={<ToggleLeft className="h-3 w-3 text-t3" />}
|
||||
isSelected={featureType === FeatureType.Boolean}
|
||||
onClick={() => setFeatureType(APIFeatureType.Boolean)}
|
||||
/> */}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -6,7 +6,7 @@ export const getDefaultFeature = (entityCreate?: boolean): any => {
|
||||
return {
|
||||
type: FeatureType.Metered,
|
||||
config: {
|
||||
defaultMeteredConfig,
|
||||
...defaultMeteredConfig,
|
||||
usage_type: FeatureUsageType.Continuous,
|
||||
},
|
||||
name: "",
|
||||
|
||||
@@ -11,31 +11,31 @@ export const useMemberships = () => {
|
||||
url: "/organization/members",
|
||||
});
|
||||
|
||||
const { data: session } = useSession();
|
||||
const { data: orgs } = useListOrganizations();
|
||||
// const { data: session } = useSession();
|
||||
// const { data: orgs } = useListOrganizations();
|
||||
|
||||
const handleRemovedFromOrg = async () => {
|
||||
const inOrg = orgs?.find(
|
||||
(org: any) => org.id === session?.session?.activeOrganizationId,
|
||||
);
|
||||
// const handleRemovedFromOrg = async () => {
|
||||
// const inOrg = orgs?.find(
|
||||
// (org: any) => org.id === session?.session?.activeOrganizationId,
|
||||
// );
|
||||
|
||||
if (!inOrg) {
|
||||
if (orgs && orgs.length > 0) {
|
||||
await authClient.organization.setActive({
|
||||
organizationId: orgs[0].id,
|
||||
});
|
||||
} else {
|
||||
const { data, error } = await authClient.revokeSessions();
|
||||
console.log("Revoked sessions", data, error);
|
||||
}
|
||||
window.location.reload();
|
||||
}
|
||||
};
|
||||
// if (!inOrg) {
|
||||
// if (orgs && orgs.length > 0) {
|
||||
// await authClient.organization.setActive({
|
||||
// organizationId: orgs[0].id,
|
||||
// });
|
||||
// } else {
|
||||
// const { data, error } = await authClient.revokeSessions();
|
||||
// console.log("Revoked sessions", data, error);
|
||||
// }
|
||||
// window.location.reload();
|
||||
// }
|
||||
// };
|
||||
|
||||
useEffect(() => {
|
||||
if (!orgs) return;
|
||||
handleRemovedFromOrg();
|
||||
}, [orgs]);
|
||||
// useEffect(() => {
|
||||
// if (!orgs) return;
|
||||
// handleRemovedFromOrg();
|
||||
// }, [orgs]);
|
||||
|
||||
return {
|
||||
memberships: data?.memberships || [],
|
||||
|
||||
@@ -48,7 +48,12 @@ export const SelectEditProduct = () => {
|
||||
return (
|
||||
<DropdownMenuItem
|
||||
key={p.id}
|
||||
onClick={() => setProduct(p)}
|
||||
onClick={() => {
|
||||
setProduct(p);
|
||||
setQueryStates({
|
||||
productId: p.id,
|
||||
});
|
||||
}}
|
||||
className="flex items-center justify-between group"
|
||||
>
|
||||
{p.name}
|
||||
|
||||
@@ -21,18 +21,8 @@ import { getBackendErr, getRedirectUrl } from "@/utils/genUtils";
|
||||
import { useEnv } from "@/utils/envUtils";
|
||||
import { useNavigate } from "react-router";
|
||||
|
||||
function CreateFixedPrice({
|
||||
config,
|
||||
setConfig,
|
||||
show,
|
||||
setShow,
|
||||
}: {
|
||||
config: any;
|
||||
setConfig: (config: any) => void;
|
||||
show: any;
|
||||
setShow: (show: any) => void;
|
||||
}) {
|
||||
const { item, selectedIndex } = useProductItemContext();
|
||||
function CreateFixedPrice() {
|
||||
const { item, setItem, selectedIndex } = useProductItemContext();
|
||||
const { org, product, counts, hasChanges } = useProductContext();
|
||||
const [copyLoading, setCopyLoading] = useState(false);
|
||||
const axiosInstance = useAxiosInstance();
|
||||
@@ -125,23 +115,25 @@ function CreateFixedPrice({
|
||||
return (
|
||||
<div>
|
||||
{/* <p className="text-t3 text-md mt-4 mb-2 font-medium">Rates</p> */}
|
||||
<div className="flex flex-col w-full gap-6 animate-in fade-in duration-300 !overflow-visible">
|
||||
<div className="w-full flex flex-col">
|
||||
<div className="flex flex-col w-full gap-6 !overflow-visible">
|
||||
<div className="w-full flex flex-col overflow-visible">
|
||||
<FieldLabel>Fixed Price</FieldLabel>
|
||||
<div className="flex h-full items-center justify-between gap-2 !overflow-visible">
|
||||
<Input
|
||||
value={config.price}
|
||||
value={item.price}
|
||||
onChange={(e) => {
|
||||
setConfig({ ...config, price: e.target.value });
|
||||
setItem({ ...item, price: e.target.value });
|
||||
}}
|
||||
placeholder="30.00"
|
||||
type="number"
|
||||
step="any"
|
||||
className="h-full !text-lg min-w-36"
|
||||
className="min-w-36"
|
||||
endContent={
|
||||
<span className="text-t2 w-fit px-2 flex justify-center">
|
||||
{org?.default_currency?.toUpperCase() || "USD"}
|
||||
</span>
|
||||
}
|
||||
/>
|
||||
<span className="text-t2 w-fit px-2 flex justify-center">
|
||||
{org?.default_currency?.toUpperCase() || "USD"}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="w-full">
|
||||
|
||||
@@ -2,22 +2,30 @@ import { Button } from "@/components/ui/button";
|
||||
import { Dialog, DialogTrigger } from "@/components/ui/dialog";
|
||||
|
||||
import { useEffect, useState } from "react";
|
||||
import { ProductItemContext } from "./ProductItemContext";
|
||||
import {
|
||||
ProductItemContext,
|
||||
useProductItemContext,
|
||||
} from "./ProductItemContext";
|
||||
|
||||
import {
|
||||
ProductItemInterval,
|
||||
ProductItem,
|
||||
CreateFeature as CreateFeatureType,
|
||||
FrontendProductItem,
|
||||
Infinite,
|
||||
} from "@autumn/shared";
|
||||
|
||||
import { useProductContext } from "../ProductContext";
|
||||
import { validateProductItem } from "@/utils/product/product-item/validateProductItem";
|
||||
import { useAxiosInstance } from "@/services/useAxiosInstance";
|
||||
import { CreateItemDialogContent } from "./create-product-item/CreateItemDialogContent";
|
||||
import { Plus } from "lucide-react";
|
||||
import { useSteps } from "./useSteps";
|
||||
import { CreateItemStep } from "./utils/CreateItemStep";
|
||||
import { isFeatureItem } from "@/utils/product/getItemType";
|
||||
import { isFeatureItem, isFeaturePriceItem } from "@/utils/product/getItemType";
|
||||
import { emptyPriceItem } from "./create-product-item/defaultItemConfigs";
|
||||
import { itemsHaveSameInterval } from "@/utils/product/productItemUtils";
|
||||
import { toast } from "sonner";
|
||||
import { getFeature } from "@/utils/product/entitlementUtils";
|
||||
|
||||
export const defaultProductItem: ProductItem = {
|
||||
feature_id: null,
|
||||
@@ -36,20 +44,109 @@ export const defaultProductItem: ProductItem = {
|
||||
reset_usage_when_enabled: true,
|
||||
};
|
||||
|
||||
const defaultPriceItem: ProductItem = {
|
||||
feature_id: null,
|
||||
included_usage: null,
|
||||
const useMergeFeatureItem = ({
|
||||
item,
|
||||
setOpen,
|
||||
}: {
|
||||
item: ProductItem;
|
||||
setOpen: (open: boolean) => void;
|
||||
}) => {
|
||||
const { product, setProduct } = useProductContext();
|
||||
const getOtherFeaturePriceItemIndex = () => {
|
||||
return product.items.findIndex(
|
||||
(i: any) =>
|
||||
i.feature_id === item.feature_id &&
|
||||
isFeaturePriceItem(i) &&
|
||||
itemsHaveSameInterval({ item1: i, item2: item })
|
||||
);
|
||||
};
|
||||
|
||||
interval: ProductItemInterval.Month,
|
||||
const shouldMergeFeatureItem = () => {
|
||||
const otherItemIndex = getOtherFeaturePriceItemIndex();
|
||||
const isFeature = isFeatureItem(item);
|
||||
return isFeature && otherItemIndex !== -1;
|
||||
};
|
||||
|
||||
// Price config
|
||||
price: 0,
|
||||
tiers: null,
|
||||
billing_units: 1,
|
||||
const mergeFeatureItem = () => {
|
||||
const otherItemIndex = getOtherFeaturePriceItemIndex();
|
||||
const newItems = [...product.items];
|
||||
const newIncludedUsage = parseFloat(item.included_usage?.toString() || "0");
|
||||
if (isNaN(newIncludedUsage)) {
|
||||
toast.error("You must set an included usage for this item");
|
||||
return;
|
||||
}
|
||||
|
||||
// Others
|
||||
entity_feature_id: null,
|
||||
reset_usage_when_enabled: true,
|
||||
newItems[otherItemIndex] = {
|
||||
...newItems[otherItemIndex],
|
||||
included_usage: newIncludedUsage,
|
||||
};
|
||||
|
||||
setProduct({ ...product, items: newItems });
|
||||
setOpen(false);
|
||||
};
|
||||
|
||||
return {
|
||||
shouldMergeFeatureItem,
|
||||
mergeFeatureItem,
|
||||
};
|
||||
};
|
||||
|
||||
const useMergeFeaturePriceItem = ({
|
||||
item,
|
||||
setOpen,
|
||||
}: {
|
||||
item: ProductItem;
|
||||
setOpen: (open: boolean) => void;
|
||||
}) => {
|
||||
const { product, setProduct, features } = useProductContext();
|
||||
|
||||
const getOtherFeatureItemIndex = () => {
|
||||
return product.items.findIndex(
|
||||
(i: any) =>
|
||||
i.feature_id === item.feature_id &&
|
||||
isFeatureItem(i) &&
|
||||
itemsHaveSameInterval({ item1: i, item2: item })
|
||||
);
|
||||
};
|
||||
|
||||
const shouldMergeFeaturePriceItem = () => {
|
||||
const otherItemIndex = getOtherFeatureItemIndex();
|
||||
const isFeaturePrice = isFeaturePriceItem(item);
|
||||
return isFeaturePrice && otherItemIndex !== -1 && item.feature_id;
|
||||
};
|
||||
|
||||
const mergeFeaturePriceItem = () => {
|
||||
const otherItemIndex = getOtherFeatureItemIndex();
|
||||
const otherItem = product.items[otherItemIndex];
|
||||
|
||||
// 1. If unlimited, don't allow this item
|
||||
if (otherItem.included_usage === Infinite) {
|
||||
toast.error(
|
||||
`Cannot create a priced feature when you have another item for this feature (${otherItem.feature_id}) which is unlimited`
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const newItems = [...product.items];
|
||||
const newItem = validateProductItem({
|
||||
item: item as FrontendProductItem,
|
||||
features,
|
||||
});
|
||||
if (!newItem) return;
|
||||
|
||||
newItems[otherItemIndex] = {
|
||||
...newItem,
|
||||
included_usage: otherItem.included_usage,
|
||||
};
|
||||
|
||||
setProduct({ ...product, items: newItems });
|
||||
setOpen(false);
|
||||
};
|
||||
|
||||
return {
|
||||
shouldMergeFeaturePriceItem,
|
||||
mergeFeaturePriceItem,
|
||||
};
|
||||
};
|
||||
|
||||
export function CreateProductItem() {
|
||||
@@ -59,25 +156,52 @@ export function CreateProductItem() {
|
||||
const { features, product, setProduct, setFeatures, counts, mutate } =
|
||||
useProductContext();
|
||||
|
||||
// const axiosInstance = useAxiosInstance();
|
||||
// const hasCustomers = counts?.all > 0;
|
||||
const [configState, setConfigState] = useState({
|
||||
showPrice: false,
|
||||
});
|
||||
|
||||
// const setSelectedFeature = (feature: CreateFeatureType) => {
|
||||
// setFeatures([...features, feature]);
|
||||
// setItem({ ...item, feature_id: feature.id! });
|
||||
// };
|
||||
const { shouldMergeFeatureItem, mergeFeatureItem } = useMergeFeatureItem({
|
||||
item,
|
||||
setOpen,
|
||||
});
|
||||
const { shouldMergeFeaturePriceItem, mergeFeaturePriceItem } =
|
||||
useMergeFeaturePriceItem({
|
||||
item,
|
||||
setOpen,
|
||||
});
|
||||
|
||||
const warning = () => {
|
||||
if (shouldMergeFeatureItem() && item.feature_id) {
|
||||
const feature = getFeature(item.feature_id, features);
|
||||
return `You already have a usage-based price for ${feature?.name}. Adding this feature will merge it with that price, and create an overage price (eg 100 free, then $0.5 thereafter)`;
|
||||
}
|
||||
|
||||
if (shouldMergeFeaturePriceItem() && item.feature_id) {
|
||||
const feature = getFeature(item.feature_id, features);
|
||||
return `You already have a feature item for ${feature?.name}. Adding a variable price will merge it with that item, and create an overage price (eg 100 free, then $0.5 thereafter)`;
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
const handleCreateProductItem = async (entityFeatureId?: string) => {
|
||||
if (shouldMergeFeatureItem()) {
|
||||
mergeFeatureItem();
|
||||
return;
|
||||
}
|
||||
|
||||
if (shouldMergeFeaturePriceItem()) {
|
||||
mergeFeaturePriceItem();
|
||||
return;
|
||||
}
|
||||
|
||||
const validatedItem = validateProductItem({
|
||||
item: {
|
||||
...item,
|
||||
...(item as FrontendProductItem),
|
||||
entity_feature_id: entityFeatureId
|
||||
? entityFeatureId
|
||||
: item.entity_feature_id,
|
||||
},
|
||||
// show: {
|
||||
// price: true,
|
||||
// },
|
||||
features,
|
||||
});
|
||||
|
||||
@@ -93,12 +217,6 @@ export function CreateProductItem() {
|
||||
initialStep: CreateItemStep.CreateItem,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (open && isFeatureItem(item) && features.length == 0) {
|
||||
stepState.replaceStep(CreateItemStep.CreateFeature);
|
||||
}
|
||||
}, [open]);
|
||||
|
||||
return (
|
||||
<ProductItemContext.Provider
|
||||
value={{
|
||||
@@ -109,6 +227,8 @@ export function CreateProductItem() {
|
||||
isUpdate: false,
|
||||
handleCreateProductItem,
|
||||
stepState,
|
||||
setOpen,
|
||||
warning: warning(),
|
||||
}}
|
||||
>
|
||||
<Dialog open={open} onOpenChange={setOpen}>
|
||||
@@ -127,7 +247,7 @@ export function CreateProductItem() {
|
||||
<Button
|
||||
className="w-24"
|
||||
variant="add"
|
||||
onClick={() => setItem(defaultPriceItem)}
|
||||
onClick={() => setItem(emptyPriceItem)}
|
||||
startIcon={<Plus size={14} />}
|
||||
>
|
||||
Price
|
||||
@@ -139,65 +259,3 @@ export function CreateProductItem() {
|
||||
</ProductItemContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
{
|
||||
/* <DialogTrigger asChild>
|
||||
<Button
|
||||
variant="add"
|
||||
className="w-24 border-l-0"
|
||||
onClick={() => setItem(defaultPriceItem)}
|
||||
>
|
||||
Price
|
||||
</Button>
|
||||
</DialogTrigger> */
|
||||
}
|
||||
{
|
||||
/* <DialogContent className="translate-y-[0%] top-[20%] flex flex-col gap-0 w-fit p-0">
|
||||
<DialogContentWrapper>
|
||||
<DialogHeader className="p-0">
|
||||
<div className="flex flex-col ">
|
||||
{showCreateFeature && (
|
||||
<Button
|
||||
variant="ghost"
|
||||
className="text-xs py-0 px-2 w-fit -ml-5 -mt-5 hover:bg-transparent"
|
||||
onClick={() => setShowCreateFeature(false)}
|
||||
>
|
||||
← Product
|
||||
</Button>
|
||||
)}
|
||||
|
||||
<DialogTitle>
|
||||
{showCreateFeature ||
|
||||
(features.length == 0 && item.price === null)
|
||||
? "Create Feature"
|
||||
: "Add Product Item"}
|
||||
</DialogTitle>
|
||||
</div>
|
||||
</DialogHeader>
|
||||
<div className="flex !overflow-visible w-fit">
|
||||
{showCreateFeature ||
|
||||
(features.length == 0 && item.price === null) ? (
|
||||
<div className="w-full -mt-2">
|
||||
<CreateFeature
|
||||
isFromEntitlement={true}
|
||||
setShowFeatureCreate={setShowCreateFeature}
|
||||
setSelectedFeature={setSelectedFeature}
|
||||
setOpen={setOpen}
|
||||
open={open}
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<div className="flex flex-col gap-4 w-fit !overflow-visible">
|
||||
<ProductItemConfig />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</DialogContentWrapper>
|
||||
{showCreateFeature ||
|
||||
(features.length == 0 && item.price === null) ? (
|
||||
<div className="" />
|
||||
) : (
|
||||
<ItemConfigFooter setIntroDone={() => {}} />
|
||||
)}
|
||||
</DialogContent> */
|
||||
}
|
||||
|
||||
@@ -113,20 +113,11 @@ export const EntitiesDropdownContent = () => {
|
||||
</DialogTrigger>
|
||||
<CustomDialogContent>
|
||||
<CreateFeature
|
||||
// isFromEntitlement={false}
|
||||
// setShowFeatureCreate={() => {}}
|
||||
// setSelectedFeature={() => {}}
|
||||
setOpen={setCreateFeatureOpen}
|
||||
open={createFeatureOpen}
|
||||
entityCreate={true}
|
||||
/>
|
||||
</CustomDialogContent>
|
||||
{/* <DialogContent className="w-[500px]">
|
||||
<DialogHeader>
|
||||
<DialogTitle>Create Entity</DialogTitle>
|
||||
</DialogHeader>
|
||||
|
||||
</DialogContent> */}
|
||||
</Dialog>
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -17,7 +17,12 @@ import {
|
||||
} from "@/utils/product/productItemUtils";
|
||||
import { ConfigWithFeature } from "./components/ConfigWithFeature";
|
||||
import FixedPriceConfig from "./components/ConfigFixedPrice";
|
||||
import { isFeaturePriceItem, isPriceItem } from "@/utils/product/getItemType";
|
||||
import {
|
||||
isFeatureItem,
|
||||
isFeaturePriceItem,
|
||||
isPriceItem,
|
||||
} from "@/utils/product/getItemType";
|
||||
import { PriceItemConfig } from "./product-item-config/PriceItemConfig";
|
||||
|
||||
export const ProductItemConfig = () => {
|
||||
// HOOKS
|
||||
@@ -75,33 +80,24 @@ export const ProductItemConfig = () => {
|
||||
newItem.config = newConfig;
|
||||
}
|
||||
}
|
||||
// If showProration is false, don't touch the config at all - preserve whatever is there
|
||||
|
||||
setItem(newItem);
|
||||
}
|
||||
}
|
||||
}, [item.feature_id, item.usage_model]);
|
||||
|
||||
const isPrice = isPriceItem(item);
|
||||
|
||||
// const isFeature = isFeatureItem(item);
|
||||
const isPrice = item.isPrice;
|
||||
// isPriceItem(item) && "w-sm",
|
||||
// isFeaturePriceItem(item) && "!w-sm",
|
||||
// isFeaturePriceItem(item) && item.tiers?.length > 1 && "w-sm"
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
"flex flex-col gap-6 w-md transition-all ease-in-out duration-300 !overflow-visible", //modal animations
|
||||
isPriceItem(item) && "w-xs",
|
||||
isFeaturePriceItem(item) && "w-md",
|
||||
isFeaturePriceItem(item) && item.tiers?.length > 1 && "w-md"
|
||||
"flex flex-col gap-6 w-sm transition-all ease-in-out duration-300 !overflow-visible" //modal animations
|
||||
)}
|
||||
>
|
||||
{isPrice ? (
|
||||
<FixedPriceConfig show={show} setShow={setShow} />
|
||||
) : (
|
||||
<ConfigWithFeature
|
||||
show={show}
|
||||
setShow={setShow}
|
||||
handleAddPrice={handleAddPrice}
|
||||
/>
|
||||
)}
|
||||
{isPrice ? <PriceItemConfig /> : <ConfigWithFeature />}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -227,7 +227,6 @@ export const ProductItemRow = ({
|
||||
};
|
||||
|
||||
const itemType = getItemType(item);
|
||||
const isLast = index === product.items.length - 1;
|
||||
|
||||
return (
|
||||
<div
|
||||
|
||||
@@ -19,6 +19,7 @@ import { cn } from "@/lib/utils";
|
||||
import { EntitiesDropdownContent } from "./EntitiesDropdown";
|
||||
import { CreateFreeTrial } from "../free-trial/CreateFreeTrial";
|
||||
import { InfoTooltip } from "@/components/general/modal-components/InfoTooltip";
|
||||
import { getFrontendItemConfig } from "./utils/getFrontendItemConfig";
|
||||
|
||||
export const ProductItemTable = () => {
|
||||
const { product, features, org, entityFeatureIds, isOnboarding, autoSave } =
|
||||
@@ -31,7 +32,9 @@ export const ProductItemTable = () => {
|
||||
const [freeTrialOpen, setFreeTrialOpen] = useState(false);
|
||||
|
||||
const handleRowClick = (item: ProductItem, index: number) => {
|
||||
setSelectedItem(item);
|
||||
const frontendItem = getFrontendItemConfig(item);
|
||||
|
||||
setSelectedItem(frontendItem);
|
||||
setSelectedIndex(index);
|
||||
setOpen(true);
|
||||
};
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Dialog, DialogContent, DialogTitle } from "@/components/ui/dialog";
|
||||
import { useEffect, useState } from "react";
|
||||
import { ProductItemConfig } from "./ProductItemConfig";
|
||||
import { ProductItem } from "@autumn/shared";
|
||||
import { FrontendProductItem, ProductItem } from "@autumn/shared";
|
||||
import { ProductItemContext } from "./ProductItemContext";
|
||||
import { useProductContext } from "../ProductContext";
|
||||
import { notNullish } from "@/utils/genUtils";
|
||||
@@ -14,6 +14,12 @@ import {
|
||||
CustomDialogFooter,
|
||||
} from "@/components/general/modal-components/DialogContentWrapper";
|
||||
import { ItemConfigFooter } from "./product-item-config/item-config-footer/ItemConfigFooter";
|
||||
import {
|
||||
AdvancedConfigSidebar,
|
||||
MainDialogBodyWrapper,
|
||||
ToggleAdvancedConfigButton,
|
||||
} from "./product-item-config/AdvancedConfigSidebar";
|
||||
import { isPriceItem } from "@/utils/product/getItemType";
|
||||
|
||||
export default function UpdateProductItem({
|
||||
selectedItem,
|
||||
@@ -31,9 +37,20 @@ export default function UpdateProductItem({
|
||||
const { product, setProduct, features } = useProductContext();
|
||||
const [showCreateFeature, setShowCreateFeature] = useState(false);
|
||||
|
||||
const [advancedOpen, setAdvancedOpen] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (!open) {
|
||||
setTimeout(() => {
|
||||
setAdvancedOpen(false);
|
||||
}, 300);
|
||||
}
|
||||
}, [open]);
|
||||
|
||||
const handleUpdateProductItem = () => {
|
||||
const frontendItem = selectedItem as FrontendProductItem;
|
||||
const validatedItem = validateProductItem({
|
||||
item: selectedItem!,
|
||||
item: frontendItem!,
|
||||
features,
|
||||
});
|
||||
|
||||
@@ -72,20 +89,31 @@ export default function UpdateProductItem({
|
||||
}}
|
||||
>
|
||||
<Dialog open={open} onOpenChange={setOpen}>
|
||||
<CustomDialogContent>
|
||||
<CustomDialogBody>
|
||||
<div className="flex items-center justify-between pr-9.5">
|
||||
<DialogTitle>Update Item</DialogTitle>
|
||||
{selectedItem?.feature_id && (
|
||||
<CopyButton text={selectedItem.feature_id || ""}>
|
||||
{selectedItem.feature_id || ""}
|
||||
</CopyButton>
|
||||
)}
|
||||
</div>
|
||||
<ProductItemConfig />
|
||||
</CustomDialogBody>
|
||||
|
||||
<ItemConfigFooter />
|
||||
<CustomDialogContent className="!max-w-none ">
|
||||
<div className="flex relative overflow-hidden w-full h-full overflow-y-auto">
|
||||
<MainDialogBodyWrapper advancedOpen={advancedOpen}>
|
||||
<CustomDialogBody className="!pb-0">
|
||||
<div className="flex items-center justify-between pr-9.5">
|
||||
<DialogTitle>Update Item</DialogTitle>
|
||||
{selectedItem?.feature_id && (
|
||||
<CopyButton text={selectedItem.feature_id || ""}>
|
||||
{selectedItem.feature_id || ""}
|
||||
</CopyButton>
|
||||
)}
|
||||
</div>
|
||||
<ProductItemConfig />
|
||||
</CustomDialogBody>
|
||||
<ToggleAdvancedConfigButton
|
||||
advancedOpen={advancedOpen}
|
||||
setAdvancedOpen={setAdvancedOpen}
|
||||
showAdvancedButton={
|
||||
selectedItem ? !isPriceItem(selectedItem) : false
|
||||
}
|
||||
/>
|
||||
<ItemConfigFooter />
|
||||
</MainDialogBodyWrapper>
|
||||
<AdvancedConfigSidebar advancedOpen={advancedOpen} />
|
||||
</div>
|
||||
</CustomDialogContent>
|
||||
|
||||
{/* <DialogContent className="translate-y-[0%] top-[20%] flex flex-col w-fit gap-0 p-0">
|
||||
|
||||
@@ -5,30 +5,76 @@ import { useProductContext } from "../../ProductContext";
|
||||
import { FeatureType } from "@autumn/shared";
|
||||
import { getFeature } from "@/utils/product/entitlementUtils";
|
||||
import { FeatureConfig } from "../product-item-config/FeatureItemConfig";
|
||||
import { WarningBox } from "@/components/general/modal-components/WarningBox";
|
||||
import { ArrowRight } from "lucide-react";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { isFeatureItem, isFeaturePriceItem } from "@/utils/product/getItemType";
|
||||
import { itemsHaveSameInterval } from "@/utils/product/productItemUtils";
|
||||
import { toast } from "sonner";
|
||||
|
||||
export const ConfigWithFeature = ({
|
||||
show,
|
||||
setShow,
|
||||
handleAddPrice,
|
||||
}: {
|
||||
show: any;
|
||||
setShow: (show: any) => void;
|
||||
handleAddPrice: () => void;
|
||||
}) => {
|
||||
const { features } = useProductContext();
|
||||
const { item } = useProductItemContext();
|
||||
export const ConfigWithFeature = () => {
|
||||
const { features, product, setProduct } = useProductContext();
|
||||
const { item, isUpdate, setOpen, warning } = useProductItemContext();
|
||||
|
||||
const isBooleanFeature =
|
||||
getFeature(item.feature_id, features)?.type === FeatureType.Boolean;
|
||||
|
||||
const otherItemIndex = product.items.findIndex(
|
||||
(i: any) =>
|
||||
i.feature_id === item.feature_id &&
|
||||
isFeaturePriceItem(i) &&
|
||||
itemsHaveSameInterval({ item1: i, item2: item })
|
||||
);
|
||||
|
||||
const handleAddToExistingItem = () => {
|
||||
const newItems = [...product.items];
|
||||
const newIncludedUsage = parseFloat(item.included_usage);
|
||||
if (!item.included_usage || isNaN(newIncludedUsage)) {
|
||||
toast.error("You must set an included usage for this item");
|
||||
return;
|
||||
}
|
||||
newItems[otherItemIndex] = {
|
||||
...newItems[otherItemIndex],
|
||||
included_usage: newIncludedUsage,
|
||||
};
|
||||
|
||||
setProduct({ ...product, items: newItems });
|
||||
setOpen(false);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-4 text-sm w-full">
|
||||
<div>
|
||||
<FieldLabel>Feature</FieldLabel>
|
||||
<SelectItemFeature show={show} setShow={setShow} />
|
||||
<SelectItemFeature />
|
||||
</div>
|
||||
|
||||
{!isBooleanFeature && <FeatureConfig />}
|
||||
|
||||
{warning && (
|
||||
<WarningBox className="py-2">
|
||||
<div className="flex flex-col gap-2 relative">
|
||||
<div>
|
||||
{/* You already have a usage-based price for this feature. If you're
|
||||
looking to make it an overage (eg. 100 free, then $0.5
|
||||
thereafter), you should add it to the existing item. */}
|
||||
{warning}
|
||||
</div>
|
||||
|
||||
{/* <div className="flex w-full p-0">
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
className="w-fit gap-1 !max-h-5 text-xs -mx-2 text-yellow-500 hover:text-yellow-700 hover:bg-transparent"
|
||||
endIcon={<ArrowRight size={12} />}
|
||||
onClick={handleAddToExistingItem}
|
||||
>
|
||||
Add to existing item
|
||||
</Button>
|
||||
</div> */}
|
||||
</div>
|
||||
</WarningBox>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -16,24 +16,12 @@ import { getItemType } from "@/utils/product/productItemUtils";
|
||||
import { CreateItemStep } from "../utils/CreateItemStep";
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
export const SelectItemFeature = ({
|
||||
show,
|
||||
setShow,
|
||||
}: {
|
||||
show: any;
|
||||
setShow: any;
|
||||
}) => {
|
||||
export const SelectItemFeature = () => {
|
||||
const { features } = useProductContext();
|
||||
const { item, setItem, isUpdate, stepState } = useProductItemContext();
|
||||
const [open, setOpen] = useState(false);
|
||||
const itemType = getItemType(item);
|
||||
|
||||
// useEffect(() => {
|
||||
// if (stepState.previousStep === CreateItemStep.SelectItemType) {
|
||||
// setOpen(true);
|
||||
// }
|
||||
// }, [stepState.previousStep]);
|
||||
|
||||
return (
|
||||
<div className="flex items-center gap-2 w-full">
|
||||
<Select
|
||||
@@ -51,7 +39,8 @@ export const SelectItemFeature = ({
|
||||
<SelectContent>
|
||||
{features
|
||||
.filter((feature: Feature) => {
|
||||
if (feature.archived) return false;
|
||||
if (feature.archived && feature.id !== item.feature_id)
|
||||
return false;
|
||||
if (itemType === ProductItemType.FeaturePrice) {
|
||||
return feature.type !== FeatureType.Boolean;
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user