From 1568d35449798c64ce089c6f4c875b674c716e00 Mon Sep 17 00:00:00 2001 From: lwj <674416404@qq.com> Date: Fri, 15 May 2026 21:42:24 +0800 Subject: [PATCH 1/2] =?UTF-8?q?feat(cnb-delete-branch):=20=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E5=8D=95=E5=85=83=E6=B5=8B=E8=AF=95=E5=B9=B6=E9=85=8D?= =?UTF-8?q?=E7=BD=AE=20CI?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/ci.yml | 16 + package.json | 4 +- packages/cnb-delete-branch/dist/index.mjs | 6 +- packages/cnb-delete-branch/index.test.ts | 141 +++++ packages/cnb-delete-branch/index.ts | 28 +- pnpm-lock.yaml | 616 +++++++++++++++++++++- pnpm-workspace.yaml | 1 + 7 files changed, 791 insertions(+), 21 deletions(-) create mode 100644 packages/cnb-delete-branch/index.test.ts diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bdebd90..64a925f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -37,3 +37,19 @@ jobs: - run: pnpm run lint - run: pnpm run typecheck + + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + + - uses: pnpm/action-setup@v6 + + - uses: actions/setup-node@v6 + with: + node-version-file: .node-version + cache: pnpm + + - run: pnpm ci + + - run: pnpm run test diff --git a/package.json b/package.json index 19cbbd8..24e2b66 100644 --- a/package.json +++ b/package.json @@ -7,11 +7,13 @@ "build": "pnpm -r run build", "lint": "eslint", "lint:fix": "eslint --fix", + "test": "vitest run", "typecheck": "tsgo --noEmit" }, "devDependencies": { "@antfu/eslint-config": "catalog:", "@typescript/native-preview": "catalog:", - "eslint": "catalog:" + "eslint": "catalog:", + "vitest": "catalog:" } } diff --git a/packages/cnb-delete-branch/dist/index.mjs b/packages/cnb-delete-branch/dist/index.mjs index c7611f7..9dab18c 100644 --- a/packages/cnb-delete-branch/dist/index.mjs +++ b/packages/cnb-delete-branch/dist/index.mjs @@ -1,4 +1,6 @@ import { createRequire } from "node:module"; +import process$1 from "node:process"; +import { pathToFileURL } from "node:url"; import * as os$1 from "os"; import os, { EOL } from "os"; import * as fs from "fs"; @@ -16234,8 +16236,8 @@ async function main() { setFailed(error instanceof Error ? error.message : String(error)); } } -main().catch((error) => { +if (process$1.argv[1] && import.meta.url === pathToFileURL(process$1.argv[1]).href) main().catch((error) => { setFailed(`cnb-delete-branch failed: ${error instanceof Error ? error.message : String(error)}`); }); //#endregion -export {}; +export { CNBRequestError, deleteBranch, encodePath, fetchCNB, getPullBranchName, getPullRepoPath, listPulls, main, patchPull }; diff --git a/packages/cnb-delete-branch/index.test.ts b/packages/cnb-delete-branch/index.test.ts new file mode 100644 index 0000000..5735fa5 --- /dev/null +++ b/packages/cnb-delete-branch/index.test.ts @@ -0,0 +1,141 @@ +import type { PullRequest } from './types' +import { beforeEach, describe, expect, it, vi } from 'vitest' +import { + CNBRequestError, + deleteBranch, + encodePath, + fetchCNB, + getPullBranchName, + getPullRepoPath, + listPulls, + patchPull, +} from './index' + +vi.mock('@actions/core', () => ({ + endGroup: vi.fn(), + getInput: vi.fn(), + info: vi.fn(), + setFailed: vi.fn(), + startGroup: vi.fn(), +})) + +function mockFetchOnce(status: number, body = '', statusText = ''): void { + vi.mocked(fetch).mockResolvedValueOnce(new Response(body, { status, statusText })) +} + +function createPullRequest(number: string, ref = 'refs/heads/feature', repo = 'tdesign/test'): PullRequest { + return { + assignees: [], + author: {} as PullRequest['author'], + base: null, + blocked_on: '', + body: '', + comment_count: 0, + created_at: '', + head: { + ref, + repo: { + id: repo, + name: repo.split('/').at(-1) || repo, + path: repo, + web_url: '', + }, + sha: '', + }, + is_wip: false, + labels: [], + last_acted_at: '', + mergeable_state: '', + merged_by: {} as PullRequest['merged_by'], + number, + repo: {} as PullRequest['repo'], + review_count: 0, + state: 'open', + title: `PR ${number}`, + updated_at: '', + } +} + +describe('cnb-delete-branch', () => { + beforeEach(() => { + vi.stubGlobal('fetch', vi.fn()) + }) + + it('encodes repo paths but preserves path separators', () => { + expect(encodePath('tdesign/workflows')).toBe('tdesign/workflows') + expect(encodePath('tdesign/branch with space')).toBe('tdesign/branch%20with%20space') + }) + + it('sends CNB JSON headers and parses JSON responses', async () => { + mockFetchOnce(200, JSON.stringify({ ok: true })) + + await expect(fetchCNB('token', '/tdesign/test/-/pulls')).resolves.toEqual({ + status: 200, + data: { ok: true }, + }) + + expect(fetch).toHaveBeenCalledWith('https://api.cnb.cool/tdesign/test/-/pulls', { + headers: { + 'Accept': 'application/json', + 'Authorization': 'Bearer token', + 'Content-Type': 'application/json', + }, + }) + }) + + it('throws CNBRequestError for failed API responses', async () => { + mockFetchOnce(403, JSON.stringify({ errmsg: 'forbidden' }), 'Forbidden') + + await expect(fetchCNB('token', '/tdesign/test/-/pulls')).rejects.toMatchObject({ + message: '[CNB] GET /tdesign/test/-/pulls failed: forbidden', + status: 403, + }) + }) + + it('lists pull requests across pages', async () => { + const firstPage = Array.from({ length: 100 }, (_, index) => createPullRequest(String(index + 1))) + const secondPage = [createPullRequest('101')] + mockFetchOnce(200, JSON.stringify(firstPage)) + mockFetchOnce(200, JSON.stringify(secondPage)) + + const pulls = await listPulls('token', 'tdesign/test', 'open') + + expect(pulls).toHaveLength(101) + expect(fetch).toHaveBeenNthCalledWith( + 1, + 'https://api.cnb.cool/tdesign/test/-/pulls?state=open&page=1&page_size=100', + expect.any(Object), + ) + expect(fetch).toHaveBeenNthCalledWith( + 2, + 'https://api.cnb.cool/tdesign/test/-/pulls?state=open&page=2&page_size=100', + expect.any(Object), + ) + }) + + it('patches pull request state through the CNB pull endpoint', async () => { + mockFetchOnce(200, '{}') + + await expect(patchPull('token', 'tdesign/test', '12', { state: 'closed' })).resolves.toBe(true) + + expect(fetch).toHaveBeenCalledWith('https://api.cnb.cool/tdesign/test/-/pulls/12', expect.objectContaining({ + body: JSON.stringify({ state: 'closed' }), + method: 'PATCH', + })) + }) + + it('treats missing branch as a successful no-op but rethrows other delete failures', async () => { + mockFetchOnce(404, JSON.stringify({ errmsg: 'not found' }), 'Not Found') + await expect(deleteBranch('token', 'tdesign/test', 'feature')).resolves.toBe(false) + + mockFetchOnce(403, JSON.stringify({ errmsg: 'forbidden' }), 'Forbidden') + await expect(deleteBranch('token', 'tdesign/test', 'feature')).rejects.toBeInstanceOf(CNBRequestError) + }) + + it('reads pull branch and repo safely when head data is missing', () => { + expect(getPullBranchName(createPullRequest('1', 'refs/heads/feature/test'))).toBe('feature/test') + expect(getPullRepoPath(createPullRequest('1'))).toBe('tdesign/test') + expect(getPullBranchName({ head: null } as PullRequest)).toBeUndefined() + expect(getPullRepoPath({ head: null } as PullRequest)).toBeUndefined() + }) +}) diff --git a/packages/cnb-delete-branch/index.ts b/packages/cnb-delete-branch/index.ts index eaeaa85..b80eb6d 100644 --- a/packages/cnb-delete-branch/index.ts +++ b/packages/cnb-delete-branch/index.ts @@ -1,4 +1,6 @@ import type { PullRequest } from './types' +import process from 'node:process' +import { pathToFileURL } from 'node:url' import * as core from '@actions/core' const CNB_API_URL = 'https://api.cnb.cool' @@ -9,7 +11,7 @@ interface CNBResponse { data?: T } -class CNBRequestError extends Error { +export class CNBRequestError extends Error { constructor(message: string, public status: number) { super(message) this.name = 'CNBRequestError' @@ -28,19 +30,19 @@ function parseJson(text: string): T | undefined { } } -function encodePath(value: string): string { +export function encodePath(value: string): string { return value.split('/').map(encodeURIComponent).join('/') } -function getPullRepoPath(pr: PullRequest): string | undefined { +export function getPullRepoPath(pr: PullRequest): string | undefined { return pr.head?.repo?.path } -function getPullBranchName(pr: PullRequest): string | undefined { +export function getPullBranchName(pr: PullRequest): string | undefined { return pr.head?.ref?.replace(/^refs\/heads\//, '') } -async function fetchCNB( +export async function fetchCNB( token: string, path: string, options?: RequestInit, @@ -74,7 +76,7 @@ async function fetchCNB( } } -async function listPulls(token: string, repo: string, state: string): Promise { +export async function listPulls(token: string, repo: string, state: string): Promise { const pulls: PullRequest[] = [] for (let page = 1; ; page += 1) { @@ -94,7 +96,7 @@ async function listPulls(token: string, repo: string, state: string): Promise { +export async function deleteBranch(token: string, repo: string, branch: string): Promise { try { await fetchCNB(token, `/${encodePath(repo)}/-/git/branches/${encodePath(branch)}`, { method: 'DELETE', @@ -122,7 +124,7 @@ async function deleteBranch(token: string, repo: string, branch: string): Promis } } -async function main(): Promise { +export async function main(): Promise { const repo = core.getInput('repo', { required: true }) const branch = core.getInput('branch', { required: true }) const token = core.getInput('token', { required: true }) @@ -175,6 +177,8 @@ async function main(): Promise { } } -main().catch((error) => { - core.setFailed(`cnb-delete-branch failed: ${error instanceof Error ? error.message : String(error)}`) -}) +if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) { + main().catch((error) => { + core.setFailed(`cnb-delete-branch failed: ${error instanceof Error ? error.message : String(error)}`) + }) +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3b6514f..007bba5 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -33,6 +33,9 @@ catalogs: tsdown: specifier: ^0.22.0 version: 0.22.0 + vitest: + specifier: ^4.1.6 + version: 4.1.6 importers: @@ -40,13 +43,16 @@ importers: devDependencies: '@antfu/eslint-config': specifier: 'catalog:' - version: 8.3.0(@typescript-eslint/rule-tester@8.56.1(eslint@10.3.0)(typescript@5.9.3))(@typescript-eslint/typescript-estree@8.59.3(typescript@5.9.3))(@typescript-eslint/utils@8.59.3(eslint@10.3.0)(typescript@5.9.3))(@vue/compiler-sfc@3.5.24)(eslint@10.3.0)(typescript@5.9.3) + version: 8.3.0(@typescript-eslint/rule-tester@8.56.1(eslint@10.3.0)(typescript@5.9.3))(@typescript-eslint/typescript-estree@8.59.3(typescript@5.9.3))(@typescript-eslint/utils@8.59.3(eslint@10.3.0)(typescript@5.9.3))(@vue/compiler-sfc@3.5.24)(eslint@10.3.0)(typescript@5.9.3)(vitest@4.1.6(@types/node@24.12.4)(vite@8.0.13(@types/node@24.12.4)(yaml@2.8.2))) '@typescript/native-preview': specifier: 'catalog:' version: 7.0.0-dev.20260515.1 eslint: specifier: 'catalog:' version: 10.3.0 + vitest: + specifier: 'catalog:' + version: 4.1.6(@types/node@24.12.4)(vite@8.0.13(@types/node@24.12.4)(yaml@2.8.2)) packages/close-release-issue: dependencies: @@ -440,6 +446,9 @@ packages: '@oxc-project/types@0.129.0': resolution: {integrity: sha512-3oz8m3FGdr2nDXVqmFUw7jolKliC4MoyXYIG2c7gpjBnzUWQpUGIYcXYKxTdTi+N2jusvt610ckTMkxdwHkYEg==} + '@oxc-project/types@0.130.0': + resolution: {integrity: sha512-ibD2usx9JRu7f5pu2tMKMI4cpA4NgXJQoYRP4pQ7Pxmn1l6k/53qWtQWZayhYy3X4QZkt90Ot+mJEaeXouio6Q==} + '@pkgr/core@0.2.9': resolution: {integrity: sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==} engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} @@ -453,30 +462,60 @@ packages: cpu: [arm64] os: [android] + '@rolldown/binding-android-arm64@1.0.1': + resolution: {integrity: sha512-fJI3I0r3C3Oj/zdBCpaCmBRZYf07xpaq4yCfDDoSFm+beWNzbIl26puW8RraUdugoJw/95zerNOn6jasAhzSmg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [android] + '@rolldown/binding-darwin-arm64@1.0.0': resolution: {integrity: sha512-6XcD+8k0gPVItNagEw78/qqcBDwKcwDYS8V2hRmVsfUSIrd8cWe/CBvRDI5toqFyPfj+FJr6t8U6Xj2P2prEew==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [darwin] + '@rolldown/binding-darwin-arm64@1.0.1': + resolution: {integrity: sha512-cKnAhWEsV7TPcA/5EAteDp6KcJZBQ2G+BqE7zayMMi7kMvwRsbv7WT9aOnn0WNl4SKEIf43vjS31iUPu80nzXg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [darwin] + '@rolldown/binding-darwin-x64@1.0.0': resolution: {integrity: sha512-iN/tWVXRQDWvmZlKdceP1Dwug9GDpEymhb9p4xnEe6zvCg5lFmzVljl+1qR1NVx3yfGpr2Na+CuLmv5IU8uzfQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [darwin] + '@rolldown/binding-darwin-x64@1.0.1': + resolution: {integrity: sha512-YKrVwQjIRBPo+5G/u03wGjbdy4q7pyzCe93DK9VJ7zkVmeg8LJ7GbgsiHWdR4xSoe4CAXRD7Bcjgbtr64bkXNg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [darwin] + '@rolldown/binding-freebsd-x64@1.0.0': resolution: {integrity: sha512-jjQMDvvwSOuhOwMszD/klSOjyWMM3zI64hWTj9KT5x4MxRbZAf+7vLQ6qouRhtsLVFHr3f0ILaJAfgENPiQdAQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [freebsd] + '@rolldown/binding-freebsd-x64@1.0.1': + resolution: {integrity: sha512-z/oBsREo46SsFqBwYtFe0kpJeBijAT48O/WXLI4suiCLBkr03RTtTJMCzSdDd2znlh8VJizL09XVkQgk8IZonw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [freebsd] + '@rolldown/binding-linux-arm-gnueabihf@1.0.0': resolution: {integrity: sha512-d//Dtg2x6/m3mbV64yUGNnDGNZaDGRpDLLNGerHQUVObuNaIQaaDp25yUiqGXtHEXX+NP2d0wAlmKgpYgIAJ2A==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [linux] + '@rolldown/binding-linux-arm-gnueabihf@1.0.1': + resolution: {integrity: sha512-ik8q7GM11zxvYxFc2PeDcT6TBvhCQMaUxfph/M5l9sKuTs/Sjg3L+Byw0F7w0ZVLBZmx30P+gG0ECzzN+MFcmQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + '@rolldown/binding-linux-arm64-gnu@1.0.0': resolution: {integrity: sha512-n7Ofp0mx+aB2cC+Sdy5YtMnXtY9lchnHbY+3Yt0uq9JsWQExf4f5Whu0tK0R8Jdc9S6RchTHjIFY7uc92puOVQ==} engines: {node: ^20.19.0 || >=22.12.0} @@ -484,6 +523,13 @@ packages: os: [linux] libc: [glibc] + '@rolldown/binding-linux-arm64-gnu@1.0.1': + resolution: {integrity: sha512-QoSx2EkyrrdZ6kcyE8stqZ62t0Yra8Fs5ia9lOxJrh6TMQJK7gQKmscdTHf7pOXKREKrVwOtJcQG3qVSfc866A==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [glibc] + '@rolldown/binding-linux-arm64-musl@1.0.0': resolution: {integrity: sha512-EIVjy2cgd7uuMMo94FVkBp7F6DhcZAUwNURkSG3RwUmvAXR6s0ISxM81U+IydcZByPG0pZIHsf1b6kTxoFDgJA==} engines: {node: ^20.19.0 || >=22.12.0} @@ -491,6 +537,13 @@ packages: os: [linux] libc: [musl] + '@rolldown/binding-linux-arm64-musl@1.0.1': + resolution: {integrity: sha512-uwNwFpwKeNiZawfAWBgg0VIztPTV3ihhh1vV334h9ivnNLorxnQMU6Fz8wG1Zb4Qh9LC1/MkcyT3YlDXG3Rsgg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [musl] + '@rolldown/binding-linux-ppc64-gnu@1.0.0': resolution: {integrity: sha512-JEwwOPcwTLAcpDQlqSmjEmfs63xJnSiUNIGvLcDLUHCWK4XowpS/7c7tUsUH6uT/ct6bMUTdXKfI8967FYj6mg==} engines: {node: ^20.19.0 || >=22.12.0} @@ -498,6 +551,13 @@ packages: os: [linux] libc: [glibc] + '@rolldown/binding-linux-ppc64-gnu@1.0.1': + resolution: {integrity: sha512-zY1bul7OWr7DFBiJ++wofXvnr8B45ce3QsQUhKrIhXsygAh7bTkwyeM1bi1a2g5C/yC/N8TZyGDEoMfm/l9mpg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [ppc64] + os: [linux] + libc: [glibc] + '@rolldown/binding-linux-s390x-gnu@1.0.0': resolution: {integrity: sha512-0wjCFhLrihtAubnT9iA0N++0pSV0z5Hg7tNGdNJ4RFaINceHadoF+kiFGyY1qSSNVIAZtLotG8Ju1bgDPkjnFA==} engines: {node: ^20.19.0 || >=22.12.0} @@ -505,6 +565,13 @@ packages: os: [linux] libc: [glibc] + '@rolldown/binding-linux-s390x-gnu@1.0.1': + resolution: {integrity: sha512-0frlsT/f4Ft6I7SMESTKnF3cZsdicQn1dCMkF/jT9wDLE+gGoiQfv1nmT9e+s7s/fekvvy6tZM2jHvI2tkbJDQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [s390x] + os: [linux] + libc: [glibc] + '@rolldown/binding-linux-x64-gnu@1.0.0': resolution: {integrity: sha512-Dfn7iak9BcMMePxcoJfpSbWqnEyrp/dRF63/8qW/eHBdOZov6x5aShLLEYGYdIeSJ6vMLK/XCVB+lGIxm41bQA==} engines: {node: ^20.19.0 || >=22.12.0} @@ -512,6 +579,13 @@ packages: os: [linux] libc: [glibc] + '@rolldown/binding-linux-x64-gnu@1.0.1': + resolution: {integrity: sha512-XABVmGp9Tg0WspTVvwduTc4fpqy6JnAUrSQe6OuyqD/03nI7r0O9OWUkMIwFrjKAIqolvqoA4ZrJppgwE0Gxmw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [glibc] + '@rolldown/binding-linux-x64-musl@1.0.0': resolution: {integrity: sha512-5/utzzDmD/pD/bmuaUcbTf/sZYy0aztwIVlfpoW1fTjCZ0BaPOMVWGZL1zvgxyi7ZIVYWlxKONHmSbHuiOh8Jw==} engines: {node: ^20.19.0 || >=22.12.0} @@ -519,29 +593,59 @@ packages: os: [linux] libc: [musl] + '@rolldown/binding-linux-x64-musl@1.0.1': + resolution: {integrity: sha512-bV4fzswuzVcKD90o/VM6QqKxnxlDq0g2BISDLNVmxrnhpv1DDbyPhCIjYfvzYLV+MvkKKnQt2Q6AO86SEBULUQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [musl] + '@rolldown/binding-openharmony-arm64@1.0.0': resolution: {integrity: sha512-ouJs8VcUomfLfpbUECqFMRqdV4x6aeAK3MA4m6vTrJJjKyWTV5KnxZx7Jd9G+GlDaQQxubcba00x16OyJ1meig==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [openharmony] + '@rolldown/binding-openharmony-arm64@1.0.1': + resolution: {integrity: sha512-/Mh0Zhq3OP7fVs0kcQHZP6lZEthMGTaSf8UBQYSFEZDWGXXlEC+nJ6EqenaK2t4LBXMe3A+K/G2BVXXdtOr4PQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [openharmony] + '@rolldown/binding-wasm32-wasi@1.0.0': resolution: {integrity: sha512-E+oHKGiDA+lsKMmFtffDDw91EryDT7uJocrIuCHqhm6bCTM6xFK+3gaCkYOHfPwQr0cCNarSM2xaELoQDz9jJg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [wasm32] + '@rolldown/binding-wasm32-wasi@1.0.1': + resolution: {integrity: sha512-+1xc9X45l8ufsBAm6Gjvx2qDRIY9lTVt0cgWNcJ+1gdhXvkbxePA60yRTwSTuXL09CMhyJmjpV7E3NoyxbqFQQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [wasm32] + '@rolldown/binding-win32-arm64-msvc@1.0.0': resolution: {integrity: sha512-yYK02n8Rngo+gbm1y6G0+7jk1sJ/2Wt7K0me0Y7k/ErBpyf+LJ2gFpqWVTcRV1rUepBlQRmpgWkTQCiiwrK0Ow==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [win32] + '@rolldown/binding-win32-arm64-msvc@1.0.1': + resolution: {integrity: sha512-1D+UqZdfnuR+Jy1GgMJwi85bD40H21uNmOPRWQhw4oRSuolZ/B5rixZ45DK2KXOTCvmVCecauWgEhbw8bI7tOw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [win32] + '@rolldown/binding-win32-x64-msvc@1.0.0': resolution: {integrity: sha512-14bpChMahXRRXiTwahSl+zzHPW6qQTXtkMuJBFlbo+pqSAews2d4BdCSHfrJ/MBsCZtpmTafsY+1QhBzitcmdg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [win32] + '@rolldown/binding-win32-x64-msvc@1.0.1': + resolution: {integrity: sha512-INAycaWuhlOK3wk4mRHGsdgwYWmd9cChdPdE9bwWmy6rn9VqVNYNFGhOdXrofXUxwHIncSiPNb8tNm8knDVIeQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [win32] + '@rolldown/pluginutils@1.0.0': resolution: {integrity: sha512-aKs/3GSWyV0mrhNmt/96/Z3yczC3yvrzYATCiCXQebBsGyYzjNdUphRVLeJQ67ySKVXRfMxt2lm12pmXvbPFQQ==} @@ -549,6 +653,9 @@ packages: resolution: {integrity: sha512-TeheYy0ILzBEI/CO55CP6zJCSdSWeRtGnHy8U8dWSUH4I68iqTsy7HkMktR4xakThc9jotkPQUXT4ITdbV7cHA==} engines: {node: '>=18'} + '@standard-schema/spec@1.1.0': + resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==} + '@stylistic/eslint-plugin@5.10.0': resolution: {integrity: sha512-nPK52ZHvot8Ju/0A4ucSX1dcPV2/1clx0kLcH5wDmrE4naKso7TUC/voUyU1O9OTKTrR6MYip6LP0ogEMQ9jPQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -558,9 +665,15 @@ packages: '@tybys/wasm-util@0.10.1': resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==} + '@types/chai@5.2.3': + resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==} + '@types/debug@4.1.12': resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==} + '@types/deep-eql@4.0.2': + resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==} + '@types/esrecurse@4.3.1': resolution: {integrity: sha512-xJBAbDifo5hpffDBuHl0Y8ywswbiAp/Wi7Y/GtAgSlZyIABppyurxVueOPE8LUQOxdlgi6Zqce7uoEpqNTeiUw==} @@ -800,6 +913,35 @@ packages: vitest: optional: true + '@vitest/expect@4.1.6': + resolution: {integrity: sha512-7EHDquPthALSV0jhhjgEW8FXaviMx7rSqu8W6oqCoAuOhKov814P99QDV1pxMA3QPv21YudvJngIhjrNI4opLg==} + + '@vitest/mocker@4.1.6': + resolution: {integrity: sha512-MCFc63czMjEInOlcY2cpQCvCN+KgbAn+60xu9cMgP4sKaLC5JNAKw7JH8QdAnoAC88hW1IiSNZ+GgVXlN1UcMQ==} + peerDependencies: + msw: ^2.4.9 + vite: ^6.0.0 || ^7.0.0 || ^8.0.0 + peerDependenciesMeta: + msw: + optional: true + vite: + optional: true + + '@vitest/pretty-format@4.1.6': + resolution: {integrity: sha512-h5SxD/IzNhZYnrSZRsUZQIC+vD0GY8cUvq0iwsmkFKixRCKLLWqCXa/FIQ4S1R+sI+PGoojkHsdNrbZiM9Qpgw==} + + '@vitest/runner@4.1.6': + resolution: {integrity: sha512-nOPCmn2+yD0ZNmKdsXGv/UxMMWbMuKeD6GyYncNwdkYDxpQvrPSKYj2rWuDjC2Y4b6w6hjip5dBKFzEUuZe3vA==} + + '@vitest/snapshot@4.1.6': + resolution: {integrity: sha512-YhsdE6xAVfTDmzjxL2ZDUvjj+ZsgyOKe+TdQzqkD72wIOmHka8NuGQ6NpTNZv9D2Z63fbwWKJPeVpEw4EQgYxw==} + + '@vitest/spy@4.1.6': + resolution: {integrity: sha512-JFKxMx6udhwKh/Ldo270e17QX710vgunMkuPAvXjHSvC6oqLWAHhVhjg/I71q0u0CBSErIODV1Kjv0FQNSWjdg==} + + '@vitest/utils@4.1.6': + resolution: {integrity: sha512-FxIY+U81R3LGKCxaHHFRQ5+g6/iRgGLmeHWdp2Amj4ljQRrEIWHmZyDfDYBRZlpyqA7qKxtS9DD1dhk8RnRIVQ==} + '@vue/compiler-core@3.5.24': resolution: {integrity: sha512-eDl5H57AOpNakGNAkFDH+y7kTqrQpJkZFXhWZQGyx/5Wh7B1uQYvcWkvZi11BDhscPgj8N7XV3oRwiPnx1Vrig==} @@ -836,6 +978,10 @@ packages: resolution: {integrity: sha512-ixiS0nLNNG5jNQzgZJNoUpBKdo9yTYZMGJ+QgT2jmjR7G7+QHRCc4v6LQ3NgE7EBJq+o0ams3waJwkrlBom8Ig==} engines: {node: '>=14'} + assertion-error@2.0.1: + resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} + engines: {node: '>=12'} + ast-kit@3.0.0-beta.1: resolution: {integrity: sha512-trmleAnZ2PxN/loHWVhhx1qeOHSRXq4TDsBBxq3GqeJitfk3+jTQ+v/C1km/KYq9M7wKqCewMh+/NAvVH7m+bw==} engines: {node: '>=20.19.0'} @@ -880,6 +1026,10 @@ packages: ccount@2.0.1: resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} + chai@6.2.2: + resolution: {integrity: sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==} + engines: {node: '>=18'} + change-case@5.4.4: resolution: {integrity: sha512-HRQyTk2/YPEkt9TnUPbOpr64Uw3KOicFWPVBb+xiHvd6eBx/qPr9xqfBFDT8P2vWsvvz4jbEkfDe71W3VyNu2w==} @@ -912,6 +1062,9 @@ packages: confbox@0.2.2: resolution: {integrity: sha512-1NB+BKqhtNipMsov4xI/NnhCKp9XG9NamYp5PVm9klAT0fsrNPjaFICsCFhNhwZJKNh7zB/3q8qXz0E9oaMNtQ==} + convert-source-map@2.0.0: + resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + core-js-compat@3.49.0: resolution: {integrity: sha512-VQXt1jr9cBz03b331DFDCCP90b3fanciLkgiOoy8SBHy06gNf+vQ1A3WFLqG7I8TipYIKeYK9wxd0tUrvHcOZA==} @@ -946,6 +1099,10 @@ packages: resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} engines: {node: '>=6'} + detect-libc@2.1.2: + resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} + engines: {node: '>=8'} + devlop@1.1.0: resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==} @@ -977,6 +1134,9 @@ packages: resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} engines: {node: '>=0.12'} + es-module-lexer@2.1.0: + resolution: {integrity: sha512-n27zTYMjYu1aj4MjCWzSP7G9r75utsaoc8m61weK+W8JMBGGQybd43GstCXZ3WNmSFtGT9wi59qQTW6mhTR5LQ==} + escalade@3.2.0: resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} engines: {node: '>=6'} @@ -1197,6 +1357,10 @@ packages: resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} engines: {node: '>=0.10.0'} + expect-type@1.3.0: + resolution: {integrity: sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==} + engines: {node: '>=12.0.0'} + exsolve@1.0.8: resolution: {integrity: sha512-LmDxfWXwcTArk8fUEnOfSZpHOJ6zOMUJKOtFLFqJLoKJetuQG874Uc7/Kki7zFLzYybmZhp1M7+98pfMqeX8yA==} @@ -1256,6 +1420,11 @@ packages: resolution: {integrity: sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww==} engines: {node: '>=0.4.x'} + fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + get-tsconfig@4.13.7: resolution: {integrity: sha512-7tN6rFgBlMgpBML5j8typ92BKFi2sFQvIdpAqLA2beia5avZDrMs0FLZiM5etShWq5irVyGcGMEA1jcDaK7A/Q==} @@ -1366,6 +1535,80 @@ packages: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} + lightningcss-android-arm64@1.32.0: + resolution: {integrity: sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [android] + + lightningcss-darwin-arm64@1.32.0: + resolution: {integrity: sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [darwin] + + lightningcss-darwin-x64@1.32.0: + resolution: {integrity: sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [darwin] + + lightningcss-freebsd-x64@1.32.0: + resolution: {integrity: sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [freebsd] + + lightningcss-linux-arm-gnueabihf@1.32.0: + resolution: {integrity: sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==} + engines: {node: '>= 12.0.0'} + cpu: [arm] + os: [linux] + + lightningcss-linux-arm64-gnu@1.32.0: + resolution: {integrity: sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + libc: [glibc] + + lightningcss-linux-arm64-musl@1.32.0: + resolution: {integrity: sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + libc: [musl] + + lightningcss-linux-x64-gnu@1.32.0: + resolution: {integrity: sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + libc: [glibc] + + lightningcss-linux-x64-musl@1.32.0: + resolution: {integrity: sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + libc: [musl] + + lightningcss-win32-arm64-msvc@1.32.0: + resolution: {integrity: sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [win32] + + lightningcss-win32-x64-msvc@1.32.0: + resolution: {integrity: sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [win32] + + lightningcss@1.32.0: + resolution: {integrity: sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==} + engines: {node: '>= 12.0.0'} + local-pkg@1.1.2: resolution: {integrity: sha512-arhlxbFRmoQHl33a0Zkle/YWlmNwoyt6QNZEIJcqNbdrsix5Lvc4HyyI3EnwxTYlZYc32EbYrQ8SzEZ7dqgg9A==} engines: {node: '>=14'} @@ -1612,6 +1855,10 @@ packages: resolution: {integrity: sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==} engines: {node: '>=4'} + postcss@8.5.14: + resolution: {integrity: sha512-SoSL4+OSEtR99LHFZQiJLkT59C5B1amGO1NzTwj7TT1qCUgUO6hxOvzkOYxD+vMrXBM3XJIKzokoERdqQq/Zmg==} + engines: {node: ^10 || ^12 || >=14} + postcss@8.5.6: resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==} engines: {node: ^10 || ^12 || >=14} @@ -1677,6 +1924,11 @@ packages: engines: {node: ^20.19.0 || >=22.12.0} hasBin: true + rolldown@1.0.1: + resolution: {integrity: sha512-X0KQHljNnEkWNqqiz9zJrGunh1B0HgOxLXvnFpCOcadzcy5qohZ3tqMEUg00vncoRovXuK3ZqCT9KnnKzoInFQ==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + scslre@0.3.0: resolution: {integrity: sha512-3A6sD0WYP7+QrjbfNA2FN3FsOaGGFoekCVgTyypy53gPxhbkCIjtO6YWgdrfM+n/8sI8JeXZOIxsHjMTNxQ4nQ==} engines: {node: ^14.0.0 || >=16.0.0} @@ -1694,6 +1946,9 @@ packages: resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} engines: {node: '>=8'} + siginfo@2.0.0: + resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} + sisteransi@1.0.5: resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} @@ -1710,6 +1965,12 @@ packages: spdx-license-ids@3.0.22: resolution: {integrity: sha512-4PRT4nh1EImPbt2jASOKHX7PB7I+e4IWNLvkKFDxNhJlfjbYlleYQh285Z/3mPTHSAK/AvdMmw5BNNuYH8ShgQ==} + stackback@0.0.2: + resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} + + std-env@4.1.0: + resolution: {integrity: sha512-Rq7ybcX2RuC55r9oaPVEW7/xu3tj8u4GeBYHBWCychFtzMIr86A7e3PPEBPT37sHStKX3+TiX/Fr/ACmJLVlLQ==} + strip-indent@4.1.1: resolution: {integrity: sha512-SlyRoSkdh1dYP0PzclLE7r0M9sgbFKKMFXpFRUMNuKhQSbC6VQIGzq3E0qsfvGJaUFJPGv6Ws1NZ/haTAjfbMA==} engines: {node: '>=12'} @@ -1722,6 +1983,9 @@ packages: resolution: {integrity: sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==} engines: {node: '>=6'} + tinybench@2.9.0: + resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} + tinyexec@1.1.2: resolution: {integrity: sha512-dAqSqE/RabpBKI8+h26GfLq6Vb3JVXs30XYQjdMjaj/c2tS8IYYMbIzP599KtRj7c57/wYApb3QjgRgXmrCukA==} engines: {node: '>=18'} @@ -1730,6 +1994,10 @@ packages: resolution: {integrity: sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==} engines: {node: '>=12.0.0'} + tinyrainbow@3.1.0: + resolution: {integrity: sha512-Bf+ILmBgretUrdJxzXM0SgXLZ3XfiaUuOj/IKQHuTXip+05Xn+uyEYdVg0kYDipTBcLrCVyUzAPz7QmArb0mmw==} + engines: {node: '>=14.0.0'} + to-valid-identifier@1.0.0: resolution: {integrity: sha512-41wJyvKep3yT2tyPqX/4blcfybknGB4D+oETKLs7Q76UiPqRpUJK3hr1nxelyYO0PHKVzJwlu0aCeEAsGI6rpw==} engines: {node: '>=20'} @@ -1841,6 +2109,90 @@ packages: util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + vite@8.0.13: + resolution: {integrity: sha512-MFtjBYgzmSxmgA4RAfjIyXWpGe1oALnjgUTzzV7QLx/TKxCzjtMH6Fd9/eVK+5Fg1qNoz5VAwsmMs/NofrmJvw==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + peerDependencies: + '@types/node': ^20.19.0 || >=22.12.0 + '@vitejs/devtools': ^0.1.18 + esbuild: ^0.27.0 || ^0.28.0 + jiti: '>=1.21.0' + less: ^4.0.0 + sass: ^1.70.0 + sass-embedded: ^1.70.0 + stylus: '>=0.54.8' + sugarss: ^5.0.0 + terser: ^5.16.0 + tsx: ^4.8.1 + yaml: ^2.4.2 + peerDependenciesMeta: + '@types/node': + optional: true + '@vitejs/devtools': + optional: true + esbuild: + optional: true + jiti: + optional: true + less: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + tsx: + optional: true + yaml: + optional: true + + vitest@4.1.6: + resolution: {integrity: sha512-6lvjbS3p9b4CrdCmguzbh2/4uoXhGE2q71R4OX5sqF9R1bo9Xd6fGrMAfvp5wnCzlBnFVdCOp6onuTQVbo8iUQ==} + engines: {node: ^20.0.0 || ^22.0.0 || >=24.0.0} + hasBin: true + peerDependencies: + '@edge-runtime/vm': '*' + '@opentelemetry/api': ^1.9.0 + '@types/node': ^20.0.0 || ^22.0.0 || >=24.0.0 + '@vitest/browser-playwright': 4.1.6 + '@vitest/browser-preview': 4.1.6 + '@vitest/browser-webdriverio': 4.1.6 + '@vitest/coverage-istanbul': 4.1.6 + '@vitest/coverage-v8': 4.1.6 + '@vitest/ui': 4.1.6 + happy-dom: '*' + jsdom: '*' + vite: ^6.0.0 || ^7.0.0 || ^8.0.0 + peerDependenciesMeta: + '@edge-runtime/vm': + optional: true + '@opentelemetry/api': + optional: true + '@types/node': + optional: true + '@vitest/browser-playwright': + optional: true + '@vitest/browser-preview': + optional: true + '@vitest/browser-webdriverio': + optional: true + '@vitest/coverage-istanbul': + optional: true + '@vitest/coverage-v8': + optional: true + '@vitest/ui': + optional: true + happy-dom: + optional: true + jsdom: + optional: true + vue-eslint-parser@10.4.0: resolution: {integrity: sha512-Vxi9pJdbN3ZnVGLODVtZ7y4Y2kzAAE2Cm0CZ3ZDRvydVYxZ6VrnBhLikBsRS+dpwj4Jv4UCv21PTEwF5rQ9WXg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -1852,6 +2204,11 @@ packages: engines: {node: '>= 8'} hasBin: true + why-is-node-running@2.3.0: + resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==} + engines: {node: '>=8'} + hasBin: true + word-wrap@1.2.5: resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} engines: {node: '>=0.10.0'} @@ -1909,7 +2266,7 @@ snapshots: '@actions/io@3.0.2': {} - '@antfu/eslint-config@8.3.0(@typescript-eslint/rule-tester@8.56.1(eslint@10.3.0)(typescript@5.9.3))(@typescript-eslint/typescript-estree@8.59.3(typescript@5.9.3))(@typescript-eslint/utils@8.59.3(eslint@10.3.0)(typescript@5.9.3))(@vue/compiler-sfc@3.5.24)(eslint@10.3.0)(typescript@5.9.3)': + '@antfu/eslint-config@8.3.0(@typescript-eslint/rule-tester@8.56.1(eslint@10.3.0)(typescript@5.9.3))(@typescript-eslint/typescript-estree@8.59.3(typescript@5.9.3))(@typescript-eslint/utils@8.59.3(eslint@10.3.0)(typescript@5.9.3))(@vue/compiler-sfc@3.5.24)(eslint@10.3.0)(typescript@5.9.3)(vitest@4.1.6(@types/node@24.12.4)(vite@8.0.13(@types/node@24.12.4)(yaml@2.8.2)))': dependencies: '@antfu/install-pkg': 1.1.0 '@clack/prompts': 1.4.0 @@ -1919,7 +2276,7 @@ snapshots: '@stylistic/eslint-plugin': 5.10.0(eslint@10.3.0) '@typescript-eslint/eslint-plugin': 8.59.3(@typescript-eslint/parser@8.59.3(eslint@10.3.0)(typescript@5.9.3))(eslint@10.3.0)(typescript@5.9.3) '@typescript-eslint/parser': 8.59.3(eslint@10.3.0)(typescript@5.9.3) - '@vitest/eslint-plugin': 1.6.17(@typescript-eslint/eslint-plugin@8.59.3(@typescript-eslint/parser@8.59.3(eslint@10.3.0)(typescript@5.9.3))(eslint@10.3.0)(typescript@5.9.3))(eslint@10.3.0)(typescript@5.9.3) + '@vitest/eslint-plugin': 1.6.17(@typescript-eslint/eslint-plugin@8.59.3(@typescript-eslint/parser@8.59.3(eslint@10.3.0)(typescript@5.9.3))(eslint@10.3.0)(typescript@5.9.3))(eslint@10.3.0)(typescript@5.9.3)(vitest@4.1.6(@types/node@24.12.4)(vite@8.0.13(@types/node@24.12.4)(yaml@2.8.2))) ansis: 4.2.0 cac: 7.0.0 eslint: 10.3.0 @@ -2217,6 +2574,8 @@ snapshots: '@oxc-project/types@0.129.0': {} + '@oxc-project/types@0.130.0': {} + '@pkgr/core@0.2.9': {} '@quansync/fs@1.0.0': @@ -2226,39 +2585,75 @@ snapshots: '@rolldown/binding-android-arm64@1.0.0': optional: true + '@rolldown/binding-android-arm64@1.0.1': + optional: true + '@rolldown/binding-darwin-arm64@1.0.0': optional: true + '@rolldown/binding-darwin-arm64@1.0.1': + optional: true + '@rolldown/binding-darwin-x64@1.0.0': optional: true + '@rolldown/binding-darwin-x64@1.0.1': + optional: true + '@rolldown/binding-freebsd-x64@1.0.0': optional: true + '@rolldown/binding-freebsd-x64@1.0.1': + optional: true + '@rolldown/binding-linux-arm-gnueabihf@1.0.0': optional: true + '@rolldown/binding-linux-arm-gnueabihf@1.0.1': + optional: true + '@rolldown/binding-linux-arm64-gnu@1.0.0': optional: true + '@rolldown/binding-linux-arm64-gnu@1.0.1': + optional: true + '@rolldown/binding-linux-arm64-musl@1.0.0': optional: true + '@rolldown/binding-linux-arm64-musl@1.0.1': + optional: true + '@rolldown/binding-linux-ppc64-gnu@1.0.0': optional: true + '@rolldown/binding-linux-ppc64-gnu@1.0.1': + optional: true + '@rolldown/binding-linux-s390x-gnu@1.0.0': optional: true + '@rolldown/binding-linux-s390x-gnu@1.0.1': + optional: true + '@rolldown/binding-linux-x64-gnu@1.0.0': optional: true + '@rolldown/binding-linux-x64-gnu@1.0.1': + optional: true + '@rolldown/binding-linux-x64-musl@1.0.0': optional: true + '@rolldown/binding-linux-x64-musl@1.0.1': + optional: true + '@rolldown/binding-openharmony-arm64@1.0.0': optional: true + '@rolldown/binding-openharmony-arm64@1.0.1': + optional: true + '@rolldown/binding-wasm32-wasi@1.0.0': dependencies: '@emnapi/core': 1.10.0 @@ -2266,16 +2661,31 @@ snapshots: '@napi-rs/wasm-runtime': 1.1.4(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0) optional: true + '@rolldown/binding-wasm32-wasi@1.0.1': + dependencies: + '@emnapi/core': 1.10.0 + '@emnapi/runtime': 1.10.0 + '@napi-rs/wasm-runtime': 1.1.4(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0) + optional: true + '@rolldown/binding-win32-arm64-msvc@1.0.0': optional: true + '@rolldown/binding-win32-arm64-msvc@1.0.1': + optional: true + '@rolldown/binding-win32-x64-msvc@1.0.0': optional: true + '@rolldown/binding-win32-x64-msvc@1.0.1': + optional: true + '@rolldown/pluginutils@1.0.0': {} '@sindresorhus/base62@1.0.0': {} + '@standard-schema/spec@1.1.0': {} + '@stylistic/eslint-plugin@5.10.0(eslint@10.3.0)': dependencies: '@eslint-community/eslint-utils': 4.9.1(eslint@10.3.0) @@ -2291,10 +2701,17 @@ snapshots: tslib: 2.8.1 optional: true + '@types/chai@5.2.3': + dependencies: + '@types/deep-eql': 4.0.2 + assertion-error: 2.0.1 + '@types/debug@4.1.12': dependencies: '@types/ms': 2.1.0 + '@types/deep-eql@4.0.2': {} + '@types/esrecurse@4.3.1': {} '@types/estree@1.0.8': {} @@ -2363,8 +2780,8 @@ snapshots: '@typescript-eslint/project-service@8.56.1(typescript@5.9.3)': dependencies: - '@typescript-eslint/tsconfig-utils': 8.58.1(typescript@5.9.3) - '@typescript-eslint/types': 8.58.1 + '@typescript-eslint/tsconfig-utils': 8.59.3(typescript@5.9.3) + '@typescript-eslint/types': 8.59.3 debug: 4.4.3 typescript: 5.9.3 transitivePeerDependencies: @@ -2571,7 +2988,7 @@ snapshots: '@typescript/native-preview-win32-arm64': 7.0.0-dev.20260515.1 '@typescript/native-preview-win32-x64': 7.0.0-dev.20260515.1 - '@vitest/eslint-plugin@1.6.17(@typescript-eslint/eslint-plugin@8.59.3(@typescript-eslint/parser@8.59.3(eslint@10.3.0)(typescript@5.9.3))(eslint@10.3.0)(typescript@5.9.3))(eslint@10.3.0)(typescript@5.9.3)': + '@vitest/eslint-plugin@1.6.17(@typescript-eslint/eslint-plugin@8.59.3(@typescript-eslint/parser@8.59.3(eslint@10.3.0)(typescript@5.9.3))(eslint@10.3.0)(typescript@5.9.3))(eslint@10.3.0)(typescript@5.9.3)(vitest@4.1.6(@types/node@24.12.4)(vite@8.0.13(@types/node@24.12.4)(yaml@2.8.2)))': dependencies: '@typescript-eslint/scope-manager': 8.58.1 '@typescript-eslint/utils': 8.58.1(eslint@10.3.0)(typescript@5.9.3) @@ -2579,9 +2996,51 @@ snapshots: optionalDependencies: '@typescript-eslint/eslint-plugin': 8.59.3(@typescript-eslint/parser@8.59.3(eslint@10.3.0)(typescript@5.9.3))(eslint@10.3.0)(typescript@5.9.3) typescript: 5.9.3 + vitest: 4.1.6(@types/node@24.12.4)(vite@8.0.13(@types/node@24.12.4)(yaml@2.8.2)) transitivePeerDependencies: - supports-color + '@vitest/expect@4.1.6': + dependencies: + '@standard-schema/spec': 1.1.0 + '@types/chai': 5.2.3 + '@vitest/spy': 4.1.6 + '@vitest/utils': 4.1.6 + chai: 6.2.2 + tinyrainbow: 3.1.0 + + '@vitest/mocker@4.1.6(vite@8.0.13(@types/node@24.12.4)(yaml@2.8.2))': + dependencies: + '@vitest/spy': 4.1.6 + estree-walker: 3.0.3 + magic-string: 0.30.21 + optionalDependencies: + vite: 8.0.13(@types/node@24.12.4)(yaml@2.8.2) + + '@vitest/pretty-format@4.1.6': + dependencies: + tinyrainbow: 3.1.0 + + '@vitest/runner@4.1.6': + dependencies: + '@vitest/utils': 4.1.6 + pathe: 2.0.3 + + '@vitest/snapshot@4.1.6': + dependencies: + '@vitest/pretty-format': 4.1.6 + '@vitest/utils': 4.1.6 + magic-string: 0.30.21 + pathe: 2.0.3 + + '@vitest/spy@4.1.6': {} + + '@vitest/utils@4.1.6': + dependencies: + '@vitest/pretty-format': 4.1.6 + convert-source-map: 2.0.0 + tinyrainbow: 3.1.0 + '@vue/compiler-core@3.5.24': dependencies: '@babel/parser': 7.29.0 @@ -2631,6 +3090,8 @@ snapshots: are-docs-informative@0.0.2: {} + assertion-error@2.0.1: {} + ast-kit@3.0.0-beta.1: dependencies: '@babel/parser': 8.0.0-rc.3 @@ -2667,6 +3128,8 @@ snapshots: ccount@2.0.1: {} + chai@6.2.2: {} + change-case@5.4.4: {} character-entities@2.0.2: {} @@ -2687,6 +3150,8 @@ snapshots: confbox@0.2.2: {} + convert-source-map@2.0.0: {} + core-js-compat@3.49.0: dependencies: browserslist: 4.28.1 @@ -2713,6 +3178,8 @@ snapshots: dequal@2.0.3: {} + detect-libc@2.1.2: {} + devlop@1.1.0: dependencies: dequal: 2.0.3 @@ -2732,6 +3199,8 @@ snapshots: entities@4.5.0: {} + es-module-lexer@2.1.0: {} + escalade@3.2.0: {} escape-string-regexp@1.0.5: {} @@ -3015,6 +3484,8 @@ snapshots: esutils@2.0.3: {} + expect-type@1.3.0: {} + exsolve@1.0.8: {} fast-content-type-parse@3.0.0: {} @@ -3063,6 +3534,9 @@ snapshots: format@0.2.2: {} + fsevents@2.3.3: + optional: true + get-tsconfig@4.13.7: dependencies: resolve-pkg-maps: 1.0.0 @@ -3144,6 +3618,55 @@ snapshots: prelude-ls: 1.2.1 type-check: 0.4.0 + lightningcss-android-arm64@1.32.0: + optional: true + + lightningcss-darwin-arm64@1.32.0: + optional: true + + lightningcss-darwin-x64@1.32.0: + optional: true + + lightningcss-freebsd-x64@1.32.0: + optional: true + + lightningcss-linux-arm-gnueabihf@1.32.0: + optional: true + + lightningcss-linux-arm64-gnu@1.32.0: + optional: true + + lightningcss-linux-arm64-musl@1.32.0: + optional: true + + lightningcss-linux-x64-gnu@1.32.0: + optional: true + + lightningcss-linux-x64-musl@1.32.0: + optional: true + + lightningcss-win32-arm64-msvc@1.32.0: + optional: true + + lightningcss-win32-x64-msvc@1.32.0: + optional: true + + lightningcss@1.32.0: + dependencies: + detect-libc: 2.1.2 + optionalDependencies: + lightningcss-android-arm64: 1.32.0 + lightningcss-darwin-arm64: 1.32.0 + lightningcss-darwin-x64: 1.32.0 + lightningcss-freebsd-x64: 1.32.0 + lightningcss-linux-arm-gnueabihf: 1.32.0 + lightningcss-linux-arm64-gnu: 1.32.0 + lightningcss-linux-arm64-musl: 1.32.0 + lightningcss-linux-x64-gnu: 1.32.0 + lightningcss-linux-x64-musl: 1.32.0 + lightningcss-win32-arm64-msvc: 1.32.0 + lightningcss-win32-x64-msvc: 1.32.0 + local-pkg@1.1.2: dependencies: mlly: 1.8.0 @@ -3588,6 +4111,12 @@ snapshots: cssesc: 3.0.0 util-deprecate: 1.0.2 + postcss@8.5.14: + dependencies: + nanoid: 3.3.11 + picocolors: 1.1.1 + source-map-js: 1.2.1 + postcss@8.5.6: dependencies: nanoid: 3.3.11 @@ -3659,6 +4188,27 @@ snapshots: '@rolldown/binding-win32-arm64-msvc': 1.0.0 '@rolldown/binding-win32-x64-msvc': 1.0.0 + rolldown@1.0.1: + dependencies: + '@oxc-project/types': 0.130.0 + '@rolldown/pluginutils': 1.0.0 + optionalDependencies: + '@rolldown/binding-android-arm64': 1.0.1 + '@rolldown/binding-darwin-arm64': 1.0.1 + '@rolldown/binding-darwin-x64': 1.0.1 + '@rolldown/binding-freebsd-x64': 1.0.1 + '@rolldown/binding-linux-arm-gnueabihf': 1.0.1 + '@rolldown/binding-linux-arm64-gnu': 1.0.1 + '@rolldown/binding-linux-arm64-musl': 1.0.1 + '@rolldown/binding-linux-ppc64-gnu': 1.0.1 + '@rolldown/binding-linux-s390x-gnu': 1.0.1 + '@rolldown/binding-linux-x64-gnu': 1.0.1 + '@rolldown/binding-linux-x64-musl': 1.0.1 + '@rolldown/binding-openharmony-arm64': 1.0.1 + '@rolldown/binding-wasm32-wasi': 1.0.1 + '@rolldown/binding-win32-arm64-msvc': 1.0.1 + '@rolldown/binding-win32-x64-msvc': 1.0.1 + scslre@0.3.0: dependencies: '@eslint-community/regexpp': 4.12.2 @@ -3673,6 +4223,8 @@ snapshots: shebang-regex@3.0.0: {} + siginfo@2.0.0: {} + sisteransi@1.0.5: {} source-map-js@1.2.1: {} @@ -3686,6 +4238,10 @@ snapshots: spdx-license-ids@3.0.22: {} + stackback@0.0.2: {} + + std-env@4.1.0: {} + strip-indent@4.1.1: {} synckit@0.11.12: @@ -3694,6 +4250,8 @@ snapshots: tapable@2.3.0: {} + tinybench@2.9.0: {} + tinyexec@1.1.2: {} tinyglobby@0.2.16: @@ -3701,6 +4259,8 @@ snapshots: fdir: 6.5.0(picomatch@4.0.4) picomatch: 4.0.4 + tinyrainbow@3.1.0: {} + to-valid-identifier@1.0.0: dependencies: '@sindresorhus/base62': 1.0.0 @@ -3801,6 +4361,45 @@ snapshots: util-deprecate@1.0.2: {} + vite@8.0.13(@types/node@24.12.4)(yaml@2.8.2): + dependencies: + lightningcss: 1.32.0 + picomatch: 4.0.4 + postcss: 8.5.14 + rolldown: 1.0.1 + tinyglobby: 0.2.16 + optionalDependencies: + '@types/node': 24.12.4 + fsevents: 2.3.3 + yaml: 2.8.2 + + vitest@4.1.6(@types/node@24.12.4)(vite@8.0.13(@types/node@24.12.4)(yaml@2.8.2)): + dependencies: + '@vitest/expect': 4.1.6 + '@vitest/mocker': 4.1.6(vite@8.0.13(@types/node@24.12.4)(yaml@2.8.2)) + '@vitest/pretty-format': 4.1.6 + '@vitest/runner': 4.1.6 + '@vitest/snapshot': 4.1.6 + '@vitest/spy': 4.1.6 + '@vitest/utils': 4.1.6 + es-module-lexer: 2.1.0 + expect-type: 1.3.0 + magic-string: 0.30.21 + obug: 2.1.1 + pathe: 2.0.3 + picomatch: 4.0.4 + std-env: 4.1.0 + tinybench: 2.9.0 + tinyexec: 1.1.2 + tinyglobby: 0.2.16 + tinyrainbow: 3.1.0 + vite: 8.0.13(@types/node@24.12.4)(yaml@2.8.2) + why-is-node-running: 2.3.0 + optionalDependencies: + '@types/node': 24.12.4 + transitivePeerDependencies: + - msw + vue-eslint-parser@10.4.0(eslint@10.3.0): dependencies: debug: 4.4.3 @@ -3817,6 +4416,11 @@ snapshots: dependencies: isexe: 2.0.0 + why-is-node-running@2.3.0: + dependencies: + siginfo: 2.0.0 + stackback: 0.0.2 + word-wrap@1.2.5: {} xml-name-validator@4.0.0: {} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 3a51070..9c78d6d 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -17,3 +17,4 @@ catalog: '@typescript/native-preview': 7.0.0-dev.20260515.1 eslint: ^10.3.0 tsdown: ^0.22.0 + vitest: ^4.1.6 From 26a0352ad775fd2f8076c1f5dc2f839f86b5276f Mon Sep 17 00:00:00 2001 From: lwj <674416404@qq.com> Date: Fri, 15 May 2026 21:47:41 +0800 Subject: [PATCH 2/2] =?UTF-8?q?test(cnb-delete-branch):=20=E5=B0=86?= =?UTF-8?q?=E6=B5=8B=E8=AF=95=E6=8F=8F=E8=BF=B0=E7=BF=BB=E8=AF=91=E4=B8=BA?= =?UTF-8?q?=E4=B8=AD=E6=96=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/cnb-delete-branch/index.test.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/cnb-delete-branch/index.test.ts b/packages/cnb-delete-branch/index.test.ts index 5735fa5..2ce8d32 100644 --- a/packages/cnb-delete-branch/index.test.ts +++ b/packages/cnb-delete-branch/index.test.ts @@ -56,17 +56,17 @@ function createPullRequest(number: string, ref = 'refs/heads/feature', repo = 't } } -describe('cnb-delete-branch', () => { +describe('删除 CNB 分支', () => { beforeEach(() => { vi.stubGlobal('fetch', vi.fn()) }) - it('encodes repo paths but preserves path separators', () => { + it('编码仓库路径时保留路径分隔符', () => { expect(encodePath('tdesign/workflows')).toBe('tdesign/workflows') expect(encodePath('tdesign/branch with space')).toBe('tdesign/branch%20with%20space') }) - it('sends CNB JSON headers and parses JSON responses', async () => { + it('发送 CNB JSON 请求头并解析 JSON 响应', async () => { mockFetchOnce(200, JSON.stringify({ ok: true })) await expect(fetchCNB('token', '/tdesign/test/-/pulls')).resolves.toEqual({ @@ -83,7 +83,7 @@ describe('cnb-delete-branch', () => { }) }) - it('throws CNBRequestError for failed API responses', async () => { + it('请求失败时抛出 CNBRequestError', async () => { mockFetchOnce(403, JSON.stringify({ errmsg: 'forbidden' }), 'Forbidden') await expect(fetchCNB('token', '/tdesign/test/-/pulls')).rejects.toMatchObject({ @@ -92,7 +92,7 @@ describe('cnb-delete-branch', () => { }) }) - it('lists pull requests across pages', async () => { + it('分页拉取 Pull Request 列表', async () => { const firstPage = Array.from({ length: 100 }, (_, index) => createPullRequest(String(index + 1))) const secondPage = [createPullRequest('101')] mockFetchOnce(200, JSON.stringify(firstPage)) @@ -113,7 +113,7 @@ describe('cnb-delete-branch', () => { ) }) - it('patches pull request state through the CNB pull endpoint', async () => { + it('通过 CNB Pull Request 接口更新 PR 状态', async () => { mockFetchOnce(200, '{}') await expect(patchPull('token', 'tdesign/test', '12', { state: 'closed' })).resolves.toBe(true) @@ -124,7 +124,7 @@ describe('cnb-delete-branch', () => { })) }) - it('treats missing branch as a successful no-op but rethrows other delete failures', async () => { + it('分支不存在时视为成功跳过,其他删除失败继续抛出', async () => { mockFetchOnce(404, JSON.stringify({ errmsg: 'not found' }), 'Not Found') await expect(deleteBranch('token', 'tdesign/test', 'feature')).resolves.toBe(false) @@ -132,7 +132,7 @@ describe('cnb-delete-branch', () => { await expect(deleteBranch('token', 'tdesign/test', 'feature')).rejects.toBeInstanceOf(CNBRequestError) }) - it('reads pull branch and repo safely when head data is missing', () => { + it('head 数据缺失时安全读取 PR 分支和仓库', () => { expect(getPullBranchName(createPullRequest('1', 'refs/heads/feature/test'))).toBe('feature/test') expect(getPullRepoPath(createPullRequest('1'))).toBe('tdesign/test') expect(getPullBranchName({ head: null } as PullRequest)).toBeUndefined()