ultracite 6.5.0 → 7.0.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/README.md +1 -1
- package/config/biome/angular/biome.jsonc +9 -0
- package/config/{astro → biome/astro}/biome.jsonc +1 -1
- package/config/{core → biome/core}/biome.jsonc +45 -44
- package/config/{next → biome/next}/biome.jsonc +1 -1
- package/config/{qwik → biome/qwik}/biome.jsonc +1 -1
- package/config/{react → biome/react}/biome.jsonc +1 -1
- package/config/{remix → biome/remix}/biome.jsonc +1 -1
- package/config/{solid → biome/solid}/biome.jsonc +1 -1
- package/config/{svelte → biome/svelte}/biome.jsonc +1 -1
- package/config/{vue → biome/vue}/biome.jsonc +1 -1
- package/config/eslint/angular/eslint.config.mjs +18 -0
- package/config/eslint/angular/rules/angular.mjs +17 -0
- package/config/eslint/astro/eslint.config.mjs +18 -0
- package/config/eslint/astro/rules/astro.mjs +17 -0
- package/config/eslint/core/eslint.config.mjs +168 -0
- package/config/eslint/core/rules/compat.mjs +5 -0
- package/config/eslint/core/rules/cypress.mjs +17 -0
- package/config/eslint/core/rules/eslint-typescript.mjs +43 -0
- package/config/eslint/core/rules/eslint.mjs +30 -0
- package/config/eslint/core/rules/github.mjs +19 -0
- package/config/eslint/core/rules/import.mjs +44 -0
- package/config/eslint/core/rules/jest.mjs +17 -0
- package/config/eslint/core/rules/n.mjs +24 -0
- package/config/eslint/core/rules/prettier.mjs +5 -0
- package/config/eslint/core/rules/promise.mjs +20 -0
- package/config/eslint/core/rules/sonarjs.mjs +19 -0
- package/config/eslint/core/rules/storybook.mjs +17 -0
- package/config/eslint/core/rules/tailwindcss.mjs +22 -0
- package/config/eslint/core/rules/typescript.mjs +62 -0
- package/config/eslint/core/rules/unicorn.mjs +34 -0
- package/config/eslint/core/rules/unused-imports.mjs +17 -0
- package/config/eslint/next/eslint.config.mjs +18 -0
- package/config/eslint/next/rules/next.mjs +17 -0
- package/config/eslint/qwik/eslint.config.mjs +18 -0
- package/config/eslint/qwik/rules/qwik.mjs +17 -0
- package/config/eslint/react/eslint.config.mjs +43 -0
- package/config/eslint/react/rules/jsx-a11y.mjs +27 -0
- package/config/eslint/react/rules/query.mjs +15 -0
- package/config/eslint/react/rules/react-hooks.mjs +17 -0
- package/config/eslint/react/rules/react.mjs +46 -0
- package/config/eslint/remix/eslint.config.mjs +18 -0
- package/config/eslint/remix/rules/remix.mjs +17 -0
- package/config/eslint/solid/eslint.config.mjs +18 -0
- package/config/eslint/solid/rules/solid.mjs +17 -0
- package/config/eslint/svelte/eslint.config.mjs +18 -0
- package/config/eslint/svelte/rules/svelte.mjs +17 -0
- package/config/eslint/vue/eslint.config.mjs +18 -0
- package/config/eslint/vue/rules/vue.mjs +17 -0
- package/config/oxlint/angular/.oxlintrc.json +4 -0
- package/config/oxlint/astro/.oxlintrc.json +4 -0
- package/config/oxlint/core/.oxlintrc.json +92 -0
- package/config/oxlint/next/.oxlintrc.json +13 -0
- package/config/oxlint/qwik/.oxlintrc.json +4 -0
- package/config/oxlint/react/.oxlintrc.json +18 -0
- package/config/oxlint/remix/.oxlintrc.json +4 -0
- package/config/oxlint/solid/.oxlintrc.json +4 -0
- package/config/oxlint/svelte/.oxlintrc.json +4 -0
- package/config/oxlint/vue/.oxlintrc.json +5 -0
- package/config/prettier/prettier.config.mjs +14 -0
- package/config/stylelint/stylelint.config.mjs +38 -0
- package/dist/index.d.ts +7 -16
- package/dist/index.js +43 -174
- package/package.json +51 -10
- package/config/angular/biome.jsonc +0 -9
package/dist/index.js
CHANGED
|
@@ -1,14 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
var
|
|
3
|
-
888 888 888 88888888888 8888888b. d8888 .d8888b. 8888888 88888888888 8888888888
|
|
4
|
-
888 888 888 888 888 Y88b d88888 d88P Y88b 888 888 888
|
|
5
|
-
888 888 888 888 888 888 d88P888 888 888 888 888 888
|
|
6
|
-
888 888 888 888 888 d88P d88P 888 888 888 888 8888888
|
|
7
|
-
888 888 888 888 8888888P" d88P 888 888 888 888 888
|
|
8
|
-
888 888 888 888 888 T88b d88P 888 888 888 888 888 888
|
|
9
|
-
Y88b. .d88P 888 888 888 T88b d8888888888 Y88b d88P 888 888 888
|
|
10
|
-
"Y88888P" 88888888 888 888 T88b d88P 888 "Y8888P" 8888888 888 8888888888
|
|
11
|
-
`,v=async({dependencies:e,devDependencies:t,scripts:s})=>{let n=await Fe("package.json","utf8"),o=JSON.parse(n),i={...o};(o.devDependencies||t)&&(i.devDependencies={...o.devDependencies,...t}),(o.dependencies||e)&&(i.dependencies={...o.dependencies,...e}),(o.scripts||s)&&(i.scripts={...o.scripts,...s}),await Ft("package.json",JSON.stringify(i,null,2))},Ot=/[ $(){}[\]&|;<>!"'`*?#~]/,Dt=/'/g,K=e=>e.map(t=>Ot.test(t)?`'${t.replace(Dt,"'\\''")}' `:t)});var st={};z(st,{husky:()=>S});import{execSync as Os}from"child_process";import{mkdir as Ds,readFile as Ms,writeFile as et}from"fs/promises";import{addDevDependency as Ts,dlxCommand as ke}from"nypm";var tt,ie,S,be=F(()=>{"use strict";h();tt=e=>`#!/bin/sh
|
|
2
|
+
var ht=Object.defineProperty;var Ce=Object.getOwnPropertyDescriptor;var be=Object.getOwnPropertyNames;var Ee=Object.prototype.hasOwnProperty;var wt=(t=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(t,{get:(e,n)=>(typeof require<"u"?require:e)[n]}):t)(function(t){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+t+'" is not supported')}),At=t=>e=>{var n=t[e];if(n)return n();throw new Error("Module not found in bundle: "+e)};var R=(t,e)=>()=>(t&&(e=t(t=0)),e);var Q=(t,e)=>{for(var n in e)ht(t,n,{get:e[n],enumerable:!0})},je=(t,e,n,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of be(e))!Ee.call(t,o)&&o!==n&&ht(t,o,{get:()=>e[o],enumerable:!(i=Ce(e,o))||i.enumerable});return t};var Z=t=>je(ht({},"__esModule",{value:!0}),t);import{access as $e,mkdir as Se,readFile as Jt,writeFile as Oe}from"fs/promises";import{dirname as ve}from"path";import{parse as Ne}from"jsonc-parser";var c,b,x,Fe,Re,d,k,De,Le,Ae,q,m=R(()=>{"use strict";c=async t=>{try{return await $e(t),!0}catch{return!1}},b=async()=>{if(await c("pnpm-workspace.yaml"))return!0;try{let t=Ne(await Jt("package.json","utf-8"));return t?!!t.workspaces||!!t.workspace:!1}catch{return!1}},x=async({dependencies:t,devDependencies:e,scripts:n})=>{let i=await Jt("package.json","utf8"),o=JSON.parse(i),s={...o};(o.devDependencies||e)&&(s.devDependencies={...o.devDependencies,...e}),(o.dependencies||t)&&(s.dependencies={...o.dependencies,...t}),(o.scripts||n)&&(s.scripts={...o.scripts,...n}),await Oe("package.json",JSON.stringify(s,null,2))},Fe=/[ $(){}[\]&|;<>!"'`*?#~]/,Re=/'/g,d=t=>t.map(e=>Fe.test(e)?`'${e.replace(Re,"'\\''")}' `:e),k=async t=>{let e=ve(t);if(e!=="."){let n=e.startsWith("./")?e.slice(2):e;await Se(n,{recursive:!0})}},De=["./biome.json","./biome.jsonc"],Le=["./eslint.config.mjs","./eslint.config.js","./eslint.config.cjs","./eslint.config.ts","./eslint.config.mts","./eslint.config.cts"],Ae="./.oxlintrc.json",q=async()=>{for(let t of De)if(await c(t))return"biome";for(let t of Le)if(await c(t))return"eslint";return await c(Ae)?"oxlint":null}});var Gt={};Q(Gt,{husky:()=>v});import{execSync as kn}from"child_process";import{mkdir as Cn,readFile as bn,writeFile as zt}from"fs/promises";import{addDevDependency as En,dlxCommand as Et}from"nypm";var Ht,ot,v,jt=R(()=>{"use strict";m();Ht=t=>`#!/bin/sh
|
|
12
3
|
# Exit on any error
|
|
13
4
|
set -e
|
|
14
5
|
|
|
@@ -31,7 +22,7 @@ git stash push --quiet --keep-index --message "pre-commit-stash" || true
|
|
|
31
22
|
STASHED=$?
|
|
32
23
|
|
|
33
24
|
# Run formatter on the staged files
|
|
34
|
-
${
|
|
25
|
+
${t}
|
|
35
26
|
FORMAT_EXIT_CODE=$?
|
|
36
27
|
|
|
37
28
|
# Restore working directory state
|
|
@@ -76,10 +67,10 @@ if [ "$STAGED_HASH" != "$NEW_STAGED_HASH" ]; then
|
|
|
76
67
|
fi
|
|
77
68
|
|
|
78
69
|
exit $FORMAT_EXIT_CODE
|
|
79
|
-
`,
|
|
80
|
-
${
|
|
70
|
+
`,ot="./.husky/pre-commit",v={exists:()=>c(ot),install:async t=>{await En("husky",{packageManager:t,workspace:await b(),silent:!0}),await x({scripts:{prepare:"husky"}})},init:t=>{let e=Et(t,"husky",{args:["init"]});try{kn(e,{stdio:"pipe"})}catch{}},create:async t=>{await Cn(".husky",{recursive:!0});let e=Et(t,"ultracite",{args:["fix"],short:t==="npm"}),n=Ht(e);await zt(ot,n)},update:async t=>{let e=await bn(ot,"utf-8"),n=Et(t,"ultracite",{args:["fix"],short:t==="npm"}),i=Ht(n);await zt(ot,`${e}
|
|
71
|
+
${i}`)}}});var Vt={};Q(Vt,{lefthook:()=>B});import{execSync as jn}from"child_process";import{readFile as Pn,writeFile as H}from"fs/promises";import{addDevDependency as $n,dlxCommand as Xt}from"nypm";var Sn,On,Kt,N,Yt,B,Pt=R(()=>{"use strict";m();Sn=/(pre-commit:\s*\n\s*jobs:\s*\n)/,On=/(pre-commit:\s*\n)/,Kt=t=>Xt(t,"ultracite",{args:["fix"],short:t==="npm"}),N="./lefthook.yml",Yt=t=>`pre-commit:
|
|
81
72
|
jobs:
|
|
82
|
-
- run: ${
|
|
73
|
+
- run: ${Kt(t)}
|
|
83
74
|
glob:
|
|
84
75
|
- "*.js"
|
|
85
76
|
- "*.jsx"
|
|
@@ -89,7 +80,7 @@ ${n}`)}}});var rt={};z(rt,{lefthook:()=>O});import{execSync as Us}from"child_pro
|
|
|
89
80
|
- "*.jsonc"
|
|
90
81
|
- "*.css"
|
|
91
82
|
stage_fixed: true
|
|
92
|
-
`,
|
|
83
|
+
`,B={exists:()=>c(N),install:async t=>{await $n("lefthook",{packageManager:t,workspace:await b(),silent:!0}),await x({scripts:{prepare:"lefthook install"}});let e=Xt(t,"lefthook",{args:["install"],short:t==="npm"});jn(e,{stdio:"pipe"})},create:async t=>{let e=Yt(t);await H(N,e)},update:async t=>{let e=await Pn(N,"utf-8"),n=Kt(t),i=Yt(t);if(e.includes(n))return;if(e.startsWith("# EXAMPLE USAGE:")){await H(N,i);return}if(e.includes("pre-commit:"))if(e.includes("jobs:")){let s=` - run: ${n}
|
|
93
84
|
glob:
|
|
94
85
|
- "*.js"
|
|
95
86
|
- "*.jsx"
|
|
@@ -98,9 +89,9 @@ ${n}`)}}});var rt={};z(rt,{lefthook:()=>O});import{execSync as Us}from"child_pro
|
|
|
98
89
|
- "*.json"
|
|
99
90
|
- "*.jsonc"
|
|
100
91
|
- "*.css"
|
|
101
|
-
stage_fixed: true`,
|
|
102
|
-
`);await
|
|
103
|
-
- run: ${
|
|
92
|
+
stage_fixed: true`,r=e.replace(Sn,`$1${s}
|
|
93
|
+
`);await H(N,r)}else{let s=` jobs:
|
|
94
|
+
- run: ${n}
|
|
104
95
|
glob:
|
|
105
96
|
- "*.js"
|
|
106
97
|
- "*.jsx"
|
|
@@ -109,173 +100,51 @@ ${n}`)}}});var rt={};z(rt,{lefthook:()=>O});import{execSync as Us}from"child_pro
|
|
|
109
100
|
- "*.json"
|
|
110
101
|
- "*.jsonc"
|
|
111
102
|
- "*.css"
|
|
112
|
-
stage_fixed: true`,
|
|
113
|
-
`);await
|
|
114
|
-
${
|
|
103
|
+
stage_fixed: true`,r=e.replace(On,`$1${s}
|
|
104
|
+
`);await H(N,r)}else await H(N,`${e}
|
|
105
|
+
${i}`)}}});var Zt={};Q(Zt,{preCommit:()=>Y});import{readFile as vn,writeFile as $t}from"fs/promises";import{dlxCommand as Nn}from"nypm";var G,Fn,Qt,Rn,Y,St=R(()=>{"use strict";m();G="./.pre-commit-config.yaml",Fn=/^repos:\s*\n/m,Qt=t=>Nn(t,"ultracite",{args:["fix"],short:t==="npm"}),Rn=t=>`repos:
|
|
115
106
|
- repo: local
|
|
116
107
|
hooks:
|
|
117
108
|
- id: ultracite
|
|
118
109
|
name: ultracite
|
|
119
|
-
entry: ${
|
|
110
|
+
entry: ${Qt(t)}
|
|
120
111
|
language: system
|
|
121
112
|
types_or: [javascript, jsx, ts, tsx, json, css]
|
|
122
113
|
pass_filenames: false
|
|
123
|
-
`,
|
|
114
|
+
`,Y={exists:()=>c(G),create:async t=>{let e=Rn(t);await $t(G,e)},update:async t=>{let e=await vn(G,"utf-8"),n=Qt(t);if(e.includes("id: ultracite"))return;let i=` - repo: local
|
|
124
115
|
hooks:
|
|
125
116
|
- id: ultracite
|
|
126
117
|
name: ultracite
|
|
127
|
-
entry: ${
|
|
118
|
+
entry: ${n}
|
|
128
119
|
language: system
|
|
129
120
|
types_or: [javascript, jsx, ts, tsx, json, css]
|
|
130
121
|
pass_filenames: false
|
|
131
|
-
`;if(
|
|
132
|
-
${
|
|
122
|
+
`;if(e.includes("repos:")){let o=e.replace(Fn,`repos:
|
|
123
|
+
${i}`);await $t(G,o)}else await $t(G,`${e}
|
|
133
124
|
repos:
|
|
134
|
-
${
|
|
135
|
-
`).filter(
|
|
136
|
-
`;for(let o of
|
|
137
|
-
`}else
|
|
138
|
-
`;return
|
|
139
|
-
`;await
|
|
140
|
-
`;await E(e,o)},$e=async e=>{await E(".lintstagedrc.json",JSON.stringify(P(e),null,2))},rn=async(e,t)=>{if(e==="./package.json"){await en(t);return}if(e.endsWith(".json")||e==="./.lintstagedrc"){await tn(e,t);return}if(e.endsWith(".yaml")||e.endsWith(".yml")){await sn(e,t);return}let s=await qs();if(e.endsWith(".mjs")||e.endsWith(".js")&&s){try{await nn(e,t)}catch{await $e(t)}return}if(e.endsWith(".cjs")||e.endsWith(".js")&&!s)try{await on(e,t)}catch{await $e(t)}},D={exists:async()=>{for(let e of dt)if(await f(e))return!0;return!1},install:async e=>{await Ys("lint-staged",{packageManager:e,workspace:await C(),silent:!0})},create:async e=>{await E(".lintstagedrc.json",JSON.stringify(P(e),null,2))},update:async e=>{let t=null;for(let s of dt)if(await f(s)){t=s;break}if(!t){await $e(e);return}await rn(t,e)}}});import{initTRPC as Fn}from"@trpc/server";import{createCli as Nn}from"trpc-cli";import d from"zod";var k={name:"ultracite",description:"The AI-ready formatter that helps you write and generate code faster.",version:"6.5.0",type:"module",bin:{ultracite:"dist/index.js"},files:["config","dist","README.md"],scripts:{build:"tsup",test:"bun test","test:coverage":"bun test --coverage"},exports:{"./*":"./config/*/biome.jsonc"},author:"Hayden Bleasel <hello@haydenbleasel.com>",bugs:{url:"https://github.com/haydenbleasel/ultracite/issues"},homepage:"https://www.ultracite.ai/",keywords:["ultracite","biome","linter","formatter","fixer"],license:"MIT",publishConfig:{access:"public",registry:"https://registry.npmjs.org/"},repository:{type:"git",url:"git+https://github.com/haydenbleasel/ultracite.git"},devDependencies:{"@biomejs/biome":"2.3.10","@types/node":"^25.0.0",tsup:"^8.5.1",turbo:"^2.6.3"},dependencies:{"@clack/prompts":"^0.11.0","@trpc/server":"^11.8.0",deepmerge:"^4.3.1",glob:"^13.0.0","jsonc-parser":"^3.3.1",nypm:"^0.6.2",picocolors:"^1.1.1","trpc-cli":"^0.12.1",zod:"^4.1.13"},packageManager:"bun@1.3.4"};import{spawnSync as Mt}from"child_process";import Tt from"process";import{detectPackageManager as Ut,dlxCommand as It}from"nypm";import l from"picocolors";var b=e=>`\x1B[38;5;208m${e}\x1B[39m`,Ae=(e,t)=>{let n=e.slice(0,t[0]).split(`
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
`),
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
${
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
- **Format code**: \`${e} ultracite fix\`
|
|
161
|
-
- **Check for issues**: \`${e} ultracite check\`
|
|
162
|
-
- **Diagnose setup**: \`${e} ultracite doctor\`
|
|
163
|
-
|
|
164
|
-
Biome (the underlying engine) provides extremely fast Rust-based linting and formatting. Most issues are automatically fixable.
|
|
165
|
-
|
|
166
|
-
---
|
|
167
|
-
|
|
168
|
-
## Core Principles
|
|
169
|
-
|
|
170
|
-
Write code that is **accessible, performant, type-safe, and maintainable**. Focus on clarity and explicit intent over brevity.
|
|
171
|
-
|
|
172
|
-
### Type Safety & Explicitness
|
|
173
|
-
|
|
174
|
-
- Use explicit types for function parameters and return values when they enhance clarity
|
|
175
|
-
- Prefer \`unknown\` over \`any\` when the type is genuinely unknown
|
|
176
|
-
- Use const assertions (\`as const\`) for immutable values and literal types
|
|
177
|
-
- Leverage TypeScript's type narrowing instead of type assertions
|
|
178
|
-
- Use meaningful variable names instead of magic numbers - extract constants with descriptive names
|
|
179
|
-
|
|
180
|
-
### Modern JavaScript/TypeScript
|
|
181
|
-
|
|
182
|
-
- Use arrow functions for callbacks and short functions
|
|
183
|
-
- Prefer \`for...of\` loops over \`.forEach()\` and indexed \`for\` loops
|
|
184
|
-
- Use optional chaining (\`?.\`) and nullish coalescing (\`??\`) for safer property access
|
|
185
|
-
- Prefer template literals over string concatenation
|
|
186
|
-
- Use destructuring for object and array assignments
|
|
187
|
-
- Use \`const\` by default, \`let\` only when reassignment is needed, never \`var\`
|
|
188
|
-
|
|
189
|
-
### Async & Promises
|
|
190
|
-
|
|
191
|
-
- Always \`await\` promises in async functions - don't forget to use the return value
|
|
192
|
-
- Use \`async/await\` syntax instead of promise chains for better readability
|
|
193
|
-
- Handle errors appropriately in async code with try-catch blocks
|
|
194
|
-
- Don't use async functions as Promise executors
|
|
195
|
-
|
|
196
|
-
### React & JSX
|
|
197
|
-
|
|
198
|
-
- Use function components over class components
|
|
199
|
-
- Call hooks at the top level only, never conditionally
|
|
200
|
-
- Specify all dependencies in hook dependency arrays correctly
|
|
201
|
-
- Use the \`key\` prop for elements in iterables (prefer unique IDs over array indices)
|
|
202
|
-
- Nest children between opening and closing tags instead of passing as props
|
|
203
|
-
- Don't define components inside other components
|
|
204
|
-
- Use semantic HTML and ARIA attributes for accessibility:
|
|
205
|
-
- Provide meaningful alt text for images
|
|
206
|
-
- Use proper heading hierarchy
|
|
207
|
-
- Add labels for form inputs
|
|
208
|
-
- Include keyboard event handlers alongside mouse events
|
|
209
|
-
- Use semantic elements (\`<button>\`, \`<nav>\`, etc.) instead of divs with roles
|
|
210
|
-
|
|
211
|
-
### Error Handling & Debugging
|
|
212
|
-
|
|
213
|
-
- Remove \`console.log\`, \`debugger\`, and \`alert\` statements from production code
|
|
214
|
-
- Throw \`Error\` objects with descriptive messages, not strings or other values
|
|
215
|
-
- Use \`try-catch\` blocks meaningfully - don't catch errors just to rethrow them
|
|
216
|
-
- Prefer early returns over nested conditionals for error cases
|
|
217
|
-
|
|
218
|
-
### Code Organization
|
|
219
|
-
|
|
220
|
-
- Keep functions focused and under reasonable cognitive complexity limits
|
|
221
|
-
- Extract complex conditions into well-named boolean variables
|
|
222
|
-
- Use early returns to reduce nesting
|
|
223
|
-
- Prefer simple conditionals over nested ternary operators
|
|
224
|
-
- Group related code together and separate concerns
|
|
225
|
-
|
|
226
|
-
### Security
|
|
227
|
-
|
|
228
|
-
- Add \`rel="noopener"\` when using \`target="_blank"\` on links
|
|
229
|
-
- Avoid \`dangerouslySetInnerHTML\` unless absolutely necessary
|
|
230
|
-
- Don't use \`eval()\` or assign directly to \`document.cookie\`
|
|
231
|
-
- Validate and sanitize user input
|
|
232
|
-
|
|
233
|
-
### Performance
|
|
234
|
-
|
|
235
|
-
- Avoid spread syntax in accumulators within loops
|
|
236
|
-
- Use top-level regex literals instead of creating them in loops
|
|
237
|
-
- Prefer specific imports over namespace imports
|
|
238
|
-
- Avoid barrel files (index files that re-export everything)
|
|
239
|
-
- Use proper image components (e.g., Next.js \`<Image>\`) over \`<img>\` tags
|
|
240
|
-
|
|
241
|
-
### Framework-Specific Guidance
|
|
242
|
-
|
|
243
|
-
**Next.js:**
|
|
244
|
-
- Use Next.js \`<Image>\` component for images
|
|
245
|
-
- Use \`next/head\` or App Router metadata API for head elements
|
|
246
|
-
- Use Server Components for async data fetching instead of async Client Components
|
|
247
|
-
|
|
248
|
-
**React 19+:**
|
|
249
|
-
- Use ref as a prop instead of \`React.forwardRef\`
|
|
250
|
-
|
|
251
|
-
**Solid/Svelte/Vue/Qwik:**
|
|
252
|
-
- Use \`class\` and \`for\` attributes (not \`className\` or \`htmlFor\`)
|
|
253
|
-
|
|
254
|
-
---
|
|
255
|
-
|
|
256
|
-
## Testing
|
|
257
|
-
|
|
258
|
-
- Write assertions inside \`it()\` or \`test()\` blocks
|
|
259
|
-
- Avoid done callbacks in async tests - use async/await instead
|
|
260
|
-
- Don't use \`.only\` or \`.skip\` in committed code
|
|
261
|
-
- Keep test suites reasonably flat - avoid excessive \`describe\` nesting
|
|
262
|
-
|
|
263
|
-
## When Biome Can't Help
|
|
264
|
-
|
|
265
|
-
Biome's linter will catch most issues automatically. Focus your attention on:
|
|
266
|
-
|
|
267
|
-
1. **Business logic correctness** - Biome can't validate your algorithms
|
|
268
|
-
2. **Meaningful naming** - Use descriptive names for functions, variables, and types
|
|
269
|
-
3. **Architecture decisions** - Component structure, data flow, and API design
|
|
270
|
-
4. **Edge cases** - Handle boundary conditions and error states
|
|
271
|
-
5. **User experience** - Accessibility, performance, and usability considerations
|
|
272
|
-
6. **Documentation** - Add comments for complex logic, but prefer self-documenting code
|
|
273
|
-
|
|
274
|
-
---
|
|
275
|
-
|
|
276
|
-
Most formatting and common issues are automatically fixed by Biome. Run \`${e} ultracite fix\` before committing to ensure compliance.
|
|
277
|
-
`;var ze=(e,t)=>{let s=Le[e],n=gs(t,""),o=He(n),i=s.header?`${s.header}
|
|
278
|
-
|
|
279
|
-
${o}`:o,a=async()=>{let r=us(s.path);if(r!=="."){let c=r.startsWith("./")?r.slice(2):r;await ms(c,{recursive:!0})}};return{exists:()=>f(s.path),create:async()=>{await a(),await ee(s.path,i)},update:async()=>{if(await a(),s.appendMode){if(!await f(s.path)){await ee(s.path,i);return}let r=await ps(s.path,"utf-8");if(r.includes(o.trim()))return;await ee(s.path,`${r}
|
|
280
|
-
|
|
281
|
-
${o}`)}else await ee(s.path,i)}}};h();import{readFile as hs,writeFile as Ge}from"fs/promises";import ys from"deepmerge";import{parse as ws}from"jsonc-parser";var Ve={$schema:"./node_modules/@biomejs/biome/configuration_schema.json",extends:["ultracite/core"]},he=async()=>await f("./biome.json")?"./biome.json":"./biome.jsonc",te={exists:async()=>{let e=await he();return f(e)},create:async e=>{let t=await he(),s=["ultracite/core"];if(e?.frameworks&&e.frameworks.length>0)for(let o of e.frameworks)s.push(`ultracite/${o}`);let n={...Ve,extends:s};return Ge(t,JSON.stringify(n,null,2))},update:async e=>{let t=await he(),s=await hs(t,"utf-8"),o=ws(s)||{},a=[...o.extends&&Array.isArray(o.extends)?o.extends:[]];if(a.includes("ultracite/core")||a.push("ultracite/core"),e?.frameworks&&e.frameworks.length>0)for(let p of e.frameworks){let u=`ultracite/${p}`;a.includes(u)||a.push(u)}o.extends=a;let r={$schema:Ve.$schema},c=ys(o,r);await Ge(t,JSON.stringify(c,null,2))}};h();import{spawnSync as ks}from"child_process";import{mkdir as bs,readFile as xs,writeFile as Ye}from"fs/promises";import vs from"deepmerge";import{parse as Cs}from"jsonc-parser";var ye={"editor.defaultFormatter":"esbenp.prettier-vscode","[javascript]":{"editor.defaultFormatter":"biomejs.biome"},"[typescript]":{"editor.defaultFormatter":"biomejs.biome"},"[javascriptreact]":{"editor.defaultFormatter":"biomejs.biome"},"[typescriptreact]":{"editor.defaultFormatter":"biomejs.biome"},"[json]":{"editor.defaultFormatter":"biomejs.biome"},"[jsonc]":{"editor.defaultFormatter":"biomejs.biome"},"[css]":{"editor.defaultFormatter":"biomejs.biome"},"[graphql]":{"editor.defaultFormatter":"biomejs.biome"},"typescript.tsdk":"node_modules/typescript/lib","editor.formatOnSave":!0,"editor.formatOnPaste":!0,"emmet.showExpandedAbbreviation":"never","editor.codeActionsOnSave":{"source.fixAll.biome":"explicit","source.organizeImports.biome":"explicit"}};var se="./.vscode/settings.json",J={exists:()=>f(se),create:async()=>{await bs(".vscode",{recursive:!0}),await Ye(se,JSON.stringify(ye,null,2))},update:async()=>{let e=await xs(se,"utf-8"),s=Cs(e)||{},n=vs(s,ye);await Ye(se,JSON.stringify(n,null,2))},extension:()=>ks("code --install-extension biomejs.biome",{stdio:"pipe",shell:!0})};h();import{mkdir as js,readFile as Ps,writeFile as Ke}from"fs/promises";import $s from"deepmerge";import{parse as Ss}from"jsonc-parser";var we={formatter:"language_server",format_on_save:"on",languages:{JavaScript:{formatter:{language_server:{name:"biome"}},code_actions_on_format:{"source.fixAll.biome":!0,"source.organizeImports.biome":!0}},TypeScript:{formatter:{language_server:{name:"biome"}},code_actions_on_format:{"source.fixAll.biome":!0,"source.organizeImports.biome":!0}},TSX:{formatter:{language_server:{name:"biome"}},code_actions_on_format:{"source.fixAll.biome":!0,"source.organizeImports.biome":!0}}},lsp:{"typescript-language-server":{settings:{typescript:{preferences:{includePackageJsonAutoImports:"on"}}}}}};var ne="./.zed/settings.json",oe={exists:()=>f(ne),create:async()=>{await js(".zed",{recursive:!0}),await Ke(ne,JSON.stringify(we,null,2))},update:async()=>{let e=await Ps(ne,"utf-8"),s=Ss(e)||{},n=$s(s,we);await Ke(ne,JSON.stringify(n,null,2))}};import{mkdir as Rs,readFile as Xe,writeFile as N}from"fs/promises";import{dirname as Es}from"path";import{dlxCommand as As}from"nypm";h();var Qe=e=>({version:1,hooks:{afterFileEdit:[{command:e}]}}),Ze=e=>({hooks:{PostToolUse:[{matcher:"Edit|Write",hooks:[{type:"command",command:e}]}]}}),Fs=async(e,t)=>{if(!await f(e)){await N(e,JSON.stringify(Qe(t),null,2));return}let s=await Xe(e,"utf-8"),n=JSON.parse(s);n.hooks.afterFileEdit.some(i=>i.command.includes("ultracite"))||(n.hooks.afterFileEdit.push({command:t}),await N(e,JSON.stringify(n,null,2)))},Ns=async(e,t)=>{if(!await f(e)){await N(e,JSON.stringify(Ze(t),null,2));return}let s=await Xe(e,"utf-8"),n=JSON.parse(s);n.hooks||(n.hooks={}),n.hooks.PostToolUse||(n.hooks.PostToolUse=[]),n.hooks.PostToolUse.some(i=>i.hooks?.some(a=>a.command.includes("ultracite")))||(n.hooks.PostToolUse.push({matcher:"Edit|Write",hooks:[{type:"command",command:t}]}),await N(e,JSON.stringify(n,null,2)))},qe=(e,t)=>{let s=We[e],n=As(t,"ultracite",{args:["fix"],short:t==="npm"}),o=async()=>{let i=Es(s.path);if(i!=="."){let a=i.startsWith("./")?i.slice(2):i;await Rs(a,{recursive:!0})}};return{exists:()=>f(s.path),create:async()=>{await o(),e==="cursor"?await N(s.path,JSON.stringify(Qe(n),null,2)):e==="claude"&&await N(s.path,JSON.stringify(Ze(n),null,2))},update:async()=>{await o(),e==="cursor"?await Fs(s.path,n):e==="claude"&&await Ns(s.path,n)}}};be();xe();Pe();Ce();import{readFile as an,writeFile as ft}from"fs/promises";import{glob as cn}from"glob";import{applyEdits as ln,modify as dn,parse as fn}from"jsonc-parser";var mt=async()=>{try{return await cn("**/tsconfig*.json",{ignore:["**/node_modules/**","**/dist/**","**/build/**","**/.next/**"],absolute:!1})}catch{return[]}},mn=e=>{if(!e)return!1;let t=e.compilerOptions;return t?t.strict===!0||t.strictNullChecks===!0:!1},pn=async e=>{try{let t=await an(e,"utf-8"),s=fn(t);if(mn(s))return;if(s===void 0){await ft(e,JSON.stringify({compilerOptions:{strictNullChecks:!0}},null,2));return}let o=dn(t,["compilerOptions","strictNullChecks"],!0,{formattingOptions:{tabSize:2,insertSpaces:!0}}),i=ln(t,o);await ft(e,i)}catch(t){console.warn(`Failed to update ${e}:`,t)}},Re={exists:async()=>(await mt()).length>0,update:async()=>{let e=await mt();if(e.length===0){console.warn("No tsconfig.json files found in the project");return}await Promise.all(e.map(t=>pn(t)))}};h();var pt=k.devDependencies["@biomejs/biome"],ut=k.version,wn=async(e,t=!0,s=!1)=>{let n=w();s||n.start("Installing dependencies...");let o=[`ultracite@${ut}`,`@biomejs/biome@${pt}`];if(t)for(let i of o)await hn(i,{packageManager:e,workspace:await C(),silent:!0});else await v({devDependencies:{"@biomejs/biome":pt,ultracite:ut}});s||n.stop("Dependencies installed.")},kn=async(e=!1)=>{let t=w();if(e||t.start("Checking for tsconfig.json files..."),await Re.exists()){e||t.message("Found tsconfig.json files, updating with strictNullChecks..."),await Re.update(),e||t.stop("tsconfig.json files updated.");return}e||t.stop("No tsconfig.json files found, skipping.")},bn=async(e=!1)=>{let t=w();if(e||t.start("Checking for .vscode/settings.json..."),await J.exists()){e||t.message("settings.json found, updating..."),await J.update(),e||t.stop("settings.json updated.");return}e||t.message("settings.json not found, creating..."),await J.create(),e||(t.message("settings.json created."),t.message("Installing Biome extension..."));try{let s=J.extension();e||(s.status===0?t.stop("settings.json created and Biome extension installed."):t.stop("settings.json created. Install Biome extension manually."))}catch{e||t.stop("settings.json created. Install Biome extension manually.")}},xn=async(e=!1)=>{let t=w();if(e||t.start("Checking for .zed/settings.json..."),await oe.exists()){e||t.message("settings.json found, updating..."),await oe.update(),e||t.stop("settings.json updated.");return}e||t.message("settings.json not found, creating..."),await oe.create(),e||t.message("settings.json created. Install the Biome extension: https://biomejs.dev/reference/zed/")},vn=async(e,t=!1)=>{let s=w();if(t||s.start("Checking for Biome configuration..."),await te.exists()){t||s.message("Biome configuration found, updating..."),await te.update({frameworks:e}),t||s.stop("Biome configuration updated.");return}t||s.message("Biome configuration not found, creating..."),await te.create({frameworks:e}),t||s.stop("Biome configuration created.")},Cn=async(e,t=!0,s=!1)=>{let n=w();if(s||(n.start("Initializing pre-commit hooks..."),n.message("Installing Husky...")),t?await S.install(e):await v({devDependencies:{husky:"latest"},scripts:{prepare:"husky"}}),s||n.message("Initializing Husky..."),S.init(e),await S.exists()){s||n.message("Pre-commit hook found, updating..."),await S.update(e),s||n.stop("Pre-commit hook updated.");return}s||n.message("Pre-commit hook not found, creating..."),await S.create(e),s||n.stop("Pre-commit hook created.")},jn=async(e,t=!0,s=!1)=>{let n=w();if(s||(n.start("Initializing lefthook..."),n.message("Installing lefthook...")),t?await O.install(e):await v({devDependencies:{lefthook:"latest"}}),await O.exists()){s||n.message("lefthook.yml found, updating..."),await O.update(e),s||n.stop("lefthook.yml updated.");return}s||n.message("lefthook.yml not found, creating..."),await O.create(e),s||n.stop("lefthook.yml created.")},Pn=async(e,t=!0,s=!1)=>{let n=w();if(s||(n.start("Initializing lint-staged..."),n.message("Installing lint-staged...")),t?await D.install(e):await v({devDependencies:{"lint-staged":"latest"}}),await D.exists()){s||n.message("lint-staged found, updating..."),await D.update(e),s||n.stop("lint-staged updated.");return}s||n.message("lint-staged not found, creating..."),await D.create(e),s||n.stop("lint-staged created.")},$n=async(e,t=!1)=>{let s=w();if(t||s.start("Initializing pre-commit..."),await W.exists()){t||s.message(".pre-commit-config.yaml found, updating..."),await W.update(e),t||s.stop(".pre-commit-config.yaml updated.");return}t||s.message(".pre-commit-config.yaml not found, creating..."),await W.create(e),t||s.stop(".pre-commit-config.yaml created.")},Sn=async(e,t,s,n=!1)=>{let o=w();n||o.start(`Checking for ${t}...`);let i=ze(e,s);if(await i.exists()){n||o.message(`${t} found, updating...`),await i.update(),n||o.stop(`${t} updated.`);return}n||o.message(`${t} not found, creating...`),await i.create(),n||o.stop(`${t} created.`)},Rn=async(e,t,s,n=!1)=>{let o=w();n||o.start(`Checking for ${t} hooks...`);let i=qe(e,s);if(await i.exists()){n||o.message(`${t} hooks found, updating...`),await i.update(),n||o.stop(`${t} hooks updated.`);return}n||o.message(`${t} hooks not found, creating...`),await i.create(),n||o.stop(`${t} hooks created.`)},En=async(e,t=!1)=>{let s=w();t||s.start("Removing Prettier dependencies and configuration...");try{let n=await pe.remove(e);t||(n.packagesRemoved.length>0&&s.message(`Removed Prettier packages: ${n.packagesRemoved.join(", ")}`),n.filesRemoved.length>0&&s.message(`Removed config files: ${n.filesRemoved.join(", ")}`),n.vsCodeCleaned&&s.message("Cleaned VS Code settings"),s.stop("Prettier removed successfully."))}catch{t||s.stop("Failed to remove Prettier completely, but continuing...")}},An=async(e,t=!1)=>{let s=w();t||s.start("Removing ESLint dependencies and configuration...");try{let n=await me.remove(e);t||(n.packagesRemoved.length>0&&s.message(`Removed ESLint packages: ${n.packagesRemoved.join(", ")}`),n.filesRemoved.length>0&&s.message(`Removed config files: ${n.filesRemoved.join(", ")}`),n.vsCodeCleaned&&s.message("Cleaned VS Code settings"),s.stop("ESLint removed successfully."))}catch{t||s.stop("Failed to remove ESLint completely, but continuing...")}},gt=async e=>{let t=e??{},s=t.quiet??!1;s||gn(Y);try{let{pm:n}=t;if(!n){let m=await yn(un.cwd());if(!m)throw new Error("No package manager specified or detected");if(!s&&m.warnings)for(let g of m.warnings)ae.warn(g);s||ae.info(`Detected lockfile, using ${m.name}`),n=m.name}let o=t.migrate?.includes("prettier"),i=t.migrate?.includes("eslint");if(!s&&(o===void 0||i===void 0)){let m=[];if(o===void 0&&await pe.hasPrettier()&&m.push({label:"Remove Prettier (dependencies, config files, VS Code settings)",value:"prettier"}),i===void 0&&await me.hasEsLint()&&m.push({label:"Remove ESLint (dependencies, config files, VS Code settings)",value:"eslint"}),m.length>0){let g=await U({message:"Remove existing formatters/linters (recommended for clean migration)?",options:m,required:!1});if(T(g)){M("Operation cancelled.");return}o===void 0&&(o=g.includes("prettier")),i===void 0&&(i=g.includes("eslint"))}}s&&(o===void 0&&(o=!1),i===void 0&&(i=!1));let a=t.frameworks;if(a===void 0)if(s||t.pm||t.editors||t.agents||t.hooks||t.integrations!==void 0||t.migrate!==void 0)a=[];else{let g=await U({message:"Which frameworks are you using (optional)?",options:[{label:"React",value:"react"},{label:"Next.js",value:"next"},{label:"Solid",value:"solid"},{label:"Vue",value:"vue"},{label:"Svelte",value:"svelte"},{label:"Qwik",value:"qwik"},{label:"Angular",value:"angular"},{label:"Remix / TanStack Router / React Router",value:"remix"},{label:"Astro",value:"astro"}],required:!1});if(T(g)){M("Operation cancelled.");return}a=g}let r=t.editors;if(!r)if(s)r=[];else{let m=await U({message:"Which editors do you want to configure (recommended)?",options:[{label:"VSCode / Cursor / Windsurf",value:"vscode"},{label:"Zed",value:"zed"}],required:!1});if(T(m)){M("Operation cancelled.");return}r=m}let c=t.agents,p=t.hooks,u={"vscode-copilot":"GitHub Copilot (VSCode)",cursor:"Cursor",windsurf:"Windsurf",zed:"Zed",claude:"Claude Code",codex:"OpenAI Codex / Jules / OpenCode",kiro:"Kiro IDE",cline:"Cline",amp:"AMP",aider:"Aider","firebase-studio":"Firebase Studio","open-hands":"Open Hands","gemini-cli":"Gemini CLI",junie:"Junie",augmentcode:"Augment Code","kilo-code":"Kilo Code",goose:"Codename Goose","roo-code":"Roo Code",warp:"Warp",droid:"Droid",antigravity:"Antigravity"};if(!c)if(s)c=[];else{let m=await U({message:"Which agents do you want to enable (optional)?",options:Object.entries(u).map(([g,ce])=>({value:g,label:ce})),required:!1});if(T(m)){M("Operation cancelled.");return}c=m}let x={cursor:"Cursor",claude:"Claude Code"};if(!p)if(s)p=[];else{let m=await U({message:"Which agent hooks do you want to enable (optional)?",options:Object.entries(x).map(([g,ce])=>({value:g,label:ce})),required:!1});if(T(m)){M("Operation cancelled.");return}p=m}let y=t.integrations;if(y===void 0)if(s||t.pm||t.editors||t.agents||t.hooks||t.migrate!==void 0)y=[];else{let g=await U({message:"Would you like any of the following (optional)?",options:[{label:"Husky pre-commit hook",value:"husky"},{label:"Lefthook pre-commit hook",value:"lefthook"},{label:"Lint-staged",value:"lint-staged"},{label:"pre-commit (Python framework)",value:"pre-commit"}],required:!1});if(T(g)){M("Operation cancelled.");return}y=g}o&&await En(n,s),i&&await An(n,s),await wn(n,!t.skipInstall,s),await kn(s),await vn(a,s),r?.includes("vscode")&&await bn(s),r?.includes("zed")&&await xn(s);for(let m of c??[])await Sn(m,u[m],n,s);for(let m of p??[])await Rn(m,x[m],n,s);y?.includes("husky")&&await Cn(n,!t.skipInstall,s),y?.includes("lefthook")&&await jn(n,!t.skipInstall,s),y?.includes("lint-staged")&&await Pn(n,!t.skipInstall,s),y?.includes("pre-commit")&&await $n(n,s),s||ae.success("Successfully initialized Ultracite configuration!")}catch(n){let o=n instanceof Error?n.message:"Unknown error";throw s||ae.error(`Failed to initialize Ultracite configuration: ${o}`),n}};var A=Fn.meta().create(),On=A.router({init:A.procedure.meta({description:"Initialize Ultracite in the current directory"}).input(d.object({pm:d.enum(j.packageManagers).optional().describe("Package manager to use"),editors:d.array(d.enum(j.editorConfigs)).optional().describe("Editors to configure"),agents:d.array(d.enum(j.agents)).optional().describe("Agents to enable"),hooks:d.array(d.enum(j.hooks)).optional().describe("Hooks to enable"),frameworks:d.array(d.enum(j.frameworks)).optional().describe("Frameworks being used"),integrations:d.array(d.enum(j.integrations)).optional().describe("Additional integrations to enable"),migrate:d.array(d.enum(j.migrations)).optional().describe("Migration tools to remove (e.g., eslint, prettier). Removes dependencies, config files, and editor settings."),skipInstall:d.boolean().default(!1).describe("Skip installing dependencies"),quiet:d.boolean().default(process.env.CI==="true"||process.env.CI==="1").describe("Suppress all interactive prompts and visual output. Automatically enabled in CI environments.")})).mutation(async({input:e})=>{await gt(e)}),check:A.procedure.meta({description:"Run Biome linter without fixing files"}).input(d.tuple([d.array(d.string()).optional().default([]).describe("specific files to lint"),d.object({"diagnostic-level":d.enum(["info","warn","error"]).optional().describe("level of diagnostics to show. In order, from the lowest to the most important: info, warn, error.")})]).optional()).query(async({input:e})=>{await fe(e)}),fix:A.procedure.meta({description:"Run Biome linter and fixes files"}).input(d.tuple([d.array(d.string()).optional().default([]).describe("specific files to format"),d.object({unsafe:d.boolean().optional().describe("apply unsafe fixes")})])).mutation(async({input:e})=>{let[t,s]=e;await ge(t,{unsafe:s.unsafe})}),doctor:A.procedure.meta({description:"Verify your Ultracite setup and check for issues"}).query(async()=>{await Be()}),lint:A.procedure.meta({description:"\u26A0\uFE0F DEPRECATED: Use 'check' instead - Run Biome linter without fixing files"}).input(d.array(d.string()).optional().default([]).describe("specific files to lint")).query(async({input:e})=>{console.warn("\u26A0\uFE0F Warning: 'lint' command is deprecated. Please use 'check' instead."),await fe([e,{}])}),format:A.procedure.meta({description:"\u26A0\uFE0F DEPRECATED: Use 'fix' instead - Run Biome linter and fixes files"}).input(d.tuple([d.array(d.string()).optional().default([]).describe("specific files to format"),d.object({unsafe:d.boolean().optional().describe("apply unsafe fixes")})])).mutation(async({input:e})=>{let[t,s]=e;console.warn("\u26A0\uFE0F Warning: 'format' command is deprecated. Please use 'fix' instead."),await ge(t,{unsafe:s.unsafe})})}),Dn=Nn({router:On,name:k.name,version:k.version,description:k.description});process.env.TEST||Dn.run();export{On as router};
|
|
125
|
+
${i}`)}}});var Dn,Ot=R(()=>{Dn=At({"./husky.ts":()=>(jt(),Z(Gt)),"./lefthook.ts":()=>(Pt(),Z(Vt)),"./lint-staged.ts":()=>(vt(),Z(qt)),"./pre-commit.ts":()=>(St(),Z(Zt))})});var qt={};Q(qt,{lintStaged:()=>W});import{readFile as st,writeFile as F}from"fs/promises";import{pathToFileURL as Ln}from"url";import X from"deepmerge";import{parse as Ft}from"jsonc-parser";import{addDevDependency as An,dlxCommand as Jn}from"nypm";var j,te,Tn,In,Mn,_n,Bn,Wn,Un,zn,Hn,Nt,Gn,W,vt=R(()=>{"use strict";m();Ot();j=t=>({"*.{js,jsx,ts,tsx,json,jsonc,css,scss,md,mdx}":[Jn(t,"ultracite",{args:["fix"],short:t==="npm"})]}),te=["./package.json","./.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"],Tn=(t,e,n,i)=>{let o=t.trim();if(o.includes(":")&&!o.startsWith("-")){n&&i.length>0&&(e[n]=i);let[s,...r]=o.split(":"),a=r.join(":").trim(),p=s.trim().replace(/['"]/g,"");return a&&a!==""?(a.startsWith("[")&&a.endsWith("]")?e[p]=a.slice(1,-1).split(",").map(h=>h.trim().replace(/['"]/g,"")):e[p]=a.replace(/['"]/g,""),{newCurrentKey:null,newCurrentArray:[]}):{newCurrentKey:p,newCurrentArray:[]}}if(o.startsWith("-")&&n){let s=[...i,o.slice(1).trim().replace(/['"]/g,"")];return{newCurrentKey:n,newCurrentArray:s}}return{newCurrentKey:n,newCurrentArray:i}},In=t=>{let e=t.split(`
|
|
126
|
+
`).filter(s=>s.trim()&&!s.trim().startsWith("#")),n={},i=null,o=[];for(let s of e){let r=Tn(s,n,i,o);i=r.newCurrentKey,o=r.newCurrentArray}return i&&o.length>0&&(n[i]=o),n},Mn=t=>{let e="";for(let[n,i]of Object.entries(t))if(Array.isArray(i)){e+=`${n}:
|
|
127
|
+
`;for(let o of i)e+=` - '${o}'
|
|
128
|
+
`}else e+=`${n}: '${i}'
|
|
129
|
+
`;return e},_n=async()=>{try{let t=Ft(await st("./package.json","utf-8"));return t?t.type==="module":!1}catch{return!1}},Bn=async t=>{let e=Ft(await st("./package.json","utf-8"));e&&(e["lint-staged"]?e["lint-staged"]=X(e["lint-staged"],j(t)):e["lint-staged"]=j(t),await F("./package.json",JSON.stringify(e,null,2)))},Wn=async(t,e)=>{let n=await st(t,"utf-8"),i=Ft(n);if(!i)return;let o=X(i,j(e));await F(t,JSON.stringify(o,null,2))},Un=async(t,e)=>{let n=await st(t,"utf-8"),i=In(n);if(!i)return;let o=X(i,j(e));await F(t,Mn(o))},zn=async(t,e)=>{let o=(await import(Ln(t).href)).default||{},s=X(o,j(e)),r=`export default ${JSON.stringify(s,null,2)};
|
|
130
|
+
`;await F(t,r)},Hn=async(t,e)=>{delete wt.cache[wt.resolve(`./${t}`)];let n=Dn(`./${t}`),i=X(n,j(e)),o=`module.exports = ${JSON.stringify(i,null,2)};
|
|
131
|
+
`;await F(t,o)},Nt=async t=>{await F(".lintstagedrc.json",JSON.stringify(j(t),null,2))},Gn=async(t,e)=>{if(t==="./package.json"){await Bn(e);return}if(t.endsWith(".json")||t==="./.lintstagedrc"){await Wn(t,e);return}if(t.endsWith(".yaml")||t.endsWith(".yml")){await Un(t,e);return}let n=await _n();if(t.endsWith(".mjs")||t.endsWith(".js")&&n){try{await zn(t,e)}catch{await Nt(e)}return}if(t.endsWith(".cjs")||t.endsWith(".js")&&!n)try{await Hn(t,e)}catch{await Nt(e)}},W={exists:async()=>{for(let t of te)if(await c(t))return!0;return!1},install:async t=>{await An("lint-staged",{packageManager:t,workspace:await b(),silent:!0})},create:async t=>{await F(".lintstagedrc.json",JSON.stringify(j(t),null,2))},update:async t=>{let e=null;for(let n of te)if(await c(n)){e=n;break}if(!e){await Nt(t);return}await Gn(e,t)}}});import{options as C}from"@repo/data/options";import{initTRPC as Bi}from"@trpc/server";import{packageManagers as Wi}from"nypm";import{createCli as Ui}from"trpc-cli";import f from"zod";var y={name:"ultracite",description:"The AI-ready formatter that helps you write and generate code faster.",version:"7.0.0",type:"module",bin:{ultracite:"dist/index.js"},files:["config","dist","README.md"],scripts:{build:"tsup",test:"bun test","test:coverage":"bun test --coverage"},exports:{"./biome/*":"./config/biome/*/biome.jsonc","./eslint/*":"./config/eslint/*/eslint.config.mjs","./oxlint/*":"./config/oxlint/*/.oxlintrc.json","./prettier":"./config/prettier/prettier.config.mjs","./stylelint":"./config/stylelint/stylelint.config.mjs","./*":"./config/*/biome.jsonc"},author:"Hayden Bleasel <hello@haydenbleasel.com>",bugs:{url:"https://github.com/haydenbleasel/ultracite/issues"},homepage:"https://www.ultracite.ai/",keywords:["ultracite","biome","linter","formatter","fixer"],license:"MIT",publishConfig:{access:"public",registry:"https://registry.npmjs.org/"},repository:{type:"git",url:"git+https://github.com/haydenbleasel/ultracite.git"},devDependencies:{"@biomejs/biome":"catalog:","@eslint/js":"^9.39.2","@next/eslint-plugin-next":"^16.1.1","@tanstack/eslint-plugin-query":"^5.91.2","@types/node":"catalog:","@typescript-eslint/eslint-plugin":"^8.51.0","@typescript-eslint/parser":"^8.51.0","eslint-config-prettier":"^10.1.8","eslint-import-resolver-typescript":"^4.4.4","eslint-plugin-angular":"^5.0.0","eslint-plugin-astro":"^1.5.0","eslint-plugin-compat":"^6.0.2","eslint-plugin-cypress":"^5.2.0","eslint-plugin-github":"6.0.0","eslint-plugin-html":"^8.1.3","eslint-plugin-import":"^2.32.0","eslint-plugin-jest":"^29.12.0","eslint-plugin-jsx-a11y":"^6.10.2","eslint-plugin-n":"^17.23.1","eslint-plugin-prettier":"^5.5.4","eslint-plugin-promise":"^7.2.1","eslint-plugin-qwik":"^1.18.0","eslint-plugin-react":"^7.37.5","eslint-plugin-react-hooks":"^7.0.1","eslint-plugin-remix":"^1.1.1","eslint-plugin-solid":"^0.14.5","eslint-plugin-sonarjs":"^3.0.5","eslint-plugin-storybook":"^10.1.11","eslint-plugin-svelte":"^3.13.1","eslint-plugin-tailwindcss":"^3.18.2","eslint-plugin-unicorn":"^62.0.0","eslint-plugin-unused-imports":"^4.3.0","eslint-plugin-vue":"^10.6.2",globals:"^16.5.0","prettier-plugin-tailwindcss":"^0.7.2","stylelint-config-idiomatic-order":"^10.0.0","stylelint-config-standard":"^39.0.1","stylelint-prettier":"^5.0.3",tsup:"^8.5.1"},dependencies:{"@clack/prompts":"^0.11.0","@trpc/server":"^11.8.1","@repo/data":"workspace:*",deepmerge:"catalog:",glob:"^13.0.0","jsonc-parser":"^3.3.1",nypm:"^0.6.2",oxlint:"^1.36.0","trpc-cli":"^0.12.1",zod:"catalog:"},packageManager:"bun@1.3.5"};m();import{spawnSync as D}from"child_process";import L from"process";import{detectPackageManager as A,dlxCommand as J}from"nypm";var Je=async(t,e)=>{let n=["check","--no-errors-on-unmatched"];e&&n.push(`--diagnostic-level=${e}`),t.length>0?n.push(...d(t)):n.push("./");let o=(await A(L.cwd()))?.name||"npm",s=J(o,"@biomejs/biome",{args:n,short:o==="npm"}),r=D(s,{stdio:"inherit",shell:!0});if(r.error)throw new Error(`Failed to run Biome: ${r.error.message}`);return{hasErrors:r.status!==0}},Te=async t=>{let e=t.length>0?d(t):["."],i=(await A(L.cwd()))?.name||"npm",o=J(i,"eslint",{args:e,short:i==="npm"}),s=D(o,{stdio:"inherit",shell:!0});if(s.error)throw new Error(`Failed to run ESLint: ${s.error.message}`);return{hasErrors:s.status!==0}},Ie=async t=>{let e=["--check",...t.length>0?d(t):["."]],i=(await A(L.cwd()))?.name||"npm",o=J(i,"prettier",{args:e,short:i==="npm"}),s=D(o,{stdio:"inherit",shell:!0});if(s.error)throw new Error(`Failed to run Prettier: ${s.error.message}`);return{hasErrors:s.status!==0}},Me=async t=>{let e=t.length>0?d(t):["."],i=(await A(L.cwd()))?.name||"npm",o=J(i,"stylelint",{args:e,short:i==="npm"}),s=D(o,{stdio:"inherit",shell:!0});if(s.error)throw new Error(`Failed to run Stylelint: ${s.error.message}`);return{hasErrors:s.status!==0}},_e=async t=>{let e=t.length>0?d(t):["."],i=(await A(L.cwd()))?.name||"npm",o=J(i,"oxlint",{args:e,short:i==="npm"}),s=D(o,{stdio:"inherit",shell:!0});if(s.error)throw new Error(`Failed to run Oxlint: ${s.error.message}`);return{hasErrors:s.status!==0}},Be=async t=>{let e=["--check",...t.length>0?d(t):["."]],i=(await A(L.cwd()))?.name||"npm",o=J(i,"oxfmt",{args:e,short:i==="npm"}),s=D(o,{stdio:"inherit",shell:!0});if(s.error)throw new Error(`Failed to run oxfmt: ${s.error.message}`);return{hasErrors:s.status!==0}},Tt=async t=>{let e=t?.[0]||[],n=t?.[1]["diagnostic-level"],o=t?.[1].linter||await q();if(!o)throw new Error("No linter configuration found. Run `ultracite init` to set up a linter.");switch(o){case"eslint":{let s=await Ie(e),r=await Te(e),a=await Me(e);return{hasErrors:s.hasErrors||r.hasErrors||a.hasErrors}}case"oxlint":{let s=await Be(e),r=await _e(e);return{hasErrors:s.hasErrors||r.hasErrors}}default:return Je(e,n)}};import{spawnSync as xt}from"child_process";import{existsSync as S}from"fs";import{readFile as et}from"fs/promises";import{join as O}from"path";import w from"process";import{intro as We,log as tt,outro as yt,spinner as Ue}from"@clack/prompts";import{parse as It}from"jsonc-parser";import{detectPackageManager as nt,dlxCommand as it}from"nypm";var ze=[".prettierrc",".prettierrc.js",".prettierrc.cjs",".prettierrc.mjs",".prettierrc.json",".prettierrc.yaml",".prettierrc.yml","prettier.config.js","prettier.config.mjs","prettier.config.cjs"],He=[".eslintrc",".eslintrc.js",".eslintrc.cjs",".eslintrc.mjs",".eslintrc.json",".eslintrc.yaml",".eslintrc.yml","eslint.config.js","eslint.config.mjs","eslint.config.cjs","eslint.config.ts","eslint.config.mts","eslint.config.cts"],Ge=async()=>{let e=(await nt(w.cwd()))?.name||"npm",n=it(e,"@biomejs/biome",{args:["--version"],short:e==="npm"}),i=xt(n,{shell:!0,encoding:"utf-8"});return i.status===0&&i.stdout?{name:"Biome installation",status:"pass",message:`Biome is installed (${i.stdout.trim()})`}:{name:"Biome installation",status:"fail",message:"Biome is not installed or not accessible"}},Ye=async()=>{let e=(await nt(w.cwd()))?.name||"npm",n=it(e,"eslint",{args:["--version"],short:e==="npm"}),i=xt(n,{shell:!0,encoding:"utf-8"});return i.status===0&&i.stdout?{name:"ESLint installation",status:"pass",message:`ESLint is installed (${i.stdout.trim()})`}:{name:"ESLint installation",status:"warn",message:"ESLint is not installed (optional)"}},Xe=async()=>{let e=(await nt(w.cwd()))?.name||"npm",n=it(e,"oxlint",{args:["--version"],short:e==="npm"}),i=xt(n,{shell:!0,encoding:"utf-8"});return i.status===0&&i.stdout?{name:"Oxlint installation",status:"pass",message:`Oxlint is installed (${i.stdout.trim()})`}:{name:"Oxlint installation",status:"warn",message:"Oxlint is not installed (optional)"}},Ke=async()=>{let t=O(w.cwd(),"biome.json"),e=O(w.cwd(),"biome.jsonc"),n=null;if(S(t)?n=t:S(e)&&(n=e),!n)return{name:"Biome configuration",status:"warn",message:"No biome.json or biome.jsonc file found"};try{let i=await et(n,"utf-8"),o=It(i);return Array.isArray(o?.extends)&&o.extends.includes("ultracite/biome/core")?{name:"Biome configuration",status:"pass",message:"biome.json(c) extends ultracite/biome/core"}:{name:"Biome configuration",status:"warn",message:"biome.json(c) exists but doesn't extend ultracite/biome/core"}}catch{return{name:"Biome configuration",status:"fail",message:"Could not parse biome.json(c) file"}}},Ve=async()=>{let t=["eslint.config.mjs","eslint.config.js","eslint.config.cjs","eslint.config.ts","eslint.config.mts","eslint.config.cts"],e=null;for(let n of t){let i=O(w.cwd(),n);if(S(i)){e=i;break}}if(!e)return{name:"ESLint configuration",status:"warn",message:"No eslint.config.* file found (optional)"};try{return(await et(e,"utf-8")).includes("ultracite/eslint")?{name:"ESLint configuration",status:"pass",message:"eslint.config.* imports ultracite/eslint"}:{name:"ESLint configuration",status:"warn",message:"eslint.config.* exists but doesn't import ultracite/eslint"}}catch{return{name:"ESLint configuration",status:"fail",message:"Could not read eslint.config.* file"}}},Qe=async()=>{let t=O(w.cwd(),".oxlintrc.json");if(!S(t))return{name:"Oxlint configuration",status:"warn",message:"No .oxlintrc.json file found (optional)"};try{let e=await et(t,"utf-8"),n=It(e);return Array.isArray(n?.extends)&&n.extends.includes("ultracite/oxlint/core")?{name:"Oxlint configuration",status:"pass",message:".oxlintrc.json extends ultracite/oxlint/core"}:{name:"Oxlint configuration",status:"warn",message:".oxlintrc.json exists but doesn't extend ultracite/oxlint/core"}}catch{return{name:"Oxlint configuration",status:"fail",message:"Could not parse .oxlintrc.json file"}}},Ze=async()=>{let t=O(w.cwd(),"package.json");if(!S(t))return{name:"Ultracite dependency",status:"warn",message:"No package.json found"};try{let e=JSON.parse(await et(t,"utf-8")),n=e.dependencies?.ultracite||e.devDependencies?.ultracite||e.peerDependencies?.ultracite;return n?{name:"Ultracite dependency",status:"pass",message:`Ultracite is in package.json (${n})`}:{name:"Ultracite dependency",status:"warn",message:"Ultracite not found in package.json dependencies"}}catch{return{name:"Ultracite dependency",status:"warn",message:"Could not parse package.json"}}},qe=()=>{let t=ze.some(i=>S(O(w.cwd(),i))),n=He.filter(i=>!i.startsWith("eslint.config")).some(i=>S(O(w.cwd(),i)));if(t||n){let i=[];return t&&i.push("Prettier"),n&&i.push("ESLint (legacy config)"),{name:"Conflicting tools",status:"warn",message:`Found potentially conflicting tools: ${i.join(", ")}`}}return{name:"Conflicting tools",status:"pass",message:"No conflicting formatting/linting tools found"}},E=async(t,e)=>{let n=Ue();n.start(`Checking ${e}...`);let i=await t();return i.status==="pass"||i.status,n.stop(i.message),i},Mt=async()=>{We(`Ultracite v${y.version} Doctor`);let e=(await nt(w.cwd()))?.name||"npm",n=it(e,"ultracite",{args:["init"],short:e==="npm"}),i=[];i.push(await E(Ge,"Biome installation")),i.push(await E(Ye,"ESLint installation")),i.push(await E(Xe,"Oxlint installation")),i.push(await E(Ke,"Biome configuration")),i.push(await E(Ve,"ESLint configuration")),i.push(await E(Qe,"Oxlint configuration")),i.push(await E(Ze,"Ultracite dependency")),i.push(await E(qe,"conflicting tools"));let o=i.filter(a=>a.status==="pass").length,s=i.filter(a=>a.status==="fail").length,r=i.filter(a=>a.status==="warn").length;if(tt.info(`Summary: ${o} passed, ${r} warnings, ${s} failed`),s>0)throw tt.error(`Some checks failed. Run '${n}' to fix issues.`),yt("Doctor complete"),new Error("Doctor checks failed");if(r>0){tt.warn(`Some optional improvements available. Run '${n}' to configure.`),yt("Doctor complete");return}tt.success("Everything looks good!"),yt("Doctor complete")};m();import{spawnSync as T}from"child_process";import I from"process";import{detectPackageManager as M,dlxCommand as _}from"nypm";var tn=async(t,e)=>{let n=["check","--write","--no-errors-on-unmatched"];e&&n.push("--unsafe"),t.length>0?n.push(...d(t)):n.push("./");let o=(await M(I.cwd()))?.name||"npm",s=_(o,"@biomejs/biome",{args:n,short:o==="npm"}),r=T(s,{stdio:"inherit",shell:!0});if(r.error)throw new Error(`Failed to run Biome: ${r.error.message}`);return{hasErrors:r.status!==0}},en=async t=>{let e=["--fix",...t.length>0?d(t):["."]],i=(await M(I.cwd()))?.name||"npm",o=_(i,"eslint",{args:e,short:i==="npm"}),s=T(o,{stdio:"inherit",shell:!0});if(s.error)throw new Error(`Failed to run ESLint: ${s.error.message}`);return{hasErrors:s.status!==0}},nn=async t=>{let e=["--write",...t.length>0?d(t):["."]],i=(await M(I.cwd()))?.name||"npm",o=_(i,"prettier",{args:e,short:i==="npm"}),s=T(o,{stdio:"inherit",shell:!0});if(s.error)throw new Error(`Failed to run Prettier: ${s.error.message}`);return{hasErrors:s.status!==0}},on=async t=>{let e=["--fix",...t.length>0?d(t):["."]],i=(await M(I.cwd()))?.name||"npm",o=_(i,"stylelint",{args:e,short:i==="npm"}),s=T(o,{stdio:"inherit",shell:!0});if(s.error)throw new Error(`Failed to run Stylelint: ${s.error.message}`);return{hasErrors:s.status!==0}},sn=async t=>{let e=["--fix",...t.length>0?d(t):["."]],i=(await M(I.cwd()))?.name||"npm",o=_(i,"oxlint",{args:e,short:i==="npm"}),s=T(o,{stdio:"inherit",shell:!0});if(s.error)throw new Error(`Failed to run Oxlint: ${s.error.message}`);return{hasErrors:s.status!==0}},rn=async t=>{let e=["--write",...t.length>0?d(t):["."]],i=(await M(I.cwd()))?.name||"npm",o=_(i,"oxfmt",{args:e,short:i==="npm"}),s=T(o,{stdio:"inherit",shell:!0});if(s.error)throw new Error(`Failed to run oxfmt: ${s.error.message}`);return{hasErrors:s.status!==0}},_t=async(t,e={})=>{let n=e.linter||await q();if(!n)throw new Error("No linter configuration found. Run `ultracite init` to set up a linter.");switch(n){case"eslint":{let i=await nn(t),o=await en(t),s=await on(t);return{hasErrors:i.hasErrors||o.hasErrors||s.hasErrors}}case"oxlint":{let i=await rn(t),o=await sn(t);return{hasErrors:i.hasErrors||o.hasErrors}}default:return tn(t,e.unsafe)}};import xi from"process";import{cancel as U,intro as ki,isCancel as z,log as ut,multiselect as K,select as Ci,spinner as g}from"@clack/prompts";import{agents as bi}from"@repo/data/agents";import{editors as xe}from"@repo/data/editors";import{providers as Ei}from"@repo/data/providers";import{addDevDependency as ji,detectPackageManager as Pi}from"nypm";m();import{readFile as an,writeFile as kt}from"fs/promises";import{agents as cn}from"@repo/data/agents";import{getRules as ln}from"@repo/data/rules";import{dlxCommand as fn}from"nypm";var Bt=(t,e)=>{let n=cn.find(r=>r.id===t);if(!n)throw new Error(`Agent "${t}" not found`);let i=fn(e,""),o=ln(i),s=n.config.header?`${n.config.header}
|
|
132
|
+
|
|
133
|
+
${o}`:o;return{exists:()=>c(n.config.path),create:async()=>{await k(n.config.path),await kt(n.config.path,s)},update:async()=>{await k(n.config.path);let r=await c(n.config.path);if(!(n.config.appendMode&&r)){await kt(n.config.path,s);return}let a=await an(n.config.path,"utf-8");a.includes(o.trim())||await kt(n.config.path,`${a}
|
|
134
|
+
|
|
135
|
+
${o}`)}}};m();import{spawnSync as mn}from"child_process";import{readFile as pn,writeFile as Ct}from"fs/promises";import{editors as gn}from"@repo/data/editors";import un from"deepmerge";import{parse as dn}from"jsonc-parser";var Wt=(t,e="biome")=>{let n=gn.find(o=>o.id===t);if(!n)throw new Error(`Editor "${t}" not found`);let i=n.config.getContent(e);return{exists:()=>c(n.config.path),create:async()=>{await k(n.config.path),await Ct(n.config.path,JSON.stringify(i,null,2))},update:async()=>{if(await k(n.config.path),!await c(n.config.path)){await Ct(n.config.path,JSON.stringify(i,null,2));return}let s=await pn(n.config.path,"utf-8"),a=dn(s)||{},p=un(a,i);await Ct(n.config.path,JSON.stringify(p,null,2))},extension:n.config.extensionCommand?o=>mn(`${n.config.extensionCommand} ${o}`,{stdio:"pipe",shell:!0}):void 0}};m();import{readFile as hn,writeFile as bt}from"fs/promises";import{editors as wn}from"@repo/data/editors";import yn from"deepmerge";import{dlxCommand as xn}from"nypm";var Ut=(t,e)=>{let n=wn.find(a=>a.id===t);if(!n)throw new Error(`Editor "${t}" not found`);if(!n.hooks)throw new Error(`Editor "${t}" does not support hooks`);let i=xn(e,"ultracite",{args:["fix"],short:e==="npm"}),o=n.hooks.getContent(i),s=a=>JSON.stringify(a).includes("ultracite"),r=async()=>{if(!n.hooks?.path)throw new Error(`Editor "${t}" does not support hooks`);if(!await c(n.hooks.path)){await bt(n.hooks.path,JSON.stringify(o,null,2));return}let p=await hn(n.hooks.path,"utf-8"),h=JSON.parse(p);if(!s(h)){let P=yn(h,o);await bt(n.hooks.path,JSON.stringify(P,null,2))}};return{exists:()=>n.hooks?.path?c(n.hooks.path):!1,create:async()=>{if(!n.hooks?.path)throw new Error(`Editor "${t}" does not support hooks`);await k(n.hooks.path),await bt(n.hooks.path,JSON.stringify(o,null,2))},update:async()=>{if(!n.hooks?.path)throw new Error(`Editor "${t}" does not support hooks`);await k(n.hooks.path),await r()}}};jt();Pt();vt();St();m();import{readFile as Yn,writeFile as ee}from"fs/promises";import Xn from"deepmerge";import{parse as Kn}from"jsonc-parser";var ne={$schema:"./node_modules/@biomejs/biome/configuration_schema.json",extends:["ultracite/biome/core"]},Rt=async()=>await c("./biome.json")?"./biome.json":"./biome.jsonc",rt={exists:async()=>{let t=await Rt();return c(t)},create:async t=>{let e=await Rt(),n=["ultracite/biome/core"];if(t?.frameworks&&t.frameworks.length>0)for(let o of t.frameworks)n.push(`ultracite/biome/${o}`);let i={...ne,extends:n};return ee(e,JSON.stringify(i,null,2))},update:async t=>{let e=await Rt(),n=await Yn(e,"utf-8"),o=Kn(n)||{},r=[...o.extends&&Array.isArray(o.extends)?o.extends:[]];if(r.includes("ultracite/biome/core")||r.push("ultracite/biome/core"),t?.frameworks&&t.frameworks.length>0)for(let h of t.frameworks){let P=`ultracite/biome/${h}`;r.includes(P)||r.push(P)}o.extends=r;let a={$schema:ne.$schema},p=Xn(o,a);await ee(e,JSON.stringify(p,null,2))}};m();import{writeFile as ie}from"fs/promises";var Vn=["./eslint.config.mjs","./eslint.config.js","./eslint.config.cjs","./eslint.config.ts","./eslint.config.mts","./eslint.config.cts"],oe="./eslint.config.mjs",Qn=async()=>{for(let t of Vn)if(await c(t))return t;return null},se=t=>{let e=['import core from "ultracite/eslint/core";'],n=["...core"];if(t?.frameworks&&t.frameworks.length>0)for(let i of t.frameworks)e.push(`import ${i} from "ultracite/eslint/${i}";`),n.push(`...${i}`);return`${e.join(`
|
|
136
|
+
`)}
|
|
137
|
+
|
|
138
|
+
export default [
|
|
139
|
+
${n.join(`,
|
|
140
|
+
`)},
|
|
141
|
+
];
|
|
142
|
+
`},at={exists:async()=>await Qn()!==null,create:async t=>{let e=se(t);await ie(oe,e)},update:async t=>{let e=se(t);await ie(oe,e)}};m();import{readFile as Zn,writeFile as re}from"fs/promises";import qn from"deepmerge";import{parse as ti}from"jsonc-parser";var ct="./.oxfmtrc.jsonc",ae={$schema:"./node_modules/oxfmt/configuration_schema.json",printWidth:80,tabWidth:2,useTabs:!1,semi:!0,singleQuote:!1,quoteProps:"as-needed",jsxSingleQuote:!1,trailingComma:"es5",bracketSpacing:!0,bracketSameLine:!1,arrowParens:"always",endOfLine:"lf",experimentalSortPackageJson:!0,experimentalSortImports:{ignoreCase:!0,newlinesBetween:!0,order:"asc"}},lt={exists:async()=>await c(ct),create:async()=>{let t=`// Ultracite oxfmt Configuration
|
|
143
|
+
// https://oxc.rs/docs/guide/usage/formatter/config-file-reference.html
|
|
144
|
+
${JSON.stringify(ae,null,2)}
|
|
145
|
+
`;return await re(ct,t)},update:async()=>{let t=await Zn(ct,"utf-8"),n=ti(t)||{},i=qn(n,ae),o=`// Ultracite oxfmt Configuration
|
|
146
|
+
// https://oxc.rs/docs/guide/usage/formatter/config-file-reference.html
|
|
147
|
+
${JSON.stringify(i,null,2)}
|
|
148
|
+
`;await re(ct,o)}};m();import{readFile as ei,writeFile as ce}from"fs/promises";import ni from"deepmerge";import{parse as ii}from"jsonc-parser";var ft="./.oxlintrc.json",le={$schema:"./node_modules/oxlint/configuration_schema.json",extends:["ultracite/oxlint/core"]},mt={exists:async()=>await c(ft),create:async t=>{let e=["ultracite/oxlint/core"];if(t?.frameworks&&t.frameworks.length>0)for(let i of t.frameworks)e.push(`ultracite/oxlint/${i}`);let n={...le,extends:e};return await ce(ft,JSON.stringify(n,null,2))},update:async t=>{let e=await ei(ft,"utf-8"),i=ii(e)||{},s=[...i.extends&&Array.isArray(i.extends)?i.extends:[]];if(s.includes("ultracite/oxlint/core")||s.push("ultracite/oxlint/core"),t?.frameworks&&t.frameworks.length>0)for(let p of t.frameworks){let h=`ultracite/oxlint/${p}`;s.includes(h)||s.push(h)}i.extends=s;let r={$schema:le.$schema},a=ni(i,r);await ce(ft,JSON.stringify(a,null,2))}};m();import{readFile as oi,writeFile as fe}from"fs/promises";var si=["./.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"],me="./prettier.config.mjs",ri=async()=>{try{return"prettier"in JSON.parse(await oi("./package.json","utf-8"))}catch{return!1}},ai=async()=>{if(await ri())return"./package.json";for(let t of si)if(await c(t))return t;return null},pe=()=>`export { default } from "ultracite/prettier";
|
|
149
|
+
`,pt={exists:async()=>await ai()!==null,create:async()=>{let t=pe();await fe(me,t)},update:async()=>{let t=pe();await fe(me,t)}};m();import{readFile as ci,writeFile as ge}from"fs/promises";var li=["./.stylelintrc.mjs","./stylelint.config.mjs","./.stylelintrc.cjs","./stylelint.config.cjs","./.stylelintrc.js","./stylelint.config.js","./.stylelintrc","./.stylelintrc.json","./.stylelintrc.yml","./.stylelintrc.yaml"],ue="./stylelint.config.mjs",fi=async()=>{try{return"stylelint"in JSON.parse(await ci("./package.json","utf-8"))}catch{return!1}},mi=async()=>{if(await fi())return"./package.json";for(let t of li)if(await c(t))return t;return null},de=()=>`export { default } from "ultracite/stylelint";
|
|
150
|
+
`,gt={exists:async()=>await mi()!==null,create:async()=>{let t=de();await ge(ue,t)},update:async()=>{let t=de();await ge(ue,t)}};import{readFile as pi,writeFile as he}from"fs/promises";import{glob as gi}from"glob";import{applyEdits as ui,modify as di,parse as hi}from"jsonc-parser";var we=async()=>{try{return await gi("**/tsconfig*.json",{ignore:["**/node_modules/**","**/dist/**","**/build/**","**/.next/**"],absolute:!1})}catch{return[]}},wi=t=>{if(!t)return!1;let e=t.compilerOptions;return e?e.strict===!0||e.strictNullChecks===!0:!1},yi=async t=>{try{let e=await pi(t,"utf-8"),n=hi(e);if(wi(n))return;if(n===void 0){await he(t,JSON.stringify({compilerOptions:{strictNullChecks:!0}},null,2));return}let o=di(e,["compilerOptions","strictNullChecks"],!0,{formattingOptions:{tabSize:2,insertSpaces:!0}}),s=ui(e,o);await he(t,s)}catch(e){console.warn(`Failed to update ${t}:`,e)}},Dt={exists:async()=>(await we()).length>0,update:async()=>{let t=await we();if(t.length===0){console.warn("No tsconfig.json files found in the project");return}await Promise.all(t.map(e=>yi(e)))}};m();var ye=y.devDependencies["@biomejs/biome"],Lt=y.version,$i=async(t,e="biome",n=!0,i=!1)=>{let o=g();i||o.start("Installing dependencies...");let s=[`ultracite@${Lt}`];if(e==="biome"&&s.push(`@biomejs/biome@${ye}`),e==="eslint"&&(s.push("eslint@latest"),s.push("prettier@latest"),s.push("stylelint@latest")),e==="oxlint"&&(s.push("oxlint@latest"),s.push("oxfmt@latest")),n)for(let r of s)await ji(r,{packageManager:t,workspace:await b(),silent:!0});else{let r={ultracite:Lt};e==="biome"&&(r["@biomejs/biome"]=ye),e==="eslint"&&(r.eslint="latest",r.prettier="latest",r.stylelint="latest"),e==="oxlint"&&(r.oxlint="latest",r.oxfmt="latest"),await x({devDependencies:r})}i||o.stop("Dependencies installed.")},Si=async(t=!1)=>{let e=g();if(t||e.start("Checking for tsconfig.json files..."),await Dt.exists()){t||e.message("Found tsconfig.json files, updating with strictNullChecks..."),await Dt.update(),t||e.stop("tsconfig.json files updated.");return}t||e.stop("No tsconfig.json files found, skipping.")},Oi=async(t,e="biome",n=!1)=>{let i=xe.find(r=>r.id===t);if(!i)throw new Error(`Editor "${t}" not found`);let o=Wt(t,e),s=g();if(n||s.start(`Checking for ${i.config.path}...`),await o.exists()){n||s.message(`${i.config.path} found, updating...`),await o.update(),n||s.stop(`${i.config.path} updated.`);return}if(n||s.message(`${i.config.path} not found, creating...`),await o.create(),o.extension){let r=Ei.find(a=>a.id===e)?.vscodeExtensionId;if(!r)throw new Error(`Linter extension not found for ${e}`);n||s.message(`Installing ${r} extension...`);try{if(o.extension(r).status===0){n||s.stop(`${i.config.path} created and ${r} extension installed.`);return}}catch{}n||s.stop(`${i.config.path} created. Install ${r} extension manually.`);return}n||(t==="zed"?s.stop(`${i.config.path} created. Install the Biome extension: https://biomejs.dev/reference/zed/`):s.stop(`${i.config.path} created.`))},vi=async(t,e=!1)=>{let n=g();if(e||n.start("Checking for Biome configuration..."),await rt.exists()){e||n.message("Biome configuration found, updating..."),await rt.update({frameworks:t}),e||n.stop("Biome configuration updated.");return}e||n.message("Biome configuration not found, creating..."),await rt.create({frameworks:t}),e||n.stop("Biome configuration created.")},Ni=async(t,e=!1)=>{let n=g();if(e||n.start("Checking for ESLint configuration..."),await at.exists()){e||n.message("ESLint configuration found, updating..."),await at.update({frameworks:t}),e||n.stop("ESLint configuration updated.");return}e||n.message("ESLint configuration not found, creating..."),await at.create({frameworks:t}),e||n.stop("ESLint configuration created.")},Fi=async(t,e=!1)=>{let n=g();if(e||n.start("Checking for Oxlint configuration..."),await mt.exists()){e||n.message("Oxlint configuration found, updating..."),await mt.update({frameworks:t}),e||n.stop("Oxlint configuration updated.");return}e||n.message("Oxlint configuration not found, creating..."),await mt.create({frameworks:t}),e||n.stop("Oxlint configuration created.")},Ri=async(t=!1)=>{let e=g();if(t||e.start("Checking for Prettier configuration..."),await pt.exists()){t||e.message("Prettier configuration found, updating..."),await pt.update(),t||e.stop("Prettier configuration updated.");return}t||e.message("Prettier configuration not found, creating..."),await pt.create(),t||e.stop("Prettier configuration created.")},Di=async(t=!1)=>{let e=g();if(t||e.start("Checking for Stylelint configuration..."),await gt.exists()){t||e.message("Stylelint configuration found, updating..."),await gt.update(),t||e.stop("Stylelint configuration updated.");return}t||e.message("Stylelint configuration not found, creating..."),await gt.create(),t||e.stop("Stylelint configuration created.")},Li=async(t=!1)=>{let e=g();if(t||e.start("Checking for oxfmt configuration..."),await lt.exists()){t||e.message("oxfmt configuration found, updating..."),await lt.update(),t||e.stop("oxfmt configuration updated.");return}t||e.message("oxfmt configuration not found, creating..."),await lt.create(),t||e.stop("oxfmt configuration created.")},Ai=async(t,e=!0,n=!1)=>{let i=g();if(n||(i.start("Initializing pre-commit hooks..."),i.message("Installing Husky...")),e?await v.install(t):await x({devDependencies:{husky:"latest"},scripts:{prepare:"husky"}}),n||i.message("Initializing Husky..."),v.init(t),await v.exists()){n||i.message("Pre-commit hook found, updating..."),await v.update(t),n||i.stop("Pre-commit hook updated.");return}n||i.message("Pre-commit hook not found, creating..."),await v.create(t),n||i.stop("Pre-commit hook created.")},Ji=async(t,e=!0,n=!1)=>{let i=g();if(n||(i.start("Initializing lefthook..."),i.message("Installing lefthook...")),e?await B.install(t):await x({devDependencies:{lefthook:"latest"}}),await B.exists()){n||i.message("lefthook.yml found, updating..."),await B.update(t),n||i.stop("lefthook.yml updated.");return}n||i.message("lefthook.yml not found, creating..."),await B.create(t),n||i.stop("lefthook.yml created.")},Ti=async(t,e=!0,n=!1)=>{let i=g();if(n||(i.start("Initializing lint-staged..."),i.message("Installing lint-staged...")),e?await W.install(t):await x({devDependencies:{"lint-staged":"latest"}}),await W.exists()){n||i.message("lint-staged found, updating..."),await W.update(t),n||i.stop("lint-staged updated.");return}n||i.message("lint-staged not found, creating..."),await W.create(t),n||i.stop("lint-staged created.")},Ii=async(t,e=!1)=>{let n=g();if(e||n.start("Initializing pre-commit..."),await Y.exists()){e||n.message(".pre-commit-config.yaml found, updating..."),await Y.update(t),e||n.stop(".pre-commit-config.yaml updated.");return}e||n.message(".pre-commit-config.yaml not found, creating..."),await Y.create(t),e||n.stop(".pre-commit-config.yaml created.")},Mi=async(t,e,n,i=!1)=>{let o=g();i||o.start(`Checking for ${e}...`);let s=Bt(t,n);if(await s.exists()){i||o.message(`${e} found, updating...`),await s.update(),i||o.stop(`${e} updated.`);return}i||o.message(`${e} not found, creating...`),await s.create(),i||o.stop(`${e} created.`)},_i=async(t,e,n,i=!1)=>{let o=g();i||o.start(`Checking for ${e} hooks...`);let s=Ut(t,n);if(await s.exists()){i||o.message(`${e} hooks found, updating...`),await s.update(),i||o.stop(`${e} hooks updated.`);return}i||o.message(`${e} hooks not found, creating...`),await s.create(),i||o.stop(`${e} hooks created.`)},ke=async t=>{let e=t??{},n=e.quiet??!1;n||ki(`Ultracite v${Lt} Initialization`);try{let{pm:i}=e;if(!i){let l=await Pi(xi.cwd());if(!l)throw new Error("No package manager specified or detected");if(!n&&l.warnings)for(let u of l.warnings)ut.warn(u);n||ut.info(`Detected lockfile, using ${l.name}`),i=l.name}let o=e.linter;if(o===void 0)if(n||e.pm||e.editors||e.agents||e.hooks||e.integrations!==void 0||e.frameworks!==void 0)o="biome";else{let u=await Ci({message:"Which linter do you want to use?",options:[{label:"Biome (Recommended)",value:"biome"},{label:"ESLint + Prettier + Stylelint",value:"eslint"},{label:"Oxlint + Oxfmt",value:"oxlint"}]});if(z(u)){U("Operation cancelled.");return}o=u}let s=e.frameworks;if(s===void 0)if(n||e.pm||e.editors||e.agents||e.hooks||e.integrations!==void 0)s=[];else{let u=await K({message:"Which frameworks are you using (optional)?",options:[{label:"React",value:"react"},{label:"Next.js",value:"next"},{label:"Solid",value:"solid"},{label:"Vue",value:"vue"},{label:"Svelte",value:"svelte"},{label:"Qwik",value:"qwik"},{label:"Angular",value:"angular"},{label:"Remix / TanStack Router / React Router",value:"remix"},{label:"Astro",value:"astro"}],required:!1});if(z(u)){U("Operation cancelled.");return}s=u}let r=e.editors;if(!r)if(n)r=[];else{let l=await K({message:"Which editors do you want to configure (recommended)?",options:[{label:"VSCode / Cursor / Windsurf",value:"vscode"},{label:"Zed",value:"zed"}],required:!1});if(z(l)){U("Operation cancelled.");return}r=l}let a=e.agents,p=e.hooks,h=Object.fromEntries(bi.map(l=>[l.id,l.name]));if(!a)if(n)a=[];else{let l=await K({message:"Which agents do you want to enable (optional)?",options:Object.entries(h).map(([u,dt])=>({value:u,label:dt})),required:!1});if(z(l)){U("Operation cancelled.");return}a=l}let P=Object.fromEntries(xe.filter(l=>l.hooks).map(l=>[l.id,l.name]));if(!p)if(n)p=[];else{let l=await K({message:"Which agent hooks do you want to enable (optional)?",options:Object.entries(P).map(([u,dt])=>({value:u,label:dt})),required:!1});if(z(l)){U("Operation cancelled.");return}p=l}let $=e.integrations;if($===void 0)if(n||e.pm||e.editors||e.agents||e.hooks)$=[];else{let u=await K({message:"Would you like any of the following (optional)?",options:[{label:"Husky pre-commit hook",value:"husky"},{label:"Lefthook pre-commit hook",value:"lefthook"},{label:"Lint-staged",value:"lint-staged"},{label:"pre-commit (Python framework)",value:"pre-commit"}],required:!1});if(z(u)){U("Operation cancelled.");return}$=u}await $i(i,o,!e.skipInstall,n),await Si(n),o==="biome"&&await vi(s,n),o==="eslint"&&(await Ni(s,n),await Ri(n),await Di(n)),o==="oxlint"&&(await Fi(s,n),await Li(n));for(let l of r??[])await Oi(l,o,n);for(let l of a??[])await Mi(l,h[l],i,n);for(let l of p??[])await _i(l,P[l],i,n);$?.includes("husky")&&await Ai(i,!e.skipInstall,n),$?.includes("lefthook")&&await Ji(i,!e.skipInstall,n),$?.includes("lint-staged")&&await Ti(i,!e.skipInstall,n),$?.includes("pre-commit")&&await Ii(i,n),n||ut.success("Successfully initialized Ultracite configuration!")}catch(i){let o=i instanceof Error?i.message:"Unknown error";throw n||ut.error(`Failed to initialize Ultracite configuration: ${o}`),i}};var V=Bi.meta().create(),zi=V.router({init:V.procedure.meta({description:"Initialize Ultracite in the current directory"}).input(f.object({pm:f.enum(Wi.map(t=>t.name)).optional().describe("Package manager to use"),linter:f.enum(C.linters).optional().describe("Linter / formatter to use"),editors:f.array(f.enum(C.editorConfigs)).optional().describe("Editors to configure"),agents:f.array(f.enum(C.agents)).optional().describe("Agents to enable"),hooks:f.array(f.enum(C.hooks)).optional().describe("Hooks to enable"),frameworks:f.array(f.enum(C.frameworks)).optional().describe("Frameworks being used"),integrations:f.array(f.enum(C.integrations)).optional().describe("Additional integrations to enable"),migrate:f.array(f.enum(C.migrations)).optional().describe("Migration tools to remove (e.g., eslint, prettier). Removes dependencies, config files, and editor settings."),skipInstall:f.boolean().default(!1).describe("Skip installing dependencies"),quiet:f.boolean().default(process.env.CI==="true"||process.env.CI==="1").describe("Suppress all interactive prompts and visual output. Automatically enabled in CI environments.")})).mutation(async({input:t})=>{await ke(t)}),check:V.procedure.meta({description:"Run linter without fixing files"}).input(f.tuple([f.array(f.string()).optional().default([]).describe("specific files to lint"),f.object({"diagnostic-level":f.enum(["info","warn","error"]).optional().describe("level of diagnostics to show. In order, from the lowest to the most important: info, warn, error."),linter:f.enum(C.linters).optional().describe("linter to use (biome, eslint, or oxlint)")})]).optional()).query(async({input:t})=>{await Tt(t)}),fix:V.procedure.meta({description:"Run linter and fix files"}).input(f.tuple([f.array(f.string()).optional().default([]).describe("specific files to format"),f.object({unsafe:f.boolean().optional().describe("apply unsafe fixes"),linter:f.enum(C.linters).optional().describe("linter to use (biome, eslint, or oxlint)")})]).optional()).mutation(async({input:t})=>{let[e,n]=t??[[],{}];await _t(e,{unsafe:n.unsafe,linter:n.linter})}),doctor:V.procedure.meta({description:"Verify your Ultracite setup and check for issues"}).query(async()=>{await Mt()})}),Hi=Ui({router:zi,name:y.name,version:y.version,description:y.description});process.env.TEST||Hi.run();export{zi as router};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ultracite",
|
|
3
3
|
"description": "The AI-ready formatter that helps you write and generate code faster.",
|
|
4
|
-
"version": "
|
|
4
|
+
"version": "7.0.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"ultracite": "dist/index.js"
|
|
@@ -17,6 +17,11 @@
|
|
|
17
17
|
"test:coverage": "bun test --coverage"
|
|
18
18
|
},
|
|
19
19
|
"exports": {
|
|
20
|
+
"./biome/*": "./config/biome/*/biome.jsonc",
|
|
21
|
+
"./eslint/*": "./config/eslint/*/eslint.config.mjs",
|
|
22
|
+
"./oxlint/*": "./config/oxlint/*/.oxlintrc.json",
|
|
23
|
+
"./prettier": "./config/prettier/prettier.config.mjs",
|
|
24
|
+
"./stylelint": "./config/stylelint/stylelint.config.mjs",
|
|
20
25
|
"./*": "./config/*/biome.jsonc"
|
|
21
26
|
},
|
|
22
27
|
"author": "Hayden Bleasel <hello@haydenbleasel.com>",
|
|
@@ -41,21 +46,57 @@
|
|
|
41
46
|
"url": "git+https://github.com/haydenbleasel/ultracite.git"
|
|
42
47
|
},
|
|
43
48
|
"devDependencies": {
|
|
44
|
-
"@biomejs/biome": "
|
|
45
|
-
"@
|
|
46
|
-
"
|
|
47
|
-
"
|
|
49
|
+
"@biomejs/biome": "catalog:",
|
|
50
|
+
"@eslint/js": "^9.39.2",
|
|
51
|
+
"@next/eslint-plugin-next": "^16.1.1",
|
|
52
|
+
"@tanstack/eslint-plugin-query": "^5.91.2",
|
|
53
|
+
"@types/node": "catalog:",
|
|
54
|
+
"@typescript-eslint/eslint-plugin": "^8.51.0",
|
|
55
|
+
"@typescript-eslint/parser": "^8.51.0",
|
|
56
|
+
"eslint-config-prettier": "^10.1.8",
|
|
57
|
+
"eslint-import-resolver-typescript": "^4.4.4",
|
|
58
|
+
"eslint-plugin-angular": "^5.0.0",
|
|
59
|
+
"eslint-plugin-astro": "^1.5.0",
|
|
60
|
+
"eslint-plugin-compat": "^6.0.2",
|
|
61
|
+
"eslint-plugin-cypress": "^5.2.0",
|
|
62
|
+
"eslint-plugin-github": "6.0.0",
|
|
63
|
+
"eslint-plugin-html": "^8.1.3",
|
|
64
|
+
"eslint-plugin-import": "^2.32.0",
|
|
65
|
+
"eslint-plugin-jest": "^29.12.0",
|
|
66
|
+
"eslint-plugin-jsx-a11y": "^6.10.2",
|
|
67
|
+
"eslint-plugin-n": "^17.23.1",
|
|
68
|
+
"eslint-plugin-prettier": "^5.5.4",
|
|
69
|
+
"eslint-plugin-promise": "^7.2.1",
|
|
70
|
+
"eslint-plugin-qwik": "^1.18.0",
|
|
71
|
+
"eslint-plugin-react": "^7.37.5",
|
|
72
|
+
"eslint-plugin-react-hooks": "^7.0.1",
|
|
73
|
+
"eslint-plugin-remix": "^1.1.1",
|
|
74
|
+
"eslint-plugin-solid": "^0.14.5",
|
|
75
|
+
"eslint-plugin-sonarjs": "^3.0.5",
|
|
76
|
+
"eslint-plugin-storybook": "^10.1.11",
|
|
77
|
+
"eslint-plugin-svelte": "^3.13.1",
|
|
78
|
+
"eslint-plugin-tailwindcss": "^3.18.2",
|
|
79
|
+
"eslint-plugin-unicorn": "^62.0.0",
|
|
80
|
+
"eslint-plugin-unused-imports": "^4.3.0",
|
|
81
|
+
"eslint-plugin-vue": "^10.6.2",
|
|
82
|
+
"globals": "^16.5.0",
|
|
83
|
+
"prettier-plugin-tailwindcss": "^0.7.2",
|
|
84
|
+
"stylelint-config-idiomatic-order": "^10.0.0",
|
|
85
|
+
"stylelint-config-standard": "^39.0.1",
|
|
86
|
+
"stylelint-prettier": "^5.0.3",
|
|
87
|
+
"tsup": "^8.5.1"
|
|
48
88
|
},
|
|
49
89
|
"dependencies": {
|
|
50
90
|
"@clack/prompts": "^0.11.0",
|
|
51
|
-
"@trpc/server": "^11.8.
|
|
52
|
-
"
|
|
91
|
+
"@trpc/server": "^11.8.1",
|
|
92
|
+
"@repo/data": "workspace:*",
|
|
93
|
+
"deepmerge": "catalog:",
|
|
53
94
|
"glob": "^13.0.0",
|
|
54
95
|
"jsonc-parser": "^3.3.1",
|
|
55
96
|
"nypm": "^0.6.2",
|
|
56
|
-
"
|
|
97
|
+
"oxlint": "^1.36.0",
|
|
57
98
|
"trpc-cli": "^0.12.1",
|
|
58
|
-
"zod": "
|
|
99
|
+
"zod": "catalog:"
|
|
59
100
|
},
|
|
60
|
-
"packageManager": "bun@1.3.
|
|
101
|
+
"packageManager": "bun@1.3.5"
|
|
61
102
|
}
|