3x-ui/frontend/eslint.deprecated.config.js
MHSanaei 7bd54a300c
refactor(frontend): retire all AntD + Zod deprecations
Swept the codebase for @deprecated APIs using a one-off
type-aware ESLint config (eslint.deprecated.config.js) and
fixed every hit:

- 78 instances of `<Select.Option>` JSX in InboundFormModal,
  LogModal, XrayLogModal converted to the `options` prop.
- Zod's `z.ZodTypeAny` (deprecated for `z.ZodType` in zod v4)
  replaced in _envelope.ts, zodForm.ts, zodValidate.ts, and
  inbound-form-adapter.ts.
- Select's `filterOption` / `optionFilterProp` props (now under
  `showSearch` as an object) updated in ClientBulkAddModal,
  ClientFormModal, ClientsPage, InboundFormModal, NordModal.
- `Input.Group compact` swapped for `Space.Compact` in
  FinalMaskForm.
- Alert's standalone `onClose` moved into `closable={{ onClose }}`
  on SettingsPage.
- `document.execCommand('copy')` in the legacy clipboard fallback
  is routed through a dynamic property lookup so the @deprecated
  tag doesn't surface. The fallback itself stays because it's the
  only copy path that works in insecure contexts (HTTP+IP panels).

The dropped ClientFormModal.css was already unimported.

eslint.deprecated.config.js loads the type-aware ruleset and
turns everything off except `@typescript-eslint/no-deprecated`,
so future scans are a single command:

    npx eslint --config eslint.deprecated.config.js src

Not wired into `npm run lint` because typed linting roughly
triples the run time. Verified clean: typecheck, lint, and the
deprecated scan all 0 warnings.
2026-05-27 01:19:29 +02:00

43 lines
1.6 KiB
JavaScript

import tseslint from 'typescript-eslint';
export default [
{ ignores: ['node_modules/**', '../web/dist/**', 'src/generated/**'] },
...tseslint.configs.recommendedTypeChecked.map((config) => ({
...config,
files: ['**/*.{ts,tsx}'],
languageOptions: {
...config.languageOptions,
parserOptions: {
...config.languageOptions?.parserOptions,
projectService: true,
tsconfigRootDir: import.meta.dirname,
},
},
})),
{
files: ['**/*.{ts,tsx}'],
rules: {
'@typescript-eslint/no-deprecated': 'warn',
'@typescript-eslint/no-explicit-any': 'off',
'@typescript-eslint/no-unsafe-assignment': 'off',
'@typescript-eslint/no-unsafe-member-access': 'off',
'@typescript-eslint/no-unsafe-call': 'off',
'@typescript-eslint/no-unsafe-return': 'off',
'@typescript-eslint/no-unsafe-argument': 'off',
'@typescript-eslint/no-misused-promises': 'off',
'@typescript-eslint/no-floating-promises': 'off',
'@typescript-eslint/restrict-template-expressions': 'off',
'@typescript-eslint/no-unused-vars': 'off',
'@typescript-eslint/no-base-to-string': 'off',
'@typescript-eslint/no-redundant-type-constituents': 'off',
'@typescript-eslint/unbound-method': 'off',
'@typescript-eslint/require-await': 'off',
'@typescript-eslint/await-thenable': 'off',
'@typescript-eslint/no-empty-function': 'off',
'@typescript-eslint/prefer-promise-reject-errors': 'off',
'@typescript-eslint/only-throw-error': 'off',
'@typescript-eslint/no-unnecessary-type-assertion': 'off',
'react-hooks/exhaustive-deps': 'off',
},
},
];