Ver Fonte

Merge pull request #10945 from growilabs/support/upgrade-vite

support: Upgrade vite v6, vitest v3, and related packages
mergify[bot] há 4 dias atrás
pai
commit
df4a38f291

+ 21 - 0
.claude/rules/coding-style.md

@@ -201,6 +201,27 @@ Implemented react-window for virtualizing page tree
 to improve performance with 10k+ pages.
 ```
 
+## Cross-Platform Compatibility
+
+GROWI must work on Windows, macOS, and Linux. Never use platform-specific shell commands in npm scripts.
+
+```json
+// ❌ WRONG: Unix-only commands in npm scripts
+"clean": "rm -rf dist",
+"copy": "cp src/foo.ts dist/foo.ts",
+"move": "mv src dist"
+
+// ✅ CORRECT: Cross-platform tools
+"clean": "rimraf dist",
+"copy": "node -e \"require('fs').cpSync('src/foo.ts','dist/foo.ts')\"",
+"move": "node -e \"require('fs').renameSync('src','dist')\""
+```
+
+**Rules**:
+- Use `rimraf` instead of `rm -rf`
+- Use Node.js one-liners or cross-platform tools (`cpy-cli`, `cpx2`) instead of `cp`, `mv`, `echo`, `ls`
+- Never assume a POSIX shell in npm scripts
+
 ## Code Quality Checklist
 
 Before marking work complete:

+ 0 - 2
.github/workflows/ci-app-prod.yml

@@ -9,7 +9,6 @@ on:
       - .github/mergify.yml
       - .github/workflows/ci-app-prod.yml
       - .github/workflows/reusable-app-prod.yml
-      - .github/workflows/reusable-app-reg-suit.yml
       - tsconfig.base.json
       - turbo.json
       - pnpm-lock.yaml
@@ -23,7 +22,6 @@ on:
       - .github/mergify.yml
       - .github/workflows/ci-app-prod.yml
       - .github/workflows/reusable-app-prod.yml
-      - .github/workflows/reusable-app-reg-suit.yml
       - tsconfig.base.json
       - pnpm-lock.yaml
       - turbo.json

+ 0 - 88
.github/workflows/reusable-app-reg-suit.yml

@@ -1,88 +0,0 @@
-name: Reusable VRT reporting workflow for production
-
-on:
-  workflow_call:
-    inputs:
-      node-version:
-        required: true
-        type: string
-      checkout-ref:
-        type: string
-        default: ${{ github.head_ref }}
-      skip-reg-suit:
-        type: boolean
-      cypress-report-artifact-name-pattern:
-        required: true
-        type: string
-    secrets:
-      REG_NOTIFY_GITHUB_PLUGIN_CLIENTID:
-        required: true
-      AWS_ACCESS_KEY_ID:
-        required: true
-      AWS_SECRET_ACCESS_KEY:
-        required: true
-      SLACK_WEBHOOK_URL:
-        required: true
-    outputs:
-      EXPECTED_IMAGES_EXIST:
-        value: ${{ jobs.run-reg-suit.outputs.EXPECTED_IMAGES_EXIST }}
-
-
-jobs:
-
-  run-reg-suit:
-    # use secrets for "VRT" environment
-    # https://github.com/growilabs/growi/settings/environments/376165508/edit
-    environment: VRT
-
-    if: ${{ !inputs.skip-reg-suit }}
-
-    env:
-      REG_NOTIFY_GITHUB_PLUGIN_CLIENTID: ${{ secrets.REG_NOTIFY_GITHUB_PLUGIN_CLIENTID }}
-      AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
-      AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
-      SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
-
-    runs-on: ubuntu-latest
-
-    outputs:
-      EXPECTED_IMAGES_EXIST: ${{ steps.check-expected-images.outputs.EXPECTED_IMAGES_EXIST }}
-
-    steps:
-    - uses: actions/checkout@v4
-      with:
-        ref: ${{ inputs.checkout-ref }}
-        fetch-depth: 0
-
-    - uses: pnpm/action-setup@v4
-
-    - uses: actions/setup-node@v4
-      with:
-        node-version: ${{ inputs.node-version }}
-        cache: 'pnpm'
-
-    - name: Install dependencies
-      run: |
-        pnpm install --frozen-lockfile
-
-    - name: Download screenshots taken by cypress
-      uses: actions/download-artifact@v4
-      with:
-        path: apps/app/test/cypress
-        pattern: ${{ inputs.cypress-report-artifact-name-pattern }}
-        merge-multiple: true
-
-    - name: Run reg-suit
-      working-directory: ./apps/app
-      run: |
-        pnpm run reg:run
-
-    - name: Slack Notification
-      uses: weseek/ghaction-slack-notification@master
-      if: failure()
-      with:
-        type: ${{ job.status }}
-        job_name: '*Node CI for growi - run-reg-suit (${{ inputs.node-version }})*'
-        channel: '#ci'
-        isCompactMode: true
-        url: ${{ secrets.SLACK_WEBHOOK_URL }}

+ 31 - 0
apps/app/bin/postbuild-server.ts

@@ -0,0 +1,31 @@
+/**
+ * Post-build script for server compilation.
+ *
+ * tspc compiles both `src/` and `config/` (which will be migrated to TypeScript),
+ * so the output directory (`transpiled/`) mirrors the source tree structure
+ * (e.g. `transpiled/src/`, `transpiled/config/`).
+ *
+ * Setting `rootDir: "src"` and `outDir: "dist"` in tsconfig would eliminate this script,
+ * but that would break once `config/` is included in the compilation.
+ * Instead, this script extracts only `transpiled/src/` into `dist/` and discards the rest.
+ */
+import { readdirSync, renameSync, rmSync } from 'node:fs';
+
+const TRANSPILED_DIR = 'transpiled';
+const DIST_DIR = 'dist';
+const SRC_SUBDIR = `${TRANSPILED_DIR}/src`;
+
+// List transpiled contents for debugging
+// biome-ignore lint/suspicious/noConsole: This is a build script, console output is expected.
+console.log('Listing files under transpiled:');
+// biome-ignore lint/suspicious/noConsole: This is a build script, console output is expected.
+console.log(readdirSync(TRANSPILED_DIR).join('\n'));
+
+// Remove old dist
+rmSync(DIST_DIR, { recursive: true, force: true });
+
+// Move transpiled/src -> dist
+renameSync(SRC_SUBDIR, DIST_DIR);
+
+// Remove leftover transpiled directory
+rmSync(TRANSPILED_DIR, { recursive: true, force: true });

+ 2 - 2
apps/app/package.json

@@ -9,8 +9,8 @@
     "start": "next start",
     "build:client": "next build",
     "build:server": "cross-env NODE_ENV=production tspc -p tsconfig.build.server.json",
-    "postbuild:server": "shx echo \"Listing files under transpiled\" && shx ls transpiled && shx rm -rf dist && shx mv transpiled/src dist && shx rm -rf transpiled",
-    "clean": "shx rm -rf dist transpiled .next next.config.js",
+    "postbuild:server": "node bin/postbuild-server.ts",
+    "clean": "rimraf dist transpiled .next next.config.js",
     "server": "cross-env NODE_ENV=production node -r dotenv-flow/config dist/server/app.js",
     "server:ci": "pnpm run server --ci",
     "preserver": "cross-env NODE_ENV=production pnpm run migrate",

+ 0 - 26
apps/app/regconfig.json

@@ -1,26 +0,0 @@
-{
-  "core": {
-    "workingDir": ".reg",
-    "actualDir": "test/playwright/screenshots",
-    "thresholdRate": 0.001,
-    "addIgnore": true,
-    "ximgdiff": {
-      "invocationType": "client"
-    }
-  },
-  "plugins": {
-    "reg-keygen-git-hash-plugin": true,
-    "reg-notify-github-plugin": {
-      "prCommentBehavior": "new",
-      "setCommitStatus": false,
-      "shortDescription": true,
-      "clientId": "$REG_NOTIFY_GITHUB_PLUGIN_CLIENTID"
-    },
-    "reg-notify-slack-plugin": {
-      "webhookUrl": "$SLACK_WEBHOOK_URL"
-    },
-    "reg-publish-s3-plugin": {
-      "bucketName": "growi-vrt-snapshots"
-    }
-  }
-}

+ 1 - 1
apps/app/src/server/crowi/index.ts

@@ -50,7 +50,7 @@ import {
 } from '../service/g2g-transfer';
 import { GrowiBridgeService } from '../service/growi-bridge';
 import { initializeImportService } from '../service/import';
-import InAppNotificationService from '../service/in-app-notification';
+import { InAppNotificationService } from '../service/in-app-notification';
 import { InstallerService } from '../service/installer';
 import { normalizeData } from '../service/normalize-data';
 import PageService from '../service/page';

+ 1 - 1
apps/app/src/server/middlewares/exclude-read-only-user.spec.ts

@@ -44,7 +44,7 @@ describe('excludeReadOnlyUser', () => {
 
     expect(next).not.toBeCalled();
     expect(res.apiv3Err).toBeCalledWith(
-      new ErrorV3('This user is read only user', 'validatioin_failed'),
+      new ErrorV3('This user is read only user', 'validation_failed'),
     );
   });
 });

+ 1 - 3
apps/app/src/server/service/in-app-notification.ts

@@ -24,7 +24,7 @@ const { STATUS_UNOPENED, STATUS_OPENED } = InAppNotificationStatuses;
 
 const logger = loggerFactory('growi:service:inAppNotification');
 
-export default class InAppNotificationService {
+export class InAppNotificationService {
   crowi!: Crowi;
 
   socketIoService!: any;
@@ -254,5 +254,3 @@ export default class InAppNotificationService {
     return;
   };
 }
-
-module.exports = InAppNotificationService;

+ 14 - 2
apps/app/vitest.workspace.mts

@@ -1,13 +1,18 @@
 import react from '@vitejs/plugin-react';
 import tsconfigPaths from 'vite-tsconfig-paths';
-import { defineConfig, defineWorkspace, mergeConfig } from 'vitest/config';
+import {
+  defaultExclude,
+  defineConfig,
+  defineWorkspace,
+  mergeConfig,
+} from 'vitest/config';
 
 const configShared = defineConfig({
   plugins: [tsconfigPaths()],
   test: {
     clearMocks: true,
     globals: true,
-    exclude: ['playwright/**'],
+    exclude: [...defaultExclude, 'playwright/**', 'tmp/**'],
   },
 });
 
@@ -27,6 +32,13 @@ export default defineWorkspace([
       // Prefer require (CJS) for server-side packages
       conditions: ['require', 'node', 'default'],
     },
+    ssr: {
+      resolve: {
+        // Vite 6+: SSR uses ssr.resolve.conditions (default: ['node', 'import']).
+        // Override to match resolve.conditions so CJS-only server packages resolve correctly.
+        conditions: ['require', 'node', 'default'],
+      },
+    },
     test: {
       name: 'app-integration',
       environment: 'node',

+ 1 - 1
apps/slackbot-proxy/package.json

@@ -5,7 +5,7 @@
   "private": true,
   "scripts": {
     "build": "tspc -p tsconfig.build.json",
-    "clean": "shx rm -rf dist",
+    "clean": "rimraf dist",
     "cp:public": "cp -RT ./src/public ./dist/public",
     "cp:views": "cp -RT ./src/views ./dist/views",
     "cp:bootstrap": "cp -RT ./node_modules/bootstrap/dist ./dist/public/bootstrap",

+ 12 - 16
package.json

@@ -57,23 +57,19 @@
     "@types/glob": "^8.1.0",
     "@types/node": "^24.0.0",
     "@typescript/native-preview": "7.0.0-dev.20260114.1",
-    "@vitejs/plugin-react": "^4.3.1",
-    "@vitest/coverage-v8": "^2.1.1",
-    "@vitest/ui": "^2.1.1",
+    "@vitejs/plugin-react": "^4.7.0",
+    "@vitest/coverage-v8": "^3.2.4",
+    "@vitest/ui": "^3.2.4",
+    "cpy-cli": "^7.0.0",
     "cross-env": "^7.0.0",
     "dotenv-flow": "^3.2.0",
     "glob": "^8.1.0",
     "lefthook": "^2.0.13",
     "mock-require": "^3.0.3",
-    "nodemon": "^3.1.3",
-    "npm-run-all": "^4.1.5",
-    "reg-keygen-git-hash-plugin": "^0.11.1",
-    "reg-notify-github-plugin": "^0.11.1",
-    "reg-notify-slack-plugin": "^0.11.0",
-    "reg-publish-s3-plugin": "^0.11.0",
-    "reg-suit": "^0.12.2",
+    "nodemon": "^3.1.14",
+    "npm-run-all2": "^8.0.4",
     "rollup-plugin-node-externals": "^6.1.1",
-    "shx": "^0.3.4",
+    "rimraf": "^6.1.3",
     "stylelint": "^16.5.0",
     "stylelint-config-recess-order": "^5.0.1",
     "stylelint-config-recommended-scss": "^14.0.0",
@@ -85,11 +81,11 @@
     "turbo": "^2.1.3",
     "typescript": "^5.9.3",
     "typescript-transform-paths": "^3.5.6",
-    "vite": "^5.4.21",
-    "vite-plugin-dts": "^3.9.1",
-    "vite-tsconfig-paths": "^5.0.1",
-    "vitest": "^2.1.1",
-    "vitest-mock-extended": "^2.0.2"
+    "vite": "^6.4.1",
+    "vite-plugin-dts": "^4.5.4",
+    "vite-tsconfig-paths": "^5.1.4",
+    "vitest": "^3.2.4",
+    "vitest-mock-extended": "^3.1.0"
   },
   "// comments for pnpm.overrides": {
     "@lykmapipo/common>flat": "flat v6 is provided only by ESM, but @lykmapipo/common requires CommonJS version",

+ 1 - 1
packages/core/package.json

@@ -65,7 +65,7 @@
   },
   "scripts": {
     "build": "vite build",
-    "clean": "shx rm -rf dist",
+    "clean": "rimraf dist",
     "dev": "vite build --mode dev",
     "watch": "pnpm run dev -w --emptyOutDir=false",
     "lint:biome": "biome check",

+ 1 - 1
packages/editor/package.json

@@ -9,7 +9,7 @@
   "module": "dist/index.js",
   "scripts": {
     "build": "tsc && vite build",
-    "clean": "shx rm -rf dist",
+    "clean": "rimraf dist",
     "dev": "vite build --mode dev",
     "watch": "pnpm run dev -w --emptyOutDir=false",
     "serve": "vite",

+ 1 - 0
packages/editor/vite.config.ts

@@ -91,6 +91,7 @@ export default defineConfig({
         ignore: [...excludeFiles, '**/*.spec.ts'],
       }),
       name: 'editor-libs',
+      cssFileName: 'style',
       formats: ['es'],
     },
     rollupOptions: {

+ 1 - 1
packages/pluginkit/package.json

@@ -16,7 +16,7 @@
   ],
   "scripts": {
     "build": "vite build",
-    "clean": "shx rm -rf dist",
+    "clean": "rimraf dist",
     "dev": "vite build --mode dev",
     "watch": "pnpm run dev -w --emptyOutDir=false",
     "lint:biome": "biome check",

+ 1 - 1
packages/presentation/package.json

@@ -31,7 +31,7 @@
   "scripts": {
     "generate:marpit-base-css": "node scripts/extract-marpit-css.ts",
     "build": "vite build",
-    "clean": "shx rm -rf dist",
+    "clean": "rimraf dist",
     "dev": "vite build --mode dev",
     "watch": "pnpm run dev -w --emptyOutDir=false",
     "lint:biome": "biome check",

+ 1 - 0
packages/presentation/vite.config.ts

@@ -27,6 +27,7 @@ export default defineConfig({
         ignore: '**/*.spec.ts',
       }),
       name: 'presentation-libs',
+      cssFileName: 'style',
       formats: ['es'],
     },
     rollupOptions: {

+ 1 - 1
packages/preset-themes/package.json

@@ -14,7 +14,7 @@
     "build": "run-p build:*",
     "build:libs": "vite -c vite.libs.config.ts build",
     "build:themes": "vite -c vite.themes.config.ts build",
-    "clean": "shx rm -rf dist",
+    "clean": "rimraf dist",
     "dev": "run-p dev:*",
     "dev:libs": "pnpm run build:libs --mode dev",
     "dev:themes": "pnpm run build:themes --mode dev",

+ 2 - 2
packages/remark-attachment-refs/package.json

@@ -30,7 +30,7 @@
     "build": "run-p build:*",
     "build:server": "vite build -c vite.server.config.ts",
     "build:client": "vite build -c vite.client.config.ts",
-    "clean": "shx rm -rf dist",
+    "clean": "rimraf dist",
     "dev": "run-p dev:*",
     "dev:server": "vite build -c vite.server.config.ts --mode dev",
     "dev:client": "vite build -c vite.client.config.ts --mode dev",
@@ -66,7 +66,7 @@
     "happy-dom": "^15.7.4",
     "hast-util-sanitize": "^5.0.1",
     "hast-util-select": "^6.0.2",
-    "npm-run-all": "^4.1.5",
+    "npm-run-all2": "^8.0.4",
     "supertest": "^7.0.0",
     "unified": "^11.0.0",
     "unist-util-visit": "^5.0.0"

+ 1 - 0
packages/remark-attachment-refs/vite.client.config.ts

@@ -27,6 +27,7 @@ export default defineConfig({
         index: 'src/client/index.ts',
       },
       name: 'remark-attachment-refs-libs',
+      cssFileName: 'style',
       formats: ['es'],
     },
   },

+ 1 - 1
packages/remark-drawio/package.json

@@ -22,7 +22,7 @@
   "typings": "dist/index.d.ts",
   "scripts": {
     "build": "vite build",
-    "clean": "shx rm -rf dist",
+    "clean": "rimraf dist",
     "dev": "vite build --mode dev",
     "watch": "pnpm run dev -w --emptyOutDir=false",
     "lint:biome": "biome check",

+ 1 - 0
packages/remark-drawio/vite.config.ts

@@ -26,6 +26,7 @@ export default defineConfig({
         index: 'src/index.ts',
       },
       name: 'remark-drawio-libs',
+      cssFileName: 'style',
       formats: ['es'],
     },
   },

+ 3 - 3
packages/remark-growi-directive/package.json

@@ -17,8 +17,8 @@
   "typings": "dist/index.d.ts",
   "scripts": {
     "build": "tsc -p tsconfig.build.json",
-    "postbuild": "shx cp ./src/mdast-util-growi-directive/index.d.ts ./dist/mdast-util-growi-directive/index.d.ts",
-    "clean": "shx rm -rf dist",
+    "postbuild": "cpy src/mdast-util-growi-directive/index.d.ts dist/mdast-util-growi-directive/",
+    "clean": "rimraf dist",
     "dev": "pnpm run build",
     "watch": "tsc -w",
     "test": "cross-env NODE_ENV=test npm run test-coverage",
@@ -49,7 +49,7 @@
     "mdast-util-from-markdown": "^2.0.1",
     "micromark": "^4.0.0",
     "remark": "^15.0.1",
-    "rimraf": "^3.0.0",
+    "rimraf": "^6.1.3",
     "to-vfile": "^7.0.0",
     "type-coverage": "^2.0.0",
     "unist-util-remove-position": "^5.0.0"

+ 1 - 1
packages/remark-lsx/package.json

@@ -16,7 +16,7 @@
     "build": "run-p build:*",
     "build:client": "vite build -c vite.client.config.ts",
     "build:server": "vite build -c vite.server.config.ts",
-    "clean": "shx rm -rf dist",
+    "clean": "rimraf dist",
     "dev": "run-p dev:*",
     "dev:client": "vite build -c vite.client.config.ts --mode dev",
     "dev:server": "vite build -c vite.server.config.ts --mode dev",

+ 1 - 3
packages/remark-lsx/src/server/routes/list-pages/add-depth-condition.spec.ts

@@ -40,9 +40,7 @@ describe('addDepthCondition()', () => {
 
       // then
       expect(caller).toThrowError(
-        new Error(
-          "The specified option 'depth' is { start: -1, end: 10 } : the start must be larger or equal than 1",
-        ),
+        "The specified option 'depth' is { start: -1, end: 10 } : the start must be larger or equal than 1",
       );
       expect(mocks.getDepthOfPathMock).not.toHaveBeenCalled();
     });

+ 1 - 0
packages/remark-lsx/vite.client.config.ts

@@ -27,6 +27,7 @@ export default defineConfig({
         index: 'src/client/index.ts',
       },
       name: 'remark-lsx-libs',
+      cssFileName: 'style',
       formats: ['es'],
     },
   },

+ 1 - 1
packages/slack/package.json

@@ -40,7 +40,7 @@
   },
   "scripts": {
     "build": "vite build",
-    "clean": "shx rm -rf dist",
+    "clean": "rimraf dist",
     "dev": "vite build --mode dev",
     "watch": "pnpm run dev -w --emptyOutDir=false",
     "lint:biome": "biome check",

+ 2 - 1
packages/ui/package.json

@@ -23,13 +23,14 @@
       "import": "./dist/utils/index.js"
     },
     "./dist/style": {
+      "style": "./dist/style.css",
       "import": "./dist/style.css"
     },
     "./scss/*": "./scss/*.scss"
   },
   "scripts": {
     "build": "vite build",
-    "clean": "shx rm -rf dist",
+    "clean": "rimraf dist",
     "dev": "vite build --mode dev",
     "watch": "pnpm run dev -w --emptyOutDir=false",
     "lint:biome": "biome check",

+ 1 - 0
packages/ui/vite.config.ts

@@ -29,6 +29,7 @@ export default defineConfig({
       }),
       name: 'ui-libs',
       formats: ['es'],
+      cssFileName: 'style',
     },
     rollupOptions: {
       output: {

Diff do ficheiro suprimidas por serem muito extensas
+ 263 - 251
pnpm-lock.yaml


Alguns ficheiros não foram mostrados porque muitos ficheiros mudaram neste diff