@webpieces/code-rules 0.0.1 → 0.2.114

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.
Files changed (63) hide show
  1. package/package.json +4 -3
  2. package/src/cli.d.ts +1 -0
  3. package/src/cli.js +19 -0
  4. package/src/cli.js.map +1 -0
  5. package/src/diff-utils.d.ts +24 -0
  6. package/src/{diff-utils.ts → diff-utils.js} +30 -38
  7. package/src/diff-utils.js.map +1 -0
  8. package/src/from-shared-config.d.ts +28 -0
  9. package/src/from-shared-config.js +119 -0
  10. package/src/from-shared-config.js.map +1 -0
  11. package/src/index.js +33 -0
  12. package/src/index.js.map +1 -0
  13. package/src/validate-catch-error-pattern.d.ts +47 -0
  14. package/src/{validate-catch-error-pattern.ts → validate-catch-error-pattern.js} +74 -195
  15. package/src/validate-catch-error-pattern.js.map +1 -0
  16. package/src/validate-code.d.ts +98 -0
  17. package/src/{validate-code.ts → validate-code.js} +65 -259
  18. package/src/validate-code.js.map +1 -0
  19. package/src/validate-dtos.d.ts +41 -0
  20. package/src/{validate-dtos.ts → validate-dtos.js} +88 -215
  21. package/src/validate-dtos.js.map +1 -0
  22. package/src/validate-modified-files.d.ts +24 -0
  23. package/src/{validate-modified-files.ts → validate-modified-files.js} +46 -115
  24. package/src/validate-modified-files.js.map +1 -0
  25. package/src/validate-modified-methods.d.ts +30 -0
  26. package/src/{validate-modified-methods.ts → validate-modified-methods.js} +94 -196
  27. package/src/validate-modified-methods.js.map +1 -0
  28. package/src/validate-new-methods.d.ts +27 -0
  29. package/src/{validate-new-methods.ts → validate-new-methods.js} +63 -133
  30. package/src/validate-new-methods.js.map +1 -0
  31. package/src/validate-no-any-unknown.d.ts +41 -0
  32. package/src/{validate-no-any-unknown.ts → validate-no-any-unknown.js} +69 -146
  33. package/src/validate-no-any-unknown.js.map +1 -0
  34. package/src/validate-no-destructure.d.ts +51 -0
  35. package/src/{validate-no-destructure.ts → validate-no-destructure.js} +80 -166
  36. package/src/validate-no-destructure.js.map +1 -0
  37. package/src/validate-no-direct-api-resolver.d.ts +46 -0
  38. package/src/{validate-no-direct-api-resolver.ts → validate-no-direct-api-resolver.js} +112 -211
  39. package/src/validate-no-direct-api-resolver.js.map +1 -0
  40. package/src/validate-no-implicit-any.d.ts +36 -0
  41. package/src/{validate-no-implicit-any.ts → validate-no-implicit-any.js} +94 -141
  42. package/src/validate-no-implicit-any.js.map +1 -0
  43. package/src/validate-no-inline-types.d.ts +90 -0
  44. package/src/{validate-no-inline-types.ts → validate-no-inline-types.js} +93 -198
  45. package/src/validate-no-inline-types.js.map +1 -0
  46. package/src/validate-no-unmanaged-exceptions.d.ts +43 -0
  47. package/src/{validate-no-unmanaged-exceptions.ts → validate-no-unmanaged-exceptions.js} +71 -140
  48. package/src/validate-no-unmanaged-exceptions.js.map +1 -0
  49. package/src/validate-prisma-converters.d.ts +59 -0
  50. package/src/{validate-prisma-converters.ts → validate-prisma-converters.js} +120 -307
  51. package/src/validate-prisma-converters.js.map +1 -0
  52. package/src/validate-return-types.d.ts +28 -0
  53. package/src/{validate-return-types.ts → validate-return-types.js} +84 -168
  54. package/src/validate-return-types.js.map +1 -0
  55. package/LICENSE +0 -373
  56. package/jest.config.ts +0 -20
  57. package/project.json +0 -22
  58. package/src/cli.ts +0 -17
  59. package/src/from-shared-config.ts +0 -118
  60. package/tsconfig.json +0 -22
  61. package/tsconfig.lib.json +0 -10
  62. package/tsconfig.spec.json +0 -14
  63. /package/src/{index.ts → index.d.ts} +0 -0
