Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(linting): Update versions and avoid {} #10266

Merged
merged 17 commits into from
Mar 28, 2024
Merged
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
22 changes: 22 additions & 0 deletions .changesets/10266.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
- chore(linting): Update versions and avoid `{}` (#10266) by @Josh-Walker-GM

This PR updates the versions of the `eslint` and the `@typescript-eslint` packages from v5 to v7. The primary motivation for this change is that you no longer see the:
```
=============

WARNING: You are currently running a version of TypeScript which is not officially supported by @typescript-eslint/typescript-estree.

You may find that it works just fine, or you may not.

SUPPORTED TYPESCRIPT VERSIONS: >=3.3.1 <5.2.0

YOUR TYPESCRIPT VERSION: 5.3.3

Please only submit bug reports when using the officially supported version.

=============
```
warning in your terminal when you run `yarn rw lint`.

This is a major upgrade of the `@typescript-eslint` package and although we think it is unlikely to introduce a breaking change for you we would recommend that you read the associated documentation. The v6 upgrade can be found [here](https://typescript-eslint.io/blog/announcing-typescript-eslint-v6/) and the v7 one [here](https://typescript-eslint.io/blog/announcing-typescript-eslint-v7/).

4 changes: 2 additions & 2 deletions packages/eslint-config/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@
"@redwoodjs/eslint-plugin": "workspace:*",
"@redwoodjs/internal": "workspace:*",
"@redwoodjs/project-config": "workspace:*",
"@typescript-eslint/eslint-plugin": "5.62.0",
"@typescript-eslint/parser": "5.62.0",
"@typescript-eslint/eslint-plugin": "7.3.1",
"@typescript-eslint/parser": "7.3.1",
"eslint": "8.57.0",
"eslint-config-prettier": "9.1.0",
"eslint-import-resolver-babel-module": "5.3.2",
Expand Down
23 changes: 13 additions & 10 deletions packages/eslint-config/shared.js
Original file line number Diff line number Diff line change
Expand Up @@ -151,22 +151,25 @@ module.exports = {
parser: '@typescript-eslint/parser',
extends: ['plugin:@typescript-eslint/recommended', 'prettier'],
rules: {
// 'recommended' rules we alter
'@typescript-eslint/no-explicit-any': 'warn',
'@typescript-eslint/no-var-requires': 'off',
'@typescript-eslint/explicit-function-return-type': 'off',
'@typescript-eslint/no-empty-interface': 'off',
'@typescript-eslint/explicit-module-boundary-types': 'off',
'@typescript-eslint/ban-types': 'warn',
'no-empty-function': 'off',
'@typescript-eslint/no-empty-function': 'off',
camelcase: 'off',
'@typescript-eslint/camelcase': 'off',
'no-use-before-define': 'off',
'@typescript-eslint/no-use-before-define': 'off',
'@typescript-eslint/prefer-namespace-keyword': 'off',
'@typescript-eslint/no-unused-vars': [
'error',
{ varsIgnorePattern: '^_', argsIgnorePattern: '^_' },
],
// Specific 'stylistic' rules we enable
'@typescript-eslint/adjacent-overload-signatures': 'error',
'@typescript-eslint/no-inferrable-types': 'error',
'@typescript-eslint/no-non-null-assertion': 'warn',
// Other non-grouped rules we alter
'valid-typeof': 'off',
camelcase: 'off',
'@typescript-eslint/camelcase': 'off',
'no-empty-function': 'off',
'no-use-before-define': 'off',
'@typescript-eslint/no-use-before-define': 'off',
},
},
{
Expand Down
13 changes: 7 additions & 6 deletions packages/eslint-plugin/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,21 +18,22 @@
"build:types": "tsc --build --verbose",
"build:watch": "nodemon --watch src --ext \"js,jsx,ts,tsx\" --ignore dist --exec \"yarn build\"",
"prepublishOnly": "NODE_ENV=production yarn build",
"test": "glob './src/**/__tests__/*.test.ts' --cmd='tsx --no-warnings --test' && echo",
"test:watch": "glob './src/**/__tests__/*.test.ts' --cmd='tsx --no-warnings --test --watch'"
"test": "vitest run",
"test:watch": "vitest watch"
},
"dependencies": {
"@typescript-eslint/utils": "5.62.0",
"@typescript-eslint/utils": "7.3.1",
"eslint": "8.57.0"
},
"devDependencies": {
"@redwoodjs/framework-tools": "workspace:*",
"@types/eslint": "8.56.6",
"@types/estree": "1.0.5",
"@typescript-eslint/parser": "5.62.0",
"glob": "10.3.10",
"@typescript-eslint/parser": "7.3.1",
"@typescript-eslint/rule-tester": "7.3.1",
"tsx": "4.7.1",
"typescript": "5.4.3"
"typescript": "5.4.3",
"vitest": "1.4.0"
},
"gitHead": "3905ed045508b861b495f8d5630d76c7a157d8f1"
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,7 @@
import { describe, it } from 'node:test'

import { RuleTester } from 'eslint'
import { RuleTester } from '@typescript-eslint/rule-tester'

import { processEnvComputedRule } from '../process-env-computed.js'

// @ts-expect-error - Types are wrong
RuleTester.describe = describe
// @ts-expect-error - Types are wrong
RuleTester.it = it

const ruleTester = new RuleTester()

ruleTester.run('process-env-computed', processEnvComputedRule, {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,9 @@
import { describe, it } from 'node:test'

import { RuleTester } from 'eslint'
import { RuleTester } from '@typescript-eslint/rule-tester'

import { serviceTypeAnnotations } from '../service-type-annotations.js'

// @ts-expect-error - Types are wrong
RuleTester.describe = describe
// @ts-expect-error - Types are wrong
RuleTester.it = it

const ruleTester = new RuleTester({
parser: require.resolve('@typescript-eslint/parser'),
parser: '@typescript-eslint/parser',
})

ruleTester.run('service-type-annotations', serviceTypeAnnotations, {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,8 @@
import { describe, it } from 'node:test'

import { ESLintUtils } from '@typescript-eslint/utils'
import { RuleTester } from '@typescript-eslint/rule-tester'

import { unsupportedRouteComponents } from '../unsupported-route-components.js'

ESLintUtils.RuleTester.describe = describe
ESLintUtils.RuleTester.it = it

const ruleTester = new ESLintUtils.RuleTester({
const ruleTester = new RuleTester({
parser: '@typescript-eslint/parser',
parserOptions: {
ecmaVersion: 'latest',
Expand Down
7 changes: 6 additions & 1 deletion packages/eslint-plugin/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
import type { ESLintUtils } from '@typescript-eslint/utils'

import { processEnvComputedRule } from './process-env-computed.js'
import { serviceTypeAnnotations } from './service-type-annotations.js'
import { unsupportedRouteComponents } from './unsupported-route-components.js'

export const rules = {
export const rules: Record<
string,
ESLintUtils.RuleModule<string, never[], ESLintUtils.RuleListener>
> = {
'process-env-computed': processEnvComputedRule,
'service-type-annotations': serviceTypeAnnotations,
'unsupported-route-components': unsupportedRouteComponents,
Expand Down
46 changes: 19 additions & 27 deletions packages/eslint-plugin/src/process-env-computed.ts
Original file line number Diff line number Diff line change
@@ -1,29 +1,18 @@
import type { Rule } from 'eslint'
import type { Identifier, MemberExpression } from 'estree'
import type { TSESTree } from '@typescript-eslint/utils'
import { ESLintUtils, AST_NODE_TYPES } from '@typescript-eslint/utils'

function isProcessEnv(node: unknown) {
const createRule = ESLintUtils.RuleCreator.withoutDocs

function isProcessEnv(node: TSESTree.Node) {
return (
isMemberExpression(node) &&
node.type === AST_NODE_TYPES.MemberExpression &&
hasName(node.object, 'process') &&
hasName(node.property, 'env')
)
}

function isIdentifier(node: unknown): node is Identifier {
return (
typeof node !== 'undefined' && (node as Identifier).type === 'Identifier'
)
}

function isMemberExpression(node: unknown): node is MemberExpression {
return (
typeof node !== 'undefined' &&
(node as MemberExpression).type === 'MemberExpression'
)
}

function hasName(node: unknown, name: string) {
return isIdentifier(node) && node.name === name
function hasName(node: TSESTree.Node, name: string) {
return node.type === AST_NODE_TYPES.Identifier && node.name === name
}

function isTestFile(filename: string) {
Expand All @@ -46,31 +35,34 @@ function isTestFile(filename: string) {
)
}

export const processEnvComputedRule: Rule.RuleModule = {
export const processEnvComputedRule = createRule({
meta: {
type: 'problem',
docs: {
description: 'Find computed member access on process.env',
},
// fixable: 'code',
messages: {
unexpected:
'Accessing process.env via array syntax will break in production. Use dot notation e.g. process.env.MY_ENV_VAR instead',
},
schema: [], // No additional configuration needed
},
defaultOptions: [],
create(context) {
return {
MemberExpression: function (node) {
if (
const matches =
isProcessEnv(node.object) &&
node.computed &&
!isTestFile(context.filename)
) {

if (matches) {
context.report({
message:
'Accessing process.env via array syntax will break in production. Use dot notation e.g. process.env.MY_ENV_VAR instead',
messageId: 'unexpected',
node,
// fix(fixer) {},
})
}
},
}
},
}
})
64 changes: 30 additions & 34 deletions packages/eslint-plugin/src/service-type-annotations.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,34 @@
import { basename } from 'path'
import { basename } from 'node:path'

import type { Identifier } from '@typescript-eslint/types/dist/generated/ast-spec'
import type { Rule } from 'eslint'
import type {
Declaration,
ImportDeclaration,
VariableDeclaration,
} from 'estree'
import type { TSESTree } from '@typescript-eslint/utils'
import { ESLintUtils, AST_NODE_TYPES } from '@typescript-eslint/utils'

export const serviceTypeAnnotations: Rule.RuleModule = {
const createRule = ESLintUtils.RuleCreator.withoutDocs

const capitalizeFirstLetter = (str: string) =>
str.charAt(0).toUpperCase() + str.slice(1)

export const serviceTypeAnnotations = createRule({
meta: {
docs: {
description:
'Sets the types on a query/mutation resolver function to the correct type',
},
messages: {
needsType:
'The query/mutation function ({{name}}) needs a type annotation of {{typeName}}.',
},
fixable: 'code',
type: 'suggestion',
schema: [],
},
defaultOptions: [],
create(context) {
const thisFilename = basename(context.filename)
const sansTS = thisFilename.replace('.ts', '')
const thisFileCorrespondingImport = `types/${sansTS}`

let importForThisFile: ImportDeclaration | null = null
let importForThisFile: TSESTree.ImportDeclaration | null = null
return {
// Make sure we have a reference to the import for the relative file
// which includes definitions for this service
Expand All @@ -25,7 +39,10 @@ export const serviceTypeAnnotations: Rule.RuleModule = {

// Then start looking at every exported fn/const
ExportNamedDeclaration(node) {
if (!node.declaration || !isVariableDeclaration(node.declaration)) {
if (
!node.declaration ||
node.declaration.type !== AST_NODE_TYPES.VariableDeclaration
) {
return
}

Expand Down Expand Up @@ -54,7 +71,7 @@ export const serviceTypeAnnotations: Rule.RuleModule = {
}

// Switch from the estree type to the typescript-eslint type
const tsID = vd.id as Identifier
const tsID = vd.id as TSESTree.Identifier

// If there's no type annotation, then we should add one
if (!tsID.typeAnnotation) {
Expand Down Expand Up @@ -142,25 +159,4 @@ export const serviceTypeAnnotations: Rule.RuleModule = {
},
}
},
meta: {
docs: {
description:
'Sets the types on a query/mutation resolver function to the correct type',
recommended: false,
},
messages: {
needsType:
'The query/mutation function ({{name}}) needs a type annotation of {{typeName}}.',
},
fixable: 'code',
type: 'suggestion',
},
}

const capitalizeFirstLetter = (str: string) =>
str.charAt(0).toUpperCase() + str.slice(1)

const isVariableDeclaration = (
node: Declaration,
): node is VariableDeclaration =>
typeof node !== 'undefined' && 'declarations' in node
})
2 changes: 1 addition & 1 deletion packages/eslint-plugin/src/unsupported-route-components.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export const unsupportedRouteComponents = createRule({
type: 'problem',
docs: {
description: 'Find unsupported route components',
recommended: 'error',
recommended: 'recommended',
Josh-Walker-GM marked this conversation as resolved.
Show resolved Hide resolved
},
messages: {
unexpected:
Expand Down
2 changes: 2 additions & 0 deletions packages/eslint-plugin/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
{
"extends": "../../tsconfig.compilerOption.json",
"compilerOptions": {
"moduleResolution": "NodeNext",
"module": "NodeNext",
"strict": true,
"rootDir": "src",
"outDir": "dist",
Expand Down
10 changes: 10 additions & 0 deletions packages/eslint-plugin/vitest.config.mts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { defineConfig } from 'vitest/config'

export default defineConfig({
test: {
// Globals are enabled for the benefit of '@typescript-eslint/rule-tester'
globals: true
},
})


5 changes: 3 additions & 2 deletions packages/router/src/skipNav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@ import * as React from 'react'

// Original Code Source @reach/polymorphic
// https://github.com/reach/reach-ui/blob/dev/packages/polymorphic/src/reach-polymorphic.ts
// We updated three instances of type "{}" to "object" to avoid linting errors

type Merge<P1 = {}, P2 = {}> = Omit<P1, keyof P2> & P2
type Merge<P1 = object, P2 = object> = Omit<P1, keyof P2> & P2
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Happy to be overruled on the object's here


type ForwardRefExoticComponent<E, OwnProps> = React.ForwardRefExoticComponent<
Merge<
Expand All @@ -21,7 +22,7 @@ type ForwardRefExoticComponent<E, OwnProps> = React.ForwardRefExoticComponent<

interface ForwardRefComponent<
IntrinsicElementString,
OwnProps = {},
OwnProps = object,
/*
* Extends original type to ensure built in React types play nice with
* polymorphic components still e.g. `React.ElementRef` etc.
Expand Down
2 changes: 1 addition & 1 deletion packages/structure/src/x/vscode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ export class TreeItem2Wrapper {
constructor(
public item: TreeItem2,
public parent?: TreeItem2Wrapper,
public indexInParent: number = 0,
public indexInParent = 0,
) {}
@lazy() get keys(): string[] {
if (!this.parent) {
Expand Down
2 changes: 2 additions & 0 deletions tasks/linting-diff/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
differences.json
log.txt
Loading
Loading