@checkdigit/eslint-plugin 7.5.0 → 7.6.0-PR.75-5da1
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/dist-mjs/agent/add-assert-import.mjs +58 -0
- package/dist-mjs/agent/add-base-path-const.mjs +65 -0
- package/dist-mjs/agent/add-base-path-import.mjs +60 -0
- package/dist-mjs/agent/add-url-domain.mjs +61 -0
- package/dist-mjs/agent/agent-test-wiring.mjs +221 -0
- package/dist-mjs/agent/fetch-response-body-json.mjs +146 -0
- package/dist-mjs/agent/fetch-response-header-getter.mjs +117 -0
- package/dist-mjs/agent/fetch-response-status.mjs +66 -0
- package/dist-mjs/agent/fetch-then.mjs +269 -0
- package/dist-mjs/agent/fetch.mjs +38 -0
- package/dist-mjs/agent/file.mjs +43 -0
- package/dist-mjs/agent/fix-function-call-arguments.mjs +153 -0
- package/dist-mjs/agent/no-fixture.mjs +361 -0
- package/dist-mjs/agent/no-mapped-response.mjs +75 -0
- package/dist-mjs/agent/no-service-wrapper.mjs +185 -0
- package/dist-mjs/agent/no-status-code.mjs +59 -0
- package/dist-mjs/agent/no-unused-function-argument.mjs +79 -0
- package/dist-mjs/agent/no-unused-imports.mjs +81 -0
- package/dist-mjs/agent/no-unused-service-variable.mjs +74 -0
- package/dist-mjs/agent/response-reference.mjs +70 -0
- package/dist-mjs/agent/url.mjs +32 -0
- package/dist-mjs/index.mjs +146 -4
- package/dist-types/agent/add-assert-import.d.ts +4 -0
- package/dist-types/agent/add-base-path-const.d.ts +4 -0
- package/dist-types/agent/add-base-path-import.d.ts +4 -0
- package/dist-types/agent/add-url-domain.d.ts +4 -0
- package/dist-types/agent/agent-test-wiring.d.ts +4 -0
- package/dist-types/agent/fetch-response-body-json.d.ts +4 -0
- package/dist-types/agent/fetch-response-header-getter.d.ts +4 -0
- package/dist-types/agent/fetch-response-status.d.ts +4 -0
- package/dist-types/agent/fetch-then.d.ts +4 -0
- package/dist-types/agent/fetch.d.ts +5 -0
- package/dist-types/agent/file.d.ts +7 -0
- package/dist-types/agent/fix-function-call-arguments.d.ts +9 -0
- package/dist-types/agent/no-fixture.d.ts +4 -0
- package/dist-types/agent/no-mapped-response.d.ts +4 -0
- package/dist-types/agent/no-service-wrapper.d.ts +4 -0
- package/dist-types/agent/no-status-code.d.ts +4 -0
- package/dist-types/agent/no-unused-function-argument.d.ts +4 -0
- package/dist-types/agent/no-unused-imports.d.ts +4 -0
- package/dist-types/agent/no-unused-service-variable.d.ts +4 -0
- package/dist-types/agent/response-reference.d.ts +16 -0
- package/dist-types/agent/url.d.ts +4 -0
- package/package.json +1 -96
- package/src/agent/add-assert-import.ts +74 -0
- package/src/agent/add-base-path-const.ts +81 -0
- package/src/agent/add-base-path-import.ts +69 -0
- package/src/agent/add-url-domain.ts +76 -0
- package/src/agent/agent-test-wiring.ts +273 -0
- package/src/agent/fetch-response-body-json.ts +197 -0
- package/src/agent/fetch-response-header-getter.ts +148 -0
- package/src/agent/fetch-response-status.ts +87 -0
- package/src/agent/fetch-then.ts +357 -0
- package/src/agent/fetch.ts +57 -0
- package/src/agent/file.ts +42 -0
- package/src/agent/fix-function-call-arguments.ts +200 -0
- package/src/agent/no-fixture.ts +521 -0
- package/src/agent/no-mapped-response.ts +84 -0
- package/src/agent/no-service-wrapper.ts +241 -0
- package/src/agent/no-status-code.ts +72 -0
- package/src/agent/no-unused-function-argument.ts +98 -0
- package/src/agent/no-unused-imports.ts +103 -0
- package/src/agent/no-unused-service-variable.ts +93 -0
- package/src/agent/response-reference.ts +129 -0
- package/src/agent/url.ts +32 -0
- package/src/index.ts +142 -0
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
// src/agent/add-assert-import.ts
|
|
2
|
+
import { strict as assert } from "node:assert";
|
|
3
|
+
import { AST_NODE_TYPES, ESLintUtils } from "@typescript-eslint/utils";
|
|
4
|
+
import getDocumentationUrl from "../get-documentation-url.mjs";
|
|
5
|
+
var ruleId = "add-assert-import";
|
|
6
|
+
var ASSERT_IMPORT_STATEMENT = "import { strict as assert } from 'node:assert';";
|
|
7
|
+
var createRule = ESLintUtils.RuleCreator((name) => getDocumentationUrl(name));
|
|
8
|
+
var rule = createRule({
|
|
9
|
+
name: ruleId,
|
|
10
|
+
meta: {
|
|
11
|
+
type: "suggestion",
|
|
12
|
+
docs: {
|
|
13
|
+
description: "Add import of assert module of node."
|
|
14
|
+
},
|
|
15
|
+
messages: {
|
|
16
|
+
addAssertImport: "Add import of assert module of node."
|
|
17
|
+
},
|
|
18
|
+
fixable: "code",
|
|
19
|
+
schema: []
|
|
20
|
+
},
|
|
21
|
+
defaultOptions: [],
|
|
22
|
+
create(context) {
|
|
23
|
+
let isAssertImported = false;
|
|
24
|
+
let isAssertUsed = false;
|
|
25
|
+
return {
|
|
26
|
+
ImportDeclaration: (node) => {
|
|
27
|
+
if (node.source.value === "assert" || node.source.value === "node:assert") {
|
|
28
|
+
isAssertImported = true;
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
CallExpression: (callExpression) => {
|
|
32
|
+
if (callExpression.callee.type === AST_NODE_TYPES.Identifier && callExpression.callee.name === "assert" || callExpression.callee.type === AST_NODE_TYPES.MemberExpression && callExpression.callee.object.type === AST_NODE_TYPES.Identifier && callExpression.callee.object.name === "assert") {
|
|
33
|
+
isAssertUsed = true;
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
"Program:exit": (program) => {
|
|
37
|
+
if (isAssertUsed && !isAssertImported) {
|
|
38
|
+
const firstStatement = program.body[0];
|
|
39
|
+
assert(firstStatement);
|
|
40
|
+
context.report({
|
|
41
|
+
node: program,
|
|
42
|
+
messageId: "addAssertImport",
|
|
43
|
+
fix(fixer) {
|
|
44
|
+
return fixer.insertTextBefore(firstStatement, `${ASSERT_IMPORT_STATEMENT}
|
|
45
|
+
`);
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
var add_assert_import_default = rule;
|
|
54
|
+
export {
|
|
55
|
+
add_assert_import_default as default,
|
|
56
|
+
ruleId
|
|
57
|
+
};
|
|
58
|
+
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vc3JjL2FnZW50L2FkZC1hc3NlcnQtaW1wb3J0LnRzIl0sCiAgIm1hcHBpbmdzIjogIjtBQVFBLFNBQVMsVUFBVSxjQUFjO0FBRWpDLFNBQVMsZ0JBQWdCLG1CQUFtQjtBQUU1QyxPQUFPLHlCQUF5QjtBQUV6QixJQUFNLFNBQVM7QUFFdEIsSUFBTSwwQkFBMEI7QUFFaEMsSUFBTSxhQUFhLFlBQVksWUFBWSxDQUFDLFNBQVMsb0JBQW9CLElBQUksQ0FBQztBQUU5RSxJQUFNLE9BQWtELFdBQVc7QUFBQSxFQUNqRSxNQUFNO0FBQUEsRUFDTixNQUFNO0FBQUEsSUFDSixNQUFNO0FBQUEsSUFDTixNQUFNO0FBQUEsTUFDSixhQUFhO0FBQUEsSUFDZjtBQUFBLElBQ0EsVUFBVTtBQUFBLE1BQ1IsaUJBQWlCO0FBQUEsSUFDbkI7QUFBQSxJQUNBLFNBQVM7QUFBQSxJQUNULFFBQVEsQ0FBQztBQUFBLEVBQ1g7QUFBQSxFQUNBLGdCQUFnQixDQUFDO0FBQUEsRUFDakIsT0FBTyxTQUFTO0FBQ2QsUUFBSSxtQkFBbUI7QUFDdkIsUUFBSSxlQUFlO0FBRW5CLFdBQU87QUFBQSxNQUNMLG1CQUFtQixDQUFDLFNBQVM7QUFDM0IsWUFBSSxLQUFLLE9BQU8sVUFBVSxZQUFZLEtBQUssT0FBTyxVQUFVLGVBQWU7QUFDekUsNkJBQW1CO0FBQUEsUUFDckI7QUFBQSxNQUNGO0FBQUEsTUFDQSxnQkFBZ0IsQ0FBQyxtQkFBbUI7QUFFbEMsWUFDRyxlQUFlLE9BQU8sU0FBUyxlQUFlLGNBQWMsZUFBZSxPQUFPLFNBQVMsWUFDM0YsZUFBZSxPQUFPLFNBQVMsZUFBZSxvQkFDN0MsZUFBZSxPQUFPLE9BQU8sU0FBUyxlQUFlLGNBQ3JELGVBQWUsT0FBTyxPQUFPLFNBQVMsVUFDeEM7QUFDQSx5QkFBZTtBQUFBLFFBQ2pCO0FBQUEsTUFDRjtBQUFBLE1BQ0EsZ0JBQWdCLENBQUMsWUFBWTtBQUUzQixZQUFJLGdCQUFnQixDQUFDLGtCQUFrQjtBQUNyQyxnQkFBTSxpQkFBaUIsUUFBUSxLQUFLLENBQUM7QUFDckMsaUJBQU8sY0FBYztBQUNyQixrQkFBUSxPQUFPO0FBQUEsWUFDYixNQUFNO0FBQUEsWUFDTixXQUFXO0FBQUEsWUFDWCxJQUFJLE9BQU87QUFDVCxxQkFBTyxNQUFNLGlCQUFpQixnQkFBZ0IsR0FBRyx1QkFBdUI7QUFBQSxDQUFJO0FBQUEsWUFDOUU7QUFBQSxVQUNGLENBQUM7QUFBQSxRQUNIO0FBQUEsTUFDRjtBQUFBLElBQ0Y7QUFBQSxFQUNGO0FBQ0YsQ0FBQztBQUVELElBQU8sNEJBQVE7IiwKICAibmFtZXMiOiBbXQp9Cg==
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
// src/agent/add-base-path-const.ts
|
|
2
|
+
import { strict as assert } from "node:assert";
|
|
3
|
+
import { AST_NODE_TYPES, ESLintUtils } from "@typescript-eslint/utils";
|
|
4
|
+
import getDocumentationUrl from "../get-documentation-url.mjs";
|
|
5
|
+
import { getProjectRootFolder, getSwaggerPathByIndexFile, isApiIndexFile, loadPackageJson, loadSwagger } from "./file.mjs";
|
|
6
|
+
var ruleId = "add-base-path-const";
|
|
7
|
+
var createRule = ESLintUtils.RuleCreator((name) => getDocumentationUrl(name));
|
|
8
|
+
var rule = createRule({
|
|
9
|
+
name: ruleId,
|
|
10
|
+
meta: {
|
|
11
|
+
type: "suggestion",
|
|
12
|
+
docs: {
|
|
13
|
+
description: "Add BASE_PATH const variable."
|
|
14
|
+
},
|
|
15
|
+
messages: {
|
|
16
|
+
addBasePathConst: "Add BASE_PATH const variable."
|
|
17
|
+
},
|
|
18
|
+
fixable: "code",
|
|
19
|
+
schema: []
|
|
20
|
+
},
|
|
21
|
+
defaultOptions: [],
|
|
22
|
+
create(context) {
|
|
23
|
+
const sourceCode = context.sourceCode;
|
|
24
|
+
return {
|
|
25
|
+
Program: (program) => {
|
|
26
|
+
if (!isApiIndexFile(context.filename)) {
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
const scope = sourceCode.getScope(program).childScopes[0];
|
|
30
|
+
assert(scope);
|
|
31
|
+
const foundBasePathConst = scope.variables.find((variable) => variable.name === "BASE_PATH");
|
|
32
|
+
if (foundBasePathConst) {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
const swaggerPath = getSwaggerPathByIndexFile(context.filename);
|
|
36
|
+
const swaggerFileContents = loadSwagger(swaggerPath);
|
|
37
|
+
const baseUrlLine = swaggerFileContents.split("\n").find((line) => /^\s*-\s*url:\s*\/.*$/u.test(line) || /^basePath:.*/u.test(line));
|
|
38
|
+
const baseUrl = baseUrlLine?.split(":")[1]?.trim();
|
|
39
|
+
assert(baseUrl !== void 0);
|
|
40
|
+
const packageRoot = getProjectRootFolder(context.filename);
|
|
41
|
+
const packageJson = JSON.parse(loadPackageJson(packageRoot));
|
|
42
|
+
const serviceName = packageJson.name.split("/")[1];
|
|
43
|
+
assert(serviceName !== void 0);
|
|
44
|
+
const domain = `https://${serviceName}.checkdigit${baseUrl}`;
|
|
45
|
+
const lastImportStatement = program.body.findLast((node) => node.type === AST_NODE_TYPES.ImportDeclaration);
|
|
46
|
+
assert(lastImportStatement);
|
|
47
|
+
context.report({
|
|
48
|
+
messageId: "addBasePathConst",
|
|
49
|
+
node: program,
|
|
50
|
+
fix(fixer) {
|
|
51
|
+
return fixer.insertTextAfter(lastImportStatement, `
|
|
52
|
+
export const BASE_PATH = '${domain}';
|
|
53
|
+
`);
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
var add_base_path_const_default = rule;
|
|
61
|
+
export {
|
|
62
|
+
add_base_path_const_default as default,
|
|
63
|
+
ruleId
|
|
64
|
+
};
|
|
65
|
+
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vc3JjL2FnZW50L2FkZC1iYXNlLXBhdGgtY29uc3QudHMiXSwKICAibWFwcGluZ3MiOiAiO0FBUUEsU0FBUyxVQUFVLGNBQWM7QUFFakMsU0FBUyxnQkFBZ0IsbUJBQTZCO0FBRXRELE9BQU8seUJBQXlCO0FBQ2hDLFNBQVMsc0JBQXNCLDJCQUEyQixnQkFBZ0IsaUJBQWlCLG1CQUFtQjtBQUV2RyxJQUFNLFNBQVM7QUFFdEIsSUFBTSxhQUFhLFlBQVksWUFBWSxDQUFDLFNBQVMsb0JBQW9CLElBQUksQ0FBQztBQUU5RSxJQUFNLE9BQW1ELFdBQVc7QUFBQSxFQUNsRSxNQUFNO0FBQUEsRUFDTixNQUFNO0FBQUEsSUFDSixNQUFNO0FBQUEsSUFDTixNQUFNO0FBQUEsTUFDSixhQUFhO0FBQUEsSUFDZjtBQUFBLElBQ0EsVUFBVTtBQUFBLE1BQ1Isa0JBQWtCO0FBQUEsSUFDcEI7QUFBQSxJQUNBLFNBQVM7QUFBQSxJQUNULFFBQVEsQ0FBQztBQUFBLEVBQ1g7QUFBQSxFQUNBLGdCQUFnQixDQUFDO0FBQUEsRUFDakIsT0FBTyxTQUFTO0FBQ2QsVUFBTSxhQUFhLFFBQVE7QUFFM0IsV0FBTztBQUFBLE1BQ0wsU0FBUyxDQUFDLFlBQThCO0FBQ3RDLFlBQUksQ0FBQyxlQUFlLFFBQVEsUUFBUSxHQUFHO0FBQ3JDO0FBQUEsUUFDRjtBQUVBLGNBQU0sUUFBUSxXQUFXLFNBQVMsT0FBTyxFQUFFLFlBQVksQ0FBQztBQUN4RCxlQUFPLEtBQUs7QUFFWixjQUFNLHFCQUFxQixNQUFNLFVBQVUsS0FBSyxDQUFDLGFBQWEsU0FBUyxTQUFTLFdBQVc7QUFDM0YsWUFBSSxvQkFBb0I7QUFDdEI7QUFBQSxRQUNGO0FBRUEsY0FBTSxjQUFjLDBCQUEwQixRQUFRLFFBQVE7QUFDOUQsY0FBTSxzQkFBc0IsWUFBWSxXQUFXO0FBQ25ELGNBQU0sY0FBYyxvQkFDakIsTUFBTSxJQUFJLEVBQ1YsS0FBSyxDQUFDLFNBQVMsd0JBQXdCLEtBQUssSUFBSSxLQUFLLGdCQUFnQixLQUFLLElBQUksQ0FBQztBQUNsRixjQUFNLFVBQVUsYUFBYSxNQUFNLEdBQUcsRUFBRSxDQUFDLEdBQUcsS0FBSztBQUNqRCxlQUFPLFlBQVksTUFBUztBQUU1QixjQUFNLGNBQWMscUJBQXFCLFFBQVEsUUFBUTtBQUN6RCxjQUFNLGNBQWMsS0FBSyxNQUFNLGdCQUFnQixXQUFXLENBQUM7QUFDM0QsY0FBTSxjQUFjLFlBQVksS0FBSyxNQUFNLEdBQUcsRUFBRSxDQUFDO0FBQ2pELGVBQU8sZ0JBQWdCLE1BQVM7QUFFaEMsY0FBTSxTQUFTLFdBQVcsV0FBVyxjQUFjLE9BQU87QUFFMUQsY0FBTSxzQkFBc0IsUUFBUSxLQUFLLFNBQVMsQ0FBQyxTQUFTLEtBQUssU0FBUyxlQUFlLGlCQUFpQjtBQUMxRyxlQUFPLG1CQUFtQjtBQUUxQixnQkFBUSxPQUFPO0FBQUEsVUFDYixXQUFXO0FBQUEsVUFDWCxNQUFNO0FBQUEsVUFDTixJQUFJLE9BQU87QUFDVCxtQkFBTyxNQUFNLGdCQUFnQixxQkFBcUI7QUFBQSw0QkFBK0IsTUFBTTtBQUFBLENBQU07QUFBQSxVQUMvRjtBQUFBLFFBQ0YsQ0FBQztBQUFBLE1BQ0g7QUFBQSxJQUNGO0FBQUEsRUFDRjtBQUNGLENBQUM7QUFFRCxJQUFPLDhCQUFROyIsCiAgIm5hbWVzIjogW10KfQo=
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
// src/agent/add-base-path-import.ts
|
|
2
|
+
import { strict as assert } from "node:assert";
|
|
3
|
+
import { AST_NODE_TYPES, ESLintUtils } from "@typescript-eslint/utils";
|
|
4
|
+
import getDocumentationUrl from "../get-documentation-url.mjs";
|
|
5
|
+
import { getApiIndexPathByFilename } from "./file.mjs";
|
|
6
|
+
var ruleId = "add-base-path-import";
|
|
7
|
+
var createRule = ESLintUtils.RuleCreator((name) => getDocumentationUrl(name));
|
|
8
|
+
var rule = createRule({
|
|
9
|
+
name: ruleId,
|
|
10
|
+
meta: {
|
|
11
|
+
type: "suggestion",
|
|
12
|
+
docs: {
|
|
13
|
+
description: "Add import of BASE_PATH if it is used but not imported."
|
|
14
|
+
},
|
|
15
|
+
messages: {
|
|
16
|
+
addBasePathImport: "Add import of BASE_PATH."
|
|
17
|
+
},
|
|
18
|
+
fixable: "code",
|
|
19
|
+
schema: []
|
|
20
|
+
},
|
|
21
|
+
defaultOptions: [],
|
|
22
|
+
create(context) {
|
|
23
|
+
const sourceCode = context.sourceCode;
|
|
24
|
+
return {
|
|
25
|
+
Program: (program) => {
|
|
26
|
+
const isBasePathUsed = sourceCode.text.includes(`\${BASE_PATH}`);
|
|
27
|
+
if (isBasePathUsed) {
|
|
28
|
+
const topScope = sourceCode.getScope(program).childScopes[0];
|
|
29
|
+
assert(topScope);
|
|
30
|
+
if (topScope.variables.some((variable) => variable.name === "BASE_PATH")) {
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
const apiIndexPath = getApiIndexPathByFilename(context.filename);
|
|
34
|
+
if (apiIndexPath !== void 0) {
|
|
35
|
+
const lastImportStatement = program.body.findLast(
|
|
36
|
+
(statement) => statement.type === AST_NODE_TYPES.ImportDeclaration
|
|
37
|
+
);
|
|
38
|
+
assert(lastImportStatement);
|
|
39
|
+
const basePathImportStatement = `
|
|
40
|
+
import { BASE_PATH } from '${apiIndexPath}';
|
|
41
|
+
`;
|
|
42
|
+
context.report({
|
|
43
|
+
node: program,
|
|
44
|
+
messageId: "addBasePathImport",
|
|
45
|
+
fix(fixer) {
|
|
46
|
+
return fixer.insertTextAfter(lastImportStatement, basePathImportStatement);
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
var add_base_path_import_default = rule;
|
|
56
|
+
export {
|
|
57
|
+
add_base_path_import_default as default,
|
|
58
|
+
ruleId
|
|
59
|
+
};
|
|
60
|
+
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vc3JjL2FnZW50L2FkZC1iYXNlLXBhdGgtaW1wb3J0LnRzIl0sCiAgIm1hcHBpbmdzIjogIjtBQVFBLFNBQVMsVUFBVSxjQUFjO0FBRWpDLFNBQVMsZ0JBQWdCLG1CQUFtQjtBQUU1QyxPQUFPLHlCQUF5QjtBQUNoQyxTQUFTLGlDQUFpQztBQUVuQyxJQUFNLFNBQVM7QUFFdEIsSUFBTSxhQUFhLFlBQVksWUFBWSxDQUFDLFNBQVMsb0JBQW9CLElBQUksQ0FBQztBQUU5RSxJQUFNLE9BQW9ELFdBQVc7QUFBQSxFQUNuRSxNQUFNO0FBQUEsRUFDTixNQUFNO0FBQUEsSUFDSixNQUFNO0FBQUEsSUFDTixNQUFNO0FBQUEsTUFDSixhQUFhO0FBQUEsSUFDZjtBQUFBLElBQ0EsVUFBVTtBQUFBLE1BQ1IsbUJBQW1CO0FBQUEsSUFDckI7QUFBQSxJQUNBLFNBQVM7QUFBQSxJQUNULFFBQVEsQ0FBQztBQUFBLEVBQ1g7QUFBQSxFQUNBLGdCQUFnQixDQUFDO0FBQUEsRUFDakIsT0FBTyxTQUFTO0FBQ2QsVUFBTSxhQUFhLFFBQVE7QUFFM0IsV0FBTztBQUFBLE1BQ0wsU0FBUyxDQUFDLFlBQVk7QUFDcEIsY0FBTSxpQkFBaUIsV0FBVyxLQUFLLFNBQVMsZUFBZTtBQUMvRCxZQUFJLGdCQUFnQjtBQUNsQixnQkFBTSxXQUFXLFdBQVcsU0FBUyxPQUFPLEVBQUUsWUFBWSxDQUFDO0FBQzNELGlCQUFPLFFBQVE7QUFDZixjQUFJLFNBQVMsVUFBVSxLQUFLLENBQUMsYUFBYSxTQUFTLFNBQVMsV0FBVyxHQUFHO0FBQ3hFO0FBQUEsVUFDRjtBQUVBLGdCQUFNLGVBQWUsMEJBQTBCLFFBQVEsUUFBUTtBQUMvRCxjQUFJLGlCQUFpQixRQUFXO0FBQzlCLGtCQUFNLHNCQUFzQixRQUFRLEtBQUs7QUFBQSxjQUN2QyxDQUFDLGNBQWMsVUFBVSxTQUFTLGVBQWU7QUFBQSxZQUNuRDtBQUNBLG1CQUFPLG1CQUFtQjtBQUUxQixrQkFBTSwwQkFBMEI7QUFBQSw2QkFBZ0MsWUFBWTtBQUFBO0FBQzVFLG9CQUFRLE9BQU87QUFBQSxjQUNiLE1BQU07QUFBQSxjQUNOLFdBQVc7QUFBQSxjQUNYLElBQUksT0FBTztBQUNULHVCQUFPLE1BQU0sZ0JBQWdCLHFCQUFxQix1QkFBdUI7QUFBQSxjQUMzRTtBQUFBLFlBQ0YsQ0FBQztBQUFBLFVBQ0g7QUFBQSxRQUNGO0FBQUEsTUFDRjtBQUFBLElBQ0Y7QUFBQSxFQUNGO0FBQ0YsQ0FBQztBQUVELElBQU8sK0JBQVE7IiwKICAibmFtZXMiOiBbXQp9Cg==
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
// src/agent/add-url-domain.ts
|
|
2
|
+
import { AST_NODE_TYPES, ESLintUtils } from "@typescript-eslint/utils";
|
|
3
|
+
import getDocumentationUrl from "../get-documentation-url.mjs";
|
|
4
|
+
import { addBasePathUrlDomain } from "./url.mjs";
|
|
5
|
+
var ruleId = "add-url-domain";
|
|
6
|
+
var createRule = ESLintUtils.RuleCreator((name) => getDocumentationUrl(name));
|
|
7
|
+
var rule = createRule({
|
|
8
|
+
name: ruleId,
|
|
9
|
+
meta: {
|
|
10
|
+
type: "suggestion",
|
|
11
|
+
docs: {
|
|
12
|
+
description: "Add HTTP domain to the BASE_PATH like url constant variable."
|
|
13
|
+
},
|
|
14
|
+
messages: {
|
|
15
|
+
addDomain: "Add HTTP domain to the BASE_PATH like url constant variable.",
|
|
16
|
+
unknownError: 'Unknown error occurred in file "{{fileName}}": {{ error }}.'
|
|
17
|
+
},
|
|
18
|
+
fixable: "code",
|
|
19
|
+
schema: []
|
|
20
|
+
},
|
|
21
|
+
defaultOptions: [],
|
|
22
|
+
create(context) {
|
|
23
|
+
const sourceCode = context.sourceCode;
|
|
24
|
+
return {
|
|
25
|
+
"VariableDeclarator[id.name=/^([A-Z]+_)*BASE_PATH$/]": (basePathDeclarator) => {
|
|
26
|
+
try {
|
|
27
|
+
if (basePathDeclarator.init === null || basePathDeclarator.init.type !== AST_NODE_TYPES.Literal && basePathDeclarator.init.type !== AST_NODE_TYPES.TemplateLiteral) {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
const urlText = sourceCode.getText(basePathDeclarator.init);
|
|
31
|
+
const replacement = addBasePathUrlDomain(urlText);
|
|
32
|
+
if (replacement !== urlText) {
|
|
33
|
+
context.report({
|
|
34
|
+
messageId: "addDomain",
|
|
35
|
+
node: basePathDeclarator.init,
|
|
36
|
+
fix(fixer) {
|
|
37
|
+
return fixer.replaceText(basePathDeclarator.init, replacement);
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
} catch (error) {
|
|
42
|
+
console.error(`Failed to apply ${ruleId} rule for file "${context.filename}":`, error);
|
|
43
|
+
context.report({
|
|
44
|
+
node: basePathDeclarator,
|
|
45
|
+
messageId: "unknownError",
|
|
46
|
+
data: {
|
|
47
|
+
fileName: context.filename,
|
|
48
|
+
error: error instanceof Error ? error.toString() : JSON.stringify(error)
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
var add_url_domain_default = rule;
|
|
57
|
+
export {
|
|
58
|
+
add_url_domain_default as default,
|
|
59
|
+
ruleId
|
|
60
|
+
};
|
|
61
|
+
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vc3JjL2FnZW50L2FkZC11cmwtZG9tYWluLnRzIl0sCiAgIm1hcHBpbmdzIjogIjtBQVFBLFNBQVMsZ0JBQWdCLG1CQUE2QjtBQUV0RCxPQUFPLHlCQUF5QjtBQUNoQyxTQUFTLDRCQUE0QjtBQUU5QixJQUFNLFNBQVM7QUFFdEIsSUFBTSxhQUFhLFlBQVksWUFBWSxDQUFDLFNBQVMsb0JBQW9CLElBQUksQ0FBQztBQUU5RSxJQUFNLE9BQTZELFdBQVc7QUFBQSxFQUM1RSxNQUFNO0FBQUEsRUFDTixNQUFNO0FBQUEsSUFDSixNQUFNO0FBQUEsSUFDTixNQUFNO0FBQUEsTUFDSixhQUFhO0FBQUEsSUFDZjtBQUFBLElBQ0EsVUFBVTtBQUFBLE1BQ1IsV0FBVztBQUFBLE1BQ1gsY0FBYztBQUFBLElBQ2hCO0FBQUEsSUFDQSxTQUFTO0FBQUEsSUFDVCxRQUFRLENBQUM7QUFBQSxFQUNYO0FBQUEsRUFDQSxnQkFBZ0IsQ0FBQztBQUFBLEVBQ2pCLE9BQU8sU0FBUztBQUNkLFVBQU0sYUFBYSxRQUFRO0FBRTNCLFdBQU87QUFBQSxNQUNMLHVEQUF1RCxDQUFDLHVCQUFvRDtBQUMxRyxZQUFJO0FBQ0YsY0FDRSxtQkFBbUIsU0FBUyxRQUMzQixtQkFBbUIsS0FBSyxTQUFTLGVBQWUsV0FDL0MsbUJBQW1CLEtBQUssU0FBUyxlQUFlLGlCQUNsRDtBQUNBO0FBQUEsVUFDRjtBQUVBLGdCQUFNLFVBQVUsV0FBVyxRQUFRLG1CQUFtQixJQUFJO0FBQzFELGdCQUFNLGNBQWMscUJBQXFCLE9BQU87QUFFaEQsY0FBSSxnQkFBZ0IsU0FBUztBQUMzQixvQkFBUSxPQUFPO0FBQUEsY0FDYixXQUFXO0FBQUEsY0FDWCxNQUFNLG1CQUFtQjtBQUFBLGNBQ3pCLElBQUksT0FBTztBQUNULHVCQUFPLE1BQU0sWUFBWSxtQkFBbUIsTUFBdUIsV0FBVztBQUFBLGNBQ2hGO0FBQUEsWUFDRixDQUFDO0FBQUEsVUFDSDtBQUFBLFFBQ0YsU0FBUyxPQUFPO0FBRWQsa0JBQVEsTUFBTSxtQkFBbUIsTUFBTSxtQkFBbUIsUUFBUSxRQUFRLE1BQU0sS0FBSztBQUNyRixrQkFBUSxPQUFPO0FBQUEsWUFDYixNQUFNO0FBQUEsWUFDTixXQUFXO0FBQUEsWUFDWCxNQUFNO0FBQUEsY0FDSixVQUFVLFFBQVE7QUFBQSxjQUNsQixPQUFPLGlCQUFpQixRQUFRLE1BQU0sU0FBUyxJQUFJLEtBQUssVUFBVSxLQUFLO0FBQUEsWUFDekU7QUFBQSxVQUNGLENBQUM7QUFBQSxRQUNIO0FBQUEsTUFDRjtBQUFBLElBQ0Y7QUFBQSxFQUNGO0FBQ0YsQ0FBQztBQUVELElBQU8seUJBQVE7IiwKICAibmFtZXMiOiBbXQp9Cg==
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
// src/agent/agent-test-wiring.ts
|
|
2
|
+
import { strict as assert } from "node:assert";
|
|
3
|
+
import { AST_TOKEN_TYPES, ESLintUtils, TSESTree } from "@typescript-eslint/utils";
|
|
4
|
+
import debug from "debug";
|
|
5
|
+
import getDocumentationUrl from "../get-documentation-url.mjs";
|
|
6
|
+
var ruleId = "agent-test-wiring";
|
|
7
|
+
var createRule = ESLintUtils.RuleCreator((name) => getDocumentationUrl(name));
|
|
8
|
+
var log = debug("eslint-plugin:agent:agent-test-wiring");
|
|
9
|
+
var STATEMENT_FIXTURE_RESET = "fixture.reset()";
|
|
10
|
+
var STATEMENT_FIXTURE_RESET_AWAITED = `await ${STATEMENT_FIXTURE_RESET};`;
|
|
11
|
+
var STATEMENT_AGENT_DECLARATION = "let agent: Agent;";
|
|
12
|
+
var STATEMENT_AGENT_CREATION = "agent = await createAgent();";
|
|
13
|
+
var STATEMENT_AGENT_REGISTER = "agent.register(await fixturePlugin(fixture));";
|
|
14
|
+
var STATEMENT_AGENT_ENABLE = "agent.enable();";
|
|
15
|
+
var STATEMENT_AGENT_DISPOSE = "await agent[Symbol.asyncDispose]();";
|
|
16
|
+
var rule = createRule({
|
|
17
|
+
name: ruleId,
|
|
18
|
+
meta: {
|
|
19
|
+
type: "suggestion",
|
|
20
|
+
docs: {
|
|
21
|
+
description: "Update test wiring."
|
|
22
|
+
},
|
|
23
|
+
messages: {
|
|
24
|
+
updateTestWiring: "Updating test wiring.",
|
|
25
|
+
unknownError: 'Unknown error occurred in file "{{fileName}}": {{ error }}.'
|
|
26
|
+
},
|
|
27
|
+
fixable: "code",
|
|
28
|
+
schema: []
|
|
29
|
+
},
|
|
30
|
+
defaultOptions: [],
|
|
31
|
+
// eslint-disable-next-line max-lines-per-function
|
|
32
|
+
create(context) {
|
|
33
|
+
log("Processing file:", context.filename);
|
|
34
|
+
const sourceCode = context.sourceCode;
|
|
35
|
+
const importDeclarations = /* @__PURE__ */ new Map();
|
|
36
|
+
let isFixtureUsed = false;
|
|
37
|
+
let beforeAll;
|
|
38
|
+
let beforeEach;
|
|
39
|
+
let afterAll;
|
|
40
|
+
return {
|
|
41
|
+
ImportDeclaration(importDeclaration) {
|
|
42
|
+
const moduleName = importDeclaration.source.value;
|
|
43
|
+
importDeclarations.set(moduleName, importDeclaration);
|
|
44
|
+
if (moduleName === "@checkdigit/fixture" && importDeclaration.specifiers.some(
|
|
45
|
+
(specifier) => specifier.type === TSESTree.AST_NODE_TYPES.ImportSpecifier && specifier.imported.type === TSESTree.AST_NODE_TYPES.Identifier && specifier.imported.name === "createFixture"
|
|
46
|
+
)) {
|
|
47
|
+
isFixtureUsed = true;
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
'CallExpression[callee.name="beforeAll"]': (callExpression) => {
|
|
51
|
+
beforeAll = callExpression;
|
|
52
|
+
},
|
|
53
|
+
'CallExpression[callee.name="beforeEach"]': (callExpression) => {
|
|
54
|
+
beforeEach = callExpression;
|
|
55
|
+
},
|
|
56
|
+
'CallExpression[callee.name="afterAll"]': (callExpression) => {
|
|
57
|
+
afterAll = callExpression;
|
|
58
|
+
},
|
|
59
|
+
// eslint-disable-next-line sonarjs/cognitive-complexity
|
|
60
|
+
"Program:exit"(program) {
|
|
61
|
+
if (!isFixtureUsed || beforeAll === void 0 && beforeEach === void 0) {
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
try {
|
|
65
|
+
let jestImportFixer;
|
|
66
|
+
let agentImportFixer;
|
|
67
|
+
let fixturePluginImportFixer;
|
|
68
|
+
let agentDeclarationFixer;
|
|
69
|
+
let beforeAllOrEachFixer;
|
|
70
|
+
let afterAllFixer;
|
|
71
|
+
const lastImportDeclaration = [...importDeclarations.values()].at(-1);
|
|
72
|
+
assert.ok(lastImportDeclaration);
|
|
73
|
+
const jestImportDeclaration = importDeclarations.get("@jest/globals");
|
|
74
|
+
assert.ok(jestImportDeclaration);
|
|
75
|
+
const importsToAdd = ["afterAll", "beforeAll"].filter(
|
|
76
|
+
(jestHook) => !jestImportDeclaration.specifiers.some(
|
|
77
|
+
(specifier) => specifier.type === TSESTree.AST_NODE_TYPES.ImportSpecifier && specifier.imported.type === TSESTree.AST_NODE_TYPES.Identifier && specifier.imported.name === jestHook
|
|
78
|
+
)
|
|
79
|
+
);
|
|
80
|
+
if (importsToAdd.length > 0) {
|
|
81
|
+
const firstImportSpecifier = jestImportDeclaration.specifiers[0];
|
|
82
|
+
assert.ok(firstImportSpecifier);
|
|
83
|
+
jestImportFixer = (fixer) => fixer.insertTextBefore(firstImportSpecifier, `${importsToAdd.join(", ")}, `);
|
|
84
|
+
}
|
|
85
|
+
const agentImportDeclaration = importDeclarations.get("@checkdigit/agent");
|
|
86
|
+
if (!agentImportDeclaration) {
|
|
87
|
+
agentImportFixer = (fixer) => fixer.insertTextAfter(
|
|
88
|
+
lastImportDeclaration,
|
|
89
|
+
`
|
|
90
|
+
import createAgent, { type Agent } from '@checkdigit/agent';`
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
const pathLets = context.filename.split("/");
|
|
94
|
+
const currentFileIndex = pathLets.length - 1;
|
|
95
|
+
const pluginFolderIndex = pathLets.lastIndexOf("src") + 1;
|
|
96
|
+
const fixturePluginImportPath = `${"../".repeat(currentFileIndex - pluginFolderIndex)}plugin/fixture.test`;
|
|
97
|
+
if (!importDeclarations.get(fixturePluginImportPath)) {
|
|
98
|
+
fixturePluginImportFixer = (fixer) => fixer.insertTextAfter(lastImportDeclaration, `
|
|
99
|
+
import fixturePlugin from '${fixturePluginImportPath}';`);
|
|
100
|
+
}
|
|
101
|
+
if (beforeAll === void 0) {
|
|
102
|
+
beforeAllOrEachFixer = (fixer) => fixer.insertTextBefore(
|
|
103
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
104
|
+
beforeEach,
|
|
105
|
+
[
|
|
106
|
+
STATEMENT_AGENT_DECLARATION,
|
|
107
|
+
`beforeAll(async () => {`,
|
|
108
|
+
[STATEMENT_AGENT_CREATION, STATEMENT_AGENT_REGISTER, STATEMENT_AGENT_ENABLE].join("\n"),
|
|
109
|
+
`});
|
|
110
|
+
`
|
|
111
|
+
].join("\n")
|
|
112
|
+
);
|
|
113
|
+
} else {
|
|
114
|
+
const beforeAllArgument = beforeAll.arguments[0];
|
|
115
|
+
assert.ok(beforeAllArgument !== void 0);
|
|
116
|
+
if (!sourceCode.getText(beforeAllArgument).includes(STATEMENT_AGENT_CREATION)) {
|
|
117
|
+
if (beforeAllArgument.type === TSESTree.AST_NODE_TYPES.ArrowFunctionExpression && beforeAllArgument.body.type === TSESTree.AST_NODE_TYPES.BlockStatement) {
|
|
118
|
+
const fixtureResetStatement = beforeAllArgument.body.body.find(
|
|
119
|
+
(statement) => sourceCode.getText(statement) === STATEMENT_FIXTURE_RESET_AWAITED
|
|
120
|
+
);
|
|
121
|
+
assert.ok(fixtureResetStatement !== void 0);
|
|
122
|
+
beforeAllOrEachFixer = (fixer) => fixer.replaceText(
|
|
123
|
+
fixtureResetStatement,
|
|
124
|
+
[
|
|
125
|
+
STATEMENT_AGENT_CREATION,
|
|
126
|
+
STATEMENT_AGENT_REGISTER,
|
|
127
|
+
STATEMENT_AGENT_ENABLE,
|
|
128
|
+
STATEMENT_FIXTURE_RESET_AWAITED
|
|
129
|
+
].join("\n")
|
|
130
|
+
);
|
|
131
|
+
} else {
|
|
132
|
+
beforeAllOrEachFixer = (fixer) => fixer.replaceText(
|
|
133
|
+
beforeAllArgument,
|
|
134
|
+
[
|
|
135
|
+
`async () => {`,
|
|
136
|
+
STATEMENT_AGENT_CREATION,
|
|
137
|
+
STATEMENT_AGENT_REGISTER,
|
|
138
|
+
STATEMENT_AGENT_ENABLE,
|
|
139
|
+
STATEMENT_FIXTURE_RESET_AWAITED,
|
|
140
|
+
`}`
|
|
141
|
+
].join("\n")
|
|
142
|
+
);
|
|
143
|
+
}
|
|
144
|
+
agentDeclarationFixer = (fixer) => (
|
|
145
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
146
|
+
fixer.insertTextBefore(beforeAll, `${STATEMENT_AGENT_DECLARATION}
|
|
147
|
+
`)
|
|
148
|
+
);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
if (afterAll !== void 0) {
|
|
152
|
+
const afterAllArrowFunctionExpression = afterAll.arguments[0];
|
|
153
|
+
assert.ok(
|
|
154
|
+
afterAllArrowFunctionExpression !== void 0 && afterAllArrowFunctionExpression.type === TSESTree.AST_NODE_TYPES.ArrowFunctionExpression
|
|
155
|
+
);
|
|
156
|
+
const arrowFunctionBody = afterAllArrowFunctionExpression.body;
|
|
157
|
+
assert.ok(arrowFunctionBody.type === TSESTree.AST_NODE_TYPES.BlockStatement);
|
|
158
|
+
const afterAllBodyText = sourceCode.getText(arrowFunctionBody);
|
|
159
|
+
if (!afterAllBodyText.includes(STATEMENT_AGENT_DISPOSE)) {
|
|
160
|
+
const lastStatement = arrowFunctionBody.body.at(-1);
|
|
161
|
+
assert.ok(lastStatement);
|
|
162
|
+
afterAllFixer = (fixer) => fixer.insertTextAfter(lastStatement, STATEMENT_AGENT_DISPOSE);
|
|
163
|
+
}
|
|
164
|
+
} else {
|
|
165
|
+
const nextToken = sourceCode.getTokenAfter(beforeAll ?? beforeEach);
|
|
166
|
+
afterAllFixer = (fixer) => fixer.insertTextAfter(
|
|
167
|
+
nextToken !== null && nextToken.type === AST_TOKEN_TYPES.Punctuator ? nextToken : (
|
|
168
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
169
|
+
beforeAll
|
|
170
|
+
),
|
|
171
|
+
["", `afterAll(async () => {`, STATEMENT_AGENT_DISPOSE, `});`].join("\n")
|
|
172
|
+
);
|
|
173
|
+
}
|
|
174
|
+
if (jestImportFixer !== void 0 || agentImportFixer !== void 0 || fixturePluginImportFixer !== void 0 || agentDeclarationFixer !== void 0 || beforeAllOrEachFixer !== void 0 || afterAllFixer !== void 0) {
|
|
175
|
+
context.report({
|
|
176
|
+
messageId: "updateTestWiring",
|
|
177
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
178
|
+
node: beforeAll ?? beforeEach,
|
|
179
|
+
*fix(fixer) {
|
|
180
|
+
if (jestImportFixer !== void 0) {
|
|
181
|
+
yield jestImportFixer(fixer);
|
|
182
|
+
}
|
|
183
|
+
if (agentImportFixer !== void 0) {
|
|
184
|
+
yield agentImportFixer(fixer);
|
|
185
|
+
}
|
|
186
|
+
if (fixturePluginImportFixer !== void 0) {
|
|
187
|
+
yield fixturePluginImportFixer(fixer);
|
|
188
|
+
}
|
|
189
|
+
if (agentDeclarationFixer !== void 0) {
|
|
190
|
+
yield agentDeclarationFixer(fixer);
|
|
191
|
+
}
|
|
192
|
+
if (beforeAllOrEachFixer !== void 0) {
|
|
193
|
+
yield beforeAllOrEachFixer(fixer);
|
|
194
|
+
}
|
|
195
|
+
if (afterAllFixer !== void 0) {
|
|
196
|
+
yield afterAllFixer(fixer);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
} catch (error) {
|
|
202
|
+
console.error(`Failed to apply ${ruleId} rule for file "${context.filename}":`, error);
|
|
203
|
+
context.report({
|
|
204
|
+
node: program,
|
|
205
|
+
messageId: "unknownError",
|
|
206
|
+
data: {
|
|
207
|
+
fileName: context.filename,
|
|
208
|
+
error: error instanceof Error ? error.toString() : JSON.stringify(error)
|
|
209
|
+
}
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
});
|
|
216
|
+
var agent_test_wiring_default = rule;
|
|
217
|
+
export {
|
|
218
|
+
agent_test_wiring_default as default,
|
|
219
|
+
ruleId
|
|
220
|
+
};
|
|
221
|
+
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vc3JjL2FnZW50L2FnZW50LXRlc3Qtd2lyaW5nLnRzIl0sCiAgIm1hcHBpbmdzIjogIjtBQVFBLFNBQVMsVUFBVSxjQUFjO0FBRWpDLFNBQVMsaUJBQWlCLGFBQWEsZ0JBQWdCO0FBRXZELE9BQU8sV0FBVztBQUVsQixPQUFPLHlCQUF5QjtBQUV6QixJQUFNLFNBQVM7QUFDdEIsSUFBTSxhQUFhLFlBQVksWUFBWSxDQUFDLFNBQVMsb0JBQW9CLElBQUksQ0FBQztBQUM5RSxJQUFNLE1BQU0sTUFBTSx1Q0FBdUM7QUFFekQsSUFBTSwwQkFBMEI7QUFDaEMsSUFBTSxrQ0FBa0MsU0FBUyx1QkFBdUI7QUFDeEUsSUFBTSw4QkFBOEI7QUFDcEMsSUFBTSwyQkFBMkI7QUFDakMsSUFBTSwyQkFBMkI7QUFDakMsSUFBTSx5QkFBeUI7QUFDL0IsSUFBTSwwQkFBMEI7QUFFaEMsSUFBTSxPQUFvRSxXQUFXO0FBQUEsRUFDbkYsTUFBTTtBQUFBLEVBQ04sTUFBTTtBQUFBLElBQ0osTUFBTTtBQUFBLElBQ04sTUFBTTtBQUFBLE1BQ0osYUFBYTtBQUFBLElBQ2Y7QUFBQSxJQUNBLFVBQVU7QUFBQSxNQUNSLGtCQUFrQjtBQUFBLE1BQ2xCLGNBQWM7QUFBQSxJQUNoQjtBQUFBLElBQ0EsU0FBUztBQUFBLElBQ1QsUUFBUSxDQUFDO0FBQUEsRUFDWDtBQUFBLEVBQ0EsZ0JBQWdCLENBQUM7QUFBQTtBQUFBLEVBRWpCLE9BQU8sU0FBUztBQUNkLFFBQUksb0JBQW9CLFFBQVEsUUFBUTtBQUN4QyxVQUFNLGFBQWEsUUFBUTtBQUMzQixVQUFNLHFCQUFxQixvQkFBSSxJQUF3QztBQUN2RSxRQUFJLGdCQUFnQjtBQUNwQixRQUFJO0FBQ0osUUFBSTtBQUNKLFFBQUk7QUFFSixXQUFPO0FBQUEsTUFDTCxrQkFBa0IsbUJBQW1CO0FBQ25DLGNBQU0sYUFBYSxrQkFBa0IsT0FBTztBQUM1QywyQkFBbUIsSUFBSSxZQUFZLGlCQUFpQjtBQUNwRCxZQUNFLGVB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LFlBQ3BHO0FBQUEsVUFDRixPQUFPO0FBRUwsa0JBQU0sWUFBWSxXQUFXLGNBQWMsYUFBYSxVQUFXO0FBQ25FLDRCQUFnQixDQUFDLFVBQ2YsTUFBTTtBQUFBLGNBQ0osY0FBYyxRQUFRLFVBQVUsU0FBUyxnQkFBZ0IsYUFDckQ7QUFBQTtBQUFBLGdCQUVBO0FBQUE7QUFBQSxjQUNKLENBQUMsSUFBSSwwQkFBMEIseUJBQXlCLEtBQUssRUFBRSxLQUFLLElBQUk7QUFBQSxZQUMxRTtBQUFBLFVBQ0o7QUFFQSxjQUNFLG9CQUFvQixVQUNwQixxQkFBcUIsVUFDckIsNkJBQTZCLFVBQzdCLDBCQUEwQixVQUMxQix5QkFBeUIsVUFDekIsa0JBQWtCLFFBQ2xCO0FBQ0Esb0JBQVEsT0FBTztBQUFBLGNBQ2IsV0FBVztBQUFBO0FBQUEsY0FFWCxNQUFNLGFBQWE7QUFBQSxjQUNuQixDQUFDLElBQUksT0FBTztBQUNWLG9CQUFJLG9CQUFvQixRQUFXO0FBQ2pDLHdCQUFNLGdCQUFnQixLQUFLO0FBQUEsZ0JBQzdCO0FBQ0Esb0JBQUkscUJBQXFCLFFBQVc7QUFDbEMsd0JBQU0saUJBQWlCLEtBQUs7QUFBQSxnQkFDOUI7QUFDQSxvQkFBSSw2QkFBNkIsUUFBVztBQUMxQyx3QkFBTSx5QkFBeUIsS0FBSztBQUFBLGdCQUN0QztBQUNBLG9CQUFJLDBCQUEwQixRQUFXO0FBQ3ZDLHdCQUFNLHNCQUFzQixLQUFLO0FBQUEsZ0JBQ25DO0FBQ0Esb0JBQUkseUJBQXlCLFFBQVc7QUFDdEMsd0JBQU0scUJBQXFCLEtBQUs7QUFBQSxnQkFDbEM7QUFDQSxvQkFBSSxrQkFBa0IsUUFBVztBQUMvQix3QkFBTSxjQUFjLEtBQUs7QUFBQSxnQkFDM0I7QUFBQSxjQUNGO0FBQUEsWUFDRixDQUFDO0FBQUEsVUFDSDtBQUFBLFFBQ0YsU0FBUyxPQUFPO0FBRWQsa0JBQVEsTUFBTSxtQkFBbUIsTUFBTSxtQkFBbUIsUUFBUSxRQUFRLE1BQU0sS0FBSztBQUNyRixrQkFBUSxPQUFPO0FBQUEsWUFDYixNQUFNO0FBQUEsWUFDTixXQUFXO0FBQUEsWUFDWCxNQUFNO0FBQUEsY0FDSixVQUFVLFFBQVE7QUFBQSxjQUNsQixPQUFPLGlCQUFpQixRQUFRLE1BQU0sU0FBUyxJQUFJLEtBQUssVUFBVSxLQUFLO0FBQUEsWUFDekU7QUFBQSxVQUNGLENBQUM7QUFBQSxRQUNIO0FBQUEsTUFDRjtBQUFBLElBQ0Y7QUFBQSxFQUNGO0FBQ0YsQ0FBQztBQUVELElBQU8sNEJBQVE7IiwKICAibmFtZXMiOiBbXQp9Cg==
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
// src/agent/fetch-response-body-json.ts
|
|
2
|
+
import { strict as assert } from "node:assert";
|
|
3
|
+
import { AST_NODE_TYPES, ESLintUtils } from "@typescript-eslint/utils";
|
|
4
|
+
import getDocumentationUrl from "../get-documentation-url.mjs";
|
|
5
|
+
import { getAncestor } from "../library/ts-tree.mjs";
|
|
6
|
+
var ruleId = "fetch-response-body-json";
|
|
7
|
+
var createRule = ESLintUtils.RuleCreator((name) => getDocumentationUrl(name));
|
|
8
|
+
var rule = createRule({
|
|
9
|
+
name: ruleId,
|
|
10
|
+
meta: {
|
|
11
|
+
type: "suggestion",
|
|
12
|
+
docs: {
|
|
13
|
+
description: 'Replace "response.body" with "await response.json()".'
|
|
14
|
+
},
|
|
15
|
+
messages: {
|
|
16
|
+
refactorNeeded: "Please extract the fetch call and check its reponse status code before accessing its response body.",
|
|
17
|
+
replaceBodyWithJson: 'Replace "response.body" with "await response.json()".',
|
|
18
|
+
unknownError: 'Unknown error occurred in file "{{fileName}}": {{ error }}.'
|
|
19
|
+
},
|
|
20
|
+
fixable: "code",
|
|
21
|
+
schema: []
|
|
22
|
+
},
|
|
23
|
+
defaultOptions: [],
|
|
24
|
+
create(context) {
|
|
25
|
+
const parserServices = ESLintUtils.getParserServices(context);
|
|
26
|
+
const typeChecker = parserServices.program.getTypeChecker();
|
|
27
|
+
const allChanges = /* @__PURE__ */ new Map();
|
|
28
|
+
return {
|
|
29
|
+
'MemberExpression[property.name="body"]': (responseBodyNode) => {
|
|
30
|
+
try {
|
|
31
|
+
const responseNode = parserServices.esTreeNodeToTSNodeMap.get(responseBodyNode.object);
|
|
32
|
+
const responseType = typeChecker.getTypeAtLocation(responseNode);
|
|
33
|
+
const shouldReplace = responseType.getProperties().some((symbol) => symbol.name === "body") && responseType.getProperties().some((symbol) => symbol.name === "json");
|
|
34
|
+
if (shouldReplace) {
|
|
35
|
+
if (responseBodyNode.object.type !== AST_NODE_TYPES.Identifier) {
|
|
36
|
+
context.report({
|
|
37
|
+
node: responseBodyNode,
|
|
38
|
+
messageId: "refactorNeeded"
|
|
39
|
+
});
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
const enclosingFunction = getAncestor(
|
|
43
|
+
responseBodyNode,
|
|
44
|
+
(node) => node.type === AST_NODE_TYPES.ArrowFunctionExpression || node.type === AST_NODE_TYPES.FunctionExpression || node.type === AST_NODE_TYPES.FunctionDeclaration
|
|
45
|
+
);
|
|
46
|
+
const enclosingStatement = getAncestor(
|
|
47
|
+
responseBodyNode,
|
|
48
|
+
(node) => (node.type === AST_NODE_TYPES.VariableDeclaration || node.type === AST_NODE_TYPES.ExpressionStatement || node.type === AST_NODE_TYPES.ReturnStatement) && node.parent.type === AST_NODE_TYPES.BlockStatement
|
|
49
|
+
);
|
|
50
|
+
const enclosingStatementIndex = enclosingFunction.body.body.indexOf(
|
|
51
|
+
enclosingStatement
|
|
52
|
+
);
|
|
53
|
+
const responseVariableName = responseBodyNode.object.name;
|
|
54
|
+
const isResponseBodyVariableDeclared = enclosingStatement.type === AST_NODE_TYPES.VariableDeclaration && enclosingStatement.declarations.some(
|
|
55
|
+
(declaration) => declaration.init === responseBodyNode || declaration.init?.type === AST_NODE_TYPES.TSAsExpression && declaration.init.expression === responseBodyNode
|
|
56
|
+
);
|
|
57
|
+
const responseBodyVariableName = isResponseBodyVariableDeclared ? enclosingStatement.declarations.find(
|
|
58
|
+
(declaration) => declaration.init === responseBodyNode || declaration.init?.type === AST_NODE_TYPES.TSAsExpression && declaration.init.expression === responseBodyNode
|
|
59
|
+
)?.id : `${responseBodyNode.object.name}Body`;
|
|
60
|
+
const change = {
|
|
61
|
+
enclosingFunction,
|
|
62
|
+
enclosingStatement,
|
|
63
|
+
enclosingStatementIndex,
|
|
64
|
+
responseVariableName,
|
|
65
|
+
responseBodyNode,
|
|
66
|
+
responseBodyVariableName,
|
|
67
|
+
isResponseBodyVariableDeclared
|
|
68
|
+
};
|
|
69
|
+
const changesByFunction = allChanges.get(enclosingFunction) ?? /* @__PURE__ */ new Map();
|
|
70
|
+
const changesByResponse = changesByFunction.get(responseVariableName) ?? [];
|
|
71
|
+
changesByResponse.push(change);
|
|
72
|
+
changesByFunction.set(responseVariableName, changesByResponse);
|
|
73
|
+
allChanges.set(enclosingFunction, changesByFunction);
|
|
74
|
+
}
|
|
75
|
+
} catch (error) {
|
|
76
|
+
console.error(`Failed to apply ${ruleId} rule for file "${context.filename}":`, error);
|
|
77
|
+
context.report({
|
|
78
|
+
node: responseBodyNode,
|
|
79
|
+
messageId: "unknownError",
|
|
80
|
+
data: {
|
|
81
|
+
fileName: context.filename,
|
|
82
|
+
error: error instanceof Error ? error.toString() : JSON.stringify(error)
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
},
|
|
87
|
+
"Program:exit": () => {
|
|
88
|
+
if (allChanges.size === 0) {
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
const fixes = [];
|
|
92
|
+
for (const changesByFunction of allChanges.values()) {
|
|
93
|
+
for (const changesByResponse of changesByFunction.values()) {
|
|
94
|
+
const orderedChanges = changesByResponse.sort(
|
|
95
|
+
(changeA, changeB) => changeA.enclosingStatementIndex - changeB.enclosingStatementIndex
|
|
96
|
+
);
|
|
97
|
+
const firstChange = orderedChanges[0];
|
|
98
|
+
assert(firstChange);
|
|
99
|
+
const {
|
|
100
|
+
responseBodyNode,
|
|
101
|
+
responseVariableName,
|
|
102
|
+
responseBodyVariableName,
|
|
103
|
+
isResponseBodyVariableDeclared,
|
|
104
|
+
enclosingStatement
|
|
105
|
+
} = firstChange;
|
|
106
|
+
let remainingChanges;
|
|
107
|
+
if (!isResponseBodyVariableDeclared) {
|
|
108
|
+
fixes.push({
|
|
109
|
+
node: context.sourceCode.getTokenBefore(enclosingStatement),
|
|
110
|
+
text: `
|
|
111
|
+
const ${responseBodyVariableName} = await ${responseVariableName}.json();`,
|
|
112
|
+
insert: true
|
|
113
|
+
});
|
|
114
|
+
remainingChanges = orderedChanges;
|
|
115
|
+
} else {
|
|
116
|
+
fixes.push({
|
|
117
|
+
node: responseBodyNode,
|
|
118
|
+
text: `await ${responseVariableName}.json()`,
|
|
119
|
+
insert: false
|
|
120
|
+
});
|
|
121
|
+
remainingChanges = orderedChanges.slice(1);
|
|
122
|
+
}
|
|
123
|
+
for (const change of remainingChanges) {
|
|
124
|
+
fixes.push({ node: change.responseBodyNode, text: responseBodyVariableName, insert: false });
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
for (const fix of fixes.reverse()) {
|
|
129
|
+
context.report({
|
|
130
|
+
node: fix.node,
|
|
131
|
+
messageId: "replaceBodyWithJson",
|
|
132
|
+
fix(fixer) {
|
|
133
|
+
return fix.insert ? fixer.insertTextAfter(fix.node, fix.text) : fixer.replaceText(fix.node, fix.text);
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
var fetch_response_body_json_default = rule;
|
|
142
|
+
export {
|
|
143
|
+
fetch_response_body_json_default as default,
|
|
144
|
+
ruleId
|
|
145
|
+
};
|
|
146
|
+
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vc3JjL2FnZW50L2ZldGNoLXJlc3BvbnNlLWJvZHktanNvbi50cyJdLAogICJtYXBwaW5ncyI6ICI7QUFRQSxTQUFTLFVBQVUsY0FBYztBQUVqQyxTQUFTLGdCQUFnQixtQkFBNkI7QUFFdEQsT0FBTyx5QkFBeUI7QUFDaEMsU0FBUyxtQkFBbUI7QUFFckIsSUFBTSxTQUFTO0FBRXRCLElBQU0sYUFBYSxZQUFZLFlBQVksQ0FBQyxTQUFTLG9CQUFvQixJQUFJLENBQUM7QUFhOUUsSUFBTSxPQUEwRixXQUFXO0FBQUEsRUFDekcsTUFBTTtBQUFBLEVBQ04sTUFBTTtBQUFBLElBQ0osTUFBTTtBQUFBLElBQ04sTUFBTTtBQUFBLE1BQ0osYUFBYTtBQUFBLElBQ2Y7QUFBQSxJQUNBLFVBQVU7QUFBQSxNQUNSLGdCQUNFO0FBQUEsTUFDRixxQkFBcUI7QUFBQSxNQUNyQixjQUFjO0FBQUEsSUFDaEI7QUFBQSxJQUNBLFNBQVM7QUFBQSxJQUNULFFBQVEsQ0FBQztBQUFBLEVBQ1g7QUFBQSxFQUNBLGdCQUFnQixDQUFDO0FBQUEsRUFDakIsT0FBTyxTQUFTO0FBQ2QsVUFBTSxpQkFBaUIsWUFBWSxrQkFBa0IsT0FBTztBQUM1RCxVQUFNLGNBQWMsZUFBZSxRQUFRLGVBQWU7QUFDMUQsVUFBTSxhQUFhLG9CQUFJLElBQTBDO0FBRWpFLFdBQU87QUFBQSxNQUNMLDBDQUEwQyxDQUFDLHFCQUFnRDtBQUN6RixZQUFJO0FBQ0YsZ0JBQU0sZUFBZSxlQUFlLHNCQUFzQixJQUFJLGlCQUFpQixNQUFNO0FBQ3JGLGdCQUFNLGVBQWUsWUFBWSxrQkFBa0IsWUFBWTtBQUUvRCxnQkFBTSxnQkFDSixhQUFhLGNBQWMsRUFBRSxLQUFLLENBQUMsV0FBVyxPQUFPLFNBQVMsTUFBTSxLQUNwRSxhQUFhLGNBQWMsRUFBRSxLQUFLLENBQUMsV0FBVyxPQUFPLFNBQVMsTUFBTTtBQUV0RSxjQUFJLGVBQWU7QUFDakIsZ0JBQUksaUJBQWlCLE9BQU8sU0FBUyxl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
|