diff --git a/components/google_maps_platform/.gitignore b/components/google_maps_platform/.gitignore deleted file mode 100644 index ec761ccab7595..0000000000000 --- a/components/google_maps_platform/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -*.js -*.mjs -dist \ No newline at end of file diff --git a/components/google_maps_platform/actions/get-place-details/get-place-details.mjs b/components/google_maps_platform/actions/get-place-details/get-place-details.mjs new file mode 100644 index 0000000000000..12de9b93285e1 --- /dev/null +++ b/components/google_maps_platform/actions/get-place-details/get-place-details.mjs @@ -0,0 +1,26 @@ +import app from "../../google_maps_platform.app.mjs"; + +export default { + key: "google_maps_platform-get-place-details", + name: "Get Place Details", + description: "Retrieves detailed information for a specific place using its Place ID. [See the documentation](https://developers.google.com/maps/documentation/places/web-service/place-details)", + version: "0.0.1", + type: "action", + props: { + app, + placeId: { + type: "string", + label: "Place ID", + description: "A textual identifier that uniquely identifies a place, returned from Search Places Action.", + }, + }, + async run({ $ }) { + const response = await this.app.getPlaceDetails({ + $, + placeId: this.placeId, + }); + + $.export("$summary", `Retrieved details for Place ID ${this.placeId}`); + return response; + }, +}; diff --git a/components/google_maps_platform/actions/search-places/search-places.mjs b/components/google_maps_platform/actions/search-places/search-places.mjs new file mode 100644 index 0000000000000..dcb8ae35cb644 --- /dev/null +++ b/components/google_maps_platform/actions/search-places/search-places.mjs @@ -0,0 +1,123 @@ +import { + LANGUAGE_CODE_OPTIONS, + PRICE_LEVEL_OPTIONS, + RANK_PREFERENCE_OPTIONS, +} from "../../common/constants.mjs"; +import { parseObject } from "../../common/utils.mjs"; +import app from "../../google_maps_platform.app.mjs"; + +export default { + key: "google_maps_platform-search-places", + name: "Search Places", + description: "Searches for places based on location, radius, and optional filters like keywords, place type, or name. [See the documentation](https://developers.google.com/maps/documentation/places/web-service/text-search)", + version: "0.0.1", + type: "action", + props: { + app, + textQuery: { + type: "string", + label: "Text Query", + description: "The text string on which to search, for example: \"restaurant\", \"123 Main Street\", or \"best place to visit in San Francisco\". The API returns candidate matches based on this string and orders the results based on their perceived relevance.", + }, + includedType: { + type: "string", + label: "Included Type", + description: "Restricts the results to places matching the specified type defined by [Table A](https://developers.google.com/maps/documentation/places/web-service/place-types#table-a). Only one type may be specified.", + optional: true, + }, + includePureServiceAreaBusinesses: { + type: "boolean", + label: "Include Pure Service Area Businesses", + description: "If set to `true`, the response includes businesses that visit or deliver to customers directly, but don't have a physical business location. If set to `false`, the API returns only businesses with a physical business location.", + optional: true, + }, + languageCode: { + type: "string", + label: "Language Code", + description: "The language in which to return results.", + options: LANGUAGE_CODE_OPTIONS, + optional: true, + }, + locationBias: { + type: "object", + label: "Location Bias", + description: "Specifies an area to search. This location serves as a bias which means results around the specified location can be returned, including results outside the specified area. [See the documentation](https://developers.google.com/maps/documentation/places/web-service/text-search#location-bias) for further information.", + optional: true, + }, + locationRestriction: { + type: "string", + label: "Location Restriction", + description: "Specifies an area to search. Results outside the specified area are not returned.", + optional: true, + }, + evOptions: { + type: "object", + label: "EV Options", + description: "Specifies parameters for identifying available electric vehicle (EV) charging connectors and charging rates. [See the documentation](https://developers.google.com/maps/documentation/places/web-service/text-search#evoptions) for further information.", + optional: true, + }, + minRating: { + type: "string", + label: "Min Rating", + description: "Restricts results to only those whose average user rating is greater than or equal to this limit. Values must be between 0.0 and 5.0 (inclusive) in increments of 0.5. For example: 0, 0.5, 1.0, ... , 5.0 inclusive. Values are rounded up to the nearest 0.5. For example, a value of 0.6 eliminates all results with a rating less than 1.0.", + optional: true, + }, + openNow: { + type: "boolean", + label: "Open Now", + description: "If `true`, return only those places that are open for business at the time the query is sent. If `false`, return all businesses regardless of open status. Places that don't specify opening hours in the Google Places database are returned if you set this parameter to `false`.", + optional: true, + }, + priceLevels: { + type: "string[]", + label: "Price Levels", + description: "Restrict the search to places that are marked at certain price levels. The default is to select all price levels.", + options: PRICE_LEVEL_OPTIONS, + optional: true, + }, + rankPreference: { + type: "string", + label: "Rank Preference", + description: "Specifies how the results are ranked in the response based on the type of query: For a categorical query such as \"Restaurants in New York City\", RELEVANCE (rank results by search relevance) is the default. You can set Rank Preference to RELEVANCE or DISTANCE (rank results by distance). For a non-categorical query such as \"Mountain View, CA\", it is recommended that you leave Rank Preference unset.", + options: RANK_PREFERENCE_OPTIONS, + optional: true, + }, + regionCode: { + type: "string", + label: "Region Code", + description: "The region code used to format the response, specified as a [two-character CLDR code](https://www.unicode.org/cldr/charts/46/supplemental/territory_language_information.html) value. This parameter can also have a bias effect on the search results.", + optional: true, + }, + strictTypeFiltering: { + type: "boolean", + label: "Strict Type Filtering", + description: "Used with the `Included Type` parameter. When set to `true`, only places that match the specified types specified by includeType are returned. When `false`, the default, the response can contain places that don't match the specified types.", + optional: true, + }, + }, + async run({ $ }) { + const response = await this.app.searchPlaces({ + $, + data: { + textQuery: this.textQuery, + includedType: this.includedType, + includePureServiceAreaBusinesses: this.includePureServiceAreaBusinesses, + languageCode: this.languageCode, + locationBias: parseObject(this.locationBias), + locationRestriction: this.locationRestriction, + evOptions: parseObject(this.evOptions), + minRating: this.minRating, + openNow: this.openNow, + priceLevels: parseObject(this.priceLevels), + rankPreference: this.rankPreference, + regionCode: this.regionCode, + strictTypeFiltering: this.strictTypeFiltering, + }, + }); + + const placeCount = response.places?.length || 0; + $.export("$summary", `Found ${placeCount} place(s)`); + + return response; + }, +}; diff --git a/components/google_maps_platform/app/google_maps_platform.app.ts b/components/google_maps_platform/app/google_maps_platform.app.ts deleted file mode 100644 index b9271d2b6472a..0000000000000 --- a/components/google_maps_platform/app/google_maps_platform.app.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { defineApp } from "@pipedream/types"; - -export default defineApp({ - type: "app", - app: "google_maps_platform", - propDefinitions: {}, - methods: { - // this.$auth contains connected account data - authKeys() { - console.log(Object.keys(this.$auth)); - }, - }, -}); \ No newline at end of file diff --git a/components/google_maps_platform/common/constants.mjs b/components/google_maps_platform/common/constants.mjs new file mode 100644 index 0000000000000..5862d59bf62a3 --- /dev/null +++ b/components/google_maps_platform/common/constants.mjs @@ -0,0 +1,364 @@ +export const LANGUAGE_CODE_OPTIONS = [ + { + label: "Afrikaans", + value: "af", + }, + { + label: "Albanian", + value: "sq", + }, + { + label: "Amharic", + value: "am", + }, + { + label: "Arabic", + value: "ar", + }, + { + label: "Armenian", + value: "hy", + }, + { + label: "Azerbaijani", + value: "az", + }, + { + label: "Basque", + value: "eu", + }, + { + label: "Belarusian", + value: "be", + }, + { + label: "Bengali", + value: "bn", + }, + { + label: "Bosnian", + value: "bs", + }, + { + label: "Bulgarian", + value: "bg", + }, + { + label: "Burmese", + value: "my", + }, + { + label: "Catalan", + value: "ca", + }, + { + label: "Chinese", + value: "zh", + }, + { + label: "Chinese (Simplified)", + value: "zh-CN", + }, + { + label: "Chinese (Hong Kong)", + value: "zh-HK", + }, + { + label: "Chinese (Traditional)", + value: "zh-TW", + }, + { + label: "Croatian", + value: "hr", + }, + { + label: "Czech", + value: "cs", + }, + { + label: "Danish", + value: "da", + }, + { + label: "Dutch", + value: "nl", + }, + { + label: "English", + value: "en", + }, + { + label: "English (Australian)", + value: "en-AU", + }, + { + label: "English (Great Britain)", + value: "en-GB", + }, + { + label: "Estonian", + value: "et", + }, + { + label: "Farsi", + value: "fa", + }, + { + label: "Finnish", + value: "fi", + }, + { + label: "Filipino", + value: "fil", + }, + { + label: "French", + value: "fr", + }, + { + label: "French (Canada)", + value: "fr-CA", + }, + { + label: "Galician", + value: "gl", + }, + { + label: "Georgian", + value: "ka", + }, + { + label: "German", + value: "de", + }, + { + label: "Greek", + value: "el", + }, + { + label: "Gujarati", + value: "gu", + }, + { + label: "Hebrew", + value: "iw", + }, + { + label: "Hindi", + value: "hi", + }, + { + label: "Hungarian", + value: "hu", + }, + { + label: "Icelandic", + value: "is", + }, + { + label: "Indonesian", + value: "id", + }, + { + label: "Italian", + value: "it", + }, + { + label: "Japanese", + value: "ja", + }, + { + label: "Kannada", + value: "kn", + }, + { + label: "Kazakh", + value: "kk", + }, + { + label: "Khmer", + value: "km", + }, + { + label: "Korean", + value: "ko", + }, + { + label: "Kyrgyz", + value: "ky", + }, + { + label: "Lao", + value: "lo", + }, + { + label: "Latvian", + value: "lv", + }, + { + label: "Lithuanian", + value: "lt", + }, + { + label: "Macedonian", + value: "mk", + }, + { + label: "Malay", + value: "ms", + }, + { + label: "Malayalam", + value: "ml", + }, + { + label: "Marathi", + value: "mr", + }, + { + label: "Mongolian", + value: "mn", + }, + { + label: "Nepali", + value: "ne", + }, + { + label: "Norwegian", + value: "no", + }, + { + label: "Polish", + value: "pl", + }, + { + label: "Portuguese", + value: "pt", + }, + { + label: "Portuguese (Brazil)", + value: "pt-BR", + }, + { + label: "Portuguese (Portugal)", + value: "pt-PT", + }, + { + label: "Punjabi", + value: "pa", + }, + { + label: "Romanian", + value: "ro", + }, + { + label: "Russian", + value: "ru", + }, + { + label: "Serbian", + value: "sr", + }, + { + label: "Sinhalese", + value: "si", + }, + { + label: "Slovak", + value: "sk", + }, + { + label: "Slovenian", + value: "sl", + }, + { + label: "Spanish", + value: "es", + }, + { + label: "Spanish (Latin America)", + value: "es-419", + }, + { + label: "Swahili", + value: "sw", + }, + { + label: "Swedish", + value: "sv", + }, + { + label: "Tamil", + value: "ta", + }, + { + label: "Telugu", + value: "te", + }, + { + label: "Thai", + value: "th", + }, + { + label: "Turkish", + value: "tr", + }, + { + label: "Ukrainian", + value: "uk", + }, + { + label: "Urdu", + value: "ur", + }, + { + label: "Uzbek", + value: "uz", + }, + { + label: "Vietnamese", + value: "vi", + }, + { + label: "Zulu", + value: "zu", + }, +]; + +export const PRICE_LEVEL_OPTIONS = [ + { + label: "Place price level is unspecified or unknown.", + value: "PRICE_LEVEL_UNSPECIFIED", + }, + { + label: "Place provides free services.", + value: "PRICE_LEVEL_FREE", + }, + { + label: "Place provides inexpensive services.", + value: "PRICE_LEVEL_INEXPENSIVE", + }, + { + label: "Place provides moderately priced services.", + value: "PRICE_LEVEL_MODERATE", + }, + { + label: "Place provides expensive services.", + value: "PRICE_LEVEL_EXPENSIVE", + }, + { + label: "Place provides very expensive services.", + value: "PRICE_LEVEL_VERY_EXPENSIVE", + }, +]; + +export const RANK_PREFERENCE_OPTIONS = [ + { + label: "Rank results by search relevance.", + value: "RELEVANCE", + }, + { + label: "Rank results by distance.", + value: "DISTANCE", + }, +]; diff --git a/components/google_maps_platform/common/utils.mjs b/components/google_maps_platform/common/utils.mjs new file mode 100644 index 0000000000000..dcc9cc61f6f41 --- /dev/null +++ b/components/google_maps_platform/common/utils.mjs @@ -0,0 +1,24 @@ +export const parseObject = (obj) => { + if (!obj) return undefined; + + if (Array.isArray(obj)) { + return obj.map((item) => { + if (typeof item === "string") { + try { + return JSON.parse(item); + } catch (e) { + return item; + } + } + return item; + }); + } + if (typeof obj === "string") { + try { + return JSON.parse(obj); + } catch (e) { + return obj; + } + } + return obj; +}; diff --git a/components/google_maps_platform/google_maps_platform.app.mjs b/components/google_maps_platform/google_maps_platform.app.mjs new file mode 100644 index 0000000000000..d6137f34f33da --- /dev/null +++ b/components/google_maps_platform/google_maps_platform.app.mjs @@ -0,0 +1,42 @@ +import { axios } from "@pipedream/platform"; + +export default { + type: "app", + app: "google_maps_platform", + methods: { + _baseUrl() { + return "https://places.googleapis.com/v1/places"; + }, + _headers() { + return { + "X-Goog-Api-Key": this.$auth.api_key, + "Content-Type": "application/json", + "X-Goog-FieldMask": "*", + }; + }, + _makeRequest({ + $ = this, path, ...opts + }) { + return axios($, { + url: this._baseUrl() + path, + headers: this._headers(), + ...opts, + }); + }, + searchPlaces(opts = {}) { + return this._makeRequest({ + method: "POST", + path: ":searchText", + ...opts, + }); + }, + getPlaceDetails({ + placeId, ...opts + }) { + return this._makeRequest({ + path: `/${placeId}`, + ...opts, + }); + }, + }, +}; diff --git a/components/google_maps_platform/package.json b/components/google_maps_platform/package.json index 70a98483e4ed1..98de8f15249da 100644 --- a/components/google_maps_platform/package.json +++ b/components/google_maps_platform/package.json @@ -1,16 +1,18 @@ { "name": "@pipedream/google_maps_platform", - "version": "0.0.2", + "version": "0.1.0", "description": "Pipedream Google Maps Platform (Places API) Components", - "main": "dist/app/google_maps_platform.app.mjs", + "main": "google_maps_platform.app.mjs", "keywords": [ "pipedream", "google_maps_platform" ], - "files": ["dist"], "homepage": "https://pipedream.com/apps/google_maps_platform", "author": "Pipedream (https://pipedream.com/)", "publishConfig": { "access": "public" + }, + "dependencies": { + "@pipedream/platform": "^3.0.3" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 74e2588af2eb8..83543b8cae429 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -4453,7 +4453,11 @@ importers: specifier: ^3.0.3 version: 3.0.3 - components/google_maps_platform: {} + components/google_maps_platform: + dependencies: + '@pipedream/platform': + specifier: ^3.0.3 + version: 3.0.3 components/google_meet: dependencies: @@ -32201,6 +32205,8 @@ snapshots: '@putout/operator-filesystem': 5.0.0(putout@36.13.1(eslint@8.57.1)(typescript@5.6.3)) '@putout/operator-json': 2.2.0 putout: 36.13.1(eslint@8.57.1)(typescript@5.6.3) + transitivePeerDependencies: + - supports-color '@putout/operator-regexp@1.0.0(putout@36.13.1(eslint@8.57.1)(typescript@5.6.3))': dependencies: