@webpieces/code-rules 0.3.195 ā 0.3.197
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +2 -2
- package/src/diff-utils.d.ts +3 -22
- package/src/diff-utils.js +9 -116
- package/src/diff-utils.js.map +1 -1
- package/src/validate-catch-error-pattern.d.ts +1 -1
- package/src/validate-catch-error-pattern.js +7 -152
- package/src/validate-catch-error-pattern.js.map +1 -1
- package/src/validate-dtos.d.ts +1 -1
- package/src/validate-dtos.js +6 -141
- package/src/validate-dtos.js.map +1 -1
- package/src/validate-modified-files.js +3 -87
- package/src/validate-modified-files.js.map +1 -1
- package/src/validate-modified-methods.d.ts +1 -1
- package/src/validate-modified-methods.js +7 -197
- package/src/validate-modified-methods.js.map +1 -1
- package/src/validate-new-methods.js +4 -164
- package/src/validate-new-methods.js.map +1 -1
- package/src/validate-no-any-unknown.d.ts +1 -1
- package/src/validate-no-any-unknown.js +7 -143
- package/src/validate-no-any-unknown.js.map +1 -1
- package/src/validate-no-destructure.d.ts +1 -1
- package/src/validate-no-destructure.js +7 -143
- package/src/validate-no-destructure.js.map +1 -1
- package/src/validate-no-direct-api-resolver.d.ts +1 -1
- package/src/validate-no-direct-api-resolver.js +10 -89
- package/src/validate-no-direct-api-resolver.js.map +1 -1
- package/src/validate-no-implicit-any.d.ts +1 -1
- package/src/validate-no-implicit-any.js +6 -94
- package/src/validate-no-implicit-any.js.map +1 -1
- package/src/validate-no-inline-types.d.ts +1 -1
- package/src/validate-no-inline-types.js +10 -174
- package/src/validate-no-inline-types.js.map +1 -1
- package/src/validate-no-symbol-di-tokens.d.ts +1 -1
- package/src/validate-no-symbol-di-tokens.js +6 -130
- package/src/validate-no-symbol-di-tokens.js.map +1 -1
- package/src/validate-no-unmanaged-exceptions.d.ts +1 -1
- package/src/validate-no-unmanaged-exceptions.js +7 -152
- package/src/validate-no-unmanaged-exceptions.js.map +1 -1
- package/src/validate-prisma-converters.d.ts +1 -1
- package/src/validate-prisma-converters.js +10 -89
- package/src/validate-prisma-converters.js.map +1 -1
- package/src/validate-return-types.d.ts +1 -1
- package/src/validate-return-types.js +10 -174
- package/src/validate-return-types.js.map +1 -1
|
@@ -43,96 +43,17 @@
|
|
|
43
43
|
* ============================================================================
|
|
44
44
|
* - OFF: Skip validation entirely
|
|
45
45
|
* - NEW_AND_MODIFIED_METHODS: Validate new/modified methods in converters + changed lines in non-converters
|
|
46
|
-
* -
|
|
46
|
+
* - NEW_AND_MODIFIED_FILES: Validate all methods in modified files
|
|
47
47
|
*/
|
|
48
48
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
49
49
|
exports.PrismaConverterValidator = void 0;
|
|
50
50
|
const tslib_1 = require("tslib");
|
|
51
|
-
const child_process_1 = require("child_process");
|
|
52
51
|
const fs = tslib_1.__importStar(require("fs"));
|
|
53
52
|
const path = tslib_1.__importStar(require("path"));
|
|
54
53
|
const ts = tslib_1.__importStar(require("typescript"));
|
|
55
|
-
const diff_utils_1 = require("./diff-utils");
|
|
56
54
|
const rules_config_1 = require("@webpieces/rules-config");
|
|
57
55
|
const code_validator_1 = require("./code-validator");
|
|
58
56
|
const resolve_mode_1 = require("./resolve-mode");
|
|
59
|
-
/**
|
|
60
|
-
* Auto-detect the base branch by finding the merge-base with origin/main.
|
|
61
|
-
*/
|
|
62
|
-
function detectBase(workspaceRoot) {
|
|
63
|
-
// eslint-disable-next-line @webpieces/no-unmanaged-exceptions
|
|
64
|
-
try {
|
|
65
|
-
const mergeBase = (0, child_process_1.execSync)('git merge-base HEAD origin/main', {
|
|
66
|
-
cwd: workspaceRoot,
|
|
67
|
-
encoding: 'utf-8',
|
|
68
|
-
stdio: ['pipe', 'pipe', 'pipe'],
|
|
69
|
-
}).trim();
|
|
70
|
-
if (mergeBase) {
|
|
71
|
-
return mergeBase;
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
catch (err) {
|
|
75
|
-
//const error = toError(err);
|
|
76
|
-
// eslint-disable-next-line @webpieces/no-unmanaged-exceptions
|
|
77
|
-
try {
|
|
78
|
-
const mergeBase = (0, child_process_1.execSync)('git merge-base HEAD main', {
|
|
79
|
-
cwd: workspaceRoot,
|
|
80
|
-
encoding: 'utf-8',
|
|
81
|
-
stdio: ['pipe', 'pipe', 'pipe'],
|
|
82
|
-
}).trim();
|
|
83
|
-
if (mergeBase) {
|
|
84
|
-
return mergeBase;
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
catch (err2) {
|
|
88
|
-
//const error2 = toError(err2);
|
|
89
|
-
// Ignore
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
return null;
|
|
93
|
-
}
|
|
94
|
-
/**
|
|
95
|
-
* Get changed TypeScript files between base and head (or working tree if head not specified).
|
|
96
|
-
*/
|
|
97
|
-
// webpieces-disable max-lines-new-methods -- Git command handling with untracked files requires multiple code paths
|
|
98
|
-
function getChangedTypeScriptFiles(workspaceRoot, base, head) {
|
|
99
|
-
// eslint-disable-next-line @webpieces/no-unmanaged-exceptions
|
|
100
|
-
try {
|
|
101
|
-
const diffTarget = head ? `${base} ${head}` : base;
|
|
102
|
-
const output = (0, child_process_1.execSync)(`git diff --name-only ${diffTarget} -- '*.ts' '*.tsx'`, {
|
|
103
|
-
cwd: workspaceRoot,
|
|
104
|
-
encoding: 'utf-8',
|
|
105
|
-
});
|
|
106
|
-
const changedFiles = output
|
|
107
|
-
.trim()
|
|
108
|
-
.split('\n')
|
|
109
|
-
.filter((f) => f && !f.includes('.spec.ts') && !f.includes('.test.ts'));
|
|
110
|
-
if (!head) {
|
|
111
|
-
// eslint-disable-next-line @webpieces/no-unmanaged-exceptions
|
|
112
|
-
try {
|
|
113
|
-
const untrackedOutput = (0, child_process_1.execSync)(`git ls-files --others --exclude-standard '*.ts' '*.tsx'`, {
|
|
114
|
-
cwd: workspaceRoot,
|
|
115
|
-
encoding: 'utf-8',
|
|
116
|
-
});
|
|
117
|
-
const untrackedFiles = untrackedOutput
|
|
118
|
-
.trim()
|
|
119
|
-
.split('\n')
|
|
120
|
-
.filter((f) => f && !f.includes('.spec.ts') && !f.includes('.test.ts'));
|
|
121
|
-
const allFiles = new Set([...changedFiles, ...untrackedFiles]);
|
|
122
|
-
return Array.from(allFiles);
|
|
123
|
-
}
|
|
124
|
-
catch (err) {
|
|
125
|
-
//const error = toError(err);
|
|
126
|
-
return changedFiles;
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
return changedFiles;
|
|
130
|
-
}
|
|
131
|
-
catch (err) {
|
|
132
|
-
//const error = toError(err);
|
|
133
|
-
return [];
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
57
|
/**
|
|
137
58
|
* Parse schema.prisma to extract all model names into a Set.
|
|
138
59
|
*/
|
|
@@ -406,7 +327,7 @@ function findConverterViolationsForModifiedMethods(filePath, workspaceRoot, pris
|
|
|
406
327
|
if (ts.isFunctionDeclaration(node) && node.name) {
|
|
407
328
|
const start = ctx.sourceFile.getLineAndCharacterOfPosition(node.getStart(ctx.sourceFile));
|
|
408
329
|
const end = ctx.sourceFile.getLineAndCharacterOfPosition(node.getEnd());
|
|
409
|
-
if ((0,
|
|
330
|
+
if ((0, rules_config_1.isNewOrModified)(node.name.text, start.line + 1, end.line + 1, changedLines, newMethodNames)) {
|
|
410
331
|
const violation = checkStandaloneFunction(node, ctx);
|
|
411
332
|
if (violation)
|
|
412
333
|
violations.push(violation);
|
|
@@ -416,7 +337,7 @@ function findConverterViolationsForModifiedMethods(filePath, workspaceRoot, pris
|
|
|
416
337
|
const start = ctx.sourceFile.getLineAndCharacterOfPosition(node.getStart(ctx.sourceFile));
|
|
417
338
|
const end = ctx.sourceFile.getLineAndCharacterOfPosition(node.getEnd());
|
|
418
339
|
const methodName = node.name.getText(ctx.sourceFile);
|
|
419
|
-
if ((0,
|
|
340
|
+
if ((0, rules_config_1.isNewOrModified)(methodName, start.line + 1, end.line + 1, changedLines, newMethodNames)) {
|
|
420
341
|
violations.push(...checkConverterMethod(node, ctx));
|
|
421
342
|
}
|
|
422
343
|
}
|
|
@@ -475,9 +396,9 @@ function collectViolationsForModifiedMethodAndCode(changedFiles, convertersPaths
|
|
|
475
396
|
if (converterFiles.length > 0) {
|
|
476
397
|
console.log(`š Checking ${converterFiles.length} converter file(s) (new/modified methods only)...`);
|
|
477
398
|
for (const file of converterFiles) {
|
|
478
|
-
const diff = (0,
|
|
479
|
-
const changedLines = (0,
|
|
480
|
-
const newMethodNames = (0,
|
|
399
|
+
const diff = (0, rules_config_1.getFileDiff)(workspaceRoot, file, base, head);
|
|
400
|
+
const changedLines = (0, rules_config_1.getChangedLineNumbers)(diff);
|
|
401
|
+
const newMethodNames = (0, rules_config_1.findNewMethodSignaturesInDiff)(diff);
|
|
481
402
|
if (changedLines.size === 0 && newMethodNames.size === 0)
|
|
482
403
|
continue;
|
|
483
404
|
allViolations.push(...findConverterViolationsForModifiedMethods(file, workspaceRoot, prismaModels, disableAllowed, changedLines, newMethodNames));
|
|
@@ -486,8 +407,8 @@ function collectViolationsForModifiedMethodAndCode(changedFiles, convertersPaths
|
|
|
486
407
|
if (nonConverterFiles.length > 0) {
|
|
487
408
|
console.log(`š Checking ${nonConverterFiles.length} non-converter file(s) for Dto creation (changed lines only)...`);
|
|
488
409
|
for (const file of nonConverterFiles) {
|
|
489
|
-
const diff = (0,
|
|
490
|
-
const changedLines = (0,
|
|
410
|
+
const diff = (0, rules_config_1.getFileDiff)(workspaceRoot, file, base, head);
|
|
411
|
+
const changedLines = (0, rules_config_1.getChangedLineNumbers)(diff);
|
|
491
412
|
if (changedLines.size === 0)
|
|
492
413
|
continue;
|
|
493
414
|
allViolations.push(...findDtoCreationOnChangedLines(file, workspaceRoot, prismaModels, convertersPaths, disableAllowed, changedLines));
|
|
@@ -533,7 +454,7 @@ function resolveBase(workspaceRoot) {
|
|
|
533
454
|
const envBase = process.env['NX_BASE'];
|
|
534
455
|
if (envBase)
|
|
535
456
|
return envBase;
|
|
536
|
-
return detectBase(workspaceRoot) ?? undefined;
|
|
457
|
+
return (0, rules_config_1.detectBase)(workspaceRoot) ?? undefined;
|
|
537
458
|
}
|
|
538
459
|
/**
|
|
539
460
|
* Collect all violations from converter and non-converter files.
|
|
@@ -572,7 +493,7 @@ function validateChangedFiles(workspaceRoot, schemaPath, convertersPaths, enforc
|
|
|
572
493
|
return { success: true };
|
|
573
494
|
}
|
|
574
495
|
console.log(` Found ${prismaModels.size} model(s) in schema.prisma`);
|
|
575
|
-
let changedFiles =
|
|
496
|
+
let changedFiles = (0, rules_config_1.getChangedFiles)(workspaceRoot, base, head);
|
|
576
497
|
if (enforcePaths.length > 0) {
|
|
577
498
|
changedFiles = changedFiles.filter((f) => enforcePaths.some((ep) => f.startsWith(ep)));
|
|
578
499
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validate-prisma-converters.js","sourceRoot":"","sources":["../../../../../packages/tooling/code-rules/src/validate-prisma-converters.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Validate Prisma Converters Executor\n *\n * Validates that Prisma converter methods follow a scalable pattern:\n * methods returning XxxDto (where XxxDbo exists in schema.prisma) must\n * accept that exact XxxDbo as the first parameter. This keeps single-table\n * converters clean and forces join converters to compose them.\n *\n * ============================================================================\n * RULES\n * ============================================================================\n *\n * 1. First param must be exact Dbo:\n * If method returns XxxDto and XxxDbo exists in schema.prisma,\n * the first parameter must be of type XxxDbo.\n *\n * 2. Extra params must be booleans:\n * Additional parameters beyond the Dbo are allowed but must be boolean\n * (used for filtering payloads / security info).\n *\n * 3. No async converters:\n * Methods returning Promise<XxxDto> are flagged ā converters should be\n * pure data mapping, no async work.\n *\n * 4. No standalone functions:\n * Standalone functions in converter files are flagged ā must be class\n * methods so the converter class can be injected (dependency tree tracing).\n *\n * 5. Dto creation outside converters directory:\n * Files outside the configured convertersPath that create `new XxxDto(...)`\n * where XxxDbo exists in schema.prisma are flagged ā Dto instances tied to\n * a Dbo must only be created via a converter class.\n *\n * ============================================================================\n * SKIP CONDITIONS\n * ============================================================================\n * - Methods with @deprecated decorator or JSDoc tag\n * - Lines with: // webpieces-disable prisma-converter -- [reason]\n *\n * ============================================================================\n * MODES\n * ============================================================================\n * - OFF: Skip validation entirely\n * - NEW_AND_MODIFIED_METHODS: Validate new/modified methods in converters + changed lines in non-converters\n * - MODIFIED_FILES: Validate all methods in modified files\n */\n\nimport { execSync } from 'child_process';\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport * as ts from 'typescript';\nimport { getFileDiff, getChangedLineNumbers, findNewMethodSignaturesInDiff, isNewOrModified } from './diff-utils';\nimport { hasDisable, RULE_NAMES, PrismaConverterConfig, PrismaConverterMode } from '@webpieces/rules-config';\nimport { CodeValidator, ExecutorResult } from './code-validator';\nimport { shouldSkipRule } from './resolve-mode';\n\ninterface PrismaConverterViolation {\n file: string;\n line: number;\n message: string;\n}\n\ninterface UnwrapResult {\n inner: string;\n isAsync: boolean;\n}\n\ninterface FileContext {\n filePath: string;\n fileLines: string[];\n sourceFile: ts.SourceFile;\n prismaModels: Set<string>;\n disableAllowed: boolean;\n}\n\n/**\n * Auto-detect the base branch by finding the merge-base with origin/main.\n */\nfunction detectBase(workspaceRoot: string): string | null {\n // eslint-disable-next-line @webpieces/no-unmanaged-exceptions\n try {\n const mergeBase = execSync('git merge-base HEAD origin/main', {\n cwd: workspaceRoot,\n encoding: 'utf-8',\n stdio: ['pipe', 'pipe', 'pipe'],\n }).trim();\n\n if (mergeBase) {\n return mergeBase;\n }\n } catch (err: unknown) {\n //const error = toError(err);\n // eslint-disable-next-line @webpieces/no-unmanaged-exceptions\n try {\n const mergeBase = execSync('git merge-base HEAD main', {\n cwd: workspaceRoot,\n encoding: 'utf-8',\n stdio: ['pipe', 'pipe', 'pipe'],\n }).trim();\n\n if (mergeBase) {\n return mergeBase;\n }\n } catch (err2: unknown) {\n //const error2 = toError(err2);\n // Ignore\n }\n }\n return null;\n}\n\n/**\n * Get changed TypeScript files between base and head (or working tree if head not specified).\n */\n// webpieces-disable max-lines-new-methods -- Git command handling with untracked files requires multiple code paths\nfunction getChangedTypeScriptFiles(workspaceRoot: string, base: string, head?: string): string[] {\n // eslint-disable-next-line @webpieces/no-unmanaged-exceptions\n try {\n const diffTarget = head ? `${base} ${head}` : base;\n const output = execSync(`git diff --name-only ${diffTarget} -- '*.ts' '*.tsx'`, {\n cwd: workspaceRoot,\n encoding: 'utf-8',\n });\n const changedFiles = output\n .trim()\n .split('\\n')\n .filter((f) => f && !f.includes('.spec.ts') && !f.includes('.test.ts'));\n\n if (!head) {\n // eslint-disable-next-line @webpieces/no-unmanaged-exceptions\n try {\n const untrackedOutput = execSync(`git ls-files --others --exclude-standard '*.ts' '*.tsx'`, {\n cwd: workspaceRoot,\n encoding: 'utf-8',\n });\n const untrackedFiles = untrackedOutput\n .trim()\n .split('\\n')\n .filter((f) => f && !f.includes('.spec.ts') && !f.includes('.test.ts'));\n const allFiles = new Set([...changedFiles, ...untrackedFiles]);\n return Array.from(allFiles);\n } catch (err: unknown) {\n //const error = toError(err);\n return changedFiles;\n }\n }\n\n return changedFiles;\n } catch (err: unknown) {\n //const error = toError(err);\n return [];\n }\n}\n\n/**\n * Parse schema.prisma to extract all model names into a Set.\n */\nfunction parsePrismaModels(schemaPath: string): Set<string> {\n const models = new Set<string>();\n\n if (!fs.existsSync(schemaPath)) {\n return models;\n }\n\n const content = fs.readFileSync(schemaPath, 'utf-8');\n const regex = /^model\\s+(\\w+)\\s*\\{/gm;\n let match: RegExpExecArray | null;\n\n while ((match = regex.exec(content)) !== null) {\n models.add(match[1]);\n }\n\n return models;\n}\n\n/**\n * Derive the expected Dbo name from a return type ending in Dto.\n * \"XxxDto\" -> \"XxxDbo\". Returns null if name doesn't end with Dto.\n */\nfunction deriveExpectedDboName(returnType: string): string | null {\n if (!returnType.endsWith('Dto')) return null;\n return returnType.slice(0, -3) + 'Dbo';\n}\n\n/**\n * Check if a line has a webpieces-disable comment for prisma-converter.\n */\nfunction hasDisableComment(lines: string[], lineNumber: number): boolean {\n const startCheck = Math.max(0, lineNumber - 5);\n for (let i = lineNumber - 2; i >= startCheck; i--) {\n const line = lines[i]?.trim() ?? '';\n if (line.startsWith('function ') || line.startsWith('class ') || line.endsWith('}')) {\n break;\n }\n if (hasDisable(line, RULE_NAMES.PRISMA_CONVERTER)) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * Check if a method/function node has a @deprecated decorator.\n */\nfunction hasDeprecatedDecorator(node: ts.MethodDeclaration | ts.FunctionDeclaration): boolean {\n const modifiers = ts.canHaveDecorators(node) ? ts.getDecorators(node) : undefined;\n if (!modifiers) return false;\n\n for (const decorator of modifiers) {\n const expr = decorator.expression;\n // @deprecated or @deprecated()\n if (ts.isIdentifier(expr) && expr.text === 'deprecated') return true;\n if (ts.isCallExpression(expr) && ts.isIdentifier(expr.expression) && expr.expression.text === 'deprecated') {\n return true;\n }\n }\n return false;\n}\n\n/**\n * Check if a node has @deprecated in its JSDoc comments.\n */\nfunction hasDeprecatedJsDoc(node: ts.Node): boolean {\n const jsDocs = ts.getJSDocTags(node);\n for (const tag of jsDocs) {\n if (tag.tagName.text === 'deprecated') return true;\n }\n return false;\n}\n\n/**\n * Check if a method is deprecated via decorator or JSDoc.\n */\nfunction isDeprecated(node: ts.MethodDeclaration | ts.FunctionDeclaration): boolean {\n return hasDeprecatedDecorator(node) || hasDeprecatedJsDoc(node);\n}\n\n/**\n * Extract the text of a type node, stripping whitespace.\n */\nfunction getTypeText(typeNode: ts.TypeNode, sourceFile: ts.SourceFile): string {\n return typeNode.getText(sourceFile).trim();\n}\n\n/**\n * Unwrap Promise<T> to get T. Returns the inner type text if wrapped, otherwise returns as-is.\n */\nfunction unwrapPromise(typeText: string): UnwrapResult {\n const promiseMatch = typeText.match(/^Promise\\s*<\\s*(.+)\\s*>$/);\n if (promiseMatch) {\n return { inner: promiseMatch[1].trim(), isAsync: true };\n }\n return { inner: typeText, isAsync: false };\n}\n\n/**\n * Check a standalone function declaration in a converter file and return a violation if applicable.\n */\nfunction checkStandaloneFunction(\n node: ts.FunctionDeclaration,\n ctx: FileContext\n): PrismaConverterViolation | null {\n if (!node.name) return null;\n\n const startPos = node.getStart(ctx.sourceFile);\n const pos = ctx.sourceFile.getLineAndCharacterOfPosition(startPos);\n const line = pos.line + 1;\n\n if ((ctx.disableAllowed && hasDisableComment(ctx.fileLines, line)) || isDeprecated(node)) return null;\n\n return {\n file: ctx.filePath,\n line,\n message: `Standalone function \"${node.name.text}\" found in converter file. ` +\n 'Move to a converter class so it can be injected via DI.',\n };\n}\n\n/**\n * Validate the parameters of a converter method that returns a Dto with a matching Dbo.\n */\nfunction checkMethodParams(\n node: ts.MethodDeclaration,\n innerType: string,\n expectedDbo: string,\n ctx: FileContext,\n line: number\n): PrismaConverterViolation[] {\n const violations: PrismaConverterViolation[] = [];\n const params = node.parameters;\n\n if (params.length === 0) {\n violations.push({\n file: ctx.filePath,\n line,\n message: `Method returns \"${innerType}\" but has no parameters. ` +\n `First parameter must be of type \"${expectedDbo}\".`,\n });\n return violations;\n }\n\n const firstParam = params[0];\n if (firstParam.type) {\n const firstParamType = getTypeText(firstParam.type, ctx.sourceFile);\n if (firstParamType !== expectedDbo) {\n violations.push({\n file: ctx.filePath,\n line,\n message: `Method returns \"${innerType}\" but first parameter is \"${firstParamType}\". ` +\n `First parameter must be of type \"${expectedDbo}\".`,\n });\n }\n }\n\n for (let i = 1; i < params.length; i++) {\n const param = params[i];\n if (param.type) {\n const paramType = getTypeText(param.type, ctx.sourceFile);\n if (paramType !== 'boolean') {\n const paramName = param.name.getText(ctx.sourceFile);\n violations.push({\n file: ctx.filePath,\n line,\n message: `Extra parameter \"${paramName}\" has type \"${paramType}\" but must be \"boolean\". ` +\n 'Additional converter parameters are only for boolean flags (payload filtering / security).',\n });\n }\n }\n }\n\n return violations;\n}\n\n/**\n * Check a class method declaration for converter pattern violations.\n */\nfunction checkConverterMethod(\n node: ts.MethodDeclaration,\n ctx: FileContext\n): PrismaConverterViolation[] {\n if (!node.name || !node.type) return [];\n\n const startPos = node.getStart(ctx.sourceFile);\n const pos = ctx.sourceFile.getLineAndCharacterOfPosition(startPos);\n const line = pos.line + 1;\n\n if ((ctx.disableAllowed && hasDisableComment(ctx.fileLines, line)) || isDeprecated(node)) return [];\n\n const returnTypeText = getTypeText(node.type, ctx.sourceFile);\n const unwrapResult = unwrapPromise(returnTypeText);\n const innerType = unwrapResult.inner;\n const isAsync = unwrapResult.isAsync;\n const expectedDbo = deriveExpectedDboName(innerType);\n\n if (!expectedDbo || !ctx.prismaModels.has(expectedDbo)) return [];\n\n if (isAsync) {\n return [{\n file: ctx.filePath,\n line,\n message: `Async converter method returning \"Promise<${innerType}>\" found. ` +\n 'Converters should be pure data mapping with no async work. Remove async/Promise.',\n }];\n }\n\n return checkMethodParams(node, innerType, expectedDbo, ctx, line);\n}\n\n/**\n * Find converter method violations in a single file.\n * Checks class methods for proper Dbo parameter patterns and flags standalone functions.\n */\nfunction findConverterViolationsInFile(\n filePath: string,\n workspaceRoot: string,\n prismaModels: Set<string>,\n disableAllowed: boolean\n): PrismaConverterViolation[] {\n const fullPath = path.join(workspaceRoot, filePath);\n if (!fs.existsSync(fullPath)) return [];\n\n const content = fs.readFileSync(fullPath, 'utf-8');\n const ctx: FileContext = {\n filePath,\n fileLines: content.split('\\n'),\n sourceFile: ts.createSourceFile(filePath, content, ts.ScriptTarget.Latest, true),\n prismaModels,\n disableAllowed,\n };\n\n const violations: PrismaConverterViolation[] = [];\n\n function visitNode(node: ts.Node): void {\n if (ts.isFunctionDeclaration(node)) {\n const violation = checkStandaloneFunction(node, ctx);\n if (violation) violations.push(violation);\n }\n\n if (ts.isMethodDeclaration(node)) {\n violations.push(...checkConverterMethod(node, ctx));\n }\n\n ts.forEachChild(node, visitNode);\n }\n\n visitNode(ctx.sourceFile);\n return violations;\n}\n\n/**\n * Find violations in non-converter files: creating `new XxxDto(...)` where XxxDbo exists in prisma.\n * These Dto instances must only be created inside converter classes.\n */\n// webpieces-disable max-lines-new-methods -- AST traversal for new-expression detection with prisma model matching\nfunction findDtoCreationOutsideConverters(\n filePath: string,\n workspaceRoot: string,\n prismaModels: Set<string>,\n convertersPaths: string[],\n disableAllowed: boolean\n): PrismaConverterViolation[] {\n const fullPath = path.join(workspaceRoot, filePath);\n if (!fs.existsSync(fullPath)) return [];\n\n const content = fs.readFileSync(fullPath, 'utf-8');\n const fileLines = content.split('\\n');\n const sourceFile = ts.createSourceFile(filePath, content, ts.ScriptTarget.Latest, true);\n\n const violations: PrismaConverterViolation[] = [];\n\n function visitNode(node: ts.Node): void {\n // Detect `new XxxDto(...)` expressions\n if (ts.isNewExpression(node) && ts.isIdentifier(node.expression)) {\n const className = node.expression.text;\n const expectedDbo = deriveExpectedDboName(className);\n\n if (expectedDbo && prismaModels.has(expectedDbo)) {\n const startPos = node.getStart(sourceFile);\n const pos = sourceFile.getLineAndCharacterOfPosition(startPos);\n const line = pos.line + 1;\n\n if (!disableAllowed || !hasDisableComment(fileLines, line)) {\n const dirs = convertersPaths.map((p) => `\"${p}\"`).join(', ');\n violations.push({\n file: filePath,\n line,\n message: `\"${className}\" can only be created from its Dbo using a converter in one of these directories: ${dirs}. ` +\n 'Move this Dto construction into a converter class method.',\n });\n }\n }\n }\n\n ts.forEachChild(node, visitNode);\n }\n\n visitNode(sourceFile);\n return violations;\n}\n\n/**\n * Find converter violations only for new/modified methods (NEW_AND_MODIFIED_METHODS mode).\n * For converter files: only check methods/functions that are new or have changed lines in their range.\n */\n// webpieces-disable max-lines-new-methods -- AST traversal with method boundary filtering for new/modified detection\nfunction findConverterViolationsForModifiedMethods(\n filePath: string,\n workspaceRoot: string,\n prismaModels: Set<string>,\n disableAllowed: boolean,\n changedLines: Set<number>,\n newMethodNames: Set<string>\n): PrismaConverterViolation[] {\n const fullPath = path.join(workspaceRoot, filePath);\n if (!fs.existsSync(fullPath)) return [];\n\n const content = fs.readFileSync(fullPath, 'utf-8');\n const ctx: FileContext = {\n filePath,\n fileLines: content.split('\\n'),\n sourceFile: ts.createSourceFile(filePath, content, ts.ScriptTarget.Latest, true),\n prismaModels,\n disableAllowed,\n };\n\n const violations: PrismaConverterViolation[] = [];\n\n function visitNode(node: ts.Node): void {\n if (ts.isFunctionDeclaration(node) && node.name) {\n const start = ctx.sourceFile.getLineAndCharacterOfPosition(node.getStart(ctx.sourceFile));\n const end = ctx.sourceFile.getLineAndCharacterOfPosition(node.getEnd());\n if (isNewOrModified(node.name.text, start.line + 1, end.line + 1, changedLines, newMethodNames)) {\n const violation = checkStandaloneFunction(node, ctx);\n if (violation) violations.push(violation);\n }\n }\n\n if (ts.isMethodDeclaration(node) && node.name) {\n const start = ctx.sourceFile.getLineAndCharacterOfPosition(node.getStart(ctx.sourceFile));\n const end = ctx.sourceFile.getLineAndCharacterOfPosition(node.getEnd());\n const methodName = node.name.getText(ctx.sourceFile);\n if (isNewOrModified(methodName, start.line + 1, end.line + 1, changedLines, newMethodNames)) {\n violations.push(...checkConverterMethod(node, ctx));\n }\n }\n\n ts.forEachChild(node, visitNode);\n }\n\n visitNode(ctx.sourceFile);\n return violations;\n}\n\n/**\n * Find Dto creation violations only on changed lines (NEW_AND_MODIFIED_METHODS mode).\n * For non-converter files: only flag `new XxxDto(...)` on changed lines in the diff.\n */\n// webpieces-disable max-lines-new-methods -- AST traversal for new-expression detection with changed-line filtering\nfunction findDtoCreationOnChangedLines(\n filePath: string,\n workspaceRoot: string,\n prismaModels: Set<string>,\n convertersPaths: string[],\n disableAllowed: boolean,\n changedLines: Set<number>\n): PrismaConverterViolation[] {\n const fullPath = path.join(workspaceRoot, filePath);\n if (!fs.existsSync(fullPath)) return [];\n\n const content = fs.readFileSync(fullPath, 'utf-8');\n const fileLines = content.split('\\n');\n const sourceFile = ts.createSourceFile(filePath, content, ts.ScriptTarget.Latest, true);\n\n const violations: PrismaConverterViolation[] = [];\n\n function visitNode(node: ts.Node): void {\n if (ts.isNewExpression(node) && ts.isIdentifier(node.expression)) {\n const className = node.expression.text;\n const expectedDbo = deriveExpectedDboName(className);\n\n if (expectedDbo && prismaModels.has(expectedDbo)) {\n const startPos = node.getStart(sourceFile);\n const pos = sourceFile.getLineAndCharacterOfPosition(startPos);\n const line = pos.line + 1;\n\n if (changedLines.has(line) && (!disableAllowed || !hasDisableComment(fileLines, line))) {\n const dirs = convertersPaths.map((p) => `\"${p}\"`).join(', ');\n violations.push({\n file: filePath,\n line,\n message: `\"${className}\" can only be created from its Dbo using a converter in one of these directories: ${dirs}. ` +\n 'Move this Dto construction into a converter class method.',\n });\n }\n }\n }\n\n ts.forEachChild(node, visitNode);\n }\n\n visitNode(sourceFile);\n return violations;\n}\n\n/**\n * Collect violations for NEW_AND_MODIFIED_METHODS mode.\n * Converter files: method-level ā only check new/modified methods.\n * Non-converter files: line-level ā only flag new XxxDto() on changed lines.\n */\n// webpieces-disable max-lines-new-methods -- File classification and diff-based violation collection\nfunction collectViolationsForModifiedMethodAndCode(\n changedFiles: string[],\n convertersPaths: string[],\n workspaceRoot: string,\n prismaModels: Set<string>,\n disableAllowed: boolean,\n base: string,\n head: string | undefined\n): PrismaConverterViolation[] {\n const converterFiles = changedFiles.filter((f) =>\n convertersPaths.some((cp) => f.startsWith(cp))\n );\n const nonConverterFiles = changedFiles.filter((f) =>\n !convertersPaths.some((cp) => f.startsWith(cp))\n );\n\n const allViolations: PrismaConverterViolation[] = [];\n\n if (converterFiles.length > 0) {\n console.log(`š Checking ${converterFiles.length} converter file(s) (new/modified methods only)...`);\n for (const file of converterFiles) {\n const diff = getFileDiff(workspaceRoot, file, base, head);\n const changedLines = getChangedLineNumbers(diff);\n const newMethodNames = findNewMethodSignaturesInDiff(diff);\n if (changedLines.size === 0 && newMethodNames.size === 0) continue;\n allViolations.push(...findConverterViolationsForModifiedMethods(\n file, workspaceRoot, prismaModels, disableAllowed, changedLines, newMethodNames\n ));\n }\n }\n\n if (nonConverterFiles.length > 0) {\n console.log(`š Checking ${nonConverterFiles.length} non-converter file(s) for Dto creation (changed lines only)...`);\n for (const file of nonConverterFiles) {\n const diff = getFileDiff(workspaceRoot, file, base, head);\n const changedLines = getChangedLineNumbers(diff);\n if (changedLines.size === 0) continue;\n allViolations.push(...findDtoCreationOnChangedLines(\n file, workspaceRoot, prismaModels, convertersPaths, disableAllowed, changedLines\n ));\n }\n }\n\n return allViolations;\n}\n\n/**\n * Report violations to console.\n */\nfunction reportViolations(violations: PrismaConverterViolation[], mode: PrismaConverterMode): void {\n console.error('');\n console.error('ā Prisma converter violations found!');\n console.error('');\n console.error('š Converter methods returning XxxDto (where XxxDbo exists in schema.prisma)');\n console.error(' must accept XxxDbo as the first parameter. This keeps single-table');\n console.error(' converters clean and forces join converters to compose them.');\n console.error('');\n console.error(' GOOD: convertUserDbo(userDbo: UserDbo): UserDto { }');\n console.error(' GOOD: convertVersionDbo(version: VersionDbo, partial?: boolean): VersionDto { }');\n console.error(' GOOD: convertToJoinDto(item: SomeJoinType): CourseJoinDto { } // no matching JoinDbo');\n console.error('');\n console.error(' BAD: async convertUser(dbo: UserDbo): Promise<UserDto> { } // no async');\n console.error(' BAD: convertCourse(course: CourseWithMeta): CourseDto { } // wrong first param');\n console.error(' BAD: convertUser(dbo: UserDbo, name: string): UserDto { } // extra non-boolean');\n console.error(' BAD: export function convertSession(s: SessionDbo): SessionDto // standalone function');\n console.error('');\n\n for (const v of violations) {\n console.error(` ā ${v.file}:${v.line}`);\n console.error(` ${v.message}`);\n }\n console.error('');\n\n console.error(' Escape hatch (use sparingly):');\n console.error(' // webpieces-disable prisma-converter -- [your reason]');\n console.error('');\n console.error(` Current mode: ${mode}`);\n console.error('');\n}\n\n/**\n * Resolve git base ref from env vars or auto-detection.\n */\nfunction resolveBase(workspaceRoot: string): string | undefined {\n const envBase = process.env['NX_BASE'];\n if (envBase) return envBase;\n return detectBase(workspaceRoot) ?? undefined;\n}\n\n/**\n * Collect all violations from converter and non-converter files.\n */\nfunction collectAllViolations(\n changedFiles: string[],\n convertersPaths: string[],\n workspaceRoot: string,\n prismaModels: Set<string>,\n disableAllowed: boolean\n): PrismaConverterViolation[] {\n const converterFiles = changedFiles.filter((f) =>\n convertersPaths.some((cp) => f.startsWith(cp))\n );\n const nonConverterFiles = changedFiles.filter((f) =>\n !convertersPaths.some((cp) => f.startsWith(cp))\n );\n\n const allViolations: PrismaConverterViolation[] = [];\n\n if (converterFiles.length > 0) {\n console.log(`š Checking ${converterFiles.length} converter file(s)...`);\n for (const file of converterFiles) {\n allViolations.push(...findConverterViolationsInFile(file, workspaceRoot, prismaModels, disableAllowed));\n }\n }\n\n if (nonConverterFiles.length > 0) {\n console.log(`š Checking ${nonConverterFiles.length} non-converter file(s) for Dto creation...`);\n for (const file of nonConverterFiles) {\n allViolations.push(...findDtoCreationOutsideConverters(file, workspaceRoot, prismaModels, convertersPaths, disableAllowed));\n }\n }\n\n return allViolations;\n}\n\n/**\n * Run validation after early-exit checks have passed.\n */\nfunction validateChangedFiles(\n workspaceRoot: string,\n schemaPath: string,\n convertersPaths: string[],\n enforcePaths: string[],\n base: string,\n mode: PrismaConverterMode,\n disableAllowed: boolean\n): ExecutorResult {\n const head = process.env['NX_HEAD'];\n\n console.log(` Base: ${base}`);\n console.log(` Head: ${head ?? 'working tree (includes uncommitted changes)'}`);\n console.log('');\n\n const fullSchemaPath = path.join(workspaceRoot, schemaPath);\n const prismaModels = parsePrismaModels(fullSchemaPath);\n\n if (prismaModels.size === 0) {\n console.log('āļø No models found in schema.prisma');\n console.log('');\n return { success: true };\n }\n\n console.log(` Found ${prismaModels.size} model(s) in schema.prisma`);\n\n let changedFiles = getChangedTypeScriptFiles(workspaceRoot, base, head);\n if (enforcePaths.length > 0) {\n changedFiles = changedFiles.filter((f) =>\n enforcePaths.some((ep) => f.startsWith(ep))\n );\n }\n\n if (changedFiles.length === 0) {\n console.log('ā
No TypeScript files changed');\n return { success: true };\n }\n\n let allViolations: PrismaConverterViolation[];\n\n if (mode === 'NEW_AND_MODIFIED_METHODS') {\n allViolations = collectViolationsForModifiedMethodAndCode(\n changedFiles, convertersPaths, workspaceRoot, prismaModels, disableAllowed, base, head\n );\n } else {\n allViolations = collectAllViolations(changedFiles, convertersPaths, workspaceRoot, prismaModels, disableAllowed);\n }\n\n if (allViolations.length === 0) {\n console.log('ā
All converter patterns are valid');\n return { success: true };\n }\n\n reportViolations(allViolations, mode);\n return { success: false };\n}\n\n/**\n * Resolve mode considering ignoreModifiedUntilEpoch override.\n * When active, downgrades to OFF. When expired, logs a warning.\n */\nfunction resolvePrismaConverterMode(\n normalMode: PrismaConverterMode,\n epoch: number | undefined,\n branchPattern: string | undefined\n): PrismaConverterMode {\n if (normalMode === 'OFF') {\n return normalMode;\n }\n const skip = shouldSkipRule(epoch, branchPattern);\n if (skip.skip) {\n console.log(`\\nāļø Skipping prisma-converter validation (${skip.reason})`);\n console.log('');\n return 'OFF';\n }\n return normalMode;\n}\n\nasync function runValidatorImpl(\n options: PrismaConverterConfig,\n workspaceRoot: string\n): Promise<ExecutorResult> {\n const mode = resolvePrismaConverterMode(options.mode ?? 'OFF', options.ignoreModifiedUntilEpoch, options.ignoreRuleWhileOnBranch);\n\n if (mode === 'OFF') {\n console.log('\\nāļø Skipping prisma-converter validation (mode: OFF)');\n console.log('');\n return { success: true };\n }\n\n const schemaPath = options.schemaPath;\n const convertersPaths = options.convertersPaths ?? [];\n const enforcePaths = options.enforcePaths ?? [];\n\n if (!schemaPath || convertersPaths.length === 0) {\n const reason = !schemaPath ? 'no schemaPath configured' : 'no convertersPaths configured';\n console.log(`\\nāļø Skipping prisma-converter validation (${reason})`);\n console.log('');\n return { success: true };\n }\n\n console.log('\\nš Validating Prisma Converters\\n');\n console.log(` Mode: ${mode}`);\n console.log(` Schema: ${schemaPath}`);\n console.log(` Converter paths: ${convertersPaths.join(', ')}`);\n if (enforcePaths.length > 0) {\n console.log(` Enforce paths: ${enforcePaths.join(', ')}`);\n }\n\n const base = resolveBase(workspaceRoot);\n\n if (!base) {\n console.log('\\nāļø Skipping prisma-converter validation (could not detect base branch)');\n console.log('');\n return { success: true };\n }\n\n const disableAllowed = options.disableAllowed ?? true;\n return validateChangedFiles(workspaceRoot, schemaPath, convertersPaths, enforcePaths, base, mode, disableAllowed);\n}\n\nexport class PrismaConverterValidator extends CodeValidator<PrismaConverterConfig> {\n constructor(config: PrismaConverterConfig) {\n super(config, 'prisma-converter');\n }\n\n async run(workspaceRoot: string): Promise<ExecutorResult> {\n return runValidatorImpl(this.config, workspaceRoot);\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"validate-prisma-converters.js","sourceRoot":"","sources":["../../../../../packages/tooling/code-rules/src/validate-prisma-converters.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Validate Prisma Converters Executor\n *\n * Validates that Prisma converter methods follow a scalable pattern:\n * methods returning XxxDto (where XxxDbo exists in schema.prisma) must\n * accept that exact XxxDbo as the first parameter. This keeps single-table\n * converters clean and forces join converters to compose them.\n *\n * ============================================================================\n * RULES\n * ============================================================================\n *\n * 1. First param must be exact Dbo:\n * If method returns XxxDto and XxxDbo exists in schema.prisma,\n * the first parameter must be of type XxxDbo.\n *\n * 2. Extra params must be booleans:\n * Additional parameters beyond the Dbo are allowed but must be boolean\n * (used for filtering payloads / security info).\n *\n * 3. No async converters:\n * Methods returning Promise<XxxDto> are flagged ā converters should be\n * pure data mapping, no async work.\n *\n * 4. No standalone functions:\n * Standalone functions in converter files are flagged ā must be class\n * methods so the converter class can be injected (dependency tree tracing).\n *\n * 5. Dto creation outside converters directory:\n * Files outside the configured convertersPath that create `new XxxDto(...)`\n * where XxxDbo exists in schema.prisma are flagged ā Dto instances tied to\n * a Dbo must only be created via a converter class.\n *\n * ============================================================================\n * SKIP CONDITIONS\n * ============================================================================\n * - Methods with @deprecated decorator or JSDoc tag\n * - Lines with: // webpieces-disable prisma-converter -- [reason]\n *\n * ============================================================================\n * MODES\n * ============================================================================\n * - OFF: Skip validation entirely\n * - NEW_AND_MODIFIED_METHODS: Validate new/modified methods in converters + changed lines in non-converters\n * - NEW_AND_MODIFIED_FILES: Validate all methods in modified files\n */\n\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport * as ts from 'typescript';\nimport { hasDisable, RULE_NAMES, PrismaConverterConfig, PrismaConverterMode, detectBase, getChangedFiles, getFileDiff, getChangedLineNumbers, findNewMethodSignaturesInDiff, isNewOrModified } from '@webpieces/rules-config';\nimport { CodeValidator, ExecutorResult } from './code-validator';\nimport { shouldSkipRule } from './resolve-mode';\n\ninterface PrismaConverterViolation {\n file: string;\n line: number;\n message: string;\n}\n\ninterface UnwrapResult {\n inner: string;\n isAsync: boolean;\n}\n\ninterface FileContext {\n filePath: string;\n fileLines: string[];\n sourceFile: ts.SourceFile;\n prismaModels: Set<string>;\n disableAllowed: boolean;\n}\n\n/**\n * Parse schema.prisma to extract all model names into a Set.\n */\nfunction parsePrismaModels(schemaPath: string): Set<string> {\n const models = new Set<string>();\n\n if (!fs.existsSync(schemaPath)) {\n return models;\n }\n\n const content = fs.readFileSync(schemaPath, 'utf-8');\n const regex = /^model\\s+(\\w+)\\s*\\{/gm;\n let match: RegExpExecArray | null;\n\n while ((match = regex.exec(content)) !== null) {\n models.add(match[1]);\n }\n\n return models;\n}\n\n/**\n * Derive the expected Dbo name from a return type ending in Dto.\n * \"XxxDto\" -> \"XxxDbo\". Returns null if name doesn't end with Dto.\n */\nfunction deriveExpectedDboName(returnType: string): string | null {\n if (!returnType.endsWith('Dto')) return null;\n return returnType.slice(0, -3) + 'Dbo';\n}\n\n/**\n * Check if a line has a webpieces-disable comment for prisma-converter.\n */\nfunction hasDisableComment(lines: string[], lineNumber: number): boolean {\n const startCheck = Math.max(0, lineNumber - 5);\n for (let i = lineNumber - 2; i >= startCheck; i--) {\n const line = lines[i]?.trim() ?? '';\n if (line.startsWith('function ') || line.startsWith('class ') || line.endsWith('}')) {\n break;\n }\n if (hasDisable(line, RULE_NAMES.PRISMA_CONVERTER)) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * Check if a method/function node has a @deprecated decorator.\n */\nfunction hasDeprecatedDecorator(node: ts.MethodDeclaration | ts.FunctionDeclaration): boolean {\n const modifiers = ts.canHaveDecorators(node) ? ts.getDecorators(node) : undefined;\n if (!modifiers) return false;\n\n for (const decorator of modifiers) {\n const expr = decorator.expression;\n // @deprecated or @deprecated()\n if (ts.isIdentifier(expr) && expr.text === 'deprecated') return true;\n if (ts.isCallExpression(expr) && ts.isIdentifier(expr.expression) && expr.expression.text === 'deprecated') {\n return true;\n }\n }\n return false;\n}\n\n/**\n * Check if a node has @deprecated in its JSDoc comments.\n */\nfunction hasDeprecatedJsDoc(node: ts.Node): boolean {\n const jsDocs = ts.getJSDocTags(node);\n for (const tag of jsDocs) {\n if (tag.tagName.text === 'deprecated') return true;\n }\n return false;\n}\n\n/**\n * Check if a method is deprecated via decorator or JSDoc.\n */\nfunction isDeprecated(node: ts.MethodDeclaration | ts.FunctionDeclaration): boolean {\n return hasDeprecatedDecorator(node) || hasDeprecatedJsDoc(node);\n}\n\n/**\n * Extract the text of a type node, stripping whitespace.\n */\nfunction getTypeText(typeNode: ts.TypeNode, sourceFile: ts.SourceFile): string {\n return typeNode.getText(sourceFile).trim();\n}\n\n/**\n * Unwrap Promise<T> to get T. Returns the inner type text if wrapped, otherwise returns as-is.\n */\nfunction unwrapPromise(typeText: string): UnwrapResult {\n const promiseMatch = typeText.match(/^Promise\\s*<\\s*(.+)\\s*>$/);\n if (promiseMatch) {\n return { inner: promiseMatch[1].trim(), isAsync: true };\n }\n return { inner: typeText, isAsync: false };\n}\n\n/**\n * Check a standalone function declaration in a converter file and return a violation if applicable.\n */\nfunction checkStandaloneFunction(\n node: ts.FunctionDeclaration,\n ctx: FileContext\n): PrismaConverterViolation | null {\n if (!node.name) return null;\n\n const startPos = node.getStart(ctx.sourceFile);\n const pos = ctx.sourceFile.getLineAndCharacterOfPosition(startPos);\n const line = pos.line + 1;\n\n if ((ctx.disableAllowed && hasDisableComment(ctx.fileLines, line)) || isDeprecated(node)) return null;\n\n return {\n file: ctx.filePath,\n line,\n message: `Standalone function \"${node.name.text}\" found in converter file. ` +\n 'Move to a converter class so it can be injected via DI.',\n };\n}\n\n/**\n * Validate the parameters of a converter method that returns a Dto with a matching Dbo.\n */\nfunction checkMethodParams(\n node: ts.MethodDeclaration,\n innerType: string,\n expectedDbo: string,\n ctx: FileContext,\n line: number\n): PrismaConverterViolation[] {\n const violations: PrismaConverterViolation[] = [];\n const params = node.parameters;\n\n if (params.length === 0) {\n violations.push({\n file: ctx.filePath,\n line,\n message: `Method returns \"${innerType}\" but has no parameters. ` +\n `First parameter must be of type \"${expectedDbo}\".`,\n });\n return violations;\n }\n\n const firstParam = params[0];\n if (firstParam.type) {\n const firstParamType = getTypeText(firstParam.type, ctx.sourceFile);\n if (firstParamType !== expectedDbo) {\n violations.push({\n file: ctx.filePath,\n line,\n message: `Method returns \"${innerType}\" but first parameter is \"${firstParamType}\". ` +\n `First parameter must be of type \"${expectedDbo}\".`,\n });\n }\n }\n\n for (let i = 1; i < params.length; i++) {\n const param = params[i];\n if (param.type) {\n const paramType = getTypeText(param.type, ctx.sourceFile);\n if (paramType !== 'boolean') {\n const paramName = param.name.getText(ctx.sourceFile);\n violations.push({\n file: ctx.filePath,\n line,\n message: `Extra parameter \"${paramName}\" has type \"${paramType}\" but must be \"boolean\". ` +\n 'Additional converter parameters are only for boolean flags (payload filtering / security).',\n });\n }\n }\n }\n\n return violations;\n}\n\n/**\n * Check a class method declaration for converter pattern violations.\n */\nfunction checkConverterMethod(\n node: ts.MethodDeclaration,\n ctx: FileContext\n): PrismaConverterViolation[] {\n if (!node.name || !node.type) return [];\n\n const startPos = node.getStart(ctx.sourceFile);\n const pos = ctx.sourceFile.getLineAndCharacterOfPosition(startPos);\n const line = pos.line + 1;\n\n if ((ctx.disableAllowed && hasDisableComment(ctx.fileLines, line)) || isDeprecated(node)) return [];\n\n const returnTypeText = getTypeText(node.type, ctx.sourceFile);\n const unwrapResult = unwrapPromise(returnTypeText);\n const innerType = unwrapResult.inner;\n const isAsync = unwrapResult.isAsync;\n const expectedDbo = deriveExpectedDboName(innerType);\n\n if (!expectedDbo || !ctx.prismaModels.has(expectedDbo)) return [];\n\n if (isAsync) {\n return [{\n file: ctx.filePath,\n line,\n message: `Async converter method returning \"Promise<${innerType}>\" found. ` +\n 'Converters should be pure data mapping with no async work. Remove async/Promise.',\n }];\n }\n\n return checkMethodParams(node, innerType, expectedDbo, ctx, line);\n}\n\n/**\n * Find converter method violations in a single file.\n * Checks class methods for proper Dbo parameter patterns and flags standalone functions.\n */\nfunction findConverterViolationsInFile(\n filePath: string,\n workspaceRoot: string,\n prismaModels: Set<string>,\n disableAllowed: boolean\n): PrismaConverterViolation[] {\n const fullPath = path.join(workspaceRoot, filePath);\n if (!fs.existsSync(fullPath)) return [];\n\n const content = fs.readFileSync(fullPath, 'utf-8');\n const ctx: FileContext = {\n filePath,\n fileLines: content.split('\\n'),\n sourceFile: ts.createSourceFile(filePath, content, ts.ScriptTarget.Latest, true),\n prismaModels,\n disableAllowed,\n };\n\n const violations: PrismaConverterViolation[] = [];\n\n function visitNode(node: ts.Node): void {\n if (ts.isFunctionDeclaration(node)) {\n const violation = checkStandaloneFunction(node, ctx);\n if (violation) violations.push(violation);\n }\n\n if (ts.isMethodDeclaration(node)) {\n violations.push(...checkConverterMethod(node, ctx));\n }\n\n ts.forEachChild(node, visitNode);\n }\n\n visitNode(ctx.sourceFile);\n return violations;\n}\n\n/**\n * Find violations in non-converter files: creating `new XxxDto(...)` where XxxDbo exists in prisma.\n * These Dto instances must only be created inside converter classes.\n */\n// webpieces-disable max-lines-new-methods -- AST traversal for new-expression detection with prisma model matching\nfunction findDtoCreationOutsideConverters(\n filePath: string,\n workspaceRoot: string,\n prismaModels: Set<string>,\n convertersPaths: string[],\n disableAllowed: boolean\n): PrismaConverterViolation[] {\n const fullPath = path.join(workspaceRoot, filePath);\n if (!fs.existsSync(fullPath)) return [];\n\n const content = fs.readFileSync(fullPath, 'utf-8');\n const fileLines = content.split('\\n');\n const sourceFile = ts.createSourceFile(filePath, content, ts.ScriptTarget.Latest, true);\n\n const violations: PrismaConverterViolation[] = [];\n\n function visitNode(node: ts.Node): void {\n // Detect `new XxxDto(...)` expressions\n if (ts.isNewExpression(node) && ts.isIdentifier(node.expression)) {\n const className = node.expression.text;\n const expectedDbo = deriveExpectedDboName(className);\n\n if (expectedDbo && prismaModels.has(expectedDbo)) {\n const startPos = node.getStart(sourceFile);\n const pos = sourceFile.getLineAndCharacterOfPosition(startPos);\n const line = pos.line + 1;\n\n if (!disableAllowed || !hasDisableComment(fileLines, line)) {\n const dirs = convertersPaths.map((p) => `\"${p}\"`).join(', ');\n violations.push({\n file: filePath,\n line,\n message: `\"${className}\" can only be created from its Dbo using a converter in one of these directories: ${dirs}. ` +\n 'Move this Dto construction into a converter class method.',\n });\n }\n }\n }\n\n ts.forEachChild(node, visitNode);\n }\n\n visitNode(sourceFile);\n return violations;\n}\n\n/**\n * Find converter violations only for new/modified methods (NEW_AND_MODIFIED_METHODS mode).\n * For converter files: only check methods/functions that are new or have changed lines in their range.\n */\n// webpieces-disable max-lines-new-methods -- AST traversal with method boundary filtering for new/modified detection\nfunction findConverterViolationsForModifiedMethods(\n filePath: string,\n workspaceRoot: string,\n prismaModels: Set<string>,\n disableAllowed: boolean,\n changedLines: Set<number>,\n newMethodNames: Set<string>\n): PrismaConverterViolation[] {\n const fullPath = path.join(workspaceRoot, filePath);\n if (!fs.existsSync(fullPath)) return [];\n\n const content = fs.readFileSync(fullPath, 'utf-8');\n const ctx: FileContext = {\n filePath,\n fileLines: content.split('\\n'),\n sourceFile: ts.createSourceFile(filePath, content, ts.ScriptTarget.Latest, true),\n prismaModels,\n disableAllowed,\n };\n\n const violations: PrismaConverterViolation[] = [];\n\n function visitNode(node: ts.Node): void {\n if (ts.isFunctionDeclaration(node) && node.name) {\n const start = ctx.sourceFile.getLineAndCharacterOfPosition(node.getStart(ctx.sourceFile));\n const end = ctx.sourceFile.getLineAndCharacterOfPosition(node.getEnd());\n if (isNewOrModified(node.name.text, start.line + 1, end.line + 1, changedLines, newMethodNames)) {\n const violation = checkStandaloneFunction(node, ctx);\n if (violation) violations.push(violation);\n }\n }\n\n if (ts.isMethodDeclaration(node) && node.name) {\n const start = ctx.sourceFile.getLineAndCharacterOfPosition(node.getStart(ctx.sourceFile));\n const end = ctx.sourceFile.getLineAndCharacterOfPosition(node.getEnd());\n const methodName = node.name.getText(ctx.sourceFile);\n if (isNewOrModified(methodName, start.line + 1, end.line + 1, changedLines, newMethodNames)) {\n violations.push(...checkConverterMethod(node, ctx));\n }\n }\n\n ts.forEachChild(node, visitNode);\n }\n\n visitNode(ctx.sourceFile);\n return violations;\n}\n\n/**\n * Find Dto creation violations only on changed lines (NEW_AND_MODIFIED_METHODS mode).\n * For non-converter files: only flag `new XxxDto(...)` on changed lines in the diff.\n */\n// webpieces-disable max-lines-new-methods -- AST traversal for new-expression detection with changed-line filtering\nfunction findDtoCreationOnChangedLines(\n filePath: string,\n workspaceRoot: string,\n prismaModels: Set<string>,\n convertersPaths: string[],\n disableAllowed: boolean,\n changedLines: Set<number>\n): PrismaConverterViolation[] {\n const fullPath = path.join(workspaceRoot, filePath);\n if (!fs.existsSync(fullPath)) return [];\n\n const content = fs.readFileSync(fullPath, 'utf-8');\n const fileLines = content.split('\\n');\n const sourceFile = ts.createSourceFile(filePath, content, ts.ScriptTarget.Latest, true);\n\n const violations: PrismaConverterViolation[] = [];\n\n function visitNode(node: ts.Node): void {\n if (ts.isNewExpression(node) && ts.isIdentifier(node.expression)) {\n const className = node.expression.text;\n const expectedDbo = deriveExpectedDboName(className);\n\n if (expectedDbo && prismaModels.has(expectedDbo)) {\n const startPos = node.getStart(sourceFile);\n const pos = sourceFile.getLineAndCharacterOfPosition(startPos);\n const line = pos.line + 1;\n\n if (changedLines.has(line) && (!disableAllowed || !hasDisableComment(fileLines, line))) {\n const dirs = convertersPaths.map((p) => `\"${p}\"`).join(', ');\n violations.push({\n file: filePath,\n line,\n message: `\"${className}\" can only be created from its Dbo using a converter in one of these directories: ${dirs}. ` +\n 'Move this Dto construction into a converter class method.',\n });\n }\n }\n }\n\n ts.forEachChild(node, visitNode);\n }\n\n visitNode(sourceFile);\n return violations;\n}\n\n/**\n * Collect violations for NEW_AND_MODIFIED_METHODS mode.\n * Converter files: method-level ā only check new/modified methods.\n * Non-converter files: line-level ā only flag new XxxDto() on changed lines.\n */\n// webpieces-disable max-lines-new-methods -- File classification and diff-based violation collection\nfunction collectViolationsForModifiedMethodAndCode(\n changedFiles: string[],\n convertersPaths: string[],\n workspaceRoot: string,\n prismaModels: Set<string>,\n disableAllowed: boolean,\n base: string,\n head: string | undefined\n): PrismaConverterViolation[] {\n const converterFiles = changedFiles.filter((f) =>\n convertersPaths.some((cp) => f.startsWith(cp))\n );\n const nonConverterFiles = changedFiles.filter((f) =>\n !convertersPaths.some((cp) => f.startsWith(cp))\n );\n\n const allViolations: PrismaConverterViolation[] = [];\n\n if (converterFiles.length > 0) {\n console.log(`š Checking ${converterFiles.length} converter file(s) (new/modified methods only)...`);\n for (const file of converterFiles) {\n const diff = getFileDiff(workspaceRoot, file, base, head);\n const changedLines = getChangedLineNumbers(diff);\n const newMethodNames = findNewMethodSignaturesInDiff(diff);\n if (changedLines.size === 0 && newMethodNames.size === 0) continue;\n allViolations.push(...findConverterViolationsForModifiedMethods(\n file, workspaceRoot, prismaModels, disableAllowed, changedLines, newMethodNames\n ));\n }\n }\n\n if (nonConverterFiles.length > 0) {\n console.log(`š Checking ${nonConverterFiles.length} non-converter file(s) for Dto creation (changed lines only)...`);\n for (const file of nonConverterFiles) {\n const diff = getFileDiff(workspaceRoot, file, base, head);\n const changedLines = getChangedLineNumbers(diff);\n if (changedLines.size === 0) continue;\n allViolations.push(...findDtoCreationOnChangedLines(\n file, workspaceRoot, prismaModels, convertersPaths, disableAllowed, changedLines\n ));\n }\n }\n\n return allViolations;\n}\n\n/**\n * Report violations to console.\n */\nfunction reportViolations(violations: PrismaConverterViolation[], mode: PrismaConverterMode): void {\n console.error('');\n console.error('ā Prisma converter violations found!');\n console.error('');\n console.error('š Converter methods returning XxxDto (where XxxDbo exists in schema.prisma)');\n console.error(' must accept XxxDbo as the first parameter. This keeps single-table');\n console.error(' converters clean and forces join converters to compose them.');\n console.error('');\n console.error(' GOOD: convertUserDbo(userDbo: UserDbo): UserDto { }');\n console.error(' GOOD: convertVersionDbo(version: VersionDbo, partial?: boolean): VersionDto { }');\n console.error(' GOOD: convertToJoinDto(item: SomeJoinType): CourseJoinDto { } // no matching JoinDbo');\n console.error('');\n console.error(' BAD: async convertUser(dbo: UserDbo): Promise<UserDto> { } // no async');\n console.error(' BAD: convertCourse(course: CourseWithMeta): CourseDto { } // wrong first param');\n console.error(' BAD: convertUser(dbo: UserDbo, name: string): UserDto { } // extra non-boolean');\n console.error(' BAD: export function convertSession(s: SessionDbo): SessionDto // standalone function');\n console.error('');\n\n for (const v of violations) {\n console.error(` ā ${v.file}:${v.line}`);\n console.error(` ${v.message}`);\n }\n console.error('');\n\n console.error(' Escape hatch (use sparingly):');\n console.error(' // webpieces-disable prisma-converter -- [your reason]');\n console.error('');\n console.error(` Current mode: ${mode}`);\n console.error('');\n}\n\n/**\n * Resolve git base ref from env vars or auto-detection.\n */\nfunction resolveBase(workspaceRoot: string): string | undefined {\n const envBase = process.env['NX_BASE'];\n if (envBase) return envBase;\n return detectBase(workspaceRoot) ?? undefined;\n}\n\n/**\n * Collect all violations from converter and non-converter files.\n */\nfunction collectAllViolations(\n changedFiles: string[],\n convertersPaths: string[],\n workspaceRoot: string,\n prismaModels: Set<string>,\n disableAllowed: boolean\n): PrismaConverterViolation[] {\n const converterFiles = changedFiles.filter((f) =>\n convertersPaths.some((cp) => f.startsWith(cp))\n );\n const nonConverterFiles = changedFiles.filter((f) =>\n !convertersPaths.some((cp) => f.startsWith(cp))\n );\n\n const allViolations: PrismaConverterViolation[] = [];\n\n if (converterFiles.length > 0) {\n console.log(`š Checking ${converterFiles.length} converter file(s)...`);\n for (const file of converterFiles) {\n allViolations.push(...findConverterViolationsInFile(file, workspaceRoot, prismaModels, disableAllowed));\n }\n }\n\n if (nonConverterFiles.length > 0) {\n console.log(`š Checking ${nonConverterFiles.length} non-converter file(s) for Dto creation...`);\n for (const file of nonConverterFiles) {\n allViolations.push(...findDtoCreationOutsideConverters(file, workspaceRoot, prismaModels, convertersPaths, disableAllowed));\n }\n }\n\n return allViolations;\n}\n\n/**\n * Run validation after early-exit checks have passed.\n */\nfunction validateChangedFiles(\n workspaceRoot: string,\n schemaPath: string,\n convertersPaths: string[],\n enforcePaths: string[],\n base: string,\n mode: PrismaConverterMode,\n disableAllowed: boolean\n): ExecutorResult {\n const head = process.env['NX_HEAD'];\n\n console.log(` Base: ${base}`);\n console.log(` Head: ${head ?? 'working tree (includes uncommitted changes)'}`);\n console.log('');\n\n const fullSchemaPath = path.join(workspaceRoot, schemaPath);\n const prismaModels = parsePrismaModels(fullSchemaPath);\n\n if (prismaModels.size === 0) {\n console.log('āļø No models found in schema.prisma');\n console.log('');\n return { success: true };\n }\n\n console.log(` Found ${prismaModels.size} model(s) in schema.prisma`);\n\n let changedFiles = getChangedFiles(workspaceRoot, base, head);\n if (enforcePaths.length > 0) {\n changedFiles = changedFiles.filter((f) =>\n enforcePaths.some((ep) => f.startsWith(ep))\n );\n }\n\n if (changedFiles.length === 0) {\n console.log('ā
No TypeScript files changed');\n return { success: true };\n }\n\n let allViolations: PrismaConverterViolation[];\n\n if (mode === 'NEW_AND_MODIFIED_METHODS') {\n allViolations = collectViolationsForModifiedMethodAndCode(\n changedFiles, convertersPaths, workspaceRoot, prismaModels, disableAllowed, base, head\n );\n } else {\n allViolations = collectAllViolations(changedFiles, convertersPaths, workspaceRoot, prismaModels, disableAllowed);\n }\n\n if (allViolations.length === 0) {\n console.log('ā
All converter patterns are valid');\n return { success: true };\n }\n\n reportViolations(allViolations, mode);\n return { success: false };\n}\n\n/**\n * Resolve mode considering ignoreModifiedUntilEpoch override.\n * When active, downgrades to OFF. When expired, logs a warning.\n */\nfunction resolvePrismaConverterMode(\n normalMode: PrismaConverterMode,\n epoch: number | undefined,\n branchPattern: string | undefined\n): PrismaConverterMode {\n if (normalMode === 'OFF') {\n return normalMode;\n }\n const skip = shouldSkipRule(epoch, branchPattern);\n if (skip.skip) {\n console.log(`\\nāļø Skipping prisma-converter validation (${skip.reason})`);\n console.log('');\n return 'OFF';\n }\n return normalMode;\n}\n\nasync function runValidatorImpl(\n options: PrismaConverterConfig,\n workspaceRoot: string\n): Promise<ExecutorResult> {\n const mode = resolvePrismaConverterMode(options.mode ?? 'OFF', options.ignoreModifiedUntilEpoch, options.ignoreRuleWhileOnBranch);\n\n if (mode === 'OFF') {\n console.log('\\nāļø Skipping prisma-converter validation (mode: OFF)');\n console.log('');\n return { success: true };\n }\n\n const schemaPath = options.schemaPath;\n const convertersPaths = options.convertersPaths ?? [];\n const enforcePaths = options.enforcePaths ?? [];\n\n if (!schemaPath || convertersPaths.length === 0) {\n const reason = !schemaPath ? 'no schemaPath configured' : 'no convertersPaths configured';\n console.log(`\\nāļø Skipping prisma-converter validation (${reason})`);\n console.log('');\n return { success: true };\n }\n\n console.log('\\nš Validating Prisma Converters\\n');\n console.log(` Mode: ${mode}`);\n console.log(` Schema: ${schemaPath}`);\n console.log(` Converter paths: ${convertersPaths.join(', ')}`);\n if (enforcePaths.length > 0) {\n console.log(` Enforce paths: ${enforcePaths.join(', ')}`);\n }\n\n const base = resolveBase(workspaceRoot);\n\n if (!base) {\n console.log('\\nāļø Skipping prisma-converter validation (could not detect base branch)');\n console.log('');\n return { success: true };\n }\n\n const disableAllowed = options.disableAllowed ?? true;\n return validateChangedFiles(workspaceRoot, schemaPath, convertersPaths, enforcePaths, base, mode, disableAllowed);\n}\n\nexport class PrismaConverterValidator extends CodeValidator<PrismaConverterConfig> {\n constructor(config: PrismaConverterConfig) {\n super(config, 'prisma-converter');\n }\n\n async run(workspaceRoot: string): Promise<ExecutorResult> {\n return runValidatorImpl(this.config, workspaceRoot);\n }\n}\n"]}
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
* - OFF: Skip validation entirely
|
|
13
13
|
* - NEW_METHODS: Only validate new methods (detected via git diff)
|
|
14
14
|
* - NEW_AND_MODIFIED_METHODS: Validate new methods + methods with changes in their line range
|
|
15
|
-
* -
|
|
15
|
+
* - NEW_AND_MODIFIED_FILES: Validate all methods in modified files
|
|
16
16
|
*
|
|
17
17
|
* Escape hatch: Add webpieces-disable require-return-type comment with justification
|
|
18
18
|
*/
|