From 4918a4b963a1511d5fbc0c17c59d79b01e0f24d9 Mon Sep 17 00:00:00 2001 From: elrrrrrrr Date: Fri, 27 Mar 2026 19:07:19 +0800 Subject: [PATCH 01/10] chore(ci): migrate from pnpm to utoo for dependency management - Replace pnpm/action-setup with setup-utoo in all CI jobs - Use ut install --from pnpm for dependency installation - Replace pnpm run/filter commands with ut run equivalents - Use --workspaces --if-present for topological workspace execution - Use --workspace for targeted package execution - Use -- passthrough for tsdown args (ut run build -- --workspace) - Remove pnpm dedupe --check step (no longer needed) - Fix tools/scripts ci script to use ut run cov --- .github/workflows/ci.yml | 53 +++++++++++++++++--------------------- package.json | 27 ++++++++++--------- tools/scripts/package.json | 4 +-- 3 files changed, 38 insertions(+), 46 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3f51ba81f9..17383416c4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -27,35 +27,31 @@ jobs: - name: Checkout repository uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6 - - name: Install pnpm - uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4 + - name: Setup utoo + uses: utooland/setup-utoo@3a51006d0b66afcc32d1b9177a4b200b74f4a8cb # main - name: Set up Node.js uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6 with: node-version: '24' - cache: 'pnpm' - name: Install dependencies - run: pnpm install --frozen-lockfile + run: ut install --from pnpm - name: Run lint - run: pnpm run lint - - - name: Check dedupe - run: pnpm dedupe --check + run: ut run lint - name: Run typecheck - run: pnpm run typecheck + run: ut run typecheck - name: Run format check - run: pnpm run fmtcheck + run: ut run fmtcheck - name: Run build - run: pnpm run build + run: ut run build - name: Run site build - run: pnpm run site:build + run: ut run site:build test: strategy: @@ -157,25 +153,24 @@ jobs: # & mysqladmin -u root password root & mysql -uroot -e "CREATE DATABASE IF NOT EXISTS test;" - - name: Install pnpm - uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4 + - name: Setup utoo + uses: utooland/setup-utoo@3a51006d0b66afcc32d1b9177a4b200b74f4a8cb # main - name: Set up Node.js uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6 with: node-version: ${{ matrix.node }} - cache: 'pnpm' - name: Install dependencies - run: pnpm install --frozen-lockfile + run: ut install --from pnpm - name: Run tests - run: pnpm run ci --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }} + run: ut run ci -- --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }} - name: Run example tests if: ${{ matrix.node != '20' && matrix.os != 'windows-latest' }} run: | - pnpm run example:test:all + ut run example:test:all - name: Code Coverage # skip on windows, it will hangup on codecov @@ -205,22 +200,21 @@ jobs: - name: Checkout repository uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6 - - name: Install pnpm - uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4 + - name: Setup utoo + uses: utooland/setup-utoo@3a51006d0b66afcc32d1b9177a4b200b74f4a8cb # main - name: Set up Node.js uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6 with: node-version: ${{ matrix.node }} - cache: 'pnpm' - name: Install dependencies - run: pnpm install --frozen-lockfile + run: ut install --from pnpm - name: Run tests run: | - pnpm build --workspace ./tools/egg-bin - pnpm run --filter ./tools/egg-bin ci + ut run build -- --workspace ./tools/egg-bin + ut run ci --workspace ./tools/egg-bin env: # https://github.com/jamiebuilds/ci-parallel-vars CI_NODE_INDEX: ${{ matrix.shardIndex }} @@ -251,22 +245,21 @@ jobs: - name: Checkout repository uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6 - - name: Install pnpm - uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4 + - name: Setup utoo + uses: utooland/setup-utoo@3a51006d0b66afcc32d1b9177a4b200b74f4a8cb # main - name: Set up Node.js uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6 with: node-version: ${{ matrix.node }} - cache: 'pnpm' - name: Install dependencies - run: pnpm install --frozen-lockfile + run: ut install --from pnpm - name: Run tests run: | - pnpm build - pnpm run --filter=./tools/scripts ci + ut run build + ut run ci --workspace ./tools/scripts - name: Code Coverage if: ${{ matrix.os != 'windows-latest' }} diff --git a/package.json b/package.json index e8f828791c..c21be7babb 100644 --- a/package.json +++ b/package.json @@ -13,26 +13,25 @@ ], "type": "module", "scripts": { - "clean-dist": "pnpm -r --parallel exec rimraf dist", - "clean": "pnpm -r --parallel run clean && pnpm clean-dist", + "clean-dist": "ut run clean --workspaces", "build": "tsdown", - "prelint": "pnpm clean-dist", + "prelint": "ut run clean-dist", "lint": "oxlint --type-aware --type-check --quiet", "fmt": "oxfmt", - "typecheck": "pnpm clean && pnpm -r run typecheck", + "typecheck": "ut run clean-dist && ut run typecheck --workspaces", "fmtcheck": "oxfmt --check .", - "pretest": "pnpm run clean && pnpm -r run pretest", + "pretest": "ut run clean-dist && ut run pretest --workspaces --if-present", "test": "vitest run --bail 1 --retry 2 --testTimeout 20000 --hookTimeout 20000", - "test:cov": "pnpm run test --coverage", - "preci": "pnpm -r --parallel run pretest", - "ci": "pnpm run test --coverage", - "site:dev": "pnpm --filter=site run dev", - "site:build": "pnpm --filter=site run build", + "test:cov": "ut run test -- --coverage", + "preci": "ut run pretest --workspaces --if-present", + "ci": "ut run test -- --coverage", + "site:dev": "ut run dev --workspace site", + "site:build": "ut run build --workspace site", "puml": "puml . --dest ./site", - "example:dev:commonjs": "pnpm --filter=helloworld-commonjs run dev", - "example:dev:typescript": "pnpm --filter=helloworld-typescript run dev", - "example:dev:tegg": "pnpm --filter=helloworld-tegg run dev", - "example:test:all": "pnpm --filter=helloworld-* run test", + "example:dev:commonjs": "ut run dev --workspace helloworld-commonjs", + "example:dev:typescript": "ut run dev --workspace helloworld-typescript", + "example:dev:tegg": "ut run dev --workspace helloworld-tegg", + "example:test:all": "ut run test --workspace helloworld-typescript && ut run test --workspace helloworld-tegg", "prepare": "husky", "version:patch": "node scripts/version.js patch", "version:minor": "node scripts/version.js minor", diff --git a/tools/scripts/package.json b/tools/scripts/package.json index 895e386d60..3663293d22 100644 --- a/tools/scripts/package.json +++ b/tools/scripts/package.json @@ -50,8 +50,8 @@ "scripts": { "typecheck": "tsgo --noEmit", "test": "vitest run --bail 1 --no-file-parallelism", - "cov": "pnpm test --coverage", - "ci": "pnpm run cov" + "cov": "ut run test -- --coverage", + "ci": "ut run cov" }, "dependencies": { "@eggjs/utils": "workspace:*", From cdc29a52875717524f783e5164afa66f595ecd15 Mon Sep 17 00:00:00 2001 From: elrrrrrrr Date: Fri, 27 Mar 2026 19:14:41 +0800 Subject: [PATCH 02/10] fix(ci): add unplugin-unused to root devDependencies ut does not install optional peer deps automatically, so unplugin-unused (required by tsdown's unused.level feature) must be declared explicitly. Also includes workspaces/overrides fields auto-resolved from pnpm config by ut install. --- package.json | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/package.json b/package.json index c21be7babb..b2abf85e69 100644 --- a/package.json +++ b/package.json @@ -8,6 +8,16 @@ "type": "git", "url": "git+https://github.com/eggjs/egg.git" }, + "workspaces": [ + "packages/*", + "plugins/*", + "examples/*", + "tools/*", + "site", + "tegg/core/*", + "tegg/plugin/*", + "tegg/standalone/*" + ], "files": [ "README.md" ], @@ -66,9 +76,13 @@ "tsdown": "catalog:", "tsx": "catalog:", "typescript": "catalog:", + "unplugin-unused": "catalog:", "urllib": "catalog:", "vitest": "catalog:" }, + "overrides": { + "vite": "npm:rolldown-vite@^7.1.13" + }, "lint-staged": { "*": [ "oxfmt --no-error-on-unmatched-pattern", From 1478ae3e2ed5a3c94a22a1b556211aea0a957710 Mon Sep 17 00:00:00 2001 From: elrrrrrrr Date: Fri, 27 Mar 2026 19:18:37 +0800 Subject: [PATCH 03/10] fix(build): force publint to use npm pack instead of pnpm publint auto-detects pnpm via pnpm-lock.yaml and calls pnpm pack, but pnpm is not on PATH when using setup-utoo. Set pack: 'npm' explicitly so pnpm binary is not required for publint checks. --- tsdown.config.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/tsdown.config.ts b/tsdown.config.ts index 389c514ae1..12ff5fa10c 100644 --- a/tsdown.config.ts +++ b/tsdown.config.ts @@ -22,6 +22,7 @@ export default defineConfig({ publint: { level: 'suggestion', strict: true, + pack: 'npm', }, // Default entry pattern - glob to include all source files From c331e8e3de047d15fe5bbbb358d69b90c4bc86a7 Mon Sep 17 00:00:00 2001 From: elrrrrrrr Date: Fri, 27 Mar 2026 19:42:40 +0800 Subject: [PATCH 04/10] chore(ci): migrate e2e-test workflow to utoo - Replace pnpm/action-setup with setup-utoo - Use ut install --from pnpm for dependency installation - Use ut run build for building all packages - Replace pnpm -r pack with npm pack --workspaces - Sync pnpm-lock.yaml to include unplugin-unused --- .github/workflows/e2e-test.yml | 11 +++++------ pnpm-lock.yaml | 19 +++++++++---------- 2 files changed, 14 insertions(+), 16 deletions(-) diff --git a/.github/workflows/e2e-test.yml b/.github/workflows/e2e-test.yml index 969c3b9526..1eb55100ff 100644 --- a/.github/workflows/e2e-test.yml +++ b/.github/workflows/e2e-test.yml @@ -138,24 +138,23 @@ jobs: with: ecosystem-ci-project: ${{ matrix.project.name }} - - name: Install pnpm - uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4 + - name: Setup utoo + uses: utooland/setup-utoo@3a51006d0b66afcc32d1b9177a4b200b74f4a8cb # main - name: Set up Node.js uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6 with: node-version: ${{ matrix.project.node-version }} - cache: 'pnpm' - name: Install dependencies - run: pnpm install --frozen-lockfile + run: ut install --from pnpm - name: Build all packages - run: pnpm build + run: ut run build - name: Pack packages into tgz run: | - pnpm -r pack + npm pack --workspaces - name: Override dependencies from tgz in ${{ matrix.project.name }} working-directory: ecosystem-ci/${{ matrix.project.name }} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7755709050..508ad0a2eb 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -570,6 +570,9 @@ catalogs: typescript: specifier: ^5.9.3 version: 5.9.3 + unplugin-unused: + specifier: ^0.5.4 + version: 0.5.4 urijs: specifier: ^1.19.11 version: 1.19.11 @@ -675,6 +678,9 @@ importers: typescript: specifier: 'catalog:' version: 5.9.3 + unplugin-unused: + specifier: 'catalog:' + version: 0.5.4 urllib: specifier: 'catalog:' version: 4.8.2 @@ -10173,7 +10179,6 @@ snapshots: dependencies: '@jridgewell/gen-mapping': 0.3.13 '@jridgewell/trace-mapping': 0.3.31 - optional: true '@jridgewell/resolve-uri@3.1.2': {} @@ -12136,8 +12141,7 @@ snapshots: concat-map@0.0.1: {} - confbox@0.2.2: - optional: true + confbox@0.2.2: {} config-chain@1.1.13: dependencies: @@ -12741,8 +12745,7 @@ snapshots: transitivePeerDependencies: - supports-color - exsolve@1.0.7: - optional: true + exsolve@1.0.7: {} extend-shallow@2.0.1: dependencies: @@ -14885,7 +14888,6 @@ snapshots: confbox: 0.2.2 exsolve: 1.0.7 pathe: 2.0.3 - optional: true platform@1.3.6: {} @@ -15945,7 +15947,6 @@ snapshots: js-tokens: 9.0.1 pkg-types: 2.3.0 unplugin: 2.3.10 - optional: true unplugin@2.3.10: dependencies: @@ -15953,7 +15954,6 @@ snapshots: acorn: 8.15.0 picomatch: 4.0.3 webpack-virtual-modules: 0.6.2 - optional: true unrun@0.2.20: dependencies: @@ -16169,8 +16169,7 @@ snapshots: web-streams-polyfill@4.0.0-beta.3: {} - webpack-virtual-modules@0.6.2: - optional: true + webpack-virtual-modules@0.6.2: {} whatwg-encoding@3.1.1: dependencies: From 6dbd2ffcf4ddaea171d2651e7717dfce21ccad74 Mon Sep 17 00:00:00 2001 From: elrrrrrrr Date: Fri, 27 Mar 2026 19:52:38 +0800 Subject: [PATCH 05/10] fix(ci): replace npm pack --workspaces with pack-all.mjs script npm pack --workspaces fails on packages without version (e.g. site). Also, pnpm -r pack places tarballs in workspace root, while npm pack places them in each package's own directory. pack-all.mjs replicates pnpm -r pack behavior: - reads workspace patterns from pnpm-workspace.yaml - skips private/unnamed/unversioned packages - packs each with --pack-destination to workspace root --- .github/workflows/e2e-test.yml | 2 +- ecosystem-ci/pack-all.mjs | 23 +++++++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 ecosystem-ci/pack-all.mjs diff --git a/.github/workflows/e2e-test.yml b/.github/workflows/e2e-test.yml index 1eb55100ff..1dc1459799 100644 --- a/.github/workflows/e2e-test.yml +++ b/.github/workflows/e2e-test.yml @@ -154,7 +154,7 @@ jobs: - name: Pack packages into tgz run: | - npm pack --workspaces + node ecosystem-ci/pack-all.mjs - name: Override dependencies from tgz in ${{ matrix.project.name }} working-directory: ecosystem-ci/${{ matrix.project.name }} diff --git a/ecosystem-ci/pack-all.mjs b/ecosystem-ci/pack-all.mjs new file mode 100644 index 0000000000..dc567aff95 --- /dev/null +++ b/ecosystem-ci/pack-all.mjs @@ -0,0 +1,23 @@ +/** + * Pack all non-private workspace packages into the workspace root. + * Replicates `pnpm -r pack` behavior (pnpm places tarballs in workspace root). +import { execSync } from 'node:child_process'; + */ +import { readFileSync } from 'node:fs'; +import { glob } from 'node:fs/promises'; +import { dirname, join } from 'node:path'; +import { fileURLToPath } from 'node:url'; + +import yaml from 'js-yaml'; + +const rootDir = join(fileURLToPath(import.meta.url), '../..'); +const wsConfig = yaml.load(readFileSync(join(rootDir, 'pnpm-workspace.yaml'), 'utf8')); + +for (const pattern of wsConfig.packages ?? []) { + for await (const entry of glob(`${pattern}/package.json`, { cwd: rootDir })) { + const pkg = JSON.parse(readFileSync(join(rootDir, entry), 'utf8')); + if (pkg.private || !pkg.name || !pkg.version) continue; + const pkgDir = join(rootDir, dirname(entry)); + execSync(`npm pack --pack-destination "${rootDir}"`, { cwd: pkgDir, stdio: 'inherit' }); + } +} From f2605fdf769e82f424f64de4e2ba0dc826ef3f58 Mon Sep 17 00:00:00 2001 From: elrrrrrrr Date: Fri, 27 Mar 2026 19:59:16 +0800 Subject: [PATCH 06/10] fix(e2e): restore execSync import broken by formatter in pack-all.mjs oxfmt reordered imports and placed execSync import inside the JSDoc comment block, making it unavailable at runtime. Co-Authored-By: Claude Sonnet 4.6 --- ecosystem-ci/pack-all.mjs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/ecosystem-ci/pack-all.mjs b/ecosystem-ci/pack-all.mjs index dc567aff95..08ca5d93b0 100644 --- a/ecosystem-ci/pack-all.mjs +++ b/ecosystem-ci/pack-all.mjs @@ -1,8 +1,4 @@ -/** - * Pack all non-private workspace packages into the workspace root. - * Replicates `pnpm -r pack` behavior (pnpm places tarballs in workspace root). import { execSync } from 'node:child_process'; - */ import { readFileSync } from 'node:fs'; import { glob } from 'node:fs/promises'; import { dirname, join } from 'node:path'; From 709d50ebb54ae2dfc738c9144258044271eade37 Mon Sep 17 00:00:00 2001 From: elrrrrrrr Date: Fri, 27 Mar 2026 20:23:20 +0800 Subject: [PATCH 07/10] fix(e2e): replace npm install/run with ut in e2e test commands npm does not understand catalog: protocol; ut install handles it correctly. Co-Authored-By: Claude Sonnet 4.6 --- .github/workflows/e2e-test.yml | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/.github/workflows/e2e-test.yml b/.github/workflows/e2e-test.yml index 1dc1459799..fa9b867344 100644 --- a/.github/workflows/e2e-test.yml +++ b/.github/workflows/e2e-test.yml @@ -47,25 +47,25 @@ jobs: - name: cnpmcore node-version: 24 command: | - npm install - npm run lint -- --quiet - npm run typecheck - npm run build - npm run prepublishOnly + ut install + ut run lint -- --quiet + ut run typecheck + ut run build + ut run prepublishOnly # Clean build artifacts to avoid double-loading (src + dist) - npm run clean + ut run clean # Run the full test suite echo "Preparing databases..." mysql -h 127.0.0.1 -u root -e "CREATE DATABASE IF NOT EXISTS cnpmcore_unittest" CNPMCORE_DATABASE_NAME=cnpmcore_unittest bash ./prepare-database-mysql.sh CNPMCORE_DATABASE_NAME=cnpmcore bash ./prepare-database-mysql.sh - npm run test:local + ut run test:local # Deployment test: start the app and verify it boots correctly - npm run clean - npm run tsc:prod + ut run clean + ut run tsc:prod # Overlay compiled .js onto source locations so both egg loader # and tegg module scanner find .js files at the expected paths cp -r dist/* . @@ -120,18 +120,18 @@ jobs: command: | # examples/helloworld https://github.com/eggjs/examples/blob/master/helloworld/package.json cd helloworld - npm install - npm run lint - npm run test - npm run prepublishOnly + ut install + ut run lint + ut run test + ut run prepublishOnly cd .. # examples/hello-tegg https://github.com/eggjs/examples/blob/master/hello-tegg/package.json cd hello-tegg - npm install - npm run lint - npm run test - npm run prepublishOnly + ut install + ut run lint + ut run test + ut run prepublishOnly steps: - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6 - uses: ./.github/actions/clone From 248df7c0d59312bfc170195f7d0df818b9c9d195 Mon Sep 17 00:00:00 2001 From: elrrrrrrr Date: Fri, 27 Mar 2026 20:32:57 +0800 Subject: [PATCH 08/10] fix(e2e): resolve catalog: and workspace: in pack-all.mjs before npm pack npm pack does not resolve pnpm catalog: or workspace: protocol entries, leaving them raw in the tgz package.json. Downstream npm install then fails with EUNSUPPORTEDPROTOCOL. Pre-resolve these to actual semver versions before packing, then restore the originals. Also revert downstream test commands back to npm install/run since cnpmcore/examples use plain semver and npm can install the cleaned tgzs. Co-Authored-By: Claude Sonnet 4.6 --- .github/workflows/e2e-test.yml | 34 ++++++++++++------------- ecosystem-ci/pack-all.mjs | 45 +++++++++++++++++++++++++++++++--- 2 files changed, 59 insertions(+), 20 deletions(-) diff --git a/.github/workflows/e2e-test.yml b/.github/workflows/e2e-test.yml index fa9b867344..1dc1459799 100644 --- a/.github/workflows/e2e-test.yml +++ b/.github/workflows/e2e-test.yml @@ -47,25 +47,25 @@ jobs: - name: cnpmcore node-version: 24 command: | - ut install - ut run lint -- --quiet - ut run typecheck - ut run build - ut run prepublishOnly + npm install + npm run lint -- --quiet + npm run typecheck + npm run build + npm run prepublishOnly # Clean build artifacts to avoid double-loading (src + dist) - ut run clean + npm run clean # Run the full test suite echo "Preparing databases..." mysql -h 127.0.0.1 -u root -e "CREATE DATABASE IF NOT EXISTS cnpmcore_unittest" CNPMCORE_DATABASE_NAME=cnpmcore_unittest bash ./prepare-database-mysql.sh CNPMCORE_DATABASE_NAME=cnpmcore bash ./prepare-database-mysql.sh - ut run test:local + npm run test:local # Deployment test: start the app and verify it boots correctly - ut run clean - ut run tsc:prod + npm run clean + npm run tsc:prod # Overlay compiled .js onto source locations so both egg loader # and tegg module scanner find .js files at the expected paths cp -r dist/* . @@ -120,18 +120,18 @@ jobs: command: | # examples/helloworld https://github.com/eggjs/examples/blob/master/helloworld/package.json cd helloworld - ut install - ut run lint - ut run test - ut run prepublishOnly + npm install + npm run lint + npm run test + npm run prepublishOnly cd .. # examples/hello-tegg https://github.com/eggjs/examples/blob/master/hello-tegg/package.json cd hello-tegg - ut install - ut run lint - ut run test - ut run prepublishOnly + npm install + npm run lint + npm run test + npm run prepublishOnly steps: - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6 - uses: ./.github/actions/clone diff --git a/ecosystem-ci/pack-all.mjs b/ecosystem-ci/pack-all.mjs index 08ca5d93b0..eeb46c5815 100644 --- a/ecosystem-ci/pack-all.mjs +++ b/ecosystem-ci/pack-all.mjs @@ -1,5 +1,5 @@ import { execSync } from 'node:child_process'; -import { readFileSync } from 'node:fs'; +import { readFileSync, writeFileSync } from 'node:fs'; import { glob } from 'node:fs/promises'; import { dirname, join } from 'node:path'; import { fileURLToPath } from 'node:url'; @@ -8,12 +8,51 @@ import yaml from 'js-yaml'; const rootDir = join(fileURLToPath(import.meta.url), '../..'); const wsConfig = yaml.load(readFileSync(join(rootDir, 'pnpm-workspace.yaml'), 'utf8')); +const catalog = wsConfig.catalog ?? {}; +// Build a map of workspace package versions for resolving workspace: protocol +const workspaceVersions = {}; for (const pattern of wsConfig.packages ?? []) { for await (const entry of glob(`${pattern}/package.json`, { cwd: rootDir })) { const pkg = JSON.parse(readFileSync(join(rootDir, entry), 'utf8')); + if (pkg.name && pkg.version) workspaceVersions[pkg.name] = pkg.version; + } +} + +function resolveVersion(name, version) { + if (typeof version !== 'string') return version; + if (version === 'catalog:' || version.startsWith('catalog:')) { + return catalog[name] ?? version; + } + if (version.startsWith('workspace:')) { + return workspaceVersions[name] ? `^${workspaceVersions[name]}` : version; + } + return version; +} + +function resolveDeps(deps) { + if (!deps) return deps; + return Object.fromEntries(Object.entries(deps).map(([k, v]) => [k, resolveVersion(k, v)])); +} + +for (const pattern of wsConfig.packages ?? []) { + for await (const entry of glob(`${pattern}/package.json`, { cwd: rootDir })) { + const pkgPath = join(rootDir, entry); + const original = readFileSync(pkgPath, 'utf8'); + const pkg = JSON.parse(original); if (pkg.private || !pkg.name || !pkg.version) continue; - const pkgDir = join(rootDir, dirname(entry)); - execSync(`npm pack --pack-destination "${rootDir}"`, { cwd: pkgDir, stdio: 'inherit' }); + + const patched = { + ...pkg, + dependencies: resolveDeps(pkg.dependencies), + peerDependencies: resolveDeps(pkg.peerDependencies), + optionalDependencies: resolveDeps(pkg.optionalDependencies), + }; + writeFileSync(pkgPath, JSON.stringify(patched, null, 2) + '\n'); + try { + execSync(`npm pack --pack-destination "${rootDir}"`, { cwd: join(rootDir, dirname(entry)), stdio: 'inherit' }); + } finally { + writeFileSync(pkgPath, original); + } } } From 277e47896b8ba87b18847ccbb777f67825be5cf0 Mon Sep 17 00:00:00 2001 From: elrrrrrrr Date: Fri, 27 Mar 2026 20:45:33 +0800 Subject: [PATCH 09/10] fix(e2e): apply publishConfig overrides in pack-all.mjs before npm pack npm pack does not apply publishConfig.exports automatically. Packages use devExports (src/) in exports and dist/ in publishConfig.exports. Without merging publishConfig first, the tgz contains src/ exports and downstream npm install fails to find the source files. Co-Authored-By: Claude Sonnet 4.6 --- ecosystem-ci/pack-all.mjs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ecosystem-ci/pack-all.mjs b/ecosystem-ci/pack-all.mjs index eeb46c5815..62236ab0c7 100644 --- a/ecosystem-ci/pack-all.mjs +++ b/ecosystem-ci/pack-all.mjs @@ -42,8 +42,14 @@ for (const pattern of wsConfig.packages ?? []) { const pkg = JSON.parse(original); if (pkg.private || !pkg.name || !pkg.version) continue; + // Apply publishConfig overrides (npm pack does not do this automatically) + const publishConfig = pkg.publishConfig ?? {}; + const publishOverrides = Object.fromEntries( + Object.entries(publishConfig).filter(([k]) => !['access', 'registry', 'tag'].includes(k)), + ); const patched = { ...pkg, + ...publishOverrides, dependencies: resolveDeps(pkg.dependencies), peerDependencies: resolveDeps(pkg.peerDependencies), optionalDependencies: resolveDeps(pkg.optionalDependencies), From 9e89ed20943897db52f1ba994796f1eb7e38d936 Mon Sep 17 00:00:00 2001 From: elrrrrrrr Date: Fri, 27 Mar 2026 20:47:08 +0800 Subject: [PATCH 10/10] fix(ci): remove ./ prefix from ut --workspace paths utoo does not recognize workspace paths with ./ prefix. Change ./tools/egg-bin and ./tools/scripts to tools/egg-bin and tools/scripts respectively. Co-Authored-By: Claude Sonnet 4.6 --- .github/workflows/ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 17383416c4..a897c48567 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -213,8 +213,8 @@ jobs: - name: Run tests run: | - ut run build -- --workspace ./tools/egg-bin - ut run ci --workspace ./tools/egg-bin + ut run build -- --workspace tools/egg-bin + ut run ci --workspace tools/egg-bin env: # https://github.com/jamiebuilds/ci-parallel-vars CI_NODE_INDEX: ${{ matrix.shardIndex }} @@ -259,7 +259,7 @@ jobs: - name: Run tests run: | ut run build - ut run ci --workspace ./tools/scripts + ut run ci --workspace tools/scripts - name: Code Coverage if: ${{ matrix.os != 'windows-latest' }}