Merge branch 'feat/model-plugins-implementing' into deploy/dev

This commit is contained in:
yyh
2026-03-09 23:45:48 +08:00
34 changed files with 5964 additions and 2756 deletions

33
.github/actions/setup-web/action.yml vendored Normal file
View File

@ -0,0 +1,33 @@
name: Setup Web Environment
description: Setup pnpm, Node.js, and install web dependencies.
inputs:
node-version:
description: Node.js version to use
required: false
default: "22"
install-dependencies:
description: Whether to install web dependencies after setting up Node.js
required: false
default: "true"
runs:
using: composite
steps:
- name: Install pnpm
uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4.2.0
with:
package_json_file: web/package.json
run_install: false
- name: Setup Node.js
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
with:
node-version: ${{ inputs.node-version }}
cache: pnpm
cache-dependency-path: ./web/pnpm-lock.yaml
- name: Install dependencies
if: ${{ inputs.install-dependencies == 'true' }}
shell: bash
run: pnpm --dir web install --frozen-lockfile

View File

@ -25,14 +25,11 @@ updates:
interval: "weekly"
open-pull-requests-limit: 2
ignore:
- dependency-name: "@sentry/react"
- dependency-name: "ky"
- dependency-name: "tailwind-merge"
update-types: ["version-update:semver-major"]
- dependency-name: "tailwindcss"
update-types: ["version-update:semver-major"]
- dependency-name: "echarts"
update-types: ["version-update:semver-major"]
- dependency-name: "uuid"
update-types: ["version-update:semver-major"]
- dependency-name: "react-markdown"
update-types: ["version-update:semver-major"]
- dependency-name: "react-syntax-highlighter"

View File

@ -22,12 +22,12 @@ jobs:
steps:
- name: Checkout code
uses: actions/checkout@v6
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- name: Setup UV and Python
uses: astral-sh/setup-uv@v7
uses: astral-sh/setup-uv@5a095e7a2014a4212f075830d4f7277575a9d098 # v7.3.1
with:
enable-cache: true
python-version: ${{ matrix.python-version }}
@ -51,7 +51,7 @@ jobs:
run: sh .github/workflows/expose_service_ports.sh
- name: Set up Sandbox
uses: hoverkraft-tech/compose-action@v2
uses: hoverkraft-tech/compose-action@4894d2492015c1774ee5a13a95b1072093087ec3 # v2.5.0
with:
compose-file: |
docker/docker-compose.middleware.yaml

View File

@ -12,22 +12,22 @@ jobs:
if: github.repository == 'langgenius/dify'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Check Docker Compose inputs
id: docker-compose-changes
uses: tj-actions/changed-files@v47
uses: tj-actions/changed-files@22103cc46bda19c2b464ffe86db46df6922fd323 # v47.0.5
with:
files: |
docker/generate_docker_compose
docker/.env.example
docker/docker-compose-template.yaml
docker/docker-compose.yaml
- uses: actions/setup-python@v6
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
python-version: "3.11"
- uses: astral-sh/setup-uv@v7
- uses: astral-sh/setup-uv@5a095e7a2014a4212f075830d4f7277575a9d098 # v7.3.1
- name: Generate Docker Compose
if: steps.docker-compose-changes.outputs.any_changed == 'true'
@ -84,4 +84,14 @@ jobs:
run: |
uvx --python 3.13 mdformat . --exclude ".agents/skills/**"
- uses: autofix-ci/action@635ffb0c9798bd160680f18fd73371e355b85f27
- name: Setup web environment
uses: ./.github/actions/setup-web
with:
node-version: "24"
- name: ESLint autofix
run: |
cd web
pnpm eslint --concurrency=2 --prune-suppressions
- uses: autofix-ci/action@7a166d7532b277f34e16238930461bf77f9d7ed8 # v1.3.3

View File

