@webpieces/code-rules 0.0.1 → 0.2.113
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 +4 -3
- package/src/cli.d.ts +1 -0
- package/src/cli.js +19 -0
- package/src/cli.js.map +1 -0
- package/src/diff-utils.d.ts +24 -0
- package/src/{diff-utils.ts → diff-utils.js} +30 -38
- package/src/diff-utils.js.map +1 -0
- package/src/from-shared-config.d.ts +28 -0
- package/src/from-shared-config.js +119 -0
- package/src/from-shared-config.js.map +1 -0
- package/src/index.js +33 -0
- package/src/index.js.map +1 -0
- package/src/validate-catch-error-pattern.d.ts +47 -0
- package/src/{validate-catch-error-pattern.ts → validate-catch-error-pattern.js} +74 -195
- package/src/validate-catch-error-pattern.js.map +1 -0
- package/src/validate-code.d.ts +98 -0
- package/src/{validate-code.ts → validate-code.js} +65 -259
- package/src/validate-code.js.map +1 -0
- package/src/validate-dtos.d.ts +41 -0
- package/src/{validate-dtos.ts → validate-dtos.js} +88 -215
- package/src/validate-dtos.js.map +1 -0
- package/src/validate-modified-files.d.ts +24 -0
- package/src/{validate-modified-files.ts → validate-modified-files.js} +46 -115
- package/src/validate-modified-files.js.map +1 -0
- package/src/validate-modified-methods.d.ts +30 -0
- package/src/{validate-modified-methods.ts → validate-modified-methods.js} +94 -196
- package/src/validate-modified-methods.js.map +1 -0
- package/src/validate-new-methods.d.ts +27 -0
- package/src/{validate-new-methods.ts → validate-new-methods.js} +63 -133
- package/src/validate-new-methods.js.map +1 -0
- package/src/validate-no-any-unknown.d.ts +41 -0
- package/src/{validate-no-any-unknown.ts → validate-no-any-unknown.js} +69 -146
- package/src/validate-no-any-unknown.js.map +1 -0
- package/src/validate-no-destructure.d.ts +51 -0
- package/src/{validate-no-destructure.ts → validate-no-destructure.js} +80 -166
- package/src/validate-no-destructure.js.map +1 -0
- package/src/validate-no-direct-api-resolver.d.ts +46 -0
- package/src/{validate-no-direct-api-resolver.ts → validate-no-direct-api-resolver.js} +112 -211
- package/src/validate-no-direct-api-resolver.js.map +1 -0
- package/src/validate-no-implicit-any.d.ts +36 -0
- package/src/{validate-no-implicit-any.ts → validate-no-implicit-any.js} +94 -141
- package/src/validate-no-implicit-any.js.map +1 -0
- package/src/validate-no-inline-types.d.ts +90 -0
- package/src/{validate-no-inline-types.ts → validate-no-inline-types.js} +93 -198
- package/src/validate-no-inline-types.js.map +1 -0
- package/src/validate-no-unmanaged-exceptions.d.ts +43 -0
- package/src/{validate-no-unmanaged-exceptions.ts → validate-no-unmanaged-exceptions.js} +71 -140
- package/src/validate-no-unmanaged-exceptions.js.map +1 -0
- package/src/validate-prisma-converters.d.ts +59 -0
- package/src/{validate-prisma-converters.ts → validate-prisma-converters.js} +120 -307
- package/src/validate-prisma-converters.js.map +1 -0
- package/src/validate-return-types.d.ts +28 -0
- package/src/{validate-return-types.ts → validate-return-types.js} +84 -168
- package/src/validate-return-types.js.map +1 -0
- package/LICENSE +0 -373
- package/jest.config.ts +0 -20
- package/project.json +0 -22
- package/src/cli.ts +0 -17
- package/src/from-shared-config.ts +0 -118
- package/tsconfig.json +0 -22
- package/tsconfig.lib.json +0 -10
- package/tsconfig.spec.json +0 -14
- /package/src/{index.ts → index.d.ts} +0 -0
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
"use strict";
|
|
1
2
|
/**
|
|
2
3
|
* Validate Prisma Converters Executor
|
|
3
4
|
*
|
|
@@ -44,92 +45,58 @@
|
|
|
44
45
|
* - NEW_AND_MODIFIED_METHODS: Validate new/modified methods in converters + changed lines in non-converters
|
|
45
46
|
* - MODIFIED_FILES: Validate all methods in modified files
|
|
46
47
|
*/
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
export interface ValidatePrismaConvertersOptions {
|
|
57
|
-
mode?: PrismaConverterMode;
|
|
58
|
-
disableAllowed?: boolean;
|
|
59
|
-
schemaPath?: string;
|
|
60
|
-
convertersPaths?: string[];
|
|
61
|
-
enforcePaths?: string[];
|
|
62
|
-
ignoreModifiedUntilEpoch?: number;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
export interface ExecutorResult {
|
|
66
|
-
success: boolean;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
interface PrismaConverterViolation {
|
|
70
|
-
file: string;
|
|
71
|
-
line: number;
|
|
72
|
-
message: string;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
interface UnwrapResult {
|
|
76
|
-
inner: string;
|
|
77
|
-
isAsync: boolean;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
interface FileContext {
|
|
81
|
-
filePath: string;
|
|
82
|
-
fileLines: string[];
|
|
83
|
-
sourceFile: ts.SourceFile;
|
|
84
|
-
prismaModels: Set<string>;
|
|
85
|
-
disableAllowed: boolean;
|
|
86
|
-
}
|
|
87
|
-
|
|
48
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
49
|
+
exports.default = runValidator;
|
|
50
|
+
const tslib_1 = require("tslib");
|
|
51
|
+
const child_process_1 = require("child_process");
|
|
52
|
+
const fs = tslib_1.__importStar(require("fs"));
|
|
53
|
+
const path = tslib_1.__importStar(require("path"));
|
|
54
|
+
const ts = tslib_1.__importStar(require("typescript"));
|
|
55
|
+
const diff_utils_1 = require("./diff-utils");
|
|
88
56
|
/**
|
|
89
57
|
* Auto-detect the base branch by finding the merge-base with origin/main.
|
|
90
58
|
*/
|
|
91
|
-
function detectBase(workspaceRoot
|
|
59
|
+
function detectBase(workspaceRoot) {
|
|
92
60
|
// eslint-disable-next-line @webpieces/no-unmanaged-exceptions
|
|
93
61
|
try {
|
|
94
|
-
const mergeBase = execSync('git merge-base HEAD origin/main', {
|
|
62
|
+
const mergeBase = (0, child_process_1.execSync)('git merge-base HEAD origin/main', {
|
|
95
63
|
cwd: workspaceRoot,
|
|
96
64
|
encoding: 'utf-8',
|
|
97
65
|
stdio: ['pipe', 'pipe', 'pipe'],
|
|
98
66
|
}).trim();
|
|
99
|
-
|
|
100
67
|
if (mergeBase) {
|
|
101
68
|
return mergeBase;
|
|
102
69
|
}
|
|
103
|
-
}
|
|
70
|
+
}
|
|
71
|
+
catch (err) {
|
|
104
72
|
//const error = toError(err);
|
|
105
73
|
// eslint-disable-next-line @webpieces/no-unmanaged-exceptions
|
|
106
74
|
try {
|
|
107
|
-
const mergeBase = execSync('git merge-base HEAD main', {
|
|
75
|
+
const mergeBase = (0, child_process_1.execSync)('git merge-base HEAD main', {
|
|
108
76
|
cwd: workspaceRoot,
|
|
109
77
|
encoding: 'utf-8',
|
|
110
78
|
stdio: ['pipe', 'pipe', 'pipe'],
|
|
111
79
|
}).trim();
|
|
112
|
-
|
|
113
80
|
if (mergeBase) {
|
|
114
81
|
return mergeBase;
|
|
115
82
|
}
|
|
116
|
-
}
|
|
83
|
+
}
|
|
84
|
+
catch (err2) {
|
|
117
85
|
//const error2 = toError(err2);
|
|
118
86
|
// Ignore
|
|
119
87
|
}
|
|
120
88
|
}
|
|
121
89
|
return null;
|
|
122
90
|
}
|
|
123
|
-
|
|
124
91
|
/**
|
|
125
92
|
* Get changed TypeScript files between base and head (or working tree if head not specified).
|
|
126
93
|
*/
|
|
127
94
|
// webpieces-disable max-lines-new-methods -- Git command handling with untracked files requires multiple code paths
|
|
128
|
-
function getChangedTypeScriptFiles(workspaceRoot
|
|
95
|
+
function getChangedTypeScriptFiles(workspaceRoot, base, head) {
|
|
129
96
|
// eslint-disable-next-line @webpieces/no-unmanaged-exceptions
|
|
130
97
|
try {
|
|
131
98
|
const diffTarget = head ? `${base} ${head}` : base;
|
|
132
|
-
const output = execSync(`git diff --name-only ${diffTarget} -- '*.ts' '*.tsx'`, {
|
|
99
|
+
const output = (0, child_process_1.execSync)(`git diff --name-only ${diffTarget} -- '*.ts' '*.tsx'`, {
|
|
133
100
|
cwd: workspaceRoot,
|
|
134
101
|
encoding: 'utf-8',
|
|
135
102
|
});
|
|
@@ -137,11 +104,10 @@ function getChangedTypeScriptFiles(workspaceRoot: string, base: string, head?: s
|
|
|
137
104
|
.trim()
|
|
138
105
|
.split('\n')
|
|
139
106
|
.filter((f) => f && !f.includes('.spec.ts') && !f.includes('.test.ts'));
|
|
140
|
-
|
|
141
107
|
if (!head) {
|
|
142
108
|
// eslint-disable-next-line @webpieces/no-unmanaged-exceptions
|
|
143
109
|
try {
|
|
144
|
-
const untrackedOutput = execSync(`git ls-files --others --exclude-standard '*.ts' '*.tsx'`, {
|
|
110
|
+
const untrackedOutput = (0, child_process_1.execSync)(`git ls-files --others --exclude-standard '*.ts' '*.tsx'`, {
|
|
145
111
|
cwd: workspaceRoot,
|
|
146
112
|
encoding: 'utf-8',
|
|
147
113
|
});
|
|
@@ -151,53 +117,48 @@ function getChangedTypeScriptFiles(workspaceRoot: string, base: string, head?: s
|
|
|
151
117
|
.filter((f) => f && !f.includes('.spec.ts') && !f.includes('.test.ts'));
|
|
152
118
|
const allFiles = new Set([...changedFiles, ...untrackedFiles]);
|
|
153
119
|
return Array.from(allFiles);
|
|
154
|
-
}
|
|
120
|
+
}
|
|
121
|
+
catch (err) {
|
|
155
122
|
//const error = toError(err);
|
|
156
123
|
return changedFiles;
|
|
157
124
|
}
|
|
158
125
|
}
|
|
159
|
-
|
|
160
126
|
return changedFiles;
|
|
161
|
-
}
|
|
127
|
+
}
|
|
128
|
+
catch (err) {
|
|
162
129
|
//const error = toError(err);
|
|
163
130
|
return [];
|
|
164
131
|
}
|
|
165
132
|
}
|
|
166
|
-
|
|
167
133
|
/**
|
|
168
134
|
* Parse schema.prisma to extract all model names into a Set.
|
|
169
135
|
*/
|
|
170
|
-
function parsePrismaModels(schemaPath
|
|
171
|
-
const models = new Set
|
|
172
|
-
|
|
136
|
+
function parsePrismaModels(schemaPath) {
|
|
137
|
+
const models = new Set();
|
|
173
138
|
if (!fs.existsSync(schemaPath)) {
|
|
174
139
|
return models;
|
|
175
140
|
}
|
|
176
|
-
|
|
177
141
|
const content = fs.readFileSync(schemaPath, 'utf-8');
|
|
178
142
|
const regex = /^model\s+(\w+)\s*\{/gm;
|
|
179
|
-
let match
|
|
180
|
-
|
|
143
|
+
let match;
|
|
181
144
|
while ((match = regex.exec(content)) !== null) {
|
|
182
145
|
models.add(match[1]);
|
|
183
146
|
}
|
|
184
|
-
|
|
185
147
|
return models;
|
|
186
148
|
}
|
|
187
|
-
|
|
188
149
|
/**
|
|
189
150
|
* Derive the expected Dbo name from a return type ending in Dto.
|
|
190
151
|
* "XxxDto" -> "XxxDbo". Returns null if name doesn't end with Dto.
|
|
191
152
|
*/
|
|
192
|
-
function deriveExpectedDboName(returnType
|
|
193
|
-
if (!returnType.endsWith('Dto'))
|
|
153
|
+
function deriveExpectedDboName(returnType) {
|
|
154
|
+
if (!returnType.endsWith('Dto'))
|
|
155
|
+
return null;
|
|
194
156
|
return returnType.slice(0, -3) + 'Dbo';
|
|
195
157
|
}
|
|
196
|
-
|
|
197
158
|
/**
|
|
198
159
|
* Check if a line has a webpieces-disable comment for prisma-converter.
|
|
199
160
|
*/
|
|
200
|
-
function hasDisableComment(lines
|
|
161
|
+
function hasDisableComment(lines, lineNumber) {
|
|
201
162
|
const startCheck = Math.max(0, lineNumber - 5);
|
|
202
163
|
for (let i = lineNumber - 2; i >= startCheck; i--) {
|
|
203
164
|
const line = lines[i]?.trim() ?? '';
|
|
@@ -210,76 +171,68 @@ function hasDisableComment(lines: string[], lineNumber: number): boolean {
|
|
|
210
171
|
}
|
|
211
172
|
return false;
|
|
212
173
|
}
|
|
213
|
-
|
|
214
174
|
/**
|
|
215
175
|
* Check if a method/function node has a @deprecated decorator.
|
|
216
176
|
*/
|
|
217
|
-
function hasDeprecatedDecorator(node
|
|
177
|
+
function hasDeprecatedDecorator(node) {
|
|
218
178
|
const modifiers = ts.canHaveDecorators(node) ? ts.getDecorators(node) : undefined;
|
|
219
|
-
if (!modifiers)
|
|
220
|
-
|
|
179
|
+
if (!modifiers)
|
|
180
|
+
return false;
|
|
221
181
|
for (const decorator of modifiers) {
|
|
222
182
|
const expr = decorator.expression;
|
|
223
183
|
// @deprecated or @deprecated()
|
|
224
|
-
if (ts.isIdentifier(expr) && expr.text === 'deprecated')
|
|
184
|
+
if (ts.isIdentifier(expr) && expr.text === 'deprecated')
|
|
185
|
+
return true;
|
|
225
186
|
if (ts.isCallExpression(expr) && ts.isIdentifier(expr.expression) && expr.expression.text === 'deprecated') {
|
|
226
187
|
return true;
|
|
227
188
|
}
|
|
228
189
|
}
|
|
229
190
|
return false;
|
|
230
191
|
}
|
|
231
|
-
|
|
232
192
|
/**
|
|
233
193
|
* Check if a node has @deprecated in its JSDoc comments.
|
|
234
194
|
*/
|
|
235
|
-
function hasDeprecatedJsDoc(node
|
|
195
|
+
function hasDeprecatedJsDoc(node) {
|
|
236
196
|
const jsDocs = ts.getJSDocTags(node);
|
|
237
197
|
for (const tag of jsDocs) {
|
|
238
|
-
if (tag.tagName.text === 'deprecated')
|
|
198
|
+
if (tag.tagName.text === 'deprecated')
|
|
199
|
+
return true;
|
|
239
200
|
}
|
|
240
201
|
return false;
|
|
241
202
|
}
|
|
242
|
-
|
|
243
203
|
/**
|
|
244
204
|
* Check if a method is deprecated via decorator or JSDoc.
|
|
245
205
|
*/
|
|
246
|
-
function isDeprecated(node
|
|
206
|
+
function isDeprecated(node) {
|
|
247
207
|
return hasDeprecatedDecorator(node) || hasDeprecatedJsDoc(node);
|
|
248
208
|
}
|
|
249
|
-
|
|
250
209
|
/**
|
|
251
210
|
* Extract the text of a type node, stripping whitespace.
|
|
252
211
|
*/
|
|
253
|
-
function getTypeText(typeNode
|
|
212
|
+
function getTypeText(typeNode, sourceFile) {
|
|
254
213
|
return typeNode.getText(sourceFile).trim();
|
|
255
214
|
}
|
|
256
|
-
|
|
257
215
|
/**
|
|
258
216
|
* Unwrap Promise<T> to get T. Returns the inner type text if wrapped, otherwise returns as-is.
|
|
259
217
|
*/
|
|
260
|
-
function unwrapPromise(typeText
|
|
218
|
+
function unwrapPromise(typeText) {
|
|
261
219
|
const promiseMatch = typeText.match(/^Promise\s*<\s*(.+)\s*>$/);
|
|
262
220
|
if (promiseMatch) {
|
|
263
221
|
return { inner: promiseMatch[1].trim(), isAsync: true };
|
|
264
222
|
}
|
|
265
223
|
return { inner: typeText, isAsync: false };
|
|
266
224
|
}
|
|
267
|
-
|
|
268
225
|
/**
|
|
269
226
|
* Check a standalone function declaration in a converter file and return a violation if applicable.
|
|
270
227
|
*/
|
|
271
|
-
function checkStandaloneFunction(
|
|
272
|
-
node
|
|
273
|
-
|
|
274
|
-
): PrismaConverterViolation | null {
|
|
275
|
-
if (!node.name) return null;
|
|
276
|
-
|
|
228
|
+
function checkStandaloneFunction(node, ctx) {
|
|
229
|
+
if (!node.name)
|
|
230
|
+
return null;
|
|
277
231
|
const startPos = node.getStart(ctx.sourceFile);
|
|
278
232
|
const pos = ctx.sourceFile.getLineAndCharacterOfPosition(startPos);
|
|
279
233
|
const line = pos.line + 1;
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
234
|
+
if ((ctx.disableAllowed && hasDisableComment(ctx.fileLines, line)) || isDeprecated(node))
|
|
235
|
+
return null;
|
|
283
236
|
return {
|
|
284
237
|
file: ctx.filePath,
|
|
285
238
|
line,
|
|
@@ -287,20 +240,12 @@ function checkStandaloneFunction(
|
|
|
287
240
|
'Move to a converter class so it can be injected via DI.',
|
|
288
241
|
};
|
|
289
242
|
}
|
|
290
|
-
|
|
291
243
|
/**
|
|
292
244
|
* Validate the parameters of a converter method that returns a Dto with a matching Dbo.
|
|
293
245
|
*/
|
|
294
|
-
function checkMethodParams(
|
|
295
|
-
|
|
296
|
-
innerType: string,
|
|
297
|
-
expectedDbo: string,
|
|
298
|
-
ctx: FileContext,
|
|
299
|
-
line: number
|
|
300
|
-
): PrismaConverterViolation[] {
|
|
301
|
-
const violations: PrismaConverterViolation[] = [];
|
|
246
|
+
function checkMethodParams(node, innerType, expectedDbo, ctx, line) {
|
|
247
|
+
const violations = [];
|
|
302
248
|
const params = node.parameters;
|
|
303
|
-
|
|
304
249
|
if (params.length === 0) {
|
|
305
250
|
violations.push({
|
|
306
251
|
file: ctx.filePath,
|
|
@@ -310,7 +255,6 @@ function checkMethodParams(
|
|
|
310
255
|
});
|
|
311
256
|
return violations;
|
|
312
257
|
}
|
|
313
|
-
|
|
314
258
|
const firstParam = params[0];
|
|
315
259
|
if (firstParam.type) {
|
|
316
260
|
const firstParamType = getTypeText(firstParam.type, ctx.sourceFile);
|
|
@@ -323,7 +267,6 @@ function checkMethodParams(
|
|
|
323
267
|
});
|
|
324
268
|
}
|
|
325
269
|
}
|
|
326
|
-
|
|
327
270
|
for (let i = 1; i < params.length; i++) {
|
|
328
271
|
const param = params[i];
|
|
329
272
|
if (param.type) {
|
|
@@ -339,118 +282,89 @@ function checkMethodParams(
|
|
|
339
282
|
}
|
|
340
283
|
}
|
|
341
284
|
}
|
|
342
|
-
|
|
343
285
|
return violations;
|
|
344
286
|
}
|
|
345
|
-
|
|
346
287
|
/**
|
|
347
288
|
* Check a class method declaration for converter pattern violations.
|
|
348
289
|
*/
|
|
349
|
-
function checkConverterMethod(
|
|
350
|
-
node
|
|
351
|
-
|
|
352
|
-
): PrismaConverterViolation[] {
|
|
353
|
-
if (!node.name || !node.type) return [];
|
|
354
|
-
|
|
290
|
+
function checkConverterMethod(node, ctx) {
|
|
291
|
+
if (!node.name || !node.type)
|
|
292
|
+
return [];
|
|
355
293
|
const startPos = node.getStart(ctx.sourceFile);
|
|
356
294
|
const pos = ctx.sourceFile.getLineAndCharacterOfPosition(startPos);
|
|
357
295
|
const line = pos.line + 1;
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
296
|
+
if ((ctx.disableAllowed && hasDisableComment(ctx.fileLines, line)) || isDeprecated(node))
|
|
297
|
+
return [];
|
|
361
298
|
const returnTypeText = getTypeText(node.type, ctx.sourceFile);
|
|
362
299
|
const unwrapResult = unwrapPromise(returnTypeText);
|
|
363
300
|
const innerType = unwrapResult.inner;
|
|
364
301
|
const isAsync = unwrapResult.isAsync;
|
|
365
302
|
const expectedDbo = deriveExpectedDboName(innerType);
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
303
|
+
if (!expectedDbo || !ctx.prismaModels.has(expectedDbo))
|
|
304
|
+
return [];
|
|
369
305
|
if (isAsync) {
|
|
370
306
|
return [{
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
307
|
+
file: ctx.filePath,
|
|
308
|
+
line,
|
|
309
|
+
message: `Async converter method returning "Promise<${innerType}>" found. ` +
|
|
310
|
+
'Converters should be pure data mapping with no async work. Remove async/Promise.',
|
|
311
|
+
}];
|
|
376
312
|
}
|
|
377
|
-
|
|
378
313
|
return checkMethodParams(node, innerType, expectedDbo, ctx, line);
|
|
379
314
|
}
|
|
380
|
-
|
|
381
315
|
/**
|
|
382
316
|
* Find converter method violations in a single file.
|
|
383
317
|
* Checks class methods for proper Dbo parameter patterns and flags standalone functions.
|
|
384
318
|
*/
|
|
385
|
-
function findConverterViolationsInFile(
|
|
386
|
-
filePath: string,
|
|
387
|
-
workspaceRoot: string,
|
|
388
|
-
prismaModels: Set<string>,
|
|
389
|
-
disableAllowed: boolean
|
|
390
|
-
): PrismaConverterViolation[] {
|
|
319
|
+
function findConverterViolationsInFile(filePath, workspaceRoot, prismaModels, disableAllowed) {
|
|
391
320
|
const fullPath = path.join(workspaceRoot, filePath);
|
|
392
|
-
if (!fs.existsSync(fullPath))
|
|
393
|
-
|
|
321
|
+
if (!fs.existsSync(fullPath))
|
|
322
|
+
return [];
|
|
394
323
|
const content = fs.readFileSync(fullPath, 'utf-8');
|
|
395
|
-
const ctx
|
|
324
|
+
const ctx = {
|
|
396
325
|
filePath,
|
|
397
326
|
fileLines: content.split('\n'),
|
|
398
327
|
sourceFile: ts.createSourceFile(filePath, content, ts.ScriptTarget.Latest, true),
|
|
399
328
|
prismaModels,
|
|
400
329
|
disableAllowed,
|
|
401
330
|
};
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
function visitNode(node: ts.Node): void {
|
|
331
|
+
const violations = [];
|
|
332
|
+
function visitNode(node) {
|
|
406
333
|
if (ts.isFunctionDeclaration(node)) {
|
|
407
334
|
const violation = checkStandaloneFunction(node, ctx);
|
|
408
|
-
if (violation)
|
|
335
|
+
if (violation)
|
|
336
|
+
violations.push(violation);
|
|
409
337
|
}
|
|
410
|
-
|
|
411
338
|
if (ts.isMethodDeclaration(node)) {
|
|
412
339
|
violations.push(...checkConverterMethod(node, ctx));
|
|
413
340
|
}
|
|
414
|
-
|
|
415
341
|
ts.forEachChild(node, visitNode);
|
|
416
342
|
}
|
|
417
|
-
|
|
418
343
|
visitNode(ctx.sourceFile);
|
|
419
344
|
return violations;
|
|
420
345
|
}
|
|
421
|
-
|
|
422
346
|
/**
|
|
423
347
|
* Find violations in non-converter files: creating `new XxxDto(...)` where XxxDbo exists in prisma.
|
|
424
348
|
* These Dto instances must only be created inside converter classes.
|
|
425
349
|
*/
|
|
426
350
|
// webpieces-disable max-lines-new-methods -- AST traversal for new-expression detection with prisma model matching
|
|
427
|
-
function findDtoCreationOutsideConverters(
|
|
428
|
-
filePath: string,
|
|
429
|
-
workspaceRoot: string,
|
|
430
|
-
prismaModels: Set<string>,
|
|
431
|
-
convertersPaths: string[],
|
|
432
|
-
disableAllowed: boolean
|
|
433
|
-
): PrismaConverterViolation[] {
|
|
351
|
+
function findDtoCreationOutsideConverters(filePath, workspaceRoot, prismaModels, convertersPaths, disableAllowed) {
|
|
434
352
|
const fullPath = path.join(workspaceRoot, filePath);
|
|
435
|
-
if (!fs.existsSync(fullPath))
|
|
436
|
-
|
|
353
|
+
if (!fs.existsSync(fullPath))
|
|
354
|
+
return [];
|
|
437
355
|
const content = fs.readFileSync(fullPath, 'utf-8');
|
|
438
356
|
const fileLines = content.split('\n');
|
|
439
357
|
const sourceFile = ts.createSourceFile(filePath, content, ts.ScriptTarget.Latest, true);
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
function visitNode(node: ts.Node): void {
|
|
358
|
+
const violations = [];
|
|
359
|
+
function visitNode(node) {
|
|
444
360
|
// Detect `new XxxDto(...)` expressions
|
|
445
361
|
if (ts.isNewExpression(node) && ts.isIdentifier(node.expression)) {
|
|
446
362
|
const className = node.expression.text;
|
|
447
363
|
const expectedDbo = deriveExpectedDboName(className);
|
|
448
|
-
|
|
449
364
|
if (expectedDbo && prismaModels.has(expectedDbo)) {
|
|
450
365
|
const startPos = node.getStart(sourceFile);
|
|
451
366
|
const pos = sourceFile.getLineAndCharacterOfPosition(startPos);
|
|
452
367
|
const line = pos.line + 1;
|
|
453
|
-
|
|
454
368
|
if (!disableAllowed || !hasDisableComment(fileLines, line)) {
|
|
455
369
|
const dirs = convertersPaths.map((p) => `"${p}"`).join(', ');
|
|
456
370
|
violations.push({
|
|
@@ -462,99 +376,73 @@ function findDtoCreationOutsideConverters(
|
|
|
462
376
|
}
|
|
463
377
|
}
|
|
464
378
|
}
|
|
465
|
-
|
|
466
379
|
ts.forEachChild(node, visitNode);
|
|
467
380
|
}
|
|
468
|
-
|
|
469
381
|
visitNode(sourceFile);
|
|
470
382
|
return violations;
|
|
471
383
|
}
|
|
472
|
-
|
|
473
384
|
/**
|
|
474
385
|
* Find converter violations only for new/modified methods (NEW_AND_MODIFIED_METHODS mode).
|
|
475
386
|
* For converter files: only check methods/functions that are new or have changed lines in their range.
|
|
476
387
|
*/
|
|
477
388
|
// webpieces-disable max-lines-new-methods -- AST traversal with method boundary filtering for new/modified detection
|
|
478
|
-
function findConverterViolationsForModifiedMethods(
|
|
479
|
-
filePath: string,
|
|
480
|
-
workspaceRoot: string,
|
|
481
|
-
prismaModels: Set<string>,
|
|
482
|
-
disableAllowed: boolean,
|
|
483
|
-
changedLines: Set<number>,
|
|
484
|
-
newMethodNames: Set<string>
|
|
485
|
-
): PrismaConverterViolation[] {
|
|
389
|
+
function findConverterViolationsForModifiedMethods(filePath, workspaceRoot, prismaModels, disableAllowed, changedLines, newMethodNames) {
|
|
486
390
|
const fullPath = path.join(workspaceRoot, filePath);
|
|
487
|
-
if (!fs.existsSync(fullPath))
|
|
488
|
-
|
|
391
|
+
if (!fs.existsSync(fullPath))
|
|
392
|
+
return [];
|
|
489
393
|
const content = fs.readFileSync(fullPath, 'utf-8');
|
|
490
|
-
const ctx
|
|
394
|
+
const ctx = {
|
|
491
395
|
filePath,
|
|
492
396
|
fileLines: content.split('\n'),
|
|
493
397
|
sourceFile: ts.createSourceFile(filePath, content, ts.ScriptTarget.Latest, true),
|
|
494
398
|
prismaModels,
|
|
495
399
|
disableAllowed,
|
|
496
400
|
};
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
function visitNode(node: ts.Node): void {
|
|
401
|
+
const violations = [];
|
|
402
|
+
function visitNode(node) {
|
|
501
403
|
if (ts.isFunctionDeclaration(node) && node.name) {
|
|
502
404
|
const start = ctx.sourceFile.getLineAndCharacterOfPosition(node.getStart(ctx.sourceFile));
|
|
503
405
|
const end = ctx.sourceFile.getLineAndCharacterOfPosition(node.getEnd());
|
|
504
|
-
if (isNewOrModified(node.name.text, start.line + 1, end.line + 1, changedLines, newMethodNames)) {
|
|
406
|
+
if ((0, diff_utils_1.isNewOrModified)(node.name.text, start.line + 1, end.line + 1, changedLines, newMethodNames)) {
|
|
505
407
|
const violation = checkStandaloneFunction(node, ctx);
|
|
506
|
-
if (violation)
|
|
408
|
+
if (violation)
|
|
409
|
+
violations.push(violation);
|
|
507
410
|
}
|
|
508
411
|
}
|
|
509
|
-
|
|
510
412
|
if (ts.isMethodDeclaration(node) && node.name) {
|
|
511
413
|
const start = ctx.sourceFile.getLineAndCharacterOfPosition(node.getStart(ctx.sourceFile));
|
|
512
414
|
const end = ctx.sourceFile.getLineAndCharacterOfPosition(node.getEnd());
|
|
513
415
|
const methodName = node.name.getText(ctx.sourceFile);
|
|
514
|
-
if (isNewOrModified(methodName, start.line + 1, end.line + 1, changedLines, newMethodNames)) {
|
|
416
|
+
if ((0, diff_utils_1.isNewOrModified)(methodName, start.line + 1, end.line + 1, changedLines, newMethodNames)) {
|
|
515
417
|
violations.push(...checkConverterMethod(node, ctx));
|
|
516
418
|
}
|
|
517
419
|
}
|
|
518
|
-
|
|
519
420
|
ts.forEachChild(node, visitNode);
|
|
520
421
|
}
|
|
521
|
-
|
|
522
422
|
visitNode(ctx.sourceFile);
|
|
523
423
|
return violations;
|
|
524
424
|
}
|
|
525
|
-
|
|
526
425
|
/**
|
|
527
426
|
* Find Dto creation violations only on changed lines (NEW_AND_MODIFIED_METHODS mode).
|
|
528
427
|
* For non-converter files: only flag `new XxxDto(...)` on changed lines in the diff.
|
|
529
428
|
*/
|
|
530
429
|
// webpieces-disable max-lines-new-methods -- AST traversal for new-expression detection with changed-line filtering
|
|
531
|
-
function findDtoCreationOnChangedLines(
|
|
532
|
-
filePath: string,
|
|
533
|
-
workspaceRoot: string,
|
|
534
|
-
prismaModels: Set<string>,
|
|
535
|
-
convertersPaths: string[],
|
|
536
|
-
disableAllowed: boolean,
|
|
537
|
-
changedLines: Set<number>
|
|
538
|
-
): PrismaConverterViolation[] {
|
|
430
|
+
function findDtoCreationOnChangedLines(filePath, workspaceRoot, prismaModels, convertersPaths, disableAllowed, changedLines) {
|
|
539
431
|
const fullPath = path.join(workspaceRoot, filePath);
|
|
540
|
-
if (!fs.existsSync(fullPath))
|
|
541
|
-
|
|
432
|
+
if (!fs.existsSync(fullPath))
|
|
433
|
+
return [];
|
|
542
434
|
const content = fs.readFileSync(fullPath, 'utf-8');
|
|
543
435
|
const fileLines = content.split('\n');
|
|
544
436
|
const sourceFile = ts.createSourceFile(filePath, content, ts.ScriptTarget.Latest, true);
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
function visitNode(node: ts.Node): void {
|
|
437
|
+
const violations = [];
|
|
438
|
+
function visitNode(node) {
|
|
549
439
|
if (ts.isNewExpression(node) && ts.isIdentifier(node.expression)) {
|
|
550
440
|
const className = node.expression.text;
|
|
551
441
|
const expectedDbo = deriveExpectedDboName(className);
|
|
552
|
-
|
|
553
442
|
if (expectedDbo && prismaModels.has(expectedDbo)) {
|
|
554
443
|
const startPos = node.getStart(sourceFile);
|
|
555
444
|
const pos = sourceFile.getLineAndCharacterOfPosition(startPos);
|
|
556
445
|
const line = pos.line + 1;
|
|
557
|
-
|
|
558
446
|
if (changedLines.has(line) && (!disableAllowed || !hasDisableComment(fileLines, line))) {
|
|
559
447
|
const dirs = convertersPaths.map((p) => `"${p}"`).join(', ');
|
|
560
448
|
violations.push({
|
|
@@ -566,70 +454,48 @@ function findDtoCreationOnChangedLines(
|
|
|
566
454
|
}
|
|
567
455
|
}
|
|
568
456
|
}
|
|
569
|
-
|
|
570
457
|
ts.forEachChild(node, visitNode);
|
|
571
458
|
}
|
|
572
|
-
|
|
573
459
|
visitNode(sourceFile);
|
|
574
460
|
return violations;
|
|
575
461
|
}
|
|
576
|
-
|
|
577
462
|
/**
|
|
578
463
|
* Collect violations for NEW_AND_MODIFIED_METHODS mode.
|
|
579
464
|
* Converter files: method-level — only check new/modified methods.
|
|
580
465
|
* Non-converter files: line-level — only flag new XxxDto() on changed lines.
|
|
581
466
|
*/
|
|
582
467
|
// webpieces-disable max-lines-new-methods -- File classification and diff-based violation collection
|
|
583
|
-
function collectViolationsForModifiedMethodAndCode(
|
|
584
|
-
changedFiles
|
|
585
|
-
convertersPaths
|
|
586
|
-
|
|
587
|
-
prismaModels: Set<string>,
|
|
588
|
-
disableAllowed: boolean,
|
|
589
|
-
base: string,
|
|
590
|
-
head: string | undefined
|
|
591
|
-
): PrismaConverterViolation[] {
|
|
592
|
-
const converterFiles = changedFiles.filter((f) =>
|
|
593
|
-
convertersPaths.some((cp) => f.startsWith(cp))
|
|
594
|
-
);
|
|
595
|
-
const nonConverterFiles = changedFiles.filter((f) =>
|
|
596
|
-
!convertersPaths.some((cp) => f.startsWith(cp))
|
|
597
|
-
);
|
|
598
|
-
|
|
599
|
-
const allViolations: PrismaConverterViolation[] = [];
|
|
600
|
-
|
|
468
|
+
function collectViolationsForModifiedMethodAndCode(changedFiles, convertersPaths, workspaceRoot, prismaModels, disableAllowed, base, head) {
|
|
469
|
+
const converterFiles = changedFiles.filter((f) => convertersPaths.some((cp) => f.startsWith(cp)));
|
|
470
|
+
const nonConverterFiles = changedFiles.filter((f) => !convertersPaths.some((cp) => f.startsWith(cp)));
|
|
471
|
+
const allViolations = [];
|
|
601
472
|
if (converterFiles.length > 0) {
|
|
602
473
|
console.log(`📂 Checking ${converterFiles.length} converter file(s) (new/modified methods only)...`);
|
|
603
474
|
for (const file of converterFiles) {
|
|
604
|
-
const diff = getFileDiff(workspaceRoot, file, base, head);
|
|
605
|
-
const changedLines = getChangedLineNumbers(diff);
|
|
606
|
-
const newMethodNames = findNewMethodSignaturesInDiff(diff);
|
|
607
|
-
if (changedLines.size === 0 && newMethodNames.size === 0)
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
));
|
|
475
|
+
const diff = (0, diff_utils_1.getFileDiff)(workspaceRoot, file, base, head);
|
|
476
|
+
const changedLines = (0, diff_utils_1.getChangedLineNumbers)(diff);
|
|
477
|
+
const newMethodNames = (0, diff_utils_1.findNewMethodSignaturesInDiff)(diff);
|
|
478
|
+
if (changedLines.size === 0 && newMethodNames.size === 0)
|
|
479
|
+
continue;
|
|
480
|
+
allViolations.push(...findConverterViolationsForModifiedMethods(file, workspaceRoot, prismaModels, disableAllowed, changedLines, newMethodNames));
|
|
611
481
|
}
|
|
612
482
|
}
|
|
613
|
-
|
|
614
483
|
if (nonConverterFiles.length > 0) {
|
|
615
484
|
console.log(`📂 Checking ${nonConverterFiles.length} non-converter file(s) for Dto creation (changed lines only)...`);
|
|
616
485
|
for (const file of nonConverterFiles) {
|
|
617
|
-
const diff = getFileDiff(workspaceRoot, file, base, head);
|
|
618
|
-
const changedLines = getChangedLineNumbers(diff);
|
|
619
|
-
if (changedLines.size === 0)
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
));
|
|
486
|
+
const diff = (0, diff_utils_1.getFileDiff)(workspaceRoot, file, base, head);
|
|
487
|
+
const changedLines = (0, diff_utils_1.getChangedLineNumbers)(diff);
|
|
488
|
+
if (changedLines.size === 0)
|
|
489
|
+
continue;
|
|
490
|
+
allViolations.push(...findDtoCreationOnChangedLines(file, workspaceRoot, prismaModels, convertersPaths, disableAllowed, changedLines));
|
|
623
491
|
}
|
|
624
492
|
}
|
|
625
|
-
|
|
626
493
|
return allViolations;
|
|
627
494
|
}
|
|
628
|
-
|
|
629
495
|
/**
|
|
630
496
|
* Report violations to console.
|
|
631
497
|
*/
|
|
632
|
-
function reportViolations(violations
|
|
498
|
+
function reportViolations(violations, mode) {
|
|
633
499
|
console.error('');
|
|
634
500
|
console.error('❌ Prisma converter violations found!');
|
|
635
501
|
console.error('');
|
|
@@ -646,133 +512,90 @@ function reportViolations(violations: PrismaConverterViolation[], mode: PrismaCo
|
|
|
646
512
|
console.error(' BAD: convertUser(dbo: UserDbo, name: string): UserDto { } // extra non-boolean');
|
|
647
513
|
console.error(' BAD: export function convertSession(s: SessionDbo): SessionDto // standalone function');
|
|
648
514
|
console.error('');
|
|
649
|
-
|
|
650
515
|
for (const v of violations) {
|
|
651
516
|
console.error(` ❌ ${v.file}:${v.line}`);
|
|
652
517
|
console.error(` ${v.message}`);
|
|
653
518
|
}
|
|
654
519
|
console.error('');
|
|
655
|
-
|
|
656
520
|
console.error(' Escape hatch (use sparingly):');
|
|
657
521
|
console.error(' // webpieces-disable prisma-converter -- [your reason]');
|
|
658
522
|
console.error('');
|
|
659
523
|
console.error(` Current mode: ${mode}`);
|
|
660
524
|
console.error('');
|
|
661
525
|
}
|
|
662
|
-
|
|
663
526
|
/**
|
|
664
527
|
* Resolve git base ref from env vars or auto-detection.
|
|
665
528
|
*/
|
|
666
|
-
function resolveBase(workspaceRoot
|
|
529
|
+
function resolveBase(workspaceRoot) {
|
|
667
530
|
const envBase = process.env['NX_BASE'];
|
|
668
|
-
if (envBase)
|
|
531
|
+
if (envBase)
|
|
532
|
+
return envBase;
|
|
669
533
|
return detectBase(workspaceRoot) ?? undefined;
|
|
670
534
|
}
|
|
671
|
-
|
|
672
535
|
/**
|
|
673
536
|
* Collect all violations from converter and non-converter files.
|
|
674
537
|
*/
|
|
675
|
-
function collectAllViolations(
|
|
676
|
-
changedFiles
|
|
677
|
-
convertersPaths
|
|
678
|
-
|
|
679
|
-
prismaModels: Set<string>,
|
|
680
|
-
disableAllowed: boolean
|
|
681
|
-
): PrismaConverterViolation[] {
|
|
682
|
-
const converterFiles = changedFiles.filter((f) =>
|
|
683
|
-
convertersPaths.some((cp) => f.startsWith(cp))
|
|
684
|
-
);
|
|
685
|
-
const nonConverterFiles = changedFiles.filter((f) =>
|
|
686
|
-
!convertersPaths.some((cp) => f.startsWith(cp))
|
|
687
|
-
);
|
|
688
|
-
|
|
689
|
-
const allViolations: PrismaConverterViolation[] = [];
|
|
690
|
-
|
|
538
|
+
function collectAllViolations(changedFiles, convertersPaths, workspaceRoot, prismaModels, disableAllowed) {
|
|
539
|
+
const converterFiles = changedFiles.filter((f) => convertersPaths.some((cp) => f.startsWith(cp)));
|
|
540
|
+
const nonConverterFiles = changedFiles.filter((f) => !convertersPaths.some((cp) => f.startsWith(cp)));
|
|
541
|
+
const allViolations = [];
|
|
691
542
|
if (converterFiles.length > 0) {
|
|
692
543
|
console.log(`📂 Checking ${converterFiles.length} converter file(s)...`);
|
|
693
544
|
for (const file of converterFiles) {
|
|
694
545
|
allViolations.push(...findConverterViolationsInFile(file, workspaceRoot, prismaModels, disableAllowed));
|
|
695
546
|
}
|
|
696
547
|
}
|
|
697
|
-
|
|
698
548
|
if (nonConverterFiles.length > 0) {
|
|
699
549
|
console.log(`📂 Checking ${nonConverterFiles.length} non-converter file(s) for Dto creation...`);
|
|
700
550
|
for (const file of nonConverterFiles) {
|
|
701
551
|
allViolations.push(...findDtoCreationOutsideConverters(file, workspaceRoot, prismaModels, convertersPaths, disableAllowed));
|
|
702
552
|
}
|
|
703
553
|
}
|
|
704
|
-
|
|
705
554
|
return allViolations;
|
|
706
555
|
}
|
|
707
|
-
|
|
708
556
|
/**
|
|
709
557
|
* Run validation after early-exit checks have passed.
|
|
710
558
|
*/
|
|
711
|
-
function validateChangedFiles(
|
|
712
|
-
workspaceRoot: string,
|
|
713
|
-
schemaPath: string,
|
|
714
|
-
convertersPaths: string[],
|
|
715
|
-
enforcePaths: string[],
|
|
716
|
-
base: string,
|
|
717
|
-
mode: PrismaConverterMode,
|
|
718
|
-
disableAllowed: boolean
|
|
719
|
-
): ExecutorResult {
|
|
559
|
+
function validateChangedFiles(workspaceRoot, schemaPath, convertersPaths, enforcePaths, base, mode, disableAllowed) {
|
|
720
560
|
const head = process.env['NX_HEAD'];
|
|
721
|
-
|
|
722
561
|
console.log(` Base: ${base}`);
|
|
723
562
|
console.log(` Head: ${head ?? 'working tree (includes uncommitted changes)'}`);
|
|
724
563
|
console.log('');
|
|
725
|
-
|
|
726
564
|
const fullSchemaPath = path.join(workspaceRoot, schemaPath);
|
|
727
565
|
const prismaModels = parsePrismaModels(fullSchemaPath);
|
|
728
|
-
|
|
729
566
|
if (prismaModels.size === 0) {
|
|
730
567
|
console.log('⏭️ No models found in schema.prisma');
|
|
731
568
|
console.log('');
|
|
732
569
|
return { success: true };
|
|
733
570
|
}
|
|
734
|
-
|
|
735
571
|
console.log(` Found ${prismaModels.size} model(s) in schema.prisma`);
|
|
736
|
-
|
|
737
572
|
let changedFiles = getChangedTypeScriptFiles(workspaceRoot, base, head);
|
|
738
573
|
if (enforcePaths.length > 0) {
|
|
739
|
-
changedFiles = changedFiles.filter((f) =>
|
|
740
|
-
enforcePaths.some((ep) => f.startsWith(ep))
|
|
741
|
-
);
|
|
574
|
+
changedFiles = changedFiles.filter((f) => enforcePaths.some((ep) => f.startsWith(ep)));
|
|
742
575
|
}
|
|
743
|
-
|
|
744
576
|
if (changedFiles.length === 0) {
|
|
745
577
|
console.log('✅ No TypeScript files changed');
|
|
746
578
|
return { success: true };
|
|
747
579
|
}
|
|
748
|
-
|
|
749
|
-
let allViolations: PrismaConverterViolation[];
|
|
750
|
-
|
|
580
|
+
let allViolations;
|
|
751
581
|
if (mode === 'NEW_AND_MODIFIED_METHODS') {
|
|
752
|
-
allViolations = collectViolationsForModifiedMethodAndCode(
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
} else {
|
|
582
|
+
allViolations = collectViolationsForModifiedMethodAndCode(changedFiles, convertersPaths, workspaceRoot, prismaModels, disableAllowed, base, head);
|
|
583
|
+
}
|
|
584
|
+
else {
|
|
756
585
|
allViolations = collectAllViolations(changedFiles, convertersPaths, workspaceRoot, prismaModels, disableAllowed);
|
|
757
586
|
}
|
|
758
|
-
|
|
759
587
|
if (allViolations.length === 0) {
|
|
760
588
|
console.log('✅ All converter patterns are valid');
|
|
761
589
|
return { success: true };
|
|
762
590
|
}
|
|
763
|
-
|
|
764
591
|
reportViolations(allViolations, mode);
|
|
765
592
|
return { success: false };
|
|
766
593
|
}
|
|
767
|
-
|
|
768
594
|
/**
|
|
769
595
|
* Resolve mode considering ignoreModifiedUntilEpoch override.
|
|
770
596
|
* When active, downgrades to OFF. When expired, logs a warning.
|
|
771
597
|
*/
|
|
772
|
-
function resolvePrismaConverterMode(
|
|
773
|
-
normalMode: PrismaConverterMode,
|
|
774
|
-
epoch: number | undefined
|
|
775
|
-
): PrismaConverterMode {
|
|
598
|
+
function resolvePrismaConverterMode(normalMode, epoch) {
|
|
776
599
|
if (epoch === undefined || normalMode === 'OFF') {
|
|
777
600
|
return normalMode;
|
|
778
601
|
}
|
|
@@ -785,30 +608,22 @@ function resolvePrismaConverterMode(
|
|
|
785
608
|
}
|
|
786
609
|
return normalMode;
|
|
787
610
|
}
|
|
788
|
-
|
|
789
|
-
export default async function runValidator(
|
|
790
|
-
options: ValidatePrismaConvertersOptions,
|
|
791
|
-
workspaceRoot: string
|
|
792
|
-
): Promise<ExecutorResult> {
|
|
611
|
+
async function runValidator(options, workspaceRoot) {
|
|
793
612
|
const mode = resolvePrismaConverterMode(options.mode ?? 'OFF', options.ignoreModifiedUntilEpoch);
|
|
794
|
-
|
|
795
613
|
if (mode === 'OFF') {
|
|
796
614
|
console.log('\n⏭️ Skipping prisma-converter validation (mode: OFF)');
|
|
797
615
|
console.log('');
|
|
798
616
|
return { success: true };
|
|
799
617
|
}
|
|
800
|
-
|
|
801
618
|
const schemaPath = options.schemaPath;
|
|
802
619
|
const convertersPaths = options.convertersPaths ?? [];
|
|
803
620
|
const enforcePaths = options.enforcePaths ?? [];
|
|
804
|
-
|
|
805
621
|
if (!schemaPath || convertersPaths.length === 0) {
|
|
806
622
|
const reason = !schemaPath ? 'no schemaPath configured' : 'no convertersPaths configured';
|
|
807
623
|
console.log(`\n⏭️ Skipping prisma-converter validation (${reason})`);
|
|
808
624
|
console.log('');
|
|
809
625
|
return { success: true };
|
|
810
626
|
}
|
|
811
|
-
|
|
812
627
|
console.log('\n📏 Validating Prisma Converters\n');
|
|
813
628
|
console.log(` Mode: ${mode}`);
|
|
814
629
|
console.log(` Schema: ${schemaPath}`);
|
|
@@ -816,15 +631,13 @@ export default async function runValidator(
|
|
|
816
631
|
if (enforcePaths.length > 0) {
|
|
817
632
|
console.log(` Enforce paths: ${enforcePaths.join(', ')}`);
|
|
818
633
|
}
|
|
819
|
-
|
|
820
634
|
const base = resolveBase(workspaceRoot);
|
|
821
|
-
|
|
822
635
|
if (!base) {
|
|
823
636
|
console.log('\n⏭️ Skipping prisma-converter validation (could not detect base branch)');
|
|
824
637
|
console.log('');
|
|
825
638
|
return { success: true };
|
|
826
639
|
}
|
|
827
|
-
|
|
828
640
|
const disableAllowed = options.disableAllowed ?? true;
|
|
829
641
|
return validateChangedFiles(workspaceRoot, schemaPath, convertersPaths, enforcePaths, base, mode, disableAllowed);
|
|
830
642
|
}
|
|
643
|
+
//# sourceMappingURL=validate-prisma-converters.js.map
|