@checkdigit/eslint-plugin 7.2.0 → 7.3.0-PR.75-aa6d
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-url-domain.mjs +61 -0
- package/dist-mjs/agent/agent-test-wiring.mjs +170 -0
- package/dist-mjs/agent/fetch-response-body-json.mjs +63 -0
- package/dist-mjs/agent/fetch-response-header-getter.mjs +117 -0
- package/dist-mjs/agent/fetch-then.mjs +267 -0
- package/dist-mjs/agent/fetch.mjs +34 -0
- package/dist-mjs/agent/fix-function-call-arguments.mjs +153 -0
- package/dist-mjs/agent/no-fixture.mjs +326 -0
- package/dist-mjs/agent/no-mapped-response.mjs +75 -0
- package/dist-mjs/agent/no-service-wrapper.mjs +183 -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 +56 -0
- package/dist-mjs/agent/url.mjs +26 -0
- package/dist-mjs/index.mjs +104 -7
- 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-then.d.ts +4 -0
- package/dist-types/agent/fetch.d.ts +4 -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 +5 -0
- package/dist-types/index.d.ts +4 -2
- package/package.json +1 -96
- package/src/agent/add-url-domain.ts +76 -0
- package/src/agent/agent-test-wiring.ts +204 -0
- package/src/agent/fetch-response-body-json.ts +77 -0
- package/src/agent/fetch-response-header-getter.ts +148 -0
- package/src/agent/fetch-then.ts +355 -0
- package/src/agent/fetch.ts +53 -0
- package/src/agent/fix-function-call-arguments.ts +184 -0
- package/src/agent/no-fixture.ts +455 -0
- package/src/agent/no-mapped-response.ts +84 -0
- package/src/agent/no-service-wrapper.ts +239 -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 +109 -0
- package/src/agent/url.ts +25 -0
- package/src/index.ts +105 -6
|
@@ -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,170 @@
|
|
|
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 getDocumentationUrl from "../get-documentation-url.mjs";
|
|
5
|
+
var ruleId = "agent-test-wiring";
|
|
6
|
+
var createRule = ESLintUtils.RuleCreator((name) => getDocumentationUrl(name));
|
|
7
|
+
var rule = createRule({
|
|
8
|
+
name: ruleId,
|
|
9
|
+
meta: {
|
|
10
|
+
type: "suggestion",
|
|
11
|
+
docs: {
|
|
12
|
+
description: "Update test wiring."
|
|
13
|
+
},
|
|
14
|
+
messages: {
|
|
15
|
+
updateTestWiring: "Updating test wiring.",
|
|
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
|
+
const importDeclarations = /* @__PURE__ */ new Map();
|
|
25
|
+
let beforeAllCallExpression;
|
|
26
|
+
let afterAllCallExpression;
|
|
27
|
+
return {
|
|
28
|
+
ImportDeclaration(importDeclaration) {
|
|
29
|
+
const moduleName = importDeclaration.source.value;
|
|
30
|
+
importDeclarations.set(moduleName, importDeclaration);
|
|
31
|
+
},
|
|
32
|
+
'CallExpression[callee.name="beforeAll"]': (callExpression) => {
|
|
33
|
+
beforeAllCallExpression = callExpression;
|
|
34
|
+
},
|
|
35
|
+
'CallExpression[callee.name="afterAll"]': (callExpression) => {
|
|
36
|
+
afterAllCallExpression = callExpression;
|
|
37
|
+
},
|
|
38
|
+
"Program:exit"(program) {
|
|
39
|
+
try {
|
|
40
|
+
let jestImportFixer;
|
|
41
|
+
let agentImportFixer;
|
|
42
|
+
let fixturePluginImportFixer;
|
|
43
|
+
let agentDeclarationFixer;
|
|
44
|
+
let beforeAllFixer;
|
|
45
|
+
let afterAllFixer;
|
|
46
|
+
const lastImportDeclaration = [...importDeclarations.values()].at(-1);
|
|
47
|
+
assert.ok(lastImportDeclaration);
|
|
48
|
+
const jestImportDeclaration = importDeclarations.get("@jest/globals");
|
|
49
|
+
if (jestImportDeclaration && !jestImportDeclaration.specifiers.some(
|
|
50
|
+
(specifier) => specifier.type === TSESTree.AST_NODE_TYPES.ImportSpecifier && specifier.imported.type === TSESTree.AST_NODE_TYPES.Identifier && specifier.imported.name === "afterAll"
|
|
51
|
+
)) {
|
|
52
|
+
const firstImportSpecifier = jestImportDeclaration.specifiers[0];
|
|
53
|
+
assert.ok(firstImportSpecifier);
|
|
54
|
+
jestImportFixer = (fixer) => fixer.insertTextBefore(firstImportSpecifier, "afterAll, ");
|
|
55
|
+
}
|
|
56
|
+
const agentImportDeclaration = importDeclarations.get("@checkdigit/agent");
|
|
57
|
+
if (!agentImportDeclaration) {
|
|
58
|
+
agentImportFixer = (fixer) => fixer.insertTextAfter(
|
|
59
|
+
lastImportDeclaration,
|
|
60
|
+
`
|
|
61
|
+
import createAgent, { type Agent } from '@checkdigit/agent';`
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
const fixturePluginImportDeclaration = importDeclarations.get("../../plugin/fixture.test");
|
|
65
|
+
if (!fixturePluginImportDeclaration) {
|
|
66
|
+
fixturePluginImportFixer = (fixer) => fixer.insertTextAfter(lastImportDeclaration, `
|
|
67
|
+
import fixturePlugin from '../../plugin/fixture.test';`);
|
|
68
|
+
}
|
|
69
|
+
if (beforeAllCallExpression !== void 0) {
|
|
70
|
+
const beforeAllArrowFunctionExpression = beforeAllCallExpression.arguments[0];
|
|
71
|
+
assert.ok(
|
|
72
|
+
beforeAllArrowFunctionExpression !== void 0 && beforeAllArrowFunctionExpression.type === TSESTree.AST_NODE_TYPES.ArrowFunctionExpression
|
|
73
|
+
);
|
|
74
|
+
const arrowFunctionBody = beforeAllArrowFunctionExpression.body;
|
|
75
|
+
assert.ok(arrowFunctionBody.type === TSESTree.AST_NODE_TYPES.BlockStatement);
|
|
76
|
+
const targetStatement = arrowFunctionBody.body.find(
|
|
77
|
+
(statement) => sourceCode.getText(statement) === "await fixture.reset();"
|
|
78
|
+
);
|
|
79
|
+
if (targetStatement !== void 0) {
|
|
80
|
+
const beforeAllBodyText = sourceCode.getText(arrowFunctionBody);
|
|
81
|
+
if (!beforeAllBodyText.includes("agent = await createAgent();")) {
|
|
82
|
+
beforeAllFixer = (fixer) => fixer.replaceText(
|
|
83
|
+
targetStatement,
|
|
84
|
+
[
|
|
85
|
+
"agent = await createAgent();",
|
|
86
|
+
"agent.register(await fixturePlugin(fixture));",
|
|
87
|
+
"agent.enable();",
|
|
88
|
+
"await fixture.reset();"
|
|
89
|
+
].join("\n")
|
|
90
|
+
);
|
|
91
|
+
agentDeclarationFixer = (fixer) => (
|
|
92
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
93
|
+
fixer.insertTextBefore(beforeAllCallExpression, "let agent: Agent;\n")
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
if (afterAllCallExpression !== void 0) {
|
|
99
|
+
const afterAllArrowFunctionExpression = afterAllCallExpression.arguments[0];
|
|
100
|
+
assert.ok(
|
|
101
|
+
afterAllArrowFunctionExpression !== void 0 && afterAllArrowFunctionExpression.type === TSESTree.AST_NODE_TYPES.ArrowFunctionExpression
|
|
102
|
+
);
|
|
103
|
+
const arrowFunctionBody = afterAllArrowFunctionExpression.body;
|
|
104
|
+
assert.ok(arrowFunctionBody.type === TSESTree.AST_NODE_TYPES.BlockStatement);
|
|
105
|
+
const afterAllBodyText = sourceCode.getText(arrowFunctionBody);
|
|
106
|
+
if (!afterAllBodyText.includes("await agent[Symbol.asyncDispose]();")) {
|
|
107
|
+
const lastStatement = arrowFunctionBody.body.at(-1);
|
|
108
|
+
assert.ok(lastStatement);
|
|
109
|
+
afterAllFixer = (fixer) => fixer.insertTextAfter(lastStatement, "await agent[Symbol.asyncDispose]();");
|
|
110
|
+
}
|
|
111
|
+
} else if (beforeAllCallExpression !== void 0) {
|
|
112
|
+
const nextToken = sourceCode.getTokenAfter(beforeAllCallExpression);
|
|
113
|
+
afterAllFixer = (fixer) => fixer.insertTextAfter(
|
|
114
|
+
nextToken !== null && nextToken.type === AST_TOKEN_TYPES.Punctuator ? nextToken : (
|
|
115
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
116
|
+
beforeAllCallExpression
|
|
117
|
+
),
|
|
118
|
+
`
|
|
119
|
+
afterAll(async () => {
|
|
120
|
+
await agent[Symbol.asyncDispose]();
|
|
121
|
+
});`
|
|
122
|
+
);
|
|
123
|
+
}
|
|
124
|
+
if (jestImportFixer !== void 0 || agentImportFixer !== void 0 || fixturePluginImportFixer !== void 0 || agentDeclarationFixer !== void 0 || beforeAllFixer !== void 0 || afterAllFixer !== void 0) {
|
|
125
|
+
context.report({
|
|
126
|
+
messageId: "updateTestWiring",
|
|
127
|
+
node: program,
|
|
128
|
+
*fix(fixer) {
|
|
129
|
+
if (jestImportFixer !== void 0) {
|
|
130
|
+
yield jestImportFixer(fixer);
|
|
131
|
+
}
|
|
132
|
+
if (agentImportFixer !== void 0) {
|
|
133
|
+
yield agentImportFixer(fixer);
|
|
134
|
+
}
|
|
135
|
+
if (fixturePluginImportFixer !== void 0) {
|
|
136
|
+
yield fixturePluginImportFixer(fixer);
|
|
137
|
+
}
|
|
138
|
+
if (agentDeclarationFixer !== void 0) {
|
|
139
|
+
yield agentDeclarationFixer(fixer);
|
|
140
|
+
}
|
|
141
|
+
if (beforeAllFixer !== void 0) {
|
|
142
|
+
yield beforeAllFixer(fixer);
|
|
143
|
+
}
|
|
144
|
+
if (afterAllFixer !== void 0) {
|
|
145
|
+
yield afterAllFixer(fixer);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
} catch (error) {
|
|
151
|
+
console.error(`Failed to apply ${ruleId} rule for file "${context.filename}":`, error);
|
|
152
|
+
context.report({
|
|
153
|
+
node: program,
|
|
154
|
+
messageId: "unknownError",
|
|
155
|
+
data: {
|
|
156
|
+
fileName: context.filename,
|
|
157
|
+
error: error instanceof Error ? error.toString() : JSON.stringify(error)
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
});
|
|
165
|
+
var agent_test_wiring_default = rule;
|
|
166
|
+
export {
|
|
167
|
+
agent_test_wiring_default as default,
|
|
168
|
+
ruleId
|
|
169
|
+
};
|
|
170
|
+
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vc3JjL2FnZW50L2FnZW50LXRlc3Qtd2lyaW5nLnRzIl0sCiAgIm1hcHBpbmdzIjogIjtBQVFBLFNBQVMsVUFBVSxjQUFjO0FBQ2pDLFNBQVMsaUJBQWlCLGFBQWEsZ0JBQWdCO0FBRXZELE9BQU8seUJBQXlCO0FBRXpCLElBQU0sU0FBUztBQUV0QixJQUFNLGFBQWEsWUFBWSxZQUFZLENBQUMsU0FBUyxvQkFBb0IsSUFBSSxDQUFDO0FBRTlFLElBQU0sT0FBb0UsV0FBVztBQUFBLEVBQ25GLE1BQU07QUFBQSxFQUNOLE1BQU07QUFBQSxJQUNKLE1BQU07QUFBQSxJQUNOLE1BQU07QUFBQSxNQUNKLGFBQWE7QUFBQSxJQUNmO0FBQUEsSUFDQSxVQUFVO0FBQUEsTUFDUixrQkFBa0I7QUFBQSxNQUNsQixjQUFjO0FBQUEsSUFDaEI7QUFBQSxJQUNBLFNBQVM7QUFBQSxJQUNULFFBQVEsQ0FBQztBQUFBLEVBQ1g7QUFBQSxFQUNBLGdCQUFnQixDQUFDO0FBQUEsRUFDakIsT0FBTyxTQUFTO0FBQ2QsVUFBTSxhQUFhLFFBQVE7QUFDM0IsVUFBTSxxQkFBcUIsb0JBQUksSUFBd0M7QUFDdkUsUUFBSTtBQUNKLFFBQUk7QUFFSixXQUFPO0FBQUEsTUFDTCxrQkFBa0IsbUJBQW1CO0FBQ25DLGNBQU0sYUFBYSxrQkFBa0IsT0FBTztBQUM1QywyQkFBbUIsSUFBSSxZQUFZLGlCQUFpQjtBQUFBLE1BQ3REO0FBQUEsTUFDQSwyQ0FBMkMsQ0FBQyxtQkFBNEM7QUFDdEYsa0NBQTBCO0FBQUEsTUFDNUI7QUFBQSxNQUNBLDBDQUEwQyxDQUFDLG1CQUE0QztBQUNyRixpQ0FBeUI7QUFBQSxNQUMzQjtBQUFBLE1BQ0EsZUFBZSxTQUFTO0FBQ3RCLFlBQUk7QUFDRixjQUFJO0FBQ0osY0FBSTtBQUNKLGNBQUk7QUFDSixjQUFJO0FBQ0osY0FBSTtBQUNKLGNBQUk7QUFFSixnQkFBTSx3QkFBd0IsQ0FBQyxHQUFHLG1CQUFtQixPQUFPLENBQUMsRUFBRSxHQUFHLEVBQUU7QUFDcEUsaUJBQU8sR0FBRyxxQkFBcUI7QUFFL0IsZ0JBQU0sd0JBQXdCLG1CQUFtQixJQUFJLGVBQWU7QUFDcEUsY0FDRSx5QkFDQSxDQUFDLHNCQUFzQixXQUFXO0FBQUEsWUFDaEMsQ0FBQyxjQUNDLFVBQVUsU0FBUyxTQUFTLGVBQWUsbUJBQzNDLFVBQVUsU0FBUyxTQUFTLFNBQVMsZUFBZSxjQUNwRCxVQUFVLFNBQVMsU0FBUztBQUFBLFVBQ2hDLEdBQ0E7QUFDQSxrQkFBTSx1QkFBdUIsc0JBQXNCLFdBQVcsQ0FBQztBQUMvRCxtQkFBTyxHQUFHLG9CQUFvQjtBQUM5Qiw4QkFBa0IsQ0FBQyxVQUFxQixNQUFNLGlCQUFpQixzQkFBc0IsWUFBWTtBQUFBLFVBQ25HO0FBRUEsZ0JBQU0seUJBQXlCLG1CQUFtQixJQUFJLG1CQUFtQjtBQUN6RSxjQUFJLENBQUMsd0JBQXdCO0FBQzNCLCtCQUFtQixDQUFDLFVBQ2xCLE1BQU07QUFBQSxjQUNKO0FBQUEsY0FDQTtBQUFBO0FBQUEsWUFDRjtBQUFBLFVBQ0o7QUFFQSxnQkFBTSxpQ0FBaUMsbUJBQW1CLElBQUksMkJBQTJCO0FBQ3pGLGNBQUksQ0FBQyxnQ0FBZ0M7QUFDbkMsdUNBQTJCLENBQUMsVUFDMUIsTUFBTSxnQkFBZ0IsdUJBQXVCO0FBQUEsdURBQTBEO0FBQUEsVUFDM0c7QUFFQSxjQUFJLDRCQUE0QixRQUFXO0FBQ3pDLGtCQUFNLG1DQUFtQyx3QkFBd0IsVUFBVSxDQUFDO0FBQzVFLG1CQUFPO0FBQUEsY0FDTCxxQ0FBcUMsVUFDbkMsaUNBQWlDLFNBQVMsU0FBUyxlQUFlO0FBQUEsWUFDdEU7QUFDQSxrQkFBTSxvQkFBb0IsaUNBQWlDO0FBQzNELG1CQUFPLEdBQUcsa0JBQWtCLFNBQVMsU0FBUyxlQUFlLGNBQWM7QUFFM0Usa0JBQU0sa0JBQWtCLGtCQUFrQixLQUFLO0FBQUEsY0FDN0MsQ0FBQyxjQUFjLFdBQVcsUUFBUSxTQUFTLE1BQU07QUFBQSxZQUNuRDtBQUNBLGdCQUFJLG9CQUFvQixRQUFXO0FBQ2pDLG9CQUFNLG9CQUFvQixXQUFXLFFBQVEsaUJBQWlCO0FBQzlELGtCQUFJLENBQUMsa0JBQWtCLFNBQVMsOEJBQThCLEdBQUc7QUFDL0QsaUNBQWlCLENBQUMsVUFDaEIsTUFBTTtBQUFBLGtCQUNKO0FBQUEsa0JBQ0E7QUFBQSxvQkFDRTtBQUFBLG9CQUNBO0FBQUEsb0JBQ0E7QUFBQSxvQkFDQTtBQUFBLGtCQUNGLEVBQUUsS0FBSyxJQUFJO0FBQUEsZ0JBQ2I7QUFDRix3Q0FBd0IsQ0FBQztBQUFBO0FBQUEsa0JBRXZCLE1BQU0saUJBQWlCLHlCQUEwQixxQkFBcUI7QUFBQTtBQUFBLGNBQzFFO0FBQUEsWUFDRjtBQUFBLFVBQ0Y7QUFFQSxjQUFJLDJCQUEyQixRQUFXO0FBQ3hDLGtCQUFNLGtDQUFrQyx1QkFBdUIsVUFBVSxDQUFDO0FBQzFFLG1CQUFPO0FBQUEsY0FDTCxvQ0FBb0MsVUFDbEMsZ0NBQWdDLFNBQVMsU0FBUyxlQUFlO0FBQUEsWUFDckU7QUFDQSxrQkFBTSxvQkFBb0IsZ0NBQWdDO0FBQzFELG1CQUFPLEdBQUcsa0JBQWtCLFNBQVMsU0FBUyxlQUFlLGNBQWM7QUFFM0Usa0JBQU0sbUJBQW1CLFdBQVcsUUFBUSxpQkFBaUI7QUFDN0QsZ0JBQUksQ0FBQyxpQkFBaUIsU0FBUyxxQ0FBcUMsR0FBRztBQUNyRSxvQkFBTSxnQkFBZ0Isa0JBQWtCLEtBQUssR0FBRyxFQUFFO0FBQ2xELHFCQUFPLEdBQUcsYUFBYTtBQUN2Qiw4QkFBZ0IsQ0FBQyxVQUNmLE1BQU0sZ0JBQWdCLGVBQWUscUNBQXFDO0FBQUEsWUFDOUU7QUFBQSxVQUNGLFdBQVcsNEJBQTRCLFFBQVc7QUFDaEQsa0JBQU0sWUFBWSxXQUFXLGNBQWMsdUJBQXVCO0FBQ2xFLDRCQUFnQixDQUFDLFVBQ2YsTUFBTTtBQUFBLGNBQ0osY0FBYyxRQUFRLFVBQVUsU0FBUyxnQkFBZ0IsYUFDckQ7QUFBQTtBQUFBLGdCQUVBO0FBQUE7QUFBQSxjQUNKO0FBQUE7QUFBQTtBQUFBO0FBQUEsWUFHRjtBQUFBLFVBQ0o7QUFFQSxjQUNFLG9CQUFvQixVQUNwQixxQkFBcUIsVUFDckIsNkJBQTZCLFVBQzdCLDBCQUEwQixVQUMxQixtQkFBbUIsVUFDbkIsa0JBQWtCLFFBQ2xCO0FBQ0Esb0JBQVEsT0FBTztBQUFBLGNBQ2IsV0FBVztBQUFBLGNBQ1gsTUFBTTtBQUFBLGNBQ04sQ0FBQyxJQUFJLE9BQU87QUFDVixvQkFBSSxvQkFBb0IsUUFBVztBQUNqQyx3QkFBTSxnQkFBZ0IsS0FBSztBQUFBLGdCQUM3QjtBQUNBLG9CQUFJLHFCQUFxQixRQUFXO0FBQ2xDLHdCQUFNLGlCQUFpQixLQUFLO0FBQUEsZ0JBQzlCO0FBQ0Esb0JBQUksNkJBQTZCLFFBQVc7QUFDMUMsd0JBQU0seUJBQXlCLEtBQUs7QUFBQSxnQkFDdEM7QUFDQSxvQkFBSSwwQkFBMEIsUUFBVztBQUN2Qyx3QkFBTSxzQkFBc0IsS0FBSztBQUFBLGdCQUNuQztBQUNBLG9CQUFJLG1CQUFtQixRQUFXO0FBQ2hDLHdCQUFNLGVBQWUsS0FBSztBQUFBLGdCQUM1QjtBQUNBLG9CQUFJLGtCQUFrQixRQUFXO0FBQy9CLHdCQUFNLGNBQWMsS0FBSztBQUFBLGdCQUMzQjtBQUFBLGNBQ0Y7QUFBQSxZQUNGLENBQUM7QUFBQSxVQUNIO0FBQUEsUUFDRixTQUFTLE9BQU87QUFFZCxrQkFBUSxNQUFNLG1CQUFtQixNQUFNLG1CQUFtQixRQUFRLFFBQVEsTUFBTSxLQUFLO0FBQ3JGLGtCQUFRLE9BQU87QUFBQSxZQUNiLE1BQU07QUFBQSxZQUNOLFdBQVc7QUFBQSxZQUNYLE1BQU07QUFBQSxjQUNKLFVBQVUsUUFBUTtBQUFBLGNBQ2xCLE9BQU8saUJBQWlCLFFBQVEsTUFBTSxTQUFTLElBQUksS0FBSyxVQUFVLEtBQUs7QUFBQSxZQUN6RTtBQUFBLFVBQ0YsQ0FBQztBQUFBLFFBQ0g7QUFBQSxNQUNGO0FBQUEsSUFDRjtBQUFBLEVBQ0Y7QUFDRixDQUFDO0FBRUQsSUFBTyw0QkFBUTsiLAogICJuYW1lcyI6IFtdCn0K
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
// src/agent/fetch-response-body-json.ts
|
|
2
|
+
import { AST_NODE_TYPES, ESLintUtils } from "@typescript-eslint/utils";
|
|
3
|
+
import getDocumentationUrl from "../get-documentation-url.mjs";
|
|
4
|
+
var ruleId = "fetch-response-body-json";
|
|
5
|
+
var createRule = ESLintUtils.RuleCreator((name) => getDocumentationUrl(name));
|
|
6
|
+
var rule = createRule({
|
|
7
|
+
name: ruleId,
|
|
8
|
+
meta: {
|
|
9
|
+
type: "suggestion",
|
|
10
|
+
docs: {
|
|
11
|
+
description: 'Replace "response.body" with "await response.json()".'
|
|
12
|
+
},
|
|
13
|
+
messages: {
|
|
14
|
+
replaceBodyWithJson: 'Replace "response.body" with "await response.json()".',
|
|
15
|
+
unknownError: 'Unknown error occurred in file "{{fileName}}": {{ error }}.'
|
|
16
|
+
},
|
|
17
|
+
fixable: "code",
|
|
18
|
+
schema: []
|
|
19
|
+
},
|
|
20
|
+
defaultOptions: [],
|
|
21
|
+
create(context) {
|
|
22
|
+
const parserServices = ESLintUtils.getParserServices(context);
|
|
23
|
+
const typeChecker = parserServices.program.getTypeChecker();
|
|
24
|
+
const sourceCode = context.sourceCode;
|
|
25
|
+
return {
|
|
26
|
+
'MemberExpression[property.name="body"]': (responseBody) => {
|
|
27
|
+
try {
|
|
28
|
+
const responseNode = parserServices.esTreeNodeToTSNodeMap.get(responseBody.object);
|
|
29
|
+
const responseType = typeChecker.getTypeAtLocation(responseNode);
|
|
30
|
+
const shouldReplace = responseType.getProperties().some((symbol) => symbol.name === "body") && responseType.getProperties().some((symbol) => symbol.name === "json");
|
|
31
|
+
if (shouldReplace) {
|
|
32
|
+
const responseText = sourceCode.getText(responseBody.object);
|
|
33
|
+
const needAwait = responseBody.parent.type !== AST_NODE_TYPES.ReturnStatement;
|
|
34
|
+
const replacementText = needAwait ? `(await ${responseText}.json())` : `${responseText}.json()`;
|
|
35
|
+
context.report({
|
|
36
|
+
messageId: "replaceBodyWithJson",
|
|
37
|
+
node: responseBody,
|
|
38
|
+
fix(fixer) {
|
|
39
|
+
return fixer.replaceText(responseBody, replacementText);
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
} catch (error) {
|
|
44
|
+
console.error(`Failed to apply ${ruleId} rule for file "${context.filename}":`, error);
|
|
45
|
+
context.report({
|
|
46
|
+
node: responseBody,
|
|
47
|
+
messageId: "unknownError",
|
|
48
|
+
data: {
|
|
49
|
+
fileName: context.filename,
|
|
50
|
+
error: error instanceof Error ? error.toString() : JSON.stringify(error)
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
var fetch_response_body_json_default = rule;
|
|
59
|
+
export {
|
|
60
|
+
fetch_response_body_json_default as default,
|
|
61
|
+
ruleId
|
|
62
|
+
};
|
|
63
|
+
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vc3JjL2FnZW50L2ZldGNoLXJlc3BvbnNlLWJvZHktanNvbi50cyJdLAogICJtYXBwaW5ncyI6ICI7QUFRQSxTQUFTLGdCQUFnQixtQkFBNkI7QUFFdEQsT0FBTyx5QkFBeUI7QUFFekIsSUFBTSxTQUFTO0FBRXRCLElBQU0sYUFBYSxZQUFZLFlBQVksQ0FBQyxTQUFTLG9CQUFvQixJQUFJLENBQUM7QUFFOUUsSUFBTSxPQUF1RSxXQUFXO0FBQUEsRUFDdEYsTUFBTTtBQUFBLEVBQ04sTUFBTTtBQUFBLElBQ0osTUFBTTtBQUFBLElBQ04sTUFBTTtBQUFBLE1BQ0osYUFBYTtBQUFBLElBQ2Y7QUFBQSxJQUNBLFVBQVU7QUFBQSxNQUNSLHFCQUFxQjtBQUFBLE1BQ3JCLGNBQWM7QUFBQSxJQUNoQjtBQUFBLElBQ0EsU0FBUztBQUFBLElBQ1QsUUFBUSxDQUFDO0FBQUEsRUFDWDtBQUFBLEVBQ0EsZ0JBQWdCLENBQUM7QUFBQSxFQUNqQixPQUFPLFNBQVM7QUFDZCxVQUFNLGlCQUFpQixZQUFZLGtCQUFrQixPQUFPO0FBQzVELFVBQU0sY0FBYyxlQUFlLFFBQVEsZUFBZTtBQUMxRCxVQUFNLGFBQWEsUUFBUTtBQUUzQixXQUFPO0FBQUEsTUFDTCwwQ0FBMEMsQ0FBQyxpQkFBNEM7QUFDckYsWUFBSTtBQUNGLGdCQUFNLGVBQWUsZUFBZSxzQkFBc0IsSUFBSSxhQUFhLE1BQU07QUFDakYsZ0JBQU0sZUFBZSxZQUFZLGtCQUFrQixZQUFZO0FBRS9ELGdCQUFNLGdCQUNKLGFBQWEsY0FBYyxFQUFFLEtBQUssQ0FBQyxXQUFXLE9BQU8sU0FBUyxNQUFNLEtBQ3BFLGFBQWEsY0FBYyxFQUFFLEtBQUssQ0FBQyxXQUFXLE9BQU8sU0FBUyxNQUFNO0FBRXRFLGNBQUksZUFBZTtBQUNqQixrQkFBTSxlQUFlLFdBQVcsUUFBUSxhQUFhLE1BQU07QUFDM0Qsa0JBQU0sWUFBWSxhQUFhLE9BQU8sU0FBUyxlQUFlO0FBQzlELGtCQUFNLGtCQUFrQixZQUFZLFVBQVUsWUFBWSxhQUFhLEdBQUcsWUFBWTtBQUV0RixvQkFBUSxPQUFPO0FBQUEsY0FDYixXQUFXO0FBQUEsY0FDWCxNQUFNO0FBQUEsY0FDTixJQUFJLE9BQU87QUFDVCx1QkFBTyxNQUFNLFlBQVksY0FBYyxlQUFlO0FBQUEsY0FDeEQ7QUFBQSxZQUNGLENBQUM7QUFBQSxVQUNIO0FBQUEsUUFDRixTQUFTLE9BQU87QUFFZCxrQkFBUSxNQUFNLG1CQUFtQixNQUFNLG1CQUFtQixRQUFRLFFBQVEsTUFBTSxLQUFLO0FBQ3JGLGtCQUFRLE9BQU87QUFBQSxZQUNiLE1BQU07QUFBQSxZQUNOLFdBQVc7QUFBQSxZQUNYLE1BQU07QUFBQSxjQUNKLFVBQVUsUUFBUTtBQUFBLGNBQ2xCLE9BQU8saUJBQWlCLFFBQVEsTUFBTSxTQUFTLElBQUksS0FBSyxVQUFVLEtBQUs7QUFBQSxZQUN6RTtBQUFBLFVBQ0YsQ0FBQztBQUFBLFFBQ0g7QUFBQSxNQUNGO0FBQUEsSUFDRjtBQUFBLEVBQ0Y7QUFDRixDQUFDO0FBRUQsSUFBTyxtQ0FBUTsiLAogICJuYW1lcyI6IFtdCn0K
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
// src/agent/fetch-response-header-getter.ts
|
|
2
|
+
import { AST_NODE_TYPES, ESLintUtils } from "@typescript-eslint/utils";
|
|
3
|
+
import getDocumentationUrl from "../get-documentation-url.mjs";
|
|
4
|
+
var ruleId = "fetch-response-header-getter-ts";
|
|
5
|
+
var HEADER_BUILTIN_FUNCTIONS = Object.keys(Headers.prototype);
|
|
6
|
+
var createRule = ESLintUtils.RuleCreator((name) => getDocumentationUrl(name));
|
|
7
|
+
var rule = createRule({
|
|
8
|
+
name: ruleId,
|
|
9
|
+
meta: {
|
|
10
|
+
type: "suggestion",
|
|
11
|
+
docs: {
|
|
12
|
+
description: 'Use "get()" method to get header value from the headers object of the fetch response.'
|
|
13
|
+
},
|
|
14
|
+
messages: {
|
|
15
|
+
useGetter: 'Use "get()" method to get header value from the headers object of the fetch response.',
|
|
16
|
+
unknownError: 'Unknown error occurred in file "{{fileName}}": {{ error }}.'
|
|
17
|
+
},
|
|
18
|
+
fixable: "code",
|
|
19
|
+
schema: []
|
|
20
|
+
},
|
|
21
|
+
defaultOptions: [],
|
|
22
|
+
create(context) {
|
|
23
|
+
const parserServices = ESLintUtils.getParserServices(context);
|
|
24
|
+
const typeChecker = parserServices.program.getTypeChecker();
|
|
25
|
+
const sourceCode = context.sourceCode;
|
|
26
|
+
return {
|
|
27
|
+
MemberExpression: (responseHeadersAccess) => {
|
|
28
|
+
try {
|
|
29
|
+
if (responseHeadersAccess.property.type === AST_NODE_TYPES.Identifier && HEADER_BUILTIN_FUNCTIONS.includes(responseHeadersAccess.property.name)) {
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
const responseHeadersTsNode = parserServices.esTreeNodeToTSNodeMap.get(responseHeadersAccess.object);
|
|
33
|
+
let responseHeadersType = typeChecker.getTypeAtLocation(responseHeadersTsNode);
|
|
34
|
+
responseHeadersType = responseHeadersType.isUnion() ? responseHeadersType.types[0] : responseHeadersType;
|
|
35
|
+
const responseHeadersTypeName = (
|
|
36
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
37
|
+
(responseHeadersType.symbol ?? responseHeadersType.aliasSymbol)?.escapedName
|
|
38
|
+
);
|
|
39
|
+
if (responseHeadersTypeName !== "Headers" && responseHeadersTypeName !== "HeaderGetter") {
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
let replacementText;
|
|
43
|
+
if (!responseHeadersAccess.computed) {
|
|
44
|
+
replacementText = `${sourceCode.getText(responseHeadersAccess.object)}.get('${sourceCode.getText(responseHeadersAccess.property)}')`;
|
|
45
|
+
} else if (responseHeadersAccess.property.type === AST_NODE_TYPES.Identifier || responseHeadersAccess.property.type === AST_NODE_TYPES.Literal || responseHeadersAccess.property.type === AST_NODE_TYPES.TemplateLiteral) {
|
|
46
|
+
replacementText = `${sourceCode.getText(responseHeadersAccess.object)}.get(${sourceCode.getText(responseHeadersAccess.property)})`;
|
|
47
|
+
} else {
|
|
48
|
+
throw new Error(`Unexpected property type: ${responseHeadersAccess.property.type}`);
|
|
49
|
+
}
|
|
50
|
+
context.report({
|
|
51
|
+
messageId: "useGetter",
|
|
52
|
+
node: responseHeadersAccess.property,
|
|
53
|
+
fix(fixer) {
|
|
54
|
+
return fixer.replaceText(responseHeadersAccess, replacementText);
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
} catch (error) {
|
|
58
|
+
console.error(`Failed to apply ${ruleId} rule for file "${context.filename}":`, error);
|
|
59
|
+
context.report({
|
|
60
|
+
node: responseHeadersAccess,
|
|
61
|
+
messageId: "unknownError",
|
|
62
|
+
data: {
|
|
63
|
+
fileName: context.filename,
|
|
64
|
+
error: error instanceof Error ? error.toString() : JSON.stringify(error)
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
// convert response.get() to response.headers.get()
|
|
70
|
+
'CallExpression[callee.property.name="get"]': (responseHeadersAccess) => {
|
|
71
|
+
try {
|
|
72
|
+
if (responseHeadersAccess.callee.type !== AST_NODE_TYPES.MemberExpression) {
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
if (responseHeadersAccess.callee.object.type !== AST_NODE_TYPES.Identifier || responseHeadersAccess.callee.object.name === "request") {
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
const responseNode = responseHeadersAccess.callee.object;
|
|
79
|
+
const responseHeadersTsNode = parserServices.esTreeNodeToTSNodeMap.get(responseNode);
|
|
80
|
+
const responseType = typeChecker.getTypeAtLocation(responseHeadersTsNode);
|
|
81
|
+
const typeName = typeChecker.typeToString(responseType);
|
|
82
|
+
if (typeName === "InboundContext" || typeName.endsWith("RequestType")) {
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
const hasHeadersProperty = responseType.getProperties().some((symbol) => symbol.name === "headers");
|
|
86
|
+
if (!hasHeadersProperty) {
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
const replacementText = `${sourceCode.getText(responseNode)}.headers`;
|
|
90
|
+
context.report({
|
|
91
|
+
messageId: "useGetter",
|
|
92
|
+
node: responseHeadersAccess,
|
|
93
|
+
fix(fixer) {
|
|
94
|
+
return fixer.replaceText(responseNode, replacementText);
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
} catch (error) {
|
|
98
|
+
console.error(`Failed to apply ${ruleId} rule for file "${context.filename}":`, error);
|
|
99
|
+
context.report({
|
|
100
|
+
node: responseHeadersAccess,
|
|
101
|
+
messageId: "unknownError",
|
|
102
|
+
data: {
|
|
103
|
+
fileName: context.filename,
|
|
104
|
+
error: error instanceof Error ? error.toString() : JSON.stringify(error)
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
var fetch_response_header_getter_default = rule;
|
|
113
|
+
export {
|
|
114
|
+
fetch_response_header_getter_default as default,
|
|
115
|
+
ruleId
|
|
116
|
+
};
|
|
117
|
+
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vc3JjL2FnZW50L2ZldGNoLXJlc3BvbnNlLWhlYWRlci1nZXR0ZXIudHMiXSwKICAibWFwcGluZ3MiOiAiO0FBUUEsU0FBUyxnQkFBZ0IsbUJBQTZCO0FBRXRELE9BQU8seUJBQXlCO0FBRXpCLElBQU0sU0FBUztBQUN0QixJQUFNLDJCQUEyQixPQUFPLEtBQUssUUFBUSxTQUFTO0FBRTlELElBQU0sYUFBYSxZQUFZLFlBQVksQ0FBQyxTQUFTLG9CQUFvQixJQUFJLENBQUM7QUFFOUUsSUFBTSxPQUE2RCxXQUFXO0FBQUEsRUFDNUUsTUFBTTtBQUFBLEVBQ04sTUFBTTtBQUFBLElBQ0osTUFBTTtBQUFBLElBQ04sTUFBTTtBQUFBLE1BQ0osYUFBYTtBQUFBLElBQ2Y7QUFBQSxJQUNBLFVBQVU7QUFBQSxNQUNSLFdBQVc7QUFBQSxNQUNYLGNBQWM7QUFBQSxJQUNoQjtBQUFBLElBQ0EsU0FBUztBQUFBLElBQ1QsUUFBUSxDQUFDO0FBQUEsRUFDWDtBQUFBLEVBQ0EsZ0JBQWdCLENBQUM7QUFBQSxFQUNqQixPQUFPLFNBQVM7QUFDZCxVQUFNLGlCQUFpQixZQUFZLGtCQUFrQixPQUFPO0FBQzVELFVBQU0sY0FBYyxlQUFlLFFBQVEsZUFBZTtBQUMxRCxVQUFNLGFBQWEsUUFBUTtBQUUzQixXQUFPO0FBQUEsTUFDTCxrQkFBa0IsQ0FBQywwQkFBcUQ7QUFDdEUsWUFBSTtBQUNGLGNBQ0Usc0JBQXNCLFNBQVMsU0FBUyxlQUFlLGNBQ3ZELHlCQUF5QixTQUFTLHNCQUFzQixTQUFTLElBQUksR0FDckU7QUFFQTtBQUFBLFVBQ0Y7QUFFQSxnQkFBTSx3QkFBd0IsZUFBZSxzQkFBc0IsSUFBSSxzQkFBc0IsTUFBTTtBQUNuRyxjQUFJLHNCQUFzQixZQUFZLGtCQUFrQixxQkFBcUI7QUFFN0UsZ0NBQXNCLG9CQUFvQixRQUFRLElBQUksb0JBQW9CLE1BQU0sQ0FBQyxJQUFLO0FBQ3RGLGdCQUFNO0FBQUE7QUFBQSxhQUNILG9CQUFvQixVQUFV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
|