Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,11 @@ jobs:

- run: pnpm install --frozen-lockfile

- run: pnpm run lint
- name: Biome check
run: pnpm run lint

- run: pnpm run typecheck
- name: TypeScript typecheck
run: pnpm run typecheck

- run: pnpm run test
- name: Tests
run: pnpm run test
25 changes: 25 additions & 0 deletions .grit/no-iife.grit
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
engine biome(2.0)
language js(typescript, jsx)

or {
// Match: (function() { ... })() or (function(args) { ... })()
`($func)()` as $match where {
$func <: or {
`function() { $body }`,
`function($args) { $body }`,
`async function() { $body }`,
`async function($args) { $body }`
},
register_diagnostic(span=$match, message="Avoid using IIFEs. Consider extracting to a helper function.", severity="error")
},
// Match: (() => { ... })() or ((args) => { ... })()
`($arrow)()` as $match where {
$arrow <: or {
`() => $body`,
`($args) => $body`,
`async () => $body`,
`async ($args) => $body`
},
register_diagnostic(span=$match, message="Avoid using IIFEs. Consider extracting to a helper function.", severity="error")
}
}
24 changes: 24 additions & 0 deletions .grit/prefer-nullish-over-optional-nullable.grit
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Pattern: Detect .optional().nullable() or .nullable().optional() on zod schemas
// These should be replaced with .nullish() for better clarity and correctness
// Matches both direct chains and chains with other method calls in between
// Only matches expressions that start with z. to ensure we're targeting zod schemas

engine biome(2.0)
language js(typescript, jsx)

or {
// Direct chains starting from a zod constructor
`z.$fn($...).nullable().optional()` as $match where {
register_diagnostic(span=$match, message="Use .nullish() instead of .nullable().optional(). The .nullish() method is equivalent and more concise.", severity="error")
},
`z.$fn($...).optional().nullable()` as $match where {
register_diagnostic(span=$match, message="Use .nullish() instead of .optional().nullable(). The .nullish() method is equivalent and more concise.", severity="error")
},
// Allow one method in between (covers common cases like .default(), .array(), .openapi(), etc.)
`z.$fn($...).$mid.nullable().optional()` as $match where {
register_diagnostic(span=$match, message="Use .nullish() instead of .nullable().optional() with extra chaining. The .nullish() method is equivalent and more concise.", severity="error")
},
`z.$fn($...).$mid.optional().nullable()` as $match where {
register_diagnostic(span=$match, message="Use .nullish() instead of .optional().nullable() with extra chaining. The .nullish() method is equivalent and more concise.", severity="error")
}
}
45 changes: 45 additions & 0 deletions .grit/use-named-arguments.grit
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
engine biome(2.0)
language js(typescript, jsx)

