Skip to content
Open
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
5 changes: 5 additions & 0 deletions .changeset/gentle-cases-allow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@tanstack/oxlint-config': minor
---

Release @tanstack/oxlint-config
6 changes: 6 additions & 0 deletions packages/oxlint-config/oxlint.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { defineConfig } from 'oxlint'
import { tanstackConfig } from '@tanstack/oxlint-config'

export default defineConfig({
extends: [tanstackConfig],
})
50 changes: 50 additions & 0 deletions packages/oxlint-config/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
{
"name": "@tanstack/oxlint-config",
"version": "0.1.0",
"description": "Oxlint config based on @tanstack/eslint-config",
"author": "tannerlinsley",
"license": "MIT",
"repository": {
"type": "git",
"url": "git+https://github.com/TanStack/config.git",
"directory": "packages/oxlint-config"
},
"homepage": "https://tanstack.com/config",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/tannerlinsley"
},
"scripts": {
"test:types": "tsc",
"test:eslint": "oxlint ./src",
"build": "tsdown"
},
"type": "module",
"types": "./dist/index.d.ts",
"exports": {
".": "./src/index.ts",
"./package.json": "./package.json"
},
"publishConfig": {
"exports": {
".": "./dist/index.js",
"./package.json": "./package.json"
}
},
"preferGlobal": false,
"sideEffects": false,
"files": [
"dist",
"src"
],
"engines": {
"node": ">=18"
},
"dependencies": {
"@stylistic/eslint-plugin": "catalog:",
"oxlint": "catalog:"
},
"peerDependencies": {
"oxlint": "^1.0.0"
}
}
37 changes: 37 additions & 0 deletions packages/oxlint-config/src/import.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import type { OxlintConfig } from 'oxlint'

export const importConfig: OxlintConfig = {
plugins: ['import'],
rules: {
/** Bans the use of inline type-only markers for named imports */
'import/consistent-type-specifier-style': ['error', 'prefer-top-level'],
/** Reports any imports that come after non-import statements */
'import/first': 'error',

/** Stylistic preference */
// 'import/newline-after-import': 'error', // No implementation yet / unsupported

/** No require() or module.exports */
'import/no-commonjs': 'error',
/** Reports if a resolved path is imported more than once */
'import/no-duplicates': 'error',

/** Stylistic preference */
// // No implementation yet / unsupported
// 'import/order': [
// 'error',
// {
// groups: [
// 'builtin',
// 'external',
// 'internal',
// 'parent',
// 'sibling',
// 'index',
// 'object',
// 'type',
// ],
// },
// ],
},
}
33 changes: 33 additions & 0 deletions packages/oxlint-config/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import type { OxlintConfig } from 'oxlint'
import { defineConfig } from 'oxlint'
import { javascriptConfig } from './javascript.ts'
import { importConfig } from './import.ts'
import { typescriptConfig } from './typescript.ts'
import { nodeConfig } from './node.ts'
import { stylisticConfig } from './stylistic.ts'

const GLOB_EXCLUDE = [
'**/.nx/**',
'**/.svelte-kit/**',
'**/build/**',
'**/coverage/**',
'**/dist/**',
'**/snap/**',
'**/vite.config.*.timestamp-*.*',
]

export const tanstackConfig: OxlintConfig = defineConfig({
extends: [
javascriptConfig,
typescriptConfig,
importConfig,
nodeConfig,
stylisticConfig,
],
env: {
builtin: true,
es2020: true,
browser: true,
},
ignorePatterns: GLOB_EXCLUDE,
})
56 changes: 56 additions & 0 deletions packages/oxlint-config/src/javascript.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import type { OxlintConfig } from 'oxlint'

export const javascriptConfig: OxlintConfig = {
rules: {
/** TODO */
'for-direction': 'error',
'no-async-promise-executor': 'error',
'no-case-declarations': 'error',
'no-class-assign': 'error',
'no-compare-neg-zero': 'error',
'no-cond-assign': 'error',
'no-constant-binary-expression': 'error',
'no-constant-condition': 'error',
'no-control-regex': 'error',
'no-debugger': 'error',
'no-delete-var': 'error',
'no-dupe-else-if': 'error',
'no-duplicate-case': 'error',
'no-empty-character-class': 'error',
'no-empty-pattern': 'error',
'no-empty-static-block': 'error',
'no-ex-assign': 'error',
'no-extra-boolean-cast': 'error',
'no-fallthrough': 'error',
'no-global-assign': 'error',
'no-invalid-regexp': 'error',
'no-irregular-whitespace': 'error',
'no-loss-of-precision': 'error',
'no-misleading-character-class': 'error',
'no-nonoctal-decimal-escape': 'error',
'no-regex-spaces': 'error',
'no-self-assign': 'error',
/** Warn about variable with identical names in the outer scope */
// 'no-shadow': 'warn', // No implementation yet
'no-shadow-restricted-names': 'error',
'no-sparse-arrays': 'error',
'no-unsafe-finally': 'error',
'no-unsafe-optional-chaining': 'error',
'no-unused-labels': 'error',
'no-unused-private-class-members': 'error',
'no-useless-backreference': 'error',
'no-useless-catch': 'error',
'no-useless-escape': 'error',
/** Prefer let and const */
'no-var': 'error',
'no-with': 'error',
/** Prefer const if never re-assigned */
'prefer-const': 'error',
'require-yield': 'error',
/** Stylistic consistency */
'sort-imports': ['error', { ignoreDeclarationSort: true }],
'use-isnan': 'error',
/** Enforce comparing typeof against valid strings */
'valid-typeof': 'error',
},
}
9 changes: 9 additions & 0 deletions packages/oxlint-config/src/node.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import type { OxlintConfig } from 'oxlint'

