@webpieces/dev-config 0.2.80 → 0.2.82
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/architecture/executors/validate-code/executor.d.ts +7 -0
- package/architecture/executors/validate-code/executor.js +13 -2
- package/architecture/executors/validate-code/executor.js.map +1 -1
- package/architecture/executors/validate-code/executor.ts +23 -2
- package/architecture/executors/validate-code/schema.json +23 -2
- package/architecture/executors/validate-dtos/executor.d.ts +4 -2
- package/architecture/executors/validate-dtos/executor.js +126 -10
- package/architecture/executors/validate-dtos/executor.js.map +1 -1
- package/architecture/executors/validate-dtos/executor.ts +146 -11
- package/architecture/executors/validate-dtos/schema.json +2 -2
- package/architecture/executors/validate-prisma-converters/executor.d.ts +56 -0
- package/architecture/executors/validate-prisma-converters/executor.js +489 -0
- package/architecture/executors/validate-prisma-converters/executor.js.map +1 -0
- package/architecture/executors/validate-prisma-converters/executor.ts +615 -0
- package/architecture/executors/validate-prisma-converters/schema.json +24 -0
- package/executors.json +5 -0
- package/package.json +1 -1
|
@@ -3,6 +3,7 @@ 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
5
|
import { ValidateDtosMode } from '../validate-dtos/executor';
|
|
6
|
+
import { PrismaConverterMode } from '../validate-prisma-converters/executor';
|
|
6
7
|
export type MethodMaxLimitMode = 'OFF' | 'NEW_METHODS' | 'NEW_AND_MODIFIED_METHODS' | 'MODIFIED_FILES';
|
|
7
8
|
export type FileMaxLimitMode = 'OFF' | 'MODIFIED_FILES';
|
|
8
9
|
export interface MethodMaxLimitConfig {
|
|
@@ -22,6 +23,11 @@ export interface ValidateDtosConfig {
|
|
|
22
23
|
prismaSchemaPath?: string;
|
|
23
24
|
dtoSourcePaths?: string[];
|
|
24
25
|
}
|
|
26
|
+
export interface PrismaConverterConfig {
|
|
27
|
+
mode?: PrismaConverterMode;
|
|
28
|
+
schemaPath?: string;
|
|
29
|
+
convertersPaths?: string[];
|
|
30
|
+
}
|
|
25
31
|
export interface ValidateCodeOptions {
|
|
26
32
|
methodMaxLimit?: MethodMaxLimitConfig;
|
|
27
33
|
fileMaxLimit?: FileMaxLimitConfig;
|
|
@@ -29,6 +35,7 @@ export interface ValidateCodeOptions {
|
|
|
29
35
|
noInlineTypeLiteralsMode?: NoInlineTypesMode;
|
|
30
36
|
noAnyUnknownMode?: NoAnyUnknownMode;
|
|
31
37
|
validateDtos?: ValidateDtosConfig;
|
|
38
|
+
prismaConverter?: PrismaConverterConfig;
|
|
32
39
|
}
|
|
33
40
|
export interface ExecutorResult {
|
|
34
41
|
success: boolean;
|
|
@@ -9,6 +9,7 @@ const executor_4 = tslib_1.__importDefault(require("../validate-return-types/exe
|
|
|
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
11
|
const executor_7 = tslib_1.__importDefault(require("../validate-dtos/executor"));
|
|
12
|
+
const executor_8 = tslib_1.__importDefault(require("../validate-prisma-converters/executor"));
|
|
12
13
|
function formatEpochDate(epoch) {
|
|
13
14
|
return new Date(epoch * 1000).toISOString().split('T')[0];
|
|
14
15
|
}
|
|
@@ -67,6 +68,9 @@ function parseConfig(options) {
|
|
|
67
68
|
validateDtosMode: options.validateDtos?.mode ?? 'OFF',
|
|
68
69
|
validateDtosPrismaPath: options.validateDtos?.prismaSchemaPath,
|
|
69
70
|
validateDtosSrcPaths: options.validateDtos?.dtoSourcePaths ?? [],
|
|
71
|
+
prismaConverterMode: options.prismaConverter?.mode ?? 'OFF',
|
|
72
|
+
prismaConverterSchemaPath: options.prismaConverter?.schemaPath,
|
|
73
|
+
prismaConverterConvertersPaths: options.prismaConverter?.convertersPaths ?? [],
|
|
70
74
|
};
|
|
71
75
|
}
|
|
72
76
|
function formatOverride(override) {
|
|
@@ -83,12 +87,14 @@ function logConfig(config) {
|
|
|
83
87
|
console.log(` No inline type literals: ${config.noInlineTypesMode}`);
|
|
84
88
|
console.log(` No any/unknown: ${config.noAnyUnknownMode}`);
|
|
85
89
|
console.log(` Validate DTOs: ${config.validateDtosMode}`);
|
|
90
|
+
console.log(` Prisma converters: ${config.prismaConverterMode}`);
|
|
86
91
|
console.log('');
|
|
87
92
|
}
|
|
88
93
|
function isAllOff(config) {
|
|
89
94
|
return config.methodMode === 'OFF' && config.fileMode === 'OFF' &&
|
|
90
95
|
config.returnTypeMode === 'OFF' && config.noInlineTypesMode === 'OFF' &&
|
|
91
|
-
config.noAnyUnknownMode === 'OFF' && config.validateDtosMode === 'OFF'
|
|
96
|
+
config.noAnyUnknownMode === 'OFF' && config.validateDtosMode === 'OFF' &&
|
|
97
|
+
config.prismaConverterMode === 'OFF';
|
|
92
98
|
}
|
|
93
99
|
async function runMethodValidators(config, context) {
|
|
94
100
|
const results = [];
|
|
@@ -126,10 +132,15 @@ async function runExecutor(options, context) {
|
|
|
126
132
|
prismaSchemaPath: config.validateDtosPrismaPath,
|
|
127
133
|
dtoSourcePaths: config.validateDtosSrcPaths,
|
|
128
134
|
}, context);
|
|
135
|
+
const prismaConverterResult = await (0, executor_8.default)({
|
|
136
|
+
mode: config.prismaConverterMode,
|
|
137
|
+
schemaPath: config.prismaConverterSchemaPath,
|
|
138
|
+
convertersPaths: config.prismaConverterConvertersPaths,
|
|
139
|
+
}, context);
|
|
129
140
|
const allSuccess = methodResults.every((r) => r.success) &&
|
|
130
141
|
fileResult.success && returnTypesResult.success &&
|
|
131
142
|
noInlineTypesResult.success && noAnyUnknownResult.success &&
|
|
132
|
-
validateDtosResult.success;
|
|
143
|
+
validateDtosResult.success && prismaConverterResult.success;
|
|
133
144
|
console.log(allSuccess ? '\n\u2705 All code validations passed\n' : '\n\u274c Some code validations failed\n');
|
|
134
145
|
return { success: allSuccess };
|
|
135
146
|
}
|
|
@@ -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';\nimport runValidateDtosExecutor, { ValidateDtosMode } from '../validate-dtos/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 ValidateDtosConfig {\n mode?: ValidateDtosMode;\n prismaSchemaPath?: string;\n dtoSourcePaths?: string[];\n}\n\nexport interface ValidateCodeOptions {\n methodMaxLimit?: MethodMaxLimitConfig;\n fileMaxLimit?: FileMaxLimitConfig;\n requireReturnTypeMode?: ReturnTypeMode;\n noInlineTypeLiteralsMode?: NoInlineTypesMode;\n noAnyUnknownMode?: NoAnyUnknownMode;\n validateDtos?: ValidateDtosConfig;\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 validateDtosMode: ValidateDtosMode;\n validateDtosPrismaPath: string | undefined;\n validateDtosSrcPaths: string[];\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 validateDtosMode: options.validateDtos?.mode ?? 'OFF',\n validateDtosPrismaPath: options.validateDtos?.prismaSchemaPath,\n validateDtosSrcPaths: options.validateDtos?.dtoSourcePaths ?? [],\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(` Validate DTOs: ${config.validateDtosMode}`);\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' && config.validateDtosMode === '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 const validateDtosResult = await runValidateDtosExecutor({\n mode: config.validateDtosMode,\n prismaSchemaPath: config.validateDtosPrismaPath,\n dtoSourcePaths: config.validateDtosSrcPaths,\n }, context);\n\n const allSuccess = methodResults.every((r) => r.success) &&\n fileResult.success && returnTypesResult.success &&\n noInlineTypesResult.success && noAnyUnknownResult.success &&\n validateDtosResult.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"]}
|
|
1
|
+
{"version":3,"file":"executor.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/dev-config/architecture/executors/validate-code/executor.ts"],"names":[],"mappings":";;AAiNA,8BAsCC;;AAtPD,wFAAqE;AACrE,6FAA+E;AAC/E,2FAA2E;AAC3E,yFAA2F;AAC3F,4FAAmG;AACnG,2FAAgG;AAChG,iFAAsF;AACtF,8FAA0G;AAiF1G,SAAS,eAAe,CAAC,KAAa;IAClC,OAAO,IAAI,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;AAC9D,CAAC;AAED,SAAS,iBAAiB,CACtB,UAA8B,EAAE,KAAyB;IAEzD,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACtB,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC;IACrD,CAAC;IACD,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;IACrC,IAAI,UAAU,GAAG,KAAK,EAAE,CAAC;QACrB,8CAA8C;QAC9C,MAAM,UAAU,GACZ,UAAU,KAAK,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,aAAa,CAAC;QACjD,OAAO;YACH,IAAI,EAAE,UAAU;YAChB,QAAQ,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,WAAW,EAAE,eAAe,CAAC,KAAK,CAAC,EAAE;SAC9E,CAAC;IACN,CAAC;IACD,UAAU;IACV,OAAO,CAAC,GAAG,CAAC,4DAA4D,KAAK,kBAAkB,eAAe,CAAC,KAAK,CAAC,iDAAiD,UAAU,IAAI,CAAC,CAAC;IACtL,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC;AACrD,CAAC;AAED,SAAS,eAAe,CACpB,UAA4B,EAAE,KAAyB;IAEvD,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACtB,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC;IACrD,CAAC;IACD,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;IACrC,IAAI,UAAU,GAAG,KAAK,EAAE,CAAC;QACrB,6EAA6E;QAC7E,OAAO;YACH,IAAI,EAAE,KAAK;YACX,QAAQ,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,WAAW,EAAE,eAAe,CAAC,KAAK,CAAC,EAAE;SAC9E,CAAC;IACN,CAAC;IACD,UAAU;IACV,OAAO,CAAC,GAAG,CAAC,0DAA0D,KAAK,kBAAkB,eAAe,CAAC,KAAK,CAAC,iDAAiD,UAAU,IAAI,CAAC,CAAC;IACpL,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC;AACrD,CAAC;AAED,SAAS,WAAW,CAAC,OAA4B;IAC7C,MAAM,YAAY,GAAyB,OAAO,CAAC,cAAc,IAAI,EAAE,CAAC;IACxE,MAAM,UAAU,GAAuB,OAAO,CAAC,YAAY,IAAI,EAAE,CAAC;IAElE,MAAM,gBAAgB,GAAG,YAAY,CAAC,IAAI,IAAI,0BAA0B,CAAC;IACzE,MAAM,cAAc,GAAG,UAAU,CAAC,IAAI,IAAI,gBAAgB,CAAC;IAE3D,MAAM,cAAc,GAAG,iBAAiB,CAAC,gBAAgB,EAAE,YAAY,CAAC,wBAAwB,CAAC,CAAC;IAClG,MAAM,YAAY,GAAG,eAAe,CAAC,cAAc,EAAE,UAAU,CAAC,wBAAwB,CAAC,CAAC;IAE1F,OAAO;QACH,WAAW,EAAE,YAAY,CAAC,KAAK,IAAI,EAAE;QACrC,UAAU,EAAE,cAAc,CAAC,IAAI;QAC/B,oBAAoB,EAAE,YAAY,CAAC,cAAc,IAAI,IAAI;QACzD,cAAc,EAAE,cAAc,CAAC,QAAQ;QACvC,SAAS,EAAE,UAAU,CAAC,KAAK,IAAI,GAAG;QAClC,QAAQ,EAAE,YAAY,CAAC,IAAI;QAC3B,kBAAkB,EAAE,UAAU,CAAC,cAAc,IAAI,IAAI;QACrD,YAAY,EAAE,YAAY,CAAC,QAAQ;QACnC,cAAc,EAAE,OAAO,CAAC,qBAAqB,IAAI,KAAK;QACtD,iBAAiB,EAAE,OAAO,CAAC,wBAAwB,IAAI,KAAK;QAC5D,gBAAgB,EAAE,OAAO,CAAC,gBAAgB,IAAI,KAAK;QACnD,gBAAgB,EAAE,OAAO,CAAC,YAAY,EAAE,IAAI,IAAI,KAAK;QACrD,sBAAsB,EAAE,OAAO,CAAC,YAAY,EAAE,gBAAgB;QAC9D,oBAAoB,EAAE,OAAO,CAAC,YAAY,EAAE,cAAc,IAAI,EAAE;QAChE,mBAAmB,EAAE,OAAO,CAAC,eAAe,EAAE,IAAI,IAAI,KAAK;QAC3D,yBAAyB,EAAE,OAAO,CAAC,eAAe,EAAE,UAAU;QAC9D,8BAA8B,EAAE,OAAO,CAAC,eAAe,EAAE,eAAe,IAAI,EAAE;KACjF,CAAC;AACN,CAAC;AAED,SAAS,cAAc,CAAC,QAAkC;IACtD,IAAI,CAAC,QAAQ,EAAE,CAAC;QACZ,OAAO,EAAE,CAAC;IACd,CAAC;IACD,OAAO,8BAA8B,QAAQ,CAAC,UAAU,cAAc,QAAQ,CAAC,WAAW,GAAG,CAAC;AAClG,CAAC;AAED,SAAS,SAAS,CAAC,MAAoB;IACnC,OAAO,CAAC,GAAG,CAAC,2CAA2C,CAAC,CAAC;IACzD,OAAO,CAAC,GAAG,CAAC,0BAA0B,MAAM,CAAC,UAAU,GAAG,cAAc,CAAC,MAAM,CAAC,cAAc,CAAC,WAAW,MAAM,CAAC,WAAW,oBAAoB,MAAM,CAAC,oBAAoB,EAAE,CAAC,CAAC;IAC/K,OAAO,CAAC,GAAG,CAAC,wBAAwB,MAAM,CAAC,QAAQ,GAAG,cAAc,CAAC,MAAM,CAAC,YAAY,CAAC,WAAW,MAAM,CAAC,SAAS,oBAAoB,MAAM,CAAC,kBAAkB,EAAE,CAAC,CAAC;IACrK,OAAO,CAAC,GAAG,CAAC,4BAA4B,MAAM,CAAC,cAAc,EAAE,CAAC,CAAC;IACjE,OAAO,CAAC,GAAG,CAAC,+BAA+B,MAAM,CAAC,iBAAiB,EAAE,CAAC,CAAC;IACvE,OAAO,CAAC,GAAG,CAAC,sBAAsB,MAAM,CAAC,gBAAgB,EAAE,CAAC,CAAC;IAC7D,OAAO,CAAC,GAAG,CAAC,qBAAqB,MAAM,CAAC,gBAAgB,EAAE,CAAC,CAAC;IAC5D,OAAO,CAAC,GAAG,CAAC,yBAAyB,MAAM,CAAC,mBAAmB,EAAE,CAAC,CAAC;IACnE,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;AACpB,CAAC;AAED,SAAS,QAAQ,CAAC,MAAoB;IAClC,OAAO,MAAM,CAAC,UAAU,KAAK,KAAK,IAAI,MAAM,CAAC,QAAQ,KAAK,KAAK;QAC3D,MAAM,CAAC,cAAc,KAAK,KAAK,IAAI,MAAM,CAAC,iBAAiB,KAAK,KAAK;QACrE,MAAM,CAAC,gBAAgB,KAAK,KAAK,IAAI,MAAM,CAAC,gBAAgB,KAAK,KAAK;QACtE,MAAM,CAAC,mBAAmB,KAAK,KAAK,CAAC;AAC7C,CAAC;AAED,KAAK,UAAU,mBAAmB,CAAC,MAAoB,EAAE,OAAwB;IAC7E,MAAM,OAAO,GAAqB,EAAE,CAAC;IACrC,MAAM,MAAM,GAAG,MAAM,CAAC,UAAU,KAAK,aAAa,IAAI,MAAM,CAAC,UAAU,KAAK,0BAA0B,CAAC;IACvG,MAAM,WAAW,GAAG,MAAM,CAAC,UAAU,KAAK,0BAA0B,IAAI,MAAM,CAAC,UAAU,KAAK,gBAAgB,CAAC;IAE/G,IAAI,MAAM,EAAE,CAAC;QACT,OAAO,CAAC,IAAI,CAAC,MAAM,IAAA,kBAAqB,EAAC;YACrC,KAAK,EAAE,MAAM,CAAC,WAAW;YACzB,IAAI,EAAE,MAAM,CAAC,UAAU,EAAE,cAAc,EAAE,MAAM,CAAC,oBAAoB;SACvE,EAAE,OAAO,CAAC,CAAC,CAAC;IACjB,CAAC;IACD,IAAI,WAAW,EAAE,CAAC;QACd,OAAO,CAAC,IAAI,CAAC,MAAM,IAAA,kBAA0B,EAAC;YAC1C,KAAK,EAAE,MAAM,CAAC,WAAW,EAAE,IAAI,EAAE,MAAM,CAAC,UAAU,EAAE,cAAc,EAAE,MAAM,CAAC,oBAAoB;SAClG,EAAE,OAAO,CAAC,CAAC,CAAC;IACjB,CAAC;IACD,OAAO,OAAO,CAAC;AACnB,CAAC;AAEc,KAAK,UAAU,WAAW,CACrC,OAA4B,EAC5B,OAAwB;IAExB,MAAM,MAAM,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC;IAEpC,IAAI,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;QACnB,OAAO,CAAC,GAAG,CAAC,kEAAkE,CAAC,CAAC;QAChF,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAC7B,CAAC;IAED,SAAS,CAAC,MAAM,CAAC,CAAC;IAElB,MAAM,aAAa,GAAG,MAAM,mBAAmB,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjE,MAAM,UAAU,GAAG,MAAM,IAAA,kBAAwB,EAAC;QAC9C,KAAK,EAAE,MAAM,CAAC,SAAS,EAAE,IAAI,EAAE,MAAM,CAAC,QAAQ,EAAE,cAAc,EAAE,MAAM,CAAC,kBAAkB;KAC5F,EAAE,OAAO,CAAC,CAAC;IACZ,MAAM,iBAAiB,GAAG,MAAM,IAAA,kBAAsB,EAAC,EAAE,IAAI,EAAE,MAAM,CAAC,cAAc,EAAE,EAAE,OAAO,CAAC,CAAC;IACjG,MAAM,mBAAmB,GAAG,MAAM,IAAA,kBAAwB,EAAC,EAAE,IAAI,EAAE,MAAM,CAAC,iBAAiB,EAAE,EAAE,OAAO,CAAC,CAAC;IACxG,MAAM,kBAAkB,GAAG,MAAM,IAAA,kBAAuB,EAAC,EAAE,IAAI,EAAE,MAAM,CAAC,gBAAgB,EAAE,EAAE,OAAO,CAAC,CAAC;IACrG,MAAM,kBAAkB,GAAG,MAAM,IAAA,kBAAuB,EAAC;QACrD,IAAI,EAAE,MAAM,CAAC,gBAAgB;QAC7B,gBAAgB,EAAE,MAAM,CAAC,sBAAsB;QAC/C,cAAc,EAAE,MAAM,CAAC,oBAAoB;KAC9C,EAAE,OAAO,CAAC,CAAC;IACZ,MAAM,qBAAqB,GAAG,MAAM,IAAA,kBAA2B,EAAC;QAC5D,IAAI,EAAE,MAAM,CAAC,mBAAmB;QAChC,UAAU,EAAE,MAAM,CAAC,yBAAyB;QAC5C,eAAe,EAAE,MAAM,CAAC,8BAA8B;KACzD,EAAE,OAAO,CAAC,CAAC;IAEZ,MAAM,UAAU,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;QACpD,UAAU,CAAC,OAAO,IAAI,iBAAiB,CAAC,OAAO;QAC/C,mBAAmB,CAAC,OAAO,IAAI,kBAAkB,CAAC,OAAO;QACzD,kBAAkB,CAAC,OAAO,IAAI,qBAAqB,CAAC,OAAO,CAAC;IAEhE,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,wCAAwC,CAAC,CAAC,CAAC,yCAAyC,CAAC,CAAC;IAC/G,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,CAAC;AACnC,CAAC","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';\nimport runValidateDtosExecutor, { ValidateDtosMode } from '../validate-dtos/executor';\nimport runPrismaConvertersExecutor, { PrismaConverterMode } from '../validate-prisma-converters/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 ValidateDtosConfig {\n mode?: ValidateDtosMode;\n prismaSchemaPath?: string;\n dtoSourcePaths?: string[];\n}\n\nexport interface PrismaConverterConfig {\n mode?: PrismaConverterMode;\n schemaPath?: string;\n convertersPaths?: string[];\n}\n\nexport interface ValidateCodeOptions {\n methodMaxLimit?: MethodMaxLimitConfig;\n fileMaxLimit?: FileMaxLimitConfig;\n requireReturnTypeMode?: ReturnTypeMode;\n noInlineTypeLiteralsMode?: NoInlineTypesMode;\n noAnyUnknownMode?: NoAnyUnknownMode;\n validateDtos?: ValidateDtosConfig;\n prismaConverter?: PrismaConverterConfig;\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 validateDtosMode: ValidateDtosMode;\n validateDtosPrismaPath: string | undefined;\n validateDtosSrcPaths: string[];\n prismaConverterMode: PrismaConverterMode;\n prismaConverterSchemaPath: string | undefined;\n prismaConverterConvertersPaths: string[];\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 validateDtosMode: options.validateDtos?.mode ?? 'OFF',\n validateDtosPrismaPath: options.validateDtos?.prismaSchemaPath,\n validateDtosSrcPaths: options.validateDtos?.dtoSourcePaths ?? [],\n prismaConverterMode: options.prismaConverter?.mode ?? 'OFF',\n prismaConverterSchemaPath: options.prismaConverter?.schemaPath,\n prismaConverterConvertersPaths: options.prismaConverter?.convertersPaths ?? [],\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(` Validate DTOs: ${config.validateDtosMode}`);\n console.log(` Prisma converters: ${config.prismaConverterMode}`);\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' && config.validateDtosMode === 'OFF' &&\n config.prismaConverterMode === '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 const validateDtosResult = await runValidateDtosExecutor({\n mode: config.validateDtosMode,\n prismaSchemaPath: config.validateDtosPrismaPath,\n dtoSourcePaths: config.validateDtosSrcPaths,\n }, context);\n const prismaConverterResult = await runPrismaConvertersExecutor({\n mode: config.prismaConverterMode,\n schemaPath: config.prismaConverterSchemaPath,\n convertersPaths: config.prismaConverterConvertersPaths,\n }, context);\n\n const allSuccess = methodResults.every((r) => r.success) &&\n fileResult.success && returnTypesResult.success &&\n noInlineTypesResult.success && noAnyUnknownResult.success &&\n validateDtosResult.success && prismaConverterResult.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,6 +6,7 @@ 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
|
import runValidateDtosExecutor, { ValidateDtosMode } from '../validate-dtos/executor';
|
|
9
|
+
import runPrismaConvertersExecutor, { PrismaConverterMode } from '../validate-prisma-converters/executor';
|
|
9
10
|
|
|
10
11
|
export type MethodMaxLimitMode = 'OFF' | 'NEW_METHODS' | 'NEW_AND_MODIFIED_METHODS' | 'MODIFIED_FILES';
|
|
11
12
|
export type FileMaxLimitMode = 'OFF' | 'MODIFIED_FILES';
|
|
@@ -30,6 +31,12 @@ export interface ValidateDtosConfig {
|
|
|
30
31
|
dtoSourcePaths?: string[];
|
|
31
32
|
}
|
|
32
33
|
|
|
34
|
+
export interface PrismaConverterConfig {
|
|
35
|
+
mode?: PrismaConverterMode;
|
|
36
|
+
schemaPath?: string;
|
|
37
|
+
convertersPaths?: string[];
|
|
38
|
+
}
|
|
39
|
+
|
|
33
40
|
export interface ValidateCodeOptions {
|
|
34
41
|
methodMaxLimit?: MethodMaxLimitConfig;
|
|
35
42
|
fileMaxLimit?: FileMaxLimitConfig;
|
|
@@ -37,6 +44,7 @@ export interface ValidateCodeOptions {
|
|
|
37
44
|
noInlineTypeLiteralsMode?: NoInlineTypesMode;
|
|
38
45
|
noAnyUnknownMode?: NoAnyUnknownMode;
|
|
39
46
|
validateDtos?: ValidateDtosConfig;
|
|
47
|
+
prismaConverter?: PrismaConverterConfig;
|
|
40
48
|
}
|
|
41
49
|
|
|
42
50
|
export interface ExecutorResult {
|
|
@@ -64,6 +72,9 @@ interface ParsedConfig {
|
|
|
64
72
|
validateDtosMode: ValidateDtosMode;
|
|
65
73
|
validateDtosPrismaPath: string | undefined;
|
|
66
74
|
validateDtosSrcPaths: string[];
|
|
75
|
+
prismaConverterMode: PrismaConverterMode;
|
|
76
|
+
prismaConverterSchemaPath: string | undefined;
|
|
77
|
+
prismaConverterConvertersPaths: string[];
|
|
67
78
|
}
|
|
68
79
|
|
|
69
80
|
interface ResolvedMethodMode {
|
|
@@ -145,6 +156,9 @@ function parseConfig(options: ValidateCodeOptions): ParsedConfig {
|
|
|
145
156
|
validateDtosMode: options.validateDtos?.mode ?? 'OFF',
|
|
146
157
|
validateDtosPrismaPath: options.validateDtos?.prismaSchemaPath,
|
|
147
158
|
validateDtosSrcPaths: options.validateDtos?.dtoSourcePaths ?? [],
|
|
159
|
+
prismaConverterMode: options.prismaConverter?.mode ?? 'OFF',
|
|
160
|
+
prismaConverterSchemaPath: options.prismaConverter?.schemaPath,
|
|
161
|
+
prismaConverterConvertersPaths: options.prismaConverter?.convertersPaths ?? [],
|
|
148
162
|
};
|
|
149
163
|
}
|
|
150
164
|
|
|
@@ -163,13 +177,15 @@ function logConfig(config: ParsedConfig): void {
|
|
|
163
177
|
console.log(` No inline type literals: ${config.noInlineTypesMode}`);
|
|
164
178
|
console.log(` No any/unknown: ${config.noAnyUnknownMode}`);
|
|
165
179
|
console.log(` Validate DTOs: ${config.validateDtosMode}`);
|
|
180
|
+
console.log(` Prisma converters: ${config.prismaConverterMode}`);
|
|
166
181
|
console.log('');
|
|
167
182
|
}
|
|
168
183
|
|
|
169
184
|
function isAllOff(config: ParsedConfig): boolean {
|
|
170
185
|
return config.methodMode === 'OFF' && config.fileMode === 'OFF' &&
|
|
171
186
|
config.returnTypeMode === 'OFF' && config.noInlineTypesMode === 'OFF' &&
|
|
172
|
-
config.noAnyUnknownMode === 'OFF' && config.validateDtosMode === 'OFF'
|
|
187
|
+
config.noAnyUnknownMode === 'OFF' && config.validateDtosMode === 'OFF' &&
|
|
188
|
+
config.prismaConverterMode === 'OFF';
|
|
173
189
|
}
|
|
174
190
|
|
|
175
191
|
async function runMethodValidators(config: ParsedConfig, context: ExecutorContext): Promise<ExecutorResult[]> {
|
|
@@ -216,11 +232,16 @@ export default async function runExecutor(
|
|
|
216
232
|
prismaSchemaPath: config.validateDtosPrismaPath,
|
|
217
233
|
dtoSourcePaths: config.validateDtosSrcPaths,
|
|
218
234
|
}, context);
|
|
235
|
+
const prismaConverterResult = await runPrismaConvertersExecutor({
|
|
236
|
+
mode: config.prismaConverterMode,
|
|
237
|
+
schemaPath: config.prismaConverterSchemaPath,
|
|
238
|
+
convertersPaths: config.prismaConverterConvertersPaths,
|
|
239
|
+
}, context);
|
|
219
240
|
|
|
220
241
|
const allSuccess = methodResults.every((r) => r.success) &&
|
|
221
242
|
fileResult.success && returnTypesResult.success &&
|
|
222
243
|
noInlineTypesResult.success && noAnyUnknownResult.success &&
|
|
223
|
-
validateDtosResult.success;
|
|
244
|
+
validateDtosResult.success && prismaConverterResult.success;
|
|
224
245
|
|
|
225
246
|
console.log(allSuccess ? '\n\u2705 All code validations passed\n' : '\n\u274c Some code validations failed\n');
|
|
226
247
|
return { success: allSuccess };
|
|
@@ -80,8 +80,8 @@
|
|
|
80
80
|
"properties": {
|
|
81
81
|
"mode": {
|
|
82
82
|
"type": "string",
|
|
83
|
-
"enum": ["OFF", "MODIFIED_FILES"],
|
|
84
|
-
"description": "OFF: skip validation.
|
|
83
|
+
"enum": ["OFF", "MODIFIED_CLASS", "MODIFIED_FILES"],
|
|
84
|
+
"description": "OFF: skip validation. MODIFIED_CLASS: only validate Dto classes with changed lines. MODIFIED_FILES: validate all Dtos in modified files.",
|
|
85
85
|
"default": "OFF"
|
|
86
86
|
},
|
|
87
87
|
"prismaSchemaPath": {
|
|
@@ -94,6 +94,27 @@
|
|
|
94
94
|
"description": "Array of directories (relative to workspace root) containing Dto files"
|
|
95
95
|
}
|
|
96
96
|
}
|
|
97
|
+
},
|
|
98
|
+
"prismaConverter": {
|
|
99
|
+
"type": "object",
|
|
100
|
+
"description": "Validate Prisma converter methods follow scalable patterns: correct Dbo parameter, no async, no standalone functions, Dto creation only in converter directories.",
|
|
101
|
+
"properties": {
|
|
102
|
+
"mode": {
|
|
103
|
+
"type": "string",
|
|
104
|
+
"enum": ["OFF", "MODIFIED_FILES"],
|
|
105
|
+
"description": "OFF: skip validation. MODIFIED_FILES: validate converter and non-converter files modified in the diff.",
|
|
106
|
+
"default": "OFF"
|
|
107
|
+
},
|
|
108
|
+
"schemaPath": {
|
|
109
|
+
"type": "string",
|
|
110
|
+
"description": "Relative path from workspace root to schema.prisma"
|
|
111
|
+
},
|
|
112
|
+
"convertersPaths": {
|
|
113
|
+
"type": "array",
|
|
114
|
+
"items": { "type": "string" },
|
|
115
|
+
"description": "Array of directories (relative to workspace root) containing converter files"
|
|
116
|
+
}
|
|
117
|
+
}
|
|
97
118
|
}
|
|
98
119
|
},
|
|
99
120
|
"required": []
|
|
@@ -9,7 +9,8 @@
|
|
|
9
9
|
* MODES
|
|
10
10
|
* ============================================================================
|
|
11
11
|
* - OFF: Skip validation entirely
|
|
12
|
-
* -
|
|
12
|
+
* - MODIFIED_CLASS: Only validate Dto classes that have changed lines in the diff
|
|
13
|
+
* - MODIFIED_FILES: Validate ALL Dto classes in files that were modified
|
|
13
14
|
*
|
|
14
15
|
* ============================================================================
|
|
15
16
|
* SKIP CONDITIONS
|
|
@@ -22,11 +23,12 @@
|
|
|
22
23
|
* MATCHING
|
|
23
24
|
* ============================================================================
|
|
24
25
|
* - UserDto matches UserDbo by case-insensitive prefix ("user")
|
|
26
|
+
* - Dbo field names are converted from snake_case to camelCase for comparison
|
|
25
27
|
* - Dto fields must be a subset of Dbo fields
|
|
26
28
|
* - Extra Dbo fields are allowed (e.g., password)
|
|
27
29
|
*/
|
|
28
30
|
import type { ExecutorContext } from '@nx/devkit';
|
|
29
|
-
export type ValidateDtosMode = 'OFF' | 'MODIFIED_FILES';
|
|
31
|
+
export type ValidateDtosMode = 'OFF' | 'MODIFIED_CLASS' | 'MODIFIED_FILES';
|
|
30
32
|
export interface ValidateDtosOptions {
|
|
31
33
|
mode?: ValidateDtosMode;
|
|
32
34
|
prismaSchemaPath?: string;
|
|
@@ -10,7 +10,8 @@
|
|
|
10
10
|
* MODES
|
|
11
11
|
* ============================================================================
|
|
12
12
|
* - OFF: Skip validation entirely
|
|
13
|
-
* -
|
|
13
|
+
* - MODIFIED_CLASS: Only validate Dto classes that have changed lines in the diff
|
|
14
|
+
* - MODIFIED_FILES: Validate ALL Dto classes in files that were modified
|
|
14
15
|
*
|
|
15
16
|
* ============================================================================
|
|
16
17
|
* SKIP CONDITIONS
|
|
@@ -23,6 +24,7 @@
|
|
|
23
24
|
* MATCHING
|
|
24
25
|
* ============================================================================
|
|
25
26
|
* - UserDto matches UserDbo by case-insensitive prefix ("user")
|
|
27
|
+
* - Dbo field names are converted from snake_case to camelCase for comparison
|
|
26
28
|
* - Dto fields must be a subset of Dbo fields
|
|
27
29
|
* - Extra Dbo fields are allowed (e.g., password)
|
|
28
30
|
*/
|
|
@@ -103,8 +105,72 @@ function getChangedFiles(workspaceRoot, base, head) {
|
|
|
103
105
|
}
|
|
104
106
|
}
|
|
105
107
|
/**
|
|
106
|
-
*
|
|
108
|
+
* Get the diff content for a specific file.
|
|
109
|
+
*/
|
|
110
|
+
function getFileDiff(workspaceRoot, file, base, head) {
|
|
111
|
+
try {
|
|
112
|
+
const diffTarget = head ? `${base} ${head}` : base;
|
|
113
|
+
const diff = (0, child_process_1.execSync)(`git diff ${diffTarget} -- "${file}"`, {
|
|
114
|
+
cwd: workspaceRoot,
|
|
115
|
+
encoding: 'utf-8',
|
|
116
|
+
});
|
|
117
|
+
if (!diff && !head) {
|
|
118
|
+
const fullPath = path.join(workspaceRoot, file);
|
|
119
|
+
if (fs.existsSync(fullPath)) {
|
|
120
|
+
const isUntracked = (0, child_process_1.execSync)(`git ls-files --others --exclude-standard "${file}"`, {
|
|
121
|
+
cwd: workspaceRoot,
|
|
122
|
+
encoding: 'utf-8',
|
|
123
|
+
}).trim();
|
|
124
|
+
if (isUntracked) {
|
|
125
|
+
const content = fs.readFileSync(fullPath, 'utf-8');
|
|
126
|
+
const lines = content.split('\n');
|
|
127
|
+
return lines.map((line) => `+${line}`).join('\n');
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
return diff;
|
|
132
|
+
}
|
|
133
|
+
catch {
|
|
134
|
+
return '';
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Parse diff to extract changed line numbers (additions only - lines starting with +).
|
|
139
|
+
*/
|
|
140
|
+
function getChangedLineNumbers(diffContent) {
|
|
141
|
+
const changedLines = new Set();
|
|
142
|
+
const lines = diffContent.split('\n');
|
|
143
|
+
let currentLine = 0;
|
|
144
|
+
for (const line of lines) {
|
|
145
|
+
const hunkMatch = line.match(/^@@ -\d+(?:,\d+)? \+(\d+)(?:,\d+)? @@/);
|
|
146
|
+
if (hunkMatch) {
|
|
147
|
+
currentLine = parseInt(hunkMatch[1], 10);
|
|
148
|
+
continue;
|
|
149
|
+
}
|
|
150
|
+
if (line.startsWith('+') && !line.startsWith('+++')) {
|
|
151
|
+
changedLines.add(currentLine);
|
|
152
|
+
currentLine++;
|
|
153
|
+
}
|
|
154
|
+
else if (line.startsWith('-') && !line.startsWith('---')) {
|
|
155
|
+
// Deletions don't increment line number
|
|
156
|
+
}
|
|
157
|
+
else {
|
|
158
|
+
currentLine++;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
return changedLines;
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Convert a snake_case string to camelCase.
|
|
165
|
+
* e.g., "version_number" -> "versionNumber", "id" -> "id"
|
|
166
|
+
*/
|
|
167
|
+
function snakeToCamel(s) {
|
|
168
|
+
return s.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase());
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Parse schema.prisma to build a map of Dbo model name -> set of field names (camelCase).
|
|
107
172
|
* Only models whose name ends with "Dbo" are included.
|
|
173
|
+
* Field names are converted from snake_case to camelCase since Dto fields use camelCase.
|
|
108
174
|
*/
|
|
109
175
|
function parsePrismaSchema(schemaPath) {
|
|
110
176
|
const models = new Map();
|
|
@@ -137,10 +203,10 @@ function parsePrismaSchema(schemaPath) {
|
|
|
137
203
|
if (!trimmed || trimmed.startsWith('//') || trimmed.startsWith('@@')) {
|
|
138
204
|
continue;
|
|
139
205
|
}
|
|
140
|
-
// Field name is the first word on the line
|
|
206
|
+
// Field name is the first word on the line, converted to camelCase
|
|
141
207
|
const fieldMatch = trimmed.match(/^(\w+)\s/);
|
|
142
208
|
if (fieldMatch) {
|
|
143
|
-
currentFields.add(fieldMatch[1]);
|
|
209
|
+
currentFields.add(snakeToCamel(fieldMatch[1]));
|
|
144
210
|
}
|
|
145
211
|
}
|
|
146
212
|
}
|
|
@@ -179,6 +245,8 @@ function findDtosInFile(filePath, workspaceRoot) {
|
|
|
179
245
|
// Must end with Dto but NOT with JoinDto
|
|
180
246
|
if (name.endsWith('Dto') && !name.endsWith('JoinDto')) {
|
|
181
247
|
const fields = [];
|
|
248
|
+
const nodeStart = sourceFile.getLineAndCharacterOfPosition(node.getStart(sourceFile));
|
|
249
|
+
const nodeEnd = sourceFile.getLineAndCharacterOfPosition(node.getEnd());
|
|
182
250
|
for (const member of node.members) {
|
|
183
251
|
if (ts.isPropertyDeclaration(member) || ts.isPropertySignature(member)) {
|
|
184
252
|
if (member.name && ts.isIdentifier(member.name)) {
|
|
@@ -191,7 +259,13 @@ function findDtosInFile(filePath, workspaceRoot) {
|
|
|
191
259
|
}
|
|
192
260
|
}
|
|
193
261
|
}
|
|
194
|
-
dtos.push({
|
|
262
|
+
dtos.push({
|
|
263
|
+
name,
|
|
264
|
+
file: filePath,
|
|
265
|
+
startLine: nodeStart.line + 1,
|
|
266
|
+
endLine: nodeEnd.line + 1,
|
|
267
|
+
fields,
|
|
268
|
+
});
|
|
195
269
|
}
|
|
196
270
|
}
|
|
197
271
|
ts.forEachChild(node, visit);
|
|
@@ -258,7 +332,7 @@ function reportViolations(violations) {
|
|
|
258
332
|
console.error(` Available Dbo fields: ${v.availableFields.join(', ')}`);
|
|
259
333
|
}
|
|
260
334
|
console.error('');
|
|
261
|
-
console.error(' Dto fields must be a subset of Dbo fields (matching
|
|
335
|
+
console.error(' Dto fields must be a subset of Dbo fields (matching camelCase field names).');
|
|
262
336
|
console.error(' Fields marked @deprecated in the Dto are exempt from this check.');
|
|
263
337
|
console.error('');
|
|
264
338
|
console.error(' When needing fields from multiple tables (e.g., a join), use a XxxJoinDto that');
|
|
@@ -288,6 +362,39 @@ function collectDtos(dtoFiles, workspaceRoot) {
|
|
|
288
362
|
}
|
|
289
363
|
return allDtos;
|
|
290
364
|
}
|
|
365
|
+
/**
|
|
366
|
+
* Check if a Dto class overlaps with any changed lines in the diff.
|
|
367
|
+
*/
|
|
368
|
+
function isDtoTouched(dto, changedLines) {
|
|
369
|
+
for (let line = dto.startLine; line <= dto.endLine; line++) {
|
|
370
|
+
if (changedLines.has(line))
|
|
371
|
+
return true;
|
|
372
|
+
}
|
|
373
|
+
return false;
|
|
374
|
+
}
|
|
375
|
+
/**
|
|
376
|
+
* Filter Dtos to only those that have changed lines in the diff (MODIFIED_CLASS mode).
|
|
377
|
+
*/
|
|
378
|
+
function filterTouchedDtos(dtos, workspaceRoot, base, head) {
|
|
379
|
+
// Group dtos by file to avoid re-fetching diffs
|
|
380
|
+
const byFile = new Map();
|
|
381
|
+
for (const dto of dtos) {
|
|
382
|
+
const list = byFile.get(dto.file) ?? [];
|
|
383
|
+
list.push(dto);
|
|
384
|
+
byFile.set(dto.file, list);
|
|
385
|
+
}
|
|
386
|
+
const touched = [];
|
|
387
|
+
for (const [file, fileDtos] of byFile) {
|
|
388
|
+
const diff = getFileDiff(workspaceRoot, file, base, head);
|
|
389
|
+
const changedLines = getChangedLineNumbers(diff);
|
|
390
|
+
for (const dto of fileDtos) {
|
|
391
|
+
if (isDtoTouched(dto, changedLines)) {
|
|
392
|
+
touched.push(dto);
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
return touched;
|
|
397
|
+
}
|
|
291
398
|
/**
|
|
292
399
|
* Resolve git base ref from env vars or auto-detection.
|
|
293
400
|
*/
|
|
@@ -300,7 +407,8 @@ function resolveBase(workspaceRoot) {
|
|
|
300
407
|
/**
|
|
301
408
|
* Run the core validation after early-exit checks have passed.
|
|
302
409
|
*/
|
|
303
|
-
|
|
410
|
+
// webpieces-disable max-lines-new-methods -- Core validation orchestration with multiple early-exit checks
|
|
411
|
+
function validateDtoFiles(workspaceRoot, prismaSchemaPath, changedFiles, dtoSourcePaths, mode, base, head) {
|
|
304
412
|
if (changedFiles.some((f) => f.endsWith(prismaSchemaPath))) {
|
|
305
413
|
console.log('⏭️ Skipping validate-dtos (schema.prisma is modified - schema in flux)');
|
|
306
414
|
console.log('');
|
|
@@ -320,12 +428,20 @@ function validateDtoFiles(workspaceRoot, prismaSchemaPath, changedFiles, dtoSour
|
|
|
320
428
|
return { success: true };
|
|
321
429
|
}
|
|
322
430
|
console.log(` Found ${dboModels.size} Dbo model(s) in schema.prisma`);
|
|
323
|
-
|
|
431
|
+
let allDtos = collectDtos(dtoFiles, workspaceRoot);
|
|
324
432
|
if (allDtos.length === 0) {
|
|
325
433
|
console.log('✅ No Dto definitions found in changed files');
|
|
326
434
|
return { success: true };
|
|
327
435
|
}
|
|
328
|
-
|
|
436
|
+
// In MODIFIED_CLASS mode, narrow to only Dtos with changed lines
|
|
437
|
+
if (mode === 'MODIFIED_CLASS') {
|
|
438
|
+
allDtos = filterTouchedDtos(allDtos, workspaceRoot, base, head);
|
|
439
|
+
if (allDtos.length === 0) {
|
|
440
|
+
console.log('✅ No Dto classes were modified');
|
|
441
|
+
return { success: true };
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
console.log(` Validating ${allDtos.length} Dto definition(s)`);
|
|
329
445
|
const violations = findViolations(allDtos, dboModels);
|
|
330
446
|
if (violations.length === 0) {
|
|
331
447
|
console.log('✅ All Dto fields match their Dbo models');
|
|
@@ -365,6 +481,6 @@ async function runExecutor(options, context) {
|
|
|
365
481
|
console.log(` Head: ${head ?? 'working tree (includes uncommitted changes)'}`);
|
|
366
482
|
console.log('');
|
|
367
483
|
const changedFiles = getChangedFiles(workspaceRoot, base, head);
|
|
368
|
-
return validateDtoFiles(workspaceRoot, prismaSchemaPath, changedFiles, dtoSourcePaths);
|
|
484
|
+
return validateDtoFiles(workspaceRoot, prismaSchemaPath, changedFiles, dtoSourcePaths, mode, base, head);
|
|
369
485
|
}
|
|
370
486
|
//# sourceMappingURL=executor.js.map
|