From 34862c7f3d6ebfd454b4ee7f46b86cd3e2b0ab95 Mon Sep 17 00:00:00 2001 From: yashwanth195 Date: Mon, 20 Jul 2026 12:04:50 -0700 Subject: [PATCH 1/2] heft oxlint plugin --- README.md | 1 + .../add-heft-oxlint-plugin.json | 11 + .../rush/browser-approved-packages.json | 8 + .../config/subspaces/default/pnpm-lock.yaml | 651 ++++++++++++------ .../config/subspaces/default/repo-state.json | 2 +- heft-plugins/heft-oxlint-plugin/.npmignore | 36 + heft-plugins/heft-oxlint-plugin/LICENSE | 24 + heft-plugins/heft-oxlint-plugin/README.md | 17 + .../heft-oxlint-plugin/config/heft.json | 27 + .../heft-oxlint-plugin/config/rig.json | 7 + .../heft-oxlint-plugin/eslint.config.js | 18 + .../heft-oxlint-plugin/heft-plugin.json | 20 + heft-plugins/heft-oxlint-plugin/package.json | 52 ++ .../heft-oxlint-plugin/src/OxlintHelpers.ts | 363 ++++++++++ .../heft-oxlint-plugin/src/OxlintPlugin.ts | 276 ++++++++ .../schemas/heft-oxlint-plugin.schema.json | 184 +++++ .../src/test/OxlintHelpers.test.ts | 238 +++++++ heft-plugins/heft-oxlint-plugin/tsconfig.json | 3 + rush.json | 6 + 19 files changed, 1747 insertions(+), 197 deletions(-) create mode 100644 common/changes/@rushstack/heft-oxlint-plugin/add-heft-oxlint-plugin.json create mode 100644 heft-plugins/heft-oxlint-plugin/.npmignore create mode 100644 heft-plugins/heft-oxlint-plugin/LICENSE create mode 100644 heft-plugins/heft-oxlint-plugin/README.md create mode 100644 heft-plugins/heft-oxlint-plugin/config/heft.json create mode 100644 heft-plugins/heft-oxlint-plugin/config/rig.json create mode 100644 heft-plugins/heft-oxlint-plugin/eslint.config.js create mode 100644 heft-plugins/heft-oxlint-plugin/heft-plugin.json create mode 100644 heft-plugins/heft-oxlint-plugin/package.json create mode 100644 heft-plugins/heft-oxlint-plugin/src/OxlintHelpers.ts create mode 100644 heft-plugins/heft-oxlint-plugin/src/OxlintPlugin.ts create mode 100644 heft-plugins/heft-oxlint-plugin/src/schemas/heft-oxlint-plugin.schema.json create mode 100644 heft-plugins/heft-oxlint-plugin/src/test/OxlintHelpers.test.ts create mode 100644 heft-plugins/heft-oxlint-plugin/tsconfig.json diff --git a/README.md b/README.md index 8a54e1dea4e..195fb5ec7f4 100644 --- a/README.md +++ b/README.md @@ -72,6 +72,7 @@ These GitHub repositories provide supplementary resources for Rush Stack: | [/heft-plugins/heft-json-schema-typings-plugin](./heft-plugins/heft-json-schema-typings-plugin/) | [![npm version](https://badge.fury.io/js/%40rushstack%2Fheft-json-schema-typings-plugin.svg)](https://badge.fury.io/js/%40rushstack%2Fheft-json-schema-typings-plugin) | [changelog](./heft-plugins/heft-json-schema-typings-plugin/CHANGELOG.md) | [@rushstack/heft-json-schema-typings-plugin](https://www.npmjs.com/package/@rushstack/heft-json-schema-typings-plugin) | | [/heft-plugins/heft-lint-plugin](./heft-plugins/heft-lint-plugin/) | [![npm version](https://badge.fury.io/js/%40rushstack%2Fheft-lint-plugin.svg)](https://badge.fury.io/js/%40rushstack%2Fheft-lint-plugin) | [changelog](./heft-plugins/heft-lint-plugin/CHANGELOG.md) | [@rushstack/heft-lint-plugin](https://www.npmjs.com/package/@rushstack/heft-lint-plugin) | | [/heft-plugins/heft-localization-typings-plugin](./heft-plugins/heft-localization-typings-plugin/) | [![npm version](https://badge.fury.io/js/%40rushstack%2Fheft-localization-typings-plugin.svg)](https://badge.fury.io/js/%40rushstack%2Fheft-localization-typings-plugin) | [changelog](./heft-plugins/heft-localization-typings-plugin/CHANGELOG.md) | [@rushstack/heft-localization-typings-plugin](https://www.npmjs.com/package/@rushstack/heft-localization-typings-plugin) | +| [/heft-plugins/heft-oxlint-plugin](./heft-plugins/heft-oxlint-plugin/) | [![npm version](https://badge.fury.io/js/%40rushstack%2Fheft-oxlint-plugin.svg)](https://badge.fury.io/js/%40rushstack%2Fheft-oxlint-plugin) | [changelog](./heft-plugins/heft-oxlint-plugin/CHANGELOG.md) | [@rushstack/heft-oxlint-plugin](https://www.npmjs.com/package/@rushstack/heft-oxlint-plugin) | | [/heft-plugins/heft-rspack-plugin](./heft-plugins/heft-rspack-plugin/) | [![npm version](https://badge.fury.io/js/%40rushstack%2Fheft-rspack-plugin.svg)](https://badge.fury.io/js/%40rushstack%2Fheft-rspack-plugin) | [changelog](./heft-plugins/heft-rspack-plugin/CHANGELOG.md) | [@rushstack/heft-rspack-plugin](https://www.npmjs.com/package/@rushstack/heft-rspack-plugin) | | [/heft-plugins/heft-sass-load-themed-styles-plugin](./heft-plugins/heft-sass-load-themed-styles-plugin/) | [![npm version](https://badge.fury.io/js/%40rushstack%2Fheft-sass-load-themed-styles-plugin.svg)](https://badge.fury.io/js/%40rushstack%2Fheft-sass-load-themed-styles-plugin) | [changelog](./heft-plugins/heft-sass-load-themed-styles-plugin/CHANGELOG.md) | [@rushstack/heft-sass-load-themed-styles-plugin](https://www.npmjs.com/package/@rushstack/heft-sass-load-themed-styles-plugin) | | [/heft-plugins/heft-sass-plugin](./heft-plugins/heft-sass-plugin/) | [![npm version](https://badge.fury.io/js/%40rushstack%2Fheft-sass-plugin.svg)](https://badge.fury.io/js/%40rushstack%2Fheft-sass-plugin) | [changelog](./heft-plugins/heft-sass-plugin/CHANGELOG.md) | [@rushstack/heft-sass-plugin](https://www.npmjs.com/package/@rushstack/heft-sass-plugin) | diff --git a/common/changes/@rushstack/heft-oxlint-plugin/add-heft-oxlint-plugin.json b/common/changes/@rushstack/heft-oxlint-plugin/add-heft-oxlint-plugin.json new file mode 100644 index 00000000000..cd668dd970c --- /dev/null +++ b/common/changes/@rushstack/heft-oxlint-plugin/add-heft-oxlint-plugin.json @@ -0,0 +1,11 @@ +{ + "changes": [ + { + "packageName": "@rushstack/heft-oxlint-plugin", + "comment": "Initial release of a Heft plugin for running oxlint, the fast Rust-based JavaScript/TypeScript linter.", + "type": "none" + } + ], + "packageName": "@rushstack/heft-oxlint-plugin", + "email": "yashwanth195@users.noreply.github.com" +} diff --git a/common/config/rush/browser-approved-packages.json b/common/config/rush/browser-approved-packages.json index 1a87efdf7fd..ab82552b5ea 100644 --- a/common/config/rush/browser-approved-packages.json +++ b/common/config/rush/browser-approved-packages.json @@ -38,6 +38,10 @@ "name": "@reduxjs/toolkit", "allowedCategories": [ "libraries", "vscode-extensions" ] }, + { + "name": "@rushstack/heft-oxlint-plugin", + "allowedCategories": [ "libraries" ] + }, { "name": "@rushstack/problem-matcher", "allowedCategories": [ "libraries" ] @@ -62,6 +66,10 @@ "name": "office-ui-fabric-core", "allowedCategories": [ "libraries" ] }, + { + "name": "oxlint", + "allowedCategories": [ "libraries" ] + }, { "name": "prism-react-renderer", "allowedCategories": [ "libraries" ] diff --git a/common/config/subspaces/default/pnpm-lock.yaml b/common/config/subspaces/default/pnpm-lock.yaml index a6e518999de..6bb11cb26f7 100644 --- a/common/config/subspaces/default/pnpm-lock.yaml +++ b/common/config/subspaces/default/pnpm-lock.yaml @@ -3338,6 +3338,34 @@ importers: specifier: workspace:* version: link:../../rigs/local-node-rig + ../../../heft-plugins/heft-oxlint-plugin: + dependencies: + '@rushstack/node-core-library': + specifier: workspace:* + version: link:../../libraries/node-core-library + devDependencies: + '@rushstack/heft': + specifier: workspace:* + version: link:../../apps/heft + '@rushstack/heft-typescript-plugin': + specifier: workspace:* + version: link:../heft-typescript-plugin + '@rushstack/terminal': + specifier: workspace:* + version: link:../../libraries/terminal + decoupled-local-node-rig: + specifier: workspace:* + version: link:../../rigs/decoupled-local-node-rig + eslint: + specifier: ~9.37.0 + version: 9.37.0 + oxlint: + specifier: ~1.71.0 + version: 1.71.0 + typescript: + specifier: ~5.8.2 + version: 5.8.2 + ../../../heft-plugins/heft-rspack-plugin: dependencies: '@rspack/dev-server': @@ -6809,7 +6837,7 @@ packages: hasBin: true '@colors/colors@1.5.0': - resolution: {integrity: sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==} + resolution: {integrity: sha1-u1BFecHK6SPmV2pPXaQ9Jfl729k=} engines: {node: '>=0.1.90'} '@csstools/color-helpers@5.1.0': @@ -6849,13 +6877,13 @@ packages: engines: {node: '>=10.0.0'} '@emnapi/core@1.9.2': - resolution: {integrity: sha512-UC+ZhH3XtczQYfOlu3lNEkdW/p4dsJ1r/bP7H8+rhao3TTTMO1ATq/4DdIi23XuGoFY+Cz0JmCbdVl0hz9jZcA==} + resolution: {integrity: sha1-OHAmXs/8c1LQHq1i2Ng9g1ii0DQ=} '@emnapi/runtime@1.9.2': - resolution: {integrity: sha512-3U4+MIWHImeyu1wnmVygh5WlgfYDtyf0k8AbLhMFxOipihf6nrWC4syIm/SwEeec0mNSafiiNnMJwbza/Is6Lw==} + resolution: {integrity: sha1-i0aaPbFggXytsd6QUCEanR6oT6I=} '@emnapi/wasi-threads@1.2.1': - resolution: {integrity: sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==} + resolution: {integrity: sha1-KP7SGhuhznl8RKBwq8lNQvOuhUg=} '@emotion/cache@10.0.29': resolution: {integrity: sha512-fU2VtSVlHiF27empSbxi1O2JFdNWZO+2NFHfwO0pxgTep6Xa3uGb+3pVKfLww2l/IBGLNEZl5Xf/++A4wAYDYQ==} @@ -6930,319 +6958,319 @@ packages: engines: {node: '>=16'} '@esbuild/aix-ppc64@0.25.12': - resolution: {integrity: sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==} + resolution: {integrity: sha1-gPy+NhMOWLdnBRHoiLjoiiWe12w=} engines: {node: '>=18'} cpu: [ppc64] os: [aix] '@esbuild/aix-ppc64@0.28.0': - resolution: {integrity: sha512-lhRUCeuOyJQURhTxl4WkpFTjIsbDayJHih5kZC1giwE+MhIzAb7mEsQMqMf18rHLsrb5qI1tafG20mLxEWcWlA==} + resolution: {integrity: sha1-eiicFY4py/WeoK/IPMgPBtHIlAI=} engines: {node: '>=18'} cpu: [ppc64] os: [aix] '@esbuild/android-arm64@0.25.12': - resolution: {integrity: sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==} + resolution: {integrity: sha1-iqSWX40KeYLcIXNL9mATI6Ztp1I=} engines: {node: '>=18'} cpu: [arm64] os: [android] '@esbuild/android-arm64@0.28.0': - resolution: {integrity: sha512-+WzIXQOSaGs33tLEgYPYe/yQHf0WTU0X42Jca3y8NWMbUVhp7rUnw+vAsRC/QiDrdD31IszMrZy+qwPOPjd+rw==} + resolution: {integrity: sha1-uIKNnt+jqSZgZE643m5PPCA9exc=} engines: {node: '>=18'} cpu: [arm64] os: [android] '@esbuild/android-arm@0.25.12': - resolution: {integrity: sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==} + resolution: {integrity: sha1-MAcSEB9/UPHSYnoWLm4JsQm2dno=} engines: {node: '>=18'} cpu: [arm] os: [android] '@esbuild/android-arm@0.28.0': - resolution: {integrity: sha512-wqh0ByljabXLKHeWXYLqoJ5jKC4XBaw6Hk08OfMrCRd2nP2ZQ5eleDZC41XHyCNgktBGYMbqnrJKq/K/lzPMSQ==} + resolution: {integrity: sha1-XsGEdgXgW12+XfkNuf9+PkxY3Kc=} engines: {node: '>=18'} cpu: [arm] os: [android] '@esbuild/android-x64@0.25.12': - resolution: {integrity: sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==} + resolution: {integrity: sha1-h9+ycWEgK9yVjvSLthsJx1j67hY=} engines: {node: '>=18'} cpu: [x64] os: [android] '@esbuild/android-x64@0.28.0': - resolution: {integrity: sha512-+VJggoaKhk2VNNqVL7f6S189UzShHC/mR9EE8rDdSkdpN0KflSwWY/gWjDrNxxisg8Fp1ZCD9jLMo4m0OUfeUA==} + resolution: {integrity: sha1-OQZCF1uI74K61MzgP4qxP+mxkS4=} engines: {node: '>=18'} cpu: [x64] os: [android] '@esbuild/darwin-arm64@0.25.12': - resolution: {integrity: sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==} + resolution: {integrity: sha1-eRl4mOwf90XSHAceHHzDyALwwf0=} engines: {node: '>=18'} cpu: [arm64] os: [darwin] '@esbuild/darwin-arm64@0.28.0': - resolution: {integrity: sha512-0T+A9WZm+bZ84nZBtk1ckYsOvyA3x7e2Acj1KdVfV4/2tdG4fzUp91YHx+GArWLtwqp77pBXVCPn2We7Letr0Q==} + resolution: {integrity: sha1-rkUyWWDVlQzWlR5PlzlvTh/32NM=} engines: {node: '>=18'} cpu: [arm64] os: [darwin] '@esbuild/darwin-x64@0.25.12': - resolution: {integrity: sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==} + resolution: {integrity: sha1-FGQAqFYhM/RcTS6tzzfd0JcYB54=} engines: {node: '>=18'} cpu: [x64] os: [darwin] '@esbuild/darwin-x64@0.28.0': - resolution: {integrity: sha512-fyzLm/DLDl/84OCfp2f/XQ4flmORsjU7VKt8HLjvIXChJoFFOIL6pLJPH4Yhd1n1gGFF9mPwtlN5Wf82DZs+LQ==} + resolution: {integrity: sha1-wHkkfViba5lEllnZTwaVG4S/8uQ=} engines: {node: '>=18'} cpu: [x64] os: [darwin] '@esbuild/freebsd-arm64@0.25.12': - resolution: {integrity: sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==} + resolution: {integrity: sha1-HF+bpyBuFY/SskxZ+i0si7R8oP4=} engines: {node: '>=18'} cpu: [arm64] os: [freebsd] '@esbuild/freebsd-arm64@0.28.0': - resolution: {integrity: sha512-l9GeW5UZBT9k9brBYI+0WDffcRxgHQD8ShN2Ur4xWq/NFzUKm3k5lsH4PdaRgb2w7mI9u61nr2gI2mLI27Nh3Q==} + resolution: {integrity: sha1-RcRWIVpIZZPJSQApcgLcEciAo3o=} engines: {node: '>=18'} cpu: [arm64] os: [freebsd] '@esbuild/freebsd-x64@0.25.12': - resolution: {integrity: sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==} + resolution: {integrity: sha1-6mMfSja+qsS5J5+g/MbKKerusrM=} engines: {node: '>=18'} cpu: [x64] os: [freebsd] '@esbuild/freebsd-x64@0.28.0': - resolution: {integrity: sha512-BXoQai/A0wPO6Es3yFJ7APCiKGc1tdAEOgeTNy3SsB491S3aHn4S4r3e976eUnPdU+NbdtmBuLncYir2tMU9Nw==} + resolution: {integrity: sha1-A5lJTByF5DiOm3BAvWDUjypbDSw=} engines: {node: '>=18'} cpu: [x64] os: [freebsd] '@esbuild/linux-arm64@0.25.12': - resolution: {integrity: sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==} + resolution: {integrity: sha1-4QZrzlg5TxsRQd7shVel8KIvWXc=} engines: {node: '>=18'} cpu: [arm64] os: [linux] '@esbuild/linux-arm64@0.28.0': - resolution: {integrity: sha512-RVyzfb3FWsGA55n6WY0MEIEPURL1FcbhFE6BffZEMEekfCzCIMtB5yyDcFnVbTnwk+CLAgTujmV/Lgvih56W+A==} + resolution: {integrity: sha1-1tnwnvDeVBFr9Fmk1TysfglS/jk=} engines: {node: '>=18'} cpu: [arm64] os: [linux] '@esbuild/linux-arm@0.25.12': - resolution: {integrity: sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==} + resolution: {integrity: sha1-RSzWayCTLQi9xTqLYcDjC69DSLk=} engines: {node: '>=18'} cpu: [arm] os: [linux] '@esbuild/linux-arm@0.28.0': - resolution: {integrity: sha512-CjaaREJagqJp7iTaNQjjidaNbCKYcd4IDkzbwwxtSvjI7NZm79qiHc8HqciMddQ6CKvJT6aBd8lO9kN/ZudLlw==} + resolution: {integrity: sha1-e0L/qEwoiulP3EMcGyionjw7kng=} engines: {node: '>=18'} cpu: [arm] os: [linux] '@esbuild/linux-ia32@0.25.12': - resolution: {integrity: sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==} + resolution: {integrity: sha1-sk+KzEW89UGSx/LzvhtT5lUer+A=} engines: {node: '>=18'} cpu: [ia32] os: [linux] '@esbuild/linux-ia32@0.28.0': - resolution: {integrity: sha512-KBnSTt1kxl9x70q+ydterVdl+Cn0H18ngRMRCEQfrbqdUuntQQ0LoMZv47uB97NljZFzY6HcfqEZ2SAyIUTQBQ==} + resolution: {integrity: sha1-3rFdES7Y3WBTRra5U9I6If+BJT8=} engines: {node: '>=18'} cpu: [ia32] os: [linux] '@esbuild/linux-loong64@0.14.54': - resolution: {integrity: sha512-bZBrLAIX1kpWelV0XemxBZllyRmM6vgFQQG2GdNb+r3Fkp0FOh1NJSvekXDs7jq70k4euu1cryLMfU+mTXlEpw==} + resolution: {integrity: sha1-3ipL5ni9TQ0f+7hubed5zeWZkCg=} engines: {node: '>=12'} cpu: [loong64] os: [linux] '@esbuild/linux-loong64@0.25.12': - resolution: {integrity: sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==} + resolution: {integrity: sha1-+c//p/yDIlcfvEyLMmjK8VvYGtA=} engines: {node: '>=18'} cpu: [loong64] os: [linux] '@esbuild/linux-loong64@0.28.0': - resolution: {integrity: sha512-zpSlUce1mnxzgBADvxKXX5sl8aYQHo2ezvMNI8I0lbblJtp8V4odlm3Yzlj7gPyt3T8ReksE6bK+pT3WD+aJRg==} + resolution: {integrity: sha1-gfuJ0H7sx5sVfephAzdXcm/ODKQ=} engines: {node: '>=18'} cpu: [loong64] os: [linux] '@esbuild/linux-mips64el@0.25.12': - resolution: {integrity: sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==} + resolution: {integrity: sha1-V1oUvXRkT/q4ka3H1+YNJ1KW8s0=} engines: {node: '>=18'} cpu: [mips64el] os: [linux] '@esbuild/linux-mips64el@0.28.0': - resolution: {integrity: sha512-2jIfP6mmjkdmeTlsX/9vmdmhBmKADrWqN7zcdtHIeNSCH1SqIoNI63cYsjQR8J+wGa4Y5izRcSHSm8K3QWmk3w==} + resolution: {integrity: sha1-0OQmkbP/evn7Ihe3D8AfNDvbYrs=} engines: {node: '>=18'} cpu: [mips64el] os: [linux] '@esbuild/linux-ppc64@0.25.12': - resolution: {integrity: sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==} + resolution: {integrity: sha1-dbmccKlfvV93OddpK+/mBgFZGGk=} engines: {node: '>=18'} cpu: [ppc64] os: [linux] '@esbuild/linux-ppc64@0.28.0': - resolution: {integrity: sha512-bc0FE9wWeC0WBm49IQMPSPILRocGTQt3j5KPCA8os6VprfuJ7KD+5PzESSrJ6GmPIPJK965ZJHTUlSA6GNYEhg==} + resolution: {integrity: sha1-OJ8+XpjxfUd8RnzIcTbhoHburYc=} engines: {node: '>=18'} cpu: [ppc64] os: [linux] '@esbuild/linux-riscv64@0.25.12': - resolution: {integrity: sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==} + resolution: {integrity: sha1-LjJZRAMhpE553fdTXDJQV9qHXNY=} engines: {node: '>=18'} cpu: [riscv64] os: [linux] '@esbuild/linux-riscv64@0.28.0': - resolution: {integrity: sha512-SQPZOwoTTT/HXFXQJG/vBX8sOFagGqvZyXcgLA3NhIqcBv1BJU1d46c0rGcrij2B56Z2rNiSLaZOYW5cUk7yLQ==} + resolution: {integrity: sha1-djvWDVmyQr4S2h5n1XKfMCTGBfo=} engines: {node: '>=18'} cpu: [riscv64] os: [linux] '@esbuild/linux-s390x@0.25.12': - resolution: {integrity: sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==} + resolution: {integrity: sha1-F2dsq7/lko2lsqDW311YzQjbJmM=} engines: {node: '>=18'} cpu: [s390x] os: [linux] '@esbuild/linux-s390x@0.28.0': - resolution: {integrity: sha512-SCfR0HN8CEEjnYnySJTd2cw0k9OHB/YFzt5zgJEwa+wL/T/raGWYMBqwDNAC6dqFKmJYZoQBRfHjgwLHGSrn3Q==} + resolution: {integrity: sha1-qsYGFjSHLkZ33mk7zoAw1zsf0FU=} engines: {node: '>=18'} cpu: [s390x] os: [linux] '@esbuild/linux-x64@0.25.12': - resolution: {integrity: sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==} + resolution: {integrity: sha1-BYN3VoXKggZtBMNQfwlSTTzXowY=} engines: {node: '>=18'} cpu: [x64] os: [linux] '@esbuild/linux-x64@0.28.0': - resolution: {integrity: sha512-us0dSb9iFxIi8srnpl931Nvs65it/Jd2a2K3qs7fz2WfGPHqzfzZTfec7oxZJRNPXPnNYZtanmRc4AL/JwVzHQ==} + resolution: {integrity: sha1-TykXdHGI/ndjK87GWy2EtCJBl3k=} engines: {node: '>=18'} cpu: [x64] os: [linux] '@esbuild/netbsd-arm64@0.25.12': - resolution: {integrity: sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==} + resolution: {integrity: sha1-8ExAScsuJS/paxb+2Q9wdGsT9KQ=} engines: {node: '>=18'} cpu: [arm64] os: [netbsd] '@esbuild/netbsd-arm64@0.28.0': - resolution: {integrity: sha512-CR/RYotgtCKwtftMwJlUU7xCVNg3lMYZ0RzTmAHSfLCXw3NtZtNpswLEj/Kkf6kEL3Gw+BpOekRX0BYCtklhUw==} + resolution: {integrity: sha1-gU3wrlegw4aBRJG4OX7rqCCUqUc=} engines: {node: '>=18'} cpu: [arm64] os: [netbsd] '@esbuild/netbsd-x64@0.25.12': - resolution: {integrity: sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==} + resolution: {integrity: sha1-d9oNCg2CbXySHuo9QCklSLJYoHY=} engines: {node: '>=18'} cpu: [x64] os: [netbsd] '@esbuild/netbsd-x64@0.28.0': - resolution: {integrity: sha512-nU1yhmYutL+fQ71Kxnhg8uEOdC0pwEW9entHykTgEbna2pw2dkbFSMeqjjyHZoCmt8SBkOSvV+yNmm94aUrrqw==} + resolution: {integrity: sha1-4BvffmD6GgjkbUbZYLDZu4rCEK8=} engines: {node: '>=18'} cpu: [x64] os: [netbsd] '@esbuild/openbsd-arm64@0.25.12': - resolution: {integrity: sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==} + resolution: {integrity: sha1-Ypb1hnrt7yioGyKrIAnHhqlS3M0=} engines: {node: '>=18'} cpu: [arm64] os: [openbsd] '@esbuild/openbsd-arm64@0.28.0': - resolution: {integrity: sha512-cXb5vApOsRsxsEl4mcZ1XY3D4DzcoMxR/nnc4IyqYs0rTI8ZKmW6kyyg+11Z8yvgMfAEldKzP7AdP64HnSC/6g==} + resolution: {integrity: sha1-ShXDaqzKaNLVpMkLcQwGdZ9MH/o=} engines: {node: '>=18'} cpu: [arm64] os: [openbsd] '@esbuild/openbsd-x64@0.25.12': - resolution: {integrity: sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==} + resolution: {integrity: sha1-+NIzAzYOJ7Fs8GWyO7/0PBQUJnk=} engines: {node: '>=18'} cpu: [x64] os: [openbsd] '@esbuild/openbsd-x64@0.28.0': - resolution: {integrity: sha512-8wZM2qqtv9UP3mzy7HiGYNH/zjTA355mpeuA+859TyR+e+Tc08IHYpLJuMsfpDJwoLo1ikIJI8jC3GFjnRClzA==} + resolution: {integrity: sha1-R15hAUmKjszjAI18OIER16J8F70=} engines: {node: '>=18'} cpu: [x64] os: [openbsd] '@esbuild/openharmony-arm64@0.25.12': - resolution: {integrity: sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==} + resolution: {integrity: sha1-SeC3aHRKOSS+DX/ZfdbOmykj2I0=} engines: {node: '>=18'} cpu: [arm64] os: [openharmony] '@esbuild/openharmony-arm64@0.28.0': - resolution: {integrity: sha512-FLGfyizszcef5C3YtoyQDACyg95+dndv79i2EekILBofh5wpCa1KuBqOWKrEHZg3zrL3t5ouE5jgr94vA+Wb2w==} + resolution: {integrity: sha1-z9w5V/C3pp8b3hKarRf8wvb6Az4=} engines: {node: '>=18'} cpu: [arm64] os: [openharmony] '@esbuild/sunos-x64@0.25.12': - resolution: {integrity: sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==} + resolution: {integrity: sha1-pu19Z3jWflKMgfsWWyP0kRubE9Y=} engines: {node: '>=18'} cpu: [x64] os: [sunos] '@esbuild/sunos-x64@0.28.0': - resolution: {integrity: sha512-1ZgjUoEdHZZl/YlV76TSCz9Hqj9h9YmMGAgAPYd+q4SicWNX3G5GCyx9uhQWSLcbvPW8Ni7lj4gDa1T40akdlw==} + resolution: {integrity: sha1-oBPIVv7KzRw67Jhciv4dHLAXSX0=} engines: {node: '>=18'} cpu: [x64] os: [sunos] '@esbuild/win32-arm64@0.25.12': - resolution: {integrity: sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==} + resolution: {integrity: sha1-msFMN44bZTrxfQjn0840yu9YcyM=} engines: {node: '>=18'} cpu: [arm64] os: [win32] '@esbuild/win32-arm64@0.28.0': - resolution: {integrity: sha512-Q9StnDmQ/enxnpxCCLSg0oo4+34B9TdXpuyPeTedN/6+iXBJ4J+zwfQI28u/Jl40nOYAxGoNi7mFP40RUtkmUA==} + resolution: {integrity: sha1-6uBeDzUnHK04mLQxaNPpo7uvR+U=} engines: {node: '>=18'} cpu: [arm64] os: [win32] '@esbuild/win32-ia32@0.25.12': - resolution: {integrity: sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==} + resolution: {integrity: sha1-kYlC3LuzXMFPyjmvuRteaj0Scmc=} engines: {node: '>=18'} cpu: [ia32] os: [win32] '@esbuild/win32-ia32@0.28.0': - resolution: {integrity: sha512-zF3ag/gfiCe6U2iczcRzSYJKH1DCI+ByzSENHlM2FcDbEeo5Zd2C86Aq0tKUYAJJ1obRP84ymxIAksZUcdztHA==} + resolution: {integrity: sha1-BhYevFv3XAjWn+s8ayJWBRWROZg=} engines: {node: '>=18'} cpu: [ia32] os: [win32] '@esbuild/win32-x64@0.25.12': - resolution: {integrity: sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==} + resolution: {integrity: sha1-m9rYF2vngRrRSNH4dyNZBB9GxsU=} engines: {node: '>=18'} cpu: [x64] os: [win32] '@esbuild/win32-x64@0.28.0': - resolution: {integrity: sha512-pEl1bO9mfAmIC+tW5btTmrKaujg3zGtUmWNdCw/xs70FBjwAL3o9OEKNHvNmnyylD6ubxUERiEhdsL0xBQ9efw==} + resolution: {integrity: sha1-BNkNV1K0zmXStqwl66CP92JP4Hw=} engines: {node: '>=18'} cpu: [x64] os: [win32] @@ -8499,10 +8527,10 @@ packages: engines: {node: '>=4'} '@napi-rs/wasm-runtime@0.2.12': - resolution: {integrity: sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==} + resolution: {integrity: sha1-PniouW5sM6bFF+GJTvvVOFp8tvI=} '@napi-rs/wasm-runtime@1.0.7': - resolution: {integrity: sha512-SeDnOO0Tk7Okiq6DbXmmBODgOAb9dp9gjlphokTUxmt8U3liIP1ZsozBahH69j/RJv+Rfs6IwUKHTgQYJ/HBAw==} + resolution: {integrity: sha1-3P6pmnXwYgmiNfPZQeNGClHpsUw=} '@noble/hashes@1.4.0': resolution: {integrity: sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==} @@ -8532,6 +8560,128 @@ packages: engines: {node: '>=10'} deprecated: This functionality has been moved to @npmcli/fs + '@oxlint/binding-android-arm-eabi@1.71.0': + resolution: {integrity: sha1-hgB+KTt6nMho9u9EFt5mrf99UgQ=} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [android] + + '@oxlint/binding-android-arm64@1.71.0': + resolution: {integrity: sha1-nb0CWG/HIkoQHjy/P0hOrAf50mo=} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [android] + + '@oxlint/binding-darwin-arm64@1.71.0': + resolution: {integrity: sha1-eA9SQhJB2hgPJkHToj6nIFIHkLU=} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [darwin] + + '@oxlint/binding-darwin-x64@1.71.0': + resolution: {integrity: sha1-ChLX+0bl5bAmZGqomYRew3r4TfE=} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [darwin] + + '@oxlint/binding-freebsd-x64@1.71.0': + resolution: {integrity: sha1-UzsBoSAHX/++s1SMB1PO/Tld2r0=} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [freebsd] + + '@oxlint/binding-linux-arm-gnueabihf@1.71.0': + resolution: {integrity: sha1-EFQRgTHD1JqKEyghqsnQ8V3oQdk=} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + + '@oxlint/binding-linux-arm-musleabihf@1.71.0': + resolution: {integrity: sha1-0Y223az7wGmNlmDtqS/7/cRRAbY=} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + + '@oxlint/binding-linux-arm64-gnu@1.71.0': + resolution: {integrity: sha1-S7iwJArXkNGZdI5LqGyshxFG0cY=} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@oxlint/binding-linux-arm64-musl@1.71.0': + resolution: {integrity: sha1-jLsaZgPZ6qBfmyVGnQT3HfqjrgU=} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@oxlint/binding-linux-ppc64-gnu@1.71.0': + resolution: {integrity: sha1-v0gBIOjBu7+/OISm+uwHzy7T2PI=} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [ppc64] + os: [linux] + libc: [glibc] + + '@oxlint/binding-linux-riscv64-gnu@1.71.0': + resolution: {integrity: sha1-ki+4B031Nd40bXsf9DPDlPUqYA0=} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [riscv64] + os: [linux] + libc: [glibc] + + '@oxlint/binding-linux-riscv64-musl@1.71.0': + resolution: {integrity: sha1-VaQ3aTpjsOECbBZ1bFQWYe58nHQ=} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [riscv64] + os: [linux] + libc: [musl] + + '@oxlint/binding-linux-s390x-gnu@1.71.0': + resolution: {integrity: sha1-KT5BNt6CC3F23qDj6n5KCq5RbGs=} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [s390x] + os: [linux] + libc: [glibc] + + '@oxlint/binding-linux-x64-gnu@1.71.0': + resolution: {integrity: sha1-I1oET4wI1j+6uX7vcFgOshLF9Fk=} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@oxlint/binding-linux-x64-musl@1.71.0': + resolution: {integrity: sha1-C+j2veztYN4pDRGAEGDUBGicS0M=} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [musl] + + '@oxlint/binding-openharmony-arm64@1.71.0': + resolution: {integrity: sha1-VuyV4rwMdb4d5wNG4Nh1mh0x7vI=} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [openharmony] + + '@oxlint/binding-win32-arm64-msvc@1.71.0': + resolution: {integrity: sha1-4YfIhBlLiCL/E0ctWxLn9h1U5ns=} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [win32] + + '@oxlint/binding-win32-ia32-msvc@1.71.0': + resolution: {integrity: sha1-okuOrBh6Qla2iTWz/baxGwTu4Mc=} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [ia32] + os: [win32] + + '@oxlint/binding-win32-x64-msvc@1.71.0': + resolution: {integrity: sha1-sIzKhigT+Li92u5ydE2i4mJKhDE=} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [win32] + '@peculiar/asn1-cms@2.6.1': resolution: {integrity: sha512-vdG4fBF6Lkirkcl53q6eOdn3XYKt+kJTG59edgRZORlg/3atWWEReRCx5rYE1ZzTTX6vLK5zDMjHh7vbrcXGtw==} @@ -8567,7 +8717,7 @@ packages: engines: {node: '>=20.0.0'} '@pkgjs/parseargs@0.11.0': - resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} + resolution: {integrity: sha1-p36nQvqyV3UUVDTrHSMoz1ATrDM=} engines: {node: '>=14'} '@pkgr/core@0.2.9': @@ -8696,7 +8846,7 @@ packages: '@pnpm/logger': ^5.0.0 '@pnpm/lockfile-types@5.1.5': - resolution: {integrity: sha512-02FP0HynzX+2DcuPtuMy7PH+kLIC0pevAydAOK+zug2bwdlSLErlvSkc+4+3dw60eRWgUXUqyfO2eR/Ansdbng==} + resolution: {integrity: sha1-FLhcl23c90dPWmopNRy1eZWdDsg=} engines: {node: '>=16.14'} '@pnpm/lockfile.fs@1001.1.32': @@ -8710,7 +8860,7 @@ packages: engines: {node: '>=18.12'} '@pnpm/lockfile.types@1001.1.0': - resolution: {integrity: sha512-/rfDUV8M9iMm0QXahHPv6SD6eKNkrMXlhECJVhDkdL4NIifcv6/HZwYtxd0PIndExz04+OE+iV9K8zKG9i/OEA==} + resolution: {integrity: sha1-rhsx7V+7Du0y0CpfVlG8zilTW6E=} engines: {node: '>=18.12'} '@pnpm/lockfile.types@1002.0.1': @@ -8750,7 +8900,7 @@ packages: engines: {node: '>=10.16'} '@pnpm/patching.types@1000.1.0': - resolution: {integrity: sha512-Zib2ysLctRnWM4KXXlljR44qSKwyEqYmLk+8VPBDBEK3l5Gp5mT3N4ix9E4qjYynvFqahumsxzOfxOYQhUGMGw==} + resolution: {integrity: sha1-1AOzl0N4A7hZx/sullgMiXtitx4=} engines: {node: '>=18.12'} '@pnpm/patching.types@900.0.0': @@ -8762,7 +8912,7 @@ packages: engines: {node: '>=18.12'} '@pnpm/ramda@0.28.1': - resolution: {integrity: sha512-zcAG+lvU0fMziNeGXpPyCyCJYp5ZVrPElEE4t14jAmViaihohocZ+dDkcRIyAomox8pQsuZnv1EyHR+pOhmUWw==} + resolution: {integrity: sha1-DzKrxSddWGoD4Nwd2QoAmsZo/zM=} '@pnpm/read-modules-dir@2.0.3': resolution: {integrity: sha512-i9OgRvSlxrTS9a2oXokhDxvQzDtfqtsooJ9jaGoHkznue5aFCTSrNZFQ6M18o8hC03QWfnxaKi0BtOvNkKu2+A==} @@ -8789,7 +8939,7 @@ packages: engines: {node: '>=18.12'} '@pnpm/types@1000.7.0': - resolution: {integrity: sha512-1s7FvDqmOEIeFGLUj/VO8sF5lGFxeE/1WALrBpfZhDnMXY/x8FbmuygTTE5joWifebcZ8Ww8Kw2CgBoStsIevQ==} + resolution: {integrity: sha1-g1Hkb73+JfgP7Jdb/fWNDKStYkw=} engines: {node: '>=18.12'} '@pnpm/types@1000.8.0': @@ -8813,7 +8963,7 @@ packages: engines: {node: '>=14.6'} '@pnpm/types@9.4.2': - resolution: {integrity: sha512-g1hcF8Nv4gd76POilz9gD4LITAPXOe5nX4ijgr8ixCbLQZfcpYiMfJ+C1RlMNRUDo8vhlNB4O3bUlxmT6EAQXA==} + resolution: {integrity: sha1-CjTDxB1UUkYdjYlYN0pyf5xGz7I=} engines: {node: '>=16.14'} '@pnpm/types@900.0.0': @@ -8839,7 +8989,7 @@ packages: resolution: {integrity: sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==} '@pothos/core@3.41.2': - resolution: {integrity: sha512-iR1gqd93IyD/snTW47HwKSsRCrvnJaYwjVNcUG8BztZPqMxyJKPAnjPHAgu1XB82KEdysrNqIUnXqnzZIs08QA==} + resolution: {integrity: sha1-ruJt4pccOHJDU0S8NM4Kv5qUVL0=} peerDependencies: graphql: '>=15.1.0' @@ -9080,56 +9230,61 @@ packages: engines: {node: '>=14.0.0'} '@rollup/rollup-linux-x64-gnu@4.53.3': - resolution: {integrity: sha512-3EhFi1FU6YL8HTUJZ51imGJWEX//ajQPfqWLI3BQq4TlvHy4X0MOr5q3D2Zof/ka0d5FNdPwZXm3Yyib/UEd+w==} + resolution: {integrity: sha1-/Q3qO7mqB+cINXnyXhwihaRsufo=} cpu: [x64] os: [linux] + libc: [glibc] '@rspack/binding-darwin-arm64@1.6.8': - resolution: {integrity: sha512-e8CTQtzaeGnf+BIzR7wRMUwKfIg0jd/sxMRc1Vd0bCMHBhSN9EsGoMuJJaKeRrSmy2nwMCNWHIG+TvT1CEKg+A==} + resolution: {integrity: sha1-Uph8DLxIeiQL3GsaMYODctrd7is=} cpu: [arm64] os: [darwin] '@rspack/binding-darwin-x64@1.6.8': - resolution: {integrity: sha512-ku1XpTEPt6Za11zhpFWhfwrTQogcgi9RJrOUVC4FESiPO9aKyd4hJ+JiPgLY0MZOqsptK6vEAgOip+uDVXrCpg==} + resolution: {integrity: sha1-E8gBzoIQ0Rt7C8Sse/A27DKGKTU=} cpu: [x64] os: [darwin] '@rspack/binding-linux-arm64-gnu@1.6.8': - resolution: {integrity: sha512-fvZX6xZPvBT8qipSpvkKMX5M7yd2BSpZNCZXcefw6gA3uC7LI3gu+er0LrDXY1PtPzVuHTyDx+abwWpagV3PiQ==} + resolution: {integrity: sha1-1wMhrFu9W8EB3potoBxvuYRgFWU=} cpu: [arm64] os: [linux] + libc: [glibc] '@rspack/binding-linux-arm64-musl@1.6.8': - resolution: {integrity: sha512-++XMKcMNrt59HcFBLnRaJcn70k3X0GwkAegZBVpel8xYIAgvoXT5+L8P1ExId/yTFxqedaz8DbcxQnNmMozviw==} + resolution: {integrity: sha1-T5GWtiM2Sc5D5khaXScU7zjfxgM=} cpu: [arm64] os: [linux] + libc: [musl] '@rspack/binding-linux-x64-gnu@1.6.8': - resolution: {integrity: sha512-tv3BWkTE1TndfX+DsE1rSTg8fBevCxujNZ3MlfZ22Wfy9x1FMXTJlWG8VIOXmaaJ1wUHzv8S7cE2YUUJ2LuiCg==} + resolution: {integrity: sha1-t45/YrQVezHhgf6J0xmmAXgqgCs=} cpu: [x64] os: [linux] + libc: [glibc] '@rspack/binding-linux-x64-musl@1.6.8': - resolution: {integrity: sha512-DCGgZ5/in1O3FjHWqXnDsncRy+48cMhfuUAAUyl0yDj1NpsZu9pP+xfGLvGcQTiYrVl7IH9Aojf1eShP/77WGA==} + resolution: {integrity: sha1-xXj3MNip+rhm5KFZIEV++df9X1g=} cpu: [x64] os: [linux] + libc: [musl] '@rspack/binding-wasm32-wasi@1.6.8': - resolution: {integrity: sha512-VUwdhl/lI4m6o1OGCZ9JwtMjTV/yLY5VZTQdEPKb40JMTlmZ5MBlr5xk7ByaXXYHr6I+qnqEm73iMKQvg6iknw==} + resolution: {integrity: sha1-dtI1iewxrWurZ4TaiffMQsffAnU=} cpu: [wasm32] '@rspack/binding-win32-arm64-msvc@1.6.8': - resolution: {integrity: sha512-23YX7zlOZlub+nPGDBUzktb4D5D6ETUAluKjXEeHIZ9m7fSlEYBnGL66YE+3t1DHXGd0OqsdwlvrNGcyo6EXDQ==} + resolution: {integrity: sha1-tCy6SrdYjOcvDBPJaNPWLophq0Y=} cpu: [arm64] os: [win32] '@rspack/binding-win32-ia32-msvc@1.6.8': - resolution: {integrity: sha512-cFgRE3APxrY4AEdooVk2LtipwNNT/9mrnjdC5lVbsIsz+SxvGbZR231bxDJEqP15+RJOaD07FO1sIjINFqXMEg==} + resolution: {integrity: sha1-KTojRIxqEfJamru5iWEwWcfaPsQ=} cpu: [ia32] os: [win32] '@rspack/binding-win32-x64-msvc@1.6.8': - resolution: {integrity: sha512-cIuhVsZYd3o3Neo1JSAhJYw6BDvlxaBoqvgwRkG1rs0ExFmEmgYyG7ip9pFKnKNWph/tmW3rDYypmEfjs1is7g==} + resolution: {integrity: sha1-9f0/AbZpTuCMvDgsO9QtZJCrlEY=} cpu: [x64] os: [win32] @@ -9970,61 +10125,65 @@ packages: react-dom: ^16.8.0 || ^17.0.0 '@swc/core-darwin-arm64@1.7.10': - resolution: {integrity: sha512-TYp4x/9w/C/yMU1olK5hTKq/Hi7BjG71UJ4V1U1WxI1JA3uokjQ/GoktDfmH5V5pX4dgGSOJwUe2RjoN8Z/XnA==} + resolution: {integrity: sha1-PuU+21AbI7EERqmNH21tSH2Iodk=} engines: {node: '>=10'} cpu: [arm64] os: [darwin] '@swc/core-darwin-x64@1.7.10': - resolution: {integrity: sha512-P3LJjAWh5yLc6p5IUwV5LgRfA3R1oDCZDMabYyb2BVQuJTD4MfegW9DhBcUUF5dhBLwq3191KpLVzE+dLTbiXw==} + resolution: {integrity: sha1-cdNUFYDjbr73bTfwCBxJp/Gv6tY=} engines: {node: '>=10'} cpu: [x64] os: [darwin] '@swc/core-linux-arm-gnueabihf@1.7.10': - resolution: {integrity: sha512-yGOFjE7w/akRTmqGY3FvWYrqbxO7OB2N2FHj2LO5HtzXflfoABb5RyRvdEquX+17J6mEpu4EwjYNraTD/WHIEQ==} + resolution: {integrity: sha1-ez86gp2R+FmlAP5gfmgUiY7oGdk=} engines: {node: '>=10'} cpu: [arm] os: [linux] '@swc/core-linux-arm64-gnu@1.7.10': - resolution: {integrity: sha512-SPWsgWHfdWKKjLrYlvhxcdBJ7Ruy6crJbPoE9NfD95eJEjMnS2yZTqj2ChFsY737WeyhWYlHzgYhYOVCp83YwQ==} + resolution: {integrity: sha1-vdDQ9kwrLAneqXa+ncJI/TWd5VE=} engines: {node: '>=10'} cpu: [arm64] os: [linux] + libc: [glibc] '@swc/core-linux-arm64-musl@1.7.10': - resolution: {integrity: sha512-PUi50bkNqnBL3Z/Zq6jSfwgN9A/taA6u2Zou0tjDJi7oVdpjdr7SxNgCGzMJ/nNg5D/IQn1opM1jktMvpsPAuQ==} + resolution: {integrity: sha1-vJgIuyS6Ek++l3KQGadFvV6IWas=} engines: {node: '>=10'} cpu: [arm64] os: [linux] + libc: [musl] '@swc/core-linux-x64-gnu@1.7.10': - resolution: {integrity: sha512-Sc+pY55gknCAmBQBR6DhlA7jZSxHaLSDb5Sevzi6DOFMXR79NpA6zWTNKwp1GK2AnRIkbAfvYLgOxS5uWTFVpg==} + resolution: {integrity: sha1-EBpx3PkiTrLO7HgaJUqTd0xl/zE=} engines: {node: '>=10'} cpu: [x64] os: [linux] + libc: [glibc] '@swc/core-linux-x64-musl@1.7.10': - resolution: {integrity: sha512-g5NKx2LXaGd0K26hmEts1Cvb7ptIvq3MHSgr6/D1tRPcDZw1Sp0dYsmyOv0ho4F5GOJyiCooG3oE9FXdb7jIpQ==} + resolution: {integrity: sha1-b8Grv32BgzQ76Ur64L9ZaumNQEg=} engines: {node: '>=10'} cpu: [x64] os: [linux] + libc: [musl] '@swc/core-win32-arm64-msvc@1.7.10': - resolution: {integrity: sha512-plRIsOcfy9t9Q/ivm5DA7I0HaIvfAWPbI+bvVRrr3C/1K2CSqnqZJjEWOAmx2LiyipijNnEaFYuLBp0IkGuJpg==} + resolution: {integrity: sha1-XW7P2kzF6D7IZZEZ8WB7FmP3Cm0=} engines: {node: '>=10'} cpu: [arm64] os: [win32] '@swc/core-win32-ia32-msvc@1.7.10': - resolution: {integrity: sha512-GntrVNT23viHtbfzmlK8lfBiKeajH24GzbDT7qXhnoO20suUPcyYZxyvCb4gWM2zu8ZBTPHNlqfrNsriQCZ+lQ==} + resolution: {integrity: sha1-N/MXfaU7KLLcjIOu/vwgIFBk688=} engines: {node: '>=10'} cpu: [ia32] os: [win32] '@swc/core-win32-x64-msvc@1.7.10': - resolution: {integrity: sha512-uXIF8GuSappe1imm6Lf7pHGepfCBjDQlS+qTqvEGE0wZAsL1IVATK9P/cH/OCLfJXeQDTLeSYmrpwjtXNt46tQ==} + resolution: {integrity: sha1-KBQzXAAylcSoCOwbnPGepU+a1uU=} engines: {node: '>=10'} cpu: [x64] os: [win32] @@ -10073,7 +10232,7 @@ packages: resolution: {integrity: sha512-yw0omUrxGp8+gEAuieZFeXB4bCqFvmyCDL3GOBv+Q6+cK0m5824ViHZKPgK5DYG1ijN/lbi1hP3UVKywPN7rbQ==} '@tybys/wasm-util@0.10.1': - resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==} + resolution: {integrity: sha1-7N3TIFzx4tUnRkn/Du3SmR7X9BQ=} '@types/argparse@1.0.38': resolution: {integrity: sha512-ebDJ9b0e702Yr7pWgB0jzm+CX4Srzz8RcXtLJDJB+BSccqMa36uyH/zUsSYao5+BD1ytv3k3rPYCq4mAE1hsXA==} @@ -10589,97 +10748,105 @@ packages: resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==} '@unrs/resolver-binding-android-arm-eabi@1.11.1': - resolution: {integrity: sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw==} + resolution: {integrity: sha1-n1sEUDCI5qNUKV6OqP48uZ5Dr4E=} cpu: [arm] os: [android] '@unrs/resolver-binding-android-arm64@1.11.1': - resolution: {integrity: sha512-lCxkVtb4wp1v+EoN+HjIG9cIIzPkX5OtM03pQYkG+U5O/wL53LC4QbIeazgiKqluGeVEeBlZahHalCaBvU1a2g==} + resolution: {integrity: sha1-dBSIVDG9cXi5ia7cTSXMyzhlvJ8=} cpu: [arm64] os: [android] '@unrs/resolver-binding-darwin-arm64@1.11.1': - resolution: {integrity: sha512-gPVA1UjRu1Y/IsB/dQEsp2V1pm44Of6+LWvbLc9SDk1c2KhhDRDBUkQCYVWe6f26uJb3fOK8saWMgtX8IrMk3g==} + resolution: {integrity: sha1-tKhVb0IXH7nJ97rII1BF6Cqgy98=} cpu: [arm64] os: [darwin] '@unrs/resolver-binding-darwin-x64@1.11.1': - resolution: {integrity: sha512-cFzP7rWKd3lZaCsDze07QX1SC24lO8mPty9vdP+YVa3MGdVgPmFc59317b2ioXtgCMKGiCLxJ4HQs62oz6GfRQ==} + resolution: {integrity: sha1-/U2BJXsT9NGgg4kKahfADeVx8Nw=} cpu: [x64] os: [darwin] '@unrs/resolver-binding-freebsd-x64@1.11.1': - resolution: {integrity: sha512-fqtGgak3zX4DCB6PFpsH5+Kmt/8CIi4Bry4rb1ho6Av2QHTREM+47y282Uqiu3ZRF5IQioJQ5qWRV6jduA+iGw==} + resolution: {integrity: sha1-0lEwhNDzfEB3V+IvMr2SSnjP2Zs=} cpu: [x64] os: [freebsd] '@unrs/resolver-binding-linux-arm-gnueabihf@1.11.1': - resolution: {integrity: sha512-u92mvlcYtp9MRKmP+ZvMmtPN34+/3lMHlyMj7wXJDeXxuM0Vgzz0+PPJNsro1m3IZPYChIkn944wW8TYgGKFHw==} + resolution: {integrity: sha1-hE0mBdBXSI13+rCXBfKGa4YWTgo=} cpu: [arm] os: [linux] '@unrs/resolver-binding-linux-arm-musleabihf@1.11.1': - resolution: {integrity: sha512-cINaoY2z7LVCrfHkIcmvj7osTOtm6VVT16b5oQdS4beibX2SYBwgYLmqhBjA1t51CarSaBuX5YNsWLjsqfW5Cw==} + resolution: {integrity: sha1-IEiSmVzvtr0dAX1S0JcZO8Yd2tM=} cpu: [arm] os: [linux] '@unrs/resolver-binding-linux-arm64-gnu@1.11.1': - resolution: {integrity: sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ==} + resolution: {integrity: sha1-Aj6ww6rEYGahC+ej82Lns087350=} cpu: [arm64] os: [linux] + libc: [glibc] '@unrs/resolver-binding-linux-arm64-musl@1.11.1': - resolution: {integrity: sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w==} + resolution: {integrity: sha1-nm+auwZCTjFApgrJlhOXhvXZm+A=} cpu: [arm64] os: [linux] + libc: [musl] '@unrs/resolver-binding-linux-ppc64-gnu@1.11.1': - resolution: {integrity: sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA==} + resolution: {integrity: sha1-sRFBfxfJ0bAu++yOCDmPDFUnu0Q=} cpu: [ppc64] os: [linux] + libc: [glibc] '@unrs/resolver-binding-linux-riscv64-gnu@1.11.1': - resolution: {integrity: sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ==} + resolution: {integrity: sha1-kv+/AnSK8+mYc5RcmoperQHVCKk=} cpu: [riscv64] os: [linux] + libc: [glibc] '@unrs/resolver-binding-linux-riscv64-musl@1.11.1': - resolution: {integrity: sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew==} + resolution: {integrity: sha1-C+xvElj8OQ5rMF6f9EJWyyB94WU=} cpu: [riscv64] os: [linux] + libc: [musl] '@unrs/resolver-binding-linux-s390x-gnu@1.11.1': - resolution: {integrity: sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg==} + resolution: {integrity: sha1-V3hDoITFlS9ZBncGM8z7idrJvJQ=} cpu: [s390x] os: [linux] + libc: [glibc] '@unrs/resolver-binding-linux-x64-gnu@1.11.1': - resolution: {integrity: sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w==} + resolution: {integrity: sha1-NvsxjuvdaQ9toyrF4EmadvqIGTU=} cpu: [x64] os: [linux] + libc: [glibc] '@unrs/resolver-binding-linux-x64-musl@1.11.1': - resolution: {integrity: sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA==} + resolution: {integrity: sha1-v7mvdfeD+Y9qIsQkQhTv5N8YU9Y=} cpu: [x64] os: [linux] + libc: [musl] '@unrs/resolver-binding-wasm32-wasi@1.11.1': - resolution: {integrity: sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ==} + resolution: {integrity: sha1-dSw1ndh1aEsnQpUA2IIm18xy9x0=} engines: {node: '>=14.0.0'} cpu: [wasm32] '@unrs/resolver-binding-win32-arm64-msvc@1.11.1': - resolution: {integrity: sha512-nRcz5Il4ln0kMhfL8S3hLkxI85BXs3o8EYoattsJNdsX4YUU89iOkVn7g0VHSRxFuVMdM4Q1jEpIId1Ihim/Uw==} + resolution: {integrity: sha1-zlc15gDkwvu0Cc0FGzt9pKOZrzU=} cpu: [arm64] os: [win32] '@unrs/resolver-binding-win32-ia32-msvc@1.11.1': - resolution: {integrity: sha512-DCEI6t5i1NmAZp6pFonpD5m7i6aFrpofcp4LA2i8IIq60Jyo28hamKBxNrZcyOwVOZkgsRp9O2sXWBWP8MnvIQ==} + resolution: {integrity: sha1-cvxXvHxk7Fw94NZO4NGBAxe8YKY=} cpu: [ia32] os: [win32] '@unrs/resolver-binding-win32-x64-msvc@1.11.1': - resolution: {integrity: sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g==} + resolution: {integrity: sha1-U4seEDv42YZOe4XMlvqNb7bEB3c=} cpu: [x64] os: [win32] @@ -10711,47 +10878,47 @@ packages: engines: {node: '>=8.9.3'} '@vscode/vsce-sign-alpine-arm64@2.0.6': - resolution: {integrity: sha512-wKkJBsvKF+f0GfsUuGT0tSW0kZL87QggEiqNqK6/8hvqsXvpx8OsTEc3mnE1kejkh5r+qUyQ7PtF8jZYN0mo8Q==} + resolution: {integrity: sha1-LNJEyvXo7FQ/QvuR1N87kzZByPo=} cpu: [arm64] os: [alpine] '@vscode/vsce-sign-alpine-x64@2.0.6': - resolution: {integrity: sha512-YoAGlmdK39vKi9jA18i4ufBbd95OqGJxRvF3n6ZbCyziwy3O+JgOpIUPxv5tjeO6gQfx29qBivQ8ZZTUF2Ba0w==} + resolution: {integrity: sha1-sOgKR5IAHGbif+7iwR6CGtH6FoA=} cpu: [x64] os: [alpine] '@vscode/vsce-sign-darwin-arm64@2.0.6': - resolution: {integrity: sha512-5HMHaJRIQuozm/XQIiJiA0W9uhdblwwl2ZNDSSAeXGO9YhB9MH5C4KIHOmvyjUnKy4UCuiP43VKpIxW1VWP4tQ==} + resolution: {integrity: sha1-S4+hq1XygKmZhb48BvtzDleBDM4=} cpu: [arm64] os: [darwin] '@vscode/vsce-sign-darwin-x64@2.0.6': - resolution: {integrity: sha512-25GsUbTAiNfHSuRItoQafXOIpxlYj+IXb4/qarrXu7kmbH94jlm5sdWSCKrrREs8+GsXF1b+l3OB7VJy5jsykw==} + resolution: {integrity: sha1-0skYbZUFSYJyy93YODuwOOvPWCA=} cpu: [x64] os: [darwin] '@vscode/vsce-sign-linux-arm64@2.0.6': - resolution: {integrity: sha512-cfb1qK7lygtMa4NUl2582nP7aliLYuDEVpAbXJMkDq1qE+olIw/es+C8j1LJwvcRq1I2yWGtSn3EkDp9Dq5FdA==} + resolution: {integrity: sha1-s9hWAUQEC5INjG7dQ3QxS1glVIE=} cpu: [arm64] os: [linux] '@vscode/vsce-sign-linux-arm@2.0.6': - resolution: {integrity: sha512-UndEc2Xlq4HsuMPnwu7420uqceXjs4yb5W8E2/UkaHBB9OWCwMd3/bRe/1eLe3D8kPpxzcaeTyXiK3RdzS/1CA==} + resolution: {integrity: sha1-CifEKkrbN+lu7HjNe/o4jNTp++8=} cpu: [arm] os: [linux] '@vscode/vsce-sign-linux-x64@2.0.6': - resolution: {integrity: sha512-/olerl1A4sOqdP+hjvJ1sbQjKN07Y3DVnxO4gnbn/ahtQvFrdhUi0G1VsZXDNjfqmXw57DmPi5ASnj/8PGZhAA==} + resolution: {integrity: sha1-reEcru7VJPwWvWxDykmuoAKV3ow=} cpu: [x64] os: [linux] '@vscode/vsce-sign-win32-arm64@2.0.6': - resolution: {integrity: sha512-ivM/MiGIY0PJNZBoGtlRBM/xDpwbdlCWomUWuLmIxbi1Cxe/1nooYrEQoaHD8ojVRgzdQEUzMsRbyF5cJJgYOg==} + resolution: {integrity: sha1-BoiWgUjgPrOSR5yEkcclBnIb7/w=} cpu: [arm64] os: [win32] '@vscode/vsce-sign-win32-x64@2.0.6': - resolution: {integrity: sha512-mgth9Kvze+u8CruYMmhHw6Zgy3GRX2S+Ed5oSokDEK5vPEwGGKnmuXua9tmFhomeAnhgJnL4DCna3TiNuGrBTQ==} + resolution: {integrity: sha1-dEMO/0HSaBjCP5gmsEXYx1cy6us=} cpu: [x64] os: [win32] @@ -10876,11 +11043,11 @@ packages: engines: {node: '>=10.13'} '@zkochan/js-yaml@0.0.11': - resolution: {integrity: sha512-SO+h5Jg079r2JvGle0jbdtk1EY7ppu6TGzmfWTp3Gy61IEb1OVKBocJ6ydTn4++nYFNfRKYenI2MniZQwsM9KQ==} + resolution: {integrity: sha1-T2aH2CGxW1MG1Z391Mu32K5wHI0=} hasBin: true '@zkochan/js-yaml@0.0.6': - resolution: {integrity: sha512-nzvgl3VfhcELQ8LyVrYOru+UtAy1nrygk2+AGbTm8a5YcO6o8lSjAT+pfg3vJWxIoZKOUhrK6UU7xW/+00kQrg==} + resolution: {integrity: sha1-l18LMG5wXii4BooHc3+kbT/ASCY=} hasBin: true '@zkochan/rimraf@2.1.3': @@ -10892,7 +11059,7 @@ packages: engines: {node: '>=18.12'} '@zkochan/which@2.0.3': - resolution: {integrity: sha512-C1ReN7vt2/2O0fyTsx5xnbQuxBrmG5NMSbcIkPKCCfCTJgpZBsuRYzFXHj3nVq8vTfK7vxHUmzfCpSHgO7j4rg==} + resolution: {integrity: sha1-okOQNZOQ04wVH6YHgbNiC8WhMtA=} engines: {node: '>= 8'} hasBin: true @@ -11532,7 +11699,7 @@ packages: resolution: {integrity: sha512-D4H1y5KYwpJgK8wk1Cue5LLPgmwHKYSChkbspQg5JtVuR5ulGckxfR62H3AE9UDkdMC8yyXlqYihuz3Aqg2XZg==} bindings@1.5.0: - resolution: {integrity: sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==} + resolution: {integrity: sha1-EDU8npRTNLwFEabZCzj7x8nFBN8=} bl@4.1.0: resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} @@ -11993,7 +12160,7 @@ packages: engines: {node: '>= 12'} commander@9.5.0: - resolution: {integrity: sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==} + resolution: {integrity: sha1-vAjR61zt98y3l6lhmdQce8PmDTA=} engines: {node: ^12.20.0 || >=14} comment-parser@1.4.1: @@ -12179,7 +12346,7 @@ packages: hasBin: true cross-spawn@6.0.6: - resolution: {integrity: sha512-VqCUuhcd1iB+dsv8gxPttb5iZh/D0iubSP21g36KXdEuf6I5JiioesUVjpCdHV9MZRUfVFlvwtIUyPfxo5trtw==} + resolution: {integrity: sha1-MNDvoHEt2361p24ehyG/+vprXVc=} engines: {node: '>=4.8'} cross-spawn@7.0.6: @@ -12704,7 +12871,7 @@ packages: engines: {node: '>= 0.8'} encoding@0.1.13: - resolution: {integrity: sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==} + resolution: {integrity: sha1-VldK/deR9UqOmyeFwFgqLSYhD6k=} end-of-stream@1.4.5: resolution: {integrity: sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==} @@ -12812,97 +12979,97 @@ packages: resolution: {integrity: sha512-Twf7I2v4/1tLoIXMT8HlqaBSS5H2wQTs2wx3MNYCI8K1R1/clXyCazrcVCPm/FuO9cyV8+leEaZOWD5C253NDg==} esbuild-android-64@0.14.54: - resolution: {integrity: sha512-Tz2++Aqqz0rJ7kYBfz+iqyE3QMycD4vk7LBRyWaAVFgFtQ/O8EJOnVmTOiDWYZ/uYzB4kvP+bqejYdVKzE5lAQ==} + resolution: {integrity: sha1-UF9BgyiEMTu6/7J3BLi8qi2GFr4=} engines: {node: '>=12'} cpu: [x64] os: [android] esbuild-android-arm64@0.14.54: - resolution: {integrity: sha512-F9E+/QDi9sSkLaClO8SOV6etqPd+5DgJje1F9lOWoNncDdOBL2YF59IhsWATSt0TLZbYCf3pNlTHvVV5VfHdvg==} + resolution: {integrity: sha1-jOadfKuklkbgCZaP5XVKIamHF3E=} engines: {node: '>=12'} cpu: [arm64] os: [android] esbuild-darwin-64@0.14.54: - resolution: {integrity: sha512-jtdKWV3nBviOd5v4hOpkVmpxsBy90CGzebpbO9beiqUYVMBtSc0AL9zGftFuBon7PNDcdvNCEuQqw2x0wP9yug==} + resolution: {integrity: sha1-JLpnuajLiQo8CNkBj4h8wiHN2iU=} engines: {node: '>=12'} cpu: [x64] os: [darwin] esbuild-darwin-arm64@0.14.54: - resolution: {integrity: sha512-OPafJHD2oUPyvJMrsCvDGkRrVCar5aVyHfWGQzY1dWnzErjrDuSETxwA2HSsyg2jORLY8yBfzc1MIpUkXlctmw==} + resolution: {integrity: sha1-P3zbeIiO4F5IjSUKK9qrH6Zxv3M=} engines: {node: '>=12'} cpu: [arm64] os: [darwin] esbuild-freebsd-64@0.14.54: - resolution: {integrity: sha512-OKwd4gmwHqOTp4mOGZKe/XUlbDJ4Q9TjX0hMPIDBUWWu/kwhBAudJdBoxnjNf9ocIB6GN6CPowYpR/hRCbSYAg==} + resolution: {integrity: sha1-CSUPmXpW7UZQ8+GXnJBf/EC76U0=} engines: {node: '>=12'} cpu: [x64] os: [freebsd] esbuild-freebsd-arm64@0.14.54: - resolution: {integrity: sha512-sFwueGr7OvIFiQT6WeG0jRLjkjdqWWSrfbVwZp8iMP+8UHEHRBvlaxL6IuKNDwAozNUmbb8nIMXa7oAOARGs1Q==} + resolution: {integrity: sha1-uvtG7QT8X5fL2wFthpR6eVefjkg=} engines: {node: '>=12'} cpu: [arm64] os: [freebsd] esbuild-linux-32@0.14.54: - resolution: {integrity: sha512-1ZuY+JDI//WmklKlBgJnglpUL1owm2OX+8E1syCD6UAxcMM/XoWd76OHSjl/0MR0LisSAXDqgjT3uJqT67O3qw==} + resolution: {integrity: sha1-4qjEqO/cNVQFMlAz/OvrlB94H+U=} engines: {node: '>=12'} cpu: [ia32] os: [linux] esbuild-linux-64@0.14.54: - resolution: {integrity: sha512-EgjAgH5HwTbtNsTqQOXWApBaPVdDn7XcK+/PtJwZLT1UmpLoznPd8c5CxqsH2dQK3j05YsB3L17T8vE7cp4cCg==} + resolution: {integrity: sha1-3l/boclWZs9yNp9StAsDvnEiZlI=} engines: {node: '>=12'} cpu: [x64] os: [linux] esbuild-linux-arm64@0.14.54: - resolution: {integrity: sha512-WL71L+0Rwv+Gv/HTmxTEmpv0UgmxYa5ftZILVi2QmZBgX3q7+tDeOQNqGtdXSdsL8TQi1vIaVFHUPDe0O0kdig==} + resolution: {integrity: sha1-2uTNQq6Xh0aLalwVjaTIToOwzos=} engines: {node: '>=12'} cpu: [arm64] os: [linux] esbuild-linux-arm@0.14.54: - resolution: {integrity: sha512-qqz/SjemQhVMTnvcLGoLOdFpCYbz4v4fUo+TfsWG+1aOu70/80RV6bgNpR2JCrppV2moUQkww+6bWxXRL9YMGw==} + resolution: {integrity: sha1-osHf9tDyHb6PxpmKEiZ1Uz3fzVk=} engines: {node: '>=12'} cpu: [arm] os: [linux] esbuild-linux-mips64le@0.14.54: - resolution: {integrity: sha512-qTHGQB8D1etd0u1+sB6p0ikLKRVuCWhYQhAHRPkO+OF3I/iSlTKNNS0Lh2Oc0g0UFGguaFZZiPJdJey3AGpAlw==} + resolution: {integrity: sha1-2ZGOnky5cvjW2ujoZVv57hMe2jQ=} engines: {node: '>=12'} cpu: [mips64el] os: [linux] esbuild-linux-ppc64le@0.14.54: - resolution: {integrity: sha512-j3OMlzHiqwZBDPRCDFKcx595XVfOfOnv68Ax3U4UKZ3MTYQB5Yz3X1mn5GnodEVYzhtZgxEBidLWeIs8FDSfrQ==} + resolution: {integrity: sha1-P5oPbUEHP7GmQGgIRcfeUplfE34=} engines: {node: '>=12'} cpu: [ppc64] os: [linux] esbuild-linux-riscv64@0.14.54: - resolution: {integrity: sha512-y7Vt7Wl9dkOGZjxQZnDAqqn+XOqFD7IMWiewY5SPlNlzMX39ocPQlOaoxvT4FllA5viyV26/QzHtvTjVNOxHZg==} + resolution: {integrity: sha1-YYhTwCgXimGDe8eZ0gE9RpXkUcg=} engines: {node: '>=12'} cpu: [riscv64] os: [linux] esbuild-linux-s390x@0.14.54: - resolution: {integrity: sha512-zaHpW9dziAsi7lRcyV4r8dhfG1qBidQWUXweUjnw+lliChJqQr+6XD71K41oEIC3Mx1KStovEmlzm+MkGZHnHA==} + resolution: {integrity: sha1-0YhcTFp2u7Wg/hguLIxg654p8qY=} engines: {node: '>=12'} cpu: [s390x] os: [linux] esbuild-netbsd-64@0.14.54: - resolution: {integrity: sha512-PR01lmIMnfJTgeU9VJTDY9ZerDWVFIUzAtJuDHwwceppW7cQWjBBqP48NdeRtoP04/AtO9a7w3viI+PIDr6d+w==} + resolution: {integrity: sha1-aa6Rei/yQbffHb8iuvBL0zA0noE=} engines: {node: '>=12'} cpu: [x64] os: [netbsd] esbuild-openbsd-64@0.14.54: - resolution: {integrity: sha512-Qyk7ikT2o7Wu76UsvvDS5q0amJvmRzDyVlL0qf5VLsLchjCa1+IAvd8kTBgUxD7VBUUVgItLkk609ZHUc1oCaw==} + resolution: {integrity: sha1-20yElSh6NQpnkN4i7eokelfF1Hs=} engines: {node: '>=12'} cpu: [x64] os: [openbsd] @@ -12919,25 +13086,25 @@ packages: esbuild: '*' esbuild-sunos-64@0.14.54: - resolution: {integrity: sha512-28GZ24KmMSeKi5ueWzMcco6EBHStL3B6ubM7M51RmPwXQGLe0teBGJocmWhgwccA1GeFXqxzILIxXpHbl9Q/Kw==} + resolution: {integrity: sha1-VCh+49pz04RLchwhvIDB3H4b99o=} engines: {node: '>=12'} cpu: [x64] os: [sunos] esbuild-windows-32@0.14.54: - resolution: {integrity: sha512-T+rdZW19ql9MjS7pixmZYVObd9G7kcaZo+sETqNH4RCkuuYSuv9AGHUVnPoP9hhuE1WM1ZimHz1CIBHBboLU7w==} + resolution: {integrity: sha1-+Kr5pWZ2MLQPD7OqN78Bu9NAzjE=} engines: {node: '>=12'} cpu: [ia32] os: [win32] esbuild-windows-64@0.14.54: - resolution: {integrity: sha512-AoHTRBUuYwXtZhjXZbA1pGfTo8cJo3vZIcWGLiUcTNgHpJJMC1rVA44ZereBHMJtotyN71S8Qw0npiCIkW96cQ==} + resolution: {integrity: sha1-v1S1G9PpsPGIb/2yJKQXYDHqCvQ=} engines: {node: '>=12'} cpu: [x64] os: [win32] esbuild-windows-arm64@0.14.54: - resolution: {integrity: sha512-M0kuUvXhot1zOISQGXwWn6YtS+Y/1RT9WrVIOywZnJHo3jCDyewAc79aKNQWFCQm+xNHVTq9h8dZKvygoXQQRg==} + resolution: {integrity: sha1-k30VZ1oV5LDk+v26o6Aad2or6YI=} engines: {node: '>=12'} cpu: [arm64] os: [win32] @@ -13232,11 +13399,11 @@ packages: resolution: {integrity: sha512-nQn+hI3yp+oD0huYhKwvYI32+JFeq+XkNcD1GAo3Y/MjxsfVGmrrzrnzjWiNY6f+pUCP440fThsFh5gZrRAU/w==} execa@1.0.0: - resolution: {integrity: sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==} + resolution: {integrity: sha1-xiNqW7TfbW8V6I5/AXeYIWdJ3dg=} engines: {node: '>=6'} execa@5.1.1: - resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} + resolution: {integrity: sha1-+ArZy/Qpj3vR1MlVXCHpN0HEEd0=} engines: {node: '>=10'} exit-x@0.2.2: @@ -13418,7 +13585,7 @@ packages: resolution: {integrity: sha512-IzF5MBq+5CR0jXx5RxPe4BICl/oEhBSXKaL9fLhAXrIfIUS77Hr4vzrYyqYMHN6uTt+BOqi3fDCTjjEBCjERKw==} file-uri-to-path@1.0.0: - resolution: {integrity: sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==} + resolution: {integrity: sha1-VTp7hEb/b2hDWcRF8eN6BdrMM90=} fill-range@4.0.0: resolution: {integrity: sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==} @@ -13624,18 +13791,18 @@ packages: resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} fsevents@1.2.13: - resolution: {integrity: sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==} + resolution: {integrity: sha1-8yXLBFVZJCi88Rs4M3DvcOO/zDg=} engines: {node: '>= 4.0'} os: [darwin] deprecated: Upgrade to fsevents v2 to mitigate potential security issues fsevents@2.3.2: - resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} + resolution: {integrity: sha1-ilJveLj99GI7cJ4Ll1xSwkwC/Ro=} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} os: [darwin] fsevents@2.3.3: - resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + resolution: {integrity: sha1-ysZAd4XQNnWipeGlMFxpezR9kNY=} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} os: [darwin] @@ -13706,15 +13873,15 @@ packages: engines: {node: '>= 0.4'} get-stream@4.1.0: - resolution: {integrity: sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==} + resolution: {integrity: sha1-wbJVV189wh1Zv8ec09K0axw6VLU=} engines: {node: '>=6'} get-stream@5.2.0: - resolution: {integrity: sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==} + resolution: {integrity: sha1-SWaheV7lrOZecGxLe+txJX1uItM=} engines: {node: '>=8'} get-stream@6.0.1: - resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} + resolution: {integrity: sha1-omLY7vZ6ztV8KFKtYWdSakPL97c=} engines: {node: '>=10'} get-symbol-description@1.1.0: @@ -13848,7 +14015,7 @@ packages: resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} graphql@16.13.2: - resolution: {integrity: sha512-5bJ+nf/UCpAjHM8i06fl7eLyVC9iuNAjm9qzkiu2ZGhM0VscSvS6WDPfAwkdkBuoXGM9FJSbKl6wylMwP9Ktig==} + resolution: {integrity: sha1-TStz31eWsgHxvCdl9dcGf2ictV8=} engines: {node: ^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0} gzip-size@6.0.0: @@ -14084,7 +14251,7 @@ packages: engines: {node: '>= 14'} human-signals@2.1.0: - resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} + resolution: {integrity: sha1-3JH8ukLk0G5Kuu0zs+ejwC9RTqA=} engines: {node: '>=10.17.0'} humanize-ms@1.2.1: @@ -14481,11 +14648,11 @@ packages: engines: {node: '>= 0.4'} is-stream@1.1.0: - resolution: {integrity: sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==} + resolution: {integrity: sha1-EtSj3U5o4Lec6428hBc66A2RykQ=} engines: {node: '>=0.10.0'} is-stream@2.0.1: - resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} + resolution: {integrity: sha1-+sHj1TuXrVqdCunO8jifWBClwHc=} engines: {node: '>=8'} is-string@1.1.1: @@ -14558,7 +14725,7 @@ packages: resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} isexe@2.0.0: - resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + resolution: {integrity: sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=} isobject@2.1.0: resolution: {integrity: sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA==} @@ -15039,7 +15206,7 @@ packages: resolution: {integrity: sha512-o5kvLbuTF+o326CMVYpjlaykxqYP9DphFQZ2ZpgrvBouyvOxyEB7oqe8nOLFpiV5VCtz0D3pt8gXQYWpLpBnmA==} keytar@7.9.0: - resolution: {integrity: sha512-VPD8mtVtm5JNtA2AErl6Chp06JBfy7diFQ7TQQhdpWOl6MrCRB+eRbvAZUsbGQS9kiMq0coJsy0W0vHpDCkWsQ==} + resolution: {integrity: sha1-TGIlcI9RtQy/d8Wq6BchlkwpGMs=} keyv@4.5.4: resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} @@ -15402,7 +15569,7 @@ packages: engines: {node: '>=18'} merge-stream@2.0.0: - resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} + resolution: {integrity: sha1-UoI2KaFN0AyXcPtq1H3GMQ8sH2A=} merge2@1.4.1: resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} @@ -15454,11 +15621,11 @@ packages: hasBin: true mimic-fn@2.1.0: - resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} + resolution: {integrity: sha1-ftLCzMyvhNP/y3pptXcR/CCDQBs=} engines: {node: '>=6'} mimic-fn@3.1.0: - resolution: {integrity: sha512-Ysbi9uYW9hFyfrThdDEQuykN4Ey6BuwPD2kpI5ES/nFTDn/98yxYNLZJcgUAKPT/mcrLLKaGzJR9YVxJrIdASQ==} + resolution: {integrity: sha1-ZXVRRbvz42lUuUnBZFBCdFHVynQ=} engines: {node: '>=8'} mimic-response@1.0.1: @@ -15607,7 +15774,7 @@ packages: resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} nan@2.26.2: - resolution: {integrity: sha512-0tTvBTYkt3tdGw22nrAy50x7gpbGCCFH3AFcyS5WiUu7Eu4vWlri1woE6qHBSfy11vksDqkiwjOnlR7WV8G1Hw==} + resolution: {integrity: sha1-Ll4ldkIkxze5iXeQtXwylNTc7pw=} nanoid@3.3.11: resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} @@ -15757,11 +15924,11 @@ packages: hasBin: true npm-run-path@2.0.2: - resolution: {integrity: sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==} + resolution: {integrity: sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=} engines: {node: '>=4'} npm-run-path@4.0.1: - resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} + resolution: {integrity: sha1-t+zR5e1T2o43pV4cImnguX7XSOo=} engines: {node: '>=8'} npmlog@4.1.2: @@ -15872,7 +16039,7 @@ packages: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} onetime@5.1.2: - resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} + resolution: {integrity: sha1-0Oluu1awdHbfHdnEgG5SN5hcpF4=} engines: {node: '>=6'} open@10.2.0: @@ -15917,6 +16084,19 @@ packages: resolution: {integrity: sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==} engines: {node: '>= 0.4'} + oxlint@1.71.0: + resolution: {integrity: sha512-U1m1X+C0vDj7DC1e13IoZULzEcPczE7UOMTs8VlZGHUEIUaSTZKo5qkPsQEfzpgnQ29Pea/w3Xntk62UCecxZw==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + peerDependencies: + oxlint-tsgolint: '>=0.22.1' + vite-plus: '*' + peerDependenciesMeta: + oxlint-tsgolint: + optional: true + vite-plus: + optional: true + p-all@2.1.0: resolution: {integrity: sha512-HbZxz5FONzz/z2gJfk6bFca0BCiSRF8jU3yCsWOen/vR6lZjfPOu/e7L3uFzTW1i0H8TlC3vqQstEJPQL4/uLA==} engines: {node: '>=6'} @@ -16088,15 +16268,15 @@ packages: engines: {node: '>=0.10.0'} path-key@2.0.1: - resolution: {integrity: sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==} + resolution: {integrity: sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=} engines: {node: '>=4'} path-key@3.1.1: - resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + resolution: {integrity: sha1-WB9q3mWMu6ZaDTOA3ndTKVBU83U=} engines: {node: '>=8'} path-name@1.0.0: - resolution: {integrity: sha512-/dcAb5vMXH0f51yvMuSUqFpxUcA8JelbRmE5mW/p4CUJxrNgK24IkstnV7ENtg2IDGBOu6izKTG6eilbnbNKWQ==} + resolution: {integrity: sha1-jKBjpj3nmC36lXYO2v/RAhRJTyQ=} path-parse@1.0.7: resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} @@ -16690,7 +16870,7 @@ packages: resolution: {integrity: sha512-SbiLPU40JuJniHexQSAgad32hfwd+DRUdwF2PlVuI5RZD0/vahUco7R8vD86J/tcEKKF9vZrUVwgtmGCqlCKyA==} ramda@0.28.0: - resolution: {integrity: sha512-9QnLuG/kPVgWvMQ4aODhsBUFKOUmnbUnsSXACv+NCQZcHbeb+v8Lodp8OVxtRULN1/xOyYLLaL6npE6dMq5QTA==} + resolution: {integrity: sha1-rNeFaQEAM36LBjyrNHABm+QnzJc=} randombytes@2.1.0: resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} @@ -17171,7 +17351,7 @@ packages: resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} safe-execa@0.1.2: - resolution: {integrity: sha512-vdTshSQ2JsRCgT8eKZWNJIL26C6bVqy1SOmuCMlKHegVeo8KYRobRrefOdUq9OozSPUUiSxrylteeRmLOMFfWg==} + resolution: {integrity: sha1-L7sKbxoAx6RexwM/gmWXV/kb6Mc=} engines: {node: '>=12'} safe-push-apply@1.0.0: @@ -17198,121 +17378,121 @@ packages: hasBin: true sass-embedded-android-arm64@1.85.1: - resolution: {integrity: sha512-27oRheqNA3SJM2hAxpVbs7mCKUwKPWmEEhyiNFpBINb5ELVLg+Ck5RsGg+SJmo130ul5YX0vinmVB5uPWc8X5w==} + resolution: {integrity: sha1-HKnF4G6hqOz3T/f76mcXBs/lAyA=} engines: {node: '>=14.0.0'} cpu: [arm64] os: [android] sass-embedded-android-arm@1.85.1: - resolution: {integrity: sha512-GkcgUGMZtEF9gheuE1dxCU0ZSAifuaFXi/aX7ZXvjtdwmTl9Zc/OHR9oiUJkc8IW9UI7H8TuwlTAA8+SwgwIeQ==} + resolution: {integrity: sha1-87zVn7BcKTGuoSaUlqCYj4C5Nq8=} engines: {node: '>=14.0.0'} cpu: [arm] os: [android] sass-embedded-android-ia32@1.85.1: - resolution: {integrity: sha512-f3x16NyRgtXFksIaO/xXKrUhttUBv8V0XsAR2Dhdb/yz4yrDrhzw9Wh8fmw7PlQqECcQvFaoDr3XIIM6lKzasw==} + resolution: {integrity: sha1-C0jPGwoVfAZtjWyPTHz102trIps=} engines: {node: '>=14.0.0'} cpu: [ia32] os: [android] sass-embedded-android-riscv64@1.85.1: - resolution: {integrity: sha512-IP6OijpJ8Mqo7XqCe0LsuZVbAxEFVboa0kXqqR5K55LebEplsTIA2GnmRyMay3Yr/2FVGsZbCb6Wlgkw23eCiA==} + resolution: {integrity: sha1-sgJKrrdUVAEb0qOujuTKwnO15xE=} engines: {node: '>=14.0.0'} cpu: [riscv64] os: [android] sass-embedded-android-x64@1.85.1: - resolution: {integrity: sha512-Mh7CA53wR3ADvXAYipFc/R3vV4PVOzoKwWzPxmq+7i8UZrtsVjKONxGtqWe9JG1mna0C9CRZAx0sv/BzbOJxWg==} + resolution: {integrity: sha1-xTkYMMuzw3jlF3vA4D6Up4LNHME=} engines: {node: '>=14.0.0'} cpu: [x64] os: [android] sass-embedded-darwin-arm64@1.85.1: - resolution: {integrity: sha512-msWxzhvcP9hqGVegxVePVEfv9mVNTlUgGr6k7O7Ihji702mbtrH/lKwF4aRkkt4g1j7tv10+JtQXmTNi/pi9kA==} + resolution: {integrity: sha1-eay7aGfQFolvhDlxvfoKx24QHfg=} engines: {node: '>=14.0.0'} cpu: [arm64] os: [darwin] sass-embedded-darwin-x64@1.85.1: - resolution: {integrity: sha512-J4UFHUiyI9Z+mwYMwz11Ky9TYr3hY1fCxeQddjNGL/+ovldtb0yAIHvoVM0BGprQDm5JqhtUk8KyJ3RMJqpaAA==} + resolution: {integrity: sha1-FH7PSb8tGC295s7zN6WKBbepOrE=} engines: {node: '>=14.0.0'} cpu: [x64] os: [darwin] sass-embedded-linux-arm64@1.85.1: - resolution: {integrity: sha512-jGadetB03BMFG2rq3OXub/uvC/lGpbQOiLGEz3NLb2nRZWyauRhzDtvZqkr6BEhxgIWtMtz2020yD8ZJSw/r2w==} + resolution: {integrity: sha1-XHtcJ0lTKZZjClUS0OG/bYRyrNM=} engines: {node: '>=14.0.0'} cpu: [arm64] os: [linux] sass-embedded-linux-arm@1.85.1: - resolution: {integrity: sha512-X0fDh95nNSw1wfRlnkE4oscoEA5Au4nnk785s9jghPFkTBg+A+5uB6trCjf0fM22+Iw6kiP4YYmDdw3BqxAKLQ==} + resolution: {integrity: sha1-iZy6lLc+sRn2Q0aInkZt4xtvXTw=} engines: {node: '>=14.0.0'} cpu: [arm] os: [linux] sass-embedded-linux-ia32@1.85.1: - resolution: {integrity: sha512-7HlYY90d9mitDtNi5s+S+5wYZrTVbkBH2/kf7ixrzh2BFfT0YM81UHLJRnGX93y9aOMBL6DSZAIfkt1RsV9bkQ==} + resolution: {integrity: sha1-8bpT8DQ4ljWv6cEFm8Nqd5NkIbg=} engines: {node: '>=14.0.0'} cpu: [ia32] os: [linux] sass-embedded-linux-musl-arm64@1.85.1: - resolution: {integrity: sha512-FLkIT0p18XOkR6wryJ13LqGBDsrYev2dRk9dtiU18NCpNXruKsdBQ1ZnWHVKB3h1dA9lFyEEisC0sooKdNfeOQ==} + resolution: {integrity: sha1-sUziYVx6tGJuiMuiZW+Ro6dI4c4=} engines: {node: '>=14.0.0'} cpu: [arm64] os: [linux] sass-embedded-linux-musl-arm@1.85.1: - resolution: {integrity: sha512-5vcdEqE8QZnu6i6shZo7x2N36V7YUoFotWj2rGekII5ty7Nkaj+VtZhUEOp9tAzEOlaFuDp5CyO1kUCvweT64A==} + resolution: {integrity: sha1-Qo5eKZqf9N/SC1eGHSRAQotfvfY=} engines: {node: '>=14.0.0'} cpu: [arm] os: [linux] sass-embedded-linux-musl-ia32@1.85.1: - resolution: {integrity: sha512-N1093T84zQJor1yyIAdYScB5eAuQarGK1tKgZ4uTnxVlgA7Xi1lXV8Eh7ox9sDqKCaWkVQ3MjqU26vYRBeRWyw==} + resolution: {integrity: sha1-BwYJr9mc0Pnq5yGGyfSi0M32lE0=} engines: {node: '>=14.0.0'} cpu: [ia32] os: [linux] sass-embedded-linux-musl-riscv64@1.85.1: - resolution: {integrity: sha512-WRsZS/7qlfYXsa93FBpSruieuURIu7ySfFhzYfF1IbKrNAGwmbduutkHZh2ddm5/vQMvQ0Rdosgv+CslaQHMcw==} + resolution: {integrity: sha1-D0JkvkAnfXzBgUnJ4PA68JVi5vc=} engines: {node: '>=14.0.0'} cpu: [riscv64] os: [linux] sass-embedded-linux-musl-x64@1.85.1: - resolution: {integrity: sha512-+OlLIilA5TnP0YEqTQ8yZtkW+bJIQYvzoGoNLUEskeyeGuOiIyn2CwL6G4JQB4xZQFaxPHb7JD3EueFkQbH0Pw==} + resolution: {integrity: sha1-tUteH2RtHwwJ2d9+Dm1JYNbtf6E=} engines: {node: '>=14.0.0'} cpu: [x64] os: [linux] sass-embedded-linux-riscv64@1.85.1: - resolution: {integrity: sha512-mKKlOwMGLN7yP1p0gB5yG/HX4fYLnpWaqstNuOOXH+fOzTaNg0+1hALg0H0CDIqypPO74M5MS9T6FAJZGdT6dQ==} + resolution: {integrity: sha1-Jxh3Mwf5T+uBXk4vu1qnMiao03U=} engines: {node: '>=14.0.0'} cpu: [riscv64] os: [linux] sass-embedded-linux-x64@1.85.1: - resolution: {integrity: sha512-uKRTv0z8NgtHV7xSren78+yoWB79sNi7TMqI7Bxd8fcRNIgHQSA8QBdF8led2ETC004hr8h71BrY60RPO+SSvA==} + resolution: {integrity: sha1-BmTMiGuHgYrJ0pv06fKZ/mxj9SQ=} engines: {node: '>=14.0.0'} cpu: [x64] os: [linux] sass-embedded-win32-arm64@1.85.1: - resolution: {integrity: sha512-/GMiZXBOc6AEMBC3g25Rp+x8fq9Z6Ql7037l5rajBPhZ+DdFwtdHY0Ou3oIU6XuWUwD06U3ii4XufXVFhsP6PA==} + resolution: {integrity: sha1-0Ht1X4QI193huDCNOlf7/NqdkJw=} engines: {node: '>=14.0.0'} cpu: [arm64] os: [win32] sass-embedded-win32-ia32@1.85.1: - resolution: {integrity: sha512-L+4BWkKKBGFOKVQ2PQ5HwFfkM5FvTf1Xx2VSRvEWt9HxPXp6SPDho6zC8fqNQ3hSjoaoASEIJcSvgfdQYO0gdg==} + resolution: {integrity: sha1-Xl8W4aMPjfMRSKr2WncimNcDfXA=} engines: {node: '>=14.0.0'} cpu: [ia32] os: [win32] sass-embedded-win32-x64@1.85.1: - resolution: {integrity: sha512-/FO0AGKWxVfCk4GKsC0yXWBpUZdySe3YAAbQQL0lL6xUd1OiUY8Kow6g4Kc1TB/+z0iuQKKTqI/acJMEYl4iTQ==} + resolution: {integrity: sha1-dY+5bBbncmWkt/JHSkOWLXHvX/0=} engines: {node: '>=14.0.0'} cpu: [x64] os: [win32] @@ -17554,7 +17734,7 @@ packages: engines: {node: '>= 0.4'} signal-exit@3.0.7: - resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} + resolution: {integrity: sha1-qaF2f4r4QVURTqq9c/mSc8j1mtk=} signal-exit@4.1.0: resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} @@ -17881,7 +18061,7 @@ packages: engines: {node: '>=0.10.0'} strip-final-newline@2.0.0: - resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} + resolution: {integrity: sha1-ibhS+y/L6Tb29LMYevsKEsGrWK0=} engines: {node: '>=6'} strip-indent@3.0.0: @@ -18369,7 +18549,7 @@ packages: resolution: {integrity: sha512-yDJTmhydvl5lJzBmy/hyOAA0d+aqCBuwl818haVdYCRrWV84o7YyeVm4QlVHStqNrrJSTb6jKuFAVqAFsr+K3Q==} uglify-js@3.19.3: - resolution: {integrity: sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==} + resolution: {integrity: sha1-gjFem7xvKyWIiFis0f/4RBA1t38=} engines: {node: '>=0.8.0'} hasBin: true @@ -18642,7 +18822,7 @@ packages: resolution: {integrity: sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==} watchpack-chokidar2@2.0.1: - resolution: {integrity: sha512-nCFfBIPKr5Sh61s4LPpy1Wtfi0HE8isJ3d2Yb5/Ppw2P2B/3eVSEBjKfN0fmHJSK14+31KwMKmcrzs2GM4P0Ww==} + resolution: {integrity: sha1-OFAAcu5uzmbzdpk2lQ6hdxvhyVc=} watchpack@1.7.5: resolution: {integrity: sha512-9P3MWk6SrKjHsGkLT2KHXdQ/9SNkyoJbabxnKOoJepsvJjJG8uYTR3yTPxPQvNDI3w4Nz1xnE0TLHK4RIVe/MQ==} @@ -23622,6 +23802,63 @@ snapshots: mkdirp: 1.0.4 rimraf: 3.0.2 + '@oxlint/binding-android-arm-eabi@1.71.0': + optional: true + + '@oxlint/binding-android-arm64@1.71.0': + optional: true + + '@oxlint/binding-darwin-arm64@1.71.0': + optional: true + + '@oxlint/binding-darwin-x64@1.71.0': + optional: true + + '@oxlint/binding-freebsd-x64@1.71.0': + optional: true + + '@oxlint/binding-linux-arm-gnueabihf@1.71.0': + optional: true + + '@oxlint/binding-linux-arm-musleabihf@1.71.0': + optional: true + + '@oxlint/binding-linux-arm64-gnu@1.71.0': + optional: true + + '@oxlint/binding-linux-arm64-musl@1.71.0': + optional: true + + '@oxlint/binding-linux-ppc64-gnu@1.71.0': + optional: true + + '@oxlint/binding-linux-riscv64-gnu@1.71.0': + optional: true + + '@oxlint/binding-linux-riscv64-musl@1.71.0': + optional: true + + '@oxlint/binding-linux-s390x-gnu@1.71.0': + optional: true + + '@oxlint/binding-linux-x64-gnu@1.71.0': + optional: true + + '@oxlint/binding-linux-x64-musl@1.71.0': + optional: true + + '@oxlint/binding-openharmony-arm64@1.71.0': + optional: true + + '@oxlint/binding-win32-arm64-msvc@1.71.0': + optional: true + + '@oxlint/binding-win32-ia32-msvc@1.71.0': + optional: true + + '@oxlint/binding-win32-x64-msvc@1.71.0': + optional: true + '@peculiar/asn1-cms@2.6.1': dependencies: '@peculiar/asn1-schema': 2.6.0 @@ -30811,7 +31048,7 @@ snapshots: eslint@8.57.1: dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@8.57.1) + '@eslint-community/eslint-utils': 4.9.1(eslint@9.37.0) '@eslint-community/regexpp': 4.12.2 '@eslint/eslintrc': 2.1.4 '@eslint/js': 8.57.1 @@ -34660,6 +34897,28 @@ snapshots: object-keys: 1.1.1 safe-push-apply: 1.0.0 + oxlint@1.71.0: + optionalDependencies: + '@oxlint/binding-android-arm-eabi': 1.71.0 + '@oxlint/binding-android-arm64': 1.71.0 + '@oxlint/binding-darwin-arm64': 1.71.0 + '@oxlint/binding-darwin-x64': 1.71.0 + '@oxlint/binding-freebsd-x64': 1.71.0 + '@oxlint/binding-linux-arm-gnueabihf': 1.71.0 + '@oxlint/binding-linux-arm-musleabihf': 1.71.0 + '@oxlint/binding-linux-arm64-gnu': 1.71.0 + '@oxlint/binding-linux-arm64-musl': 1.71.0 + '@oxlint/binding-linux-ppc64-gnu': 1.71.0 + '@oxlint/binding-linux-riscv64-gnu': 1.71.0 + '@oxlint/binding-linux-riscv64-musl': 1.71.0 + '@oxlint/binding-linux-s390x-gnu': 1.71.0 + '@oxlint/binding-linux-x64-gnu': 1.71.0 + '@oxlint/binding-linux-x64-musl': 1.71.0 + '@oxlint/binding-openharmony-arm64': 1.71.0 + '@oxlint/binding-win32-arm64-msvc': 1.71.0 + '@oxlint/binding-win32-ia32-msvc': 1.71.0 + '@oxlint/binding-win32-x64-msvc': 1.71.0 + p-all@2.1.0: dependencies: p-map: 2.1.0 diff --git a/common/config/subspaces/default/repo-state.json b/common/config/subspaces/default/repo-state.json index eb492e850ed..fb0817d998a 100644 --- a/common/config/subspaces/default/repo-state.json +++ b/common/config/subspaces/default/repo-state.json @@ -1,5 +1,5 @@ // DO NOT MODIFY THIS FILE MANUALLY BUT DO COMMIT IT. It is generated and used by Rush. { - "pnpmShrinkwrapHash": "288ee1cccceca305122bc3d4b1eb550efbcb2a0b", + "pnpmShrinkwrapHash": "8541b9dfa424a16f78b9f5eb17e757fb548027d3", "preferredVersionsHash": "029c99bd6e65c5e1f25e2848340509811ff9753c" } diff --git a/heft-plugins/heft-oxlint-plugin/.npmignore b/heft-plugins/heft-oxlint-plugin/.npmignore new file mode 100644 index 00000000000..f7a40e10213 --- /dev/null +++ b/heft-plugins/heft-oxlint-plugin/.npmignore @@ -0,0 +1,36 @@ +# THIS IS A STANDARD TEMPLATE FOR .npmignore FILES IN THIS REPO. + +# Ignore all files by default, to avoid accidentally publishing unintended files. +* + +# Use negative patterns to bring back the specific things we want to publish. +!/bin/** +!/lib/** +!/lib-*/** +!/dist/** +!/includes/** + +!CHANGELOG.md +!CHANGELOG.json +!heft-plugin.json +!rush-plugin-manifest.json +!ThirdPartyNotice.txt + +# Ignore certain patterns that should not get published. +/dist/*.stats.* +/lib/**/test/ +/lib-*/**/test/ +*.test.js +*.test.[cm]js +*.test.d.ts +*.test.d.[cm]ts + +# NOTE: These don't need to be specified, because NPM includes them automatically. +# +# package.json +# README.md +# LICENSE + +# --------------------------------------------------------------------------- +# DO NOT MODIFY ABOVE THIS LINE! Add any project-specific overrides below. +# --------------------------------------------------------------------------- diff --git a/heft-plugins/heft-oxlint-plugin/LICENSE b/heft-plugins/heft-oxlint-plugin/LICENSE new file mode 100644 index 00000000000..603a14c7a67 --- /dev/null +++ b/heft-plugins/heft-oxlint-plugin/LICENSE @@ -0,0 +1,24 @@ +@rushstack/heft-oxlint-plugin + +Copyright (c) Microsoft Corporation. All rights reserved. + +MIT License + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/heft-plugins/heft-oxlint-plugin/README.md b/heft-plugins/heft-oxlint-plugin/README.md new file mode 100644 index 00000000000..1a80f547996 --- /dev/null +++ b/heft-plugins/heft-oxlint-plugin/README.md @@ -0,0 +1,17 @@ +# @rushstack/heft-oxlint-plugin + +This is a Heft plugin to run [oxlint](https://oxc.rs/docs/guide/usage/linter), the fast Rust-based +JavaScript/TypeScript linter from the Oxc project. + +Unlike `@rushstack/heft-lint-plugin` (ESLint/TSLint), oxlint does not perform type-aware linting and +does not require a TypeScript program, so this plugin runs as a standalone task that invokes the +`oxlint` binary and reports its findings through the Heft logger. + +## Links + +- [CHANGELOG.md]( + https://github.com/microsoft/rushstack/blob/main/heft-plugins/heft-oxlint-plugin/CHANGELOG.md) - Find + out what's new in the latest version +- [@rushstack/heft](https://www.npmjs.com/package/@rushstack/heft) - Heft is a config-driven toolchain that invokes popular tools such as TypeScript, ESLint, Jest, Webpack, and API Extractor. + +Heft is part of the [Rush Stack](https://rushstack.io/) family of projects. diff --git a/heft-plugins/heft-oxlint-plugin/config/heft.json b/heft-plugins/heft-oxlint-plugin/config/heft.json new file mode 100644 index 00000000000..8d1359f022f --- /dev/null +++ b/heft-plugins/heft-oxlint-plugin/config/heft.json @@ -0,0 +1,27 @@ +{ + "$schema": "https://developer.microsoft.com/json-schemas/heft/v0/heft.schema.json", + "extends": "decoupled-local-node-rig/profiles/default/config/heft.json", + + "phasesByName": { + "build": { + "tasksByName": { + "copy-json-schemas": { + "taskPlugin": { + "pluginPackage": "@rushstack/heft", + "pluginName": "copy-files-plugin", + "options": { + "copyOperations": [ + { + "sourcePath": "src/schemas", + "destinationFolders": ["temp/json-schemas/heft/v1"], + "fileExtensions": [".schema.json"], + "hardlink": true + } + ] + } + } + } + } + } + } +} diff --git a/heft-plugins/heft-oxlint-plugin/config/rig.json b/heft-plugins/heft-oxlint-plugin/config/rig.json new file mode 100644 index 00000000000..cc98dea43dd --- /dev/null +++ b/heft-plugins/heft-oxlint-plugin/config/rig.json @@ -0,0 +1,7 @@ +{ + // The "rig.json" file directs tools to look for their config files in an external package. + // Documentation for this system: https://www.npmjs.com/package/@rushstack/rig-package + "$schema": "https://developer.microsoft.com/json-schemas/rig-package/rig.schema.json", + + "rigPackageName": "decoupled-local-node-rig" +} diff --git a/heft-plugins/heft-oxlint-plugin/eslint.config.js b/heft-plugins/heft-oxlint-plugin/eslint.config.js new file mode 100644 index 00000000000..e54effd122a --- /dev/null +++ b/heft-plugins/heft-oxlint-plugin/eslint.config.js @@ -0,0 +1,18 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. +// See LICENSE in the project root for license information. + +const nodeTrustedToolProfile = require('decoupled-local-node-rig/profiles/default/includes/eslint/flat/profile/node-trusted-tool'); +const friendlyLocalsMixin = require('decoupled-local-node-rig/profiles/default/includes/eslint/flat/mixins/friendly-locals'); + +module.exports = [ + ...nodeTrustedToolProfile, + ...friendlyLocalsMixin, + { + files: ['**/*.ts', '**/*.tsx'], + languageOptions: { + parserOptions: { + tsconfigRootDir: __dirname + } + } + } +]; diff --git a/heft-plugins/heft-oxlint-plugin/heft-plugin.json b/heft-plugins/heft-oxlint-plugin/heft-plugin.json new file mode 100644 index 00000000000..ad136730aad --- /dev/null +++ b/heft-plugins/heft-oxlint-plugin/heft-plugin.json @@ -0,0 +1,20 @@ +{ + "$schema": "https://developer.microsoft.com/json-schemas/heft/v0/heft-plugin.schema.json", + + "taskPlugins": [ + { + "pluginName": "oxlint-plugin", + "entryPoint": "./lib-commonjs/OxlintPlugin", + "optionsSchema": "./lib-commonjs/schemas/heft-oxlint-plugin.schema.json", + + "parameterScope": "oxlint", + "parameters": [ + { + "longName": "--fix", + "parameterKind": "flag", + "description": "Fix all encountered rule violations where the violated rule provides a fixer. When running in production mode, fixes will be disabled regardless of this parameter." + } + ] + } + ] +} diff --git a/heft-plugins/heft-oxlint-plugin/package.json b/heft-plugins/heft-oxlint-plugin/package.json new file mode 100644 index 00000000000..0c14454defb --- /dev/null +++ b/heft-plugins/heft-oxlint-plugin/package.json @@ -0,0 +1,52 @@ +{ + "name": "@rushstack/heft-oxlint-plugin", + "version": "0.1.0", + "description": "A Heft plugin for using oxlint, the fast Rust-based JavaScript/TypeScript linter", + "repository": { + "type": "git", + "url": "https://github.com/microsoft/rushstack.git", + "directory": "heft-plugins/heft-oxlint-plugin" + }, + "homepage": "https://rushstack.io/pages/heft/overview/", + "license": "MIT", + "scripts": { + "build": "heft build --clean", + "start": "heft build-watch", + "_phase:build": "heft run --only build -- --clean", + "_phase:test": "heft run --only test -- --clean" + }, + "peerDependencies": { + "@rushstack/heft": "1.2.16" + }, + "dependencies": { + "@rushstack/node-core-library": "workspace:*" + }, + "devDependencies": { + "@rushstack/heft": "workspace:*", + "@rushstack/heft-typescript-plugin": "workspace:*", + "@rushstack/terminal": "workspace:*", + "decoupled-local-node-rig": "workspace:*", + "eslint": "~9.37.0", + "oxlint": "~1.71.0", + "typescript": "~5.8.2" + }, + "exports": { + "./lib/*.schema.json": "./lib-commonjs/*.schema.json", + "./lib/*": { + "types": "./lib-dts/*.d.ts", + "node": "./lib-commonjs/*.js", + "import": "./lib-esm/*.js", + "require": "./lib-commonjs/*.js" + }, + "./heft-plugin.json": "./heft-plugin.json", + "./package.json": "./package.json" + }, + "typesVersions": { + "*": { + "lib/*": [ + "lib-dts/*" + ] + } + }, + "sideEffects": false +} diff --git a/heft-plugins/heft-oxlint-plugin/src/OxlintHelpers.ts b/heft-plugins/heft-oxlint-plugin/src/OxlintHelpers.ts new file mode 100644 index 00000000000..57e0a17ec88 --- /dev/null +++ b/heft-plugins/heft-oxlint-plugin/src/OxlintHelpers.ts @@ -0,0 +1,363 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. +// See LICENSE in the project root for license information. + +import * as path from 'node:path'; + +import { FileError } from '@rushstack/node-core-library'; + +/** + * Options for the oxlint plugin, specified in the "options" field of heft.json. + * + * @remarks + * These options expose the full oxlint command-line surface. Anything that can also be expressed in + * an `.oxlintrc.json` file (rules, plugins, ignores, etc.) may be configured there instead; the + * options below are layered on top of oxlint's own configuration resolution. + * + * @public + */ +export interface IOxlintPluginOptions { + // ----- Basic configuration ----- + + /** + * An optional path (relative to the project root) to an oxlint configuration file + * (e.g. ".oxlintrc.json"). Maps to oxlint's `--config`. If omitted, oxlint searches for a + * configuration file using its default resolution. + */ + configFilePath?: string; + + /** + * Override the TypeScript config used for import resolution. Maps to oxlint's `--tsconfig`. + */ + tsConfigFilePath?: string; + + /** + * The list of file or folder paths (relative to the project root) that oxlint should lint. + * Defaults to ["src"]. + */ + paths?: string[]; + + // ----- Allowing / denying rules and categories ----- + + /** + * Allow (suppress) the listed rules or categories. Maps to oxlint's `--allow` (`-A`). + */ + allow?: string[]; + + /** + * Warn on the listed rules or categories. Maps to oxlint's `--warn` (`-W`). + */ + warn?: string[]; + + /** + * Deny (error on) the listed rules or categories. Maps to oxlint's `--deny` (`-D`). + */ + deny?: string[]; + + // ----- Plugins ----- + + /** Disable the unicorn plugin, which is on by default. Maps to `--disable-unicorn-plugin`. */ + disableUnicornPlugin?: boolean; + /** Disable oxc unique rules, which are on by default. Maps to `--disable-oxc-plugin`. */ + disableOxcPlugin?: boolean; + /** Disable the TypeScript plugin, which is on by default. Maps to `--disable-typescript-plugin`. */ + disableTypeScriptPlugin?: boolean; + /** Enable the import plugin. Maps to `--import-plugin`. */ + importPlugin?: boolean; + /** Enable the react plugin. Maps to `--react-plugin`. */ + reactPlugin?: boolean; + /** Enable the jsdoc plugin. Maps to `--jsdoc-plugin`. */ + jsdocPlugin?: boolean; + /** Enable the Jest plugin. Maps to `--jest-plugin`. */ + jestPlugin?: boolean; + /** Enable the Vitest plugin. Maps to `--vitest-plugin`. */ + vitestPlugin?: boolean; + /** Enable the JSX-a11y plugin. Maps to `--jsx-a11y-plugin`. */ + jsxA11yPlugin?: boolean; + /** Enable the Next.js plugin. Maps to `--nextjs-plugin`. */ + nextjsPlugin?: boolean; + /** Enable the React performance plugin. Maps to `--react-perf-plugin`. */ + reactPerfPlugin?: boolean; + /** Enable the promise plugin. Maps to `--promise-plugin`. */ + promisePlugin?: boolean; + /** Enable the node plugin. Maps to `--node-plugin`. */ + nodePlugin?: boolean; + /** Enable the vue plugin. Maps to `--vue-plugin`. */ + vuePlugin?: boolean; + + // ----- Fixing ----- + + /** + * If set to true, fix all encountered rule violations where the violated rule provides a fixer, + * regardless of whether the "--fix" command-line argument is provided. Maps to oxlint's `--fix`. + * When running in production mode, fixes will be disabled regardless of this setting. + */ + alwaysFix?: boolean; + /** Apply auto-fixable suggestions. Maps to `--fix-suggestions`. Disabled in production mode. */ + fixSuggestions?: boolean; + /** Apply dangerous fixes and suggestions. Maps to `--fix-dangerously`. Disabled in production mode. */ + fixDangerously?: boolean; + + // ----- Ignoring files ----- + + /** Specify the file to use as your `.eslintignore`. Maps to `--ignore-path`. */ + ignorePath?: string; + /** Patterns of files to ignore. Maps to `--ignore-pattern`. */ + ignorePattern?: string[]; + /** Disable excluding files from ignore files/patterns. Maps to `--no-ignore`. */ + noIgnore?: boolean; + + // ----- Handling warnings ----- + + /** Disable reporting on warnings; only errors are reported. Maps to `--quiet`. */ + quiet?: boolean; + /** Ensure warnings produce a non-zero exit code. Maps to `--deny-warnings`. */ + denyWarnings?: boolean; + /** Warning threshold that forces an error exit status when exceeded. Maps to `--max-warnings`. */ + maxWarnings?: number; + + // ----- Miscellaneous ----- + + /** Number of threads to use. Set to 1 to use a single CPU core. Maps to `--threads`. */ + threads?: number; + /** Do not error when no files are selected for linting. Maps to `--no-error-on-unmatched-pattern`. */ + noErrorOnUnmatchedPattern?: boolean; + /** Disable automatic loading of nested configuration files. Maps to `--disable-nested-config`. */ + disableNestedConfig?: boolean; + /** Enable rules that require type information. Maps to `--type-aware`. */ + typeAware?: boolean; + /** Enable experimental type checking (includes TypeScript compiler diagnostics). Maps to `--type-check`. */ + typeCheck?: boolean; + /** Report unused inline disable directives. Maps to `--report-unused-disable-directives`. */ + reportUnusedDisableDirectives?: boolean; + /** + * Report unused inline disable directives at the specified severity. Maps to + * `--report-unused-disable-directives-severity`. Mutually exclusive with + * `reportUnusedDisableDirectives`. + */ + reportUnusedDisableDirectivesSeverity?: 'off' | 'warn' | 'error'; + + // ----- Output ----- + + /** + * If specified, a Static Analysis Results Interchange Format (SARIF) log of all findings will be + * written to the provided path, relative to the project root. This is produced by an additional + * oxlint invocation using `--format=sarif`. + */ + sarifLogPath?: string; +} + +/** + * The shape of a single diagnostic produced by `oxlint --format=json`. + */ +export interface IOxlintDiagnosticSpan { + offset: number; + length: number; + line: number; + column: number; +} + +export interface IOxlintDiagnosticLabel { + label?: string; + span?: IOxlintDiagnosticSpan; +} + +export interface IOxlintDiagnostic { + message: string; + code?: string; + severity: 'error' | 'warning' | 'advice'; + help?: string; + url?: string; + filename: string; + labels?: IOxlintDiagnosticLabel[]; +} + +export interface IOxlintJsonOutput { + diagnostics: IOxlintDiagnostic[]; +} + +const DEFAULT_PATHS: ReadonlyArray = ['src']; + +// The file extensions that oxlint is able to lint. Changed files with any other extension (for +// example generated ".json" or ".css" assets that appear in a TypeScript program) are skipped. +const LINTABLE_EXTENSIONS: ReadonlySet = new Set([ + '.js', + '.mjs', + '.cjs', + '.jsx', + '.ts', + '.mts', + '.cts', + '.tsx' +]); + +// Declaration file suffixes are excluded, since linting hand-authored or generated type +// declarations rarely produces actionable diagnostics. +const DECLARATION_FILE_SUFFIXES: ReadonlyArray = ['.d.ts', '.d.mts', '.d.cts']; + +// Maps each boolean plugin option to its oxlint command-line flag. +const BOOLEAN_FLAGS: ReadonlyArray<[keyof IOxlintPluginOptions, string]> = [ + ['disableUnicornPlugin', '--disable-unicorn-plugin'], + ['disableOxcPlugin', '--disable-oxc-plugin'], + ['disableTypeScriptPlugin', '--disable-typescript-plugin'], + ['importPlugin', '--import-plugin'], + ['reactPlugin', '--react-plugin'], + ['jsdocPlugin', '--jsdoc-plugin'], + ['jestPlugin', '--jest-plugin'], + ['vitestPlugin', '--vitest-plugin'], + ['jsxA11yPlugin', '--jsx-a11y-plugin'], + ['nextjsPlugin', '--nextjs-plugin'], + ['reactPerfPlugin', '--react-perf-plugin'], + ['promisePlugin', '--promise-plugin'], + ['nodePlugin', '--node-plugin'], + ['vuePlugin', '--vue-plugin'], + ['noIgnore', '--no-ignore'], + ['quiet', '--quiet'], + ['denyWarnings', '--deny-warnings'], + ['noErrorOnUnmatchedPattern', '--no-error-on-unmatched-pattern'], + ['disableNestedConfig', '--disable-nested-config'], + ['typeAware', '--type-aware'], + ['typeCheck', '--type-check'], + ['reportUnusedDisableDirectives', '--report-unused-disable-directives'] +]; + +/** + * Builds the oxlint command-line arguments shared by every invocation, excluding `--format`, + * fix-related flags, and the positional paths. + */ +export function buildCommonArgs(options: IOxlintPluginOptions | undefined): string[] { + const args: string[] = []; + if (!options) { + return args; + } + + if (options.configFilePath) { + args.push('--config', options.configFilePath); + } + if (options.tsConfigFilePath) { + args.push('--tsconfig', options.tsConfigFilePath); + } + + for (const rule of options.allow ?? []) { + args.push('--allow', rule); + } + for (const rule of options.warn ?? []) { + args.push('--warn', rule); + } + for (const rule of options.deny ?? []) { + args.push('--deny', rule); + } + + for (const [optionName, flag] of BOOLEAN_FLAGS) { + if (options[optionName]) { + args.push(flag); + } + } + + if (options.ignorePath) { + args.push('--ignore-path', options.ignorePath); + } + for (const pattern of options.ignorePattern ?? []) { + args.push('--ignore-pattern', pattern); + } + if (options.maxWarnings !== undefined) { + args.push('--max-warnings', `${options.maxWarnings}`); + } + if (options.threads !== undefined) { + args.push('--threads', `${options.threads}`); + } + if (options.reportUnusedDisableDirectivesSeverity) { + args.push('--report-unused-disable-directives-severity', options.reportUnusedDisableDirectivesSeverity); + } + + return args; +} + +/** + * Builds the fix-related oxlint arguments. Returns an empty array when fixing is disabled. + */ +export function buildFixArgs(fix: boolean, options: IOxlintPluginOptions | undefined): string[] { + if (!fix) { + return []; + } + const args: string[] = ['--fix']; + if (options?.fixSuggestions) { + args.push('--fix-suggestions'); + } + if (options?.fixDangerously) { + args.push('--fix-dangerously'); + } + return args; +} + +/** + * Resolves the list of positional paths that oxlint should lint, defaulting to ["src"]. + */ +export function resolveLintPaths(options: IOxlintPluginOptions | undefined): ReadonlyArray { + return options?.paths && options.paths.length > 0 ? options.paths : DEFAULT_PATHS; +} + +/** + * Given a collection of absolute file paths (typically the changed source files reported by the + * TypeScript plugin), returns the subset that oxlint should lint, expressed as paths relative to + * the build folder. Files outside the build folder, inside "node_modules", declaration files, or + * files without a lintable JavaScript/TypeScript extension are excluded. The result is sorted and + * de-duplicated for deterministic output. + */ +export function filterChangedFilePaths( + changedFilePaths: Iterable, + buildFolderPath: string +): string[] { + const relativePaths: Set = new Set(); + for (const absolutePath of changedFilePaths) { + const relativePath: string = path.relative(buildFolderPath, absolutePath); + + // Skip files that are outside of the build folder (e.g. the TypeScript "lib.d.ts" files or + // "@types" packages that appear in the program's source files). + if (!relativePath || relativePath.startsWith('..') || path.isAbsolute(relativePath)) { + continue; + } + + // Skip dependencies + if (relativePath.split(/[\\/]/).includes('node_modules')) { + continue; + } + + // Skip declaration files + const lowerCasePath: string = absolutePath.toLowerCase(); + if (DECLARATION_FILE_SUFFIXES.some((suffix) => lowerCasePath.endsWith(suffix))) { + continue; + } + + // Skip non-lintable files + if (!LINTABLE_EXTENSIONS.has(path.extname(absolutePath).toLowerCase())) { + continue; + } + + relativePaths.add(relativePath); + } + + return Array.from(relativePaths).sort(); +} + +/** + * Formats an oxlint diagnostic into a human-readable message, prefixing the rule code when present. + */ +export function formatDiagnosticMessage(diagnostic: IOxlintDiagnostic): string { + return diagnostic.code ? `(${diagnostic.code}) ${diagnostic.message}` : diagnostic.message; +} + +/** + * Converts an oxlint diagnostic into a Heft {@link FileError}. + */ +export function createFileErrorForDiagnostic( + diagnostic: IOxlintDiagnostic, + buildFolderPath: string +): FileError { + const span: IOxlintDiagnosticSpan | undefined = diagnostic.labels?.[0]?.span; + return new FileError(formatDiagnosticMessage(diagnostic), { + absolutePath: path.resolve(buildFolderPath, diagnostic.filename), + projectFolder: buildFolderPath, + line: span?.line, + column: span?.column + }); +} diff --git a/heft-plugins/heft-oxlint-plugin/src/OxlintPlugin.ts b/heft-plugins/heft-oxlint-plugin/src/OxlintPlugin.ts new file mode 100644 index 00000000000..b8fc650250a --- /dev/null +++ b/heft-plugins/heft-oxlint-plugin/src/OxlintPlugin.ts @@ -0,0 +1,276 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. +// See LICENSE in the project root for license information. + +import * as path from 'node:path'; +import type { ChildProcess } from 'node:child_process'; + +import type { HeftConfiguration, IHeftTaskSession, IHeftTaskPlugin, IScopedLogger } from '@rushstack/heft'; +import type { + TypeScriptPluginName, + IChangedFilesHookOptions, + ITypeScriptPluginAccessor +} from '@rushstack/heft-typescript-plugin'; +import { + AlreadyReportedError, + Executable, + FileSystem, + Import, + JsonFile, + type IWaitForExitResult +} from '@rushstack/node-core-library'; + +import { + buildCommonArgs, + buildFixArgs, + resolveLintPaths, + filterChangedFilePaths, + createFileErrorForDiagnostic, + type IOxlintPluginOptions, + type IOxlintJsonOutput +} from './OxlintHelpers'; + +export type { + IOxlintPluginOptions, + IOxlintDiagnostic, + IOxlintDiagnosticLabel, + IOxlintDiagnosticSpan, + IOxlintJsonOutput +} from './OxlintHelpers'; + +const PLUGIN_NAME: 'oxlint-plugin' = 'oxlint-plugin'; +const TYPESCRIPT_PLUGIN_PACKAGE_NAME: '@rushstack/heft-typescript-plugin' = + '@rushstack/heft-typescript-plugin'; +const TYPESCRIPT_PLUGIN_NAME: typeof TypeScriptPluginName = 'typescript-plugin'; +const FIX_PARAMETER_NAME: string = '--fix'; + +interface IOxlintInvocation { + binPath: string; + buildFolderPath: string; + args: string[]; + logger: IScopedLogger; +} + +function checkFix(taskSession: IHeftTaskSession, pluginOptions?: IOxlintPluginOptions): boolean { + let fix: boolean = + !!pluginOptions?.alwaysFix || taskSession.parameters.getFlagParameter(FIX_PARAMETER_NAME).value; + if (fix && taskSession.parameters.production) { + // Write this as a standard output message since we don't want to throw errors when running in + // production mode and "alwaysFix" is specified in the plugin options + taskSession.logger.terminal.writeLine( + 'Fix mode has been disabled since Heft is running in production mode' + ); + fix = false; + } + return fix; +} + +export default class OxlintPlugin implements IHeftTaskPlugin { + public apply( + taskSession: IHeftTaskSession, + heftConfiguration: HeftConfiguration, + pluginOptions?: IOxlintPluginOptions + ): void { + // Disable linting in watch mode. Some lint rules require the context of multiple files, which + // may not be available in watch mode. + if (taskSession.parameters.watch) { + let warningPrinted: boolean = false; + taskSession.hooks.run.tapPromise(PLUGIN_NAME, async () => { + if (warningPrinted) { + return; + } + taskSession.logger.terminal.writeWarningLine("Linting isn't currently supported in watch mode"); + warningPrinted = true; + }); + return; + } + + // Mirror the behavior of the ESLint plugin: when running alongside the TypeScript plugin, only + // lint the files that TypeScript reports as changed so that incremental builds stay fast. When + // run standalone (no TypeScript phase), fall back to linting the configured paths. + let inTypeScriptPhase: boolean = false; + let lintEverything: boolean = false; + const changedFilePaths: Set = new Set(); + + taskSession.requestAccessToPluginByName( + TYPESCRIPT_PLUGIN_PACKAGE_NAME, + TYPESCRIPT_PLUGIN_NAME, + (accessor: ITypeScriptPluginAccessor) => { + inTypeScriptPhase = true; + accessor.onChangedFilesHook.tap(PLUGIN_NAME, (options: IChangedFilesHookOptions) => { + if (options.changedFiles) { + for (const changedFile of options.changedFiles) { + changedFilePaths.add(changedFile.fileName); + } + } else { + // An undefined "changedFiles" set indicates a full (non-incremental) build, so lint + // the configured paths in their entirety. + lintEverything = true; + } + }); + } + ); + + taskSession.hooks.run.tapPromise(PLUGIN_NAME, async () => { + let lintPaths: ReadonlyArray; + if (inTypeScriptPhase && !lintEverything) { + lintPaths = filterChangedFilePaths(changedFilePaths, heftConfiguration.buildFolderPath); + if (lintPaths.length === 0) { + taskSession.logger.terminal.writeVerboseLine('No changed files to lint'); + return; + } + } else { + lintPaths = resolveLintPaths(pluginOptions); + } + + await this._runOxlintAsync(taskSession, heftConfiguration, pluginOptions, lintPaths); + }); + } + + private async _runOxlintAsync( + taskSession: IHeftTaskSession, + heftConfiguration: HeftConfiguration, + pluginOptions: IOxlintPluginOptions | undefined, + lintPaths: ReadonlyArray + ): Promise { + const logger: IScopedLogger = taskSession.logger; + const buildFolderPath: string = heftConfiguration.buildFolderPath; + + const binPath: string = await this._getOxlintBinPathAsync(buildFolderPath, logger); + + const fix: boolean = checkFix(taskSession, pluginOptions); + const commonArgs: string[] = buildCommonArgs(pluginOptions); + const fixArgs: string[] = buildFixArgs(fix, pluginOptions); + + // Run oxlint with JSON output so that diagnostics can be parsed and surfaced through the Heft logger. + const jsonArgs: string[] = [...commonArgs, ...fixArgs, '--format=json', ...lintPaths]; + const jsonResult: IWaitForExitResult = await this._spawnOxlintAsync({ + binPath, + buildFolderPath, + args: jsonArgs, + logger + }); + + this._reportDiagnostics(jsonResult, buildFolderPath, logger); + + // If requested, run oxlint a second time to produce a SARIF log file. oxlint can emit SARIF to + // stdout but does not support writing directly to a file. + if (pluginOptions?.sarifLogPath) { + await this._writeSarifLogAsync({ + binPath, + buildFolderPath, + commonArgs, + lintPaths, + sarifLogPath: pluginOptions.sarifLogPath, + logger + }); + } + + // We rely on the diagnostics reported above to emit errors to the logger. If they did, we throw an + // AlreadyReportedError to indicate that the task failed without re-reporting the errors. + if (logger.hasErrors) { + throw new AlreadyReportedError(); + } + } + + private async _getOxlintBinPathAsync(buildFolderPath: string, logger: IScopedLogger): Promise { + // Resolve the oxlint package relative to the project being linted, then read its "bin" entry. + const packageJsonPath: string = Import.resolveModule({ + modulePath: 'oxlint/package.json', + baseFolderPath: buildFolderPath + }); + const packageFolder: string = path.dirname(packageJsonPath); + const packageJson: { bin?: string | Record } = await JsonFile.loadAsync(packageJsonPath); + + let relativeBinPath: string | undefined; + if (typeof packageJson.bin === 'string') { + relativeBinPath = packageJson.bin; + } else if (packageJson.bin) { + relativeBinPath = packageJson.bin.oxlint; + } + + if (!relativeBinPath) { + throw new Error('Unable to determine the oxlint binary path from its package.json "bin" field.'); + } + + const binPath: string = path.resolve(packageFolder, relativeBinPath); + logger.terminal.writeVerboseLine(`Resolved oxlint binary: ${binPath}`); + return binPath; + } + + private async _spawnOxlintAsync(invocation: IOxlintInvocation): Promise> { + const { binPath, buildFolderPath, args, logger } = invocation; + + // The oxlint "bin" launcher is an ESM Node script, so it must be invoked via Node directly. + logger.terminal.writeVerboseLine(`Running oxlint: node ${binPath} ${args.join(' ')}`); + const childProcess: ChildProcess = Executable.spawn(process.execPath, [binPath, ...args], { + currentWorkingDirectory: buildFolderPath, + stdio: ['ignore', 'pipe', 'pipe'] + }); + + return await Executable.waitForExitAsync(childProcess, { encoding: 'utf8' }); + } + + private _reportDiagnostics( + result: IWaitForExitResult, + buildFolderPath: string, + logger: IScopedLogger + ): void { + const stdout: string = (result.stdout ?? '').trim(); + + if (!stdout) { + // oxlint produced no JSON payload. If it also failed, surface stderr to aid debugging. + if (result.exitCode !== 0 && result.stderr) { + logger.emitError(new Error(`oxlint failed:\n${result.stderr.trim()}`)); + } + return; + } + + let parsed: IOxlintJsonOutput; + try { + parsed = JSON.parse(stdout) as IOxlintJsonOutput; + } catch (error) { + logger.emitError(new Error(`Unable to parse oxlint JSON output: ${(error as Error).message}`)); + if (result.stderr) { + logger.terminal.writeVerboseLine(result.stderr.trim()); + } + return; + } + + for (const diagnostic of parsed.diagnostics ?? []) { + const fileError: ReturnType = createFileErrorForDiagnostic( + diagnostic, + buildFolderPath + ); + if (diagnostic.severity === 'error') { + logger.emitError(fileError); + } else { + logger.emitWarning(fileError); + } + } + } + + private async _writeSarifLogAsync(options: { + binPath: string; + buildFolderPath: string; + commonArgs: string[]; + lintPaths: ReadonlyArray; + sarifLogPath: string; + logger: IScopedLogger; + }): Promise { + const { binPath, buildFolderPath, commonArgs, lintPaths, sarifLogPath, logger } = options; + + const sarifArgs: string[] = [...commonArgs, '--format=sarif', ...lintPaths]; + const sarifResult: IWaitForExitResult = await this._spawnOxlintAsync({ + binPath, + buildFolderPath, + args: sarifArgs, + logger + }); + + const absoluteSarifLogPath: string = path.resolve(buildFolderPath, sarifLogPath); + await FileSystem.writeFileAsync(absoluteSarifLogPath, sarifResult.stdout ?? '', { + ensureFolderExists: true + }); + logger.terminal.writeVerboseLine(`Wrote oxlint SARIF log to: ${absoluteSarifLogPath}`); + } +} diff --git a/heft-plugins/heft-oxlint-plugin/src/schemas/heft-oxlint-plugin.schema.json b/heft-plugins/heft-oxlint-plugin/src/schemas/heft-oxlint-plugin.schema.json new file mode 100644 index 00000000000..93f6f23d091 --- /dev/null +++ b/heft-plugins/heft-oxlint-plugin/src/schemas/heft-oxlint-plugin.schema.json @@ -0,0 +1,184 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "title": "Heft oxlint Plugin Options Configuration", + "description": "This schema describes the \"options\" field that can be specified in heft.json when loading \"@rushstack/heft-oxlint-plugin\".", + "type": "object", + + "additionalProperties": false, + + "properties": { + "configFilePath": { + "title": "Config File Path", + "description": "An optional path (relative to the project root) to an oxlint configuration file (e.g. \".oxlintrc.json\"). Maps to oxlint's --config. If omitted, oxlint will search for a configuration file using its default resolution.", + "type": "string" + }, + + "tsConfigFilePath": { + "title": "TypeScript Config File Path", + "description": "Override the TypeScript config used for import resolution. Maps to oxlint's --tsconfig.", + "type": "string" + }, + + "paths": { + "title": "Paths", + "description": "The list of file or folder paths (relative to the project root) that oxlint should lint. Defaults to [\"src\"].", + "type": "array", + "items": { "type": "string" } + }, + + "allow": { + "title": "Allow", + "description": "Allow (suppress) the listed rules or categories. Maps to oxlint's --allow (-A).", + "type": "array", + "items": { "type": "string" } + }, + + "warn": { + "title": "Warn", + "description": "Warn on the listed rules or categories. Maps to oxlint's --warn (-W).", + "type": "array", + "items": { "type": "string" } + }, + + "deny": { + "title": "Deny", + "description": "Deny (error on) the listed rules or categories. Maps to oxlint's --deny (-D).", + "type": "array", + "items": { "type": "string" } + }, + + "disableUnicornPlugin": { + "description": "Disable the unicorn plugin, which is on by default. Maps to --disable-unicorn-plugin.", + "type": "boolean" + }, + "disableOxcPlugin": { + "description": "Disable oxc unique rules, which are on by default. Maps to --disable-oxc-plugin.", + "type": "boolean" + }, + "disableTypeScriptPlugin": { + "description": "Disable the TypeScript plugin, which is on by default. Maps to --disable-typescript-plugin.", + "type": "boolean" + }, + "importPlugin": { + "description": "Enable the import plugin. Maps to --import-plugin.", + "type": "boolean" + }, + "reactPlugin": { + "description": "Enable the react plugin. Maps to --react-plugin.", + "type": "boolean" + }, + "jsdocPlugin": { + "description": "Enable the jsdoc plugin. Maps to --jsdoc-plugin.", + "type": "boolean" + }, + "jestPlugin": { + "description": "Enable the Jest plugin. Maps to --jest-plugin.", + "type": "boolean" + }, + "vitestPlugin": { + "description": "Enable the Vitest plugin. Maps to --vitest-plugin.", + "type": "boolean" + }, + "jsxA11yPlugin": { + "description": "Enable the JSX-a11y plugin. Maps to --jsx-a11y-plugin.", + "type": "boolean" + }, + "nextjsPlugin": { + "description": "Enable the Next.js plugin. Maps to --nextjs-plugin.", + "type": "boolean" + }, + "reactPerfPlugin": { + "description": "Enable the React performance plugin. Maps to --react-perf-plugin.", + "type": "boolean" + }, + "promisePlugin": { + "description": "Enable the promise plugin. Maps to --promise-plugin.", + "type": "boolean" + }, + "nodePlugin": { + "description": "Enable the node plugin. Maps to --node-plugin.", + "type": "boolean" + }, + "vuePlugin": { + "description": "Enable the vue plugin. Maps to --vue-plugin.", + "type": "boolean" + }, + + "alwaysFix": { + "title": "Always Fix", + "description": "If set to true, fix all encountered rule violations where the violated rule provides a fixer, regardless of if the \"--fix\" command-line argument is provided. Maps to oxlint's --fix. When running in production mode, fixes will be disabled regardless of this setting.", + "type": "boolean" + }, + "fixSuggestions": { + "description": "Apply auto-fixable suggestions. Maps to --fix-suggestions. Disabled in production mode.", + "type": "boolean" + }, + "fixDangerously": { + "description": "Apply dangerous fixes and suggestions. Maps to --fix-dangerously. Disabled in production mode.", + "type": "boolean" + }, + + "ignorePath": { + "description": "Specify the file to use as your .eslintignore. Maps to --ignore-path.", + "type": "string" + }, + "ignorePattern": { + "description": "Patterns of files to ignore. Maps to --ignore-pattern.", + "type": "array", + "items": { "type": "string" } + }, + "noIgnore": { + "description": "Disable excluding files from ignore files/patterns. Maps to --no-ignore.", + "type": "boolean" + }, + + "quiet": { + "description": "Disable reporting on warnings; only errors are reported. Maps to --quiet.", + "type": "boolean" + }, + "denyWarnings": { + "description": "Ensure warnings produce a non-zero exit code. Maps to --deny-warnings.", + "type": "boolean" + }, + "maxWarnings": { + "description": "Warning threshold that forces an error exit status when exceeded. Maps to --max-warnings.", + "type": "integer" + }, + + "threads": { + "description": "Number of threads to use. Set to 1 to use a single CPU core. Maps to --threads.", + "type": "integer" + }, + "noErrorOnUnmatchedPattern": { + "description": "Do not error when no files are selected for linting. Maps to --no-error-on-unmatched-pattern.", + "type": "boolean" + }, + "disableNestedConfig": { + "description": "Disable automatic loading of nested configuration files. Maps to --disable-nested-config.", + "type": "boolean" + }, + "typeAware": { + "description": "Enable rules that require type information. Maps to --type-aware.", + "type": "boolean" + }, + "typeCheck": { + "description": "Enable experimental type checking (includes TypeScript compiler diagnostics). Maps to --type-check.", + "type": "boolean" + }, + "reportUnusedDisableDirectives": { + "description": "Report unused inline disable directives. Maps to --report-unused-disable-directives.", + "type": "boolean" + }, + "reportUnusedDisableDirectivesSeverity": { + "description": "Report unused inline disable directives at the specified severity. Maps to --report-unused-disable-directives-severity. Mutually exclusive with reportUnusedDisableDirectives.", + "type": "string", + "enum": ["off", "warn", "error"] + }, + + "sarifLogPath": { + "title": "SARIF Log Path", + "description": "If specified, a log of all findings will be emitted in the Static Analysis Results Interchange Format (https://sarifweb.azurewebsites.net/) at the provided path, relative to the project root. This is produced by an additional oxlint invocation using --format=sarif.", + "type": "string" + } + } +} diff --git a/heft-plugins/heft-oxlint-plugin/src/test/OxlintHelpers.test.ts b/heft-plugins/heft-oxlint-plugin/src/test/OxlintHelpers.test.ts new file mode 100644 index 00000000000..3a84c4e4fc9 --- /dev/null +++ b/heft-plugins/heft-oxlint-plugin/src/test/OxlintHelpers.test.ts @@ -0,0 +1,238 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. +// See LICENSE in the project root for license information. + +import * as path from 'node:path'; + +import { + buildCommonArgs, + buildFixArgs, + resolveLintPaths, + filterChangedFilePaths, + formatDiagnosticMessage, + createFileErrorForDiagnostic, + type IOxlintPluginOptions, + type IOxlintDiagnostic +} from '../OxlintHelpers'; + +describe('buildCommonArgs', () => { + it('returns no arguments when options are undefined', () => { + expect(buildCommonArgs(undefined)).toEqual([]); + }); + + it('returns no arguments when options are empty', () => { + expect(buildCommonArgs({})).toEqual([]); + }); + + it('maps config and tsconfig paths', () => { + const options: IOxlintPluginOptions = { + configFilePath: '.oxlintrc.json', + tsConfigFilePath: 'tsconfig.json' + }; + expect(buildCommonArgs(options)).toEqual(['--config', '.oxlintrc.json', '--tsconfig', 'tsconfig.json']); + }); + + it('maps allow, warn, and deny lists in order', () => { + const options: IOxlintPluginOptions = { + allow: ['no-debugger'], + warn: ['no-console', 'correctness'], + deny: ['no-unused-vars'] + }; + expect(buildCommonArgs(options)).toEqual([ + '--allow', + 'no-debugger', + '--warn', + 'no-console', + '--warn', + 'correctness', + '--deny', + 'no-unused-vars' + ]); + }); + + it('maps boolean flags only when truthy', () => { + const options: IOxlintPluginOptions = { + disableTypeScriptPlugin: true, + importPlugin: true, + reactPlugin: false, + quiet: true + }; + expect(buildCommonArgs(options)).toEqual(['--disable-typescript-plugin', '--import-plugin', '--quiet']); + }); + + it('maps numeric and severity options', () => { + const options: IOxlintPluginOptions = { + maxWarnings: 5, + threads: 1, + reportUnusedDisableDirectivesSeverity: 'error' + }; + expect(buildCommonArgs(options)).toEqual([ + '--max-warnings', + '5', + '--threads', + '1', + '--report-unused-disable-directives-severity', + 'error' + ]); + }); + + it('emits --max-warnings 0 when maxWarnings is 0', () => { + expect(buildCommonArgs({ maxWarnings: 0 })).toEqual(['--max-warnings', '0']); + }); + + it('maps ignore options', () => { + const options: IOxlintPluginOptions = { + ignorePath: '.eslintignore', + ignorePattern: ['**/dist/**', '**/temp/**'], + noIgnore: true + }; + expect(buildCommonArgs(options)).toEqual([ + '--no-ignore', + '--ignore-path', + '.eslintignore', + '--ignore-pattern', + '**/dist/**', + '--ignore-pattern', + '**/temp/**' + ]); + }); +}); + +describe('buildFixArgs', () => { + it('returns no arguments when fix is disabled', () => { + expect(buildFixArgs(false, { fixSuggestions: true, fixDangerously: true })).toEqual([]); + }); + + it('returns --fix when fix is enabled with no extra options', () => { + expect(buildFixArgs(true, undefined)).toEqual(['--fix']); + }); + + it('appends suggestion and dangerous flags when enabled', () => { + expect(buildFixArgs(true, { fixSuggestions: true, fixDangerously: true })).toEqual([ + '--fix', + '--fix-suggestions', + '--fix-dangerously' + ]); + }); +}); + +describe('resolveLintPaths', () => { + it('defaults to ["src"] when no paths are provided', () => { + expect(resolveLintPaths(undefined)).toEqual(['src']); + expect(resolveLintPaths({})).toEqual(['src']); + expect(resolveLintPaths({ paths: [] })).toEqual(['src']); + }); + + it('uses custom paths when provided', () => { + expect(resolveLintPaths({ paths: ['lib', 'scripts'] })).toEqual(['lib', 'scripts']); + }); +}); + +describe('filterChangedFilePaths', () => { + const buildFolderPath: string = path.resolve('/repo/project'); + + it('returns an empty array when nothing is provided', () => { + expect(filterChangedFilePaths([], buildFolderPath)).toEqual([]); + }); + + it('keeps lintable files inside the build folder as sorted relative paths', () => { + const changed: string[] = [ + path.resolve(buildFolderPath, 'src/b.ts'), + path.resolve(buildFolderPath, 'src/a.tsx'), + path.resolve(buildFolderPath, 'src/nested/c.js') + ]; + expect(filterChangedFilePaths(changed, buildFolderPath)).toEqual([ + path.join('src', 'a.tsx'), + path.join('src', 'b.ts'), + path.join('src', 'nested', 'c.js') + ]); + }); + + it('excludes files outside the build folder', () => { + const changed: string[] = [ + path.resolve('/repo/other/src/a.ts'), + path.resolve(buildFolderPath, '../sibling/b.ts') + ]; + expect(filterChangedFilePaths(changed, buildFolderPath)).toEqual([]); + }); + + it('excludes node_modules, declaration files, and non-lintable extensions', () => { + const changed: string[] = [ + path.resolve(buildFolderPath, 'node_modules/pkg/index.ts'), + path.resolve(buildFolderPath, 'src/types.d.ts'), + path.resolve(buildFolderPath, 'src/styles.css'), + path.resolve(buildFolderPath, 'src/data.json'), + path.resolve(buildFolderPath, 'src/keep.ts') + ]; + expect(filterChangedFilePaths(changed, buildFolderPath)).toEqual([path.join('src', 'keep.ts')]); + }); + + it('de-duplicates repeated paths', () => { + const changed: string[] = [ + path.resolve(buildFolderPath, 'src/a.ts'), + path.resolve(buildFolderPath, 'src/a.ts') + ]; + expect(filterChangedFilePaths(changed, buildFolderPath)).toEqual([path.join('src', 'a.ts')]); + }); +}); + +describe('formatDiagnosticMessage', () => { + it('prefixes the rule code when present', () => { + const diagnostic: IOxlintDiagnostic = { + message: "'x' is never used", + code: 'eslint(no-unused-vars)', + severity: 'error', + filename: 'src/file.ts' + }; + expect(formatDiagnosticMessage(diagnostic)).toBe("(eslint(no-unused-vars)) 'x' is never used"); + }); + + it('returns the message unchanged when no code is present', () => { + const diagnostic: IOxlintDiagnostic = { + message: 'something went wrong', + severity: 'warning', + filename: 'src/file.ts' + }; + expect(formatDiagnosticMessage(diagnostic)).toBe('something went wrong'); + }); +}); + +describe('createFileErrorForDiagnostic', () => { + const buildFolderPath: string = path.resolve('/repo/project'); + + it('resolves the absolute path and uses line/column from the first label span', () => { + const diagnostic: IOxlintDiagnostic = { + message: "'x' is never used", + code: 'eslint(no-unused-vars)', + severity: 'error', + filename: 'src/file.ts', + labels: [ + { + span: { offset: 10, length: 1, line: 3, column: 7 } + } + ] + }; + const fileError: ReturnType = createFileErrorForDiagnostic( + diagnostic, + buildFolderPath + ); + expect(fileError.absolutePath).toBe(path.resolve(buildFolderPath, 'src/file.ts')); + expect(fileError.line).toBe(3); + expect(fileError.column).toBe(7); + expect(fileError.message).toBe("(eslint(no-unused-vars)) 'x' is never used"); + }); + + it('omits line/column when no labels are present', () => { + const diagnostic: IOxlintDiagnostic = { + message: 'broken', + severity: 'warning', + filename: 'src/other.ts' + }; + const fileError: ReturnType = createFileErrorForDiagnostic( + diagnostic, + buildFolderPath + ); + expect(fileError.absolutePath).toBe(path.resolve(buildFolderPath, 'src/other.ts')); + expect(fileError.line).toBeUndefined(); + expect(fileError.column).toBeUndefined(); + }); +}); diff --git a/heft-plugins/heft-oxlint-plugin/tsconfig.json b/heft-plugins/heft-oxlint-plugin/tsconfig.json new file mode 100644 index 00000000000..1a33d17b873 --- /dev/null +++ b/heft-plugins/heft-oxlint-plugin/tsconfig.json @@ -0,0 +1,3 @@ +{ + "extends": "./node_modules/decoupled-local-node-rig/profiles/default/tsconfig-base.json" +} diff --git a/rush.json b/rush.json index 622021e313e..ceb1cc5dd93 100644 --- a/rush.json +++ b/rush.json @@ -1126,6 +1126,12 @@ "reviewCategory": "libraries", "shouldPublish": true }, + { + "packageName": "@rushstack/heft-oxlint-plugin", + "projectFolder": "heft-plugins/heft-oxlint-plugin", + "reviewCategory": "libraries", + "shouldPublish": true + }, { "packageName": "@rushstack/heft-localization-typings-plugin", "projectFolder": "heft-plugins/heft-localization-typings-plugin", From da0ce606d47f564fdd79f165dba70e91ee43ad4d Mon Sep 17 00:00:00 2001 From: Yashwanth Reddy Verupaka Date: Tue, 21 Jul 2026 20:31:02 +0000 Subject: [PATCH 2/2] Support rig-resolved type-aware linting --- .../add-heft-oxlint-plugin.json | 2 +- heft-plugins/heft-oxlint-plugin/README.md | 8 +- .../heft-oxlint-plugin/src/OxlintHelpers.ts | 182 ++++++++++++- .../heft-oxlint-plugin/src/OxlintPlugin.ts | 248 ++++++++++++------ .../schemas/heft-oxlint-plugin.schema.json | 6 +- .../src/test/OxlintHelpers.test.ts | 120 ++++++++- 6 files changed, 477 insertions(+), 89 deletions(-) diff --git a/common/changes/@rushstack/heft-oxlint-plugin/add-heft-oxlint-plugin.json b/common/changes/@rushstack/heft-oxlint-plugin/add-heft-oxlint-plugin.json index cd668dd970c..5a514365f7a 100644 --- a/common/changes/@rushstack/heft-oxlint-plugin/add-heft-oxlint-plugin.json +++ b/common/changes/@rushstack/heft-oxlint-plugin/add-heft-oxlint-plugin.json @@ -3,7 +3,7 @@ { "packageName": "@rushstack/heft-oxlint-plugin", "comment": "Initial release of a Heft plugin for running oxlint, the fast Rust-based JavaScript/TypeScript linter.", - "type": "none" + "type": "minor" } ], "packageName": "@rushstack/heft-oxlint-plugin", diff --git a/heft-plugins/heft-oxlint-plugin/README.md b/heft-plugins/heft-oxlint-plugin/README.md index 1a80f547996..c35b3184b66 100644 --- a/heft-plugins/heft-oxlint-plugin/README.md +++ b/heft-plugins/heft-oxlint-plugin/README.md @@ -3,9 +3,11 @@ This is a Heft plugin to run [oxlint](https://oxc.rs/docs/guide/usage/linter), the fast Rust-based JavaScript/TypeScript linter from the Oxc project. -Unlike `@rushstack/heft-lint-plugin` (ESLint/TSLint), oxlint does not perform type-aware linting and -does not require a TypeScript program, so this plugin runs as a standalone task that invokes the -`oxlint` binary and reports its findings through the Heft logger. +This plugin runs as a standalone task that invokes the `oxlint` binary and reports its findings +through the Heft logger. Type-aware linting is supported via the `typeAware` option (which passes +`--type-aware` to oxlint); enabling it additionally requires the `oxlint-tsgolint` package. As with +the `oxlint` package itself, `oxlint-tsgolint` is resolved from the consuming project or its shared +rig, so it can be installed once in a rig rather than in every project. ## Links diff --git a/heft-plugins/heft-oxlint-plugin/src/OxlintHelpers.ts b/heft-plugins/heft-oxlint-plugin/src/OxlintHelpers.ts index 57e0a17ec88..3be6e950795 100644 --- a/heft-plugins/heft-oxlint-plugin/src/OxlintHelpers.ts +++ b/heft-plugins/heft-oxlint-plugin/src/OxlintHelpers.ts @@ -123,9 +123,16 @@ export interface IOxlintPluginOptions { noErrorOnUnmatchedPattern?: boolean; /** Disable automatic loading of nested configuration files. Maps to `--disable-nested-config`. */ disableNestedConfig?: boolean; - /** Enable rules that require type information. Maps to `--type-aware`. */ + /** + * Enable rules that require type information. Maps to `--type-aware`. Requires the + * `oxlint-tsgolint` package, which is resolved from the consuming project or its shared rig. + */ typeAware?: boolean; - /** Enable experimental type checking (includes TypeScript compiler diagnostics). Maps to `--type-check`. */ + /** + * Enable experimental type checking (includes TypeScript compiler diagnostics). Maps to + * `--type-check`. Requires the `oxlint-tsgolint` package, which is resolved from the consuming + * project or its shared rig. + */ typeCheck?: boolean; /** Report unused inline disable directives. Maps to `--report-unused-disable-directives`. */ reportUnusedDisableDirectives?: boolean; @@ -140,8 +147,9 @@ export interface IOxlintPluginOptions { /** * If specified, a Static Analysis Results Interchange Format (SARIF) log of all findings will be - * written to the provided path, relative to the project root. This is produced by an additional - * oxlint invocation using `--format=sarif`. + * written to the provided path, relative to the project root. When set, oxlint is run once with + * `--format=sarif` and the reported diagnostics are extracted from that same SARIF output, so no + * additional oxlint invocation is incurred. */ sarifLogPath?: string; } @@ -175,6 +183,37 @@ export interface IOxlintJsonOutput { diagnostics: IOxlintDiagnostic[]; } +// ----- SARIF types (subset needed for diagnostic extraction) ----- + +export interface IOxlintSarifRegion { + startLine?: number; + startColumn?: number; +} + +export interface IOxlintSarifPhysicalLocation { + artifactLocation?: { uri?: string }; + region?: IOxlintSarifRegion; +} + +export interface IOxlintSarifLocation { + physicalLocation?: IOxlintSarifPhysicalLocation; +} + +export interface IOxlintSarifResult { + level?: string; + message?: { text?: string }; + ruleId?: string; + locations?: IOxlintSarifLocation[]; +} + +export interface IOxlintSarifRun { + results?: IOxlintSarifResult[]; +} + +export interface IOxlintSarifLog { + runs?: IOxlintSarifRun[]; +} + const DEFAULT_PATHS: ReadonlyArray = ['src']; // The file extensions that oxlint is able to lint. Changed files with any other extension (for @@ -361,3 +400,138 @@ export function createFileErrorForDiagnostic( column: span?.column }); } + +/** + * Extracts diagnostics from an oxlint SARIF log, converting each SARIF result into the common + * {@link IOxlintDiagnostic} format used for error reporting. + */ +export function extractDiagnosticsFromSarif(sarifLog: IOxlintSarifLog): IOxlintDiagnostic[] { + const diagnostics: IOxlintDiagnostic[] = []; + + for (const run of sarifLog.runs ?? []) { + for (const result of run.results ?? []) { + const location: IOxlintSarifLocation | undefined = result.locations?.[0]; + const physicalLocation: IOxlintSarifPhysicalLocation | undefined = location?.physicalLocation; + const uri: string = physicalLocation?.artifactLocation?.uri ?? ''; + const region: IOxlintSarifRegion | undefined = physicalLocation?.region; + + let severity: 'error' | 'warning' | 'advice'; + switch (result.level) { + case 'error': + severity = 'error'; + break; + case 'note': + severity = 'advice'; + break; + default: + severity = 'warning'; + break; + } + + const diagnostic: IOxlintDiagnostic = { + message: result.message?.text ?? '', + code: result.ruleId, + severity, + filename: uri, + labels: region + ? [{ span: { offset: 0, length: 0, line: region.startLine ?? 0, column: region.startColumn ?? 0 } }] + : undefined + }; + + diagnostics.push(diagnostic); + } + } + + return diagnostics; +} + +/** + * The maximum length (in characters) permitted for a single oxlint command line. + * + * @remarks + * Windows caps the command line passed to `CreateProcess` at 32767 characters. We stay well under + * that limit to leave room for the Node executable path, the oxlint bin path, and any argument + * quoting overhead applied by the operating system. + */ +export const MAX_COMMAND_LINE_LENGTH: number = 30000; + +/** + * Splits the positional lint paths into batches such that each resulting oxlint command line stays + * within {@link MAX_COMMAND_LINE_LENGTH}. This avoids exceeding the operating system's command-line + * length limit (notably on Windows, where a large set of changed files could otherwise overflow the + * ~32 KiB `CreateProcess` limit). + * + * @param prefixArgs - The command-line tokens that precede the paths on every invocation (for + * example the Node executable, the oxlint bin path, and all non-path oxlint arguments). + * @param lintPaths - The positional file or folder paths to lint. + * @param maxCommandLineLength - The maximum permitted command-line length. + * @returns One or more batches of lint paths. A single path that on its own exceeds the limit is + * still returned in its own batch, since it cannot be split any further. Always returns at least + * one batch so that callers can iterate uniformly. + */ +export function batchLintPaths( + prefixArgs: ReadonlyArray, + lintPaths: ReadonlyArray, + maxCommandLineLength: number = MAX_COMMAND_LINE_LENGTH +): string[][] { + // Length contributed by the fixed prefix, counting a separating space before each token. + let prefixLength: number = 0; + for (const arg of prefixArgs) { + prefixLength += arg.length + 1; + } + + const batches: string[][] = []; + let currentBatch: string[] = []; + let currentLength: number = prefixLength; + + for (const lintPath of lintPaths) { + const pathLength: number = lintPath.length + 1; + if (currentBatch.length > 0 && currentLength + pathLength > maxCommandLineLength) { + batches.push(currentBatch); + currentBatch = []; + currentLength = prefixLength; + } + currentBatch.push(lintPath); + currentLength += pathLength; + } + + if (currentBatch.length > 0) { + batches.push(currentBatch); + } + + if (batches.length === 0) { + batches.push([]); + } + + return batches; +} + +/** + * Merges the raw SARIF log output produced by one or more oxlint invocations into a single SARIF + * document. + * + * @remarks + * When linting is split into multiple batches (see {@link batchLintPaths}), each batch produces its + * own SARIF log. This concatenates the `runs` from every batch into the first log so that all of the + * findings are preserved in one file. When only a single log is provided, its original text is + * returned unchanged so that the output is byte-for-byte identical to what oxlint emitted. + * + * @param rawSarifLogs - The raw (unparsed) SARIF stdout captured from each oxlint invocation. + * @returns The merged SARIF log serialized as a string. + */ +export function mergeSarifLogs(rawSarifLogs: ReadonlyArray): string { + if (rawSarifLogs.length === 1) { + return rawSarifLogs[0]; + } + + const base: { runs?: unknown[] } = JSON.parse(rawSarifLogs[0]); + base.runs = base.runs ?? []; + for (let i: number = 1; i < rawSarifLogs.length; ++i) { + const next: { runs?: unknown[] } = JSON.parse(rawSarifLogs[i]); + if (next.runs) { + base.runs.push(...next.runs); + } + } + + return JSON.stringify(base, undefined, 2); +} diff --git a/heft-plugins/heft-oxlint-plugin/src/OxlintPlugin.ts b/heft-plugins/heft-oxlint-plugin/src/OxlintPlugin.ts index b8fc650250a..0edd972a9d6 100644 --- a/heft-plugins/heft-oxlint-plugin/src/OxlintPlugin.ts +++ b/heft-plugins/heft-oxlint-plugin/src/OxlintPlugin.ts @@ -25,8 +25,13 @@ import { resolveLintPaths, filterChangedFilePaths, createFileErrorForDiagnostic, + extractDiagnosticsFromSarif, + batchLintPaths, + mergeSarifLogs, type IOxlintPluginOptions, - type IOxlintJsonOutput + type IOxlintJsonOutput, + type IOxlintSarifLog, + type IOxlintDiagnostic } from './OxlintHelpers'; export type { @@ -43,11 +48,19 @@ const TYPESCRIPT_PLUGIN_PACKAGE_NAME: '@rushstack/heft-typescript-plugin' = const TYPESCRIPT_PLUGIN_NAME: typeof TypeScriptPluginName = 'typescript-plugin'; const FIX_PARAMETER_NAME: string = '--fix'; +// oxlint delegates type-aware rules (--type-aware / --type-check) to the native "tsgolint" binary +// from the "oxlint-tsgolint" package. It honors OXLINT_TSGOLINT_PATH, letting us point it at a copy +// resolved via the rig package resolver (installed in the project or a shared rig). +const TSGOLINT_PACKAGE_NAME: 'oxlint-tsgolint' = 'oxlint-tsgolint'; +const TSGOLINT_NATIVE_PACKAGE_SCOPE: '@oxlint-tsgolint' = '@oxlint-tsgolint'; +const OXLINT_TSGOLINT_PATH_ENV_VARIABLE_NAME: 'OXLINT_TSGOLINT_PATH' = 'OXLINT_TSGOLINT_PATH'; + interface IOxlintInvocation { binPath: string; buildFolderPath: string; args: string[]; logger: IScopedLogger; + environment?: NodeJS.ProcessEnv; } function checkFix(taskSession: IHeftTaskSession, pluginOptions?: IOxlintPluginOptions): boolean { @@ -122,11 +135,11 @@ export default class OxlintPlugin implements IHeftTaskPlugin = await this._spawnOxlintAsync({ - binPath, - buildFolderPath, - args: jsonArgs, - logger - }); + // When a SARIF log is requested, run oxlint with SARIF output. The SARIF payload contains all of + // the diagnostics we need, so we extract them from it rather than paying the full lint cost a + // second time. Otherwise, use JSON output, which is a more compact format for diagnostic + // reporting. + const format: string = sarifLogPath ? 'sarif' : 'json'; + const fixedArgs: string[] = [...commonArgs, ...fixArgs, `--format=${format}`]; + + // Split the lint paths into batches so that a project with a very large number of changed files + // does not exceed the operating system's command-line length limit (notably ~32 KiB on Windows). + // In the common case this yields a single batch and behaves exactly like a single oxlint run. + const batches: string[][] = batchLintPaths([process.execPath, binPath, ...fixedArgs], lintPaths); + if (batches.length > 1) { + logger.terminal.writeVerboseLine( + `Linting ${lintPaths.length} paths across ${batches.length} oxlint invocations to stay ` + + 'within the command-line length limit' + ); + } - this._reportDiagnostics(jsonResult, buildFolderPath, logger); + const diagnostics: IOxlintDiagnostic[] = []; + const sarifBatchOutputs: string[] = []; - // If requested, run oxlint a second time to produce a SARIF log file. oxlint can emit SARIF to - // stdout but does not support writing directly to a file. - if (pluginOptions?.sarifLogPath) { - await this._writeSarifLogAsync({ + for (const batch of batches) { + const result: IWaitForExitResult = await this.#spawnOxlintAsync({ binPath, buildFolderPath, - commonArgs, - lintPaths, - sarifLogPath: pluginOptions.sarifLogPath, - logger + args: [...fixedArgs, ...batch], + logger, + environment }); + + const stdout: string = (result.stdout ?? '').trim(); + if (!stdout) { + // oxlint produced no payload. If it also failed, surface stderr to aid debugging. + if (result.exitCode !== 0 && result.stderr) { + logger.emitError(new Error(`oxlint failed:\n${result.stderr.trim()}`)); + } + continue; + } + + if (sarifLogPath) { + const parsed: IOxlintSarifLog | undefined = this.#parseOxlintOutput( + stdout, + 'SARIF', + result.stderr, + logger + ); + if (parsed) { + sarifBatchOutputs.push(stdout); + diagnostics.push(...extractDiagnosticsFromSarif(parsed)); + } + } else { + const parsed: IOxlintJsonOutput | undefined = this.#parseOxlintOutput( + stdout, + 'JSON', + result.stderr, + logger + ); + if (parsed) { + diagnostics.push(...(parsed.diagnostics ?? [])); + } + } + } + + this.#emitDiagnostics(diagnostics, buildFolderPath, logger); + + // oxlint can emit SARIF to stdout but does not support writing directly to a file, so persist the + // captured output (merged across batches when necessary) ourselves. + if (sarifLogPath && sarifBatchOutputs.length > 0) { + const absoluteSarifLogPath: string = path.resolve(buildFolderPath, sarifLogPath); + await FileSystem.writeFileAsync(absoluteSarifLogPath, mergeSarifLogs(sarifBatchOutputs), { + ensureFolderExists: true + }); + logger.terminal.writeVerboseLine(`Wrote oxlint SARIF log to: ${absoluteSarifLogPath}`); } // We rely on the diagnostics reported above to emit errors to the logger. If they did, we throw an @@ -172,13 +249,14 @@ export default class OxlintPlugin implements IHeftTaskPlugin { - // Resolve the oxlint package relative to the project being linted, then read its "bin" entry. - const packageJsonPath: string = Import.resolveModule({ - modulePath: 'oxlint/package.json', - baseFolderPath: buildFolderPath - }); - const packageFolder: string = path.dirname(packageJsonPath); + async #getOxlintBinPathAsync(heftConfiguration: HeftConfiguration, logger: IScopedLogger): Promise { + // Resolve the oxlint package using the rig package resolver, which allows the linter to be + // installed in the project's rig rather than directly in the project, then read its "bin" entry. + const packageFolder: string = await heftConfiguration.rigPackageResolver.resolvePackageAsync( + 'oxlint', + logger.terminal + ); + const packageJsonPath: string = path.join(packageFolder, 'package.json'); const packageJson: { bin?: string | Record } = await JsonFile.loadAsync(packageJsonPath); let relativeBinPath: string | undefined; @@ -197,46 +275,87 @@ export default class OxlintPlugin implements IHeftTaskPlugin> { - const { binPath, buildFolderPath, args, logger } = invocation; + async #getTsgolintBinaryPathAsync( + heftConfiguration: HeftConfiguration, + logger: IScopedLogger + ): Promise { + // Resolve "oxlint-tsgolint" via the rig package resolver (project or rig). It provides the native + // binary through optional dependencies named "@oxlint-tsgolint/-". + const packageFolder: string = await heftConfiguration.rigPackageResolver.resolvePackageAsync( + TSGOLINT_PACKAGE_NAME, + logger.terminal + ); + + const nativePackageName: string = `${TSGOLINT_NATIVE_PACKAGE_SCOPE}/${process.platform}-${process.arch}`; + const binaryName: string = process.platform === 'win32' ? 'tsgolint.exe' : 'tsgolint'; + + let nativePackageJsonPath: string; + try { + // Resolve the native package's "package.json" (the binary itself is extensionless and not a + // resolvable module) and derive the binary path from its folder. + nativePackageJsonPath = await Import.resolveModuleAsync({ + modulePath: `${nativePackageName}/package.json`, + baseFolderPath: packageFolder + }); + } catch (error) { + throw new Error( + `Unable to resolve the tsgolint native binary package "${nativePackageName}" from ` + + `"${packageFolder}". Ensure the "${TSGOLINT_PACKAGE_NAME}" package is installed for this ` + + `platform so that type-aware linting can run. (${(error as Error).message})` + ); + } + + const binaryPath: string = path.join(path.dirname(nativePackageJsonPath), binaryName); + if (!(await FileSystem.existsAsync(binaryPath))) { + throw new Error( + `The tsgolint native binary was not found at the expected location "${binaryPath}". Ensure the ` + + `"${TSGOLINT_PACKAGE_NAME}" package is correctly installed for this platform.` + ); + } + + logger.terminal.writeVerboseLine(`Resolved tsgolint binary: ${binaryPath}`); + return binaryPath; + } + + async #spawnOxlintAsync(invocation: IOxlintInvocation): Promise> { + const { binPath, buildFolderPath, args, logger, environment } = invocation; // The oxlint "bin" launcher is an ESM Node script, so it must be invoked via Node directly. logger.terminal.writeVerboseLine(`Running oxlint: node ${binPath} ${args.join(' ')}`); const childProcess: ChildProcess = Executable.spawn(process.execPath, [binPath, ...args], { currentWorkingDirectory: buildFolderPath, - stdio: ['ignore', 'pipe', 'pipe'] + stdio: ['ignore', 'pipe', 'pipe'], + environment }); return await Executable.waitForExitAsync(childProcess, { encoding: 'utf8' }); } - private _reportDiagnostics( - result: IWaitForExitResult, - buildFolderPath: string, + #parseOxlintOutput( + stdout: string, + formatLabel: string, + stderr: string | undefined, logger: IScopedLogger - ): void { - const stdout: string = (result.stdout ?? '').trim(); - - if (!stdout) { - // oxlint produced no JSON payload. If it also failed, surface stderr to aid debugging. - if (result.exitCode !== 0 && result.stderr) { - logger.emitError(new Error(`oxlint failed:\n${result.stderr.trim()}`)); - } - return; - } - - let parsed: IOxlintJsonOutput; + ): T | undefined { try { - parsed = JSON.parse(stdout) as IOxlintJsonOutput; + return JSON.parse(stdout) as T; } catch (error) { - logger.emitError(new Error(`Unable to parse oxlint JSON output: ${(error as Error).message}`)); - if (result.stderr) { - logger.terminal.writeVerboseLine(result.stderr.trim()); + logger.emitError( + new Error(`Unable to parse oxlint ${formatLabel} output: ${(error as Error).message}`) + ); + if (stderr) { + logger.terminal.writeVerboseLine(stderr.trim()); } - return; + return undefined; } + } - for (const diagnostic of parsed.diagnostics ?? []) { + #emitDiagnostics( + diagnostics: ReadonlyArray, + buildFolderPath: string, + logger: IScopedLogger + ): void { + for (const diagnostic of diagnostics) { const fileError: ReturnType = createFileErrorForDiagnostic( diagnostic, buildFolderPath @@ -248,29 +367,4 @@ export default class OxlintPlugin implements IHeftTaskPlugin; - sarifLogPath: string; - logger: IScopedLogger; - }): Promise { - const { binPath, buildFolderPath, commonArgs, lintPaths, sarifLogPath, logger } = options; - - const sarifArgs: string[] = [...commonArgs, '--format=sarif', ...lintPaths]; - const sarifResult: IWaitForExitResult = await this._spawnOxlintAsync({ - binPath, - buildFolderPath, - args: sarifArgs, - logger - }); - - const absoluteSarifLogPath: string = path.resolve(buildFolderPath, sarifLogPath); - await FileSystem.writeFileAsync(absoluteSarifLogPath, sarifResult.stdout ?? '', { - ensureFolderExists: true - }); - logger.terminal.writeVerboseLine(`Wrote oxlint SARIF log to: ${absoluteSarifLogPath}`); - } } diff --git a/heft-plugins/heft-oxlint-plugin/src/schemas/heft-oxlint-plugin.schema.json b/heft-plugins/heft-oxlint-plugin/src/schemas/heft-oxlint-plugin.schema.json index 93f6f23d091..1b0934bd6e1 100644 --- a/heft-plugins/heft-oxlint-plugin/src/schemas/heft-oxlint-plugin.schema.json +++ b/heft-plugins/heft-oxlint-plugin/src/schemas/heft-oxlint-plugin.schema.json @@ -158,11 +158,11 @@ "type": "boolean" }, "typeAware": { - "description": "Enable rules that require type information. Maps to --type-aware.", + "description": "Enable rules that require type information. Maps to --type-aware. Requires the oxlint-tsgolint package, which is resolved from the consuming project or its shared rig.", "type": "boolean" }, "typeCheck": { - "description": "Enable experimental type checking (includes TypeScript compiler diagnostics). Maps to --type-check.", + "description": "Enable experimental type checking (includes TypeScript compiler diagnostics). Maps to --type-check. Requires the oxlint-tsgolint package, which is resolved from the consuming project or its shared rig.", "type": "boolean" }, "reportUnusedDisableDirectives": { @@ -177,7 +177,7 @@ "sarifLogPath": { "title": "SARIF Log Path", - "description": "If specified, a log of all findings will be emitted in the Static Analysis Results Interchange Format (https://sarifweb.azurewebsites.net/) at the provided path, relative to the project root. This is produced by an additional oxlint invocation using --format=sarif.", + "description": "If specified, a log of all findings will be emitted in the Static Analysis Results Interchange Format (https://sarifweb.azurewebsites.net/) at the provided path, relative to the project root. When set, oxlint is run once with --format=sarif and the reported diagnostics are extracted from that same SARIF output, so no additional oxlint invocation is incurred.", "type": "string" } } diff --git a/heft-plugins/heft-oxlint-plugin/src/test/OxlintHelpers.test.ts b/heft-plugins/heft-oxlint-plugin/src/test/OxlintHelpers.test.ts index 3a84c4e4fc9..47a0d667096 100644 --- a/heft-plugins/heft-oxlint-plugin/src/test/OxlintHelpers.test.ts +++ b/heft-plugins/heft-oxlint-plugin/src/test/OxlintHelpers.test.ts @@ -10,8 +10,12 @@ import { filterChangedFilePaths, formatDiagnosticMessage, createFileErrorForDiagnostic, + extractDiagnosticsFromSarif, + batchLintPaths, + mergeSarifLogs, type IOxlintPluginOptions, - type IOxlintDiagnostic + type IOxlintDiagnostic, + type IOxlintSarifLog } from '../OxlintHelpers'; describe('buildCommonArgs', () => { @@ -236,3 +240,117 @@ describe('createFileErrorForDiagnostic', () => { expect(fileError.column).toBeUndefined(); }); }); + +describe('extractDiagnosticsFromSarif', () => { + it('returns an empty array for an empty log', () => { + expect(extractDiagnosticsFromSarif({})).toEqual([]); + expect(extractDiagnosticsFromSarif({ runs: [] })).toEqual([]); + expect(extractDiagnosticsFromSarif({ runs: [{ results: [] }] })).toEqual([]); + }); + + it('maps SARIF levels to diagnostic severities and reads location data', () => { + const sarifLog: IOxlintSarifLog = { + runs: [ + { + results: [ + { + level: 'error', + ruleId: 'no-unused-vars', + message: { text: "'x' is never used" }, + locations: [ + { + physicalLocation: { + artifactLocation: { uri: 'src/a.ts' }, + region: { startLine: 3, startColumn: 7 } + } + } + ] + }, + { + level: 'warning', + message: { text: 'be careful' }, + locations: [{ physicalLocation: { artifactLocation: { uri: 'src/b.ts' } } }] + }, + { + level: 'note', + message: { text: 'just advice' } + } + ] + } + ] + }; + + const diagnostics: IOxlintDiagnostic[] = extractDiagnosticsFromSarif(sarifLog); + expect(diagnostics).toHaveLength(3); + + expect(diagnostics[0]).toMatchObject({ + severity: 'error', + code: 'no-unused-vars', + message: "'x' is never used", + filename: 'src/a.ts' + }); + expect(diagnostics[0].labels?.[0]?.span).toMatchObject({ line: 3, column: 7 }); + + expect(diagnostics[1]).toMatchObject({ + severity: 'warning', + message: 'be careful', + filename: 'src/b.ts' + }); + expect(diagnostics[2]).toMatchObject({ severity: 'advice', message: 'just advice', filename: '' }); + }); +}); + +describe('batchLintPaths', () => { + it('returns a single batch when everything fits', () => { + const paths: string[] = ['src/a.ts', 'src/b.ts', 'src/c.ts']; + expect(batchLintPaths(['node', 'oxlint', '--format=json'], paths)).toEqual([paths]); + }); + + it('always returns at least one batch, even with no paths', () => { + expect(batchLintPaths(['node', 'oxlint'], [])).toEqual([[]]); + }); + + it('splits paths into multiple batches when the command line would be too long', () => { + const paths: string[] = ['aaaa', 'bbbb', 'cccc', 'dddd']; + // prefix "node oxlint" contributes 5 + 7 = 12; each 4-char path contributes 5. + // With a limit of 22, prefix(12) + one path(5) = 17 fits, two paths = 22 fits, three = 27 does not. + const batches: string[][] = batchLintPaths(['node', 'oxlint'], paths, 22); + expect(batches).toEqual([ + ['aaaa', 'bbbb'], + ['cccc', 'dddd'] + ]); + }); + + it('places an oversized single path in its own batch rather than dropping it', () => { + const longPath: string = 'x'.repeat(100); + const batches: string[][] = batchLintPaths(['node'], ['a', longPath, 'b'], 20); + expect(batches).toEqual([['a'], [longPath], ['b']]); + }); + + it('preserves every path across the produced batches', () => { + const paths: string[] = []; + for (let index: number = 0; index < 50; ++index) { + paths.push(`src/file-${index}.ts`); + } + const batches: string[][] = batchLintPaths(['node', 'oxlint', '--format=sarif'], paths, 80); + expect(batches.flat()).toEqual(paths); + expect(batches.length).toBeGreaterThan(1); + }); +}); + +describe('mergeSarifLogs', () => { + it('returns the original text unchanged for a single log', () => { + const raw: string = '{"runs":[{"results":[]}]}'; + expect(mergeSarifLogs([raw])).toBe(raw); + }); + + it('concatenates the runs from multiple logs', () => { + const first: string = JSON.stringify({ $schema: 'sarif', version: '2.1.0', runs: [{ results: [1] }] }); + const second: string = JSON.stringify({ version: '2.1.0', runs: [{ results: [2] }] }); + const merged: IOxlintSarifLog & { $schema?: string } = JSON.parse(mergeSarifLogs([first, second])); + expect(merged.$schema).toBe('sarif'); + expect(merged.runs).toHaveLength(2); + expect(merged.runs?.[0]?.results).toEqual([1]); + expect(merged.runs?.[1]?.results).toEqual([2]); + }); +});