mirror of
https://github.com/langgenius/dify.git
synced 2026-03-30 12:26:51 +00:00
Compare commits
1 Commits
main
...
dependabot
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d7e33788be |
1
.github/actions/setup-web/action.yml
vendored
1
.github/actions/setup-web/action.yml
vendored
@@ -6,6 +6,7 @@ runs:
|
||||
- name: Setup Vite+
|
||||
uses: voidzero-dev/setup-vp@20553a7a7429c429a74894104a2835d7fed28a72 # v1.3.0
|
||||
with:
|
||||
working-directory: web
|
||||
node-version-file: .nvmrc
|
||||
cache: true
|
||||
run-install: true
|
||||
|
||||
4
.github/workflows/autofix.yml
vendored
4
.github/workflows/autofix.yml
vendored
@@ -39,10 +39,6 @@ jobs:
|
||||
with:
|
||||
files: |
|
||||
web/**
|
||||
package.json
|
||||
pnpm-lock.yaml
|
||||
pnpm-workspace.yaml
|
||||
.nvmrc
|
||||
- name: Check api inputs
|
||||
if: github.event_name != 'merge_group'
|
||||
id: api-changes
|
||||
|
||||
30
.github/workflows/build-push.yml
vendored
30
.github/workflows/build-push.yml
vendored
@@ -24,39 +24,27 @@ env:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ${{ matrix.runs_on }}
|
||||
runs-on: ${{ matrix.platform == 'linux/arm64' && 'arm64_runner' || 'ubuntu-latest' }}
|
||||
if: github.repository == 'langgenius/dify'
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- service_name: "build-api-amd64"
|
||||
image_name_env: "DIFY_API_IMAGE_NAME"
|
||||
artifact_context: "api"
|
||||
build_context: "{{defaultContext}}:api"
|
||||
file: "Dockerfile"
|
||||
context: "api"
|
||||
platform: linux/amd64
|
||||
runs_on: ubuntu-latest
|
||||
- service_name: "build-api-arm64"
|
||||
image_name_env: "DIFY_API_IMAGE_NAME"
|
||||
artifact_context: "api"
|
||||
build_context: "{{defaultContext}}:api"
|
||||
file: "Dockerfile"
|
||||
context: "api"
|
||||
platform: linux/arm64
|
||||
runs_on: ubuntu-24.04-arm
|
||||
- service_name: "build-web-amd64"
|
||||
image_name_env: "DIFY_WEB_IMAGE_NAME"
|
||||
artifact_context: "web"
|
||||
build_context: "{{defaultContext}}"
|
||||
file: "web/Dockerfile"
|
||||
context: "web"
|
||||
platform: linux/amd64
|
||||
runs_on: ubuntu-latest
|
||||
- service_name: "build-web-arm64"
|
||||
image_name_env: "DIFY_WEB_IMAGE_NAME"
|
||||
artifact_context: "web"
|
||||
build_context: "{{defaultContext}}"
|
||||
file: "web/Dockerfile"
|
||||
context: "web"
|
||||
platform: linux/arm64
|
||||
runs_on: ubuntu-24.04-arm
|
||||
|
||||
steps:
|
||||
- name: Prepare
|
||||
@@ -70,6 +58,9 @@ jobs:
|
||||
username: ${{ env.DOCKERHUB_USER }}
|
||||
password: ${{ env.DOCKERHUB_TOKEN }}
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a # v4.0.0
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
|
||||
|
||||
@@ -83,8 +74,7 @@ jobs:
|
||||
id: build
|
||||
uses: docker/build-push-action@d08e5c354a6adb9ed34480a06d141179aa583294 # v7.0.0
|
||||
with:
|
||||
context: ${{ matrix.build_context }}
|
||||
file: ${{ matrix.file }}
|
||||
context: "{{defaultContext}}:${{ matrix.context }}"
|
||||
platforms: ${{ matrix.platform }}
|
||||
build-args: COMMIT_SHA=${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.revision'] }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
@@ -103,7 +93,7 @@ jobs:
|
||||
- name: Upload digest
|
||||
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
|
||||
with:
|
||||
name: digests-${{ matrix.artifact_context }}-${{ env.PLATFORM_PAIR }}
|
||||
name: digests-${{ matrix.context }}-${{ env.PLATFORM_PAIR }}
|
||||
path: /tmp/digests/*
|
||||
if-no-files-found: error
|
||||
retention-days: 1
|
||||
|
||||
30
.github/workflows/docker-build.yml
vendored
30
.github/workflows/docker-build.yml
vendored
@@ -6,12 +6,7 @@ on:
|
||||
- "main"
|
||||
paths:
|
||||
- api/Dockerfile
|
||||
- web/docker/**
|
||||
- web/Dockerfile
|
||||
- package.json
|
||||
- pnpm-lock.yaml
|
||||
- pnpm-workspace.yaml
|
||||
- .nvmrc
|
||||
|
||||
concurrency:
|
||||
group: docker-build-${{ github.head_ref || github.run_id }}
|
||||
@@ -19,31 +14,26 @@ concurrency:
|
||||
|
||||
jobs:
|
||||
build-docker:
|
||||
runs-on: ${{ matrix.runs_on }}
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- service_name: "api-amd64"
|
||||
platform: linux/amd64
|
||||
runs_on: ubuntu-latest
|
||||
context: "{{defaultContext}}:api"
|
||||
file: "Dockerfile"
|
||||
context: "api"
|
||||
- service_name: "api-arm64"
|
||||
platform: linux/arm64
|
||||
runs_on: ubuntu-24.04-arm
|
||||
context: "{{defaultContext}}:api"
|
||||
file: "Dockerfile"
|
||||
context: "api"
|
||||
- service_name: "web-amd64"
|
||||
platform: linux/amd64
|
||||
runs_on: ubuntu-latest
|
||||
context: "{{defaultContext}}"
|
||||
file: "web/Dockerfile"
|
||||
context: "web"
|
||||
- service_name: "web-arm64"
|
||||
platform: linux/arm64
|
||||
runs_on: ubuntu-24.04-arm
|
||||
context: "{{defaultContext}}"
|
||||
file: "web/Dockerfile"
|
||||
context: "web"
|
||||
steps:
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a # v4.0.0
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
|
||||
|
||||
@@ -51,8 +41,8 @@ jobs:
|
||||
uses: docker/build-push-action@d08e5c354a6adb9ed34480a06d141179aa583294 # v7.0.0
|
||||
with:
|
||||
push: false
|
||||
context: ${{ matrix.context }}
|
||||
file: ${{ matrix.file }}
|
||||
context: "{{defaultContext}}:${{ matrix.context }}"
|
||||
file: "${{ matrix.file }}"
|
||||
platforms: ${{ matrix.platform }}
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
|
||||
8
.github/workflows/main-ci.yml
vendored
8
.github/workflows/main-ci.yml
vendored
@@ -65,10 +65,6 @@ jobs:
|
||||
- 'docker/volumes/sandbox/conf/**'
|
||||
web:
|
||||
- 'web/**'
|
||||
- 'package.json'
|
||||
- 'pnpm-lock.yaml'
|
||||
- 'pnpm-workspace.yaml'
|
||||
- '.nvmrc'
|
||||
- '.github/workflows/web-tests.yml'
|
||||
- '.github/actions/setup-web/**'
|
||||
e2e:
|
||||
@@ -77,10 +73,6 @@ jobs:
|
||||
- 'api/uv.lock'
|
||||
- 'e2e/**'
|
||||
- 'web/**'
|
||||
- 'package.json'
|
||||
- 'pnpm-lock.yaml'
|
||||
- 'pnpm-workspace.yaml'
|
||||
- '.nvmrc'
|
||||
- 'docker/docker-compose.middleware.yaml'
|
||||
- 'docker/middleware.env.example'
|
||||
- '.github/workflows/web-e2e.yml'
|
||||
|
||||
8
.github/workflows/style.yml
vendored
8
.github/workflows/style.yml
vendored
@@ -77,10 +77,6 @@ jobs:
|
||||
with:
|
||||
files: |
|
||||
web/**
|
||||
package.json
|
||||
pnpm-lock.yaml
|
||||
pnpm-workspace.yaml
|
||||
.nvmrc
|
||||
.github/workflows/style.yml
|
||||
.github/actions/setup-web/**
|
||||
|
||||
@@ -94,9 +90,9 @@ jobs:
|
||||
uses: actions/cache/restore@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4
|
||||
with:
|
||||
path: web/.eslintcache
|
||||
key: ${{ runner.os }}-web-eslint-${{ hashFiles('web/package.json', 'pnpm-lock.yaml', 'web/eslint.config.mjs', 'web/eslint.constants.mjs', 'web/plugins/eslint/**') }}-${{ github.sha }}
|
||||
key: ${{ runner.os }}-web-eslint-${{ hashFiles('web/package.json', 'web/pnpm-lock.yaml', 'web/eslint.config.mjs', 'web/eslint.constants.mjs', 'web/plugins/eslint/**') }}-${{ github.sha }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-web-eslint-${{ hashFiles('web/package.json', 'pnpm-lock.yaml', 'web/eslint.config.mjs', 'web/eslint.constants.mjs', 'web/plugins/eslint/**') }}-
|
||||
${{ runner.os }}-web-eslint-${{ hashFiles('web/package.json', 'web/pnpm-lock.yaml', 'web/eslint.config.mjs', 'web/eslint.constants.mjs', 'web/plugins/eslint/**') }}-
|
||||
|
||||
- name: Web style check
|
||||
if: steps.changed-files.outputs.any_changed == 'true'
|
||||
|
||||
3
.github/workflows/tool-test-sdks.yaml
vendored
3
.github/workflows/tool-test-sdks.yaml
vendored
@@ -6,9 +6,6 @@ on:
|
||||
- main
|
||||
paths:
|
||||
- sdks/**
|
||||
- package.json
|
||||
- pnpm-lock.yaml
|
||||
- pnpm-workspace.yaml
|
||||
|
||||
concurrency:
|
||||
group: sdk-tests-${{ github.head_ref || github.run_id }}
|
||||
|
||||
4
.github/workflows/web-e2e.yml
vendored
4
.github/workflows/web-e2e.yml
vendored
@@ -27,6 +27,10 @@ jobs:
|
||||
- name: Setup web dependencies
|
||||
uses: ./.github/actions/setup-web
|
||||
|
||||
- name: Install E2E package dependencies
|
||||
working-directory: ./e2e
|
||||
run: vp install --frozen-lockfile
|
||||
|
||||
- name: Setup UV and Python
|
||||
uses: astral-sh/setup-uv@cec208311dfd045dd5311c1add060b2062131d57 # v8.0.0
|
||||
with:
|
||||
|
||||
31
.github/workflows/web-tests.yml
vendored
31
.github/workflows/web-tests.yml
vendored
@@ -89,3 +89,34 @@ jobs:
|
||||
flags: web
|
||||
env:
|
||||
CODECOV_TOKEN: ${{ env.CODECOV_TOKEN }}
|
||||
|
||||
web-build:
|
||||
name: Web Build
|
||||
runs-on: ubuntu-latest
|
||||
defaults:
|
||||
run:
|
||||
working-directory: ./web
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Check changed files
|
||||
id: changed-files
|
||||
uses: tj-actions/changed-files@22103cc46bda19c2b464ffe86db46df6922fd323 # v47.0.5
|
||||
with:
|
||||
files: |
|
||||
web/**
|
||||
.github/workflows/web-tests.yml
|
||||
.github/actions/setup-web/**
|
||||
|
||||
- name: Setup web environment
|
||||
if: steps.changed-files.outputs.any_changed == 'true'
|
||||
uses: ./.github/actions/setup-web
|
||||
|
||||
- name: Web build check
|
||||
if: steps.changed-files.outputs.any_changed == 'true'
|
||||
working-directory: ./web
|
||||
run: vp run build
|
||||
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -212,7 +212,6 @@ api/.vscode
|
||||
|
||||
# pnpm
|
||||
/.pnpm-store
|
||||
/node_modules
|
||||
|
||||
# plugin migrate
|
||||
plugins.jsonl
|
||||
@@ -240,4 +239,4 @@ scripts/stress-test/reports/
|
||||
*.local.md
|
||||
|
||||
# Code Agent Folder
|
||||
.qoder/*
|
||||
.qoder/*
|
||||
6
Makefile
6
Makefile
@@ -24,8 +24,8 @@ prepare-docker:
|
||||
# Step 2: Prepare web environment
|
||||
prepare-web:
|
||||
@echo "🌐 Setting up web environment..."
|
||||
@cp -n web/.env.example web/.env.local 2>/dev/null || echo "Web .env.local already exists"
|
||||
@pnpm install
|
||||
@cp -n web/.env.example web/.env 2>/dev/null || echo "Web .env already exists"
|
||||
@cd web && pnpm install
|
||||
@echo "✅ Web environment prepared (not started)"
|
||||
|
||||
# Step 3: Prepare API environment
|
||||
@@ -93,7 +93,7 @@ test:
|
||||
# Build Docker images
|
||||
build-web:
|
||||
@echo "Building web Docker image: $(WEB_IMAGE):$(VERSION)..."
|
||||
docker build -f web/Dockerfile -t $(WEB_IMAGE):$(VERSION) .
|
||||
docker build -t $(WEB_IMAGE):$(VERSION) ./web
|
||||
@echo "Web Docker image built successfully: $(WEB_IMAGE):$(VERSION)"
|
||||
|
||||
build-api:
|
||||
|
||||
@@ -40,8 +40,6 @@ The scripts resolve paths relative to their location, so you can run them from a
|
||||
./dev/start-web
|
||||
```
|
||||
|
||||
`./dev/setup` and `./dev/start-web` install JavaScript dependencies through the repository root workspace, so you do not need a separate `cd web && pnpm install` step.
|
||||
|
||||
1. Set up your application by visiting `http://localhost:3000`.
|
||||
|
||||
1. Start the worker service (async and scheduler tasks, runs from `api`).
|
||||
|
||||
@@ -29,31 +29,6 @@ from services.entities.knowledge_entities.knowledge_entities import SegmentUpdat
|
||||
from services.errors.chunk import ChildChunkDeleteIndexError, ChildChunkIndexingError
|
||||
from services.errors.chunk import ChildChunkDeleteIndexError as ChildChunkDeleteIndexServiceError
|
||||
from services.errors.chunk import ChildChunkIndexingError as ChildChunkIndexingServiceError
|
||||
from services.summary_index_service import SummaryIndexService
|
||||
|
||||
|
||||
def _marshal_segment_with_summary(segment, dataset_id: str) -> dict:
|
||||
"""Marshal a single segment and enrich it with summary content."""
|
||||
segment_dict = dict(marshal(segment, segment_fields)) # type: ignore[arg-type]
|
||||
summary = SummaryIndexService.get_segment_summary(segment_id=segment.id, dataset_id=dataset_id)
|
||||
segment_dict["summary"] = summary.summary_content if summary else None
|
||||
return segment_dict
|
||||
|
||||
|
||||
def _marshal_segments_with_summary(segments, dataset_id: str) -> list[dict]:
|
||||
"""Marshal multiple segments and enrich them with summary content (batch query)."""
|
||||
segment_ids = [segment.id for segment in segments]
|
||||
summaries: dict = {}
|
||||
if segment_ids:
|
||||
summary_records = SummaryIndexService.get_segments_summaries(segment_ids=segment_ids, dataset_id=dataset_id)
|
||||
summaries = {chunk_id: record.summary_content for chunk_id, record in summary_records.items()}
|
||||
|
||||
result = []
|
||||
for segment in segments:
|
||||
segment_dict = dict(marshal(segment, segment_fields)) # type: ignore[arg-type]
|
||||
segment_dict["summary"] = summaries.get(segment.id)
|
||||
result.append(segment_dict)
|
||||
return result
|
||||
|
||||
|
||||
class SegmentCreatePayload(BaseModel):
|
||||
@@ -157,7 +132,7 @@ class SegmentApi(DatasetApiResource):
|
||||
for args_item in payload.segments:
|
||||
SegmentService.segment_create_args_validate(args_item, document)
|
||||
segments = SegmentService.multi_create_segment(payload.segments, document, dataset)
|
||||
return {"data": _marshal_segments_with_summary(segments, dataset_id), "doc_form": document.doc_form}, 200
|
||||
return {"data": marshal(segments, segment_fields), "doc_form": document.doc_form}, 200
|
||||
else:
|
||||
return {"error": "Segments is required"}, 400
|
||||
|
||||
@@ -221,7 +196,7 @@ class SegmentApi(DatasetApiResource):
|
||||
)
|
||||
|
||||
response = {
|
||||
"data": _marshal_segments_with_summary(segments, dataset_id),
|
||||
"data": marshal(segments, segment_fields),
|
||||
"doc_form": document.doc_form,
|
||||
"total": total,
|
||||
"has_more": len(segments) == limit,
|
||||
@@ -321,7 +296,7 @@ class DatasetSegmentApi(DatasetApiResource):
|
||||
payload = SegmentUpdatePayload.model_validate(service_api_ns.payload or {})
|
||||
|
||||
updated_segment = SegmentService.update_segment(payload.segment, segment, document, dataset)
|
||||
return {"data": _marshal_segment_with_summary(updated_segment, dataset_id), "doc_form": document.doc_form}, 200
|
||||
return {"data": marshal(updated_segment, segment_fields), "doc_form": document.doc_form}, 200
|
||||
|
||||
@service_api_ns.doc("get_segment")
|
||||
@service_api_ns.doc(description="Get a specific segment by ID")
|
||||
@@ -351,7 +326,7 @@ class DatasetSegmentApi(DatasetApiResource):
|
||||
if not segment:
|
||||
raise NotFound("Segment not found.")
|
||||
|
||||
return {"data": _marshal_segment_with_summary(segment, dataset_id), "doc_form": document.doc_form}, 200
|
||||
return {"data": marshal(segment, segment_fields), "doc_form": document.doc_form}, 200
|
||||
|
||||
|
||||
@service_api_ns.route(
|
||||
|
||||
@@ -72,12 +72,12 @@ dependencies = [
|
||||
"readabilipy~=0.3.0",
|
||||
"redis[hiredis]~=7.4.0",
|
||||
"resend~=2.26.0",
|
||||
"sentry-sdk[flask]~=2.55.0",
|
||||
"sentry-sdk[flask]~=2.56.0",
|
||||
"sqlalchemy~=2.0.29",
|
||||
"starlette==1.0.0",
|
||||
"tiktoken~=0.12.0",
|
||||
"transformers~=5.3.0",
|
||||
"unstructured[docx,epub,md,ppt,pptx]~=0.21.5",
|
||||
"unstructured[docx,epub,md,ppt,pptx]~=0.22.6",
|
||||
"pypandoc~=1.13",
|
||||
"yarl~=1.23.0",
|
||||
"sseclient-py~=1.9.0",
|
||||
|
||||
@@ -768,7 +768,6 @@ class TestSegmentApiGet:
|
||||
``current_account_with_tenant()`` and ``marshal``.
|
||||
"""
|
||||
|
||||
@patch("controllers.service_api.dataset.segment.SummaryIndexService")
|
||||
@patch("controllers.service_api.dataset.segment.marshal")
|
||||
@patch("controllers.service_api.dataset.segment.SegmentService")
|
||||
@patch("controllers.service_api.dataset.segment.DocumentService")
|
||||
@@ -781,7 +780,6 @@ class TestSegmentApiGet:
|
||||
mock_doc_svc,
|
||||
mock_seg_svc,
|
||||
mock_marshal,
|
||||
mock_summary_svc,
|
||||
app,
|
||||
mock_tenant,
|
||||
mock_dataset,
|
||||
@@ -793,8 +791,7 @@ class TestSegmentApiGet:
|
||||
mock_db.session.scalar.return_value = mock_dataset
|
||||
mock_doc_svc.get_document.return_value = Mock(doc_form=IndexStructureType.PARAGRAPH_INDEX)
|
||||
mock_seg_svc.get_segments.return_value = ([mock_segment], 1)
|
||||
mock_marshal.return_value = {"id": mock_segment.id}
|
||||
mock_summary_svc.get_segments_summaries.return_value = {}
|
||||
mock_marshal.return_value = [{"id": mock_segment.id}]
|
||||
|
||||
# Act
|
||||
with app.test_request_context(
|
||||
@@ -875,7 +872,6 @@ class TestSegmentApiPost:
|
||||
mock_rate_limit.enabled = False
|
||||
mock_feature_svc.get_knowledge_rate_limit.return_value = mock_rate_limit
|
||||
|
||||
@patch("controllers.service_api.dataset.segment.SummaryIndexService")
|
||||
@patch("controllers.service_api.dataset.segment.marshal")
|
||||
@patch("controllers.service_api.dataset.segment.SegmentService")
|
||||
@patch("controllers.service_api.dataset.segment.DocumentService")
|
||||
@@ -892,7 +888,6 @@ class TestSegmentApiPost:
|
||||
mock_doc_svc,
|
||||
mock_seg_svc,
|
||||
mock_marshal,
|
||||
mock_summary_svc,
|
||||
app,
|
||||
mock_tenant,
|
||||
mock_dataset,
|
||||
@@ -914,8 +909,7 @@ class TestSegmentApiPost:
|
||||
|
||||
mock_seg_svc.segment_create_args_validate.return_value = None
|
||||
mock_seg_svc.multi_create_segment.return_value = [mock_segment]
|
||||
mock_marshal.return_value = {"id": mock_segment.id}
|
||||
mock_summary_svc.get_segments_summaries.return_value = {}
|
||||
mock_marshal.return_value = [{"id": mock_segment.id}]
|
||||
|
||||
segments_data = [{"content": "Test segment content", "answer": "Test answer"}]
|
||||
|
||||
@@ -1212,7 +1206,6 @@ class TestDatasetSegmentApiUpdate:
|
||||
mock_rate_limit.enabled = False
|
||||
mock_feature_svc.get_knowledge_rate_limit.return_value = mock_rate_limit
|
||||
|
||||
@patch("controllers.service_api.dataset.segment.SummaryIndexService")
|
||||
@patch("controllers.service_api.dataset.segment.marshal")
|
||||
@patch("controllers.service_api.dataset.segment.SegmentService")
|
||||
@patch("controllers.service_api.dataset.segment.DocumentService")
|
||||
@@ -1231,7 +1224,6 @@ class TestDatasetSegmentApiUpdate:
|
||||
mock_doc_svc,
|
||||
mock_seg_svc,
|
||||
mock_marshal,
|
||||
mock_summary_svc,
|
||||
app,
|
||||
mock_tenant,
|
||||
mock_dataset,
|
||||
@@ -1248,7 +1240,6 @@ class TestDatasetSegmentApiUpdate:
|
||||
updated = Mock()
|
||||
mock_seg_svc.update_segment.return_value = updated
|
||||
mock_marshal.return_value = {"id": mock_segment.id}
|
||||
mock_summary_svc.get_segment_summary.return_value = None
|
||||
|
||||
with app.test_request_context(
|
||||
f"/datasets/{mock_dataset.id}/documents/doc-id/segments/{mock_segment.id}",
|
||||
@@ -1358,7 +1349,6 @@ class TestDatasetSegmentApiGetSingle:
|
||||
``current_account_with_tenant()`` and ``marshal``.
|
||||
"""
|
||||
|
||||
@patch("controllers.service_api.dataset.segment.SummaryIndexService")
|
||||
@patch("controllers.service_api.dataset.segment.marshal")
|
||||
@patch("controllers.service_api.dataset.segment.SegmentService")
|
||||
@patch("controllers.service_api.dataset.segment.DocumentService")
|
||||
@@ -1373,7 +1363,6 @@ class TestDatasetSegmentApiGetSingle:
|
||||
mock_doc_svc,
|
||||
mock_seg_svc,
|
||||
mock_marshal,
|
||||
mock_summary_svc,
|
||||
app,
|
||||
mock_tenant,
|
||||
mock_dataset,
|
||||
@@ -1387,7 +1376,6 @@ class TestDatasetSegmentApiGetSingle:
|
||||
mock_doc_svc.get_document.return_value = mock_doc
|
||||
mock_seg_svc.get_segment_by_id.return_value = mock_segment
|
||||
mock_marshal.return_value = {"id": mock_segment.id}
|
||||
mock_summary_svc.get_segment_summary.return_value = None
|
||||
|
||||
with app.test_request_context(
|
||||
f"/datasets/{mock_dataset.id}/documents/doc-id/segments/{mock_segment.id}",
|
||||
@@ -1405,55 +1393,6 @@ class TestDatasetSegmentApiGetSingle:
|
||||
assert "data" in response
|
||||
assert response["doc_form"] == IndexStructureType.PARAGRAPH_INDEX
|
||||
|
||||
@patch("controllers.service_api.dataset.segment.SummaryIndexService")
|
||||
@patch("controllers.service_api.dataset.segment.marshal")
|
||||
@patch("controllers.service_api.dataset.segment.SegmentService")
|
||||
@patch("controllers.service_api.dataset.segment.DocumentService")
|
||||
@patch("controllers.service_api.dataset.segment.DatasetService")
|
||||
@patch("controllers.service_api.dataset.segment.current_account_with_tenant")
|
||||
@patch("controllers.service_api.dataset.segment.db")
|
||||
def test_get_single_segment_includes_summary(
|
||||
self,
|
||||
mock_db,
|
||||
mock_account_fn,
|
||||
mock_dataset_svc,
|
||||
mock_doc_svc,
|
||||
mock_seg_svc,
|
||||
mock_marshal,
|
||||
mock_summary_svc,
|
||||
app,
|
||||
mock_tenant,
|
||||
mock_dataset,
|
||||
mock_segment,
|
||||
):
|
||||
"""Test that single segment response includes summary content from SummaryIndexService."""
|
||||
mock_account_fn.return_value = (Mock(), mock_tenant.id)
|
||||
mock_db.session.scalar.return_value = mock_dataset
|
||||
mock_dataset_svc.check_dataset_model_setting.return_value = None
|
||||
mock_doc = Mock(doc_form=IndexStructureType.PARAGRAPH_INDEX)
|
||||
mock_doc_svc.get_document.return_value = mock_doc
|
||||
mock_seg_svc.get_segment_by_id.return_value = mock_segment
|
||||
mock_marshal.return_value = {"id": mock_segment.id, "summary": None}
|
||||
|
||||
mock_summary_record = Mock()
|
||||
mock_summary_record.summary_content = "This is the segment summary"
|
||||
mock_summary_svc.get_segment_summary.return_value = mock_summary_record
|
||||
|
||||
with app.test_request_context(
|
||||
f"/datasets/{mock_dataset.id}/documents/doc-id/segments/{mock_segment.id}",
|
||||
method="GET",
|
||||
):
|
||||
api = DatasetSegmentApi()
|
||||
response, status = api.get(
|
||||
tenant_id=mock_tenant.id,
|
||||
dataset_id=mock_dataset.id,
|
||||
document_id="doc-id",
|
||||
segment_id=mock_segment.id,
|
||||
)
|
||||
|
||||
assert status == 200
|
||||
assert response["data"]["summary"] == "This is the segment summary"
|
||||
|
||||
@patch("controllers.service_api.dataset.segment.current_account_with_tenant")
|
||||
@patch("controllers.service_api.dataset.segment.db")
|
||||
def test_get_single_segment_dataset_not_found(
|
||||
|
||||
@@ -24,4 +24,5 @@ cp "$MIDDLEWARE_ENV_EXAMPLE" "$MIDDLEWARE_ENV"
|
||||
cd "$ROOT/api"
|
||||
uv sync --group dev
|
||||
|
||||
pnpm --dir "$ROOT" install
|
||||
cd "$ROOT/web"
|
||||
pnpm install
|
||||
|
||||
@@ -3,6 +3,6 @@
|
||||
set -x
|
||||
|
||||
SCRIPT_DIR="$(dirname "$(realpath "$0")")"
|
||||
ROOT_DIR="$(dirname "$SCRIPT_DIR")"
|
||||
cd "$SCRIPT_DIR/../web"
|
||||
|
||||
pnpm --dir "$ROOT_DIR" install && pnpm --dir "$ROOT_DIR/web" dev:inspect
|
||||
pnpm install && pnpm dev:inspect
|
||||
|
||||
@@ -19,18 +19,15 @@ It tests:
|
||||
- `uv`
|
||||
- Docker
|
||||
|
||||
Run the following commands from the repository root.
|
||||
|
||||
Install Playwright browsers once:
|
||||
|
||||
```bash
|
||||
cd e2e
|
||||
pnpm install
|
||||
pnpm -C e2e e2e:install
|
||||
pnpm -C e2e check
|
||||
pnpm e2e:install
|
||||
pnpm check
|
||||
```
|
||||
|
||||
`pnpm install` is resolved through the repository workspace and uses the shared root lockfile plus `pnpm-workspace.yaml`.
|
||||
|
||||
Use `pnpm check` as the default local verification step after editing E2E TypeScript, Cucumber support code, or feature glue. It runs formatting, linting, and type checks for this package.
|
||||
|
||||
Common commands:
|
||||
@@ -38,20 +35,20 @@ Common commands:
|
||||
```bash
|
||||
# authenticated-only regression (default excludes @fresh)
|
||||
# expects backend API, frontend artifact, and middleware stack to already be running
|
||||
pnpm -C e2e e2e
|
||||
pnpm e2e
|
||||
|
||||
# full reset + fresh install + authenticated scenarios
|
||||
# starts required middleware/dependencies for you
|
||||
pnpm -C e2e e2e:full
|
||||
pnpm e2e:full
|
||||
|
||||
# run a tagged subset
|
||||
pnpm -C e2e e2e -- --tags @smoke
|
||||
pnpm e2e -- --tags @smoke
|
||||
|
||||
# headed browser
|
||||
pnpm -C e2e e2e:headed -- --tags @smoke
|
||||
pnpm e2e:headed -- --tags @smoke
|
||||
|
||||
# slow down browser actions for local debugging
|
||||
E2E_SLOW_MO=500 pnpm -C e2e e2e:headed -- --tags @smoke
|
||||
E2E_SLOW_MO=500 pnpm e2e:headed -- --tags @smoke
|
||||
```
|
||||
|
||||
Frontend artifact behavior:
|
||||
@@ -104,7 +101,7 @@ Because of that, the `@fresh` install scenario only runs in the `pnpm e2e:full*`
|
||||
Reset all persisted E2E state:
|
||||
|
||||
```bash
|
||||
pnpm -C e2e e2e:reset
|
||||
pnpm e2e:reset
|
||||
```
|
||||
|
||||
This removes:
|
||||
@@ -120,7 +117,7 @@ This removes:
|
||||
Start the full middleware stack:
|
||||
|
||||
```bash
|
||||
pnpm -C e2e e2e:middleware:up
|
||||
pnpm e2e:middleware:up
|
||||
```
|
||||
|
||||
Stop the full middleware stack:
|
||||
|
||||
@@ -14,11 +14,21 @@
|
||||
"e2e:reset": "tsx ./scripts/setup.ts reset"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@cucumber/cucumber": "catalog:",
|
||||
"@playwright/test": "catalog:",
|
||||
"@types/node": "catalog:",
|
||||
"tsx": "catalog:",
|
||||
"typescript": "catalog:",
|
||||
"vite-plus": "catalog:"
|
||||
"@cucumber/cucumber": "12.7.0",
|
||||
"@playwright/test": "1.51.1",
|
||||
"@types/node": "25.5.0",
|
||||
"tsx": "4.21.0",
|
||||
"typescript": "5.9.3",
|
||||
"vite-plus": "latest"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^22.22.1"
|
||||
},
|
||||
"packageManager": "pnpm@10.32.1",
|
||||
"pnpm": {
|
||||
"overrides": {
|
||||
"vite": "npm:@voidzero-dev/vite-plus-core@latest",
|
||||
"vitest": "npm:@voidzero-dev/vite-plus-test@latest"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
2632
e2e/pnpm-lock.yaml
generated
Normal file
2632
e2e/pnpm-lock.yaml
generated
Normal file
File diff suppressed because it is too large
Load Diff
11
package.json
11
package.json
@@ -1,11 +0,0 @@
|
||||
{
|
||||
"name": "dify",
|
||||
"private": true,
|
||||
"engines": {
|
||||
"node": "^22.22.1"
|
||||
},
|
||||
"packageManager": "pnpm@10.33.0",
|
||||
"devDependencies": {
|
||||
"taze": "catalog:"
|
||||
}
|
||||
}
|
||||
@@ -1,257 +0,0 @@
|
||||
packages:
|
||||
- web
|
||||
- e2e
|
||||
- sdks/nodejs-client
|
||||
overrides:
|
||||
"@lexical/code": npm:lexical-code-no-prism@0.41.0
|
||||
"@monaco-editor/loader": 1.7.0
|
||||
"@nolyfill/safe-buffer": npm:safe-buffer@^5.2.1
|
||||
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.2
|
||||
devalue@<5.3.2: 5.3.2
|
||||
dompurify@>=3.1.3 <=3.3.1: 3.3.2
|
||||
es-iterator-helpers: npm:@nolyfill/es-iterator-helpers@^1.0.21
|
||||
esbuild@<0.27.2: 0.27.2
|
||||
flatted@<=3.4.1: 3.4.2
|
||||
glob@>=10.2.0 <10.5.0: 11.1.0
|
||||
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
|
||||
picomatch@<2.3.2: 2.3.2
|
||||
picomatch@>=4.0.0 <4.0.4: 4.0.4
|
||||
prismjs: ~1.30
|
||||
prismjs@<1.30.0: 1.30.0
|
||||
rollup@>=4.0.0 <4.59.0: 4.59.0
|
||||
safe-buffer: ^5.2.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
|
||||
smol-toml@<1.6.1: 1.6.1
|
||||
solid-js: 1.9.11
|
||||
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
|
||||
svgo@>=3.0.0 <3.3.3: 3.3.3
|
||||
tar@<=7.5.10: 7.5.11
|
||||
typed-array-buffer: npm:@nolyfill/typed-array-buffer@^1.0.44
|
||||
undici@>=7.0.0 <7.24.0: 7.24.0
|
||||
vite: npm:@voidzero-dev/vite-plus-core@0.1.14
|
||||
vitest: npm:@voidzero-dev/vite-plus-test@0.1.14
|
||||
which-typed-array: npm:@nolyfill/which-typed-array@^1.0.44
|
||||
yaml@>=2.0.0 <2.8.3: 2.8.3
|
||||
yauzl@<3.2.1: 3.2.1
|
||||
ignoredBuiltDependencies:
|
||||
- canvas
|
||||
- core-js-pure
|
||||
onlyBuiltDependencies:
|
||||
- "@parcel/watcher"
|
||||
- esbuild
|
||||
- sharp
|
||||
catalog:
|
||||
"@amplitude/analytics-browser": 2.38.0
|
||||
"@amplitude/plugin-session-replay-browser": 1.27.5
|
||||
"@antfu/eslint-config": 7.7.3
|
||||
"@base-ui/react": 1.3.0
|
||||
"@chromatic-com/storybook": 5.1.1
|
||||
"@cucumber/cucumber": 12.7.0
|
||||
"@egoist/tailwindcss-icons": 1.9.2
|
||||
"@emoji-mart/data": 1.2.1
|
||||
"@eslint-react/eslint-plugin": 3.0.0
|
||||
"@eslint/js": ^10.0.1
|
||||
"@floating-ui/react": 0.27.19
|
||||
"@formatjs/intl-localematcher": 0.8.2
|
||||
"@headlessui/react": 2.2.9
|
||||
"@heroicons/react": 2.2.0
|
||||
"@hono/node-server": 1.19.11
|
||||
"@iconify-json/heroicons": 1.2.3
|
||||
"@iconify-json/ri": 1.2.10
|
||||
"@lexical/code": 0.42.0
|
||||
"@lexical/link": 0.42.0
|
||||
"@lexical/list": 0.42.0
|
||||
"@lexical/react": 0.42.0
|
||||
"@lexical/selection": 0.42.0
|
||||
"@lexical/text": 0.42.0
|
||||
"@lexical/utils": 0.42.0
|
||||
"@mdx-js/loader": 3.1.1
|
||||
"@mdx-js/react": 3.1.1
|
||||
"@mdx-js/rollup": 3.1.1
|
||||
"@monaco-editor/react": 4.7.0
|
||||
"@next/eslint-plugin-next": 16.2.1
|
||||
"@next/mdx": 16.2.1
|
||||
"@orpc/client": 1.13.13
|
||||
"@orpc/contract": 1.13.13
|
||||
"@orpc/openapi-client": 1.13.13
|
||||
"@orpc/tanstack-query": 1.13.13
|
||||
"@playwright/test": 1.58.2
|
||||
"@remixicon/react": 4.9.0
|
||||
"@rgrove/parse-xml": 4.2.0
|
||||
"@sentry/react": 10.46.0
|
||||
"@storybook/addon-docs": 10.3.3
|
||||
"@storybook/addon-links": 10.3.3
|
||||
"@storybook/addon-onboarding": 10.3.3
|
||||
"@storybook/addon-themes": 10.3.3
|
||||
"@storybook/nextjs-vite": 10.3.3
|
||||
"@storybook/react": 10.3.3
|
||||
"@streamdown/math": 1.0.2
|
||||
"@svgdotjs/svg.js": 3.2.5
|
||||
"@t3-oss/env-nextjs": 0.13.11
|
||||
"@tailwindcss/typography": 0.5.19
|
||||
"@tanstack/eslint-plugin-query": 5.95.2
|
||||
"@tanstack/react-devtools": 0.10.0
|
||||
"@tanstack/react-form": 1.28.5
|
||||
"@tanstack/react-form-devtools": 0.2.19
|
||||
"@tanstack/react-query": 5.95.2
|
||||
"@tanstack/react-query-devtools": 5.95.2
|
||||
"@testing-library/dom": 10.4.1
|
||||
"@testing-library/jest-dom": 6.9.1
|
||||
"@testing-library/react": 16.3.2
|
||||
"@testing-library/user-event": 14.6.1
|
||||
"@tsslint/cli": 3.0.2
|
||||
"@tsslint/compat-eslint": 3.0.2
|
||||
"@tsslint/config": 3.0.2
|
||||
"@types/js-cookie": 3.0.6
|
||||
"@types/js-yaml": 4.0.9
|
||||
"@types/negotiator": 0.6.4
|
||||
"@types/node": 25.5.0
|
||||
"@types/postcss-js": 4.1.0
|
||||
"@types/qs": 6.15.0
|
||||
"@types/react": 19.2.14
|
||||
"@types/react-dom": 19.2.3
|
||||
"@types/react-syntax-highlighter": 15.5.13
|
||||
"@types/react-window": 1.8.8
|
||||
"@types/sortablejs": 1.15.9
|
||||
"@typescript-eslint/eslint-plugin": ^8.57.2
|
||||
"@typescript-eslint/parser": 8.57.2
|
||||
"@typescript/native-preview": 7.0.0-dev.20260329.1
|
||||
"@vitejs/plugin-react": 6.0.1
|
||||
"@vitejs/plugin-rsc": 0.5.21
|
||||
"@vitest/coverage-v8": 4.1.2
|
||||
abcjs: 6.6.2
|
||||
agentation: 3.0.2
|
||||
ahooks: 3.9.7
|
||||
autoprefixer: 10.4.27
|
||||
axios: ^1.14.0
|
||||
class-variance-authority: 0.7.1
|
||||
clsx: 2.1.1
|
||||
cmdk: 1.1.1
|
||||
code-inspector-plugin: 1.4.5
|
||||
copy-to-clipboard: 3.3.3
|
||||
cron-parser: 5.5.0
|
||||
dayjs: 1.11.20
|
||||
decimal.js: 10.6.0
|
||||
dompurify: 3.3.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.45.1
|
||||
eslint: 10.1.0
|
||||
eslint-markdown: 0.6.0
|
||||
eslint-plugin-better-tailwindcss: 4.3.2
|
||||
eslint-plugin-hyoban: 0.14.1
|
||||
eslint-plugin-markdown-preferences: 0.40.3
|
||||
eslint-plugin-no-barrel-files: 1.2.2
|
||||
eslint-plugin-react-hooks: 7.0.1
|
||||
eslint-plugin-react-refresh: 0.5.2
|
||||
eslint-plugin-sonarjs: 4.0.2
|
||||
eslint-plugin-storybook: 10.3.3
|
||||
fast-deep-equal: 3.1.3
|
||||
foxact: 0.3.0
|
||||
happy-dom: 20.8.9
|
||||
hono: 4.12.9
|
||||
html-entities: 2.6.0
|
||||
html-to-image: 1.11.13
|
||||
husky: 9.1.7
|
||||
i18next: 25.10.10
|
||||
i18next-resources-to-backend: 1.2.1
|
||||
iconify-import-svg: 0.1.2
|
||||
immer: 11.1.4
|
||||
jotai: 2.19.0
|
||||
js-audio-recorder: 1.0.7
|
||||
js-cookie: 3.0.5
|
||||
js-yaml: 4.1.1
|
||||
jsonschema: 1.5.0
|
||||
katex: 0.16.44
|
||||
knip: 6.1.0
|
||||
ky: 1.14.3
|
||||
lamejs: 1.2.1
|
||||
lexical: 0.42.0
|
||||
lint-staged: 16.4.0
|
||||
mermaid: 11.13.0
|
||||
mime: 4.1.0
|
||||
mitt: 3.0.1
|
||||
negotiator: 1.0.0
|
||||
next: 16.2.1
|
||||
next-themes: 0.4.6
|
||||
nuqs: 2.8.9
|
||||
pinyin-pro: 3.28.0
|
||||
postcss: 8.5.8
|
||||
postcss-js: 5.1.0
|
||||
qrcode.react: 4.2.0
|
||||
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.7
|
||||
react-hotkeys-hook: 5.2.4
|
||||
react-i18next: 16.6.6
|
||||
react-multi-email: 1.0.25
|
||||
react-papaparse: 4.4.0
|
||||
react-pdf-highlighter: 8.0.0-rc.0
|
||||
react-server-dom-webpack: 19.2.4
|
||||
react-sortablejs: 6.1.4
|
||||
react-syntax-highlighter: 15.6.6
|
||||
react-textarea-autosize: 8.5.9
|
||||
react-window: 1.8.11
|
||||
reactflow: 11.11.4
|
||||
remark-breaks: 4.0.0
|
||||
remark-directive: 4.0.0
|
||||
sass: 1.98.0
|
||||
scheduler: 0.27.0
|
||||
sharp: 0.34.5
|
||||
sortablejs: 1.15.7
|
||||
std-semver: 1.0.8
|
||||
storybook: 10.3.3
|
||||
streamdown: 2.5.0
|
||||
string-ts: 2.3.1
|
||||
tailwind-merge: 2.6.1
|
||||
tailwindcss: 3.4.19
|
||||
taze: 19.10.0
|
||||
tldts: 7.0.27
|
||||
tsup: ^8.5.1
|
||||
tsx: 4.21.0
|
||||
typescript: 5.9.3
|
||||
uglify-js: 3.19.3
|
||||
unist-util-visit: 5.1.0
|
||||
use-context-selector: 2.0.0
|
||||
uuid: 13.0.0
|
||||
vinext: 0.0.38
|
||||
vite: npm:@voidzero-dev/vite-plus-core@0.1.14
|
||||
vite-plugin-inspect: 12.0.0-beta.1
|
||||
vite-plus: 0.1.14
|
||||
vitest: npm:@voidzero-dev/vite-plus-test@0.1.14
|
||||
vitest-canvas-mock: 1.1.4
|
||||
zod: 4.3.6
|
||||
zundo: 2.3.0
|
||||
zustand: 5.0.12
|
||||
@@ -100,10 +100,6 @@ Notes:
|
||||
- Chat/completion require a stable `user` identifier in the request payload.
|
||||
- For streaming responses, iterate the returned AsyncIterable. Use `stream.toText()` to collect text.
|
||||
|
||||
## Maintainers
|
||||
|
||||
This package is published from the repository workspace. Install dependencies from the repository root with `pnpm install`, then use `./scripts/publish.sh` for dry runs and publishing so `catalog:` dependencies are resolved before release.
|
||||
|
||||
## License
|
||||
|
||||
This SDK is released under the MIT License.
|
||||
|
||||
@@ -54,17 +54,24 @@
|
||||
"publish:npm": "./scripts/publish.sh"
|
||||
},
|
||||
"dependencies": {
|
||||
"axios": "catalog:"
|
||||
"axios": "^1.13.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/js": "catalog:",
|
||||
"@types/node": "catalog:",
|
||||
"@typescript-eslint/eslint-plugin": "catalog:",
|
||||
"@typescript-eslint/parser": "catalog:",
|
||||
"@vitest/coverage-v8": "catalog:",
|
||||
"eslint": "catalog:",
|
||||
"tsup": "catalog:",
|
||||
"typescript": "catalog:",
|
||||
"vitest": "catalog:"
|
||||
"@eslint/js": "^10.0.1",
|
||||
"@types/node": "^25.4.0",
|
||||
"@typescript-eslint/eslint-plugin": "^8.57.0",
|
||||
"@typescript-eslint/parser": "^8.57.0",
|
||||
"@vitest/coverage-v8": "4.0.18",
|
||||
"eslint": "^10.0.3",
|
||||
"tsup": "^8.5.1",
|
||||
"typescript": "^5.9.3",
|
||||
"vitest": "^4.0.18"
|
||||
},
|
||||
"pnpm": {
|
||||
"overrides": {
|
||||
"flatted@<=3.4.1": "3.4.2",
|
||||
"picomatch@>=4.0.0 <4.0.4": "4.0.4",
|
||||
"rollup@>=4.0.0 <4.59.0": "4.59.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
2255
sdks/nodejs-client/pnpm-lock.yaml
generated
Normal file
2255
sdks/nodejs-client/pnpm-lock.yaml
generated
Normal file
File diff suppressed because it is too large
Load Diff
2
sdks/nodejs-client/pnpm-workspace.yaml
Normal file
2
sdks/nodejs-client/pnpm-workspace.yaml
Normal file
@@ -0,0 +1,2 @@
|
||||
onlyBuiltDependencies:
|
||||
- esbuild
|
||||
@@ -5,12 +5,10 @@
|
||||
# A beautiful and reliable script to publish the SDK to npm
|
||||
#
|
||||
# Usage:
|
||||
# ./scripts/publish.sh # Normal publish
|
||||
# ./scripts/publish.sh # Normal publish
|
||||
# ./scripts/publish.sh --dry-run # Test without publishing
|
||||
# ./scripts/publish.sh --skip-tests # Skip tests (not recommended)
|
||||
#
|
||||
# This script requires pnpm because the workspace uses catalog: dependencies.
|
||||
#
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
@@ -64,27 +62,11 @@ divider() {
|
||||
echo -e "${DIM}─────────────────────────────────────────────────────────────────${NC}"
|
||||
}
|
||||
|
||||
run_npm() {
|
||||
env \
|
||||
-u npm_config_npm_globalconfig \
|
||||
-u NPM_CONFIG_NPM_GLOBALCONFIG \
|
||||
-u npm_config_verify_deps_before_run \
|
||||
-u NPM_CONFIG_VERIFY_DEPS_BEFORE_RUN \
|
||||
-u npm_config__jsr_registry \
|
||||
-u NPM_CONFIG__JSR_REGISTRY \
|
||||
-u npm_config_catalog \
|
||||
-u NPM_CONFIG_CATALOG \
|
||||
-u npm_config_overrides \
|
||||
-u NPM_CONFIG_OVERRIDES \
|
||||
npm "$@"
|
||||
}
|
||||
|
||||
# ============================================================================
|
||||
# Configuration
|
||||
# ============================================================================
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||
REPO_ROOT="$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel 2>/dev/null || (cd "$SCRIPT_DIR/../../.." && pwd))"
|
||||
|
||||
DRY_RUN=false
|
||||
SKIP_TESTS=false
|
||||
@@ -141,23 +123,23 @@ main() {
|
||||
error "npm is not installed"
|
||||
exit 1
|
||||
fi
|
||||
NPM_VERSION=$(run_npm -v)
|
||||
NPM_VERSION=$(npm -v)
|
||||
success "npm: v$NPM_VERSION"
|
||||
|
||||
if ! command -v pnpm &> /dev/null; then
|
||||
error "pnpm is required because this workspace publishes catalog: dependencies"
|
||||
info "Install pnpm with Corepack: corepack enable"
|
||||
exit 1
|
||||
# Check pnpm (optional, for local dev)
|
||||
if command -v pnpm &> /dev/null; then
|
||||
PNPM_VERSION=$(pnpm -v)
|
||||
success "pnpm: v$PNPM_VERSION"
|
||||
else
|
||||
info "pnpm not found (optional)"
|
||||
fi
|
||||
PNPM_VERSION=$(pnpm -v)
|
||||
success "pnpm: v$PNPM_VERSION"
|
||||
|
||||
# Check npm login status
|
||||
if ! run_npm whoami &> /dev/null; then
|
||||
if ! npm whoami &> /dev/null; then
|
||||
error "Not logged in to npm. Run 'npm login' first."
|
||||
exit 1
|
||||
fi
|
||||
NPM_USER=$(run_npm whoami)
|
||||
NPM_USER=$(npm whoami)
|
||||
success "Logged in as: ${BOLD}$NPM_USER${NC}"
|
||||
|
||||
# ========================================================================
|
||||
@@ -172,11 +154,11 @@ main() {
|
||||
success "Version: ${BOLD}$PACKAGE_VERSION${NC}"
|
||||
|
||||
# Check if version already exists on npm
|
||||
if run_npm view "$PACKAGE_NAME@$PACKAGE_VERSION" version &> /dev/null; then
|
||||
if npm view "$PACKAGE_NAME@$PACKAGE_VERSION" version &> /dev/null; then
|
||||
error "Version $PACKAGE_VERSION already exists on npm!"
|
||||
echo ""
|
||||
info "Current published versions:"
|
||||
run_npm view "$PACKAGE_NAME" versions --json 2>/dev/null | tail -5
|
||||
npm view "$PACKAGE_NAME" versions --json 2>/dev/null | tail -5
|
||||
echo ""
|
||||
warning "Please update the version in package.json before publishing."
|
||||
exit 1
|
||||
@@ -188,7 +170,11 @@ main() {
|
||||
# ========================================================================
|
||||
step "Step 3/6: Installing dependencies..."
|
||||
|
||||
pnpm --dir "$REPO_ROOT" install --frozen-lockfile 2>/dev/null || pnpm --dir "$REPO_ROOT" install
|
||||
if command -v pnpm &> /dev/null; then
|
||||
pnpm install --frozen-lockfile 2>/dev/null || pnpm install
|
||||
else
|
||||
npm ci 2>/dev/null || npm install
|
||||
fi
|
||||
success "Dependencies installed"
|
||||
|
||||
# ========================================================================
|
||||
@@ -199,7 +185,11 @@ main() {
|
||||
if [[ "$SKIP_TESTS" == true ]]; then
|
||||
warning "Skipping tests (--skip-tests flag)"
|
||||
else
|
||||
pnpm test
|
||||
if command -v pnpm &> /dev/null; then
|
||||
pnpm test
|
||||
else
|
||||
npm test
|
||||
fi
|
||||
success "All tests passed"
|
||||
fi
|
||||
|
||||
@@ -211,7 +201,11 @@ main() {
|
||||
# Clean previous build
|
||||
rm -rf dist
|
||||
|
||||
pnpm run build
|
||||
if command -v pnpm &> /dev/null; then
|
||||
pnpm run build
|
||||
else
|
||||
npm run build
|
||||
fi
|
||||
success "Build completed"
|
||||
|
||||
# Verify build output
|
||||
@@ -229,32 +223,15 @@ main() {
|
||||
# Step 6: Publish
|
||||
# ========================================================================
|
||||
step "Step 6/6: Publishing to npm..."
|
||||
|
||||
PACK_DIR="$(mktemp -d)"
|
||||
trap 'rm -rf "$PACK_DIR"' EXIT
|
||||
|
||||
pnpm pack --pack-destination "$PACK_DIR" >/dev/null
|
||||
PACKAGE_TARBALL="$(find "$PACK_DIR" -maxdepth 1 -name '*.tgz' | head -n 1)"
|
||||
|
||||
if [[ -z "$PACKAGE_TARBALL" ]]; then
|
||||
error "Pack failed - no tarball generated"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if tar -xOf "$PACKAGE_TARBALL" package/package.json | grep -q '"catalog:'; then
|
||||
error "Packed manifest still contains catalog: references"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
divider
|
||||
echo -e "${CYAN}Package contents:${NC}"
|
||||
tar -tzf "$PACKAGE_TARBALL" | head -30
|
||||
npm pack --dry-run 2>&1 | head -30
|
||||
divider
|
||||
|
||||
if [[ "$DRY_RUN" == true ]]; then
|
||||
warning "DRY-RUN: Skipping actual publish"
|
||||
echo ""
|
||||
info "Packed artifact: $PACKAGE_TARBALL"
|
||||
info "To publish for real, run without --dry-run flag"
|
||||
else
|
||||
echo ""
|
||||
@@ -262,7 +239,7 @@ main() {
|
||||
echo -e "${DIM}Press Enter to continue, or Ctrl+C to cancel...${NC}"
|
||||
read -r
|
||||
|
||||
pnpm publish --access public --no-git-checks
|
||||
npm publish --access public
|
||||
|
||||
echo ""
|
||||
success "🎉 Successfully published ${BOLD}$PACKAGE_NAME@$PACKAGE_VERSION${NC} to npm!"
|
||||
|
||||
32
web/.dockerignore
Normal file
32
web/.dockerignore
Normal file
@@ -0,0 +1,32 @@
|
||||
.env
|
||||
.env.*
|
||||
|
||||
# Logs
|
||||
logs
|
||||
*.log*
|
||||
|
||||
# node
|
||||
node_modules
|
||||
dist
|
||||
build
|
||||
coverage
|
||||
.husky
|
||||
.next
|
||||
.pnpm-store
|
||||
|
||||
# vscode
|
||||
.vscode
|
||||
|
||||
# webstorm
|
||||
.idea
|
||||
*.iml
|
||||
*.iws
|
||||
*.ipr
|
||||
|
||||
|
||||
# Jetbrains
|
||||
.idea
|
||||
|
||||
# git
|
||||
.git
|
||||
.gitignore
|
||||
@@ -19,27 +19,21 @@ ENV NEXT_PUBLIC_BASE_PATH="$NEXT_PUBLIC_BASE_PATH"
|
||||
# install packages
|
||||
FROM base AS packages
|
||||
|
||||
WORKDIR /app
|
||||
WORKDIR /app/web
|
||||
|
||||
COPY package.json pnpm-lock.yaml pnpm-workspace.yaml /app/
|
||||
COPY web/package.json /app/web/
|
||||
COPY e2e/package.json /app/e2e/
|
||||
COPY sdks/nodejs-client/package.json /app/sdks/nodejs-client/
|
||||
COPY package.json pnpm-lock.yaml /app/web/
|
||||
|
||||
# Use packageManager from package.json
|
||||
RUN corepack install
|
||||
|
||||
# Install only the web workspace to keep image builds from pulling in
|
||||
# unrelated workspace dependencies such as e2e tooling.
|
||||
RUN pnpm install --filter ./web... --frozen-lockfile
|
||||
RUN pnpm install --frozen-lockfile
|
||||
|
||||
# build resources
|
||||
FROM base AS builder
|
||||
WORKDIR /app
|
||||
COPY --from=packages /app/ .
|
||||
WORKDIR /app/web
|
||||
COPY --from=packages /app/web/ .
|
||||
COPY . .
|
||||
|
||||
WORKDIR /app/web
|
||||
ENV NODE_OPTIONS="--max-old-space-size=4096"
|
||||
RUN pnpm build
|
||||
|
||||
@@ -70,13 +64,13 @@ RUN addgroup -S -g ${dify_uid} dify && \
|
||||
chown -R dify:dify /app
|
||||
|
||||
|
||||
WORKDIR /app
|
||||
WORKDIR /app/web
|
||||
|
||||
COPY --from=builder --chown=dify:dify /app/web/public ./web/public
|
||||
COPY --from=builder --chown=dify:dify /app/web/public ./public
|
||||
COPY --from=builder --chown=dify:dify /app/web/.next/standalone ./
|
||||
COPY --from=builder --chown=dify:dify /app/web/.next/static ./web/.next/static
|
||||
COPY --from=builder --chown=dify:dify /app/web/.next/static ./.next/static
|
||||
|
||||
COPY --chown=dify:dify --chmod=755 web/docker/entrypoint.sh ./entrypoint.sh
|
||||
COPY --chown=dify:dify --chmod=755 docker/entrypoint.sh ./entrypoint.sh
|
||||
|
||||
ARG COMMIT_SHA
|
||||
ENV COMMIT_SHA=${COMMIT_SHA}
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
**
|
||||
!package.json
|
||||
!pnpm-lock.yaml
|
||||
!pnpm-workspace.yaml
|
||||
!.nvmrc
|
||||
!web/
|
||||
!web/**
|
||||
!e2e/
|
||||
!e2e/package.json
|
||||
!sdks/
|
||||
!sdks/nodejs-client/
|
||||
!sdks/nodejs-client/package.json
|
||||
|
||||
.git
|
||||
node_modules
|
||||
.pnpm-store
|
||||
web/.env
|
||||
web/.env.*
|
||||
web/logs
|
||||
web/*.log*
|
||||
web/node_modules
|
||||
web/dist
|
||||
web/build
|
||||
web/coverage
|
||||
web/.husky
|
||||
web/.next
|
||||
web/.pnpm-store
|
||||
web/.vscode
|
||||
web/.idea
|
||||
web/*.iml
|
||||
web/*.iws
|
||||
web/*.ipr
|
||||
e2e/node_modules
|
||||
sdks/nodejs-client/node_modules
|
||||
@@ -24,24 +24,18 @@ For example, use `vp install` instead of `pnpm install` and `vp test` instead of
|
||||
>
|
||||
> Learn more: [Corepack]
|
||||
|
||||
Run the following commands from the repository root.
|
||||
|
||||
First, install the dependencies:
|
||||
|
||||
```bash
|
||||
pnpm install
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
> JavaScript dependencies are managed by the workspace files at the repository root: `package.json`, `pnpm-lock.yaml`, `pnpm-workspace.yaml`, and `.nvmrc`.
|
||||
> Install dependencies from the repository root, then run frontend scripts from `web/`.
|
||||
|
||||
Then, configure the environment variables.
|
||||
Create `web/.env.local` and copy the contents from `web/.env.example`.
|
||||
Create a file named `.env.local` in the current directory and copy the contents from `.env.example`.
|
||||
Modify the values of these environment variables according to your requirements:
|
||||
|
||||
```bash
|
||||
cp web/.env.example web/.env.local
|
||||
cp .env.example .env.local
|
||||
```
|
||||
|
||||
> [!IMPORTANT]
|
||||
@@ -52,16 +46,16 @@ cp web/.env.example web/.env.local
|
||||
Finally, run the development server:
|
||||
|
||||
```bash
|
||||
pnpm -C web run dev
|
||||
pnpm run dev
|
||||
# or if you are using vinext which provides a better development experience
|
||||
pnpm -C web run dev:vinext
|
||||
pnpm run dev:vinext
|
||||
# (optional) start the dev proxy server so that you can use online API in development
|
||||
pnpm -C web run dev:proxy
|
||||
pnpm run dev:proxy
|
||||
```
|
||||
|
||||
Open <http://localhost:3000> with your browser to see the result.
|
||||
|
||||
You can start editing the files under `web/app`.
|
||||
You can start editing the file under folder `app`.
|
||||
The page auto-updates as you edit the file.
|
||||
|
||||
## Deploy
|
||||
@@ -71,25 +65,19 @@ The page auto-updates as you edit the file.
|
||||
First, build the app for production:
|
||||
|
||||
```bash
|
||||
pnpm -C web run build
|
||||
pnpm run build
|
||||
```
|
||||
|
||||
Then, start the server:
|
||||
|
||||
```bash
|
||||
pnpm -C web run start
|
||||
```
|
||||
|
||||
If you build the Docker image manually, use the repository root as the build context:
|
||||
|
||||
```bash
|
||||
docker build -f web/Dockerfile -t dify-web .
|
||||
pnpm run start
|
||||
```
|
||||
|
||||
If you want to customize the host and port:
|
||||
|
||||
```bash
|
||||
pnpm -C web run start --port=3001 --host=0.0.0.0
|
||||
pnpm run start --port=3001 --host=0.0.0.0
|
||||
```
|
||||
|
||||
## Storybook
|
||||
@@ -99,7 +87,7 @@ This project uses [Storybook] for UI component development.
|
||||
To start the storybook server, run:
|
||||
|
||||
```bash
|
||||
pnpm -C web storybook
|
||||
pnpm storybook
|
||||
```
|
||||
|
||||
Open <http://localhost:6006> with your browser to see the result.
|
||||
@@ -124,7 +112,7 @@ We use [Vitest] and [React Testing Library] for Unit Testing.
|
||||
Run test:
|
||||
|
||||
```bash
|
||||
pnpm -C web test
|
||||
pnpm test
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import type { Mock } from 'vitest'
|
||||
import type { FeatureStoreState } from '@/app/components/base/features/store'
|
||||
import { render, screen } from '@testing-library/react'
|
||||
import userEvent from '@testing-library/user-event'
|
||||
@@ -27,7 +28,7 @@ type SetupOptions = {
|
||||
}
|
||||
|
||||
let mockFeatureStoreState: FeatureStoreState
|
||||
let mockSetFeatures = vi.fn()
|
||||
let mockSetFeatures: Mock
|
||||
const mockStore = {
|
||||
getState: vi.fn<() => FeatureStoreState>(() => mockFeatureStoreState),
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import type { Mock } from 'vitest'
|
||||
import type { FeatureStoreState } from '@/app/components/base/features/store'
|
||||
import { render, screen } from '@testing-library/react'
|
||||
import userEvent from '@testing-library/user-event'
|
||||
@@ -27,7 +28,7 @@ type SetupOptions = {
|
||||
}
|
||||
|
||||
let mockFeatureStoreState: FeatureStoreState
|
||||
let mockSetFeatures = vi.fn()
|
||||
let mockSetFeatures: Mock
|
||||
const mockStore = {
|
||||
getState: vi.fn<() => FeatureStoreState>(() => mockFeatureStoreState),
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import type { Mock } from 'vitest'
|
||||
import type { ModelConfig, PromptVariable } from '@/models/debug'
|
||||
import type { ToolItem } from '@/types/app'
|
||||
import { render, screen } from '@testing-library/react'
|
||||
@@ -73,10 +74,10 @@ type MockContext = {
|
||||
history: boolean
|
||||
query: boolean
|
||||
}
|
||||
showHistoryModal: () => void
|
||||
showHistoryModal: Mock
|
||||
modelConfig: ModelConfig
|
||||
setModelConfig: (modelConfig: ModelConfig) => void
|
||||
setPrevPromptConfig: (configs: ModelConfig['configs']) => void
|
||||
setModelConfig: Mock
|
||||
setPrevPromptConfig: Mock
|
||||
}
|
||||
|
||||
const createPromptVariable = (overrides: Partial<PromptVariable> = {}): PromptVariable => ({
|
||||
@@ -141,7 +142,7 @@ const createContextValue = (overrides: Partial<MockContext> = {}): MockContext =
|
||||
...overrides,
|
||||
})
|
||||
|
||||
const mockUseContext = vi.mocked(useContextSelector.useContext)
|
||||
const mockUseContext = useContextSelector.useContext as Mock
|
||||
|
||||
const renderConfig = (contextOverrides: Partial<MockContext> = {}) => {
|
||||
const contextValue = createContextValue(contextOverrides)
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
import type { Mock } from 'vitest'
|
||||
import { act, renderHook } from '@testing-library/react'
|
||||
import { useDSLDragDrop } from '../use-dsl-drag-drop'
|
||||
|
||||
describe('useDSLDragDrop', () => {
|
||||
let container: HTMLDivElement
|
||||
let mockOnDSLFileDropped = vi.fn<(file: File) => void>()
|
||||
let mockOnDSLFileDropped: Mock
|
||||
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks()
|
||||
container = document.createElement('div')
|
||||
document.body.appendChild(container)
|
||||
mockOnDSLFileDropped = vi.fn<(file: File) => void>()
|
||||
mockOnDSLFileDropped = vi.fn()
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
|
||||
@@ -11,15 +11,15 @@ type EmblaEventName = 'reInit' | 'select'
|
||||
type EmblaListener = (api: MockEmblaApi | undefined) => void
|
||||
|
||||
type MockEmblaApi = {
|
||||
scrollPrev: Mock<() => void>
|
||||
scrollNext: Mock<() => void>
|
||||
scrollTo: Mock<(index: number) => void>
|
||||
selectedScrollSnap: Mock<() => number>
|
||||
canScrollPrev: Mock<() => boolean>
|
||||
canScrollNext: Mock<() => boolean>
|
||||
slideNodes: Mock<() => HTMLDivElement[]>
|
||||
on: Mock<(event: EmblaEventName, callback: EmblaListener) => void>
|
||||
off: Mock<(event: EmblaEventName, callback: EmblaListener) => void>
|
||||
scrollPrev: Mock
|
||||
scrollNext: Mock
|
||||
scrollTo: Mock
|
||||
selectedScrollSnap: Mock
|
||||
canScrollPrev: Mock
|
||||
canScrollNext: Mock
|
||||
slideNodes: Mock
|
||||
on: Mock
|
||||
off: Mock
|
||||
}
|
||||
|
||||
let mockCanScrollPrev = false
|
||||
@@ -33,19 +33,19 @@ const mockCarouselRef = vi.fn()
|
||||
const mockedUseEmblaCarousel = vi.mocked(useEmblaCarousel)
|
||||
|
||||
const createMockEmblaApi = (): MockEmblaApi => ({
|
||||
scrollPrev: vi.fn<() => void>(),
|
||||
scrollNext: vi.fn<() => void>(),
|
||||
scrollTo: vi.fn<(index: number) => void>(),
|
||||
selectedScrollSnap: vi.fn<() => number>(() => mockSelectedIndex),
|
||||
canScrollPrev: vi.fn<() => boolean>(() => mockCanScrollPrev),
|
||||
canScrollNext: vi.fn<() => boolean>(() => mockCanScrollNext),
|
||||
slideNodes: vi.fn<() => HTMLDivElement[]>(() =>
|
||||
Array.from({ length: mockSlideCount }, () => document.createElement('div')),
|
||||
scrollPrev: vi.fn(),
|
||||
scrollNext: vi.fn(),
|
||||
scrollTo: vi.fn(),
|
||||
selectedScrollSnap: vi.fn(() => mockSelectedIndex),
|
||||
canScrollPrev: vi.fn(() => mockCanScrollPrev),
|
||||
canScrollNext: vi.fn(() => mockCanScrollNext),
|
||||
slideNodes: vi.fn(() =>
|
||||
Array.from({ length: mockSlideCount }).fill(document.createElement('div')),
|
||||
),
|
||||
on: vi.fn<(event: EmblaEventName, callback: EmblaListener) => void>((event, callback) => {
|
||||
on: vi.fn((event: EmblaEventName, callback: EmblaListener) => {
|
||||
listeners[event].push(callback)
|
||||
}),
|
||||
off: vi.fn<(event: EmblaEventName, callback: EmblaListener) => void>((event, callback) => {
|
||||
off: vi.fn((event: EmblaEventName, callback: EmblaListener) => {
|
||||
listeners[event] = listeners[event].filter(listener => listener !== callback)
|
||||
}),
|
||||
})
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import type { Mock } from 'vitest'
|
||||
import { render, screen, waitFor } from '@testing-library/react'
|
||||
import userEvent from '@testing-library/user-event'
|
||||
import UpgradeBtn from '../index'
|
||||
@@ -13,16 +14,14 @@ vi.mock('@/context/modal-context', () => ({
|
||||
}),
|
||||
}))
|
||||
|
||||
type GtagHandler = (command: string, action: string, payload: { loc: string }) => void
|
||||
|
||||
// Typed window accessor for gtag tracking tests
|
||||
const gtagWindow = window as unknown as { gtag?: GtagHandler }
|
||||
let mockGtag = vi.fn<GtagHandler>()
|
||||
const gtagWindow = window as unknown as Record<string, Mock | undefined>
|
||||
let mockGtag: Mock | undefined
|
||||
|
||||
describe('UpgradeBtn', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks()
|
||||
mockGtag = vi.fn<GtagHandler>()
|
||||
mockGtag = vi.fn()
|
||||
gtagWindow.gtag = mockGtag
|
||||
})
|
||||
|
||||
|
||||
@@ -56,7 +56,6 @@ export default antfu(
|
||||
},
|
||||
},
|
||||
e18e: false,
|
||||
pnpm: false,
|
||||
},
|
||||
{
|
||||
plugins: {
|
||||
|
||||
@@ -10,6 +10,7 @@ const nextConfig: NextConfig = {
|
||||
basePath: env.NEXT_PUBLIC_BASE_PATH,
|
||||
transpilePackages: ['@t3-oss/env-core', '@t3-oss/env-nextjs', 'echarts', 'zrender'],
|
||||
turbopack: {
|
||||
root: process.cwd(),
|
||||
rules: codeInspectorPlugin({
|
||||
bundler: 'turbopack',
|
||||
}),
|
||||
|
||||
435
web/package.json
435
web/package.json
@@ -3,6 +3,7 @@
|
||||
"type": "module",
|
||||
"version": "1.13.3",
|
||||
"private": true,
|
||||
"packageManager": "pnpm@10.32.1",
|
||||
"imports": {
|
||||
"#i18n": {
|
||||
"react-server": "./i18n-config/lib.server.ts",
|
||||
@@ -21,6 +22,9 @@
|
||||
"and_uc >= 15.5",
|
||||
"and_qq >= 14.9"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^22.22.1"
|
||||
},
|
||||
"scripts": {
|
||||
"analyze": "next experimental-analyze",
|
||||
"analyze-component": "node ./scripts/analyze-component.js",
|
||||
@@ -54,189 +58,258 @@
|
||||
"uglify-embed": "node ./bin/uglify-embed"
|
||||
},
|
||||
"dependencies": {
|
||||
"@amplitude/analytics-browser": "catalog:",
|
||||
"@amplitude/plugin-session-replay-browser": "catalog:",
|
||||
"@base-ui/react": "catalog:",
|
||||
"@emoji-mart/data": "catalog:",
|
||||
"@floating-ui/react": "catalog:",
|
||||
"@formatjs/intl-localematcher": "catalog:",
|
||||
"@headlessui/react": "catalog:",
|
||||
"@heroicons/react": "catalog:",
|
||||
"@lexical/code": "catalog:",
|
||||
"@lexical/link": "catalog:",
|
||||
"@lexical/list": "catalog:",
|
||||
"@lexical/react": "catalog:",
|
||||
"@lexical/selection": "catalog:",
|
||||
"@lexical/text": "catalog:",
|
||||
"@lexical/utils": "catalog:",
|
||||
"@monaco-editor/react": "catalog:",
|
||||
"@orpc/client": "catalog:",
|
||||
"@orpc/contract": "catalog:",
|
||||
"@orpc/openapi-client": "catalog:",
|
||||
"@orpc/tanstack-query": "catalog:",
|
||||
"@remixicon/react": "catalog:",
|
||||
"@sentry/react": "catalog:",
|
||||
"@streamdown/math": "catalog:",
|
||||
"@svgdotjs/svg.js": "catalog:",
|
||||
"@t3-oss/env-nextjs": "catalog:",
|
||||
"@tailwindcss/typography": "catalog:",
|
||||
"@tanstack/react-form": "catalog:",
|
||||
"@tanstack/react-query": "catalog:",
|
||||
"abcjs": "catalog:",
|
||||
"ahooks": "catalog:",
|
||||
"class-variance-authority": "catalog:",
|
||||
"clsx": "catalog:",
|
||||
"cmdk": "catalog:",
|
||||
"copy-to-clipboard": "catalog:",
|
||||
"cron-parser": "catalog:",
|
||||
"dayjs": "catalog:",
|
||||
"decimal.js": "catalog:",
|
||||
"dompurify": "catalog:",
|
||||
"echarts": "catalog:",
|
||||
"echarts-for-react": "catalog:",
|
||||
"elkjs": "catalog:",
|
||||
"embla-carousel-autoplay": "catalog:",
|
||||
"embla-carousel-react": "catalog:",
|
||||
"emoji-mart": "catalog:",
|
||||
"es-toolkit": "catalog:",
|
||||
"fast-deep-equal": "catalog:",
|
||||
"foxact": "catalog:",
|
||||
"html-entities": "catalog:",
|
||||
"html-to-image": "catalog:",
|
||||
"i18next": "catalog:",
|
||||
"i18next-resources-to-backend": "catalog:",
|
||||
"immer": "catalog:",
|
||||
"jotai": "catalog:",
|
||||
"js-audio-recorder": "catalog:",
|
||||
"js-cookie": "catalog:",
|
||||
"js-yaml": "catalog:",
|
||||
"jsonschema": "catalog:",
|
||||
"katex": "catalog:",
|
||||
"ky": "catalog:",
|
||||
"lamejs": "catalog:",
|
||||
"lexical": "catalog:",
|
||||
"mermaid": "catalog:",
|
||||
"mime": "catalog:",
|
||||
"mitt": "catalog:",
|
||||
"negotiator": "catalog:",
|
||||
"next": "catalog:",
|
||||
"next-themes": "catalog:",
|
||||
"nuqs": "catalog:",
|
||||
"pinyin-pro": "catalog:",
|
||||
"qrcode.react": "catalog:",
|
||||
"qs": "catalog:",
|
||||
"react": "catalog:",
|
||||
"react-18-input-autosize": "catalog:",
|
||||
"react-dom": "catalog:",
|
||||
"react-easy-crop": "catalog:",
|
||||
"react-hotkeys-hook": "catalog:",
|
||||
"react-i18next": "catalog:",
|
||||
"react-multi-email": "catalog:",
|
||||
"react-papaparse": "catalog:",
|
||||
"react-pdf-highlighter": "catalog:",
|
||||
"react-sortablejs": "catalog:",
|
||||
"react-syntax-highlighter": "catalog:",
|
||||
"react-textarea-autosize": "catalog:",
|
||||
"react-window": "catalog:",
|
||||
"reactflow": "catalog:",
|
||||
"remark-breaks": "catalog:",
|
||||
"remark-directive": "catalog:",
|
||||
"scheduler": "catalog:",
|
||||
"sharp": "catalog:",
|
||||
"sortablejs": "catalog:",
|
||||
"std-semver": "catalog:",
|
||||
"streamdown": "catalog:",
|
||||
"string-ts": "catalog:",
|
||||
"tailwind-merge": "catalog:",
|
||||
"tldts": "catalog:",
|
||||
"unist-util-visit": "catalog:",
|
||||
"use-context-selector": "catalog:",
|
||||
"uuid": "catalog:",
|
||||
"zod": "catalog:",
|
||||
"zundo": "catalog:",
|
||||
"zustand": "catalog:"
|
||||
"@amplitude/analytics-browser": "2.37.0",
|
||||
"@amplitude/plugin-session-replay-browser": "1.27.1",
|
||||
"@base-ui/react": "1.3.0",
|
||||
"@emoji-mart/data": "1.2.1",
|
||||
"@floating-ui/react": "0.27.19",
|
||||
"@formatjs/intl-localematcher": "0.8.2",
|
||||
"@headlessui/react": "2.2.9",
|
||||
"@heroicons/react": "2.2.0",
|
||||
"@lexical/code": "0.42.0",
|
||||
"@lexical/link": "0.42.0",
|
||||
"@lexical/list": "0.42.0",
|
||||
"@lexical/react": "0.42.0",
|
||||
"@lexical/selection": "0.42.0",
|
||||
"@lexical/text": "0.42.0",
|
||||
"@lexical/utils": "0.42.0",
|
||||
"@monaco-editor/react": "4.7.0",
|
||||
"@orpc/client": "1.13.9",
|
||||
"@orpc/contract": "1.13.9",
|
||||
"@orpc/openapi-client": "1.13.9",
|
||||
"@orpc/tanstack-query": "1.13.9",
|
||||
"@remixicon/react": "4.9.0",
|
||||
"@sentry/react": "10.45.0",
|
||||
"@streamdown/math": "1.0.2",
|
||||
"@svgdotjs/svg.js": "3.2.5",
|
||||
"@t3-oss/env-nextjs": "0.13.11",
|
||||
"@tailwindcss/typography": "0.5.19",
|
||||
"@tanstack/react-form": "1.28.5",
|
||||
"@tanstack/react-query": "5.95.0",
|
||||
"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.5.0",
|
||||
"dayjs": "1.11.20",
|
||||
"decimal.js": "10.6.0",
|
||||
"dompurify": "3.3.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.45.1",
|
||||
"fast-deep-equal": "3.1.3",
|
||||
"foxact": "0.3.0",
|
||||
"html-entities": "2.6.0",
|
||||
"html-to-image": "1.11.13",
|
||||
"i18next": "25.10.4",
|
||||
"i18next-resources-to-backend": "1.2.1",
|
||||
"immer": "11.1.4",
|
||||
"jotai": "2.18.1",
|
||||
"js-audio-recorder": "1.0.7",
|
||||
"js-cookie": "3.0.5",
|
||||
"js-yaml": "4.1.1",
|
||||
"jsonschema": "1.5.0",
|
||||
"katex": "0.16.40",
|
||||
"ky": "1.14.3",
|
||||
"lamejs": "1.2.1",
|
||||
"lexical": "0.42.0",
|
||||
"mermaid": "11.13.0",
|
||||
"mime": "4.1.0",
|
||||
"mitt": "3.0.1",
|
||||
"negotiator": "1.0.0",
|
||||
"next": "16.2.1",
|
||||
"next-themes": "0.4.6",
|
||||
"nuqs": "2.8.9",
|
||||
"pinyin-pro": "3.28.0",
|
||||
"qrcode.react": "4.2.0",
|
||||
"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.6",
|
||||
"react-hotkeys-hook": "5.2.4",
|
||||
"react-i18next": "16.6.1",
|
||||
"react-multi-email": "1.0.25",
|
||||
"react-papaparse": "4.4.0",
|
||||
"react-pdf-highlighter": "8.0.0-rc.0",
|
||||
"react-sortablejs": "6.1.4",
|
||||
"react-syntax-highlighter": "15.6.6",
|
||||
"react-textarea-autosize": "8.5.9",
|
||||
"react-window": "1.8.11",
|
||||
"reactflow": "11.11.4",
|
||||
"remark-breaks": "4.0.0",
|
||||
"remark-directive": "4.0.0",
|
||||
"scheduler": "0.27.0",
|
||||
"sharp": "0.34.5",
|
||||
"sortablejs": "1.15.7",
|
||||
"std-semver": "1.0.8",
|
||||
"streamdown": "2.5.0",
|
||||
"string-ts": "2.3.1",
|
||||
"tailwind-merge": "2.6.1",
|
||||
"tldts": "7.0.27",
|
||||
"unist-util-visit": "5.1.0",
|
||||
"use-context-selector": "2.0.0",
|
||||
"uuid": "13.0.0",
|
||||
"zod": "4.3.6",
|
||||
"zundo": "2.3.0",
|
||||
"zustand": "5.0.12"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@antfu/eslint-config": "catalog:",
|
||||
"@chromatic-com/storybook": "catalog:",
|
||||
"@egoist/tailwindcss-icons": "catalog:",
|
||||
"@eslint-react/eslint-plugin": "catalog:",
|
||||
"@hono/node-server": "catalog:",
|
||||
"@iconify-json/heroicons": "catalog:",
|
||||
"@iconify-json/ri": "catalog:",
|
||||
"@mdx-js/loader": "catalog:",
|
||||
"@mdx-js/react": "catalog:",
|
||||
"@mdx-js/rollup": "catalog:",
|
||||
"@next/eslint-plugin-next": "catalog:",
|
||||
"@next/mdx": "catalog:",
|
||||
"@rgrove/parse-xml": "catalog:",
|
||||
"@storybook/addon-docs": "catalog:",
|
||||
"@storybook/addon-links": "catalog:",
|
||||
"@storybook/addon-onboarding": "catalog:",
|
||||
"@storybook/addon-themes": "catalog:",
|
||||
"@storybook/nextjs-vite": "catalog:",
|
||||
"@storybook/react": "catalog:",
|
||||
"@tanstack/eslint-plugin-query": "catalog:",
|
||||
"@tanstack/react-devtools": "catalog:",
|
||||
"@tanstack/react-form-devtools": "catalog:",
|
||||
"@tanstack/react-query-devtools": "catalog:",
|
||||
"@testing-library/dom": "catalog:",
|
||||
"@testing-library/jest-dom": "catalog:",
|
||||
"@testing-library/react": "catalog:",
|
||||
"@testing-library/user-event": "catalog:",
|
||||
"@tsslint/cli": "catalog:",
|
||||
"@tsslint/compat-eslint": "catalog:",
|
||||
"@tsslint/config": "catalog:",
|
||||
"@types/js-cookie": "catalog:",
|
||||
"@types/js-yaml": "catalog:",
|
||||
"@types/negotiator": "catalog:",
|
||||
"@types/node": "catalog:",
|
||||
"@types/postcss-js": "catalog:",
|
||||
"@types/qs": "catalog:",
|
||||
"@types/react": "catalog:",
|
||||
"@types/react-dom": "catalog:",
|
||||
"@types/react-syntax-highlighter": "catalog:",
|
||||
"@types/react-window": "catalog:",
|
||||
"@types/sortablejs": "catalog:",
|
||||
"@typescript-eslint/parser": "catalog:",
|
||||
"@typescript/native-preview": "catalog:",
|
||||
"@vitejs/plugin-react": "catalog:",
|
||||
"@vitejs/plugin-rsc": "catalog:",
|
||||
"@vitest/coverage-v8": "catalog:",
|
||||
"agentation": "catalog:",
|
||||
"autoprefixer": "catalog:",
|
||||
"code-inspector-plugin": "catalog:",
|
||||
"eslint": "catalog:",
|
||||
"eslint-markdown": "catalog:",
|
||||
"eslint-plugin-better-tailwindcss": "catalog:",
|
||||
"eslint-plugin-hyoban": "catalog:",
|
||||
"eslint-plugin-markdown-preferences": "catalog:",
|
||||
"eslint-plugin-no-barrel-files": "catalog:",
|
||||
"eslint-plugin-react-hooks": "catalog:",
|
||||
"eslint-plugin-react-refresh": "catalog:",
|
||||
"eslint-plugin-sonarjs": "catalog:",
|
||||
"eslint-plugin-storybook": "catalog:",
|
||||
"happy-dom": "catalog:",
|
||||
"hono": "catalog:",
|
||||
"husky": "catalog:",
|
||||
"iconify-import-svg": "catalog:",
|
||||
"knip": "catalog:",
|
||||
"lint-staged": "catalog:",
|
||||
"postcss": "catalog:",
|
||||
"postcss-js": "catalog:",
|
||||
"react-server-dom-webpack": "catalog:",
|
||||
"sass": "catalog:",
|
||||
"storybook": "catalog:",
|
||||
"tailwindcss": "catalog:",
|
||||
"tsx": "catalog:",
|
||||
"typescript": "catalog:",
|
||||
"uglify-js": "catalog:",
|
||||
"vinext": "catalog:",
|
||||
"vite": "catalog:",
|
||||
"vite-plugin-inspect": "catalog:",
|
||||
"vite-plus": "catalog:",
|
||||
"vitest": "catalog:",
|
||||
"vitest-canvas-mock": "catalog:"
|
||||
"@antfu/eslint-config": "7.7.3",
|
||||
"@chromatic-com/storybook": "5.0.2",
|
||||
"@egoist/tailwindcss-icons": "1.9.2",
|
||||
"@eslint-react/eslint-plugin": "3.0.0",
|
||||
"@hono/node-server": "1.19.11",
|
||||
"@iconify-json/heroicons": "1.2.3",
|
||||
"@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.2.1",
|
||||
"@next/mdx": "16.2.1",
|
||||
"@rgrove/parse-xml": "4.2.0",
|
||||
"@storybook/addon-docs": "10.3.1",
|
||||
"@storybook/addon-links": "10.3.1",
|
||||
"@storybook/addon-onboarding": "10.3.1",
|
||||
"@storybook/addon-themes": "10.3.1",
|
||||
"@storybook/nextjs-vite": "10.3.1",
|
||||
"@storybook/react": "10.3.1",
|
||||
"@tanstack/eslint-plugin-query": "5.95.0",
|
||||
"@tanstack/react-devtools": "0.10.0",
|
||||
"@tanstack/react-form-devtools": "0.2.19",
|
||||
"@tanstack/react-query-devtools": "5.95.0",
|
||||
"@testing-library/dom": "10.4.1",
|
||||
"@testing-library/jest-dom": "6.9.1",
|
||||
"@testing-library/react": "16.3.2",
|
||||
"@testing-library/user-event": "14.6.1",
|
||||
"@tsslint/cli": "3.0.2",
|
||||
"@tsslint/compat-eslint": "3.0.2",
|
||||
"@tsslint/config": "3.0.2",
|
||||
"@types/js-cookie": "3.0.6",
|
||||
"@types/js-yaml": "4.0.9",
|
||||
"@types/negotiator": "0.6.4",
|
||||
"@types/node": "25.5.0",
|
||||
"@types/postcss-js": "4.1.0",
|
||||
"@types/qs": "6.15.0",
|
||||
"@types/react": "19.2.14",
|
||||
"@types/react-dom": "19.2.3",
|
||||
"@types/react-syntax-highlighter": "15.5.13",
|
||||
"@types/react-window": "1.8.8",
|
||||
"@types/sortablejs": "1.15.9",
|
||||
"@typescript-eslint/parser": "8.57.1",
|
||||
"@typescript/native-preview": "7.0.0-dev.20260322.1",
|
||||
"@vitejs/plugin-react": "6.0.1",
|
||||
"@vitejs/plugin-rsc": "0.5.21",
|
||||
"@vitest/coverage-v8": "4.1.0",
|
||||
"agentation": "2.3.3",
|
||||
"autoprefixer": "10.4.27",
|
||||
"code-inspector-plugin": "1.4.5",
|
||||
"eslint": "10.1.0",
|
||||
"eslint-markdown": "0.6.0",
|
||||
"eslint-plugin-better-tailwindcss": "4.3.2",
|
||||
"eslint-plugin-hyoban": "0.14.1",
|
||||
"eslint-plugin-markdown-preferences": "0.40.3",
|
||||
"eslint-plugin-no-barrel-files": "1.2.2",
|
||||
"eslint-plugin-react-hooks": "7.0.1",
|
||||
"eslint-plugin-react-refresh": "0.5.2",
|
||||
"eslint-plugin-sonarjs": "4.0.2",
|
||||
"eslint-plugin-storybook": "10.3.1",
|
||||
"happy-dom": "20.8.9",
|
||||
"hono": "4.12.8",
|
||||
"husky": "9.1.7",
|
||||
"iconify-import-svg": "0.1.2",
|
||||
"knip": "6.0.2",
|
||||
"lint-staged": "16.4.0",
|
||||
"postcss": "8.5.8",
|
||||
"postcss-js": "5.1.0",
|
||||
"react-server-dom-webpack": "19.2.4",
|
||||
"sass": "1.98.0",
|
||||
"storybook": "10.3.1",
|
||||
"tailwindcss": "3.4.19",
|
||||
"taze": "19.10.0",
|
||||
"tsx": "4.21.0",
|
||||
"typescript": "5.9.3",
|
||||
"uglify-js": "3.19.3",
|
||||
"vinext": "https://pkg.pr.new/vinext@b6a2cac",
|
||||
"vite": "npm:@voidzero-dev/vite-plus-core@0.1.13",
|
||||
"vite-plugin-inspect": "11.3.3",
|
||||
"vite-plus": "0.1.13",
|
||||
"vitest": "npm:@voidzero-dev/vite-plus-test@0.1.13",
|
||||
"vitest-canvas-mock": "1.1.3"
|
||||
},
|
||||
"pnpm": {
|
||||
"overrides": {
|
||||
"@lexical/code": "npm:lexical-code-no-prism@0.41.0",
|
||||
"@monaco-editor/loader": "1.7.0",
|
||||
"@nolyfill/safe-buffer": "npm:safe-buffer@^5.2.1",
|
||||
"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.2",
|
||||
"devalue@<5.3.2": "5.3.2",
|
||||
"dompurify@>=3.1.3 <=3.3.1": "3.3.2",
|
||||
"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.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",
|
||||
"picomatch@<2.3.2": "2.3.2",
|
||||
"picomatch@>=4.0.0 <4.0.4": "4.0.4",
|
||||
"prismjs": "~1.30",
|
||||
"prismjs@<1.30.0": "1.30.0",
|
||||
"rollup@>=4.0.0 <4.59.0": "4.59.0",
|
||||
"safe-buffer": "^5.2.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",
|
||||
"smol-toml@<1.6.1": "1.6.1",
|
||||
"solid-js": "1.9.11",
|
||||
"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",
|
||||
"svgo@>=3.0.0 <3.3.3": "3.3.3",
|
||||
"tar@<=7.5.10": "7.5.11",
|
||||
"typed-array-buffer": "npm:@nolyfill/typed-array-buffer@^1.0.44",
|
||||
"undici@>=7.0.0 <7.24.0": "7.24.0",
|
||||
"vite": "npm:@voidzero-dev/vite-plus-core@0.1.13",
|
||||
"vitest": "npm:@voidzero-dev/vite-plus-test@0.1.13",
|
||||
"which-typed-array": "npm:@nolyfill/which-typed-array@^1.0.44",
|
||||
"yaml@>=2.0.0 <2.8.3": "2.8.3",
|
||||
"yauzl@<3.2.1": "3.2.1"
|
||||
},
|
||||
"ignoredBuiltDependencies": [
|
||||
"canvas",
|
||||
"core-js-pure"
|
||||
],
|
||||
"onlyBuiltDependencies": [
|
||||
"@parcel/watcher",
|
||||
"esbuild",
|
||||
"sharp"
|
||||
]
|
||||
},
|
||||
"lint-staged": {
|
||||
"*": "eslint --fix --pass-on-unpruned-suppressions"
|
||||
|
||||
4859
pnpm-lock.yaml → web/pnpm-lock.yaml
generated
4859
pnpm-lock.yaml → web/pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -8,6 +8,21 @@ import { spawn } from 'node:child_process'
|
||||
import { cp, mkdir, stat } from 'node:fs/promises'
|
||||
import path from 'node:path'
|
||||
|
||||
// Configuration for directories to copy
|
||||
const DIRS_TO_COPY = [
|
||||
{
|
||||
src: path.join('.next', 'static'),
|
||||
dest: path.join('.next', 'standalone', '.next', 'static'),
|
||||
},
|
||||
{
|
||||
src: 'public',
|
||||
dest: path.join('.next', 'standalone', 'public'),
|
||||
},
|
||||
]
|
||||
|
||||
// Path to the server script
|
||||
const SERVER_SCRIPT_PATH = path.join('.next', 'standalone', 'server.js')
|
||||
|
||||
// Function to check if a path exists
|
||||
const pathExists = async (path) => {
|
||||
try {
|
||||
@@ -25,23 +40,6 @@ const pathExists = async (path) => {
|
||||
}
|
||||
}
|
||||
|
||||
const STANDALONE_ROOT_CANDIDATES = [
|
||||
path.join('.next', 'standalone', 'web'),
|
||||
path.join('.next', 'standalone'),
|
||||
]
|
||||
|
||||
const getStandaloneRoot = async () => {
|
||||
for (const standaloneRoot of STANDALONE_ROOT_CANDIDATES) {
|
||||
const serverScriptPath = path.join(standaloneRoot, 'server.js')
|
||||
if (await pathExists(serverScriptPath))
|
||||
return standaloneRoot
|
||||
}
|
||||
|
||||
throw new Error(
|
||||
`Unable to find Next standalone server entry. Checked: ${STANDALONE_ROOT_CANDIDATES.join(', ')}`,
|
||||
)
|
||||
}
|
||||
|
||||
// Function to recursively copy directories
|
||||
const copyDir = async (src, dest) => {
|
||||
console.debug(`Copying directory from ${src} to ${dest}`)
|
||||
@@ -50,20 +48,9 @@ const copyDir = async (src, dest) => {
|
||||
}
|
||||
|
||||
// Process each directory copy operation
|
||||
const copyAllDirs = async (standaloneRoot) => {
|
||||
const dirsToCopy = [
|
||||
{
|
||||
src: path.join('.next', 'static'),
|
||||
dest: path.join(standaloneRoot, '.next', 'static'),
|
||||
},
|
||||
{
|
||||
src: 'public',
|
||||
dest: path.join(standaloneRoot, 'public'),
|
||||
},
|
||||
]
|
||||
|
||||
const copyAllDirs = async () => {
|
||||
console.debug('Starting directory copy operations')
|
||||
for (const { src, dest } of dirsToCopy) {
|
||||
for (const { src, dest } of DIRS_TO_COPY) {
|
||||
try {
|
||||
// Instead of pre-creating destination directory, we ensure parent directory exists
|
||||
const destParent = path.dirname(dest)
|
||||
@@ -88,22 +75,19 @@ const copyAllDirs = async (standaloneRoot) => {
|
||||
// Run copy operations and start server
|
||||
const main = async () => {
|
||||
console.debug('Starting copy-and-start script')
|
||||
const standaloneRoot = await getStandaloneRoot()
|
||||
const serverScriptPath = path.join(standaloneRoot, 'server.js')
|
||||
|
||||
await copyAllDirs(standaloneRoot)
|
||||
await copyAllDirs()
|
||||
|
||||
// Start server
|
||||
const port = process.env.npm_config_port || process.env.PORT || '3000'
|
||||
const host = process.env.npm_config_host || process.env.HOSTNAME || '0.0.0.0'
|
||||
|
||||
console.info(`Starting server on ${host}:${port}`)
|
||||
console.debug(`Server script path: ${serverScriptPath}`)
|
||||
console.debug(`Server script path: ${SERVER_SCRIPT_PATH}`)
|
||||
console.debug(`Environment variables - PORT: ${port}, HOSTNAME: ${host}`)
|
||||
|
||||
const server = spawn(
|
||||
process.execPath,
|
||||
[serverScriptPath],
|
||||
[SERVER_SCRIPT_PATH],
|
||||
{
|
||||
env: {
|
||||
...process.env,
|
||||
|
||||
@@ -10,7 +10,6 @@ export default defineConfig({
|
||||
// We can not upgrade these yet
|
||||
'tailwind-merge',
|
||||
'tailwindcss',
|
||||
'typescript',
|
||||
],
|
||||
|
||||
write: true,
|
||||
@@ -1,11 +1,8 @@
|
||||
import * as jestDomMatchers from '@testing-library/jest-dom/matchers'
|
||||
import { act, cleanup } from '@testing-library/react'
|
||||
import * as React from 'react'
|
||||
import '@testing-library/jest-dom/vitest'
|
||||
import 'vitest-canvas-mock'
|
||||
|
||||
expect.extend(jestDomMatchers)
|
||||
|
||||
// Suppress act() warnings from @headlessui/react internal Transition component
|
||||
// These warnings are caused by Headless UI's internal async state updates, not our code
|
||||
const originalConsoleError = console.error
|
||||
|
||||
Reference in New Issue
Block a user