@@ -1,3 +1,4 @@
1
+ "use strict";
1
2
  /**
2
3
  * Validate No Inline Types Executor
3
4
  *
@@ -78,40 +79,22 @@
78
79
  * - Third-party library APIs that expect inline types
79
80
  * - Legacy code being incrementally migrated
80
81
  */
81
-
82
- import { execSync } from 'child_process';
83
- import * as fs from 'fs';
84
- import * as path from 'path';
85
- import * as ts from 'typescript';
86
-
87
- export type NoInlineTypesMode = 'OFF' | 'NEW_METHODS' | 'NEW_AND_MODIFIED_METHODS' | 'MODIFIED_FILES';
88
-
89
- export interface ValidateNoInlineTypesOptions {
90
- mode?: NoInlineTypesMode;
91
- disableAllowed?: boolean;
92
- ignoreModifiedUntilEpoch?: number;
93
- }
94
-
95
- export interface ExecutorResult {
96
- success: boolean;
97
- }
98
-
99
- interface InlineTypeViolation {
100
- file: string;
101
- line: number;
102
- column: number;
103
- context: string;
104
- }
105
-
82
+ Object.defineProperty(exports, "__esModule", { value: true });
83
+ exports.default = runValidator;
84
+ const tslib_1 = require("tslib");
85
+ const child_process_1 = require("child_process");
86
+ const fs = tslib_1.__importStar(require("fs"));
87
+ const path = tslib_1.__importStar(require("path"));
88
+ const ts = tslib_1.__importStar(require("typescript"));
106
89
  /**
107
90
  * Get changed TypeScript files between base and head (or working tree if head not specified).
108
91
  */
109
92
  // webpieces-disable max-lines-new-methods -- Git command handling with untracked files requires multiple code paths
