diff --git a/components/mapbox/.gitignore b/components/mapbox/.gitignore deleted file mode 100644 index ec761ccab7595..0000000000000 --- a/components/mapbox/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -*.js -*.mjs -dist \ No newline at end of file diff --git a/components/mapbox/actions/create-tileset/create-tileset.mjs b/components/mapbox/actions/create-tileset/create-tileset.mjs new file mode 100644 index 0000000000000..2cc4423f4172f --- /dev/null +++ b/components/mapbox/actions/create-tileset/create-tileset.mjs @@ -0,0 +1,99 @@ +import mapbox from "../../mapbox.app.mjs"; +import fs from "fs"; +import FormData from "form-data"; + +export default { + key: "mapbox-create-tileset", + name: "Create Tileset", + description: "Uploads and creates a new tileset from a data source. [See the documentation](https://docs.mapbox.com/api/maps/mapbox-tiling-service/)", + version: "0.0.1", + type: "action", + props: { + mapbox, + username: { + type: "string", + label: "Username", + description: "The Mapbox username of the account for which to create a tileset source", + }, + tilesetName: { + type: "string", + label: "Tileset Name", + description: "A unique name for the tileset source to be created. Limited to 32 characters. The only allowed special characters are `-` (hyphen) and `_` (underscore)", + }, + filePath: { + type: "string", + label: "File Path", + description: "The path to a tileset source file in the `/tmp` directory. [See the documentation on working with files](https://pipedream.com/docs/code/nodejs/working-with-files/#writing-a-file-to-tmp)", + }, + recipe: { + type: "object", + label: "Recipe", + description: "A recipe that describes how the GeoJSON data you uploaded should be transformed into tiles. A tileset source is raw geographic data formatted as [line-delimited GeoJSON](https://en.wikipedia.org/wiki/JSON_streaming#Line-delimited_JSON), or a supported [raster file format](https://docs.mapbox.com/mapbox-tiling-service/raster/supported-file-formats/). For more information on how to create and format recipes, see the [Recipe reference](https://docs.mapbox.com/mapbox-tiling-service/reference/) and [Recipe examples](https://docs.mapbox.com/mapbox-tiling-service/examples/).", + }, + description: { + type: "string", + label: "Description", + description: "A description of the tileset", + optional: true, + }, + private: { + type: "boolean", + label: "Private", + description: "Describes whether the tileset must be used with an access token from your Mapbox account. Default is `true`.", + optional: true, + }, + }, + async run({ $ }) { + const filePath = this.filePath.includes("tmp/") + ? this.filePath + : `/tmp/${this.filePath}`; + + // Create Tileset Source + try { + const fileData = new FormData(); + const content = fs.createReadStream(filePath); + fileData.append("file", content); + + await this.mapbox.createTilesetSource({ + $, + username: this.username, + id: this.tilesetName, + data: fileData, + headers: fileData.getHeaders(), + }); + } catch (e) { + throw new Error(`Error uploading file: \`${filePath}\`. Error: ${e}`); + } + + const recipe = typeof this.recipe === "string" + ? JSON.parse(this.recipe) + : this.recipe; + + // Validate Recipe + const { + valid, errors, + } = await this.mapbox.validateRecipe({ + $, + data: recipe, + }); + + if (!valid) { + throw new Error(`Error validating recipe: ${errors}`); + } + + // Create Tileset + const response = await this.mapbox.createTileset({ + $, + tilesetId: `${this.username}.${this.tilesetName}`, + data: { + recipe, + name: this.tilesetName, + description: this.description, + private: this.private, + }, + }); + + $.export("$summary", `Created tileset ${this.tilesetName}`); + return response; + }, +}; diff --git a/components/mapbox/actions/generate-directions/generate-directions.mjs b/components/mapbox/actions/generate-directions/generate-directions.mjs new file mode 100644 index 0000000000000..c332eed59a202 --- /dev/null +++ b/components/mapbox/actions/generate-directions/generate-directions.mjs @@ -0,0 +1,60 @@ +import mapbox from "../../mapbox.app.mjs"; + +export default { + key: "mapbox-generate-directions", + name: "Generate Directions", + description: "Generates directions between two or more locations using Mapbox API. [See the documentation](https://docs.mapbox.com/api/navigation/directions/).", + version: "0.0.1", + type: "action", + props: { + mapbox, + startCoordinate: { + type: "string", + label: "Start Coordinate", + description: "The starting point in the format `longitude,latitude`, E.g. `-85.244869,37.835819`", + }, + endCoordinate: { + type: "string", + label: "End Coordinate", + description: "The ending point in the format `longitude,latitude`, E.g. `-85.244869,37.835819`", + }, + transportationMode: { + propDefinition: [ + mapbox, + "transportationMode", + ], + }, + steps: { + type: "boolean", + label: "Steps", + description: "Whether to return steps and turn-by-turn instructions (`true`) or not (`false`, default)", + optional: true, + }, + alternatives: { + type: "boolean", + label: "Alternatives", + description: "Whether to try to return alternative routes (`true`) or not (`false`, default). An alternative route is a route that is significantly different from the fastest route, but still close in time.", + optional: true, + }, + exclude: { + propDefinition: [ + mapbox, + "exclude", + ], + }, + }, + async run({ $ }) { + const directions = await this.mapbox.getDirections({ + $, + transportationMode: this.transportationMode, + coordinates: `${this.startCoordinate};${this.endCoordinate}`, + params: { + steps: this.steps, + alternatives: this.alternatives, + exclude: this.exclude && this.exclude.join(","), + }, + }); + $.export("$summary", "Generated directions successfully."); + return directions; + }, +}; diff --git a/components/mapbox/actions/geocode-address/geocode-address.mjs b/components/mapbox/actions/geocode-address/geocode-address.mjs new file mode 100644 index 0000000000000..8fb8d9c07765e --- /dev/null +++ b/components/mapbox/actions/geocode-address/geocode-address.mjs @@ -0,0 +1,41 @@ +import mapbox from "../../mapbox.app.mjs"; + +export default { + key: "mapbox-geocode-address", + name: "Geocode Address", + description: "Retrieves the geocoded location for a given address. [See the documentation](https://docs.mapbox.com/api/search/geocoding/)", + version: "0.0.1", + type: "action", + props: { + mapbox, + address: { + type: "string", + label: "Address", + description: "The address (or partial address) to geocode. This could be an address, a city name, etc. Must consist of at most 20 words and numbers separated by spacing and punctuation, and at most 256 characters.", + }, + boundingBox: { + type: "string", + label: "Bounding Box", + description: "Limit results to only those contained within the supplied bounding box. Bounding boxes should be supplied as four numbers separated by commas, in `minLon,minLat,maxLon,maxLat` order. The bounding box cannot cross the 180th meridian. You can use the [Location Helper](https://labs.mapbox.com/location-helper) to find a bounding box for use with this API.", + optional: true, + }, + proximity: { + type: "string", + label: "Proximity", + description: "Bias the response to favor results that are closer to this location. Provided as two comma-separated coordinates in `longitude,latitude` order.", + optional: true, + }, + }, + async run({ $ }) { + const response = await this.mapbox.geocode({ + $, + params: { + q: this.address, + bBox: this.boundingBox, + proximity: this.proximity, + }, + }); + $.export("$summary", `Geocoded location for "${this.address}" retrieved successfully`); + return response; + }, +}; diff --git a/components/mapbox/app/mapbox.app.ts b/components/mapbox/app/mapbox.app.ts deleted file mode 100644 index a778df2269db4..0000000000000 --- a/components/mapbox/app/mapbox.app.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { defineApp } from "@pipedream/types"; - -export default defineApp({ - type: "app", - app: "mapbox", - propDefinitions: {}, - methods: { - // this.$auth contains connected account data - authKeys() { - console.log(Object.keys(this.$auth)); - }, - }, -}); diff --git a/components/mapbox/common/constants.mjs b/components/mapbox/common/constants.mjs new file mode 100644 index 0000000000000..a1101632447cd --- /dev/null +++ b/components/mapbox/common/constants.mjs @@ -0,0 +1,21 @@ +const TRANSPORTATION_MODES = [ + "driving", + "walking", + "cycling", + "driving-traffic", +]; + +const EXCLUDE_OPTIONS = [ + "motorway", + "toll", + "ferry", + "unpaved", + "cash_only_tolls", + "country_border", + "state_border", +]; + +export default { + TRANSPORTATION_MODES, + EXCLUDE_OPTIONS, +}; diff --git a/components/mapbox/mapbox.app.mjs b/components/mapbox/mapbox.app.mjs new file mode 100644 index 0000000000000..e11265eed2e3f --- /dev/null +++ b/components/mapbox/mapbox.app.mjs @@ -0,0 +1,81 @@ +import { axios } from "@pipedream/platform"; +import constants from "./common/constants.mjs"; + +export default { + type: "app", + app: "mapbox", + propDefinitions: { + transportationMode: { + type: "string", + label: "Transportation Mode", + description: "The mode of transportation", + options: constants.TRANSPORTATION_MODES, + }, + exclude: { + type: "string[]", + label: "Exclude", + description: "Exclude certain road types and custom locations from routing", + options: constants.EXCLUDE_OPTIONS, + optional: true, + }, + }, + methods: { + _baseUrl() { + return "https://api.mapbox.com"; + }, + _makeRequest({ + $ = this, + path, + params, + ...otherOpts + }) { + return axios($, { + url: `${this._baseUrl()}${path}`, + params: { + access_token: this.$auth.access_token, + ...params, + }, + ...otherOpts, + }); + }, + geocode(opts = {}) { + return this._makeRequest({ + path: "/search/geocode/v6/forward", + ...opts, + }); + }, + getDirections({ + transportationMode, coordinates, ...opts + }) { + return this._makeRequest({ + path: `/directions/v5/mapbox/${transportationMode}/${coordinates}`, + ...opts, + }); + }, + createTilesetSource({ + username, id, ...opts + }) { + return this._makeRequest({ + method: "POST", + path: `/tilesets/v1/sources/${username}/${id}`, + ...opts, + }); + }, + validateRecipe(opts = {}) { + return this._makeRequest({ + method: "PUT", + path: "/tilesets/v1/validateRecipe", + ...opts, + }); + }, + createTileset({ + tilesetId, ...opts + }) { + return this._makeRequest({ + method: "POST", + path: `/tilesets/v1/${tilesetId}`, + ...opts, + }); + }, + }, +}; diff --git a/components/mapbox/package.json b/components/mapbox/package.json index 6adaa9ef9e5f5..680b99cc3f4cb 100644 --- a/components/mapbox/package.json +++ b/components/mapbox/package.json @@ -1,18 +1,19 @@ { "name": "@pipedream/mapbox", - "version": "0.0.3", + "version": "0.1.0", "description": "Pipedream Mapbox Components", - "main": "dist/app/mapbox.app.mjs", + "main": "mapbox.app.mjs", "keywords": [ "pipedream", "mapbox" ], - "files": [ - "dist" - ], "homepage": "https://pipedream.com/apps/mapbox", "author": "Pipedream (https://pipedream.com/)", "publishConfig": { "access": "public" + }, + "dependencies": { + "@pipedream/platform": "^3.0.3", + "form-data": "^4.0.1" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 20bb7dd5b0d53..f9e425321f58f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -3258,8 +3258,7 @@ importers: specifier: ^0.12.7 version: 0.12.7 - components/elastic_cloud: - specifiers: {} + components/elastic_cloud: {} components/elastic_email: {} @@ -4209,8 +4208,7 @@ importers: components/glide: {} - components/globalping: - specifiers: {} + components/globalping: {} components/gloria_ai: dependencies: @@ -6339,8 +6337,7 @@ importers: specifier: ^3.0.0 version: 3.0.3 - components/mailtrap: - specifiers: {} + components/mailtrap: {} components/mailwizz: dependencies: @@ -6376,7 +6373,14 @@ importers: specifier: ^1.5.1 version: 1.6.6 - components/mapbox: {} + components/mapbox: + dependencies: + '@pipedream/platform': + specifier: ^3.0.3 + version: 3.0.3 + form-data: + specifier: ^4.0.1 + version: 4.0.1 components/mapulus: dependencies: @@ -9902,8 +9906,7 @@ importers: components/simplybook_me: {} - components/sinch_messagemedia: - specifiers: {} + components/sinch_messagemedia: {} components/sitecreator_io: dependencies: