ultracite 7.6.5 → 7.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/config/biome/core/biome.jsonc +2 -0
- package/config/eslint/core/rules/eslint-typescript.mjs +3 -1
- package/config/eslint/core/rules/eslint.mjs +0 -11
- package/config/eslint/core/rules/import.mjs +1 -0
- package/config/eslint/core/rules/typescript.mjs +1 -27
- package/config/eslint/jest/eslint.config.mjs +8 -1
- package/config/eslint/jest/rules/jest.mjs +10 -1
- package/config/eslint/nestjs/eslint.config.mjs +17 -1
- package/config/eslint/nestjs/rules/nestjs.mjs +17 -0
- package/config/eslint/next/eslint.config.mjs +6 -0
- package/config/eslint/react/rules/react-hooks.mjs +1 -3
- package/config/eslint/react/rules/react.mjs +3 -0
- package/config/eslint/remix/eslint.config.mjs +7 -0
- package/config/eslint/vitest/eslint.config.mjs +8 -1
- package/config/eslint/vitest/rules/vitest.mjs +7 -5
- package/dist/index.js +1 -1
- package/package.json +6 -5
|
@@ -413,6 +413,7 @@
|
|
|
413
413
|
"noDoubleEquals": "error",
|
|
414
414
|
"noDuplicateCase": "error",
|
|
415
415
|
"noDuplicateClassMembers": "error",
|
|
416
|
+
"noDuplicateDependencies": "error",
|
|
416
417
|
"noDuplicateElseIf": "error",
|
|
417
418
|
"noDuplicateFields": "error",
|
|
418
419
|
"noDuplicateObjectKeys": "error",
|
|
@@ -470,6 +471,7 @@
|
|
|
470
471
|
"noUnusedExpressions": "error",
|
|
471
472
|
|
|
472
473
|
"noConsole": "off",
|
|
474
|
+
"useDeprecatedDate": "off",
|
|
473
475
|
|
|
474
476
|
/** ------ Project/Scanner rules. Use ultracite/biome/type-aware to enable. ------ **/
|
|
475
477
|
"noDeprecatedImports": "off",
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
const config = {
|
|
2
|
-
// ESLint
|
|
2
|
+
// ESLint core rules disabled because either:
|
|
3
|
+
// - @typescript-eslint provides a type-aware equivalent (no-shadow, no-unused-vars, etc.), OR
|
|
4
|
+
// - Prettier/Oxfmt owns formatting (brace-style, indent, semi, quotes, etc.)
|
|
3
5
|
"brace-style": "off",
|
|
4
6
|
camelcase: "off",
|
|
5
7
|
"comma-dangle": "off",
|
|
@@ -5,7 +5,6 @@ const baseRules = { ...plugin.configs.all.rules };
|
|
|
5
5
|
|
|
6
6
|
const overrideRules = {
|
|
7
7
|
"capitalized-comments": "off",
|
|
8
|
-
complexity: "off",
|
|
9
8
|
"id-length": ["error", { exceptions: ["x", "y", "z"] }],
|
|
10
9
|
"max-lines": "off",
|
|
11
10
|
"max-lines-per-function": "off",
|
|
@@ -13,19 +12,9 @@ const overrideRules = {
|
|
|
13
12
|
"max-statements": "off",
|
|
14
13
|
"no-ternary": "off",
|
|
15
14
|
"no-undefined": "off",
|
|
16
|
-
"no-unused-private-class-members": "off",
|
|
17
15
|
"one-var": "off",
|
|
18
|
-
"prefer-destructuring": [
|
|
19
|
-
"error",
|
|
20
|
-
{
|
|
21
|
-
array: false,
|
|
22
|
-
object: true,
|
|
23
|
-
},
|
|
24
|
-
],
|
|
25
16
|
// https://github.com/eslint/eslint/issues/11542
|
|
26
17
|
"sort-imports": "off",
|
|
27
|
-
"sort-keys": "off",
|
|
28
|
-
"sort-vars": "off",
|
|
29
18
|
};
|
|
30
19
|
|
|
31
20
|
const config = Object.assign(baseRules, overrideRules);
|
|
@@ -11,20 +11,8 @@ const baseRules = Object.fromEntries(
|
|
|
11
11
|
);
|
|
12
12
|
|
|
13
13
|
const overrideRules = {
|
|
14
|
-
// Disabled for Prettier
|
|
15
|
-
"@typescript-eslint/block-spacing": "off",
|
|
16
|
-
"@typescript-eslint/brace-style": "off",
|
|
17
|
-
"@typescript-eslint/comma-dangle": "off",
|
|
18
|
-
"@typescript-eslint/comma-spacing": "off",
|
|
19
14
|
"@typescript-eslint/consistent-type-definitions": ["error", "type"],
|
|
20
15
|
"@typescript-eslint/explicit-function-return-type": "off",
|
|
21
|
-
"@typescript-eslint/func-call-spacing": "off",
|
|
22
|
-
"@typescript-eslint/indent": "off",
|
|
23
|
-
"@typescript-eslint/key-spacing": "off",
|
|
24
|
-
"@typescript-eslint/keyword-spacing": "off",
|
|
25
|
-
"@typescript-eslint/lines-around-comment": "off",
|
|
26
|
-
"@typescript-eslint/lines-between-class-members": "off",
|
|
27
|
-
"@typescript-eslint/member-delimiter-style": "off",
|
|
28
16
|
"@typescript-eslint/naming-convention": [
|
|
29
17
|
"error",
|
|
30
18
|
{
|
|
@@ -37,23 +25,9 @@ const overrideRules = {
|
|
|
37
25
|
selector: "objectLiteralProperty",
|
|
38
26
|
},
|
|
39
27
|
],
|
|
40
|
-
"@typescript-eslint/no-confusing-void-expression": "off",
|
|
41
|
-
"@typescript-eslint/no-extra-parens": "off",
|
|
42
28
|
"@typescript-eslint/no-magic-numbers": "off",
|
|
43
|
-
"@typescript-eslint/no-misused-promises": "off",
|
|
44
|
-
"@typescript-eslint/no-type-alias": "off",
|
|
45
|
-
"@typescript-eslint/object-curly-spacing": "off",
|
|
46
|
-
"@typescript-eslint/padding-line-between-statements": "off",
|
|
47
|
-
"@typescript-eslint/prefer-readonly": "off",
|
|
48
29
|
"@typescript-eslint/prefer-readonly-parameter-types": "off",
|
|
49
|
-
"@typescript-eslint/
|
|
50
|
-
"@typescript-eslint/semi": "off",
|
|
51
|
-
"@typescript-eslint/sort-type-union-intersection-members": "off",
|
|
52
|
-
"@typescript-eslint/space-before-blocks": "off",
|
|
53
|
-
"@typescript-eslint/space-before-function-paren": "off",
|
|
54
|
-
"@typescript-eslint/space-infix-ops": "off",
|
|
55
|
-
"@typescript-eslint/strict-boolean-expressions": "off",
|
|
56
|
-
"@typescript-eslint/type-annotation-spacing": "off",
|
|
30
|
+
"@typescript-eslint/return-await": ["error", "always"],
|
|
57
31
|
};
|
|
58
32
|
|
|
59
33
|
const config = Object.assign(baseRules, overrideRules);
|
|
@@ -7,7 +7,10 @@ import jestRules from "./rules/jest.mjs";
|
|
|
7
7
|
|
|
8
8
|
const config = [
|
|
9
9
|
{
|
|
10
|
-
files: [
|
|
10
|
+
files: [
|
|
11
|
+
"**/*.{test,spec}.{ts,tsx,js,jsx}",
|
|
12
|
+
"**/__tests__/**/*.{ts,tsx,js,jsx}",
|
|
13
|
+
],
|
|
11
14
|
languageOptions: {
|
|
12
15
|
globals: {
|
|
13
16
|
...globals.jest,
|
|
@@ -18,6 +21,10 @@ const config = [
|
|
|
18
21
|
},
|
|
19
22
|
rules: {
|
|
20
23
|
...jestRules,
|
|
24
|
+
// Mock callbacks often need empty functions
|
|
25
|
+
"no-empty-function": "off",
|
|
26
|
+
// Mock factories use Promise.resolve/reject (conflicts with require-await)
|
|
27
|
+
"promise/prefer-await-to-then": "off",
|
|
21
28
|
},
|
|
22
29
|
},
|
|
23
30
|
];
|
|
@@ -10,7 +10,16 @@ const baseRules = Object.fromEntries(
|
|
|
10
10
|
availableKeys.map((key) => [`jest/${key}`, "error"])
|
|
11
11
|
);
|
|
12
12
|
|
|
13
|
-
const overrideRules = {
|
|
13
|
+
const overrideRules = {
|
|
14
|
+
// Mock factories use conditionals for path-based routing
|
|
15
|
+
"jest/no-conditional-in-test": "off",
|
|
16
|
+
// bun:test uses beforeEach hooks for mock.restore()
|
|
17
|
+
"jest/no-hooks": "off",
|
|
18
|
+
// Too strict for general use — not all tests need explicit assertion counts
|
|
19
|
+
"jest/prefer-expect-assertions": "off",
|
|
20
|
+
// bun:test mock.module() must be called at top level
|
|
21
|
+
"jest/require-hook": "off",
|
|
22
|
+
};
|
|
14
23
|
|
|
15
24
|
const config = Object.assign(baseRules, overrideRules);
|
|
16
25
|
|
|
@@ -1,3 +1,19 @@
|
|
|
1
|
-
|
|
1
|
+
/* eslint-disable n/no-unpublished-import, n/no-extraneous-import, import/no-extraneous-dependencies, id-length */
|
|
2
|
+
|
|
3
|
+
import { plugin as nestjsTyped } from "@darraghor/eslint-plugin-nestjs-typed";
|
|
4
|
+
|
|
5
|
+
import nestjsRules from "./rules/nestjs.mjs";
|
|
6
|
+
|
|
7
|
+
const config = [
|
|
8
|
+
{
|
|
9
|
+
files: ["**/*.ts"],
|
|
10
|
+
plugins: {
|
|
11
|
+
"@darraghor/nestjs-typed": nestjsTyped,
|
|
12
|
+
},
|
|
13
|
+
rules: {
|
|
14
|
+
...nestjsRules,
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
];
|
|
2
18
|
|
|
3
19
|
export default config;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { plugin } from "@darraghor/eslint-plugin-nestjs-typed";
|
|
2
|
+
|
|
3
|
+
const { rules } = plugin;
|
|
4
|
+
|
|
5
|
+
const availableKeys = Object.keys(rules).filter(
|
|
6
|
+
(key) => !rules[key].meta.deprecated
|
|
7
|
+
);
|
|
8
|
+
|
|
9
|
+
const baseRules = Object.fromEntries(
|
|
10
|
+
availableKeys.map((key) => [`@darraghor/nestjs-typed/${key}`, "error"])
|
|
11
|
+
);
|
|
12
|
+
|
|
13
|
+
const overrideRules = {};
|
|
14
|
+
|
|
15
|
+
const config = Object.assign(baseRules, overrideRules);
|
|
16
|
+
|
|
17
|
+
export default config;
|
|
@@ -8,9 +8,7 @@ const baseRules = Object.fromEntries(
|
|
|
8
8
|
availableKeys.map((key) => [`react-hooks/${key}`, "error"])
|
|
9
9
|
);
|
|
10
10
|
|
|
11
|
-
const overrideRules = {
|
|
12
|
-
"react-hooks/exhaustive-deps": "error",
|
|
13
|
-
};
|
|
11
|
+
const overrideRules = {};
|
|
14
12
|
|
|
15
13
|
const config = Object.assign(baseRules, overrideRules);
|
|
16
14
|
|
|
@@ -18,6 +18,7 @@ const overrideRules = {
|
|
|
18
18
|
namedComponents: "arrow-function",
|
|
19
19
|
},
|
|
20
20
|
],
|
|
21
|
+
"react/jsx-boolean-value": "off",
|
|
21
22
|
"react/jsx-filename-extension": [
|
|
22
23
|
"error",
|
|
23
24
|
{
|
|
@@ -36,7 +37,9 @@ const overrideRules = {
|
|
|
36
37
|
"react/no-arrow-function-lifecycle": "off",
|
|
37
38
|
"react/no-invalid-html-attribute": "off",
|
|
38
39
|
"react/no-multi-comp": "off",
|
|
40
|
+
"react/no-unknown-property": "off",
|
|
39
41
|
"react/no-unused-class-component-methods": "off",
|
|
42
|
+
"react/only-export-components": "off",
|
|
40
43
|
"react/react-in-jsx-scope": "off",
|
|
41
44
|
"react/require-default-props": "off",
|
|
42
45
|
};
|
|
@@ -6,12 +6,19 @@ import vitestRules from "./rules/vitest.mjs";
|
|
|
6
6
|
|
|
7
7
|
const config = [
|
|
8
8
|
{
|
|
9
|
-
files: [
|
|
9
|
+
files: [
|
|
10
|
+
"**/*.{test,spec}.{ts,tsx,js,jsx}",
|
|
11
|
+
"**/__tests__/**/*.{ts,tsx,js,jsx}",
|
|
12
|
+
],
|
|
10
13
|
plugins: {
|
|
11
14
|
vitest,
|
|
12
15
|
},
|
|
13
16
|
rules: {
|
|
14
17
|
...vitestRules,
|
|
18
|
+
// Mock callbacks often need empty functions
|
|
19
|
+
"no-empty-function": "off",
|
|
20
|
+
// Mock factories use Promise.resolve/reject (conflicts with require-await)
|
|
21
|
+
"promise/prefer-await-to-then": "off",
|
|
15
22
|
},
|
|
16
23
|
},
|
|
17
24
|
];
|
|
@@ -15,7 +15,7 @@ const overrideRules = {
|
|
|
15
15
|
"vitest/no-conditional-in-test": "off",
|
|
16
16
|
"vitest/no-hooks": "off",
|
|
17
17
|
|
|
18
|
-
//
|
|
18
|
+
// Explicit imports are preferred over globals
|
|
19
19
|
"vitest/no-importing-vitest-globals": "off",
|
|
20
20
|
|
|
21
21
|
// Conflicts with prefer-called-once (the original #604 issue)
|
|
@@ -23,19 +23,21 @@ const overrideRules = {
|
|
|
23
23
|
|
|
24
24
|
// Too strict for general use
|
|
25
25
|
"vitest/prefer-expect-assertions": "off",
|
|
26
|
-
|
|
26
|
+
|
|
27
|
+
// Conflicts with prefer-describe-function-title — function names aren't lowercase strings
|
|
28
|
+
"vitest/prefer-lowercase-title": "off",
|
|
27
29
|
|
|
28
30
|
// Conflicts with prefer-to-be-truthy and prefer-to-be-falsy (#645)
|
|
29
31
|
// prefer-strict-boolean-matchers: use toBe(true)/toBe(false)
|
|
30
32
|
// prefer-to-be-truthy/falsy: use toBeTruthy()/toBeFalsy()
|
|
31
33
|
"vitest/prefer-strict-boolean-matchers": "off",
|
|
32
34
|
|
|
33
|
-
// Too strict for general use
|
|
34
|
-
"vitest/prefer-to-have-been-called-times": "off",
|
|
35
|
-
|
|
36
35
|
// Too strict — matching oxlint jest disabled rules
|
|
37
36
|
"vitest/require-hook": "off",
|
|
38
37
|
"vitest/require-test-timeout": "off",
|
|
38
|
+
|
|
39
|
+
// Conflicts with prefer-describe-function-title — function refs aren't string titles (#665)
|
|
40
|
+
"vitest/valid-title": "off",
|
|
39
41
|
};
|
|
40
42
|
|
|
41
43
|
const config = Object.assign(baseRules, overrideRules);
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import le from"process";import{Command as b0}from"commander";var p={name:"ultracite",version:"7.
|
|
2
|
+
import le from"process";import{Command as b0}from"commander";var p={name:"ultracite",version:"7.7.0",description:"The AI-ready formatter that helps you write and generate code faster.",keywords:["biome","fixer","formatter","linter","ultracite"],homepage:"https://www.ultracite.ai/",bugs:{url:"https://github.com/haydenbleasel/ultracite/issues"},license:"MIT",author:"Hayden Bleasel <hello@haydenbleasel.com>",repository:{type:"git",url:"git+https://github.com/haydenbleasel/ultracite.git"},bin:{ultracite:"dist/index.js"},files:["config","dist","README.md"],type:"module",exports:{"./biome/*":"./config/biome/*/biome.jsonc","./eslint/*":"./config/eslint/*/eslint.config.mjs","./oxlint/*":{types:"./config/oxlint/*/index.d.mts",default:"./config/oxlint/*/index.mjs"},"./oxfmt":{types:"./config/oxfmt/index.d.mts",default:"./config/oxfmt/index.mjs"},"./prettier":"./config/prettier/prettier.config.mjs","./stylelint":"./config/stylelint/stylelint.config.mjs"},publishConfig:{access:"public",registry:"https://registry.npmjs.org/"},scripts:{prebuild:"bun run scripts/generate-dts.ts",build:"tsup",test:"bun test","test:coverage":"bun test --coverage",bench:"bun run benchmarks/cli.bench.ts",types:"tsgo --noEmit"},dependencies:{"@clack/prompts":"^1.3.0",commander:"^14.0.3","cross-spawn":"^7.0.6",deepmerge:"^4.3.1",glob:"^13.0.6","jsonc-parser":"^3.3.1",nypm:"^0.6.6",yaml:"^2.8.4",zod:"^4.4.3"},devDependencies:{"@angular-eslint/eslint-plugin":"^21.3.1","@biomejs/biome":"2.4.15","@darraghor/eslint-plugin-nestjs-typed":"^7.1.32","@eslint/js":"^10.0.1","@next/eslint-plugin-next":"^16.2.6","@repo/data":"workspace:*","@tanstack/eslint-plugin-query":"^5.100.9","@types/bun":"^1.3.13","@types/cross-spawn":"^6.0.6","@types/node":"^25.6.2","@typescript-eslint/eslint-plugin":"^8.59.2","@typescript-eslint/parser":"^8.59.2","@vitest/eslint-plugin":"^1.6.17","eslint-config-prettier":"^10.1.8","eslint-import-resolver-typescript":"^4.4.4","eslint-plugin-astro":"^1.7.0","eslint-plugin-compat":"^7.0.2","eslint-plugin-cypress":"^6.4.1","eslint-plugin-github":"6.0.0","eslint-plugin-html":"^8.1.4","eslint-plugin-import-x":"^4.16.2","eslint-plugin-jest":"^29.15.2","eslint-plugin-jsx-a11y":"^6.10.2","eslint-plugin-n":"^18.0.1","eslint-plugin-prettier":"^5.5.5","eslint-plugin-promise":"^7.3.0","eslint-plugin-qwik":"^1.19.2","eslint-plugin-react":"^7.37.5","eslint-plugin-react-hooks":"^7.1.1","eslint-plugin-remix":"^1.1.1","eslint-plugin-solid":"^0.14.5","eslint-plugin-sonarjs":"^4.0.3","eslint-plugin-storybook":"^10.3.6","eslint-plugin-svelte":"^3.17.1","eslint-plugin-unicorn":"^64.0.0","eslint-plugin-unused-imports":"^4.4.1","eslint-plugin-vue":"^10.9.1",globals:"^17.6.0",oxlint:"^1.63.0","prettier-plugin-astro":"^0.14.1","prettier-plugin-svelte":"^3.5.1","prettier-plugin-tailwindcss":"^0.8.0","stylelint-config-idiomatic-order":"^10.0.0","stylelint-config-standard":"^40.0.0","stylelint-prettier":"^5.0.3",tsup:"^8.5.1"},peerDependencies:{oxfmt:">=0.1.0",oxlint:"^1.0.0"},peerDependenciesMeta:{oxfmt:{optional:!0},oxlint:{optional:!0}},packageManager:"bun@1.3.13"};import{sync as V1}from"cross-spawn";var F=class extends Error{commandName;exitCode;name="LinterExitError";constructor(t,o){super(`${t} exited with code ${o}`),this.commandName=t,this.exitCode=o}},w=(e,t,o)=>V1(e,t,{...o,shell:!1}),k=(e,t)=>{if(t.error)throw new Error(`Failed to run ${e}: ${t.error.message}`);if(t.status===null)throw new Error(`${e} was killed by signal ${t.signal??"unknown"}`);if(t.status!==0)throw new F(e,t.status)},M=e=>{let t=null;for(let o of e)try{o()}catch(i){if(i instanceof F){t??=i;continue}throw i}if(t)throw new F(t.commandName,t.exitCode)};import{accessSync as K1,mkdirSync as Q1}from"fs";import{readFile as Z1,writeFile as Y1}from"fs/promises";import{dirname as qe,join as Te}from"path";import X1 from"process";import{glob as eo}from"glob";import to from"yaml";import{readFileSync as W1}from"fs";import{readFile as q1}from"fs/promises";import{parse as $e}from"jsonc-parser";import{z as f}from"zod";var H1=f.looseObject({dependencies:f.record(f.string(),f.string()).optional(),devDependencies:f.record(f.string(),f.string()).optional(),"lint-staged":f.unknown().optional(),name:f.string().optional(),peerDependencies:f.record(f.string(),f.string()).optional(),prettier:f.unknown().optional(),scripts:f.record(f.string(),f.string()).optional(),stylelint:f.unknown().optional(),type:f.string().optional(),version:f.string().optional(),workspace:f.unknown().optional(),workspaces:f.union([f.array(f.string()),f.record(f.string(),f.unknown())]).optional()}),Q=e=>{let t=$e(e),o=H1.safeParse(t);return o.success?o.data:void 0},G=(e="package.json")=>{try{let t=W1(e,"utf-8");return Q(t)}catch{return}},de=async(e="package.json")=>{try{let t=await q1(e,"utf-8");return Q(t)}catch{return}},_e=f.looseObject({extends:f.array(f.string()).optional()}),Je=f.looseObject({compilerOptions:f.looseObject({strict:f.boolean().optional(),strictNullChecks:f.boolean().optional()}).optional()}),pe=(e,t)=>{let o=$e(e),i=t.safeParse(o);return i.success?i.data:void 0};var m=e=>{try{return K1(e),!0}catch{return!1}},P=()=>{if(m("pnpm-workspace.yaml"))return!0;let e=G();return e?!!e.workspaces||!!e.workspace:!1},x=async({dependencies:e,devDependencies:t,scripts:o,type:i})=>{let s=await de();if(!s)throw new Error("Failed to parse package.json: file is missing or invalid");let r={...s};i&&(r.type=i),(s.devDependencies||t)&&(r.devDependencies={...s.devDependencies,...t}),(s.dependencies||e)&&(r.dependencies={...s.dependencies,...e}),(s.scripts||o)&&(r.scripts={...s.scripts,...o}),await Y1("package.json",`${JSON.stringify(r,null,2)}
|
|
3
3
|
`)},E=e=>{let t=qe(e);if(t!=="."){let o=t.startsWith("./")?t.slice(2):t;Q1(o,{recursive:!0})}},Ve=/^[a-z][a-z0-9-]*$/u,C=e=>{if(!Ve.test(e))throw new Error(`Invalid framework name "${e}": must match ${Ve}`);return e},oo=["biome.json","biome.jsonc"],io=["eslint.config.mjs","eslint.config.js","eslint.config.cjs","eslint.config.ts","eslint.config.mts","eslint.config.cts"],so=[".oxlintrc.json","oxlint.config.ts"],no={"@angular/core":["angular"],"@builder.io/qwik":["qwik"],"@nestjs/core":["nestjs"],"@qwik.dev/core":["qwik"],"@remix-run/node":["remix"],"@remix-run/react":["react","remix"],"@tanstack/react-router":["react","remix"],astro:["astro"],jest:["jest"],next:["react","next"],nuxt:["vue"],react:["react"],"react-router":["react","remix"],"solid-js":["solid"],svelte:["svelte"],vitest:["vitest"],vue:["vue"]},We=e=>e?[...Object.keys(e.dependencies??{}),...Object.keys(e.devDependencies??{}),...Object.keys(e.peerDependencies??{})]:[],ao=async e=>{let t=new Set,o=e?.workspaces;if(Array.isArray(o))for(let i of o)t.add(i);else if(o&&typeof o=="object"){let{packages:i}=o;if(Array.isArray(i))for(let s of i)typeof s=="string"&&t.add(s)}if(m("pnpm-workspace.yaml"))try{let i=await Z1("pnpm-workspace.yaml","utf-8"),s=to.parse(i);if(Array.isArray(s?.packages))for(let r of s.packages)typeof r=="string"&&t.add(r)}catch{}return[...t]},He=async()=>{let e=new Set;try{let t=await de(),o=new Set(We(t)),i=await ao(t);if(i.length>0){let s=await eo(i.map(l=>`${l.replace(/\/+$/u,"")}/package.json`),{absolute:!1,ignore:["**/node_modules/**"]}),r=await Promise.all(s.map(l=>de(l)));for(let l of r)for(let c of We(l))o.add(c)}for(let s of o){let r=no[s];if(r)for(let l of r)e.add(l)}}catch{}return[...e]},$=(e=X1.cwd())=>{let t=e;for(;;){for(let i of oo)if(m(Te(t,i)))return"biome";for(let i of io)if(m(Te(t,i)))return"eslint";for(let i of so)if(m(Te(t,i)))return"oxlint";let o=qe(t);if(o===t)break;t=o}return null};var ro=(e,t)=>{let o=["check","--no-errors-on-unmatched",...t];e.length>0?o.push(...e):o.push("./");let i=w("biome",o,{stdio:"inherit"});k("Biome",i)},lo=(e,t)=>{let o=[...t,...e.length>0?e:["."]],i=w("eslint",o,{stdio:"inherit"});k("ESLint",i)},co=(e,t)=>{let o=["--check",...t,...e.length>0?e:["."]],i=w("prettier",o,{stdio:"inherit"});k("Prettier",i)},po=(e,t)=>{let o=[...t,...e.length>0?e:["."]],i=w("stylelint",o,{stdio:"inherit"});k("Stylelint",i)},mo=(e,t)=>{let o=[...t,...e.length>0?e:["."]],i=w("oxlint",o,{stdio:"inherit"});k("Oxlint",i)},fo=(e,t)=>{let o=["--check",...t,...e.length>0?e:["."]],i=w("oxfmt",o,{stdio:"inherit"});k("oxfmt",i)},Ke=(e=[],t=[])=>{let o=$();if(!o)throw new Error("No linter configuration found. Run `ultracite init` to set up a linter.");switch(o){case"eslint":{M([()=>co(e,[]),()=>lo(e,t),()=>po(e,[])]);break}case"oxlint":{M([()=>fo(e,[]),()=>mo(e,t)]);break}default:ro(e,t)}};import{existsSync as S,readFileSync as fe}from"fs";import{join as z}from"path";import A from"process";import{intro as go,log as I,outro as me,spinner as uo}from"@clack/prompts";import{parse as ho}from"jsonc-parser";var _=(e,t)=>{let o=w(e,["--version"],{encoding:"utf-8"});return o.status===0&&o.stdout?{message:`${e} is installed (${String(o.stdout).trim()})`,name:`${e} installation`,status:"pass"}:{message:`${e} is not installed${t?"":" (optional)"}`,name:`${e} installation`,status:t?"fail":"warn"}},wo=()=>{let e=z(A.cwd(),"biome.json"),t=z(A.cwd(),"biome.jsonc"),o=null;if(S(e)?o=e:S(t)&&(o=t),!o)return{message:"No biome.json or biome.jsonc file found",name:"Biome configuration",status:"fail"};try{let i=fe(o,"utf-8"),s=ho(i);return Array.isArray(s?.extends)&&s.extends.includes("ultracite/biome/core")?{message:"biome.json(c) extends ultracite/biome/core",name:"Biome configuration",status:"pass"}:{message:"biome.json(c) exists but doesn't extend ultracite/biome/core",name:"Biome configuration",status:"warn"}}catch{return{message:"Could not parse biome.json(c) file",name:"Biome configuration",status:"fail"}}},vo=()=>{let e=["eslint.config.mjs","eslint.config.js","eslint.config.cjs","eslint.config.ts","eslint.config.mts","eslint.config.cts"],t=null;for(let o of e){let i=z(A.cwd(),o);if(S(i)){t=i;break}}if(!t)return{message:"No eslint.config.* file found",name:"ESLint configuration",status:"fail"};try{return fe(t,"utf-8").includes("ultracite/eslint")?{message:"eslint.config.* imports ultracite/eslint",name:"ESLint configuration",status:"pass"}:{message:"eslint.config.* exists but doesn't import ultracite/eslint",name:"ESLint configuration",status:"warn"}}catch{return{message:"Could not read eslint.config.* file",name:"ESLint configuration",status:"fail"}}},yo=()=>{let e=["prettier.config.mjs","prettier.config.js","prettier.config.cjs","prettier.config.ts",".prettierrc",".prettierrc.json",".prettierrc.mjs",".prettierrc.cjs",".prettierrc.js",".prettierrc.yml",".prettierrc.yaml"];for(let t of e)if(S(z(A.cwd(),t)))return{message:`Prettier configuration found (${t})`,name:"Prettier configuration",status:"pass"};return{message:"No Prettier configuration found",name:"Prettier configuration",status:"fail"}},ko=()=>{let e=["stylelint.config.mjs","stylelint.config.js","stylelint.config.cjs",".stylelintrc",".stylelintrc.json",".stylelintrc.mjs",".stylelintrc.js",".stylelintrc.yml",".stylelintrc.yaml"];for(let t of e)if(S(z(A.cwd(),t)))return{message:`Stylelint configuration found (${t})`,name:"Stylelint configuration",status:"pass"};return{message:"No Stylelint configuration found",name:"Stylelint configuration",status:"warn"}},bo=()=>{let e=z(A.cwd(),"oxlint.config.ts");if(!S(e))return{message:"No oxlint.config.ts file found",name:"Oxlint configuration",status:"fail"};try{return fe(e,"utf-8").includes("ultracite/oxlint/")?{message:"oxlint.config.ts extends ultracite oxlint config",name:"Oxlint configuration",status:"pass"}:{message:"oxlint.config.ts exists but doesn't extend ultracite config",name:"Oxlint configuration",status:"warn"}}catch{return{message:"Could not read oxlint.config.ts file",name:"Oxlint configuration",status:"fail"}}},xo=()=>{let e=z(A.cwd(),"oxfmt.config.ts");if(!S(e))return{message:"No oxfmt.config.ts file found",name:"oxfmt configuration",status:"fail"};try{return fe(e,"utf-8").includes("ultracite/oxfmt")?{message:"oxfmt.config.ts extends ultracite oxfmt config",name:"oxfmt configuration",status:"pass"}:{message:"oxfmt.config.ts exists but doesn't extend ultracite config",name:"oxfmt configuration",status:"warn"}}catch{return{message:"Could not read oxfmt.config.ts file",name:"oxfmt configuration",status:"fail"}}},Co=()=>{let e=z(A.cwd(),"package.json");if(!S(e))return{message:"No package.json found",name:"Ultracite dependency",status:"warn"};let t=G(e);if(!t)return{message:"Could not parse package.json",name:"Ultracite dependency",status:"warn"};let o=t.dependencies?.ultracite||t.devDependencies?.ultracite||t.peerDependencies?.ultracite;return o?{message:`Ultracite is in package.json (${o})`,name:"Ultracite dependency",status:"pass"}:{message:"Ultracite not found in package.json dependencies",name:"Ultracite dependency",status:"warn"}},So=e=>{let t=[];return e!=="eslint"&&[".prettierrc",".prettierrc.js",".prettierrc.cjs",".prettierrc.mjs",".prettierrc.json",".prettierrc.yaml",".prettierrc.yml","prettier.config.js","prettier.config.mjs","prettier.config.cjs"].some(s=>S(z(A.cwd(),s)))&&t.push("Prettier"),[".eslintrc",".eslintrc.js",".eslintrc.cjs",".eslintrc.mjs",".eslintrc.json",".eslintrc.yaml",".eslintrc.yml"].some(i=>S(z(A.cwd(),i)))&&t.push("ESLint (legacy config)"),t.length>0?{message:`Found potentially conflicting tools: ${t.join(", ")}`,name:"Conflicting tools",status:"warn"}:{message:"No conflicting formatting/linting tools found",name:"Conflicting tools",status:"pass"}},zo=e=>{let t=[];switch(e){case"biome":{t.push({fn:()=>_("biome",!0),name:"Biome installation"},{fn:wo,name:"Biome configuration"});break}case"eslint":{t.push({fn:()=>_("eslint",!0),name:"ESLint installation"},{fn:vo,name:"ESLint configuration"},{fn:()=>_("prettier",!0),name:"Prettier installation"},{fn:yo,name:"Prettier configuration"},{fn:()=>_("stylelint",!1),name:"Stylelint installation"},{fn:ko,name:"Stylelint configuration"});break}case"oxlint":{t.push({fn:()=>_("oxlint",!0),name:"Oxlint installation"},{fn:bo,name:"Oxlint configuration"},{fn:()=>_("oxfmt",!0),name:"oxfmt installation"},{fn:xo,name:"oxfmt configuration"});break}default:break}return t.push({fn:Co,name:"Ultracite dependency"},{fn:()=>So(e),name:"Conflicting tools"}),t},Qe=()=>{go(`Ultracite v${p.version} Doctor`);let e=$();if(!e)throw I.error("No linter configuration found. Run `ultracite init` to set up a linter."),me("Doctor complete"),new Error("Doctor checks failed");I.info(`Detected linter: ${e}`);let t=uo();t.start("Running diagnostics...");let i=zo(e).map(({fn:c})=>c());t.stop("Diagnostics complete.");for(let c of i)c.status==="pass"?I.success(c.message):c.status==="warn"?I.warn(c.message):I.error(c.message);let s=i.filter(c=>c.status==="pass").length,r=i.filter(c=>c.status==="fail").length,l=i.filter(c=>c.status==="warn").length;if(I.info(`Summary: ${s} passed, ${l} warnings, ${r} failed`),r>0)throw I.error("Some checks failed. Run 'ultracite init' to fix issues."),me("Doctor complete"),new Error("Doctor checks failed");if(l>0){I.warn("Some optional improvements available. Run 'ultracite init' to configure."),me("Doctor complete");return}I.success("Everything looks good!"),me("Doctor complete")};var Ao=(e,t)=>{let o=["check","--write","--no-errors-on-unmatched",...t];e.length>0?o.push(...e):o.push("./");let i=w("biome",o,{stdio:"inherit"});k("Biome",i)},Uo=(e,t)=>{let o=["--fix",...t,...e.length>0?e:["."]],i=w("eslint",o,{stdio:"inherit"});k("ESLint",i)},Eo=(e,t)=>{let o=["--write",...t,...e.length>0?e:["."]],i=w("prettier",o,{stdio:"inherit"});k("Prettier",i)},Io=(e,t)=>{let o=["--fix",...t,...e.length>0?e:["."]],i=w("stylelint",o,{stdio:"inherit"});k("Stylelint",i)},jo=(e,t)=>{let o=t.includes("--unsafe"),i=t.filter(l=>l!=="--unsafe"),s=[o?"--fix-dangerously":"--fix",...i,...e.length>0?e:["."]],r=w("oxlint",s,{stdio:"inherit"});k("Oxlint",r)},To=(e,t)=>{let o=["--write",...t,...e.length>0?e:["."]],i=w("oxfmt",o,{stdio:"inherit"});k("oxfmt",i)},Ze=(e,t=[])=>{let o=$();if(!o)throw new Error("No linter configuration found. Run `ultracite init` to set up a linter.");switch(o){case"eslint":{M([()=>Eo(e,[]),()=>Uo(e,t),()=>Io(e,[])]);break}case"oxlint":{M([()=>To(e,[]),()=>jo(e,t)]);break}default:Ao(e,t)}};import Yi from"process";import{cancel as q,intro as Xi,isCancel as H,log as ae,multiselect as re,select as e0,spinner as y}from"@clack/prompts";var Ye="./adal-VMG3GLKT.svg";var Xe="./aider-K7JLZT2D.svg";var et="./amazon-q-TSOJNPXB.svg";var tt="./amp-EV4LVL5I.svg";var ot="./augmentcode-Q62PVXKO.svg";var ge="./bob-MRQ23J26.svg";var it="./claude-6DLEHRDQ.svg";var st="./cline-6HWKIYN7.svg";var nt="./coder-7BVXO5OJ.svg";var at="./codex-NQZ5TJCL.svg";var rt="./continue-LKI2ZW3R.svg";var lt="./copilot-L2IY45R2.svg";var ct="./crush-LYLRDQGZ.svg";var ue="./cursor-GQNH5LCA.svg";var dt="./devin-KY5ISKEW.svg";var pt="./droid-266OHJBT.svg";var mt="./firebase-studio-ILLWWYU7.svg";var ft="./firebender-UNO6LSZG.svg";var gt="./gemini-OYS6V4BH.svg";var ut="./goose-XBIEVD4H.svg";var ht="./jules-HJPVWU73.svg";var wt="./junie-RUWBUV6N.svg";var vt="./kilo-code-4QYUYY2E.svg";var yt="./kimi-6SOFW673.svg";var kt="./langchain-5SXQKAL3.svg";var bt="./lovable-UELF2DY5.svg";var xt="./mcpjam-V2GHUPJN.svg";var Ct="./mistral-HQ63EC2B.svg";var St="./ona-KYYK3HQX.svg";var zt="./open-hands-K5EYKO6T.svg";var At="./openclaw-XFPF7FMJ.svg";var Ut="./opencode-K3274JKQ.svg";var Et="./pi-AZOSKO3D.svg";var It="./qoder-LPW47DKG.svg";var jt="./qwen-N3D5CQYL.svg";var Tt="./replit-WKR4Y6HH.svg";var Gt="./roo-code-CVLBTS7D.svg";var Pt="./snowflake-S3LTTUXJ.svg";var Dt="./vercel-27VSITAQ.svg";var Bt="./warp-OZKAAQRT.svg";var Ft="./zencoder-VTSK5Z7Z.svg";var he=(e,t)=>`# Ultracite Code Standards
|
|
4
4
|
|
|
5
5
|
This project uses **Ultracite**, a zero-config preset that enforces strict code quality standards through automated formatting and linting.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ultracite",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.7.0",
|
|
4
4
|
"description": "The AI-ready formatter that helps you write and generate code faster.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"biome",
|
|
@@ -66,18 +66,19 @@
|
|
|
66
66
|
"zod": "^4.4.3"
|
|
67
67
|
},
|
|
68
68
|
"devDependencies": {
|
|
69
|
-
"@angular-eslint/eslint-plugin": "
|
|
70
|
-
"@biomejs/biome": "2.4.
|
|
69
|
+
"@angular-eslint/eslint-plugin": "^21.3.1",
|
|
70
|
+
"@biomejs/biome": "2.4.15",
|
|
71
|
+
"@darraghor/eslint-plugin-nestjs-typed": "^7.1.32",
|
|
71
72
|
"@eslint/js": "^10.0.1",
|
|
72
73
|
"@next/eslint-plugin-next": "^16.2.6",
|
|
73
74
|
"@repo/data": "workspace:*",
|
|
74
75
|
"@tanstack/eslint-plugin-query": "^5.100.9",
|
|
75
76
|
"@types/bun": "^1.3.13",
|
|
76
77
|
"@types/cross-spawn": "^6.0.6",
|
|
77
|
-
"@types/node": "^25.6.
|
|
78
|
+
"@types/node": "^25.6.2",
|
|
78
79
|
"@typescript-eslint/eslint-plugin": "^8.59.2",
|
|
79
80
|
"@typescript-eslint/parser": "^8.59.2",
|
|
80
|
-
"@vitest/eslint-plugin": "^1.6.
|
|
81
|
+
"@vitest/eslint-plugin": "^1.6.17",
|
|
81
82
|
"eslint-config-prettier": "^10.1.8",
|
|
82
83
|
"eslint-import-resolver-typescript": "^4.4.4",
|
|
83
84
|
"eslint-plugin-astro": "^1.7.0",
|