@clipboard-health/eslint-plugin 2.7.2 → 2.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/index.d.ts +3 -0
- package/src/index.js +2 -0
- package/src/index.js.map +1 -1
- package/src/lib/rules/require-contract-response-parse/index.d.ts +23 -0
- package/src/lib/rules/require-contract-response-parse/index.js +377 -0
- package/src/lib/rules/require-contract-response-parse/index.js.map +1 -0
package/package.json
CHANGED
package/src/index.d.ts
CHANGED
|
@@ -5,6 +5,9 @@ export declare const rules: {
|
|
|
5
5
|
"no-cross-contract-imports": import("@typescript-eslint/utils/ts-eslint").RuleModule<"noCrossContractImport", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
|
|
6
6
|
name: string;
|
|
7
7
|
};
|
|
8
|
+
"require-contract-response-parse": import("@typescript-eslint/utils/ts-eslint").RuleModule<"inlineAnySchema" | "missingContractParse" | "nonContractSchema", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
|
|
9
|
+
name: string;
|
|
10
|
+
};
|
|
8
11
|
"require-http-module-factory": import("@typescript-eslint/utils/ts-eslint").RuleModule<"noImport" | "requireFactory" | "wrongPackage", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
|
|
9
12
|
name: string;
|
|
10
13
|
};
|
package/src/index.js
CHANGED
|
@@ -4,12 +4,14 @@ exports.rules = void 0;
|
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const enforce_ts_rest_in_controllers_1 = tslib_1.__importDefault(require("./lib/rules/enforce-ts-rest-in-controllers"));
|
|
6
6
|
const no_cross_contract_imports_1 = tslib_1.__importDefault(require("./lib/rules/no-cross-contract-imports"));
|
|
7
|
+
const require_contract_response_parse_1 = tslib_1.__importDefault(require("./lib/rules/require-contract-response-parse"));
|
|
7
8
|
const require_http_module_factory_1 = tslib_1.__importDefault(require("./lib/rules/require-http-module-factory"));
|
|
8
9
|
const require_run_validators_with_upsert_1 = tslib_1.__importDefault(require("./lib/rules/require-run-validators-with-upsert"));
|
|
9
10
|
const require_zod_import_in_contracts_1 = tslib_1.__importDefault(require("./lib/rules/require-zod-import-in-contracts"));
|
|
10
11
|
exports.rules = {
|
|
11
12
|
"enforce-ts-rest-in-controllers": enforce_ts_rest_in_controllers_1.default,
|
|
12
13
|
"no-cross-contract-imports": no_cross_contract_imports_1.default,
|
|
14
|
+
"require-contract-response-parse": require_contract_response_parse_1.default,
|
|
13
15
|
"require-http-module-factory": require_http_module_factory_1.default,
|
|
14
16
|
"require-run-validators-with-upsert": require_run_validators_with_upsert_1.default,
|
|
15
17
|
"require-zod-import-in-contracts": require_zod_import_in_contracts_1.default,
|
package/src/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../packages/eslint-plugin/src/index.ts"],"names":[],"mappings":";;;;AAAA,wHAAoF;AACpF,8GAA2E;AAC3E,kHAA+E;AAC/E,gIAA4F;AAC5F,0HAAsF;AAEzE,QAAA,KAAK,GAAG;IACnB,gCAAgC,EAAE,wCAA0B;IAC5D,2BAA2B,EAAE,mCAAsB;IACnD,6BAA6B,EAAE,qCAAwB;IACvD,oCAAoC,EAAE,4CAA8B;IACpE,iCAAiC,EAAE,yCAA2B;CAC/D,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../packages/eslint-plugin/src/index.ts"],"names":[],"mappings":";;;;AAAA,wHAAoF;AACpF,8GAA2E;AAC3E,0HAAuF;AACvF,kHAA+E;AAC/E,gIAA4F;AAC5F,0HAAsF;AAEzE,QAAA,KAAK,GAAG;IACnB,gCAAgC,EAAE,wCAA0B;IAC5D,2BAA2B,EAAE,mCAAsB;IACnD,iCAAiC,EAAE,yCAA4B;IAC/D,6BAA6B,EAAE,qCAAwB;IACvD,oCAAoC,EAAE,4CAA8B;IACpE,iCAAiC,EAAE,yCAA2B;CAC/D,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Require contract-package response schemas before response-shape assertions.
|
|
3
|
+
*
|
|
4
|
+
* Migration playbook:
|
|
5
|
+
* 1. Find the endpoint in its `@clipboard-health/contract-*` package and use the schema for the
|
|
6
|
+
* asserted status code, commonly `contract.endpoint.responses[status]` or an exported
|
|
7
|
+
* `XResponseSchema`.
|
|
8
|
+
* 2. Parse before shape assertions with `parseBody(response, schema)` or
|
|
9
|
+
* `schema.parse(response.parsedBody)`, then assert on the parsed value.
|
|
10
|
+
* 3. If the contract package has no response schema, file a contract-gap ticket and add the schema
|
|
11
|
+
* there. An inline permissive schema or ESLint exemption is not a contract oracle.
|
|
12
|
+
*
|
|
13
|
+
* Warn-to-error ratchet:
|
|
14
|
+
* Enable the rule as a warning across the migration scope. Migrate one directory at a time and add
|
|
15
|
+
* an error-level override for each completed directory. CI may suppress the warning backlog with
|
|
16
|
+
* `--quiet`, making every error-level directory a blocking ratchet. Once the full scope is migrated,
|
|
17
|
+
* replace the overrides with one error-level setting and restore the zero-warning budget.
|
|
18
|
+
*/
|
|
19
|
+
import { type TSESLint } from "@typescript-eslint/utils";
|
|
20
|
+
declare const rule: TSESLint.RuleModule<"inlineAnySchema" | "missingContractParse" | "nonContractSchema", [], unknown, TSESLint.RuleListener> & {
|
|
21
|
+
name: string;
|
|
22
|
+
};
|
|
23
|
+
export default rule;
|
|
@@ -0,0 +1,377 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
/**
|
|
4
|
+
* @fileoverview Require contract-package response schemas before response-shape assertions.
|
|
5
|
+
*
|
|
6
|
+
* Migration playbook:
|
|
7
|
+
* 1. Find the endpoint in its `@clipboard-health/contract-*` package and use the schema for the
|
|
8
|
+
* asserted status code, commonly `contract.endpoint.responses[status]` or an exported
|
|
9
|
+
* `XResponseSchema`.
|
|
10
|
+
* 2. Parse before shape assertions with `parseBody(response, schema)` or
|
|
11
|
+
* `schema.parse(response.parsedBody)`, then assert on the parsed value.
|
|
12
|
+
* 3. If the contract package has no response schema, file a contract-gap ticket and add the schema
|
|
13
|
+
* there. An inline permissive schema or ESLint exemption is not a contract oracle.
|
|
14
|
+
*
|
|
15
|
+
* Warn-to-error ratchet:
|
|
16
|
+
* Enable the rule as a warning across the migration scope. Migrate one directory at a time and add
|
|
17
|
+
* an error-level override for each completed directory. CI may suppress the warning backlog with
|
|
18
|
+
* `--quiet`, making every error-level directory a blocking ratchet. Once the full scope is migrated,
|
|
19
|
+
* replace the overrides with one error-level setting and restore the zero-warning budget.
|
|
20
|
+
*/
|
|
21
|
+
const utils_1 = require("@typescript-eslint/utils");
|
|
22
|
+
const createRule_1 = require("../../createRule");
|
|
23
|
+
const CONTRACT_PACKAGE_PREFIX = "@clipboard-health/contract-";
|
|
24
|
+
const ANY_SCHEMA_METHODS = new Set(["any", "unknown"]);
|
|
25
|
+
const SCHEMA_PARSE_METHODS = new Set(["parse", "parseAsync"]);
|
|
26
|
+
const MATCHER_MODIFIERS = new Set(["not", "rejects", "resolves"]);
|
|
27
|
+
const CONTROL_FLOW_TYPES = new Set([
|
|
28
|
+
utils_1.AST_NODE_TYPES.CatchClause,
|
|
29
|
+
utils_1.AST_NODE_TYPES.ConditionalExpression,
|
|
30
|
+
utils_1.AST_NODE_TYPES.DoWhileStatement,
|
|
31
|
+
utils_1.AST_NODE_TYPES.ForInStatement,
|
|
32
|
+
utils_1.AST_NODE_TYPES.ForOfStatement,
|
|
33
|
+
utils_1.AST_NODE_TYPES.ForStatement,
|
|
34
|
+
utils_1.AST_NODE_TYPES.IfStatement,
|
|
35
|
+
utils_1.AST_NODE_TYPES.LogicalExpression,
|
|
36
|
+
utils_1.AST_NODE_TYPES.SwitchCase,
|
|
37
|
+
utils_1.AST_NODE_TYPES.SwitchStatement,
|
|
38
|
+
utils_1.AST_NODE_TYPES.TryStatement,
|
|
39
|
+
utils_1.AST_NODE_TYPES.WhileStatement,
|
|
40
|
+
]);
|
|
41
|
+
function unwrap(node) {
|
|
42
|
+
let current = node;
|
|
43
|
+
while (current?.type === utils_1.AST_NODE_TYPES.ChainExpression ||
|
|
44
|
+
current?.type === utils_1.AST_NODE_TYPES.TSAsExpression ||
|
|
45
|
+
current?.type === utils_1.AST_NODE_TYPES.TSInstantiationExpression ||
|
|
46
|
+
current?.type === utils_1.AST_NODE_TYPES.TSNonNullExpression ||
|
|
47
|
+
current?.type === utils_1.AST_NODE_TYPES.TSSatisfiesExpression ||
|
|
48
|
+
current?.type === utils_1.AST_NODE_TYPES.TSTypeAssertion) {
|
|
49
|
+
current = current.expression;
|
|
50
|
+
}
|
|
51
|
+
return current;
|
|
52
|
+
}
|
|
53
|
+
function memberPropertyName(node) {
|
|
54
|
+
if (!node.computed && node.property.type === utils_1.AST_NODE_TYPES.Identifier) {
|
|
55
|
+
return node.property.name;
|
|
56
|
+
}
|
|
57
|
+
if (node.computed && node.property.type === utils_1.AST_NODE_TYPES.Literal) {
|
|
58
|
+
return typeof node.property.value === "string" ? node.property.value : undefined;
|
|
59
|
+
}
|
|
60
|
+
return undefined;
|
|
61
|
+
}
|
|
62
|
+
function containingFunction(node) {
|
|
63
|
+
let current = node.parent;
|
|
64
|
+
while (current) {
|
|
65
|
+
if (current.type === utils_1.AST_NODE_TYPES.ArrowFunctionExpression ||
|
|
66
|
+
current.type === utils_1.AST_NODE_TYPES.FunctionDeclaration ||
|
|
67
|
+
current.type === utils_1.AST_NODE_TYPES.FunctionExpression) {
|
|
68
|
+
return current;
|
|
69
|
+
}
|
|
70
|
+
current = current.parent;
|
|
71
|
+
}
|
|
72
|
+
return undefined;
|
|
73
|
+
}
|
|
74
|
+
function addEvidence(collection, key, node) {
|
|
75
|
+
const nodes = collection.get(key) ?? [];
|
|
76
|
+
nodes.push(node);
|
|
77
|
+
collection.set(key, nodes);
|
|
78
|
+
}
|
|
79
|
+
function isAncestor(ancestor, node) {
|
|
80
|
+
let current = node;
|
|
81
|
+
while (current) {
|
|
82
|
+
if (current === ancestor) {
|
|
83
|
+
return true;
|
|
84
|
+
}
|
|
85
|
+
current = current.parent;
|
|
86
|
+
}
|
|
87
|
+
return false;
|
|
88
|
+
}
|
|
89
|
+
function directChild(ancestor, node) {
|
|
90
|
+
let current = node;
|
|
91
|
+
while (current?.parent && current.parent !== ancestor) {
|
|
92
|
+
current = current.parent;
|
|
93
|
+
}
|
|
94
|
+
return current?.parent === ancestor ? current : undefined;
|
|
95
|
+
}
|
|
96
|
+
function objectContainsParsedBodyProperty(node) {
|
|
97
|
+
if (node?.type !== utils_1.AST_NODE_TYPES.ObjectExpression) {
|
|
98
|
+
return false;
|
|
99
|
+
}
|
|
100
|
+
return node.properties.some((property) => {
|
|
101
|
+
if (property.type !== utils_1.AST_NODE_TYPES.Property) {
|
|
102
|
+
return false;
|
|
103
|
+
}
|
|
104
|
+
const propertyName = property.key.type === utils_1.AST_NODE_TYPES.Identifier
|
|
105
|
+
? property.key.name
|
|
106
|
+
: property.key.type === utils_1.AST_NODE_TYPES.Literal
|
|
107
|
+
? property.key.value
|
|
108
|
+
: undefined;
|
|
109
|
+
return propertyName === "parsedBody" || objectContainsParsedBodyProperty(property.value);
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
function isParsedBodyPropertyPath(node) {
|
|
113
|
+
if (node?.type === utils_1.AST_NODE_TYPES.Literal && typeof node.value === "string") {
|
|
114
|
+
return /^parsedBody(?:\.|\[|$)/u.test(node.value);
|
|
115
|
+
}
|
|
116
|
+
return (node?.type === utils_1.AST_NODE_TYPES.ArrayExpression &&
|
|
117
|
+
node.elements[0]?.type === utils_1.AST_NODE_TYPES.Literal &&
|
|
118
|
+
node.elements[0].value === "parsedBody");
|
|
119
|
+
}
|
|
120
|
+
const rule = (0, createRule_1.createRule)({
|
|
121
|
+
name: "require-contract-response-parse",
|
|
122
|
+
defaultOptions: [],
|
|
123
|
+
meta: {
|
|
124
|
+
type: "problem",
|
|
125
|
+
docs: {
|
|
126
|
+
description: "Require response assertions to use contract-package schemas",
|
|
127
|
+
},
|
|
128
|
+
schema: [],
|
|
129
|
+
messages: {
|
|
130
|
+
inlineAnySchema: "Inline z.{{method}}() schemas are not contract oracles. Use the endpoint response schema from a @clipboard-health/contract-* package.",
|
|
131
|
+
missingContractParse: "Parse this response body with its @clipboard-health/contract-* response schema before asserting its shape.",
|
|
132
|
+
nonContractSchema: "This schema is not a contract oracle. Use the endpoint response schema from a @clipboard-health/contract-* package.",
|
|
133
|
+
},
|
|
134
|
+
},
|
|
135
|
+
create(context) {
|
|
136
|
+
const contractBindings = new Set();
|
|
137
|
+
const zodBindings = new Set();
|
|
138
|
+
const functionStates = new Map();
|
|
139
|
+
const topLevelState = { parses: new Map(), writes: new Map() };
|
|
140
|
+
const validatedParsedBodyAccesses = new WeakSet();
|
|
141
|
+
function rootIdentifier(node) {
|
|
142
|
+
let current = unwrap(node);
|
|
143
|
+
while (current?.type === utils_1.AST_NODE_TYPES.MemberExpression) {
|
|
144
|
+
current = unwrap(current.object);
|
|
145
|
+
}
|
|
146
|
+
return current?.type === utils_1.AST_NODE_TYPES.Identifier ? current : undefined;
|
|
147
|
+
}
|
|
148
|
+
function parsedBodyAccess(node) {
|
|
149
|
+
let current = unwrap(node);
|
|
150
|
+
while (current?.type === utils_1.AST_NODE_TYPES.MemberExpression) {
|
|
151
|
+
if (memberPropertyName(current) === "parsedBody") {
|
|
152
|
+
return current;
|
|
153
|
+
}
|
|
154
|
+
current = unwrap(current.object);
|
|
155
|
+
}
|
|
156
|
+
return undefined;
|
|
157
|
+
}
|
|
158
|
+
function findVariable(node) {
|
|
159
|
+
return utils_1.ASTUtils.findVariable(context.sourceCode.getScope(node), node) ?? undefined;
|
|
160
|
+
}
|
|
161
|
+
function responseKey(node) {
|
|
162
|
+
const current = unwrap(node);
|
|
163
|
+
if (current?.type === utils_1.AST_NODE_TYPES.Identifier) {
|
|
164
|
+
return findVariable(current) ?? current.name;
|
|
165
|
+
}
|
|
166
|
+
if (current?.type === utils_1.AST_NODE_TYPES.MemberExpression) {
|
|
167
|
+
return context.sourceCode.getText(current);
|
|
168
|
+
}
|
|
169
|
+
return undefined;
|
|
170
|
+
}
|
|
171
|
+
function isContractSchema(node) {
|
|
172
|
+
const identifier = rootIdentifier(node);
|
|
173
|
+
if (!identifier) {
|
|
174
|
+
return false;
|
|
175
|
+
}
|
|
176
|
+
const variable = findVariable(identifier);
|
|
177
|
+
return variable !== undefined && contractBindings.has(variable);
|
|
178
|
+
}
|
|
179
|
+
function stateFor(node) {
|
|
180
|
+
const functionNode = containingFunction(node);
|
|
181
|
+
if (!functionNode) {
|
|
182
|
+
return topLevelState;
|
|
183
|
+
}
|
|
184
|
+
const existingState = functionStates.get(functionNode);
|
|
185
|
+
if (existingState) {
|
|
186
|
+
return existingState;
|
|
187
|
+
}
|
|
188
|
+
const state = { parses: new Map(), writes: new Map() };
|
|
189
|
+
functionStates.set(functionNode, state);
|
|
190
|
+
return state;
|
|
191
|
+
}
|
|
192
|
+
function parseDominatesAssertion(parseNode, assertionNode) {
|
|
193
|
+
if (containingFunction(parseNode) !== containingFunction(assertionNode) ||
|
|
194
|
+
parseNode.range[0] >= assertionNode.range[0]) {
|
|
195
|
+
return false;
|
|
196
|
+
}
|
|
197
|
+
let current = parseNode.parent;
|
|
198
|
+
const functionNode = containingFunction(parseNode);
|
|
199
|
+
while (current && current !== functionNode) {
|
|
200
|
+
if (CONTROL_FLOW_TYPES.has(current.type) &&
|
|
201
|
+
(!isAncestor(current, assertionNode) ||
|
|
202
|
+
directChild(current, parseNode) !== directChild(current, assertionNode))) {
|
|
203
|
+
return false;
|
|
204
|
+
}
|
|
205
|
+
current = current.parent;
|
|
206
|
+
}
|
|
207
|
+
return true;
|
|
208
|
+
}
|
|
209
|
+
function hasContractParse(node, key) {
|
|
210
|
+
const state = stateFor(node);
|
|
211
|
+
const parses = state.parses.get(key) ?? [];
|
|
212
|
+
const writes = state.writes.get(key) ?? [];
|
|
213
|
+
return parses.some((parseNode) => parseDominatesAssertion(parseNode, node) &&
|
|
214
|
+
!writes.some((writeNode) => writeNode.range[0] > parseNode.range[1] && writeNode.range[0] < node.range[0]));
|
|
215
|
+
}
|
|
216
|
+
function recordResponseWrite(node, expression) {
|
|
217
|
+
const key = responseKey(expression);
|
|
218
|
+
if (key !== undefined) {
|
|
219
|
+
addEvidence(stateFor(node).writes, key, node);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
function checkParseBody(node) {
|
|
223
|
+
if (node.callee.type !== utils_1.AST_NODE_TYPES.Identifier || node.callee.name !== "parseBody") {
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
const [response, schema] = node.arguments;
|
|
227
|
+
if (!response || !schema) {
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
if (!isContractSchema(schema)) {
|
|
231
|
+
context.report({ node: schema, messageId: "nonContractSchema" });
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
const key = responseKey(response);
|
|
235
|
+
if (key !== undefined) {
|
|
236
|
+
addEvidence(stateFor(node).parses, key, node);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
function checkSchemaParse(node) {
|
|
240
|
+
if (node.callee.type !== utils_1.AST_NODE_TYPES.MemberExpression ||
|
|
241
|
+
!SCHEMA_PARSE_METHODS.has(memberPropertyName(node.callee) ?? "") ||
|
|
242
|
+
!isContractSchema(node.callee.object)) {
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
const argument = unwrap(node.arguments[0]);
|
|
246
|
+
const access = parsedBodyAccess(argument);
|
|
247
|
+
if (!access || argument !== access) {
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
validatedParsedBodyAccesses.add(access);
|
|
251
|
+
const key = responseKey(access.object);
|
|
252
|
+
if (key !== undefined) {
|
|
253
|
+
addEvidence(stateFor(node).parses, key, node);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
function checkParsedBodyAccess(node) {
|
|
257
|
+
if (memberPropertyName(node) !== "parsedBody" || validatedParsedBodyAccesses.has(node)) {
|
|
258
|
+
return;
|
|
259
|
+
}
|
|
260
|
+
const key = responseKey(node.object);
|
|
261
|
+
if (key === undefined || !hasContractParse(node, key)) {
|
|
262
|
+
context.report({ node, messageId: "missingContractParse" });
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
function expectCall(node) {
|
|
266
|
+
if (node.callee.type !== utils_1.AST_NODE_TYPES.MemberExpression) {
|
|
267
|
+
return undefined;
|
|
268
|
+
}
|
|
269
|
+
let matcherTarget = node.callee.object;
|
|
270
|
+
while (matcherTarget.type === utils_1.AST_NODE_TYPES.MemberExpression &&
|
|
271
|
+
MATCHER_MODIFIERS.has(memberPropertyName(matcherTarget) ?? "")) {
|
|
272
|
+
matcherTarget = matcherTarget.object;
|
|
273
|
+
}
|
|
274
|
+
if (matcherTarget.type !== utils_1.AST_NODE_TYPES.CallExpression ||
|
|
275
|
+
matcherTarget.callee.type !== utils_1.AST_NODE_TYPES.Identifier ||
|
|
276
|
+
matcherTarget.callee.name !== "expect") {
|
|
277
|
+
return undefined;
|
|
278
|
+
}
|
|
279
|
+
return matcherTarget;
|
|
280
|
+
}
|
|
281
|
+
function checkWholeResponseAssertion(node) {
|
|
282
|
+
const expectation = expectCall(node);
|
|
283
|
+
if (!expectation) {
|
|
284
|
+
return;
|
|
285
|
+
}
|
|
286
|
+
const assertsParsedBodyProperty = node.arguments.some((argument) => objectContainsParsedBodyProperty(argument));
|
|
287
|
+
const matcherName = node.callee.type === utils_1.AST_NODE_TYPES.MemberExpression
|
|
288
|
+
? memberPropertyName(node.callee)
|
|
289
|
+
: undefined;
|
|
290
|
+
const assertsParsedBodyPath = matcherName === "toHaveProperty" && isParsedBodyPropertyPath(node.arguments[0]);
|
|
291
|
+
if (!assertsParsedBodyProperty && !assertsParsedBodyPath) {
|
|
292
|
+
return;
|
|
293
|
+
}
|
|
294
|
+
const key = responseKey(expectation.arguments[0]);
|
|
295
|
+
if (key !== undefined && !hasContractParse(node, key)) {
|
|
296
|
+
context.report({ node: expectation, messageId: "missingContractParse" });
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
function checkParsedBodyDestructuring(node) {
|
|
300
|
+
if (node.id.type !== utils_1.AST_NODE_TYPES.ObjectPattern) {
|
|
301
|
+
return;
|
|
302
|
+
}
|
|
303
|
+
const parsedBodyProperty = node.id.properties.find((property) => {
|
|
304
|
+
if (property.type !== utils_1.AST_NODE_TYPES.Property) {
|
|
305
|
+
return false;
|
|
306
|
+
}
|
|
307
|
+
return ((property.key.type === utils_1.AST_NODE_TYPES.Identifier && property.key.name === "parsedBody") ||
|
|
308
|
+
(property.key.type === utils_1.AST_NODE_TYPES.Literal && property.key.value === "parsedBody"));
|
|
309
|
+
});
|
|
310
|
+
if (!parsedBodyProperty) {
|
|
311
|
+
return;
|
|
312
|
+
}
|
|
313
|
+
const key = responseKey(node.init ?? undefined);
|
|
314
|
+
if (key === undefined || !hasContractParse(node, key)) {
|
|
315
|
+
context.report({ node: parsedBodyProperty, messageId: "missingContractParse" });
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
function checkInlineAnySchema(node) {
|
|
319
|
+
if (node.callee.type !== utils_1.AST_NODE_TYPES.MemberExpression) {
|
|
320
|
+
return;
|
|
321
|
+
}
|
|
322
|
+
const method = memberPropertyName(node.callee);
|
|
323
|
+
const identifier = rootIdentifier(node.callee.object);
|
|
324
|
+
if (!method || !ANY_SCHEMA_METHODS.has(method) || !identifier) {
|
|
325
|
+
return;
|
|
326
|
+
}
|
|
327
|
+
const variable = findVariable(identifier);
|
|
328
|
+
if (variable !== undefined && zodBindings.has(variable)) {
|
|
329
|
+
context.report({ node, messageId: "inlineAnySchema", data: { method } });
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
return {
|
|
333
|
+
ImportDeclaration(node) {
|
|
334
|
+
if (node.source.value.startsWith(CONTRACT_PACKAGE_PREFIX)) {
|
|
335
|
+
for (const specifier of node.specifiers) {
|
|
336
|
+
const [variable] = context.sourceCode.getDeclaredVariables(specifier);
|
|
337
|
+
if (variable) {
|
|
338
|
+
contractBindings.add(variable);
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
if (node.source.value === "zod") {
|
|
343
|
+
for (const specifier of node.specifiers) {
|
|
344
|
+
const importsZodNamespace = specifier.type === utils_1.AST_NODE_TYPES.ImportNamespaceSpecifier;
|
|
345
|
+
const importsZodDefault = specifier.type === utils_1.AST_NODE_TYPES.ImportDefaultSpecifier;
|
|
346
|
+
const importsZodBinding = specifier.type === utils_1.AST_NODE_TYPES.ImportSpecifier &&
|
|
347
|
+
specifier.imported.type === utils_1.AST_NODE_TYPES.Identifier &&
|
|
348
|
+
specifier.imported.name === "z";
|
|
349
|
+
if (!importsZodNamespace && !importsZodDefault && !importsZodBinding) {
|
|
350
|
+
continue;
|
|
351
|
+
}
|
|
352
|
+
const [variable] = context.sourceCode.getDeclaredVariables(specifier);
|
|
353
|
+
if (variable) {
|
|
354
|
+
zodBindings.add(variable);
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
},
|
|
359
|
+
CallExpression(node) {
|
|
360
|
+
checkInlineAnySchema(node);
|
|
361
|
+
checkParseBody(node);
|
|
362
|
+
checkSchemaParse(node);
|
|
363
|
+
checkWholeResponseAssertion(node);
|
|
364
|
+
},
|
|
365
|
+
MemberExpression: checkParsedBodyAccess,
|
|
366
|
+
VariableDeclarator: checkParsedBodyDestructuring,
|
|
367
|
+
AssignmentExpression(node) {
|
|
368
|
+
recordResponseWrite(node, node.left);
|
|
369
|
+
},
|
|
370
|
+
UpdateExpression(node) {
|
|
371
|
+
recordResponseWrite(node, node.argument);
|
|
372
|
+
},
|
|
373
|
+
};
|
|
374
|
+
},
|
|
375
|
+
});
|
|
376
|
+
exports.default = rule;
|
|
377
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../../packages/eslint-plugin/src/lib/rules/require-contract-response-parse/index.ts"],"names":[],"mappings":"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"}
|