├── .npmrc ├── docs ├── github_app_id.png ├── github_app_private_key.png └── pr-comment-setup.md ├── .gitignore ├── .editorconfig ├── tests ├── svelte-loader.ts ├── rollup-plugin-svelte.ts ├── mdsvex.ts ├── svelte-preprocess.ts ├── svelte-eslint-parser.ts ├── melt-ui.ts ├── prettier-plugin-svelte.ts ├── language-tools.ts ├── sv.ts ├── eslint-plugin-svelte.ts ├── vite-plugin-svelte.ts ├── skeleton.ts ├── _carbon-components-svelte.ts ├── storybook.ts ├── sveltekit.ts ├── _histoire.ts └── _selftest.ts ├── .github ├── renovate.json5 └── workflows │ ├── ci.yml │ ├── ecosystem-ci-selected.yml │ ├── ecosystem-ci.yml │ └── ecosystem-ci-from-pr.yml ├── tsconfig.json ├── .prettierrc.json ├── eslint.config.js ├── LICENSE ├── types.d.ts ├── package.json ├── README.md ├── discord-webhook.ts ├── ecosystem-ci.ts ├── utils.ts └── pnpm-lock.yaml /.npmrc: -------------------------------------------------------------------------------- 1 | engine-strict = true 2 | strict-peer-dependencies = false 3 | package-manager-strict = false 4 | -------------------------------------------------------------------------------- /docs/github_app_id.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sveltejs/svelte-ecosystem-ci/main/docs/github_app_id.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .DS_Store? 3 | node_modules 4 | svelte 5 | workspace 6 | .pnpm-debug.log 7 | .idea 8 | -------------------------------------------------------------------------------- /docs/github_app_private_key.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sveltejs/svelte-ecosystem-ci/main/docs/github_app_private_key.png -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | end_of_line = lf 5 | insert_final_newline = true 6 | indent_style = tab 7 | indent_size = 2 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | 11 | [package.json] 12 | indent_style = space 13 | -------------------------------------------------------------------------------- /tests/svelte-loader.ts: -------------------------------------------------------------------------------- 1 | import { runInRepo } from '../utils.ts' 2 | import { RunOptions } from '../types.ts' 3 | 4 | export async function test(options: RunOptions) { 5 | await runInRepo({ 6 | ...options, 7 | repo: 'sveltejs/svelte-loader', 8 | branch: 'master', 9 | test: 'test', 10 | }) 11 | } 12 | -------------------------------------------------------------------------------- /tests/rollup-plugin-svelte.ts: -------------------------------------------------------------------------------- 1 | import { runInRepo } from '../utils.ts' 2 | import { RunOptions } from '../types.ts' 3 | 4 | export async function test(options: RunOptions) { 5 | await runInRepo({ 6 | ...options, 7 | repo: 'sveltejs/rollup-plugin-svelte', 8 | branch: 'master', 9 | test: 'test', 10 | }) 11 | } 12 | -------------------------------------------------------------------------------- /tests/mdsvex.ts: -------------------------------------------------------------------------------- 1 | import { runInRepo } from '../utils.ts' 2 | import { RunOptions } from '../types.ts' 3 | 4 | export async function test(options: RunOptions) { 5 | await runInRepo({ 6 | ...options, 7 | repo: 'pngwn/MDsveX', 8 | branch: 'main', 9 | build: 'pnpm -r build', 10 | test: 'pnpm test', 11 | }) 12 | } 13 | -------------------------------------------------------------------------------- /tests/svelte-preprocess.ts: -------------------------------------------------------------------------------- 1 | import { runInRepo } from '../utils.ts' 2 | import { RunOptions } from '../types.ts' 3 | 4 | export async function test(options: RunOptions) { 5 | await runInRepo({ 6 | ...options, 7 | repo: 'sveltejs/svelte-preprocess', 8 | branch: 'main', 9 | build: 'build', 10 | test: 'test', 11 | }) 12 | } 13 | -------------------------------------------------------------------------------- /tests/svelte-eslint-parser.ts: -------------------------------------------------------------------------------- 1 | import { runInRepo } from '../utils.ts' 2 | import { RunOptions } from '../types.ts' 3 | 4 | export async function test(options: RunOptions) { 5 | await runInRepo({ 6 | ...options, 7 | repo: 'sveltejs/svelte-eslint-parser', 8 | branch: 'main', 9 | build: 'build', 10 | test: 'test', 11 | }) 12 | } 13 | -------------------------------------------------------------------------------- /tests/melt-ui.ts: -------------------------------------------------------------------------------- 1 | import { runInRepo } from '../utils.ts' 2 | import { RunOptions } from '../types.ts' 3 | 4 | export async function test(options: RunOptions) { 5 | await runInRepo({ 6 | ...options, 7 | repo: 'melt-ui/next-gen', 8 | branch: 'main', 9 | beforeTest: 'pnpm exec playwright install', 10 | test: 'pnpm test', 11 | }) 12 | } 13 | -------------------------------------------------------------------------------- /tests/prettier-plugin-svelte.ts: -------------------------------------------------------------------------------- 1 | import { runInRepo } from '../utils.ts' 2 | import { RunOptions } from '../types.ts' 3 | 4 | export async function test(options: RunOptions) { 5 | await runInRepo({ 6 | ...options, 7 | repo: 'sveltejs/prettier-plugin-svelte', 8 | branch: 'master', 9 | build: 'build', 10 | test: 'test', 11 | }) 12 | } 13 | -------------------------------------------------------------------------------- /tests/language-tools.ts: -------------------------------------------------------------------------------- 1 | import { runInRepo } from '../utils.ts' 2 | import { RunOptions } from '../types.ts' 3 | 4 | export async function test(options: RunOptions) { 5 | await runInRepo({ 6 | ...options, 7 | repo: 'sveltejs/language-tools', 8 | branch: 'master', 9 | beforeBuild: 'bootstrap', 10 | build: 'build', 11 | test: 'test', 12 | }) 13 | } 14 | -------------------------------------------------------------------------------- /tests/sv.ts: -------------------------------------------------------------------------------- 1 | import { runInRepo } from '../utils.ts' 2 | import { RunOptions } from '../types.js' 3 | 4 | export async function test(options: RunOptions) { 5 | await runInRepo({ 6 | ...options, 7 | repo: 'sveltejs/cli', 8 | branch: 'main', 9 | build: 'pnpm build', 10 | beforeTest: 'pnpm playwright install chromium', 11 | test: 'pnpm test', 12 | }) 13 | } 14 | -------------------------------------------------------------------------------- /.github/renovate.json5: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json", 3 | "extends": ["config:base", "schedule:weekly", "group:allNonMajor"], 4 | "labels": ["dependencies"], 5 | "ignorePaths": [], 6 | "rangeStrategy": "bump", 7 | "packageRules": [ 8 | { 9 | "depTypeList": ["peerDependencies", "engines"], 10 | "enabled": false, 11 | }, 12 | ], 13 | "ignoreDeps": [], 14 | } 15 | -------------------------------------------------------------------------------- /tests/eslint-plugin-svelte.ts: -------------------------------------------------------------------------------- 1 | import { runInRepo } from '../utils.ts' 2 | import { RunOptions } from '../types.ts' 3 | 4 | export async function test(options: RunOptions) { 5 | await runInRepo({ 6 | ...options, 7 | repo: 'sveltejs/eslint-plugin-svelte', 8 | branch: 'main', 9 | build: 'pnpm --dir packages/eslint-plugin-svelte build', 10 | test: 'pnpm --dir packages/eslint-plugin-svelte test', 11 | }) 12 | } 13 | -------------------------------------------------------------------------------- /tests/vite-plugin-svelte.ts: -------------------------------------------------------------------------------- 1 | import { runInRepo } from '../utils.ts' 2 | import { RunOptions } from '../types.ts' 3 | 4 | export async function test(options: RunOptions) { 5 | await runInRepo({ 6 | ...options, 7 | repo: 'sveltejs/vite-plugin-svelte', 8 | branch: 'main', 9 | beforeTest: 'pnpm playwright install chromium', 10 | test: ['check:lint', 'check:types', 'test'], 11 | overrides: { 12 | 'svelte-check': true, 13 | '@sveltejs/kit': true, 14 | }, 15 | }) 16 | } 17 | -------------------------------------------------------------------------------- /tests/skeleton.ts: -------------------------------------------------------------------------------- 1 | import { runInRepo } from '../utils.ts' 2 | import { RunOptions } from '../types.ts' 3 | 4 | export async function test(options: RunOptions) { 5 | await runInRepo({ 6 | ...options, 7 | repo: 'skeletonlabs/skeleton', 8 | branch: 'main', 9 | build: 'pnpm --dir packages/skeleton-svelte build', 10 | beforeTest: 'pnpm exec playwright install chromium', 11 | test: ['exec vitest run', 'check'].map( 12 | (script) => `pnpm --dir packages/skeleton-svelte ${script}`, 13 | ), 14 | }) 15 | } 16 | -------------------------------------------------------------------------------- /tests/_carbon-components-svelte.ts: -------------------------------------------------------------------------------- 1 | import { runInRepo } from '../utils.ts' 2 | import { RunOptions } from '../types.ts' 3 | 4 | export async function test(options: RunOptions) { 5 | await runInRepo({ 6 | ...options, 7 | repo: 'carbon-design-system/carbon-components-svelte', 8 | branch: 'master', 9 | build: 'build:lib', 10 | test: 'test:types', 11 | overrides: { 12 | 'rollup-plugin-svelte': true, 13 | 'svelte-check': 'latest', // should be true but building it is currently broken 14 | }, 15 | }) 16 | } 17 | -------------------------------------------------------------------------------- /tests/storybook.ts: -------------------------------------------------------------------------------- 1 | import { runInRepo } from '../utils.ts' 2 | import type { RunOptions } from '../types.d.ts' 3 | 4 | export async function test(options: RunOptions) { 5 | await runInRepo({ 6 | ...options, 7 | repo: 'storybookjs/storybook', 8 | branch: 'next', 9 | build: 'svelte-ecosystem-ci:build', 10 | beforeTest: 'svelte-ecosystem-ci:before-test', 11 | test: 'svelte-ecosystem-ci:test', 12 | overrides: { 13 | '@sveltejs/vite-plugin-svelte': true, 14 | '@sveltejs/vite-plugin-svelte-inspector': true, 15 | '@sveltejs/kit': true, 16 | }, 17 | }) 18 | } 19 | -------------------------------------------------------------------------------- /tests/sveltekit.ts: -------------------------------------------------------------------------------- 1 | import { runInRepo } from '../utils.ts' 2 | import { RunOptions } from '../types.ts' 3 | 4 | export async function test(options: RunOptions) { 5 | await runInRepo({ 6 | ...options, 7 | repo: 'sveltejs/kit', 8 | branch: 'main', 9 | overrides: { 10 | '@sveltejs/vite-plugin-svelte': true, 11 | '@sveltejs/vite-plugin-svelte-inspector': true, 12 | 'svelte-check': true, 13 | }, 14 | beforeTest: 'pnpm playwright install', 15 | test: ['test:vite-ecosystem-ci', 'lint', 'check'], // TODO do we want another set of tests for svelte? 16 | }) 17 | } 18 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": ["./**/*.ts"], 3 | "exclude": ["**/node_modules/**", "./workspace/**"], 4 | "compilerOptions": { 5 | "target": "esnext", 6 | "module": "nodenext", 7 | "moduleResolution": "nodenext", 8 | "allowImportingTsExtensions": true, 9 | "noEmit": true, 10 | "skipLibCheck": true, 11 | "strict": true, 12 | "declaration": true, 13 | "noImplicitOverride": true, 14 | "noUnusedLocals": true, 15 | "esModuleInterop": true, 16 | "useUnknownInCatchVariables": false, 17 | "allowSyntheticDefaultImports": true, 18 | "lib": ["esnext"], 19 | "sourceMap": true 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "useTabs": true, 3 | "semi": false, 4 | "tabWidth": 2, 5 | "singleQuote": true, 6 | "printWidth": 80, 7 | "trailingComma": "all", 8 | "overrides": [ 9 | { 10 | "files": ["*.json5"], 11 | "options": { 12 | "singleQuote": false, 13 | "quoteProps": "preserve" 14 | } 15 | }, 16 | { 17 | "files": ["*.yml"], 18 | "options": { 19 | "singleQuote": false 20 | } 21 | }, 22 | { 23 | "files": "**/pnpm-lock.yaml", 24 | "options": { 25 | "requirePragma": true 26 | } 27 | }, 28 | { 29 | "files": "**/package.json", 30 | "options": { 31 | "useTabs": false, 32 | "tabWidth": 2 33 | } 34 | } 35 | ] 36 | } 37 | -------------------------------------------------------------------------------- /tests/_histoire.ts: -------------------------------------------------------------------------------- 1 | import { runInRepo } from '../utils.ts' 2 | import { RunOptions } from '../types.ts' 3 | 4 | // TODO currently the tests around svelte are very few in histoire 5 | const scripts_to_test = { 6 | 'examples/svelte3': ['test:examples'], 7 | // TODO sveltekit example in histoire is broken 8 | //'examples/sveltekit':['sk:build','story:build'] 9 | } 10 | function test_command(dir: string, cmd: string) { 11 | return `pnpm --dir ${dir} --if-present run ${cmd}` 12 | } 13 | 14 | const tests = Object.entries(scripts_to_test) 15 | .map(([dir, cmds]) => cmds.map((cmd) => test_command(dir, cmd))) 16 | .flat() 17 | export async function test(options: RunOptions) { 18 | await runInRepo({ 19 | ...options, 20 | repo: 'histoire-dev/histoire', 21 | branch: 'main', 22 | build: 'build', 23 | overrides: { 24 | '@sveltejs/vite-plugin-svelte': true, 25 | '@sveltejs/kit': true, 26 | '@sveltejs/adapter-auto': true, 27 | // TODO link more packages? 28 | // '@sveltejs/adapter-node': true, 29 | // '@sveltejs/adapter-static': true 30 | }, 31 | test: tests, 32 | }) 33 | } 34 | -------------------------------------------------------------------------------- /eslint.config.js: -------------------------------------------------------------------------------- 1 | // @ts-check 2 | import eslint from '@eslint/js' 3 | import pluginN from 'eslint-plugin-n' 4 | import tseslint from 'typescript-eslint' 5 | 6 | export default tseslint.config( 7 | { 8 | ignores: ['.idea/**', '.vscode/**', 'workspace/**', 'node_modules/**'], 9 | }, 10 | eslint.configs.recommended, 11 | ...tseslint.configs.recommended, 12 | { 13 | name: 'main', 14 | languageOptions: { 15 | parser: tseslint.parser, 16 | parserOptions: { 17 | sourceType: 'module', 18 | ecmaVersion: 2022, 19 | project: true, 20 | }, 21 | }, 22 | plugins: { 23 | n: pluginN, 24 | }, 25 | rules: { 26 | eqeqeq: ['warn', 'always', { null: 'never' }], 27 | 'no-debugger': ['error'], 28 | 'no-empty': ['warn', { allowEmptyCatch: true }], 29 | 'no-process-exit': 'off', 30 | 'no-useless-escape': 'off', 31 | 'prefer-const': [ 32 | 'warn', 33 | { 34 | destructuring: 'all', 35 | }, 36 | ], 37 | 'n/no-missing-import': 'off', // doesn't like ts imports 38 | 'n/no-process-exit': 'off', 39 | '@typescript-eslint/no-explicit-any': 'off', // we use any in some places 40 | }, 41 | }, 42 | ) 43 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023-present, Svelte contributors 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /tests/_selftest.ts: -------------------------------------------------------------------------------- 1 | import path from 'path' 2 | import fs from 'fs' 3 | import { runInRepo } from '../utils.ts' 4 | import { RunOptions } from '../types.ts' 5 | 6 | export async function test(options: RunOptions) { 7 | await runInRepo({ 8 | ...options, 9 | repo: 'sveltejs/svelte-ecosystem-ci', 10 | build: async () => { 11 | const dir = path.resolve(options.workspace, 'svelte-ecosystem-ci') 12 | const pkgFile = path.join(dir, 'package.json') 13 | const pkg = JSON.parse(await fs.promises.readFile(pkgFile, 'utf-8')) 14 | if (pkg.name !== 'svelte-ecosystem-ci') { 15 | throw new Error( 16 | `invalid checkout, expected package.json with "name":"svelte-ecosystem-ci" in ${dir}`, 17 | ) 18 | } 19 | const compilerOutputFile = 20 | options.svelteMajor === 4 21 | ? ' ../../svelte/packages/svelte/compiler.cjs' 22 | : '../../svelte/packages/svelte/compiler/index.js' 23 | pkg.scripts.selftestscript = `[ -f ${compilerOutputFile} ] || (echo 'svelte build failed' && exit 1)` 24 | await fs.promises.writeFile( 25 | pkgFile, 26 | JSON.stringify(pkg, null, 2), 27 | 'utf-8', 28 | ) 29 | }, 30 | test: 'pnpm run selftestscript', 31 | verify: false, 32 | }) 33 | } 34 | -------------------------------------------------------------------------------- /docs/pr-comment-setup.md: -------------------------------------------------------------------------------- 1 | # Setting up "PR comment trigger" feature 2 | 3 | ## (1) Create a GitHub App 4 | 5 | 1. [Create a GitHub App](https://docs.github.com/en/apps/creating-github-apps/registering-a-github-app/registering-a-github-app). Webhook is not needed. The following permissions are required: 6 | - Metadata: Read only 7 | - Actions: Read and Write 8 | - Issues: Read and Write 9 | - Pull requests: Read and Write 10 | 1. Install that App to the organization/user. Give that App access to sveltejs/svelte and sveltejs/svelte-ecosystem-ci. 11 | 1. Check the App ID. It's written on `https://github.com/settings/apps/`. This is used later. 12 | ![GitHub App ID](github_app_id.png) 13 | 1. Generate a private key. It can be generated on the same page with the App ID. The key will be downloaded when you generate it. 14 | ![GitHub App private key](github_app_private_key.png) 15 | 16 | ## (2) Adding secrets to sveltejs/svelte and sveltejs/svelte-ecosystem-ci 17 | 18 | - sveltejs/svelte 19 | - `ECOSYSTEM_CI_GITHUB_APP_ID`: ID of the created GitHub App 20 | - `ECOSYSTEM_CI_GITHUB_APP_PRIVATE_KEY`: the content of the private key of the created GitHub App 21 | - sveltejs/svelte-ecosystem-ci 22 | - `ECOSYSTEM_CI_GITHUB_APP_ID`: ID of the created GitHub App 23 | - `ECOSYSTEM_CI_GITHUB_APP_PRIVATE_KEY`: the content of the private key of the created GitHub App 24 | 25 | ## (3) Adding workflows to sveltejs/svelte 26 | 27 | Add [this workflow](https://github.com/sveltejs/svelte/blob/main/.github/workflows/ecosystem-ci-trigger.yml). 28 | -------------------------------------------------------------------------------- /types.d.ts: -------------------------------------------------------------------------------- 1 | import type { AGENTS } from '@antfu/ni' 2 | export interface EnvironmentData { 3 | root: string 4 | workspace: string 5 | sveltePath: string 6 | cwd: string 7 | env: ProcessEnv 8 | } 9 | 10 | export interface RunOptions { 11 | workspace: string 12 | root: string 13 | sveltePath: string 14 | svelteMajor: number 15 | verify?: boolean 16 | skipGit?: boolean 17 | release?: string 18 | agent?: (typeof AGENTS)[number] 19 | build?: Task | Task[] 20 | test?: Task | Task[] 21 | beforeInstall?: Task | Task[] 22 | beforeBuild?: Task | Task[] 23 | beforeTest?: Task | Task[] 24 | } 25 | 26 | type Task = string | { script: string; args?: string[] } | (() => Promise) 27 | 28 | export interface CommandOptions { 29 | suites?: string[] 30 | repo?: string 31 | branch?: string 32 | tag?: string 33 | commit?: string 34 | release?: string 35 | verify?: boolean 36 | skipGit?: boolean 37 | } 38 | 39 | export interface RepoOptions { 40 | repo: string 41 | dir?: string 42 | branch?: string 43 | tag?: string 44 | commit?: string 45 | shallow?: boolean 46 | overrides?: Overrides 47 | } 48 | 49 | export interface Overrides { 50 | [key: string]: string | boolean 51 | } 52 | 53 | export interface ProcessEnv { 54 | [key: string]: string | undefined 55 | } 56 | 57 | interface DependencyInfo { 58 | from: string 59 | version: string 60 | resolved: string 61 | path: string 62 | } 63 | interface PackageInfo { 64 | name: string 65 | version: string 66 | path: string 67 | private: boolean 68 | dependencies: Record 69 | devDependencies: Record 70 | optionalDependencies: Record 71 | } 72 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | env: 4 | # 7 GiB by default on GitHub, setting to 6 GiB 5 | # https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners#supported-runners-and-hardware-resources 6 | NODE_OPTIONS: --max-old-space-size=6144 7 | # configure corepack to be strict but not download newer versions or change anything 8 | COREPACK_DEFAULT_TO_LATEST: 0 9 | COREPACK_ENABLE_AUTO_PIN: 0 10 | COREPACK_ENABLE_STRICT: 1 11 | # see https://turbo.build/repo/docs/telemetry#how-do-i-opt-out 12 | TURBO_TELEMETRY_DISABLED: 1 13 | DO_NOT_TRACK: 1 14 | on: 15 | push: 16 | branches: 17 | - main 18 | pull_request: 19 | branches: 20 | - main 21 | 22 | jobs: 23 | ci: 24 | timeout-minutes: 10 25 | runs-on: ubuntu-latest 26 | permissions: 27 | contents: read # to clone the repo 28 | steps: 29 | - uses: actions/checkout@v4 30 | - uses: actions/setup-node@v4 31 | with: 32 | node-version: ^24.11.1 33 | - run: corepack enable 34 | - run: pnpm --version 35 | - uses: actions/setup-node@v4 36 | with: 37 | node-version: ^24.11.1 38 | cache: "pnpm" 39 | cache-dependency-path: "**/pnpm-lock.yaml" 40 | - name: install 41 | run: pnpm install --frozen-lockfile --prefer-offline 42 | - name: format 43 | run: pnpm format 44 | - name: lint 45 | run: pnpm run lint 46 | - name: typecheck 47 | run: pnpm run typecheck 48 | - name: audit 49 | if: (${{ success() }} || ${{ failure() }}) 50 | run: pnpm audit --prod --audit-level moderate 51 | - name: test 52 | if: (${{ success() }} || ${{ failure() }}) 53 | run: pnpm test:self 54 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "svelte-ecosystem-ci", 3 | "private": true, 4 | "version": "0.0.1", 5 | "description": "svelte Ecosystem CI", 6 | "scripts": { 7 | "prepare": "pnpm exec simple-git-hooks", 8 | "lint": "eslint '**/*.ts'", 9 | "lint:fix": "pnpm lint --fix", 10 | "typecheck": "tsc", 11 | "format": "prettier --ignore-path .gitignore --check .", 12 | "format:fix": "pnpm format --write", 13 | "test:self": "tsx ecosystem-ci.ts _selftest", 14 | "test": "tsx ecosystem-ci.ts", 15 | "bisect": "tsx ecosystem-ci.ts bisect" 16 | }, 17 | "simple-git-hooks": { 18 | "pre-commit": "pnpm exec lint-staged --concurrent false" 19 | }, 20 | "lint-staged": { 21 | "*": [ 22 | "prettier --write --ignore-unknown" 23 | ], 24 | "*.ts": [ 25 | "eslint --fix" 26 | ] 27 | }, 28 | "packageManager": "pnpm@10.6.3", 29 | "type": "module", 30 | "engines": { 31 | "node": ">=22", 32 | "pnpm": "^10.2.1" 33 | }, 34 | "repository": { 35 | "type": "git", 36 | "url": "git+https://github.com/sveltejs/svelte-ecosystem-ci.git" 37 | }, 38 | "license": "MIT", 39 | "bugs": { 40 | "url": "https://github.com/sveltejs/svelte-ecosystem-ci/issues" 41 | }, 42 | "homepage": "https://github.com/sveltejs/svelte-ecosystem-ci#readme", 43 | "dependencies": { 44 | "@actions/core": "^1.11.1", 45 | "cac": "^6.7.14", 46 | "execa": "^9.5.2", 47 | "node-fetch": "^3.3.2" 48 | }, 49 | "devDependencies": { 50 | "@antfu/ni": "^24.3.0", 51 | "@eslint/js": "^9.25.1", 52 | "@types/node": "^22.14.1", 53 | "@types/semver": "^7.7.0", 54 | "eslint": "^9.25.1", 55 | "eslint-plugin-n": "^17.17.0", 56 | "lint-staged": "^15.5.1", 57 | "prettier": "^3.5.3", 58 | "semver": "^7.7.1", 59 | "simple-git-hooks": "^2.12.1", 60 | "tsx": "^4.19.3", 61 | "typescript": "^5.8.3", 62 | "typescript-eslint": "^8.31.0" 63 | }, 64 | "pnpm": { 65 | "overrides": { 66 | "cross-spawn@>=7.0.0 <7.0.5": "^7.0.6" 67 | }, 68 | "onlyBuiltDependencies": [ 69 | "esbuild", 70 | "simple-git-hooks" 71 | ], 72 | "auditConfig": { 73 | "ignoreGhsas": [ 74 | "GHSA-67mh-4wv8-2f99" 75 | ] 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # svelte-ecosystem-ci 2 | 3 | This repository is used to run integration tests for svelte ecosystem projects 4 | 5 | ## via github workflow 6 | 7 | ### scheduled 8 | 9 | Workflows are scheduled to run automatically every Monday, Wednesday and Friday 10 | 11 | ### manually 12 | 13 | - open [workflow](../../actions/workflows/ecosystem-ci-selected.yml) 14 | - click 'Run workflow' button on top right of the list 15 | - select suite to run in dropdown 16 | - start workflow 17 | 18 | ## via shell script 19 | 20 | - clone this repo 21 | - run `pnpm i` 22 | - run `pnpm test` to run all suites 23 | - or `pnpm test ` to select a suite 24 | - or `tsx ecosystem-ci.ts` 25 | 26 | You can pass `--tag v2.8.0-beta.1`, `--branch somebranch` or `--commit abcd1234` option to select a specific svelte version to build. 27 | If you pass `--release 2.7.13`, svelte build will be skipped and svelte is fetched from the registry instead 28 | 29 | The repositories are checked out into `workspace` subdirectory as shallow clones 30 | 31 | ## via comment on PR 32 | 33 | - comment `/ecosystem-ci run` on a PR 34 | - or `/ecosystem-ci run ` to select a suite 35 | 36 | Users with triage permission to sveltejs/svelte repository can only use this. 37 | 38 | See [docs/pr-comment-setup.md](./docs/pr-comment-setup.md) for how to setup this feature. 39 | 40 | # how to add a new integration test 41 | 42 | - check out the existing [tests](./tests) and add one yourself. Thanks to some utilities it is really easy 43 | - once you are confident the suite works, add it to the lists of suites in the [workflows](../../actions/) 44 | 45 | # reporting results 46 | 47 | ## Discord 48 | 49 | Results are posted automatically to `#ecosystem-ci` on [svelte discord](https://svelte.dev/chat/) 50 | 51 | ### on your own server 52 | 53 | - Go to `Server settings > Integrations > Webhooks` and click `New Webhook` 54 | - Give it a name, icon and a channel to post to 55 | - copy the webhook url 56 | - get in touch with admins of this repo so they can add the webhook 57 | 58 | #### how to add a discord webhook here 59 | 60 | - Go to `/settings/secrets/actions` and click on `New repository secret` 61 | - set `Name` as `DISCORD_WEBHOOK_URL` 62 | - paste the discord webhook url you copied from above into `Value` 63 | - Click `Add secret` 64 | -------------------------------------------------------------------------------- /.github/workflows/ecosystem-ci-selected.yml: -------------------------------------------------------------------------------- 1 | # integration tests for svelte ecosystem - single run of selected testsuite 2 | name: svelte-ecosystem-ci-selected 3 | 4 | env: 5 | # 7 GiB by default on GitHub, setting to 6 GiB 6 | # https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners#supported-runners-and-hardware-resources 7 | NODE_OPTIONS: --max-old-space-size=6144 8 | # configure corepack to be strict but not download newer versions or change anything 9 | COREPACK_DEFAULT_TO_LATEST: 0 10 | COREPACK_ENABLE_AUTO_PIN: 0 11 | COREPACK_ENABLE_STRICT: 1 12 | # see https://turbo.build/repo/docs/telemetry#how-do-i-opt-out 13 | TURBO_TELEMETRY_DISABLED: 1 14 | DO_NOT_TRACK: 1 15 | on: 16 | workflow_dispatch: 17 | inputs: 18 | refType: 19 | description: "type of svelte ref to use" 20 | required: true 21 | type: choice 22 | options: 23 | - branch 24 | - tag 25 | - commit 26 | - release 27 | default: "branch" 28 | ref: 29 | description: "svelte ref to use" 30 | required: true 31 | type: string 32 | default: "main" 33 | repo: 34 | description: "svelte repository to use" 35 | required: true 36 | type: string 37 | default: "sveltejs/svelte" 38 | suite: 39 | description: "testsuite to run" 40 | required: true 41 | type: choice 42 | options: 43 | - eslint-plugin-svelte 44 | - language-tools 45 | - mdsvex 46 | - melt-ui 47 | - prettier-plugin-svelte 48 | - rollup-plugin-svelte 49 | - skeleton 50 | - storybook 51 | - sv 52 | - svelte-eslint-parser 53 | - svelte-loader 54 | - svelte-preprocess 55 | - sveltekit 56 | - vite-plugin-svelte 57 | sendDiscordReport: 58 | description: "send results to discord" 59 | type: boolean 60 | jobs: 61 | execute-selected-suite: 62 | timeout-minutes: 30 63 | runs-on: ubuntu-latest 64 | permissions: 65 | contents: read # to clone the repo 66 | steps: 67 | - uses: actions/checkout@v4 68 | - uses: actions/setup-node@v4 69 | with: 70 | node-version: ^24.11.1 71 | id: setup-node 72 | - run: corepack enable 73 | - run: pnpm --version 74 | - run: pnpm i --frozen-lockfile 75 | - run: >- 76 | pnpm tsx ecosystem-ci.ts 77 | "--$REF_TYPE" "$REF" 78 | --repo "$REPO" 79 | "$SUITE" 80 | id: ecosystem-ci-run 81 | env: 82 | REF_TYPE: ${{ inputs.refType }} 83 | REF: ${{ inputs.ref }} 84 | REPO: ${{ inputs.repo }} 85 | SUITE: ${{ inputs.suite }} 86 | - if: always() && (inputs.sendDiscordReport || github.event_name != 'workflow_dispatch') 87 | run: pnpm tsx discord-webhook.ts 88 | env: 89 | WORKFLOW_NAME: ci-selected 90 | REF_TYPE: ${{ inputs.refType }} 91 | REF: ${{ inputs.ref }} 92 | REPO: ${{ inputs.repo }} 93 | SUITE: ${{ inputs.suite }} 94 | STATUS: ${{ job.status }} 95 | DISCORD_WEBHOOK_URL: ${{ secrets.DISCORD_WEBHOOK_URL }} 96 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 97 | -------------------------------------------------------------------------------- /.github/workflows/ecosystem-ci.yml: -------------------------------------------------------------------------------- 1 | # integration tests for svelte ecosystem projects - scheduled or manual run for all suites 2 | name: svelte-ecosystem-ci 3 | 4 | env: 5 | # 7 GiB by default on GitHub, setting to 6 GiB 6 | # https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners#supported-runners-and-hardware-resources 7 | NODE_OPTIONS: --max-old-space-size=6144 8 | # configure corepack to be strict but not download newer versions or change anything 9 | COREPACK_DEFAULT_TO_LATEST: 0 10 | COREPACK_ENABLE_AUTO_PIN: 0 11 | COREPACK_ENABLE_STRICT: 1 12 | # see https://turbo.build/repo/docs/telemetry#how-do-i-opt-out 13 | TURBO_TELEMETRY_DISABLED: 1 14 | DO_NOT_TRACK: 1 15 | on: 16 | schedule: 17 | - cron: "0 5 * * 1,3,5" # monday,wednesday,friday 5AM 18 | workflow_dispatch: 19 | inputs: 20 | refType: 21 | description: "type of ref" 22 | required: true 23 | type: choice 24 | options: 25 | - branch 26 | - tag 27 | - commit 28 | - release 29 | default: "branch" 30 | ref: 31 | description: "svelte ref to use" 32 | required: true 33 | type: string 34 | default: "main" 35 | repo: 36 | description: "svelte repository to use" 37 | required: true 38 | type: string 39 | default: "sveltejs/svelte" 40 | sendDiscordReport: 41 | description: "send results to discord" 42 | type: boolean 43 | repository_dispatch: 44 | types: [ecosystem-ci] 45 | jobs: 46 | test-ecosystem: 47 | timeout-minutes: 30 48 | runs-on: ubuntu-latest 49 | strategy: 50 | matrix: 51 | suite: 52 | - eslint-plugin-svelte 53 | - language-tools 54 | - mdsvex 55 | - melt-ui 56 | - prettier-plugin-svelte 57 | - rollup-plugin-svelte 58 | - skeleton 59 | - storybook 60 | - sv 61 | - svelte-eslint-parser 62 | - svelte-loader 63 | - svelte-preprocess 64 | - sveltekit 65 | - vite-plugin-svelte 66 | fail-fast: false 67 | permissions: 68 | contents: read # to clone the repo 69 | steps: 70 | - uses: actions/checkout@v4 71 | - uses: actions/setup-node@v4 72 | with: 73 | node-version: ^24.11.1 74 | id: setup-node 75 | - run: corepack enable 76 | - run: pnpm --version 77 | - run: pnpm i --frozen-lockfile 78 | - run: >- 79 | pnpm tsx ecosystem-ci.ts 80 | "--$REF_TYPE" "$REF" 81 | --repo "$REPO" 82 | "$SUITE" 83 | id: ecosystem-ci-run 84 | env: 85 | REF_TYPE: ${{ inputs.refType || github.event.client_payload.refType || 'branch' }} 86 | REF: ${{ inputs.ref || github.event.client_payload.ref || 'main' }} 87 | REPO: ${{ inputs.repo || github.event.client_payload.repo || 'sveltejs/svelte' }} 88 | SUITE: ${{ matrix.suite }} 89 | - if: always() && (inputs.sendDiscordReport || github.event_name != 'workflow_dispatch') 90 | run: pnpm tsx discord-webhook.ts 91 | env: 92 | WORKFLOW_NAME: ci 93 | REF_TYPE: ${{ inputs.refType || github.event.client_payload.refType || 'branch' }} 94 | REF: ${{ inputs.ref || github.event.client_payload.ref || 'main' }} 95 | REPO: ${{ inputs.repo || github.event.client_payload.repo || 'sveltejs/svelte' }} 96 | SUITE: ${{ matrix.suite }} 97 | STATUS: ${{ job.status }} 98 | DISCORD_WEBHOOK_URL: ${{ secrets.DISCORD_WEBHOOK_URL }} 99 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 100 | -------------------------------------------------------------------------------- /discord-webhook.ts: -------------------------------------------------------------------------------- 1 | import fetch from 'node-fetch' 2 | import { getPermanentRef, setupEnvironment } from './utils.ts' 3 | 4 | type RefType = 'branch' | 'tag' | 'commit' | 'release' 5 | type Status = 'success' | 'failure' | 'cancelled' 6 | type Env = { 7 | WORKFLOW_NAME?: string 8 | REF_TYPE?: RefType 9 | REF?: string 10 | REPO?: string 11 | SUITE?: string 12 | STATUS?: Status 13 | DISCORD_WEBHOOK_URL?: string 14 | IS_ROLLDOWN_VITE?: '1' 15 | } 16 | 17 | const statusConfig = { 18 | success: { 19 | color: parseInt('57ab5a', 16), 20 | emoji: ':white_check_mark:', 21 | }, 22 | expectedFailure: { 23 | color: parseInt('c69026', 16), 24 | emoji: ':construction:', 25 | }, 26 | failure: { 27 | color: parseInt('e5534b', 16), 28 | emoji: ':x:', 29 | }, 30 | cancelled: { 31 | color: parseInt('768390', 16), 32 | emoji: ':stop_button:', 33 | }, 34 | } 35 | 36 | async function run() { 37 | if (!process.env.GITHUB_ACTIONS) { 38 | throw new Error('This script can only run on GitHub Actions.') 39 | } 40 | if (!process.env.DISCORD_WEBHOOK_URL) { 41 | console.warn( 42 | "Skipped beacuse process.env.DISCORD_WEBHOOK_URL was empty or didn't exist", 43 | ) 44 | return 45 | } 46 | if (!process.env.GITHUB_TOKEN) { 47 | console.warn( 48 | "Not using a token because process.env.GITHUB_TOKEN was empty or didn't exist", 49 | ) 50 | } 51 | 52 | const env = process.env as Env 53 | 54 | assertEnv('WORKFLOW_NAME', env.WORKFLOW_NAME) 55 | assertEnv('REF_TYPE', env.REF_TYPE) 56 | assertEnv('REF', env.REF) 57 | assertEnv('REPO', env.REPO) 58 | assertEnv('SUITE', env.SUITE) 59 | assertEnv('STATUS', env.STATUS) 60 | assertEnv('DISCORD_WEBHOOK_URL', env.DISCORD_WEBHOOK_URL) 61 | const isRolldownVite = !!env.IS_ROLLDOWN_VITE 62 | const expectedFailureReason = isRolldownVite 63 | ? await loadExpectedFailureReason(env.SUITE) 64 | : undefined 65 | const status = 66 | env.STATUS === 'failure' && expectedFailureReason 67 | ? 'expectedFailure' 68 | : env.STATUS 69 | 70 | await setupEnvironment() 71 | 72 | const refType = env.REF_TYPE 73 | // svelte repo is not cloned when release 74 | const permRef = refType === 'release' ? undefined : await getPermanentRef() 75 | 76 | const targetText = createTargetText(refType, env.REF, permRef, env.REPO) 77 | 78 | const webhookContent = { 79 | username: `svelte-ecosystem-ci (${env.WORKFLOW_NAME})`, 80 | avatar_url: 'https://github.com/sveltejs.png', 81 | embeds: [ 82 | { 83 | title: `${statusConfig[status].emoji} ${env.SUITE}`, 84 | description: await createDescription( 85 | env.SUITE, 86 | targetText, 87 | expectedFailureReason, 88 | ), 89 | color: statusConfig[status].color, 90 | }, 91 | ], 92 | } 93 | 94 | const res = await fetch(env.DISCORD_WEBHOOK_URL, { 95 | method: 'POST', 96 | headers: { 97 | 'Content-Type': 'application/json', 98 | }, 99 | body: JSON.stringify(webhookContent), 100 | }) 101 | if (res.ok) { 102 | console.log('Sent Webhook') 103 | } else { 104 | console.error(`Webhook failed ${res.status}:`, await res.text()) 105 | } 106 | } 107 | 108 | function assertEnv( 109 | name: string, 110 | value: T, 111 | ): asserts value is Exclude { 112 | if (!value) { 113 | throw new Error(`process.env.${name} is empty or does not exist.`) 114 | } 115 | } 116 | 117 | async function loadExpectedFailureReason(suite: string) { 118 | const module = await import(`./tests/${suite}.ts`) 119 | const reason: string | undefined = module.rolldownViteExpectedFailureReason 120 | return reason?.trim() 121 | } 122 | 123 | async function createRunUrl(suite: string) { 124 | const result = await fetchJobs() 125 | if (!result) { 126 | return undefined 127 | } 128 | 129 | if (result.total_count <= 0) { 130 | console.warn('total_count was 0') 131 | return undefined 132 | } 133 | 134 | const job = result.jobs.find((job) => job.name === process.env.GITHUB_JOB) 135 | if (job) { 136 | return job.html_url 137 | } 138 | 139 | // when matrix 140 | const jobM = result.jobs.find( 141 | (job) => job.name === `${process.env.GITHUB_JOB} (${suite})`, 142 | ) 143 | return jobM?.html_url 144 | } 145 | 146 | interface GitHubActionsJob { 147 | name: string 148 | html_url: string 149 | } 150 | 151 | async function fetchJobs() { 152 | const url = `${process.env.GITHUB_API_URL}/repos/${process.env.GITHUB_REPOSITORY}/actions/runs/${process.env.GITHUB_RUN_ID}/jobs` 153 | const res = await fetch(url, { 154 | headers: { 155 | Accept: 'application/vnd.github.v3+json', 156 | ...(process.env.GITHUB_TOKEN 157 | ? { 158 | Authorization: `token ${process.env.GITHUB_TOKEN}`, 159 | } 160 | : undefined), 161 | }, 162 | }) 163 | if (!res.ok) { 164 | console.warn( 165 | `Failed to fetch jobs (${res.status} ${res.statusText}): ${res.text()}`, 166 | ) 167 | return null 168 | } 169 | 170 | const result = await res.json() 171 | return result as { 172 | total_count: number 173 | jobs: GitHubActionsJob[] 174 | } 175 | } 176 | 177 | async function createDescription( 178 | suite: string, 179 | targetText: string, 180 | expectedFailureReason: string | undefined, 181 | ) { 182 | const runUrl = await createRunUrl(suite) 183 | const open = runUrl === undefined ? 'Null' : `[Open](${runUrl})` 184 | let message = ` 185 | :scroll:\u00a0\u00a0${open}\u3000\u3000:zap:\u00a0\u00a0${targetText} 186 | `.trim() 187 | if (expectedFailureReason) { 188 | message += 189 | '\n' + 190 | ` 191 | :bulb:\u00a0\u00a0${expectedFailureReason} 192 | `.trim() 193 | } 194 | return message 195 | } 196 | 197 | function createTargetText( 198 | refType: RefType, 199 | ref: string, 200 | permRef: string | undefined, 201 | repo: string, 202 | ) { 203 | const repoText = repo !== 'sveltejs/svelte' ? `${repo}:` : '' 204 | if (refType === 'branch') { 205 | const shortRef = permRef?.slice(0, 7) 206 | const link = `https://github.com/${repo}/commits/${permRef || ref}` 207 | return `[${repoText}${ref} (${shortRef || 'unknown'})](${link})` 208 | } 209 | 210 | const refTypeText = refType === 'release' ? ' (release)' : '' 211 | const link = `https://github.com/${repo}/commits/${ref}` 212 | return `[${repoText}${ref}${refTypeText}](${link})` 213 | } 214 | 215 | run().catch((e) => { 216 | console.error('Error sending webhook:', e) 217 | }) 218 | -------------------------------------------------------------------------------- /ecosystem-ci.ts: -------------------------------------------------------------------------------- 1 | import fs from 'fs' 2 | import path from 'path' 3 | import process from 'process' 4 | import { cac } from 'cac' 5 | 6 | import { 7 | setupEnvironment, 8 | setupSvelteRepo, 9 | buildSvelte, 10 | bisectSvelte, 11 | parseSvelteMajor, 12 | parseMajorVersion, 13 | } from './utils.ts' 14 | import type { CommandOptions, RunOptions } from './types.d.ts' 15 | 16 | const cli = cac() 17 | cli 18 | .command('[...suites]', 'build svelte and run selected suites') 19 | .option('--verify', 'verify checkouts by running tests', { default: false }) 20 | .option('--repo ', 'svelte repository to use', { 21 | default: 'sveltejs/svelte', 22 | }) 23 | .option('--branch ', 'svelte branch to use', { default: 'main' }) 24 | .option('--tag ', 'svelte tag to use') 25 | .option('--commit ', 'svelte commit sha to use') 26 | .option('--release ', 'svelte release to use from npm registry') 27 | .action(async (suites, options: CommandOptions) => { 28 | if (options.commit) { 29 | const url = `https://pkg.pr.new/svelte@${options.commit}` 30 | 31 | const { status } = await fetch(url) 32 | if (status === 200) { 33 | options.release = url 34 | delete options.commit 35 | 36 | console.log(`continuous release available on ${url}`) 37 | } 38 | } 39 | const { root, sveltePath, workspace } = await setupEnvironment() 40 | const suitesToRun = getSuitesToRun(suites, root) 41 | let svelteMajor 42 | if (!options.release) { 43 | await setupSvelteRepo(options) 44 | await buildSvelte({ verify: options.verify }) 45 | svelteMajor = parseSvelteMajor(sveltePath) 46 | } else { 47 | svelteMajor = parseMajorVersion(options.release) 48 | } 49 | const runOptions: RunOptions = { 50 | root, 51 | sveltePath, 52 | svelteMajor, 53 | workspace, 54 | release: options.release, 55 | verify: options.verify, 56 | skipGit: false, 57 | } 58 | for (const suite of suitesToRun) { 59 | await run(suite, runOptions) 60 | } 61 | }) 62 | 63 | cli 64 | .command('build-svelte', 'build svelte only') 65 | .option('--verify', 'verify svelte checkout by running tests', { 66 | default: false, 67 | }) 68 | .option('--repo ', 'svelte repository to use', { 69 | default: 'sveltejs/svelte', 70 | }) 71 | .option('--branch ', 'svelte branch to use', { default: 'main' }) 72 | .option('--tag ', 'svelte tag to use') 73 | .option('--commit ', 'svelte commit sha to use') 74 | .action(async (options: CommandOptions) => { 75 | await setupEnvironment() 76 | await setupSvelteRepo(options) 77 | await buildSvelte({ verify: options.verify }) 78 | }) 79 | 80 | cli 81 | .command('run-suites [...suites]', 'run single suite with pre-built svelte') 82 | .option( 83 | '--verify', 84 | 'verify checkout by running tests before using local svelte', 85 | { default: false }, 86 | ) 87 | .option('--repo ', 'svelte repository to use', { 88 | default: 'sveltejs/svelte', 89 | }) 90 | .option('--release ', 'svelte release to use from npm registry') 91 | .action(async (suites, options: CommandOptions) => { 92 | const { root, sveltePath, workspace } = await setupEnvironment() 93 | const suitesToRun = getSuitesToRun(suites, root) 94 | const runOptions: RunOptions = { 95 | ...options, 96 | root, 97 | sveltePath, 98 | svelteMajor: parseSvelteMajor(sveltePath), 99 | workspace, 100 | } 101 | for (const suite of suitesToRun) { 102 | await run(suite, runOptions) 103 | } 104 | }) 105 | 106 | cli 107 | .command( 108 | 'bisect [...suites]', 109 | 'use git bisect to find a commit in svelte that broke suites', 110 | ) 111 | .option('--good ', 'last known good ref, e.g. a previous tag. REQUIRED!') 112 | .option('--verify', 'verify checkouts by running tests', { default: false }) 113 | .option('--repo ', 'svelte repository to use', { 114 | default: 'sveltejs/svelte', 115 | }) 116 | .option('--branch ', 'svelte branch to use', { default: 'main' }) 117 | .option('--tag ', 'svelte tag to use') 118 | .option('--commit ', 'svelte commit sha to use') 119 | .action(async (suites, options: CommandOptions & { good: string }) => { 120 | if (!options.good) { 121 | console.log( 122 | 'you have to specify a known good version with `--good `', 123 | ) 124 | process.exit(1) 125 | } 126 | const { root, sveltePath, workspace } = await setupEnvironment() 127 | const suitesToRun = getSuitesToRun(suites, root) 128 | let isFirstRun = true 129 | const { verify } = options 130 | const runSuite = async () => { 131 | try { 132 | await buildSvelte({ verify: isFirstRun && verify }) 133 | for (const suite of suitesToRun) { 134 | await run(suite, { 135 | verify: !!(isFirstRun && verify), 136 | skipGit: !isFirstRun, 137 | root, 138 | sveltePath, 139 | svelteMajor: parseSvelteMajor(sveltePath), 140 | workspace, 141 | }) 142 | } 143 | isFirstRun = false 144 | return null 145 | } catch (e) { 146 | return e 147 | } 148 | } 149 | await setupSvelteRepo({ ...options, shallow: false }) 150 | const initialError = await runSuite() 151 | if (initialError) { 152 | await bisectSvelte(options.good, runSuite) 153 | } else { 154 | console.log(`no errors for starting commit, cannot bisect`) 155 | } 156 | }) 157 | cli.help() 158 | cli.parse() 159 | 160 | async function run(suite: string, options: RunOptions) { 161 | const { test } = await import(`./tests/${suite}.ts`) 162 | await test({ 163 | ...options, 164 | workspace: path.resolve(options.workspace, suite), 165 | }) 166 | } 167 | 168 | function getSuitesToRun(suites: string[], root: string) { 169 | let suitesToRun: string[] = suites 170 | const availableSuites: string[] = fs 171 | .readdirSync(path.join(root, 'tests')) 172 | .filter((f: string) => !f.startsWith('_') && f.endsWith('.ts')) 173 | .map((f: string) => f.slice(0, -3)) 174 | availableSuites.sort() 175 | if (suitesToRun.length === 0) { 176 | suitesToRun = availableSuites 177 | } else { 178 | const invalidSuites = suitesToRun.filter( 179 | (x) => !x.startsWith('_') && !availableSuites.includes(x), 180 | ) 181 | if (invalidSuites.length) { 182 | console.log(`invalid suite(s): ${invalidSuites.join(', ')}`) 183 | console.log(`available suites: ${availableSuites.join(', ')}`) 184 | process.exit(1) 185 | } 186 | } 187 | return suitesToRun 188 | } 189 | -------------------------------------------------------------------------------- /.github/workflows/ecosystem-ci-from-pr.yml: -------------------------------------------------------------------------------- 1 | # integration tests for svelte ecosystem - run from pr comments 2 | name: svelte-ecosystem-ci-from-pr 3 | 4 | env: 5 | # 7 GiB by default on GitHub, setting to 6 GiB 6 | # https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners#supported-runners-and-hardware-resources 7 | NODE_OPTIONS: --max-old-space-size=6144 8 | # configure corepack to be strict but not download newer versions or change anything 9 | COREPACK_DEFAULT_TO_LATEST: 0 10 | COREPACK_ENABLE_AUTO_PIN: 0 11 | COREPACK_ENABLE_STRICT: 1 12 | # see https://turbo.build/repo/docs/telemetry#how-do-i-opt-out 13 | TURBO_TELEMETRY_DISABLED: 1 14 | DO_NOT_TRACK: 1 15 | on: 16 | workflow_dispatch: 17 | inputs: 18 | prNumber: 19 | description: "PR number (e.g. 9887)" 20 | required: true 21 | type: string 22 | branchName: 23 | description: "svelte branch to use" 24 | required: true 25 | type: string 26 | default: "main" 27 | repo: 28 | description: "svelte repository to use" 29 | required: true 30 | type: string 31 | default: "sveltejs/svelte" 32 | commit: 33 | description: "svelte commit sha to use" 34 | type: string 35 | suite: 36 | description: "testsuite to run. runs all testsuits when `-`." 37 | required: false 38 | type: choice 39 | options: 40 | - "-" 41 | - eslint-plugin-svelte 42 | - language-tools 43 | - mdsvex 44 | - melt-ui 45 | - prettier-plugin-svelte 46 | - rollup-plugin-svelte 47 | - skeleton 48 | - storybook 49 | - sv 50 | - svelte-eslint-parser 51 | - svelte-loader 52 | - svelte-preprocess 53 | - sveltekit 54 | - vite-plugin-svelte 55 | jobs: 56 | init: 57 | runs-on: ubuntu-latest 58 | outputs: 59 | comment-id: ${{ steps.create-comment.outputs.result }} 60 | permissions: {} 61 | steps: 62 | - id: generate-token 63 | uses: actions/create-github-app-token@v2 64 | with: 65 | app-id: ${{ secrets.ECOSYSTEM_CI_GITHUB_APP_ID }} 66 | private-key: ${{ secrets.ECOSYSTEM_CI_GITHUB_APP_PRIVATE_KEY }} 67 | repositories: svelte 68 | - id: create-comment 69 | uses: actions/github-script@v7 70 | with: 71 | github-token: ${{ steps.generate-token.outputs.token }} 72 | result-encoding: string 73 | script: | 74 | const url = `${context.serverUrl}//${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}` 75 | const urlLink = `[Open](${url})` 76 | 77 | const { data: comment } = await github.rest.issues.createComment({ 78 | issue_number: context.payload.inputs.prNumber, 79 | owner: context.repo.owner, 80 | repo: 'svelte', 81 | body: `⏳ Triggered ecosystem CI: ${urlLink}` 82 | }) 83 | return comment.id 84 | 85 | execute-selected-suite: 86 | timeout-minutes: 30 87 | runs-on: ubuntu-latest 88 | needs: init 89 | if: "inputs.suite != '-'" 90 | outputs: 91 | ref: ${{ steps.get-ref.outputs.ref }} 92 | permissions: 93 | contents: read # to clone the repo 94 | steps: 95 | - uses: actions/checkout@v4 96 | - uses: actions/setup-node@v4 97 | with: 98 | node-version: ^24.11.1 99 | - run: corepack enable 100 | - run: pnpm --version 101 | - run: pnpm i --frozen-lockfile 102 | - run: >- 103 | pnpm tsx ecosystem-ci.ts 104 | --branch "$BRANCH_NAME" 105 | --repo "$REPO" 106 | $(if [ -n "$COMMIT" ] ; then echo "--commit $COMMIT"; fi) 107 | "$SUITE" 108 | env: 109 | BRANCH_NAME: ${{ inputs.branchName }} 110 | REPO: ${{ inputs.repo }} 111 | COMMIT: ${{ inputs.commit }} 112 | SUITE: ${{ inputs.suite }} 113 | - id: get-ref 114 | if: always() 115 | run: | 116 | REF="${REF:-"$(git log -1 --pretty=format:%H)"}" 117 | echo "ref=$REF" >> $GITHUB_OUTPUT 118 | env: 119 | COMMIT: ${{ inputs.commit }} 120 | working-directory: ${{ inputs.commit && '.' || 'workspace/svelte' }} 121 | 122 | execute-all: 123 | timeout-minutes: 30 124 | runs-on: ubuntu-latest 125 | needs: init 126 | if: "inputs.suite == '-'" 127 | outputs: 128 | ref: ${{ steps.get-ref.outputs.ref }} 129 | permissions: 130 | contents: read # to clone the repo 131 | strategy: 132 | matrix: 133 | suite: 134 | - eslint-plugin-svelte 135 | - language-tools 136 | - mdsvex 137 | - melt-ui 138 | - prettier-plugin-svelte 139 | - rollup-plugin-svelte 140 | - skeleton 141 | - storybook 142 | - sv 143 | - svelte-eslint-parser 144 | - svelte-loader 145 | - svelte-preprocess 146 | - sveltekit 147 | - vite-plugin-svelte 148 | fail-fast: false 149 | steps: 150 | - uses: actions/checkout@v4 151 | - uses: actions/setup-node@v4 152 | with: 153 | node-version: ^24.11.1 154 | - run: corepack enable 155 | - run: pnpm --version 156 | - run: pnpm i --frozen-lockfile 157 | - run: >- 158 | pnpm tsx ecosystem-ci.ts 159 | --branch "$BRANCH_NAME" 160 | --repo "$REPO" 161 | $(if [ -n "$COMMIT" ] ; then echo "--commit $COMMIT"; fi) 162 | "$SUITE" 163 | env: 164 | BRANCH_NAME: ${{ inputs.branchName }} 165 | REPO: ${{ inputs.repo }} 166 | COMMIT: ${{ inputs.commit }} 167 | SUITE: ${{ matrix.suite }} 168 | - id: get-ref 169 | if: always() 170 | run: | 171 | REF="${REF:-"$(git log -1 --pretty=format:%H)"}" 172 | echo "ref=$REF" >> $GITHUB_OUTPUT 173 | env: 174 | COMMIT: ${{ inputs.commit }} 175 | working-directory: ${{ inputs.commit && '.' || 'workspace/svelte' }} 176 | 177 | update-comment: 178 | runs-on: ubuntu-latest 179 | needs: [init, execute-selected-suite, execute-all] 180 | if: always() 181 | permissions: {} 182 | steps: 183 | - id: generate-token 184 | uses: actions/create-github-app-token@v2 185 | with: 186 | app-id: ${{ secrets.ECOSYSTEM_CI_GITHUB_APP_ID }} 187 | private-key: ${{ secrets.ECOSYSTEM_CI_GITHUB_APP_PRIVATE_KEY }} 188 | repositories: | 189 | svelte 190 | svelte-ecosystem-ci 191 | - uses: actions/github-script@v7 192 | with: 193 | github-token: ${{ steps.generate-token.outputs.token }} 194 | script: | 195 | const mainRepoName = 'svelte' 196 | const ref = process.env.REF 197 | const refLink = `[\`${ref.slice(0, 7)}\`](${context.serverUrl}/${context.repo.owner}/${mainRepoName}/pull/${context.payload.inputs.prNumber}/commits/${ref})` 198 | 199 | const { data: { jobs } } = await github.rest.actions.listJobsForWorkflowRun({ 200 | owner: context.repo.owner, 201 | repo: context.repo.repo, 202 | run_id: context.runId, 203 | per_page: 100 204 | }); 205 | 206 | const selectedSuite = context.payload.inputs.suite 207 | let results 208 | if (selectedSuite !== "-") { 209 | const { conclusion, html_url } = jobs.find(job => job.name === "execute-selected-suite") 210 | results = [{ suite: selectedSuite, conclusion, link: html_url }] 211 | } else { 212 | results = jobs 213 | .filter(job => job.name.startsWith('execute-all ')) 214 | .map(job => { 215 | const suite = job.name.replace(/^execute-all \(([^)]+)\)$/, "$1") 216 | return { suite, conclusion: job.conclusion, link: job.html_url } 217 | }) 218 | } 219 | 220 | const url = `${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}` 221 | const urlLink = `[Open](${url})` 222 | 223 | const conclusionEmoji = { 224 | success: ":white_check_mark:", 225 | failure: ":x:", 226 | cancelled: ":stop_button:" 227 | } 228 | 229 | // check for previous ecosystem-ci runs against the main branch 230 | 231 | // first, list workflow runs for ecosystem-ci.yml 232 | const { data: { workflow_runs } } = await github.rest.actions.listWorkflowRuns({ 233 | owner: context.repo.owner, 234 | repo: context.repo.repo, 235 | workflow_id: 'ecosystem-ci.yml' 236 | }); 237 | 238 | // for simplity, we only take the latest completed scheduled run 239 | // otherwise we would have to check the inputs for every maunally triggerred runs, which is an overkill 240 | const latestScheduledRun = workflow_runs.find(run => run.event === "schedule" && run.status === "completed") 241 | 242 | // get the jobs for the latest scheduled run 243 | const { data: { jobs: scheduledJobs } } = await github.rest.actions.listJobsForWorkflowRun({ 244 | owner: context.repo.owner, 245 | repo: context.repo.repo, 246 | run_id: latestScheduledRun.id 247 | }); 248 | const scheduledResults = scheduledJobs 249 | .filter(job => job.name.startsWith('test-ecosystem ')) 250 | .map(job => { 251 | const suite = job.name.replace(/^test-ecosystem \(([^)]+)\)$/, "$1") 252 | return { suite, conclusion: job.conclusion, link: job.html_url } 253 | }) 254 | 255 | const rows = [] 256 | const successfulSuitesWithoutChanges = [] 257 | results.forEach(current => { 258 | const latest = scheduledResults.find(s => s.suite === current.suite) || {} // in case a new suite is added after latest scheduled 259 | 260 | if (current.conclusion === "success" && latest.conclusion === "success") { 261 | successfulSuitesWithoutChanges.push(`[${current.suite}](${current.link})`) 262 | } 263 | else { 264 | const firstColumn = current.suite 265 | const secondColumn = `${conclusionEmoji[current.conclusion]} [${current.conclusion}](${current.link})` 266 | const thirdColumn = `${conclusionEmoji[latest.conclusion]} [${latest.conclusion}](${latest.link})` 267 | 268 | rows.push(`| ${firstColumn} | ${secondColumn} | ${thirdColumn} |`) 269 | } 270 | }) 271 | 272 | let body = ` 273 | 📝 Ran ecosystem CI on ${refLink}: ${urlLink} 274 | 275 | ` 276 | if (rows.length > 0) { 277 | body += `| suite | result | [latest scheduled](${latestScheduledRun.html_url}) | 278 | |-------|--------|----------------| 279 | ${rows.join("\n")} 280 | 281 | ${conclusionEmoji.success} ${successfulSuitesWithoutChanges.join(", ")} 282 | ` 283 | } else { 284 | body += `${conclusionEmoji.success} ${successfulSuitesWithoutChanges.join(", ")} 285 | ` 286 | } 287 | 288 | await github.rest.issues.createComment({ 289 | issue_number: context.payload.inputs.prNumber, 290 | owner: context.repo.owner, 291 | repo: mainRepoName, 292 | body 293 | }) 294 | 295 | await github.rest.issues.deleteComment({ 296 | owner: context.repo.owner, 297 | repo: mainRepoName, 298 | comment_id: +process.env.COMMENT_ID 299 | }) 300 | env: 301 | REF: ${{ needs.execute-all.outputs.ref || needs.execute-selected-suite.outputs.ref }} 302 | COMMENT_ID: ${{ needs.init.outputs.comment-id }} 303 | -------------------------------------------------------------------------------- /utils.ts: -------------------------------------------------------------------------------- 1 | import path from 'path' 2 | import fs from 'fs' 3 | import { fileURLToPath, pathToFileURL } from 'url' 4 | import { execaCommand } from 'execa' 5 | import type { 6 | EnvironmentData, 7 | Overrides, 8 | ProcessEnv, 9 | RepoOptions, 10 | RunOptions, 11 | Task, 12 | } from './types.d.ts' 13 | import { detect, AGENTS, getCommand, serializeCommand } from '@antfu/ni' 14 | import actionsCore from '@actions/core' 15 | import * as semver from 'semver' 16 | 17 | const isGitHubActions = !!process.env.GITHUB_ACTIONS 18 | 19 | let sveltePath: string 20 | let cwd: string 21 | let env: ProcessEnv 22 | 23 | function cd(dir: string) { 24 | cwd = path.resolve(cwd, dir) 25 | } 26 | 27 | export async function $(literals: TemplateStringsArray, ...values: any[]) { 28 | const cmd = literals.reduce( 29 | (result, current, i) => 30 | result + current + (values?.[i] != null ? `${values[i]}` : ''), 31 | '', 32 | ) 33 | 34 | if (isGitHubActions) { 35 | actionsCore.startGroup(`${cwd} $> ${cmd}`) 36 | } else { 37 | console.log(`${cwd} $> ${cmd}`) 38 | } 39 | 40 | const proc = execaCommand(cmd, { 41 | env, 42 | stdio: 'pipe', 43 | cwd, 44 | }) 45 | if (proc.stdin) process.stdin.pipe(proc.stdin) 46 | if (proc.stdout) proc.stdout.pipe(process.stdout) 47 | if (proc.stderr) proc.stderr.pipe(process.stderr) 48 | 49 | let result 50 | try { 51 | result = await proc 52 | } catch (error) { 53 | // Since we already piped the io to the parent process, we remove the duplicated 54 | // messages here so it's easier to read the error message. 55 | if (error.stdout) error.stdout = 'value removed by svelte-ecosystem-ci' 56 | if (error.stderr) error.stderr = 'value removed by svelte-ecosystem-ci' 57 | if (error.stdio) error.stdio = ['value removed by svelte-ecosystem-ci'] 58 | throw error 59 | } 60 | 61 | if (isGitHubActions) { 62 | actionsCore.endGroup() 63 | } 64 | 65 | return result.stdout 66 | } 67 | 68 | export async function setupEnvironment(): Promise { 69 | const root = dirnameFrom(import.meta.url) 70 | const workspace = path.resolve(root, 'workspace') 71 | sveltePath = path.resolve(workspace, 'svelte') 72 | cwd = process.cwd() 73 | env = { 74 | ...process.env, 75 | CI: 'true', 76 | TURBO_FORCE: 'true', // disable turbo caching, ecosystem-ci modifies things and we don't want replays 77 | YARN_ENABLE_IMMUTABLE_INSTALLS: 'false', // to avoid errors with mutated lockfile due to overrides 78 | NODE_OPTIONS: '--max-old-space-size=6144', // GITHUB CI has 7GB max, stay below 79 | ECOSYSTEM_CI: 'true', // flag for tests, can be used to conditionally skip irrelevant tests. 80 | TURBO_TELEMETRY_DISABLED: '1', // # see https://turbo.build/repo/docs/telemetry#how-do-i-opt-out 81 | DO_NOT_TRACK: '1', 82 | } 83 | initWorkspace(workspace) 84 | return { root, workspace, sveltePath, cwd, env } 85 | } 86 | 87 | function initWorkspace(workspace: string) { 88 | if (!fs.existsSync(workspace)) { 89 | fs.mkdirSync(workspace, { recursive: true }) 90 | } 91 | const eslintrc = path.join(workspace, '.eslintrc.json') 92 | if (!fs.existsSync(eslintrc)) { 93 | fs.writeFileSync(eslintrc, '{"root":true}\n', 'utf-8') 94 | } 95 | const editorconfig = path.join(workspace, '.editorconfig') 96 | if (!fs.existsSync(editorconfig)) { 97 | fs.writeFileSync(editorconfig, 'root = true\n', 'utf-8') 98 | } 99 | const tsconfig = path.join(workspace, 'tsconfig.json') 100 | if (!fs.existsSync(tsconfig)) { 101 | fs.writeFileSync(tsconfig, '{}\n', 'utf-8') 102 | } 103 | } 104 | 105 | export async function setupRepo(options: RepoOptions) { 106 | if (options.branch == null) { 107 | options.branch = 'main' 108 | } 109 | if (options.shallow == null) { 110 | options.shallow = true 111 | } 112 | 113 | let { repo, commit, branch, tag, dir, shallow } = options 114 | if (!dir) { 115 | throw new Error('setupRepo must be called with options.dir') 116 | } 117 | if (!repo.includes(':')) { 118 | repo = `https://github.com/${repo}.git` 119 | } 120 | 121 | let needClone = true 122 | if (fs.existsSync(dir)) { 123 | const _cwd = cwd 124 | cd(dir) 125 | let currentClonedRepo: string | undefined 126 | try { 127 | currentClonedRepo = await $`git ls-remote --get-url` 128 | } catch { 129 | // when not a git repo 130 | } 131 | if (repo === currentClonedRepo) { 132 | const isShallow = 133 | (await $`git rev-parse --is-shallow-repository`).trim() === 'true' 134 | if (isShallow === shallow) { 135 | needClone = false 136 | } 137 | } 138 | cd(_cwd) 139 | 140 | if (needClone) { 141 | fs.rmSync(dir, { recursive: true, force: true }) 142 | } 143 | } 144 | 145 | if (needClone) { 146 | await $`git -c advice.detachedHead=false clone ${ 147 | shallow ? '--depth=1 --no-tags' : '' 148 | } --branch ${tag || branch} ${repo} ${dir}` 149 | } 150 | cd(dir) 151 | await $`git clean -fdxq` 152 | if (!needClone && shallow && !commit) { 153 | await $`git remote set-branches origin ${branch}` 154 | } 155 | await $`git fetch ${shallow ? '--depth=1 --no-tags' : '--tags'} origin ${ 156 | tag ? `tag ${tag}` : `${commit || branch}` 157 | }` 158 | if (shallow) { 159 | await $`git -c advice.detachedHead=false checkout ${ 160 | tag ? `tags/${tag}` : `${commit || branch}` 161 | }` 162 | } else { 163 | await $`git checkout ${branch}` 164 | await $`git merge FETCH_HEAD` 165 | if (tag || commit) { 166 | await $`git reset --hard ${tag || commit}` 167 | } 168 | } 169 | } 170 | 171 | function toCommand( 172 | task: Task | Task[] | void, 173 | agent: (typeof AGENTS)[number], 174 | ): ((scripts: any) => Promise) | void { 175 | return async (scripts: any) => { 176 | const tasks = Array.isArray(task) ? task : [task] 177 | for (const task of tasks) { 178 | if (task == null || task === '') { 179 | continue 180 | } else if (typeof task === 'string') { 181 | if (scripts[task] != null) { 182 | const runTaskWithAgent = getCommand(agent, 'run', [task]) 183 | await $`${serializeCommand(runTaskWithAgent)}` 184 | } else { 185 | await $`${task}` 186 | } 187 | } else if (typeof task === 'function') { 188 | await task() 189 | } else if (task?.script) { 190 | if (scripts[task.script] != null) { 191 | const runTaskWithAgent = getCommand(agent, 'run', [ 192 | task.script, 193 | ...(task.args ?? []), 194 | ]) 195 | await $`${serializeCommand(runTaskWithAgent)}` 196 | } else { 197 | throw new Error( 198 | `invalid task, script "${task.script}" does not exist in package.json`, 199 | ) 200 | } 201 | } else { 202 | throw new Error( 203 | `invalid task, expected string or function but got ${typeof task}: ${task}`, 204 | ) 205 | } 206 | } 207 | } 208 | } 209 | 210 | export async function runInRepo(options: RunOptions & RepoOptions) { 211 | if (options.verify == null) { 212 | options.verify = true 213 | } 214 | if (options.skipGit == null) { 215 | options.skipGit = false 216 | } 217 | if (options.branch == null) { 218 | options.branch = 'main' 219 | } 220 | 221 | const { 222 | build, 223 | test, 224 | repo, 225 | branch, 226 | tag, 227 | commit, 228 | skipGit, 229 | verify, 230 | beforeInstall, 231 | beforeBuild, 232 | beforeTest, 233 | } = options 234 | 235 | const dir = path.resolve( 236 | options.workspace, 237 | options.dir || repo.substring(repo.lastIndexOf('/') + 1), 238 | ) 239 | 240 | if (!skipGit) { 241 | await setupRepo({ repo, dir, branch, tag, commit }) 242 | } else { 243 | cd(dir) 244 | } 245 | if (options.agent == null) { 246 | const detectedAgent = await detect({ cwd: dir, autoInstall: false }) 247 | if (detectedAgent == null) { 248 | throw new Error(`Failed to detect packagemanager in ${dir}`) 249 | } 250 | options.agent = detectedAgent 251 | } 252 | if (!AGENTS.includes(options.agent)) { 253 | throw new Error( 254 | `Invalid agent ${options.agent}. Allowed values: ${AGENTS.join(', ')}`, 255 | ) 256 | } 257 | const agent = options.agent 258 | const beforeInstallCommand = toCommand(beforeInstall, agent) 259 | const beforeBuildCommand = toCommand(beforeBuild, agent) 260 | const beforeTestCommand = toCommand(beforeTest, agent) 261 | const buildCommand = toCommand(build, agent) 262 | const testCommand = toCommand(test, agent) 263 | 264 | const pkgFile = path.join(dir, 'package.json') 265 | const pkg = JSON.parse(await fs.promises.readFile(pkgFile, 'utf-8')) 266 | 267 | await beforeInstallCommand?.(pkg.scripts) 268 | 269 | if (verify && test) { 270 | const frozenInstall = getCommand(agent, 'frozen') 271 | await $`${serializeCommand(frozenInstall)}` 272 | await beforeBuildCommand?.(pkg.scripts) 273 | await buildCommand?.(pkg.scripts) 274 | await beforeTestCommand?.(pkg.scripts) 275 | await testCommand?.(pkg.scripts) 276 | } 277 | let overrides = options.overrides || {} 278 | if (options.release) { 279 | if (overrides.svelte && overrides.svelte !== options.release) { 280 | throw new Error( 281 | `conflicting overrides.svelte=${overrides.svelte} and --release=${options.release} config. Use either one or the other`, 282 | ) 283 | } else { 284 | overrides.svelte = options.release 285 | } 286 | } else { 287 | overrides.svelte ||= `${options.sveltePath}/packages/svelte` 288 | const localOverrides = await buildOverrides(pkg, options, overrides) 289 | cd(dir) // buildOverrides changed dir, change it back 290 | overrides = { 291 | ...overrides, 292 | ...localOverrides, 293 | } 294 | } 295 | await applyPackageOverrides(dir, pkg, overrides) 296 | await beforeBuildCommand?.(pkg.scripts) 297 | await buildCommand?.(pkg.scripts) 298 | if (test) { 299 | await beforeTestCommand?.(pkg.scripts) 300 | await testCommand?.(pkg.scripts) 301 | } 302 | return { dir } 303 | } 304 | 305 | export async function setupSvelteRepo(options: Partial) { 306 | const repo = options.repo || 'sveltejs/svelte' 307 | await setupRepo({ 308 | repo, 309 | dir: sveltePath, 310 | branch: 'main', 311 | shallow: true, 312 | ...options, 313 | }) 314 | 315 | try { 316 | const rootPackageJsonFile = path.join(sveltePath, 'package.json') 317 | const rootPackageJson = JSON.parse( 318 | await fs.promises.readFile(rootPackageJsonFile, 'utf-8'), 319 | ) 320 | const { name } = rootPackageJson 321 | const expected = 'svelte-monorepo' 322 | if (name !== expected) { 323 | throw new Error( 324 | `expected "name" field of ${repo}/package.json to be "${expected}", but got "${name}".`, 325 | ) 326 | } 327 | const needsWrite = await overridePackageManagerVersion( 328 | rootPackageJson, 329 | 'pnpm', 330 | ) 331 | if (needsWrite) { 332 | fs.writeFileSync( 333 | rootPackageJsonFile, 334 | JSON.stringify(rootPackageJson, null, 2), 335 | 'utf-8', 336 | ) 337 | if (rootPackageJson.devDependencies?.pnpm) { 338 | await $`pnpm install -Dw pnpm --lockfile-only` 339 | } 340 | } 341 | } catch (e) { 342 | throw new Error(`Failed to setup svelte repo`, { cause: e }) 343 | } 344 | } 345 | 346 | export async function getPermanentRef() { 347 | cd(sveltePath) 348 | try { 349 | const ref = await $`git log -1 --pretty=format:%H` 350 | return ref 351 | } catch (e) { 352 | console.warn(`Failed to obtain perm ref. ${e}`) 353 | return undefined 354 | } 355 | } 356 | 357 | export async function buildSvelte({ verify = false }) { 358 | cd(`${sveltePath}/packages/svelte`) 359 | const frozenInstall = getCommand('pnpm', 'frozen') 360 | const runBuild = getCommand('pnpm', 'run', ['build']) 361 | const runTest = getCommand('pnpm', 'run', ['test']) 362 | await $`${serializeCommand(frozenInstall)}` 363 | const oldPublish = process.env.PUBLISH 364 | process.env.PUBLISH = '1' 365 | await $`${serializeCommand(runBuild)}` // set publish so build bundles deps 366 | process.env.PUBLISH = oldPublish 367 | if (verify) { 368 | await $`${serializeCommand(runTest)}` 369 | } 370 | } 371 | 372 | export async function bisectSvelte( 373 | good: string, 374 | runSuite: () => Promise, 375 | ) { 376 | // sometimes build modifies files in git, e.g. LICENSE.md 377 | // this would stop bisect, so to reset those changes 378 | const resetChanges = async () => $`git reset --hard HEAD` 379 | 380 | try { 381 | cd(sveltePath) 382 | await resetChanges() 383 | await $`git bisect start` 384 | await $`git bisect bad` 385 | await $`git bisect good ${good}` 386 | let bisecting = true 387 | while (bisecting) { 388 | const commitMsg = await $`git log -1 --format=%s` 389 | const isNonCodeCommit = commitMsg.match(/^(?:release|docs)[:(]/) 390 | if (isNonCodeCommit) { 391 | await $`git bisect skip` 392 | continue // see if next commit can be skipped too 393 | } 394 | const error = await runSuite() 395 | cd(sveltePath) 396 | await resetChanges() 397 | const bisectOut = await $`git bisect ${error ? 'bad' : 'good'}` 398 | bisecting = bisectOut.substring(0, 10).toLowerCase() === 'bisecting:' // as long as git prints 'bisecting: ' there are more revisions to test 399 | } 400 | } catch (e) { 401 | console.log('error while bisecting', e) 402 | } finally { 403 | try { 404 | cd(sveltePath) 405 | await $`git bisect reset` 406 | } catch (e) { 407 | console.log('Error while resetting bisect', e) 408 | } 409 | } 410 | } 411 | 412 | function isLocalOverride(v: string): boolean { 413 | if (!v.includes('/') || v.startsWith('@')) { 414 | // not path-like (either a version number or a package name) 415 | return false 416 | } 417 | try { 418 | return !!fs.lstatSync(v)?.isDirectory() 419 | } catch (e) { 420 | if (e.code !== 'ENOENT') { 421 | throw e 422 | } 423 | return false 424 | } 425 | } 426 | 427 | /** 428 | * utility to override packageManager version 429 | * 430 | * @param pkg parsed package.json 431 | * @param pm package manager to override eg. `pnpm` 432 | * @returns {boolean} true if pkg was updated, caller is responsible for writing it to disk 433 | */ 434 | async function overridePackageManagerVersion( 435 | pkg: { [key: string]: any }, 436 | pm: string, 437 | ): Promise { 438 | const versionInUse = pkg.packageManager?.startsWith(`${pm}@`) 439 | ? pkg.packageManager.substring(pm.length + 1) 440 | : await $`${pm} --version` 441 | let overrideWithVersion: string | null = null 442 | if (pm === 'pnpm') { 443 | if (semver.eq(versionInUse, '7.18.0')) { 444 | // avoid bug with absolute overrides in pnpm 7.18.0 445 | overrideWithVersion = '7.18.1' 446 | } 447 | } 448 | if (overrideWithVersion) { 449 | console.warn( 450 | `detected ${pm}@${versionInUse} used in ${pkg.name}, changing pkg.packageManager and pkg.engines.${pm} to enforce use of ${pm}@${overrideWithVersion}`, 451 | ) 452 | // corepack reads this and uses pnpm @ newVersion then 453 | pkg.packageManager = `${pm}@${overrideWithVersion}` 454 | if (!pkg.engines) { 455 | pkg.engines = {} 456 | } 457 | pkg.engines[pm] = overrideWithVersion 458 | 459 | if (pkg.devDependencies?.[pm]) { 460 | // if for some reason the pm is in devDependencies, that would be a local version that'd be preferred over our forced global 461 | // so ensure it here too. 462 | pkg.devDependencies[pm] = overrideWithVersion 463 | } 464 | 465 | return true 466 | } 467 | return false 468 | } 469 | 470 | export async function applyPackageOverrides( 471 | dir: string, 472 | pkg: any, 473 | overrides: Overrides = {}, 474 | ) { 475 | const useFileProtocol = (v: string) => 476 | isLocalOverride(v) ? `file:${path.resolve(v)}` : v 477 | // remove boolean flags 478 | overrides = Object.fromEntries( 479 | Object.entries(overrides) 480 | //eslint-disable-next-line @typescript-eslint/no-unused-vars 481 | .filter(([key, value]) => typeof value === 'string') 482 | .map(([key, value]) => [key, useFileProtocol(value as string)]), 483 | ) 484 | await $`git clean -fdxq` // remove current install 485 | 486 | const agent = await detect({ cwd: dir, autoInstall: false }) 487 | if (!agent) { 488 | throw new Error(`failed to detect packageManager in ${dir}`) 489 | } 490 | // Remove version from agent string: 491 | // yarn@berry => yarn 492 | // pnpm@6, pnpm@7 => pnpm 493 | const pm = agent?.split('@')[0] 494 | 495 | await overridePackageManagerVersion(pkg, pm) 496 | 497 | if (pm === 'pnpm') { 498 | const overridesWithoutSpecialSyntax = Object.fromEntries( 499 | Object.entries(overrides) 500 | //eslint-disable-next-line @typescript-eslint/no-unused-vars 501 | .filter(([key, value]) => !key.includes('>')), 502 | ) 503 | 504 | if (!pkg.devDependencies) { 505 | pkg.devDependencies = {} 506 | } 507 | pkg.devDependencies = { 508 | ...pkg.devDependencies, 509 | ...overridesWithoutSpecialSyntax, // overrides must be present in devDependencies or dependencies otherwise they may not work 510 | } 511 | if (!pkg.pnpm) { 512 | pkg.pnpm = {} 513 | } 514 | pkg.pnpm.overrides = { 515 | ...pkg.pnpm.overrides, 516 | ...overrides, 517 | } 518 | } else if (pm === 'yarn') { 519 | pkg.resolutions = { 520 | ...pkg.resolutions, 521 | ...overrides, 522 | } 523 | } else if (pm === 'npm') { 524 | pkg.overrides = { 525 | ...pkg.overrides, 526 | ...overrides, 527 | } 528 | // npm does not allow overriding direct dependencies, force it by updating the blocks themselves 529 | for (const [name, version] of Object.entries(overrides)) { 530 | if (pkg.dependencies?.[name]) { 531 | pkg.dependencies[name] = version 532 | } 533 | if (pkg.devDependencies?.[name]) { 534 | pkg.devDependencies[name] = version 535 | } 536 | } 537 | } else { 538 | throw new Error(`unsupported package manager detected: ${pm}`) 539 | } 540 | const pkgFile = path.join(dir, 'package.json') 541 | await fs.promises.writeFile(pkgFile, JSON.stringify(pkg, null, 2), 'utf-8') 542 | 543 | // use of `ni` command here could cause lockfile violation errors so fall back to native commands that avoid these 544 | if (pm === 'pnpm') { 545 | const workspaceFile = path.join(dir, 'pnpm-workspace.yaml') 546 | if (fs.existsSync(workspaceFile)) { 547 | const content = fs.readFileSync(workspaceFile, 'utf-8') 548 | if (content.includes('minimumReleaseAge')) { 549 | fs.writeFileSync( 550 | workspaceFile, 551 | content.replace( 552 | /^([ \t]*minimumReleaseAge[ \t]*:[ \t]*\d+[^\r\n]*)$/m, 553 | '# $1 -- disabled by ecosystem-ci', 554 | ), 555 | 'utf-8', 556 | ) 557 | } 558 | } 559 | await $`pnpm install --prefer-frozen-lockfile --strict-peer-dependencies false` 560 | } else if (pm === 'yarn') { 561 | await $`yarn install` 562 | } else if (pm === 'npm') { 563 | await $`npm install` 564 | } 565 | } 566 | 567 | export function dirnameFrom(url: string) { 568 | return path.dirname(fileURLToPath(url)) 569 | } 570 | 571 | export function parseSvelteMajor(sveltePath: string): number { 572 | const content = fs.readFileSync( 573 | path.join(sveltePath, 'package.json'), 574 | 'utf-8', 575 | ) 576 | const pkg = JSON.parse(content) 577 | return parseMajorVersion(pkg.version) 578 | } 579 | 580 | export function parseMajorVersion(version: string) { 581 | return parseInt(version.split('.', 1)[0], 10) 582 | } 583 | 584 | async function buildOverrides( 585 | pkg: any, 586 | options: RunOptions, 587 | repoOverrides: Overrides, 588 | ) { 589 | const { root } = options 590 | const buildsPath = path.join(root, 'builds') 591 | const buildFiles: string[] = fs 592 | .readdirSync(buildsPath) 593 | .filter((f: string) => !f.startsWith('_') && f.endsWith('.ts')) 594 | .map((f) => path.join(buildsPath, f)) 595 | const buildDefinitions: { 596 | packages: { [key: string]: string } 597 | build: (options: RunOptions) => Promise<{ dir: string }> 598 | dir?: string 599 | }[] = await Promise.all(buildFiles.map((f) => import(pathToFileURL(f).href))) 600 | const deps = new Set([ 601 | ...Object.keys(pkg.dependencies ?? {}), 602 | ...Object.keys(pkg.devDependencies ?? {}), 603 | ...Object.keys(pkg.peerDependencies ?? {}), 604 | ]) 605 | 606 | const needsOverride = (p: string) => 607 | repoOverrides[p] === true || (deps.has(p) && repoOverrides[p] == null) 608 | const buildsToRun = buildDefinitions.filter(({ packages }) => 609 | Object.keys(packages).some(needsOverride), 610 | ) 611 | const overrides: Overrides = {} 612 | for (const buildDef of buildsToRun) { 613 | const { dir } = await buildDef.build({ 614 | root: options.root, 615 | workspace: options.workspace, 616 | sveltePath: options.sveltePath, 617 | svelteMajor: options.svelteMajor, 618 | skipGit: options.skipGit, 619 | release: options.release, 620 | verify: options.verify, 621 | // do not pass along scripts 622 | }) 623 | for (const [name, path] of Object.entries(buildDef.packages)) { 624 | if (needsOverride(name)) { 625 | overrides[name] = `${dir}/${path}` 626 | } 627 | } 628 | } 629 | return overrides 630 | } 631 | -------------------------------------------------------------------------------- /pnpm-lock.yaml: -------------------------------------------------------------------------------- 1 | lockfileVersion: '9.0' 2 | 3 | settings: 4 | autoInstallPeers: true 5 | excludeLinksFromLockfile: false 6 | 7 | overrides: 8 | cross-spawn@>=7.0.0 <7.0.5: ^7.0.6 9 | 10 | importers: 11 | 12 | .: 13 | dependencies: 14 | '@actions/core': 15 | specifier: ^1.11.1 16 | version: 1.11.1 17 | cac: 18 | specifier: ^6.7.14 19 | version: 6.7.14 20 | execa: 21 | specifier: ^9.5.2 22 | version: 9.5.2 23 | node-fetch: 24 | specifier: ^3.3.2 25 | version: 3.3.2 26 | devDependencies: 27 | '@antfu/ni': 28 | specifier: ^24.3.0 29 | version: 24.3.0 30 | '@eslint/js': 31 | specifier: ^9.25.1 32 | version: 9.25.1 33 | '@types/node': 34 | specifier: ^22.14.1 35 | version: 22.14.1 36 | '@types/semver': 37 | specifier: ^7.7.0 38 | version: 7.7.0 39 | eslint: 40 | specifier: ^9.25.1 41 | version: 9.30.1 42 | eslint-plugin-n: 43 | specifier: ^17.17.0 44 | version: 17.21.0(eslint@9.30.1)(typescript@5.8.3) 45 | lint-staged: 46 | specifier: ^15.5.1 47 | version: 15.5.1 48 | prettier: 49 | specifier: ^3.5.3 50 | version: 3.5.3 51 | semver: 52 | specifier: ^7.7.1 53 | version: 7.7.1 54 | simple-git-hooks: 55 | specifier: ^2.12.1 56 | version: 2.12.1 57 | tsx: 58 | specifier: ^4.19.3 59 | version: 4.19.3 60 | typescript: 61 | specifier: ^5.8.3 62 | version: 5.8.3 63 | typescript-eslint: 64 | specifier: ^8.31.0 65 | version: 8.35.1(eslint@9.30.1)(typescript@5.8.3) 66 | 67 | packages: 68 | 69 | '@actions/core@1.11.1': 70 | resolution: {integrity: sha512-hXJCSrkwfA46Vd9Z3q4cpEpHB1rL5NG04+/rbqW9d3+CSvtB1tYe8UTpAlixa1vj0m/ULglfEK2UKxMGxCxv5A==} 71 | 72 | '@actions/exec@1.1.1': 73 | resolution: {integrity: sha512-+sCcHHbVdk93a0XT19ECtO/gIXoxvdsgQLzb2fE2/5sIZmWQuluYyjPQtrtTHdU1YzTZ7bAPN4sITq2xi1679w==} 74 | 75 | '@actions/http-client@2.2.3': 76 | resolution: {integrity: sha512-mx8hyJi/hjFvbPokCg4uRd4ZX78t+YyRPtnKWwIl+RzNaVuFpQHfmlGVfsKEJN8LwTCvL+DfVgAM04XaHkm6bA==} 77 | 78 | '@actions/io@1.1.3': 79 | resolution: {integrity: sha512-wi9JjgKLYS7U/z8PPbco+PvTb/nRWjeoFlJ1Qer83k/3C5PHQi28hiVdeE2kHXmIL99mQFawx8qt/JPjZilJ8Q==} 80 | 81 | '@antfu/ni@24.3.0': 82 | resolution: {integrity: sha512-wBSav4mBxvHEW9RbdSo1SWLQ6MAlT0Dc423weC58yOWqW4OcMvtnNDdDrxOZeJ88fEIyPK93gDUWIelBxzSf8g==} 83 | hasBin: true 84 | 85 | '@esbuild/aix-ppc64@0.25.3': 86 | resolution: {integrity: sha512-W8bFfPA8DowP8l//sxjJLSLkD8iEjMc7cBVyP+u4cEv9sM7mdUCkgsj+t0n/BWPFtv7WWCN5Yzj0N6FJNUUqBQ==} 87 | engines: {node: '>=18'} 88 | cpu: [ppc64] 89 | os: [aix] 90 | 91 | '@esbuild/android-arm64@0.25.3': 92 | resolution: {integrity: sha512-XelR6MzjlZuBM4f5z2IQHK6LkK34Cvv6Rj2EntER3lwCBFdg6h2lKbtRjpTTsdEjD/WSe1q8UyPBXP1x3i/wYQ==} 93 | engines: {node: '>=18'} 94 | cpu: [arm64] 95 | os: [android] 96 | 97 | '@esbuild/android-arm@0.25.3': 98 | resolution: {integrity: sha512-PuwVXbnP87Tcff5I9ngV0lmiSu40xw1At6i3GsU77U7cjDDB4s0X2cyFuBiDa1SBk9DnvWwnGvVaGBqoFWPb7A==} 99 | engines: {node: '>=18'} 100 | cpu: [arm] 101 | os: [android] 102 | 103 | '@esbuild/android-x64@0.25.3': 104 | resolution: {integrity: sha512-ogtTpYHT/g1GWS/zKM0cc/tIebFjm1F9Aw1boQ2Y0eUQ+J89d0jFY//s9ei9jVIlkYi8AfOjiixcLJSGNSOAdQ==} 105 | engines: {node: '>=18'} 106 | cpu: [x64] 107 | os: [android] 108 | 109 | '@esbuild/darwin-arm64@0.25.3': 110 | resolution: {integrity: sha512-eESK5yfPNTqpAmDfFWNsOhmIOaQA59tAcF/EfYvo5/QWQCzXn5iUSOnqt3ra3UdzBv073ykTtmeLJZGt3HhA+w==} 111 | engines: {node: '>=18'} 112 | cpu: [arm64] 113 | os: [darwin] 114 | 115 | '@esbuild/darwin-x64@0.25.3': 116 | resolution: {integrity: sha512-Kd8glo7sIZtwOLcPbW0yLpKmBNWMANZhrC1r6K++uDR2zyzb6AeOYtI6udbtabmQpFaxJ8uduXMAo1gs5ozz8A==} 117 | engines: {node: '>=18'} 118 | cpu: [x64] 119 | os: [darwin] 120 | 121 | '@esbuild/freebsd-arm64@0.25.3': 122 | resolution: {integrity: sha512-EJiyS70BYybOBpJth3M0KLOus0n+RRMKTYzhYhFeMwp7e/RaajXvP+BWlmEXNk6uk+KAu46j/kaQzr6au+JcIw==} 123 | engines: {node: '>=18'} 124 | cpu: [arm64] 125 | os: [freebsd] 126 | 127 | '@esbuild/freebsd-x64@0.25.3': 128 | resolution: {integrity: sha512-Q+wSjaLpGxYf7zC0kL0nDlhsfuFkoN+EXrx2KSB33RhinWzejOd6AvgmP5JbkgXKmjhmpfgKZq24pneodYqE8Q==} 129 | engines: {node: '>=18'} 130 | cpu: [x64] 131 | os: [freebsd] 132 | 133 | '@esbuild/linux-arm64@0.25.3': 134 | resolution: {integrity: sha512-xCUgnNYhRD5bb1C1nqrDV1PfkwgbswTTBRbAd8aH5PhYzikdf/ddtsYyMXFfGSsb/6t6QaPSzxtbfAZr9uox4A==} 135 | engines: {node: '>=18'} 136 | cpu: [arm64] 137 | os: [linux] 138 | 139 | '@esbuild/linux-arm@0.25.3': 140 | resolution: {integrity: sha512-dUOVmAUzuHy2ZOKIHIKHCm58HKzFqd+puLaS424h6I85GlSDRZIA5ycBixb3mFgM0Jdh+ZOSB6KptX30DD8YOQ==} 141 | engines: {node: '>=18'} 142 | cpu: [arm] 143 | os: [linux] 144 | 145 | '@esbuild/linux-ia32@0.25.3': 146 | resolution: {integrity: sha512-yplPOpczHOO4jTYKmuYuANI3WhvIPSVANGcNUeMlxH4twz/TeXuzEP41tGKNGWJjuMhotpGabeFYGAOU2ummBw==} 147 | engines: {node: '>=18'} 148 | cpu: [ia32] 149 | os: [linux] 150 | 151 | '@esbuild/linux-loong64@0.25.3': 152 | resolution: {integrity: sha512-P4BLP5/fjyihmXCELRGrLd793q/lBtKMQl8ARGpDxgzgIKJDRJ/u4r1A/HgpBpKpKZelGct2PGI4T+axcedf6g==} 153 | engines: {node: '>=18'} 154 | cpu: [loong64] 155 | os: [linux] 156 | 157 | '@esbuild/linux-mips64el@0.25.3': 158 | resolution: {integrity: sha512-eRAOV2ODpu6P5divMEMa26RRqb2yUoYsuQQOuFUexUoQndm4MdpXXDBbUoKIc0iPa4aCO7gIhtnYomkn2x+bag==} 159 | engines: {node: '>=18'} 160 | cpu: [mips64el] 161 | os: [linux] 162 | 163 | '@esbuild/linux-ppc64@0.25.3': 164 | resolution: {integrity: sha512-ZC4jV2p7VbzTlnl8nZKLcBkfzIf4Yad1SJM4ZMKYnJqZFD4rTI+pBG65u8ev4jk3/MPwY9DvGn50wi3uhdaghg==} 165 | engines: {node: '>=18'} 166 | cpu: [ppc64] 167 | os: [linux] 168 | 169 | '@esbuild/linux-riscv64@0.25.3': 170 | resolution: {integrity: sha512-LDDODcFzNtECTrUUbVCs6j9/bDVqy7DDRsuIXJg6so+mFksgwG7ZVnTruYi5V+z3eE5y+BJZw7VvUadkbfg7QA==} 171 | engines: {node: '>=18'} 172 | cpu: [riscv64] 173 | os: [linux] 174 | 175 | '@esbuild/linux-s390x@0.25.3': 176 | resolution: {integrity: sha512-s+w/NOY2k0yC2p9SLen+ymflgcpRkvwwa02fqmAwhBRI3SC12uiS10edHHXlVWwfAagYSY5UpmT/zISXPMW3tQ==} 177 | engines: {node: '>=18'} 178 | cpu: [s390x] 179 | os: [linux] 180 | 181 | '@esbuild/linux-x64@0.25.3': 182 | resolution: {integrity: sha512-nQHDz4pXjSDC6UfOE1Fw9Q8d6GCAd9KdvMZpfVGWSJztYCarRgSDfOVBY5xwhQXseiyxapkiSJi/5/ja8mRFFA==} 183 | engines: {node: '>=18'} 184 | cpu: [x64] 185 | os: [linux] 186 | 187 | '@esbuild/netbsd-arm64@0.25.3': 188 | resolution: {integrity: sha512-1QaLtOWq0mzK6tzzp0jRN3eccmN3hezey7mhLnzC6oNlJoUJz4nym5ZD7mDnS/LZQgkrhEbEiTn515lPeLpgWA==} 189 | engines: {node: '>=18'} 190 | cpu: [arm64] 191 | os: [netbsd] 192 | 193 | '@esbuild/netbsd-x64@0.25.3': 194 | resolution: {integrity: sha512-i5Hm68HXHdgv8wkrt+10Bc50zM0/eonPb/a/OFVfB6Qvpiirco5gBA5bz7S2SHuU+Y4LWn/zehzNX14Sp4r27g==} 195 | engines: {node: '>=18'} 196 | cpu: [x64] 197 | os: [netbsd] 198 | 199 | '@esbuild/openbsd-arm64@0.25.3': 200 | resolution: {integrity: sha512-zGAVApJEYTbOC6H/3QBr2mq3upG/LBEXr85/pTtKiv2IXcgKV0RT0QA/hSXZqSvLEpXeIxah7LczB4lkiYhTAQ==} 201 | engines: {node: '>=18'} 202 | cpu: [arm64] 203 | os: [openbsd] 204 | 205 | '@esbuild/openbsd-x64@0.25.3': 206 | resolution: {integrity: sha512-fpqctI45NnCIDKBH5AXQBsD0NDPbEFczK98hk/aa6HJxbl+UtLkJV2+Bvy5hLSLk3LHmqt0NTkKNso1A9y1a4w==} 207 | engines: {node: '>=18'} 208 | cpu: [x64] 209 | os: [openbsd] 210 | 211 | '@esbuild/sunos-x64@0.25.3': 212 | resolution: {integrity: sha512-ROJhm7d8bk9dMCUZjkS8fgzsPAZEjtRJqCAmVgB0gMrvG7hfmPmz9k1rwO4jSiblFjYmNvbECL9uhaPzONMfgA==} 213 | engines: {node: '>=18'} 214 | cpu: [x64] 215 | os: [sunos] 216 | 217 | '@esbuild/win32-arm64@0.25.3': 218 | resolution: {integrity: sha512-YWcow8peiHpNBiIXHwaswPnAXLsLVygFwCB3A7Bh5jRkIBFWHGmNQ48AlX4xDvQNoMZlPYzjVOQDYEzWCqufMQ==} 219 | engines: {node: '>=18'} 220 | cpu: [arm64] 221 | os: [win32] 222 | 223 | '@esbuild/win32-ia32@0.25.3': 224 | resolution: {integrity: sha512-qspTZOIGoXVS4DpNqUYUs9UxVb04khS1Degaw/MnfMe7goQ3lTfQ13Vw4qY/Nj0979BGvMRpAYbs/BAxEvU8ew==} 225 | engines: {node: '>=18'} 226 | cpu: [ia32] 227 | os: [win32] 228 | 229 | '@esbuild/win32-x64@0.25.3': 230 | resolution: {integrity: sha512-ICgUR+kPimx0vvRzf+N/7L7tVSQeE3BYY+NhHRHXS1kBuPO7z2+7ea2HbhDyZdTephgvNvKrlDDKUexuCVBVvg==} 231 | engines: {node: '>=18'} 232 | cpu: [x64] 233 | os: [win32] 234 | 235 | '@eslint-community/eslint-utils@4.7.0': 236 | resolution: {integrity: sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==} 237 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 238 | peerDependencies: 239 | eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 240 | 241 | '@eslint-community/regexpp@4.12.1': 242 | resolution: {integrity: sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==} 243 | engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} 244 | 245 | '@eslint/config-array@0.21.0': 246 | resolution: {integrity: sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ==} 247 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 248 | 249 | '@eslint/config-helpers@0.3.0': 250 | resolution: {integrity: sha512-ViuymvFmcJi04qdZeDc2whTHryouGcDlaxPqarTD0ZE10ISpxGUVZGZDx4w01upyIynL3iu6IXH2bS1NhclQMw==} 251 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 252 | 253 | '@eslint/core@0.14.0': 254 | resolution: {integrity: sha512-qIbV0/JZr7iSDjqAc60IqbLdsj9GDt16xQtWD+B78d/HAlvysGdZZ6rpJHGAc2T0FQx1X6thsSPdnoiGKdNtdg==} 255 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 256 | 257 | '@eslint/core@0.15.1': 258 | resolution: {integrity: sha512-bkOp+iumZCCbt1K1CmWf0R9pM5yKpDv+ZXtvSyQpudrI9kuFLp+bM2WOPXImuD/ceQuaa8f5pj93Y7zyECIGNA==} 259 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 260 | 261 | '@eslint/eslintrc@3.3.1': 262 | resolution: {integrity: sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==} 263 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 264 | 265 | '@eslint/js@9.25.1': 266 | resolution: {integrity: sha512-dEIwmjntEx8u3Uvv+kr3PDeeArL8Hw07H9kyYxCjnM9pBjfEhk6uLXSchxxzgiwtRhhzVzqmUSDFBOi1TuZ7qg==} 267 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 268 | 269 | '@eslint/js@9.30.1': 270 | resolution: {integrity: sha512-zXhuECFlyep42KZUhWjfvsmXGX39W8K8LFb8AWXM9gSV9dQB+MrJGLKvW6Zw0Ggnbpw0VHTtrhFXYe3Gym18jg==} 271 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 272 | 273 | '@eslint/object-schema@2.1.6': 274 | resolution: {integrity: sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==} 275 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 276 | 277 | '@eslint/plugin-kit@0.3.3': 278 | resolution: {integrity: sha512-1+WqvgNMhmlAambTvT3KPtCl/Ibr68VldY2XY40SL1CE0ZXiakFR/cbTspaF5HsnpDMvcYYoJHfl4980NBjGag==} 279 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 280 | 281 | '@fastify/busboy@2.1.1': 282 | resolution: {integrity: sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==} 283 | engines: {node: '>=14'} 284 | 285 | '@humanfs/core@0.19.1': 286 | resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} 287 | engines: {node: '>=18.18.0'} 288 | 289 | '@humanfs/node@0.16.6': 290 | resolution: {integrity: sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==} 291 | engines: {node: '>=18.18.0'} 292 | 293 | '@humanwhocodes/module-importer@1.0.1': 294 | resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} 295 | engines: {node: '>=12.22'} 296 | 297 | '@humanwhocodes/retry@0.3.1': 298 | resolution: {integrity: sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==} 299 | engines: {node: '>=18.18'} 300 | 301 | '@humanwhocodes/retry@0.4.3': 302 | resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==} 303 | engines: {node: '>=18.18'} 304 | 305 | '@nodelib/fs.scandir@2.1.5': 306 | resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} 307 | engines: {node: '>= 8'} 308 | 309 | '@nodelib/fs.stat@2.0.5': 310 | resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} 311 | engines: {node: '>= 8'} 312 | 313 | '@nodelib/fs.walk@1.2.8': 314 | resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} 315 | engines: {node: '>= 8'} 316 | 317 | '@sec-ant/readable-stream@0.4.1': 318 | resolution: {integrity: sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==} 319 | 320 | '@sindresorhus/merge-streams@4.0.0': 321 | resolution: {integrity: sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==} 322 | engines: {node: '>=18'} 323 | 324 | '@types/estree@1.0.8': 325 | resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} 326 | 327 | '@types/json-schema@7.0.15': 328 | resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} 329 | 330 | '@types/node@22.14.1': 331 | resolution: {integrity: sha512-u0HuPQwe/dHrItgHHpmw3N2fYCR6x4ivMNbPHRkBVP4CvN+kiRrKHWk3i8tXiO/joPwXLMYvF9TTF0eqgHIuOw==} 332 | 333 | '@types/semver@7.7.0': 334 | resolution: {integrity: sha512-k107IF4+Xr7UHjwDc7Cfd6PRQfbdkiRabXGRjo07b4WyPahFBZCZ1sE+BNxYIJPPg73UkfOsVOLwqVc/6ETrIA==} 335 | 336 | '@typescript-eslint/eslint-plugin@8.35.1': 337 | resolution: {integrity: sha512-9XNTlo7P7RJxbVeICaIIIEipqxLKguyh+3UbXuT2XQuFp6d8VOeDEGuz5IiX0dgZo8CiI6aOFLg4e8cF71SFVg==} 338 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 339 | peerDependencies: 340 | '@typescript-eslint/parser': ^8.35.1 341 | eslint: ^8.57.0 || ^9.0.0 342 | typescript: '>=4.8.4 <5.9.0' 343 | 344 | '@typescript-eslint/parser@8.35.1': 345 | resolution: {integrity: sha512-3MyiDfrfLeK06bi/g9DqJxP5pV74LNv4rFTyvGDmT3x2p1yp1lOd+qYZfiRPIOf/oON+WRZR5wxxuF85qOar+w==} 346 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 347 | peerDependencies: 348 | eslint: ^8.57.0 || ^9.0.0 349 | typescript: '>=4.8.4 <5.9.0' 350 | 351 | '@typescript-eslint/project-service@8.35.1': 352 | resolution: {integrity: sha512-VYxn/5LOpVxADAuP3NrnxxHYfzVtQzLKeldIhDhzC8UHaiQvYlXvKuVho1qLduFbJjjy5U5bkGwa3rUGUb1Q6Q==} 353 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 354 | peerDependencies: 355 | typescript: '>=4.8.4 <5.9.0' 356 | 357 | '@typescript-eslint/scope-manager@8.35.1': 358 | resolution: {integrity: sha512-s/Bpd4i7ht2934nG+UoSPlYXd08KYz3bmjLEb7Ye1UVob0d1ENiT3lY8bsCmik4RqfSbPw9xJJHbugpPpP5JUg==} 359 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 360 | 361 | '@typescript-eslint/tsconfig-utils@8.35.1': 362 | resolution: {integrity: sha512-K5/U9VmT9dTHoNowWZpz+/TObS3xqC5h0xAIjXPw+MNcKV9qg6eSatEnmeAwkjHijhACH0/N7bkhKvbt1+DXWQ==} 363 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 364 | peerDependencies: 365 | typescript: '>=4.8.4 <5.9.0' 366 | 367 | '@typescript-eslint/type-utils@8.35.1': 368 | resolution: {integrity: sha512-HOrUBlfVRz5W2LIKpXzZoy6VTZzMu2n8q9C2V/cFngIC5U1nStJgv0tMV4sZPzdf4wQm9/ToWUFPMN9Vq9VJQQ==} 369 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 370 | peerDependencies: 371 | eslint: ^8.57.0 || ^9.0.0 372 | typescript: '>=4.8.4 <5.9.0' 373 | 374 | '@typescript-eslint/types@8.35.1': 375 | resolution: {integrity: sha512-q/O04vVnKHfrrhNAscndAn1tuQhIkwqnaW+eu5waD5IPts2eX1dgJxgqcPx5BX109/qAz7IG6VrEPTOYKCNfRQ==} 376 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 377 | 378 | '@typescript-eslint/typescript-estree@8.35.1': 379 | resolution: {integrity: sha512-Vvpuvj4tBxIka7cPs6Y1uvM7gJgdF5Uu9F+mBJBPY4MhvjrjWGK4H0lVgLJd/8PWZ23FTqsaJaLEkBCFUk8Y9g==} 380 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 381 | peerDependencies: 382 | typescript: '>=4.8.4 <5.9.0' 383 | 384 | '@typescript-eslint/utils@8.35.1': 385 | resolution: {integrity: sha512-lhnwatFmOFcazAsUm3ZnZFpXSxiwoa1Lj50HphnDe1Et01NF4+hrdXONSUHIcbVu2eFb1bAf+5yjXkGVkXBKAQ==} 386 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 387 | peerDependencies: 388 | eslint: ^8.57.0 || ^9.0.0 389 | typescript: '>=4.8.4 <5.9.0' 390 | 391 | '@typescript-eslint/visitor-keys@8.35.1': 392 | resolution: {integrity: sha512-VRwixir4zBWCSTP/ljEo091lbpypz57PoeAQ9imjG+vbeof9LplljsL1mos4ccG6H9IjfrVGM359RozUnuFhpw==} 393 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 394 | 395 | acorn-jsx@5.3.2: 396 | resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} 397 | peerDependencies: 398 | acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 399 | 400 | acorn@8.15.0: 401 | resolution: {integrity: sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==} 402 | engines: {node: '>=0.4.0'} 403 | hasBin: true 404 | 405 | ajv@6.12.6: 406 | resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} 407 | 408 | ansi-escapes@7.0.0: 409 | resolution: {integrity: sha512-GdYO7a61mR0fOlAsvC9/rIHf7L96sBc6dEWzeOu+KAea5bZyQRPIpojrVoI4AXGJS/ycu/fBTdLrUkA4ODrvjw==} 410 | engines: {node: '>=18'} 411 | 412 | ansi-regex@6.1.0: 413 | resolution: {integrity: sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==} 414 | engines: {node: '>=12'} 415 | 416 | ansi-styles@4.3.0: 417 | resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} 418 | engines: {node: '>=8'} 419 | 420 | ansi-styles@6.2.1: 421 | resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} 422 | engines: {node: '>=12'} 423 | 424 | ansis@3.17.0: 425 | resolution: {integrity: sha512-0qWUglt9JEqLFr3w1I1pbrChn1grhaiAR2ocX1PP/flRmxgtwTzPFFFnfIlD6aMOLQZgSuCRlidD70lvx8yhzg==} 426 | engines: {node: '>=14'} 427 | 428 | argparse@2.0.1: 429 | resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} 430 | 431 | balanced-match@1.0.2: 432 | resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} 433 | 434 | brace-expansion@1.1.12: 435 | resolution: {integrity: sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==} 436 | 437 | brace-expansion@2.0.2: 438 | resolution: {integrity: sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==} 439 | 440 | braces@3.0.3: 441 | resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} 442 | engines: {node: '>=8'} 443 | 444 | cac@6.7.14: 445 | resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} 446 | engines: {node: '>=8'} 447 | 448 | callsites@3.1.0: 449 | resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} 450 | engines: {node: '>=6'} 451 | 452 | chalk@4.1.2: 453 | resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} 454 | engines: {node: '>=10'} 455 | 456 | chalk@5.4.1: 457 | resolution: {integrity: sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==} 458 | engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} 459 | 460 | cli-cursor@5.0.0: 461 | resolution: {integrity: sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==} 462 | engines: {node: '>=18'} 463 | 464 | cli-truncate@4.0.0: 465 | resolution: {integrity: sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==} 466 | engines: {node: '>=18'} 467 | 468 | color-convert@2.0.1: 469 | resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} 470 | engines: {node: '>=7.0.0'} 471 | 472 | color-name@1.1.4: 473 | resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} 474 | 475 | colorette@2.0.20: 476 | resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} 477 | 478 | commander@13.1.0: 479 | resolution: {integrity: sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw==} 480 | engines: {node: '>=18'} 481 | 482 | concat-map@0.0.1: 483 | resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} 484 | 485 | cross-spawn@7.0.6: 486 | resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} 487 | engines: {node: '>= 8'} 488 | 489 | data-uri-to-buffer@4.0.1: 490 | resolution: {integrity: sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==} 491 | engines: {node: '>= 12'} 492 | 493 | debug@4.4.0: 494 | resolution: {integrity: sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==} 495 | engines: {node: '>=6.0'} 496 | peerDependencies: 497 | supports-color: '*' 498 | peerDependenciesMeta: 499 | supports-color: 500 | optional: true 501 | 502 | debug@4.4.1: 503 | resolution: {integrity: sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==} 504 | engines: {node: '>=6.0'} 505 | peerDependencies: 506 | supports-color: '*' 507 | peerDependenciesMeta: 508 | supports-color: 509 | optional: true 510 | 511 | deep-is@0.1.4: 512 | resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} 513 | 514 | emoji-regex@10.4.0: 515 | resolution: {integrity: sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==} 516 | 517 | enhanced-resolve@5.18.2: 518 | resolution: {integrity: sha512-6Jw4sE1maoRJo3q8MsSIn2onJFbLTOjY9hlx4DZXmOKvLRd1Ok2kXmAGXaafL2+ijsJZ1ClYbl/pmqr9+k4iUQ==} 519 | engines: {node: '>=10.13.0'} 520 | 521 | environment@1.1.0: 522 | resolution: {integrity: sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==} 523 | engines: {node: '>=18'} 524 | 525 | esbuild@0.25.3: 526 | resolution: {integrity: sha512-qKA6Pvai73+M2FtftpNKRxJ78GIjmFXFxd/1DVBqGo/qNhLSfv+G12n9pNoWdytJC8U00TrViOwpjT0zgqQS8Q==} 527 | engines: {node: '>=18'} 528 | hasBin: true 529 | 530 | escape-string-regexp@4.0.0: 531 | resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} 532 | engines: {node: '>=10'} 533 | 534 | eslint-compat-utils@0.5.1: 535 | resolution: {integrity: sha512-3z3vFexKIEnjHE3zCMRo6fn/e44U7T1khUjg+Hp0ZQMCigh28rALD0nPFBcGZuiLC5rLZa2ubQHDRln09JfU2Q==} 536 | engines: {node: '>=12'} 537 | peerDependencies: 538 | eslint: '>=6.0.0' 539 | 540 | eslint-plugin-es-x@7.8.0: 541 | resolution: {integrity: sha512-7Ds8+wAAoV3T+LAKeu39Y5BzXCrGKrcISfgKEqTS4BDN8SFEDQd0S43jiQ8vIa3wUKD07qitZdfzlenSi8/0qQ==} 542 | engines: {node: ^14.18.0 || >=16.0.0} 543 | peerDependencies: 544 | eslint: '>=8' 545 | 546 | eslint-plugin-n@17.21.0: 547 | resolution: {integrity: sha512-1+iZ8We4ZlwVMtb/DcHG3y5/bZOdazIpa/4TySo22MLKdwrLcfrX0hbadnCvykSQCCmkAnWmIP8jZVb2AAq29A==} 548 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 549 | peerDependencies: 550 | eslint: '>=8.23.0' 551 | 552 | eslint-scope@8.4.0: 553 | resolution: {integrity: sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==} 554 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 555 | 556 | eslint-visitor-keys@3.4.3: 557 | resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} 558 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 559 | 560 | eslint-visitor-keys@4.2.1: 561 | resolution: {integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==} 562 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 563 | 564 | eslint@9.30.1: 565 | resolution: {integrity: sha512-zmxXPNMOXmwm9E0yQLi5uqXHs7uq2UIiqEKo3Gq+3fwo1XrJ+hijAZImyF7hclW3E6oHz43Yk3RP8at6OTKflQ==} 566 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 567 | hasBin: true 568 | peerDependencies: 569 | jiti: '*' 570 | peerDependenciesMeta: 571 | jiti: 572 | optional: true 573 | 574 | espree@10.4.0: 575 | resolution: {integrity: sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==} 576 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 577 | 578 | esquery@1.6.0: 579 | resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==} 580 | engines: {node: '>=0.10'} 581 | 582 | esrecurse@4.3.0: 583 | resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} 584 | engines: {node: '>=4.0'} 585 | 586 | estraverse@5.3.0: 587 | resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} 588 | engines: {node: '>=4.0'} 589 | 590 | esutils@2.0.3: 591 | resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} 592 | engines: {node: '>=0.10.0'} 593 | 594 | eventemitter3@5.0.1: 595 | resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==} 596 | 597 | execa@8.0.1: 598 | resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==} 599 | engines: {node: '>=16.17'} 600 | 601 | execa@9.5.2: 602 | resolution: {integrity: sha512-EHlpxMCpHWSAh1dgS6bVeoLAXGnJNdR93aabr4QCGbzOM73o5XmRfM/e5FUqsw3aagP8S8XEWUWFAxnRBnAF0Q==} 603 | engines: {node: ^18.19.0 || >=20.5.0} 604 | 605 | fast-deep-equal@3.1.3: 606 | resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} 607 | 608 | fast-glob@3.3.3: 609 | resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} 610 | engines: {node: '>=8.6.0'} 611 | 612 | fast-json-stable-stringify@2.1.0: 613 | resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} 614 | 615 | fast-levenshtein@2.0.6: 616 | resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} 617 | 618 | fastq@1.19.1: 619 | resolution: {integrity: sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==} 620 | 621 | fetch-blob@3.2.0: 622 | resolution: {integrity: sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==} 623 | engines: {node: ^12.20 || >= 14.13} 624 | 625 | figures@6.1.0: 626 | resolution: {integrity: sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg==} 627 | engines: {node: '>=18'} 628 | 629 | file-entry-cache@8.0.0: 630 | resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} 631 | engines: {node: '>=16.0.0'} 632 | 633 | fill-range@7.1.1: 634 | resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} 635 | engines: {node: '>=8'} 636 | 637 | find-up@5.0.0: 638 | resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} 639 | engines: {node: '>=10'} 640 | 641 | flat-cache@4.0.1: 642 | resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} 643 | engines: {node: '>=16'} 644 | 645 | flatted@3.3.3: 646 | resolution: {integrity: sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==} 647 | 648 | formdata-polyfill@4.0.10: 649 | resolution: {integrity: sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==} 650 | engines: {node: '>=12.20.0'} 651 | 652 | fsevents@2.3.3: 653 | resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} 654 | engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} 655 | os: [darwin] 656 | 657 | fzf@0.5.2: 658 | resolution: {integrity: sha512-Tt4kuxLXFKHy8KT40zwsUPUkg1CrsgY25FxA2U/j/0WgEDCk3ddc/zLTCCcbSHX9FcKtLuVaDGtGE/STWC+j3Q==} 659 | 660 | get-east-asian-width@1.3.0: 661 | resolution: {integrity: sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ==} 662 | engines: {node: '>=18'} 663 | 664 | get-stream@8.0.1: 665 | resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==} 666 | engines: {node: '>=16'} 667 | 668 | get-stream@9.0.1: 669 | resolution: {integrity: sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA==} 670 | engines: {node: '>=18'} 671 | 672 | get-tsconfig@4.10.0: 673 | resolution: {integrity: sha512-kGzZ3LWWQcGIAmg6iWvXn0ei6WDtV26wzHRMwDSzmAbcXrTEXxHy6IehI6/4eT6VRKyMP1eF1VqwrVUmE/LR7A==} 674 | 675 | get-tsconfig@4.10.1: 676 | resolution: {integrity: sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ==} 677 | 678 | glob-parent@5.1.2: 679 | resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} 680 | engines: {node: '>= 6'} 681 | 682 | glob-parent@6.0.2: 683 | resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} 684 | engines: {node: '>=10.13.0'} 685 | 686 | globals@14.0.0: 687 | resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} 688 | engines: {node: '>=18'} 689 | 690 | globals@15.15.0: 691 | resolution: {integrity: sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==} 692 | engines: {node: '>=18'} 693 | 694 | graceful-fs@4.2.11: 695 | resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} 696 | 697 | graphemer@1.4.0: 698 | resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} 699 | 700 | has-flag@4.0.0: 701 | resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} 702 | engines: {node: '>=8'} 703 | 704 | human-signals@5.0.0: 705 | resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==} 706 | engines: {node: '>=16.17.0'} 707 | 708 | human-signals@8.0.1: 709 | resolution: {integrity: sha512-eKCa6bwnJhvxj14kZk5NCPc6Hb6BdsU9DZcOnmQKSnO1VKrfV0zCvtttPZUsBvjmNDn8rpcJfpwSYnHBjc95MQ==} 710 | engines: {node: '>=18.18.0'} 711 | 712 | ignore@5.3.2: 713 | resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} 714 | engines: {node: '>= 4'} 715 | 716 | ignore@7.0.5: 717 | resolution: {integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==} 718 | engines: {node: '>= 4'} 719 | 720 | import-fresh@3.3.1: 721 | resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} 722 | engines: {node: '>=6'} 723 | 724 | imurmurhash@0.1.4: 725 | resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} 726 | engines: {node: '>=0.8.19'} 727 | 728 | is-extglob@2.1.1: 729 | resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} 730 | engines: {node: '>=0.10.0'} 731 | 732 | is-fullwidth-code-point@4.0.0: 733 | resolution: {integrity: sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==} 734 | engines: {node: '>=12'} 735 | 736 | is-fullwidth-code-point@5.0.0: 737 | resolution: {integrity: sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==} 738 | engines: {node: '>=18'} 739 | 740 | is-glob@4.0.3: 741 | resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} 742 | engines: {node: '>=0.10.0'} 743 | 744 | is-number@7.0.0: 745 | resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} 746 | engines: {node: '>=0.12.0'} 747 | 748 | is-plain-obj@4.1.0: 749 | resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==} 750 | engines: {node: '>=12'} 751 | 752 | is-stream@3.0.0: 753 | resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==} 754 | engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} 755 | 756 | is-stream@4.0.1: 757 | resolution: {integrity: sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==} 758 | engines: {node: '>=18'} 759 | 760 | is-unicode-supported@2.1.0: 761 | resolution: {integrity: sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==} 762 | engines: {node: '>=18'} 763 | 764 | isexe@2.0.0: 765 | resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} 766 | 767 | js-yaml@4.1.0: 768 | resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} 769 | hasBin: true 770 | 771 | json-buffer@3.0.1: 772 | resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} 773 | 774 | json-schema-traverse@0.4.1: 775 | resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} 776 | 777 | json-stable-stringify-without-jsonify@1.0.1: 778 | resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} 779 | 780 | keyv@4.5.4: 781 | resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} 782 | 783 | levn@0.4.1: 784 | resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} 785 | engines: {node: '>= 0.8.0'} 786 | 787 | lilconfig@3.1.3: 788 | resolution: {integrity: sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==} 789 | engines: {node: '>=14'} 790 | 791 | lint-staged@15.5.1: 792 | resolution: {integrity: sha512-6m7u8mue4Xn6wK6gZvSCQwBvMBR36xfY24nF5bMTf2MHDYG6S3yhJuOgdYVw99hsjyDt2d4z168b3naI8+NWtQ==} 793 | engines: {node: '>=18.12.0'} 794 | hasBin: true 795 | 796 | listr2@8.3.2: 797 | resolution: {integrity: sha512-vsBzcU4oE+v0lj4FhVLzr9dBTv4/fHIa57l+GCwovP8MoFNZJTOhGU8PXd4v2VJCbECAaijBiHntiekFMLvo0g==} 798 | engines: {node: '>=18.0.0'} 799 | 800 | locate-path@6.0.0: 801 | resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} 802 | engines: {node: '>=10'} 803 | 804 | lodash.merge@4.6.2: 805 | resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} 806 | 807 | log-update@6.1.0: 808 | resolution: {integrity: sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==} 809 | engines: {node: '>=18'} 810 | 811 | merge-stream@2.0.0: 812 | resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} 813 | 814 | merge2@1.4.1: 815 | resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} 816 | engines: {node: '>= 8'} 817 | 818 | micromatch@4.0.8: 819 | resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} 820 | engines: {node: '>=8.6'} 821 | 822 | mimic-fn@4.0.0: 823 | resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} 824 | engines: {node: '>=12'} 825 | 826 | mimic-function@5.0.1: 827 | resolution: {integrity: sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==} 828 | engines: {node: '>=18'} 829 | 830 | minimatch@3.1.2: 831 | resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} 832 | 833 | minimatch@9.0.5: 834 | resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} 835 | engines: {node: '>=16 || 14 >=14.17'} 836 | 837 | ms@2.1.3: 838 | resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} 839 | 840 | natural-compare@1.4.0: 841 | resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} 842 | 843 | node-domexception@1.0.0: 844 | resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==} 845 | engines: {node: '>=10.5.0'} 846 | deprecated: Use your platform's native DOMException instead 847 | 848 | node-fetch@3.3.2: 849 | resolution: {integrity: sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==} 850 | engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} 851 | 852 | npm-run-path@5.3.0: 853 | resolution: {integrity: sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==} 854 | engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} 855 | 856 | npm-run-path@6.0.0: 857 | resolution: {integrity: sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA==} 858 | engines: {node: '>=18'} 859 | 860 | onetime@6.0.0: 861 | resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==} 862 | engines: {node: '>=12'} 863 | 864 | onetime@7.0.0: 865 | resolution: {integrity: sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==} 866 | engines: {node: '>=18'} 867 | 868 | optionator@0.9.4: 869 | resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} 870 | engines: {node: '>= 0.8.0'} 871 | 872 | p-limit@3.1.0: 873 | resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} 874 | engines: {node: '>=10'} 875 | 876 | p-locate@5.0.0: 877 | resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} 878 | engines: {node: '>=10'} 879 | 880 | package-manager-detector@1.2.0: 881 | resolution: {integrity: sha512-PutJepsOtsqVfUsxCzgTTpyXmiAgvKptIgY4th5eq5UXXFhj5PxfQ9hnGkypMeovpAvVshFRItoFHYO18TCOqA==} 882 | 883 | parent-module@1.0.1: 884 | resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} 885 | engines: {node: '>=6'} 886 | 887 | parse-ms@4.0.0: 888 | resolution: {integrity: sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw==} 889 | engines: {node: '>=18'} 890 | 891 | path-exists@4.0.0: 892 | resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} 893 | engines: {node: '>=8'} 894 | 895 | path-key@3.1.1: 896 | resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} 897 | engines: {node: '>=8'} 898 | 899 | path-key@4.0.0: 900 | resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==} 901 | engines: {node: '>=12'} 902 | 903 | picomatch@2.3.1: 904 | resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} 905 | engines: {node: '>=8.6'} 906 | 907 | picomatch@4.0.2: 908 | resolution: {integrity: sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==} 909 | engines: {node: '>=12'} 910 | 911 | pidtree@0.6.0: 912 | resolution: {integrity: sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==} 913 | engines: {node: '>=0.10'} 914 | hasBin: true 915 | 916 | prelude-ls@1.2.1: 917 | resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} 918 | engines: {node: '>= 0.8.0'} 919 | 920 | prettier@3.5.3: 921 | resolution: {integrity: sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==} 922 | engines: {node: '>=14'} 923 | hasBin: true 924 | 925 | pretty-ms@9.2.0: 926 | resolution: {integrity: sha512-4yf0QO/sllf/1zbZWYnvWw3NxCQwLXKzIj0G849LSufP15BXKM0rbD2Z3wVnkMfjdn/CB0Dpp444gYAACdsplg==} 927 | engines: {node: '>=18'} 928 | 929 | punycode@2.3.1: 930 | resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} 931 | engines: {node: '>=6'} 932 | 933 | queue-microtask@1.2.3: 934 | resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} 935 | 936 | resolve-from@4.0.0: 937 | resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} 938 | engines: {node: '>=4'} 939 | 940 | resolve-pkg-maps@1.0.0: 941 | resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} 942 | 943 | restore-cursor@5.1.0: 944 | resolution: {integrity: sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==} 945 | engines: {node: '>=18'} 946 | 947 | reusify@1.1.0: 948 | resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} 949 | engines: {iojs: '>=1.0.0', node: '>=0.10.0'} 950 | 951 | rfdc@1.4.1: 952 | resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==} 953 | 954 | run-parallel@1.2.0: 955 | resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} 956 | 957 | semver@7.7.1: 958 | resolution: {integrity: sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==} 959 | engines: {node: '>=10'} 960 | hasBin: true 961 | 962 | shebang-command@2.0.0: 963 | resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} 964 | engines: {node: '>=8'} 965 | 966 | shebang-regex@3.0.0: 967 | resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} 968 | engines: {node: '>=8'} 969 | 970 | signal-exit@4.1.0: 971 | resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} 972 | engines: {node: '>=14'} 973 | 974 | simple-git-hooks@2.12.1: 975 | resolution: {integrity: sha512-NB3V4XyCOrWTIhjh85DyEoVlM3adHWwqQXKYHmuegy/108bJPP6YxuPGm4ZKBq1+GVKRbKJuzNY//09cMJYp+A==} 976 | hasBin: true 977 | 978 | slice-ansi@5.0.0: 979 | resolution: {integrity: sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==} 980 | engines: {node: '>=12'} 981 | 982 | slice-ansi@7.1.0: 983 | resolution: {integrity: sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==} 984 | engines: {node: '>=18'} 985 | 986 | string-argv@0.3.2: 987 | resolution: {integrity: sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==} 988 | engines: {node: '>=0.6.19'} 989 | 990 | string-width@7.2.0: 991 | resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==} 992 | engines: {node: '>=18'} 993 | 994 | strip-ansi@7.1.0: 995 | resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} 996 | engines: {node: '>=12'} 997 | 998 | strip-final-newline@3.0.0: 999 | resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==} 1000 | engines: {node: '>=12'} 1001 | 1002 | strip-final-newline@4.0.0: 1003 | resolution: {integrity: sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw==} 1004 | engines: {node: '>=18'} 1005 | 1006 | strip-json-comments@3.1.1: 1007 | resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} 1008 | engines: {node: '>=8'} 1009 | 1010 | supports-color@7.2.0: 1011 | resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} 1012 | engines: {node: '>=8'} 1013 | 1014 | tapable@2.2.2: 1015 | resolution: {integrity: sha512-Re10+NauLTMCudc7T5WLFLAwDhQ0JWdrMK+9B2M8zR5hRExKmsRDCBA7/aV/pNJFltmBFO5BAMlQFi/vq3nKOg==} 1016 | engines: {node: '>=6'} 1017 | 1018 | tinyexec@1.0.1: 1019 | resolution: {integrity: sha512-5uC6DDlmeqiOwCPmK9jMSdOuZTh8bU39Ys6yidB+UTt5hfZUPGAypSgFRiEp+jbi9qH40BLDvy85jIU88wKSqw==} 1020 | 1021 | to-regex-range@5.0.1: 1022 | resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} 1023 | engines: {node: '>=8.0'} 1024 | 1025 | ts-api-utils@2.1.0: 1026 | resolution: {integrity: sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==} 1027 | engines: {node: '>=18.12'} 1028 | peerDependencies: 1029 | typescript: '>=4.8.4' 1030 | 1031 | ts-declaration-location@1.0.7: 1032 | resolution: {integrity: sha512-EDyGAwH1gO0Ausm9gV6T2nUvBgXT5kGoCMJPllOaooZ+4VvJiKBdZE7wK18N1deEowhcUptS+5GXZK8U/fvpwA==} 1033 | peerDependencies: 1034 | typescript: '>=4.0.0' 1035 | 1036 | tsx@4.19.3: 1037 | resolution: {integrity: sha512-4H8vUNGNjQ4V2EOoGw005+c+dGuPSnhpPBPHBtsZdGZBk/iJb4kguGlPWaZTZ3q5nMtFOEsY0nRDlh9PJyd6SQ==} 1038 | engines: {node: '>=18.0.0'} 1039 | hasBin: true 1040 | 1041 | tunnel@0.0.6: 1042 | resolution: {integrity: sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==} 1043 | engines: {node: '>=0.6.11 <=0.7.0 || >=0.7.3'} 1044 | 1045 | type-check@0.4.0: 1046 | resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} 1047 | engines: {node: '>= 0.8.0'} 1048 | 1049 | typescript-eslint@8.35.1: 1050 | resolution: {integrity: sha512-xslJjFzhOmHYQzSB/QTeASAHbjmxOGEP6Coh93TXmUBFQoJ1VU35UHIDmG06Jd6taf3wqqC1ntBnCMeymy5Ovw==} 1051 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 1052 | peerDependencies: 1053 | eslint: ^8.57.0 || ^9.0.0 1054 | typescript: '>=4.8.4 <5.9.0' 1055 | 1056 | typescript@5.8.3: 1057 | resolution: {integrity: sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==} 1058 | engines: {node: '>=14.17'} 1059 | hasBin: true 1060 | 1061 | undici-types@6.21.0: 1062 | resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} 1063 | 1064 | undici@5.29.0: 1065 | resolution: {integrity: sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg==} 1066 | engines: {node: '>=14.0'} 1067 | 1068 | unicorn-magic@0.3.0: 1069 | resolution: {integrity: sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==} 1070 | engines: {node: '>=18'} 1071 | 1072 | uri-js@4.4.1: 1073 | resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} 1074 | 1075 | web-streams-polyfill@3.3.3: 1076 | resolution: {integrity: sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==} 1077 | engines: {node: '>= 8'} 1078 | 1079 | which@2.0.2: 1080 | resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} 1081 | engines: {node: '>= 8'} 1082 | hasBin: true 1083 | 1084 | word-wrap@1.2.5: 1085 | resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} 1086 | engines: {node: '>=0.10.0'} 1087 | 1088 | wrap-ansi@9.0.0: 1089 | resolution: {integrity: sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==} 1090 | engines: {node: '>=18'} 1091 | 1092 | yaml@2.7.1: 1093 | resolution: {integrity: sha512-10ULxpnOCQXxJvBgxsn9ptjq6uviG/htZKk9veJGhlqn3w/DxQ631zFF+nlQXLwmImeS5amR2dl2U8sg6U9jsQ==} 1094 | engines: {node: '>= 14'} 1095 | hasBin: true 1096 | 1097 | yocto-queue@0.1.0: 1098 | resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} 1099 | engines: {node: '>=10'} 1100 | 1101 | yoctocolors@2.1.1: 1102 | resolution: {integrity: sha512-GQHQqAopRhwU8Kt1DDM8NjibDXHC8eoh1erhGAJPEyveY9qqVeXvVikNKrDz69sHowPMorbPUrH/mx8c50eiBQ==} 1103 | engines: {node: '>=18'} 1104 | 1105 | snapshots: 1106 | 1107 | '@actions/core@1.11.1': 1108 | dependencies: 1109 | '@actions/exec': 1.1.1 1110 | '@actions/http-client': 2.2.3 1111 | 1112 | '@actions/exec@1.1.1': 1113 | dependencies: 1114 | '@actions/io': 1.1.3 1115 | 1116 | '@actions/http-client@2.2.3': 1117 | dependencies: 1118 | tunnel: 0.0.6 1119 | undici: 5.29.0 1120 | 1121 | '@actions/io@1.1.3': {} 1122 | 1123 | '@antfu/ni@24.3.0': 1124 | dependencies: 1125 | ansis: 3.17.0 1126 | fzf: 0.5.2 1127 | package-manager-detector: 1.2.0 1128 | tinyexec: 1.0.1 1129 | 1130 | '@esbuild/aix-ppc64@0.25.3': 1131 | optional: true 1132 | 1133 | '@esbuild/android-arm64@0.25.3': 1134 | optional: true 1135 | 1136 | '@esbuild/android-arm@0.25.3': 1137 | optional: true 1138 | 1139 | '@esbuild/android-x64@0.25.3': 1140 | optional: true 1141 | 1142 | '@esbuild/darwin-arm64@0.25.3': 1143 | optional: true 1144 | 1145 | '@esbuild/darwin-x64@0.25.3': 1146 | optional: true 1147 | 1148 | '@esbuild/freebsd-arm64@0.25.3': 1149 | optional: true 1150 | 1151 | '@esbuild/freebsd-x64@0.25.3': 1152 | optional: true 1153 | 1154 | '@esbuild/linux-arm64@0.25.3': 1155 | optional: true 1156 | 1157 | '@esbuild/linux-arm@0.25.3': 1158 | optional: true 1159 | 1160 | '@esbuild/linux-ia32@0.25.3': 1161 | optional: true 1162 | 1163 | '@esbuild/linux-loong64@0.25.3': 1164 | optional: true 1165 | 1166 | '@esbuild/linux-mips64el@0.25.3': 1167 | optional: true 1168 | 1169 | '@esbuild/linux-ppc64@0.25.3': 1170 | optional: true 1171 | 1172 | '@esbuild/linux-riscv64@0.25.3': 1173 | optional: true 1174 | 1175 | '@esbuild/linux-s390x@0.25.3': 1176 | optional: true 1177 | 1178 | '@esbuild/linux-x64@0.25.3': 1179 | optional: true 1180 | 1181 | '@esbuild/netbsd-arm64@0.25.3': 1182 | optional: true 1183 | 1184 | '@esbuild/netbsd-x64@0.25.3': 1185 | optional: true 1186 | 1187 | '@esbuild/openbsd-arm64@0.25.3': 1188 | optional: true 1189 | 1190 | '@esbuild/openbsd-x64@0.25.3': 1191 | optional: true 1192 | 1193 | '@esbuild/sunos-x64@0.25.3': 1194 | optional: true 1195 | 1196 | '@esbuild/win32-arm64@0.25.3': 1197 | optional: true 1198 | 1199 | '@esbuild/win32-ia32@0.25.3': 1200 | optional: true 1201 | 1202 | '@esbuild/win32-x64@0.25.3': 1203 | optional: true 1204 | 1205 | '@eslint-community/eslint-utils@4.7.0(eslint@9.30.1)': 1206 | dependencies: 1207 | eslint: 9.30.1 1208 | eslint-visitor-keys: 3.4.3 1209 | 1210 | '@eslint-community/regexpp@4.12.1': {} 1211 | 1212 | '@eslint/config-array@0.21.0': 1213 | dependencies: 1214 | '@eslint/object-schema': 2.1.6 1215 | debug: 4.4.1 1216 | minimatch: 3.1.2 1217 | transitivePeerDependencies: 1218 | - supports-color 1219 | 1220 | '@eslint/config-helpers@0.3.0': {} 1221 | 1222 | '@eslint/core@0.14.0': 1223 | dependencies: 1224 | '@types/json-schema': 7.0.15 1225 | 1226 | '@eslint/core@0.15.1': 1227 | dependencies: 1228 | '@types/json-schema': 7.0.15 1229 | 1230 | '@eslint/eslintrc@3.3.1': 1231 | dependencies: 1232 | ajv: 6.12.6 1233 | debug: 4.4.1 1234 | espree: 10.4.0 1235 | globals: 14.0.0 1236 | ignore: 5.3.2 1237 | import-fresh: 3.3.1 1238 | js-yaml: 4.1.0 1239 | minimatch: 3.1.2 1240 | strip-json-comments: 3.1.1 1241 | transitivePeerDependencies: 1242 | - supports-color 1243 | 1244 | '@eslint/js@9.25.1': {} 1245 | 1246 | '@eslint/js@9.30.1': {} 1247 | 1248 | '@eslint/object-schema@2.1.6': {} 1249 | 1250 | '@eslint/plugin-kit@0.3.3': 1251 | dependencies: 1252 | '@eslint/core': 0.15.1 1253 | levn: 0.4.1 1254 | 1255 | '@fastify/busboy@2.1.1': {} 1256 | 1257 | '@humanfs/core@0.19.1': {} 1258 | 1259 | '@humanfs/node@0.16.6': 1260 | dependencies: 1261 | '@humanfs/core': 0.19.1 1262 | '@humanwhocodes/retry': 0.3.1 1263 | 1264 | '@humanwhocodes/module-importer@1.0.1': {} 1265 | 1266 | '@humanwhocodes/retry@0.3.1': {} 1267 | 1268 | '@humanwhocodes/retry@0.4.3': {} 1269 | 1270 | '@nodelib/fs.scandir@2.1.5': 1271 | dependencies: 1272 | '@nodelib/fs.stat': 2.0.5 1273 | run-parallel: 1.2.0 1274 | 1275 | '@nodelib/fs.stat@2.0.5': {} 1276 | 1277 | '@nodelib/fs.walk@1.2.8': 1278 | dependencies: 1279 | '@nodelib/fs.scandir': 2.1.5 1280 | fastq: 1.19.1 1281 | 1282 | '@sec-ant/readable-stream@0.4.1': {} 1283 | 1284 | '@sindresorhus/merge-streams@4.0.0': {} 1285 | 1286 | '@types/estree@1.0.8': {} 1287 | 1288 | '@types/json-schema@7.0.15': {} 1289 | 1290 | '@types/node@22.14.1': 1291 | dependencies: 1292 | undici-types: 6.21.0 1293 | 1294 | '@types/semver@7.7.0': {} 1295 | 1296 | '@typescript-eslint/eslint-plugin@8.35.1(@typescript-eslint/parser@8.35.1(eslint@9.30.1)(typescript@5.8.3))(eslint@9.30.1)(typescript@5.8.3)': 1297 | dependencies: 1298 | '@eslint-community/regexpp': 4.12.1 1299 | '@typescript-eslint/parser': 8.35.1(eslint@9.30.1)(typescript@5.8.3) 1300 | '@typescript-eslint/scope-manager': 8.35.1 1301 | '@typescript-eslint/type-utils': 8.35.1(eslint@9.30.1)(typescript@5.8.3) 1302 | '@typescript-eslint/utils': 8.35.1(eslint@9.30.1)(typescript@5.8.3) 1303 | '@typescript-eslint/visitor-keys': 8.35.1 1304 | eslint: 9.30.1 1305 | graphemer: 1.4.0 1306 | ignore: 7.0.5 1307 | natural-compare: 1.4.0 1308 | ts-api-utils: 2.1.0(typescript@5.8.3) 1309 | typescript: 5.8.3 1310 | transitivePeerDependencies: 1311 | - supports-color 1312 | 1313 | '@typescript-eslint/parser@8.35.1(eslint@9.30.1)(typescript@5.8.3)': 1314 | dependencies: 1315 | '@typescript-eslint/scope-manager': 8.35.1 1316 | '@typescript-eslint/types': 8.35.1 1317 | '@typescript-eslint/typescript-estree': 8.35.1(typescript@5.8.3) 1318 | '@typescript-eslint/visitor-keys': 8.35.1 1319 | debug: 4.4.1 1320 | eslint: 9.30.1 1321 | typescript: 5.8.3 1322 | transitivePeerDependencies: 1323 | - supports-color 1324 | 1325 | '@typescript-eslint/project-service@8.35.1(typescript@5.8.3)': 1326 | dependencies: 1327 | '@typescript-eslint/tsconfig-utils': 8.35.1(typescript@5.8.3) 1328 | '@typescript-eslint/types': 8.35.1 1329 | debug: 4.4.1 1330 | typescript: 5.8.3 1331 | transitivePeerDependencies: 1332 | - supports-color 1333 | 1334 | '@typescript-eslint/scope-manager@8.35.1': 1335 | dependencies: 1336 | '@typescript-eslint/types': 8.35.1 1337 | '@typescript-eslint/visitor-keys': 8.35.1 1338 | 1339 | '@typescript-eslint/tsconfig-utils@8.35.1(typescript@5.8.3)': 1340 | dependencies: 1341 | typescript: 5.8.3 1342 | 1343 | '@typescript-eslint/type-utils@8.35.1(eslint@9.30.1)(typescript@5.8.3)': 1344 | dependencies: 1345 | '@typescript-eslint/typescript-estree': 8.35.1(typescript@5.8.3) 1346 | '@typescript-eslint/utils': 8.35.1(eslint@9.30.1)(typescript@5.8.3) 1347 | debug: 4.4.1 1348 | eslint: 9.30.1 1349 | ts-api-utils: 2.1.0(typescript@5.8.3) 1350 | typescript: 5.8.3 1351 | transitivePeerDependencies: 1352 | - supports-color 1353 | 1354 | '@typescript-eslint/types@8.35.1': {} 1355 | 1356 | '@typescript-eslint/typescript-estree@8.35.1(typescript@5.8.3)': 1357 | dependencies: 1358 | '@typescript-eslint/project-service': 8.35.1(typescript@5.8.3) 1359 | '@typescript-eslint/tsconfig-utils': 8.35.1(typescript@5.8.3) 1360 | '@typescript-eslint/types': 8.35.1 1361 | '@typescript-eslint/visitor-keys': 8.35.1 1362 | debug: 4.4.1 1363 | fast-glob: 3.3.3 1364 | is-glob: 4.0.3 1365 | minimatch: 9.0.5 1366 | semver: 7.7.1 1367 | ts-api-utils: 2.1.0(typescript@5.8.3) 1368 | typescript: 5.8.3 1369 | transitivePeerDependencies: 1370 | - supports-color 1371 | 1372 | '@typescript-eslint/utils@8.35.1(eslint@9.30.1)(typescript@5.8.3)': 1373 | dependencies: 1374 | '@eslint-community/eslint-utils': 4.7.0(eslint@9.30.1) 1375 | '@typescript-eslint/scope-manager': 8.35.1 1376 | '@typescript-eslint/types': 8.35.1 1377 | '@typescript-eslint/typescript-estree': 8.35.1(typescript@5.8.3) 1378 | eslint: 9.30.1 1379 | typescript: 5.8.3 1380 | transitivePeerDependencies: 1381 | - supports-color 1382 | 1383 | '@typescript-eslint/visitor-keys@8.35.1': 1384 | dependencies: 1385 | '@typescript-eslint/types': 8.35.1 1386 | eslint-visitor-keys: 4.2.1 1387 | 1388 | acorn-jsx@5.3.2(acorn@8.15.0): 1389 | dependencies: 1390 | acorn: 8.15.0 1391 | 1392 | acorn@8.15.0: {} 1393 | 1394 | ajv@6.12.6: 1395 | dependencies: 1396 | fast-deep-equal: 3.1.3 1397 | fast-json-stable-stringify: 2.1.0 1398 | json-schema-traverse: 0.4.1 1399 | uri-js: 4.4.1 1400 | 1401 | ansi-escapes@7.0.0: 1402 | dependencies: 1403 | environment: 1.1.0 1404 | 1405 | ansi-regex@6.1.0: {} 1406 | 1407 | ansi-styles@4.3.0: 1408 | dependencies: 1409 | color-convert: 2.0.1 1410 | 1411 | ansi-styles@6.2.1: {} 1412 | 1413 | ansis@3.17.0: {} 1414 | 1415 | argparse@2.0.1: {} 1416 | 1417 | balanced-match@1.0.2: {} 1418 | 1419 | brace-expansion@1.1.12: 1420 | dependencies: 1421 | balanced-match: 1.0.2 1422 | concat-map: 0.0.1 1423 | 1424 | brace-expansion@2.0.2: 1425 | dependencies: 1426 | balanced-match: 1.0.2 1427 | 1428 | braces@3.0.3: 1429 | dependencies: 1430 | fill-range: 7.1.1 1431 | 1432 | cac@6.7.14: {} 1433 | 1434 | callsites@3.1.0: {} 1435 | 1436 | chalk@4.1.2: 1437 | dependencies: 1438 | ansi-styles: 4.3.0 1439 | supports-color: 7.2.0 1440 | 1441 | chalk@5.4.1: {} 1442 | 1443 | cli-cursor@5.0.0: 1444 | dependencies: 1445 | restore-cursor: 5.1.0 1446 | 1447 | cli-truncate@4.0.0: 1448 | dependencies: 1449 | slice-ansi: 5.0.0 1450 | string-width: 7.2.0 1451 | 1452 | color-convert@2.0.1: 1453 | dependencies: 1454 | color-name: 1.1.4 1455 | 1456 | color-name@1.1.4: {} 1457 | 1458 | colorette@2.0.20: {} 1459 | 1460 | commander@13.1.0: {} 1461 | 1462 | concat-map@0.0.1: {} 1463 | 1464 | cross-spawn@7.0.6: 1465 | dependencies: 1466 | path-key: 3.1.1 1467 | shebang-command: 2.0.0 1468 | which: 2.0.2 1469 | 1470 | data-uri-to-buffer@4.0.1: {} 1471 | 1472 | debug@4.4.0: 1473 | dependencies: 1474 | ms: 2.1.3 1475 | 1476 | debug@4.4.1: 1477 | dependencies: 1478 | ms: 2.1.3 1479 | 1480 | deep-is@0.1.4: {} 1481 | 1482 | emoji-regex@10.4.0: {} 1483 | 1484 | enhanced-resolve@5.18.2: 1485 | dependencies: 1486 | graceful-fs: 4.2.11 1487 | tapable: 2.2.2 1488 | 1489 | environment@1.1.0: {} 1490 | 1491 | esbuild@0.25.3: 1492 | optionalDependencies: 1493 | '@esbuild/aix-ppc64': 0.25.3 1494 | '@esbuild/android-arm': 0.25.3 1495 | '@esbuild/android-arm64': 0.25.3 1496 | '@esbuild/android-x64': 0.25.3 1497 | '@esbuild/darwin-arm64': 0.25.3 1498 | '@esbuild/darwin-x64': 0.25.3 1499 | '@esbuild/freebsd-arm64': 0.25.3 1500 | '@esbuild/freebsd-x64': 0.25.3 1501 | '@esbuild/linux-arm': 0.25.3 1502 | '@esbuild/linux-arm64': 0.25.3 1503 | '@esbuild/linux-ia32': 0.25.3 1504 | '@esbuild/linux-loong64': 0.25.3 1505 | '@esbuild/linux-mips64el': 0.25.3 1506 | '@esbuild/linux-ppc64': 0.25.3 1507 | '@esbuild/linux-riscv64': 0.25.3 1508 | '@esbuild/linux-s390x': 0.25.3 1509 | '@esbuild/linux-x64': 0.25.3 1510 | '@esbuild/netbsd-arm64': 0.25.3 1511 | '@esbuild/netbsd-x64': 0.25.3 1512 | '@esbuild/openbsd-arm64': 0.25.3 1513 | '@esbuild/openbsd-x64': 0.25.3 1514 | '@esbuild/sunos-x64': 0.25.3 1515 | '@esbuild/win32-arm64': 0.25.3 1516 | '@esbuild/win32-ia32': 0.25.3 1517 | '@esbuild/win32-x64': 0.25.3 1518 | 1519 | escape-string-regexp@4.0.0: {} 1520 | 1521 | eslint-compat-utils@0.5.1(eslint@9.30.1): 1522 | dependencies: 1523 | eslint: 9.30.1 1524 | semver: 7.7.1 1525 | 1526 | eslint-plugin-es-x@7.8.0(eslint@9.30.1): 1527 | dependencies: 1528 | '@eslint-community/eslint-utils': 4.7.0(eslint@9.30.1) 1529 | '@eslint-community/regexpp': 4.12.1 1530 | eslint: 9.30.1 1531 | eslint-compat-utils: 0.5.1(eslint@9.30.1) 1532 | 1533 | eslint-plugin-n@17.21.0(eslint@9.30.1)(typescript@5.8.3): 1534 | dependencies: 1535 | '@eslint-community/eslint-utils': 4.7.0(eslint@9.30.1) 1536 | enhanced-resolve: 5.18.2 1537 | eslint: 9.30.1 1538 | eslint-plugin-es-x: 7.8.0(eslint@9.30.1) 1539 | get-tsconfig: 4.10.1 1540 | globals: 15.15.0 1541 | ignore: 5.3.2 1542 | minimatch: 9.0.5 1543 | semver: 7.7.1 1544 | ts-declaration-location: 1.0.7(typescript@5.8.3) 1545 | transitivePeerDependencies: 1546 | - typescript 1547 | 1548 | eslint-scope@8.4.0: 1549 | dependencies: 1550 | esrecurse: 4.3.0 1551 | estraverse: 5.3.0 1552 | 1553 | eslint-visitor-keys@3.4.3: {} 1554 | 1555 | eslint-visitor-keys@4.2.1: {} 1556 | 1557 | eslint@9.30.1: 1558 | dependencies: 1559 | '@eslint-community/eslint-utils': 4.7.0(eslint@9.30.1) 1560 | '@eslint-community/regexpp': 4.12.1 1561 | '@eslint/config-array': 0.21.0 1562 | '@eslint/config-helpers': 0.3.0 1563 | '@eslint/core': 0.14.0 1564 | '@eslint/eslintrc': 3.3.1 1565 | '@eslint/js': 9.30.1 1566 | '@eslint/plugin-kit': 0.3.3 1567 | '@humanfs/node': 0.16.6 1568 | '@humanwhocodes/module-importer': 1.0.1 1569 | '@humanwhocodes/retry': 0.4.3 1570 | '@types/estree': 1.0.8 1571 | '@types/json-schema': 7.0.15 1572 | ajv: 6.12.6 1573 | chalk: 4.1.2 1574 | cross-spawn: 7.0.6 1575 | debug: 4.4.1 1576 | escape-string-regexp: 4.0.0 1577 | eslint-scope: 8.4.0 1578 | eslint-visitor-keys: 4.2.1 1579 | espree: 10.4.0 1580 | esquery: 1.6.0 1581 | esutils: 2.0.3 1582 | fast-deep-equal: 3.1.3 1583 | file-entry-cache: 8.0.0 1584 | find-up: 5.0.0 1585 | glob-parent: 6.0.2 1586 | ignore: 5.3.2 1587 | imurmurhash: 0.1.4 1588 | is-glob: 4.0.3 1589 | json-stable-stringify-without-jsonify: 1.0.1 1590 | lodash.merge: 4.6.2 1591 | minimatch: 3.1.2 1592 | natural-compare: 1.4.0 1593 | optionator: 0.9.4 1594 | transitivePeerDependencies: 1595 | - supports-color 1596 | 1597 | espree@10.4.0: 1598 | dependencies: 1599 | acorn: 8.15.0 1600 | acorn-jsx: 5.3.2(acorn@8.15.0) 1601 | eslint-visitor-keys: 4.2.1 1602 | 1603 | esquery@1.6.0: 1604 | dependencies: 1605 | estraverse: 5.3.0 1606 | 1607 | esrecurse@4.3.0: 1608 | dependencies: 1609 | estraverse: 5.3.0 1610 | 1611 | estraverse@5.3.0: {} 1612 | 1613 | esutils@2.0.3: {} 1614 | 1615 | eventemitter3@5.0.1: {} 1616 | 1617 | execa@8.0.1: 1618 | dependencies: 1619 | cross-spawn: 7.0.6 1620 | get-stream: 8.0.1 1621 | human-signals: 5.0.0 1622 | is-stream: 3.0.0 1623 | merge-stream: 2.0.0 1624 | npm-run-path: 5.3.0 1625 | onetime: 6.0.0 1626 | signal-exit: 4.1.0 1627 | strip-final-newline: 3.0.0 1628 | 1629 | execa@9.5.2: 1630 | dependencies: 1631 | '@sindresorhus/merge-streams': 4.0.0 1632 | cross-spawn: 7.0.6 1633 | figures: 6.1.0 1634 | get-stream: 9.0.1 1635 | human-signals: 8.0.1 1636 | is-plain-obj: 4.1.0 1637 | is-stream: 4.0.1 1638 | npm-run-path: 6.0.0 1639 | pretty-ms: 9.2.0 1640 | signal-exit: 4.1.0 1641 | strip-final-newline: 4.0.0 1642 | yoctocolors: 2.1.1 1643 | 1644 | fast-deep-equal@3.1.3: {} 1645 | 1646 | fast-glob@3.3.3: 1647 | dependencies: 1648 | '@nodelib/fs.stat': 2.0.5 1649 | '@nodelib/fs.walk': 1.2.8 1650 | glob-parent: 5.1.2 1651 | merge2: 1.4.1 1652 | micromatch: 4.0.8 1653 | 1654 | fast-json-stable-stringify@2.1.0: {} 1655 | 1656 | fast-levenshtein@2.0.6: {} 1657 | 1658 | fastq@1.19.1: 1659 | dependencies: 1660 | reusify: 1.1.0 1661 | 1662 | fetch-blob@3.2.0: 1663 | dependencies: 1664 | node-domexception: 1.0.0 1665 | web-streams-polyfill: 3.3.3 1666 | 1667 | figures@6.1.0: 1668 | dependencies: 1669 | is-unicode-supported: 2.1.0 1670 | 1671 | file-entry-cache@8.0.0: 1672 | dependencies: 1673 | flat-cache: 4.0.1 1674 | 1675 | fill-range@7.1.1: 1676 | dependencies: 1677 | to-regex-range: 5.0.1 1678 | 1679 | find-up@5.0.0: 1680 | dependencies: 1681 | locate-path: 6.0.0 1682 | path-exists: 4.0.0 1683 | 1684 | flat-cache@4.0.1: 1685 | dependencies: 1686 | flatted: 3.3.3 1687 | keyv: 4.5.4 1688 | 1689 | flatted@3.3.3: {} 1690 | 1691 | formdata-polyfill@4.0.10: 1692 | dependencies: 1693 | fetch-blob: 3.2.0 1694 | 1695 | fsevents@2.3.3: 1696 | optional: true 1697 | 1698 | fzf@0.5.2: {} 1699 | 1700 | get-east-asian-width@1.3.0: {} 1701 | 1702 | get-stream@8.0.1: {} 1703 | 1704 | get-stream@9.0.1: 1705 | dependencies: 1706 | '@sec-ant/readable-stream': 0.4.1 1707 | is-stream: 4.0.1 1708 | 1709 | get-tsconfig@4.10.0: 1710 | dependencies: 1711 | resolve-pkg-maps: 1.0.0 1712 | 1713 | get-tsconfig@4.10.1: 1714 | dependencies: 1715 | resolve-pkg-maps: 1.0.0 1716 | 1717 | glob-parent@5.1.2: 1718 | dependencies: 1719 | is-glob: 4.0.3 1720 | 1721 | glob-parent@6.0.2: 1722 | dependencies: 1723 | is-glob: 4.0.3 1724 | 1725 | globals@14.0.0: {} 1726 | 1727 | globals@15.15.0: {} 1728 | 1729 | graceful-fs@4.2.11: {} 1730 | 1731 | graphemer@1.4.0: {} 1732 | 1733 | has-flag@4.0.0: {} 1734 | 1735 | human-signals@5.0.0: {} 1736 | 1737 | human-signals@8.0.1: {} 1738 | 1739 | ignore@5.3.2: {} 1740 | 1741 | ignore@7.0.5: {} 1742 | 1743 | import-fresh@3.3.1: 1744 | dependencies: 1745 | parent-module: 1.0.1 1746 | resolve-from: 4.0.0 1747 | 1748 | imurmurhash@0.1.4: {} 1749 | 1750 | is-extglob@2.1.1: {} 1751 | 1752 | is-fullwidth-code-point@4.0.0: {} 1753 | 1754 | is-fullwidth-code-point@5.0.0: 1755 | dependencies: 1756 | get-east-asian-width: 1.3.0 1757 | 1758 | is-glob@4.0.3: 1759 | dependencies: 1760 | is-extglob: 2.1.1 1761 | 1762 | is-number@7.0.0: {} 1763 | 1764 | is-plain-obj@4.1.0: {} 1765 | 1766 | is-stream@3.0.0: {} 1767 | 1768 | is-stream@4.0.1: {} 1769 | 1770 | is-unicode-supported@2.1.0: {} 1771 | 1772 | isexe@2.0.0: {} 1773 | 1774 | js-yaml@4.1.0: 1775 | dependencies: 1776 | argparse: 2.0.1 1777 | 1778 | json-buffer@3.0.1: {} 1779 | 1780 | json-schema-traverse@0.4.1: {} 1781 | 1782 | json-stable-stringify-without-jsonify@1.0.1: {} 1783 | 1784 | keyv@4.5.4: 1785 | dependencies: 1786 | json-buffer: 3.0.1 1787 | 1788 | levn@0.4.1: 1789 | dependencies: 1790 | prelude-ls: 1.2.1 1791 | type-check: 0.4.0 1792 | 1793 | lilconfig@3.1.3: {} 1794 | 1795 | lint-staged@15.5.1: 1796 | dependencies: 1797 | chalk: 5.4.1 1798 | commander: 13.1.0 1799 | debug: 4.4.0 1800 | execa: 8.0.1 1801 | lilconfig: 3.1.3 1802 | listr2: 8.3.2 1803 | micromatch: 4.0.8 1804 | pidtree: 0.6.0 1805 | string-argv: 0.3.2 1806 | yaml: 2.7.1 1807 | transitivePeerDependencies: 1808 | - supports-color 1809 | 1810 | listr2@8.3.2: 1811 | dependencies: 1812 | cli-truncate: 4.0.0 1813 | colorette: 2.0.20 1814 | eventemitter3: 5.0.1 1815 | log-update: 6.1.0 1816 | rfdc: 1.4.1 1817 | wrap-ansi: 9.0.0 1818 | 1819 | locate-path@6.0.0: 1820 | dependencies: 1821 | p-locate: 5.0.0 1822 | 1823 | lodash.merge@4.6.2: {} 1824 | 1825 | log-update@6.1.0: 1826 | dependencies: 1827 | ansi-escapes: 7.0.0 1828 | cli-cursor: 5.0.0 1829 | slice-ansi: 7.1.0 1830 | strip-ansi: 7.1.0 1831 | wrap-ansi: 9.0.0 1832 | 1833 | merge-stream@2.0.0: {} 1834 | 1835 | merge2@1.4.1: {} 1836 | 1837 | micromatch@4.0.8: 1838 | dependencies: 1839 | braces: 3.0.3 1840 | picomatch: 2.3.1 1841 | 1842 | mimic-fn@4.0.0: {} 1843 | 1844 | mimic-function@5.0.1: {} 1845 | 1846 | minimatch@3.1.2: 1847 | dependencies: 1848 | brace-expansion: 1.1.12 1849 | 1850 | minimatch@9.0.5: 1851 | dependencies: 1852 | brace-expansion: 2.0.2 1853 | 1854 | ms@2.1.3: {} 1855 | 1856 | natural-compare@1.4.0: {} 1857 | 1858 | node-domexception@1.0.0: {} 1859 | 1860 | node-fetch@3.3.2: 1861 | dependencies: 1862 | data-uri-to-buffer: 4.0.1 1863 | fetch-blob: 3.2.0 1864 | formdata-polyfill: 4.0.10 1865 | 1866 | npm-run-path@5.3.0: 1867 | dependencies: 1868 | path-key: 4.0.0 1869 | 1870 | npm-run-path@6.0.0: 1871 | dependencies: 1872 | path-key: 4.0.0 1873 | unicorn-magic: 0.3.0 1874 | 1875 | onetime@6.0.0: 1876 | dependencies: 1877 | mimic-fn: 4.0.0 1878 | 1879 | onetime@7.0.0: 1880 | dependencies: 1881 | mimic-function: 5.0.1 1882 | 1883 | optionator@0.9.4: 1884 | dependencies: 1885 | deep-is: 0.1.4 1886 | fast-levenshtein: 2.0.6 1887 | levn: 0.4.1 1888 | prelude-ls: 1.2.1 1889 | type-check: 0.4.0 1890 | word-wrap: 1.2.5 1891 | 1892 | p-limit@3.1.0: 1893 | dependencies: 1894 | yocto-queue: 0.1.0 1895 | 1896 | p-locate@5.0.0: 1897 | dependencies: 1898 | p-limit: 3.1.0 1899 | 1900 | package-manager-detector@1.2.0: {} 1901 | 1902 | parent-module@1.0.1: 1903 | dependencies: 1904 | callsites: 3.1.0 1905 | 1906 | parse-ms@4.0.0: {} 1907 | 1908 | path-exists@4.0.0: {} 1909 | 1910 | path-key@3.1.1: {} 1911 | 1912 | path-key@4.0.0: {} 1913 | 1914 | picomatch@2.3.1: {} 1915 | 1916 | picomatch@4.0.2: {} 1917 | 1918 | pidtree@0.6.0: {} 1919 | 1920 | prelude-ls@1.2.1: {} 1921 | 1922 | prettier@3.5.3: {} 1923 | 1924 | pretty-ms@9.2.0: 1925 | dependencies: 1926 | parse-ms: 4.0.0 1927 | 1928 | punycode@2.3.1: {} 1929 | 1930 | queue-microtask@1.2.3: {} 1931 | 1932 | resolve-from@4.0.0: {} 1933 | 1934 | resolve-pkg-maps@1.0.0: {} 1935 | 1936 | restore-cursor@5.1.0: 1937 | dependencies: 1938 | onetime: 7.0.0 1939 | signal-exit: 4.1.0 1940 | 1941 | reusify@1.1.0: {} 1942 | 1943 | rfdc@1.4.1: {} 1944 | 1945 | run-parallel@1.2.0: 1946 | dependencies: 1947 | queue-microtask: 1.2.3 1948 | 1949 | semver@7.7.1: {} 1950 | 1951 | shebang-command@2.0.0: 1952 | dependencies: 1953 | shebang-regex: 3.0.0 1954 | 1955 | shebang-regex@3.0.0: {} 1956 | 1957 | signal-exit@4.1.0: {} 1958 | 1959 | simple-git-hooks@2.12.1: {} 1960 | 1961 | slice-ansi@5.0.0: 1962 | dependencies: 1963 | ansi-styles: 6.2.1 1964 | is-fullwidth-code-point: 4.0.0 1965 | 1966 | slice-ansi@7.1.0: 1967 | dependencies: 1968 | ansi-styles: 6.2.1 1969 | is-fullwidth-code-point: 5.0.0 1970 | 1971 | string-argv@0.3.2: {} 1972 | 1973 | string-width@7.2.0: 1974 | dependencies: 1975 | emoji-regex: 10.4.0 1976 | get-east-asian-width: 1.3.0 1977 | strip-ansi: 7.1.0 1978 | 1979 | strip-ansi@7.1.0: 1980 | dependencies: 1981 | ansi-regex: 6.1.0 1982 | 1983 | strip-final-newline@3.0.0: {} 1984 | 1985 | strip-final-newline@4.0.0: {} 1986 | 1987 | strip-json-comments@3.1.1: {} 1988 | 1989 | supports-color@7.2.0: 1990 | dependencies: 1991 | has-flag: 4.0.0 1992 | 1993 | tapable@2.2.2: {} 1994 | 1995 | tinyexec@1.0.1: {} 1996 | 1997 | to-regex-range@5.0.1: 1998 | dependencies: 1999 | is-number: 7.0.0 2000 | 2001 | ts-api-utils@2.1.0(typescript@5.8.3): 2002 | dependencies: 2003 | typescript: 5.8.3 2004 | 2005 | ts-declaration-location@1.0.7(typescript@5.8.3): 2006 | dependencies: 2007 | picomatch: 4.0.2 2008 | typescript: 5.8.3 2009 | 2010 | tsx@4.19.3: 2011 | dependencies: 2012 | esbuild: 0.25.3 2013 | get-tsconfig: 4.10.0 2014 | optionalDependencies: 2015 | fsevents: 2.3.3 2016 | 2017 | tunnel@0.0.6: {} 2018 | 2019 | type-check@0.4.0: 2020 | dependencies: 2021 | prelude-ls: 1.2.1 2022 | 2023 | typescript-eslint@8.35.1(eslint@9.30.1)(typescript@5.8.3): 2024 | dependencies: 2025 | '@typescript-eslint/eslint-plugin': 8.35.1(@typescript-eslint/parser@8.35.1(eslint@9.30.1)(typescript@5.8.3))(eslint@9.30.1)(typescript@5.8.3) 2026 | '@typescript-eslint/parser': 8.35.1(eslint@9.30.1)(typescript@5.8.3) 2027 | '@typescript-eslint/utils': 8.35.1(eslint@9.30.1)(typescript@5.8.3) 2028 | eslint: 9.30.1 2029 | typescript: 5.8.3 2030 | transitivePeerDependencies: 2031 | - supports-color 2032 | 2033 | typescript@5.8.3: {} 2034 | 2035 | undici-types@6.21.0: {} 2036 | 2037 | undici@5.29.0: 2038 | dependencies: 2039 | '@fastify/busboy': 2.1.1 2040 | 2041 | unicorn-magic@0.3.0: {} 2042 | 2043 | uri-js@4.4.1: 2044 | dependencies: 2045 | punycode: 2.3.1 2046 | 2047 | web-streams-polyfill@3.3.3: {} 2048 | 2049 | which@2.0.2: 2050 | dependencies: 2051 | isexe: 2.0.0 2052 | 2053 | word-wrap@1.2.5: {} 2054 | 2055 | wrap-ansi@9.0.0: 2056 | dependencies: 2057 | ansi-styles: 6.2.1 2058 | string-width: 7.2.0 2059 | strip-ansi: 7.1.0 2060 | 2061 | yaml@2.7.1: {} 2062 | 2063 | yocto-queue@0.1.0: {} 2064 | 2065 | yoctocolors@2.1.1: {} 2066 | --------------------------------------------------------------------------------