From f7a8b56d63dc9ef99c981e8368fefb7e427fb341 Mon Sep 17 00:00:00 2001 From: Justin Poehnelt Date: Tue, 21 Dec 2021 16:22:32 -0700 Subject: [PATCH 1/6] feat: add suggestions for no-api-keys --- package.json | 2 +- src/rules/no-api-keys.test.ts | 16 +++++++++++++++- src/rules/no-api-keys.ts | 20 ++++++++++++++++++++ 3 files changed, 36 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index e5db83b..aaf396a 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "prepare": "tsc", "format": "eslint --ext .js,.ts src --fix", "pretest": "eslint --ext .js,.ts src", - "test": "jest" + "test": "jest --detectOpenHandles" }, "dependencies": { "@typescript-eslint/experimental-utils": "^5.2.0", diff --git a/src/rules/no-api-keys.test.ts b/src/rules/no-api-keys.test.ts index 51196fe..b5ebd1a 100644 --- a/src/rules/no-api-keys.test.ts +++ b/src/rules/no-api-keys.test.ts @@ -32,7 +32,21 @@ new RuleTester({ invalid: [ { code: 'const apiKey = "AIza00000000000000000000000000000000000";', - errors: [{ messageId }], + errors: [ + { + messageId, + suggestions: [ + { + messageId: "replaceWithEnvVar", + output: "const apiKey = process.env.GOOGLE_MAPS_API_KEY;", + }, + { + messageId: "replaceWithPlaceholder", + output: 'const apiKey = "YOUR_API_KEY";', + }, + ], + }, + ], }, ], }); diff --git a/src/rules/no-api-keys.ts b/src/rules/no-api-keys.ts index 6badb40..12aa9fd 100644 --- a/src/rules/no-api-keys.ts +++ b/src/rules/no-api-keys.ts @@ -40,7 +40,10 @@ export default createRule({ }, messages: { [messageId]: "Avoid placing API keys in source code.", + replaceWithEnvVar: "Use environment variables instead.", + replaceWithPlaceholder: "Use placeholder `YOUR_API_KEY` instead.", }, + hasSuggestions: true, schema: [], type: "suggestion", }, @@ -52,6 +55,23 @@ export default createRule({ context.report({ node, messageId, + suggest: [ + { + messageId: "replaceWithEnvVar", + fix: (fixer) => { + return fixer.replaceText( + node, + `process.env.GOOGLE_MAPS_API_KEY` + ); + }, + }, + { + messageId: "replaceWithPlaceholder", + fix: (fixer) => { + return fixer.replaceText(node, `"YOUR_API_KEY"`); + }, + }, + ], }); } }, From d6c44ce682838f2666b6957450757fd22472bfa0 Mon Sep 17 00:00:00 2001 From: Justin Poehnelt Date: Tue, 21 Dec 2021 16:55:38 -0700 Subject: [PATCH 2/6] feat: add fixer for place fields objectexpression --- docs/rules/place-fields.md | 13 +++++++++- package-lock.json | 46 +++++++++++++++++----------------- package.json | 4 +-- src/rules/place-fields.test.ts | 6 ++++- src/rules/place-fields.ts | 16 +++++++++++- 5 files changed, 57 insertions(+), 28 deletions(-) diff --git a/docs/rules/place-fields.md b/docs/rules/place-fields.md index dd5d2fd..91e7a8a 100644 --- a/docs/rules/place-fields.md +++ b/docs/rules/place-fields.md @@ -7,6 +7,8 @@ Use the `fields` option to limit the fields returned by the API and costs. Reque 📋 This rule is enabled in `plugin:googlemaps/recommended`. +🔧 The `--fix` option on the [command line](https://eslint.org/docs/user-guide/command-line-interface#fixing-problems) can automatically fix some of the problems reported by this rule. + ## Rule details ❌ Examples of **incorrect** code: @@ -16,7 +18,7 @@ const request = {place_id: 'foo'}; service.getDetails(request) const service = new google.maps.places.PlacesService(); - service.getDetails({}) +service.getDetails({}) const service = new google.maps.places.PlacesService(); service.getDetails({...{bar: 'foo'}}) @@ -47,6 +49,15 @@ service.getDetails(buildRequest()) const service = new google.maps.places.Autocomplete(null, {fields: ['place_id']}); ``` +🔧 Examples of code **fixed** by this rule: +```js +const service = new google.maps.places.PlacesService(); /* → */ const service = new google.maps.places.PlacesService(); +service.getDetails({}) /* → */ service.getDetails({fields: /** TODO: Add necessary fields to the request */ ['place_id'], }) + +const service = new google.maps.places.PlacesService(); /* → */ const service = new google.maps.places.PlacesService(); +service.getDetails({...{bar: 'foo'}}) /* → */ service.getDetails({fields: /** TODO: Add necessary fields to the request */ ['place_id'], ...{bar: 'foo'}}) +``` + ## Resources * [Rule source](/src/rules/place-fields.ts) diff --git a/package-lock.json b/package-lock.json index 6496b83..4278942 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1167,14 +1167,14 @@ } }, "@typescript-eslint/experimental-utils": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.3.0.tgz", - "integrity": "sha512-NFVxYTjKj69qB0FM+piah1x3G/63WB8vCBMnlnEHUsiLzXSTWb9FmFn36FD9Zb4APKBLY3xRArOGSMQkuzTF1w==", + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.8.0.tgz", + "integrity": "sha512-KN5FvNH71bhZ8fKtL+lhW7bjm7cxs1nt+hrDZWIqb6ViCffQcWyLunGrgvISgkRojIDcXIsH+xlFfI4RCDA0xA==", "requires": { "@types/json-schema": "^7.0.9", - "@typescript-eslint/scope-manager": "5.3.0", - "@typescript-eslint/types": "5.3.0", - "@typescript-eslint/typescript-estree": "5.3.0", + "@typescript-eslint/scope-manager": "5.8.0", + "@typescript-eslint/types": "5.8.0", + "@typescript-eslint/typescript-estree": "5.8.0", "eslint-scope": "^5.1.1", "eslint-utils": "^3.0.0" } @@ -1235,26 +1235,26 @@ } }, "@typescript-eslint/scope-manager": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.3.0.tgz", - "integrity": "sha512-22Uic9oRlTsPppy5Tcwfj+QET5RWEnZ5414Prby465XxQrQFZ6nnm5KnXgnsAJefG4hEgMnaxTB3kNEyjdjj6A==", + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.8.0.tgz", + "integrity": "sha512-x82CYJsLOjPCDuFFEbS6e7K1QEWj7u5Wk1alw8A+gnJiYwNnDJk0ib6PCegbaPMjrfBvFKa7SxE3EOnnIQz2Gg==", "requires": { - "@typescript-eslint/types": "5.3.0", - "@typescript-eslint/visitor-keys": "5.3.0" + "@typescript-eslint/types": "5.8.0", + "@typescript-eslint/visitor-keys": "5.8.0" } }, "@typescript-eslint/types": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.3.0.tgz", - "integrity": "sha512-fce5pG41/w8O6ahQEhXmMV+xuh4+GayzqEogN24EK+vECA3I6pUwKuLi5QbXO721EMitpQne5VKXofPonYlAQg==" + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.8.0.tgz", + "integrity": "sha512-LdCYOqeqZWqCMOmwFnum6YfW9F3nKuxJiR84CdIRN5nfHJ7gyvGpXWqL/AaW0k3Po0+wm93ARAsOdzlZDPCcXg==" }, "@typescript-eslint/typescript-estree": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.3.0.tgz", - "integrity": "sha512-FJ0nqcaUOpn/6Z4Jwbtf+o0valjBLkqc3MWkMvrhA2TvzFXtcclIM8F4MBEmYa2kgcI8EZeSAzwoSrIC8JYkug==", + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.8.0.tgz", + "integrity": "sha512-srfeZ3URdEcUsSLbkOFqS7WoxOqn8JNil2NSLO9O+I2/Uyc85+UlfpEvQHIpj5dVts7KKOZnftoJD/Fdv0L7nQ==", "requires": { - "@typescript-eslint/types": "5.3.0", - "@typescript-eslint/visitor-keys": "5.3.0", + "@typescript-eslint/types": "5.8.0", + "@typescript-eslint/visitor-keys": "5.8.0", "debug": "^4.3.2", "globby": "^11.0.4", "is-glob": "^4.0.3", @@ -1263,11 +1263,11 @@ } }, "@typescript-eslint/visitor-keys": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.3.0.tgz", - "integrity": "sha512-oVIAfIQuq0x2TFDNLVavUn548WL+7hdhxYn+9j3YdJJXB7mH9dAmZNJsPDa7Jc+B9WGqoiex7GUDbyMxV0a/aw==", + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.8.0.tgz", + "integrity": "sha512-+HDIGOEMnqbxdAHegxvnOqESUH6RWFRR2b8qxP1W9CZnnYh4Usz6MBL+2KMAgPk/P0o9c1HqnYtwzVH6GTIqug==", "requires": { - "@typescript-eslint/types": "5.3.0", + "@typescript-eslint/types": "5.8.0", "eslint-visitor-keys": "^3.0.0" } }, diff --git a/package.json b/package.json index aaf396a..705507f 100644 --- a/package.json +++ b/package.json @@ -26,8 +26,8 @@ "test": "jest --detectOpenHandles" }, "dependencies": { - "@typescript-eslint/experimental-utils": "^5.2.0", - "@typescript-eslint/scope-manager": "^5.2.0" + "@typescript-eslint/experimental-utils": "^5.8.0", + "@typescript-eslint/scope-manager": "^5.8.0" }, "devDependencies": { "@types/eslint": "^8.2.1", diff --git a/src/rules/place-fields.test.ts b/src/rules/place-fields.test.ts index b29cc12..55459e8 100644 --- a/src/rules/place-fields.test.ts +++ b/src/rules/place-fields.test.ts @@ -51,13 +51,17 @@ service.getDetails(request)`, }, { code: `const service = new google.maps.places.PlacesService(); - service.getDetails({})`, +service.getDetails({})`, errors: [{ messageId }], + output: `const service = new google.maps.places.PlacesService(); +service.getDetails({fields: /** TODO: Add necessary fields to the request */ ['place_id'], })`, }, { code: `const service = new google.maps.places.PlacesService(); service.getDetails({...{bar: 'foo'}})`, errors: [{ messageId }], + output: `const service = new google.maps.places.PlacesService(); +service.getDetails({fields: /** TODO: Add necessary fields to the request */ ['place_id'], ...{bar: 'foo'}})`, }, // Autocomplete { diff --git a/src/rules/place-fields.ts b/src/rules/place-fields.ts index 81c3008..a281767 100644 --- a/src/rules/place-fields.ts +++ b/src/rules/place-fields.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { TSESTree } from "@typescript-eslint/experimental-utils"; +import { TSESLint, TSESTree } from "@typescript-eslint/experimental-utils"; import { Reference } from "@typescript-eslint/scope-manager"; import { createRule, camelCased } from "../utils/rules"; @@ -35,6 +35,7 @@ export default createRule({ }, schema: [], type: "suggestion", + fixable: "code", }, defaultOptions: [], create: (context) => { @@ -94,6 +95,19 @@ export default createRule({ context.report({ messageId, node: node.property, + fix: + requestArgument.type === "ObjectExpression" + ? (fixer: TSESLint.RuleFixer) => { + return [ + fixer.insertTextBefore( + context + .getSourceCode() + .getTokens(requestArgument)[1], + `fields: /** TODO: Add necessary fields to the request */ ['place_id'], ` + ), + ]; + } + : null, }); } } From 0ba6dee83d6112c4e682384942cbf58e9bd8114d Mon Sep 17 00:00:00 2001 From: Justin Poehnelt Date: Tue, 21 Dec 2021 16:58:11 -0700 Subject: [PATCH 3/6] docs: improve test cases for docs --- docs/rules/place-fields.md | 12 ++++++------ src/rules/place-fields.test.ts | 14 +++++++------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/docs/rules/place-fields.md b/docs/rules/place-fields.md index 91e7a8a..10deb06 100644 --- a/docs/rules/place-fields.md +++ b/docs/rules/place-fields.md @@ -14,14 +14,14 @@ Use the `fields` option to limit the fields returned by the API and costs. Reque ❌ Examples of **incorrect** code: ```js const service = new google.maps.places.PlacesService(); -const request = {place_id: 'foo'}; -service.getDetails(request) +service.getDetails({place_id: 'foo'}) const service = new google.maps.places.PlacesService(); -service.getDetails({}) +const request = {place_id: 'foo'}; +service.getDetails(request) const service = new google.maps.places.PlacesService(); -service.getDetails({...{bar: 'foo'}}) +service.getDetails({...{place_id: 'foo'}}) const service = new google.maps.places.Autocomplete(null, {}); const service = new google.maps.places.Autocomplete(null); @@ -52,10 +52,10 @@ const service = new google.maps.places.Autocomplete(null, {fields: ['place_id']} 🔧 Examples of code **fixed** by this rule: ```js const service = new google.maps.places.PlacesService(); /* → */ const service = new google.maps.places.PlacesService(); -service.getDetails({}) /* → */ service.getDetails({fields: /** TODO: Add necessary fields to the request */ ['place_id'], }) +service.getDetails({place_id: 'foo'}) /* → */ service.getDetails({fields: /** TODO: Add necessary fields to the request */ ['place_id'], place_id: 'foo'}) const service = new google.maps.places.PlacesService(); /* → */ const service = new google.maps.places.PlacesService(); -service.getDetails({...{bar: 'foo'}}) /* → */ service.getDetails({fields: /** TODO: Add necessary fields to the request */ ['place_id'], ...{bar: 'foo'}}) +service.getDetails({...{place_id: 'foo'}}) /* → */ service.getDetails({fields: /** TODO: Add necessary fields to the request */ ['place_id'], ...{place_id: 'foo'}}) ``` ## Resources diff --git a/src/rules/place-fields.test.ts b/src/rules/place-fields.test.ts index 55459e8..ddf6952 100644 --- a/src/rules/place-fields.test.ts +++ b/src/rules/place-fields.test.ts @@ -45,23 +45,23 @@ service.getDetails(buildRequest())`, // getDetails { code: `const service = new google.maps.places.PlacesService(); -const request = {place_id: 'foo'}; -service.getDetails(request)`, +service.getDetails({place_id: 'foo'})`, errors: [{ messageId }], + output: `const service = new google.maps.places.PlacesService(); +service.getDetails({fields: /** TODO: Add necessary fields to the request */ ['place_id'], place_id: 'foo'})`, }, { code: `const service = new google.maps.places.PlacesService(); -service.getDetails({})`, +const request = {place_id: 'foo'}; +service.getDetails(request)`, errors: [{ messageId }], - output: `const service = new google.maps.places.PlacesService(); -service.getDetails({fields: /** TODO: Add necessary fields to the request */ ['place_id'], })`, }, { code: `const service = new google.maps.places.PlacesService(); -service.getDetails({...{bar: 'foo'}})`, +service.getDetails({...{place_id: 'foo'}})`, errors: [{ messageId }], output: `const service = new google.maps.places.PlacesService(); -service.getDetails({fields: /** TODO: Add necessary fields to the request */ ['place_id'], ...{bar: 'foo'}})`, +service.getDetails({fields: /** TODO: Add necessary fields to the request */ ['place_id'], ...{place_id: 'foo'}})`, }, // Autocomplete { From 08b55c8ef88534f68c231348e6fe604c336d7758 Mon Sep 17 00:00:00 2001 From: Justin Poehnelt Date: Tue, 21 Dec 2021 17:00:47 -0700 Subject: [PATCH 4/6] docs(README): provide example of fixable rule --- README.md | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 93cbc17..1a0f867 100644 --- a/README.md +++ b/README.md @@ -32,13 +32,24 @@ To use rules provided by the plugin, use the following: } ``` +Some rules are fixable with `eslint --fix`. For example the [place-fields](docs/rules/place-fields.md) rule. + +```js +service.getDetails({place_id: 'foo'}) +``` +becomes + +```js +service.getDetails({fields: /** TODO: Add necessary fields to the request */ ['place_id'], place_id: 'foo'}) +``` + ## Rules | Rule | Description | Configurations | Type | | ------------------------------------------------------------ | ---------------------------------- | ---------------- | ------------ | | [no-api-keys](docs/rules/no-api-keys.md) | Keep API keys out of code. | ![recommended][] | ![suggest][] | | [place-fields](docs/rules/place-fields.md) | Always use place fields. | ![recommended][] | ![suggest][] | -| [require-js-api-loader](docs/rules/require-js-api-loader.md) | Require @googlemaps/js-api-loader. | ![recommended][] | ![suggest][] | +| [require-js-api-loader](docs/rules/require-js-api-loader.md) | Require @googlemaps/js-api-loader. | ![recommended][] | ![fixable][] | [recommended]: https://img.shields.io/badge/-recommended-lightgrey.svg [suggest]: https://img.shields.io/badge/-suggest-yellow.svg From 257e1ec3e8293a066e36b3eac58f86e53435b4da Mon Sep 17 00:00:00 2001 From: Justin Poehnelt Date: Tue, 21 Dec 2021 17:04:20 -0700 Subject: [PATCH 5/6] chore: remove place_id from getDetails fix --- README.md | 2 +- docs/rules/place-fields.md | 4 ++-- src/rules/place-fields.test.ts | 4 ++-- src/rules/place-fields.ts | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 1a0f867..3e0159f 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,7 @@ service.getDetails({place_id: 'foo'}) becomes ```js -service.getDetails({fields: /** TODO: Add necessary fields to the request */ ['place_id'], place_id: 'foo'}) +service.getDetails({fields: /** TODO: Add necessary fields to the request */ [], place_id: 'foo'}) ``` ## Rules diff --git a/docs/rules/place-fields.md b/docs/rules/place-fields.md index 10deb06..8c52a08 100644 --- a/docs/rules/place-fields.md +++ b/docs/rules/place-fields.md @@ -52,10 +52,10 @@ const service = new google.maps.places.Autocomplete(null, {fields: ['place_id']} 🔧 Examples of code **fixed** by this rule: ```js const service = new google.maps.places.PlacesService(); /* → */ const service = new google.maps.places.PlacesService(); -service.getDetails({place_id: 'foo'}) /* → */ service.getDetails({fields: /** TODO: Add necessary fields to the request */ ['place_id'], place_id: 'foo'}) +service.getDetails({place_id: 'foo'}) /* → */ service.getDetails({fields: /** TODO: Add necessary fields to the request */ [], place_id: 'foo'}) const service = new google.maps.places.PlacesService(); /* → */ const service = new google.maps.places.PlacesService(); -service.getDetails({...{place_id: 'foo'}}) /* → */ service.getDetails({fields: /** TODO: Add necessary fields to the request */ ['place_id'], ...{place_id: 'foo'}}) +service.getDetails({...{place_id: 'foo'}}) /* → */ service.getDetails({fields: /** TODO: Add necessary fields to the request */ [], ...{place_id: 'foo'}}) ``` ## Resources diff --git a/src/rules/place-fields.test.ts b/src/rules/place-fields.test.ts index ddf6952..cdd7c6f 100644 --- a/src/rules/place-fields.test.ts +++ b/src/rules/place-fields.test.ts @@ -48,7 +48,7 @@ service.getDetails(buildRequest())`, service.getDetails({place_id: 'foo'})`, errors: [{ messageId }], output: `const service = new google.maps.places.PlacesService(); -service.getDetails({fields: /** TODO: Add necessary fields to the request */ ['place_id'], place_id: 'foo'})`, +service.getDetails({fields: /** TODO: Add necessary fields to the request */ [], place_id: 'foo'})`, }, { code: `const service = new google.maps.places.PlacesService(); @@ -61,7 +61,7 @@ service.getDetails(request)`, service.getDetails({...{place_id: 'foo'}})`, errors: [{ messageId }], output: `const service = new google.maps.places.PlacesService(); -service.getDetails({fields: /** TODO: Add necessary fields to the request */ ['place_id'], ...{place_id: 'foo'}})`, +service.getDetails({fields: /** TODO: Add necessary fields to the request */ [], ...{place_id: 'foo'}})`, }, // Autocomplete { diff --git a/src/rules/place-fields.ts b/src/rules/place-fields.ts index a281767..efeda88 100644 --- a/src/rules/place-fields.ts +++ b/src/rules/place-fields.ts @@ -103,7 +103,7 @@ export default createRule({ context .getSourceCode() .getTokens(requestArgument)[1], - `fields: /** TODO: Add necessary fields to the request */ ['place_id'], ` + `fields: /** TODO: Add necessary fields to the request */ [], ` ), ]; } From c4ec1c568ec3267fe19bfbbf37f0d2332bb362a7 Mon Sep 17 00:00:00 2001 From: Justin Poehnelt Date: Wed, 22 Dec 2021 09:56:47 -0700 Subject: [PATCH 6/6] docs: update place-fields docs --- docs/rules/place-fields.md | 10 ++++++++-- src/rules/place-fields.ts | 11 +++++++++-- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/docs/rules/place-fields.md b/docs/rules/place-fields.md index 8c52a08..62a4946 100644 --- a/docs/rules/place-fields.md +++ b/docs/rules/place-fields.md @@ -2,8 +2,14 @@ # place-fields -Use the `fields` option to limit the fields returned by the API and costs. Request to the Places API are billed by the fields that are returned. See [data-skus](https://developers.google.com/maps/documentation/places/web-service/usage-and-billing#data-skus) for more details. -> **Note**: This rule is not exhaustive and ignores `Autocomplete.setFields()`. +Use the `fields` option to limit the fields returned by the API and costs. Requests to the Places API are billed by the fields that are returned. See [Places Data SKUs](https://developers.google.com/maps/documentation/places/web-service/usage-and-billing#data-skus) for more details. + +More information about fields for specific API calls can be found at the following links: + +- [Place Details fields guidance](https://goo.gle/3H0TxxG) +- [Place Autocomplete fields guidance](https://goo.gle/3sp2XyS) + +> **Note**: This rule is not exhaustive. For example, it ignores `Autocomplete.setFields()`. 📋 This rule is enabled in `plugin:googlemaps/recommended`. diff --git a/src/rules/place-fields.ts b/src/rules/place-fields.ts index efeda88..d440223 100644 --- a/src/rules/place-fields.ts +++ b/src/rules/place-fields.ts @@ -20,8 +20,15 @@ import { createRule, camelCased } from "../utils/rules"; export const messageId = camelCased(__filename); -const description = `Use the \`fields\` option to limit the fields returned by the API and costs. Request to the Places API are billed by the fields that are returned. See [data-skus](https://developers.google.com/maps/documentation/places/web-service/usage-and-billing#data-skus) for more details. -> **Note**: This rule is not exhaustive and ignores \`Autocomplete.setFields()\`.`; +const description = `Use the \`fields\` option to limit the fields returned by the API and costs. Requests to the Places API are billed by the fields that are returned. See [Places Data SKUs](https://developers.google.com/maps/documentation/places/web-service/usage-and-billing#data-skus) for more details. + +More information about fields for specific API calls can be found at the following links: + +- [Place Details fields guidance](https://goo.gle/3H0TxxG) +- [Place Autocomplete fields guidance](https://goo.gle/3sp2XyS) + +> **Note**: This rule is not exhaustive. For example, it ignores \`Autocomplete.setFields()\`.`; + export default createRule({ name: __filename, meta: {