From 148e3e1fa0c7346ed3c149dbbf6201853065c37e Mon Sep 17 00:00:00 2001 From: Florian Maunier Date: Mon, 16 Dec 2024 18:29:10 +0100 Subject: [PATCH] refactor(backend): convert all to typescript modules --- package-lock.json | 18 +++++++++ packages/backend/eslint.config.js | 5 +++ .../lib/configs/{default.js => default.ts} | 4 +- .../backend/lib/configs/{node.js => node.ts} | 4 +- .../configs/{typescript.js => typescript.ts} | 4 +- packages/backend/lib/index.js | 11 ------ packages/backend/lib/index.ts | 16 ++++++++ .../{array-foreach.js => array-foreach.ts} | 15 +++++-- .../lib/rules/{no-then.js => no-then.ts} | 13 +++++-- packages/backend/lib/utils/docUrl.ts | 13 +++++++ packages/backend/lib/utils/url.js | 11 ------ packages/backend/package.json | 3 +- packages/backend/tests/array-foreach.js | 26 ++++++------- packages/backend/tests/no-then.js | 39 +++++++++++++++++++ packages/backend/tsconfig.json | 7 ++-- 15 files changed, 140 insertions(+), 49 deletions(-) rename packages/backend/lib/configs/{default.js => default.ts} (97%) rename packages/backend/lib/configs/{node.js => node.ts} (78%) rename packages/backend/lib/configs/{typescript.js => typescript.ts} (92%) delete mode 100644 packages/backend/lib/index.js create mode 100644 packages/backend/lib/index.ts rename packages/backend/lib/rules/{array-foreach.js => array-foreach.ts} (54%) rename packages/backend/lib/rules/{no-then.js => no-then.ts} (64%) create mode 100644 packages/backend/lib/utils/docUrl.ts delete mode 100644 packages/backend/lib/utils/url.js create mode 100644 packages/backend/tests/no-then.js diff --git a/package-lock.json b/package-lock.json index 48e426c..2c44b1f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -345,6 +345,16 @@ "license": "MIT", "peer": true }, + "node_modules/@types/node": { + "version": "22.10.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.2.tgz", + "integrity": "sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.20.0" + } + }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "8.17.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.17.0.tgz", @@ -2915,6 +2925,13 @@ } } }, + "node_modules/undici-types": { + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", + "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", + "dev": true, + "license": "MIT" + }, "node_modules/uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", @@ -3251,6 +3268,7 @@ "typescript-eslint": "^8.17.0" }, "devDependencies": { + "@types/node": "^22.10.2", "eslint-plugin-eslint-plugin": "^6.3.2", "eslint-plugin-n": "^17.14.0", "mocha": "^11.0.1", diff --git a/packages/backend/eslint.config.js b/packages/backend/eslint.config.js index 103d5a9..52150b2 100644 --- a/packages/backend/eslint.config.js +++ b/packages/backend/eslint.config.js @@ -10,6 +10,11 @@ export default tseslint.config( tseslint.configs.recommended, nodePlugin.configs['flat/recommended'], eslintPlugin.configs['flat/recommended'], + { + rules: { + 'n/file-extension-in-import': ['error', 'always'], + }, + }, { languageOptions: { globals: { diff --git a/packages/backend/lib/configs/default.js b/packages/backend/lib/configs/default.ts similarity index 97% rename from packages/backend/lib/configs/default.js rename to packages/backend/lib/configs/default.ts index 9dfe035..0100f0f 100644 --- a/packages/backend/lib/configs/default.js +++ b/packages/backend/lib/configs/default.ts @@ -1,4 +1,4 @@ -module.exports = { +const defaultConfig = { plugins: ['prettier'], extends: ['eslint:recommended'], rules: { @@ -82,3 +82,5 @@ module.exports = { }, ], }; + +export default defaultConfig; diff --git a/packages/backend/lib/configs/node.js b/packages/backend/lib/configs/node.ts similarity index 78% rename from packages/backend/lib/configs/node.js rename to packages/backend/lib/configs/node.ts index 96b0e78..7dc4e89 100644 --- a/packages/backend/lib/configs/node.js +++ b/packages/backend/lib/configs/node.ts @@ -1,4 +1,4 @@ -module.exports = { +const nodeConfig = { rules: {}, env: { node: true, @@ -12,3 +12,5 @@ module.exports = { ecmaVersion: 2018, }, }; + +export default nodeConfig; diff --git a/packages/backend/lib/configs/typescript.js b/packages/backend/lib/configs/typescript.ts similarity index 92% rename from packages/backend/lib/configs/typescript.js rename to packages/backend/lib/configs/typescript.ts index bf66c56..7cca7a5 100644 --- a/packages/backend/lib/configs/typescript.js +++ b/packages/backend/lib/configs/typescript.ts @@ -1,4 +1,4 @@ -module.exports = { +const typescriptConfig = { plugins: ['@typescript-eslint'], extends: [ 'eslint:recommended', @@ -20,3 +20,5 @@ module.exports = { '@typescript-eslint/no-shadow': 'error', }, }; + +export default typescriptConfig; diff --git a/packages/backend/lib/index.js b/packages/backend/lib/index.js deleted file mode 100644 index d534fb0..0000000 --- a/packages/backend/lib/index.js +++ /dev/null @@ -1,11 +0,0 @@ -module.exports = { - rules: { - 'array-foreach': require('./rules/array-foreach'), - 'no-then': require('./rules/no-then'), - }, - configs: { - default: require('./configs/default'), - node: require('./configs/node'), - typescript: require('./configs/typescript'), - }, -}; diff --git a/packages/backend/lib/index.ts b/packages/backend/lib/index.ts new file mode 100644 index 0000000..db6c3cc --- /dev/null +++ b/packages/backend/lib/index.ts @@ -0,0 +1,16 @@ +import defaultConfig from './configs/default.js'; +import nodeConfig from './configs/node.js'; +import typescriptConfig from './configs/typescript.js'; +import arrayForeach from './rules/array-foreach.js'; +import noThen from './rules/no-then.js'; + +export const rules = { + 'array-foreach': arrayForeach, + 'no-then': noThen, +}; + +export const configs = { + default: defaultConfig, + node: nodeConfig, + typescript: typescriptConfig, +}; diff --git a/packages/backend/lib/rules/array-foreach.js b/packages/backend/lib/rules/array-foreach.ts similarity index 54% rename from packages/backend/lib/rules/array-foreach.js rename to packages/backend/lib/rules/array-foreach.ts index 6f3a86e..87ecfad 100644 --- a/packages/backend/lib/rules/array-foreach.js +++ b/packages/backend/lib/rules/array-foreach.ts @@ -1,9 +1,12 @@ -module.exports = { +import { Rule } from 'eslint'; +import docUrl from '../utils/docUrl.js'; + +const arrayForeach: Rule.RuleModule = { meta: { type: 'suggestion', docs: { description: 'enforce `for..of` loops over `Array.forEach`', - url: require('../utils/url')(module), + url: docUrl(import.meta), }, schema: [], messages: { @@ -13,7 +16,11 @@ module.exports = { create(context) { return { CallExpression(node) { - if (node.callee.property && node.callee.property.name === 'forEach') { + if ( + node.callee.type === 'MemberExpression' && + node.callee.property.type === 'Identifier' && + node.callee.property.name === 'forEach' + ) { context.report({ node, messageId: 'preferMessage', @@ -23,3 +30,5 @@ module.exports = { }; }, }; + +export default arrayForeach; diff --git a/packages/backend/lib/rules/no-then.js b/packages/backend/lib/rules/no-then.ts similarity index 64% rename from packages/backend/lib/rules/no-then.js rename to packages/backend/lib/rules/no-then.ts index 74d1ddb..fbd7892 100644 --- a/packages/backend/lib/rules/no-then.js +++ b/packages/backend/lib/rules/no-then.ts @@ -1,9 +1,12 @@ -module.exports = { +import { Rule } from 'eslint'; +import docUrl from '../utils/docUrl.js'; + +const noThen: Rule.RuleModule = { meta: { type: 'suggestion', docs: { description: 'enforce using `async/await` syntax over Promises', - url: require('../utils/url')(module), + url: docUrl(import.meta), }, schema: [], messages: { @@ -15,12 +18,12 @@ module.exports = { create(context) { return { MemberExpression(node) { - if (node.property && node.property.name === 'then') { + if (node.property.type === 'Identifier' && node.property.name === 'then') { context.report({ node: node.property, messageId: 'thenMessage', }); - } else if (node.property && node.property.name === 'catch') { + } else if (node.property.type === 'Identifier' && node.property.name === 'catch') { context.report({ node: node.property, messageId: 'catchMessage', @@ -30,3 +33,5 @@ module.exports = { }; }, }; + +export default noThen; diff --git a/packages/backend/lib/utils/docUrl.ts b/packages/backend/lib/utils/docUrl.ts new file mode 100644 index 0000000..3d30dae --- /dev/null +++ b/packages/backend/lib/utils/docUrl.ts @@ -0,0 +1,13 @@ +import * as path from 'node:path'; + +import packageJson from '../../package.json' with { type: 'json' }; + +const docUrl = ({ filename }: ImportMeta) => { + const url = new URL(packageJson.homepage); + const rule = path.basename(filename, '.js'); + url.hash = ''; + url.pathname += `/blob/v${packageJson.version}/docs/rules/${rule}.md`; + return url.toString(); +}; + +export default docUrl; diff --git a/packages/backend/lib/utils/url.js b/packages/backend/lib/utils/url.js deleted file mode 100644 index 4b27579..0000000 --- a/packages/backend/lib/utils/url.js +++ /dev/null @@ -1,11 +0,0 @@ -const path = require("path"); - -const { homepage, version } = require("../../package.json"); - -module.exports = ({ id }) => { - const url = new URL(homepage); - const rule = path.basename(id, ".js"); - url.hash = ""; - url.pathname += `/blob/v${version}/docs/rules/${rule}.md`; - return url.toString(); -}; diff --git a/packages/backend/package.json b/packages/backend/package.json index f68ce95..c768e5e 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -18,7 +18,7 @@ "main": "lib/index.js", "scripts": { "lint": "eslint", - "test": "mocha tests --recursive", + "test": "npm run build && mocha tests --recursive", "clean": "rimraf dist", "build": "npm run clean && tsc --build" }, @@ -41,6 +41,7 @@ "typescript-eslint": "^8.17.0" }, "devDependencies": { + "@types/node": "^22.10.2", "eslint-plugin-eslint-plugin": "^6.3.2", "eslint-plugin-n": "^17.14.0", "mocha": "^11.0.1", diff --git a/packages/backend/tests/array-foreach.js b/packages/backend/tests/array-foreach.js index 3bfcd92..fef1a68 100644 --- a/packages/backend/tests/array-foreach.js +++ b/packages/backend/tests/array-foreach.js @@ -1,30 +1,30 @@ -const rule = require('../lib/rules/array-foreach') -const RuleTester = require('eslint').RuleTester +import { RuleTester } from 'eslint'; +import rule from '../dist/lib/rules/array-foreach.js'; -const ruleTester = new RuleTester() +const ruleTester = new RuleTester(); ruleTester.run('array-foreach', rule, { valid: [ { code: 'for (const el of els) { el }', - parserOptions: {ecmaVersion: 6} + languageOptions: { ecmaVersion: 2018 }, }, { code: 'els.map(el => el)', - parserOptions: {ecmaVersion: 6} + languageOptions: { ecmaVersion: 2018 }, }, - {code: 'forEach()'} + { code: 'forEach()' }, ], invalid: [ { code: 'els.forEach(el => el)', - parserOptions: {ecmaVersion: 6}, + languageOptions: { ecmaVersion: 2018 }, errors: [ { message: 'Prefer for...of instead of Array.forEach', - type: 'CallExpression' - } - ] - } - ] -}) + type: 'CallExpression', + }, + ], + }, + ], +}); diff --git a/packages/backend/tests/no-then.js b/packages/backend/tests/no-then.js new file mode 100644 index 0000000..71e19e3 --- /dev/null +++ b/packages/backend/tests/no-then.js @@ -0,0 +1,39 @@ +import { RuleTester } from 'eslint'; +import rule from '../dist/lib/rules/no-then.js'; + +const ruleTester = new RuleTester(); + +ruleTester.run('no-then', rule, { + valid: [ + { + code: 'async () => { await promise }', + languageOptions: { ecmaVersion: 2018 }, + }, + { + code: 'async () => { try { await promise } catch (e) { throw e } }', + languageOptions: { ecmaVersion: 2018 }, + }, + ], + invalid: [ + { + code: 'promise.then(() => {})', + languageOptions: { ecmaVersion: 2018 }, + errors: [ + { + message: 'Prefer async/await to Promise.then()', + type: 'Identifier', + }, + ], + }, + { + code: 'promise.catch(() => {})', + languageOptions: { ecmaVersion: 2018 }, + errors: [ + { + message: 'Prefer async/await to Promise.catch()', + type: 'Identifier', + }, + ], + }, + ], +}); diff --git a/packages/backend/tsconfig.json b/packages/backend/tsconfig.json index 373f926..73e172c 100644 --- a/packages/backend/tsconfig.json +++ b/packages/backend/tsconfig.json @@ -2,12 +2,12 @@ "$schema": "https://json.schemastore.org/tsconfig", "compilerOptions": { "lib": ["es2023"], - "module": "node16", + "module": "nodenext", "target": "es2022", "strict": true, "esModuleInterop": true, "skipLibCheck": true, - "moduleResolution": "node16", + "moduleResolution": "nodenext", "allowUnusedLabels": false, "allowUnreachableCode": false, "exactOptionalPropertyTypes": true, @@ -22,7 +22,8 @@ "checkJs": true, "outDir": "./dist", "sourceMap": true, - "baseUrl": "./lib" + "baseUrl": "./lib", + "resolveJsonModule": true }, "include": ["./lib"] }