diff --git a/package.json b/package.json index 80dd4413..06d97e20 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "scripts": { "test": "yarn workspaces foreach run test --colors", "lint": "yarn workspaces foreach run lint", - "build": "yarn workspaces foreach run build" + "build": "yarn workspace react-obsidian build && yarn workspace eslint-plugin-obsidian build" }, "workspaces": [ "packages/*" diff --git a/packages/eslint-plugin-obsidian/jest.config.js b/packages/eslint-plugin-obsidian/jest.config.js index 65b9b87d..36b2f522 100644 --- a/packages/eslint-plugin-obsidian/jest.config.js +++ b/packages/eslint-plugin-obsidian/jest.config.js @@ -3,7 +3,7 @@ const config = { resetMocks: true, resetModules: true, roots: [ - 'rules', + 'tests' ], testEnvironment: 'jsdom', }; diff --git a/packages/eslint-plugin-obsidian/package.json b/packages/eslint-plugin-obsidian/package.json index 7128af5c..25f5b97b 100644 --- a/packages/eslint-plugin-obsidian/package.json +++ b/packages/eslint-plugin-obsidian/package.json @@ -4,7 +4,7 @@ "main": "dist/index.js", "version": "2.5.0", "scripts": { - "build": "npx tsc", + "build": "npx tsc --project tsconfig.prod.json", "test": "npx jest", "lint": "eslint rules --ignore-pattern '*.d.ts' --ext .ts,.tsx,.js" }, @@ -15,7 +15,8 @@ "LICENSE" ], "peerDependencies": { - "eslint": "8.x.x" + "eslint": "8.x.x", + "react-obsidian": "2.x.x" }, "dependencies": { "@typescript-eslint/parser": "6.6.x", @@ -48,7 +49,6 @@ "eslint-plugin-unused-imports": "3.1.x", "jest": "29.5.x", "jest-extended": "^4.0.0", - "react-obsidian": "2.x.x", "typescript": "^4.5.4" }, "keywords": [ diff --git a/packages/eslint-plugin-obsidian/rules/framework/pathResolver.ts b/packages/eslint-plugin-obsidian/rules/framework/pathResolver.ts new file mode 100644 index 00000000..6273c7c7 --- /dev/null +++ b/packages/eslint-plugin-obsidian/rules/framework/pathResolver.ts @@ -0,0 +1,8 @@ +import type { RuleContext } from '@typescript-eslint/utils/ts-eslint'; +import path = require('path') ; + +export class PathResolver { + public resolve(context: RuleContext, relativeFilePath: string) { + return path.join(path.dirname(context.getFilename()), `${relativeFilePath}.ts`); + } +} \ No newline at end of file diff --git a/packages/eslint-plugin-obsidian/rules/index.ts b/packages/eslint-plugin-obsidian/rules/index.ts index 59fbbca7..4710f590 100644 --- a/packages/eslint-plugin-obsidian/rules/index.ts +++ b/packages/eslint-plugin-obsidian/rules/index.ts @@ -1,7 +1,7 @@ -const { unresolvedProviderDependencies } = require('./unresolvedProviderDependencies'); +const { unresolvedProviderDependenciesGenerator } = require('./unresolvedProviderDependencies'); module.exports = { rules: { - 'unresolved-provider-dependencies': unresolvedProviderDependencies, + 'unresolved-provider-dependencies': unresolvedProviderDependenciesGenerator(), }, }; diff --git a/packages/eslint-plugin-obsidian/rules/unresolvedProviderDependencies/ASTFunctions.ts b/packages/eslint-plugin-obsidian/rules/unresolvedProviderDependencies/ASTFunctions.ts index 372c1538..e6e0418d 100644 --- a/packages/eslint-plugin-obsidian/rules/unresolvedProviderDependencies/ASTFunctions.ts +++ b/packages/eslint-plugin-obsidian/rules/unresolvedProviderDependencies/ASTFunctions.ts @@ -1,8 +1,8 @@ import { TSESTree } from '@typescript-eslint/types'; import * as fs from 'fs'; import { parse } from '@typescript-eslint/parser'; -import path = require('path') ; import type { RuleContext } from '@typescript-eslint/utils/ts-eslint'; +import { PathResolver } from '../framework/pathResolver'; export type MessageIds = 'unresolved-provider-dependencies'; @@ -30,6 +30,7 @@ export function getDependenciesFromSubgraphs( imports: TSESTree.ImportDeclaration[], subGraphs:string[], context:RuleContext<'unresolved-provider-dependencies', []>, + pathResolver: PathResolver, ) { const paths:Record[] = []; const dependencies: string[] = []; @@ -42,8 +43,8 @@ export function getDependenciesFromSubgraphs( }); paths.forEach((el) => { // eslint-disable-next-line dot-notation - const filePath = path.join(path.dirname(context.getFilename()), `${el['path']}.ts`); - const fileContent = fs.readFileSync(filePath, 'utf8'); + const filePath = pathResolver.resolve(context, el['path']); + const fileContent = fs.readFileSync(filePath, { encoding: 'utf8'}); const fileAST = parse( fileContent, { diff --git a/packages/eslint-plugin-obsidian/rules/unresolvedProviderDependencies/createFunction.ts b/packages/eslint-plugin-obsidian/rules/unresolvedProviderDependencies/createRule.ts similarity index 85% rename from packages/eslint-plugin-obsidian/rules/unresolvedProviderDependencies/createFunction.ts rename to packages/eslint-plugin-obsidian/rules/unresolvedProviderDependencies/createRule.ts index 9670929d..7993f314 100644 --- a/packages/eslint-plugin-obsidian/rules/unresolvedProviderDependencies/createFunction.ts +++ b/packages/eslint-plugin-obsidian/rules/unresolvedProviderDependencies/createRule.ts @@ -8,8 +8,12 @@ import { getDecoratorName, getPropertyDeclarations, } from './ASTFunctions'; +import type { PathResolver } from '../framework/pathResolver'; -export function create(context: RuleContext<'unresolved-provider-dependencies', []>) { +export function create( + context: RuleContext<'unresolved-provider-dependencies', []>, + pathResolver: PathResolver, +) { const imports:TSESTree.ImportDeclaration[] = []; const dependencies:string[] = []; @@ -24,7 +28,7 @@ export function create(context: RuleContext<'unresolved-provider-dependencies', if (decoratorNames.includes('Graph')) { const subGraphs = getSubGraphs(decorators); if (subGraphs.length > 0) { - dependencies.push(...getDependenciesFromSubgraphs(imports, subGraphs, context)); + dependencies.push(...getDependenciesFromSubgraphs(imports, subGraphs, context, pathResolver)); } dependencies.push(...mapFunctions(node)); dependencies.push(...getPropertyDeclarations(node)); diff --git a/packages/eslint-plugin-obsidian/rules/unresolvedProviderDependencies/index.ts b/packages/eslint-plugin-obsidian/rules/unresolvedProviderDependencies/index.ts index b9db3e19..b2b24573 100644 --- a/packages/eslint-plugin-obsidian/rules/unresolvedProviderDependencies/index.ts +++ b/packages/eslint-plugin-obsidian/rules/unresolvedProviderDependencies/index.ts @@ -1,26 +1,33 @@ import { ESLintUtils, type TSESLint } from '@typescript-eslint/utils'; -import { create } from './createFunction'; +import type { RuleContext } from '@typescript-eslint/utils/ts-eslint'; +import { create } from './createRule'; +import { PathResolver } from '../framework/pathResolver'; + +type Rule = TSESLint.RuleModule<'unresolved-provider-dependencies', []>; const createRule = ESLintUtils.RuleCreator( (name) => `https://wix-incubator.github.io/obsidian/docs/documentation/meta/eslint#${name}`, ); -type Rule = TSESLint.RuleModule<'unresolved-provider-dependencies', []>; - - -export const unresolvedProviderDependencies: Rule = createRule({ - create, - name: 'unresolved-provider-dependencies', - meta: { - docs: { - description: 'Dependencies must be defined in the graph or its subgraphs.', - recommended: 'strict', +export const unresolvedProviderDependenciesGenerator = ( + pathResolver: PathResolver = new PathResolver(), +) => { + return createRule({ + create: (context: RuleContext<'unresolved-provider-dependencies', []>) => { + return create(context, pathResolver); }, - messages: { - 'unresolved-provider-dependencies': 'Dependency {{ dependencyName }} is unresolved.', + name: 'unresolved-provider-dependencies', + meta: { + docs: { + description: 'Dependencies must be defined in the graph or its subgraphs.', + recommended: 'strict', + }, + messages: { + 'unresolved-provider-dependencies': 'Dependency {{ dependencyName }} is unresolved.', + }, + schema: [], + type: 'problem', }, - schema: [], - type: 'problem', - }, - defaultOptions: [], -}); + defaultOptions: [], + }) satisfies Rule; +}; \ No newline at end of file diff --git a/packages/eslint-plugin-obsidian/rules/unresolvedProviderDependencies/unresolvedDependencies.test.ts b/packages/eslint-plugin-obsidian/rules/unresolvedProviderDependencies/unresolvedDependencies.test.ts deleted file mode 100644 index 5d1065fa..00000000 --- a/packages/eslint-plugin-obsidian/rules/unresolvedProviderDependencies/unresolvedDependencies.test.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { RuleTester } from '@typescript-eslint/rule-tester'; -import { validGraphSimple } from './testUtils/validGraphs'; -import { invalidGraph } from './invalidGraphs'; -import { unresolvedProviderDependencies } from '.'; - -const ruleTester = new RuleTester(); - -ruleTester.run('unresolved-provider-dependencies', unresolvedProviderDependencies, { - valid: [validGraphSimple], - invalid: [{ - code: invalidGraph, - errors: [{ - messageId: 'unresolved-provider-dependencies', - }], - }], -}); diff --git a/packages/eslint-plugin-obsidian/tests/stubs/PathResolverStub.ts b/packages/eslint-plugin-obsidian/tests/stubs/PathResolverStub.ts new file mode 100644 index 00000000..adf1f46c --- /dev/null +++ b/packages/eslint-plugin-obsidian/tests/stubs/PathResolverStub.ts @@ -0,0 +1,14 @@ +import type { RuleContext } from '@typescript-eslint/utils/ts-eslint'; +import path = require('path') ; +import { PathResolver } from '../../rules/framework/pathResolver'; + +export class PathResolverStub implements PathResolver { + public resolve(context: RuleContext, relativeFilePath: string): string { + switch(relativeFilePath) { + case './subgraph': + return `${context.cwd}/tests/unresolvedProviderDependencies/testUtils/subgraph.ts`; + default: + return path.join(path.dirname(context.getFilename()), `${relativeFilePath}.ts`); + } + } +} \ No newline at end of file diff --git a/packages/eslint-plugin-obsidian/rules/unresolvedProviderDependencies/testUtils/subgraph.ts b/packages/eslint-plugin-obsidian/tests/unresolvedProviderDependencies/testUtils/subgraph.ts similarity index 100% rename from packages/eslint-plugin-obsidian/rules/unresolvedProviderDependencies/testUtils/subgraph.ts rename to packages/eslint-plugin-obsidian/tests/unresolvedProviderDependencies/testUtils/subgraph.ts diff --git a/packages/eslint-plugin-obsidian/rules/unresolvedProviderDependencies/testUtils/validGraphs.ts b/packages/eslint-plugin-obsidian/tests/unresolvedProviderDependencies/testUtils/validGraphs.ts similarity index 100% rename from packages/eslint-plugin-obsidian/rules/unresolvedProviderDependencies/testUtils/validGraphs.ts rename to packages/eslint-plugin-obsidian/tests/unresolvedProviderDependencies/testUtils/validGraphs.ts diff --git a/packages/eslint-plugin-obsidian/tests/unresolvedProviderDependencies/unresolvedDependencies.test.ts b/packages/eslint-plugin-obsidian/tests/unresolvedProviderDependencies/unresolvedDependencies.test.ts new file mode 100644 index 00000000..a502dd19 --- /dev/null +++ b/packages/eslint-plugin-obsidian/tests/unresolvedProviderDependencies/unresolvedDependencies.test.ts @@ -0,0 +1,23 @@ +import { RuleTester } from '@typescript-eslint/rule-tester'; +import { validGraphSimple, validGraphWithSubgraph } from './testUtils/validGraphs'; +import { unresolvedProviderDependenciesGenerator } from '../../rules/unresolvedProviderDependencies'; +import { invalidGraph } from '../../rules/unresolvedProviderDependencies/invalidGraphs'; +import { PathResolverStub } from '../stubs/PathResolverStub'; + +const ruleTester = new RuleTester(); + +ruleTester.run( + 'unresolved-provider-dependencies', + unresolvedProviderDependenciesGenerator(new PathResolverStub()), + { + valid: [validGraphSimple, validGraphWithSubgraph], + invalid: [ + { + code: invalidGraph, + errors: [{ + messageId: 'unresolved-provider-dependencies', + }], + }, + ], + } +); diff --git a/packages/eslint-plugin-obsidian/tsconfig.json b/packages/eslint-plugin-obsidian/tsconfig.json index ee6d0607..325870d6 100644 --- a/packages/eslint-plugin-obsidian/tsconfig.json +++ b/packages/eslint-plugin-obsidian/tsconfig.json @@ -1,6 +1,7 @@ { "include": [ "rules/**/*", + "tests/**/*", ".eslintrc.js", ], "exclude": [ diff --git a/packages/eslint-plugin-obsidian/tsconfig.prod.json b/packages/eslint-plugin-obsidian/tsconfig.prod.json new file mode 100644 index 00000000..2fcaf67e --- /dev/null +++ b/packages/eslint-plugin-obsidian/tsconfig.prod.json @@ -0,0 +1,7 @@ +{ + "extends": "./tsconfig.json", + "exclude": [ + "**/*.test.*", + "tests" + ] +} diff --git a/yarn.lock b/yarn.lock index 829c2754..0d72cef7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4054,10 +4054,10 @@ __metadata: jest: 29.5.x jest-extended: ^4.0.0 lodash: ^4.17.21 - react-obsidian: 2.x.x typescript: ^4.5.4 peerDependencies: eslint: 8.x.x + react-obsidian: 2.x.x languageName: unknown linkType: soft @@ -6836,7 +6836,7 @@ __metadata: languageName: node linkType: hard -"react-obsidian@2.x.x, react-obsidian@workspace:packages/react-obsidian": +"react-obsidian@workspace:packages/react-obsidian": version: 0.0.0-use.local resolution: "react-obsidian@workspace:packages/react-obsidian" dependencies: