mirror of
https://github.com/langgenius/dify.git
synced 2026-04-05 05:24:20 +08:00
refactor: introduce pnpm workspace (#34241)
Co-authored-by: yyh <yuanyouhuilyz@gmail.com> Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This commit is contained in:
@@ -1,32 +0,0 @@
|
||||
.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
|
||||
@@ -1 +0,0 @@
|
||||
22
|
||||
@@ -19,21 +19,27 @@ ENV NEXT_PUBLIC_BASE_PATH="$NEXT_PUBLIC_BASE_PATH"
|
||||
# install packages
|
||||
FROM base AS packages
|
||||
|
||||
WORKDIR /app/web
|
||||
WORKDIR /app
|
||||
|
||||
COPY package.json pnpm-lock.yaml /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/
|
||||
|
||||
# Use packageManager from package.json
|
||||
RUN corepack install
|
||||
|
||||
RUN pnpm install --frozen-lockfile
|
||||
# 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
|
||||
|
||||
# build resources
|
||||
FROM base AS builder
|
||||
WORKDIR /app/web
|
||||
COPY --from=packages /app/web/ .
|
||||
WORKDIR /app
|
||||
COPY --from=packages /app/ .
|
||||
COPY . .
|
||||
|
||||
WORKDIR /app/web
|
||||
ENV NODE_OPTIONS="--max-old-space-size=4096"
|
||||
RUN pnpm build
|
||||
|
||||
@@ -64,13 +70,13 @@ RUN addgroup -S -g ${dify_uid} dify && \
|
||||
chown -R dify:dify /app
|
||||
|
||||
|
||||
WORKDIR /app/web
|
||||
WORKDIR /app
|
||||
|
||||
COPY --from=builder --chown=dify:dify /app/web/public ./public
|
||||
COPY --from=builder --chown=dify:dify /app/web/public ./web/public
|
||||
COPY --from=builder --chown=dify:dify /app/web/.next/standalone ./
|
||||
COPY --from=builder --chown=dify:dify /app/web/.next/static ./.next/static
|
||||
COPY --from=builder --chown=dify:dify /app/web/.next/static ./web/.next/static
|
||||
|
||||
COPY --chown=dify:dify --chmod=755 docker/entrypoint.sh ./entrypoint.sh
|
||||
COPY --chown=dify:dify --chmod=755 web/docker/entrypoint.sh ./entrypoint.sh
|
||||
|
||||
ARG COMMIT_SHA
|
||||
ENV COMMIT_SHA=${COMMIT_SHA}
|
||||
|
||||
34
web/Dockerfile.dockerignore
Normal file
34
web/Dockerfile.dockerignore
Normal file
@@ -0,0 +1,34 @@
|
||||
**
|
||||
!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,18 +24,24 @@ 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 a file named `.env.local` in the current directory and copy the contents from `.env.example`.
|
||||
Create `web/.env.local` and copy the contents from `web/.env.example`.
|
||||
Modify the values of these environment variables according to your requirements:
|
||||
|
||||
```bash
|
||||
cp .env.example .env.local
|
||||
cp web/.env.example web/.env.local
|
||||
```
|
||||
|
||||
> [!IMPORTANT]
|
||||
@@ -46,16 +52,16 @@ cp .env.example .env.local
|
||||
Finally, run the development server:
|
||||
|
||||
```bash
|
||||
pnpm run dev
|
||||
pnpm -C web run dev
|
||||
# or if you are using vinext which provides a better development experience
|
||||
pnpm run dev:vinext
|
||||
pnpm -C web run dev:vinext
|
||||
# (optional) start the dev proxy server so that you can use online API in development
|
||||
pnpm run dev:proxy
|
||||
pnpm -C web run dev:proxy
|
||||
```
|
||||
|
||||
Open <http://localhost:3000> with your browser to see the result.
|
||||
|
||||
You can start editing the file under folder `app`.
|
||||
You can start editing the files under `web/app`.
|
||||
The page auto-updates as you edit the file.
|
||||
|
||||
## Deploy
|
||||
@@ -65,19 +71,25 @@ The page auto-updates as you edit the file.
|
||||
First, build the app for production:
|
||||
|
||||
```bash
|
||||
pnpm run build
|
||||
pnpm -C web run build
|
||||
```
|
||||
|
||||
Then, start the server:
|
||||
|
||||
```bash
|
||||
pnpm run start
|
||||
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 .
|
||||
```
|
||||
|
||||
If you want to customize the host and port:
|
||||
|
||||
```bash
|
||||
pnpm run start --port=3001 --host=0.0.0.0
|
||||
pnpm -C web run start --port=3001 --host=0.0.0.0
|
||||
```
|
||||
|
||||
## Storybook
|
||||
@@ -87,7 +99,7 @@ This project uses [Storybook] for UI component development.
|
||||
To start the storybook server, run:
|
||||
|
||||
```bash
|
||||
pnpm storybook
|
||||
pnpm -C web storybook
|
||||
```
|
||||
|
||||
Open <http://localhost:6006> with your browser to see the result.
|
||||
@@ -112,7 +124,7 @@ We use [Vitest] and [React Testing Library] for Unit Testing.
|
||||
Run test:
|
||||
|
||||
```bash
|
||||
pnpm test
|
||||
pnpm -C web test
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
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'
|
||||
@@ -28,7 +27,7 @@ type SetupOptions = {
|
||||
}
|
||||
|
||||
let mockFeatureStoreState: FeatureStoreState
|
||||
let mockSetFeatures: Mock
|
||||
let mockSetFeatures = vi.fn()
|
||||
const mockStore = {
|
||||
getState: vi.fn<() => FeatureStoreState>(() => mockFeatureStoreState),
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
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'
|
||||
@@ -28,7 +27,7 @@ type SetupOptions = {
|
||||
}
|
||||
|
||||
let mockFeatureStoreState: FeatureStoreState
|
||||
let mockSetFeatures: Mock
|
||||
let mockSetFeatures = vi.fn()
|
||||
const mockStore = {
|
||||
getState: vi.fn<() => FeatureStoreState>(() => mockFeatureStoreState),
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
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'
|
||||
@@ -74,10 +73,10 @@ type MockContext = {
|
||||
history: boolean
|
||||
query: boolean
|
||||
}
|
||||
showHistoryModal: Mock
|
||||
showHistoryModal: () => void
|
||||
modelConfig: ModelConfig
|
||||
setModelConfig: Mock
|
||||
setPrevPromptConfig: Mock
|
||||
setModelConfig: (modelConfig: ModelConfig) => void
|
||||
setPrevPromptConfig: (configs: ModelConfig['configs']) => void
|
||||
}
|
||||
|
||||
const createPromptVariable = (overrides: Partial<PromptVariable> = {}): PromptVariable => ({
|
||||
@@ -142,7 +141,7 @@ const createContextValue = (overrides: Partial<MockContext> = {}): MockContext =
|
||||
...overrides,
|
||||
})
|
||||
|
||||
const mockUseContext = useContextSelector.useContext as Mock
|
||||
const mockUseContext = vi.mocked(useContextSelector.useContext)
|
||||
|
||||
const renderConfig = (contextOverrides: Partial<MockContext> = {}) => {
|
||||
const contextValue = createContextValue(contextOverrides)
|
||||
|
||||
@@ -1,16 +1,15 @@
|
||||
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: Mock
|
||||
let mockOnDSLFileDropped = vi.fn<(file: File) => void>()
|
||||
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks()
|
||||
container = document.createElement('div')
|
||||
document.body.appendChild(container)
|
||||
mockOnDSLFileDropped = vi.fn()
|
||||
mockOnDSLFileDropped = vi.fn<(file: File) => void>()
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
|
||||
@@ -11,15 +11,15 @@ type EmblaEventName = 'reInit' | 'select'
|
||||
type EmblaListener = (api: MockEmblaApi | undefined) => void
|
||||
|
||||
type MockEmblaApi = {
|
||||
scrollPrev: Mock
|
||||
scrollNext: Mock
|
||||
scrollTo: Mock
|
||||
selectedScrollSnap: Mock
|
||||
canScrollPrev: Mock
|
||||
canScrollNext: Mock
|
||||
slideNodes: Mock
|
||||
on: Mock
|
||||
off: Mock
|
||||
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>
|
||||
}
|
||||
|
||||
let mockCanScrollPrev = false
|
||||
@@ -33,19 +33,19 @@ const mockCarouselRef = vi.fn()
|
||||
const mockedUseEmblaCarousel = vi.mocked(useEmblaCarousel)
|
||||
|
||||
const createMockEmblaApi = (): MockEmblaApi => ({
|
||||
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')),
|
||||
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')),
|
||||
),
|
||||
on: vi.fn((event: EmblaEventName, callback: EmblaListener) => {
|
||||
on: vi.fn<(event: EmblaEventName, callback: EmblaListener) => void>((event, callback) => {
|
||||
listeners[event].push(callback)
|
||||
}),
|
||||
off: vi.fn((event: EmblaEventName, callback: EmblaListener) => {
|
||||
off: vi.fn<(event: EmblaEventName, callback: EmblaListener) => void>((event, callback) => {
|
||||
listeners[event] = listeners[event].filter(listener => listener !== callback)
|
||||
}),
|
||||
})
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import type { Mock } from 'vitest'
|
||||
import { render, screen, waitFor } from '@testing-library/react'
|
||||
import userEvent from '@testing-library/user-event'
|
||||
import UpgradeBtn from '../index'
|
||||
@@ -14,14 +13,16 @@ 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 Record<string, Mock | undefined>
|
||||
let mockGtag: Mock | undefined
|
||||
const gtagWindow = window as unknown as { gtag?: GtagHandler }
|
||||
let mockGtag = vi.fn<GtagHandler>()
|
||||
|
||||
describe('UpgradeBtn', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks()
|
||||
mockGtag = vi.fn()
|
||||
mockGtag = vi.fn<GtagHandler>()
|
||||
gtagWindow.gtag = mockGtag
|
||||
})
|
||||
|
||||
|
||||
@@ -56,6 +56,7 @@ export default antfu(
|
||||
},
|
||||
},
|
||||
e18e: false,
|
||||
pnpm: false,
|
||||
},
|
||||
{
|
||||
plugins: {
|
||||
|
||||
@@ -10,7 +10,6 @@ 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,7 +3,6 @@
|
||||
"type": "module",
|
||||
"version": "1.13.3",
|
||||
"private": true,
|
||||
"packageManager": "pnpm@10.32.1",
|
||||
"imports": {
|
||||
"#i18n": {
|
||||
"react-server": "./i18n-config/lib.server.ts",
|
||||
@@ -22,9 +21,6 @@
|
||||
"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",
|
||||
@@ -58,258 +54,189 @@
|
||||
"uglify-embed": "node ./bin/uglify-embed"
|
||||
},
|
||||
"dependencies": {
|
||||
"@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"
|
||||
"@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:"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@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"
|
||||
]
|
||||
"@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:"
|
||||
},
|
||||
"lint-staged": {
|
||||
"*": "eslint --fix --pass-on-unpruned-suppressions"
|
||||
|
||||
16206
web/pnpm-lock.yaml
generated
16206
web/pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -8,21 +8,6 @@ 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 {
|
||||
@@ -40,6 +25,23 @@ 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}`)
|
||||
@@ -48,9 +50,20 @@ const copyDir = async (src, dest) => {
|
||||
}
|
||||
|
||||
// Process each directory copy operation
|
||||
const copyAllDirs = async () => {
|
||||
const copyAllDirs = async (standaloneRoot) => {
|
||||
const dirsToCopy = [
|
||||
{
|
||||
src: path.join('.next', 'static'),
|
||||
dest: path.join(standaloneRoot, '.next', 'static'),
|
||||
},
|
||||
{
|
||||
src: 'public',
|
||||
dest: path.join(standaloneRoot, 'public'),
|
||||
},
|
||||
]
|
||||
|
||||
console.debug('Starting directory copy operations')
|
||||
for (const { src, dest } of DIRS_TO_COPY) {
|
||||
for (const { src, dest } of dirsToCopy) {
|
||||
try {
|
||||
// Instead of pre-creating destination directory, we ensure parent directory exists
|
||||
const destParent = path.dirname(dest)
|
||||
@@ -75,19 +88,22 @@ const copyAllDirs = async () => {
|
||||
// Run copy operations and start server
|
||||
const main = async () => {
|
||||
console.debug('Starting copy-and-start script')
|
||||
await copyAllDirs()
|
||||
const standaloneRoot = await getStandaloneRoot()
|
||||
const serverScriptPath = path.join(standaloneRoot, 'server.js')
|
||||
|
||||
await copyAllDirs(standaloneRoot)
|
||||
|
||||
// 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: ${SERVER_SCRIPT_PATH}`)
|
||||
console.debug(`Server script path: ${serverScriptPath}`)
|
||||
console.debug(`Environment variables - PORT: ${port}, HOSTNAME: ${host}`)
|
||||
|
||||
const server = spawn(
|
||||
process.execPath,
|
||||
[SERVER_SCRIPT_PATH],
|
||||
[serverScriptPath],
|
||||
{
|
||||
env: {
|
||||
...process.env,
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
import { defineConfig } from 'taze'
|
||||
|
||||
export default defineConfig({
|
||||
exclude: [
|
||||
// We are going to replace these
|
||||
'react-syntax-highlighter',
|
||||
'react-window',
|
||||
'@types/react-window',
|
||||
|
||||
// We can not upgrade these yet
|
||||
'tailwind-merge',
|
||||
'tailwindcss',
|
||||
],
|
||||
|
||||
write: true,
|
||||
install: false,
|
||||
recursive: true,
|
||||
interactive: true,
|
||||
})
|
||||
@@ -1,8 +1,11 @@
|
||||
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