Migrate to Oxlint (#10384)
Co-authored-by: DS Boyce <260543580+ds-boyce@users.noreply.github.com>
This commit is contained in:
+2
-2
@@ -108,8 +108,8 @@ google-services.json
|
||||
# Performance results (Flashlight)
|
||||
.perf/
|
||||
|
||||
# ESLint
|
||||
.eslintcache
|
||||
# Oxlint
|
||||
.oxlintcache
|
||||
|
||||
# i18n
|
||||
src/locale/locales/_build/
|
||||
|
||||
+407
@@ -0,0 +1,407 @@
|
||||
{
|
||||
"$schema": "./node_modules/oxlint/configuration_schema.json",
|
||||
"plugins": [
|
||||
"typescript",
|
||||
"react",
|
||||
"import"
|
||||
],
|
||||
"categories": {
|
||||
"correctness": "off"
|
||||
},
|
||||
"options": {
|
||||
"typeAware": true
|
||||
},
|
||||
"env": {
|
||||
"builtin": true
|
||||
},
|
||||
"settings": {
|
||||
"import-x/extensions": [
|
||||
".ts",
|
||||
".tsx",
|
||||
".cts",
|
||||
".mts",
|
||||
".js",
|
||||
".jsx",
|
||||
".cjs",
|
||||
".mjs"
|
||||
],
|
||||
"import-x/external-module-folders": [
|
||||
"node_modules",
|
||||
"node_modules/@types"
|
||||
],
|
||||
"import-x/parsers": {
|
||||
"@typescript-eslint/parser": [
|
||||
".ts",
|
||||
".tsx",
|
||||
".cts",
|
||||
".mts"
|
||||
]
|
||||
},
|
||||
"import-x/resolver": {
|
||||
"node": {
|
||||
"extensions": [
|
||||
".js",
|
||||
".web.js",
|
||||
".ios.js",
|
||||
".android.js"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"ignorePatterns": [
|
||||
"**/__mocks__/*.ts",
|
||||
"ios/**",
|
||||
"android/**",
|
||||
"coverage/**",
|
||||
"*.lock",
|
||||
".husky/**",
|
||||
"patches/**",
|
||||
"*.html",
|
||||
"bskyweb/**",
|
||||
"bskyembed/**",
|
||||
"bskyogcard/**",
|
||||
"src/locale/locales/_build/**",
|
||||
"src/locale/locales/**/*.js",
|
||||
"*.e2e.ts",
|
||||
"*.e2e.tsx",
|
||||
"eslint.config.mjs",
|
||||
".jscodeshift/**"
|
||||
],
|
||||
"rules": {
|
||||
"constructor-super": "error",
|
||||
"for-direction": "error",
|
||||
"getter-return": "error",
|
||||
"no-async-promise-executor": "error",
|
||||
"no-case-declarations": "error",
|
||||
"no-class-assign": "error",
|
||||
"no-compare-neg-zero": "error",
|
||||
"no-cond-assign": "error",
|
||||
"no-const-assign": "error",
|
||||
"no-constant-binary-expression": "error",
|
||||
"no-constant-condition": "error",
|
||||
"no-control-regex": "error",
|
||||
"no-debugger": "error",
|
||||
"no-delete-var": "error",
|
||||
"no-dupe-class-members": "error",
|
||||
"no-dupe-else-if": "error",
|
||||
"no-dupe-keys": "error",
|
||||
"no-duplicate-case": "error",
|
||||
"no-empty": "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-func-assign": "error",
|
||||
"no-global-assign": "error",
|
||||
"no-import-assign": "error",
|
||||
"no-invalid-regexp": "error",
|
||||
"no-irregular-whitespace": "error",
|
||||
"no-loss-of-precision": "error",
|
||||
"no-misleading-character-class": "error",
|
||||
"no-new-native-nonconstructor": "error",
|
||||
"no-nonoctal-decimal-escape": "error",
|
||||
"no-obj-calls": "error",
|
||||
"no-prototype-builtins": "error",
|
||||
"no-redeclare": "error",
|
||||
"no-regex-spaces": "error",
|
||||
"no-self-assign": "error",
|
||||
"no-setter-return": "error",
|
||||
"no-shadow-restricted-names": "error",
|
||||
"no-sparse-arrays": "error",
|
||||
"no-this-before-super": "error",
|
||||
"no-unexpected-multiline": "error",
|
||||
"no-unreachable": "error",
|
||||
"no-unsafe-finally": "error",
|
||||
"no-unsafe-negation": "error",
|
||||
"no-unsafe-optional-chaining": "error",
|
||||
"no-unused-labels": "error",
|
||||
"no-unused-private-class-members": "error",
|
||||
"no-unused-vars": "error",
|
||||
"no-useless-backreference": "error",
|
||||
"no-useless-catch": "error",
|
||||
"no-useless-escape": "error",
|
||||
"no-with": "error",
|
||||
"require-yield": "error",
|
||||
"use-isnan": "error",
|
||||
"valid-typeof": "error",
|
||||
"no-array-constructor": "error",
|
||||
"no-unused-expressions": "error",
|
||||
"import/namespace": "off",
|
||||
"import/default": "error",
|
||||
"import/no-named-as-default": "warn",
|
||||
"import/no-named-as-default-member": "warn",
|
||||
"import/no-duplicates": "warn",
|
||||
"react/rules-of-hooks": "error",
|
||||
"react/exhaustive-deps": "warn",
|
||||
"typescript/await-thenable": "error",
|
||||
"typescript/ban-ts-comment": "error",
|
||||
"typescript/no-array-delete": "error",
|
||||
"typescript/no-base-to-string": "error",
|
||||
"typescript/no-duplicate-enum-values": "error",
|
||||
"typescript/no-duplicate-type-constituents": "error",
|
||||
"typescript/no-empty-object-type": "error",
|
||||
"typescript/no-explicit-any": "error",
|
||||
"typescript/no-extra-non-null-assertion": "error",
|
||||
"typescript/no-floating-promises": "error",
|
||||
"typescript/no-for-in-array": "error",
|
||||
"typescript/no-implied-eval": "error",
|
||||
"typescript/no-misused-new": "error",
|
||||
"typescript/no-misused-promises": "error",
|
||||
"typescript/no-namespace": "error",
|
||||
"typescript/no-non-null-asserted-optional-chain": "error",
|
||||
"typescript/no-redundant-type-constituents": "error",
|
||||
"typescript/no-require-imports": "error",
|
||||
"typescript/no-this-alias": "error",
|
||||
"typescript/no-unnecessary-type-assertion": "error",
|
||||
"typescript/no-unnecessary-type-constraint": "error",
|
||||
"typescript/no-unsafe-argument": "error",
|
||||
"typescript/no-unsafe-assignment": "error",
|
||||
"typescript/no-unsafe-call": "error",
|
||||
"typescript/no-unsafe-declaration-merging": "error",
|
||||
"typescript/no-unsafe-enum-comparison": "error",
|
||||
"typescript/no-unsafe-function-type": "error",
|
||||
"typescript/no-unsafe-member-access": "error",
|
||||
"typescript/no-unsafe-return": "error",
|
||||
"typescript/no-unsafe-unary-minus": "error",
|
||||
"typescript/no-wrapper-object-types": "error",
|
||||
"typescript/only-throw-error": "error",
|
||||
"typescript/prefer-as-const": "error",
|
||||
"typescript/prefer-namespace-keyword": "error",
|
||||
"typescript/prefer-promise-reject-errors": "error",
|
||||
"typescript/require-await": "error",
|
||||
"typescript/restrict-plus-operands": "error",
|
||||
"typescript/restrict-template-expressions": "error",
|
||||
"typescript/triple-slash-reference": "error",
|
||||
"typescript/unbound-method": "error"
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"files": [
|
||||
"**/*.ts",
|
||||
"**/*.tsx",
|
||||
"**/*.mts",
|
||||
"**/*.cts"
|
||||
],
|
||||
"rules": {
|
||||
"constructor-super": "off",
|
||||
"getter-return": "off",
|
||||
"no-class-assign": "off",
|
||||
"no-const-assign": "off",
|
||||
"no-dupe-class-members": "off",
|
||||
"no-dupe-keys": "off",
|
||||
"no-func-assign": "off",
|
||||
"no-import-assign": "off",
|
||||
"no-new-native-nonconstructor": "off",
|
||||
"no-obj-calls": "off",
|
||||
"no-redeclare": "off",
|
||||
"no-setter-return": "off",
|
||||
"no-this-before-super": "off",
|
||||
"no-unreachable": "off",
|
||||
"no-unsafe-negation": "off",
|
||||
"no-var": "error",
|
||||
"no-with": "off",
|
||||
"prefer-const": "error",
|
||||
"prefer-rest-params": "error",
|
||||
"prefer-spread": "error"
|
||||
}
|
||||
},
|
||||
{
|
||||
"files": [
|
||||
"**/*.{js,jsx,ts,tsx}"
|
||||
],
|
||||
"rules": {
|
||||
"bsky-internal/avoid-unwrapped-text": [
|
||||
"error",
|
||||
{
|
||||
"impliedTextComponents": [
|
||||
"H1",
|
||||
"H2",
|
||||
"H3",
|
||||
"H4",
|
||||
"H5",
|
||||
"H6",
|
||||
"P",
|
||||
"Admonition",
|
||||
"Admonition.Admonition",
|
||||
"Toast.Action",
|
||||
"AgeAssuranceAdmonition",
|
||||
"Span",
|
||||
"StackedButton"
|
||||
],
|
||||
"impliedTextProps": [],
|
||||
"suggestedTextWrappers": {
|
||||
"Button": "ButtonText",
|
||||
"ToggleButton.Button": "ToggleButton.ButtonText",
|
||||
"SegmentedControl.Item": "SegmentedControl.ItemText"
|
||||
}
|
||||
}
|
||||
],
|
||||
"bsky-internal/use-exact-imports": "error",
|
||||
"bsky-internal/use-prefixed-imports": "error",
|
||||
"bsky-internal/lingui-msg-rule": "error",
|
||||
"react/display-name": "error",
|
||||
"react/jsx-key": "error",
|
||||
"react/jsx-no-comment-textnodes": "error",
|
||||
"react/jsx-no-duplicate-props": "error",
|
||||
"react/jsx-no-target-blank": "error",
|
||||
"react/jsx-no-undef": "error",
|
||||
"react/no-children-prop": "error",
|
||||
"react/no-danger-with-children": "error",
|
||||
"react/no-direct-mutation-state": "error",
|
||||
"react/no-find-dom-node": "error",
|
||||
"react/no-is-mounted": "error",
|
||||
"react/no-render-return-value": "error",
|
||||
"react/no-string-refs": "error",
|
||||
"react/no-unescaped-entities": "off",
|
||||
"react/no-unknown-property": "error",
|
||||
"react/no-unsafe": "off",
|
||||
"react/react-in-jsx-scope": "off",
|
||||
"react/hook-use-state": "warn",
|
||||
"react-native/no-inline-styles": "off",
|
||||
"react-native-a11y/has-accessibility-hint": "error",
|
||||
"react-native-a11y/has-accessibility-props": "error",
|
||||
"react-native-a11y/has-valid-accessibility-actions": "error",
|
||||
"react-native-a11y/has-valid-accessibility-component-type": "error",
|
||||
"react-native-a11y/has-valid-accessibility-descriptors": "error",
|
||||
"react-native-a11y/has-valid-accessibility-role": "error",
|
||||
"react-native-a11y/has-valid-accessibility-state": "error",
|
||||
"react-native-a11y/has-valid-accessibility-states": "error",
|
||||
"react-native-a11y/has-valid-accessibility-traits": "error",
|
||||
"react-native-a11y/has-valid-accessibility-value": "error",
|
||||
"react-native-a11y/no-nested-touchables": "error",
|
||||
"react-native-a11y/has-valid-accessibility-ignores-invert-colors": "error",
|
||||
"react-native-a11y/has-valid-accessibility-live-region": "error",
|
||||
"react-native-a11y/has-valid-important-for-accessibility": "error",
|
||||
"react-compiler/react-compiler": "warn",
|
||||
"simple-import-sort/imports": [
|
||||
"error",
|
||||
{
|
||||
"groups": [
|
||||
[
|
||||
"^\\u0000"
|
||||
],
|
||||
[
|
||||
"^node:"
|
||||
],
|
||||
[
|
||||
"^(react\\/(.*)$)|^(react$)|^(react-native(.*)$)",
|
||||
"^(expo(.*)$)|^(expo$)",
|
||||
"^(?!(?:alf|components|lib|locale|logger|platform|screens|state|view)(?:$|\\/))@?\\w"
|
||||
],
|
||||
[
|
||||
"^(?:#\\/)?(?:lib|state|logger|platform|locale)(?:$|\\/)",
|
||||
"^(?:#\\/)?view(?:$|\\/)",
|
||||
"^(?:#\\/)?screens(?:$|\\/)",
|
||||
"^(?:#\\/)?alf(?:$|\\/)",
|
||||
"^(?:#\\/)?components(?:$|\\/)",
|
||||
"^#\\/",
|
||||
"^\\."
|
||||
],
|
||||
[
|
||||
"^"
|
||||
]
|
||||
]
|
||||
}
|
||||
],
|
||||
"simple-import-sort/exports": "error",
|
||||
"no-unused-vars": [
|
||||
"error",
|
||||
{
|
||||
"argsIgnorePattern": "^_",
|
||||
"varsIgnorePattern": "^_.+",
|
||||
"caughtErrors": "none",
|
||||
"ignoreRestSiblings": true
|
||||
}
|
||||
],
|
||||
"no-restricted-imports": [
|
||||
"error",
|
||||
{
|
||||
"paths": [
|
||||
{
|
||||
"name": "react",
|
||||
"importNames": [
|
||||
"React",
|
||||
"default"
|
||||
],
|
||||
"message": "React is already in the global type namespace. Use named imports for runtime modules."
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"no-empty-pattern": "off",
|
||||
"no-async-promise-executor": "off",
|
||||
"no-constant-binary-expression": "warn",
|
||||
"prefer-const": "off",
|
||||
"no-empty": "off",
|
||||
"no-unsafe-optional-chaining": "off",
|
||||
"no-prototype-builtins": "off",
|
||||
"no-var": "off",
|
||||
"prefer-rest-params": "off",
|
||||
"no-case-declarations": "off",
|
||||
"no-irregular-whitespace": "off",
|
||||
"no-useless-escape": "off",
|
||||
"no-sparse-arrays": "off",
|
||||
"no-fallthrough": "off",
|
||||
"no-control-regex": "off",
|
||||
"no-unused-expressions": [
|
||||
"error",
|
||||
{
|
||||
"allowTernary": true
|
||||
}
|
||||
],
|
||||
"import/consistent-type-specifier-style": [
|
||||
"warn",
|
||||
"prefer-inline"
|
||||
],
|
||||
"import/no-nodejs-modules": "error",
|
||||
"typescript/consistent-type-imports": [
|
||||
"warn",
|
||||
{
|
||||
"prefer": "type-imports",
|
||||
"fixStyle": "inline-type-imports"
|
||||
}
|
||||
],
|
||||
"typescript/no-require-imports": "off",
|
||||
"typescript/ban-ts-comment": "off",
|
||||
"typescript/no-empty-object-type": "off",
|
||||
"typescript/no-unsafe-function-type": "off",
|
||||
"typescript/no-unsafe-assignment": "off",
|
||||
"typescript/unbound-method": "off",
|
||||
"typescript/no-unsafe-argument": "off",
|
||||
"typescript/no-unsafe-return": "off"
|
||||
},
|
||||
"jsPlugins": [
|
||||
"eslint-plugin-bsky-internal",
|
||||
"eslint-plugin-react-native",
|
||||
"eslint-plugin-react-native-a11y",
|
||||
"eslint-plugin-react-compiler",
|
||||
"eslint-plugin-simple-import-sort"
|
||||
],
|
||||
"env": {
|
||||
"es2026": true,
|
||||
"browser": true,
|
||||
"node": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"files": [
|
||||
"bskyogcard/**/*.{js,jsx,ts,tsx}",
|
||||
"dev-env/**/*.{js,jsx,ts,tsx}"
|
||||
],
|
||||
"rules": {
|
||||
"import/no-nodejs-modules": "off"
|
||||
}
|
||||
},
|
||||
{
|
||||
"files": [
|
||||
"**/__tests__/**/*.{js,jsx,ts,tsx}",
|
||||
"**/*.test.{js,jsx,ts,tsx}"
|
||||
],
|
||||
"env": {
|
||||
"jest": true
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -30,7 +30,7 @@ pnpm ios # Run on iOS
|
||||
# Testing & Quality
|
||||
# IMPORTANT: Always use these pnpm scripts, never call the underlying tools directly
|
||||
pnpm test # Run Jest tests
|
||||
pnpm lint # Run ESLint
|
||||
pnpm lint # Run Oxlint
|
||||
pnpm typecheck # Run TypeScript type checking
|
||||
pnpm prettier # Run Prettier for code formatting
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,319 +0,0 @@
|
||||
// @ts-check
|
||||
import js from '@eslint/js'
|
||||
import tseslint from 'typescript-eslint'
|
||||
import {defineConfig} from 'eslint/config'
|
||||
import react from 'eslint-plugin-react'
|
||||
import reactHooks from 'eslint-plugin-react-hooks'
|
||||
// @ts-expect-error no types
|
||||
import reactNative from 'eslint-plugin-react-native'
|
||||
// @ts-expect-error no types
|
||||
import reactNativeA11y from 'eslint-plugin-react-native-a11y'
|
||||
import simpleImportSort from 'eslint-plugin-simple-import-sort'
|
||||
import importX from 'eslint-plugin-import-x'
|
||||
import lingui from 'eslint-plugin-lingui'
|
||||
import reactCompiler from 'eslint-plugin-react-compiler'
|
||||
import bskyInternal from 'eslint-plugin-bsky-internal'
|
||||
import globals from 'globals'
|
||||
import tsParser from '@typescript-eslint/parser'
|
||||
|
||||
export default defineConfig(
|
||||
/**
|
||||
* Global ignores
|
||||
*/
|
||||
{
|
||||
ignores: [
|
||||
'**/__mocks__/*.ts',
|
||||
'ios/**',
|
||||
'android/**',
|
||||
'coverage/**',
|
||||
'*.lock',
|
||||
'.husky/**',
|
||||
'patches/**',
|
||||
'*.html',
|
||||
'bskyweb/**',
|
||||
'bskyembed/**',
|
||||
'bskyogcard/**',
|
||||
'src/locale/locales/_build/**',
|
||||
'src/locale/locales/**/*.js',
|
||||
'*.e2e.ts',
|
||||
'*.e2e.tsx',
|
||||
'eslint.config.mjs',
|
||||
'babel.config.js',
|
||||
'metro.config.js',
|
||||
'.jscodeshift/**',
|
||||
],
|
||||
},
|
||||
|
||||
/**
|
||||
* Base configurations
|
||||
*/
|
||||
js.configs.recommended,
|
||||
tseslint.configs.recommendedTypeChecked,
|
||||
reactHooks.configs.flat.recommended,
|
||||
importX.flatConfigs.recommended,
|
||||
importX.flatConfigs.typescript,
|
||||
importX.flatConfigs['react-native'],
|
||||
|
||||
/**
|
||||
* Main configuration for all JS/TS/JSX/TSX files
|
||||
*/
|
||||
{
|
||||
files: ['**/*.{js,jsx,ts,tsx}'],
|
||||
plugins: {
|
||||
react,
|
||||
'react-native': reactNative,
|
||||
'react-native-a11y': reactNativeA11y,
|
||||
'simple-import-sort': simpleImportSort,
|
||||
// @ts-expect-error - not sure why
|
||||
lingui,
|
||||
'react-compiler': reactCompiler,
|
||||
'bsky-internal': bskyInternal,
|
||||
},
|
||||
languageOptions: {
|
||||
ecmaVersion: 'latest',
|
||||
sourceType: 'module',
|
||||
globals: {
|
||||
...globals.browser,
|
||||
...globals.node,
|
||||
},
|
||||
parserOptions: {
|
||||
parser: tsParser,
|
||||
projectService: true,
|
||||
tsconfigRootDir: import.meta.dirname,
|
||||
ecmaFeatures: {
|
||||
jsx: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
settings: {
|
||||
react: {
|
||||
version: 'detect',
|
||||
},
|
||||
componentWrapperFunctions: ['observer'],
|
||||
},
|
||||
rules: {
|
||||
/**
|
||||
* Custom rules
|
||||
*/
|
||||
'bsky-internal/avoid-unwrapped-text': [
|
||||
'error',
|
||||
{
|
||||
impliedTextComponents: [
|
||||
'H1',
|
||||
'H2',
|
||||
'H3',
|
||||
'H4',
|
||||
'H5',
|
||||
'H6',
|
||||
'P',
|
||||
'Admonition',
|
||||
'Admonition.Admonition',
|
||||
'Toast.Action',
|
||||
'AgeAssuranceAdmonition',
|
||||
'Span',
|
||||
'StackedButton',
|
||||
],
|
||||
impliedTextProps: [],
|
||||
suggestedTextWrappers: {
|
||||
Button: 'ButtonText',
|
||||
'ToggleButton.Button': 'ToggleButton.ButtonText',
|
||||
'SegmentedControl.Item': 'SegmentedControl.ItemText',
|
||||
},
|
||||
},
|
||||
],
|
||||
'bsky-internal/use-exact-imports': 'error',
|
||||
'bsky-internal/use-prefixed-imports': 'error',
|
||||
'bsky-internal/lingui-msg-rule': 'error',
|
||||
|
||||
/**
|
||||
* React & React Native
|
||||
*/
|
||||
...react.configs.recommended.rules,
|
||||
...react.configs['jsx-runtime'].rules,
|
||||
'react/hook-use-state': 'warn',
|
||||
'react/no-unescaped-entities': 'off',
|
||||
'react/prop-types': 'off',
|
||||
'react-native/no-inline-styles': 'off',
|
||||
...reactNativeA11y.configs.all.rules,
|
||||
'react-compiler/react-compiler': 'warn',
|
||||
'react-hooks/set-state-in-effect': 'error',
|
||||
'react-hooks/purity': 'error',
|
||||
'react-hooks/refs': 'error',
|
||||
'react-hooks/immutability': 'error',
|
||||
|
||||
/**
|
||||
* Import sorting
|
||||
*/
|
||||
'simple-import-sort/imports': [
|
||||
'error',
|
||||
{
|
||||
groups: [
|
||||
// Side effect imports.
|
||||
['^\\u0000'],
|
||||
// Node.js builtins prefixed with `node:`.
|
||||
['^node:'],
|
||||
// Packages.
|
||||
// Things that start with a letter (or digit or underscore), or `@` followed by a letter.
|
||||
// React/React Native prioritized, followed by expo
|
||||
// Followed by all packages excluding unprefixed relative ones
|
||||
[
|
||||
'^(react\\/(.*)$)|^(react$)|^(react-native(.*)$)',
|
||||
'^(expo(.*)$)|^(expo$)',
|
||||
'^(?!(?:alf|components|lib|locale|logger|platform|screens|state|view)(?:$|\\/))@?\\w',
|
||||
],
|
||||
// Relative imports.
|
||||
// Ideally, anything that starts with a dot or #
|
||||
// due to unprefixed relative imports being used, we whitelist the relative paths we use
|
||||
// (?:$|\\/) matches end of string or /
|
||||
[
|
||||
'^(?:#\\/)?(?:lib|state|logger|platform|locale)(?:$|\\/)',
|
||||
'^(?:#\\/)?view(?:$|\\/)',
|
||||
'^(?:#\\/)?screens(?:$|\\/)',
|
||||
'^(?:#\\/)?alf(?:$|\\/)',
|
||||
'^(?:#\\/)?components(?:$|\\/)',
|
||||
'^#\\/',
|
||||
'^\\.',
|
||||
],
|
||||
// anything else - hopefully we don't have any of these
|
||||
['^'],
|
||||
],
|
||||
},
|
||||
],
|
||||
'simple-import-sort/exports': 'error',
|
||||
|
||||
/**
|
||||
* Import linting
|
||||
*/
|
||||
'import-x/consistent-type-specifier-style': ['warn', 'prefer-inline'],
|
||||
'import-x/no-unresolved': [
|
||||
'error',
|
||||
{
|
||||
/*
|
||||
* The `postinstall` hook runs `compile-if-needed` locally, but not in
|
||||
* CI. For CI-sake, ignore this.
|
||||
*/
|
||||
ignore: ['^#\/locale\/locales\/.+\/messages'],
|
||||
},
|
||||
],
|
||||
'import-x/no-extraneous-dependencies': [
|
||||
'error',
|
||||
{
|
||||
whitelist: [
|
||||
// test files only
|
||||
'@jest/globals',
|
||||
// we only use a really simple util from this, and we know it will be present
|
||||
'expo-modules-core',
|
||||
// this is a dep for @atproto/api, but we absolutely need them in sync, so just
|
||||
// rely on the transient version
|
||||
'@atproto/common-web',
|
||||
],
|
||||
},
|
||||
],
|
||||
'import-x/no-nodejs-modules': 'error',
|
||||
|
||||
/**
|
||||
* TypeScript-specific rules
|
||||
*/
|
||||
'no-unused-vars': 'off', // off, we use TS-specific rule below
|
||||
'@typescript-eslint/no-unused-vars': [
|
||||
'error',
|
||||
{
|
||||
argsIgnorePattern: '^_',
|
||||
varsIgnorePattern: '^_.+',
|
||||
caughtErrors: 'none',
|
||||
ignoreRestSiblings: true,
|
||||
},
|
||||
],
|
||||
'@typescript-eslint/consistent-type-imports': [
|
||||
'warn',
|
||||
{prefer: 'type-imports', fixStyle: 'inline-type-imports'},
|
||||
],
|
||||
'@typescript-eslint/no-require-imports': 'off',
|
||||
'@typescript-eslint/no-unused-expressions': [
|
||||
'error',
|
||||
{
|
||||
allowTernary: true,
|
||||
},
|
||||
],
|
||||
/**
|
||||
* Maintain previous behavior via eslint-suppressions.json - these are
|
||||
* stricter in typescript-eslint v8. `off` ones are a bit too nit-picky.
|
||||
*/
|
||||
'@typescript-eslint/no-explicit-any': 'error',
|
||||
'@typescript-eslint/ban-ts-comment': 'off',
|
||||
'@typescript-eslint/no-empty-object-type': 'off',
|
||||
'@typescript-eslint/no-unsafe-function-type': 'off',
|
||||
'@typescript-eslint/no-unsafe-assignment': 'off',
|
||||
'@typescript-eslint/unbound-method': 'off',
|
||||
'@typescript-eslint/no-unsafe-argument': 'off',
|
||||
'@typescript-eslint/no-unsafe-return': 'off',
|
||||
'@typescript-eslint/no-unsafe-member-access': 'error',
|
||||
'@typescript-eslint/no-unsafe-call': 'error',
|
||||
'@typescript-eslint/no-floating-promises': 'error',
|
||||
'@typescript-eslint/no-misused-promises': 'error',
|
||||
'@typescript-eslint/require-await': 'error',
|
||||
'@typescript-eslint/no-unsafe-enum-comparison': 'error',
|
||||
'@typescript-eslint/no-unnecessary-type-assertion': 'error',
|
||||
'@typescript-eslint/no-redundant-type-constituents': 'error',
|
||||
'@typescript-eslint/no-duplicate-type-constituents': 'error',
|
||||
'@typescript-eslint/no-base-to-string': 'error',
|
||||
'@typescript-eslint/prefer-promise-reject-errors': 'error',
|
||||
'@typescript-eslint/await-thenable': 'error',
|
||||
|
||||
'no-restricted-imports': [
|
||||
'error',
|
||||
{
|
||||
paths: [
|
||||
{
|
||||
name: 'react',
|
||||
importNames: ['React', 'default'],
|
||||
message:
|
||||
'React is already in the global type namespace. Use named imports for runtime modules.',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
|
||||
/**
|
||||
* Turn off rules that we haven't enforced thus far
|
||||
*/
|
||||
'no-empty-pattern': 'off',
|
||||
'no-async-promise-executor': 'off',
|
||||
'no-constant-binary-expression': 'warn',
|
||||
'prefer-const': 'off',
|
||||
'no-empty': 'off',
|
||||
'no-unsafe-optional-chaining': 'off',
|
||||
'no-prototype-builtins': 'off',
|
||||
'no-var': 'off',
|
||||
'prefer-rest-params': 'off',
|
||||
'no-case-declarations': 'off',
|
||||
'no-irregular-whitespace': 'off',
|
||||
'no-useless-escape': 'off',
|
||||
'no-sparse-arrays': 'off',
|
||||
'no-fallthrough': 'off',
|
||||
'no-control-regex': 'off',
|
||||
},
|
||||
},
|
||||
|
||||
/**
|
||||
* bskyogcard, dev-env - server-side, Node.js imports are fine
|
||||
*/
|
||||
{
|
||||
files: ['bskyogcard/**/*.{js,jsx,ts,tsx}', 'dev-env/**/*.{js,jsx,ts,tsx}'],
|
||||
rules: {
|
||||
'import-x/no-nodejs-modules': 'off',
|
||||
},
|
||||
},
|
||||
|
||||
/**
|
||||
* Test files configuration
|
||||
*/
|
||||
{
|
||||
files: ['**/__tests__/**/*.{js,jsx,ts,tsx}', '**/*.test.{js,jsx,ts,tsx}'],
|
||||
languageOptions: {
|
||||
globals: {
|
||||
...globals.jest,
|
||||
},
|
||||
},
|
||||
},
|
||||
)
|
||||
+3
-8
@@ -1,16 +1,11 @@
|
||||
const {RuleTester} = require('eslint')
|
||||
const tseslint = require('typescript-eslint')
|
||||
const {RuleTester} = require('oxlint/plugins-dev')
|
||||
const avoidUnwrappedText = require('../avoid-unwrapped-text')
|
||||
|
||||
const ruleTester = new RuleTester({
|
||||
eslintCompat: true,
|
||||
languageOptions: {
|
||||
parser: tseslint.parser,
|
||||
parserOptions: {
|
||||
ecmaFeatures: {
|
||||
jsx: true,
|
||||
},
|
||||
ecmaVersion: 'latest',
|
||||
sourceType: 'module',
|
||||
lang: 'tsx',
|
||||
},
|
||||
},
|
||||
})
|
||||
+3
-8
@@ -1,16 +1,11 @@
|
||||
const {RuleTester} = require('eslint')
|
||||
const tseslint = require('typescript-eslint')
|
||||
const {RuleTester} = require('oxlint/plugins-dev')
|
||||
const linguiMsgRule = require('../lingui-msg-rule')
|
||||
|
||||
const ruleTester = new RuleTester({
|
||||
eslintCompat: true,
|
||||
languageOptions: {
|
||||
parser: tseslint.parser,
|
||||
parserOptions: {
|
||||
ecmaFeatures: {
|
||||
jsx: true,
|
||||
},
|
||||
ecmaVersion: 'latest',
|
||||
sourceType: 'module',
|
||||
lang: 'tsx',
|
||||
},
|
||||
},
|
||||
})
|
||||
@@ -0,0 +1,3 @@
|
||||
## Eslint plugin tests
|
||||
|
||||
These are disabled as Oxlint’s RuleTester doesn’t work well with Hermes.
|
||||
File diff suppressed because it is too large
Load Diff
+4
-10
@@ -59,7 +59,7 @@
|
||||
"test-watch": "NODE_ENV=test jest --watchAll",
|
||||
"test-ci": "NODE_ENV=test jest --ci --forceExit --reporters=default --reporters=jest-junit",
|
||||
"test-coverage": "NODE_ENV=test jest --coverage",
|
||||
"lint": "eslint --cache --quiet src modules",
|
||||
"lint": "oxlint --quiet src modules",
|
||||
"lint-native": "swiftlint ./modules && ktlint ./modules",
|
||||
"lint-native:fix": "swiftlint --fix ./modules && ktlint --format ./modules",
|
||||
"typecheck": "tsgo --project ./tsconfig.check.json",
|
||||
@@ -256,7 +256,6 @@
|
||||
"@babel/preset-env": "^7.26.0",
|
||||
"@babel/runtime": "^7.26.0",
|
||||
"@crowdin/cli": "^4.14.1",
|
||||
"@eslint/js": "^9.39.2",
|
||||
"@lingui/babel-plugin-lingui-macro": "^5.9.2",
|
||||
"@lingui/cli": "^5.9.2",
|
||||
"@pmmmwh/react-refresh-webpack-plugin": "^0.5.15",
|
||||
@@ -276,14 +275,8 @@
|
||||
"babel-plugin-module-resolver": "^5.0.2",
|
||||
"babel-plugin-react-compiler": "19.1.0-rc.3",
|
||||
"babel-preset-expo": "~54.0.10",
|
||||
"eslint": "^9.39.2",
|
||||
"eslint-import-resolver-typescript": "^4.4.4",
|
||||
"eslint-plugin-bsky-internal": "link:eslint",
|
||||
"eslint-plugin-import-x": "^4.16.2",
|
||||
"eslint-plugin-lingui": "^0.12.0",
|
||||
"eslint-plugin-react": "^7.37.5",
|
||||
"eslint-plugin-react-compiler": "19.1.0-rc.2",
|
||||
"eslint-plugin-react-hooks": "^7.1.1",
|
||||
"eslint-plugin-react-native": "^5.0.0",
|
||||
"eslint-plugin-react-native-a11y": "^3.5.1",
|
||||
"eslint-plugin-simple-import-sort": "^13.0.0",
|
||||
@@ -295,13 +288,14 @@
|
||||
"jest-expo": "~54.0.17",
|
||||
"jest-junit": "^16.0.0",
|
||||
"lint-staged": "^17.0.8",
|
||||
"oxlint": "^1.73.0",
|
||||
"oxlint-tsgolint": "^0.24.0",
|
||||
"prettier": "^3.8.3",
|
||||
"react-native-dotenv": "^3.4.11",
|
||||
"react-refresh": "^0.14.0",
|
||||
"svgo": "^3.3.2",
|
||||
"ts-plugin-sort-import-suggestions": "^1.0.4",
|
||||
"typescript": "^6.0.2",
|
||||
"typescript-eslint": "^8.58.0",
|
||||
"webpack-bundle-analyzer": "^4.10.1"
|
||||
},
|
||||
"jest": {
|
||||
@@ -366,7 +360,7 @@
|
||||
},
|
||||
"lint-staged": {
|
||||
"*{.js,.jsx,.ts,.tsx}": [
|
||||
"eslint --cache --fix"
|
||||
"oxlint --fix"
|
||||
],
|
||||
"*{.js,.jsx,.ts,.tsx,.css}": [
|
||||
"prettier --cache --write --ignore-unknown"
|
||||
|
||||
Generated
+292
-1108
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user