or {
// Function declarations
`function $name($a, $b, $c, $d, $...) { $body }` as $match where {
register_diagnostic(span=$match, message="Functions with more than 3 parameters should use named arguments with object destructuring", severity="error")
},
// Function declarations with return type
`function $name($a, $b, $c, $d, $...): $ret { $body }` as $match where {
register_diagnostic(span=$match, message="Functions with more than 3 parameters should use named arguments with object destructuring", severity="error")
},
// Async function declarations
`async function $name($a, $b, $c, $d, $...) { $body }` as $match where {
register_diagnostic(span=$match, message="Functions with more than 3 parameters should use named arguments with object destructuring", severity="error")
},
// Async function declarations with return type
`async function $name($a, $b, $c, $d, $...): $ret { $body }` as $match where {
register_diagnostic(span=$match, message="Functions with more than 3 parameters should use named arguments with object destructuring", severity="error")
},
// Function expressions
`function($a, $b, $c, $d, $...) { $body }` as $match where {
register_diagnostic(span=$match, message="Functions with more than 3 parameters should use named arguments with object destructuring", severity="error")
},
// Function expressions with return type
`function($a, $b, $c, $d, $...): $ret { $body }` as $match where {
register_diagnostic(span=$match, message="Functions with more than 3 parameters should use named arguments with object destructuring", severity="error")
},
// Async function expressions
`async function($a, $b, $c, $d, $...) { $body }` as $match where {
register_diagnostic(span=$match, message="Functions with more than 3 parameters should use named arguments with object destructuring", severity="error")
},
// Async function expressions with return type
`async function($a, $b, $c, $d, $...): $ret { $body }` as $match where {
register_diagnostic(span=$match, message="Functions with more than 3 parameters should use named arguments with object destructuring", severity="error")
},
// Arrow functions
`($a, $b, $c, $d, $...) => $body` as $match where {
register_diagnostic(span=$match, message="Functions with more than 3 parameters should use named arguments with object destructuring", severity="error")
},
// Arrow functions with return type
`($a, $b, $c, $d, $...): $ret => $body` as $match where {
register_diagnostic(span=$match, message="Functions with more than 3 parameters should use named arguments with object destructuring", severity="error")
}
}
136 changes: 136 additions & 0 deletions biome.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
{
"$schema": "https://biomejs.dev/schemas/2.4.8/schema.json",
"vcs": {
"enabled": true,
"clientKind": "git",
"useIgnoreFile": true,
"defaultBranch": "origin/main"
},
"plugins": [
".grit/no-iife.grit",
".grit/use-named-arguments.grit",
".grit/prefer-nullish-over-optional-nullable.grit"
],
"files": {
"ignoreUnknown": false,
"includes": [
"**",
"!**/*.json",
"!!**/biome.json",
"!esm/**"
]
},
"formatter": {
"enabled": true,
"indentStyle": "space",
"indentWidth": 2,
"lineWidth": 100,
"expand": "always",
"attributePosition": "multiline"
},
"assist": {
"actions": {
"source": {
"organizeImports": {
"level": "on"
}
}
}
},
"linter": {
"enabled": true,
"rules": {
"recommended": true,
"complexity": {
"useLiteralKeys": "off",
"noExtraBooleanCast": "off",
"noForEach": "off",
"noBannedTypes": "error",
"noUselessSwitchCase": "off"
},
"style": {
"noNonNullAssertion": "off",
"useNodejsImportProtocol": "error",
"useTemplate": "off",
"useBlockStatements": "error",
"noParameterAssign": "error",
"useConst": "error",
"useAsConstAssertion": "error",
"useDefaultParameterLast": "error",
"useEnumInitializers": "error",
"useSelfClosingElements": "error",
"useSingleVarDeclarator": "error",
"noUnusedTemplateLiteral": "error",
"useNumberNamespace": "error",
"noInferrableTypes": "error",
"noUselessElse": "error",
"useImportType": {
"level": "on",
"options": {
"style": "separatedType"
}
}
},
"correctness": {
"noUnusedImports": "error",
"useExhaustiveDependencies": "off",
"noInnerDeclarations": "error",
"useParseIntRadix": "error"
},
"suspicious": {
"noExplicitAny": "off",
"noAssignInExpressions": "error",
"noAsyncPromiseExecutor": "off",
"noFallthroughSwitchClause": "error",
"noConsole": "off",
"noDoubleEquals": {
"level": "error",
"options": {
"ignoreNull": false
}
},
"noExtraNonNullAssertion": "error"
},
"performance": {
"recommended": true,
"noAccumulatingSpread": "error"
},
"security": {
"recommended": true
}
}
},
"javascript": {
"formatter": {
"expand": "always",
"lineWidth": 100,
"arrowParentheses": "always",
"quoteProperties": "asNeeded",
"trailingCommas": "all",
"semicolons": "always",
"bracketSpacing": true,
"bracketSameLine": false,
"quoteStyle": "single",
"enabled": true
}
},
"overrides": [
{
"includes": [
"tests/**",
"**/*.test.ts",
"**/*.spec.ts"
],
"linter": {
"rules": {
"suspicious": {
"noExplicitAny": "off"
},
"correctness": {
"useYield": "off"
}
}
}
}
]
}
29 changes: 0 additions & 29 deletions eslint.config.mjs

This file was deleted.

8 changes: 3 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,8 @@
"LICENSE"
],
"scripts": {
"lint": "eslint --cache --max-warnings=0 src",
"lint": "biome check src tests",
"lint:fix": "biome check --write src tests",
"build": "tsc",
"test": "vitest --run --project unit",
"test:e2e": "vitest --run --project e2e",
Expand All @@ -117,15 +118,12 @@
"zod": "^4.0.0"
},
"devDependencies": {
"@biomejs/biome": "^2.4.10",
"@changesets/changelog-github": "^0.6.0",
"@changesets/cli": "^2.30.0",
"@eslint/js": "^9.19.0",
"@types/node": "^22.13.12",
"dotenv": "^16.4.7",
"eslint": "^9.19.0",
"globals": "^15.14.0",
"typescript": "~5.8.3",
"typescript-eslint": "^8.26.0",
"vitest": "^3.2.4"
},
"pnpm": {
Expand Down
Loading
Loading