@guayaba/workflow-piece-google-forms 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/.eslintrc.json ADDED
@@ -0,0 +1,18 @@
1
+ {
2
+ "extends": ["../../../../.eslintrc.json"],
3
+ "ignorePatterns": ["!**/*"],
4
+ "overrides": [
5
+ {
6
+ "files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
7
+ "rules": {}
8
+ },
9
+ {
10
+ "files": ["*.ts", "*.tsx"],
11
+ "rules": {}
12
+ },
13
+ {
14
+ "files": ["*.js", "*.jsx"],
15
+ "rules": {}
16
+ }
17
+ ]
18
+ }
package/README.md ADDED
@@ -0,0 +1,5 @@
1
+ # pieces-google-forms
2
+
3
+ ## Building
4
+
5
+ Run `turbo run build --filter=@guayaba/workflow-piece-google-forms` to build the library.
Binary file
package/package.json ADDED
@@ -0,0 +1,23 @@
1
+ {
2
+ "name": "@guayaba/workflow-piece-google-forms",
3
+ "version": "0.5.1",
4
+ "main": "./dist/src/index.js",
5
+ "types": "./dist/src/index.d.ts",
6
+ "dependencies": {
7
+ "@guayaba/workflows-common": "workspace:*",
8
+ "@guayaba/workflows-framework": "workspace:*",
9
+ "@guayaba/workflows-shared": "workspace:*",
10
+ "dayjs": "1.11.9",
11
+ "googleapis": "129.0.0",
12
+ "googleapis-common": "7.2.0",
13
+ "tslib": "2.6.2"
14
+ },
15
+ "scripts": {
16
+ "build": "tsc -p tsconfig.lib.json && cp package.json dist/",
17
+ "lint": "eslint 'src/**/*.ts'"
18
+ },
19
+ "publishConfig": {
20
+ "registry": "https://registry.npmjs.org",
21
+ "access": "public"
22
+ }
23
+ }
@@ -0,0 +1,24 @@
1
+ {
2
+ "Google Forms": "Google Forms",
3
+ "Receive form responses from Google Forms": "Receive form responses from Google Forms",
4
+ "Custom API Call": "Custom API Call",
5
+ "Make a custom API call to a specific endpoint": "Make a custom API call to a specific endpoint",
6
+ "Method": "Method",
7
+ "Headers": "Headers",
8
+ "Query Parameters": "Query Parameters",
9
+ "Body": "Body",
10
+ "No Error on Failure": "No Error on Failure",
11
+ "Timeout (in seconds)": "Timeout (in seconds)",
12
+ "Authorization headers are injected automatically from your connection.": "Authorization headers are injected automatically from your connection.",
13
+ "GET": "GET",
14
+ "POST": "POST",
15
+ "PATCH": "PATCH",
16
+ "PUT": "PUT",
17
+ "DELETE": "DELETE",
18
+ "HEAD": "HEAD",
19
+ "New Response": "New Response",
20
+ "Triggers when there is new response": "Triggers when there is new response",
21
+ "Form": "Form",
22
+ "Include Team Drive Forms": "Include Team Drive Forms",
23
+ "Determines if forms from Team Drives should be included in the results.": "Determines if forms from Team Drives should be included in the results."
24
+ }
@@ -0,0 +1,31 @@
1
+ {
2
+ "Receive form responses from Google Forms": "Erhalte Formularantworten von Google Formularen",
3
+ "Custom API Call": "Eigener API-Aufruf",
4
+ "Make a custom API call to a specific endpoint": "Einen benutzerdefinierten API-Aufruf an einen bestimmten Endpunkt machen",
5
+ "Method": "Methode",
6
+ "Headers": "Kopfzeilen",
7
+ "Query Parameters": "Abfrageparameter",
8
+ "Body Type": "Körpertyp",
9
+ "Body": "Körper",
10
+ "Response is Binary ?": "Antwort ist binär?",
11
+ "No Error on Failure": "Kein Fehler bei Fehler",
12
+ "Timeout (in seconds)": "Timeout (in Sekunden)",
13
+ "Follow redirects": "Weiterleitungen folgen",
14
+ "Authorization headers are injected automatically from your connection.": "Autorisierungs-Header werden automatisch von Ihrer Verbindung injiziert.",
15
+ "Enable for files like PDFs, images, etc.": "Aktivieren für Dateien wie PDFs, Bilder usw.",
16
+ "GET": "ERHALTEN",
17
+ "POST": "POST",
18
+ "PATCH": "PATCH",
19
+ "PUT": "PUT",
20
+ "DELETE": "LÖSCHEN",
21
+ "HEAD": "HEAD",
22
+ "None": "Keine",
23
+ "JSON": "JSON",
24
+ "Form Data": "Formulardaten",
25
+ "Raw": "Rohe",
26
+ "New Response": "Neue Antwort",
27
+ "Triggers when there is new response": "Wird ausgelöst, wenn eine neue Antwort vorhanden ist",
28
+ "Form": "Formular",
29
+ "Include Team Drive Forms": "Teamlaufwerksformulare einbeziehen",
30
+ "Determines if forms from Team Drives should be included in the results.": "Legt fest, ob Formulare von Team Drives in die Ergebnisse aufgenommen werden sollen."
31
+ }
@@ -0,0 +1,31 @@
1
+ {
2
+ "Receive form responses from Google Forms": "Recibir respuestas de formularios de Google Forms",
3
+ "Custom API Call": "Llamada API personalizada",
4
+ "Make a custom API call to a specific endpoint": "Hacer una llamada API personalizada a un extremo específico",
5
+ "Method": "Método",
6
+ "Headers": "Encabezados",
7
+ "Query Parameters": "Parámetros de consulta",
8
+ "Body Type": "Tipo de cuerpo",
9
+ "Body": "Cuerpo",
10
+ "Response is Binary ?": "¿Respuesta es binaria?",
11
+ "No Error on Failure": "No hay ningún error en fallo",
12
+ "Timeout (in seconds)": "Tiempo de espera (en segundos)",
13
+ "Follow redirects": "Seguir redirecciones",
14
+ "Authorization headers are injected automatically from your connection.": "Las cabeceras de autorización se inyectan automáticamente desde tu conexión.",
15
+ "Enable for files like PDFs, images, etc.": "Activar para archivos como PDFs, imágenes, etc.",
16
+ "GET": "RECOGER",
17
+ "POST": "POST",
18
+ "PATCH": "PATCH",
19
+ "PUT": "PUT",
20
+ "DELETE": "BORRAR",
21
+ "HEAD": "LIMPIO",
22
+ "None": "Ninguna",
23
+ "JSON": "JSON",
24
+ "Form Data": "Datos de Formulario",
25
+ "Raw": "Rápido",
26
+ "New Response": "Nueva respuesta",
27
+ "Triggers when there is new response": "Dispara cuando hay nueva respuesta",
28
+ "Form": "Forma",
29
+ "Include Team Drive Forms": "Incluye Formularios de Unidad de Equipo",
30
+ "Determines if forms from Team Drives should be included in the results.": "Determina si los formularios de Team Drives deben ser incluidos en los resultados."
31
+ }
@@ -0,0 +1,31 @@
1
+ {
2
+ "Receive form responses from Google Forms": "Recevoir des réponses de formulaires de Google Forms",
3
+ "Custom API Call": "Appel API personnalisé",
4
+ "Make a custom API call to a specific endpoint": "Passez un appel API personnalisé à un endpoint spécifique",
5
+ "Method": "Méthode",
6
+ "Headers": "Headers",
7
+ "Query Parameters": "Paramètres de requête",
8
+ "Body Type": "Body Type",
9
+ "Body": "Body",
10
+ "Response is Binary ?": "La réponse est Binaire ?",
11
+ "No Error on Failure": "Aucune erreur en cas d'échec",
12
+ "Timeout (in seconds)": "Délai d'attente (en secondes)",
13
+ "Follow redirects": "Suivre les redirections",
14
+ "Authorization headers are injected automatically from your connection.": "Les Headers d'autorisation sont injectés automatiquement à partir de votre connexion.",
15
+ "Enable for files like PDFs, images, etc.": "Activer pour les fichiers comme les PDFs, les images, etc.",
16
+ "GET": "GET",
17
+ "POST": "POST",
18
+ "PATCH": "PATCH",
19
+ "PUT": "PUT",
20
+ "DELETE": "DELETE",
21
+ "HEAD": "HEAD",
22
+ "None": "Aucun",
23
+ "JSON": "JSON",
24
+ "Form Data": "Données du formulaire",
25
+ "Raw": "Brut",
26
+ "New Response": "Nouvelle réponse",
27
+ "Triggers when there is new response": "Se déclenche lorsqu'il y a une nouvelle réponse",
28
+ "Form": "Formulaire",
29
+ "Include Team Drive Forms": "Inclure les formulaires Team Drive",
30
+ "Determines if forms from Team Drives should be included in the results.": "Détermine si les formulaires de Team Drives doivent être inclus dans les résultats."
31
+ }
@@ -0,0 +1,24 @@
1
+ {
2
+ "Google Forms": "Google Forms",
3
+ "Receive form responses from Google Forms": "Receive form responses from Google Forms",
4
+ "Custom API Call": "Custom API Call",
5
+ "Make a custom API call to a specific endpoint": "Make a custom API call to a specific endpoint",
6
+ "Method": "Method",
7
+ "Headers": "Headers",
8
+ "Query Parameters": "Query Parameters",
9
+ "Body": "Body",
10
+ "No Error on Failure": "No Error on Failure",
11
+ "Timeout (in seconds)": "Timeout (in seconds)",
12
+ "Authorization headers are injected automatically from your connection.": "Authorization headers are injected automatically from your connection.",
13
+ "GET": "GET",
14
+ "POST": "POST",
15
+ "PATCH": "PATCH",
16
+ "PUT": "PUT",
17
+ "DELETE": "DELETE",
18
+ "HEAD": "HEAD",
19
+ "New Response": "New Response",
20
+ "Triggers when there is new response": "Triggers when there is new response",
21
+ "Form": "Form",
22
+ "Include Team Drive Forms": "Include Team Drive Forms",
23
+ "Determines if forms from Team Drives should be included in the results.": "Determines if forms from Team Drives should be included in the results."
24
+ }
@@ -0,0 +1,24 @@
1
+ {
2
+ "Google Forms": "Google Forms",
3
+ "Receive form responses from Google Forms": "Receive form responses from Google Forms",
4
+ "Custom API Call": "Custom API Call",
5
+ "Make a custom API call to a specific endpoint": "Make a custom API call to a specific endpoint",
6
+ "Method": "Method",
7
+ "Headers": "Headers",
8
+ "Query Parameters": "Query Parameters",
9
+ "Body": "Body",
10
+ "No Error on Failure": "No Error on Failure",
11
+ "Timeout (in seconds)": "Timeout (in seconds)",
12
+ "Authorization headers are injected automatically from your connection.": "Authorization headers are injected automatically from your connection.",
13
+ "GET": "GET",
14
+ "POST": "POST",
15
+ "PATCH": "PATCH",
16
+ "PUT": "PUT",
17
+ "DELETE": "DELETE",
18
+ "HEAD": "HEAD",
19
+ "New Response": "New Response",
20
+ "Triggers when there is new response": "Triggers when there is new response",
21
+ "Form": "Form",
22
+ "Include Team Drive Forms": "Include Team Drive Forms",
23
+ "Determines if forms from Team Drives should be included in the results.": "Determines if forms from Team Drives should be included in the results."
24
+ }
@@ -0,0 +1,31 @@
1
+ {
2
+ "Receive form responses from Google Forms": "Googleフォームからフォームの応答を受信する",
3
+ "Custom API Call": "カスタムAPI通話",
4
+ "Make a custom API call to a specific endpoint": "特定のエンドポイントへのカスタム API コールを実行します。",
5
+ "Method": "方法",
6
+ "Headers": "ヘッダー",
7
+ "Query Parameters": "クエリパラメータ",
8
+ "Body Type": "ボディタイプ",
9
+ "Body": "本文",
10
+ "Response is Binary ?": "応答はバイナリですか?",
11
+ "No Error on Failure": "失敗時にエラーはありません",
12
+ "Timeout (in seconds)": "タイムアウト(秒)",
13
+ "Follow redirects": "リダイレクトをフォローする",
14
+ "Authorization headers are injected automatically from your connection.": "認証ヘッダは接続から自動的に注入されます。",
15
+ "Enable for files like PDFs, images, etc.": "PDF、画像などのファイルを有効にする",
16
+ "GET": "取得",
17
+ "POST": "POST",
18
+ "PATCH": "PATCH",
19
+ "PUT": "PUT",
20
+ "DELETE": "削除",
21
+ "HEAD": "頭",
22
+ "None": "なし",
23
+ "JSON": "JSON",
24
+ "Form Data": "フォームデータ",
25
+ "Raw": "Raw",
26
+ "New Response": "新しい回答",
27
+ "Triggers when there is new response": "新しい応答があるときにトリガーします",
28
+ "Form": "フォーム",
29
+ "Include Team Drive Forms": "チームドライブフォームを含める",
30
+ "Determines if forms from Team Drives should be included in the results.": "チームドライブのフォームを結果に含めるかどうかを指定します。"
31
+ }
@@ -0,0 +1,31 @@
1
+ {
2
+ "Receive form responses from Google Forms": "Formulierantwoorden ontvangen van Google Formulieren",
3
+ "Custom API Call": "Custom API Call",
4
+ "Make a custom API call to a specific endpoint": "Maak een aangepaste API call naar een specifiek eindpunt",
5
+ "Method": "Methode",
6
+ "Headers": "Kopteksten",
7
+ "Query Parameters": "Query parameters",
8
+ "Body Type": "Type lichaam",
9
+ "Body": "Lichaam",
10
+ "Response is Binary ?": "Antwoord is binair?",
11
+ "No Error on Failure": "Geen fout bij fout",
12
+ "Timeout (in seconds)": "Time-out (in seconden)",
13
+ "Follow redirects": "Volg omleidingen",
14
+ "Authorization headers are injected automatically from your connection.": "Autorisatie headers worden automatisch geïnjecteerd vanuit uw verbinding.",
15
+ "Enable for files like PDFs, images, etc.": "Inschakelen voor bestanden zoals PDF's, afbeeldingen etc.",
16
+ "GET": "KRIJG",
17
+ "POST": "POSTE",
18
+ "PATCH": "BEKIJK",
19
+ "PUT": "PUT",
20
+ "DELETE": "VERWIJDEREN",
21
+ "HEAD": "HOOFD",
22
+ "None": "geen",
23
+ "JSON": "JSON",
24
+ "Form Data": "Formulieren gegevens",
25
+ "Raw": "Onbewerkte",
26
+ "New Response": "Nieuw Antwoord",
27
+ "Triggers when there is new response": "Triggert wanneer er een nieuwe reactie is",
28
+ "Form": "Vorm",
29
+ "Include Team Drive Forms": "Inclusief Team Drive formulieren",
30
+ "Determines if forms from Team Drives should be included in the results.": "Bepaalt of vormen van Team Drives moeten worden opgenomen in de resultaten."
31
+ }
@@ -0,0 +1,31 @@
1
+ {
2
+ "Receive form responses from Google Forms": "Receber respostas de formulários do Google Formulários",
3
+ "Custom API Call": "Chamada de API personalizada",
4
+ "Make a custom API call to a specific endpoint": "Faça uma chamada de API personalizada para um ponto de extremidade específico",
5
+ "Method": "Método",
6
+ "Headers": "Cabeçalhos",
7
+ "Query Parameters": "Parâmetros da consulta",
8
+ "Body Type": "Tipo de Corpo",
9
+ "Body": "Conteúdo",
10
+ "Response is Binary ?": "A resposta é binária ?",
11
+ "No Error on Failure": "Nenhum erro no Failure",
12
+ "Timeout (in seconds)": "Tempo limite (em segundos)",
13
+ "Follow redirects": "Seguir redirecionamentos",
14
+ "Authorization headers are injected automatically from your connection.": "Os cabeçalhos de autorização são inseridos automaticamente a partir da sua conexão.",
15
+ "Enable for files like PDFs, images, etc.": "Habilitar para arquivos como PDFs, imagens, etc.",
16
+ "GET": "OBTER",
17
+ "POST": "POSTAR",
18
+ "PATCH": "COMPRAR",
19
+ "PUT": "COLOCAR",
20
+ "DELETE": "EXCLUIR",
21
+ "HEAD": "CABEÇA",
22
+ "None": "Nenhuma",
23
+ "JSON": "JSON",
24
+ "Form Data": "Dados de Formulário",
25
+ "Raw": "RAW",
26
+ "New Response": "Nova Resposta",
27
+ "Triggers when there is new response": "Dispara quando há uma nova resposta",
28
+ "Form": "Formulário",
29
+ "Include Team Drive Forms": "Incluir Formulários de Drive do Time",
30
+ "Determines if forms from Team Drives should be included in the results.": "Determina se os formulários de unidades de equipe devem ser incluídos nos resultados."
31
+ }
@@ -0,0 +1,24 @@
1
+ {
2
+ "Google Forms": "Формы Google",
3
+ "Receive form responses from Google Forms": "Получать ответы в форме от Google Forms",
4
+ "Custom API Call": "Пользовательский вызов API",
5
+ "Make a custom API call to a specific endpoint": "Сделать пользовательский API вызов к определенной конечной точке",
6
+ "Method": "Метод",
7
+ "Headers": "Заголовки",
8
+ "Query Parameters": "Параметры запроса",
9
+ "Body": "Тело",
10
+ "No Error on Failure": "Нет ошибок при ошибке",
11
+ "Timeout (in seconds)": "Таймаут (в секундах)",
12
+ "Authorization headers are injected automatically from your connection.": "Заголовки авторизации включаются автоматически из вашего соединения.",
13
+ "GET": "ПОЛУЧИТЬ",
14
+ "POST": "ПОСТ",
15
+ "PATCH": "ПАТЧ",
16
+ "PUT": "ПОКУПИТЬ",
17
+ "DELETE": "УДАЛИТЬ",
18
+ "HEAD": "HEAD",
19
+ "New Response": "Новый ответ",
20
+ "Triggers when there is new response": "Триггеры при новом ответе",
21
+ "Form": "Форма",
22
+ "Include Team Drive Forms": "Включить Team Drive Формы",
23
+ "Determines if forms from Team Drives should be included in the results.": "Определяет, должны ли в результаты включаться формы из Team Drive."
24
+ }
@@ -0,0 +1,31 @@
1
+ {
2
+ "Receive form responses from Google Forms": "Receive form responses from Google Forms",
3
+ "Custom API Call": "Custom API Call",
4
+ "Make a custom API call to a specific endpoint": "Make a custom API call to a specific endpoint",
5
+ "Method": "Method",
6
+ "Headers": "Headers",
7
+ "Query Parameters": "Query Parameters",
8
+ "Body Type": "Body Type",
9
+ "Body": "Body",
10
+ "Response is Binary ?": "Response is Binary ?",
11
+ "No Error on Failure": "No Error on Failure",
12
+ "Timeout (in seconds)": "Timeout (in seconds)",
13
+ "Follow redirects": "Follow redirects",
14
+ "Authorization headers are injected automatically from your connection.": "Authorization headers are injected automatically from your connection.",
15
+ "Enable for files like PDFs, images, etc.": "Enable for files like PDFs, images, etc.",
16
+ "GET": "GET",
17
+ "POST": "POST",
18
+ "PATCH": "PATCH",
19
+ "PUT": "PUT",
20
+ "DELETE": "DELETE",
21
+ "HEAD": "HEAD",
22
+ "None": "None",
23
+ "JSON": "JSON",
24
+ "Form Data": "Form Data",
25
+ "Raw": "Raw",
26
+ "New Response": "New Response",
27
+ "Triggers when there is new response": "Triggers when there is new response",
28
+ "Form": "Form",
29
+ "Include Team Drive Forms": "Include Team Drive Forms",
30
+ "Determines if forms from Team Drives should be included in the results.": "Determines if forms from Team Drives should be included in the results."
31
+ }
@@ -0,0 +1,24 @@
1
+ {
2
+ "Google Forms": "Google Forms",
3
+ "Receive form responses from Google Forms": "Receive form responses from Google Forms",
4
+ "Custom API Call": "Custom API Call",
5
+ "Make a custom API call to a specific endpoint": "Make a custom API call to a specific endpoint",
6
+ "Method": "Method",
7
+ "Headers": "Headers",
8
+ "Query Parameters": "Query Parameters",
9
+ "Body": "Body",
10
+ "No Error on Failure": "No Error on Failure",
11
+ "Timeout (in seconds)": "Timeout (in seconds)",
12
+ "Authorization headers are injected automatically from your connection.": "Authorization headers are injected automatically from your connection.",
13
+ "GET": "GET",
14
+ "POST": "POST",
15
+ "PATCH": "PATCH",
16
+ "PUT": "PUT",
17
+ "DELETE": "DELETE",
18
+ "HEAD": "HEAD",
19
+ "New Response": "New Response",
20
+ "Triggers when there is new response": "Triggers when there is new response",
21
+ "Form": "Form",
22
+ "Include Team Drive Forms": "Include Team Drive Forms",
23
+ "Determines if forms from Team Drives should be included in the results.": "Determines if forms from Team Drives should be included in the results."
24
+ }
@@ -0,0 +1,31 @@
1
+ {
2
+ "Receive form responses from Google Forms": "Receive form responses from Google Forms",
3
+ "Custom API Call": "自定义 API 呼叫",
4
+ "Make a custom API call to a specific endpoint": "将一个自定义 API 调用到一个特定的终点",
5
+ "Method": "方法",
6
+ "Headers": "信头",
7
+ "Query Parameters": "查询参数",
8
+ "Body Type": "Body Type",
9
+ "Body": "正文内容",
10
+ "Response is Binary ?": "Response is Binary ?",
11
+ "No Error on Failure": "失败时没有错误",
12
+ "Timeout (in seconds)": "超时(秒)",
13
+ "Follow redirects": "Follow redirects",
14
+ "Authorization headers are injected automatically from your connection.": "授权头自动从您的连接中注入。",
15
+ "Enable for files like PDFs, images, etc.": "Enable for files like PDFs, images, etc.",
16
+ "GET": "获取",
17
+ "POST": "帖子",
18
+ "PATCH": "PATCH",
19
+ "PUT": "弹出",
20
+ "DELETE": "删除",
21
+ "HEAD": "黑色",
22
+ "None": "无",
23
+ "JSON": "JSON",
24
+ "Form Data": "表单数据",
25
+ "Raw": "原始文件",
26
+ "New Response": "New Response",
27
+ "Triggers when there is new response": "Triggers when there is new response",
28
+ "Form": "Form",
29
+ "Include Team Drive Forms": "Include Team Drive Forms",
30
+ "Determines if forms from Team Drives should be included in the results.": "Determines if forms from Team Drives should be included in the results."
31
+ }
package/src/index.ts ADDED
@@ -0,0 +1,30 @@
1
+ import { createCustomApiCallAction } from '@guayaba/workflows-common';
2
+ import {
3
+ createPiece,
4
+ } from '@guayaba/workflows-framework';
5
+ import { PieceCategory } from '@guayaba/workflows-shared';
6
+ import { newResponse } from './lib/triggers/new-form-response';
7
+ import { googleFormsAuth, getAccessToken } from './lib/common/common';
8
+
9
+ export { googleFormsAuth, getAccessToken, GoogleFormsAuthValue } from './lib/common/common';
10
+
11
+ export const googleForms = createPiece({
12
+ displayName: 'Google Forms',
13
+ description: 'Receive form responses from Google Forms',
14
+
15
+ minimumSupportedRelease: '0.30.0',
16
+ logoUrl: 'https://cdn.activepieces.com/pieces/google-forms.png',
17
+ categories: [PieceCategory.FORMS_AND_SURVEYS],
18
+ authors: ["kishanprmr","MoShizzle","khaledmashaly","abuaboud","Startouf"],
19
+ auth: googleFormsAuth,
20
+ actions: [
21
+ createCustomApiCallAction({
22
+ baseUrl: () => 'https://forms.googleapis.com/v1',
23
+ auth: googleFormsAuth,
24
+ authMapping: async (auth) => ({
25
+ Authorization: `Bearer ${await getAccessToken(auth as any)}`,
26
+ }),
27
+ }),
28
+ ],
29
+ triggers: [newResponse],
30
+ });
@@ -0,0 +1,136 @@
1
+ import { AppConnectionValueForAuthProperty, PieceAuth, Property } from '@guayaba/workflows-framework';
2
+ import {
3
+ httpClient,
4
+ HttpMethod,
5
+ AuthenticationType,
6
+ } from '@guayaba/workflows-common';
7
+ import { AppConnectionType } from '@guayaba/workflows-shared';
8
+ import { google } from 'googleapis';
9
+ import { OAuth2Client } from 'googleapis-common';
10
+
11
+ export const googleFormsScopes = [
12
+ 'https://www.googleapis.com/auth/forms.responses.readonly',
13
+ 'https://www.googleapis.com/auth/drive.readonly',
14
+ ];
15
+
16
+ export const googleFormsAuth = [PieceAuth.OAuth2({
17
+ description: '',
18
+ authUrl: 'https://accounts.google.com/o/oauth2/auth',
19
+ tokenUrl: 'https://oauth2.googleapis.com/token',
20
+ required: true,
21
+ scope: googleFormsScopes,
22
+ }), PieceAuth.CustomAuth({
23
+ displayName: 'Service Account (Advanced)',
24
+ description: 'Authenticate via service account from https://console.cloud.google.com/ > IAM & Admin > Service Accounts > Create Service Account > Keys > Add key. <br> <br> You can optionally use domain-wide delegation (https://support.google.com/a/answer/162106?hl=en#zippy=%2Cset-up-domain-wide-delegation-for-a-client) to access forms without adding the service account to each one. <br> <br> **Note:** Without a user email, the service account only has access to files/folders you explicitly share with it.',
25
+ required: true,
26
+ props: {
27
+ serviceAccount: Property.ShortText({
28
+ displayName: 'Service Account JSON Key',
29
+ required: true,
30
+ }),
31
+ userEmail: Property.ShortText({
32
+ displayName: 'User Email',
33
+ required: false,
34
+ description: 'Email address of the user to impersonate for domain-wide delegation.',
35
+ }),
36
+ },
37
+ validate: async ({ auth }) => {
38
+ try {
39
+ await getAccessToken({
40
+ type: AppConnectionType.CUSTOM_AUTH,
41
+ props: { ...auth },
42
+ });
43
+ } catch (e) {
44
+ return {
45
+ valid: false,
46
+ error: (e as Error).message,
47
+ };
48
+ }
49
+ return {
50
+ valid: true,
51
+ };
52
+ },
53
+ })];
54
+
55
+ export type GoogleFormsAuthValue = AppConnectionValueForAuthProperty<typeof googleFormsAuth>;
56
+
57
+ export async function createGoogleClient(auth: GoogleFormsAuthValue): Promise<OAuth2Client> {
58
+ if (auth.type === AppConnectionType.CUSTOM_AUTH) {
59
+ const serviceAccount = JSON.parse(auth.props.serviceAccount);
60
+ return new google.auth.JWT({
61
+ email: serviceAccount.client_email,
62
+ key: serviceAccount.private_key,
63
+ scopes: googleFormsScopes,
64
+ subject: auth.props.userEmail,
65
+ });
66
+ }
67
+ const authClient = new OAuth2Client();
68
+ authClient.setCredentials(auth);
69
+ return authClient;
70
+ }
71
+
72
+ export const getAccessToken = async (auth: GoogleFormsAuthValue): Promise<string> => {
73
+ if (auth.type === AppConnectionType.CUSTOM_AUTH) {
74
+ const googleClient = await createGoogleClient(auth);
75
+ const response = await googleClient.getAccessToken();
76
+ if (response.token) {
77
+ return response.token;
78
+ } else {
79
+ throw new Error('Could not retrieve access token from service account json');
80
+ }
81
+ }
82
+ return auth.access_token;
83
+ };
84
+
85
+ export const googleFormsCommon = {
86
+ include_team_drives: Property.Checkbox({
87
+ displayName: 'Include Team Drive Forms',
88
+ description:
89
+ 'Determines if forms from Team Drives should be included in the results.',
90
+ defaultValue: false,
91
+ required: false,
92
+ }),
93
+ form_id: Property.Dropdown({
94
+ displayName: 'Form',
95
+ required: true,
96
+ auth: googleFormsAuth,
97
+ refreshers: ['include_team_drives'],
98
+ options: async ({ auth, include_team_drives }) => {
99
+ if (!auth) {
100
+ return {
101
+ disabled: true,
102
+ options: [],
103
+ placeholder: 'Please authenticate first',
104
+ };
105
+ }
106
+ const authValue = auth as GoogleFormsAuthValue;
107
+ const accessToken = await getAccessToken(authValue);
108
+ const files = (
109
+ await httpClient.sendRequest<{ files: { id: string; name: string }[] }>(
110
+ {
111
+ method: HttpMethod.GET,
112
+ url: `https://www.googleapis.com/drive/v3/files`,
113
+ queryParams: {
114
+ q: "mimeType='application/vnd.google-apps.form'",
115
+ includeItemsFromAllDrives: include_team_drives ? 'true' : 'false',
116
+ supportsAllDrives: 'true',
117
+ },
118
+ authentication: {
119
+ type: AuthenticationType.BEARER_TOKEN,
120
+ token: accessToken,
121
+ },
122
+ }
123
+ )
124
+ ).body.files;
125
+ return {
126
+ disabled: false,
127
+ options: files.map((file: { id: string; name: string }) => {
128
+ return {
129
+ label: file.name,
130
+ value: file.id,
131
+ };
132
+ }),
133
+ };
134
+ },
135
+ }),
136
+ };
@@ -0,0 +1,136 @@
1
+ import {
2
+ DedupeStrategy,
3
+ httpClient,
4
+ HttpMethod,
5
+ Polling,
6
+ pollingHelper,
7
+ } from '@guayaba/workflows-common';
8
+ import {
9
+ AppConnectionValueForAuthProperty,
10
+ createTrigger,
11
+ TriggerStrategy,
12
+ } from '@guayaba/workflows-framework';
13
+ import dayjs from 'dayjs';
14
+ import { googleFormsCommon, googleFormsAuth, getAccessToken, GoogleFormsAuthValue } from '../common/common';
15
+
16
+ export const newResponse = createTrigger({
17
+ auth: googleFormsAuth,
18
+ name: 'new_response',
19
+ displayName: 'New Response',
20
+ description: 'Triggers when there is new response',
21
+ props: {
22
+ form_id: googleFormsCommon.form_id,
23
+ include_team_drives: googleFormsCommon.include_team_drives,
24
+ },
25
+ sampleData: {
26
+ responseId:
27
+ 'ACYDBNhZI4SENjOwT4QIcXOhgco3JhuLftjpLspxETYljVZofOWuqH7bxKQqJWDwGw2IFqE',
28
+ createTime: '2023-04-01T03:19:28.889Z',
29
+ lastSubmittedTime: '2023-04-01T03:19:28.889881Z',
30
+ answers: {
31
+ '5bdc4001': {
32
+ questionId: '5bdc4001',
33
+ textAnswers: {
34
+ answers: [
35
+ {
36
+ value: 'test',
37
+ },
38
+ ],
39
+ },
40
+ },
41
+ '283d759e': {
42
+ questionId: '283d759e',
43
+ textAnswers: {
44
+ answers: [
45
+ {
46
+ value: 'نعم',
47
+ },
48
+ ],
49
+ },
50
+ },
51
+ '46f3e9cf': {
52
+ questionId: '46f3e9cf',
53
+ textAnswers: {
54
+ answers: [
55
+ {
56
+ value: 'test',
57
+ },
58
+ ],
59
+ },
60
+ },
61
+ },
62
+ },
63
+ type: TriggerStrategy.POLLING,
64
+ async test(ctx) {
65
+ return await pollingHelper.test(polling, ctx);
66
+ },
67
+ async onEnable(ctx) {
68
+ await pollingHelper.onEnable(polling, {
69
+ auth: ctx.auth,
70
+ store: ctx.store,
71
+ propsValue: ctx.propsValue,
72
+ });
73
+ },
74
+ async onDisable(ctx) {
75
+ await pollingHelper.onDisable(polling, {
76
+ auth: ctx.auth,
77
+ store: ctx.store,
78
+ propsValue: ctx.propsValue,
79
+ });
80
+ },
81
+ async run(ctx) {
82
+ return await pollingHelper.poll(polling, ctx);
83
+ },
84
+ });
85
+
86
+ const polling: Polling<AppConnectionValueForAuthProperty<typeof googleFormsAuth>, { form_id: string }> = {
87
+ strategy: DedupeStrategy.TIMEBASED,
88
+ items: async ({ auth, propsValue, lastFetchEpochMS }) => {
89
+ const items = await getResponse(
90
+ auth,
91
+ propsValue.form_id,
92
+ lastFetchEpochMS === 0 ? null : dayjs(lastFetchEpochMS).toISOString()
93
+ );
94
+
95
+ return items
96
+ .sort(
97
+ (a, b) =>
98
+ new Date(b.lastSubmittedTime).getTime() -
99
+ new Date(a.lastSubmittedTime).getTime()
100
+ )
101
+ .map((item) => ({
102
+ epochMilliSeconds: dayjs(item.lastSubmittedTime).valueOf(),
103
+ data: item,
104
+ }));
105
+ },
106
+ };
107
+
108
+ const getResponse = async (
109
+ authentication: GoogleFormsAuthValue,
110
+ form_id: string,
111
+ startDate: string | null
112
+ ) => {
113
+ let filter = {};
114
+ if (startDate) {
115
+ filter = {
116
+ filter: 'timestamp > ' + startDate,
117
+ };
118
+ }
119
+ const accessToken = await getAccessToken(authentication);
120
+ const response = await httpClient.sendRequest<{
121
+ responses: { lastSubmittedTime: string }[];
122
+ }>({
123
+ url: `https://forms.googleapis.com/v1/forms/${form_id}/responses`,
124
+ method: HttpMethod.GET,
125
+ headers: {
126
+ Authorization: `Bearer ${accessToken}`,
127
+ },
128
+ queryParams: filter,
129
+ });
130
+
131
+ const formResponses = response.body.responses;
132
+ if (formResponses && Array.isArray(formResponses)) {
133
+ return formResponses;
134
+ }
135
+ return [];
136
+ };
package/tsconfig.json ADDED
@@ -0,0 +1,16 @@
1
+ {
2
+ "extends": "../../../../tsconfig.base.json",
3
+ "files": [],
4
+ "include": [],
5
+ "references": [
6
+ {
7
+ "path": "./tsconfig.lib.json"
8
+ }
9
+ ],
10
+ "compilerOptions": {
11
+ "forceConsistentCasingInFileNames": true,
12
+ "strict": true,
13
+ "noImplicitReturns": true,
14
+ "noFallthroughCasesInSwitch": true
15
+ }
16
+ }
@@ -0,0 +1,15 @@
1
+ {
2
+ "extends": "./tsconfig.json",
3
+ "compilerOptions": {
4
+ "module": "commonjs",
5
+ "rootDir": ".",
6
+ "baseUrl": ".",
7
+ "paths": {},
8
+ "outDir": "./dist",
9
+ "declaration": true,
10
+ "declarationMap": true,
11
+ "types": ["node"]
12
+ },
13
+ "exclude": ["jest.config.ts", "src/**/*.spec.ts", "src/**/*.test.ts"],
14
+ "include": ["src/**/*.ts"]
15
+ }