diff --git a/.eslintrc.js b/.eslintrc.js index 7415e3a..cabc396 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,3 +1,3 @@ module.exports = { extends: './index.js', -} +}; diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 0000000..11b703a --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,34 @@ +name: ESLint + +on: + pull_request: + types: [opened, synchronize] + +concurrency: + group: eslint-${{ github.ref }} + cancel-in-progress: true + +jobs: + lint: + runs-on: ubuntu-latest + env: + CI: true + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Node + uses: actions/setup-node@v4 + with: + node-version: 20 + + - name: Run npm install + if: steps.cache-node-modules.outputs.cache-hit != 'true' + uses: nick-fields/retry@3f757583fb1b1f940bc8ef4bf4734c8dc02a5847 + with: + timeout_minutes: 30 + max_attempts: 3 + command: npm ci + + - name: Run ESLint + run: npm run lint diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..e87c766 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,34 @@ +name: Jest unit tests + +on: + pull_request: + types: [opened, synchronize] + +concurrency: + group: jest-${{ github.ref }} + cancel-in-progress: true + +jobs: + jest: + runs-on: ubuntu-latest + env: + CI: true + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Node + uses: actions/setup-node@v4 + with: + node-version: 20 + + - name: Run npm install + if: steps.cache-node-modules.outputs.cache-hit != 'true' + uses: nick-fields/retry@3f757583fb1b1f940bc8ef4bf4734c8dc02a5847 + with: + timeout_minutes: 30 + max_attempts: 3 + command: npm ci + + - name: Run Jest tests + run: npm run test diff --git a/eslint-plugin-expensify/prefer-at.js b/eslint-plugin-expensify/prefer-at.js index c7c1056..3133419 100644 --- a/eslint-plugin-expensify/prefer-at.js +++ b/eslint-plugin-expensify/prefer-at.js @@ -1,7 +1,7 @@ -const { AST_NODE_TYPES, ESLintUtils } = require('@typescript-eslint/utils'); +const {AST_NODE_TYPES, ESLintUtils} = require('@typescript-eslint/utils'); const message = require('./CONST').MESSAGE.PREFER_AT; -const { isLeftHandSide } = require('./utils/is-left-hand-side'); +const {isLeftHandSide} = require('./utils/is-left-hand-side'); module.exports = { meta: { @@ -34,7 +34,9 @@ module.exports = { return null; case AST_NODE_TYPES.BinaryExpression: + // eslint-disable-next-line no-case-declarations const left = parseExpression(node.left); + // eslint-disable-next-line no-case-declarations const right = parseExpression(node.right); if (left !== null && right !== null) { return `(${left} ${node.operator} ${right})`; @@ -42,6 +44,7 @@ module.exports = { return null; case AST_NODE_TYPES.UnaryExpression: + // eslint-disable-next-line no-case-declarations const argument = parseExpression(node.argument); if (argument !== null) { return `${node.operator}${argument}`; @@ -70,49 +73,52 @@ module.exports = { } function checkNode(node) { - if (node.type === AST_NODE_TYPES.MemberExpression && node.property) { - if (!isArrayType(node.object)) { - return; - } + if (node.type !== AST_NODE_TYPES.MemberExpression || !node.property) { + return; + } - // Skip if the property is a method (like a?.map) - if (node.parent && node.parent.type === AST_NODE_TYPES.CallExpression && node.parent.callee === node) { - return; - } + if (!isArrayType(node.object)) { + return; + } - // Skip if the node is part of an assignment expression - if (isLeftHandSide(node)) { - return; - } + // Skip if the property is a method (like a?.map) + if (node.parent && node.parent.type === AST_NODE_TYPES.CallExpression && node.parent.callee === node) { + return; + } - const indexExpression = parseExpression(node.property); - - if (indexExpression !== null && indexExpression !== 'length' && indexExpression !== 'at') { - context.report({ - node, - message, - fix(fixer) { - const objectText = getSourceCode(node.object); - return fixer.replaceText(node, `${objectText}.at(${getExpressionWithUpdatedBrackets(indexExpression)})`); - }, - }); - } + // Skip if the node is part of an assignment expression + if (isLeftHandSide(node)) { + return; + } + + const indexExpression = parseExpression(node.property); + + if (indexExpression !== null && indexExpression !== 'length' && indexExpression !== 'at') { + context.report({ + node, + message, + fix(fixer) { + const objectText = getSourceCode(node.object); + return fixer.replaceText(node, `${objectText}.at(${getExpressionWithUpdatedBrackets(indexExpression)})`); + }, + }); } } function shouldIgnoreNode(node) { return ( - node.parent && - node.parent.type === AST_NODE_TYPES.MemberExpression && - node.parent.property === node + node.parent + && node.parent.type === AST_NODE_TYPES.MemberExpression + && node.parent.property === node ); } return { MemberExpression(node) { - if (!shouldIgnoreNode(node)) { - checkNode(node); + if (shouldIgnoreNode(node)) { + return; } + checkNode(node); }, }; }, diff --git a/eslint-plugin-expensify/prefer-type-fest.js b/eslint-plugin-expensify/prefer-type-fest.js index 2028d1b..89fdec8 100644 --- a/eslint-plugin-expensify/prefer-type-fest.js +++ b/eslint-plugin-expensify/prefer-type-fest.js @@ -17,12 +17,13 @@ const rule = { return { Program(node) { // Find type-fest import declarations - node.body.forEach(statement => { - if (statement.type === 'ImportDeclaration' && statement.source.value === 'type-fest') { + node.body.forEach((statement) => { + if (statement.type !== 'ImportDeclaration' || statement.source.value !== 'type-fest') { + return; + } typeFestImport = statement; - } }); - }, + }, TSIndexedAccessType(node) { const objectType = node.objectType; const indexType = node.indexType; @@ -54,7 +55,7 @@ const rule = { const fixes = [fixer.replaceText(node, `ValueOf`)]; fixes.push(...addNamedImport(context, fixer, typeFestImport, 'ValueOf', 'type-fest', true)); return fixes; - } + }, }); } } @@ -68,7 +69,7 @@ const rule = { const fixes = [fixer.replaceText(node, `TupleToUnion`)]; fixes.push(...addNamedImport(context, fixer, typeFestImport, 'TupleToUnion', 'type-fest', true)); return fixes; - } + }, }); } } @@ -89,7 +90,7 @@ const rule = { const fixes = [fixer.replaceText(node, `ValueOf`)]; fixes.push(...addNamedImport(context, fixer, typeFestImport, 'ValueOf', 'type-fest', true)); return fixes; - } + }, }); } } @@ -103,7 +104,7 @@ const rule = { const fixes = [fixer.replaceText(node, `TupleToUnion`)]; fixes.push(...addNamedImport(context, fixer, typeFestImport, 'TupleToUnion', 'type-fest', true)); return fixes; - } + }, }); } } diff --git a/eslint-plugin-expensify/tests/prefer-type-fest.test.js b/eslint-plugin-expensify/tests/prefer-type-fest.test.js index 2fe9982..0bffaeb 100644 --- a/eslint-plugin-expensify/tests/prefer-type-fest.test.js +++ b/eslint-plugin-expensify/tests/prefer-type-fest.test.js @@ -51,18 +51,21 @@ ruleTester.run('prefer-type-fest', rule, { code: 'const CONST = { VIDEO_PLAYER: { PLAYBACK_SPEEDS: [0.25, 0.5, 1, 1.5, 2] } } as const; type Bad = (typeof CONST.VIDEO_PLAYER.PLAYBACK_SPEEDS)[number];', errors: [{message: PREFER_TYPE_FEST_TUPLE_TO_UNION}], parser: require.resolve('@typescript-eslint/parser'), + // eslint-disable-next-line max-len output: 'import type {TupleToUnion} from \'type-fest\';\nconst CONST = { VIDEO_PLAYER: { PLAYBACK_SPEEDS: [0.25, 0.5, 1, 1.5, 2] } } as const; type Bad = TupleToUnion;', }, { code: 'const TIMEZONES = [\'a\', \'b\'] as const; const test: Record = { a: \'a\', b: \'b\' };', errors: [{message: PREFER_TYPE_FEST_TUPLE_TO_UNION}], parser: require.resolve('@typescript-eslint/parser'), + // eslint-disable-next-line max-len output: 'import type {TupleToUnion} from \'type-fest\';\nconst TIMEZONES = [\'a\', \'b\'] as const; const test: Record> = { a: \'a\', b: \'b\' };', }, { code: 'import type {Something} from \'type-fest\';\nconst TIMEZONES = [\'a\', \'b\'] as const; const test: Record = { a: \'a\', b: \'b\' };', errors: [{message: PREFER_TYPE_FEST_TUPLE_TO_UNION}], parser: require.resolve('@typescript-eslint/parser'), + // eslint-disable-next-line max-len output: 'import type {Something, TupleToUnion} from \'type-fest\';\nconst TIMEZONES = [\'a\', \'b\'] as const; const test: Record> = { a: \'a\', b: \'b\' };', }, { @@ -76,6 +79,7 @@ ruleTester.run('prefer-type-fest', rule, { code: 'const CONST = { AVATAR_SIZE: { SMALL: \'small\', MEDIUM: \'medium\', LARGE: \'large\' } } as const; type Bad = { avatarSize?: (typeof CONST.AVATAR_SIZE)[keyof typeof CONST.AVATAR_SIZE]; }', errors: [{message: PREFER_TYPE_FEST_VALUE_OF}], parser: require.resolve('@typescript-eslint/parser'), + // eslint-disable-next-line max-len output: 'import type {ValueOf} from \'type-fest\';\nconst CONST = { AVATAR_SIZE: { SMALL: \'small\', MEDIUM: \'medium\', LARGE: \'large\' } } as const; type Bad = { avatarSize?: ValueOf; }', }, { @@ -94,6 +98,7 @@ ruleTester.run('prefer-type-fest', rule, { code: 'import somethingElse from \'something-else\';\nconst COLORS = { GREEN: \'green\', BLUE: \'blue\' } as const; type Bad = (typeof COLORS)[keyof COLORS];', errors: [{message: PREFER_TYPE_FEST_VALUE_OF}], parser: require.resolve('@typescript-eslint/parser'), + // eslint-disable-next-line max-len output: 'import type {ValueOf} from \'type-fest\';\nimport somethingElse from \'something-else\';\nconst COLORS = { GREEN: \'green\', BLUE: \'blue\' } as const; type Bad = ValueOf;', }, ], diff --git a/eslint-plugin-expensify/tests/use-periods-error-messages.test.js b/eslint-plugin-expensify/tests/use-periods-error-messages.test.js index b622105..5d62d6a 100644 --- a/eslint-plugin-expensify/tests/use-periods-error-messages.test.js +++ b/eslint-plugin-expensify/tests/use-periods-error-messages.test.js @@ -10,27 +10,39 @@ const ruleTester = new RuleTester({ }); const goodExampleSingleSentence = ` -error: { - testMessage: 'This is a test message' -} +const err = new Error('This is a test message'); `; const goodExampleMultipleSentences = ` -error: { - testMessage: 'This is a test message. Last period is mandatory.' -} +const err = new Error('This is a test message. Last period is mandatory.'); +`; + +const goodExampleSingleSentenceWithVar = ` +const errorMessage = 'This is a test message'; +const err = new Error(errorMessage); +`; + +const goodExampleMultipleSentencesWithVar = ` +const errorMessage = 'This is a test message. Last period is mandatory.'; +const err = new Error(errorMessage); `; const badExampleSingleSentence = ` -error: { - testMessage: 'This is a test message.' -} +const err = new Error('This is a test message.'); +`; + +const badExampleSingleSentenceWithVar = ` +const errorMessage = 'This is a test message.'; +const err = new Error(errorMessage); `; const badExampleMultipleSentences = ` -error: { - testMessage: 'This is a test message. Last period is mandatory' -} +const err = new Error('This is a test message. Last period is mandatory'); +`; + +const badExampleMultipleSentencesWithVar = ` +const errorMessage = 'This is a test message. Last period is mandatory'; +const err = new Error(errorMessage); `; ruleTester.run('use-periods-for-error-messages', rule, { @@ -41,6 +53,12 @@ ruleTester.run('use-periods-for-error-messages', rule, { { code: goodExampleMultipleSentences, }, + { + code: goodExampleSingleSentenceWithVar, + }, + { + code: goodExampleMultipleSentencesWithVar, + }, ], invalid: [ { @@ -49,11 +67,23 @@ ruleTester.run('use-periods-for-error-messages', rule, { message, }], }, + { + code: badExampleSingleSentenceWithVar, + errors: [{ + message, + }], + }, { code: badExampleMultipleSentences, errors: [{ message, }], }, + { + code: badExampleMultipleSentencesWithVar, + errors: [{ + message, + }], + }, ], }); diff --git a/eslint-plugin-expensify/use-double-negation-instead-of-boolean.js b/eslint-plugin-expensify/use-double-negation-instead-of-boolean.js index 1f067d2..adb453c 100644 --- a/eslint-plugin-expensify/use-double-negation-instead-of-boolean.js +++ b/eslint-plugin-expensify/use-double-negation-instead-of-boolean.js @@ -7,24 +7,25 @@ module.exports = { create(context) { return { CallExpression(node) { - if (node.callee.type === 'Identifier' && node.callee.name === 'Boolean' && node.arguments.length === 1) { - const argument = node.arguments[0]; - const sourceCode = context.getSourceCode(); - const argumentText = sourceCode.getText(argument); - let fixedText = `!!${argumentText}`; - - if (argument.type === 'LogicalExpression' || argument.type === 'BinaryExpression') { - fixedText = `!!(${argumentText})`; - } + if (node.callee.type !== 'Identifier' || node.callee.name !== 'Boolean' || node.arguments.length !== 1) { + return; + } + const argument = node.arguments[0]; + const sourceCode = context.getSourceCode(); + const argumentText = sourceCode.getText(argument); + let fixedText = `!!${argumentText}`; - context.report({ - node, - message, - fix(fixer) { - return fixer.replaceText(node, fixedText); - }, - }); + if (argument.type === 'LogicalExpression' || argument.type === 'BinaryExpression') { + fixedText = `!!(${argumentText})`; } + + context.report({ + node, + message, + fix(fixer) { + return fixer.replaceText(node, fixedText); + }, + }); }, }; }, diff --git a/eslint-plugin-expensify/use-periods-for-error-messages.js b/eslint-plugin-expensify/use-periods-for-error-messages.js index 1c34878..1aa0f37 100644 --- a/eslint-plugin-expensify/use-periods-for-error-messages.js +++ b/eslint-plugin-expensify/use-periods-for-error-messages.js @@ -1,3 +1,4 @@ +const _ = require('underscore'); const message = require('./CONST').MESSAGE.USE_PERIODS_ERROR_MESSAGES; module.exports = { @@ -9,31 +10,46 @@ module.exports = { fixable: 'code', }, create(context) { + const variableDeclarators = new Map(); return { - Property(node) { - if (!node.key || node.key.name !== 'error' || !node.value || node.value.type !== 'ObjectExpression') { + VariableDeclarator(node) { + variableDeclarators.set(node.id.name, node); + }, + NewExpression(node) { + if (!node.callee || node.callee.name !== 'Error' || node.arguments.length === 0) { return; } - node.value.properties.forEach((property) => { - if (!property.value || property.value.type !== 'Literal' || typeof property.value.value !== 'string') { + const errArg = node.arguments[0]; + let errorMessage = ''; + if (errArg.type === 'Literal') { + errorMessage = errArg.value; + } else if (variableDeclarators.has(errArg.name)) { + const variableDeclarator = variableDeclarators.get(errArg.name); + if (variableDeclarator.init.type !== 'Literal') { return; } - const errorMessage = property.value.value; + errorMessage = variableDeclarator.init.value; + } else { + return; + } - // Only enforce period rule if more than one sentence - const sentenceCount = errorMessage.split('.').filter(sentence => sentence.trim().length > 0).length; + // Only enforce period rule if more than one sentence + const sentenceCount = _.filter(errorMessage.split('.'), sentence => sentence.trim().length > 0).length; - if (sentenceCount > 1 && !errorMessage.endsWith('.')) { - context.report({ - node: property, - message, - fix: function (fixer) { - const fixedMessage = `${errorMessage}.`; - return fixer.replaceText(property.value, `'${fixedMessage}'`); + const doesViolateRule = (sentenceCount > 1 && !errorMessage.endsWith('.')) || (sentenceCount === 1 && errorMessage.endsWith('.')); + if (doesViolateRule) { + context.report({ + node, + message, + fix(fixer) { + if (errorMessage.type !== 'Literal') { + return; } - }); - } - }); + const fixedMessage = `${errorMessage}.`; + return fixer.replaceText(node.arguments[0], `'${fixedMessage}'`); + }, + }); + } }, }; }, diff --git a/eslint-plugin-expensify/utils/imports.js b/eslint-plugin-expensify/utils/imports.js index f14d0c5..d68dbda 100644 --- a/eslint-plugin-expensify/utils/imports.js +++ b/eslint-plugin-expensify/utils/imports.js @@ -1,3 +1,5 @@ +const _ = require('underscore'); + /** * Adds a named import to the import statement or creates a new import statement if it doesn't exist. * @@ -10,32 +12,30 @@ * @returns {Array} An array of fixes to be applied by the fixer. */ function addNamedImport(context, fixer, importNode, importName, importPath, importAsType = false) { - const fixes = []; - - if (importNode) { - const alreadyImported = importNode.specifiers.some( - specifier => specifier.imported.name === importName - ); + const fixes = []; + + if (importNode) { + const alreadyImported = _.some(importNode.specifiers, specifier => specifier.imported.name === importName); - if (!alreadyImported) { - const lastSpecifier = importNode.specifiers[importNode.specifiers.length - 1]; + if (!alreadyImported) { + const lastSpecifier = importNode.specifiers[importNode.specifiers.length - 1]; - // Add ValueOf to existing type-fest import - fixes.push(fixer.insertTextAfter(lastSpecifier, `, ${importName}`)); - } - } else { - // Add import if it doesn't exist - fixes.push( - fixer.insertTextBefore( - context.getSourceCode().ast.body[0], - `import ${importAsType ? "type " : ""}{${importName}} from '${importPath}';\n` - ) - ); - } + // Add ValueOf to existing type-fest import + fixes.push(fixer.insertTextAfter(lastSpecifier, `, ${importName}`)); + } + } else { + // Add import if it doesn't exist + fixes.push( + fixer.insertTextBefore( + context.getSourceCode().ast.body[0], + `import ${importAsType ? 'type ' : ''}{${importName}} from '${importPath}';\n`, + ), + ); + } - return fixes; + return fixes; } module.exports = { - addNamedImport + addNamedImport, }; diff --git a/eslint-plugin-expensify/utils/is-left-hand-side.js b/eslint-plugin-expensify/utils/is-left-hand-side.js index 6b03b32..d4ce2af 100644 --- a/eslint-plugin-expensify/utils/is-left-hand-side.js +++ b/eslint-plugin-expensify/utils/is-left-hand-side.js @@ -1,27 +1,27 @@ -// https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/rules/utils/is-left-hand-side.js - -const { AST_NODE_TYPES } = require('@typescript-eslint/utils'); - -function isLeftHandSide(node) { - const { parent } = node; - - return ( - (parent.type === AST_NODE_TYPES.AssignmentExpression || parent.type === AST_NODE_TYPES.AssignmentPattern) - && parent.left === node - ) - || (parent.type === AST_NODE_TYPES.UpdateExpression && parent.argument === node) - || (parent.type === AST_NODE_TYPES.ArrayPattern && parent.elements.includes(node)) - || ( - parent.type === AST_NODE_TYPES.Property - && parent.value === node - && parent.parent.type === AST_NODE_TYPES.ObjectPattern - && parent.parent.properties.includes(parent) - ) - || ( - parent.type === AST_NODE_TYPES.UnaryExpression - && parent.operator === 'delete' - && parent.argument === node - ); -} - -module.exports = { isLeftHandSide }; +// https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/rules/utils/is-left-hand-side.js + +const {AST_NODE_TYPES} = require('@typescript-eslint/utils'); + +function isLeftHandSide(node) { + const {parent} = node; + + return ( + (parent.type === AST_NODE_TYPES.AssignmentExpression || parent.type === AST_NODE_TYPES.AssignmentPattern) + && parent.left === node + ) + || (parent.type === AST_NODE_TYPES.UpdateExpression && parent.argument === node) + || (parent.type === AST_NODE_TYPES.ArrayPattern && parent.elements.includes(node)) + || ( + parent.type === AST_NODE_TYPES.Property + && parent.value === node + && parent.parent.type === AST_NODE_TYPES.ObjectPattern + && parent.parent.properties.includes(parent) + ) + || ( + parent.type === AST_NODE_TYPES.UnaryExpression + && parent.operator === 'delete' + && parent.argument === node + ); +} + +module.exports = {isLeftHandSide}; diff --git a/index.js b/index.js index d5d6ef1..03cda56 100644 --- a/index.js +++ b/index.js @@ -19,8 +19,9 @@ module.exports = { jquery: true, node: true, }, - parser: 'babel-eslint', + parser: '@babel/eslint-parser', parserOptions: { + requireConfigFile: false, ecmaVersion: 2018, sourceType: 'module', ecmaFeatures: { diff --git a/package-lock.json b/package-lock.json index bf3a62f..8da96ea 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,11 +9,11 @@ "version": "2.0.60", "license": "ISC", "dependencies": { + "@babel/eslint-parser": "^7.25.7", "@lwc/eslint-plugin-lwc": "^1.7.2", "@typescript-eslint/parser": "^7.12.0", "@typescript-eslint/rule-tester": "^7.16.1", "@typescript-eslint/utils": "^7.12.0", - "babel-eslint": "^10.1.0", "eslint": "^8.56.0", "eslint-config-airbnb": "19.0.4", "eslint-config-airbnb-base": "15.0.0", @@ -100,10 +100,9 @@ } }, "node_modules/@babel/eslint-parser": { - "version": "7.23.10", - "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.23.10.tgz", - "integrity": "sha512-3wSYDPZVnhseRnxRJH6ZVTNknBz76AEnyC+AYYhasjP3Yy23qz0ERR7Fcd2SHmYuSFJ2kY9gaaDd3vyqU09eSw==", - "peer": true, + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.25.7.tgz", + "integrity": "sha512-B+BO9x86VYsQHimucBAL1fxTJKF4wyKY6ZVzee9QgzdZOUfs3BaR6AQrgoGrRI+7IFS1wUz/VyQ+SoBcSpdPbw==", "dependencies": { "@nicolo-ribaudo/eslint-scope-5-internals": "5.1.1-v1", "eslint-visitor-keys": "^2.1.0", @@ -114,14 +113,13 @@ }, "peerDependencies": { "@babel/core": "^7.11.0", - "eslint": "^7.5.0 || ^8.0.0" + "eslint": "^7.5.0 || ^8.0.0 || ^9.0.0" } }, "node_modules/@babel/eslint-parser/node_modules/eslint-visitor-keys": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", - "peer": true, "engines": { "node": ">=10" } @@ -1434,7 +1432,6 @@ "version": "5.1.1-v1", "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz", "integrity": "sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg==", - "peer": true, "dependencies": { "eslint-scope": "5.1.1" } @@ -2239,26 +2236,6 @@ "dequal": "^2.0.3" } }, - "node_modules/babel-eslint": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-10.1.0.tgz", - "integrity": "sha512-ifWaTHQ0ce+448CYop8AdrQiBsGrnC+bMgfyKFdi6EsPLTAWG+QfyDeM6OH+FmWnKvEq5NnBMLvlBUPKQZoDSg==", - "deprecated": "babel-eslint is now @babel/eslint-parser. This package will no longer receive updates.", - "dependencies": { - "@babel/code-frame": "^7.0.0", - "@babel/parser": "^7.7.0", - "@babel/traverse": "^7.7.0", - "@babel/types": "^7.7.0", - "eslint-visitor-keys": "^1.0.0", - "resolve": "^1.12.0" - }, - "engines": { - "node": ">=6" - }, - "peerDependencies": { - "eslint": ">= 4.12.1" - } - }, "node_modules/babel-jest": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", @@ -3450,7 +3427,6 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "peer": true, "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^4.1.1" @@ -3463,7 +3439,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "peer": true, "engines": { "node": ">=4.0" } @@ -8108,10 +8083,9 @@ } }, "@babel/eslint-parser": { - "version": "7.23.10", - "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.23.10.tgz", - "integrity": "sha512-3wSYDPZVnhseRnxRJH6ZVTNknBz76AEnyC+AYYhasjP3Yy23qz0ERR7Fcd2SHmYuSFJ2kY9gaaDd3vyqU09eSw==", - "peer": true, + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.25.7.tgz", + "integrity": "sha512-B+BO9x86VYsQHimucBAL1fxTJKF4wyKY6ZVzee9QgzdZOUfs3BaR6AQrgoGrRI+7IFS1wUz/VyQ+SoBcSpdPbw==", "requires": { "@nicolo-ribaudo/eslint-scope-5-internals": "5.1.1-v1", "eslint-visitor-keys": "^2.1.0", @@ -8121,8 +8095,7 @@ "eslint-visitor-keys": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", - "peer": true + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==" } } }, @@ -9103,7 +9076,6 @@ "version": "5.1.1-v1", "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz", "integrity": "sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg==", - "peer": true, "requires": { "eslint-scope": "5.1.1" } @@ -9658,19 +9630,6 @@ "dequal": "^2.0.3" } }, - "babel-eslint": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-10.1.0.tgz", - "integrity": "sha512-ifWaTHQ0ce+448CYop8AdrQiBsGrnC+bMgfyKFdi6EsPLTAWG+QfyDeM6OH+FmWnKvEq5NnBMLvlBUPKQZoDSg==", - "requires": { - "@babel/code-frame": "^7.0.0", - "@babel/parser": "^7.7.0", - "@babel/traverse": "^7.7.0", - "@babel/types": "^7.7.0", - "eslint-visitor-keys": "^1.0.0", - "resolve": "^1.12.0" - } - }, "babel-jest": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", @@ -10680,7 +10639,6 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "peer": true, "requires": { "esrecurse": "^4.3.0", "estraverse": "^4.1.1" @@ -10689,8 +10647,7 @@ "estraverse": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "peer": true + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==" } } }, diff --git a/package.json b/package.json index 9929b3e..ca1d304 100644 --- a/package.json +++ b/package.json @@ -12,11 +12,11 @@ "lint": "eslint ." }, "dependencies": { + "@babel/eslint-parser": "^7.25.7", "@lwc/eslint-plugin-lwc": "^1.7.2", "@typescript-eslint/parser": "^7.12.0", "@typescript-eslint/rule-tester": "^7.16.1", "@typescript-eslint/utils": "^7.12.0", - "babel-eslint": "^10.1.0", "eslint": "^8.56.0", "eslint-config-airbnb": "19.0.4", "eslint-config-airbnb-base": "15.0.0",