@webpieces/dev-config 0.2.76 → 0.2.78

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 (36) hide show
  1. package/architecture/executors/validate-code/executor.d.ts +16 -6
  2. package/architecture/executors/validate-code/executor.js +109 -37
  3. package/architecture/executors/validate-code/executor.js.map +1 -1
  4. package/architecture/executors/validate-code/executor.ts +170 -55
  5. package/architecture/executors/validate-code/schema.json +56 -29
  6. package/architecture/executors/validate-modified-files/executor.d.ts +4 -3
  7. package/architecture/executors/validate-modified-files/executor.js +32 -30
  8. package/architecture/executors/validate-modified-files/executor.js.map +1 -1
  9. package/architecture/executors/validate-modified-files/executor.ts +36 -33
  10. package/architecture/executors/validate-modified-files/schema.json +9 -4
  11. package/architecture/executors/validate-modified-methods/executor.d.ts +7 -6
  12. package/architecture/executors/validate-modified-methods/executor.js +53 -47
  13. package/architecture/executors/validate-modified-methods/executor.js.map +1 -1
  14. package/architecture/executors/validate-modified-methods/executor.ts +57 -51
  15. package/architecture/executors/validate-modified-methods/schema.json +10 -5
  16. package/architecture/executors/validate-new-methods/executor.d.ts +4 -4
  17. package/architecture/executors/validate-new-methods/executor.js +64 -83
  18. package/architecture/executors/validate-new-methods/executor.js.map +1 -1
  19. package/architecture/executors/validate-new-methods/executor.ts +75 -96
  20. package/architecture/executors/validate-new-methods/schema.json +11 -10
  21. package/architecture/executors/validate-no-any-unknown/executor.d.ts +1 -2
  22. package/architecture/executors/validate-no-any-unknown/executor.js +57 -55
  23. package/architecture/executors/validate-no-any-unknown/executor.js.map +1 -1
  24. package/architecture/executors/validate-no-any-unknown/executor.ts +62 -57
  25. package/architecture/executors/validate-no-any-unknown/schema.json +2 -2
  26. package/architecture/executors/validate-no-inline-types/executor.d.ts +1 -2
  27. package/architecture/executors/validate-no-inline-types/executor.js +25 -58
  28. package/architecture/executors/validate-no-inline-types/executor.js.map +1 -1
  29. package/architecture/executors/validate-no-inline-types/executor.ts +26 -59
  30. package/architecture/executors/validate-no-inline-types/schema.json +2 -2
  31. package/architecture/executors/validate-return-types/executor.d.ts +1 -2
  32. package/architecture/executors/validate-return-types/executor.js +25 -58
  33. package/architecture/executors/validate-return-types/executor.js.map +1 -1
  34. package/architecture/executors/validate-return-types/executor.ts +26 -59
  35. package/architecture/executors/validate-return-types/schema.json +2 -2
  36. package/package.json +1 -1
@@ -2,13 +2,23 @@ import { ExecutorContext } from '@nx/devkit';
2
2
  import { ReturnTypeMode } from '../validate-return-types/executor';
3
3
  import { NoInlineTypesMode } from '../validate-no-inline-types/executor';
4
4
  import { NoAnyUnknownMode } from '../validate-no-any-unknown/executor';
