invar-tools 1.17.2__py3-none-any.whl → 1.17.3__py3-none-any.whl
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.
- invar/node_tools/.gitignore +10 -6
- invar/node_tools/eslint-plugin/rules/__tests__/behavior.test.js +1321 -0
- invar/node_tools/eslint-plugin/rules/__tests__/behavior.test.js.map +1 -0
- invar/node_tools/eslint-plugin/rules/__tests__/e2e-scenarios.test.js +414 -0
- invar/node_tools/eslint-plugin/rules/__tests__/e2e-scenarios.test.js.map +1 -0
- invar/node_tools/eslint-plugin/rules/__tests__/fixtures/core/function-lengths.js +142 -0
- invar/node_tools/eslint-plugin/rules/__tests__/fixtures/core/function-lengths.js.map +1 -0
- invar/node_tools/eslint-plugin/rules/__tests__/fixtures/core/has-io-imports.js +15 -0
- invar/node_tools/eslint-plugin/rules/__tests__/fixtures/core/has-io-imports.js.map +1 -0
- invar/node_tools/eslint-plugin/rules/__tests__/fixtures/core/valid-small.js +27 -0
- invar/node_tools/eslint-plugin/rules/__tests__/fixtures/core/valid-small.js.map +1 -0
- invar/node_tools/eslint-plugin/rules/__tests__/fixtures/exported-functions.js +43 -0
- invar/node_tools/eslint-plugin/rules/__tests__/fixtures/exported-functions.js.map +1 -0
- invar/node_tools/eslint-plugin/rules/__tests__/fixtures/shell/with-io.js +27 -0
- invar/node_tools/eslint-plugin/rules/__tests__/fixtures/shell/with-io.js.map +1 -0
- invar/node_tools/eslint-plugin/rules/__tests__/fixtures/tests/large.test.js +260 -0
- invar/node_tools/eslint-plugin/rules/__tests__/fixtures/tests/large.test.js.map +1 -0
- invar/node_tools/eslint-plugin/rules/max-file-lines.js +105 -0
- invar/node_tools/eslint-plugin/rules/max-file-lines.js.map +1 -0
- invar/node_tools/eslint-plugin/rules/max-function-lines.js +133 -0
- invar/node_tools/eslint-plugin/rules/max-function-lines.js.map +1 -0
- invar/node_tools/eslint-plugin/rules/no-any-in-schema.js +39 -0
- invar/node_tools/eslint-plugin/rules/no-any-in-schema.js.map +1 -0
- invar/node_tools/eslint-plugin/rules/no-empty-schema.js +69 -0
- invar/node_tools/eslint-plugin/rules/no-empty-schema.js.map +1 -0
- invar/node_tools/eslint-plugin/rules/no-impure-calls-in-core.js +52 -0
- invar/node_tools/eslint-plugin/rules/no-impure-calls-in-core.js.map +1 -0
- invar/node_tools/eslint-plugin/rules/no-io-in-core.js +99 -0
- invar/node_tools/eslint-plugin/rules/no-io-in-core.js.map +1 -0
- invar/node_tools/eslint-plugin/rules/no-pure-logic-in-shell.js +197 -0
- invar/node_tools/eslint-plugin/rules/no-pure-logic-in-shell.js.map +1 -0
- invar/node_tools/eslint-plugin/rules/no-redundant-type-schema.js +99 -0
- invar/node_tools/eslint-plugin/rules/no-redundant-type-schema.js.map +1 -0
- invar/node_tools/eslint-plugin/rules/no-runtime-imports.js +66 -0
- invar/node_tools/eslint-plugin/rules/no-runtime-imports.js.map +1 -0
- invar/node_tools/eslint-plugin/rules/require-complete-validation.js +104 -0
- invar/node_tools/eslint-plugin/rules/require-complete-validation.js.map +1 -0
- invar/node_tools/eslint-plugin/rules/require-jsdoc-example.js +81 -0
- invar/node_tools/eslint-plugin/rules/require-jsdoc-example.js.map +1 -0
- invar/node_tools/eslint-plugin/rules/require-schema-validation.js +308 -0
- invar/node_tools/eslint-plugin/rules/require-schema-validation.js.map +1 -0
- invar/node_tools/eslint-plugin/rules/shell-complexity.js +273 -0
- invar/node_tools/eslint-plugin/rules/shell-complexity.js.map +1 -0
- invar/node_tools/eslint-plugin/rules/shell-result-type.js +138 -0
- invar/node_tools/eslint-plugin/rules/shell-result-type.js.map +1 -0
- invar/node_tools/eslint-plugin/rules/thin-entry-points.js +174 -0
- invar/node_tools/eslint-plugin/rules/thin-entry-points.js.map +1 -0
- invar/node_tools/eslint-plugin/utils/layer-detection.js +91 -0
- invar/node_tools/eslint-plugin/utils/layer-detection.js.map +1 -0
- invar/node_tools/eslint-plugin/utils/math-example.js +31 -0
- invar/node_tools/eslint-plugin/utils/math-example.js.map +1 -0
- {invar_tools-1.17.2.dist-info → invar_tools-1.17.3.dist-info}/METADATA +1 -1
- {invar_tools-1.17.2.dist-info → invar_tools-1.17.3.dist-info}/RECORD +58 -8
- {invar_tools-1.17.2.dist-info → invar_tools-1.17.3.dist-info}/WHEEL +0 -0
- {invar_tools-1.17.2.dist-info → invar_tools-1.17.3.dist-info}/entry_points.txt +0 -0
- {invar_tools-1.17.2.dist-info → invar_tools-1.17.3.dist-info}/licenses/LICENSE +0 -0
- {invar_tools-1.17.2.dist-info → invar_tools-1.17.3.dist-info}/licenses/LICENSE-GPL +0 -0
- {invar_tools-1.17.2.dist-info → invar_tools-1.17.3.dist-info}/licenses/NOTICE +0 -0
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rule: require-complete-validation
|
|
3
|
+
*
|
|
4
|
+
* Detect functions where some parameters have Zod schema validation but others don't.
|
|
5
|
+
* Either all parameters should be validated, or none should be.
|
|
6
|
+
*
|
|
7
|
+
* Detects:
|
|
8
|
+
* - Functions with mixed z.infer<typeof Schema> and plain types
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Check if a parameter type is a Zod inferred type
|
|
12
|
+
* Looks for: z.infer<typeof SchemaName>
|
|
13
|
+
*/
|
|
14
|
+
function isZodInferType(typeAnnotation) {
|
|
15
|
+
if (!typeAnnotation || typeAnnotation.type !== 'TSTypeReference') {
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
const typeRef = typeAnnotation;
|
|
19
|
+
// Check for z.infer type
|
|
20
|
+
if (typeRef.typeName.type === 'TSQualifiedName' &&
|
|
21
|
+
typeRef.typeName.left.type === 'Identifier' &&
|
|
22
|
+
typeRef.typeName.left.name === 'z' &&
|
|
23
|
+
typeRef.typeName.right.type === 'Identifier' &&
|
|
24
|
+
typeRef.typeName.right.name === 'infer') {
|
|
25
|
+
return true;
|
|
26
|
+
}
|
|
27
|
+
// Also check for direct TypeOf reference: typeof SchemaName
|
|
28
|
+
if (typeRef.typeParameters && typeRef.typeParameters.params.length > 0) {
|
|
29
|
+
const firstParam = typeRef.typeParameters.params[0];
|
|
30
|
+
if (firstParam.type === 'TSTypeQuery') {
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
export const requireCompleteValidation = {
|
|
37
|
+
meta: {
|
|
38
|
+
type: 'suggestion',
|
|
39
|
+
docs: {
|
|
40
|
+
description: 'Require all function parameters to be validated, or none',
|
|
41
|
+
recommended: true,
|
|
42
|
+
},
|
|
43
|
+
schema: [],
|
|
44
|
+
messages: {
|
|
45
|
+
partialValidation: 'Function has {{validated}} parameter(s) with Zod schema validation but {{unvalidated}} without. ' +
|
|
46
|
+
'Either validate all parameters or use plain TypeScript types for all.',
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
create(context) {
|
|
50
|
+
function checkFunction(node) {
|
|
51
|
+
const params = node.params;
|
|
52
|
+
if (params.length === 0) {
|
|
53
|
+
return; // No parameters to check
|
|
54
|
+
}
|
|
55
|
+
let validatedCount = 0;
|
|
56
|
+
let unvalidatedCount = 0;
|
|
57
|
+
for (const param of params) {
|
|
58
|
+
if (param.type === 'Identifier' && param.typeAnnotation) {
|
|
59
|
+
const typeAnnotation = param.typeAnnotation.typeAnnotation;
|
|
60
|
+
if (isZodInferType(typeAnnotation)) {
|
|
61
|
+
validatedCount++;
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
unvalidatedCount++;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
else if (param.type === 'AssignmentPattern') {
|
|
68
|
+
// Handle default parameters: param: Type = defaultValue
|
|
69
|
+
if (param.left.type === 'Identifier' && param.left.typeAnnotation) {
|
|
70
|
+
const typeAnnotation = param.left.typeAnnotation.typeAnnotation;
|
|
71
|
+
if (isZodInferType(typeAnnotation)) {
|
|
72
|
+
validatedCount++;
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
unvalidatedCount++;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
// Other parameter types (rest, destructuring) count as unvalidated
|
|
81
|
+
unvalidatedCount++;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
// Report if we have a mix of validated and unvalidated parameters
|
|
85
|
+
if (validatedCount > 0 && unvalidatedCount > 0) {
|
|
86
|
+
context.report({
|
|
87
|
+
node: node,
|
|
88
|
+
messageId: 'partialValidation',
|
|
89
|
+
data: {
|
|
90
|
+
validated: String(validatedCount),
|
|
91
|
+
unvalidated: String(unvalidatedCount),
|
|
92
|
+
},
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return {
|
|
97
|
+
FunctionDeclaration: checkFunction,
|
|
98
|
+
FunctionExpression: checkFunction,
|
|
99
|
+
ArrowFunctionExpression: checkFunction,
|
|
100
|
+
};
|
|
101
|
+
},
|
|
102
|
+
};
|
|
103
|
+
export default requireCompleteValidation;
|
|
104
|
+
//# sourceMappingURL=require-complete-validation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"require-complete-validation.js","sourceRoot":"","sources":["../../src/rules/require-complete-validation.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAYH;;;GAGG;AACH,SAAS,cAAc,CAAC,cAAmB;IACzC,IAAI,CAAC,cAAc,IAAI,cAAc,CAAC,IAAI,KAAK,iBAAiB,EAAE,CAAC;QACjE,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,OAAO,GAAG,cAAc,CAAC;IAE/B,yBAAyB;IACzB,IACE,OAAO,CAAC,QAAQ,CAAC,IAAI,KAAK,iBAAiB;QAC3C,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,KAAK,YAAY;QAC1C,OAAO,CAAC,QAAQ,CAAC,IAAmB,CAAC,IAAI,KAAK,GAAG;QAClD,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,YAAY;QAC5C,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,OAAO,EACvC,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,4DAA4D;IAC5D,IAAI,OAAO,CAAC,cAAc,IAAI,OAAO,CAAC,cAAc,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvE,MAAM,UAAU,GAAG,OAAO,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QACpD,IAAI,UAAU,CAAC,IAAI,KAAK,aAAa,EAAE,CAAC;YACtC,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,CAAC,MAAM,yBAAyB,GAAoB;IACxD,IAAI,EAAE;QACJ,IAAI,EAAE,YAAY;QAClB,IAAI,EAAE;YACJ,WAAW,EAAE,0DAA0D;YACvE,WAAW,EAAE,IAAI;SAClB;QACD,MAAM,EAAE,EAAE;QACV,QAAQ,EAAE;YACR,iBAAiB,EACf,kGAAkG;gBAClG,uEAAuE;SAC1E;KACF;IAED,MAAM,CAAC,OAAO;QACZ,SAAS,aAAa,CAAC,IAAkB;YACvC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;YAE3B,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACxB,OAAO,CAAC,yBAAyB;YACnC,CAAC;YAED,IAAI,cAAc,GAAG,CAAC,CAAC;YACvB,IAAI,gBAAgB,GAAG,CAAC,CAAC;YAEzB,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;gBAC3B,IAAI,KAAK,CAAC,IAAI,KAAK,YAAY,IAAK,KAAa,CAAC,cAAc,EAAE,CAAC;oBACjE,MAAM,cAAc,GAAI,KAAa,CAAC,cAAc,CAAC,cAAc,CAAC;oBAEpE,IAAI,cAAc,CAAC,cAAc,CAAC,EAAE,CAAC;wBACnC,cAAc,EAAE,CAAC;oBACnB,CAAC;yBAAM,CAAC;wBACN,gBAAgB,EAAE,CAAC;oBACrB,CAAC;gBACH,CAAC;qBAAM,IAAI,KAAK,CAAC,IAAI,KAAK,mBAAmB,EAAE,CAAC;oBAC9C,wDAAwD;oBACxD,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,KAAK,YAAY,IAAK,KAAK,CAAC,IAAY,CAAC,cAAc,EAAE,CAAC;wBAC3E,MAAM,cAAc,GAAI,KAAK,CAAC,IAAY,CAAC,cAAc,CAAC,cAAc,CAAC;wBAEzE,IAAI,cAAc,CAAC,cAAc,CAAC,EAAE,CAAC;4BACnC,cAAc,EAAE,CAAC;wBACnB,CAAC;6BAAM,CAAC;4BACN,gBAAgB,EAAE,CAAC;wBACrB,CAAC;oBACH,CAAC;gBACH,CAAC;qBAAM,CAAC;oBACN,mEAAmE;oBACnE,gBAAgB,EAAE,CAAC;gBACrB,CAAC;YACH,CAAC;YAED,kEAAkE;YAClE,IAAI,cAAc,GAAG,CAAC,IAAI,gBAAgB,GAAG,CAAC,EAAE,CAAC;gBAC/C,OAAO,CAAC,MAAM,CAAC;oBACb,IAAI,EAAE,IAA4B;oBAClC,SAAS,EAAE,mBAAmB;oBAC9B,IAAI,EAAE;wBACJ,SAAS,EAAE,MAAM,CAAC,cAAc,CAAC;wBACjC,WAAW,EAAE,MAAM,CAAC,gBAAgB,CAAC;qBACtC;iBACF,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAED,OAAO;YACL,mBAAmB,EAAE,aAAa;YAClC,kBAAkB,EAAE,aAAa;YACjC,uBAAuB,EAAE,aAAa;SACvC,CAAC;IACJ,CAAC;CACF,CAAC;AAEF,eAAe,yBAAyB,CAAC"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rule: require-jsdoc-example
|
|
3
|
+
*
|
|
4
|
+
* Exported functions must have @example in JSDoc.
|
|
5
|
+
* Examples serve as documentation and can be used for doctest-style testing.
|
|
6
|
+
*/
|
|
7
|
+
function isExported(node) {
|
|
8
|
+
const parent = node.parent;
|
|
9
|
+
if (!parent)
|
|
10
|
+
return false;
|
|
11
|
+
if (parent.type === 'ExportNamedDeclaration')
|
|
12
|
+
return true;
|
|
13
|
+
if (parent.type === 'ExportDefaultDeclaration')
|
|
14
|
+
return true;
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
export const requireJsdocExample = {
|
|
18
|
+
meta: {
|
|
19
|
+
type: 'problem',
|
|
20
|
+
docs: {
|
|
21
|
+
description: 'Exported functions must have @example in JSDoc',
|
|
22
|
+
recommended: true,
|
|
23
|
+
},
|
|
24
|
+
schema: [],
|
|
25
|
+
messages: {
|
|
26
|
+
missingExample: 'Exported function "{{name}}" must have @example in JSDoc (required for doctest)',
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
create(context) {
|
|
30
|
+
function checkFunction(node, name, skipExportCheck = false) {
|
|
31
|
+
if (!name)
|
|
32
|
+
return;
|
|
33
|
+
// Only check export status if not already verified by selector
|
|
34
|
+
if (!skipExportCheck && !isExported(node))
|
|
35
|
+
return;
|
|
36
|
+
// Check for @example in leading comments
|
|
37
|
+
const sourceCode = context.sourceCode || context.getSourceCode();
|
|
38
|
+
const comments = sourceCode.getCommentsBefore(node);
|
|
39
|
+
const hasExample = comments.some(comment => comment.type === 'Block' &&
|
|
40
|
+
comment.value.includes('@example'));
|
|
41
|
+
if (!hasExample) {
|
|
42
|
+
context.report({
|
|
43
|
+
node,
|
|
44
|
+
messageId: 'missingExample',
|
|
45
|
+
data: { name },
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return {
|
|
50
|
+
FunctionDeclaration(node) {
|
|
51
|
+
checkFunction(node, node.id?.name || null);
|
|
52
|
+
},
|
|
53
|
+
// Also check arrow functions assigned to exported variables
|
|
54
|
+
// Selector guarantees this is already exported, so skipExportCheck=true
|
|
55
|
+
'ExportNamedDeclaration > VariableDeclaration > VariableDeclarator > ArrowFunctionExpression'(node) {
|
|
56
|
+
const anyNode = node;
|
|
57
|
+
const name = anyNode.parent?.id?.name || null;
|
|
58
|
+
if (!name)
|
|
59
|
+
return;
|
|
60
|
+
// For exported variables, the JSDoc is typically before the ExportNamedDeclaration,
|
|
61
|
+
// not before the ArrowFunctionExpression
|
|
62
|
+
const sourceCode = context.sourceCode || context.getSourceCode();
|
|
63
|
+
const exportDeclaration = anyNode.parent?.parent?.parent;
|
|
64
|
+
const comments = exportDeclaration?.type === 'ExportNamedDeclaration'
|
|
65
|
+
? sourceCode.getCommentsBefore(exportDeclaration)
|
|
66
|
+
: sourceCode.getCommentsBefore(node);
|
|
67
|
+
const hasExample = comments.some((comment) => comment.type === 'Block' &&
|
|
68
|
+
comment.value.includes('@example'));
|
|
69
|
+
if (!hasExample) {
|
|
70
|
+
context.report({
|
|
71
|
+
node,
|
|
72
|
+
messageId: 'missingExample',
|
|
73
|
+
data: { name },
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
};
|
|
78
|
+
},
|
|
79
|
+
};
|
|
80
|
+
export default requireJsdocExample;
|
|
81
|
+
//# sourceMappingURL=require-jsdoc-example.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"require-jsdoc-example.js","sourceRoot":"","sources":["../../src/rules/require-jsdoc-example.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rule: require-schema-validation
|
|
3
|
+
*
|
|
4
|
+
* Zod-typed parameters must have a corresponding .parse() or .safeParse() call.
|
|
5
|
+
*
|
|
6
|
+
* Supports three modes:
|
|
7
|
+
* - recommended: Warn on missing validation (default)
|
|
8
|
+
* - strict: Error on missing validation
|
|
9
|
+
* - risk-based: Error only for high-risk functions (payment, auth, etc.)
|
|
10
|
+
*/
|
|
11
|
+
const ZOD_TYPE_PATTERNS = [
|
|
12
|
+
/^z\./,
|
|
13
|
+
/ZodType/,
|
|
14
|
+
/z\.infer/,
|
|
15
|
+
/Schema$/,
|
|
16
|
+
];
|
|
17
|
+
// High-risk keywords for risk-based mode
|
|
18
|
+
const RISK_KEYWORDS = [
|
|
19
|
+
'payment',
|
|
20
|
+
'pay',
|
|
21
|
+
'auth',
|
|
22
|
+
'authenticate',
|
|
23
|
+
'login',
|
|
24
|
+
'token',
|
|
25
|
+
'validate',
|
|
26
|
+
'verify',
|
|
27
|
+
'encrypt',
|
|
28
|
+
'decrypt',
|
|
29
|
+
'password',
|
|
30
|
+
'credential',
|
|
31
|
+
'secret',
|
|
32
|
+
];
|
|
33
|
+
/**
|
|
34
|
+
* Check if a function name or path contains high-risk keywords
|
|
35
|
+
*/
|
|
36
|
+
function isHighRiskFunction(functionName, filePath) {
|
|
37
|
+
const combined = `${functionName} ${filePath}`.toLowerCase();
|
|
38
|
+
return RISK_KEYWORDS.some(keyword => combined.includes(keyword));
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Check if file path matches any of the enforceFor patterns.
|
|
42
|
+
* Supports glob-like patterns with wildcards.
|
|
43
|
+
* Protected against ReDoS attacks with pattern length limits.
|
|
44
|
+
*/
|
|
45
|
+
function matchesEnforcePattern(filePath, patterns) {
|
|
46
|
+
if (patterns.length === 0)
|
|
47
|
+
return false;
|
|
48
|
+
const normalizedPath = filePath.replace(/\\/g, '/').toLowerCase();
|
|
49
|
+
for (const pattern of patterns) {
|
|
50
|
+
// Protect against ReDoS: limit pattern length
|
|
51
|
+
if (pattern.length > 200) {
|
|
52
|
+
continue; // Skip overly long patterns
|
|
53
|
+
}
|
|
54
|
+
const normalizedPattern = pattern.replace(/\\/g, '/').toLowerCase();
|
|
55
|
+
// Escape special regex characters except glob wildcards
|
|
56
|
+
const escaped = normalizedPattern.replace(/[.+^${}()|[\]]/g, '\\$&');
|
|
57
|
+
// Convert glob pattern to regex with safe replacements
|
|
58
|
+
// ** matches any directory depth (use reluctant quantifier)
|
|
59
|
+
// * matches any characters except / (use reluctant quantifier)
|
|
60
|
+
const regexPattern = escaped
|
|
61
|
+
.replace(/\\\*\\\*/g, '.*?') // ** → .*? (reluctant)
|
|
62
|
+
.replace(/\\\*/g, '[^/]*?') // * → [^/]*? (reluctant)
|
|
63
|
+
.replace(/\\\?/g, '.'); // ? → .
|
|
64
|
+
try {
|
|
65
|
+
const regex = new RegExp(`^${regexPattern}$`);
|
|
66
|
+
if (regex.test(normalizedPath)) {
|
|
67
|
+
return true;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
catch (e) {
|
|
71
|
+
// Invalid regex from pattern - skip
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
function isZodType(typeAnnotation) {
|
|
78
|
+
return ZOD_TYPE_PATTERNS.some(pattern => pattern.test(typeAnnotation));
|
|
79
|
+
}
|
|
80
|
+
function hasParseCall(body, paramName) {
|
|
81
|
+
if (!body)
|
|
82
|
+
return false;
|
|
83
|
+
let found = false;
|
|
84
|
+
const MAX_DEPTH = 50; // Prevent stack overflow on deeply nested types
|
|
85
|
+
const visit = (node, depth = 0) => {
|
|
86
|
+
if (found)
|
|
87
|
+
return;
|
|
88
|
+
if (depth > MAX_DEPTH)
|
|
89
|
+
return; // Depth limit to prevent stack overflow
|
|
90
|
+
if (node.type === 'CallExpression') {
|
|
91
|
+
const callee = node.callee;
|
|
92
|
+
if (callee.type === 'MemberExpression') {
|
|
93
|
+
const property = callee.property;
|
|
94
|
+
if (property.type === 'Identifier' &&
|
|
95
|
+
(property.name === 'parse' || property.name === 'safeParse')) {
|
|
96
|
+
// Check if argument is our param
|
|
97
|
+
if (node.arguments.some(arg => arg.type === 'Identifier' && arg.name === paramName)) {
|
|
98
|
+
found = true;
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
// Recursively visit children with depth tracking
|
|
105
|
+
for (const key of Object.keys(node)) {
|
|
106
|
+
const value = node[key];
|
|
107
|
+
if (value && typeof value === 'object') {
|
|
108
|
+
if (Array.isArray(value)) {
|
|
109
|
+
for (const item of value) {
|
|
110
|
+
if (item && typeof item === 'object' && 'type' in item) {
|
|
111
|
+
visit(item, depth + 1);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
else if ('type' in value) {
|
|
116
|
+
visit(value, depth + 1);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
};
|
|
121
|
+
visit(body);
|
|
122
|
+
return found;
|
|
123
|
+
}
|
|
124
|
+
export const requireSchemaValidation = {
|
|
125
|
+
meta: {
|
|
126
|
+
type: 'problem',
|
|
127
|
+
docs: {
|
|
128
|
+
description: 'Require .parse() call for Zod-typed parameters',
|
|
129
|
+
recommended: true,
|
|
130
|
+
},
|
|
131
|
+
hasSuggestions: true,
|
|
132
|
+
schema: [
|
|
133
|
+
{
|
|
134
|
+
type: 'object',
|
|
135
|
+
properties: {
|
|
136
|
+
mode: {
|
|
137
|
+
type: 'string',
|
|
138
|
+
enum: ['recommended', 'strict', 'risk-based'],
|
|
139
|
+
default: 'recommended',
|
|
140
|
+
},
|
|
141
|
+
enforceFor: {
|
|
142
|
+
type: 'array',
|
|
143
|
+
items: {
|
|
144
|
+
type: 'string',
|
|
145
|
+
},
|
|
146
|
+
default: [],
|
|
147
|
+
},
|
|
148
|
+
},
|
|
149
|
+
additionalProperties: false,
|
|
150
|
+
},
|
|
151
|
+
],
|
|
152
|
+
messages: {
|
|
153
|
+
missingValidation: 'Parameter "{{name}}" has Zod type but no .parse() or .safeParse() call',
|
|
154
|
+
missingValidationRisk: 'High-risk function "{{functionName}}": Parameter "{{name}}" has Zod type but no .parse() or .safeParse() call',
|
|
155
|
+
addParseCall: 'Add .parse() validation for "{{name}}"',
|
|
156
|
+
},
|
|
157
|
+
},
|
|
158
|
+
create(context) {
|
|
159
|
+
const sourceCode = context.sourceCode || context.getSourceCode();
|
|
160
|
+
const options = context.options[0] || {};
|
|
161
|
+
const mode = options.mode || 'recommended';
|
|
162
|
+
const enforceFor = options.enforceFor || [];
|
|
163
|
+
const filename = context.filename || context.getFilename();
|
|
164
|
+
/**
|
|
165
|
+
* Get the text of a type annotation from source code.
|
|
166
|
+
* Strips the leading ": " to return just the type.
|
|
167
|
+
*/
|
|
168
|
+
function getTypeAnnotationText(param) {
|
|
169
|
+
const typedParam = param;
|
|
170
|
+
if (!typedParam.typeAnnotation)
|
|
171
|
+
return null;
|
|
172
|
+
const text = sourceCode.getText(typedParam.typeAnnotation);
|
|
173
|
+
// Strip leading ": " from type annotation
|
|
174
|
+
return text.replace(/^:\s*/, '');
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Get function name from node
|
|
178
|
+
*/
|
|
179
|
+
function getFunctionName(node) {
|
|
180
|
+
if (node.type === 'FunctionDeclaration' && node.id) {
|
|
181
|
+
return node.id.name;
|
|
182
|
+
}
|
|
183
|
+
// For arrow functions, try to get name from parent variable declarator
|
|
184
|
+
return 'anonymous';
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Determine if this function should be checked based on mode and options
|
|
188
|
+
*/
|
|
189
|
+
function shouldCheck(functionName) {
|
|
190
|
+
if (mode === 'strict') {
|
|
191
|
+
return true; // Always check in strict mode
|
|
192
|
+
}
|
|
193
|
+
if (mode === 'risk-based') {
|
|
194
|
+
// Check if function is high-risk by name/path
|
|
195
|
+
if (isHighRiskFunction(functionName, filename)) {
|
|
196
|
+
return true;
|
|
197
|
+
}
|
|
198
|
+
// Check if file path matches enforceFor patterns
|
|
199
|
+
if (matchesEnforcePattern(filename, enforceFor)) {
|
|
200
|
+
return true;
|
|
201
|
+
}
|
|
202
|
+
return false;
|
|
203
|
+
}
|
|
204
|
+
// recommended mode - always check (but will warn instead of error)
|
|
205
|
+
return true;
|
|
206
|
+
}
|
|
207
|
+
function checkFunction(node, params) {
|
|
208
|
+
const functionName = getFunctionName(node);
|
|
209
|
+
// Skip if shouldn't check based on mode
|
|
210
|
+
if (!shouldCheck(functionName)) {
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
const body = 'body' in node ? node.body : null;
|
|
214
|
+
const isRiskFunction = isHighRiskFunction(functionName, filename);
|
|
215
|
+
for (const param of params) {
|
|
216
|
+
if (param.typeAnnotation && isZodType(param.typeAnnotation)) {
|
|
217
|
+
if (!hasParseCall(body, param.name)) {
|
|
218
|
+
// Extract schema name from type annotation (e.g., "z.infer<typeof UserSchema>" -> "UserSchema")
|
|
219
|
+
const schemaMatch = param.typeAnnotation.match(/typeof\s+(\w+)/);
|
|
220
|
+
const schemaName = schemaMatch ? schemaMatch[1] : 'Schema';
|
|
221
|
+
const validatedVarName = `validated${param.name.charAt(0).toUpperCase()}${param.name.slice(1)}`;
|
|
222
|
+
context.report({
|
|
223
|
+
node: node,
|
|
224
|
+
messageId: isRiskFunction ? 'missingValidationRisk' : 'missingValidation',
|
|
225
|
+
data: {
|
|
226
|
+
name: param.name,
|
|
227
|
+
functionName: functionName,
|
|
228
|
+
},
|
|
229
|
+
suggest: [
|
|
230
|
+
{
|
|
231
|
+
messageId: 'addParseCall',
|
|
232
|
+
data: { name: param.name },
|
|
233
|
+
fix(fixer) {
|
|
234
|
+
// Find the opening brace of the function body
|
|
235
|
+
if (!body || body.type !== 'BlockStatement')
|
|
236
|
+
return null;
|
|
237
|
+
const blockBody = body;
|
|
238
|
+
if (!blockBody.body || blockBody.body.length === 0)
|
|
239
|
+
return null;
|
|
240
|
+
const firstStatement = blockBody.body[0];
|
|
241
|
+
// Detect indentation from the first statement
|
|
242
|
+
const firstStatementStart = firstStatement.loc?.start.column ?? 2;
|
|
243
|
+
const indent = ' '.repeat(firstStatementStart);
|
|
244
|
+
const parseCode = `const ${validatedVarName} = ${schemaName}.parse(${param.name});\n${indent}`;
|
|
245
|
+
return fixer.insertTextBefore(firstStatement, parseCode);
|
|
246
|
+
},
|
|
247
|
+
},
|
|
248
|
+
],
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* Extract param name and type annotation from various param patterns.
|
|
256
|
+
*/
|
|
257
|
+
function extractParamInfo(param) {
|
|
258
|
+
if (param.type === 'Identifier') {
|
|
259
|
+
return {
|
|
260
|
+
name: param.name,
|
|
261
|
+
typeAnnotation: getTypeAnnotationText(param),
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
// Handle destructuring patterns: { a, b }: ZodSchema
|
|
265
|
+
if (param.type === 'ObjectPattern' || param.type === 'ArrayPattern') {
|
|
266
|
+
// For destructuring, we use a placeholder name and check the pattern's type
|
|
267
|
+
const patternName = param.type === 'ObjectPattern' ? '{...}' : '[...]';
|
|
268
|
+
return {
|
|
269
|
+
name: patternName,
|
|
270
|
+
typeAnnotation: getTypeAnnotationText(param),
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
// Handle rest parameters: ...args: ZodSchema[]
|
|
274
|
+
if (param.type === 'RestElement') {
|
|
275
|
+
const restParam = param;
|
|
276
|
+
const name = restParam.argument?.name || '...rest';
|
|
277
|
+
return {
|
|
278
|
+
name,
|
|
279
|
+
typeAnnotation: getTypeAnnotationText(param),
|
|
280
|
+
};
|
|
281
|
+
}
|
|
282
|
+
// Handle assignment patterns: param = default
|
|
283
|
+
if (param.type === 'AssignmentPattern') {
|
|
284
|
+
const assignParam = param;
|
|
285
|
+
if (assignParam.left) {
|
|
286
|
+
return extractParamInfo(assignParam.left);
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
return null;
|
|
290
|
+
}
|
|
291
|
+
return {
|
|
292
|
+
FunctionDeclaration(node) {
|
|
293
|
+
const params = node.params
|
|
294
|
+
.map(p => extractParamInfo(p))
|
|
295
|
+
.filter((p) => p !== null);
|
|
296
|
+
checkFunction(node, params);
|
|
297
|
+
},
|
|
298
|
+
ArrowFunctionExpression(node) {
|
|
299
|
+
const params = node.params
|
|
300
|
+
.map(p => extractParamInfo(p))
|
|
301
|
+
.filter((p) => p !== null);
|
|
302
|
+
checkFunction(node, params);
|
|
303
|
+
},
|
|
304
|
+
};
|
|
305
|
+
},
|
|
306
|
+
};
|
|
307
|
+
export default requireSchemaValidation;
|
|
308
|
+
//# sourceMappingURL=require-schema-validation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"require-schema-validation.js","sourceRoot":"","sources":["../../src/rules/require-schema-validation.ts"],"names":[],"mappings":"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"}
|