110
- function getChangedTypeScriptFiles(workspaceRoot: string, base: string, head?: string): string[] {
93
+ function getChangedTypeScriptFiles(workspaceRoot, base, head) {
111
94
  // eslint-disable-next-line @webpieces/no-unmanaged-exceptions
112
95
  try {
113
96
  const diffTarget = head ? `${base} ${head}` : base;
114
- const output = execSync(`git diff --name-only ${diffTarget} -- '*.ts' '*.tsx'`, {
97
+ const output = (0, child_process_1.execSync)(`git diff --name-only ${diffTarget} -- '*.ts' '*.tsx'`, {
115
98
  cwd: workspaceRoot,
116
99
  encoding: 'utf-8',
117
100
  });
@@ -119,11 +102,10 @@ function getChangedTypeScriptFiles(workspaceRoot: string, base: string, head?: s
119
102
  .trim()
120
103
  .split('\n')
121
104
  .filter((f) => f && !f.includes('.spec.ts') && !f.includes('.test.ts'));
122
-
123
105
  if (!head) {
124
106
  // eslint-disable-next-line @webpieces/no-unmanaged-exceptions
125
107
  try {
126
- const untrackedOutput = execSync(`git ls-files --others --exclude-standard '*.ts' '*.tsx'`, {
108
+ const untrackedOutput = (0, child_process_1.execSync)(`git ls-files --others --exclude-standard '*.ts' '*.tsx'`, {
127
109
  cwd: workspaceRoot,
128
110
  encoding: 'utf-8',
129
111
  });
@@ -133,39 +115,37 @@ function getChangedTypeScriptFiles(workspaceRoot: string, base: string, head?: s
133
115
  .filter((f) => f && !f.includes('.spec.ts') && !f.includes('.test.ts'));
134
116
  const allFiles = new Set([...changedFiles, ...untrackedFiles]);
135
117
  return Array.from(allFiles);
136
- } catch (err: unknown) {
118
+ }
119
+ catch (err) {
137
120
  //const error = toError(err);
138
121
  return changedFiles;
139
122
  }
140
123
  }
141
-
142
124
  return changedFiles;
143
- } catch (err: unknown) {
125
+ }
126
+ catch (err) {
144
127
  //const error = toError(err);
145
128
  return [];
146
129
  }
147
130
  }
148
-
149
131
  /**
150
132
  * Get the diff content for a specific file.
151
133
  */
152
- function getFileDiff(workspaceRoot: string, file: string, base: string, head?: string): string {
134
+ function getFileDiff(workspaceRoot, file, base, head) {
153
135
  // eslint-disable-next-line @webpieces/no-unmanaged-exceptions
154
136
  try {
155
137
  const diffTarget = head ? `${base} ${head}` : base;
156
- const diff = execSync(`git diff ${diffTarget} -- "${file}"`, {
138
+ const diff = (0, child_process_1.execSync)(`git diff ${diffTarget} -- "${file}"`, {
157
139
  cwd: workspaceRoot,
158
140
  encoding: 'utf-8',
159
141
  });
160
-
161
142
  if (!diff && !head) {
162
143
  const fullPath = path.join(workspaceRoot, file);
163
144
  if (fs.existsSync(fullPath)) {
164
- const isUntracked = execSync(`git ls-files --others --exclude-standard "${file}"`, {
145
+ const isUntracked = (0, child_process_1.execSync)(`git ls-files --others --exclude-standard "${file}"`, {
165
146
  cwd: workspaceRoot,
166
147
  encoding: 'utf-8',
167
148
  }).trim();
168
-
169
149
  if (isUntracked) {
170
150
  const content = fs.readFileSync(fullPath, 'utf-8');
171
151
  const lines = content.split('\n');
@@ -173,46 +153,43 @@ function getFileDiff(workspaceRoot: string, file: string, base: string, head?: s
173
153
  }
174
154
  }
175
155
  }
176
-
177
156
  return diff;
178
- } catch (err: unknown) {
157
+ }
158
+ catch (err) {
179
159
  //const error = toError(err);
180
160
  return '';
181
161
  }
182
162
  }
183
-
184
163
  /**
185
164
  * Parse diff to extract changed line numbers (both additions and modifications).
186
165
  */
187
- function getChangedLineNumbers(diffContent: string): Set<number> {
188
- const changedLines = new Set<number>();
166
+ function getChangedLineNumbers(diffContent) {
167
+ const changedLines = new Set();
189
168
  const lines = diffContent.split('\n');
190
169
  let currentLine = 0;
191
-
192
170
  for (const line of lines) {
193
171
  const hunkMatch = line.match(/^@@ -\d+(?:,\d+)? \+(\d+)(?:,\d+)? @@/);
194
172
  if (hunkMatch) {
195
173
  currentLine = parseInt(hunkMatch[1], 10);
196
174
  continue;
197
175
  }
198
-
199
176
  if (line.startsWith('+') && !line.startsWith('+++')) {
200
177
  changedLines.add(currentLine);
201
178
  currentLine++;
202
- } else if (line.startsWith('-') && !line.startsWith('---')) {
179
+ }
180
+ else if (line.startsWith('-') && !line.startsWith('---')) {
203
181
  // Deletions don't increment line number
204
- } else {
182
+ }
183
+ else {
205
184
  currentLine++;
206
185
  }
207
186
  }
208
-
209
187
  return changedLines;
210
188
  }
211
-
212
189
  /**
213
190
  * Check if a line contains a webpieces-disable comment for no-inline-types.
214
191
  */
215
- function hasDisableComment(lines: string[], lineNumber: number): boolean {
192
+ function hasDisableComment(lines, lineNumber) {
216
193
  const startCheck = Math.max(0, lineNumber - 5);
217
194
  for (let i = lineNumber - 2; i >= startCheck; i--) {
218
195
  const line = lines[i]?.trim() ?? '';
@@ -225,7 +202,6 @@ function hasDisableComment(lines: string[], lineNumber: number): boolean {
225
202
  }
226
203
  return false;
227
204
  }
228
-
229
205
  /**
230
206
  * Check if a TypeLiteral or TupleType node is in an allowed context.
231
207
  * Only allowed if the DIRECT parent is a TypeAliasDeclaration.
@@ -244,17 +220,16 @@ function hasDisableComment(lines: string[], lineNumber: number): boolean {
244
220
  * // webpieces-disable no-inline-types -- Prisma API requires inline type argument
245
221
  * type T = Prisma.GetPayload<{ include: {...} }>;
246
222
  */
247
- function isInAllowedContext(node: ts.TypeLiteralNode | ts.TupleTypeNode): boolean {
223
+ function isInAllowedContext(node) {
248
224
  const parent = node.parent;
249
- if (!parent) return false;
250
-
225
+ if (!parent)
226
+ return false;
251
227
  // Only allowed if it's the DIRECT body of a type alias
252
228
  if (ts.isTypeAliasDeclaration(parent)) {
253
229
  return true;
254
230
  }
255
231
  return false;
256
232
  }
257
-
258
233
  /**
259
234
  * Get a description of the context where the inline type or tuple appears.
260
235
  *
@@ -264,13 +239,12 @@ function isInAllowedContext(node: ts.TypeLiteralNode | ts.TupleTypeNode): boolea
264
239
  * - "inline type in generic argument"
265
240
  */
266
241
  // webpieces-disable max-lines-new-methods -- Context detection requires checking many AST node types
267
- function getViolationContext(node: ts.TypeLiteralNode | ts.TupleTypeNode, sourceFile: ts.SourceFile): string {
242
+ function getViolationContext(node, sourceFile) {
268
243
  // eslint-disable-next-line @webpieces/no-unmanaged-exceptions
269
244
  try {
270
245
  const isTuple = ts.isTupleTypeNode(node);
271
246
  const prefix = isTuple ? 'tuple' : 'inline';
272
-
273
- let current: ts.Node = node;
247
+ let current = node;
274
248
  while (current.parent) {
275
249
  const parent = current.parent;
276
250
  if (ts.isParameter(parent)) {
@@ -289,7 +263,7 @@ function getViolationContext(node: ts.TypeLiteralNode | ts.TupleTypeNode, source
289
263
  return `${prefix} property type`;
290
264
  }
291
265
  // Check if it's nested inside another type literal
292
- let ancestor: ts.Node | undefined = parent.parent;
266
+ let ancestor = parent.parent;
293
267
  while (ancestor) {
294
268
  if (ts.isTypeLiteralNode(ancestor)) {
295
269
  return `nested ${prefix} type`;
@@ -320,51 +294,44 @@ function getViolationContext(node: ts.TypeLiteralNode | ts.TupleTypeNode, source
320
294
  current = parent;
321
295
  }
322
296
  return isTuple ? 'tuple type' : 'inline type literal';
323
- } catch (err: unknown) {
297
+ }
298
+ catch (err) {
324
299
  //const error = toError(err);
325
300
  // Defensive: return generic context if AST traversal fails
326
301
  return ts.isTupleTypeNode(node) ? 'tuple type' : 'inline type literal';
327
302
  }
328
303
  }
329
-
330
- interface MethodInfo {
331
- name: string;
332
- startLine: number;
333
- endLine: number;
334
- }
335
-
336
304
  /**
337
305
  * Find all methods/functions in a file with their line ranges.
338
306
  */
339
307
  // webpieces-disable max-lines-new-methods -- AST traversal requires inline visitor function
340
- function findMethodsInFile(filePath: string, workspaceRoot: string): MethodInfo[] {
308
+ function findMethodsInFile(filePath, workspaceRoot) {
341
309
  const fullPath = path.join(workspaceRoot, filePath);
342
- if (!fs.existsSync(fullPath)) return [];
343
-
310
+ if (!fs.existsSync(fullPath))
311
+ return [];
344
312
  const content = fs.readFileSync(fullPath, 'utf-8');
345
313
  const sourceFile = ts.createSourceFile(filePath, content, ts.ScriptTarget.Latest, true);
346
-
347
- const methods: MethodInfo[] = [];
348
-
314
+ const methods = [];
349
315
  // webpieces-disable max-lines-new-methods -- AST visitor pattern requires handling multiple node types
350
- function visit(node: ts.Node): void {
351
- let methodName: string | undefined;
352
- let startLine: number | undefined;
353
- let endLine: number | undefined;
354
-
316
+ function visit(node) {
317
+ let methodName;
318
+ let startLine;
319
+ let endLine;
355
320
  if (ts.isMethodDeclaration(node) && node.name) {
356
321
  methodName = node.name.getText(sourceFile);
357
322
  const start = sourceFile.getLineAndCharacterOfPosition(node.getStart());
358
323
  const end = sourceFile.getLineAndCharacterOfPosition(node.getEnd());
359
324
  startLine = start.line + 1;
360
325
  endLine = end.line + 1;
361
- } else if (ts.isFunctionDeclaration(node) && node.name) {
326
+ }
327
+ else if (ts.isFunctionDeclaration(node) && node.name) {
362
328
  methodName = node.name.getText(sourceFile);
363
329
  const start = sourceFile.getLineAndCharacterOfPosition(node.getStart());
364
330
  const end = sourceFile.getLineAndCharacterOfPosition(node.getEnd());
365
331
  startLine = start.line + 1;
366
332
  endLine = end.line + 1;
367
- } else if (ts.isArrowFunction(node)) {
333
+ }
334
+ else if (ts.isArrowFunction(node)) {
368
335
  if (ts.isVariableDeclaration(node.parent) && ts.isIdentifier(node.parent.name)) {
369
336
  methodName = node.parent.name.getText(sourceFile);
370
337
  const start = sourceFile.getLineAndCharacterOfPosition(node.getStart());
@@ -373,27 +340,18 @@ function findMethodsInFile(filePath: string, workspaceRoot: string): MethodInfo[
373
340
  endLine = end.line + 1;
374
341
  }
375
342
  }
376
-
377
343
  if (methodName && startLine !== undefined && endLine !== undefined) {
378
344
  methods.push({ name: methodName, startLine, endLine });
379
345
  }
380
-
381
346
  ts.forEachChild(node, visit);
382
347
  }
383
-
384
348
  visit(sourceFile);
385
349
  return methods;
386
350
  }
387
-
388
351
  /**
389
352
  * Check if a line is within any method's range and if that method has changes.
390
353
  */
391
- function isLineInChangedMethod(
392
- line: number,
393
- methods: MethodInfo[],
394
- changedLines: Set<number>,
395
- newMethodNames: Set<string>
396
- ): boolean {
354
+ function isLineInChangedMethod(line, methods, changedLines, newMethodNames) {
397
355
  for (const method of methods) {
398
356
  if (line >= method.startLine && line <= method.endLine) {
399
357
  // Check if this method is new or has changes
@@ -410,11 +368,10 @@ function isLineInChangedMethod(
410
368
  }
411
369
  return false;
412
370
  }
413
-
414
371
  /**
415
372
  * Check if a line is within a new method.
416
373
  */
417
- function isLineInNewMethod(line: number, methods: MethodInfo[], newMethodNames: Set<string>): boolean {
374
+ function isLineInNewMethod(line, methods, newMethodNames) {
418
375
  for (const method of methods) {
419
376
  if (line >= method.startLine && line <= method.endLine && newMethodNames.has(method.name)) {
420
377
  return true;
@@ -422,21 +379,18 @@ function isLineInNewMethod(line: number, methods: MethodInfo[], newMethodNames:
422
379
  }
423
380
  return false;
424
381
  }
425
-
426
382
  /**
427
383
  * Parse diff to find newly added method signatures.
428
384
  */
429
- function findNewMethodSignaturesInDiff(diffContent: string): Set<string> {
430
- const newMethods = new Set<string>();
385
+ function findNewMethodSignaturesInDiff(diffContent) {
386
+ const newMethods = new Set();
431
387
  const lines = diffContent.split('\n');
432
-
433
388
  const patterns = [
434
389
  /^\+\s*(?:export\s+)?(?:async\s+)?function\s+(\w+)\s*\(/,
435
390
  /^\+\s*(?:export\s+)?(?:const|let)\s+(\w+)\s*=\s*(?:async\s*)?\(/,
436
391
  /^\+\s*(?:export\s+)?(?:const|let)\s+(\w+)\s*=\s*(?:async\s+)?function/,
437
392
  /^\+\s*(?:(?:public|private|protected)\s+)?(?:static\s+)?(?:async\s+)?(\w+)\s*\(/,
438
393
  ];
439
-
440
394
  for (const line of lines) {
441
395
  if (line.startsWith('+') && !line.startsWith('+++')) {
442
396
  for (const pattern of patterns) {
@@ -451,17 +405,8 @@ function findNewMethodSignaturesInDiff(diffContent: string): Set<string> {
451
405
  }
452
406
  }
453
407
  }
454
-
455
408
  return newMethods;
456
409
  }
457
-
458
- interface InlineTypeInfo {
459
- line: number;
460
- column: number;
461
- context: string;
462
- hasDisableComment: boolean;
463
- }
464
-
465
410
  /**
466
411
  * Find all inline type literals AND tuple types in a file.
467
412
  *
@@ -472,17 +417,15 @@ interface InlineTypeInfo {
472
417
  * Both are flagged unless they are the DIRECT body of a type alias.
473
418
  */
474
419
  // webpieces-disable max-lines-new-methods -- AST traversal with visitor pattern
475
- function findInlineTypesInFile(filePath: string, workspaceRoot: string): InlineTypeInfo[] {
420
+ function findInlineTypesInFile(filePath, workspaceRoot) {
476
421
  const fullPath = path.join(workspaceRoot, filePath);
477
- if (!fs.existsSync(fullPath)) return [];
478
-
422
+ if (!fs.existsSync(fullPath))
423
+ return [];
479
424
  const content = fs.readFileSync(fullPath, 'utf-8');
480
425
  const fileLines = content.split('\n');
481
426
  const sourceFile = ts.createSourceFile(filePath, content, ts.ScriptTarget.Latest, true);
482
-
483
- const inlineTypes: InlineTypeInfo[] = [];
484
-
485
- function visit(node: ts.Node): void {
427
+ const inlineTypes = [];
428
+ function visit(node) {
486
429
  // eslint-disable-next-line @webpieces/no-unmanaged-exceptions
487
430
  try {
488
431
  // Check for inline type literals: { x: number }
@@ -495,7 +438,6 @@ function findInlineTypesInFile(filePath: string, workspaceRoot: string): InlineT
495
438
  const column = pos.character + 1;
496
439
  const context = getViolationContext(node, sourceFile);
497
440
  const disabled = hasDisableComment(fileLines, line);
498
-
499
441
  inlineTypes.push({
500
442
  line,
501
443
  column,
@@ -505,7 +447,6 @@ function findInlineTypesInFile(filePath: string, workspaceRoot: string): InlineT
505
447
  }
506
448
  }
507
449
  }
508
-
509
450
  // Check for tuple types: [A, B]
510
451
  if (ts.isTupleTypeNode(node)) {
511
452
  if (!isInAllowedContext(node)) {
@@ -516,7 +457,6 @@ function findInlineTypesInFile(filePath: string, workspaceRoot: string): InlineT
516
457
  const column = pos.character + 1;
517
458
  const context = getViolationContext(node, sourceFile);
518
459
  const disabled = hasDisableComment(fileLines, line);
519
-
520
460
  inlineTypes.push({
521
461
  line,
522
462
  column,
@@ -526,44 +466,34 @@ function findInlineTypesInFile(filePath: string, workspaceRoot: string): InlineT
526
466
  }
527
467
  }
528
468
  }
529
- } catch (err: unknown) {
469
+ }
470
+ catch (err) {
530
471
  //const error = toError(err);
531
472
  // Skip nodes that cause errors during analysis
532
473
  }
533
-
534
474
  ts.forEachChild(node, visit);
535
475
  }
536
-
537
476
  visit(sourceFile);
538
477
  return inlineTypes;
539
478
  }
540
-
541
479
  /**
542
480
  * Find violations in new methods only (NEW_METHODS mode).
543
481
  */
544
482
  // webpieces-disable max-lines-new-methods -- File iteration with diff parsing and method matching
545
- function findViolationsForNewMethods(
546
- workspaceRoot: string,
547
- changedFiles: string[],
548
- base: string,
549
- head: string | undefined,
550
- disableAllowed: boolean
551
- ): InlineTypeViolation[] {
552
- const violations: InlineTypeViolation[] = [];
553
-
483
+ function findViolationsForNewMethods(workspaceRoot, changedFiles, base, head, disableAllowed) {
484
+ const violations = [];
554
485
  for (const file of changedFiles) {
555
486
  const diff = getFileDiff(workspaceRoot, file, base, head);
556
487
  const newMethodNames = findNewMethodSignaturesInDiff(diff);
557
-
558
- if (newMethodNames.size === 0) continue;
559
-
488
+ if (newMethodNames.size === 0)
489
+ continue;
560
490
  const methods = findMethodsInFile(file, workspaceRoot);
561
491
  const inlineTypes = findInlineTypesInFile(file, workspaceRoot);
562
-
563
492
  for (const inlineType of inlineTypes) {
564
- if (disableAllowed && inlineType.hasDisableComment) continue;
565
- if (!isLineInNewMethod(inlineType.line, methods, newMethodNames)) continue;
566
-
493
+ if (disableAllowed && inlineType.hasDisableComment)
494
+ continue;
495
+ if (!isLineInNewMethod(inlineType.line, methods, newMethodNames))
496
+ continue;
567
497
  violations.push({
568
498
  file,
569
499
  line: inlineType.line,
@@ -572,35 +502,25 @@ function findViolationsForNewMethods(
572
502
  });
573
503
  }
574
504
  }
575
-
576
505
  return violations;
577
506
  }
578
-
579
507
  /**
580
508
  * Find violations in new and modified methods (NEW_AND_MODIFIED_METHODS mode).
581
509
  */
582
510
  // webpieces-disable max-lines-new-methods -- Combines new method detection with change detection
583
- function findViolationsForModifiedAndNewMethods(
584
- workspaceRoot: string,
585
- changedFiles: string[],
586
- base: string,
587
- head: string | undefined,
588
- disableAllowed: boolean
589
- ): InlineTypeViolation[] {
590
- const violations: InlineTypeViolation[] = [];
591
-
511
+ function findViolationsForModifiedAndNewMethods(workspaceRoot, changedFiles, base, head, disableAllowed) {
512
+ const violations = [];
592
513
  for (const file of changedFiles) {
593
514
  const diff = getFileDiff(workspaceRoot, file, base, head);
594
515
  const newMethodNames = findNewMethodSignaturesInDiff(diff);
595
516
  const changedLines = getChangedLineNumbers(diff);
596
-
597
517
  const methods = findMethodsInFile(file, workspaceRoot);
598
518
  const inlineTypes = findInlineTypesInFile(file, workspaceRoot);
599
-
600
519
  for (const inlineType of inlineTypes) {
601
- if (disableAllowed && inlineType.hasDisableComment) continue;
602
- if (!isLineInChangedMethod(inlineType.line, methods, changedLines, newMethodNames)) continue;
603
-
520
+ if (disableAllowed && inlineType.hasDisableComment)
521
+ continue;
522
+ if (!isLineInChangedMethod(inlineType.line, methods, changedLines, newMethodNames))
523
+ continue;
604
524
  violations.push({
605
525
  file,
606
526
  line: inlineType.line,
@@ -609,22 +529,18 @@ function findViolationsForModifiedAndNewMethods(
609
529
  });
610
530
  }
611
531
  }
612
-
613
532
  return violations;
614
533
  }
615
-
616
534
  /**
617
535
  * Find all violations in modified files (MODIFIED_FILES mode).
618
536
  */
619
- function findViolationsForModifiedFiles(workspaceRoot: string, changedFiles: string[], disableAllowed: boolean): InlineTypeViolation[] {
620
- const violations: InlineTypeViolation[] = [];
621
-
537
+ function findViolationsForModifiedFiles(workspaceRoot, changedFiles, disableAllowed) {
538
+ const violations = [];
622
539
  for (const file of changedFiles) {
623
540
  const inlineTypes = findInlineTypesInFile(file, workspaceRoot);
624
-
625
541
  for (const inlineType of inlineTypes) {
626
- if (disableAllowed && inlineType.hasDisableComment) continue;
627
-
542
+ if (disableAllowed && inlineType.hasDisableComment)
543
+ continue;
628
544
  violations.push({
629
545
  file,
630
546
  line: inlineType.line,
@@ -633,50 +549,47 @@ function findViolationsForModifiedFiles(workspaceRoot: string, changedFiles: str
633
549
  });
634
550
  }
635
551
  }
636
-
637
552
  return violations;
638
553
  }
639
-
640
554
  /**
641
555
  * Auto-detect the base branch by finding the merge-base with origin/main.
642
556
  */
643
- function detectBase(workspaceRoot: string): string | null {
557
+ function detectBase(workspaceRoot) {
644
558
  // eslint-disable-next-line @webpieces/no-unmanaged-exceptions
645
559
  try {
646
- const mergeBase = execSync('git merge-base HEAD origin/main', {
560
+ const mergeBase = (0, child_process_1.execSync)('git merge-base HEAD origin/main', {
647
561
  cwd: workspaceRoot,
648
562
  encoding: 'utf-8',
649
563
  stdio: ['pipe', 'pipe', 'pipe'],
650
564
  }).trim();
651
-
652
565
  if (mergeBase) {
653
566
  return mergeBase;
654
567
  }
655
- } catch (err: unknown) {
568
+ }
569
+ catch (err) {
656
570
  //const error = toError(err);
657
571
  // eslint-disable-next-line @webpieces/no-unmanaged-exceptions
658
572
  try {
659
- const mergeBase = execSync('git merge-base HEAD main', {
573
+ const mergeBase = (0, child_process_1.execSync)('git merge-base HEAD main', {
660
574
  cwd: workspaceRoot,
661
575
  encoding: 'utf-8',
662
576
  stdio: ['pipe', 'pipe', 'pipe'],
663
577
  }).trim();
664
-
665
578
  if (mergeBase) {
666
579
  return mergeBase;
667
580
  }
668
- } catch (err2: unknown) {
581
+ }
582
+ catch (err2) {
669
583
  //const error2 = toError(err2);
670
584
  // Ignore
671
585
  }
672
586
  }
673
587
  return null;
674
588
  }
675
-
676
589
  /**
677
590
  * Report violations to console.
678
591
  */
679
- function reportViolations(violations: InlineTypeViolation[], mode: NoInlineTypesMode): void {
592
+ function reportViolations(violations, mode) {
680
593
  console.error('');
681
594
  console.error('❌ Inline type literals found! Use named types instead.');
682
595
  console.error('');
@@ -690,13 +603,11 @@ function reportViolations(violations: InlineTypeViolation[], mode: NoInlineTypes
690
603
  console.error(' GOOD: type MyData = { x: number };');
691
604
  console.error(' type Nullable = MyData | null;');
692
605
  console.error('');
693
-
694
606
  for (const v of violations) {
695
607
  console.error(` ❌ ${v.file}:${v.line}:${v.column}`);
696
608
  console.error(` ${v.context}`);
697
609
  }
698
610
  console.error('');
699
-
700
611
  console.error(' To fix: Extract inline types to named type aliases or interfaces');
701
612
  console.error('');
702
613
  console.error(' Escape hatch (use sparingly):');
@@ -705,12 +616,11 @@ function reportViolations(violations: InlineTypeViolation[], mode: NoInlineTypes
705
616
  console.error(` Current mode: ${mode}`);
706
617
  console.error('');
707
618
  }
708
-
709
619
  /**
710
620
  * Resolve mode considering ignoreModifiedUntilEpoch override.
711
621
  * When active, downgrades to OFF. When expired, logs a warning.
712
622
  */
713
- function resolveMode(normalMode: NoInlineTypesMode, epoch: number | undefined): NoInlineTypesMode {
623
+ function resolveMode(normalMode, epoch) {
714
624
  if (epoch === undefined || normalMode === 'OFF') {
715
625
  return normalMode;
716
626
  }
@@ -723,65 +633,50 @@ function resolveMode(normalMode: NoInlineTypesMode, epoch: number | undefined):
723
633
  }
724
634
  return normalMode;
725
635
  }
726
-
727
- export default async function runValidator(
728
- options: ValidateNoInlineTypesOptions,
729
- workspaceRoot: string
730
- ): Promise<ExecutorResult> {
731
- const mode: NoInlineTypesMode = resolveMode(options.mode ?? 'OFF', options.ignoreModifiedUntilEpoch);
636
+ async function runValidator(options, workspaceRoot) {
637
+ const mode = resolveMode(options.mode ?? 'OFF', options.ignoreModifiedUntilEpoch);
732
638
  const disableAllowed = options.disableAllowed ?? true;
733
-
734
639
  if (mode === 'OFF') {
735
640
  console.log('\n⏭️ Skipping no-inline-types validation (mode: OFF)');
736
641
  console.log('');
737
642
  return { success: true };
738
643
  }
739
-
740
644
  console.log('\n📏 Validating No Inline Types\n');
741
645
  console.log(` Mode: ${mode}`);
742
-
743
646
  let base = process.env['NX_BASE'];
744
647
  const head = process.env['NX_HEAD'];
745
-
746
648
  if (!base) {
747
649
  base = detectBase(workspaceRoot) ?? undefined;
748
-
749
650
  if (!base) {
750
651
  console.log('\n⏭️ Skipping no-inline-types validation (could not detect base branch)');
751
652
  console.log('');
752
653
  return { success: true };
753
654
  }
754
655
  }
755
-
756
656
  console.log(` Base: ${base}`);
757
657
  console.log(` Head: ${head ?? 'working tree (includes uncommitted changes)'}`);
758
658
  console.log('');
759
-
760
659
  const changedFiles = getChangedTypeScriptFiles(workspaceRoot, base, head);
761
-
762
660
  if (changedFiles.length === 0) {
763
661
  console.log('✅ No TypeScript files changed');
764
662
  return { success: true };
765
663
  }
766
-
767
664
  console.log(`📂 Checking ${changedFiles.length} changed file(s)...`);
768
-
769
- let violations: InlineTypeViolation[] = [];
770
-
665
+ let violations = [];
771
666
  if (mode === 'NEW_METHODS') {
772
667
  violations = findViolationsForNewMethods(workspaceRoot, changedFiles, base, head, disableAllowed);
773
- } else if (mode === 'NEW_AND_MODIFIED_METHODS') {
668
+ }
669
+ else if (mode === 'NEW_AND_MODIFIED_METHODS') {
774
670
  violations = findViolationsForModifiedAndNewMethods(workspaceRoot, changedFiles, base, head, disableAllowed);
775
- } else if (mode === 'MODIFIED_FILES') {
671
+ }
672
+ else if (mode === 'MODIFIED_FILES') {
776
673
  violations = findViolationsForModifiedFiles(workspaceRoot, changedFiles, disableAllowed);
777
674
  }
778
-
779
675
  if (violations.length === 0) {
780
676
  console.log('✅ No inline type literals found');
781
677
  return { success: true };
782
678
  }
783
-
784
679
  reportViolations(violations, mode);
785
-
786
680
  return { success: false };
787
681
  }
682
+ //# sourceMappingURL=validate-no-inline-types.js.map