@ -53,26 +53,26 @@ jobs:
echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV
- name: Login to Docker Hub
uses: docker/login-action@v3
uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0
with:
username: ${{ env.DOCKERHUB_USER }}
password: ${{ env.DOCKERHUB_TOKEN }}
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a # v4.0.0
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
- name: Extract metadata for Docker
id: meta
uses: docker/metadata-action@v5
uses: docker/metadata-action@030e881283bb7a6894de51c315a6bfe6a94e05cf # v6.0.0
with:
images: ${{ env[matrix.image_name_env] }}
- name: Build Docker image
id: build
uses: docker/build-push-action@v6
uses: docker/build-push-action@d08e5c354a6adb9ed34480a06d141179aa583294 # v7.0.0
with:
context: "{{defaultContext}}:${{ matrix.context }}"
platforms: ${{ matrix.platform }}
@ -91,7 +91,7 @@ jobs:
touch "/tmp/digests/${sanitized_digest}"
- name: Upload digest
uses: actions/upload-artifact@v6
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with:
name: digests-${{ matrix.context }}-${{ env.PLATFORM_PAIR }}
path: /tmp/digests/*
@ -113,21 +113,21 @@ jobs:
context: "web"
steps:
- name: Download digests
uses: actions/download-artifact@v7
uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0
with:
path: /tmp/digests
pattern: digests-${{ matrix.context }}-*
merge-multiple: true
- name: Login to Docker Hub
uses: docker/login-action@v3
uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0
with:
username: ${{ env.DOCKERHUB_USER }}
password: ${{ env.DOCKERHUB_TOKEN }}
- name: Extract metadata for Docker
id: meta
uses: docker/metadata-action@v5
uses: docker/metadata-action@030e881283bb7a6894de51c315a6bfe6a94e05cf # v6.0.0
with:
images: ${{ env[matrix.image_name_env] }}
tags: |

View File

@ -13,13 +13,13 @@ jobs:
steps:
- name: Checkout code
uses: actions/checkout@v6
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 0
persist-credentials: false
- name: Setup UV and Python
uses: astral-sh/setup-uv@v7
uses: astral-sh/setup-uv@5a095e7a2014a4212f075830d4f7277575a9d098 # v7.3.1
with:
enable-cache: true
python-version: "3.12"
@ -40,7 +40,7 @@ jobs:
cp middleware.env.example middleware.env
- name: Set up Middlewares
uses: hoverkraft-tech/compose-action@v2.0.2
uses: hoverkraft-tech/compose-action@4894d2492015c1774ee5a13a95b1072093087ec3 # v2.5.0
with:
compose-file: |
docker/docker-compose.middleware.yaml
@ -63,13 +63,13 @@ jobs:
steps:
- name: Checkout code
uses: actions/checkout@v6
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 0
persist-credentials: false
- name: Setup UV and Python
uses: astral-sh/setup-uv@v7
uses: astral-sh/setup-uv@5a095e7a2014a4212f075830d4f7277575a9d098 # v7.3.1
with:
enable-cache: true
python-version: "3.12"
@ -94,7 +94,7 @@ jobs:
sed -i 's/DB_USERNAME=postgres/DB_USERNAME=mysql/' middleware.env
- name: Set up Middlewares
uses: hoverkraft-tech/compose-action@v2.0.2
uses: hoverkraft-tech/compose-action@4894d2492015c1774ee5a13a95b1072093087ec3 # v2.5.0
with:
compose-file: |
docker/docker-compose.middleware.yaml

View File

@ -19,7 +19,7 @@ jobs:
github.event.workflow_run.head_branch == 'deploy/agent-dev'
steps:
- name: Deploy to server
uses: appleboy/ssh-action@v1
uses: appleboy/ssh-action@0ff4204d59e8e51228ff73bce53f80d53301dee2 # v1.2.5
with:
host: ${{ secrets.AGENT_DEV_SSH_HOST }}
username: ${{ secrets.SSH_USER }}

View File

@ -16,7 +16,7 @@ jobs:
github.event.workflow_run.head_branch == 'deploy/dev'
steps:
- name: Deploy to server
uses: appleboy/ssh-action@v1
uses: appleboy/ssh-action@0ff4204d59e8e51228ff73bce53f80d53301dee2 # v1.2.5
with:
host: ${{ secrets.SSH_HOST }}
username: ${{ secrets.SSH_USER }}

View File

@ -16,7 +16,7 @@ jobs:
github.event.workflow_run.head_branch == 'build/feat/hitl'
steps:
- name: Deploy to server
uses: appleboy/ssh-action@v1
uses: appleboy/ssh-action@0ff4204d59e8e51228ff73bce53f80d53301dee2 # v1.2.5
with:
host: ${{ secrets.HITL_SSH_HOST }}
username: ${{ secrets.SSH_USER }}

View File

@ -32,13 +32,13 @@ jobs:
context: "web"
steps:
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a # v4.0.0
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
- name: Build Docker Image
uses: docker/build-push-action@v6
uses: docker/build-push-action@d08e5c354a6adb9ed34480a06d141179aa583294 # v7.0.0
with:
push: false
context: "{{defaultContext}}:${{ matrix.context }}"

View File

@ -9,6 +9,6 @@ jobs:
pull-requests: write
runs-on: ubuntu-latest
steps:
- uses: actions/labeler@v6
- uses: actions/labeler@634933edcd8ababfe52f92936142cc22ac488b1b # v6.0.1
with:
sync-labels: true

View File

@ -27,8 +27,8 @@ jobs:
vdb-changed: ${{ steps.changes.outputs.vdb }}
migration-changed: ${{ steps.changes.outputs.migration }}
steps:
- uses: actions/checkout@v6
- uses: dorny/paths-filter@v3
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
id: changes
with:
filters: |
@ -39,6 +39,7 @@ jobs:
web:
- 'web/**'
- '.github/workflows/web-tests.yml'
- '.github/actions/setup-web/**'
vdb:
- 'api/core/rag/datasource/**'
- 'docker/**'

View File

@ -21,7 +21,7 @@ jobs:
if: ${{ github.event.workflow_run.conclusion == 'success' && github.event.workflow_run.pull_requests[0].head.repo.full_name != github.repository }}
steps:
- name: Download pyrefly diff artifact
uses: actions/github-script@v8
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
@ -49,7 +49,7 @@ jobs:
run: unzip -o pyrefly_diff.zip
- name: Post comment
uses: actions/github-script@v8
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |

View File

@ -17,12 +17,12 @@ jobs:
pull-requests: write
steps:
- name: Checkout PR branch
uses: actions/checkout@v6
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 0
- name: Setup Python & UV
uses: astral-sh/setup-uv@v5
uses: astral-sh/setup-uv@5a095e7a2014a4212f075830d4f7277575a9d098 # v7.3.1
with:
enable-cache: true
@ -55,7 +55,7 @@ jobs:
echo ${{ github.event.pull_request.number }} > pr_number.txt
- name: Upload pyrefly diff
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with:
name: pyrefly_diff
path: |
@ -64,7 +64,7 @@ jobs:
- name: Comment PR with pyrefly diff
if: ${{ github.event.pull_request.head.repo.full_name == github.repository }}
uses: actions/github-script@v8
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |

View File

@ -16,6 +16,6 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check title
uses: amannn/action-semantic-pull-request@v6.1.1
uses: amannn/action-semantic-pull-request@48f256284bd46cdaab1048c3721360e808335d50 # v6.1.1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@ -18,7 +18,7 @@ jobs:
pull-requests: write
steps:
- uses: actions/stale@v10
- uses: actions/stale@b5d41d4e1d5dceea10e7104786b73624c18a190f # v10.2.0
with:
days-before-issue-stale: 15
days-before-issue-close: 3

View File

@ -19,13 +19,13 @@ jobs:
steps:
- name: Checkout code
uses: actions/checkout@v6
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- name: Check changed files
id: changed-files
uses: tj-actions/changed-files@v47
uses: tj-actions/changed-files@22103cc46bda19c2b464ffe86db46df6922fd323 # v47.0.5
with:
files: |
api/**
@ -33,7 +33,7 @@ jobs:
- name: Setup UV and Python
if: steps.changed-files.outputs.any_changed == 'true'
uses: astral-sh/setup-uv@v7
uses: astral-sh/setup-uv@5a095e7a2014a4212f075830d4f7277575a9d098 # v7.3.1
with:
enable-cache: false
python-version: "3.12"
@ -67,36 +67,22 @@ jobs:
steps:
- name: Checkout code
uses: actions/checkout@v6
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- name: Check changed files
id: changed-files
uses: tj-actions/changed-files@v47
uses: tj-actions/changed-files@22103cc46bda19c2b464ffe86db46df6922fd323 # v47.0.5
with:
files: |
web/**
.github/workflows/style.yml
.github/actions/setup-web/**
- name: Install pnpm
uses: pnpm/action-setup@v4
with:
package_json_file: web/package.json
run_install: false
- name: Setup NodeJS
uses: actions/setup-node@v6
- name: Setup web environment
if: steps.changed-files.outputs.any_changed == 'true'
with:
node-version: 22
cache: pnpm
cache-dependency-path: ./web/pnpm-lock.yaml
- name: Web dependencies
if: steps.changed-files.outputs.any_changed == 'true'
working-directory: ./web
run: pnpm install --frozen-lockfile
uses: ./.github/actions/setup-web
- name: Web style check
if: steps.changed-files.outputs.any_changed == 'true'
@ -134,14 +120,14 @@ jobs:
steps:
- name: Checkout code
uses: actions/checkout@v6
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 0
persist-credentials: false
- name: Check changed files
id: changed-files
uses: tj-actions/changed-files@v47
uses: tj-actions/changed-files@22103cc46bda19c2b464ffe86db46df6922fd323 # v47.0.5
with:
files: |
**.sh
@ -152,7 +138,7 @@ jobs:
.editorconfig
- name: Super-linter
uses: super-linter/super-linter/slim@v8
uses: super-linter/super-linter/slim@61abc07d755095a68f4987d1c2c3d1d64408f1f9 # v8.5.0
if: steps.changed-files.outputs.any_changed == 'true'
env:
BASH_SEVERITY: warning

View File

@ -21,12 +21,12 @@ jobs:
working-directory: sdks/nodejs-client
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- name: Use Node.js
uses: actions/setup-node@v6
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
with:
node-version: 22
cache: ''

View File

@ -38,7 +38,7 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v6
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 0
token: ${{ secrets.GITHUB_TOKEN }}
@ -48,18 +48,10 @@ jobs:
git config --global user.name "github-actions[bot]"
git config --global user.email "github-actions[bot]@users.noreply.github.com"
- name: Install pnpm
uses: pnpm/action-setup@v4
- name: Setup web environment
uses: ./.github/actions/setup-web
with:
package_json_file: web/package.json
run_install: false
- name: Set up Node.js
uses: actions/setup-node@v6
with:
node-version: 22
cache: pnpm
cache-dependency-path: ./web/pnpm-lock.yaml
install-dependencies: "false"
- name: Detect changed files and generate diff
id: detect_changes
@ -130,7 +122,7 @@ jobs:
- name: Run Claude Code for Translation Sync
if: steps.detect_changes.outputs.CHANGED_FILES != ''
uses: anthropics/claude-code-action@v1
uses: anthropics/claude-code-action@26ec041249acb0a944c0a47b6c0c13f05dbc5b44 # v1.0.70
with:
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
github_token: ${{ secrets.GITHUB_TOKEN }}

View File

@ -21,7 +21,7 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v6
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 0
@ -59,7 +59,7 @@ jobs:
- name: Trigger i18n sync workflow
if: steps.detect.outputs.has_changes == 'true'
uses: peter-evans/repository-dispatch@v3
uses: peter-evans/repository-dispatch@28959ce8df70de7be546dd1250a005dd32156697 # v4.0.1
with:
token: ${{ secrets.GITHUB_TOKEN }}
event-type: i18n-sync

View File

@ -19,19 +19,19 @@ jobs:
steps:
- name: Checkout code
uses: actions/checkout@v6
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- name: Free Disk Space
uses: endersonmenezes/free-disk-space@v3
uses: endersonmenezes/free-disk-space@7901478139cff6e9d44df5972fd8ab8fcade4db1 # v3.2.2
with:
remove_dotnet: true
remove_haskell: true
remove_tool_cache: true
- name: Setup UV and Python
uses: astral-sh/setup-uv@v7
uses: astral-sh/setup-uv@5a095e7a2014a4212f075830d4f7277575a9d098 # v7.3.1
with:
enable-cache: true
python-version: ${{ matrix.python-version }}
@ -60,7 +60,7 @@ jobs:
# tiflash
- name: Set up Vector Stores (Weaviate, Qdrant, PGVector, Milvus, PgVecto-RS, Chroma, MyScale, ElasticSearch, Couchbase, OceanBase)
uses: hoverkraft-tech/compose-action@v2.0.2
uses: hoverkraft-tech/compose-action@4894d2492015c1774ee5a13a95b1072093087ec3 # v2.5.0
with:
compose-file: |
docker/docker-compose.yaml

View File

@ -26,32 +26,19 @@ jobs:
steps:
- name: Checkout code
uses: actions/checkout@v6
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- name: Install pnpm
uses: pnpm/action-setup@v4
with:
package_json_file: web/package.json
run_install: false
- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version: 22
cache: pnpm
cache-dependency-path: ./web/pnpm-lock.yaml
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Setup web environment
uses: ./.github/actions/setup-web
- name: Run tests
run: pnpm vitest run --reporter=blob --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }} --coverage
- name: Upload blob report
if: ${{ !cancelled() }}
uses: actions/upload-artifact@v6
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with:
name: blob-report-${{ matrix.shardIndex }}
path: web/.vitest-reports/*
@ -70,28 +57,15 @@ jobs:
steps:
- name: Checkout code
uses: actions/checkout@v6
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- name: Install pnpm
uses: pnpm/action-setup@v4
with:
package_json_file: web/package.json
run_install: false
- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version: 22
cache: pnpm
cache-dependency-path: ./web/pnpm-lock.yaml
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Setup web environment
uses: ./.github/actions/setup-web
- name: Download blob reports
uses: actions/download-artifact@v6
uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0
with:
path: web/.vitest-reports
pattern: blob-report-*
@ -419,7 +393,7 @@ jobs:
- name: Upload Coverage Artifact
if: steps.coverage-summary.outputs.has_coverage == 'true'
uses: actions/upload-artifact@v6
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with:
name: web-coverage-report
path: web/coverage
@ -435,36 +409,22 @@ jobs:
steps:
- name: Checkout code
uses: actions/checkout@v6
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- name: Check changed files
id: changed-files
uses: tj-actions/changed-files@v47
uses: tj-actions/changed-files@22103cc46bda19c2b464ffe86db46df6922fd323 # v47.0.5
with:
files: |
web/**
.github/workflows/web-tests.yml
.github/actions/setup-web/**
- name: Install pnpm
uses: pnpm/action-setup@v4
with:
package_json_file: web/package.json
run_install: false
- name: Setup NodeJS
uses: actions/setup-node@v6
- name: Setup web environment
if: steps.changed-files.outputs.any_changed == 'true'
with:
node-version: 22
cache: pnpm
cache-dependency-path: ./web/pnpm-lock.yaml
- name: Web dependencies
if: steps.changed-files.outputs.any_changed == 'true'
working-directory: ./web
run: pnpm install --frozen-lockfile
uses: ./.github/actions/setup-web
- name: Web build check
if: steps.changed-files.outputs.any_changed == 'true'

View File

@ -172,12 +172,8 @@ describe('dataset-config/card-item', () => {
const [editButton] = within(card).getAllByRole('button', { hidden: true })
await user.click(editButton)
expect(screen.getByText('Mock settings modal')).toBeInTheDocument()
await waitFor(() => {
expect(screen.getByRole('dialog')).toBeVisible()
})
fireEvent.click(screen.getByText('Save changes'))
expect(await screen.findByText('Mock settings modal')).toBeInTheDocument()
fireEvent.click(await screen.findByText('Save changes'))
await waitFor(() => {
expect(onSave).toHaveBeenCalledWith(expect.objectContaining({ name: 'Updated dataset' }))
@ -194,7 +190,7 @@ describe('dataset-config/card-item', () => {
const card = screen.getByText(dataset.name).closest('.group') as HTMLElement
const buttons = within(card).getAllByRole('button', { hidden: true })
const deleteButton = buttons[buttons.length - 1]
const deleteButton = buttons.at(-1)!
expect(deleteButton.className).not.toContain('action-btn-destructive')
@ -233,7 +229,7 @@ describe('dataset-config/card-item', () => {
await user.click(editButton)
expect(screen.getByText('Mock settings modal')).toBeInTheDocument()
const overlay = Array.from(document.querySelectorAll('[class]'))
const overlay = [...document.querySelectorAll('[class]')]
.find(element => element.className.toString().includes('bg-black/30'))
expect(overlay).toBeInTheDocument()

View File

@ -164,7 +164,7 @@ const VoiceParamConfig = ({
</div>
<div className="flex items-center gap-1">
<Listbox
value={voiceItem ?? {}}
value={voiceItem}
disabled={!languageItem}
onChange={(value: Item) => {
handleChange({

View File

@ -1,55 +1,72 @@
import type { FormType } from '../../..'
import type { CustomActionsProps } from '../actions'
import { fireEvent, render, screen } from '@testing-library/react'
import { fireEvent, render, screen, waitFor } from '@testing-library/react'
import { beforeEach, describe, expect, it, vi } from 'vitest'
import { formContext } from '../../..'
import Actions from '../actions'
const renderWithForm = ({
canSubmit,
isSubmitting,
CustomActions,
}: {
canSubmit: boolean
isSubmitting: boolean
const mockFormState = vi.hoisted(() => ({
canSubmit: true,
isSubmitting: false,
}))
vi.mock('@tanstack/react-form', async () => {
const actual = await vi.importActual<typeof import('@tanstack/react-form')>('@tanstack/react-form')
return {
...actual,
useStore: (_store: unknown, selector: (state: typeof mockFormState) => unknown) => selector(mockFormState),
}
})
type RenderWithFormOptions = {
canSubmit?: boolean
isSubmitting?: boolean
CustomActions?: (props: CustomActionsProps) => React.ReactNode
}) => {
const submitSpy = vi.fn()
const state = {
canSubmit,
isSubmitting,
}
onSubmit?: () => void
}
const renderWithForm = ({
canSubmit = true,
isSubmitting = false,
CustomActions,
onSubmit = vi.fn(),
}: RenderWithFormOptions = {}) => {
mockFormState.canSubmit = canSubmit
mockFormState.isSubmitting = isSubmitting
const form = {
store: {
state,
subscribe: () => () => {},
},
handleSubmit: submitSpy,
store: {},
handleSubmit: onSubmit,
}
const TestComponent = () => {
return (
<formContext.Provider value={form as unknown as FormType}>
<Actions
CustomActions={CustomActions}
/>
</formContext.Provider>
)
}
render(
<formContext.Provider value={form as unknown as FormType}>
<Actions CustomActions={CustomActions} />
</formContext.Provider>,
)
render(<TestComponent />)
return { submitSpy }
return { onSubmit }
}
describe('Actions', () => {
beforeEach(() => {
vi.clearAllMocks()
})
it('should disable submit button when form cannot submit', () => {
renderWithForm({ canSubmit: false, isSubmitting: false })
renderWithForm({ canSubmit: false })
expect(screen.getByRole('button', { name: 'common.operation.submit' })).toBeDisabled()
})
it('should call form submit when users click submit button', () => {
const { submitSpy } = renderWithForm({ canSubmit: true, isSubmitting: false })
it('should call form submit when users click submit button', async () => {
const submitSpy = vi.fn()
renderWithForm({ onSubmit: submitSpy })
fireEvent.click(screen.getByRole('button', { name: 'common.operation.submit' }))
expect(submitSpy).toHaveBeenCalledTimes(1)
await waitFor(() => {
expect(submitSpy).toHaveBeenCalledTimes(1)
})
})
it('should render custom actions when provided', () => {
@ -60,15 +77,14 @@ describe('Actions', () => {
))
renderWithForm({
canSubmit: true,
isSubmitting: true,
CustomActions: customActionsSpy,
})
expect(screen.queryByRole('button', { name: 'common.operation.submit' })).not.toBeInTheDocument()
expect(screen.getByText('custom-true-true')).toBeInTheDocument()
expect(screen.getByText('custom-false-true')).toBeInTheDocument()
expect(customActionsSpy).toHaveBeenCalledWith(expect.objectContaining({
isSubmitting: true,
form: expect.any(Object),
isSubmitting: false,
canSubmit: true,
}))
})

View File

@ -100,11 +100,11 @@ const Select: FC<ISelectProps> = ({
disabled={disabled}
value={selectedItem}
className={className}
onChange={(value: Item) => {
onChange={(value) => {
if (!disabled) {
setSelectedItem(value)
setOpen(false)
onSelect(value)
onSelect(value as Item)
}
}}
>
@ -224,10 +224,10 @@ const SimpleSelect: FC<ISelectProps> = ({
<Listbox
ref={listboxRef}
value={selectedItem}
onChange={(value: Item) => {
onChange={(value) => {
if (!disabled) {
setSelectedItem(value)
onSelect(value)
onSelect(value as Item)
}
}}
>

View File

@ -1,4 +1,5 @@
import { act, fireEvent, render, screen, waitFor } from '@testing-library/react'
import { act, render, screen, waitFor } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import SVGRenderer from '..'
const mockClick = vi.fn()
@ -117,6 +118,7 @@ describe('SVGRenderer', () => {
})
it('closes image preview on cancel', async () => {
const user = userEvent.setup()
render(<SVGRenderer content={validSvg} />)
await waitFor(() => {
@ -129,9 +131,11 @@ describe('SVGRenderer', () => {
expect(screen.getByAltText('Preview')).toBeInTheDocument()
fireEvent.keyDown(document, { key: 'Escape' })
await user.click(screen.getByTestId('image-preview-close-button'))
expect(screen.queryByAltText('Preview')).not.toBeInTheDocument()
await waitFor(() => {
expect(screen.queryByAltText('Preview')).not.toBeInTheDocument()
})
})
})
})

View File

@ -1,4 +1,5 @@
import { act, cleanup, fireEvent, render, screen, waitFor } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import Operations from '../operations'
@ -355,16 +356,14 @@ describe('Operations', () => {
})
it('should show rename modal when rename is clicked', async () => {
const user = userEvent.setup()
render(<Operations {...defaultProps} />)
await openPopover()
const renameButton = screen.getByText('datasetDocuments.list.table.rename')
await act(async () => {
fireEvent.click(renameButton)
})
// Rename modal should be shown
await waitFor(() => {
expect(screen.getByDisplayValue('Test Document')).toBeInTheDocument()
})
const renameAction = screen.getByText('datasetDocuments.list.table.rename').parentElement as HTMLElement
await user.click(renameAction)
const renameInput = await screen.findByRole('textbox')
expect(renameInput).toHaveValue('Test Document')
})
it('should call sync for notion data source', async () => {

View File

@ -5,6 +5,7 @@ import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { render, screen, waitFor } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import { beforeEach, describe, expect, it, vi } from 'vitest'
import { ToastContext } from '@/app/components/base/toast/context'
import { ProcessMode } from '@/models/datasets'
import * as datasetsService from '@/service/datasets'
import * as useDataset from '@/service/knowledge/use-dataset'
@ -13,8 +14,22 @@ import { IndexingType } from '../../../../create/step-two'
import { DocumentContext } from '../../context'
import EmbeddingDetail from '../index'
const { mockNotify, mockClose } = vi.hoisted(() => ({
mockNotify: vi.fn(),
mockClose: vi.fn(),
}))
vi.mock('@/service/datasets')
vi.mock('@/service/knowledge/use-dataset')
vi.mock('@/app/components/base/toast/context', async () => {
const { createContext } = await vi.importActual<typeof import('use-context-selector')>('use-context-selector')
return {
ToastContext: createContext({
notify: mockNotify,
close: mockClose,
}),
}
})
const mockFetchIndexingStatus = vi.mocked(datasetsService.fetchIndexingStatus)
const mockPauseDocIndexing = vi.mocked(datasetsService.pauseDocIndexing)
@ -32,9 +47,11 @@ const createWrapper = (contextValue: DocumentContextValue = { datasetId: 'ds1',
const queryClient = createTestQueryClient()
return ({ children }: { children: ReactNode }) => (
<QueryClientProvider client={queryClient}>
<DocumentContext.Provider value={contextValue}>
{children}
</DocumentContext.Provider>
<ToastContext.Provider value={{ notify: mockNotify, close: vi.fn() }}>
<DocumentContext.Provider value={contextValue}>
{children}
</DocumentContext.Provider>
</ToastContext.Provider>
</QueryClientProvider>
)
}

File diff suppressed because it is too large Load Diff

View File

@ -15,12 +15,24 @@ const config: KnipConfig = {
ignoreBinaries: [
'only-allow',
],
ignoreDependencies: [],
ignoreDependencies: [
'@iconify-json/*',
'@storybook/addon-onboarding',
// vinext related
'react-server-dom-webpack',
'@vitejs/plugin-rsc',
'@mdx-js/rollup',
'@tsslint/compat-eslint',
'@tsslint/config',
],
rules: {
files: 'warn',
dependencies: 'warn',
devDependencies: 'warn',
optionalPeerDependencies: 'warn',
dependencies: 'error',
devDependencies: 'error',
optionalPeerDependencies: 'error',
unlisted: 'warn',
unresolved: 'warn',
exports: 'warn',

View File

@ -3,7 +3,7 @@
"type": "module",
"version": "1.13.0",
"private": true,
"packageManager": "pnpm@10.27.0",
"packageManager": "pnpm@10.31.0",
"imports": {
"#i18n": {
"react-server": "./i18n-config/lib.server.ts",
@ -61,13 +61,13 @@
"knip": "knip"
},
"dependencies": {
"@amplitude/analytics-browser": "2.33.1",
"@amplitude/plugin-session-replay-browser": "1.23.6",
"@amplitude/analytics-browser": "2.36.2",
"@amplitude/plugin-session-replay-browser": "1.25.20",
"@base-ui/react": "1.2.0",
"@emoji-mart/data": "1.2.1",
"@floating-ui/react": "0.26.28",
"@formatjs/intl-localematcher": "0.5.10",
"@headlessui/react": "2.2.1",
"@floating-ui/react": "0.27.19",
"@formatjs/intl-localematcher": "0.8.1",
"@headlessui/react": "2.2.9",
"@heroicons/react": "2.2.0",
"@lexical/code": "0.41.0",
"@lexical/link": "0.41.0",
@ -77,68 +77,68 @@
"@lexical/text": "0.41.0",
"@lexical/utils": "0.41.0",
"@monaco-editor/react": "4.7.0",
"@octokit/core": "6.1.6",
"@octokit/request-error": "6.1.8",
"@octokit/core": "7.0.6",
"@octokit/request-error": "7.1.0",
"@orpc/client": "1.13.6",
"@orpc/contract": "1.13.6",
"@orpc/openapi-client": "1.13.6",
"@orpc/tanstack-query": "1.13.6",
"@remixicon/react": "4.7.0",
"@sentry/react": "8.55.0",
"@remixicon/react": "4.9.0",
"@sentry/react": "10.42.0",
"@svgdotjs/svg.js": "3.2.5",
"@t3-oss/env-nextjs": "0.13.10",
"@tailwindcss/typography": "0.5.19",
"@tanstack/react-form": "1.23.7",
"@tanstack/react-query": "5.90.5",
"abcjs": "6.5.2",
"ahooks": "3.9.5",
"@tanstack/react-form": "1.28.4",
"@tanstack/react-query": "5.90.21",
"abcjs": "6.6.2",
"ahooks": "3.9.6",
"class-variance-authority": "0.7.1",
"clsx": "2.1.1",
"cmdk": "1.1.1",
"copy-to-clipboard": "3.3.3",
"cron-parser": "5.4.0",
"cron-parser": "5.5.0",
"dayjs": "1.11.19",
"decimal.js": "10.6.0",
"dompurify": "3.3.2",
"echarts": "5.6.0",
"echarts-for-react": "3.0.5",
"elkjs": "0.9.3",
"echarts": "6.0.0",
"echarts-for-react": "3.0.6",
"elkjs": "0.11.1",
"embla-carousel-autoplay": "8.6.0",
"embla-carousel-react": "8.6.0",
"emoji-mart": "5.6.0",
"es-toolkit": "1.43.0",
"es-toolkit": "1.45.1",
"fast-deep-equal": "3.1.3",
"foxact": "0.2.52",
"foxact": "0.2.54",
"html-entities": "2.6.0",
"html-to-image": "1.11.13",
"i18next": "25.7.3",
"i18next": "25.8.16",
"i18next-resources-to-backend": "1.2.1",
"immer": "11.1.0",
"jotai": "2.16.1",
"immer": "11.1.4",
"jotai": "2.18.0",
"js-audio-recorder": "1.0.7",
"js-cookie": "3.0.5",
"js-yaml": "4.1.1",
"jsonschema": "1.5.0",
"katex": "0.16.25",
"katex": "0.16.38",
"ky": "1.12.0",
"lamejs": "1.2.1",
"lexical": "0.41.0",
"mermaid": "11.11.0",
"mermaid": "11.13.0",
"mime": "4.1.0",
"mitt": "3.0.1",
"negotiator": "1.0.0",
"next": "16.1.5",
"next": "16.1.6",
"next-themes": "0.4.6",
"nuqs": "2.8.6",
"pinyin-pro": "3.27.0",
"nuqs": "2.8.9",
"pinyin-pro": "3.28.0",
"qrcode.react": "4.2.0",
"qs": "6.14.2",
"qs": "6.15.0",
"react": "19.2.4",
"react-18-input-autosize": "3.0.0",
"react-dom": "19.2.4",
"react-easy-crop": "5.5.3",
"react-hotkeys-hook": "4.6.2",
"react-i18next": "16.5.0",
"react-easy-crop": "5.5.6",
"react-hotkeys-hook": "5.2.4",
"react-i18next": "16.5.6",
"react-markdown": "9.1.0",
"react-multi-email": "1.0.25",
"react-papaparse": "4.4.0",
@ -155,44 +155,44 @@
"remark-gfm": "4.0.1",
"remark-math": "6.0.0",
"scheduler": "0.27.0",
"semver": "7.7.3",
"sharp": "0.33.5",
"sortablejs": "1.15.6",
"semver": "7.7.4",
"sharp": "0.34.5",
"sortablejs": "1.15.7",
"string-ts": "2.3.1",
"tailwind-merge": "2.6.1",
"tldts": "7.0.17",
"tldts": "7.0.25",
"use-context-selector": "2.0.0",
"uuid": "10.0.0",
"uuid": "13.0.0",
"zod": "4.3.6",
"zundo": "2.3.0",
"zustand": "5.0.9"
"zustand": "5.0.11"
},
"devDependencies": {
"@antfu/eslint-config": "7.6.1",
"@antfu/eslint-config": "7.7.0",
"@chromatic-com/storybook": "5.0.1",
"@egoist/tailwindcss-icons": "1.9.2",
"@eslint-react/eslint-plugin": "2.13.0",
"@iconify-json/heroicons": "1.2.3",
"@iconify-json/ri": "1.2.9",
"@iconify-json/ri": "1.2.10",
"@mdx-js/loader": "3.1.1",
"@mdx-js/react": "3.1.1",
"@mdx-js/rollup": "3.1.1",
"@next/eslint-plugin-next": "16.1.6",
"@next/mdx": "16.1.5",
"@next/mdx": "16.1.6",
"@rgrove/parse-xml": "4.2.0",
"@storybook/addon-docs": "10.2.13",
"@storybook/addon-links": "10.2.13",
"@storybook/addon-onboarding": "10.2.13",
"@storybook/addon-themes": "10.2.13",
"@storybook/nextjs-vite": "10.2.13",
"@storybook/react": "10.2.13",
"@storybook/addon-docs": "10.2.16",
"@storybook/addon-links": "10.2.16",
"@storybook/addon-onboarding": "10.2.16",
"@storybook/addon-themes": "10.2.16",
"@storybook/nextjs-vite": "10.2.16",
"@storybook/react": "10.2.16",
"@tanstack/eslint-plugin-query": "5.91.4",
"@tanstack/react-devtools": "0.9.2",
"@tanstack/react-form-devtools": "0.2.12",
"@tanstack/react-query-devtools": "5.90.2",
"@tanstack/react-devtools": "0.9.10",
"@tanstack/react-form-devtools": "0.2.17",
"@tanstack/react-query-devtools": "5.91.3",
"@testing-library/dom": "10.4.1",
"@testing-library/jest-dom": "6.9.1",
"@testing-library/react": "16.3.0",
"@testing-library/react": "16.3.2",
"@testing-library/user-event": "14.6.1",
"@tsslint/cli": "3.0.2",
"@tsslint/compat-eslint": "3.0.2",
@ -200,51 +200,49 @@
"@types/js-cookie": "3.0.6",
"@types/js-yaml": "4.0.9",
"@types/negotiator": "0.6.4",
"@types/node": "24.10.12",
"@types/node": "25.3.5",
"@types/postcss-js": "4.1.0",
"@types/qs": "6.14.0",
"@types/react": "19.2.9",
"@types/qs": "6.15.0",
"@types/react": "19.2.14",
"@types/react-dom": "19.2.3",
"@types/react-slider": "1.3.6",
"@types/react-syntax-highlighter": "15.5.13",
"@types/react-window": "1.8.8",
"@types/semver": "7.7.1",
"@types/sortablejs": "1.15.8",
"@types/uuid": "10.0.0",
"@types/sortablejs": "1.15.9",
"@typescript-eslint/parser": "8.56.1",
"@typescript/native-preview": "7.0.0-dev.20251209.1",
"@typescript/native-preview": "7.0.0-dev.20260309.1",
"@vitejs/plugin-react": "5.1.4",
"@vitejs/plugin-rsc": "0.5.21",
"@vitest/coverage-v8": "4.0.18",
"agentation": "2.3.0",
"autoprefixer": "10.4.21",
"code-inspector-plugin": "1.4.2",
"cross-env": "10.1.0",
"eslint": "10.0.2",
"eslint-plugin-better-tailwindcss": "https://pkg.pr.new/hyoban/eslint-plugin-better-tailwindcss@a520d15",
"eslint-plugin-hyoban": "0.11.2",
"autoprefixer": "10.4.27",
"code-inspector-plugin": "1.4.4",
"eslint": "10.0.3",
"eslint-plugin-better-tailwindcss": "4.3.2",
"eslint-plugin-hyoban": "0.14.1",
"eslint-plugin-react-hooks": "7.0.1",
"eslint-plugin-react-refresh": "0.5.2",
"eslint-plugin-sonarjs": "4.0.0",
"eslint-plugin-storybook": "10.2.13",
"eslint-plugin-sonarjs": "4.0.1",
"eslint-plugin-storybook": "10.2.16",
"husky": "9.1.7",
"iconify-import-svg": "0.1.2",
"jsdom": "27.3.0",
"jsdom": "28.1.0",
"jsdom-testing-mocks": "1.16.0",
"knip": "5.78.0",
"lint-staged": "15.5.2",
"nock": "14.0.10",
"postcss": "8.5.6",
"postcss-js": "5.0.3",
"knip": "5.86.0",
"lint-staged": "16.3.2",
"nock": "14.0.11",
"postcss": "8.5.8",
"postcss-js": "5.1.0",
"react-server-dom-webpack": "19.2.4",
"sass": "1.93.2",
"storybook": "10.2.13",
"sass": "1.97.3",
"storybook": "10.2.16",
"tailwindcss": "3.4.19",
"tsx": "4.21.0",
"typescript": "5.9.3",
"uglify-js": "3.19.3",
"vinext": "https://pkg.pr.new/vinext@1a2fd61",
"vite": "8.0.0-beta.16",
"vite": "8.0.0-beta.18",
"vite-plugin-inspect": "11.3.3",
"vite-tsconfig-paths": "6.1.1",
"vitest": "4.0.18",
@ -253,50 +251,48 @@
"pnpm": {
"overrides": {
"@lexical/code": "npm:lexical-code-no-prism@0.41.0",
"@monaco-editor/loader": "1.5.0",
"@monaco-editor/loader": "1.7.0",
"@nolyfill/safe-buffer": "npm:safe-buffer@^5.2.1",
"@stylistic/eslint-plugin": "https://pkg.pr.new/@stylistic/eslint-plugin@258f9d8",
"array-includes": "npm:@nolyfill/array-includes@^1",
"array.prototype.findlast": "npm:@nolyfill/array.prototype.findlast@^1",
"array.prototype.findlastindex": "npm:@nolyfill/array.prototype.findlastindex@^1",
"array.prototype.flat": "npm:@nolyfill/array.prototype.flat@^1",
"array.prototype.flatmap": "npm:@nolyfill/array.prototype.flatmap@^1",
"array.prototype.tosorted": "npm:@nolyfill/array.prototype.tosorted@^1",
"assert": "npm:@nolyfill/assert@^1",
"brace-expansion": "~2.0",
"array-includes": "npm:@nolyfill/array-includes@^1.0.44",
"array.prototype.findlast": "npm:@nolyfill/array.prototype.findlast@^1.0.44",
"array.prototype.findlastindex": "npm:@nolyfill/array.prototype.findlastindex@^1.0.44",
"array.prototype.flat": "npm:@nolyfill/array.prototype.flat@^1.0.44",
"array.prototype.flatmap": "npm:@nolyfill/array.prototype.flatmap@^1.0.44",
"array.prototype.tosorted": "npm:@nolyfill/array.prototype.tosorted@^1.0.44",
"assert": "npm:@nolyfill/assert@^1.0.26",
"brace-expansion@<2.0.2": "2.0.2",
"canvas": "^3.2.0",
"canvas": "^3.2.1",
"devalue@<5.3.2": "5.3.2",
"es-iterator-helpers": "npm:@nolyfill/es-iterator-helpers@^1",
"es-iterator-helpers": "npm:@nolyfill/es-iterator-helpers@^1.0.21",
"esbuild@<0.27.2": "0.27.2",
"glob@>=10.2.0,<10.5.0": "11.1.0",
"hasown": "npm:@nolyfill/hasown@^1",
"is-arguments": "npm:@nolyfill/is-arguments@^1",
"is-core-module": "npm:@nolyfill/is-core-module@^1",
"is-generator-function": "npm:@nolyfill/is-generator-function@^1",
"is-typed-array": "npm:@nolyfill/is-typed-array@^1",
"isarray": "npm:@nolyfill/isarray@^1",
"object.assign": "npm:@nolyfill/object.assign@^1",
"object.entries": "npm:@nolyfill/object.entries@^1",
"object.fromentries": "npm:@nolyfill/object.fromentries@^1",
"object.groupby": "npm:@nolyfill/object.groupby@^1",
"object.values": "npm:@nolyfill/object.values@^1",
"pbkdf2": "~3.1.3",
"hasown": "npm:@nolyfill/hasown@^1.0.44",
"is-arguments": "npm:@nolyfill/is-arguments@^1.0.44",
"is-core-module": "npm:@nolyfill/is-core-module@^1.0.39",
"is-generator-function": "npm:@nolyfill/is-generator-function@^1.0.44",
"is-typed-array": "npm:@nolyfill/is-typed-array@^1.0.44",
"isarray": "npm:@nolyfill/isarray@^1.0.44",
"object.assign": "npm:@nolyfill/object.assign@^1.0.44",
"object.entries": "npm:@nolyfill/object.entries@^1.0.44",
"object.fromentries": "npm:@nolyfill/object.fromentries@^1.0.44",
"object.groupby": "npm:@nolyfill/object.groupby@^1.0.44",
"object.values": "npm:@nolyfill/object.values@^1.0.44",
"pbkdf2": "~3.1.5",
"pbkdf2@<3.1.3": "3.1.3",
"prismjs": "~1.30",
"prismjs@<1.30.0": "1.30.0",
"safe-buffer": "^5.2.1",
"safe-regex-test": "npm:@nolyfill/safe-regex-test@^1",
"safer-buffer": "npm:@nolyfill/safer-buffer@^1",
"side-channel": "npm:@nolyfill/side-channel@^1",
"safe-regex-test": "npm:@nolyfill/safe-regex-test@^1.0.44",
"safer-buffer": "npm:@nolyfill/safer-buffer@^1.0.44",
"side-channel": "npm:@nolyfill/side-channel@^1.0.44",
"solid-js": "1.9.11",
"string-width": "~4.2.3",
"string.prototype.includes": "npm:@nolyfill/string.prototype.includes@^1",
"string.prototype.matchall": "npm:@nolyfill/string.prototype.matchall@^1",
"string.prototype.repeat": "npm:@nolyfill/string.prototype.repeat@^1",
"string.prototype.trimend": "npm:@nolyfill/string.prototype.trimend@^1",
"typed-array-buffer": "npm:@nolyfill/typed-array-buffer@^1",
"which-typed-array": "npm:@nolyfill/which-typed-array@^1"
"string-width": "~8.2.0",
"string.prototype.includes": "npm:@nolyfill/string.prototype.includes@^1.0.44",
"string.prototype.matchall": "npm:@nolyfill/string.prototype.matchall@^1.0.44",
"string.prototype.repeat": "npm:@nolyfill/string.prototype.repeat@^1.0.44",
"string.prototype.trimend": "npm:@nolyfill/string.prototype.trimend@^1.0.44",
"typed-array-buffer": "npm:@nolyfill/typed-array-buffer@^1.0.44",
"which-typed-array": "npm:@nolyfill/which-typed-array@^1.0.44"
},
"ignoredBuiltDependencies": [
"canvas",
@ -309,6 +305,6 @@
]
},
"lint-staged": {
"*": "eslint --fix"
"*": "eslint --fix --pass-on-unpruned-suppressions"
}
}

4616
web/pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@ -67,10 +67,11 @@ if (typeof globalThis.IntersectionObserver === 'undefined') {
globalThis.IntersectionObserver = class {
readonly root: Element | Document | null = null
readonly rootMargin: string = ''
readonly scrollMargin: string = ''
readonly thresholds: ReadonlyArray<number> = []
constructor(_callback: IntersectionObserverCallback, _options?: IntersectionObserverInit) { /* noop */ }
observe() { /* noop */ }
unobserve() { /* noop */ }
observe(_target: Element) { /* noop */ }
unobserve(_target: Element) { /* noop */ }
disconnect() { /* noop */ }
takeRecords(): IntersectionObserverEntry[] { return [] }
}