export const nodeConfig: OxlintConfig = {
plugins: ['unicorn'],
rules: {
/** Enforce usage of the `node:` prefix for builtin imports */
'unicorn/prefer-node-protocol': 'error',
},
}
9 changes: 9 additions & 0 deletions packages/oxlint-config/src/stylistic.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import type { OxlintConfig } from 'oxlint'

export const stylisticConfig: OxlintConfig = {
jsPlugins: [{ name: '@stylistic', specifier: '@stylistic/eslint-plugin' }],
rules: {
/** Enforce consistency of spacing after the start of a comment */
'@stylistic/spaced-comment': 'error',
},
}
84 changes: 84 additions & 0 deletions packages/oxlint-config/src/typescript.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import type { OxlintConfig } from 'oxlint'

export const typescriptConfig: OxlintConfig = {
plugins: ['typescript'],
rules: {
/** Prefer Array<T> format */
'@typescript-eslint/array-type': [
'error',
{ default: 'generic', readonly: 'generic' },
],
/** Prevent @ts-ignore, allow @ts-expect-error */
'@typescript-eslint/ban-ts-comment': [
'error',
{
'ts-expect-error': false,
'ts-ignore': 'allow-with-description',
},
],
/** Enforce import type { T } */
'@typescript-eslint/consistent-type-imports': [
'error',
{ prefer: 'type-imports' },
],
/** Shorthand method style is less strict */
// '@typescript-eslint/method-signature-style': ['error', 'property'], // No implemented yet

/** Enforces generic type convention */
// // Not implemented yet
// '@typescript-eslint/naming-convention': [
// 'error',
// {
// selector: 'typeParameter',
// format: ['PascalCase'],
// leadingUnderscore: 'forbid',
// trailingUnderscore: 'forbid',
// custom: {
// regex: '^(T|T[A-Z][A-Za-z]+)$',
// match: true,
// },
// },
// ],

/** Duplicate values can lead to bugs that are hard to track down */
'@typescript-eslint/no-duplicate-enum-values': 'error',
/** Using the operator any more than once does nothing */
'@typescript-eslint/no-extra-non-null-assertion': 'error',

/** There are several potential bugs with this compared to other loops */
// '@typescript-eslint/no-for-in-array': 'error', // Requires TypeScript-native (tsgo)

/** Don't over-define types for simple things like strings */
'@typescript-eslint/no-inferrable-types': [
'error',
{ ignoreParameters: true },
],
/** Enforce valid definition of new and constructor */
'@typescript-eslint/no-misused-new': 'error',
/** Disallow TypeScript namespaces */
'@typescript-eslint/no-namespace': 'error',
/** Disallow non-null assertions after an optional chain expression */
'@typescript-eslint/no-non-null-asserted-optional-chain': 'error',

/** Detects conditionals which will always evaluate truthy or falsy */
// '@typescript-eslint/no-unnecessary-condition': 'error', // Not implemented yet / unsupported

/** Checks if the the explicit type is identical to the inferred type */
// '@typescript-eslint/no-unnecessary-type-assertion': 'error', // Requires TypeScript-native (tsgo)

/** Disallow using the unsafe built-in Function type */
'@typescript-eslint/no-unsafe-function-type': 'error',
/** Disallow using confusing built-in primitive class wrappers */
'@typescript-eslint/no-wrapper-object-types': 'error',
/** Enforce the use of as const over literal type */
'@typescript-eslint/prefer-as-const': 'error',
/** Prefer for-of loop over the standard for loop */
'@typescript-eslint/prefer-for-of': 'warn',

/** Warn about async functions which have no await expression */
// '@typescript-eslint/require-await': 'warn', // Requires TypeScript-native (tsgo)

/** Prefer of ES6-style import declarations */
'@typescript-eslint/triple-slash-reference': 'error',
},
}
8 changes: 8 additions & 0 deletions packages/oxlint-config/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"allowImportingTsExtensions": true,
"isolatedDeclarations": true
},
"include": ["src"]
}
23 changes: 23 additions & 0 deletions packages/oxlint-config/tsdown.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { defineConfig } from 'tsdown'

export default defineConfig({
entry: ['./src/index.ts'],
format: ['esm'],
platform: 'node',
unbundle: true,
dts: true,
sourcemap: true,
clean: true,
minify: false,
fixedExtension: false,
exports: {
devExports: true,
},
publint: {
strict: true,
},
attw: {
profile: 'esm-only',
level: 'error',
},
})
Loading