UNPKG

ultracite

Version:

The AI-ready formatter that helps you write and generate code faster.

276 lines (232 loc) 72.2 kB
#!/usr/bin/env node import{createRequire as hb}from"node:module";var cb=hb(import.meta.url);import z1 from"node:process";import{log as _$}from"@clack/prompts";import{Command as T$}from"commander";var z={name:"ultracite",version:"7.9.4",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:"tsgo --noEmit && bun run build.ts",test:"bun test","test:coverage":"bun test --coverage",bench:"bun run benchmarks/cli.bench.ts",types:"tsgo --noEmit"},dependencies:{"@clack/prompts":"^1.5.1","@typescript-eslint/utils":"^8.62.1",commander:"^15.0.0","cross-spawn":"^7.0.6",deepmerge:"^4.3.1",glob:"^13.0.6","jsonc-parser":"^3.3.1",nypm:"^0.6.6",yaml:"^2.9.0",zod:"^4.4.3"},devDependencies:{"@angular-eslint/eslint-plugin":"^22.0.0","@biomejs/biome":"2.5.3","@darraghor/eslint-plugin-nestjs-typed":"^7.2.5","@eslint/js":"^10.0.0","@next/eslint-plugin-next":"^16.2.10","@tanstack/eslint-plugin-query":"^5.101.2","@tanstack/eslint-plugin-router":"^1.162.0","@tanstack/eslint-plugin-start":"^0.1.0","@types/bun":"^1.3.14","@types/cross-spawn":"^6.0.6","@types/node":"^25.9.2","@typescript-eslint/eslint-plugin":"^8.62.1","@typescript-eslint/parser":"^8.62.1","@vitest/eslint-plugin":"^1.6.21",eslint:"^10.0.0","eslint-config-prettier":"^10.1.8","eslint-import-resolver-typescript":"^4.4.5","eslint-plugin-astro":"^2.1.1","eslint-plugin-compat":"^7.0.2","eslint-plugin-cypress":"^6.4.2","eslint-plugin-github":"6.0.0","eslint-plugin-html":"^8.1.4","eslint-plugin-import-x":"^4.17.1","eslint-plugin-jest":"^29.15.4","eslint-plugin-jsdoc":"^63.0.11","eslint-plugin-jsx-a11y":"^6.10.2","eslint-plugin-n":"^18.2.1","eslint-plugin-prettier":"^5.5.6","eslint-plugin-promise":"^7.3.0","eslint-plugin-qwik":"^1.20.0","eslint-plugin-react":"^7.37.5","eslint-plugin-react-doctor":"^0.7.1","eslint-plugin-react-hooks":"^7.1.1","eslint-plugin-remix":"^1.1.1","eslint-plugin-solid":"^0.14.5","eslint-plugin-sonarjs":"^4.1.0","eslint-plugin-storybook":"^10.4.6","eslint-plugin-svelte":"^3.20.0","eslint-plugin-unicorn":"^70.0.0","eslint-plugin-unused-imports":"^4.4.1","eslint-plugin-vue":"^10.9.2",globals:"^17.7.0",oxlint:"^1.73.0","oxlint-plugin-react-doctor":"^0.7.1","prettier-plugin-astro":"^0.14.1","prettier-plugin-svelte":"^4.1.0","prettier-plugin-tailwindcss":"^0.8.0",storybook:"^10.4.6","stylelint-config-idiomatic-order":"^10.0.0","stylelint-config-standard":"^40.0.0","stylelint-prettier":"^5.0.3"},peerDependencies:{oxfmt:">=0.1.0",oxlint:"^1.0.0"},peerDependenciesMeta:{oxfmt:{optional:!0},oxlint:{optional:!0}},packageManager:"bun@1.3.14"};import{readFileSync as $2}from"node:fs";import u from"node:path";import _0 from"node:process";import{parse as y2}from"jsonc-parser";import{accessSync as lb,lstatSync as R0,mkdirSync as nb,realpathSync as m0}from"node:fs";import{readFile as rb,writeFile as sb}from"node:fs/promises";import L from"node:path";import a1 from"node:process";import{glob as ib}from"glob";import gb from"yaml";import{readFileSync as fb}from"node:fs";import{readFile as kb}from"node:fs/promises";import{parse as L0}from"jsonc-parser";import{z as X}from"zod";var Cb=X.looseObject({dependencies:X.record(X.string(),X.string()).optional(),devDependencies:X.record(X.string(),X.string()).optional(),"lint-staged":X.unknown().optional(),name:X.string().optional(),peerDependencies:X.record(X.string(),X.string()).optional(),prettier:X.unknown().optional(),scripts:X.record(X.string(),X.string()).optional(),stylelint:X.unknown().optional(),type:X.string().optional(),version:X.string().optional(),workspace:X.unknown().optional(),workspaces:X.union([X.array(X.string()),X.record(X.string(),X.unknown())]).optional()}),g=(b)=>{let $=L0(b),y=Cb.safeParse($);return y.success?y.data:void 0},h=(b="package.json")=>{try{let $=fb(b,"utf-8");return g($)}catch{return}},t=async(b="package.json")=>{try{let $=await kb(b,"utf-8");return g($)}catch{return}},N0=X.looseObject({extends:X.array(X.string()).optional()}),S0=X.looseObject({compilerOptions:X.looseObject({strict:X.boolean().optional(),strictNullChecks:X.boolean().optional()}).optional()}),I1=(b,$)=>{let y=L0(b),G=$.safeParse(y);return G.success?G.data:void 0};var e1="pnpm-workspace.yaml",V=(b)=>{try{return lb(b),!0}catch{return!1}},c=()=>{if(V(e1))return!0;let b=h();if(!b)return!1;return!!b.workspaces||!!b.workspace},R=(b)=>{let $=L.dirname(b);if($!=="."){let y=$.startsWith("./")?$.slice(2):$;nb(y,{recursive:!0})}},t1=(b,$)=>{let y=L.relative($,b);return y===""||!y.startsWith("..")&&!L.isAbsolute(y)},b0=(b)=>typeof m0==="function"?m0(b):L.resolve(b),tb=(b)=>{let $=b;while(!0)try{return b0($)}catch(y){if(y.code!=="ENOENT")throw y;let G=L.dirname($);if(G===$)return L.resolve($);$=G}},ab=(b)=>{let $=b0(a1.cwd()),y=L.resolve(a1.cwd(),b);if(!t1(y,$))throw Error(`Refusing to write outside project: ${b}`);let G=L.dirname(y),Q=tb(G);if(!t1(Q,$))throw Error(`Refusing to write through directory outside project: ${b}`);try{if((typeof R0==="function"?R0(y):void 0)?.isSymbolicLink())throw Error(`Refusing to write through symbolic link: ${b}`);let Z=b0(y);if(!t1(Z,$))throw Error(`Refusing to write outside project: ${b}`)}catch(W){if(W.code==="ENOENT")return;throw W}},v=async(b,$)=>{ab(b),R(b),await sb(b,$)},N=async({dependencies:b,devDependencies:$,scripts:y,type:G})=>{let Q=await t();if(!Q)throw Error("Failed to parse package.json: file is missing or invalid");let W={...Q};if(G)W.type=G;if(Q.devDependencies||$)W.devDependencies={...Q.devDependencies,...$};if(Q.dependencies||b)W.dependencies={...Q.dependencies,...b};if(Q.scripts||y)W.scripts={...Q.scripts,...y};await v("package.json",`${JSON.stringify(W,null,2)} `)},I0=/^[a-z][a-z0-9-]*$/u,m=(b)=>{if(!I0.test(b))throw Error(`Invalid framework name "${b}": must match ${I0}`);return b},I=["biome.json","biome.jsonc",".biome.json",".biome.jsonc"],C=["eslint.config.mjs","eslint.config.js","eslint.config.cjs","eslint.config.ts","eslint.config.mts","eslint.config.cts"],F0=[".eslintrc",".eslintrc.json",".eslintrc.js",".eslintrc.cjs",".eslintrc.yaml",".eslintrc.yml"],a=[".prettierrc.mjs","prettier.config.mjs",".prettierrc.mts","prettier.config.mts",".prettierrc.cjs","prettier.config.cjs",".prettierrc.cts","prettier.config.cts",".prettierrc.js","prettier.config.js",".prettierrc.ts","prettier.config.ts",".prettierrc",".prettierrc.json",".prettierrc.json5",".prettierrc.yml",".prettierrc.yaml",".prettierrc.toml"],e=[".stylelintrc.mjs","stylelint.config.mjs",".stylelintrc.cjs","stylelint.config.cjs",".stylelintrc.js","stylelint.config.js",".stylelintrc",".stylelintrc.json",".stylelintrc.yml",".stylelintrc.yaml"],$0=[".oxlintrc.json","oxlint.config.ts"],O0=["oxfmt.config.ts"],eb={"@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-query":["react","tanstack"],"@tanstack/react-router":["react","tanstack"],"@tanstack/react-start":["react","tanstack"],astro:["astro"],jest:["jest"],next:["react","next"],nuxt:["vue"],react:["react"],"react-router":["react","remix"],"solid-js":["solid"],svelte:["svelte"],vitest:["vitest"],vue:["vue"]},u0=(b)=>{if(!b)return[];return[...Object.keys(b.dependencies??{}),...Object.keys(b.devDependencies??{}),...Object.keys(b.peerDependencies??{})]},b2=async(b)=>{let $=new Set,y=b?.workspaces;if(Array.isArray(y))for(let G of y)$.add(G);else if(y&&typeof y==="object"){let{packages:G}=y;if(Array.isArray(G)){for(let Q of G)if(typeof Q==="string")$.add(Q)}}if(V(e1))try{let G=await rb(e1,"utf-8"),Q=gb.parse(G);if(Array.isArray(Q?.packages)){for(let W of Q.packages)if(typeof W==="string")$.add(W)}}catch{}return[...$]},o0=async()=>{let b=new Set;try{let $=await t(),y=new Set(u0($)),G=await b2($);if(G.length>0){let Q=await ib(G.map((Z)=>`${Z.replace(/\/+$/u,"")}/package.json`),{absolute:!1,ignore:["**/node_modules/**"]}),W=await Promise.all(Q.map((Z)=>t(Z)));for(let Z of W)for(let U of u0(Z))y.add(U)}for(let Q of y){let W=eb[Q];if(W)for(let Z of W)b.add(Z)}}catch{}return[...b]},b1=(b=a1.cwd())=>{let $=b;while(!0){for(let G of I)if(V(L.join($,G)))return"biome";for(let G of C)if(V(L.join($,G)))return"eslint";for(let G of $0)if(V(L.join($,G)))return"oxlint";let y=L.dirname($);if(y===$)break;$=y}return null};var T0="ultracite",u1="ultracite/biome/core",G2={biome:u1,eslint:"ultracite/eslint/core",oxlint:"ultracite/oxlint/core"},y0={exists:V,readFile:(b)=>$2(b,"utf-8")},q0=(b,$)=>{let y=b;while(!0){let G=$(y);if(G!==null)return G;let Q=u.dirname(y);if(Q===y)return null;y=Q}},Q2=(b,$)=>q0(b,(y)=>{let G=u.join(y,"node_modules",T0);return $.exists(u.join(G,"package.json"))?G:null}),W2=(b)=>{if(typeof b==="string")return b;let $=b.default;return typeof $==="string"?$:null},Z2=(b,$,y)=>{let G=W2($);if(!G)return null;if(!b.includes("*"))return b===y?G:null;let[Q,W]=b.split("*");if(!y.startsWith(Q)||!y.endsWith(W)||y.length<Q.length+W.length)return null;let Z=y.slice(Q.length,y.length-W.length);return G.replaceAll("*",Z)},E0=(b,$,y=y0)=>{let G=Q2($,y);if(!G)return null;let Q;try{Q=JSON.parse(y.readFile(u.join(G,"package.json")))?.exports??{}}catch{return null}let W=`.${b.slice(T0.length)}`;for(let[Z,U]of Object.entries(Q)){let H=Z2(Z,U,W);if(H){let B=u.join(G,H);return y.exists(B)?B:null}}return null},M0=(b,$=_0.cwd(),y=y0)=>E0(G2[b],$,y)!==null,U2=(b,$)=>q0(b,(y)=>{for(let G of I){let Q=u.join(y,G);if($.exists(Q))return Q}return null}),v2=(b,$)=>{try{let y=y2($.readFile(b));return Array.isArray(y?.extends)&&y.extends.includes(u1)}catch{return!1}},F1=(b=_0.cwd(),$=y0)=>{let y=U2(b,$);if(!y||!v2(y,$))return null;return E0(u1,u.dirname(y),$)?null:y};class l extends Error{name="UltraciteSetupError"}var O1=(b)=>[`${u.basename(b)} extends "${u1}", but Ultracite could not be resolved from ${u.dirname(b)}.`,"Biome loads that config from your project's node_modules, so Ultracite has to be installed there — running the CLI through npx/bunx doesn't install it.","Add it as a dev dependency (e.g. `npm install --save-dev ultracite`) and try again."].join(" ");import{existsSync as z2}from"node:fs";import Y2 from"node:path";var H2=(b,$,y)=>{let G=y?.indexOf(b)??-1;if(!y||G===-1)return $;return y.slice(G+1)},o1=(b)=>b.map(($)=>$.startsWith("-")?`./${$}`:$),G0="**/*.{css,scss,sass,less}",V2=[".css",".scss",".sass",".less"],X2=(b)=>{let $=b.toLowerCase();return V2.some((y)=>$.endsWith(y))},_1=(b)=>{if(b.length===0)return[G0];let $=[];for(let y of b){if(X2(y)){$.push(y);continue}if(Y2.extname(y)===""){let G=y.replace(/\/+$/u,"");$.push(G==="."||G===""?G0:`${G}/${G0}`)}}return $},Q0=({commandName:b,parsedArgs:$,pathExists:y=z2,rawArgs:G})=>{let Q=H2(b,$,G),W=Q.indexOf("--");if(W!==-1)return{files:Q.slice(W+1),passthrough:Q.slice(0,W)};let Z=[],U=[];for(let H of Q){if(H.startsWith("-")&&!y(H)){U.push(H);continue}Z.push(H)}return{files:Z,passthrough:U}};import{sync as B2}from"cross-spawn";class $1 extends Error{commandName;exitCode;name="LinterExitError";constructor(b,$){super(`${b} exited with code ${$}`);this.commandName=b,this.exitCode=$}}var A=(b,$,y)=>B2(b,$,{...y,shell:!1}),d=(b,$)=>{if($.error)throw Error(`Failed to run ${b}: ${$.error.message}`);if($.status===null)throw Error(`${b} was killed by signal ${$.signal??"unknown"}`);if($.status!==0)throw new $1(b,$.status)},y1=(b)=>{let $=null;for(let y of b)try{y()}catch(G){if(G instanceof $1){$??=G;continue}throw G}if($)throw new $1($.commandName,$.exitCode)};var K2=(b,$)=>{let y=F1();if(y)throw new l(O1(y));let G=["check","--no-errors-on-unmatched",...$];if(b.length>0)G.push(...b);else G.push("./");let Q=A("biome",G,{stdio:"inherit"});d("Biome",Q)},w2=(b,$)=>{let y=[...$,...b.length>0?b:["."]],G=A("eslint",y,{stdio:"inherit"});d("ESLint",G)},A2=(b,$)=>{let y=["--check",...$,...b.length>0?b:["."]],G=A("prettier",y,{stdio:"inherit"});d("Prettier",G)},J2=(b,$)=>{let y=_1(b);if(y.length===0)return;let G=[...$,"--allow-empty-input",...y],Q=A("stylelint",G,{stdio:"inherit"});d("Stylelint",Q)},j2=(b,$)=>{let y=[...$,...b.length>0?b:["."]],G=A("oxlint",y,{stdio:"inherit"});d("Oxlint",G)},D2=(b,$)=>{let y=["--check",...$,...b.length>0?b:["."]],G=A("oxfmt",y,{stdio:"inherit"});d("oxfmt",G)},p0=(b=[],$=[])=>{let y=b1(),G=o1(b);if(!y)throw Error("No linter configuration found. Run `ultracite init` to set up a linter.");switch(y){case"eslint":{y1([()=>A2(G,[]),()=>w2(G,$),()=>J2(G,[])]);break}case"oxlint":{y1([()=>D2(G,[]),()=>j2(G,$)]);break}default:K2(G,$)}};import{existsSync as O,readFileSync as E1}from"node:fs";import o from"node:path";import _ from"node:process";import{intro as d2,log as F,outro as T1,spinner as x2}from"@clack/prompts";import{parse as L2}from"jsonc-parser";var H1="Biome configuration",V1="ESLint configuration",W0="Prettier configuration",Z0="Stylelint configuration",X1="Oxlint configuration",B1="oxfmt configuration",Q1="Ultracite dependency",U0="Conflicting tools",q1="Doctor complete",G1=(b,$)=>{let y=A(b,["--version"],{encoding:"utf-8"});if(y.status===0&&y.stdout)return{message:`${b} is installed (${String(y.stdout).trim()})`,name:`${b} installation`,status:"pass"};return{message:`${b} is not installed${$?"":" (optional)"}`,name:`${b} installation`,status:$?"fail":"warn"}},N2=()=>{let b=null,$=null;for(let y of I){let G=o.join(_.cwd(),y);if(O(G)){b=G,$=y;break}}if(!b)return{message:`No Biome config file found (expected one of: ${I.join(", ")})`,name:H1,status:"fail"};try{let y=E1(b,"utf-8"),G=L2(y);if(Array.isArray(G?.extends)&&G.extends.includes("ultracite/biome/core"))return{message:`${$} extends ultracite/biome/core`,name:H1,status:"pass"};return{message:`${$} exists but doesn't extend ultracite/biome/core`,name:H1,status:"warn"}}catch{return{message:`Could not parse ${$} file`,name:H1,status:"fail"}}},S2=()=>{let b=null;for(let $ of C){let y=o.join(_.cwd(),$);if(O(y)){b=y;break}}if(!b)return{message:"No eslint.config.* file found",name:V1,status:"fail"};try{if(E1(b,"utf-8").includes("ultracite/eslint"))return{message:"eslint.config.* imports ultracite/eslint",name:V1,status:"pass"};return{message:"eslint.config.* exists but doesn't import ultracite/eslint",name:V1,status:"warn"}}catch{return{message:"Could not read eslint.config.* file",name:V1,status:"fail"}}},R2=()=>{for(let b of a)if(O(o.join(_.cwd(),b)))return{message:`Prettier configuration found (${b})`,name:W0,status:"pass"};return{message:"No Prettier configuration found",name:W0,status:"fail"}},m2=()=>{for(let b of e)if(O(o.join(_.cwd(),b)))return{message:`Stylelint configuration found (${b})`,name:Z0,status:"pass"};return{message:"No Stylelint configuration found",name:Z0,status:"warn"}},I2=()=>{let b=o.join(_.cwd(),"oxlint.config.ts");if(!O(b))return{message:"No oxlint.config.ts file found",name:X1,status:"fail"};try{if(E1(b,"utf-8").includes("ultracite/oxlint/"))return{message:"oxlint.config.ts extends ultracite oxlint config",name:X1,status:"pass"};return{message:"oxlint.config.ts exists but doesn't extend ultracite config",name:X1,status:"warn"}}catch{return{message:"Could not read oxlint.config.ts file",name:X1,status:"fail"}}},u2=()=>{let b=o.join(_.cwd(),"oxfmt.config.ts");if(!O(b))return{message:"No oxfmt.config.ts file found",name:B1,status:"fail"};try{if(E1(b,"utf-8").includes("ultracite/oxfmt"))return{message:"oxfmt.config.ts extends ultracite oxfmt config",name:B1,status:"pass"};return{message:"oxfmt.config.ts exists but doesn't extend ultracite config",name:B1,status:"warn"}}catch{return{message:"Could not read oxfmt.config.ts file",name:B1,status:"fail"}}},F2=(b)=>{let $=o.join(_.cwd(),"package.json");if(!O($))return{message:"No package.json found",name:Q1,status:"warn"};let y=h($);if(!y)return{message:"Could not parse package.json",name:Q1,status:"warn"};let G=y.dependencies?.ultracite||y.devDependencies?.ultracite||y.peerDependencies?.ultracite;if(!M0(b))return{message:G?`Ultracite is in package.json (${G}) but isn't installed — run your package manager's install`:"Ultracite is not installed in this project — install it as a dev dependency",name:Q1,status:"fail"};if(G)return{message:`Ultracite is installed (${G})`,name:Q1,status:"pass"};return{message:"Ultracite not found in package.json dependencies",name:Q1,status:"warn"}},O2=(b)=>{let $=[];if(b!=="eslint"){if([".prettierrc",".prettierrc.js",".prettierrc.cjs",".prettierrc.mjs",".prettierrc.json",".prettierrc.yaml",".prettierrc.yml","prettier.config.js","prettier.config.mjs","prettier.config.cjs"].some((Q)=>O(o.join(_.cwd(),Q))))$.push("Prettier")}if([".eslintrc",".eslintrc.js",".eslintrc.cjs",".eslintrc.mjs",".eslintrc.json",".eslintrc.yaml",".eslintrc.yml"].some((G)=>O(o.join(_.cwd(),G))))$.push("ESLint (legacy config)");if($.length>0)return{message:`Found potentially conflicting tools: ${$.join(", ")}`,name:U0,status:"warn"};return{message:"No conflicting formatting/linting tools found",name:U0,status:"pass"}},o2=(b)=>{let $=[];switch(b){case"biome":{$.push({fn:()=>G1("biome",!0),name:"Biome installation"},{fn:N2,name:H1});break}case"eslint":{$.push({fn:()=>G1("eslint",!0),name:"ESLint installation"},{fn:S2,name:V1},{fn:()=>G1("prettier",!0),name:"Prettier installation"},{fn:R2,name:W0},{fn:()=>G1("stylelint",!1),name:"Stylelint installation"},{fn:m2,name:Z0});break}case"oxlint":{$.push({fn:()=>G1("oxlint",!0),name:"Oxlint installation"},{fn:I2,name:X1},{fn:()=>G1("oxfmt",!0),name:"oxfmt installation"},{fn:u2,name:B1});break}default:break}return $.push({fn:()=>F2(b),name:Q1},{fn:()=>O2(b),name:U0}),$},h0=()=>{d2(`Ultracite v${z.version} Doctor`);let b=b1();if(!b)throw F.error("No linter configuration found. Run `ultracite init` to set up a linter."),T1(q1),Error("Doctor checks failed");F.info(`Detected linter: ${b}`);let $=x2();$.start("Running diagnostics...");let G=o2(b).map(({fn:U})=>U());$.stop("Diagnostics complete.");for(let U of G)if(U.status==="pass")F.success(U.message);else if(U.status==="warn")F.warn(U.message);else F.error(U.message);let Q=G.filter((U)=>U.status==="pass").length,W=G.filter((U)=>U.status==="fail").length,Z=G.filter((U)=>U.status==="warn").length;if(F.info(`Summary: ${Q} passed, ${Z} warnings, ${W} failed`),W>0)throw F.error("Some checks failed. Run 'ultracite init' to fix issues."),T1(q1),Error("Doctor checks failed");if(Z>0){F.warn("Some optional improvements available. Run 'ultracite init' to configure."),T1(q1);return}F.success("Everything looks good!"),T1(q1)};var _2=(b,$)=>{let y=F1();if(y)throw new l(O1(y));let G=["check","--write","--no-errors-on-unmatched",...$];if(b.length>0)G.push(...b);else G.push("./");let Q=A("biome",G,{stdio:"inherit"});d("Biome",Q)},T2=(b,$)=>{let y=["--fix",...$,...b.length>0?b:["."]],G=A("eslint",y,{stdio:"inherit"});d("ESLint",G)},q2=(b,$)=>{let y=["--write",...$,...b.length>0?b:["."]],G=A("prettier",y,{stdio:"inherit"});d("Prettier",G)},E2=(b,$)=>{let y=_1(b);if(y.length===0)return;let G=["--fix",...$,"--allow-empty-input",...y],Q=A("stylelint",G,{stdio:"inherit"});d("Stylelint",Q)},M2=(b,$)=>{let y=$.includes("--unsafe"),G=$.filter((Z)=>Z!=="--unsafe"),Q=[y?"--fix-dangerously":"--fix",...G,...b.length>0?b:["."]],W=A("oxlint",Q,{stdio:"inherit"});d("Oxlint",W)},p2=(b,$)=>{let y=["--write",...$,...b.length>0?b:["."]],G=A("oxfmt",y,{stdio:"inherit"});d("oxfmt",G)},c0=(b,$=[])=>{let y=b1(),G=o1(b);if(!y)throw Error("No linter configuration found. Run `ultracite init` to set up a linter.");switch(y){case"eslint":{y1([()=>q2(G,[]),()=>T2(G,$),()=>E2(G,[])]);break}case"oxlint":{y1([()=>p2(G,[]),()=>M2(G,$)]);break}default:_2(G,$)}};import U$ from"node:process";import{cancel as r,intro as v$,isCancel as s,log as R1,multiselect as v1,select as z$,spinner as D}from"@clack/prompts";import{addDevDependency as Y$,detectPackageManager as H$}from"nypm";import{readFile as h2}from"node:fs/promises";import{dlxCommand as c2}from"nypm";var v0=(b,$)=>`# Ultracite Code Standards This project uses **Ultracite**, a zero-config preset that enforces strict code quality standards through automated formatting and linting. ## Quick Reference - **Format code**: \`${b} ultracite fix\` - **Check for issues**: \`${b} ultracite check\` - **Diagnose setup**: \`${b} ultracite doctor\` ${$} (the underlying engine) provides robust linting and formatting. Most issues are automatically fixable. --- ## Core Principles Write code that is **accessible, performant, type-safe, and maintainable**. Focus on clarity and explicit intent over brevity. ### Type Safety & Explicitness - Use explicit types for function parameters and return values when they enhance clarity - Prefer \`unknown\` over \`any\` when the type is genuinely unknown - Use const assertions (\`as const\`) for immutable values and literal types - Leverage TypeScript's type narrowing instead of type assertions - Use meaningful variable names instead of magic numbers - extract constants with descriptive names ### Modern JavaScript/TypeScript - Use arrow functions for callbacks and short functions - Prefer \`for...of\` loops over \`.forEach()\` and indexed \`for\` loops - Use optional chaining (\`?.\`) and nullish coalescing (\`??\`) for safer property access - Prefer template literals over string concatenation - Use destructuring for object and array assignments - Use \`const\` by default, \`let\` only when reassignment is needed, never \`var\` ### Async & Promises - Always \`await\` promises in async functions - don't forget to use the return value - Use \`async/await\` syntax instead of promise chains for better readability - Handle errors appropriately in async code with try-catch blocks - Don't use async functions as Promise executors ### React & JSX - Use function components over class components - Call hooks at the top level only, never conditionally - Specify all dependencies in hook dependency arrays correctly - Use the \`key\` prop for elements in iterables (prefer unique IDs over array indices) - Nest children between opening and closing tags instead of passing as props - Don't define components inside other components - Use semantic HTML and ARIA attributes for accessibility: - Provide meaningful alt text for images - Use proper heading hierarchy - Add labels for form inputs - Include keyboard event handlers alongside mouse events - Use semantic elements (\`<button>\`, \`<nav>\`, etc.) instead of divs with roles ### Error Handling & Debugging - Remove \`console.log\`, \`debugger\`, and \`alert\` statements from production code - Throw \`Error\` objects with descriptive messages, not strings or other values - Use \`try-catch\` blocks meaningfully - don't catch errors just to rethrow them - Prefer early returns over nested conditionals for error cases ### Code Organization - Keep functions focused and under reasonable cognitive complexity limits - Extract complex conditions into well-named boolean variables - Use early returns to reduce nesting - Prefer simple conditionals over nested ternary operators - Group related code together and separate concerns ### Security - Add \`rel="noopener"\` when using \`target="_blank"\` on links - Avoid \`dangerouslySetInnerHTML\` unless absolutely necessary - Don't use \`eval()\` or assign directly to \`document.cookie\` - Validate and sanitize user input ### Performance - Avoid spread syntax in accumulators within loops - Use top-level regex literals instead of creating them in loops - Prefer specific imports over namespace imports - Avoid barrel files (index files that re-export everything) - Use proper image components (e.g., Next.js \`<Image>\`) over \`<img>\` tags ### Framework-Specific Guidance **Next.js:** - Use Next.js \`<Image>\` component for images - Use \`next/head\` or App Router metadata API for head elements - Use Server Components for async data fetching instead of async Client Components **React 19+:** - Use ref as a prop instead of \`React.forwardRef\` **Solid/Svelte/Vue/Qwik:** - Use \`class\` and \`for\` attributes (not \`className\` or \`htmlFor\`) --- ## Testing - Write assertions inside \`it()\` or \`test()\` blocks - Avoid done callbacks in async tests - use async/await instead - Don't use \`.only\` or \`.skip\` in committed code - Keep test suites reasonably flat - avoid excessive \`describe\` nesting ## When ${$} Can't Help ${$}'s linter will catch most issues automatically. Focus your attention on: 1. **Business logic correctness** - ${$} can't validate your algorithms 2. **Meaningful naming** - Use descriptive names for functions, variables, and types 3. **Architecture decisions** - Component structure, data flow, and API design 4. **Edge cases** - Handle boundary conditions and error states 5. **User experience** - Accessibility, performance, and usability considerations 6. **Documentation** - Add comments for complex logic, but prefer self-documenting code --- Most formatting and common issues are automatically fixed by ${$}. Run \`${b} ultracite fix\` before committing to ensure compliance. `;var n=[{config:{appendMode:!0,path:".claude/CLAUDE.md"},hooks:{getContent:(b)=>({hooks:{PostToolUse:[{hooks:[{command:b,type:"command"}],matcher:"Write|Edit"}]}}),path:".claude/settings.json"},id:"claude",name:"Claude Code"},{config:{appendMode:!0,path:"AGENTS.md"},id:"codex",name:"Codex"},{config:{appendMode:!0,path:"AGENTS.md"},id:"jules",name:"Jules"},{config:{appendMode:!0,path:"replit.md"},id:"replit",name:"Replit Agent"},{config:{appendMode:!0,path:"AGENTS.md"},id:"devin",name:"Devin"},{config:{appendMode:!0,path:"AGENTS.md"},id:"lovable",name:"Lovable"},{config:{appendMode:!0,path:"AGENTS.md"},id:"zencoder",name:"Zencoder"},{config:{appendMode:!0,path:"AGENTS.md"},id:"ona",name:"Ona"},{config:{appendMode:!0,path:"AGENTS.md"},id:"openclaw",name:"OpenClaw"},{config:{appendMode:!0,path:"AGENTS.md"},id:"continue",name:"Continue"},{config:{appendMode:!0,path:"AGENTS.md"},id:"snowflake-cortex",name:"Snowflake Cortex"},{config:{appendMode:!0,path:"AGENTS.md"},id:"deepagents",name:"Deepagents"},{config:{appendMode:!0,path:"AGENTS.md"},id:"qoder",name:"Qoder"},{config:{appendMode:!0,path:"AGENTS.md"},id:"kimi-cli",name:"Kimi CLI"},{config:{appendMode:!0,path:"AGENTS.md"},id:"mcpjam",name:"MCPJam"},{config:{appendMode:!0,path:"AGENTS.md"},id:"mux",name:"Mux"},{config:{appendMode:!0,path:"AGENTS.md"},id:"pi",name:"Pi"},{config:{appendMode:!0,path:"AGENTS.md"},id:"adal",name:"AdaL"},{config:{appendMode:!0,path:"AGENTS.md"},hooks:{getContent:(b)=>({hooks:{PostToolUse:[{command:b,type:"command"}]}}),path:".github/hooks/ultracite.json"},id:"copilot",name:"GitHub Copilot"},{config:{appendMode:!0,path:"AGENTS.md"},id:"cline",name:"Cline"},{config:{appendMode:!0,path:"AGENTS.md"},id:"amp",name:"AMP"},{config:{path:"ultracite.md"},id:"aider",name:"Aider"},{config:{appendMode:!0,path:"AGENTS.md"},id:"firebase-studio",name:"Firebase Studio"},{config:{appendMode:!0,path:"AGENTS.md"},id:"open-hands",name:"OpenHands"},{config:{appendMode:!0,path:"GEMINI.md"},id:"gemini",name:"Gemini"},{config:{appendMode:!0,path:"AGENTS.md"},id:"junie",name:"Junie"},{config:{appendMode:!0,path:"AGENTS.md"},id:"augmentcode",name:"Augment Code"},{config:{appendMode:!0,path:"AGENTS.md"},id:"bob",name:"IBM Bob"},{config:{appendMode:!0,path:"AGENTS.md"},id:"kilo-code",name:"Kilo Code"},{config:{appendMode:!0,path:"AGENTS.md"},id:"goose",name:"Goose"},{config:{appendMode:!0,path:".roo/rules/ultracite.md"},id:"roo-code",name:"Roo Code"},{config:{appendMode:!0,path:"AGENTS.md"},id:"warp",name:"Warp"},{config:{appendMode:!0,path:"AGENTS.md"},id:"droid",name:"Droid"},{config:{appendMode:!0,path:"AGENTS.md"},id:"opencode",name:"OpenCode"},{config:{appendMode:!0,path:"AGENTS.md"},id:"crush",name:"Crush"},{config:{appendMode:!0,path:"AGENTS.md"},id:"qwen",name:"Qwen Code"},{config:{appendMode:!0,path:".amazonq/rules/ultracite.md"},id:"amazon-q-cli",name:"Amazon Q CLI"},{config:{path:"firebender.json"},id:"firebender",name:"Firebender"},{config:{appendMode:!0,path:"AGENTS.md"},id:"cursor-cli",name:"Cursor CLI"},{config:{appendMode:!0,path:"AGENTS.md"},id:"mistral-vibe",name:"Mistral Vibe"},{config:{appendMode:!0,path:"AGENTS.md"},id:"vercel",name:"Vercel Agent"}];var M1=[{id:"biome",name:"Biome",vscodeExtensionId:"biomejs.biome"},{id:"eslint",name:"ESLint + Prettier + Stylelint",vscodeExtensionId:"dbaeumer.vscode-eslint"},{id:"oxlint",name:"Oxlint + Oxfmt",vscodeExtensionId:"oxc.oxc-vscode"}];var P0=(b)=>b.replace(/ Code$/u,"").replace(/ Agent$/u,""),P2=(b,$)=>{if(b==="AGENTS.md"&&$.length>1){let G=$.slice(0,3),Q=$.length>G.length?", and more":"";return`Universal (creates ${b} for ${G.join(", ")}${Q})`}let[y]=$;return`${y} (creates ${b})`},f0=()=>{let b=new Map;for(let y of n){let G=b.get(y.config.path)??[];G.push(y),b.set(y.config.path,G)}return[...b.entries()].map(([y,G])=>{let[Q]=G,W=G.map((U)=>P0(U.name)),Z=y==="AGENTS.md"&&G.length>1;return{agentIds:G.map((U)=>U.id),displayName:Z?"Universal":P0(Q.name),id:Z?"universal":Q.id,path:y,promptLabel:P2(y,W),representativeAgentId:Q.id}}).toSorted((y,G)=>{if(y.path==="AGENTS.md")return-1;if(G.path==="AGENTS.md")return 1;return 0})},k0=(b,$,y)=>{let G=n.find((H)=>H.id===b);if(!G)throw Error(`Agent "${b}" not found`);let Q=M1.find((H)=>H.id===y);if(!Q)throw Error(`Provider "${y}" not found`);let W=c2($,""),Z=v0(W,Q.name),U=G.config.header?`${G.config.header} ${Z}`:Z;return{create:async()=>{R(G.config.path),await v(G.config.path,U)},exists:()=>V(G.config.path),update:async()=>{R(G.config.path);let H=V(G.config.path);if(!(G.config.appendMode&&H)){await v(G.config.path,U);return}let B=await h2(G.config.path,"utf-8");if(B.includes(Z.trim()))return;await v(G.config.path,`${B} ${Z}`)}}};import W1 from"deepmerge";var p1={"editor.defaultFormatter":"esbenp.prettier-vscode","editor.formatOnPaste":!0,"editor.formatOnSave":!0,"emmet.showExpandedAbbreviation":"never","js/ts.tsdk.path":"node_modules/typescript/lib","js/ts.tsdk.promptToUseWorkspaceVersion":!0},f2="astro-build.astro-vscode",x="biomejs.biome",j="oxc.oxc-vscode",T="code --install-extension",q=".vscode/settings.json",k2={"[css]":{"editor.defaultFormatter":x},"[graphql]":{"editor.defaultFormatter":x},"[html]":{"editor.defaultFormatter":x},"[javascript]":{"editor.defaultFormatter":x},"[javascriptreact]":{"editor.defaultFormatter":x},"[json]":{"editor.defaultFormatter":x},"[jsonc]":{"editor.defaultFormatter":x},"[markdown]":{"editor.defaultFormatter":x},"[mdx]":{"editor.defaultFormatter":x},"[svelte]":{"editor.defaultFormatter":x},"[typescript]":{"editor.defaultFormatter":x},"[typescriptreact]":{"editor.defaultFormatter":x},"[vue]":{"editor.defaultFormatter":x},"[yaml]":{"editor.defaultFormatter":x},"editor.codeActionsOnSave":{"source.fixAll.biome":"explicit","source.organizeImports.biome":"explicit"}},C2={"[astro]":{"editor.defaultFormatter":f2},"[css]":{"editor.defaultFormatter":j},"[graphql]":{"editor.defaultFormatter":j},"[handlebars]":{"editor.defaultFormatter":j},"[html]":{"editor.defaultFormatter":j},"[javascript]":{"editor.defaultFormatter":j},"[javascriptreact]":{"editor.defaultFormatter":j},"[json]":{"editor.defaultFormatter":j},"[jsonc]":{"editor.defaultFormatter":j},"[less]":{"editor.defaultFormatter":j},"[markdown]":{"editor.defaultFormatter":j},"[scss]":{"editor.defaultFormatter":j},"[typescript]":{"editor.defaultFormatter":j},"[typescriptreact]":{"editor.defaultFormatter":j},"[vue-html]":{"editor.defaultFormatter":j},"[vue]":{"editor.defaultFormatter":j},"[yaml]":{"editor.defaultFormatter":j},"editor.codeActionsOnSave":{"source.fixAll.oxc":"explicit"}},l2={"editor.codeActionsOnSave":{"source.fixAll.eslint":"explicit","source.organizeImports":"explicit"}},E=(b="biome")=>{switch(b){case"biome":return W1(p1,k2);case"eslint":return W1(p1,l2);case"oxlint":return W1(p1,C2);default:return p1}},h1={format_on_save:"on",formatter:"language_server",lsp:{"typescript-language-server":{settings:{typescript:{preferences:{includePackageJsonAutoImports:"on"}}}}}},n2={languages:{JavaScript:{code_actions_on_format:{"source.fixAll.biome":!0,"source.organizeImports.biome":!0},formatter:{language_server:{name:"biome"}}},TSX:{code_actions_on_format:{"source.fixAll.biome":!0,"source.organizeImports.biome":!0},formatter:{language_server:{name:"biome"}}},TypeScript:{code_actions_on_format:{"source.fixAll.biome":!0,"source.organizeImports.biome":!0},formatter:{language_server:{name:"biome"}}}}},r2={languages:{JavaScript:{code_actions_on_format:{"source.fixAll.eslint":!0,"source.organizeImports.eslint":!0},formatter:{language_server:{name:"eslint"}}},TSX:{code_actions_on_format:{"source.fixAll.eslint":!0,"source.organizeImports.eslint":!0},formatter:{language_server:{name:"eslint"}}},TypeScript:{code_actions_on_format:{"source.fixAll.eslint":!0,"source.organizeImports.eslint":!0},formatter:{language_server:{name:"eslint"}}}}},s2={languages:{JavaScript:{code_actions_on_format:{"source.fixAll.oxc":!0,"source.organizeImports.oxc":!0},formatter:{language_server:{name:"oxfmt"}}},TSX:{code_actions_on_format:{"source.fixAll.oxc":!0,"source.organizeImports.oxc":!0},formatter:{language_server:{name:"oxfmt"}}},TypeScript:{code_actions_on_format:{"source.fixAll.oxc":!0,"source.organizeImports.oxc":!0},formatter:{language_server:{name:"oxfmt"}}}},lsp:{oxfmt:{initialization_options:{settings:{configPath:null,flags:{},"fmt.configPath":null,"fmt.experimental":!0,run:"onSave",typeAware:!1,unusedDisableDirectives:!1}}},oxlint:{initialization_options:{settings:{disableNestedConfig:!1,fixKind:"safe_fix",run:"onType",typeAware:!0,unusedDisableDirectives:"deny"}}}}},i2=(b="biome")=>{switch(b){case"biome":return W1(h1,n2);case"eslint":return W1(h1,r2);case"oxlint":return W1(h1,s2);default:return h1}},P=[{config:{extensionCommand:T,getContent:E,path:q},id:"vscode",name:"Visual Studio Code"},{config:{extensionCommand:T,getContent:E,path:q},hooks:{getContent:(b)=>({hooks:{afterFileEdit:[{command:b}]},version:1}),path:".cursor/hooks.json"},id:"cursor",name:"Cursor"},{config:{extensionCommand:T,getContent:E,path:q},hooks:{getContent:(b)=>({hooks:{post_write_code:[{command:b,show_output:!0}]}}),path:".windsurf/hooks.json"},id:"windsurf",name:"Windsurf"},{config:{extensionCommand:T,getContent:E,path:q},hooks:{getContent:(b)=>({hooks:{PostToolUse:[{hooks:[{command:b,timeout:20,type:"command"}],matcher:"Write|Edit"}]}}),path:".codebuddy/settings.json"},id:"codebuddy",name:"CodeBuddy"},{config:{extensionCommand:T,getContent:E,path:q},id:"antigravity",name:"Antigravity"},{config:{extensionCommand:T,getContent:E,path:q},id:"bob",name:"IBM Bob"},{config:{extensionCommand:T,getContent:E,path:q},id:"kiro",name:"Kiro"},{config:{extensionCommand:T,getContent:E,path:q},id:"trae",name:"Trae"},{config:{extensionCommand:T,getContent:E,path:q},id:"void",name:"Void"},{config:{getContent:i2,path:".zed/settings.json"},id:"zed",name:"Zed"}];var g2=(b)=>Boolean(b.hooks),t2=(b)=>Boolean(b.hooks),a2=()=>P.flatMap((b)=>g2(b)?[{hooks:b.hooks,id:b.id,name:b.name}]:[]),e2=()=>n.flatMap((b)=>t2(b)?[{hooks:b.hooks,id:b.id,name:b.name}]:[]),K1=[...a2(),...e2()];import{readFile as b4}from"node:fs/promises";import{sync as $4}from"cross-spawn";import y4 from"deepmerge";import{parse as G4}from"jsonc-parser";var C0=(b,$="biome")=>{let y=P.find((Q)=>Q.id===b);if(!y)throw Error(`Editor "${b}" not found`);let G=y.config.getContent($);return{create:async()=>{R(y.config.path),await v(y.config.path,`${JSON.stringify(G,null,2)} `)},exists:()=>V(y.config.path),extension:y.config.extensionCommand?(Q)=>{let[W,...Z]=y.config.extensionCommand.split(" ");return $4(W,[...Z,Q],{stdio:"pipe"})}:void 0,update:async()=>{if(R(y.config.path),!V(y.config.path)){await v(y.config.path,`${JSON.stringify(G,null,2)} `);return}let W=await b4(y.config.path,"utf-8"),U=G4(W)||{},H=y4(U,G);await v(y.config.path,`${JSON.stringify(H,null,2)} `)}}};var Q4=(b,$)=>{if($.length>1){let G=$.slice(0,3),Q=$.length>G.length?", and more":"";return`Universal (creates ${b} for ${G.join(", ")}${Q})`}let[y]=$;return`${y} (creates ${b})`},l0=()=>{let b=new Map;for(let y of P){let G=b.get(y.config.path)??[];G.push(y),b.set(y.config.path,G)}return[...b.entries()].map(([y,G])=>{let[Q]=G,W=G.map((U)=>U.name),Z=G.length>1;return{displayName:Z?"Universal":Q.name,editorIds:G.map((U)=>U.id),id:Z?"universal":Q.id,path:y,promptLabel:Q4(y,W),representativeEditorId:Q.id}}).toSorted((y,G)=>{if(y.id==="universal")return-1;if(G.id==="universal")return 1;return 0})};import{readFile as Z4}from"node:fs/promises";import U4 from"deepmerge";import{parse as v4}from"jsonc-parser";import{runScriptCommand as z4}from"nypm";var n0=["npm","yarn","pnpm","bun","deno"],W4=(b)=>n0.includes(b),w1=(b)=>{if(W4(b))return b;throw Error(`Unsupported package manager "${b}". Supported package managers: ${n0.join(", ")}.`)},r0=(b)=>{let $=w1(b.name);return{...b,command:$,name:$}};var Y4=(b)=>typeof b==="object"&&b!==null&&!Array.isArray(b),H4=(b,$=[])=>{let y=w1(b),G=y==="npm"&&$.length>0?["--",...$]:$;return z4(y,"fix",{args:G})},s0=(b,$,y="biome")=>{let G=K1.find((B)=>B.id===b);if(!G)throw Error(`Hook integration "${b}" not found`);let W=H4($,y==="biome"?["--skip=correctness/noUnusedImports"]:[]),Z=G.hooks.getContent(W),U=(B)=>{let w=JSON.stringify(B);return w.includes("ultracite")||w.includes(W)},H=async()=>{if(!V(G.hooks.path)){await v(G.hooks.path,`${JSON.stringify(Z,null,2)} `);return}let w=await Z4(G.hooks.path,"utf-8"),S=v4(w),J=Y4(S)?S:{};if(!U(J)){let M=U4(J,Z);await v(G.hooks.path,`${JSON.stringify(M,null,2)} `)}};return{create:async()=>{R(G.hooks.path),await v(G.hooks.path,`${JSON.stringify(Z,null,2)} `)},exists:()=>V(G.hooks.path),update:async()=>{R(G.hooks.path),await H()}}};import{mkdir as V4,readFile as X4}from"node:fs/promises";import{addDevDependency as B4,dlxCommand as A1}from"nypm";var i0=(b)=>`#!/bin/sh ${b} `,g0=(b)=>`#!/bin/sh # Check if there are any staged files STAGED_FILES=$(git diff --cached --name-only --diff-filter=ACMR) if [ -z "$STAGED_FILES" ]; then echo "No staged files to format" exit 0 fi # Run formatter, capturing the exit code so we can still re-stage and report FORMAT_EXIT_CODE=0 ${b} || FORMAT_EXIT_CODE=$? # Re-stage files that were already staged echo "$STAGED_FILES" | while IFS= read -r file; do if [ -f "$file" ]; then git add -- "$file" fi done if [ $FORMAT_EXIT_CODE -ne 0 ]; then echo "Ultracite found issues that could not be auto-fixed." exit $FORMAT_EXIT_CODE fi echo "✨ Files formatted by Ultracite" `,J1="./.husky/pre-commit",Y0="# ultracite",t0="# ultracite end",z0=(b)=>`${Y0} ${b}${t0}`,K4=(b,$)=>{let y=b.indexOf(t0,$+1);if(y!==-1)return y+1;let G=b.findIndex((Q,W)=>W>$&&Q.includes("Files formatted by Ultracite"));if(G!==-1)return G+1;return b.length},Z1={create:async(b,$=!1)=>{await V4(".husky",{recursive:!0});let y;if($){let G=A1(b,"lint-staged",{short:b==="npm"});y=i0(G)}else{let G=A1(b,"ultracite",{args:["fix"],short:b==="npm"});y=g0(G)}await v(J1,`${z0(y)} `)},exists:()=>V(J1),init:(b)=>{let[$,...y]=A1(b,"husky",{args:["init"]}).split(" "),G=A($,y,{stdio:"pipe"});if(G.error||G.status!==null&&G.status!==0);},install:async(b)=>{await B4("husky",{corepack:!1,packageManager:b,silent:!0,workspace:c()&&b.name!=="npm"}),await N({scripts:{prepare:"husky"}})},update:async(b,$=!1)=>{let y=await X4(J1,"utf-8"),G;if($){let Q=A1(b,"lint-staged",{short:b==="npm"});G=i0(Q)}else{let Q=A1(b,"ultracite",{args:["fix"],short:b==="npm"});G=g0(Q)}if(y.includes(Y0)){let Q=y.split(` `),W=Q.indexOf(Y0),Z=K4(Q,W),U=Q.slice(0,W).join(` `),H=Q.slice(Z).join(` `).replace(/^\n+/u,"").replace(/\n+$/u,""),B=[U,z0(G),H].filter((w)=>w!=="");await v(J1,`${B.join(` `)} `)}else{let Q=y.replace(/\n+$/u,"");await v(J1,`${Q} ${z0(G)} `)}}};import{execSync as w4}from"node:child_process";import{readFile as A4}from"node:fs/promises";import{addDevDependency as J4,dlxCommand as e0}from"nypm";var j4=/(?<preCommitJobs>pre-commit:\s*\n\s*jobs:\s*\n)/u,D4=/(?<preCommit>pre-commit:\s*\n)/u,bb=(b)=>e0(b,"ultracite",{args:["fix"],short:b==="npm"}),U1="./lefthook.yml",a0=(b)=>`pre-commit: jobs: - run: ${bb(b)} glob: - "**/*.js" - "**/*.jsx" - "**/*.ts" - "**/*.tsx" - "**/*.json" - "**/*.jsonc" - "**/*.css" stage_fixed: true `,j1={create:async(b)=>{let $=a0(b);await v(U1,$)},exists:()=>V(U1),install:async(b)=>{await J4("lefthook",{corepack:!1,packageManager:b,silent:!0,workspace:c()&&b.name!=="npm"}),await N({scripts:{prepare:"lefthook install"}});let $=e0(b.name,"lefthook",{args:["install"],short:b.name==="npm"});try{w4($,{stdio:"pipe"})}catch{}},update:async(b)=>{let $=await A4(U1,"utf-8"),y=bb(b),G=a0(b);if($.includes(y))return;if($.startsWith("# EXAMPLE USAGE:")){await v(U1,G);return}if($.includes("pre-commit:")){let W;if($.includes("jobs:")){let Z=` - run: ${y} glob: - "**/*.js" - "**/*.jsx" - "**/*.ts" - "**/*.tsx" - "**/*.json" - "**/*.jsonc" - "**/*.css" stage_fixed: true`;W=$.replace(j4,`$<preCommitJobs>${Z} `)}else{let Z=` jobs: - run: ${y} glob: - "**/*.js" - "**/*.jsx" - "**/*.ts" - "**/*.tsx" - "**/*.json" - "**/*.jsonc" - "**/*.css" stage_fixed: true`;W=$.replace(D4,`$<preCommit>${Z} `)}await v(U1,W)}else await v(U1,`${$} ${G}`)}};import{readFile as D1}from"node:fs/promises";import{pathToFileURL as Qb}from"node:url";import d1 from"deepmerge";import{parse as d4}from"jsonc-parser";import{addDevDependency as x4,dlxCommand as L4}from"nypm";import $b from"yaml";var c1="./package.json",f=(b)=>({"*.{js,jsx,ts,tsx,json,jsonc,css,scss,md,mdx}":[L4(b,"ultracite",{args:["fix"],short:b==="npm"})]}),yb=["./.lintstagedrc.json","./.lintstagedrc.js","./.lintstagedrc.cjs","./.lintstagedrc.mjs","./lint-staged.config.js","./lint-staged.config.cjs","./lint-staged.config.mjs","./.lintstagedrc.yaml","./.lintstagedrc.yml","./.lintstagedrc"],x1=(b)=>JSON.stringify(b).includes("ultracite"),Gb=async()=>{try{let b=await D1(c1,"utf-8");return g(b)?.["lint-staged"]}catch{return}},N4=async()=>{try{let b=await D1(c1,"utf-8");return g(b)?.type==="module"}catch{return!1}},S4=async(b)=>{let $=await D1(c1,"utf-8"),y=g($);if(!y)return;if(x1(y["lint-staged"]))return;y["lint-staged"]=y["lint-staged"]?d1(y["lint-staged"],f(b)):f(b),await v(c1,`${JSON.stringify(y,null,2)} `)},R4=async(b,$)=>{let y=await D1(b,"utf-8"),G=d4(y);if(!G)return;if(x1(G))return;let Q=d1(G,f($));await v(b,`${JSON.stringify(Q,null,2)} `)},m4=(b)=>b.replaceAll(/^(?<key>[*?{[][^\n:]*):(?<rest>.*)$/gmu,($,y,G)=>`'${y}':${G}`),I4=async(b,$)=>{let y=await D1(b,"utf-8"),G=m4(y),Q;try{Q=$b.parse(G)}catch{return}if(!Q)return;if(x1(Q))return;let W=d1(Q,f($));await v(b,$b.stringify(W))},u4=async(b,$)=>{let Q=(await import(Qb(b).href)).default||{};if(x1(Q))return;let W=d1(Q,f($)),Z=`export default ${JSON.stringify(W,null,2)}; `;await v(b,Z)},F4=async(b,$)=>{let G=await import(`${Qb(b).href}?t=${Date.now()}`),Q=G.default||G;if(x1(Q))return;let W=d1(Q,f($)),Z=`module.exports = ${JSON.stringify(W,null,2)}; `;await v(b,Z)},H0=async(b)=>{await v(".lintstagedrc.json",`${JSON.stringify(f(b),null,2)} `)},O4=async(b,$)=>{if(b.endsWith(".json")||b==="./.lintstagedrc"){await R4(b,$);return}if(b.endsWith(".yaml")||b.endsWith(".yml")){await I4(b,$);return}let y=await N4();if(b.endsWith(".mjs")||b.endsWith(".js")&&y){try{await u4(b,$)}catch{await H0($)}return}if(b.endsWith(".cjs")||b.endsWith(".js")&&!y)try{await F4(b,$)}catch{await H0($)}},L1={create:async(b)=>{await v(".lintstagedrc.json",`${JSON.stringify(f(b),null,2)} `)},exists:async()=>{if(await Gb())return!0;return yb.some((b)=>V(b))},install:async(b)=>{await x4("lint-staged",{corepack:!1,packageManager:b,silent:!0,workspace:c()&&b.name!=="npm"})},update:async(b)=>{if(await Gb()){await S4(b);return}let $=yb.find((y)=>V(y));if(!$){await H0(b);return}await O4($,b)}};import{readFile as o4}from"node:fs/promises";import{dlxCommand as _4}from"nypm";var N1="./.pre-commit-config.yaml",T4=/^repos:\s*\n/mu,Wb=(b)=>_4(b,"ultracite",{args:["fix"],short:b==="npm"}),q4=(b)=>`repos: - repo: local hooks: - id: ultracite name: ultracite entry: ${Wb(b)} language: system types_or: [javascript, jsx, ts, tsx, json, css] pass_filenames: false `,P1={create:async(b)=>{let $=q4(b);await v(N1,$)},exists:()=>V(N1),update:async(b)=>{let $=await o4(N1,"utf-8"),y=Wb(b);if($.includes("id: ultracite"))return;let G=` - repo: local hooks: - id: ultracite name: ultracite entry: ${y} language: system types_or: [javascript, jsx, ts, tsx, json, css] pass_filenames: false `;if($.includes("repos:")){let Q=$.replace(T4,`repos: ${G}`);await v(N1,Q)}else await v(N1,`${$} repos: ${G}`)}};import{readFile as E4}from"node:fs/promises";import M4 from"deepmerge";var X0="ultracite/biome/core",Zb={$schema:"./node_modules/@biomejs/biome/configuration_schema.json",extends:[X0]},p4=/^ultracite\/(?!biome\/)(?<rest>.+)$/u,V0=()=>{for(let b of I)if(V(`./${b}`))return`./${b}`;return"./biome.jsonc"},f1={create:(b)=>{let $=V0(),y=[X0];if(b?.typeAware)y.push("ultracite/biome/type-aware");if(b?.frameworks&&b.frameworks.length>0)for(let Q of b.frameworks){let W=m(Q);y.push(`ultracite/biome/${W}`)}let G={...Zb,extends:y};return v($,`${JSON.stringify(G,null,2)} `)},exists:()=>{let b=V0();return V(b)},update:async(b)=>{let $=V0(),y=await E4($,"utf-8"),Q=I1(y,N0)||{},Z=(Q.extends??[]).map((J)=>{let M=p4.exec(J);return M?`ultracite/biome/${M[1]}`:J}),U=[...new Set(Z)],H=new Set(U),B=(J)=>{if(!H.has(J))H.add(J),U.push(J)};if(B(X0),b?.typeAware)B("ultracite/biome/type-aware");if(b?.frameworks&&b.frameworks.length>0)for(let J of b.frameworks)B(`ultracite/biome/${m(J)}`);Q.extends=U;let w={$schema:Zb.$schema},S=M4(Q,w);await v($,`${JSON.stringify(S,null,2)} `)}};var h4=C.map((b)=>`./${b}`),Ub="./eslint.config.mjs",vb=()=>{for(let b of h4)if(V(b))return b;return null},zb=(b)=>{let $=['import core from "ultracite/eslint/core";'],y=["...core"];if(b?.frameworks&&b.frameworks.length>0)for(let G of b.frameworks){let Q=m(G);$.push(`import ${Q} from "ultracite/eslint/${Q}";`),y.push(`...${Q}`)}return`${$.join(` `)} export default [ ${y.join(`, `)}, ]; `},k1={create:async(b)=>{let $=zb(b);await v(Ub,$)},exists:()=>{return vb()!==null},update:async(b)=>{let $=zb(b);await v(vb()??Ub,$)}};var B0="./oxfmt.config.ts",Yb=`import { defineConfig } from "oxfmt"; import ultracite from "ultracite/oxfmt"; export default defineConfig({ ...ultracite, }); `,C1={create:async()=>await v(B0,Yb),exists:()=>V(B0),update:async()=>await v(B0,Yb)};import{readFile as c4}from"node:fs/promises";var l1="./oxlint.config.ts";var Hb={"eslint-plugin-github":{name:"github",rulePrefix:"github"},"eslint-plugin-sonarjs":{name:"sonarjs",rulePrefix:"sonarjs"},"oxlint-plugin-react-doctor":{name:"react-doctor",rulePrefix:"react-doctor"}},S1=(b)=>`ultracite/oxlint/${b}`,Vb=(b)=>{return(b.split("/").pop()??b).replaceAll(/-(?<letter>[a-z])/gu,(y,G)=>G.toUpperCase())},P4=(b)=>{if(b.length===0)return"";let $=b.map((G)=>Hb[G].name),y=b.map((G)=>Hb[G].rulePrefix);return` const selectedJsPluginNames = new Set(${JSON.stringify($)}); const selectedJsPluginRulePrefixes = new Set(${JSON.stringify(y)}); const selectedJsPlugins = { ...jsPlugins, jsPlugins: jsPlugins.jsPlugins?.filter((plugin) => selectedJsPluginNames.has(plugin.name) ), overrides: jsPlugins.overrides?.map((override) => ({ ...override, rules: Object.fromEntries( Object.entries(override.rules ?? {}).filter(([ruleName]) => selectedJsPluginRulePrefixes.has(ruleName.split("/")[0] ?? ruleName) ) ), })), rules: Object.fromEntries( Object.entries(jsPlugins.rules ?? {}).filter(([ruleName]) => selectedJsPluginRulePrefixes.has(ruleName.split("/")[0] ?? ruleName) ) ), }; `},Xb=(b,$=[])=>{let y=$.length>0,G=['import { defineConfig } from "oxlint";',...b.map((W)=>`import ${Vb(W)} from "${W}";`),y?'import jsPlugins from "ultracite/oxlint/js-plugins";':""].filter(Boolean).join(` `),Q=[...b.map((W)=>Vb(W)),...y?["selectedJsPlugins"]:[]].join(", ");return`${G}${P4($)} export default defineConfig({ extends: [${Q}], ignorePatterns: core.ignorePatterns, }); `},n1={create:async(b)=>{let $=[S1("core")];if(b?.frameworks&&b.frameworks.length>0)for(let y of b.frameworks){let G=m(y);$.push(S1(G))}return await v(l1,Xb($,b?.jsPlugins))},exists:()=>V(l1),update:async(b)=>{let $=await c4(l1,"utf-8"),y=[],G=$.matchAll(/import \w+ from ["'](?<source>[^"']+)["']/gu);for(let Z of G)if(Z[1].startsWith("ultracite/oxlint/"))y.push(Z[1].replace(/\/index\.[tj]s$/u,""));if(y.length===0){let Z=$.match(/extends:\s*\[(?<body>[\s\S]*?)\]/u);if(Z?.[1]){let U=Z[1].matchAll(/"(?<value>[^"]+)"/gu);for(let H of U){let B=H[1].replace(/^\.\/node_modules\/ultracite\/config\/oxlint\//u,"ultracite/oxlint/");y.push(B)}}}if(y.length===0&&$.includes("ultracite/oxlint"))console.warn("Warning: could not parse existing extends from oxlint.config.ts. The file will be regenerated.");let Q=(Z)=>y.some((U)=>U===S1(Z)),W=[...y];if(!Q("core"))W.push(S1("core"));if(b?.frameworks&&b.frameworks.length>0)for(let Z of b.frameworks){let U=m(Z);if(!Q(U))W.push(S1(U))}await v(l1,Xb(W,b?.jsPlugins))}};var w0="./package.json",f4=a.map((b)=>`./${b}`),K0="./prettier.config.mjs",k4=()=>{