prisma-lint
Advanced tools
Comparing version 0.3.0 to 0.4.0
@@ -24,2 +24,8 @@ import { Enum } from '@kejistan/enum'; | ||
} | ||
export function listEnumBlocks(schema) { | ||
return schema.list.filter((block) => block.type === 'enum'); | ||
} | ||
export function listCustomTypeBlocks(schema) { | ||
return schema.list.filter((block) => block.type === 'type'); | ||
} | ||
export function listAttributes(node) { | ||
@@ -26,0 +32,0 @@ const attributes = node.properties.filter((p) => p.type === PrismaPropertyType.ATTRIBUTE); |
import { getPrismaSchema } from '#src/common/get-prisma-schema.js'; | ||
import { isModelEntirelyIgnored, isRuleEntirelyIgnored, listIgnoreModelComments, } from '#src/common/ignore.js'; | ||
import { listModelBlocks, listFields } from '#src/common/prisma.js'; | ||
import { listModelBlocks, listFields, listEnumBlocks, listCustomTypeBlocks, } from '#src/common/prisma.js'; | ||
export function lintPrismaSourceCode({ rules, fileName, sourceCode, }) { | ||
@@ -9,2 +9,6 @@ // Parse source code into AST. | ||
const violations = []; | ||
const enums = listEnumBlocks(prismaSchema); | ||
const enumNames = new Set(enums.map((e) => e.name)); | ||
const customTypes = listCustomTypeBlocks(prismaSchema); | ||
const customTypeNames = new Set(customTypes.map((e) => e.name)); | ||
// Create rule instances. | ||
@@ -14,3 +18,9 @@ const namedRuleInstances = rules.map(({ ruleDefinition, ruleConfig }) => { | ||
const report = (nodeViolation) => violations.push({ ruleName, fileName, ...nodeViolation }); | ||
const context = { fileName, report, sourceCode }; | ||
const context = { | ||
customTypeNames, | ||
enumNames, | ||
fileName, | ||
report, | ||
sourceCode, | ||
}; | ||
const ruleInstance = ruleDefinition.create(ruleConfig, context); | ||
@@ -17,0 +27,0 @@ return { ruleName, ruleInstance }; |
@@ -22,4 +22,6 @@ import { z } from 'zod'; | ||
* model UserRole { | ||
* // No mapping needed. | ||
* // No mapping needed for single-word field name. | ||
* id String | ||
* // No mapping needed for association field. | ||
* grantedByUser User | ||
* } | ||
@@ -36,3 +38,2 @@ * | ||
* | ||
* | ||
* @example { compoundWords: ["GraphQL"] } | ||
@@ -62,2 +63,33 @@ * // good | ||
* | ||
* @example enum | ||
* // good | ||
* enum RoleType { | ||
* ADMIN | ||
* MEMBER | ||
* } | ||
* | ||
* model UserRole { | ||
* roleType RoleType @map(name: "role_type") | ||
* } | ||
* | ||
* // bad | ||
* model UserRole { | ||
* roleType RoleType | ||
* } | ||
* | ||
* @example custom types | ||
* // good | ||
* type UserInfo { | ||
* institution String | ||
* } | ||
* | ||
* model User { | ||
* userInfo UserInfo @map(name: "user_info") | ||
* } | ||
* | ||
* // bad | ||
* model User { | ||
* userInfo UserInfo | ||
* } | ||
* | ||
*/ | ||
@@ -71,3 +103,6 @@ export default { | ||
Field: (model, field) => { | ||
if (isAssociation(field.fieldType)) { | ||
const { fieldType } = field; | ||
if (!isEnumField(context.enumNames, fieldType) && | ||
!isCustomTypeField(context.customTypeNames, fieldType) && | ||
looksLikeAssociation(fieldType)) { | ||
return; | ||
@@ -122,3 +157,3 @@ } | ||
} | ||
function isAssociation(fieldType) { | ||
function looksLikeAssociation(fieldType) { | ||
if (typeof fieldType != 'string') { | ||
@@ -135,1 +170,13 @@ return false; | ||
} | ||
function isEnumField(enumNames, fieldType) { | ||
if (typeof fieldType != 'string') { | ||
return false; | ||
} | ||
return enumNames.has(fieldType); | ||
} | ||
function isCustomTypeField(customTypeNames, fieldType) { | ||
if (typeof fieldType != 'string') { | ||
return false; | ||
} | ||
return customTypeNames.has(fieldType); | ||
} |
{ | ||
"name": "prisma-lint", | ||
"version": "0.3.0", | ||
"version": "0.4.0", | ||
"description": "A linter for Prisma schema files.", | ||
@@ -57,3 +57,3 @@ "repository": { | ||
"eslint-plugin-import": "^2.27.5", | ||
"eslint-plugin-jest": "^27.2.1", | ||
"eslint-plugin-jest": "^28.2.0", | ||
"husky": "^9.0.7", | ||
@@ -60,0 +60,0 @@ "jest": "^29.3.1", |
65013
1841