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:
Stephen Zhou
2026-03-30 18:34:50 +08:00
committed by GitHub
parent 1aaba80211
commit 52a4bea88f
42 changed files with 4060 additions and 6942 deletions

View File

@@ -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

View File

@@ -1 +0,0 @@
22

View File

@@ -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}

View 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

View File

@@ -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]

View File

@@ -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),
}

View File

@@ -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),
}

View File

@@ -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)

View File

@@ -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(() => {

View File

@@ -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)
}),
})

View File

@@ -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
})

View File

@@ -56,6 +56,7 @@ export default antfu(
},
},
e18e: false,
pnpm: false,
},
{
plugins: {

View File

@@ -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',
}),

View File

@@ -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

File diff suppressed because it is too large Load Diff

View File

@@ -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,

View File

@@ -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,
})

View File

@@ -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