5
- export type ValidationMode = 'STRICT' | 'NORMAL' | 'OFF';
5
+ export type MethodMaxLimitMode = 'OFF' | 'NEW_METHODS' | 'NEW_AND_MODIFIED_METHODS' | 'MODIFIED_FILES';
6
+ export type FileMaxLimitMode = 'OFF' | 'MODIFIED_FILES';
7
+ export interface MethodMaxLimitConfig {
8
+ limit?: number;
9
+ mode?: MethodMaxLimitMode;
10
+ disableAllowed?: boolean;
11
+ ignoreModifiedUntilEpoch?: number;
12
+ }
13
+ export interface FileMaxLimitConfig {
14
+ limit?: number;
15
+ mode?: FileMaxLimitMode;
16
+ disableAllowed?: boolean;
17
+ ignoreModifiedUntilEpoch?: number;
18
+ }
6
19
  export interface ValidateCodeOptions {
7
- mode?: ValidationMode;
8
- newMethodsMaxLines?: number;
9
- strictNewMethodMaxLines?: number;
10
- modifiedMethodsMaxLines?: number;
11
- modifiedFilesMaxLines?: number;
20
+ methodMaxLimit?: MethodMaxLimitConfig;
21
+ fileMaxLimit?: FileMaxLimitConfig;
12
22
  requireReturnTypeMode?: ReturnTypeMode;
13
23
  noInlineTypeLiteralsMode?: NoInlineTypesMode;
14
24
  noAnyUnknownMode?: NoAnyUnknownMode;
@@ -8,46 +8,118 @@ const executor_3 = tslib_1.__importDefault(require("../validate-modified-files/e
8
8
  const executor_4 = tslib_1.__importDefault(require("../validate-return-types/executor"));
9
9
  const executor_5 = tslib_1.__importDefault(require("../validate-no-inline-types/executor"));
10
10
  const executor_6 = tslib_1.__importDefault(require("../validate-no-any-unknown/executor"));
11
- async function runExecutor(options, context) {
12
- const mode = options.mode ?? 'NORMAL';
13
- if (mode === 'OFF') {
14
- console.log('\n⏭️ Skipping all code validations (validationMode: OFF)\n');
15
- return { success: true };
11
+ function formatEpochDate(epoch) {
12
+ return new Date(epoch * 1000).toISOString().split('T')[0];
13
+ }
14
+ function resolveMethodMode(normalMode, epoch) {
15
+ if (epoch === undefined) {
16
+ return { mode: normalMode, override: undefined };
17
+ }
18
+ const nowSeconds = Date.now() / 1000;
19
+ if (nowSeconds < epoch) {
20
+ // Active: downgrade to skip modified checking
21
+ const downgraded = normalMode === 'OFF' ? 'OFF' : 'NEW_METHODS';
22
+ return {
23
+ mode: downgraded,
24
+ override: { active: true, normalMode, expiresDate: formatEpochDate(epoch) },
25
+ };
26
+ }
27
+ // Expired
28
+ console.log(`\n\u26a0\ufe0f methodMaxLimit.ignoreModifiedUntilEpoch (${epoch}) has expired (${formatEpochDate(epoch)}). Remove it from nx.json. Using normal mode: ${normalMode}\n`);
29
+ return { mode: normalMode, override: undefined };
30
+ }
31
+ function resolveFileMode(normalMode, epoch) {
32
+ if (epoch === undefined) {
33
+ return { mode: normalMode, override: undefined };
34
+ }
35
+ const nowSeconds = Date.now() / 1000;
36
+ if (nowSeconds < epoch) {
37
+ // Active: file checking is inherently about modified files, so skip entirely
38
+ return {
39
+ mode: 'OFF',
40
+ override: { active: true, normalMode, expiresDate: formatEpochDate(epoch) },
41
+ };
42
+ }
43
+ // Expired
44
+ console.log(`\n\u26a0\ufe0f fileMaxLimit.ignoreModifiedUntilEpoch (${epoch}) has expired (${formatEpochDate(epoch)}). Remove it from nx.json. Using normal mode: ${normalMode}\n`);
45
+ return { mode: normalMode, override: undefined };
46
+ }
47
+ function parseConfig(options) {
48
+ const methodConfig = options.methodMaxLimit ?? {};
49
+ const fileConfig = options.fileMaxLimit ?? {};
50
+ const normalMethodMode = methodConfig.mode ?? 'NEW_AND_MODIFIED_METHODS';
51
+ const normalFileMode = fileConfig.mode ?? 'MODIFIED_FILES';
52
+ const methodResolved = resolveMethodMode(normalMethodMode, methodConfig.ignoreModifiedUntilEpoch);
53
+ const fileResolved = resolveFileMode(normalFileMode, fileConfig.ignoreModifiedUntilEpoch);
54
+ return {
55
+ methodLimit: methodConfig.limit ?? 80,
56
+ methodMode: methodResolved.mode,
57
+ methodDisableAllowed: methodConfig.disableAllowed ?? true,
58
+ methodOverride: methodResolved.override,
59
+ fileLimit: fileConfig.limit ?? 900,
60
+ fileMode: fileResolved.mode,
61
+ fileDisableAllowed: fileConfig.disableAllowed ?? true,
62
+ fileOverride: fileResolved.override,
63
+ returnTypeMode: options.requireReturnTypeMode ?? 'OFF',
64
+ noInlineTypesMode: options.noInlineTypeLiteralsMode ?? 'OFF',
65
+ noAnyUnknownMode: options.noAnyUnknownMode ?? 'OFF',
66
+ };
67
+ }
68
+ function formatOverride(override) {
69
+ if (!override) {
70
+ return '';
16
71
  }
17
- const returnTypeMode = options.requireReturnTypeMode ?? 'OFF';
18
- const noInlineTypesMode = options.noInlineTypeLiteralsMode ?? 'OFF';
19
- const noAnyUnknownMode = options.noAnyUnknownMode ?? 'OFF';
20
- console.log('\n📏 Running Code Validations\n');
21
- console.log(` Validation mode: ${mode}${mode === 'STRICT' ? ' (disable comments ignored for modified code)' : ''}`);
22
- console.log(` New methods max: ${options.newMethodsMaxLines ?? 30} lines (soft limit)`);
23
- if (options.strictNewMethodMaxLines) {
24
- console.log(` New methods max: ${options.strictNewMethodMaxLines} lines (hard limit, no escape)`);
25
- }
26
- console.log(` Modified methods max: ${options.modifiedMethodsMaxLines ?? 80} lines`);
27
- console.log(` Modified files max: ${options.modifiedFilesMaxLines ?? 900} lines`);
28
- console.log(` Require return types: ${returnTypeMode}`);
29
- console.log(` No inline type literals: ${noInlineTypesMode}`);
30
- console.log(` No any/unknown: ${noAnyUnknownMode}`);
72
+ return ` (override active, normal: ${override.normalMode}, expires: ${override.expiresDate})`;
73
+ }
74
+ function logConfig(config) {
75
+ console.log('\n\ud83d\udccf Running Code Validations\n');
76
+ console.log(` Method limits: mode=${config.methodMode}${formatOverride(config.methodOverride)}, limit=${config.methodLimit}, disableAllowed=${config.methodDisableAllowed}`);
77
+ console.log(` File limits: mode=${config.fileMode}${formatOverride(config.fileOverride)}, limit=${config.fileLimit}, disableAllowed=${config.fileDisableAllowed}`);
78
+ console.log(` Require return types: ${config.returnTypeMode}`);
79
+ console.log(` No inline type literals: ${config.noInlineTypesMode}`);
80
+ console.log(` No any/unknown: ${config.noAnyUnknownMode}`);
31
81
  console.log('');
32
- // Run all three validators sequentially to avoid interleaved output
33
- const newMethodsResult = await (0, executor_1.default)({ max: options.newMethodsMaxLines ?? 30, strictMax: options.strictNewMethodMaxLines, mode }, context);
34
- const modifiedMethodsResult = await (0, executor_2.default)({ max: options.modifiedMethodsMaxLines ?? 80, mode }, context);
35
- const modifiedFilesResult = await (0, executor_3.default)({ max: options.modifiedFilesMaxLines ?? 900, mode }, context);
36
- const returnTypesResult = await (0, executor_4.default)({ mode: returnTypeMode }, context);
37
- const noInlineTypesResult = await (0, executor_5.default)({ mode: noInlineTypesMode }, context);
38
- const noAnyUnknownResult = await (0, executor_6.default)({ mode: noAnyUnknownMode }, context);
39
- const allSuccess = newMethodsResult.success &&
40
- modifiedMethodsResult.success &&
41
- modifiedFilesResult.success &&
42
- returnTypesResult.success &&
43
- noInlineTypesResult.success &&
44
- noAnyUnknownResult.success;
45
- if (allSuccess) {
46
- console.log('\n✅ All code validations passed\n');
47
- }
48
- else {
49
- console.log('\n❌ Some code validations failed\n');
82
+ }
83
+ function isAllOff(config) {
84
+ return config.methodMode === 'OFF' && config.fileMode === 'OFF' &&
85
+ config.returnTypeMode === 'OFF' && config.noInlineTypesMode === 'OFF' &&
86
+ config.noAnyUnknownMode === 'OFF';
87
+ }
88
+ async function runMethodValidators(config, context) {
89
+ const results = [];
90
+ const runNew = config.methodMode === 'NEW_METHODS' || config.methodMode === 'NEW_AND_MODIFIED_METHODS';
91
+ const runModified = config.methodMode === 'NEW_AND_MODIFIED_METHODS' || config.methodMode === 'MODIFIED_FILES';
92
+ if (runNew) {
93
+ results.push(await (0, executor_1.default)({
94
+ limit: config.methodLimit,
95
+ mode: config.methodMode, disableAllowed: config.methodDisableAllowed,
96
+ }, context));
97
+ }
98
+ if (runModified) {
99
+ results.push(await (0, executor_2.default)({
100
+ limit: config.methodLimit, mode: config.methodMode, disableAllowed: config.methodDisableAllowed,
101
+ }, context));
102
+ }
103
+ return results;
104
+ }
105
+ async function runExecutor(options, context) {
106
+ const config = parseConfig(options);
107
+ if (isAllOff(config)) {
108
+ console.log('\n\u23ed\ufe0f Skipping all code validations (all modes: OFF)\n');
109
+ return { success: true };
50
110
  }
111
+ logConfig(config);
112
+ const methodResults = await runMethodValidators(config, context);
113
+ const fileResult = await (0, executor_3.default)({
114
+ limit: config.fileLimit, mode: config.fileMode, disableAllowed: config.fileDisableAllowed,
115
+ }, context);
116
+ const returnTypesResult = await (0, executor_4.default)({ mode: config.returnTypeMode }, context);
117
+ const noInlineTypesResult = await (0, executor_5.default)({ mode: config.noInlineTypesMode }, context);
118
+ const noAnyUnknownResult = await (0, executor_6.default)({ mode: config.noAnyUnknownMode }, context);
119
+ const allSuccess = methodResults.every((r) => r.success) &&
120
+ fileResult.success && returnTypesResult.success &&
121
+ noInlineTypesResult.success && noAnyUnknownResult.success;
122
+ console.log(allSuccess ? '\n\u2705 All code validations passed\n' : '\n\u274c Some code validations failed\n');
51
123
  return { success: allSuccess };
52
124
  }
53
125
  //# sourceMappingURL=executor.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"executor.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/dev-config/architecture/executors/validate-code/executor.ts"],"names":[],"mappings":"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","sourcesContent":["import { ExecutorContext } from '@nx/devkit';\nimport runNewMethodsExecutor from '../validate-new-methods/executor';\nimport runModifiedMethodsExecutor from '../validate-modified-methods/executor';\nimport runModifiedFilesExecutor from '../validate-modified-files/executor';\nimport runReturnTypesExecutor, { ReturnTypeMode } from '../validate-return-types/executor';\nimport runNoInlineTypesExecutor, { NoInlineTypesMode } from '../validate-no-inline-types/executor';\nimport runNoAnyUnknownExecutor, { NoAnyUnknownMode } from '../validate-no-any-unknown/executor';\n\nexport type ValidationMode = 'STRICT' | 'NORMAL' | 'OFF';\n\nexport interface ValidateCodeOptions {\n mode?: ValidationMode;\n newMethodsMaxLines?: number;\n strictNewMethodMaxLines?: number;\n modifiedMethodsMaxLines?: number;\n modifiedFilesMaxLines?: number;\n requireReturnTypeMode?: ReturnTypeMode;\n noInlineTypeLiteralsMode?: NoInlineTypesMode;\n noAnyUnknownMode?: NoAnyUnknownMode;\n}\n\nexport interface ExecutorResult {\n success: boolean;\n}\n\nexport default async function runExecutor(\n options: ValidateCodeOptions,\n context: ExecutorContext\n): Promise<ExecutorResult> {\n const mode: ValidationMode = options.mode ?? 'NORMAL';\n\n if (mode === 'OFF') {\n console.log('\\n⏭️ Skipping all code validations (validationMode: OFF)\\n');\n return { success: true };\n }\n\n const returnTypeMode: ReturnTypeMode = options.requireReturnTypeMode ?? 'OFF';\n const noInlineTypesMode: NoInlineTypesMode = options.noInlineTypeLiteralsMode ?? 'OFF';\n const noAnyUnknownMode: NoAnyUnknownMode = options.noAnyUnknownMode ?? 'OFF';\n\n console.log('\\n📏 Running Code Validations\\n');\n console.log(` Validation mode: ${mode}${mode === 'STRICT' ? ' (disable comments ignored for modified code)' : ''}`);\n console.log(` New methods max: ${options.newMethodsMaxLines ?? 30} lines (soft limit)`);\n if (options.strictNewMethodMaxLines) {\n console.log(` New methods max: ${options.strictNewMethodMaxLines} lines (hard limit, no escape)`);\n }\n console.log(` Modified methods max: ${options.modifiedMethodsMaxLines ?? 80} lines`);\n console.log(` Modified files max: ${options.modifiedFilesMaxLines ?? 900} lines`);\n console.log(` Require return types: ${returnTypeMode}`);\n console.log(` No inline type literals: ${noInlineTypesMode}`);\n console.log(` No any/unknown: ${noAnyUnknownMode}`);\n console.log('');\n\n // Run all three validators sequentially to avoid interleaved output\n const newMethodsResult = await runNewMethodsExecutor(\n { max: options.newMethodsMaxLines ?? 30, strictMax: options.strictNewMethodMaxLines, mode },\n context\n );\n\n const modifiedMethodsResult = await runModifiedMethodsExecutor(\n { max: options.modifiedMethodsMaxLines ?? 80, mode },\n context\n );\n\n const modifiedFilesResult = await runModifiedFilesExecutor(\n { max: options.modifiedFilesMaxLines ?? 900, mode },\n context\n );\n\n const returnTypesResult = await runReturnTypesExecutor({ mode: returnTypeMode }, context);\n\n const noInlineTypesResult = await runNoInlineTypesExecutor({ mode: noInlineTypesMode }, context);\n\n const noAnyUnknownResult = await runNoAnyUnknownExecutor({ mode: noAnyUnknownMode }, context);\n\n const allSuccess =\n newMethodsResult.success &&\n modifiedMethodsResult.success &&\n modifiedFilesResult.success &&\n returnTypesResult.success &&\n noInlineTypesResult.success &&\n noAnyUnknownResult.success;\n\n if (allSuccess) {\n console.log('\\n✅ All code validations passed\\n');\n } else {\n console.log('\\n❌ Some code validations failed\\n');\n }\n\n return { success: allSuccess };\n}\n"]}
1
+ {"version":3,"file":"executor.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/dev-config/architecture/executors/validate-code/executor.ts"],"names":[],"mappings":"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","sourcesContent":["import { ExecutorContext } from '@nx/devkit';\nimport runNewMethodsExecutor from '../validate-new-methods/executor';\nimport runModifiedMethodsExecutor from '../validate-modified-methods/executor';\nimport runModifiedFilesExecutor from '../validate-modified-files/executor';\nimport runReturnTypesExecutor, { ReturnTypeMode } from '../validate-return-types/executor';\nimport runNoInlineTypesExecutor, { NoInlineTypesMode } from '../validate-no-inline-types/executor';\nimport runNoAnyUnknownExecutor, { NoAnyUnknownMode } from '../validate-no-any-unknown/executor';\n\nexport type MethodMaxLimitMode = 'OFF' | 'NEW_METHODS' | 'NEW_AND_MODIFIED_METHODS' | 'MODIFIED_FILES';\nexport type FileMaxLimitMode = 'OFF' | 'MODIFIED_FILES';\n\nexport interface MethodMaxLimitConfig {\n limit?: number;\n mode?: MethodMaxLimitMode;\n disableAllowed?: boolean;\n ignoreModifiedUntilEpoch?: number;\n}\n\nexport interface FileMaxLimitConfig {\n limit?: number;\n mode?: FileMaxLimitMode;\n disableAllowed?: boolean;\n ignoreModifiedUntilEpoch?: number;\n}\n\nexport interface ValidateCodeOptions {\n methodMaxLimit?: MethodMaxLimitConfig;\n fileMaxLimit?: FileMaxLimitConfig;\n requireReturnTypeMode?: ReturnTypeMode;\n noInlineTypeLiteralsMode?: NoInlineTypesMode;\n noAnyUnknownMode?: NoAnyUnknownMode;\n}\n\nexport interface ExecutorResult {\n success: boolean;\n}\n\ninterface OverrideInfo {\n active: boolean;\n normalMode: string;\n expiresDate: string;\n}\n\ninterface ParsedConfig {\n methodLimit: number;\n methodMode: MethodMaxLimitMode;\n methodDisableAllowed: boolean;\n methodOverride: OverrideInfo | undefined;\n fileLimit: number;\n fileMode: FileMaxLimitMode;\n fileDisableAllowed: boolean;\n fileOverride: OverrideInfo | undefined;\n returnTypeMode: ReturnTypeMode;\n noInlineTypesMode: NoInlineTypesMode;\n noAnyUnknownMode: NoAnyUnknownMode;\n}\n\ninterface ResolvedMethodMode {\n mode: MethodMaxLimitMode;\n override: OverrideInfo | undefined;\n}\n\ninterface ResolvedFileMode {\n mode: FileMaxLimitMode;\n override: OverrideInfo | undefined;\n}\n\nfunction formatEpochDate(epoch: number): string {\n return new Date(epoch * 1000).toISOString().split('T')[0];\n}\n\nfunction resolveMethodMode(\n normalMode: MethodMaxLimitMode, epoch: number | undefined\n): ResolvedMethodMode {\n if (epoch === undefined) {\n return { mode: normalMode, override: undefined };\n }\n const nowSeconds = Date.now() / 1000;\n if (nowSeconds < epoch) {\n // Active: downgrade to skip modified checking\n const downgraded: MethodMaxLimitMode =\n normalMode === 'OFF' ? 'OFF' : 'NEW_METHODS';\n return {\n mode: downgraded,\n override: { active: true, normalMode, expiresDate: formatEpochDate(epoch) },\n };\n }\n // Expired\n console.log(`\\n\\u26a0\\ufe0f methodMaxLimit.ignoreModifiedUntilEpoch (${epoch}) has expired (${formatEpochDate(epoch)}). Remove it from nx.json. Using normal mode: ${normalMode}\\n`);\n return { mode: normalMode, override: undefined };\n}\n\nfunction resolveFileMode(\n normalMode: FileMaxLimitMode, epoch: number | undefined\n): ResolvedFileMode {\n if (epoch === undefined) {\n return { mode: normalMode, override: undefined };\n }\n const nowSeconds = Date.now() / 1000;\n if (nowSeconds < epoch) {\n // Active: file checking is inherently about modified files, so skip entirely\n return {\n mode: 'OFF',\n override: { active: true, normalMode, expiresDate: formatEpochDate(epoch) },\n };\n }\n // Expired\n console.log(`\\n\\u26a0\\ufe0f fileMaxLimit.ignoreModifiedUntilEpoch (${epoch}) has expired (${formatEpochDate(epoch)}). Remove it from nx.json. Using normal mode: ${normalMode}\\n`);\n return { mode: normalMode, override: undefined };\n}\n\nfunction parseConfig(options: ValidateCodeOptions): ParsedConfig {\n const methodConfig: MethodMaxLimitConfig = options.methodMaxLimit ?? {};\n const fileConfig: FileMaxLimitConfig = options.fileMaxLimit ?? {};\n\n const normalMethodMode = methodConfig.mode ?? 'NEW_AND_MODIFIED_METHODS';\n const normalFileMode = fileConfig.mode ?? 'MODIFIED_FILES';\n\n const methodResolved = resolveMethodMode(normalMethodMode, methodConfig.ignoreModifiedUntilEpoch);\n const fileResolved = resolveFileMode(normalFileMode, fileConfig.ignoreModifiedUntilEpoch);\n\n return {\n methodLimit: methodConfig.limit ?? 80,\n methodMode: methodResolved.mode,\n methodDisableAllowed: methodConfig.disableAllowed ?? true,\n methodOverride: methodResolved.override,\n fileLimit: fileConfig.limit ?? 900,\n fileMode: fileResolved.mode,\n fileDisableAllowed: fileConfig.disableAllowed ?? true,\n fileOverride: fileResolved.override,\n returnTypeMode: options.requireReturnTypeMode ?? 'OFF',\n noInlineTypesMode: options.noInlineTypeLiteralsMode ?? 'OFF',\n noAnyUnknownMode: options.noAnyUnknownMode ?? 'OFF',\n };\n}\n\nfunction formatOverride(override: OverrideInfo | undefined): string {\n if (!override) {\n return '';\n }\n return ` (override active, normal: ${override.normalMode}, expires: ${override.expiresDate})`;\n}\n\nfunction logConfig(config: ParsedConfig): void {\n console.log('\\n\\ud83d\\udccf Running Code Validations\\n');\n console.log(` Method limits: mode=${config.methodMode}${formatOverride(config.methodOverride)}, limit=${config.methodLimit}, disableAllowed=${config.methodDisableAllowed}`);\n console.log(` File limits: mode=${config.fileMode}${formatOverride(config.fileOverride)}, limit=${config.fileLimit}, disableAllowed=${config.fileDisableAllowed}`);\n console.log(` Require return types: ${config.returnTypeMode}`);\n console.log(` No inline type literals: ${config.noInlineTypesMode}`);\n console.log(` No any/unknown: ${config.noAnyUnknownMode}`);\n console.log('');\n}\n\nfunction isAllOff(config: ParsedConfig): boolean {\n return config.methodMode === 'OFF' && config.fileMode === 'OFF' &&\n config.returnTypeMode === 'OFF' && config.noInlineTypesMode === 'OFF' &&\n config.noAnyUnknownMode === 'OFF';\n}\n\nasync function runMethodValidators(config: ParsedConfig, context: ExecutorContext): Promise<ExecutorResult[]> {\n const results: ExecutorResult[] = [];\n const runNew = config.methodMode === 'NEW_METHODS' || config.methodMode === 'NEW_AND_MODIFIED_METHODS';\n const runModified = config.methodMode === 'NEW_AND_MODIFIED_METHODS' || config.methodMode === 'MODIFIED_FILES';\n\n if (runNew) {\n results.push(await runNewMethodsExecutor({\n limit: config.methodLimit,\n mode: config.methodMode, disableAllowed: config.methodDisableAllowed,\n }, context));\n }\n if (runModified) {\n results.push(await runModifiedMethodsExecutor({\n limit: config.methodLimit, mode: config.methodMode, disableAllowed: config.methodDisableAllowed,\n }, context));\n }\n return results;\n}\n\nexport default async function runExecutor(\n options: ValidateCodeOptions,\n context: ExecutorContext\n): Promise<ExecutorResult> {\n const config = parseConfig(options);\n\n if (isAllOff(config)) {\n console.log('\\n\\u23ed\\ufe0f Skipping all code validations (all modes: OFF)\\n');\n return { success: true };\n }\n\n logConfig(config);\n\n const methodResults = await runMethodValidators(config, context);\n const fileResult = await runModifiedFilesExecutor({\n limit: config.fileLimit, mode: config.fileMode, disableAllowed: config.fileDisableAllowed,\n }, context);\n const returnTypesResult = await runReturnTypesExecutor({ mode: config.returnTypeMode }, context);\n const noInlineTypesResult = await runNoInlineTypesExecutor({ mode: config.noInlineTypesMode }, context);\n const noAnyUnknownResult = await runNoAnyUnknownExecutor({ mode: config.noAnyUnknownMode }, context);\n\n const allSuccess = methodResults.every((r) => r.success) &&\n fileResult.success && returnTypesResult.success &&\n noInlineTypesResult.success && noAnyUnknownResult.success;\n\n console.log(allSuccess ? '\\n\\u2705 All code validations passed\\n' : '\\n\\u274c Some code validations failed\\n');\n return { success: allSuccess };\n}\n"]}
@@ -6,14 +6,26 @@ import runReturnTypesExecutor, { ReturnTypeMode } from '../validate-return-types
6
6
  import runNoInlineTypesExecutor, { NoInlineTypesMode } from '../validate-no-inline-types/executor';
7
7
  import runNoAnyUnknownExecutor, { NoAnyUnknownMode } from '../validate-no-any-unknown/executor';
8
8
 
9
- export type ValidationMode = 'STRICT' | 'NORMAL' | 'OFF';
9
+ export type MethodMaxLimitMode = 'OFF' | 'NEW_METHODS' | 'NEW_AND_MODIFIED_METHODS' | 'MODIFIED_FILES';
10
+ export type FileMaxLimitMode = 'OFF' | 'MODIFIED_FILES';
11
+
12
+ export interface MethodMaxLimitConfig {
13
+ limit?: number;
14
+ mode?: MethodMaxLimitMode;
15
+ disableAllowed?: boolean;
16
+ ignoreModifiedUntilEpoch?: number;
17
+ }
18
+
19
+ export interface FileMaxLimitConfig {
20
+ limit?: number;
21
+ mode?: FileMaxLimitMode;
22
+ disableAllowed?: boolean;
23
+ ignoreModifiedUntilEpoch?: number;
24
+ }
10
25
 
11
26
  export interface ValidateCodeOptions {
12
- mode?: ValidationMode;
13
- newMethodsMaxLines?: number;
14
- strictNewMethodMaxLines?: number;
15
- modifiedMethodsMaxLines?: number;
16
- modifiedFilesMaxLines?: number;
27
+ methodMaxLimit?: MethodMaxLimitConfig;
28
+ fileMaxLimit?: FileMaxLimitConfig;
17
29
  requireReturnTypeMode?: ReturnTypeMode;
18
30
  noInlineTypeLiteralsMode?: NoInlineTypesMode;
19
31
  noAnyUnknownMode?: NoAnyUnknownMode;
@@ -23,69 +35,172 @@ export interface ExecutorResult {
23
35
  success: boolean;
24
36
  }
25
37
 
26
- export default async function runExecutor(
27
- options: ValidateCodeOptions,
28
- context: ExecutorContext
29
- ): Promise<ExecutorResult> {
30
- const mode: ValidationMode = options.mode ?? 'NORMAL';
38
+ interface OverrideInfo {
39
+ active: boolean;
40
+ normalMode: string;
41
+ expiresDate: string;
42
+ }
31
43
 
32
- if (mode === 'OFF') {
33
- console.log('\n⏭️ Skipping all code validations (validationMode: OFF)\n');
34
- return { success: true };
44
+ interface ParsedConfig {
45
+ methodLimit: number;
46
+ methodMode: MethodMaxLimitMode;
47
+ methodDisableAllowed: boolean;
48
+ methodOverride: OverrideInfo | undefined;
49
+ fileLimit: number;
50
+ fileMode: FileMaxLimitMode;
51
+ fileDisableAllowed: boolean;
52
+ fileOverride: OverrideInfo | undefined;
53
+ returnTypeMode: ReturnTypeMode;
54
+ noInlineTypesMode: NoInlineTypesMode;
55
+ noAnyUnknownMode: NoAnyUnknownMode;
56
+ }
57
+
58
+ interface ResolvedMethodMode {
59
+ mode: MethodMaxLimitMode;
60
+ override: OverrideInfo | undefined;
61
+ }
62
+
63
+ interface ResolvedFileMode {
64
+ mode: FileMaxLimitMode;
65
+ override: OverrideInfo | undefined;
66
+ }
67
+
68
+ function formatEpochDate(epoch: number): string {
69
+ return new Date(epoch * 1000).toISOString().split('T')[0];
70
+ }
71
+
72
+ function resolveMethodMode(
73
+ normalMode: MethodMaxLimitMode, epoch: number | undefined
74
+ ): ResolvedMethodMode {
75
+ if (epoch === undefined) {
76
+ return { mode: normalMode, override: undefined };
77
+ }
78
+ const nowSeconds = Date.now() / 1000;
79
+ if (nowSeconds < epoch) {
80
+ // Active: downgrade to skip modified checking
81
+ const downgraded: MethodMaxLimitMode =
82
+ normalMode === 'OFF' ? 'OFF' : 'NEW_METHODS';
83
+ return {
84
+ mode: downgraded,
85
+ override: { active: true, normalMode, expiresDate: formatEpochDate(epoch) },
86
+ };
87
+ }
88
+ // Expired
89
+ console.log(`\n\u26a0\ufe0f methodMaxLimit.ignoreModifiedUntilEpoch (${epoch}) has expired (${formatEpochDate(epoch)}). Remove it from nx.json. Using normal mode: ${normalMode}\n`);
90
+ return { mode: normalMode, override: undefined };
91
+ }
92
+
93
+ function resolveFileMode(
94
+ normalMode: FileMaxLimitMode, epoch: number | undefined
95
+ ): ResolvedFileMode {
96
+ if (epoch === undefined) {
97
+ return { mode: normalMode, override: undefined };
98
+ }
99
+ const nowSeconds = Date.now() / 1000;
100
+ if (nowSeconds < epoch) {
101
+ // Active: file checking is inherently about modified files, so skip entirely
102
+ return {
103
+ mode: 'OFF',
104
+ override: { active: true, normalMode, expiresDate: formatEpochDate(epoch) },
105
+ };
35
106
  }
107
+ // Expired
108
+ console.log(`\n\u26a0\ufe0f fileMaxLimit.ignoreModifiedUntilEpoch (${epoch}) has expired (${formatEpochDate(epoch)}). Remove it from nx.json. Using normal mode: ${normalMode}\n`);
109
+ return { mode: normalMode, override: undefined };
110
+ }
36
111
 
37
- const returnTypeMode: ReturnTypeMode = options.requireReturnTypeMode ?? 'OFF';
38
- const noInlineTypesMode: NoInlineTypesMode = options.noInlineTypeLiteralsMode ?? 'OFF';
39
- const noAnyUnknownMode: NoAnyUnknownMode = options.noAnyUnknownMode ?? 'OFF';
112
+ function parseConfig(options: ValidateCodeOptions): ParsedConfig {
113
+ const methodConfig: MethodMaxLimitConfig = options.methodMaxLimit ?? {};
114
+ const fileConfig: FileMaxLimitConfig = options.fileMaxLimit ?? {};
115
+
116
+ const normalMethodMode = methodConfig.mode ?? 'NEW_AND_MODIFIED_METHODS';
117
+ const normalFileMode = fileConfig.mode ?? 'MODIFIED_FILES';
118
+
119
+ const methodResolved = resolveMethodMode(normalMethodMode, methodConfig.ignoreModifiedUntilEpoch);
120
+ const fileResolved = resolveFileMode(normalFileMode, fileConfig.ignoreModifiedUntilEpoch);
121
+
122
+ return {
123
+ methodLimit: methodConfig.limit ?? 80,
124
+ methodMode: methodResolved.mode,
125
+ methodDisableAllowed: methodConfig.disableAllowed ?? true,
126
+ methodOverride: methodResolved.override,
127
+ fileLimit: fileConfig.limit ?? 900,
128
+ fileMode: fileResolved.mode,
129
+ fileDisableAllowed: fileConfig.disableAllowed ?? true,
130
+ fileOverride: fileResolved.override,
131
+ returnTypeMode: options.requireReturnTypeMode ?? 'OFF',
132
+ noInlineTypesMode: options.noInlineTypeLiteralsMode ?? 'OFF',
133
+ noAnyUnknownMode: options.noAnyUnknownMode ?? 'OFF',
134
+ };
135
+ }
40
136
 
41
- console.log('\n📏 Running Code Validations\n');
42
- console.log(` Validation mode: ${mode}${mode === 'STRICT' ? ' (disable comments ignored for modified code)' : ''}`);
43
- console.log(` New methods max: ${options.newMethodsMaxLines ?? 30} lines (soft limit)`);
44
- if (options.strictNewMethodMaxLines) {
45
- console.log(` New methods max: ${options.strictNewMethodMaxLines} lines (hard limit, no escape)`);
137
+ function formatOverride(override: OverrideInfo | undefined): string {
138
+ if (!override) {
139
+ return '';
46
140
  }
47
- console.log(` Modified methods max: ${options.modifiedMethodsMaxLines ?? 80} lines`);
48
- console.log(` Modified files max: ${options.modifiedFilesMaxLines ?? 900} lines`);
49
- console.log(` Require return types: ${returnTypeMode}`);
50
- console.log(` No inline type literals: ${noInlineTypesMode}`);
51
- console.log(` No any/unknown: ${noAnyUnknownMode}`);
141
+ return ` (override active, normal: ${override.normalMode}, expires: ${override.expiresDate})`;
142
+ }
143
+
144
+ function logConfig(config: ParsedConfig): void {
145
+ console.log('\n\ud83d\udccf Running Code Validations\n');
146
+ console.log(` Method limits: mode=${config.methodMode}${formatOverride(config.methodOverride)}, limit=${config.methodLimit}, disableAllowed=${config.methodDisableAllowed}`);
147
+ console.log(` File limits: mode=${config.fileMode}${formatOverride(config.fileOverride)}, limit=${config.fileLimit}, disableAllowed=${config.fileDisableAllowed}`);
148
+ console.log(` Require return types: ${config.returnTypeMode}`);
149
+ console.log(` No inline type literals: ${config.noInlineTypesMode}`);
150
+ console.log(` No any/unknown: ${config.noAnyUnknownMode}`);
52
151
  console.log('');
152
+ }
53
153
 
54
- // Run all three validators sequentially to avoid interleaved output
55
- const newMethodsResult = await runNewMethodsExecutor(
56
- { max: options.newMethodsMaxLines ?? 30, strictMax: options.strictNewMethodMaxLines, mode },
57
- context
58
- );
154
+ function isAllOff(config: ParsedConfig): boolean {
155
+ return config.methodMode === 'OFF' && config.fileMode === 'OFF' &&
156
+ config.returnTypeMode === 'OFF' && config.noInlineTypesMode === 'OFF' &&
157
+ config.noAnyUnknownMode === 'OFF';
158
+ }
59
159
 
60
- const modifiedMethodsResult = await runModifiedMethodsExecutor(
61
- { max: options.modifiedMethodsMaxLines ?? 80, mode },
62
- context
63
- );
160
+ async function runMethodValidators(config: ParsedConfig, context: ExecutorContext): Promise<ExecutorResult[]> {
161
+ const results: ExecutorResult[] = [];
162
+ const runNew = config.methodMode === 'NEW_METHODS' || config.methodMode === 'NEW_AND_MODIFIED_METHODS';
163
+ const runModified = config.methodMode === 'NEW_AND_MODIFIED_METHODS' || config.methodMode === 'MODIFIED_FILES';
64
164
 
65
- const modifiedFilesResult = await runModifiedFilesExecutor(
66
- { max: options.modifiedFilesMaxLines ?? 900, mode },
67
- context
68
- );
165
+ if (runNew) {
166
+ results.push(await runNewMethodsExecutor({
167
+ limit: config.methodLimit,
168
+ mode: config.methodMode, disableAllowed: config.methodDisableAllowed,
169
+ }, context));
170
+ }
171
+ if (runModified) {
172
+ results.push(await runModifiedMethodsExecutor({
173
+ limit: config.methodLimit, mode: config.methodMode, disableAllowed: config.methodDisableAllowed,
174
+ }, context));
175
+ }
176
+ return results;
177
+ }
69
178
 
70
- const returnTypesResult = await runReturnTypesExecutor({ mode: returnTypeMode }, context);
179
+ export default async function runExecutor(
180
+ options: ValidateCodeOptions,
181
+ context: ExecutorContext
182
+ ): Promise<ExecutorResult> {
183
+ const config = parseConfig(options);
71
184
 
72
- const noInlineTypesResult = await runNoInlineTypesExecutor({ mode: noInlineTypesMode }, context);
185
+ if (isAllOff(config)) {
186
+ console.log('\n\u23ed\ufe0f Skipping all code validations (all modes: OFF)\n');
187
+ return { success: true };
188
+ }
73
189
 
74
- const noAnyUnknownResult = await runNoAnyUnknownExecutor({ mode: noAnyUnknownMode }, context);
190
+ logConfig(config);
75
191
 
76
- const allSuccess =
77
- newMethodsResult.success &&
78
- modifiedMethodsResult.success &&
79
- modifiedFilesResult.success &&
80
- returnTypesResult.success &&
81
- noInlineTypesResult.success &&
82
- noAnyUnknownResult.success;
192
+ const methodResults = await runMethodValidators(config, context);
193
+ const fileResult = await runModifiedFilesExecutor({
194
+ limit: config.fileLimit, mode: config.fileMode, disableAllowed: config.fileDisableAllowed,
195
+ }, context);
196
+ const returnTypesResult = await runReturnTypesExecutor({ mode: config.returnTypeMode }, context);
197
+ const noInlineTypesResult = await runNoInlineTypesExecutor({ mode: config.noInlineTypesMode }, context);
198
+ const noAnyUnknownResult = await runNoAnyUnknownExecutor({ mode: config.noAnyUnknownMode }, context);
83
199
 
84
- if (allSuccess) {
85
- console.log('\n✅ All code validations passed\n');
86
- } else {
87
- console.log('\n❌ Some code validations failed\n');
88
- }
200
+ const allSuccess = methodResults.every((r) => r.success) &&
201
+ fileResult.success && returnTypesResult.success &&
202
+ noInlineTypesResult.success && noAnyUnknownResult.success;
89
203
 
204
+ console.log(allSuccess ? '\n\u2705 All code validations passed\n' : '\n\u274c Some code validations failed\n');
90
205
  return { success: allSuccess };
91
206
  }
@@ -4,47 +4,74 @@
4
4
  "description": "Combined validation for new methods, modified methods, and file sizes. Configure via targetDefaults in nx.json for runtime options (no cache issues).",
5
5
  "type": "object",
6
6
  "properties": {
7
- "mode": {
8
- "type": "string",
9
- "enum": ["STRICT", "NORMAL", "OFF"],
10
- "description": "OFF: skip all validations. NORMAL: enforce limits, disable comments work. STRICT: enforce limits, no disable comments for modified code.",
11
- "default": "NORMAL"
12
- },
13
- "newMethodsMaxLines": {
14
- "type": "number",
15
- "description": "Soft limit: Maximum lines for NEW methods (can be bypassed with disable comment)",
16
- "default": 30
17
- },
18
- "strictNewMethodMaxLines": {
19
- "type": "number",
20
- "description": "Hard limit: Absolute maximum lines for NEW methods (CANNOT be bypassed). If not set, no hard limit is enforced."
21
- },
22
- "modifiedMethodsMaxLines": {
23
- "type": "number",
24
- "description": "Maximum lines for MODIFIED methods",
25
- "default": 80
7
+ "methodMaxLimit": {
8
+ "type": "object",
9
+ "description": "Configuration for method line limit validation",
10
+ "properties": {
11
+ "limit": {
12
+ "type": "number",
13
+ "description": "Maximum lines allowed for methods",
14
+ "default": 80
15
+ },
16
+ "mode": {
17
+ "type": "string",
18
+ "enum": ["OFF", "NEW_METHODS", "NEW_AND_MODIFIED_METHODS", "MODIFIED_FILES"],
19
+ "description": "OFF: skip validation. NEW_METHODS: only new methods in diff. NEW_AND_MODIFIED_METHODS: new methods + methods with changes. MODIFIED_FILES: all methods in modified files.",
20
+ "default": "NEW_AND_MODIFIED_METHODS"
21
+ },
22
+ "disableAllowed": {
23
+ "type": "boolean",
24
+ "description": "Whether disable comments work. When false, no escape hatch (like old STRICT mode).",
25
+ "default": true
26
+ },
27
+ "ignoreModifiedUntilEpoch": {
28
+ "type": "number",
29
+ "description": "Epoch seconds. Until this time, skip modified-method validation (new methods still enforced). When expired, normal mode resumes. Omit when not needed."
30
+ }
31
+ }
26
32
  },
27
- "modifiedFilesMaxLines": {
28
- "type": "number",
29
- "description": "Maximum lines for MODIFIED files",
30
- "default": 900
33
+ "fileMaxLimit": {
34
+ "type": "object",
35
+ "description": "Configuration for file line limit validation",
36
+ "properties": {
37
+ "limit": {
38
+ "type": "number",
39
+ "description": "Maximum lines for modified files",
40
+ "default": 900
41
+ },
42
+ "mode": {
43
+ "type": "string",
44
+ "enum": ["OFF", "MODIFIED_FILES"],
45
+ "description": "OFF: skip validation. MODIFIED_FILES: all code in modified files.",
46
+ "default": "MODIFIED_FILES"
47
+ },
48
+ "disableAllowed": {
49
+ "type": "boolean",
50
+ "description": "Whether disable comments work. When false, no escape hatch (like old STRICT mode).",
51
+ "default": true
52
+ },
53
+ "ignoreModifiedUntilEpoch": {
54
+ "type": "number",
55
+ "description": "Epoch seconds. Until this time, skip modified-file validation. When expired, normal mode resumes. Omit when not needed."
56
+ }
57
+ }
31
58
  },
32
59
  "requireReturnTypeMode": {
33
60
  "type": "string",
34
- "enum": ["OFF", "NEW_METHODS", "MODIFIED_AND_NEW_METHODS", "MODIFIED_FILES", "ALL"],
35
- "description": "OFF: skip return type validation. NEW_METHODS: only new methods in diff. MODIFIED_AND_NEW_METHODS: new methods + methods with changes. MODIFIED_FILES: all methods in modified files. ALL: all methods everywhere.",
61
+ "enum": ["OFF", "NEW_METHODS", "NEW_AND_MODIFIED_METHODS", "MODIFIED_FILES"],
62
+ "description": "OFF: skip return type validation. NEW_METHODS: only new methods in diff. NEW_AND_MODIFIED_METHODS: new methods + methods with changes. MODIFIED_FILES: all methods in modified files.",
36
63
  "default": "OFF"
37
64
  },
38
65
  "noInlineTypeLiteralsMode": {
39
66
  "type": "string",
40
- "enum": ["OFF", "NEW_METHODS", "MODIFIED_AND_NEW_METHODS", "MODIFIED_FILES", "ALL"],
41
- "description": "OFF: skip validation. NEW_METHODS: only new methods. MODIFIED_AND_NEW_METHODS: new + modified methods. MODIFIED_FILES: all in modified files. ALL: everywhere. Disallows inline type literals like { x: number } - use named types instead.",
67
+ "enum": ["OFF", "NEW_METHODS", "NEW_AND_MODIFIED_METHODS", "MODIFIED_FILES"],
68
+ "description": "OFF: skip validation. NEW_METHODS: only new methods. NEW_AND_MODIFIED_METHODS: new + modified methods. MODIFIED_FILES: all in modified files. Disallows inline type literals like { x: number } - use named types instead.",
42
69
  "default": "OFF"
43
70
  },
44
71
  "noAnyUnknownMode": {
45
72
  "type": "string",
46
- "enum": ["OFF", "MODIFIED_CODE", "MODIFIED_FILES", "ALL"],
47
- "description": "OFF: skip validation. MODIFIED_CODE: only changed lines in diff. MODIFIED_FILES: all in modified files. ALL: everywhere. Disallows `any` and `unknown` TypeScript keywords.",
73
+ "enum": ["OFF", "MODIFIED_CODE", "MODIFIED_FILES"],
74
+ "description": "OFF: skip validation. MODIFIED_CODE: only changed lines in diff. MODIFIED_FILES: all in modified files. Disallows `any` and `unknown` TypeScript keywords.",
48
75
  "default": "OFF"
49
76
  }
50
77
  },
@@ -13,10 +13,11 @@
13
13
  * The disable expires after 1 month from the date specified.
14
14
  */
15
15
  import type { ExecutorContext } from '@nx/devkit';
16
- export type ValidationMode = 'STRICT' | 'NORMAL' | 'OFF';
16
+ export type FileMaxLimitMode = 'OFF' | 'MODIFIED_FILES';
17
17
  export interface ValidateModifiedFilesOptions {
18
- max?: number;
19
- mode?: ValidationMode;
18
+ limit?: number;
19
+ mode?: FileMaxLimitMode;
20
+ disableAllowed?: boolean;
20
21
  }
21
22
  export interface ExecutorResult {
22
23
  success: boolean;