From 22cea145f8e5bfc967286dc4a5dd428fe6f796c4 Mon Sep 17 00:00:00 2001 From: Faruk AYDIN Date: Mon, 7 Nov 2022 19:17:25 +0100 Subject: [PATCH 01/24] docs: Add global variable page --- packages/docs/pages/.vitepress/config.js | 4 ++ .../build-integrations/global-variable.md | 39 +++++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 packages/docs/pages/build-integrations/global-variable.md diff --git a/packages/docs/pages/.vitepress/config.js b/packages/docs/pages/.vitepress/config.js index 92ec8bf0..b549dc45 100644 --- a/packages/docs/pages/.vitepress/config.js +++ b/packages/docs/pages/.vitepress/config.js @@ -189,6 +189,10 @@ export default defineConfig({ text: 'App', link: '/build-integrations/app', }, + { + text: 'Global variable', + link: '/build-integrations/global-variable', + }, ], }, { diff --git a/packages/docs/pages/build-integrations/global-variable.md b/packages/docs/pages/build-integrations/global-variable.md new file mode 100644 index 00000000..a3bff21c --- /dev/null +++ b/packages/docs/pages/build-integrations/global-variable.md @@ -0,0 +1,39 @@ +# Global Variable + +Before handling authentication and building a trigger and an action, it's better to explain the `global variable` concept in Automatisch. Automatisch provides you the global variable that you need to use with authentication, triggers, action, and basically all the stuff you will build for the integration. + +The global variable is represented as `$` variable in the codebase, and it's a JSON object that contains the following properties: + +## $.auth.set + +```typescript +$.auth.set({ + key: 'value', +}); +``` + +It's used to set the authentication data, and you can use this method with multiple pairs. The data will be stored in the database and can be retrieved later by using `$.auth.data` property. We use this method when we store the credentials of the third-party service. Note that Automatisch encrypts the data before storing it in the database. + +## $.auth.data + +```typescript +$.auth.data; // { key: 'value' } +``` + +It's used to retrieve the authentication data that we set with `$.auth.set()`. The data will be retrieved from the database. We use the data property with the key name when we need to get one specific value from the data object. + +## $.app.baseUrl + +```typescript +$.app.baseUrl; // https://thecatapi.com +``` + +It's used to retrieve the base URL of the app that we defined previously. In our example, it returns `https://thecatapi.com`. We use this property when we need to use the base URL of the third-party service. + +## $.app.apiBaseUrl + +```typescript +$.app.apiBaseUrl; // https://api.thecatapi.com +``` + +It's used to retrieve the API base URL of the app that we defined previously. In our example, it returns `https://api.thecatapi.com`. We use this property when we need to use the API base URL of the third-party service. From 3140fb243507a598142b33b4b68968be6f803149 Mon Sep 17 00:00:00 2001 From: Faruk AYDIN Date: Mon, 7 Nov 2022 19:23:13 +0100 Subject: [PATCH 02/24] docs: Add auth page to build integration guide --- packages/docs/pages/.vitepress/config.js | 4 + .../docs/pages/build-integrations/auth.md | 173 ++++++++++++++++++ 2 files changed, 177 insertions(+) create mode 100644 packages/docs/pages/build-integrations/auth.md diff --git a/packages/docs/pages/.vitepress/config.js b/packages/docs/pages/.vitepress/config.js index b549dc45..ece9bc43 100644 --- a/packages/docs/pages/.vitepress/config.js +++ b/packages/docs/pages/.vitepress/config.js @@ -193,6 +193,10 @@ export default defineConfig({ text: 'Global variable', link: '/build-integrations/global-variable', }, + { + text: 'Auth', + link: '/build-integrations/auth', + }, ], }, { diff --git a/packages/docs/pages/build-integrations/auth.md b/packages/docs/pages/build-integrations/auth.md new file mode 100644 index 00000000..8d319fbb --- /dev/null +++ b/packages/docs/pages/build-integrations/auth.md @@ -0,0 +1,173 @@ +# Auth + +## Sign up for the cat API + +Go to the [sign up page](https://thecatapi.com/signup) of the cat API and register your account. It allows you to have 10k requests per month with a free account. You will get an API key by email after the registration. We will use this API key for authentication later on. + +## The cat API docs + +You can find detailed documentation of the cat API [here](https://docs.thecatapi.com). You need to revisit this page while building the integration. + +## Add auth to the app + +Open the `thecatapi/index.ts` file and add the highlighted lines for authentication. + +```typescript{2,13} +import defineApp from '../../helpers/define-app'; +import auth from './auth'; + +export default defineApp({ + name: 'The cat API', + key: 'thecatapi', + iconUrl: '{BASE_URL}/apps/thecatapi/assets/favicon.svg', + authDocUrl: 'https://automatisch.io/docs/apps/thecatapi/connection', + supportsConnections: true, + baseUrl: 'https://thecatapi.com', + apiBaseUrl: 'https://api.thecatapi.com', + primaryColor: '000000', + auth, +}); +``` + +## Define auth fields + +Let's create the `auth/index.ts` file inside of the `thecatapi` folder. + +```bash +touch auth/index.ts +``` + +Then let's start with defining fields the auth inside of the `auth/index.ts` file as follows: + +```typescript +export default { + fields: [ + { + key: 'screenName', + label: 'Screen Name', + type: 'string' as const, + required: true, + readOnly: false, + value: null, + placeholder: null, + description: + 'Screen name of your connection to be used on Automatisch UI.', + clickToCopy: false, + }, + { + key: 'apiKey', + label: 'API Key', + type: 'string' as const, + required: true, + readOnly: false, + value: null, + placeholder: null, + description: 'API key of the cat API service.', + clickToCopy: false, + }, + ], +}; +``` + +We have defined two fields for the auth. + +- The `apiKey` field will be used to authenticate the requests to the cat API. +- The `screenName` field will be used to identify the connection on the Automatisch UI. + +:::warning +You have to add a screen name field in case there is no API endpoint where you can get the username or any other information about the user that you can use as a screen name. Some of the APIs have an endpoint for this purpose like `/me` or `/users/me`, but in our example, the cat API doesn't have such an endpoint. +::: + +## Verify credentials + +So until now, we integrated auth folder with the app definition and defined the auth fields. Now we need to verify the credentials that the user entered. We will do that by defining the `verifyCredentials` method. + +Start with adding the `verifyCredentials` method to the `auth/index.ts` file. + +```typescript{1,8} +import verifyCredentials from './verify-credentials'; + +export default { + fields: [ + // ... + ], + + verifyCredentials, +}; +``` + +Let's create the `verify-credentials.ts` file inside the `auth` folder. + +```typescript +import { IGlobalVariable } from '@automatisch/types'; + +const verifyCredentials = async ($: IGlobalVariable) => { + // TODO: Implement verification of the credentials +}; + +export default verifyCredentials; +``` + +We have generally use `users/me` endpoint or any other endpoint that we can validate the API key or any other credentials that user provides us. For our example, we don't have a specific API endpoint to check whether the credentials are correct or not. So we will randomly pick one of the API endpoints, which will be the `GET /v1/images/search` endpoint. We will send a request to this endpoint with the API key. If the API key is correct, we will get a response from the API. If the API key is incorrect, we will get an error response from the API. + +Let's implement the authentication logic that we mentioned in the `verify-credentials.ts` file. + +```typescript +import { IGlobalVariable } from '@automatisch/types'; + +const verifyCredentials = async ($: IGlobalVariable) => { + await $.http.get('/v1/images/search'); + + await $.auth.set({ + screenName: $.auth.data.screenName, + }); +}; + +export default verifyCredentials; +``` + +Here we send a request to `/v1/images/search` endpoint with the API key. If we get a response from the API, we will set the screen name to the auth data. If we get an error response from the API, it will throw an error. + +## Is still verified? + +We have implemented the `verifyCredentials` method. Now we need to check whether the credentials are still valid or not for the test connection functionality in Automatisch. We will do that by defining the `isStillVerified` method. + +Start with adding the `isStillVerified` method to the `auth/index.ts` file. + +```typescript{2,10} +import verifyCredentials from './verify-credentials'; +import isStillVerified from './is-still-verified'; + +export default { + fields: [ + // ... + ], + + verifyCredentials, + isStillVerified, +}; +``` + +Let's create the `is-still-verified.ts` file inside the `auth` folder. + +```typescript +import { IGlobalVariable } from '@automatisch/types'; +import verifyCredentials from './verify-credentials'; + +const isStillVerified = async ($: IGlobalVariable) => { + await verifyCredentials($); + return true; +}; + +export default isStillVerified; +``` + +:::info +`isStillVerified` method needs to return `truthy` value if the credentials are still valid. +::: + +We will use the `verifyCredentials` method to check whether the credentials are still valid or not. If the credentials are still valid, we will return `true`. Otherwise it will thrown an error which will automatically handled by Automatisch. + +:::warning +You might be wondering why we need to have two separate functions even though we use only one of them behind the scenes in this scenario. That might be true in our example or any other APIs similar to the cat API but there are some other third-party APIs which we can't use the same functionality directly to check whether the credentials are still valid or not. So we need to have two separate functions for verifying the credentials and checking whether the credentials are still valid or not. +::: From 49fac8f14706638588a7973a821cf211a9b44831 Mon Sep 17 00:00:00 2001 From: Faruk AYDIN Date: Mon, 7 Nov 2022 19:34:16 +0100 Subject: [PATCH 03/24] docs: Add how to test authentication part to auth --- packages/docs/pages/build-integrations/auth.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/docs/pages/build-integrations/auth.md b/packages/docs/pages/build-integrations/auth.md index 8d319fbb..1c5ec9b9 100644 --- a/packages/docs/pages/build-integrations/auth.md +++ b/packages/docs/pages/build-integrations/auth.md @@ -171,3 +171,7 @@ We will use the `verifyCredentials` method to check whether the credentials are :::warning You might be wondering why we need to have two separate functions even though we use only one of them behind the scenes in this scenario. That might be true in our example or any other APIs similar to the cat API but there are some other third-party APIs which we can't use the same functionality directly to check whether the credentials are still valid or not. So we need to have two separate functions for verifying the credentials and checking whether the credentials are still valid or not. ::: + +Now we have completed the authentication of the cat API. Go to `My Apps` page in Automatisch, try to add a new connection, select `The Cat API` and use your API key you got with an email. Then you can also check the test connection and reconnect functionality there. + +Let's move on to the next page to build a trigger. From 3a129557e0991a42d7b7a78853cd7c3bff740e4a Mon Sep 17 00:00:00 2001 From: Faruk AYDIN Date: Mon, 7 Nov 2022 19:51:23 +0100 Subject: [PATCH 04/24] docs: Add triggers page to build integrations guide --- packages/docs/pages/.vitepress/config.js | 4 + .../docs/pages/build-integrations/triggers.md | 131 ++++++++++++++++++ 2 files changed, 135 insertions(+) create mode 100644 packages/docs/pages/build-integrations/triggers.md diff --git a/packages/docs/pages/.vitepress/config.js b/packages/docs/pages/.vitepress/config.js index ece9bc43..a73d5c63 100644 --- a/packages/docs/pages/.vitepress/config.js +++ b/packages/docs/pages/.vitepress/config.js @@ -197,6 +197,10 @@ export default defineConfig({ text: 'Auth', link: '/build-integrations/auth', }, + { + text: 'Triggers', + link: '/build-integrations/triggers', + }, ], }, { diff --git a/packages/docs/pages/build-integrations/triggers.md b/packages/docs/pages/build-integrations/triggers.md new file mode 100644 index 00000000..061a228c --- /dev/null +++ b/packages/docs/pages/build-integrations/triggers.md @@ -0,0 +1,131 @@ +# Triggers + +## Add triggers to the app + +Open the `thecatapi/index.ts` file and add the highlighted lines for triggers. + +```typescript{3,15} +import defineApp from '../../helpers/define-app'; +import auth from './auth'; +import triggers from './triggers'; + +export default defineApp({ + name: 'The cat API', + key: 'thecatapi', + iconUrl: '{BASE_URL}/apps/thecatapi/assets/favicon.svg', + authDocUrl: 'https://automatisch.io/docs/apps/thecatapi/connection', + supportsConnections: true, + baseUrl: 'https://thecatapi.com', + apiBaseUrl: 'https://api.thecatapi.com', + primaryColor: '000000', + auth, + triggers +}); +``` + +## Define triggers + +Let's create the `triggers/index.ts` file inside of the `thecatapi` folder. + +```typescript +import searchCatImages from './search-cat-images'; + +export default [searchCatImages]; +``` + +:::tip +If you add new triggers, you need to add them to the `triggers/index.ts` file and export all triggers as an array. +::: + +## Add metadata + +Let's create the `triggers/search-cat-images.ts` file inside of the `thecatapi` folder. + +```typescript +import defineTrigger from '../../../../helpers/define-trigger'; + +export default defineTrigger({ + name: 'Search cat images', + key: 'searchCatImages', + pollInterval: 15, + description: 'Triggers when there is a new cat image.', + + async run($) { + // TODO: Implement trigger! + }, +}); +``` + +Let's briefly explain what we defined here. + +- `name`: The name of the trigger. +- `key`: The key of the trigger. This is used to identify the trigger in Automatisch. +- `pollInterval`: The interval in minutes in which the trigger should be polled. Even though we allow to define `pollInterval` field, it's not used in Automatisch at the moment. Currently, the default is 15 minutes and it's not possible to change it. +- `description`: The description of the trigger. +- `run`: The function that is executed when the trigger is triggered. + +## Implement trigger + +:::danger + +- Automatisch expects you to push data in **reverse-chronological order** otherwise, the trigger will not work properly. +- You have to push the `unique identifier` (it can be IDs or any field that can be used to identify the data) as `internalId`. This is used to prevent duplicate data. + +::: + +Let's implement the `run` function. + +```typescript{10-34} +import defineTrigger from '../../../../helpers/define-trigger'; + +export default defineTrigger({ + // ... + async run($) { + let page = 0; + let response; + + const headers = { + 'x-api-key': $.auth.data.apiKey, + }; + + do { + let requestPath = `/v1/images/search?page=${page}&limit=10&order=DESC`; + response = await $.http.get(requestPath, { headers }); + + response.data.forEach((image: IJSONObject) => { + const dataItem = { + raw: image, + meta: { + internalId: image.id, + }, + }; + + $.pushTriggerItem(dataItem); + }); + + page += 1; + } while (response.data.length >= 10); + }, +}); +``` + +Let's briefly explain what we did here. We are using the `$.http` object to make HTTP requests. Our API is paginated, so we are making requests until we get less than 10 items, which means the last page. + +We do not have to return anything from the `run` function. We are using the `$.pushTriggerItem` function to push the data to Automatisch. $.pushTriggerItem accepts an object with the following fields: + +- `raw`: The raw data that you want to push to Automatisch. +- `meta`: The metadata of the data. It has to have the `internalId` field. + +:::tip + +- `$.pushTriggerItem` is smart enough to understand if the data is already pushed to Automatisch or not. If the data is already pushed, it will stop the trigger, otherwise, it will continue to fetch new data. + +- `$.pushTriggerItem` also understands whether the trigger is executed with `Test & Continue` button in the user interface or it's a trigger from a published flow. If the trigger is executed with `Test & Continue` button, it will push only one item regardless of whether we already processed the data or not and early exits the process, otherwise, it will fetch the remaining data. + +- Let's say the trigger started to execute. It fetched the first five pages of data from the third-party API with five different HTTP requests and you still need to get the next page but you started to get an API rate limit error. In this case, Automatisch will not lose the data that is already fetched from the first five requests. It stops the trigger when it got the error the first time but processes all previously fetched data. + +::: + +### Test the trigger + +Let's go to the flows page of Automatisch and create a new flow. Choose the `The cat API` app and the `Search cat images` trigger and click `Test & Continue` button. If you a see JSON response in the user interface, it means that the trigger is working properly. From d5726235521f4fd6fa8829d4d678f8871f042820 Mon Sep 17 00:00:00 2001 From: Faruk AYDIN Date: Mon, 7 Nov 2022 20:18:11 +0100 Subject: [PATCH 05/24] docs: Add examples page for build integrations --- packages/docs/pages/.vitepress/config.js | 4 ++ .../docs/pages/build-integrations/examples.md | 47 +++++++++++++++++++ 2 files changed, 51 insertions(+) create mode 100644 packages/docs/pages/build-integrations/examples.md diff --git a/packages/docs/pages/.vitepress/config.js b/packages/docs/pages/.vitepress/config.js index a73d5c63..17d0ebff 100644 --- a/packages/docs/pages/.vitepress/config.js +++ b/packages/docs/pages/.vitepress/config.js @@ -201,6 +201,10 @@ export default defineConfig({ text: 'Triggers', link: '/build-integrations/triggers', }, + { + text: 'Examples', + link: '/build-integrations/examples', + }, ], }, { diff --git a/packages/docs/pages/build-integrations/examples.md b/packages/docs/pages/build-integrations/examples.md new file mode 100644 index 00000000..af0ca661 --- /dev/null +++ b/packages/docs/pages/build-integrations/examples.md @@ -0,0 +1,47 @@ +# Examples + +## Authentication + +### 3-legged OAuth + +- [Discord](https://github.com/automatisch/automatisch/tree/main/packages/backend/src/apps/discord/auth/index.ts) +- [Flickr](https://github.com/automatisch/automatisch/tree/main/packages/backend/src/apps/flickr/auth/index.ts) +- [Github](https://github.com/automatisch/automatisch/tree/main/packages/backend/src/apps/github/auth/index.ts) +- [Salesforce](https://github.com/automatisch/automatisch/tree/main/packages/backend/src/apps/salesforce/auth/index.ts) +- [Slack](https://github.com/automatisch/automatisch/tree/main/packages/backend/src/apps/slack/auth/index.ts) +- [Twitter](https://github.com/automatisch/automatisch/tree/main/packages/backend/src/apps/twitter/auth/index.ts) + +### API key + +- [DeepL](https://github.com/automatisch/automatisch/tree/main/packages/backend/src/apps/deepl/auth/index.ts) +- [Twilio](https://github.com/automatisch/automatisch/tree/main/packages/backend/src/apps/twilio/auth/index.ts) +- [SMTP](https://github.com/automatisch/automatisch/tree/main/packages/backend/src/apps/smtp/auth/index.ts) + +### Without authentication + +- [RSS](https://github.com/automatisch/automatisch/tree/main/packages/backend/src/apps/rss/index.ts) +- [Scheduler](https://github.com/automatisch/automatisch/tree/main/packages/backend/src/apps/scheduler/index.ts) + +## Triggers + +### Pagination with descending order + +- [Search tweets - Twitter](https://github.com/automatisch/automatisch/tree/main/packages/backend/src/apps/twitter/triggers/search-tweets/index.ts) +- [New issues - Github](https://github.com/automatisch/automatisch/tree/main/packages/backend/src/apps/github/triggers/new-issues/index.ts) +- [Receive SMS - Twilio](https://github.com/automatisch/automatisch/tree/main/packages/backend/src/apps/twilio/triggers/receive-sms/index.ts) +- [New photos - Flickr](https://github.com/automatisch/automatisch/tree/main/packages/backend/src/apps/flickr/triggers/new-photos/index.ts) + +### Pagination with ascending order + +- [New stargazers - Github](https://github.com/automatisch/automatisch/tree/main/packages/backend/src/apps/github/triggers/new-stargazers/index.ts) +- [New watchers - Github](https://github.com/automatisch/automatisch/tree/main/packages/backend/src/apps/github/triggers/new-watchers/index.ts) + +## Actions + +- [Send a message to channel - Slack](https://github.com/automatisch/automatisch/tree/main/packages/backend/src/apps/slack/actions/send-a-message-to-channel/index.ts) +- [Send SMS - Twilio](https://github.com/automatisch/automatisch/tree/main/packages/backend/src/apps/twilio/actions/send-sms/index.ts) +- [Send a message to channel - Discord](https://github.com/automatisch/automatisch/tree/main/packages/backend/src/apps/discord/actions/send-message-to-channel/index.ts) +- [Create issue - Github](https://github.com/automatisch/automatisch/tree/main/packages/backend/src/apps/github/actions/create-issue/index.ts) +- [Send an email - SMTP](https://github.com/automatisch/automatisch/tree/main/packages/backend/src/apps/smtp/actions/send-email/index.ts) +- [Create tweet - Twitter](https://github.com/automatisch/automatisch/tree/main/packages/backend/src/apps/twitter/actions/create-tweet/index.ts) +- [Translate text - DeepL](https://github.com/automatisch/automatisch/tree/main/packages/backend/src/apps/deepl/actions/translate-text/index.ts) From f432e72253dac2849d23f90326e952f648bb01f6 Mon Sep 17 00:00:00 2001 From: Faruk AYDIN Date: Mon, 7 Nov 2022 21:38:22 +0100 Subject: [PATCH 06/24] docs: Add actions page to build integration section --- packages/docs/pages/.vitepress/config.js | 4 + .../docs/pages/build-integrations/actions.md | 106 ++++++++++++++++++ 2 files changed, 110 insertions(+) create mode 100644 packages/docs/pages/build-integrations/actions.md diff --git a/packages/docs/pages/.vitepress/config.js b/packages/docs/pages/.vitepress/config.js index 17d0ebff..3b44fdd5 100644 --- a/packages/docs/pages/.vitepress/config.js +++ b/packages/docs/pages/.vitepress/config.js @@ -201,6 +201,10 @@ export default defineConfig({ text: 'Triggers', link: '/build-integrations/triggers', }, + { + text: 'Actions', + link: '/build-integrations/actions', + }, { text: 'Examples', link: '/build-integrations/examples', diff --git a/packages/docs/pages/build-integrations/actions.md b/packages/docs/pages/build-integrations/actions.md new file mode 100644 index 00000000..02ac6075 --- /dev/null +++ b/packages/docs/pages/build-integrations/actions.md @@ -0,0 +1,106 @@ +# Actions + +## Add actions to the app. + +Open the thecatapi/index.ts file and add the highlighted lines for actions. + +Open the `thecatapi/index.ts` file and add the highlighted lines for triggers. + +```typescript{4,17} +import defineApp from '../../helpers/define-app'; +import auth from './auth'; +import triggers from './triggers'; +import actions from './actions'; + +export default defineApp({ + name: 'The cat API', + key: 'thecatapi', + iconUrl: '{BASE_URL}/apps/thecatapi/assets/favicon.svg', + authDocUrl: 'https://automatisch.io/docs/apps/thecatapi/connection', + supportsConnections: true, + baseUrl: 'https://thecatapi.com', + apiBaseUrl: 'https://api.thecatapi.com', + primaryColor: '000000', + auth, + triggers + actions +}); +``` + +## Define actions + +Let's create the `actions/index.ts` file inside of the `thecatapi` folder. + +```typescript +import mark-cat-image-as-favorite from './mark-cat-image-as-favorite'; + +export default [markCatImageAsFavorite]; +``` + +:::tip +If you add new actions, you need to add them to the actions/index.ts file and export all actions as an array. +::: + +## Add metadata + +Let's create the `actions/mark-cat-image-as-favorite.ts` file inside of the `thecatapi` folder. + +```typescript +import defineAction from '../../../../helpers/define-action'; + +export default defineAction({ + name: 'Mark the cat image as favorite', + key: 'markCatImageAsFavorite', + description: 'Marks the cat image as favorite.', + arguments: [ + { + label: 'Image ID', + key: 'imageId', + type: 'string' as const, + required: true, + description: 'The ID of the cat image you want to mark as favorite.', + variables: true, + }, + ], + + async run($) { + // TODO: Implement action! + }, +}); +``` + +Let's briefly explain what we defined here. + +- `name`: The name of the action. +- `key`: The key of the action. This is used to identify the action in Automatisch. +- `description`: The description of the action. +- `arguments`: The arguments of the action. These are the values that the user provides when using the action. +- `run`: The function that is executed when the action is executed. + +## Implement the action + +Let's implement the action. Open the `actions/mark-cat-image-as-favorite.ts` file and add the highlighted lines. + +```typescript{7-15} +import defineAction from '../../../../helpers/define-action'; + +export default defineAction({ + // ... + + async run($) { + const requestPath = `/v1/favorites`; + const imageId = $.step.parameters.imageId; + + const response = await $.http.post( + requestPath, + { image_id: imageId } + ); + + $.setActionItem({ raw: response.data }); + }, +}); +``` + +## Test the action + +Let's go to the flows page of Automatisch and create a new flow. Add the `Search cat images` as a trigger in the flow. Add the `Mark the cat image as favorite` action to the flow as a second step. Add one of the image IDs you got from the cat API as `Image ID` argument to the action. Click `Test & Continue` button. If you a see JSON response in the user interface, it means that both the trigger and the action we built are working properly. From 47afd60ddf0e7e955aac4c2c52961b09514d6b41 Mon Sep 17 00:00:00 2001 From: Faruk AYDIN Date: Mon, 7 Nov 2022 22:43:25 +0100 Subject: [PATCH 07/24] docs: Add warning to say integration and app used interchangeably --- packages/docs/pages/build-integrations/folder-structure.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/docs/pages/build-integrations/folder-structure.md b/packages/docs/pages/build-integrations/folder-structure.md index 095e3a24..0a34da82 100644 --- a/packages/docs/pages/build-integrations/folder-structure.md +++ b/packages/docs/pages/build-integrations/folder-structure.md @@ -1,5 +1,9 @@ # Folder Structure +:::warning +We will use the terms **integration** and **app** interchangeably in this document. +::: + Before diving into how to build an integration for Automatisch, it's better to check the folder structure of the apps and give you some idea about how we place different parts of the app. ## Folder structure of an app From c579eebd1612222fca353a6f8d86515b90d067a0 Mon Sep 17 00:00:00 2001 From: Faruk AYDIN Date: Tue, 8 Nov 2022 20:12:25 +0100 Subject: [PATCH 08/24] docs: Add content table for build integration pages --- packages/docs/pages/build-integrations/actions.md | 14 ++++++++++++++ packages/docs/pages/build-integrations/app.md | 14 ++++++++++++++ packages/docs/pages/build-integrations/auth.md | 14 ++++++++++++++ packages/docs/pages/build-integrations/examples.md | 14 ++++++++++++++ .../pages/build-integrations/folder-structure.md | 14 ++++++++++++++ .../pages/build-integrations/global-variable.md | 14 ++++++++++++++ packages/docs/pages/build-integrations/triggers.md | 14 ++++++++++++++ 7 files changed, 98 insertions(+) diff --git a/packages/docs/pages/build-integrations/actions.md b/packages/docs/pages/build-integrations/actions.md index 02ac6075..2895ff63 100644 --- a/packages/docs/pages/build-integrations/actions.md +++ b/packages/docs/pages/build-integrations/actions.md @@ -1,5 +1,19 @@ # Actions +:::info + +The build integrations section is best understood when read from beginning to end. To get the most value out of it, start from the first page and read through page by page. + +1. [Folder structure](/build-integrations/folder-structure) +2. [App](/build-integrations/app) +3. [Global variable](/build-integrations/global-variable) +4. [Auth](/build-integrations/auth) +5. [Triggers](/build-integrations/triggers) +6. [Actions](/build-integrations/actions) +7. [Examples](/build-integrations/examples) + +::: + ## Add actions to the app. Open the thecatapi/index.ts file and add the highlighted lines for actions. diff --git a/packages/docs/pages/build-integrations/app.md b/packages/docs/pages/build-integrations/app.md index 777189f0..98643438 100644 --- a/packages/docs/pages/build-integrations/app.md +++ b/packages/docs/pages/build-integrations/app.md @@ -1,5 +1,19 @@ # App +:::info + +The build integrations section is best understood when read from beginning to end. To get the most value out of it, start from the first page and read through page by page. + +1. [Folder structure](/build-integrations/folder-structure) +2. [App](/build-integrations/app) +3. [Global variable](/build-integrations/global-variable) +4. [Auth](/build-integrations/auth) +5. [Triggers](/build-integrations/triggers) +6. [Actions](/build-integrations/actions) +7. [Examples](/build-integrations/examples) + +::: + Let's start building our first app by using [TheCatApi](https://thecatapi.com/) service. It's a service that provides cat images and allows you to vote or favorite a specific cat image. It's an excellent example to demonstrate how Automatisch works with an API that has authentication and data fetching with pagination. We will build an app with the `Search cat images` trigger and `Mark the cat image as favorite` action. So we will learn how to build both triggers and actions. diff --git a/packages/docs/pages/build-integrations/auth.md b/packages/docs/pages/build-integrations/auth.md index 1c5ec9b9..bce7b572 100644 --- a/packages/docs/pages/build-integrations/auth.md +++ b/packages/docs/pages/build-integrations/auth.md @@ -1,5 +1,19 @@ # Auth +:::info + +The build integrations section is best understood when read from beginning to end. To get the most value out of it, start from the first page and read through page by page. + +1. [Folder structure](/build-integrations/folder-structure) +2. [App](/build-integrations/app) +3. [Global variable](/build-integrations/global-variable) +4. [Auth](/build-integrations/auth) +5. [Triggers](/build-integrations/triggers) +6. [Actions](/build-integrations/actions) +7. [Examples](/build-integrations/examples) + +::: + ## Sign up for the cat API Go to the [sign up page](https://thecatapi.com/signup) of the cat API and register your account. It allows you to have 10k requests per month with a free account. You will get an API key by email after the registration. We will use this API key for authentication later on. diff --git a/packages/docs/pages/build-integrations/examples.md b/packages/docs/pages/build-integrations/examples.md index af0ca661..4b44d46a 100644 --- a/packages/docs/pages/build-integrations/examples.md +++ b/packages/docs/pages/build-integrations/examples.md @@ -1,5 +1,19 @@ # Examples +:::info + +The build integrations section is best understood when read from beginning to end. To get the most value out of it, start from the first page and read through page by page. + +1. [Folder structure](/build-integrations/folder-structure) +2. [App](/build-integrations/app) +3. [Global variable](/build-integrations/global-variable) +4. [Auth](/build-integrations/auth) +5. [Triggers](/build-integrations/triggers) +6. [Actions](/build-integrations/actions) +7. [Examples](/build-integrations/examples) + +::: + ## Authentication ### 3-legged OAuth diff --git a/packages/docs/pages/build-integrations/folder-structure.md b/packages/docs/pages/build-integrations/folder-structure.md index 0a34da82..5a84ac35 100644 --- a/packages/docs/pages/build-integrations/folder-structure.md +++ b/packages/docs/pages/build-integrations/folder-structure.md @@ -1,5 +1,19 @@ # Folder Structure +:::info + +The build integrations section is best understood when read from beginning to end. To get the most value out of it, start from the first page and read through page by page. + +1. [Folder structure](/build-integrations/folder-structure) +2. [App](/build-integrations/app) +3. [Global variable](/build-integrations/global-variable) +4. [Auth](/build-integrations/auth) +5. [Triggers](/build-integrations/triggers) +6. [Actions](/build-integrations/actions) +7. [Examples](/build-integrations/examples) + +::: + :::warning We will use the terms **integration** and **app** interchangeably in this document. ::: diff --git a/packages/docs/pages/build-integrations/global-variable.md b/packages/docs/pages/build-integrations/global-variable.md index a3bff21c..3c7b5cfe 100644 --- a/packages/docs/pages/build-integrations/global-variable.md +++ b/packages/docs/pages/build-integrations/global-variable.md @@ -1,5 +1,19 @@ # Global Variable +:::info + +The build integrations section is best understood when read from beginning to end. To get the most value out of it, start from the first page and read through page by page. + +1. [Folder structure](/build-integrations/folder-structure) +2. [App](/build-integrations/app) +3. [Global variable](/build-integrations/global-variable) +4. [Auth](/build-integrations/auth) +5. [Triggers](/build-integrations/triggers) +6. [Actions](/build-integrations/actions) +7. [Examples](/build-integrations/examples) + +::: + Before handling authentication and building a trigger and an action, it's better to explain the `global variable` concept in Automatisch. Automatisch provides you the global variable that you need to use with authentication, triggers, action, and basically all the stuff you will build for the integration. The global variable is represented as `$` variable in the codebase, and it's a JSON object that contains the following properties: diff --git a/packages/docs/pages/build-integrations/triggers.md b/packages/docs/pages/build-integrations/triggers.md index 061a228c..f7c0f7bc 100644 --- a/packages/docs/pages/build-integrations/triggers.md +++ b/packages/docs/pages/build-integrations/triggers.md @@ -1,5 +1,19 @@ # Triggers +:::info + +The build integrations section is best understood when read from beginning to end. To get the most value out of it, start from the first page and read through page by page. + +1. [Folder structure](/build-integrations/folder-structure) +2. [App](/build-integrations/app) +3. [Global variable](/build-integrations/global-variable) +4. [Auth](/build-integrations/auth) +5. [Triggers](/build-integrations/triggers) +6. [Actions](/build-integrations/actions) +7. [Examples](/build-integrations/examples) + +::: + ## Add triggers to the app Open the `thecatapi/index.ts` file and add the highlighted lines for triggers. From 01ac26de8c010431abf230bab4372b84a3aa9c36 Mon Sep 17 00:00:00 2001 From: Faruk AYDIN Date: Tue, 8 Nov 2022 20:19:10 +0100 Subject: [PATCH 09/24] docs: Add warning to visit development setup page for integrations --- packages/docs/pages/build-integrations/folder-structure.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/docs/pages/build-integrations/folder-structure.md b/packages/docs/pages/build-integrations/folder-structure.md index 5a84ac35..e9f30bb8 100644 --- a/packages/docs/pages/build-integrations/folder-structure.md +++ b/packages/docs/pages/build-integrations/folder-structure.md @@ -14,6 +14,10 @@ The build integrations section is best understood when read from beginning to en ::: +:::warning +If you did not set up the development environment yet, please go back to the [development setup](/contributing/development-setup) page and follow the instructions. +::: + :::warning We will use the terms **integration** and **app** interchangeably in this document. ::: From 2c847f62af01da39f9760ec8eceaf7682ed6ba24 Mon Sep 17 00:00:00 2001 From: Faruk AYDIN Date: Tue, 8 Nov 2022 22:11:34 +0100 Subject: [PATCH 10/24] fix: Cat svg path problem for docs --- packages/docs/pages/build-integrations/app.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/docs/pages/build-integrations/app.md b/packages/docs/pages/build-integrations/app.md index 98643438..9125b9f5 100644 --- a/packages/docs/pages/build-integrations/app.md +++ b/packages/docs/pages/build-integrations/app.md @@ -62,7 +62,7 @@ export default defineApp({ ## Create the favicon -Even though we have defined the `iconUrl` inside the app definition, we still need to create the icon file. Let's create the `assets` folder inside the `thecatapi` folder and save [this SVG file](/example-app/cat.svg) as `favicon.svg` inside of the `assets` folder. After saving the file, you can go to the `My Apps` page on Automatisch and click on `Add connection` button, and then you will see `The cat API` service with the icon. +Even though we have defined the `iconUrl` inside the app definition, we still need to create the icon file. Let's create the `assets` folder inside the `thecatapi` folder and save [this SVG file](../public/example-app/cat.svg) as `favicon.svg` inside of the `assets` folder. After saving the file, you can go to the `My Apps` page on Automatisch and click on `Add connection` button, and then you will see `The cat API` service with the icon. :::tip If you're looking for SVG icons for third-party services, you can use the following repositories. From 39b7effc2605a587767b875d0807f5df8789d860 Mon Sep 17 00:00:00 2001 From: Faruk AYDIN Date: Tue, 8 Nov 2022 22:34:12 +0100 Subject: [PATCH 11/24] docs: Use tip box for the integration and app explanation --- packages/docs/pages/build-integrations/folder-structure.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/docs/pages/build-integrations/folder-structure.md b/packages/docs/pages/build-integrations/folder-structure.md index e9f30bb8..47964529 100644 --- a/packages/docs/pages/build-integrations/folder-structure.md +++ b/packages/docs/pages/build-integrations/folder-structure.md @@ -18,8 +18,8 @@ The build integrations section is best understood when read from beginning to en If you did not set up the development environment yet, please go back to the [development setup](/contributing/development-setup) page and follow the instructions. ::: -:::warning -We will use the terms **integration** and **app** interchangeably in this document. +:::tip +We will use the terms **integration** and **app** interchangeably in the documentation. ::: Before diving into how to build an integration for Automatisch, it's better to check the folder structure of the apps and give you some idea about how we place different parts of the app. From 5497084b5735232bf11f83322742b41046d7982f Mon Sep 17 00:00:00 2001 From: Faruk AYDIN Date: Tue, 8 Nov 2022 22:45:15 +0100 Subject: [PATCH 12/24] docs: Add missing properties of global variable --- .../build-integrations/global-variable.md | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/packages/docs/pages/build-integrations/global-variable.md b/packages/docs/pages/build-integrations/global-variable.md index 3c7b5cfe..53673e11 100644 --- a/packages/docs/pages/build-integrations/global-variable.md +++ b/packages/docs/pages/build-integrations/global-variable.md @@ -51,3 +51,38 @@ $.app.apiBaseUrl; // https://api.thecatapi.com ``` It's used to retrieve the API base URL of the app that we defined previously. In our example, it returns `https://api.thecatapi.com`. We use this property when we need to use the API base URL of the third-party service. + +## $.http + +It's an HTTP client to be used for making HTTP requests. It's a wrapper around the [axios](https://axios-http.com) library. We use this property when we need to make HTTP requests to the third-party service. The `apiBaseUrl` field we set up in the app will be used as the base URL for the HTTP requests. For example to search the cat images, we can use the following code: + +```typescript +$.http.get('/v1/images/search?order=DESC', { + headers: { + 'x-api-key': $.auth.data.apiKey, + }, +}); +``` + +## $.pushTriggerItem + +```typescript +$.pushTriggerItem({ + raw: resourceData, + meta: { + id: resourceData.id, + }, +}); +``` + +It's used to push trigger data to be processed by Automatisch. It must reflect the data that we get from the third-party service. Let's say for search tweets trigger it will be the JSON that represents the tweet object. + +## $.setActionItem + +```typescript +$.setActionItem({ + raw: resourceData, +}); +``` + +It's used to set the action data to be processed by Automatisch. For actions, it reflects the response data that we get from the third-party service. Let's say for create tweet action it will be the JSON that represents the response payload we get while creating a tweet. From 9d62a552feea09cda5d970517b43aae700deb5a6 Mon Sep 17 00:00:00 2001 From: Faruk AYDIN Date: Tue, 8 Nov 2022 23:18:21 +0100 Subject: [PATCH 13/24] docs: Add explanation of setActionItem usage --- packages/docs/pages/build-integrations/actions.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/docs/pages/build-integrations/actions.md b/packages/docs/pages/build-integrations/actions.md index 2895ff63..aac06cee 100644 --- a/packages/docs/pages/build-integrations/actions.md +++ b/packages/docs/pages/build-integrations/actions.md @@ -115,6 +115,10 @@ export default defineAction({ }); ``` +In this action, we send a request to the cat API to mark the cat image as favorite. We used the `$.http.post` method to send the request. The request body contains the image ID as it's required by the API. + +`$.setActionItem` is used to set the result of the action, so we set the response data as the action item. This is used to display the result of the action in the Automatisch UI and can be used in the next steps of the workflow. + ## Test the action Let's go to the flows page of Automatisch and create a new flow. Add the `Search cat images` as a trigger in the flow. Add the `Mark the cat image as favorite` action to the flow as a second step. Add one of the image IDs you got from the cat API as `Image ID` argument to the action. Click `Test & Continue` button. If you a see JSON response in the user interface, it means that both the trigger and the action we built are working properly. From 86ae81526a58dfb0e6f12cfccf55263700829a99 Mon Sep 17 00:00:00 2001 From: Faruk AYDIN Date: Tue, 8 Nov 2022 23:39:40 +0100 Subject: [PATCH 14/24] docs: Fix the wording for actions of build integrations --- packages/docs/pages/build-integrations/actions.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/docs/pages/build-integrations/actions.md b/packages/docs/pages/build-integrations/actions.md index aac06cee..2550bb88 100644 --- a/packages/docs/pages/build-integrations/actions.md +++ b/packages/docs/pages/build-integrations/actions.md @@ -16,9 +16,7 @@ The build integrations section is best understood when read from beginning to en ## Add actions to the app. -Open the thecatapi/index.ts file and add the highlighted lines for actions. - -Open the `thecatapi/index.ts` file and add the highlighted lines for triggers. +Open the `thecatapi/index.ts` file and add the highlighted lines for actions. ```typescript{4,17} import defineApp from '../../helpers/define-app'; From a973887db2f844ada016a0163c37e9b7b8361927 Mon Sep 17 00:00:00 2001 From: Faruk AYDIN Date: Wed, 9 Nov 2022 20:09:26 +0100 Subject: [PATCH 15/24] docs: Add explanation for not supporting webhook based triggers atm --- packages/docs/pages/build-integrations/triggers.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/docs/pages/build-integrations/triggers.md b/packages/docs/pages/build-integrations/triggers.md index f7c0f7bc..b4b55d60 100644 --- a/packages/docs/pages/build-integrations/triggers.md +++ b/packages/docs/pages/build-integrations/triggers.md @@ -14,6 +14,10 @@ The build integrations section is best understood when read from beginning to en ::: +:::warning +For HTTP-based triggers, Automatisch currently supports only polling. Webhook-based triggers are not supported at the moment, but we are planning to add them in the future. +::: + ## Add triggers to the app Open the `thecatapi/index.ts` file and add the highlighted lines for triggers. From 1cb951056a3f3a45d1eacf061d5d21944b1aa3f7 Mon Sep 17 00:00:00 2001 From: Faruk AYDIN Date: Wed, 9 Nov 2022 20:16:41 +0100 Subject: [PATCH 16/24] docs: Fix grammar mistakes for build integrations --- packages/docs/pages/build-integrations/actions.md | 2 +- packages/docs/pages/build-integrations/auth.md | 14 +++++++------- .../pages/build-integrations/folder-structure.md | 4 ++-- .../pages/build-integrations/global-variable.md | 8 ++++---- packages/docs/pages/build-integrations/triggers.md | 2 +- 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/packages/docs/pages/build-integrations/actions.md b/packages/docs/pages/build-integrations/actions.md index 2550bb88..2638b742 100644 --- a/packages/docs/pages/build-integrations/actions.md +++ b/packages/docs/pages/build-integrations/actions.md @@ -55,7 +55,7 @@ If you add new actions, you need to add them to the actions/index.ts file and ex ## Add metadata -Let's create the `actions/mark-cat-image-as-favorite.ts` file inside of the `thecatapi` folder. +Let's create the `actions/mark-cat-image-as-favorite.ts` file inside the `thecatapi` folder. ```typescript import defineAction from '../../../../helpers/define-action'; diff --git a/packages/docs/pages/build-integrations/auth.md b/packages/docs/pages/build-integrations/auth.md index bce7b572..83ef8a8b 100644 --- a/packages/docs/pages/build-integrations/auth.md +++ b/packages/docs/pages/build-integrations/auth.md @@ -122,9 +122,9 @@ const verifyCredentials = async ($: IGlobalVariable) => { export default verifyCredentials; ``` -We have generally use `users/me` endpoint or any other endpoint that we can validate the API key or any other credentials that user provides us. For our example, we don't have a specific API endpoint to check whether the credentials are correct or not. So we will randomly pick one of the API endpoints, which will be the `GET /v1/images/search` endpoint. We will send a request to this endpoint with the API key. If the API key is correct, we will get a response from the API. If the API key is incorrect, we will get an error response from the API. +We generally use the `users/me` endpoint or any other endpoint that we can validate the API key or any other credentials that the user provides. For our example, we don't have a specific API endpoint to check whether the credentials are correct or not. So we will randomly pick one of the API endpoints, which will be the `GET /v1/images/search` endpoint. We will send a request to this endpoint with the API key. If the API key is correct, we will get a response from the API. If the API key is incorrect, we will get an error response from the API. -Let's implement the authentication logic that we mentioned in the `verify-credentials.ts` file. +Let's implement the authentication logic that we mentioned above in the `verify-credentials.ts` file. ```typescript import { IGlobalVariable } from '@automatisch/types'; @@ -140,7 +140,7 @@ const verifyCredentials = async ($: IGlobalVariable) => { export default verifyCredentials; ``` -Here we send a request to `/v1/images/search` endpoint with the API key. If we get a response from the API, we will set the screen name to the auth data. If we get an error response from the API, it will throw an error. +Here we send a request to the `/v1/images/search` endpoint with the API key. If we get a response from the API, we will set the screen name to the auth data. If we get an error response from the API, it will throw an error. ## Is still verified? @@ -177,15 +177,15 @@ export default isStillVerified; ``` :::info -`isStillVerified` method needs to return `truthy` value if the credentials are still valid. +`isStillVerified` method needs to return the `truthy` value if the credentials are still valid. ::: -We will use the `verifyCredentials` method to check whether the credentials are still valid or not. If the credentials are still valid, we will return `true`. Otherwise it will thrown an error which will automatically handled by Automatisch. +We will use the `verifyCredentials` method to check whether the credentials are still valid or not. If the credentials are still valid, we will return `true`. Otherwise, it will throw an error which will automatically be handled by Automatisch. :::warning -You might be wondering why we need to have two separate functions even though we use only one of them behind the scenes in this scenario. That might be true in our example or any other APIs similar to the cat API but there are some other third-party APIs which we can't use the same functionality directly to check whether the credentials are still valid or not. So we need to have two separate functions for verifying the credentials and checking whether the credentials are still valid or not. +You might be wondering why we need to have two separate functions even though we use only one of them behind the scenes in this scenario. That might be true in our example or any other APIs similar to the cat API but there are some other third-party APIs that we can't use the same functionality directly to check whether the credentials are still valid or not. So we need to have two separate functions for verifying the credentials and checking whether the credentials are still valid or not. ::: -Now we have completed the authentication of the cat API. Go to `My Apps` page in Automatisch, try to add a new connection, select `The Cat API` and use your API key you got with an email. Then you can also check the test connection and reconnect functionality there. +Now we have completed the authentication of the cat API. Go to the `My Apps` page in Automatisch, try to add a new connection, select `The Cat API` and use the `API Key` you got with an email. Then you can also check the test connection and reconnect functionality there. Let's move on to the next page to build a trigger. diff --git a/packages/docs/pages/build-integrations/folder-structure.md b/packages/docs/pages/build-integrations/folder-structure.md index 47964529..37c445ad 100644 --- a/packages/docs/pages/build-integrations/folder-structure.md +++ b/packages/docs/pages/build-integrations/folder-structure.md @@ -15,7 +15,7 @@ The build integrations section is best understood when read from beginning to en ::: :::warning -If you did not set up the development environment yet, please go back to the [development setup](/contributing/development-setup) page and follow the instructions. +If you still need to set up the development environment, please go back to the [development setup](/contributing/development-setup) page and follow the instructions. ::: :::tip @@ -57,7 +57,7 @@ As mentioned above, actions are the steps we place after a trigger. Actions are ## Common -Common folder is a place where you can put utilities or shared functionality used by other folders like triggers, actions, auth, etc. +The common folder is where you can put utilities or shared functionality used by other folders like triggers, actions, auth, etc. ## Data diff --git a/packages/docs/pages/build-integrations/global-variable.md b/packages/docs/pages/build-integrations/global-variable.md index 53673e11..ad098f72 100644 --- a/packages/docs/pages/build-integrations/global-variable.md +++ b/packages/docs/pages/build-integrations/global-variable.md @@ -21,7 +21,7 @@ The global variable is represented as `$` variable in the codebase, and it's a J ## $.auth.set ```typescript -$.auth.set({ +await $.auth.set({ key: 'value', }); ``` @@ -54,10 +54,10 @@ It's used to retrieve the API base URL of the app that we defined previously. In ## $.http -It's an HTTP client to be used for making HTTP requests. It's a wrapper around the [axios](https://axios-http.com) library. We use this property when we need to make HTTP requests to the third-party service. The `apiBaseUrl` field we set up in the app will be used as the base URL for the HTTP requests. For example to search the cat images, we can use the following code: +It's an HTTP client to be used for making HTTP requests. It's a wrapper around the [axios](https://axios-http.com) library. We use this property when we need to make HTTP requests to the third-party service. The `apiBaseUrl` field we set up in the app will be used as the base URL for the HTTP requests. For example, to search the cat images, we can use the following code: ```typescript -$.http.get('/v1/images/search?order=DESC', { +await $.http.get('/v1/images/search?order=DESC', { headers: { 'x-api-key': $.auth.data.apiKey, }, @@ -75,7 +75,7 @@ $.pushTriggerItem({ }); ``` -It's used to push trigger data to be processed by Automatisch. It must reflect the data that we get from the third-party service. Let's say for search tweets trigger it will be the JSON that represents the tweet object. +It's used to push trigger data to be processed by Automatisch. It must reflect the data that we get from the third-party service. Let's say for search tweets trigger the `resourceData` will be the JSON that represents the single tweet object. ## $.setActionItem diff --git a/packages/docs/pages/build-integrations/triggers.md b/packages/docs/pages/build-integrations/triggers.md index b4b55d60..bed17db5 100644 --- a/packages/docs/pages/build-integrations/triggers.md +++ b/packages/docs/pages/build-integrations/triggers.md @@ -146,4 +146,4 @@ We do not have to return anything from the `run` function. We are using the `$.p ### Test the trigger -Let's go to the flows page of Automatisch and create a new flow. Choose the `The cat API` app and the `Search cat images` trigger and click `Test & Continue` button. If you a see JSON response in the user interface, it means that the trigger is working properly. +Let's go to the flows page of Automatisch and create a new flow. Choose `The cat API` app and the `Search cat images` trigger and click `Test & Continue` button. If you a see JSON response in the user interface, it means that the trigger is working properly. From 580e97ffe3efdcee6e0506a32c42f9fac6fababe Mon Sep 17 00:00:00 2001 From: Faruk AYDIN Date: Wed, 9 Nov 2022 20:32:28 +0100 Subject: [PATCH 17/24] docs: Adjust wording for building triggers and actions --- .../docs/pages/build-integrations/actions.md | 17 +++++++++++------ .../docs/pages/build-integrations/triggers.md | 12 ++++++------ 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/packages/docs/pages/build-integrations/actions.md b/packages/docs/pages/build-integrations/actions.md index 2638b742..0e69b9a5 100644 --- a/packages/docs/pages/build-integrations/actions.md +++ b/packages/docs/pages/build-integrations/actions.md @@ -41,7 +41,7 @@ export default defineApp({ ## Define actions -Let's create the `actions/index.ts` file inside of the `thecatapi` folder. +Create the `actions/index.ts` file inside of the `thecatapi` folder. ```typescript import mark-cat-image-as-favorite from './mark-cat-image-as-favorite'; @@ -55,7 +55,7 @@ If you add new actions, you need to add them to the actions/index.ts file and ex ## Add metadata -Let's create the `actions/mark-cat-image-as-favorite.ts` file inside the `thecatapi` folder. +Create the `actions/mark-cat-image-as-favorite.ts` file inside the `thecatapi` folder. ```typescript import defineAction from '../../../../helpers/define-action'; @@ -91,9 +91,9 @@ Let's briefly explain what we defined here. ## Implement the action -Let's implement the action. Open the `actions/mark-cat-image-as-favorite.ts` file and add the highlighted lines. +Open the `actions/mark-cat-image-as-favorite.ts` file and add the highlighted lines. -```typescript{7-15} +```typescript{7-20} import defineAction from '../../../../helpers/define-action'; export default defineAction({ @@ -103,9 +103,14 @@ export default defineAction({ const requestPath = `/v1/favorites`; const imageId = $.step.parameters.imageId; + const headers = { + 'x-api-key': $.auth.data.apiKey, + }; + const response = await $.http.post( requestPath, - { image_id: imageId } + { image_id: imageId }, + { headers } ); $.setActionItem({ raw: response.data }); @@ -119,4 +124,4 @@ In this action, we send a request to the cat API to mark the cat image as favori ## Test the action -Let's go to the flows page of Automatisch and create a new flow. Add the `Search cat images` as a trigger in the flow. Add the `Mark the cat image as favorite` action to the flow as a second step. Add one of the image IDs you got from the cat API as `Image ID` argument to the action. Click `Test & Continue` button. If you a see JSON response in the user interface, it means that both the trigger and the action we built are working properly. +Go to the flows page of Automatisch and create a new flow. Add the `Search cat images` as a trigger in the flow. Add the `Mark the cat image as favorite` action to the flow as a second step. Add one of the image IDs you got from the cat API as `Image ID` argument to the action. Click `Test & Continue` button. If you a see JSON response in the user interface, it means that both the trigger and the action we built are working properly. diff --git a/packages/docs/pages/build-integrations/triggers.md b/packages/docs/pages/build-integrations/triggers.md index bed17db5..90872070 100644 --- a/packages/docs/pages/build-integrations/triggers.md +++ b/packages/docs/pages/build-integrations/triggers.md @@ -43,7 +43,7 @@ export default defineApp({ ## Define triggers -Let's create the `triggers/index.ts` file inside of the `thecatapi` folder. +Create the `triggers/index.ts` file inside of the `thecatapi` folder. ```typescript import searchCatImages from './search-cat-images'; @@ -57,7 +57,7 @@ If you add new triggers, you need to add them to the `triggers/index.ts` file an ## Add metadata -Let's create the `triggers/search-cat-images.ts` file inside of the `thecatapi` folder. +Create the `triggers/search-cat-images.ts` file inside of the `thecatapi` folder. ```typescript import defineTrigger from '../../../../helpers/define-trigger'; @@ -91,9 +91,9 @@ Let's briefly explain what we defined here. ::: -Let's implement the `run` function. +Implement the `run` function by adding highlighted lines. -```typescript{10-34} +```typescript{6-29} import defineTrigger from '../../../../helpers/define-trigger'; export default defineTrigger({ @@ -127,7 +127,7 @@ export default defineTrigger({ }); ``` -Let's briefly explain what we did here. We are using the `$.http` object to make HTTP requests. Our API is paginated, so we are making requests until we get less than 10 items, which means the last page. +We are using the `$.http` object to make HTTP requests. Our API is paginated, so we are making requests until we get less than 10 items, which means the last page. We do not have to return anything from the `run` function. We are using the `$.pushTriggerItem` function to push the data to Automatisch. $.pushTriggerItem accepts an object with the following fields: @@ -146,4 +146,4 @@ We do not have to return anything from the `run` function. We are using the `$.p ### Test the trigger -Let's go to the flows page of Automatisch and create a new flow. Choose `The cat API` app and the `Search cat images` trigger and click `Test & Continue` button. If you a see JSON response in the user interface, it means that the trigger is working properly. +Go to the flows page of Automatisch and create a new flow. Choose `The cat API` app and the `Search cat images` trigger and click `Test & Continue` button. If you a see JSON response in the user interface, it means that the trigger is working properly. From e956b2d9594171e96cdbbc77baa032017624f3a5 Mon Sep 17 00:00:00 2001 From: Faruk AYDIN Date: Wed, 9 Nov 2022 20:48:10 +0100 Subject: [PATCH 18/24] docs: Separate the tips of pushTriggerItem method --- packages/docs/pages/build-integrations/triggers.md | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/packages/docs/pages/build-integrations/triggers.md b/packages/docs/pages/build-integrations/triggers.md index 90872070..545f7e64 100644 --- a/packages/docs/pages/build-integrations/triggers.md +++ b/packages/docs/pages/build-integrations/triggers.md @@ -136,11 +136,19 @@ We do not have to return anything from the `run` function. We are using the `$.p :::tip -- `$.pushTriggerItem` is smart enough to understand if the data is already pushed to Automatisch or not. If the data is already pushed, it will stop the trigger, otherwise, it will continue to fetch new data. +`$.pushTriggerItem` is smart enough to understand if the data is already pushed to Automatisch or not. If the data is already pushed, it will stop the trigger, otherwise, it will continue to fetch new data. -- `$.pushTriggerItem` also understands whether the trigger is executed with `Test & Continue` button in the user interface or it's a trigger from a published flow. If the trigger is executed with `Test & Continue` button, it will push only one item regardless of whether we already processed the data or not and early exits the process, otherwise, it will fetch the remaining data. +::: -- Let's say the trigger started to execute. It fetched the first five pages of data from the third-party API with five different HTTP requests and you still need to get the next page but you started to get an API rate limit error. In this case, Automatisch will not lose the data that is already fetched from the first five requests. It stops the trigger when it got the error the first time but processes all previously fetched data. +:::tip + +`$.pushTriggerItem` also understands whether the trigger is executed with `Test & Continue` button in the user interface or it's a trigger from a published flow. If the trigger is executed with `Test & Continue` button, it will push only one item regardless of whether we already processed the data or not and early exits the process, otherwise, it will fetch the remaining data. + +::: + +:::tip + +Let's say the trigger started to execute. It fetched the first five pages of data from the third-party API with five different HTTP requests and you still need to get the next page but you started to get an API rate limit error. In this case, Automatisch will not lose the data that is already fetched from the first five requests. It stops the trigger when it got the error the first time but processes all previously fetched data. ::: From 0d479426ed47be415fecda620cb33a18e03a648c Mon Sep 17 00:00:00 2001 From: Faruk AYDIN Date: Wed, 9 Nov 2022 21:30:32 +0100 Subject: [PATCH 19/24] docs: Add $.step.parameters property to global variable --- packages/docs/pages/build-integrations/global-variable.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/packages/docs/pages/build-integrations/global-variable.md b/packages/docs/pages/build-integrations/global-variable.md index ad098f72..df3e5048 100644 --- a/packages/docs/pages/build-integrations/global-variable.md +++ b/packages/docs/pages/build-integrations/global-variable.md @@ -64,6 +64,14 @@ await $.http.get('/v1/images/search?order=DESC', { }); ``` +## $.step.parameters + +```typescript +$.step.parameters; // { key: 'value' } +``` + +It refers to the parameters that are set by users in the UI. We use this property when we need to get the parameters for corresponding triggers and actions. For example [Send a message to channel](https://github.com/automatisch/automatisch/blob/main/packages/backend/src/apps/slack/actions/send-a-message-to-channel/post-message.ts) action from Slack integration, we have a step parameter called `message` that we need to use in the action. We can use `$.step.parameters.message` to get the value of the message to send a message to the Slack channel. + ## $.pushTriggerItem ```typescript From 4b8ac0ff9c45d1394211062826006418aab07895 Mon Sep 17 00:00:00 2001 From: Faruk AYDIN Date: Wed, 9 Nov 2022 21:46:17 +0100 Subject: [PATCH 20/24] docs: Add explanation to include screenName in verify credentials --- packages/docs/pages/build-integrations/auth.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/docs/pages/build-integrations/auth.md b/packages/docs/pages/build-integrations/auth.md index 83ef8a8b..78b8bfd0 100644 --- a/packages/docs/pages/build-integrations/auth.md +++ b/packages/docs/pages/build-integrations/auth.md @@ -142,6 +142,10 @@ export default verifyCredentials; Here we send a request to the `/v1/images/search` endpoint with the API key. If we get a response from the API, we will set the screen name to the auth data. If we get an error response from the API, it will throw an error. +:::warning +You must always provide a `screenName` field to auth data in the `verifyCredentials` method. Otherwise, the connection will not have a name and it will not function properly in the user interface. +::: + ## Is still verified? We have implemented the `verifyCredentials` method. Now we need to check whether the credentials are still valid or not for the test connection functionality in Automatisch. We will do that by defining the `isStillVerified` method. From af8d1190c5253d38ee061e5a669db5202081f401 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=96mer=20Faruk=20Ayd=C4=B1n?= Date: Wed, 9 Nov 2022 23:10:56 +0100 Subject: [PATCH 21/24] docs: Fix wording for the global variable page Co-authored-by: Ali BARIN --- packages/docs/pages/build-integrations/global-variable.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/docs/pages/build-integrations/global-variable.md b/packages/docs/pages/build-integrations/global-variable.md index df3e5048..396a5c49 100644 --- a/packages/docs/pages/build-integrations/global-variable.md +++ b/packages/docs/pages/build-integrations/global-variable.md @@ -14,7 +14,7 @@ The build integrations section is best understood when read from beginning to en ::: -Before handling authentication and building a trigger and an action, it's better to explain the `global variable` concept in Automatisch. Automatisch provides you the global variable that you need to use with authentication, triggers, action, and basically all the stuff you will build for the integration. +Before handling authentication and building a trigger and an action, it's better to explain the `global variable` concept in Automatisch. Automatisch provides you the global variable that you need to use with authentication, triggers, actions, and basically all the stuff you will build for the integration. The global variable is represented as `$` variable in the codebase, and it's a JSON object that contains the following properties: From 72e1fe3c2133b744368a8c0c09deb0ca673d305d Mon Sep 17 00:00:00 2001 From: Faruk AYDIN Date: Wed, 9 Nov 2022 23:29:21 +0100 Subject: [PATCH 22/24] docs: Explain that trigger array order will be reflected on UI --- packages/docs/pages/build-integrations/triggers.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/docs/pages/build-integrations/triggers.md b/packages/docs/pages/build-integrations/triggers.md index 545f7e64..20c955f4 100644 --- a/packages/docs/pages/build-integrations/triggers.md +++ b/packages/docs/pages/build-integrations/triggers.md @@ -52,7 +52,7 @@ export default [searchCatImages]; ``` :::tip -If you add new triggers, you need to add them to the `triggers/index.ts` file and export all triggers as an array. +If you add new triggers, you need to add them to the `triggers/index.ts` file and export all triggers as an array. The order of triggers in this array will be reflected in the Automatisch user interface. ::: ## Add metadata From 98041b7af2b4225e2fa74c0cd58a641b17ac51af Mon Sep 17 00:00:00 2001 From: Faruk AYDIN Date: Wed, 9 Nov 2022 23:32:57 +0100 Subject: [PATCH 23/24] docs: Explain $.auth.set expands the value rather than overriding --- packages/docs/pages/build-integrations/global-variable.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/docs/pages/build-integrations/global-variable.md b/packages/docs/pages/build-integrations/global-variable.md index 396a5c49..3137dc09 100644 --- a/packages/docs/pages/build-integrations/global-variable.md +++ b/packages/docs/pages/build-integrations/global-variable.md @@ -26,7 +26,7 @@ await $.auth.set({ }); ``` -It's used to set the authentication data, and you can use this method with multiple pairs. The data will be stored in the database and can be retrieved later by using `$.auth.data` property. We use this method when we store the credentials of the third-party service. Note that Automatisch encrypts the data before storing it in the database. +It's used to set the authentication data, and you can use this method with multiple pairs. The data will be stored in the database and can be retrieved later by using `$.auth.data` property. The data you set with this method will not override its current value but expands it. We use this method when we store the credentials of the third-party service. Note that Automatisch encrypts the data before storing it in the database. ## $.auth.data From 44159af83eb3fe834f5fe3842ce088612df99337 Mon Sep 17 00:00:00 2001 From: Faruk AYDIN Date: Wed, 9 Nov 2022 23:36:36 +0100 Subject: [PATCH 24/24] docs: Expands the explanation of already procesed control --- packages/docs/pages/build-integrations/triggers.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/docs/pages/build-integrations/triggers.md b/packages/docs/pages/build-integrations/triggers.md index 20c955f4..dcd695f1 100644 --- a/packages/docs/pages/build-integrations/triggers.md +++ b/packages/docs/pages/build-integrations/triggers.md @@ -136,7 +136,7 @@ We do not have to return anything from the `run` function. We are using the `$.p :::tip -`$.pushTriggerItem` is smart enough to understand if the data is already pushed to Automatisch or not. If the data is already pushed, it will stop the trigger, otherwise, it will continue to fetch new data. +`$.pushTriggerItem` is smart enough to understand if the data is already pushed to Automatisch or not. If the data is already pushed and processed, it will stop the trigger, otherwise, it will continue to fetch new data. The check is done by comparing the `internalId` field with the `internalId` field of the data that is already processed. The control of whether the data is already processed or not is scoped by the flow. :::