mirror of
https://github.com/glitch-soc/mastodon
synced 2025-04-24 15:24:51 +00:00
Upgrade to ESLint v9 flat config (#34324)
Co-authored-by: Nick Schonning <nschonni@gmail.com>
This commit is contained in:
parent
9686ae7060
commit
e8270e2807
21 changed files with 1011 additions and 874 deletions
|
@ -1,13 +0,0 @@
|
||||||
/build/**
|
|
||||||
/coverage/**
|
|
||||||
/db/**
|
|
||||||
/lib/**
|
|
||||||
/log/**
|
|
||||||
/node_modules/**
|
|
||||||
/nonobox/**
|
|
||||||
/public/**
|
|
||||||
!/public/embed.js
|
|
||||||
/spec/**
|
|
||||||
/tmp/**
|
|
||||||
/vendor/**
|
|
||||||
!.eslintrc.js
|
|
367
.eslintrc.js
367
.eslintrc.js
|
@ -1,367 +0,0 @@
|
||||||
// @ts-check
|
|
||||||
const { defineConfig } = require('eslint-define-config');
|
|
||||||
|
|
||||||
module.exports = defineConfig({
|
|
||||||
root: true,
|
|
||||||
|
|
||||||
extends: [
|
|
||||||
'eslint:recommended',
|
|
||||||
'plugin:react/recommended',
|
|
||||||
'plugin:react-hooks/recommended',
|
|
||||||
'plugin:jsx-a11y/recommended',
|
|
||||||
'plugin:import/recommended',
|
|
||||||
'plugin:promise/recommended',
|
|
||||||
'plugin:jsdoc/recommended',
|
|
||||||
],
|
|
||||||
|
|
||||||
env: {
|
|
||||||
browser: true,
|
|
||||||
node: true,
|
|
||||||
es6: true,
|
|
||||||
},
|
|
||||||
|
|
||||||
parser: '@typescript-eslint/parser',
|
|
||||||
|
|
||||||
plugins: [
|
|
||||||
'react',
|
|
||||||
'jsx-a11y',
|
|
||||||
'import',
|
|
||||||
'promise',
|
|
||||||
'@typescript-eslint',
|
|
||||||
'formatjs',
|
|
||||||
],
|
|
||||||
|
|
||||||
parserOptions: {
|
|
||||||
sourceType: 'module',
|
|
||||||
ecmaFeatures: {
|
|
||||||
jsx: true,
|
|
||||||
},
|
|
||||||
ecmaVersion: 2021,
|
|
||||||
requireConfigFile: false,
|
|
||||||
babelOptions: {
|
|
||||||
configFile: false,
|
|
||||||
presets: ['@babel/react', '@babel/env'],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
settings: {
|
|
||||||
react: {
|
|
||||||
version: 'detect',
|
|
||||||
},
|
|
||||||
'import/ignore': [
|
|
||||||
'node_modules',
|
|
||||||
'\\.(css|scss|json)$',
|
|
||||||
],
|
|
||||||
'import/resolver': {
|
|
||||||
typescript: {},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
rules: {
|
|
||||||
'consistent-return': 'error',
|
|
||||||
'dot-notation': 'error',
|
|
||||||
eqeqeq: ['error', 'always', { 'null': 'ignore' }],
|
|
||||||
'indent': ['error', 2],
|
|
||||||
'jsx-quotes': ['error', 'prefer-single'],
|
|
||||||
'semi': ['error', 'always'],
|
|
||||||
'no-catch-shadow': 'error',
|
|
||||||
'no-console': [
|
|
||||||
'warn',
|
|
||||||
{
|
|
||||||
allow: [
|
|
||||||
'error',
|
|
||||||
'warn',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
'no-empty': ['error', { "allowEmptyCatch": true }],
|
|
||||||
'no-restricted-properties': [
|
|
||||||
'error',
|
|
||||||
{ property: 'substring', message: 'Use .slice instead of .substring.' },
|
|
||||||
{ property: 'substr', message: 'Use .slice instead of .substr.' },
|
|
||||||
],
|
|
||||||
'no-restricted-syntax': [
|
|
||||||
'error',
|
|
||||||
{
|
|
||||||
// eslint-disable-next-line no-restricted-syntax
|
|
||||||
selector: 'Literal[value=/•/], JSXText[value=/•/]',
|
|
||||||
// eslint-disable-next-line no-restricted-syntax
|
|
||||||
message: "Use '·' (middle dot) instead of '•' (bullet)",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
'no-unused-expressions': 'error',
|
|
||||||
'no-unused-vars': 'off',
|
|
||||||
'@typescript-eslint/no-unused-vars': [
|
|
||||||
'error',
|
|
||||||
{
|
|
||||||
vars: 'all',
|
|
||||||
args: 'after-used',
|
|
||||||
destructuredArrayIgnorePattern: '^_',
|
|
||||||
ignoreRestSiblings: true,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
'valid-typeof': 'error',
|
|
||||||
|
|
||||||
'react/jsx-filename-extension': ['error', { extensions: ['.jsx', 'tsx'] }],
|
|
||||||
'react/jsx-boolean-value': 'error',
|
|
||||||
'react/display-name': 'off',
|
|
||||||
'react/jsx-fragments': ['error', 'syntax'],
|
|
||||||
'react/jsx-equals-spacing': 'error',
|
|
||||||
'react/jsx-no-bind': 'error',
|
|
||||||
'react/jsx-no-useless-fragment': 'error',
|
|
||||||
'react/jsx-no-target-blank': ['error', { allowReferrer: true }],
|
|
||||||
'react/jsx-tag-spacing': 'error',
|
|
||||||
'react/jsx-uses-react': 'off', // not needed with new JSX transform
|
|
||||||
'react/jsx-wrap-multilines': 'error',
|
|
||||||
'react/react-in-jsx-scope': 'off', // not needed with new JSX transform
|
|
||||||
'react/self-closing-comp': 'error',
|
|
||||||
|
|
||||||
// recommended values found in https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/v6.8.0/src/index.js#L46
|
|
||||||
'jsx-a11y/click-events-have-key-events': 'off',
|
|
||||||
'jsx-a11y/label-has-associated-control': 'off',
|
|
||||||
'jsx-a11y/media-has-caption': 'off',
|
|
||||||
'jsx-a11y/no-autofocus': 'off',
|
|
||||||
// recommended rule is:
|
|
||||||
// 'jsx-a11y/no-interactive-element-to-noninteractive-role': [
|
|
||||||
// 'error',
|
|
||||||
// {
|
|
||||||
// tr: ['none', 'presentation'],
|
|
||||||
// canvas: ['img'],
|
|
||||||
// },
|
|
||||||
// ],
|
|
||||||
'jsx-a11y/no-interactive-element-to-noninteractive-role': 'off',
|
|
||||||
// recommended rule is:
|
|
||||||
// 'jsx-a11y/no-noninteractive-tabindex': [
|
|
||||||
// 'error',
|
|
||||||
// {
|
|
||||||
// tags: [],
|
|
||||||
// roles: ['tabpanel'],
|
|
||||||
// allowExpressionValues: true,
|
|
||||||
// },
|
|
||||||
// ],
|
|
||||||
'jsx-a11y/no-noninteractive-tabindex': 'off',
|
|
||||||
// recommended is full 'error'
|
|
||||||
'jsx-a11y/no-static-element-interactions': [
|
|
||||||
'warn',
|
|
||||||
{
|
|
||||||
handlers: [
|
|
||||||
'onClick',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
|
|
||||||
// See https://github.com/import-js/eslint-plugin-import/blob/v2.29.1/config/recommended.js
|
|
||||||
'import/extensions': [
|
|
||||||
'error',
|
|
||||||
'always',
|
|
||||||
{
|
|
||||||
js: 'never',
|
|
||||||
jsx: 'never',
|
|
||||||
mjs: 'never',
|
|
||||||
ts: 'never',
|
|
||||||
tsx: 'never',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
'import/first': 'error',
|
|
||||||
'import/newline-after-import': 'error',
|
|
||||||
'import/no-anonymous-default-export': 'error',
|
|
||||||
'import/no-extraneous-dependencies': [
|
|
||||||
'error',
|
|
||||||
{
|
|
||||||
devDependencies: [
|
|
||||||
'.eslintrc.js',
|
|
||||||
'config/webpack/**',
|
|
||||||
'app/javascript/mastodon/performance.js',
|
|
||||||
'app/javascript/mastodon/test_setup.js',
|
|
||||||
'app/javascript/**/__tests__/**',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
'import/no-amd': 'error',
|
|
||||||
'import/no-commonjs': 'error',
|
|
||||||
'import/no-import-module-exports': 'error',
|
|
||||||
'import/no-relative-packages': 'error',
|
|
||||||
'import/no-self-import': 'error',
|
|
||||||
'import/no-useless-path-segments': 'error',
|
|
||||||
'import/no-webpack-loader-syntax': 'error',
|
|
||||||
|
|
||||||
'import/order': [
|
|
||||||
'error',
|
|
||||||
{
|
|
||||||
alphabetize: { order: 'asc' },
|
|
||||||
'newlines-between': 'always',
|
|
||||||
groups: [
|
|
||||||
'builtin',
|
|
||||||
'external',
|
|
||||||
'internal',
|
|
||||||
'parent',
|
|
||||||
['index', 'sibling'],
|
|
||||||
'object',
|
|
||||||
],
|
|
||||||
pathGroups: [
|
|
||||||
// React core packages
|
|
||||||
{
|
|
||||||
pattern: '{react,react-dom,react-dom/client,prop-types}',
|
|
||||||
group: 'builtin',
|
|
||||||
position: 'after',
|
|
||||||
},
|
|
||||||
// I18n
|
|
||||||
{
|
|
||||||
pattern: '{react-intl,intl-messageformat}',
|
|
||||||
group: 'builtin',
|
|
||||||
position: 'after',
|
|
||||||
},
|
|
||||||
// Common React utilities
|
|
||||||
{
|
|
||||||
pattern: '{classnames,react-helmet,react-router,react-router-dom}',
|
|
||||||
group: 'external',
|
|
||||||
position: 'before',
|
|
||||||
},
|
|
||||||
// Immutable / Redux / data store
|
|
||||||
{
|
|
||||||
pattern: '{immutable,@reduxjs/toolkit,react-redux,react-immutable-proptypes,react-immutable-pure-component}',
|
|
||||||
group: 'external',
|
|
||||||
position: 'before',
|
|
||||||
},
|
|
||||||
// Internal packages
|
|
||||||
{
|
|
||||||
pattern: '{mastodon/**}',
|
|
||||||
group: 'internal',
|
|
||||||
position: 'after',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
pathGroupsExcludedImportTypes: [],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
|
|
||||||
'promise/always-return': 'off',
|
|
||||||
'promise/catch-or-return': [
|
|
||||||
'error',
|
|
||||||
{
|
|
||||||
allowFinally: true,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
'promise/no-callback-in-promise': 'off',
|
|
||||||
'promise/no-nesting': 'off',
|
|
||||||
'promise/no-promise-in-callback': 'off',
|
|
||||||
|
|
||||||
'formatjs/blocklist-elements': 'error',
|
|
||||||
'formatjs/enforce-default-message': ['error', 'literal'],
|
|
||||||
'formatjs/enforce-description': 'off', // description values not currently used
|
|
||||||
'formatjs/enforce-id': 'off', // Explicit IDs are used in the project
|
|
||||||
'formatjs/enforce-placeholders': 'off', // Issues in short_number.jsx
|
|
||||||
'formatjs/enforce-plural-rules': 'error',
|
|
||||||
'formatjs/no-camel-case': 'off', // disabledAccount is only non-conforming
|
|
||||||
'formatjs/no-complex-selectors': 'error',
|
|
||||||
'formatjs/no-emoji': 'error',
|
|
||||||
'formatjs/no-id': 'off', // IDs are used for translation keys
|
|
||||||
'formatjs/no-invalid-icu': 'error',
|
|
||||||
'formatjs/no-literal-string-in-jsx': 'off', // Should be looked at, but mainly flagging punctuation outside of strings
|
|
||||||
'formatjs/no-multiple-whitespaces': 'error',
|
|
||||||
'formatjs/no-offset': 'error',
|
|
||||||
'formatjs/no-useless-message': 'error',
|
|
||||||
'formatjs/prefer-formatted-message': 'error',
|
|
||||||
'formatjs/prefer-pound-in-plural': 'error',
|
|
||||||
|
|
||||||
'jsdoc/check-types': 'off',
|
|
||||||
'jsdoc/no-undefined-types': 'off',
|
|
||||||
'jsdoc/require-jsdoc': 'off',
|
|
||||||
'jsdoc/require-param-description': 'off',
|
|
||||||
'jsdoc/require-property-description': 'off',
|
|
||||||
'jsdoc/require-returns-description': 'off',
|
|
||||||
'jsdoc/require-returns': 'off',
|
|
||||||
},
|
|
||||||
|
|
||||||
overrides: [
|
|
||||||
{
|
|
||||||
files: [
|
|
||||||
'.eslintrc.js',
|
|
||||||
'*.config.js',
|
|
||||||
'.*rc.js',
|
|
||||||
'ide-helper.js',
|
|
||||||
'config/webpack/**/*',
|
|
||||||
'config/formatjs-formatter.js',
|
|
||||||
],
|
|
||||||
|
|
||||||
env: {
|
|
||||||
commonjs: true,
|
|
||||||
},
|
|
||||||
|
|
||||||
parserOptions: {
|
|
||||||
sourceType: 'script',
|
|
||||||
},
|
|
||||||
|
|
||||||
rules: {
|
|
||||||
'import/no-commonjs': 'off',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
files: [
|
|
||||||
'**/*.ts',
|
|
||||||
'**/*.tsx',
|
|
||||||
],
|
|
||||||
|
|
||||||
extends: [
|
|
||||||
'eslint:recommended',
|
|
||||||
'plugin:@typescript-eslint/strict-type-checked',
|
|
||||||
'plugin:@typescript-eslint/stylistic-type-checked',
|
|
||||||
'plugin:react/recommended',
|
|
||||||
'plugin:react-hooks/recommended',
|
|
||||||
'plugin:jsx-a11y/recommended',
|
|
||||||
'plugin:import/recommended',
|
|
||||||
'plugin:import/typescript',
|
|
||||||
'plugin:promise/recommended',
|
|
||||||
'plugin:jsdoc/recommended-typescript',
|
|
||||||
],
|
|
||||||
|
|
||||||
parserOptions: {
|
|
||||||
projectService: true,
|
|
||||||
tsconfigRootDir: __dirname,
|
|
||||||
},
|
|
||||||
|
|
||||||
rules: {
|
|
||||||
// Disable formatting rules that have been enabled in the base config
|
|
||||||
'indent': 'off',
|
|
||||||
|
|
||||||
// This is not needed as we use noImplicitReturns, which handles this in addition to understanding types
|
|
||||||
'consistent-return': 'off',
|
|
||||||
|
|
||||||
'import/consistent-type-specifier-style': ['error', 'prefer-top-level'],
|
|
||||||
|
|
||||||
'@typescript-eslint/consistent-type-definitions': ['warn', 'interface'],
|
|
||||||
'@typescript-eslint/consistent-type-exports': 'error',
|
|
||||||
'@typescript-eslint/consistent-type-imports': 'error',
|
|
||||||
"@typescript-eslint/prefer-nullish-coalescing": ['error', { ignorePrimitives: { boolean: true } }],
|
|
||||||
"@typescript-eslint/no-restricted-imports": [
|
|
||||||
"warn",
|
|
||||||
{
|
|
||||||
"name": "react-redux",
|
|
||||||
"importNames": ["useSelector", "useDispatch"],
|
|
||||||
"message": "Use typed hooks `useAppDispatch` and `useAppSelector` instead."
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"@typescript-eslint/restrict-template-expressions": ['warn', { allowNumber: true }],
|
|
||||||
'jsdoc/require-jsdoc': 'off',
|
|
||||||
|
|
||||||
// Those rules set stricter rules for TS files
|
|
||||||
// to enforce better practices when converting from JS
|
|
||||||
'import/no-default-export': 'warn',
|
|
||||||
'react/prefer-stateless-function': 'warn',
|
|
||||||
'react/function-component-definition': ['error', { namedComponents: 'arrow-function' }],
|
|
||||||
'react/jsx-uses-react': 'off', // not needed with new JSX transform
|
|
||||||
'react/react-in-jsx-scope': 'off', // not needed with new JSX transform
|
|
||||||
'react/prop-types': 'off',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
files: [
|
|
||||||
'**/__tests__/*.js',
|
|
||||||
'**/__tests__/*.jsx',
|
|
||||||
],
|
|
||||||
|
|
||||||
env: {
|
|
||||||
jest: true,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
],
|
|
||||||
});
|
|
8
.github/renovate.json5
vendored
8
.github/renovate.json5
vendored
|
@ -97,7 +97,13 @@
|
||||||
{
|
{
|
||||||
// Group all eslint-related packages with `eslint` in the same PR
|
// Group all eslint-related packages with `eslint` in the same PR
|
||||||
matchManagers: ['npm'],
|
matchManagers: ['npm'],
|
||||||
matchPackageNames: ['eslint', 'eslint-*', '@typescript-eslint/*'],
|
matchPackageNames: [
|
||||||
|
'eslint',
|
||||||
|
'eslint-*',
|
||||||
|
'typescript-eslint',
|
||||||
|
'@eslint/*',
|
||||||
|
'globals',
|
||||||
|
],
|
||||||
matchUpdateTypes: ['patch', 'minor'],
|
matchUpdateTypes: ['patch', 'minor'],
|
||||||
groupName: 'eslint (non-major)',
|
groupName: 'eslint (non-major)',
|
||||||
},
|
},
|
||||||
|
|
6
.github/workflows/lint-js.yml
vendored
6
.github/workflows/lint-js.yml
vendored
|
@ -11,7 +11,7 @@ on:
|
||||||
- 'tsconfig.json'
|
- 'tsconfig.json'
|
||||||
- '.nvmrc'
|
- '.nvmrc'
|
||||||
- '.prettier*'
|
- '.prettier*'
|
||||||
- '.eslint*'
|
- 'eslint.config.mjs'
|
||||||
- '**/*.js'
|
- '**/*.js'
|
||||||
- '**/*.jsx'
|
- '**/*.jsx'
|
||||||
- '**/*.ts'
|
- '**/*.ts'
|
||||||
|
@ -25,7 +25,7 @@ on:
|
||||||
- 'tsconfig.json'
|
- 'tsconfig.json'
|
||||||
- '.nvmrc'
|
- '.nvmrc'
|
||||||
- '.prettier*'
|
- '.prettier*'
|
||||||
- '.eslint*'
|
- 'eslint.config.mjs'
|
||||||
- '**/*.js'
|
- '**/*.js'
|
||||||
- '**/*.jsx'
|
- '**/*.jsx'
|
||||||
- '**/*.ts'
|
- '**/*.ts'
|
||||||
|
@ -44,7 +44,7 @@ jobs:
|
||||||
uses: ./.github/actions/setup-javascript
|
uses: ./.github/actions/setup-javascript
|
||||||
|
|
||||||
- name: ESLint
|
- name: ESLint
|
||||||
run: yarn lint:js --max-warnings 0
|
run: yarn workspaces foreach --all --parallel run lint:js --max-warnings 0
|
||||||
|
|
||||||
- name: Typecheck
|
- name: Typecheck
|
||||||
run: yarn typecheck
|
run: yarn typecheck
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
module.exports = {
|
module.exports = {
|
||||||
singleQuote: true,
|
singleQuote: true,
|
||||||
jsxSingleQuote: true
|
jsxSingleQuote: true
|
||||||
}
|
};
|
||||||
|
|
|
@ -68,7 +68,7 @@ function loaded() {
|
||||||
|
|
||||||
if (id) message = localeData[id];
|
if (id) message = localeData[id];
|
||||||
|
|
||||||
if (!message) message = defaultMessage as string;
|
message ??= defaultMessage as string;
|
||||||
|
|
||||||
const messageFormat = new IntlMessageFormat(message, locale);
|
const messageFormat = new IntlMessageFormat(message, locale);
|
||||||
return messageFormat.format(values) as string;
|
return messageFormat.format(values) as string;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import React from 'react';
|
import type React from 'react';
|
||||||
|
|
||||||
import { FormattedMessage } from 'react-intl';
|
import { FormattedMessage } from 'react-intl';
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import type { PropsWithChildren } from 'react';
|
import type { PropsWithChildren } from 'react';
|
||||||
import React from 'react';
|
import type React from 'react';
|
||||||
|
|
||||||
import { Router as OriginalRouter, useHistory } from 'react-router';
|
import { Router as OriginalRouter, useHistory } from 'react-router';
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
/* eslint-disable import/no-commonjs --
|
|
||||||
We need to use CommonJS here due to preval */
|
|
||||||
// @preval
|
// @preval
|
||||||
// http://www.unicode.org/Public/emoji/5.0/emoji-test.txt
|
// http://www.unicode.org/Public/emoji/5.0/emoji-test.txt
|
||||||
// This file contains the compressed version of the emoji data from
|
// This file contains the compressed version of the emoji data from
|
||||||
|
|
|
@ -33,11 +33,8 @@ function processEmojiMapData(
|
||||||
shortCode?: ShortCodesToEmojiDataKey,
|
shortCode?: ShortCodesToEmojiDataKey,
|
||||||
) {
|
) {
|
||||||
const [native, _filename] = emojiMapData;
|
const [native, _filename] = emojiMapData;
|
||||||
let filename = emojiMapData[1];
|
// filename name can be derived from unicodeToFilename
|
||||||
if (!filename) {
|
const filename = emojiMapData[1] ?? unicodeToFilename(native);
|
||||||
// filename name can be derived from unicodeToFilename
|
|
||||||
filename = unicodeToFilename(native);
|
|
||||||
}
|
|
||||||
unicodeMapping[native] = {
|
unicodeMapping[native] = {
|
||||||
shortCode,
|
shortCode,
|
||||||
filename,
|
filename,
|
||||||
|
|
|
@ -1,6 +1,3 @@
|
||||||
/* eslint-disable import/no-commonjs --
|
|
||||||
We need to use CommonJS here as its imported into a preval file (`emoji_compressed.js`) */
|
|
||||||
|
|
||||||
// taken from:
|
// taken from:
|
||||||
// https://github.com/twitter/twemoji/blob/47732c7/twemoji-generator.js#L848-L866
|
// https://github.com/twitter/twemoji/blob/47732c7/twemoji-generator.js#L848-L866
|
||||||
exports.unicodeToFilename = (str) => {
|
exports.unicodeToFilename = (str) => {
|
||||||
|
|
|
@ -1,6 +1,3 @@
|
||||||
/* eslint-disable import/no-commonjs --
|
|
||||||
We need to use CommonJS here as its imported into a preval file (`emoji_compressed.js`) */
|
|
||||||
|
|
||||||
function padLeft(str, num) {
|
function padLeft(str, num) {
|
||||||
while (str.length < num) {
|
while (str.length < num) {
|
||||||
str = '0' + str;
|
str = '0' + str;
|
||||||
|
|
|
@ -1,6 +1,3 @@
|
||||||
/* eslint-disable import/no-commonjs --
|
|
||||||
We need to use CommonJS here as its imported into a preval file (`emoji_compressed.js`) */
|
|
||||||
|
|
||||||
/* @preval */
|
/* @preval */
|
||||||
|
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
|
|
395
eslint.config.mjs
Normal file
395
eslint.config.mjs
Normal file
|
@ -0,0 +1,395 @@
|
||||||
|
// @ts-check
|
||||||
|
|
||||||
|
import js from '@eslint/js';
|
||||||
|
import { globalIgnores } from 'eslint/config';
|
||||||
|
import formatjs from 'eslint-plugin-formatjs';
|
||||||
|
// @ts-expect-error -- No typings
|
||||||
|
import importPlugin from 'eslint-plugin-import';
|
||||||
|
import jsdoc from 'eslint-plugin-jsdoc';
|
||||||
|
import jsxA11Y from 'eslint-plugin-jsx-a11y';
|
||||||
|
import promisePlugin from 'eslint-plugin-promise';
|
||||||
|
import react from 'eslint-plugin-react';
|
||||||
|
import reactHooks from 'eslint-plugin-react-hooks';
|
||||||
|
import globals from 'globals';
|
||||||
|
import tseslint from 'typescript-eslint';
|
||||||
|
|
||||||
|
/** @type {import('typescript-eslint').ConfigArray} */
|
||||||
|
export const baseConfig = [
|
||||||
|
js.configs.recommended,
|
||||||
|
importPlugin.flatConfigs.recommended,
|
||||||
|
jsdoc.configs['flat/recommended'],
|
||||||
|
promisePlugin.configs['flat/recommended'],
|
||||||
|
{
|
||||||
|
linterOptions: {
|
||||||
|
reportUnusedDisableDirectives: 'error',
|
||||||
|
reportUnusedInlineConfigs: 'error',
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
'consistent-return': 'error',
|
||||||
|
'dot-notation': 'error',
|
||||||
|
|
||||||
|
eqeqeq: [
|
||||||
|
'error',
|
||||||
|
'always',
|
||||||
|
{
|
||||||
|
null: 'ignore',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
|
'no-console': [
|
||||||
|
'warn',
|
||||||
|
{
|
||||||
|
allow: ['error', 'warn'],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
|
'no-empty': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
allowEmptyCatch: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
|
'no-restricted-properties': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
property: 'substring',
|
||||||
|
message: 'Use .slice instead of .substring.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
property: 'substr',
|
||||||
|
message: 'Use .slice instead of .substr.',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
|
'no-unused-expressions': 'error',
|
||||||
|
'no-unused-vars': 'off',
|
||||||
|
|
||||||
|
'valid-typeof': 'error',
|
||||||
|
|
||||||
|
'import/extensions': [
|
||||||
|
'error',
|
||||||
|
'always',
|
||||||
|
{
|
||||||
|
js: 'never',
|
||||||
|
jsx: 'never',
|
||||||
|
mjs: 'never',
|
||||||
|
ts: 'never',
|
||||||
|
mts: 'never',
|
||||||
|
tsx: 'never',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'import/first': 'error',
|
||||||
|
'import/newline-after-import': 'error',
|
||||||
|
'import/no-anonymous-default-export': 'error',
|
||||||
|
'import/no-amd': 'error',
|
||||||
|
'import/no-commonjs': 'error',
|
||||||
|
'import/no-import-module-exports': 'error',
|
||||||
|
'import/no-relative-packages': 'error',
|
||||||
|
'import/no-self-import': 'error',
|
||||||
|
'import/no-useless-path-segments': 'error',
|
||||||
|
'import/order': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
alphabetize: {
|
||||||
|
order: 'asc',
|
||||||
|
},
|
||||||
|
|
||||||
|
'newlines-between': 'always',
|
||||||
|
|
||||||
|
groups: [
|
||||||
|
'builtin',
|
||||||
|
'external',
|
||||||
|
'internal',
|
||||||
|
'parent',
|
||||||
|
['index', 'sibling'],
|
||||||
|
'object',
|
||||||
|
],
|
||||||
|
|
||||||
|
pathGroups: [
|
||||||
|
{
|
||||||
|
pattern: '{react,react-dom,react-dom/client,prop-types}',
|
||||||
|
group: 'builtin',
|
||||||
|
position: 'after',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pattern: '{react-intl,intl-messageformat}',
|
||||||
|
group: 'builtin',
|
||||||
|
position: 'after',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pattern:
|
||||||
|
'{classnames,react-helmet,react-router,react-router-dom}',
|
||||||
|
group: 'external',
|
||||||
|
position: 'before',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pattern:
|
||||||
|
'{immutable,@reduxjs/toolkit,react-redux,react-immutable-proptypes,react-immutable-pure-component}',
|
||||||
|
group: 'external',
|
||||||
|
position: 'before',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pattern: '{mastodon/**}',
|
||||||
|
group: 'internal',
|
||||||
|
position: 'after',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
|
pathGroupsExcludedImportTypes: [],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
|
'jsdoc/check-types': 'off',
|
||||||
|
'jsdoc/no-undefined-types': 'off',
|
||||||
|
'jsdoc/require-jsdoc': 'off',
|
||||||
|
'jsdoc/require-param-description': 'off',
|
||||||
|
'jsdoc/require-property-description': 'off',
|
||||||
|
'jsdoc/require-returns-description': 'off',
|
||||||
|
'jsdoc/require-returns': 'off',
|
||||||
|
|
||||||
|
'promise/always-return': 'off',
|
||||||
|
'promise/catch-or-return': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
allowFinally: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'promise/no-callback-in-promise': 'off',
|
||||||
|
'promise/no-nesting': 'off',
|
||||||
|
'promise/no-promise-in-callback': 'off',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export default tseslint.config([
|
||||||
|
baseConfig,
|
||||||
|
globalIgnores([
|
||||||
|
'build/**/*',
|
||||||
|
'coverage/**/*',
|
||||||
|
'db/**/*',
|
||||||
|
'lib/**/*',
|
||||||
|
'log/**/*',
|
||||||
|
'node_modules/**/*',
|
||||||
|
'public/**/*',
|
||||||
|
'!public/embed.js',
|
||||||
|
'spec/**/*',
|
||||||
|
'tmp/**/*',
|
||||||
|
'vendor/**/*',
|
||||||
|
'streaming/**/*',
|
||||||
|
]),
|
||||||
|
react.configs.flat.recommended,
|
||||||
|
react.configs.flat['jsx-runtime'],
|
||||||
|
reactHooks.configs['recommended-latest'],
|
||||||
|
jsxA11Y.flatConfigs.recommended,
|
||||||
|
importPlugin.flatConfigs.react,
|
||||||
|
// @ts-expect-error -- For some reason the formatjs package exports an empty object?
|
||||||
|
formatjs.configs.strict,
|
||||||
|
{
|
||||||
|
languageOptions: {
|
||||||
|
globals: {
|
||||||
|
...globals.browser,
|
||||||
|
},
|
||||||
|
|
||||||
|
parser: tseslint.parser,
|
||||||
|
ecmaVersion: 2021,
|
||||||
|
sourceType: 'module',
|
||||||
|
},
|
||||||
|
|
||||||
|
settings: {
|
||||||
|
react: {
|
||||||
|
version: 'detect',
|
||||||
|
},
|
||||||
|
|
||||||
|
'import/ignore': ['node_modules', '\\.(css|scss|json)$'],
|
||||||
|
|
||||||
|
'import/resolver': {
|
||||||
|
typescript: {},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
rules: {
|
||||||
|
'no-restricted-syntax': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
// eslint-disable-next-line no-restricted-syntax
|
||||||
|
selector: 'Literal[value=/•/], JSXText[value=/•/]',
|
||||||
|
// eslint-disable-next-line no-restricted-syntax
|
||||||
|
message: "Use '·' (middle dot) instead of '•' (bullet)",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
|
'formatjs/enforce-description': 'off', // description values not currently used
|
||||||
|
'formatjs/enforce-id': 'off', // Explicit IDs are used in the project
|
||||||
|
'formatjs/enforce-placeholders': 'off', // Issues in short_number.jsx
|
||||||
|
'formatjs/no-invalid-icu': 'error',
|
||||||
|
'formatjs/no-literal-string-in-jsx': 'off', // Should be looked at, but mainly flagging punctuation outside of strings
|
||||||
|
'formatjs/no-multiple-plurals': 'off', // Should be looked at
|
||||||
|
|
||||||
|
'jsx-a11y/click-events-have-key-events': 'off',
|
||||||
|
'jsx-a11y/label-has-associated-control': 'off',
|
||||||
|
'jsx-a11y/media-has-caption': 'off',
|
||||||
|
'jsx-a11y/no-autofocus': 'off',
|
||||||
|
'jsx-a11y/no-interactive-element-to-noninteractive-role': 'off',
|
||||||
|
'jsx-a11y/no-noninteractive-tabindex': 'off',
|
||||||
|
'jsx-a11y/no-static-element-interactions': [
|
||||||
|
'warn',
|
||||||
|
{
|
||||||
|
handlers: ['onClick'],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
|
'import/no-extraneous-dependencies': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
devDependencies: [
|
||||||
|
'eslint.config.mjs',
|
||||||
|
'config/webpack/**',
|
||||||
|
'app/javascript/mastodon/performance.js',
|
||||||
|
'app/javascript/mastodon/test_setup.js',
|
||||||
|
'app/javascript/**/__tests__/**',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'import/no-webpack-loader-syntax': 'error',
|
||||||
|
|
||||||
|
'react/jsx-filename-extension': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
extensions: ['.jsx', 'tsx'],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
|
'react/jsx-boolean-value': 'error',
|
||||||
|
'react/display-name': 'off',
|
||||||
|
'react/jsx-fragments': ['error', 'syntax'],
|
||||||
|
'react/jsx-equals-spacing': 'error',
|
||||||
|
'react/jsx-no-bind': 'error',
|
||||||
|
'react/jsx-no-useless-fragment': 'error',
|
||||||
|
'react/jsx-no-target-blank': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
allowReferrer: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'react/jsx-tag-spacing': 'error',
|
||||||
|
'react/jsx-wrap-multilines': 'error',
|
||||||
|
'react/self-closing-comp': 'error',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
files: [
|
||||||
|
'app/javascript/mastodon/common.js',
|
||||||
|
'app/javascript/mastodon/features/emoji/unicode_to_unified_name.js',
|
||||||
|
'app/javascript/mastodon/features/emoji/emoji_compressed.js',
|
||||||
|
'app/javascript/mastodon/features/emoji/unicode_to_filename.js',
|
||||||
|
'app/javascript/mastodon/service_worker/web_push_locales.js',
|
||||||
|
'**/*.config.js',
|
||||||
|
'**/.*rc.js',
|
||||||
|
'**/ide-helper.js',
|
||||||
|
'config/webpack/**/*',
|
||||||
|
'config/formatjs-formatter.js',
|
||||||
|
],
|
||||||
|
|
||||||
|
languageOptions: {
|
||||||
|
globals: {
|
||||||
|
...globals.commonjs,
|
||||||
|
...globals.node,
|
||||||
|
},
|
||||||
|
|
||||||
|
ecmaVersion: 5,
|
||||||
|
sourceType: 'commonjs',
|
||||||
|
},
|
||||||
|
|
||||||
|
rules: {
|
||||||
|
'import/no-commonjs': 'off',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
files: ['**/*.ts', '**/*.tsx'],
|
||||||
|
|
||||||
|
extends: [
|
||||||
|
tseslint.configs.strictTypeChecked,
|
||||||
|
tseslint.configs.stylisticTypeChecked,
|
||||||
|
react.configs.flat.recommended,
|
||||||
|
react.configs.flat['jsx-runtime'],
|
||||||
|
reactHooks.configs['recommended-latest'],
|
||||||
|
jsxA11Y.flatConfigs.recommended,
|
||||||
|
importPlugin.flatConfigs.react,
|
||||||
|
importPlugin.flatConfigs.typescript,
|
||||||
|
jsdoc.configs['flat/recommended-typescript'],
|
||||||
|
],
|
||||||
|
|
||||||
|
languageOptions: {
|
||||||
|
parserOptions: {
|
||||||
|
projectService: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
rules: {
|
||||||
|
// This is not needed as we use noImplicitReturns, which handles this in addition to understanding types
|
||||||
|
'consistent-return': 'off',
|
||||||
|
|
||||||
|
'formatjs/enforce-plural-rules': 'off',
|
||||||
|
|
||||||
|
'import/consistent-type-specifier-style': ['error', 'prefer-top-level'],
|
||||||
|
'import/no-default-export': 'warn',
|
||||||
|
|
||||||
|
'jsdoc/require-jsdoc': 'off',
|
||||||
|
|
||||||
|
'react/prefer-stateless-function': 'warn',
|
||||||
|
'react/function-component-definition': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
namedComponents: 'arrow-function',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'react/prop-types': 'off',
|
||||||
|
|
||||||
|
'@typescript-eslint/consistent-type-definitions': ['warn', 'interface'],
|
||||||
|
'@typescript-eslint/consistent-type-exports': 'error',
|
||||||
|
'@typescript-eslint/consistent-type-imports': 'error',
|
||||||
|
'@typescript-eslint/prefer-nullish-coalescing': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
ignorePrimitives: {
|
||||||
|
boolean: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'@typescript-eslint/no-restricted-imports': [
|
||||||
|
'warn',
|
||||||
|
{
|
||||||
|
name: 'react-redux',
|
||||||
|
importNames: ['useSelector', 'useDispatch'],
|
||||||
|
message:
|
||||||
|
'Use typed hooks `useAppDispatch` and `useAppSelector` instead.',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'@typescript-eslint/no-unused-vars': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
vars: 'all',
|
||||||
|
args: 'after-used',
|
||||||
|
destructuredArrayIgnorePattern: '^_',
|
||||||
|
ignoreRestSiblings: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'@typescript-eslint/restrict-template-expressions': [
|
||||||
|
'warn',
|
||||||
|
{
|
||||||
|
allowNumber: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
files: ['**/__tests__/*.js', '**/__tests__/*.jsx'],
|
||||||
|
|
||||||
|
languageOptions: {
|
||||||
|
globals: {
|
||||||
|
...globals.jest,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]);
|
26
package.json
26
package.json
|
@ -12,14 +12,14 @@
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build:development": "cross-env RAILS_ENV=development NODE_ENV=development ./bin/webpack",
|
"build:development": "cross-env RAILS_ENV=development NODE_ENV=development ./bin/webpack",
|
||||||
"build:production": "cross-env RAILS_ENV=production NODE_ENV=production ./bin/webpack",
|
"build:production": "cross-env RAILS_ENV=production NODE_ENV=production ./bin/webpack",
|
||||||
"fix:js": "eslint . --ext=.js,.jsx,.ts,.tsx --cache --report-unused-disable-directives --fix",
|
"fix:js": "eslint . --cache --fix",
|
||||||
"fix:css": "stylelint --fix \"**/*.{css,scss}\"",
|
"fix:css": "stylelint --fix \"**/*.{css,scss}\"",
|
||||||
"fix": "yarn fix:js && yarn fix:css",
|
"fix": "yarn fix:js && yarn fix:css",
|
||||||
"format": "prettier --write --log-level warn .",
|
"format": "prettier --write --log-level warn .",
|
||||||
"format:check": "prettier --check --ignore-unknown .",
|
"format:check": "prettier --check --ignore-unknown .",
|
||||||
"i18n:extract": "formatjs extract 'app/javascript/**/*.{js,jsx,ts,tsx}' --ignore '**/*.d.ts' --out-file app/javascript/mastodon/locales/en.json --format config/formatjs-formatter.js",
|
"i18n:extract": "formatjs extract 'app/javascript/**/*.{js,jsx,ts,tsx}' --ignore '**/*.d.ts' --out-file app/javascript/mastodon/locales/en.json --format config/formatjs-formatter.js",
|
||||||
"jest": "cross-env NODE_ENV=test jest",
|
"jest": "cross-env NODE_ENV=test jest",
|
||||||
"lint:js": "eslint . --ext=.js,.jsx,.ts,.tsx --cache --report-unused-disable-directives",
|
"lint:js": "cd $INIT_CWD && eslint --cache --report-unused-disable-directives",
|
||||||
"lint:css": "stylelint \"**/*.{css,scss}\"",
|
"lint:css": "stylelint \"**/*.{css,scss}\"",
|
||||||
"lint": "yarn lint:js && yarn lint:css",
|
"lint": "yarn lint:js && yarn lint:css",
|
||||||
"postversion": "git push --tags",
|
"postversion": "git push --tags",
|
||||||
|
@ -142,6 +142,7 @@
|
||||||
"workbox-window": "^7.0.0"
|
"workbox-window": "^7.0.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@eslint/js": "^9.23.0",
|
||||||
"@formatjs/cli": "^6.1.1",
|
"@formatjs/cli": "^6.1.1",
|
||||||
"@testing-library/dom": "^10.2.0",
|
"@testing-library/dom": "^10.2.0",
|
||||||
"@testing-library/jest-dom": "^6.0.0",
|
"@testing-library/jest-dom": "^6.0.0",
|
||||||
|
@ -173,19 +174,17 @@
|
||||||
"@types/requestidlecallback": "^0.3.5",
|
"@types/requestidlecallback": "^0.3.5",
|
||||||
"@types/webpack": "^4.41.33",
|
"@types/webpack": "^4.41.33",
|
||||||
"@types/webpack-env": "^1.18.4",
|
"@types/webpack-env": "^1.18.4",
|
||||||
"@typescript-eslint/eslint-plugin": "^8.0.0",
|
|
||||||
"@typescript-eslint/parser": "^8.0.0",
|
|
||||||
"babel-jest": "^29.5.0",
|
"babel-jest": "^29.5.0",
|
||||||
"eslint": "^8.41.0",
|
"eslint": "^9.23.0",
|
||||||
"eslint-define-config": "^2.0.0",
|
"eslint-import-resolver-typescript": "^4.2.5",
|
||||||
"eslint-import-resolver-typescript": "^3.5.5",
|
"eslint-plugin-formatjs": "^5.3.1",
|
||||||
"eslint-plugin-formatjs": "^5.0.0",
|
|
||||||
"eslint-plugin-import": "~2.31.0",
|
"eslint-plugin-import": "~2.31.0",
|
||||||
"eslint-plugin-jsdoc": "^50.0.0",
|
"eslint-plugin-jsdoc": "^50.6.9",
|
||||||
"eslint-plugin-jsx-a11y": "~6.10.0",
|
"eslint-plugin-jsx-a11y": "~6.10.2",
|
||||||
"eslint-plugin-promise": "~7.2.0",
|
"eslint-plugin-promise": "~7.2.1",
|
||||||
"eslint-plugin-react": "^7.33.2",
|
"eslint-plugin-react": "^7.37.4",
|
||||||
"eslint-plugin-react-hooks": "^5.0.0",
|
"eslint-plugin-react-hooks": "^5.2.0",
|
||||||
|
"globals": "^16.0.0",
|
||||||
"husky": "^9.0.11",
|
"husky": "^9.0.11",
|
||||||
"jest": "^29.5.0",
|
"jest": "^29.5.0",
|
||||||
"jest-environment-jsdom": "^29.5.0",
|
"jest-environment-jsdom": "^29.5.0",
|
||||||
|
@ -196,6 +195,7 @@
|
||||||
"stylelint-config-prettier-scss": "^1.0.0",
|
"stylelint-config-prettier-scss": "^1.0.0",
|
||||||
"stylelint-config-standard-scss": "^14.0.0",
|
"stylelint-config-standard-scss": "^14.0.0",
|
||||||
"typescript": "^5.0.4",
|
"typescript": "^5.0.4",
|
||||||
|
"typescript-eslint": "^8.28.0",
|
||||||
"webpack-dev-server": "^3.11.3"
|
"webpack-dev-server": "^3.11.3"
|
||||||
},
|
},
|
||||||
"resolutions": {
|
"resolutions": {
|
||||||
|
|
|
@ -1,43 +0,0 @@
|
||||||
/* eslint-disable import/no-commonjs */
|
|
||||||
|
|
||||||
// @ts-check
|
|
||||||
|
|
||||||
// @ts-ignore - This needs to be a CJS file (eslint does not yet support ESM configs), and TS is complaining we use require
|
|
||||||
const { defineConfig } = require('eslint-define-config');
|
|
||||||
|
|
||||||
module.exports = defineConfig({
|
|
||||||
extends: ['../.eslintrc.js'],
|
|
||||||
env: {
|
|
||||||
browser: false,
|
|
||||||
},
|
|
||||||
parserOptions: {
|
|
||||||
project: true,
|
|
||||||
tsconfigRootDir: __dirname,
|
|
||||||
ecmaFeatures: {
|
|
||||||
jsx: false,
|
|
||||||
},
|
|
||||||
ecmaVersion: 2021,
|
|
||||||
},
|
|
||||||
rules: {
|
|
||||||
// In the streaming server we need to delete some variables to ensure
|
|
||||||
// garbage collection takes place on the values referenced by those objects;
|
|
||||||
// The alternative is to declare the variable as nullable, but then we need
|
|
||||||
// to assert it's in existence before every use, which becomes much harder
|
|
||||||
// to maintain.
|
|
||||||
'no-delete-var': 'off',
|
|
||||||
|
|
||||||
// This overrides the base configuration for this rule to pick up
|
|
||||||
// dependencies for the streaming server from the correct package.json file.
|
|
||||||
'import/no-extraneous-dependencies': [
|
|
||||||
'error',
|
|
||||||
{
|
|
||||||
devDependencies: ['streaming/.eslintrc.cjs'],
|
|
||||||
optionalDependencies: false,
|
|
||||||
peerDependencies: false,
|
|
||||||
includeTypes: true,
|
|
||||||
packageDir: __dirname,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
'import/extensions': ['error', 'always'],
|
|
||||||
},
|
|
||||||
});
|
|
45
streaming/eslint.config.mjs
Normal file
45
streaming/eslint.config.mjs
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
// @ts-check
|
||||||
|
|
||||||
|
import globals from 'globals';
|
||||||
|
import tseslint from 'typescript-eslint';
|
||||||
|
|
||||||
|
// eslint-disable-next-line import/no-relative-packages -- Must import from the root
|
||||||
|
import { baseConfig } from '../eslint.config.mjs';
|
||||||
|
|
||||||
|
export default tseslint.config([
|
||||||
|
baseConfig,
|
||||||
|
{
|
||||||
|
languageOptions: {
|
||||||
|
globals: globals.node,
|
||||||
|
|
||||||
|
parser: tseslint.parser,
|
||||||
|
ecmaVersion: 2021,
|
||||||
|
sourceType: 'module',
|
||||||
|
},
|
||||||
|
|
||||||
|
settings: {
|
||||||
|
'import/ignore': ['node_modules', '\\.(json)$'],
|
||||||
|
'import/resolver': {
|
||||||
|
typescript: {},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
rules: {
|
||||||
|
// In the streaming server we need to delete some variables to ensure
|
||||||
|
// garbage collection takes place on the values referenced by those objects;
|
||||||
|
// The alternative is to declare the variable as nullable, but then we need
|
||||||
|
// to assert it's in existence before every use, which becomes much harder
|
||||||
|
// to maintain.
|
||||||
|
'no-delete-var': 'off',
|
||||||
|
|
||||||
|
'import/no-extraneous-dependencies': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
devDependencies: ['**/*.config.mjs'],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
|
'import/extensions': ['error', 'always'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]);
|
7
streaming/lint-staged.config.mjs
Normal file
7
streaming/lint-staged.config.mjs
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
const config = {
|
||||||
|
'*': 'prettier --ignore-unknown --write',
|
||||||
|
'*.{js,ts}': 'eslint --fix',
|
||||||
|
'**/*.ts': () => 'tsc -p tsconfig.json --noEmit',
|
||||||
|
};
|
||||||
|
|
||||||
|
export default config;
|
|
@ -31,14 +31,16 @@
|
||||||
"ws": "^8.12.1"
|
"ws": "^8.12.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@eslint/js": "^9.23.0",
|
||||||
"@types/cors": "^2.8.16",
|
"@types/cors": "^2.8.16",
|
||||||
"@types/express": "^4.17.17",
|
"@types/express": "^4.17.17",
|
||||||
"@types/pg": "^8.6.6",
|
"@types/pg": "^8.6.6",
|
||||||
"@types/uuid": "^10.0.0",
|
"@types/uuid": "^10.0.0",
|
||||||
"@types/ws": "^8.5.9",
|
"@types/ws": "^8.5.9",
|
||||||
"eslint-define-config": "^2.0.0",
|
"globals": "^16.0.0",
|
||||||
"pino-pretty": "^13.0.0",
|
"pino-pretty": "^13.0.0",
|
||||||
"typescript": "^5.0.4"
|
"typescript": "^5.0.4",
|
||||||
|
"typescript-eslint": "^8.28.0"
|
||||||
},
|
},
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"bufferutil": "^4.0.7",
|
"bufferutil": "^4.0.7",
|
||||||
|
|
|
@ -8,5 +8,5 @@
|
||||||
"tsBuildInfoFile": "../tmp/cache/streaming/tsconfig.tsbuildinfo",
|
"tsBuildInfoFile": "../tmp/cache/streaming/tsconfig.tsbuildinfo",
|
||||||
"paths": {}
|
"paths": {}
|
||||||
},
|
},
|
||||||
"include": ["./*.js", "./.eslintrc.cjs"]
|
"include": ["./*.js"]
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue