@checkdigit/eslint-plugin 6.6.0-PR.75-c68b → 6.6.0-PR.75-c331

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.
@@ -12250,6 +12250,22 @@
12250
12250
  ],
12251
12251
  "format": "cjs"
12252
12252
  },
12253
+ "src/fixture/fetch-response-body-json.ts": {
12254
+ "bytes": 2433,
12255
+ "imports": [
12256
+ {
12257
+ "path": "node_modules/@typescript-eslint/utils/dist/index.js",
12258
+ "kind": "import-statement",
12259
+ "original": "@typescript-eslint/utils"
12260
+ },
12261
+ {
12262
+ "path": "src/get-documentation-url.ts",
12263
+ "kind": "import-statement",
12264
+ "original": "../get-documentation-url"
12265
+ }
12266
+ ],
12267
+ "format": "esm"
12268
+ },
12253
12269
  "src/ast/format.ts": {
12254
12270
  "bytes": 647,
12255
12271
  "imports": [
@@ -12448,7 +12464,7 @@
12448
12464
  "format": "esm"
12449
12465
  },
12450
12466
  "src/fixture/no-status-code.ts": {
12451
- "bytes": 2355,
12467
+ "bytes": 2353,
12452
12468
  "imports": [
12453
12469
  {
12454
12470
  "path": "node_modules/@typescript-eslint/utils/dist/index.js",
@@ -12509,13 +12525,18 @@
12509
12525
  "format": "esm"
12510
12526
  },
12511
12527
  "src/index.ts": {
12512
- "bytes": 3689,
12528
+ "bytes": 3927,
12513
12529
  "imports": [
12514
12530
  {
12515
12531
  "path": "src/fixture/fetch-header-getter.ts",
12516
12532
  "kind": "import-statement",
12517
12533
  "original": "./fixture/fetch-header-getter"
12518
12534
  },
12535
+ {
12536
+ "path": "src/fixture/fetch-response-body-json.ts",
12537
+ "kind": "import-statement",
12538
+ "original": "./fixture/fetch-response-body-json"
12539
+ },
12519
12540
  {
12520
12541
  "path": "src/fixture/fetch-then.ts",
12521
12542
  "kind": "import-statement",
@@ -15380,7 +15401,7 @@
15380
15401
  "bytesInOutput": 2218
15381
15402
  },
15382
15403
  "src/index.ts": {
15383
- "bytesInOutput": 2434
15404
+ "bytesInOutput": 2528
15384
15405
  },
15385
15406
  "src/ast/tree.ts": {
15386
15407
  "bytesInOutput": 1648
@@ -15400,8 +15421,11 @@
15400
15421
  "src/fixture/fetch-header-getter.ts": {
15401
15422
  "bytesInOutput": 2805
15402
15423
  },
15424
+ "src/fixture/fetch-response-body-json.ts": {
15425
+ "bytesInOutput": 2109
15426
+ },
15403
15427
  "src/ast/format.ts": {
15404
- "bytesInOutput": 382
15428
+ "bytesInOutput": 383
15405
15429
  },
15406
15430
  "src/fixture/variable.ts": {
15407
15431
  "bytesInOutput": 118
@@ -15425,10 +15449,10 @@
15425
15449
  "bytesInOutput": 1849
15426
15450
  },
15427
15451
  "src/fixture/no-service-wrapper.ts": {
15428
- "bytesInOutput": 8649
15452
+ "bytesInOutput": 8651
15429
15453
  },
15430
15454
  "src/fixture/no-status-code.ts": {
15431
- "bytesInOutput": 2036
15455
+ "bytesInOutput": 2034
15432
15456
  },
15433
15457
  "src/file-path-comment.ts": {
15434
15458
  "bytesInOutput": 1961
@@ -15458,7 +15482,7 @@
15458
15482
  "bytesInOutput": 3362
15459
15483
  }
15460
15484
  },
15461
- "bytes": 4296362
15485
+ "bytes": 4300402
15462
15486
  }
15463
15487
  }
15464
15488
  }
@@ -0,0 +1,61 @@
1
+ // src/fixture/fetch-response-body-json.ts
2
+ import { 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
+ context.report({
34
+ messageId: "replaceBodyWithJson",
35
+ node: responseBody,
36
+ fix(fixer) {
37
+ return fixer.replaceText(responseBody, `(await ${responseText}.json())`);
38
+ }
39
+ });
40
+ }
41
+ } catch (error) {
42
+ console.error(`Failed to apply ${ruleId} rule for file "${context.filename}":`, error);
43
+ context.report({
44
+ node: responseBody,
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 fetch_response_body_json_default = rule;
57
+ export {
58
+ fetch_response_body_json_default as default,
59
+ ruleId
60
+ };
61
+ //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vc3JjL2ZpeHR1cmUvZmV0Y2gtcmVzcG9uc2UtYm9keS1qc29uLnRzIl0sCiAgIm1hcHBpbmdzIjogIjtBQVFBLFNBQVMsbUJBQTZCO0FBQ3RDLE9BQU8seUJBQXlCO0FBRXpCLElBQU0sU0FBUztBQUV0QixJQUFNLGFBQWEsWUFBWSxZQUFZLENBQUMsU0FBUyxvQkFBb0IsSUFBSSxDQUFDO0FBRTlFLElBQU0sT0FBTyxXQUFXO0FBQUEsRUFDdEIsTUFBTTtBQUFBLEVBQ04sTUFBTTtBQUFBLElBQ0osTUFBTTtBQUFBLElBQ04sTUFBTTtBQUFBLE1BQ0osYUFBYTtBQUFBLElBQ2Y7QUFBQSxJQUNBLFVBQVU7QUFBQSxNQUNSLHFCQUFxQjtBQUFBLE1BQ3JCLGNBQWM7QUFBQSxJQUNoQjtBQUFBLElBQ0EsU0FBUztBQUFBLElBQ1QsUUFBUSxDQUFDO0FBQUEsRUFDWDtBQUFBLEVBQ0EsZ0JBQWdCLENBQUM7QUFBQSxFQUNqQixPQUFPLFNBQVM7QUFDZCxVQUFNLGlCQUFpQixZQUFZLGtCQUFrQixPQUFPO0FBQzVELFVBQU0sY0FBYyxlQUFlLFFBQVEsZUFBZTtBQUMxRCxVQUFNLGFBQWEsUUFBUTtBQUUzQixXQUFPO0FBQUEsTUFDTCwwQ0FBMEMsQ0FBQyxpQkFBNEM7QUFDckYsWUFBSTtBQUNGLGdCQUFNLGVBQWUsZUFBZSxzQkFBc0IsSUFBSSxhQUFhLE1BQU07QUFDakYsZ0JBQU0sZUFBZSxZQUFZLGtCQUFrQixZQUFZO0FBRS9ELGdCQUFNLGdCQUNKLGFBQWEsY0FBYyxFQUFFLEtBQUssQ0FBQyxXQUFXLE9BQU8sU0FBUyxNQUFNLEtBQ3BFLGFBQWEsY0FBYyxFQUFFLEtBQUssQ0FBQyxXQUFXLE9BQU8sU0FBUyxNQUFNO0FBRXRFLGNBQUksZUFBZTtBQUNqQixrQkFBTSxlQUFlLFdBQVcsUUFBUSxhQUFhLE1BQU07QUFDM0Qsb0JBQVEsT0FBTztBQUFBLGNBQ2IsV0FBVztBQUFBLGNBQ1gsTUFBTTtBQUFBLGNBQ04sSUFBSSxPQUFPO0FBQ1QsdUJBQU8sTUFBTSxZQUFZLGNBQWMsVUFBVSxZQUFZLFVBQVU7QUFBQSxjQUN6RTtBQUFBLFlBQ0YsQ0FBQztBQUFBLFVBQ0g7QUFBQSxRQUNGLFNBQVMsT0FBTztBQUVkLGtCQUFRLE1BQU0sbUJBQW1CLE1BQU0sbUJBQW1CLFFBQVEsUUFBUSxNQUFNLEtBQUs7QUFDckYsa0JBQVEsT0FBTztBQUFBLFlBQ2IsTUFBTTtBQUFBLFlBQ04sV0FBVztBQUFBLFlBQ1gsTUFBTTtBQUFBLGNBQ0osVUFBVSxRQUFRO0FBQUEsY0FDbEIsT0FBTyxpQkFBaUIsUUFBUSxNQUFNLFNBQVMsSUFBSSxLQUFLLFVBQVUsS0FBSztBQUFBLFlBQ3pFO0FBQUEsVUFDRixDQUFDO0FBQUEsUUFDSDtBQUFBLE1BQ0Y7QUFBQSxJQUNGO0FBQUEsRUFDRjtBQUNGLENBQUM7QUFFRCxJQUFPLG1DQUFROyIsCiAgIm5hbWVzIjogW10KfQo=
@@ -11,7 +11,7 @@ var rule = createRule({
11
11
  description: 'Access the status code property of the fetch Response using "status" instead of "statusCode".'
12
12
  },
13
13
  messages: {
14
- replaceStatusCode: 'Replacing "statusCode" with "status".',
14
+ replaceStatusCode: 'Replace "statusCode" with "status".',
15
15
  unknownError: 'Unknown error occurred in file "{{fileName}}": {{ error }}.'
16
16
  },
17
17
  fixable: "code",
@@ -1,5 +1,6 @@
1
1
  // src/index.ts
2
2
  import fetchHeaderGetter, { ruleId as fetchHeaderGetterRuleId } from "./fixture/fetch-header-getter.mjs";
3
+ import fetchResponseBodyJson, { ruleId as fetchResponseBodyJsonRuleId } from "./fixture/fetch-response-body-json.mjs";
3
4
  import fetchThen, { ruleId as fetchThenRuleId } from "./fixture/fetch-then.mjs";
4
5
  import invalidJsonStringify, { ruleId as invalidJsonStringifyRuleId } from "./invalid-json-stringify.mjs";
5
6
  import noFixture, { ruleId as noFixtureRuleId } from "./fixture/no-fixture.mjs";
@@ -32,7 +33,8 @@ var src_default = {
32
33
  [fetchHeaderGetterRuleId]: fetchHeaderGetter,
33
34
  [fetchThenRuleId]: fetchThen,
34
35
  [noServiceWrapperRuleId]: noServiceWrapper,
35
- [noStatusCodeRuleId]: noStatusCode
36
+ [noStatusCodeRuleId]: noStatusCode,
37
+ [fetchResponseBodyJsonRuleId]: fetchResponseBodyJson
36
38
  },
37
39
  configs: {
38
40
  all: {
@@ -52,7 +54,8 @@ var src_default = {
52
54
  [`@checkdigit/${fetchHeaderGetterRuleId}`]: "error",
53
55
  [`@checkdigit/${fetchThenRuleId}`]: "error",
54
56
  [`@checkdigit/${noServiceWrapperRuleId}`]: "error",
55
- [`@checkdigit/${noStatusCodeRuleId}`]: "error"
57
+ [`@checkdigit/${noStatusCodeRuleId}`]: "error",
58
+ [`@checkdigit/${fetchResponseBodyJsonRuleId}`]: "error"
56
59
  }
57
60
  },
58
61
  recommended: {
@@ -75,4 +78,4 @@ var src_default = {
75
78
  export {
76
79
  src_default as default
77
80
  };
78
- //# sourceMappingURL=data:application/json;base64,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
81
+ //# sourceMappingURL=data:application/json;base64,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
@@ -0,0 +1,4 @@
1
+ import { ESLintUtils } from '@typescript-eslint/utils';
2
+ export declare const ruleId = "fetch-response-body-json";
3
+ declare const rule: ESLintUtils.RuleModule<"replaceBodyWithJson" | "unknownError", never[], ESLintUtils.RuleListener>;
4
+ export default rule;
@@ -1,4 +1,4 @@
1
1
  import { ESLintUtils } from '@typescript-eslint/utils';
2
2
  export declare const ruleId = "no-service-wrapper";
3
- declare const rule: ESLintUtils.RuleModule<"preferNativeFetch" | "unknownError" | "invalidOptions", never[], ESLintUtils.RuleListener>;
3
+ declare const rule: ESLintUtils.RuleModule<"unknownError" | "preferNativeFetch" | "invalidOptions", never[], ESLintUtils.RuleListener>;
4
4
  export default rule;
@@ -14,8 +14,9 @@ declare const _default: {
14
14
  "no-fixture": import("eslint").Rule.RuleModule;
15
15
  "fetch-header-getter": import("eslint").Rule.RuleModule;
16
16
  "fetch-then": import("eslint").Rule.RuleModule;
17
- "no-service-wrapper": import("@typescript-eslint/utils/ts-eslint").RuleModule<"preferNativeFetch" | "unknownError" | "invalidOptions", never[], import("@typescript-eslint/utils/ts-eslint").RuleListener>;
17
+ "no-service-wrapper": import("@typescript-eslint/utils/ts-eslint").RuleModule<"unknownError" | "preferNativeFetch" | "invalidOptions", never[], import("@typescript-eslint/utils/ts-eslint").RuleListener>;
18
18
  "no-status-code": import("@typescript-eslint/utils/ts-eslint").RuleModule<"unknownError" | "replaceStatusCode", never[], import("@typescript-eslint/utils/ts-eslint").RuleListener>;
19
+ "fetch-response-body-json": import("@typescript-eslint/utils/ts-eslint").RuleModule<"replaceBodyWithJson" | "unknownError", never[], import("@typescript-eslint/utils/ts-eslint").RuleListener>;
19
20
  };
20
21
  configs: {
21
22
  all: {
@@ -36,6 +37,7 @@ declare const _default: {
36
37
  "@checkdigit/fetch-then": string;
37
38
  "@checkdigit/no-service-wrapper": string;
38
39
  "@checkdigit/no-status-code": string;
40
+ "@checkdigit/fetch-response-body-json": string;
39
41
  };
40
42
  };
41
43
  recommended: {
package/package.json CHANGED
@@ -1 +1 @@
1
- {"name":"@checkdigit/eslint-plugin","version":"6.6.0-PR.75-c68b","description":"Check Digit eslint plugins","keywords":["eslint","eslintplugin"],"homepage":"https://github.com/checkdigit/eslint-plugin#readme","bugs":{"url":"https://github.com/checkdigit/eslint-plugin/issues"},"repository":{"type":"git","url":"https://github.com/checkdigit/eslint-plugin"},"license":"MIT","author":"Check Digit, LLC","sideEffects":false,"type":"module","exports":{".":{"types":"./dist-types/index.d.ts","require":"./dist-cjs/index.cjs","import":"./dist-mjs/index.mjs","default":"./dist-mjs/index.mjs"}},"files":["src","dist-types","dist-cjs","dist-mjs","!src/**/*.test.ts","!src/**/*.spec.ts","!dist-types/**/*.test.d.ts","!dist-types/**/*.spec.d.ts","!dist-cjs/**/*.test.cjs","!dist-cjs/**/*.spec.cjs","!dist-mjs/**/*.test.mjs","!dist-mjs/**/*.spec.mjs","SECURITY.md"],"scripts":{"build:dist-cjs":"rimraf dist-cjs && npx builder --type=commonjs --sourceMap --entryPoint=index.ts --outDir=dist-cjs --outFile=index.cjs --external=espree && echo \"module.exports = module.exports.default;\" >> dist-cjs/index.cjs","build:dist-mjs":"rimraf dist-mjs && npx builder --type=module --sourceMap --outDir=dist-mjs && node dist-mjs/index.mjs","build:dist-types":"rimraf dist-types && npx builder --type=types --outDir=dist-types","ci:compile":"tsc --noEmit","ci:coverage":"NODE_OPTIONS=\"--disable-warning ExperimentalWarning --experimental-vm-modules\" jest --coverage=true","ci:lint":"npm run lint","ci:style":"npm run prettier","ci:test":"NODE_OPTIONS=\"--disable-warning ExperimentalWarning --experimental-vm-modules\" jest --coverage=false","lint":"eslint --max-warnings 0 --ignore-path .gitignore .","lint:fix":"eslint --ignore-path .gitignore . --fix","prepublishOnly":"npm run build:dist-types && npm run build:dist-cjs && npm run build:dist-mjs","prettier":"prettier --ignore-path .gitignore --list-different .","prettier:fix":"prettier --ignore-path .gitignore --write .","test":"npm run ci:compile && npm run ci:test && npm run ci:lint && npm run ci:style"},"prettier":"@checkdigit/prettier-config","jest":{"preset":"@checkdigit/jest-config"},"dependencies":{"@typescript-eslint/type-utils":"7.18.0","@typescript-eslint/utils":"7.18.0","ts-api-utils":"^1.3.0"},"devDependencies":{"@checkdigit/jest-config":"^6.0.2","@checkdigit/prettier-config":"^5.5.0","@checkdigit/typescript-config":"6.0.0","@types/eslint":"^8.56.10","@typescript-eslint/eslint-plugin":"^7.18.0","@typescript-eslint/parser":"^7.18.0","@typescript-eslint/rule-tester":"7.18.0","eslint-config-prettier":"^9.1.0","eslint-plugin-eslint-plugin":"^6.2.0","eslint-plugin-import":"^2.29.1","eslint-plugin-no-only-tests":"^3.1.0","eslint-plugin-no-secrets":"^1.0.2","eslint-plugin-node":"^11.1.0","eslint-plugin-sonarjs":"0.24.0"},"peerDependencies":{"eslint":">=8 <9"},"engines":{"node":">=20.14"}}
1
+ {"name":"@checkdigit/eslint-plugin","version":"6.6.0-PR.75-c331","description":"Check Digit eslint plugins","keywords":["eslint","eslintplugin"],"homepage":"https://github.com/checkdigit/eslint-plugin#readme","bugs":{"url":"https://github.com/checkdigit/eslint-plugin/issues"},"repository":{"type":"git","url":"https://github.com/checkdigit/eslint-plugin"},"license":"MIT","author":"Check Digit, LLC","sideEffects":false,"type":"module","exports":{".":{"types":"./dist-types/index.d.ts","require":"./dist-cjs/index.cjs","import":"./dist-mjs/index.mjs","default":"./dist-mjs/index.mjs"}},"files":["src","dist-types","dist-cjs","dist-mjs","!src/**/*.test.ts","!src/**/*.spec.ts","!dist-types/**/*.test.d.ts","!dist-types/**/*.spec.d.ts","!dist-cjs/**/*.test.cjs","!dist-cjs/**/*.spec.cjs","!dist-mjs/**/*.test.mjs","!dist-mjs/**/*.spec.mjs","SECURITY.md"],"scripts":{"build:dist-cjs":"rimraf dist-cjs && npx builder --type=commonjs --sourceMap --entryPoint=index.ts --outDir=dist-cjs --outFile=index.cjs --external=espree && echo \"module.exports = module.exports.default;\" >> dist-cjs/index.cjs","build:dist-mjs":"rimraf dist-mjs && npx builder --type=module --sourceMap --outDir=dist-mjs && node dist-mjs/index.mjs","build:dist-types":"rimraf dist-types && npx builder --type=types --outDir=dist-types","ci:compile":"tsc --noEmit","ci:coverage":"NODE_OPTIONS=\"--disable-warning ExperimentalWarning --experimental-vm-modules\" jest --coverage=true","ci:lint":"npm run lint","ci:style":"npm run prettier","ci:test":"NODE_OPTIONS=\"--disable-warning ExperimentalWarning --experimental-vm-modules\" jest --coverage=false","lint":"eslint --max-warnings 0 --ignore-path .gitignore .","lint:fix":"eslint --ignore-path .gitignore . --fix","prepublishOnly":"npm run build:dist-types && npm run build:dist-cjs && npm run build:dist-mjs","prettier":"prettier --ignore-path .gitignore --list-different .","prettier:fix":"prettier --ignore-path .gitignore --write .","test":"npm run ci:compile && npm run ci:test && npm run ci:lint && npm run ci:style"},"prettier":"@checkdigit/prettier-config","jest":{"preset":"@checkdigit/jest-config"},"dependencies":{"@typescript-eslint/type-utils":"7.18.0","@typescript-eslint/utils":"7.18.0","ts-api-utils":"^1.3.0"},"devDependencies":{"@checkdigit/jest-config":"^6.0.2","@checkdigit/prettier-config":"^5.5.0","@checkdigit/typescript-config":"6.0.0","@types/eslint":"^8.56.10","@typescript-eslint/eslint-plugin":"^7.18.0","@typescript-eslint/parser":"^7.18.0","@typescript-eslint/rule-tester":"7.18.0","eslint-config-prettier":"^9.1.0","eslint-plugin-eslint-plugin":"^6.2.0","eslint-plugin-import":"^2.29.1","eslint-plugin-no-only-tests":"^3.1.0","eslint-plugin-no-secrets":"^1.0.2","eslint-plugin-node":"^11.1.0","eslint-plugin-sonarjs":"0.24.0"},"peerDependencies":{"eslint":">=8 <9"},"engines":{"node":">=20.14"}}
@@ -0,0 +1,73 @@
1
+ // fixture/fetch-response-body-json.ts
2
+
3
+ /*
4
+ * Copyright (c) 2021-2024 Check Digit, LLC
5
+ *
6
+ * This code is licensed under the MIT license (see LICENSE.txt for details).
7
+ */
8
+
9
+ import { ESLintUtils, TSESTree } from '@typescript-eslint/utils';
10
+ import getDocumentationUrl from '../get-documentation-url';
11
+
12
+ export const ruleId = 'fetch-response-body-json';
13
+
14
+ const createRule = ESLintUtils.RuleCreator((name) => getDocumentationUrl(name));
15
+
16
+ const rule = createRule({
17
+ name: ruleId,
18
+ meta: {
19
+ type: 'suggestion',
20
+ docs: {
21
+ description: 'Replace "response.body" with "await response.json()".',
22
+ },
23
+ messages: {
24
+ replaceBodyWithJson: 'Replace "response.body" with "await response.json()".',
25
+ unknownError: 'Unknown error occurred in file "{{fileName}}": {{ error }}.',
26
+ },
27
+ fixable: 'code',
28
+ schema: [],
29
+ },
30
+ defaultOptions: [],
31
+ create(context) {
32
+ const parserServices = ESLintUtils.getParserServices(context);
33
+ const typeChecker = parserServices.program.getTypeChecker();
34
+ const sourceCode = context.sourceCode;
35
+
36
+ return {
37
+ 'MemberExpression[property.name="body"]': (responseBody: TSESTree.MemberExpression) => {
38
+ try {
39
+ const responseNode = parserServices.esTreeNodeToTSNodeMap.get(responseBody.object);
40
+ const responseType = typeChecker.getTypeAtLocation(responseNode);
41
+
42
+ const shouldReplace =
43
+ responseType.getProperties().some((symbol) => symbol.name === 'body') &&
44
+ responseType.getProperties().some((symbol) => symbol.name === 'json');
45
+
46
+ if (shouldReplace) {
47
+ const responseText = sourceCode.getText(responseBody.object);
48
+ context.report({
49
+ messageId: 'replaceBodyWithJson',
50
+ node: responseBody,
51
+ fix(fixer) {
52
+ return fixer.replaceText(responseBody, `(await ${responseText}.json())`);
53
+ },
54
+ });
55
+ }
56
+ } catch (error) {
57
+ // eslint-disable-next-line no-console
58
+ console.error(`Failed to apply ${ruleId} rule for file "${context.filename}":`, error);
59
+ context.report({
60
+ node: responseBody,
61
+ messageId: 'unknownError',
62
+ data: {
63
+ fileName: context.filename,
64
+ error: error instanceof Error ? error.toString() : JSON.stringify(error),
65
+ },
66
+ });
67
+ }
68
+ },
69
+ };
70
+ },
71
+ });
72
+
73
+ export default rule;
@@ -21,7 +21,7 @@ const rule = createRule({
21
21
  description: 'Access the status code property of the fetch Response using "status" instead of "statusCode".',
22
22
  },
23
23
  messages: {
24
- replaceStatusCode: 'Replacing "statusCode" with "status".',
24
+ replaceStatusCode: 'Replace "statusCode" with "status".',
25
25
  unknownError: 'Unknown error occurred in file "{{fileName}}": {{ error }}.',
26
26
  },
27
27
  fixable: 'code',
package/src/index.ts CHANGED
@@ -7,6 +7,7 @@
7
7
  */
8
8
 
9
9
  import fetchHeaderGetter, { ruleId as fetchHeaderGetterRuleId } from './fixture/fetch-header-getter';
10
+ import fetchResponseBodyJson, { ruleId as fetchResponseBodyJsonRuleId } from './fixture/fetch-response-body-json';
10
11
  import fetchThen, { ruleId as fetchThenRuleId } from './fixture/fetch-then';
11
12
  import invalidJsonStringify, { ruleId as invalidJsonStringifyRuleId } from './invalid-json-stringify';
12
13
  import noFixture, { ruleId as noFixtureRuleId } from './fixture/no-fixture';
@@ -41,6 +42,7 @@ export default {
41
42
  [fetchThenRuleId]: fetchThen,
42
43
  [noServiceWrapperRuleId]: noServiceWrapper,
43
44
  [noStatusCodeRuleId]: noStatusCode,
45
+ [fetchResponseBodyJsonRuleId]: fetchResponseBodyJson,
44
46
  },
45
47
  configs: {
46
48
  all: {
@@ -61,6 +63,7 @@ export default {
61
63
  [`@checkdigit/${fetchThenRuleId}`]: 'error',
62
64
  [`@checkdigit/${noServiceWrapperRuleId}`]: 'error',
63
65
  [`@checkdigit/${noStatusCodeRuleId}`]: 'error',
66
+ [`@checkdigit/${fetchResponseBodyJsonRuleId}`]: 'error',
64
67
  },
65
68
  },
66
69
  recommended: {