diff --git a/README.md b/README.md index 35ce013..b15ded5 100644 --- a/README.md +++ b/README.md @@ -4,13 +4,13 @@ Encourage use of defined aliases in TSConfig/JSConfig through ESLint. ## Why -- Automatic imports by tsserver resolve to relative paths that can be normalized. -- It's easier to refactor by finding and replacing an absolute module path - without worrying about crafting the regex for `../` and `./` +- Automatic imports by tsserver resolve to relative paths that can be normalized. +- It's easier to refactor by finding and replacing an absolute module path + without worrying about crafting the regex for `../` and `./` ## Requirements -- Node 14+ +- Node 14+ ## Install @@ -32,8 +32,8 @@ Check the [rules documentation][docs-import-alias] for further configuration. { "plugins": ["@limegrass/import-alias"], "rules": { - "@limegrass/import-alias/import-alias": "error" - } + "@limegrass/import-alias/import-alias": "error", + }, } ``` @@ -44,8 +44,8 @@ The configuration above is also equivalent to { "extends": [ // ... - your other extends, such as `"eslint:recommended"` - "plugin:@limegrass/import-alias/recommended" - ] + "plugin:@limegrass/import-alias/recommended", + ], } ``` diff --git a/docs/rules/import-alias.md b/docs/rules/import-alias.md index a91ee4b..ab6f8eb 100644 --- a/docs/rules/import-alias.md +++ b/docs/rules/import-alias.md @@ -11,9 +11,9 @@ Given the following `tsconfig.json` // ... "paths": { "#src/*": ["src/*"], - "#rules/*": ["src/rules/*"] - } - } + "#rules/*": ["src/rules/*"], + }, + }, } ``` @@ -55,10 +55,10 @@ parameter of a function named `potato` for aliasing. "@limegrass/import-alias/import-alias": [ "error", { - "aliasImportFunctions": ["require", "mock", "potato"] - } - ] - } + "aliasImportFunctions": ["require", "mock", "potato"], + }, + ], + }, } ``` @@ -79,10 +79,10 @@ configuration key. An example for a tsconfig found in a `config` folder of a pro "@limegrass/import-alias/import-alias": [ "error", { - "aliasConfigPath": "config/tsconfig.json" - } - ] - } + "aliasConfigPath": "config/tsconfig.json", + }, + ], + }, } ``` @@ -110,10 +110,10 @@ The follow example would allow sibling imports for the entire project. "@limegrass/import-alias/import-alias": [ "error", { - "relativeImportOverrides": [{ "path": ".", "depth": 0 }] - } - ] - } + "relativeImportOverrides": [{ "path": ".", "depth": 0 }], + }, + ], + }, } ``` diff --git a/eslint.config.mjs b/eslint.config.mjs index 32d3159..49d1919 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -26,8 +26,8 @@ export default [ "plugin:@typescript-eslint/recommended", "plugin:import/recommended", "plugin:import/typescript", - "prettier", "plugin:@limegrass/import-alias/recommended", + "prettier", ), ), { diff --git a/package-lock.json b/package-lock.json index 4392a15..c6395f4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -40,7 +40,7 @@ "jest": "^29.7.0", "jest-mock": "^29.7.0", "lint-staged": "^12.3.5", - "prettier": "^2.5.1", + "prettier": "^3", "rimraf": "^6.0.1", "ts-jest": "^29.1.4", "ts-node": "^10.7.0", @@ -8090,16 +8090,16 @@ } }, "node_modules/prettier": { - "version": "2.8.8", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", - "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.4.1.tgz", + "integrity": "sha512-G+YdqtITVZmOJje6QkXQWzl3fSfMxFwm1tjTyo9exhkmWSqC4Yhd1+lug++IlR2mvRVAxEDDWYkQdeSztajqgg==", "dev": true, "license": "MIT", "bin": { - "prettier": "bin-prettier.js" + "prettier": "bin/prettier.cjs" }, "engines": { - "node": ">=10.13.0" + "node": ">=14" }, "funding": { "url": "https://github.com/prettier/prettier?sponsor=1" diff --git a/package.json b/package.json index f5ddb7c..162196c 100644 --- a/package.json +++ b/package.json @@ -49,7 +49,7 @@ "jest": "^29.7.0", "jest-mock": "^29.7.0", "lint-staged": "^12.3.5", - "prettier": "^2.5.1", + "prettier": "^3", "rimraf": "^6.0.1", "ts-jest": "^29.1.4", "ts-node": "^10.7.0", diff --git a/src/alias-config.ts b/src/alias-config.ts index 1d8e207..adf5324 100644 --- a/src/alias-config.ts +++ b/src/alias-config.ts @@ -17,7 +17,7 @@ type AliasConfig = { function loadTsconfig( eslintConfigPath: string, aliasConfigPath: string | undefined, - codeFilePath: string + codeFilePath: string, ) { let config: ConfigLoaderResult; try { @@ -26,7 +26,7 @@ function loadTsconfig( config = loadConfig(aliasConfigPath); } else { config = loadConfig( - joinPath(eslintConfigPath, aliasConfigPath) + joinPath(eslintConfigPath, aliasConfigPath), ); } } else { @@ -35,7 +35,7 @@ function loadTsconfig( } catch (error) { if (error instanceof SyntaxError) { throw new Error( - `SyntaxError in TSConfig/JSConfig: ${error.message}` + `SyntaxError in TSConfig/JSConfig: ${error.message}`, ); } throw error; @@ -43,7 +43,7 @@ function loadTsconfig( if (config.resultType !== "success") { throw new Error( - `validate tsconfig or jsconfig provided and ensure compilerOptions.baseUrl is set: ${config.message}` + `validate tsconfig or jsconfig provided and ensure compilerOptions.baseUrl is set: ${config.message}`, ); } @@ -52,7 +52,7 @@ function loadTsconfig( function loadAliasConfigs( config: ConfigLoaderSuccessResult, - projectBaseDir: string + projectBaseDir: string, ): AliasConfig[] { return Object.entries(config.paths).reduce( (configs, [aliasGlob, aliasPaths]) => { @@ -67,7 +67,7 @@ function loadAliasConfigs( }); return configs; }, - [] as AliasConfig[] + [] as AliasConfig[], ); } diff --git a/src/rules/import-alias.ts b/src/rules/import-alias.ts index 0106fe9..7a7316d 100644 --- a/src/rules/import-alias.ts +++ b/src/rules/import-alias.ts @@ -22,7 +22,7 @@ function isPermittedRelativeImport( importModuleName: string, relativeImportOverrides: RelativeImportConfig[], filepath: string, - projectBaseDir: string + projectBaseDir: string, ) { const isRelativeImport = importModuleName.length > 0 && importModuleName[0] !== "."; @@ -32,7 +32,7 @@ function isPermittedRelativeImport( const importParts = importModuleName.split("/"); const relativeDepth = importParts.filter( - (moduleNamePart) => moduleNamePart === ".." + (moduleNamePart) => moduleNamePart === "..", ).length; const relativeFilepath = relative(projectBaseDir, filepath); @@ -53,13 +53,13 @@ function isPermittedRelativeImport( function getAliasSuggestion( importModuleName: string, aliasConfigs: AliasConfig[], - absoluteDir: string + absoluteDir: string, ) { const currentAliasConfig: AliasConfig | undefined = aliasConfigs.find( ({ alias }) => { const [baseModulePath] = importModuleName.split("/"); return baseModulePath === alias; - } + }, ); let absoluteModulePath: string | undefined = undefined; @@ -75,15 +75,15 @@ function getAliasSuggestion( const bestAliasConfig = getBestAliasConfig( aliasConfigs, currentAliasConfig, - absoluteModulePath + absoluteModulePath, ); if (bestAliasConfig && bestAliasConfig !== currentAliasConfig) { return slash( absoluteModulePath.replace( bestAliasConfig.path.absolute, - bestAliasConfig.alias - ) + bestAliasConfig.alias, + ), ); } } @@ -92,7 +92,7 @@ function getAliasSuggestion( function getBestAliasConfig( aliasConfigs: AliasConfig[], currentAlias: AliasConfig | undefined, - absoluteModulePath: string + absoluteModulePath: string, ) { const importPathParts = absoluteModulePath.split(pathSep); return aliasConfigs.reduce((currentBest, potentialAlias) => { @@ -101,7 +101,7 @@ function getBestAliasConfig( (isValid, aliasPathPart, index) => { return isValid && importPathParts[index] === aliasPathPart; }, - true + true, ); const isMoreSpecificAlias = !currentBest || @@ -303,7 +303,7 @@ const importAliasRule: Rule.RuleModule = { return reportProgramError( "a filepath must be provided, try with --stdin-filename, " + "call eslint on a file, " + - "or save your buffer as a file and restart eslint in your editor." + "or save your buffer as a file and restart eslint in your editor.", ); } @@ -331,7 +331,7 @@ const importAliasRule: Rule.RuleModule = { const getReportDescriptor = ( [moduleStart, moduleEnd]: [number, number], - importModuleName: string + importModuleName: string, ) => { // preserve user quote style const quotelessRange: AST.Range = [moduleStart + 1, moduleEnd - 1]; @@ -341,7 +341,7 @@ const importAliasRule: Rule.RuleModule = { importModuleName, relativeImportOverrides, filepath, - projectBaseDir + projectBaseDir, ) ) { return undefined; @@ -350,7 +350,7 @@ const importAliasRule: Rule.RuleModule = { const aliasSuggestion = getAliasSuggestion( importModuleName, aliasesResult, - absoluteDir + absoluteDir, ); if (aliasSuggestion) { @@ -359,7 +359,7 @@ const importAliasRule: Rule.RuleModule = { fix: (fixer: Rule.RuleFixer) => { return fixer.replaceTextRange( quotelessRange, - aliasSuggestion + aliasSuggestion, ); }, }; @@ -370,7 +370,7 @@ const importAliasRule: Rule.RuleModule = { if (!isAllowBaseUrlResolvedImport) { const joinedModulePath = joinPath( projectBaseDir, - importModuleName + importModuleName, ); let moduleExists = false; try { @@ -387,22 +387,22 @@ const importAliasRule: Rule.RuleModule = { const aliasConfig = getBestAliasConfig( aliasesResult, undefined, - joinedModulePath + joinedModulePath, ); if (aliasConfig) { const suggestedPathImport = slash( joinedModulePath.replace( aliasConfig.path.absolute, - aliasConfig.alias - ) + aliasConfig.alias, + ), ); return { message: `import ${importModuleName} can be written as ${suggestedPathImport}`, fix: (fixer: Rule.RuleFixer) => { return fixer.replaceTextRange( quotelessRange, - suggestedPathImport + suggestedPathImport, ); }, }; @@ -421,12 +421,12 @@ const importAliasRule: Rule.RuleModule = { node: | ImportDeclaration | ExportAllDeclaration - | ExportNamedDeclaration + | ExportNamedDeclaration, ) => { if (node.source?.range && typeof node.source.value === "string") { const suggestion = getReportDescriptor( node.source.range, - node.source.value + node.source.value, ); if (suggestion) { @@ -455,7 +455,7 @@ const importAliasRule: Rule.RuleModule = { ) { const suggestion = getReportDescriptor( importNameNode.range, - importNameNode.value + importNameNode.value, ); if (suggestion) { diff --git a/tests/rules/import-alias.config.ts b/tests/rules/import-alias.config.ts index ad9cd27..5119457 100644 --- a/tests/rules/import-alias.config.ts +++ b/tests/rules/import-alias.config.ts @@ -30,7 +30,7 @@ export function mockReaddir(filepath: string) { export function getMockAliasConfig( pathModule: typeof path, platform: "win32" | "posix", - projectDir: string + projectDir: string, ) { return [ { @@ -51,7 +51,7 @@ export function getMockAliasConfig( absolute: pathModule[platform].join( projectDir, "src", - "sub-directory" + "sub-directory", ), }, }, diff --git a/tests/rules/import-alias.invalid-cases.ts b/tests/rules/import-alias.invalid-cases.ts index b052fb6..838ca22 100644 --- a/tests/rules/import-alias.invalid-cases.ts +++ b/tests/rules/import-alias.invalid-cases.ts @@ -20,7 +20,7 @@ type InvalidTestCaseParams = { /** These configurations are based on the test setup in the import-alias.config test file */ export function getInvalidTestCaseParams( fileSystemPath: string, - optionsOverrides: Partial + optionsOverrides: Partial, ): InvalidTestCaseParams[] { const baseParams: InvalidTestCaseParams[] = [ { @@ -237,18 +237,18 @@ export function getInvalidTestCaseParams( export function generateInvalidTestCase( testCaseKind: keyof typeof FORMAT_STRING, - params: InvalidTestCaseParams + params: InvalidTestCaseParams, ): RuleTester.InvalidTestCase { const inputCode = formatCode( FORMAT_STRING[testCaseKind], - params.import.input + params.import.input, ); const outputCode = formatCode( FORMAT_STRING[testCaseKind], // RuleTester appears to default to the input string // only if output is explicitly not set (and NOT undefined). // This mimicks that behavior. - params.import.output ?? params.import.input + params.import.output ?? params.import.input, ); const testCase: RuleTester.InvalidTestCase = { diff --git a/tests/rules/import-alias.test.ts b/tests/rules/import-alias.test.ts index 3f8a9e2..8687bec 100644 --- a/tests/rules/import-alias.test.ts +++ b/tests/rules/import-alias.test.ts @@ -39,7 +39,7 @@ jest.mock("path", () => { // required when running the tests on windows join: (...args: string[]) => { return original.posix.join( - ...args.map((s: string) => s.replace(/\\/g, "/")) + ...args.map((s: string) => s.replace(/\\/g, "/")), ); }, }, @@ -72,7 +72,7 @@ function runTests(platform: "win32" | "posix") { baseUrl: ".", configFileAbsolutePath: path[platform].join( projectDir, - "tsconfig.json" + "tsconfig.json", ), } as Partial as ConfigLoaderSuccessResult); @@ -85,7 +85,7 @@ function runTests(platform: "win32" | "posix") { ruleTester.run("ExportAllDeclaration", rules["import-alias"], { valid: [ ...getValidTestCaseParams(NO_OPTION_OVERRIDES).map((params) => - generateValidTestCase("ExportAllDecalaration", params) + generateValidTestCase("ExportAllDecalaration", params), ), { name: "source-less default export [export default TestFn = () => {}]", @@ -96,9 +96,9 @@ function runTests(platform: "win32" | "posix") { invalid: [ ...getInvalidTestCaseParams( projectDirPart, - NO_OPTION_OVERRIDES + NO_OPTION_OVERRIDES, ).map((params) => - generateInvalidTestCase("ExportAllDecalaration", params) + generateInvalidTestCase("ExportAllDecalaration", params), ), ], }); @@ -106,7 +106,7 @@ function runTests(platform: "win32" | "posix") { ruleTester.run("ExportNamedDeclaration", rules["import-alias"], { valid: [ ...getValidTestCaseParams(NO_OPTION_OVERRIDES).map((params) => - generateValidTestCase("ExportNamedDecalaration", params) + generateValidTestCase("ExportNamedDecalaration", params), ), { name: `source-less named export inline [export const TestFn = () => {}]`, @@ -122,9 +122,9 @@ function runTests(platform: "win32" | "posix") { invalid: [ ...getInvalidTestCaseParams( projectDirPart, - NO_OPTION_OVERRIDES + NO_OPTION_OVERRIDES, ).map((params) => - generateInvalidTestCase("ExportNamedDecalaration", params) + generateInvalidTestCase("ExportNamedDecalaration", params), ), ], }); @@ -132,15 +132,15 @@ function runTests(platform: "win32" | "posix") { ruleTester.run("ImportDeclaration", rules["import-alias"], { valid: [ ...getValidTestCaseParams(NO_OPTION_OVERRIDES).map((params) => - generateValidTestCase("ImportDeclaration", params) + generateValidTestCase("ImportDeclaration", params), ), ], invalid: [ ...getInvalidTestCaseParams( projectDirPart, - NO_OPTION_OVERRIDES + NO_OPTION_OVERRIDES, ).map((params) => - generateInvalidTestCase("ImportDeclaration", params) + generateInvalidTestCase("ImportDeclaration", params), ), ], }); @@ -149,15 +149,15 @@ function runTests(platform: "win32" | "posix") { ruleTester.run("`require` support by default", rules["import-alias"], { valid: [ ...getValidTestCaseParams(NO_OPTION_OVERRIDES).map((params) => - generateValidTestCase("RequireCallExpression", params) + generateValidTestCase("RequireCallExpression", params), ), ], invalid: [ ...getInvalidTestCaseParams( projectDirPart, - NO_OPTION_OVERRIDES + NO_OPTION_OVERRIDES, ).map((params) => - generateInvalidTestCase("RequireCallExpression", params) + generateInvalidTestCase("RequireCallExpression", params), ), ], }); @@ -171,22 +171,22 @@ function runTests(platform: "win32" | "posix") { (params) => generateValidTestCase( "JestMockCallExpression", - params - ) + params, + ), ), ], invalid: [ ...getInvalidTestCaseParams( projectDirPart, - NO_OPTION_OVERRIDES + NO_OPTION_OVERRIDES, ).map((params) => generateInvalidTestCase( "JestMockCallExpression", - params - ) + params, + ), ), ], - } + }, ); const customCallExpressionOptionOverrides = { @@ -195,17 +195,17 @@ function runTests(platform: "win32" | "posix") { ruleTester.run("custom CallExpression support", rules["import-alias"], { valid: [ ...getValidTestCaseParams( - customCallExpressionOptionOverrides + customCallExpressionOptionOverrides, ).map((params) => - generateValidTestCase("CustomCallExpression", params) + generateValidTestCase("CustomCallExpression", params), ), ], invalid: [ ...getInvalidTestCaseParams( projectDirPart, - customCallExpressionOptionOverrides + customCallExpressionOptionOverrides, ).map((params) => - generateInvalidTestCase("CustomCallExpression", params) + generateInvalidTestCase("CustomCallExpression", params), ), ], }); diff --git a/tests/rules/import-alias.valid-cases.ts b/tests/rules/import-alias.valid-cases.ts index b791277..589097f 100644 --- a/tests/rules/import-alias.valid-cases.ts +++ b/tests/rules/import-alias.valid-cases.ts @@ -19,7 +19,7 @@ type ValidTestCaseParams = { /** These configurations are based on the test setup in the import-alias.config test file */ export function getValidTestCaseParams( - optionsOverrides: Partial + optionsOverrides: Partial, ): ValidTestCaseParams[] { const baseParams: ValidTestCaseParams[] = [ { @@ -318,7 +318,7 @@ export function getValidTestCaseParams( export function generateValidTestCase( testCaseKind: keyof typeof FORMAT_STRING, - params: ValidTestCaseParams + params: ValidTestCaseParams, ): RuleTester.ValidTestCase { const code = formatCode(FORMAT_STRING[testCaseKind], params.import.input);