diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c71f05f4e..05118d7b2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -121,7 +121,7 @@ jobs: - name: Install dependencies run: npm ci - name: E2E test affected projects - run: npx nx affected -t e2e-test --parallel=1 + run: npx nx affected -t e2e-test --verbose --parallel=1 build: runs-on: ubuntu-latest diff --git a/README.md b/README.md index e899bfa18..7265970cf 100644 --- a/README.md +++ b/README.md @@ -1,89 +1,126 @@ -

Code PushUp CLI

-

Code-Pushup Logo

-

Comprehensive tech quality monitoring

- -

Quantify tech debt — Track incremental improvements — Monitor regressions

+# @code-pushup/models ---- +[![npm](https://img.shields.io/npm/v/%40code-pushup%2Fmodels.svg)](https://www.npmjs.com/package/@code-pushup/models) +[![downloads](https://img.shields.io/npm/dm/%40code-pushup%2Fmodels)](https://npmtrends.com/@code-pushup/models) +[![dependencies](https://img.shields.io/librariesio/release/npm/%40code-pushup/models)](https://www.npmjs.com/package/@code-pushup/models?activeTab=dependencies) -[![version](https://img.shields.io/github/v/release/code-pushup/cli)](https://github.com/code-pushup/cli/releases/latest) -[![release date](https://img.shields.io/github/release-date/code-pushup/cli)](https://github.com/code-pushup/cli/releases) -![NodeJS support](https://img.shields.io/node/v/%40code-pushup%2Fcli) -[![license](https://img.shields.io/github/license/code-pushup/cli)](https://opensource.org/licenses/MIT) -[![commit activity](https://img.shields.io/github/commit-activity/m/code-pushup/cli)](https://github.com/code-pushup/cli/pulse/monthly) -[![CI](https://github.com/code-pushup/cli/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/code-pushup/cli/actions/workflows/ci.yml?query=branch%3Amain) -[![Codecov](https://codecov.io/gh/code-pushup/cli/branch/main/graph/badge.svg?token=Y7V489JZ4A)](https://codecov.io/gh/code-pushup/cli) +**Model definitions and validators** for the [Code PushUp CLI](../cli/README.md). ---- +For a full list of models defined by this package, see the auto-generated [Code PushUp models reference](./docs/models-reference.md). -![Type safety](https://api.staging.code-pushup.dev/badges/code-pushup/cli-workspace/type-safety?apiKey=cp_def67c4efe558a9149061d0c62de893e1689ad793071db332790238446173fef) -![Bug prevention](https://api.staging.code-pushup.dev/badges/code-pushup/cli-workspace/bug-prevention?apiKey=cp_def67c4efe558a9149061d0c62de893e1689ad793071db332790238446173fef) -![Code style](https://api.staging.code-pushup.dev/badges/code-pushup/cli-workspace/code-style?apiKey=cp_def67c4efe558a9149061d0c62de893e1689ad793071db332790238446173fef) -![Code coverage](https://api.staging.code-pushup.dev/badges/code-pushup/cli-workspace/code-coverage?apiKey=cp_def67c4efe558a9149061d0c62de893e1689ad793071db332790238446173fef) -![Security](https://api.staging.code-pushup.dev/badges/code-pushup/cli-workspace/security?apiKey=cp_def67c4efe558a9149061d0c62de893e1689ad793071db332790238446173fef) -![Updates](https://api.staging.code-pushup.dev/badges/code-pushup/cli-workspace/updates?apiKey=cp_def67c4efe558a9149061d0c62de893e1689ad793071db332790238446173fef) -![Documentation](https://api.staging.code-pushup.dev/badges/code-pushup/cli-workspace/docs?apiKey=cp_def67c4efe558a9149061d0c62de893e1689ad793071db332790238446173fef) +## Setup ---- +If you've already installed another `@code-pushup/*` package, then you may have already installed `@code-pushup/models` indirectly. -### 🔌 Code quality tools are like phone chargers. Everyone has a different plug. +If not, you can always install it separately: -_Common problems with keeping track of technical quality:_ +```sh +npm install --save-dev @code-pushup/models +``` -- When **tech debt is invisible**, it's difficult to plan much-needed maintenance efforts 🔧 -- Individual tools measure different metrics, inability to combine them leads to - a **lack of comprehensive overview** 🧑‍🦯 -- Open-source tools typically used for failing checks in CI, which **can't measure incremental improvements** due to arbitrary pass/fail thresholds 🤖 -- Off-the-shelf solutions tend to be opinionated and **hard to customize**, so may not fit your specific needs 🧱 +```sh +yarn add --dev @code-pushup/models +``` -_We want to change that!_ +```sh +pnpm add --save-dev @code-pushup/models +``` ---- +## Usage -## 🔎🔬 Code quality integrations for any tool 📉🔍 +### Importing Everything (Traditional) -| [🚀 Get started](./packages/cli/README.md#getting-started)️ | [🤖 CI automation](https://github.com/marketplace/actions/code-pushup) | -| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Getting started cover image | CI Automation cover | -| | | +Import the type definitions if using TypeScript: -| 📈 [Portal](https://code-pushup.dev#portal)️ | 🔌 [Custom plugins](./packages/cli/docs/custom-plugins.md) | -| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Portal integration cover image | Custom plugins | -| | | +- in `code-pushup.config.ts`: ---- + ```ts + import type { CoreConfig } from '@code-pushup/models'; -### 🔌 Officially supported plugins + export default { + // ... this is type-checked ... + } satisfies CoreConfig; + ``` -| Icon | Name | Description | -| :------------------------------------------------------------: | :-------------------------------------------------- | :--------------------------------------------------------------------------------- | -| | [ESLint](./packages/plugin-eslint#readme) | Static analysis using **ESLint** rules. | -| | [Code Coverage](./packages/plugin-coverage#readme) | Collects code **coverage** from your tests. | -| | [JS Packages](./packages/plugin-js-packages#readme) | Checks 3rd party packages for known **vulnerabilities** and **outdated** versions. | -| | [Lighthouse](./packages/plugin-lighthouse#readme) | Measures web performance and best practices with **Lighthouse**. | -| | [JSDocs](./packages/plugin-jsdocs#readme) | Analyzes how much source code is **documented** using JSDocs comments. | -| | [TypeScript](./packages/plugin-typescript#readme) | Checks for **TypeScript** errors using strict compiler flags. | +- in custom plugin: ---- + ```ts + import type { PluginConfig } from '@code-pushup/models'; -## 📝 How it works + export default function myCustomPlugin(): PluginConfig { + return { + // ... this is type-checked ... + }; + } + ``` -1. **[Configure](./packages/cli/README.md#getting-started)** - Pick from a set of supported packages or include your own ideas. 🧩 + ```ts + import type { AuditOutput } from '@code-pushup/models'; -2. **[Integrate](https://github.com/marketplace/actions/code-pushup)** - Use our integration guide and packages to set up CI integration in minutes. ⏱️ + async function myCustomPluginRunner() { + const audits: AuditOutput[] = await collectAudits(); -3. **[Observe](https://code-pushup.dev#portal)** - Guard regressions and track improvements with every code change. 🔍 + await writeFile(RUNNER_OUTPUT_FILE, JSON.stringify(audits)); + } + ``` -4. **Relax!** - Watch improvements, share reports 📈 +### Importing Specific Modules (Recommended) ---- +For better tree-shaking and smaller bundle sizes, import only what you need from specific modules: -## 💖 Want to support us? +```ts +// Import only audit-related models +import { auditSchema } from '@code-pushup/models/audit'; +import type { AuditOutput } from '@code-pushup/models/audit-output'; +// Import only configuration models +import type { CoreConfig } from '@code-pushup/models/core-config'; +import { persistConfigSchema } from '@code-pushup/models/persist-config'; +// Import only plugin-related models +import type { PluginConfig } from '@code-pushup/models/plugin-config'; +// Import only report-related models +import type { Report } from '@code-pushup/models/report'; +import { reportsDiffSchema } from '@code-pushup/models/reports-diff'; +``` -- Read how to contribute to the codebase. See: [CONTRIBUTING.md](./CONTRIBUTING.md) 🤝 - +### Available Entry Points + +The following modules are available as individual entry points: + +| Module | Import Path | Description | +| --------------- | ------------------------------------- | ----------------------------- | +| Audit | `@code-pushup/models/audit` | Audit definitions and schemas | +| Audit Output | `@code-pushup/models/audit-output` | Audit output models | +| Cache Config | `@code-pushup/models/cache-config` | Cache configuration models | +| Category Config | `@code-pushup/models/category-config` | Category configuration models | +| Commit | `@code-pushup/models/commit` | Commit-related models | +| Configuration | `@code-pushup/models/configuration` | General configuration models | +| Core Config | `@code-pushup/models/core-config` | Core configuration models | +| Group | `@code-pushup/models/group` | Group-related models | +| Issue | `@code-pushup/models/issue` | Issue definitions and schemas | +| Persist Config | `@code-pushup/models/persist-config` | Persist configuration models | +| Plugin Config | `@code-pushup/models/plugin-config` | Plugin configuration models | +| Report | `@code-pushup/models/report` | Report models | +| Reports Diff | `@code-pushup/models/reports-diff` | Report diff models | +| Runner Config | `@code-pushup/models/runner-config` | Runner configuration models | +| Source | `@code-pushup/models/source` | Source location models | +| Table | `@code-pushup/models/table` | Table formatting models | +| Tree | `@code-pushup/models/tree` | Tree structure models | +| Upload Config | `@code-pushup/models/upload-config` | Upload configuration models | + +### Runtime Validation + +If you need runtime validation, use the underlying Zod schemas: + +```ts +// Import from specific modules (recommended) +import { coreConfigSchema } from '@code-pushup/models/core-config'; +import { auditOutputSchema } from '@code-pushup/models/audit-output'; + +// Or import from main entry point +import { coreConfigSchema } from '@code-pushup/models'; + +const json = JSON.parse(readFileSync('code-pushup.config.json')); +const config = coreConfigSchema.parse(json); // throws ZodError if invalid +``` + +> **💡 Pro tip**: Using specific module imports (e.g., `@code-pushup/models/audit`) instead of the main entry point can significantly reduce your bundle size and avoid side effects by only including the code you actually use. diff --git a/eslint.config.js b/eslint.config.js index c25afb9dc..ee0a43d85 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -26,6 +26,7 @@ export default tseslint.config( enforceBuildableLibDependency: true, allow: [ String.raw`^.*/eslint(\.base)?\.config\.[cm]?js$`, + String.raw`^.*/tsdown\.base\.[cm]?js$`, String.raw`^.*/code-pushup\.(config|preset)(\.m?[jt]s)?$`, '^[./]+/tools/.*$', ], @@ -110,6 +111,14 @@ export default tseslint.config( { files: ['**/*.json'], languageOptions: { parser: jsoncParser }, + rules: { + '@nx/dependency-checks': [ + 'error', + { + ignoredDependencies: ['tsdown'], + }, + ], + }, }, { files: ['**/*.ts', '**/*.js'], @@ -138,6 +147,7 @@ export default tseslint.config( ignores: [ '**/*.mock.*', '**/code-pushup.config.ts', + '**/tsdown.config.ts', '**/mocks/fixtures/**', '**/__snapshots__/**', '**/dist', diff --git a/examples/plugins/package.json b/examples/plugins/package.json new file mode 100644 index 000000000..78dc892f9 --- /dev/null +++ b/examples/plugins/package.json @@ -0,0 +1,95 @@ +{ + "name": "examples-plugins", + "version": "0.0.1", + "type": "module", + "main": "./src/index.cjs", + "module": "./src/index.mjs", + "types": "./src/index.d.cts", + "exports": { + ".": { + "import": "./src/index.mjs", + "require": "./src/index.cjs", + "types": "./src/index.d.mts" + }, + "./file-size/src/file-size.plugin": { + "import": "./src/file-size/src/file-size.plugin.mjs", + "require": "./src/file-size/src/file-size.plugin.cjs", + "types": "./src/file-size/src/file-size.plugin.d.mts" + }, + "./lighthouse/mock/fixtures/lhr": { + "import": "./src/lighthouse/mock/fixtures/lhr.mjs", + "require": "./src/lighthouse/mock/fixtures/lhr.cjs", + "types": "./src/lighthouse/mock/fixtures/lhr.d.mts" + }, + "./lighthouse/src": { + "import": "./src/lighthouse/src/index.mjs", + "require": "./src/lighthouse/src/index.cjs", + "types": "./src/lighthouse/src/index.d.mts" + }, + "./lighthouse/src/constants": { + "import": "./src/lighthouse/src/constants.mjs", + "require": "./src/lighthouse/src/constants.cjs", + "types": "./src/lighthouse/src/constants.d.mts" + }, + "./lighthouse/src/lighthouse.plugin": { + "import": "./src/lighthouse/src/lighthouse.plugin.mjs", + "require": "./src/lighthouse/src/lighthouse.plugin.cjs", + "types": "./src/lighthouse/src/lighthouse.plugin.d.mts" + }, + "./lighthouse/src/types": { + "import": "./src/lighthouse/src/types.mjs", + "require": "./src/lighthouse/src/types.cjs", + "types": "./src/lighthouse/src/types.d.mts" + }, + "./lighthouse/src/utils": { + "import": "./src/lighthouse/src/utils.mjs", + "require": "./src/lighthouse/src/utils.cjs", + "types": "./src/lighthouse/src/utils.d.mts" + }, + "./package-json/src": { + "import": "./src/package-json/src/index.mjs", + "require": "./src/package-json/src/index.cjs", + "types": "./src/package-json/src/index.d.mts" + }, + "./package-json/src/constants": { + "import": "./src/package-json/src/constants.mjs", + "require": "./src/package-json/src/constants.cjs", + "types": "./src/package-json/src/constants.d.mts" + }, + "./package-json/src/integration/dependencies.audit": { + "import": "./src/package-json/src/integration/dependencies.audit.mjs", + "require": "./src/package-json/src/integration/dependencies.audit.cjs", + "types": "./src/package-json/src/integration/dependencies.audit.d.mts" + }, + "./package-json/src/integration/license.audit": { + "import": "./src/package-json/src/integration/license.audit.mjs", + "require": "./src/package-json/src/integration/license.audit.cjs", + "types": "./src/package-json/src/integration/license.audit.d.mts" + }, + "./package-json/src/integration/type.audit": { + "import": "./src/package-json/src/integration/type.audit.mjs", + "require": "./src/package-json/src/integration/type.audit.cjs", + "types": "./src/package-json/src/integration/type.audit.d.mts" + }, + "./package-json/src/integration/types": { + "import": "./src/package-json/src/integration/types.mjs", + "require": "./src/package-json/src/integration/types.cjs", + "types": "./src/package-json/src/integration/types.d.mts" + }, + "./package-json/src/integration/utils": { + "import": "./src/package-json/src/integration/utils.mjs", + "require": "./src/package-json/src/integration/utils.cjs", + "types": "./src/package-json/src/integration/utils.d.mts" + }, + "./package-json/src/package-json.plugin": { + "import": "./src/package-json/src/package-json.plugin.mjs", + "require": "./src/package-json/src/package-json.plugin.cjs", + "types": "./src/package-json/src/package-json.plugin.d.mts" + }, + "./package-json/src/scoring": { + "import": "./src/package-json/src/scoring.mjs", + "require": "./src/package-json/src/scoring.cjs", + "types": "./src/package-json/src/scoring.d.mts" + } + } +} diff --git a/examples/plugins/tsdown.config.ts b/examples/plugins/tsdown.config.ts new file mode 100644 index 000000000..d0a57d026 --- /dev/null +++ b/examples/plugins/tsdown.config.ts @@ -0,0 +1,10 @@ +import { defineConfig } from 'tsdown'; +import { baseConfig, getExternalDependencies } from '../../tsdown.base'; + +const __dirname = import.meta.dirname; + +export default defineConfig(async () => ({ + ...baseConfig({ projectRoot: __dirname }), + external: await getExternalDependencies(__dirname), + copy: [], +})); diff --git a/nx.json b/nx.json index 7b41eba43..cb9eb5e83 100644 --- a/nx.json +++ b/nx.json @@ -26,6 +26,7 @@ "!{projectRoot}/tsconfig.@(test|tools).json", "!{workspaceRoot}/**/(*.)coverage/**/*" ], + "tsdownConfigs": ["{projectRoot}/tsdown.config.ts"], "test-vitest-inputs": [ "os", { @@ -78,14 +79,14 @@ "--max-warnings=0", "--no-warn-ignored", "--error-on-unmatched-pattern=false", - "--format=./tools/eslint-formatter-multi/dist/src/index.js" + "--format=./tools/eslint-formatter-multi/dist/src/index.mjs" ], "env": { "ESLINT_FORMATTER_CONFIG": "{\"outputDir\":\"{projectRoot}/.eslint\"}" } } }, - "build": { + "build-old": { "dependsOn": ["^build"], "inputs": ["production", "^production"], "cache": true, @@ -98,6 +99,19 @@ "assets": ["{projectRoot}/*.md"] } }, + "build": { + "dependsOn": ["^build"], + "inputs": ["production", "^production", "tsdownConfigs"], + "cache": true, + "executor": "nx:run-commands", + "options": { + "commands": [ + "node_modules/.bin/tsdown --config {projectRoot}/tsdown.config.ts" + ], + "outputPath": "{projectRoot}/dist" + }, + "outputs": ["{projectRoot}/dist"] + }, "unit-test": { "cache": true, "inputs": ["default", "test-vitest-inputs"], @@ -361,6 +375,10 @@ "filterByTags": ["publishable"] } } + }, + { + "plugin": "./tools/src/ts-down.plugin.mjs", + "exclude": ["nx-plugin"] } ], "nxCloudId": "65d4d862d2adb16a45a4bc7c" diff --git a/package-lock.json b/package-lock.json index b8d79a01d..921f5d339 100644 --- a/package-lock.json +++ b/package-lock.json @@ -104,6 +104,7 @@ "react-dom": "18.3.1", "ts-patch": "^3.3.0", "tsconfig-paths": "^4.2.0", + "tsdown": "^0.15.1", "tsx": "^4.19.0", "type-fest": "^4.26.1", "typescript": "5.7.3", @@ -290,14 +291,14 @@ } }, "node_modules/@babel/generator": { - "version": "7.28.3", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.3.tgz", - "integrity": "sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw==", + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.5.tgz", + "integrity": "sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/parser": "^7.28.3", - "@babel/types": "^7.28.2", + "@babel/parser": "^7.28.5", + "@babel/types": "^7.28.5", "@jridgewell/gen-mapping": "^0.3.12", "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" @@ -639,9 +640,9 @@ } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", - "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", "dev": true, "license": "MIT", "engines": { @@ -687,13 +688,13 @@ } }, "node_modules/@babel/parser": { - "version": "7.28.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.3.tgz", - "integrity": "sha512-7+Ey1mAgYqFAx2h0RuoxcQT5+MlG3GTV0TQrgr7/ZliKsm/MNDxVVutlWaziMq7wJNAz8MTqz55XLpWvva6StA==", + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.5.tgz", + "integrity": "sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.28.2" + "@babel/types": "^7.28.5" }, "bin": { "parser": "bin/babel-parser.js" @@ -2271,14 +2272,14 @@ } }, "node_modules/@babel/types": { - "version": "7.28.2", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.2.tgz", - "integrity": "sha512-ruv7Ae4J5dUYULmeXw1gmb7rYRz57OWCPM57pHojnLq/3Z1CK2lNSLTCVjxVk1F/TZHwOZZrOWi0ur95BbLxNQ==", + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.5.tgz", + "integrity": "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==", "dev": true, "license": "MIT", "dependencies": { "@babel/helper-string-parser": "^7.27.1", - "@babel/helper-validator-identifier": "^7.27.1" + "@babel/helper-validator-identifier": "^7.28.5" }, "engines": { "node": ">=6.9.0" @@ -4356,10 +4357,11 @@ } }, "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", - "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", - "dev": true + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.30", @@ -6733,6 +6735,16 @@ "@octokit/openapi-types": "^20.0.0" } }, + "node_modules/@oxc-project/types": { + "version": "0.95.0", + "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.95.0.tgz", + "integrity": "sha512-vACy7vhpMPhjEJhULNxrdR0D943TkA/MigMpJCHmBHvMXxRStRi/dPtTlfQ3uDwWSzRpT8z+7ImjZVf8JWBocQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/Boshen" + } + }, "node_modules/@paulirish/trace_engine": { "version": "0.0.32", "resolved": "https://registry.npmjs.org/@paulirish/trace_engine/-/trace_engine-0.0.32.tgz", @@ -6898,6 +6910,315 @@ "tslib": "2.8.1" } }, + "node_modules/@quansync/fs": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/@quansync/fs/-/fs-0.1.5.tgz", + "integrity": "sha512-lNS9hL2aS2NZgNW7BBj+6EBl4rOf8l+tQ0eRY6JWCI8jI2kc53gSoqbjojU0OnAWhzoXiOjFyGsHcDGePB3lhA==", + "dev": true, + "license": "MIT", + "dependencies": { + "quansync": "^0.2.11" + }, + "funding": { + "url": "https://github.com/sponsors/sxzz" + } + }, + "node_modules/@rolldown/binding-android-arm64": { + "version": "1.0.0-beta.45", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.0-beta.45.tgz", + "integrity": "sha512-bfgKYhFiXJALeA/riil908+2vlyWGdwa7Ju5S+JgWZYdR4jtiPOGdM6WLfso1dojCh+4ZWeiTwPeV9IKQEX+4g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-darwin-arm64": { + "version": "1.0.0-beta.45", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.0-beta.45.tgz", + "integrity": "sha512-xjCv4CRVsSnnIxTuyH1RDJl5OEQ1c9JYOwfDAHddjJDxCw46ZX9q80+xq7Eok7KC4bRSZudMJllkvOKv0T9SeA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-darwin-x64": { + "version": "1.0.0-beta.45", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.0-beta.45.tgz", + "integrity": "sha512-ddcO9TD3D/CLUa/l8GO8LHzBOaZqWg5ClMy3jICoxwCuoz47h9dtqPsIeTiB6yR501LQTeDsjA4lIFd7u3Ljfw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-freebsd-x64": { + "version": "1.0.0-beta.45", + "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.0-beta.45.tgz", + "integrity": "sha512-MBTWdrzW9w+UMYDUvnEuh0pQvLENkl2Sis15fHTfHVW7ClbGuez+RWopZudIDEGkpZXdeI4CkRXk+vdIIebrmg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-arm-gnueabihf": { + "version": "1.0.0-beta.45", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.0-beta.45.tgz", + "integrity": "sha512-4YgoCFiki1HR6oSg+GxxfzfnVCesQxLF1LEnw9uXS/MpBmuog0EOO2rYfy69rWP4tFZL9IWp6KEfGZLrZ7aUog==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-arm64-gnu": { + "version": "1.0.0-beta.45", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.0-beta.45.tgz", + "integrity": "sha512-LE1gjAwQRrbCOorJJ7LFr10s5vqYf5a00V5Ea9wXcT2+56n5YosJkcp8eQ12FxRBv2YX8dsdQJb+ZTtYJwb6XQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-arm64-musl": { + "version": "1.0.0-beta.45", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.0-beta.45.tgz", + "integrity": "sha512-tdy8ThO/fPp40B81v0YK3QC+KODOmzJzSUOO37DinQxzlTJ026gqUSOM8tzlVixRbQJltgVDCTYF8HNPRErQTA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-x64-gnu": { + "version": "1.0.0-beta.45", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.0-beta.45.tgz", + "integrity": "sha512-lS082ROBWdmOyVY/0YB3JmsiClaWoxvC+dA8/rbhyB9VLkvVEaihLEOr4CYmrMse151C4+S6hCw6oa1iewox7g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-x64-musl": { + "version": "1.0.0-beta.45", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.0-beta.45.tgz", + "integrity": "sha512-Hi73aYY0cBkr1/SvNQqH8Cd+rSV6S9RB5izCv0ySBcRnd/Wfn5plguUoGYwBnhHgFbh6cPw9m2dUVBR6BG1gxA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-openharmony-arm64": { + "version": "1.0.0-beta.45", + "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.0-beta.45.tgz", + "integrity": "sha512-fljEqbO7RHHogNDxYtTzr+GNjlfOx21RUyGmF+NrkebZ8emYYiIqzPxsaMZuRx0rgZmVmliOzEp86/CQFDKhJQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-wasm32-wasi": { + "version": "1.0.0-beta.45", + "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.0-beta.45.tgz", + "integrity": "sha512-ZJDB7lkuZE9XUnWQSYrBObZxczut+8FZ5pdanm8nNS1DAo8zsrPuvGwn+U3fwU98WaiFsNrA4XHngesCGr8tEQ==", + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@napi-rs/wasm-runtime": "^1.0.7" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@rolldown/binding-wasm32-wasi/node_modules/@emnapi/core": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.7.0.tgz", + "integrity": "sha512-pJdKGq/1iquWYtv1RRSljZklxHCOCAJFJrImO5ZLKPJVJlVUcs8yFwNQlqS0Lo8xT1VAXXTCZocF9n26FWEKsw==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.1.0", + "tslib": "^2.4.0" + } + }, + "node_modules/@rolldown/binding-wasm32-wasi/node_modules/@emnapi/runtime": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.7.0.tgz", + "integrity": "sha512-oAYoQnCYaQZKVS53Fq23ceWMRxq5EhQsE0x0RdQ55jT7wagMu5k+fS39v1fiSLrtrLQlXwVINenqhLMtTrV/1Q==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@rolldown/binding-wasm32-wasi/node_modules/@emnapi/wasi-threads": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.1.0.tgz", + "integrity": "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@rolldown/binding-wasm32-wasi/node_modules/@napi-rs/wasm-runtime": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.0.7.tgz", + "integrity": "sha512-SeDnOO0Tk7Okiq6DbXmmBODgOAb9dp9gjlphokTUxmt8U3liIP1ZsozBahH69j/RJv+Rfs6IwUKHTgQYJ/HBAw==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "^1.5.0", + "@emnapi/runtime": "^1.5.0", + "@tybys/wasm-util": "^0.10.1" + } + }, + "node_modules/@rolldown/binding-wasm32-wasi/node_modules/@tybys/wasm-util": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz", + "integrity": "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@rolldown/binding-win32-arm64-msvc": { + "version": "1.0.0-beta.45", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.0-beta.45.tgz", + "integrity": "sha512-zyzAjItHPUmxg6Z8SyRhLdXlJn3/D9KL5b9mObUrBHhWS/GwRH4665xCiFqeuktAhhWutqfc+rOV2LjK4VYQGQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-win32-ia32-msvc": { + "version": "1.0.0-beta.45", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-1.0.0-beta.45.tgz", + "integrity": "sha512-wODcGzlfxqS6D7BR0srkJk3drPwXYLu7jPHN27ce2c4PUnVVmJnp9mJzUQGT4LpmHmmVdMZ+P6hKvyTGBzc1CA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-win32-x64-msvc": { + "version": "1.0.0-beta.45", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.0-beta.45.tgz", + "integrity": "sha512-wiU40G1nQo9rtfvF9jLbl79lUgjfaD/LTyUEw2Wg/gdF5OhjzpKMVugZQngO+RNdwYaNj+Fs+kWBWfp4VXPMHA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, "node_modules/@rolldown/pluginutils": { "version": "1.0.0-beta.32", "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.32.tgz", @@ -11646,6 +11967,30 @@ "node": "*" } }, + "node_modules/ast-kit": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ast-kit/-/ast-kit-2.2.0.tgz", + "integrity": "sha512-m1Q/RaVOnTp9JxPX+F+Zn7IcLYMzM8kZofDImfsKZd8MbR+ikdOzTeztStWqfrqIxZnYWryyI9ePm3NGjnZgGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.28.5", + "pathe": "^2.0.3" + }, + "engines": { + "node": ">=20.19.0" + }, + "funding": { + "url": "https://github.com/sponsors/sxzz" + } + }, + "node_modules/ast-kit/node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "dev": true, + "license": "MIT" + }, "node_modules/ast-types": { "version": "0.13.4", "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz", @@ -12343,6 +12688,16 @@ "node": ">=6" } }, + "node_modules/birpc": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/birpc/-/birpc-2.8.0.tgz", + "integrity": "sha512-Bz2a4qD/5GRhiHSwj30c/8kC8QGj12nNDwz3D4ErQ4Xhy35dsSDvF+RA/tWpjyU0pdGtSDiEk6B5fBGE1qNVhw==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, "node_modules/bl": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", @@ -12827,6 +13182,22 @@ "node": "*" } }, + "node_modules/chokidar": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "readdirp": "^4.0.1" + }, + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, "node_modules/chrome-launcher": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/chrome-launcher/-/chrome-launcher-1.1.2.tgz", @@ -14781,6 +15152,13 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/defu": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.4.tgz", + "integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==", + "dev": true, + "license": "MIT" + }, "node_modules/degenerator": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-5.0.1.tgz", @@ -14895,6 +15273,16 @@ "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1312386.tgz", "integrity": "sha512-DPnhUXvmvKT2dFA/j7B+riVLUt9Q6RKJlcppojL5CoRywJJKLDYnRlw0gTFKfgDPHP5E04UoB71SxoJlVZy8FA==" }, + "node_modules/diff": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-8.0.2.tgz", + "integrity": "sha512-sSuxWU5j5SR9QQji/o2qMvqRNYRDOcBTgsJ/DeCf4iSN4gW+gNMXM7wFIP+fdXZxoNiAnHUTGjCr+TSWXdRDKg==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, "node_modules/diff-sequences": { "version": "29.6.3", "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", @@ -15024,6 +15412,27 @@ "url": "https://dotenvx.com" } }, + "node_modules/dts-resolver": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/dts-resolver/-/dts-resolver-2.1.3.tgz", + "integrity": "sha512-bihc7jPC90VrosXNzK0LTE2cuLP6jr0Ro8jk+kMugHReJVLIpHz/xadeq3MhuwyO4TD4OA3L1Q8pBBFRc08Tsw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20.19.0" + }, + "funding": { + "url": "https://github.com/sponsors/sxzz" + }, + "peerDependencies": { + "oxc-resolver": ">=11.0.0" + }, + "peerDependenciesMeta": { + "oxc-resolver": { + "optional": true + } + } + }, "node_modules/dunder-proto": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.0.tgz", @@ -15150,6 +15559,16 @@ "node": ">= 4" } }, + "node_modules/empathic": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/empathic/-/empathic-2.0.0.tgz", + "integrity": "sha512-i6UzDscO/XfAcNYD75CfICkmfLedpyPDdozrLMmQc5ORaQcdMoc21OnlEylMIqI7U8eniKrPMxxtj8k0vhmJhA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + } + }, "node_modules/encodeurl": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", @@ -17936,10 +18355,11 @@ } }, "node_modules/get-tsconfig": { - "version": "4.8.1", - "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.8.1.tgz", - "integrity": "sha512-k9PN+cFBmaLWtVz29SkUoqU5O0slLuHJXt/2P+tMVFT+phsSGXGkp9t3rQIqdz0e+06EHNGs3oM6ZX1s2zHxRg==", + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.13.0.tgz", + "integrity": "sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ==", "dev": true, + "license": "MIT", "dependencies": { "resolve-pkg-maps": "^1.0.0" }, @@ -18420,6 +18840,13 @@ "node": ">=0.10.0" } }, + "node_modules/hookable": { + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/hookable/-/hookable-5.5.3.tgz", + "integrity": "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==", + "dev": true, + "license": "MIT" + }, "node_modules/hosted-git-info": { "version": "7.0.2", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.2.tgz", @@ -23063,12 +23490,13 @@ } }, "node_modules/magic-string": { - "version": "0.30.11", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.11.tgz", - "integrity": "sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A==", + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", "dev": true, + "license": "MIT", "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0" + "@jridgewell/sourcemap-codec": "^1.5.5" } }, "node_modules/magicast": { @@ -26115,6 +26543,23 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/quansync": { + "version": "0.2.11", + "resolved": "https://registry.npmjs.org/quansync/-/quansync-0.2.11.tgz", + "integrity": "sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/antfu" + }, + { + "type": "individual", + "url": "https://github.com/sponsors/sxzz" + } + ], + "license": "MIT" + }, "node_modules/query-registry": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/query-registry/-/query-registry-3.0.1.tgz", @@ -26449,6 +26894,20 @@ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true }, + "node_modules/readdirp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14.18.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, "node_modules/real-require": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/real-require/-/real-require-0.2.0.tgz", @@ -26783,6 +27242,116 @@ "node": ">=10.0.0" } }, + "node_modules/rolldown": { + "version": "1.0.0-beta.45", + "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.0-beta.45.tgz", + "integrity": "sha512-iMmuD72XXLf26Tqrv1cryNYLX6NNPLhZ3AmNkSf8+xda0H+yijjGJ+wVT9UdBUHOpKzq9RjKtQKRCWoEKQQBZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@oxc-project/types": "=0.95.0", + "@rolldown/pluginutils": "1.0.0-beta.45" + }, + "bin": { + "rolldown": "bin/cli.mjs" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "optionalDependencies": { + "@rolldown/binding-android-arm64": "1.0.0-beta.45", + "@rolldown/binding-darwin-arm64": "1.0.0-beta.45", + "@rolldown/binding-darwin-x64": "1.0.0-beta.45", + "@rolldown/binding-freebsd-x64": "1.0.0-beta.45", + "@rolldown/binding-linux-arm-gnueabihf": "1.0.0-beta.45", + "@rolldown/binding-linux-arm64-gnu": "1.0.0-beta.45", + "@rolldown/binding-linux-arm64-musl": "1.0.0-beta.45", + "@rolldown/binding-linux-x64-gnu": "1.0.0-beta.45", + "@rolldown/binding-linux-x64-musl": "1.0.0-beta.45", + "@rolldown/binding-openharmony-arm64": "1.0.0-beta.45", + "@rolldown/binding-wasm32-wasi": "1.0.0-beta.45", + "@rolldown/binding-win32-arm64-msvc": "1.0.0-beta.45", + "@rolldown/binding-win32-ia32-msvc": "1.0.0-beta.45", + "@rolldown/binding-win32-x64-msvc": "1.0.0-beta.45" + } + }, + "node_modules/rolldown-plugin-dts": { + "version": "0.17.4", + "resolved": "https://registry.npmjs.org/rolldown-plugin-dts/-/rolldown-plugin-dts-0.17.4.tgz", + "integrity": "sha512-eWno7CR/Da2jA+5mTHxeMx78p4AmoUocEKDQT8XKwhq9Oroyf67ZfBOE82d4EvDjktiQTePpKdIKc69pND88Og==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/generator": "^7.28.5", + "@babel/parser": "^7.28.5", + "@babel/types": "^7.28.5", + "ast-kit": "^2.2.0", + "birpc": "^2.7.0", + "debug": "^4.4.3", + "dts-resolver": "^2.1.2", + "get-tsconfig": "^4.13.0", + "magic-string": "^0.30.21" + }, + "engines": { + "node": ">=20.18.0" + }, + "funding": { + "url": "https://github.com/sponsors/sxzz" + }, + "peerDependencies": { + "@ts-macro/tsc": "^0.3.6", + "@typescript/native-preview": ">=7.0.0-dev.20250601.1", + "rolldown": "^1.0.0-beta.44", + "typescript": "^5.0.0", + "vue-tsc": "~3.1.0" + }, + "peerDependenciesMeta": { + "@ts-macro/tsc": { + "optional": true + }, + "@typescript/native-preview": { + "optional": true + }, + "typescript": { + "optional": true + }, + "vue-tsc": { + "optional": true + } + } + }, + "node_modules/rolldown-plugin-dts/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/rolldown-plugin-dts/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/rolldown/node_modules/@rolldown/pluginutils": { + "version": "1.0.0-beta.45", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.45.tgz", + "integrity": "sha512-Le9ulGCrD8ggInzWw/k2J8QcbPz7eGIOWqfJ2L+1R0Opm7n6J37s2hiDWlh6LJN0Lk9L5sUzMvRHKW7UxBZsQA==", + "dev": true, + "license": "MIT" + }, "node_modules/rollup": { "version": "4.48.0", "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.48.0.tgz", @@ -28819,13 +29388,13 @@ "dev": true }, "node_modules/tinyglobby": { - "version": "0.2.14", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.14.tgz", - "integrity": "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==", + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", "license": "MIT", "dependencies": { - "fdir": "^6.4.4", - "picomatch": "^4.0.2" + "fdir": "^6.5.0", + "picomatch": "^4.0.3" }, "engines": { "node": ">=12.0.0" @@ -29236,6 +29805,124 @@ "node": ">=4" } }, + "node_modules/tsdown": { + "version": "0.15.12", + "resolved": "https://registry.npmjs.org/tsdown/-/tsdown-0.15.12.tgz", + "integrity": "sha512-c8VLlQm8/lFrOAg5VMVeN4NAbejZyVQkzd+ErjuaQgJFI/9MhR9ivr0H/CM7UlOF1+ELlF6YaI7sU/4itgGQ8w==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansis": "^4.2.0", + "cac": "^6.7.14", + "chokidar": "^4.0.3", + "debug": "^4.4.3", + "diff": "^8.0.2", + "empathic": "^2.0.0", + "hookable": "^5.5.3", + "rolldown": "1.0.0-beta.45", + "rolldown-plugin-dts": "^0.17.2", + "semver": "^7.7.3", + "tinyexec": "^1.0.1", + "tinyglobby": "^0.2.15", + "tree-kill": "^1.2.2", + "unconfig": "^7.3.3" + }, + "bin": { + "tsdown": "dist/run.mjs" + }, + "engines": { + "node": ">=20.19.0" + }, + "funding": { + "url": "https://github.com/sponsors/sxzz" + }, + "peerDependencies": { + "@arethetypeswrong/core": "^0.18.1", + "publint": "^0.3.0", + "typescript": "^5.0.0", + "unplugin-lightningcss": "^0.4.0", + "unplugin-unused": "^0.5.0", + "unrun": "^0.2.1" + }, + "peerDependenciesMeta": { + "@arethetypeswrong/core": { + "optional": true + }, + "publint": { + "optional": true + }, + "typescript": { + "optional": true + }, + "unplugin-lightningcss": { + "optional": true + }, + "unplugin-unused": { + "optional": true + }, + "unrun": { + "optional": true + } + } + }, + "node_modules/tsdown/node_modules/ansis": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/ansis/-/ansis-4.2.0.tgz", + "integrity": "sha512-HqZ5rWlFjGiV0tDm3UxxgNRqsOTniqoKZu0pIAfh7TZQMGuZK+hH0drySty0si0QXj1ieop4+SkSfPZBPPkHig==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + } + }, + "node_modules/tsdown/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/tsdown/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/tsdown/node_modules/semver": { + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/tsdown/node_modules/tinyexec": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.2.tgz", + "integrity": "sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, "node_modules/tslib": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", @@ -29657,6 +30344,47 @@ "through": "^2.3.8" } }, + "node_modules/unconfig": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/unconfig/-/unconfig-7.4.0.tgz", + "integrity": "sha512-KM0SrvIvwQXJnbiSzur1Y+5jHSLVPhS31H5qzgjDQxGqS3PWrH6X7TxYX/JTuTlItarHkZ9ePK9t01Q6wu1c4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@quansync/fs": "^0.1.5", + "defu": "^6.1.4", + "jiti": "^2.6.1", + "quansync": "^0.2.11", + "unconfig-core": "7.4.0" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/unconfig-core": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/unconfig-core/-/unconfig-core-7.4.0.tgz", + "integrity": "sha512-3ew7rvES5x2LCZ/QRKV3nQQpq7eFYuszQuvZrhTHxDPKc34QFjRXI17XGiZI+WQTVIXKYeBti4v3LS39NWmhmg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@quansync/fs": "^0.1.5", + "quansync": "^0.2.11" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/unconfig/node_modules/jiti": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz", + "integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==", + "dev": true, + "license": "MIT", + "bin": { + "jiti": "lib/jiti-cli.mjs" + } + }, "node_modules/undici": { "version": "6.21.3", "resolved": "https://registry.npmjs.org/undici/-/undici-6.21.3.tgz", diff --git a/package.json b/package.json index a5fec600c..661420015 100644 --- a/package.json +++ b/package.json @@ -114,6 +114,7 @@ "react-dom": "18.3.1", "ts-patch": "^3.3.0", "tsconfig-paths": "^4.2.0", + "tsdown": "^0.15.1", "tsx": "^4.19.0", "type-fest": "^4.26.1", "typescript": "5.7.3", @@ -164,5 +165,35 @@ "commitizen": { "path": "@commitlint/cz-commitlint" } + }, + "main": "./packages/plugin-typescript/dist/src/index.cjs", + "module": "./packages/plugin-typescript/dist/src/index.mjs", + "types": "./packages/plugin-typescript/dist/src/index.d.cts", + "exports": { + "./lib/extend/jest-extended.matcher": { + "import": "./testing/test-setup/dist/src/lib/extend/jest-extended.matcher.mjs", + "require": "./testing/test-setup/dist/src/lib/extend/jest-extended.matcher.cjs" + }, + "./lib/extend/markdown-table.matcher": { + "import": "./testing/test-setup/dist/src/lib/extend/markdown-table.matcher.mjs", + "require": "./testing/test-setup/dist/src/lib/extend/markdown-table.matcher.cjs" + }, + "./lib/extend/path.matcher": { + "import": "./testing/test-setup/dist/src/lib/extend/path.matcher.mjs", + "require": "./testing/test-setup/dist/src/lib/extend/path.matcher.cjs" + }, + "./lib/extend/ui-logger.matcher": { + "import": "./testing/test-setup/dist/src/lib/extend/ui-logger.matcher.mjs", + "require": "./testing/test-setup/dist/src/lib/extend/ui-logger.matcher.cjs" + }, + "./lib/extend/ui-logger.matcher.utils": { + "import": "./testing/test-setup/dist/src/lib/extend/ui-logger.matcher.utils.mjs", + "require": "./testing/test-setup/dist/src/lib/extend/ui-logger.matcher.utils.cjs" + }, + "./lib/reset.mocks": { + "import": "./testing/test-setup/dist/src/lib/reset.mocks.mjs", + "require": "./testing/test-setup/dist/src/lib/reset.mocks.cjs" + }, + "./package.json": "./package.json" } } diff --git a/packages/ci/eslint.config.js b/packages/ci/eslint.config.js index 13888c2a8..3270b7608 100644 --- a/packages/ci/eslint.config.js +++ b/packages/ci/eslint.config.js @@ -17,7 +17,12 @@ export default tseslint.config( rules: { '@nx/dependency-checks': [ 'error', - { ignoredDependencies: ['type-fest'] }, // only for internal typings + { + ignoredDependencies: [ + 'type-fest', // only for internal typings + 'tsdown', + ], + }, ], }, }, diff --git a/packages/ci/tsdown.config.ts b/packages/ci/tsdown.config.ts new file mode 100644 index 000000000..d8c536f13 --- /dev/null +++ b/packages/ci/tsdown.config.ts @@ -0,0 +1,9 @@ +import { defineConfig } from 'tsdown'; +import { baseConfig, getExternalDependencies } from '../../tsdown.base'; + +const __dirname = import.meta.dirname; + +export default defineConfig(async () => ({ + ...baseConfig({ projectRoot: __dirname }), + external: await getExternalDependencies(__dirname), +})); diff --git a/packages/cli/src/index.ts b/packages/cli/src/index.ts index e55c1b364..8bd934cd5 100755 --- a/packages/cli/src/index.ts +++ b/packages/cli/src/index.ts @@ -6,8 +6,11 @@ import { cli } from './lib/cli.js'; import './lib/polyfills.js'; // bootstrap Yargs, parse arguments and execute command -await cli(hideBin(process.argv)).argv; +// eslint-disable-next-line unicorn/prefer-top-level-await +(async () => { + await cli(hideBin(process.argv)).argv; -// we need to explicitly exit with successful code otherwise we risk hanging process in certain situations -// eslint-disable-next-line n/no-process-exit -process.exit(0); + // we need to explicitly exit with successful code otherwise we risk hanging process in certain situations + // eslint-disable-next-line n/no-process-exit + process.exit(0); +})(); diff --git a/packages/cli/tsdown.config.ts b/packages/cli/tsdown.config.ts new file mode 100644 index 000000000..d8c536f13 --- /dev/null +++ b/packages/cli/tsdown.config.ts @@ -0,0 +1,9 @@ +import { defineConfig } from 'tsdown'; +import { baseConfig, getExternalDependencies } from '../../tsdown.base'; + +const __dirname = import.meta.dirname; + +export default defineConfig(async () => ({ + ...baseConfig({ projectRoot: __dirname }), + external: await getExternalDependencies(__dirname), +})); diff --git a/packages/core/tsdown.config.ts b/packages/core/tsdown.config.ts new file mode 100644 index 000000000..d8c536f13 --- /dev/null +++ b/packages/core/tsdown.config.ts @@ -0,0 +1,9 @@ +import { defineConfig } from 'tsdown'; +import { baseConfig, getExternalDependencies } from '../../tsdown.base'; + +const __dirname = import.meta.dirname; + +export default defineConfig(async () => ({ + ...baseConfig({ projectRoot: __dirname }), + external: await getExternalDependencies(__dirname), +})); diff --git a/packages/create-cli/eslint.config.js b/packages/create-cli/eslint.config.js index 22fda2e40..14410a0d8 100644 --- a/packages/create-cli/eslint.config.js +++ b/packages/create-cli/eslint.config.js @@ -17,7 +17,12 @@ export default tseslint.config( rules: { '@nx/dependency-checks': [ 'error', - { ignoredDependencies: ['@code-pushup/nx-plugin'] }, // nx-plugin is run via CLI + { + ignoredDependencies: [ + '@code-pushup/nx-plugin', // nx-plugin is run via CLI + 'tsdown', + ], + }, ], }, }, diff --git a/packages/create-cli/src/index.ts b/packages/create-cli/src/index.ts index 221a00a2a..ecbb0e510 100755 --- a/packages/create-cli/src/index.ts +++ b/packages/create-cli/src/index.ts @@ -1,4 +1,7 @@ #! /usr/bin/env node import { initCodePushup } from './lib/init.js'; -await initCodePushup(); +// eslint-disable-next-line unicorn/prefer-top-level-await +(async () => { + await initCodePushup(); +})(); diff --git a/packages/create-cli/tsdown.config.ts b/packages/create-cli/tsdown.config.ts new file mode 100644 index 000000000..d8c536f13 --- /dev/null +++ b/packages/create-cli/tsdown.config.ts @@ -0,0 +1,9 @@ +import { defineConfig } from 'tsdown'; +import { baseConfig, getExternalDependencies } from '../../tsdown.base'; + +const __dirname = import.meta.dirname; + +export default defineConfig(async () => ({ + ...baseConfig({ projectRoot: __dirname }), + external: await getExternalDependencies(__dirname), +})); diff --git a/packages/models/transformers/tsdown.config.ts b/packages/models/transformers/tsdown.config.ts new file mode 100644 index 000000000..6d3a52b4f --- /dev/null +++ b/packages/models/transformers/tsdown.config.ts @@ -0,0 +1,10 @@ +import { defineConfig } from 'tsdown'; +import { baseConfig, getExternalDependencies } from '../../../tsdown.base'; + +const __dirname = import.meta.dirname; + +export default defineConfig(async () => ({ + ...baseConfig({ projectRoot: __dirname }), + external: await getExternalDependencies(__dirname), + copy: [], +})); diff --git a/packages/models/tsconfig.lib.json b/packages/models/tsconfig.lib.json index 2c92983e0..60df65b5d 100644 --- a/packages/models/tsconfig.lib.json +++ b/packages/models/tsconfig.lib.json @@ -16,6 +16,7 @@ "vitest.unit.config.ts", "vitest.int.config.ts", "code-pushup.config.ts", + "tsdown.config.ts", "zod2md.config.ts", "src/**/*.test.ts", "src/**/*.mock.ts", diff --git a/packages/models/tsdown.config.ts b/packages/models/tsdown.config.ts new file mode 100644 index 000000000..003de7e15 --- /dev/null +++ b/packages/models/tsdown.config.ts @@ -0,0 +1,19 @@ +import { defineConfig } from 'tsdown'; +import { baseConfig, getExternalDependencies } from '../../tsdown.base'; + +const __dirname = import.meta.dirname; + +export default defineConfig(async () => ({ + ...baseConfig({ projectRoot: __dirname }), + external: await getExternalDependencies(__dirname), + copy: [ + { + from: `${__dirname}/package.json`, + to: `${__dirname}/dist/package.json`, + }, + { + from: `${__dirname}/README.md`, + to: `${__dirname}/dist/README.md`, + }, + ], +})); diff --git a/packages/nx-plugin/tsdown.config.ts b/packages/nx-plugin/tsdown.config.ts new file mode 100644 index 000000000..87ee494fd --- /dev/null +++ b/packages/nx-plugin/tsdown.config.ts @@ -0,0 +1,75 @@ +import { copyFile, readFile, writeFile } from 'node:fs/promises'; +import { join } from 'node:path'; +import { defineConfig } from 'tsdown'; +import { baseConfig, getExternalDependencies } from '../../tsdown.base'; + +const __dirname = import.meta.dirname; + +export default defineConfig(async () => { + const base = baseConfig({ projectRoot: __dirname }); + + // Remove generators.json and executors.json from copy array + // We'll handle them in onSuccess to update the .cjs references + const copyWithoutJsonFiles = ((base as any).copy || []).filter( + (item: any) => + !item.to.endsWith('/generators.json') && + !item.to.endsWith('/executors.json'), + ); + + return { + ...base, + format: ['cjs'], // NX supports only commonjs + external: await getExternalDependencies(__dirname), + copy: copyWithoutJsonFiles, + async onSuccess() { + // Call base onSuccess first + const baseOnSuccess = (base as any).onSuccess; + if (typeof baseOnSuccess === 'function') { + await baseOnSuccess(); + } + + // Copy and update generators.json + const generatorsJsonPath = join(__dirname, 'dist', 'generators.json'); + await copyFile(join(__dirname, 'generators.json'), generatorsJsonPath); + + const generatorsJson = JSON.parse( + await readFile(generatorsJsonPath, 'utf8'), + ); + + for (const generator of Object.values(generatorsJson.generators)) { + const gen = generator as { factory: string }; + if (gen.factory && !gen.factory.endsWith('.cjs')) { + gen.factory = gen.factory.replace(/\.js$/, '') + '.cjs'; + } + } + + await writeFile( + generatorsJsonPath, + JSON.stringify(generatorsJson, null, 2) + '\n', + 'utf8', + ); + + // Copy and update executors.json + const executorsJsonPath = join(__dirname, 'dist', 'executors.json'); + await copyFile(join(__dirname, 'executors.json'), executorsJsonPath); + + const executorsJson = JSON.parse( + await readFile(executorsJsonPath, 'utf8'), + ); + + for (const executor of Object.values(executorsJson.executors)) { + const exec = executor as { implementation: string }; + if (exec.implementation && !exec.implementation.endsWith('.cjs')) { + exec.implementation = + exec.implementation.replace(/\.js$/, '') + '.cjs'; + } + } + + await writeFile( + executorsJsonPath, + JSON.stringify(executorsJson, null, 2) + '\n', + 'utf8', + ); + }, + }; +}); diff --git a/packages/plugin-coverage/src/bin.ts b/packages/plugin-coverage/src/bin.ts index fc625dd73..b05f672f0 100644 --- a/packages/plugin-coverage/src/bin.ts +++ b/packages/plugin-coverage/src/bin.ts @@ -4,4 +4,7 @@ import { executeRunner } from './lib/runner/index.js'; const { runnerConfigPath, runnerOutputPath } = Parser(process.argv); -await executeRunner({ runnerConfigPath, runnerOutputPath }); +// eslint-disable-next-line unicorn/prefer-top-level-await +(async () => { + await executeRunner({ runnerConfigPath, runnerOutputPath }); +})(); diff --git a/packages/plugin-coverage/src/lib/coverage-plugin.ts b/packages/plugin-coverage/src/lib/coverage-plugin.ts index 93a94b4c6..2b8e235fe 100644 --- a/packages/plugin-coverage/src/lib/coverage-plugin.ts +++ b/packages/plugin-coverage/src/lib/coverage-plugin.ts @@ -63,7 +63,7 @@ export async function coveragePlugin( const runnerScriptPath = path.join( fileURLToPath(path.dirname(import.meta.url)), '..', - 'bin.js', + 'bin.mjs', ); const packageJson = createRequire(import.meta.url)( diff --git a/packages/plugin-coverage/tsdown.config.ts b/packages/plugin-coverage/tsdown.config.ts new file mode 100644 index 000000000..d8c536f13 --- /dev/null +++ b/packages/plugin-coverage/tsdown.config.ts @@ -0,0 +1,9 @@ +import { defineConfig } from 'tsdown'; +import { baseConfig, getExternalDependencies } from '../../tsdown.base'; + +const __dirname = import.meta.dirname; + +export default defineConfig(async () => ({ + ...baseConfig({ projectRoot: __dirname }), + external: await getExternalDependencies(__dirname), +})); diff --git a/packages/plugin-eslint/tsdown.config.ts b/packages/plugin-eslint/tsdown.config.ts new file mode 100644 index 000000000..d8c536f13 --- /dev/null +++ b/packages/plugin-eslint/tsdown.config.ts @@ -0,0 +1,9 @@ +import { defineConfig } from 'tsdown'; +import { baseConfig, getExternalDependencies } from '../../tsdown.base'; + +const __dirname = import.meta.dirname; + +export default defineConfig(async () => ({ + ...baseConfig({ projectRoot: __dirname }), + external: await getExternalDependencies(__dirname), +})); diff --git a/packages/plugin-js-packages/src/bin.ts b/packages/plugin-js-packages/src/bin.ts index fc625dd73..b05f672f0 100644 --- a/packages/plugin-js-packages/src/bin.ts +++ b/packages/plugin-js-packages/src/bin.ts @@ -4,4 +4,7 @@ import { executeRunner } from './lib/runner/index.js'; const { runnerConfigPath, runnerOutputPath } = Parser(process.argv); -await executeRunner({ runnerConfigPath, runnerOutputPath }); +// eslint-disable-next-line unicorn/prefer-top-level-await +(async () => { + await executeRunner({ runnerConfigPath, runnerOutputPath }); +})(); diff --git a/packages/plugin-js-packages/src/lib/js-packages-plugin.ts b/packages/plugin-js-packages/src/lib/js-packages-plugin.ts index 8fe2491cd..c851446a4 100644 --- a/packages/plugin-js-packages/src/lib/js-packages-plugin.ts +++ b/packages/plugin-js-packages/src/lib/js-packages-plugin.ts @@ -45,7 +45,7 @@ export async function jsPackagesPlugin( const runnerScriptPath = path.join( fileURLToPath(path.dirname(import.meta.url)), '..', - 'bin.js', + 'bin.mjs', ); const packageJson = createRequire(import.meta.url)( diff --git a/packages/plugin-js-packages/tsdown.config.ts b/packages/plugin-js-packages/tsdown.config.ts new file mode 100644 index 000000000..d8c536f13 --- /dev/null +++ b/packages/plugin-js-packages/tsdown.config.ts @@ -0,0 +1,9 @@ +import { defineConfig } from 'tsdown'; +import { baseConfig, getExternalDependencies } from '../../tsdown.base'; + +const __dirname = import.meta.dirname; + +export default defineConfig(async () => ({ + ...baseConfig({ projectRoot: __dirname }), + external: await getExternalDependencies(__dirname), +})); diff --git a/packages/plugin-jsdocs/tsdown.config.ts b/packages/plugin-jsdocs/tsdown.config.ts new file mode 100644 index 000000000..d8c536f13 --- /dev/null +++ b/packages/plugin-jsdocs/tsdown.config.ts @@ -0,0 +1,9 @@ +import { defineConfig } from 'tsdown'; +import { baseConfig, getExternalDependencies } from '../../tsdown.base'; + +const __dirname = import.meta.dirname; + +export default defineConfig(async () => ({ + ...baseConfig({ projectRoot: __dirname }), + external: await getExternalDependencies(__dirname), +})); diff --git a/packages/plugin-lighthouse/src/lib/runner/constants.ts b/packages/plugin-lighthouse/src/lib/runner/constants.ts index e57a7ef55..9af6e6ea2 100644 --- a/packages/plugin-lighthouse/src/lib/runner/constants.ts +++ b/packages/plugin-lighthouse/src/lib/runner/constants.ts @@ -11,12 +11,12 @@ import { DEFAULT_CHROME_FLAGS, LIGHTHOUSE_OUTPUT_PATH } from '../constants.js'; const { audits, categories } = defaultConfig; -// internal intermediate variable to derive the relevant audits +export const PLUGIN_SLUG = 'lighthouse'; + const allRawLighthouseAudits = await Promise.all( (audits ?? []).map(loadLighthouseAudit), ); -export const PLUGIN_SLUG = 'lighthouse'; export const LIGHTHOUSE_NAVIGATION_AUDITS: Audit[] = allRawLighthouseAudits // This plugin only supports the "navigation" mode of Lighthouse in the current implementation // If we don't exclude other audits we throw in the plugin output validation as some of the provided audits are not included in `lighthouse-report.json` @@ -35,6 +35,7 @@ export const LIGHTHOUSE_NAVIGATION_AUDITS: Audit[] = allRawLighthouseAudits const navigationAuditSlugs = new Set( LIGHTHOUSE_NAVIGATION_AUDITS.map(({ slug }) => slug), ); + export const LIGHTHOUSE_GROUPS: Group[] = Object.entries(categories ?? {}).map( ([id, category]) => ({ slug: id, diff --git a/packages/plugin-lighthouse/tsdown.config.ts b/packages/plugin-lighthouse/tsdown.config.ts new file mode 100644 index 000000000..e172e8fb6 --- /dev/null +++ b/packages/plugin-lighthouse/tsdown.config.ts @@ -0,0 +1,11 @@ +import { defineConfig } from 'tsdown'; +import { baseConfig, getExternalDependencies } from '../../tsdown.base'; + +const __dirname = import.meta.dirname; + +export default defineConfig(async () => ({ + ...baseConfig({ projectRoot: __dirname }), + // Override format to ESM only - this package uses top-level await in constants.ts + format: ['esm'], + external: await getExternalDependencies(__dirname), +})); diff --git a/packages/plugin-typescript/tsdown.config.ts b/packages/plugin-typescript/tsdown.config.ts new file mode 100644 index 000000000..d8c536f13 --- /dev/null +++ b/packages/plugin-typescript/tsdown.config.ts @@ -0,0 +1,9 @@ +import { defineConfig } from 'tsdown'; +import { baseConfig, getExternalDependencies } from '../../tsdown.base'; + +const __dirname = import.meta.dirname; + +export default defineConfig(async () => ({ + ...baseConfig({ projectRoot: __dirname }), + external: await getExternalDependencies(__dirname), +})); diff --git a/packages/utils/eslint.config.js b/packages/utils/eslint.config.js index 1ad01224a..0b1a1d6bf 100644 --- a/packages/utils/eslint.config.js +++ b/packages/utils/eslint.config.js @@ -17,7 +17,12 @@ export default tseslint.config( rules: { '@nx/dependency-checks': [ 'error', - { ignoredDependencies: ['esbuild'] }, // esbuild is a peer dependency of bundle-require + { + ignoredDependencies: [ + 'esbuild', // esbuild is a peer dependency of bundle-require + 'tsdown', + ], + }, ], }, }, diff --git a/packages/utils/tsdown.config.ts b/packages/utils/tsdown.config.ts new file mode 100644 index 000000000..f7cae589e --- /dev/null +++ b/packages/utils/tsdown.config.ts @@ -0,0 +1,12 @@ +import { type ExportsOptions, defineConfig } from 'tsdown'; +import { baseConfig, getExternalDependencies } from '../../tsdown.base'; + +const __dirname = import.meta.dirname; + +export default defineConfig(async () => ({ + ...baseConfig({ projectRoot: __dirname }), + external: await getExternalDependencies(__dirname), + exports: { + all: true, + }, +})); diff --git a/testing/test-nx-utils/tsdown.config.ts b/testing/test-nx-utils/tsdown.config.ts new file mode 100644 index 000000000..bc504b43b --- /dev/null +++ b/testing/test-nx-utils/tsdown.config.ts @@ -0,0 +1,16 @@ +import { defineConfig } from 'tsdown'; +import { baseConfig, getExternalDependencies } from '../../tsdown.base'; + +const __dirname = import.meta.dirname; + +export default defineConfig(async () => ({ + ...baseConfig({ projectRoot: __dirname }), + external: [ + ...(await getExternalDependencies(__dirname)), + '@nx/devkit', + '@nx/js', + 'nx', + '@code-pushup/utils', + ], + copy: [], +})); diff --git a/testing/test-setup-config/package.json b/testing/test-setup-config/package.json new file mode 100644 index 000000000..0e2d4d5fa --- /dev/null +++ b/testing/test-setup-config/package.json @@ -0,0 +1,4 @@ +{ + "name": "@code-pushup/test-setup-config", + "type": "module" +} diff --git a/testing/test-setup-config/tsdown.config.ts b/testing/test-setup-config/tsdown.config.ts new file mode 100644 index 000000000..42f80b7bc --- /dev/null +++ b/testing/test-setup-config/tsdown.config.ts @@ -0,0 +1,10 @@ +import { defineConfig } from 'tsdown'; +import { baseConfig, getExternalDependencies } from '../../tsdown.base'; + +const __dirname = import.meta.dirname; + +export default defineConfig(async () => ({ + ...baseConfig({ projectRoot: __dirname }), + external: [...(await getExternalDependencies(__dirname)), 'fsevents'], + copy: [], +})); diff --git a/testing/test-setup/tsdown.config.ts b/testing/test-setup/tsdown.config.ts new file mode 100644 index 000000000..d0a57d026 --- /dev/null +++ b/testing/test-setup/tsdown.config.ts @@ -0,0 +1,10 @@ +import { defineConfig } from 'tsdown'; +import { baseConfig, getExternalDependencies } from '../../tsdown.base'; + +const __dirname = import.meta.dirname; + +export default defineConfig(async () => ({ + ...baseConfig({ projectRoot: __dirname }), + external: await getExternalDependencies(__dirname), + copy: [], +})); diff --git a/testing/test-utils/eslint.config.js b/testing/test-utils/eslint.config.js index 2656b27cb..5b0e8e2f3 100644 --- a/testing/test-utils/eslint.config.js +++ b/testing/test-utils/eslint.config.js @@ -1,12 +1,33 @@ import tseslint from 'typescript-eslint'; import baseConfig from '../../eslint.config.js'; -export default tseslint.config(...baseConfig, { - files: ['**/*.ts'], - languageOptions: { - parserOptions: { - projectService: true, - tsconfigRootDir: import.meta.dirname, +export default tseslint.config( + ...baseConfig, + { + files: ['**/*.ts'], + languageOptions: { + parserOptions: { + projectService: true, + tsconfigRootDir: import.meta.dirname, + }, }, }, -}); + { + files: ['**/*.json'], + rules: { + '@nx/dependency-checks': [ + 'error', + { + ignoredDependencies: [ + '@code-pushup/models', + 'simple-git', + 'vitest', + '@nx/devkit', + 'ansis', + 'tsdown', + ], + }, + ], + }, + }, +); diff --git a/testing/test-utils/tsdown.config.ts b/testing/test-utils/tsdown.config.ts new file mode 100644 index 000000000..d0a57d026 --- /dev/null +++ b/testing/test-utils/tsdown.config.ts @@ -0,0 +1,10 @@ +import { defineConfig } from 'tsdown'; +import { baseConfig, getExternalDependencies } from '../../tsdown.base'; + +const __dirname = import.meta.dirname; + +export default defineConfig(async () => ({ + ...baseConfig({ projectRoot: __dirname }), + external: await getExternalDependencies(__dirname), + copy: [], +})); diff --git a/tools/eslint-formatter-multi/eslint.config.js b/tools/eslint-formatter-multi/eslint.config.js index 29bda515b..ac29358ba 100644 --- a/tools/eslint-formatter-multi/eslint.config.js +++ b/tools/eslint-formatter-multi/eslint.config.js @@ -15,7 +15,12 @@ export default tseslint.config( { files: ['**/*.json'], rules: { - '@nx/dependency-checks': ['error'], + '@nx/dependency-checks': [ + 'error', + { + ignoredDependencies: ['tsdown'], + }, + ], }, }, ); diff --git a/tools/eslint-formatter-multi/package.json b/tools/eslint-formatter-multi/package.json index 6aaddcec0..bd480bf82 100644 --- a/tools/eslint-formatter-multi/package.json +++ b/tools/eslint-formatter-multi/package.json @@ -32,8 +32,7 @@ "access": "public" }, "dependencies": { - "ansis": "^3.3.0", - "tslib": "^2.8.1" + "ansis": "^3.3.0" }, "peerDependencies": { "eslint": "^8.0.0 || ^9.0.0" diff --git a/tools/eslint-formatter-multi/tsdown.config.ts b/tools/eslint-formatter-multi/tsdown.config.ts new file mode 100644 index 000000000..ae6f25d2e --- /dev/null +++ b/tools/eslint-formatter-multi/tsdown.config.ts @@ -0,0 +1,19 @@ +import { defineConfig } from 'tsdown'; +import { baseConfig, getExternalDependencies } from '../../tsdown.base'; + +const __dirname = import.meta.dirname; + +export default defineConfig(async () => { + const base = baseConfig({ projectRoot: __dirname }); + + // Filter out README.md from copy to avoid unlink errors + const copy = (base.copy || []).filter( + (item: any) => !item.to?.endsWith('/README.md'), + ); + + return { + ...base, + external: await getExternalDependencies(__dirname), + copy, + }; +}); diff --git a/tools/src/ts-down.plugin.mjs b/tools/src/ts-down.plugin.mjs new file mode 100644 index 000000000..8e4f53667 --- /dev/null +++ b/tools/src/ts-down.plugin.mjs @@ -0,0 +1,86 @@ +import { existsSync } from 'node:fs'; +import { dirname, join } from 'node:path'; + +const TSDOWN_CONFIG_GLOB = '**/tsdown.config.{ts,js,mjs}'; + +/** + * Nx plugin to integrate TSDown into the build process. + * + * @example + * ```json + * { + * "plugins": ["./tools/src/ts-down.plugin.mjs"] + * } + * ``` + * This will automatically add a build target to any project containing a `tsdown.config.ts`, `tsdown.config.js`, or `tsdown.config.mjs` file. + */ +const createNodesV2 = [ + TSDOWN_CONFIG_GLOB, + async (configFiles, options, context) => { + return await Promise.all( + configFiles.map(async configFile => { + const projectRoot = dirname(configFile); + const normalizedProjectRoot = projectRoot === '.' ? '' : projectRoot; + + // Check if this is a valid project (has package.json or project.json) + const hasPackageJson = existsSync( + join(context.workspaceRoot, projectRoot, 'package.json'), + ); + const hasProjectJson = existsSync( + join(context.workspaceRoot, projectRoot, 'project.json'), + ); + + if (!hasPackageJson && !hasProjectJson) { + return [configFile, { projects: {} }]; + } + + const targetName = options?.targetName ?? 'tsd-build'; + + const targets = { + [targetName]: createTsdownBuildTarget(configFile, projectRoot), + }; + + const result = { + projects: { + [normalizedProjectRoot]: { + targets, + }, + }, + }; + + return [configFile, result]; + }), + ); + }, +]; + +function createTsdownBuildTarget(configFile, projectRoot) { + return { + executor: 'nx:run-commands', + options: { + command: `node_modules/.bin/tsdown --config ${configFile}`, + cwd: '{workspaceRoot}', + }, + cache: true, + inputs: [ + 'production', + '^production', + { + externalDependencies: ['tsdown'], + }, + ], + outputs: ['{projectRoot}/dist'], + metadata: { + description: 'Build the project using TSDown', + technologies: ['tsdown'], + }, + }; +} + +// Default export for nx.json plugins +const plugin = { + name: '@code-pushup/tsdown-plugin', + createNodesV2, +}; + +export default plugin; diff --git a/tsdown.base.ts b/tsdown.base.ts new file mode 100644 index 000000000..46ed71acb --- /dev/null +++ b/tsdown.base.ts @@ -0,0 +1,213 @@ +import { readFileSync } from 'node:fs'; +import { readFile, writeFile } from 'node:fs/promises'; +import { join } from 'node:path'; +import { type UserConfig, defineConfig } from 'tsdown'; + +export function baseConfig(options: { projectRoot: string }): UserConfig { + const { projectRoot } = options; + + // Read package.json to get additional files to copy + const packageJsonPath = join(projectRoot, 'package.json'); + let additionalCopyFiles: Array<{ from: string; to: string }> = []; + + try { + const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf8')); + + if (packageJson.files && Array.isArray(packageJson.files)) { + additionalCopyFiles = packageJson.files + .filter((file: string) => { + // Skip negation patterns (starting with !) + if (file.startsWith('!')) return false; + // Skip 'src' as it's already handled by the build output + if (file === 'src') return false; + // Include files that start with ./ or are specific files + return file.startsWith('./') || !file.includes('/'); + }) + .map((file: string) => ({ + from: join(projectRoot, file), + to: join(projectRoot, 'dist', file), + })); + } + } catch (error) { + // If package.json doesn't exist or can't be read, continue without additional files + } + + return defineConfig({ + entry: `${projectRoot}/src/**/!(*.test|*.mock).ts`, + tsconfig: `${projectRoot}/tsconfig.lib.json`, + outDir: `${projectRoot}/dist/src`, + unbundle: true, + format: ['esm', 'cjs'], + fixedExtension: true, + dts: true, + hash: false, + external: [], + exports: true, + copy: [ + { + from: `${projectRoot}/package.json`, + to: `${projectRoot}/dist/package.json`, + }, + { + from: `${projectRoot}/README.md`, + to: `${projectRoot}/dist/README.md`, + }, + ...additionalCopyFiles, + ], + async onSuccess() { + const distPackageJsonPath = join(projectRoot, 'dist', 'package.json'); + + try { + const packageJson = JSON.parse( + await readFile(distPackageJsonPath, 'utf8'), + ); + + // Remove fields not needed in published package + delete packageJson.devDependencies; + delete packageJson.scripts; + delete packageJson.nx; + + // Update files field to include built output + if (packageJson.files) { + packageJson.files = packageJson.files.map((file: string) => + file === 'src' ? 'src' : file, + ); + } + + // Detect if this is a CJS-only build by checking if .mjs files exist + const { existsSync } = await import('node:fs'); + const indexMjsPath = join(projectRoot, 'dist', 'src', 'index.mjs'); + const isCjsOnly = !existsSync(indexMjsPath); + + // Adjust paths for the dist directory + if (packageJson.main) { + packageJson.main = packageJson.main.replace(/^dist\//, ''); + if (isCjsOnly) { + packageJson.main = packageJson.main.replace(/\.js$/, '.cjs'); + } + } + if (packageJson.module) { + packageJson.module = packageJson.module.replace(/^dist\//, ''); + } + if (packageJson.types) { + packageJson.types = packageJson.types.replace(/^dist\//, ''); + } + if (packageJson.typings) { + packageJson.typings = packageJson.typings.replace(/^dist\//, ''); + if (isCjsOnly) { + packageJson.typings = packageJson.typings.replace( + /\.d\.ts$/, + '.d.cts', + ); + } + } + + // Update bin field to use correct extension for built files + if (packageJson.bin) { + if (typeof packageJson.bin === 'string') { + // Single bin entry + packageJson.bin = packageJson.bin + .replace(/^dist\//, '') + .replace(/\.js$/, '.mjs'); + } else { + // Multiple bin entries + packageJson.bin = Object.fromEntries( + Object.entries(packageJson.bin).map(([name, path]) => [ + name, + (path as string) + .replace(/^dist\//, '') + .replace(/\.js$/, '.mjs'), + ]), + ); + } + } + + // Generate exports field based on format + if (isCjsOnly) { + // CJS-only exports + packageJson.exports = { + '.': { + require: './src/index.cjs', + types: './src/index.d.cts', + }, + './*': { + require: './src/*/index.cjs', + types: './src/*/index.d.cts', + }, + './*/': { + require: './src/*/index.cjs', + types: './src/*/index.d.cts', + }, + './*.js': { + require: './src/*.cjs', + types: './src/*.d.cts', + }, + }; + } else { + // Dual ESM/CJS exports + packageJson.exports = { + '.': { + import: './src/index.mjs', + require: './src/index.cjs', + types: './src/index.d.mts', + }, + './*': { + import: './src/*/index.mjs', + require: './src/*/index.cjs', + types: './src/*/index.d.mts', + }, + './*/': { + import: './src/*/index.mjs', + require: './src/*/index.cjs', + types: './src/*/index.d.mts', + }, + './*.js': { + import: './src/*.mjs', + require: './src/*.cjs', + types: './src/*.d.mts', + }, + }; + } + + await writeFile( + distPackageJsonPath, + JSON.stringify(packageJson, null, 2), + 'utf8', + ); + } catch (error) { + // If package.json doesn't exist in dist (e.g., copy was overridden), skip modification + if ((error as NodeJS.ErrnoException).code !== 'ENOENT') { + throw error; + } + } + }, + }); +} + +export function getProjectNameFromActiveTask(): string { + const projectName = process.env['NX_TASK_TARGET_PROJECT']; + + if (!projectName || typeof projectName !== 'string') { + throw new Error('NX_TASK_TARGET_PROJECT is not set'); + } + + return projectName; +} + +export async function getExternalDependencies(cwd: string): Promise { + try { + const packageJson = JSON.parse( + await readFile(join(cwd, 'package.json'), 'utf8'), + ); + + return [ + ...Object.keys(packageJson.dependencies || {}), + ...Object.keys(packageJson.devDependencies || {}), + ...Object.keys(packageJson.optionalDependencies || {}), + ...Object.keys(packageJson.peerDependencies || {}), + ]; + } catch { + // No package.json or unable to read it - return empty array + return []; + } +}