diff --git a/.changeset/orange-carrots-decide.md b/.changeset/orange-carrots-decide.md new file mode 100644 index 00000000000..731d785332d --- /dev/null +++ b/.changeset/orange-carrots-decide.md @@ -0,0 +1,10 @@ +--- +'cm6-graphql': patch +'codemirror-graphql': patch +'graphiql': patch +'@graphiql/toolkit': patch +'graphql-language-service': patch +'graphql-language-service-server': patch +--- + +clean all ESLint warnings, add `--max-warnings=0` and `--cache` flags diff --git a/.eslintrc.js b/.eslintrc.js index 2863e7bc28c..fddf6b572c9 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -14,9 +14,6 @@ module.exports = { parserOptions: { ecmaVersion: 6, sourceType: 'module', - ecmaFeatures: { - jsx: true, - }, }, settings: { react: { @@ -29,10 +26,7 @@ module.exports = { es6: true, node: true, browser: true, - jest: true, - 'jest/globals': true, }, - extends: [ 'eslint:recommended', 'plugin:import/recommended', @@ -107,7 +101,7 @@ module.exports = { 'no-script-url': 1, 'no-self-compare': 1, 'no-sequences': 1, - 'no-throw-literal': 1, + 'no-throw-literal': 'error', 'no-unmodified-loop-condition': 0, 'no-useless-call': 1, 'no-useless-concat': 1, @@ -215,7 +209,7 @@ module.exports = { 'no-useless-computed-key': 1, 'no-useless-constructor': 0, 'no-useless-rename': 1, - 'no-var': 1, + 'no-var': 'error', 'object-shorthand': 1, 'prefer-arrow-callback': [0, { allowNamedFunctions: true }], // prettier --list-different 'prefer-const': 1, @@ -230,7 +224,7 @@ module.exports = { 'import/no-duplicates': 'error', 'import/no-named-as-default': 'error', 'prefer-object-spread': 'error', - // react rules + // React rules 'react/no-unused-state': 'error', 'react/jsx-curly-brace-presence': 'error', 'react/jsx-boolean-value': 'error', @@ -258,8 +252,6 @@ module.exports = { 'error', { extensions: ['.tsx', '.jsx'], allow: 'as-needed' }, ], - // Jest rules - 'jest/no-conditional-expect': 0, 'unicorn/consistent-destructuring': 'error', 'prefer-destructuring': ['error', { VariableDeclarator: { object: true } }], @@ -300,11 +292,9 @@ module.exports = { '**/*.spec.{ts,js.jsx.tsx}', ], extends: ['plugin:jest/recommended'], - env: { - 'jest/globals': true, - }, rules: { - 'jest/no-conditional-expect': 0, + 'jest/no-conditional-expect': 'off', + 'jest/expect-expect': ['error', { assertFunctionNames: ['expect*'] }], }, }, { diff --git a/.gitignore b/.gitignore index 1e3e7872751..ff592e79bbc 100644 --- a/.gitignore +++ b/.gitignore @@ -32,3 +32,4 @@ yarn-1.18.0.js .netlify examples/*/yarn.lock +.eslintcache diff --git a/examples/monaco-graphql-react-vite/src/App.tsx b/examples/monaco-graphql-react-vite/src/App.tsx index 2347e323c0b..11e71f6aea6 100644 --- a/examples/monaco-graphql-react-vite/src/App.tsx +++ b/examples/monaco-graphql-react-vite/src/App.tsx @@ -145,14 +145,13 @@ export default function App() { localStorage.setItem('variables', variablesModel.getValue()); }), ); - - // only run once on mount + // eslint-disable-next-line react-hooks/exhaustive-deps -- only run once on mount }, []); useEffect(() => { queryEditor?.addAction(queryAction); variablesEditor?.addAction(queryAction); - }, [variablesEditor]); + }, [queryEditor, variablesEditor]); /** * Handle the initial schema load */ diff --git a/package.json b/package.json index b71568af18b..7b8887d9af7 100644 --- a/package.json +++ b/package.json @@ -51,7 +51,7 @@ "dev-graphiql": "yarn workspace graphiql dev", "e2e": "yarn run e2e:build && yarn workspace graphiql e2e", "e2e:build": "yarn build && yarn workspace graphiql run build-bundles-min", - "eslint": "eslint --ext=ts,js,jsx,tsx .", + "eslint": "eslint --max-warnings=0 --cache --ext=ts,js,jsx,tsx .", "format": "yarn eslint --fix && yarn pretty", "jest": "jest", "license-check": "jsgl --local ./", diff --git a/packages/cm6-graphql/__tests__/test.spec.ts b/packages/cm6-graphql/__tests__/test.spec.ts index 1facef1c521..a16d1ce446b 100644 --- a/packages/cm6-graphql/__tests__/test.spec.ts +++ b/packages/cm6-graphql/__tests__/test.spec.ts @@ -1,3 +1,4 @@ +/* eslint-disable jest/expect-expect */ import { graphqlLanguage } from '../dist/index.js'; import { fileTests } from '@lezer/generator/dist/test'; diff --git a/packages/codemirror-graphql/src/index.d.ts b/packages/codemirror-graphql/src/index.d.ts index 80e15b64dd5..7866c87f5a5 100644 --- a/packages/codemirror-graphql/src/index.d.ts +++ b/packages/codemirror-graphql/src/index.d.ts @@ -1,7 +1,7 @@ import 'codemirror/addon/hint/show-hint'; declare module 'codemirror' { - var Init: any; + let Init: any; interface Editor { doc: CodeMirror.Doc; diff --git a/packages/codemirror-graphql/src/utils/__tests__/jsonParse-test.ts b/packages/codemirror-graphql/src/utils/__tests__/jsonParse-test.ts index 65dc9b08e09..6d2a8044e00 100644 --- a/packages/codemirror-graphql/src/utils/__tests__/jsonParse-test.ts +++ b/packages/codemirror-graphql/src/utils/__tests__/jsonParse-test.ts @@ -9,7 +9,7 @@ import jsonParse, { ParseTokenOutput } from '../jsonParse'; describe('jsonParse', () => { - function checkEscapedString( + function expectEscapedString( str: string, key: ParseTokenOutput, value: ParseTokenOutput, @@ -21,17 +21,17 @@ describe('jsonParse', () => { } it('correctly parses escaped strings', () => { - checkEscapedString( + expectEscapedString( '{ "test": "\\"" }', { kind: 'String', start: 2, end: 8, value: 'test' }, { kind: 'String', start: 10, end: 14, value: '"' }, ); - checkEscapedString( + expectEscapedString( '{ "test": "\\\\" }', { kind: 'String', start: 2, end: 8, value: 'test' }, { kind: 'String', start: 10, end: 14, value: '\\' }, ); - checkEscapedString( + expectEscapedString( '{ "slash": "\\/" }', { kind: 'String', start: 2, end: 9, value: 'slash' }, { kind: 'String', start: 11, end: 15, value: '/' }, diff --git a/packages/codemirror-graphql/src/variables/__tests__/hint-test.ts b/packages/codemirror-graphql/src/variables/__tests__/hint-test.ts index de3fdd1aec4..1ada1754e89 100644 --- a/packages/codemirror-graphql/src/variables/__tests__/hint-test.ts +++ b/packages/codemirror-graphql/src/variables/__tests__/hint-test.ts @@ -48,7 +48,7 @@ function getHintSuggestions( }); } -function checkSuggestions(source: string[], suggestions?: IHint[]) { +function expectSuggestions(source: string[], suggestions?: IHint[]) { const titles = suggestions?.map(suggestion => suggestion.text); expect(titles).toEqual(source); } @@ -62,7 +62,7 @@ describe('graphql-variables-hint', () => { it('provides correct initial token', async () => { const suggestions = await getHintSuggestions('', '', { line: 0, ch: 0 }); const initialKeywords = ['{']; - checkSuggestions(initialKeywords, suggestions?.list); + expectSuggestions(initialKeywords, suggestions?.list); }); it('provides correct field name suggestions', async () => { @@ -71,7 +71,7 @@ describe('graphql-variables-hint', () => { '{ ', { line: 0, ch: 2 }, ); - checkSuggestions(['"foo": ', '"bar": '], suggestions?.list); + expectSuggestions(['"foo": ', '"bar": '], suggestions?.list); }); it('provides correct variable suggestion indentation', async () => { @@ -90,7 +90,7 @@ describe('graphql-variables-hint', () => { '{\n ba', { line: 1, ch: 4 }, ); - checkSuggestions(['"bar": '], suggestions?.list); + expectSuggestions(['"bar": '], suggestions?.list); expect(suggestions?.from).toEqual({ line: 1, ch: 2, sticky: null }); expect(suggestions?.to).toEqual({ line: 1, ch: 4, sticky: null }); }); @@ -101,7 +101,7 @@ describe('graphql-variables-hint', () => { '{\n "', { line: 1, ch: 4 }, ); - checkSuggestions(['"foo": ', '"bar": '], suggestions?.list); + expectSuggestions(['"foo": ', '"bar": '], suggestions?.list); expect(suggestions?.from).toEqual({ line: 1, ch: 2, sticky: null }); expect(suggestions?.to).toEqual({ line: 1, ch: 3, sticky: null }); }); @@ -113,7 +113,7 @@ describe('graphql-variables-hint', () => { { line: 1, ch: 12 }, ); const TestEnum = TestSchema.getType('TestEnum'); - checkSuggestions( + expectSuggestions( (TestEnum as GraphQLEnumType) ?.getValues() .map(value => `"${value.name}"`), @@ -127,7 +127,7 @@ describe('graphql-variables-hint', () => { '{\n "myInput": ', { line: 1, ch: 13 }, ); - checkSuggestions(['{'], suggestions?.list); + expectSuggestions(['{'], suggestions?.list); }); it('provides Input Object fields', async () => { @@ -137,7 +137,7 @@ describe('graphql-variables-hint', () => { { line: 2, ch: 4 }, ); const TestInput = TestSchema.getType('TestInput'); - checkSuggestions( + expectSuggestions( Object.keys((TestInput as GraphQLInputObjectType).getFields()).map( name => `"${name}": `, ), @@ -153,7 +153,7 @@ describe('graphql-variables-hint', () => { '{\n "myInput": {\n bool', { line: 2, ch: 8 }, ); - checkSuggestions(['"boolean": ', '"listBoolean": '], suggestions?.list); + expectSuggestions(['"boolean": ', '"listBoolean": '], suggestions?.list); expect(suggestions?.from).toEqual({ line: 2, ch: 4, sticky: null }); expect(suggestions?.to).toEqual({ line: 2, ch: 8, sticky: null }); }); @@ -164,6 +164,6 @@ describe('graphql-variables-hint', () => { '{\n "myInput": {\n "boolean": ', { line: 2, ch: 15 }, ); - checkSuggestions(['true', 'false'], suggestions?.list); + expectSuggestions(['true', 'false'], suggestions?.list); }); }); diff --git a/packages/graphiql-toolkit/src/create-fetcher/__tests__/lib.spec.ts b/packages/graphiql-toolkit/src/create-fetcher/__tests__/lib.spec.ts index c3bbc72e08e..26695d6f8ef 100644 --- a/packages/graphiql-toolkit/src/create-fetcher/__tests__/lib.spec.ts +++ b/packages/graphiql-toolkit/src/create-fetcher/__tests__/lib.spec.ts @@ -105,6 +105,7 @@ describe('missing graphql-ws dependency', () => { it('should throw a nice error', () => { jest.resetModules(); jest.doMock('graphql-ws', () => { + // eslint-disable-next-line no-throw-literal throw { code: 'MODULE_NOT_FOUND' }; }); diff --git a/packages/graphiql/.eslintrc.js.old b/packages/graphiql/.eslintrc.js.old deleted file mode 100644 index dedce2d68cb..00000000000 --- a/packages/graphiql/.eslintrc.js.old +++ /dev/null @@ -1,298 +0,0 @@ -module.exports = { - parser: '@typescript-eslint/parser', - plugins: ['jest', 'react', '@typescript-eslint'], - settings: { - react: { - version: '0.15.0', - }, - }, - env: { - browser: true, - es6: true, - node: true, - jest: true, - }, - extends: ['prettier', 'plugin:@typescript-eslint/eslint-recommended', 'plugin:@typescript-eslint/recommended'], - parserOptions: { - arrowFunctions: true, - binaryLiterals: true, - blockBindings: true, - classes: true, - defaultParams: true, - destructuring: true, - experimentalObjectRestSpread: true, - forOf: true, - generators: true, - globalReturn: true, - jsx: true, - modules: true, - objectLiteralComputedProperties: true, - objectLiteralDuplicateProperties: true, - objectLiteralShorthandMethods: true, - objectLiteralShorthandProperties: true, - octalLiterals: true, - regexUFlag: true, - regexYFlag: true, - restParams: true, - spread: true, - superInFunctions: true, - templateStrings: true, - unicodeCodePointEscapes: true, - }, - rules: { - 'react/jsx-boolean-value': 'error', - 'react/jsx-handler-names': 'error', - 'react/jsx-key': 'error', - 'react/jsx-no-duplicate-props': 'error', - 'react/jsx-no-literals': 'error', - 'react/jsx-no-undef': 'error', - 'react/jsx-pascal-case': 'error', - 'react/jsx-uses-react': 'error', - 'react/jsx-uses-vars': 'error', - 'react/no-deprecated': 'error', - 'react/no-did-mount-set-state': 'error', - 'react/no-did-update-set-state': 'error', - 'react/no-direct-mutation-state': 'error', - 'react/no-string-refs': 'error', - 'react/no-unknown-property': 'error', - 'react/prop-types': [ - 'error', - { - ignore: ['children'], - }, - ], - 'react/prefer-es6-class': 'error', - 'react/prefer-stateless-function': 'error', - 'react/react-in-jsx-scope': 'error', - 'react/self-closing-comp': 'error', - 'react/sort-comp': [ - 'error', - { - order: ['static-methods', 'lifecycle', 'render', 'everything-else'], - }, - ], - // temporary - 'react/no-find-dom-node': 'warn', - 'no-constant-condition': 'error', - 'no-control-regex': 'error', - 'no-debugger': 'warn', - 'no-dupe-args': 'error', - 'no-dupe-keys': 'error', - 'no-duplicate-case': 'error', - 'no-empty': 'error', - 'no-empty-character-class': 'error', - 'no-ex-assign': 'error', - 'no-extra-boolean-cast': 'error', - 'no-func-assign': 'error', - 'no-inner-declarations': ['error', 'functions'], - 'no-invalid-regexp': 'error', - 'no-irregular-whitespace': 'error', - 'no-obj-calls': 'error', - 'no-regex-spaces': 'error', - 'no-sparse-arrays': 'error', - 'no-unreachable': 'error', - 'no-unsafe-negation': 'error', - 'use-isnan': 'error', - 'valid-typeof': 'error', - 'block-scoped-var': 'off', - complexity: 'off', - 'consistent-return': 'off', - curly: ['error', 'all'], - 'default-case': 'off', - 'dot-notation': 'off', - eqeqeq: ['error', 'smart'], - 'guard-for-in': 'error', - 'no-alert': 'error', - 'no-caller': 'error', - 'no-div-regex': 'error', - 'no-else-return': 'error', - 'no-eq-null': 'off', - 'no-eval': 'error', - 'no-extend-native': 'error', - 'no-extra-bind': 'error', - 'no-fallthrough': 'error', - 'no-global-assign': 'error', - 'no-implicit-coercion': 'error', - 'no-implied-eval': 'error', - 'no-invalid-this': 'off', - 'no-iterator': 'error', - 'no-labels': [ - 'error', - { - allowLoop: true, - }, - ], - 'no-lone-blocks': 'error', - 'no-loop-func': 'off', - 'no-multi-str': 'error', - 'no-new': 'error', - 'no-new-func': 'off', - 'no-new-wrappers': 'error', - 'no-octal': 'error', - 'no-octal-escape': 'error', - 'no-param-reassign': 'error', - 'no-proto': 'error', - 'no-redeclare': 'error', - 'no-return-assign': 'error', - 'no-script-url': 'error', - 'no-self-compare': 'off', - 'no-sequences': 'error', - 'no-throw-literal': 'error', - 'no-unused-expressions': 'error', - 'no-useless-call': 'error', - 'no-useless-escape': 'error', - 'no-useless-return': 'error', - 'no-void': 'error', - 'no-warning-comments': 'off', - 'no-with': 'error', - radix: 'error', - 'vars-on-top': 'off', - yoda: [ - 'error', - 'never', - { - exceptRange: true, - }, - ], - strict: 'off', - 'init-declarations': 'off', - 'no-delete-var': 'error', - 'no-label-var': 'error', - 'no-shadow': 'error', - 'no-shadow-restricted-names': 'error', - 'no-undef': 'error', - 'no-undef-init': 'error', - 'no-undefined': 'off', - 'no-unused-vars': [ - 'error', - { - vars: 'all', - args: 'after-used', - argsIgnorePattern: '^_', - }, - ], - 'no-use-before-define': 'off', - 'callback-return': 'error', - 'handle-callback-err': ['error', 'error'], - 'no-mixed-requires': ['error', true], - 'no-new-require': 'error', - 'no-path-concat': 'error', - 'no-process-env': 'off', - 'no-process-exit': 'off', - 'no-restricted-modules': 'off', - 'no-sync': 'error', - camelcase: [ - 'error', - { - properties: 'always', - }, - ], - 'consistent-this': 'off', - 'func-names': 'off', - 'func-style': 'off', - 'id-length': 'off', - 'id-match': ['error', '^(?:_?[a-zA-Z0-9]*)|[_A-Z0-9]+$'], - 'lines-around-comment': 'off', - 'max-depth': 'off', - 'max-nested-callbacks': 'off', - 'max-params': 'off', - 'max-statements': 'off', - 'new-cap': 'off', - 'no-array-constructor': 'error', - 'no-bitwise': 'off', - 'no-continue': 'off', - 'no-inline-comments': 'off', - 'no-lonely-if': 'error', - 'no-nested-ternary': 'off', - 'no-new-object': 'error', - 'no-plusplus': 'off', - 'no-tabs': 'error', - 'no-ternary': 'off', - 'no-underscore-dangle': 'off', - 'no-unneeded-ternary': 'error', - 'one-var': ['error', 'never'], - 'operator-assignment': ['error', 'always'], - 'padding-line-between-statements': 'off', - quotes: [ - 'error', - 'single', - { - avoidEscape: true, - allowTemplateLiterals: true, - }, - ], - 'sort-vars': 'off', - 'spaced-comment': ['error', 'always'], - 'no-class-assign': 'error', - 'no-const-assign': 'error', - 'no-this-before-super': 'error', - 'no-var': 'error', - 'object-shorthand': ['error', 'always'], - 'prefer-arrow-callback': 'error', - 'prefer-const': 'error', - 'prefer-spread': 'off', - 'require-yield': 'error', - 'array-bracket-newline': 'off', - 'array-bracket-spacing': 'off', - 'array-element-newline': 'off', - 'arrow-parens': 'off', - 'arrow-spacing': 'off', - 'block-spacing': 'off', - 'brace-style': 'off', - 'comma-dangle': 'off', - 'comma-spacing': 'off', - 'comma-style': 'off', - 'computed-property-spacing': 'off', - 'dot-location': 'off', - 'eol-last': 'off', - 'func-call-spacing': 'off', - 'function-paren-newline': 'off', - 'generator-star-spacing': 'off', - 'implicit-arrow-linebreak': 'off', - indent: 'off', - 'jsx-quotes': 'off', - 'key-spacing': 'off', - 'keyword-spacing': 'off', - 'linebreak-style': 'error', - 'max-len': 'off', - 'multiline-ternary': 'off', - 'newline-per-chained-call': 'off', - 'new-parens': 'off', - 'no-confusing-arrow': 'off', - 'no-extra-parens': 'off', - 'no-extra-semi': 'off', - 'no-floating-decimal': 'off', - 'no-mixed-operators': 'off', - 'no-mixed-spaces-and-tabs': 'off', - 'no-multi-spaces': 'off', - 'no-multiple-empty-lines': 'off', - 'no-spaced-func': 'off', - 'no-trailing-spaces': 'off', - 'no-unexpected-multiline': 'error', - 'no-whitespace-before-property': 'off', - 'nonblock-statement-body-position': 'off', - 'object-curly-newline': 'off', - 'object-curly-spacing': [0, 'always'], - 'object-property-newline': 'off', - 'one-var-declaration-per-line': 'off', - 'operator-linebreak': 'off', - 'padded-blocks': 'off', - 'quote-props': 'off', - 'rest-spread-spacing': 'off', - semi: 'off', - 'semi-spacing': 'off', - 'semi-style': 'off', - 'space-before-blocks': 'off', - 'space-before-function-paren': 'off', - 'space-in-parens': 'off', - 'space-infix-ops': 'off', - 'space-unary-ops': 'off', - 'switch-colon-spacing': 'off', - 'template-curly-spacing': 'off', - 'template-tag-spacing': 'off', - 'unicode-bom': 'off', - 'wrap-iife': 'off', - 'wrap-regex': 'off', - 'yield-star-spacing': 'off', - }, -}; diff --git a/packages/graphql-language-service-server/src/MessageProcessor.ts b/packages/graphql-language-service-server/src/MessageProcessor.ts index 61d6068297d..12fadaa1cdb 100644 --- a/packages/graphql-language-service-server/src/MessageProcessor.ts +++ b/packages/graphql-language-service-server/src/MessageProcessor.ts @@ -925,10 +925,10 @@ export class MessageProcessor { } } async _cacheSchemaFile( - uri: UnnormalizedTypeDefPointer, + _uri: UnnormalizedTypeDefPointer, project: GraphQLProjectConfig, ) { - uri = uri.toString(); + const uri = _uri.toString(); const isFileUri = existsSync(uri); let version = 1; @@ -939,7 +939,7 @@ export class MessageProcessor { if (schemaDocument) { version = schemaDocument.version++; } - const schemaText = readFileSync(uri, { encoding: 'utf-8' }); + const schemaText = readFileSync(uri, 'utf8'); this._cacheSchemaText(schemaUri, schemaText, version); } } diff --git a/packages/graphql-language-service/src/interface/getDiagnostics.ts b/packages/graphql-language-service/src/interface/getDiagnostics.ts index 19b33fa2ab4..6b88cfd3785 100644 --- a/packages/graphql-language-service/src/interface/getDiagnostics.ts +++ b/packages/graphql-language-service/src/interface/getDiagnostics.ts @@ -64,26 +64,25 @@ export function getDiagnostics( externalFragments?: FragmentDefinitionNode[] | string, ): Array { let ast = null; + let fragments = ''; if (externalFragments) { - if (typeof externalFragments === 'string') { - query += '\n\n' + externalFragments; - } else { - query += - '\n\n' + - externalFragments.reduce((agg, node) => { - agg += print(node) + '\n\n'; - return agg; - }, ''); - } + fragments = + typeof externalFragments === 'string' + ? externalFragments + : externalFragments.reduce( + (acc, node) => acc + print(node) + '\n\n', + '', + ); } + const enhancedQuery = fragments ? `${query}\n\n${fragments}` : query; try { - ast = parse(query); + ast = parse(enhancedQuery); } catch (error) { if (error instanceof GraphQLError) { const range = getRange( error.locations?.[0] ?? { line: 0, column: 0 }, - query, + enhancedQuery, ); return [