Skip to content

Commit

Permalink
feat: ensure the provider type is factory
Browse files Browse the repository at this point in the history
  • Loading branch information
thiagomini committed Feb 5, 2024
1 parent 728efed commit 061b85b
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 3 deletions.
72 changes: 70 additions & 2 deletions src/rules/enforce-custom-provider-type.rule.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import { ESLintUtils } from '@typescript-eslint/utils';
import {
ASTUtils,
AST_NODE_TYPES,
ESLintUtils,
type TSESTree,
} from '@typescript-eslint/utils';

const createRule = ESLintUtils.RuleCreator(
(name) => `https://eslint.org/docs/latest/rules/${name}`
Expand Down Expand Up @@ -45,8 +50,71 @@ export default createRule<Options, MessageIds>({
},
defaultOptions,
create(context) {
const options = context.options[0] || defaultOptions[0];
const preferredType = options.prefer;
return {
'Program:exit': (node) => {},
'Identifier[typeAnnotation.typeAnnotation.type="TSTypeReference"]': (
node: TSESTree.Identifier
) => {
const typeName = (
node.typeAnnotation?.typeAnnotation as TSESTree.TSTypeReference
).typeName;

if (ASTUtils.isIdentifier(typeName) && typeName.name === 'Provider') {
const providerType = getProviderType(node);
if (providerType && providerType !== preferredType) {
context.report({
node,
messageId: 'providerTypeMismatch',
data: {
preferred: preferredType,
},
});
}
}
},
};
},
});

function getProviderType(node: TSESTree.Identifier): ProviderType | undefined {
const parent = node.parent;

if (ASTUtils.isVariableDeclarator(parent)) {
const init = parent.init;
let type: ProviderType | undefined;
if (init?.type === AST_NODE_TYPES.ObjectExpression) {
const properties = init.properties;
for (const property of properties) {
if (
property.type === AST_NODE_TYPES.Property &&
ASTUtils.isIdentifier(property.key) &&
property.key.name === 'useFactory'
) {
type = 'factory';
break;
}

if (
property.type === AST_NODE_TYPES.Property &&
ASTUtils.isIdentifier(property.key) &&
property.key.name === 'useClass'
) {
type = 'class';
break;
}

if (
property.type === AST_NODE_TYPES.Property &&
ASTUtils.isIdentifier(property.key) &&
property.key.name === 'useValue'
) {
type = 'value';
break;
}
}
}

return type;
}
}
22 changes: 21 additions & 1 deletion tests/rules/enforce-custom-provider-type.rule.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,5 +33,25 @@ ruleTester.run('enforce-custom-provider-type', enforceCustomProviderTypeRule, {
],
},
],
invalid: [],
invalid: [
{
code: `
import { Provider } from '@nestjs/common';
const customValueProvider: Provider = {
provide: 'TOKEN',
useValue: 'some-value' // ⚠️ provider is not of type "factory"
}
`,
options: [
{
prefer: 'factory',
},
],
errors: [
{
messageId: 'providerTypeMismatch',
},
],
},
],
});

0 comments on commit 061b85b

Please sign in to comment.