feat: Implement typeform connection
This commit is contained in:
6
packages/backend/src/apps/typeform/assets/favicon.svg
Normal file
6
packages/backend/src/apps/typeform/assets/favicon.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 6.5 KiB |
93
packages/backend/src/apps/typeform/index.ts
Normal file
93
packages/backend/src/apps/typeform/index.ts
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
import { URLSearchParams } from 'url';
|
||||||
|
import axios, { AxiosInstance } from
|
||||||
|
'axios';
|
||||||
|
import App from '../../models/app';
|
||||||
|
import Field from '../../types/field';
|
||||||
|
|
||||||
|
export default class Typeform {
|
||||||
|
client?: any
|
||||||
|
connectionData: any
|
||||||
|
appData: any
|
||||||
|
scope: string[] = [
|
||||||
|
'forms:read',
|
||||||
|
'forms:write',
|
||||||
|
'webhooks:read',
|
||||||
|
'webhooks:write',
|
||||||
|
'responses:read',
|
||||||
|
'accounts:read',
|
||||||
|
'workspaces:read',
|
||||||
|
]
|
||||||
|
httpClient: AxiosInstance = axios.create({
|
||||||
|
baseURL: 'https://api.typeform.com'
|
||||||
|
})
|
||||||
|
|
||||||
|
constructor(connectionData: any) {
|
||||||
|
this.connectionData = connectionData;
|
||||||
|
this.appData = App.findOneByKey('typeform');
|
||||||
|
}
|
||||||
|
|
||||||
|
get oauthRedirectUrl() {
|
||||||
|
return this.appData.fields.find((field: Field) => field.key == 'oAuthRedirectUrl').value;
|
||||||
|
}
|
||||||
|
|
||||||
|
async createAuthData() {
|
||||||
|
const searchParams = new URLSearchParams({
|
||||||
|
client_id: this.connectionData.consumerKey,
|
||||||
|
redirect_uri: this.oauthRedirectUrl,
|
||||||
|
scope: this.scope.join(' '),
|
||||||
|
});
|
||||||
|
|
||||||
|
const url = `https://api.typeform.com/oauth/authorize?${searchParams.toString()}`;
|
||||||
|
|
||||||
|
return { url };
|
||||||
|
}
|
||||||
|
|
||||||
|
async verifyCredentials() {
|
||||||
|
const params = new URLSearchParams({
|
||||||
|
grant_type: 'authorization_code',
|
||||||
|
code: this.connectionData.oauthVerifier,
|
||||||
|
client_id: this.connectionData.consumerKey,
|
||||||
|
client_secret: this.connectionData.consumerSecret,
|
||||||
|
redirect_uri: this.oauthRedirectUrl,
|
||||||
|
});
|
||||||
|
|
||||||
|
const { data: verifiedCredentials }: any = await this.httpClient.post('/oauth/token', params.toString());
|
||||||
|
|
||||||
|
const {
|
||||||
|
access_token: accessToken,
|
||||||
|
expires_in: expiresIn,
|
||||||
|
token_type: tokenType,
|
||||||
|
} = verifiedCredentials;
|
||||||
|
|
||||||
|
const { data: user }: any = await this.httpClient.get('/me', {
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${accessToken}`,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
consumerKey: this.connectionData.consumerKey,
|
||||||
|
consumerSecret: this.connectionData.consumerSecret,
|
||||||
|
accessToken,
|
||||||
|
expiresIn,
|
||||||
|
tokenType,
|
||||||
|
userId: user.user_id,
|
||||||
|
screenName: user.alias,
|
||||||
|
email: user.email,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async isStillVerified() {
|
||||||
|
try {
|
||||||
|
await this.httpClient.get('/me', {
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${this.connectionData.accessToken}`,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} catch {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
218
packages/backend/src/apps/typeform/info.json
Normal file
218
packages/backend/src/apps/typeform/info.json
Normal file
@@ -0,0 +1,218 @@
|
|||||||
|
{
|
||||||
|
"name": "Typeform",
|
||||||
|
"key": "typeform",
|
||||||
|
"iconUrl": "{BASE_URL}/apps/typeform/assets/favicon.svg",
|
||||||
|
"docUrl": "https://automatisch.io/docs/typeform",
|
||||||
|
"primaryColor": "5865f2",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"key": "oAuthRedirectUrl",
|
||||||
|
"label": "OAuth Redirect URL",
|
||||||
|
"type": "string",
|
||||||
|
"required": true,
|
||||||
|
"readOnly": true,
|
||||||
|
"value": "https://localhost:3001/app/typeform/connections/add",
|
||||||
|
"placeholder": null,
|
||||||
|
"description": "When asked to input an OAuth callback or redirect URL in Typeform OAuth, enter the URL above.",
|
||||||
|
"docUrl": "https://automatisch.io/docs/typeform#oauth-redirect-url",
|
||||||
|
"clickToCopy": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "consumerKey",
|
||||||
|
"label": "Client ID",
|
||||||
|
"type": "string",
|
||||||
|
"required": true,
|
||||||
|
"readOnly": false,
|
||||||
|
"value": null,
|
||||||
|
"placeholder": null,
|
||||||
|
"description": null,
|
||||||
|
"docUrl": "https://automatisch.io/docs/typeform#consumer-key",
|
||||||
|
"clickToCopy": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "consumerSecret",
|
||||||
|
"label": "Client Secret",
|
||||||
|
"type": "string",
|
||||||
|
"required": true,
|
||||||
|
"readOnly": false,
|
||||||
|
"value": null,
|
||||||
|
"placeholder": null,
|
||||||
|
"description": null,
|
||||||
|
"docUrl": "https://automatisch.io/docs/typeform#consumer-secret",
|
||||||
|
"clickToCopy": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"authenticationSteps": [
|
||||||
|
{
|
||||||
|
"step": 1,
|
||||||
|
"type": "mutation",
|
||||||
|
"name": "createConnection",
|
||||||
|
"arguments": [
|
||||||
|
{
|
||||||
|
"name": "key",
|
||||||
|
"value": "{key}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "data",
|
||||||
|
"value": null,
|
||||||
|
"properties": [
|
||||||
|
{
|
||||||
|
"name": "consumerKey",
|
||||||
|
"value": "{fields.consumerKey}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "consumerSecret",
|
||||||
|
"value": "{fields.consumerSecret}"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"step": 2,
|
||||||
|
"type": "mutation",
|
||||||
|
"name": "createAuthData",
|
||||||
|
"arguments": [
|
||||||
|
{
|
||||||
|
"name": "id",
|
||||||
|
"value": "{createConnection.id}"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"step": 3,
|
||||||
|
"type": "openWithPopup",
|
||||||
|
"name": "openAuthPopup",
|
||||||
|
"arguments": [
|
||||||
|
{
|
||||||
|
"name": "url",
|
||||||
|
"value": "{createAuthData.url}"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"step": 4,
|
||||||
|
"type": "mutation",
|
||||||
|
"name": "updateConnection",
|
||||||
|
"arguments": [
|
||||||
|
{
|
||||||
|
"name": "id",
|
||||||
|
"value": "{createConnection.id}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "data",
|
||||||
|
"value": null,
|
||||||
|
"properties": [
|
||||||
|
{
|
||||||
|
"name": "oauthVerifier",
|
||||||
|
"value": "{openAuthPopup.code}"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"step": 5,
|
||||||
|
"type": "mutation",
|
||||||
|
"name": "verifyConnection",
|
||||||
|
"arguments": [
|
||||||
|
{
|
||||||
|
"name": "id",
|
||||||
|
"value": "{createConnection.id}"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"reconnectionSteps": [
|
||||||
|
{
|
||||||
|
"step": 1,
|
||||||
|
"type": "mutation",
|
||||||
|
"name": "resetConnection",
|
||||||
|
"arguments": [
|
||||||
|
{
|
||||||
|
"name": "id",
|
||||||
|
"value": "{connection.id}"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"step": 2,
|
||||||
|
"type": "mutation",
|
||||||
|
"name": "updateConnection",
|
||||||
|
"arguments": [
|
||||||
|
{
|
||||||
|
"name": "id",
|
||||||
|
"value": "{connection.id}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "data",
|
||||||
|
"value": null,
|
||||||
|
"properties": [
|
||||||
|
{
|
||||||
|
"name": "consumerKey",
|
||||||
|
"value": "{fields.consumerKey}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "consumerSecret",
|
||||||
|
"value": "{fields.consumerSecret}"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"step": 3,
|
||||||
|
"type": "mutation",
|
||||||
|
"name": "createAuthData",
|
||||||
|
"arguments": [
|
||||||
|
{
|
||||||
|
"name": "id",
|
||||||
|
"value": "{connection.id}"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"step": 4,
|
||||||
|
"type": "openWithPopup",
|
||||||
|
"name": "openAuthPopup",
|
||||||
|
"arguments": [
|
||||||
|
{
|
||||||
|
"name": "url",
|
||||||
|
"value": "{createAuthData.url}"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"step": 5,
|
||||||
|
"type": "mutation",
|
||||||
|
"name": "updateConnection",
|
||||||
|
"arguments": [
|
||||||
|
{
|
||||||
|
"name": "id",
|
||||||
|
"value": "{connection.id}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "data",
|
||||||
|
"value": null,
|
||||||
|
"properties": [
|
||||||
|
{
|
||||||
|
"name": "oauthVerifier",
|
||||||
|
"value": "{openAuthPopup.code}"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"step": 6,
|
||||||
|
"type": "mutation",
|
||||||
|
"name": "verifyConnection",
|
||||||
|
"arguments": [
|
||||||
|
{
|
||||||
|
"name": "id",
|
||||||
|
"value": "{connection.id}"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
Reference in New Issue
Block a user