Compare commits

..

1 Commits

Author SHA1 Message Date
kasia.oczkowska
96c3c19a50 feat: introduce paths 2024-06-26 15:45:26 +01:00
800 changed files with 6027 additions and 21414 deletions

View File

@@ -71,6 +71,9 @@ jobs:
- name: Migrate database
working-directory: ./packages/backend
run: yarn db:migrate
- name: Seed user
working-directory: ./packages/backend
run: yarn db:seed:user &
- name: Install certutils
run: sudo apt install -y libnss3-tools
- name: Install mkcert

View File

@@ -1,10 +1,10 @@
# syntax=docker/dockerfile:1
FROM node:18-alpine
ENV PORT=3000
ENV PORT 3000
RUN \
apk --no-cache add --virtual build-dependencies python3 build-base git make g++
apk --no-cache add --virtual build-dependencies python3 build-base git
WORKDIR /automatisch

View File

@@ -10,7 +10,7 @@ import process from 'process';
async function fetchAdminRole() {
const role = await Role.query()
.where({
name: 'Admin',
key: 'admin',
})
.limit(1)
.first();

View File

@@ -1,6 +1,6 @@
import { knexSnakeCaseMappers } from 'objection';
import appConfig from './src/config/app.js';
import path, { join } from 'path';
import path from 'path';
import { fileURLToPath } from 'url';
const fileExtension = 'js';
@@ -20,12 +20,12 @@ const knexConfig = {
searchPath: [appConfig.postgresSchema],
pool: { min: 0, max: 20 },
migrations: {
directory: join(__dirname, '/src/db/migrations'),
directory: __dirname + '/src/db/migrations',
extension: fileExtension,
loadExtensions: [`.${fileExtension}`],
},
seeds: {
directory: join(__dirname, '/src/db/seeds'),
directory: __dirname + '/src/db/seeds',
},
...(appConfig.isTest ? knexSnakeCaseMappers() : {}),
};

View File

@@ -5,13 +5,12 @@
"description": "The open source Zapier alternative. Build workflow automation without spending time and money.",
"type": "module",
"scripts": {
"dev": "nodemon --exec node src/server.js",
"worker": "nodemon --exec node src/worker.js",
"dev": "nodemon --watch 'src/**/*.js' --exec 'node' src/server.js",
"worker": "nodemon --watch 'src/**/*.js' --exec 'node' src/worker.js",
"start": "node src/server.js",
"start:worker": "node src/worker.js",
"pretest": "APP_ENV=test node ./test/setup/prepare-test-env.js",
"test": "APP_ENV=test vitest run",
"test:watch": "APP_ENV=test vitest watch",
"lint": "eslint .",
"db:create": "node ./bin/database/create.js",
"db:seed:user": "node ./bin/database/seed-user.js",
@@ -23,6 +22,8 @@
"dependencies": {
"@bull-board/express": "^3.10.1",
"@casl/ability": "^6.5.0",
"@graphql-tools/graphql-file-loader": "^7.3.4",
"@graphql-tools/load": "^7.5.2",
"@node-saml/passport-saml": "^4.0.4",
"@rudderstack/rudder-sdk-node": "^1.1.2",
"@sentry/node": "^7.42.0",
@@ -37,14 +38,17 @@
"debug": "~2.6.9",
"dotenv": "^10.0.0",
"express": "~4.18.2",
"express-async-errors": "^3.1.1",
"express-async-handler": "^1.2.0",
"express-basic-auth": "^1.2.1",
"express-graphql": "^0.12.0",
"fast-xml-parser": "^4.0.11",
"graphql-middleware": "^6.1.15",
"graphql-shield": "^7.5.0",
"graphql-tools": "^8.2.0",
"handlebars": "^4.7.7",
"http-errors": "~1.6.3",
"http-proxy-agent": "^7.0.0",
"https-proxy-agent": "^7.0.1",
"isolated-vm": "^5.0.1",
"jsonwebtoken": "^9.0.0",
"knex": "^2.4.0",
"libphonenumber-js": "^1.10.48",
@@ -99,11 +103,5 @@
},
"publishConfig": {
"access": "public"
},
"nodemonConfig": {
"watch": [
"src/"
],
"ext": "js"
}
}

View File

@@ -1,6 +1,5 @@
import createError from 'http-errors';
import express from 'express';
import 'express-async-errors';
import cors from 'cors';
import appConfig from './config/app.js';

View File

@@ -12,7 +12,7 @@ export default defineApp({
apiBaseUrl: 'https://api.airtable.com',
iconUrl: '{BASE_URL}/apps/airtable/assets/favicon.svg',
authDocUrl: '{DOCS_URL}/apps/airtable/connection',
primaryColor: '#FFBF00',
primaryColor: 'FFBF00',
supportsConnections: true,
beforeRequest: [addAuthHeader],
auth,

View File

@@ -12,7 +12,7 @@ export default defineApp({
apiBaseUrl: 'https://cloud.appwrite.io',
iconUrl: '{BASE_URL}/apps/appwrite/assets/favicon.svg',
authDocUrl: '{DOCS_URL}/apps/appwrite/connection',
primaryColor: '#FD366E',
primaryColor: 'FD366E',
supportsConnections: true,
beforeRequest: [setBaseUrl, addAuthHeader],
auth,

View File

@@ -12,7 +12,7 @@ export default defineApp({
apiBaseUrl: '',
iconUrl: '{BASE_URL}/apps/azure-openai/assets/favicon.svg',
authDocUrl: '{DOCS_URL}/apps/azure-openai/connection',
primaryColor: '#000000',
primaryColor: '000000',
supportsConnections: true,
beforeRequest: [setBaseUrl, addAuthHeader],
auth,

View File

@@ -7,7 +7,7 @@ export default defineAction({
'Creates an attachment of a specified object by given parent ID.',
arguments: [
{
label: 'Template Data',
label: 'Templete Data',
key: 'templateData',
type: 'string',
required: true,

View File

@@ -11,7 +11,7 @@ export default defineApp({
supportsConnections: true,
baseUrl: 'https://carbone.io',
apiBaseUrl: 'https://api.carbone.io',
primaryColor: '#6f42c1',
primaryColor: '6f42c1',
beforeRequest: [addAuthHeader],
auth,
actions,

View File

@@ -1,72 +0,0 @@
import defineAction from '../../../../helpers/define-action.js';
export default defineAction({
name: 'Create folder',
key: 'createFolder',
description: 'Creates a new folder.',
arguments: [
{
label: 'Workspace',
key: 'workspaceId',
type: 'dropdown',
required: true,
description: '',
variables: true,
source: {
type: 'query',
name: 'getDynamicData',
arguments: [
{
name: 'key',
value: 'listWorkspaces',
},
],
},
},
{
label: 'Space',
key: 'spaceId',
type: 'dropdown',
required: true,
dependsOn: ['parameters.workspaceId'],
description: '',
variables: true,
source: {
type: 'query',
name: 'getDynamicData',
arguments: [
{
name: 'key',
value: 'listSpaces',
},
{
name: 'parameters.workspaceId',
value: '{parameters.workspaceId}',
},
],
},
},
{
label: 'Folder Name',
key: 'folderName',
type: 'string',
required: true,
description: '',
variables: true,
},
],
async run($) {
const { spaceId, folderName } = $.step.parameters;
const body = {
name: folderName,
};
const { data } = await $.http.post(`/v2/space/${spaceId}/folder`, body);
$.setActionItem({
raw: data,
});
},
});

View File

@@ -1,135 +0,0 @@
import defineAction from '../../../../helpers/define-action.js';
export default defineAction({
name: 'Create list',
key: 'createList',
description: 'Creates a new list.',
arguments: [
{
label: 'Workspace',
key: 'workspaceId',
type: 'dropdown',
required: true,
description: '',
variables: true,
source: {
type: 'query',
name: 'getDynamicData',
arguments: [
{
name: 'key',
value: 'listWorkspaces',
},
],
},
},
{
label: 'Space',
key: 'spaceId',
type: 'dropdown',
required: true,
dependsOn: ['parameters.workspaceId'],
description: '',
variables: true,
source: {
type: 'query',
name: 'getDynamicData',
arguments: [
{
name: 'key',
value: 'listSpaces',
},
{
name: 'parameters.workspaceId',
value: '{parameters.workspaceId}',
},
],
},
},
{
label: 'Folder',
key: 'folderId',
type: 'dropdown',
required: true,
dependsOn: ['parameters.spaceId'],
description: '',
variables: true,
source: {
type: 'query',
name: 'getDynamicData',
arguments: [
{
name: 'key',
value: 'listFolders',
},
{
name: 'parameters.spaceId',
value: '{parameters.spaceId}',
},
],
},
},
{
label: 'List Name',
key: 'listName',
type: 'string',
required: true,
description: '',
variables: true,
},
{
label: 'List Info',
key: 'listInfo',
type: 'string',
required: false,
description: '',
variables: true,
},
{
label: 'Priority',
key: 'priority',
type: 'dropdown',
required: false,
description: '',
variables: true,
options: [
{ label: 'Urgent', value: 1 },
{ label: 'High', value: 2 },
{ label: 'Normal', value: 3 },
{ label: 'Low', value: 4 },
],
},
{
label: 'Due Date',
key: 'dueDate',
type: 'string',
required: false,
description: 'format: integer <int64>',
variables: true,
},
],
async run($) {
const { folderId, listName, listInfo, priority, dueDate } =
$.step.parameters;
const body = {
name: listName,
content: listInfo,
};
if (priority) {
body.priority = priority;
}
if (dueDate) {
body.due_date = dueDate;
}
const { data } = await $.http.post(`/v2/folder/${folderId}/list`, body);
$.setActionItem({
raw: data,
});
},
});

View File

@@ -1,294 +0,0 @@
import defineAction from '../../../../helpers/define-action.js';
export default defineAction({
name: 'Create task',
key: 'createTask',
description: 'Creates a new task.',
arguments: [
{
label: 'Workspace',
key: 'workspaceId',
type: 'dropdown',
required: true,
description: '',
variables: true,
source: {
type: 'query',
name: 'getDynamicData',
arguments: [
{
name: 'key',
value: 'listWorkspaces',
},
],
},
},
{
label: 'Space',
key: 'spaceId',
type: 'dropdown',
required: true,
dependsOn: ['parameters.workspaceId'],
description: '',
variables: true,
source: {
type: 'query',
name: 'getDynamicData',
arguments: [
{
name: 'key',
value: 'listSpaces',
},
{
name: 'parameters.workspaceId',
value: '{parameters.workspaceId}',
},
],
},
},
{
label: 'Folder',
key: 'folderId',
type: 'dropdown',
required: true,
dependsOn: ['parameters.spaceId'],
description: '',
variables: true,
source: {
type: 'query',
name: 'getDynamicData',
arguments: [
{
name: 'key',
value: 'listFolders',
},
{
name: 'parameters.spaceId',
value: '{parameters.spaceId}',
},
],
},
},
{
label: 'List',
key: 'listId',
type: 'dropdown',
required: true,
dependsOn: ['parameters.folderId'],
description: '',
variables: true,
source: {
type: 'query',
name: 'getDynamicData',
arguments: [
{
name: 'key',
value: 'listLists',
},
{
name: 'parameters.folderId',
value: '{parameters.folderId}',
},
],
},
},
{
label: 'Task Name',
key: 'taskName',
type: 'string',
required: true,
description: '',
variables: true,
},
{
label: 'Task Description',
key: 'taskDescription',
type: 'string',
required: false,
description: '',
variables: true,
},
{
label: 'Markdown Content',
key: 'markdownContent',
type: 'dropdown',
required: false,
description: '',
variables: true,
options: [
{ label: 'False', value: 'false' },
{ label: 'True', value: 'true' },
],
},
{
label: 'Assignees',
key: 'assigneeIds',
type: 'dynamic',
required: false,
description: '',
fields: [
{
label: 'Assignee',
key: 'assigneeId',
type: 'dropdown',
required: false,
dependsOn: ['parameters.listId'],
variables: true,
source: {
type: 'query',
name: 'getDynamicData',
arguments: [
{
name: 'key',
value: 'listAssignees',
},
{
name: 'parameters.listId',
value: '{parameters.listId}',
},
],
},
},
],
},
{
label: 'Task Status',
key: 'taskStatus',
type: 'dropdown',
required: false,
dependsOn: ['parameters.listId'],
description: '',
variables: true,
source: {
type: 'query',
name: 'getDynamicData',
arguments: [
{
name: 'key',
value: 'listStatuses',
},
{
name: 'parameters.listId',
value: '{parameters.listId}',
},
],
},
},
{
label: 'Tags',
key: 'tagIds',
type: 'dynamic',
required: false,
description: '',
fields: [
{
label: 'tag',
key: 'tagId',
type: 'dropdown',
required: false,
variables: true,
source: {
type: 'query',
name: 'getDynamicData',
arguments: [
{
name: 'key',
value: 'listTags',
},
],
},
},
],
},
{
label: 'Priority',
key: 'priority',
type: 'dropdown',
required: false,
description: '',
variables: true,
options: [
{ label: 'Urgent', value: 1 },
{ label: 'High', value: 2 },
{ label: 'Normal', value: 3 },
{ label: 'Low', value: 4 },
],
},
{
label: 'Due Date',
key: 'dueDate',
type: 'string',
required: false,
description: 'format: integer <int64>',
variables: true,
},
{
label: 'Start Date',
key: 'startDate',
type: 'string',
required: false,
description: 'format: integer <int64>',
variables: true,
},
],
async run($) {
const {
listId,
taskName,
taskDescription,
markdownContent,
assigneeIds,
taskStatus,
tagIds,
priority,
dueDate,
startDate,
} = $.step.parameters;
const tags = tagIds.map((tag) => tag.tagId);
const assignees = assigneeIds.map((assignee) =>
Number(assignee.assigneeId)
);
const body = {
name: taskName,
};
if (assignees.length) {
body.assignees = assignees;
}
if (taskStatus) {
body.status = taskStatus;
}
if (tags.length) {
body.tags = tags;
}
if (priority) {
body.priority = priority;
}
if (dueDate) {
body.due_date = dueDate;
}
if (startDate) {
body.start_date = startDate;
}
if (markdownContent) {
body.markdown_description = taskDescription;
} else {
body.description = taskDescription;
}
const { data } = await $.http.post(`/v2/list/${listId}/task`, body);
$.setActionItem({
raw: data,
});
},
});

View File

@@ -1,82 +0,0 @@
import defineAction from '../../../../helpers/define-action.js';
export default defineAction({
name: 'Find task by id',
key: 'findTaskById',
description: 'Finds a task using id.',
arguments: [
{
label: 'Task ID',
key: 'taskId',
type: 'string',
required: true,
description: '',
variables: true,
},
{
label: 'Use Custom ID',
key: 'useCustomId',
type: 'dropdown',
required: false,
description: '',
variables: true,
options: [
{
label: 'True',
value: true,
},
{
label: 'False',
value: false,
},
],
additionalFields: {
type: 'query',
name: 'getDynamicFields',
arguments: [
{
name: 'key',
value: 'listFieldsWhenUsingCustomId',
},
{
name: 'parameters.useCustomId',
value: '{parameters.useCustomId}',
},
],
},
},
{
label: 'Include Subtasks?',
key: 'includeSubtasks',
type: 'dropdown',
required: false,
description: '',
variables: true,
options: [
{
label: 'True',
value: true,
},
{
label: 'False',
value: false,
},
],
},
],
async run($) {
const { taskId, useCustomId, includeSubtasks } = $.step.parameters;
const params = {
custom_task_ids: useCustomId || false,
include_subtasks: includeSubtasks,
};
const { data } = await $.http.get(`/v2/task/${taskId}`, { params });
$.setActionItem({
raw: data,
});
},
});

View File

@@ -1,6 +0,0 @@
import createFolder from './create-folder/index.js';
import createList from './create-list/index.js';
import createTask from './create-task/index.js';
import findTaskById from './find-task-by-id/index.js';
export default [createFolder, createList, createTask, findTaskById];

View File

@@ -1,27 +0,0 @@
<svg width="185" height="185" viewBox="0 0 185 185" fill="none" xmlns="http://www.w3.org/2000/svg">
<g filter="url(#filter0_d)">
<rect x="30" y="20" width="125" height="125" rx="62.5" fill="white"/>
<rect x="30" y="20" width="125" height="125" rx="62.5" fill="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M55.8789 105.714L69.3974 95.3593C76.5762 104.732 84.1998 109.051 92.6948 109.051C101.143 109.051 108.557 104.781 115.414 95.4832L129.119 105.59C119.232 118.996 106.932 126.079 92.6948 126.079C78.5049 126.079 66.0907 119.046 55.8789 105.714Z" fill="url(#paint0_linear)"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M92.6491 60.7078L68.5883 81.4406L57.4727 68.5407L92.6969 38.1885L127.647 68.5644L116.477 81.417L92.6491 60.7078Z" fill="url(#paint1_linear)"/>
</g>
<defs>
<filter id="filter0_d" x="0" y="0" width="185" height="185" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
<feOffset dy="10"/>
<feGaussianBlur stdDeviation="15"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.0627451 0 0 0 0 0.117647 0 0 0 0 0.211765 0 0 0 0.1 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow" result="shape"/>
</filter>
<linearGradient id="paint0_linear" x1="55.8789" y1="116.251" x2="129.119" y2="116.251" gradientUnits="userSpaceOnUse">
<stop stop-color="#8930FD"/>
<stop offset="1" stop-color="#49CCF9"/>
</linearGradient>
<linearGradient id="paint1_linear" x1="57.4727" y1="67.6025" x2="127.647" y2="67.6025" gradientUnits="userSpaceOnUse">
<stop stop-color="#FF02F0"/>
<stop offset="1" stop-color="#FFC800"/>
</linearGradient>
</defs>
</svg>

Before

Width:  |  Height:  |  Size: 1.8 KiB

View File

@@ -1,21 +0,0 @@
import { URLSearchParams } from 'url';
export default async function generateAuthUrl($) {
const oauthRedirectUrlField = $.app.auth.fields.find(
(field) => field.key == 'oAuthRedirectUrl'
);
const redirectUri = oauthRedirectUrlField.value;
const state = Math.random().toString();
const searchParams = new URLSearchParams({
client_id: $.auth.data.clientId,
redirect_uri: redirectUri,
state,
});
const url = `https://app.clickup.com/api?${searchParams.toString()}`;
await $.auth.set({
url,
originalState: state,
});
}

View File

@@ -1,46 +0,0 @@
import generateAuthUrl from './generate-auth-url.js';
import verifyCredentials from './verify-credentials.js';
import isStillVerified from './is-still-verified.js';
export default {
fields: [
{
key: 'oAuthRedirectUrl',
label: 'OAuth Redirect URL',
type: 'string',
required: true,
readOnly: true,
value: '{WEB_APP_URL}/app/clickup/connections/add',
placeholder: null,
description:
'When asked to input a redirect URL in ClickUp, enter the URL above.',
clickToCopy: true,
},
{
key: 'clientId',
label: 'Client ID',
type: 'string',
required: true,
readOnly: false,
value: null,
placeholder: null,
description: null,
clickToCopy: false,
},
{
key: 'clientSecret',
label: 'Client Secret',
type: 'string',
required: true,
readOnly: false,
value: null,
placeholder: null,
description: null,
clickToCopy: false,
},
],
generateAuthUrl,
verifyCredentials,
isStillVerified,
};

View File

@@ -1,8 +0,0 @@
import getCurrentUser from '../common/get-current-user.js';
const isStillVerified = async ($) => {
const currentUser = await getCurrentUser($);
return !!currentUser.id;
};
export default isStillVerified;

View File

@@ -1,31 +0,0 @@
import getCurrentUser from '../common/get-current-user.js';
const verifyCredentials = async ($) => {
if ($.auth.data.originalState !== $.auth.data.state) {
throw new Error(`The 'state' parameter does not match.`);
}
const { data } = await $.http.post('/v2/oauth/token', {
client_id: $.auth.data.clientId,
client_secret: $.auth.data.clientSecret,
code: $.auth.data.code,
});
await $.auth.set({
accessToken: data.access_token,
tokenType: data.token_type,
});
const currentUser = await getCurrentUser($);
const screenName = [currentUser.username, currentUser.email]
.filter(Boolean)
.join(' @ ');
await $.auth.set({
clientId: $.auth.data.clientId,
clientSecret: $.auth.data.clientSecret,
screenName,
});
};
export default verifyCredentials;

View File

@@ -1,9 +0,0 @@
const addAuthHeader = ($, requestConfig) => {
if ($.auth.data?.accessToken) {
requestConfig.headers.Authorization = `${$.auth.data.tokenType} ${$.auth.data.accessToken}`;
}
return requestConfig;
};
export default addAuthHeader;

View File

@@ -1,6 +0,0 @@
const getCurrentUser = async ($) => {
const { data } = await $.http.get('/v2/user');
return data.user;
};
export default getCurrentUser;

View File

@@ -1,19 +0,0 @@
import listAssignees from './list-assignees/index.js';
import listFolders from './list-folders/index.js';
import listLists from './list-lists/index.js';
import listSpaces from './list-spaces/index.js';
import listStatuses from './list-statuses/index.js';
import listTags from './list-tags/index.js';
import listTasks from './list-tasks/index.js';
import listWorkspaces from './list-workspaces/index.js';
export default [
listAssignees,
listFolders,
listLists,
listSpaces,
listStatuses,
listTags,
listTasks,
listWorkspaces,
];

View File

@@ -1,28 +0,0 @@
export default {
name: 'List assignees',
key: 'listAssignees',
async run($) {
const assignees = {
data: [],
};
const listId = $.step.parameters.listId;
if (!listId) {
return assignees;
}
const { data } = await $.http.get(`/v2/list/${listId}/member`);
if (data.members) {
for (const member of data.members) {
assignees.data.push({
value: member.id,
name: member.username,
});
}
}
return assignees;
},
};

View File

@@ -1,28 +0,0 @@
export default {
name: 'List folders',
key: 'listFolders',
async run($) {
const folders = {
data: [],
};
const spaceId = $.step.parameters.spaceId;
if (!spaceId) {
return folders;
}
const { data } = await $.http.get(`/v2/space/${spaceId}/folder`);
if (data.folders) {
for (const folder of data.folders) {
folders.data.push({
value: folder.id,
name: folder.name,
});
}
}
return folders;
},
};

View File

@@ -1,28 +0,0 @@
export default {
name: 'List lists',
key: 'listLists',
async run($) {
const lists = {
data: [],
};
const folderId = $.step.parameters.folderId;
if (!folderId) {
return lists;
}
const { data } = await $.http.get(`/v2/folder/${folderId}/list`);
if (data.lists) {
for (const list of data.lists) {
lists.data.push({
value: list.id,
name: list.name,
});
}
}
return lists;
},
};

View File

@@ -1,28 +0,0 @@
export default {
name: 'List spaces',
key: 'listSpaces',
async run($) {
const spaces = {
data: [],
};
const workspaceId = $.step.parameters.workspaceId;
if (!workspaceId) {
return spaces;
}
const { data } = await $.http.get(`/v2/team/${workspaceId}/space`);
if (data.spaces) {
for (const space of data.spaces) {
spaces.data.push({
value: space.id,
name: space.name,
});
}
}
return spaces;
},
};

View File

@@ -1,28 +0,0 @@
export default {
name: 'List statuses',
key: 'listStatuses',
async run($) {
const statuses = {
data: [],
};
const listId = $.step.parameters.listId;
if (!listId) {
return statuses;
}
const { data } = await $.http.get(`/v2/list/${listId}`);
if (data.statuses) {
for (const status of data.statuses) {
statuses.data.push({
value: status.status,
name: status.status,
});
}
}
return statuses;
},
};

View File

@@ -1,28 +0,0 @@
export default {
name: 'List tags',
key: 'listTags',
async run($) {
const tags = {
data: [],
};
const spaceId = $.step.parameters.spaceId;
if (!spaceId) {
return spaceId;
}
const { data } = await $.http.get(`v2/space/${spaceId}/tag`);
if (data.tags) {
for (const tag of data.tags) {
tags.data.push({
value: tag.name,
name: tag.name,
});
}
}
return tags;
},
};

View File

@@ -1,41 +0,0 @@
export default {
name: 'List tasks',
key: 'listTasks',
async run($) {
const tasks = {
data: [],
};
const listId = $.step.parameters.listId;
let next = false;
if (!listId) {
return tasks;
}
const params = {
order_by: 'created',
reverse: true,
};
do {
const { data } = await $.http.get(`/v2/list/${listId}/task`, { params });
if (data.last_page) {
next = false;
} else {
next = true;
}
if (data.tasks) {
for (const task of data.tasks) {
tasks.data.push({
value: task.id,
name: task.name,
});
}
}
} while (next);
return tasks;
},
};

View File

@@ -1,23 +0,0 @@
export default {
name: 'List workspaces',
key: 'listWorkspaces',
async run($) {
const workspaces = {
data: [],
};
const { data } = await $.http.get('/v2/team');
if (data.teams) {
for (const workspace of data.teams) {
workspaces.data.push({
value: workspace.id,
name: workspace.name,
});
}
}
return workspaces;
},
};

View File

@@ -1,3 +0,0 @@
import useCustomId from './use-custom-id/index.js';
export default [useCustomId];

View File

@@ -1,29 +0,0 @@
export default {
name: 'List workspaces when using custom id',
key: 'listFieldsWhenUsingCustomId',
async run($) {
if ($.step.parameters.useCustomId) {
return [
{
label: 'Workspace',
key: 'workspaceId',
type: 'dropdown',
required: true,
description: '',
variables: true,
source: {
type: 'query',
name: 'getDynamicData',
arguments: [
{
name: 'key',
value: 'listWorkspaces',
},
],
},
},
];
}
},
};

View File

@@ -1,24 +0,0 @@
import defineApp from '../../helpers/define-app.js';
import addAuthHeader from './common/add-auth-header.js';
import auth from './auth/index.js';
import triggers from './triggers/index.js';
import dynamicData from './dynamic-data/index.js';
import actions from './actions/index.js';
import dynamicFields from './dynamic-fields/index.js';
export default defineApp({
name: 'ClickUp',
key: 'clickup',
baseUrl: 'https://clickup.com',
apiBaseUrl: 'https://api.clickup.com/api',
iconUrl: '{BASE_URL}/apps/clickup/assets/favicon.svg',
authDocUrl: '{DOCS_URL}/apps/clickup/connection',
primaryColor: '#FD71AF',
supportsConnections: true,
beforeRequest: [addAuthHeader],
auth,
triggers,
dynamicData,
actions,
dynamicFields,
});

View File

@@ -1,6 +0,0 @@
import newFolders from './new-folders/index.js';
import newLists from './new-lists/index.js';
import newTasks from './new-tasks/index.js';
import updatedTask from './updated-task/index.js';
export default [newFolders, newLists, newTasks, updatedTask];

View File

@@ -1,105 +0,0 @@
import Crypto from 'crypto';
import defineTrigger from '../../../../helpers/define-trigger.js';
export default defineTrigger({
name: 'New folders',
key: 'newFolder',
type: 'webhook',
description: 'Triggers when a new folder is created.',
arguments: [
{
label: 'Workspace',
key: 'workspaceId',
type: 'dropdown',
required: true,
description: '',
variables: true,
source: {
type: 'query',
name: 'getDynamicData',
arguments: [
{
name: 'key',
value: 'listWorkspaces',
},
],
},
},
{
label: 'Space',
key: 'spaceId',
type: 'dropdown',
required: false,
dependsOn: ['parameters.workspaceId'],
description: '',
variables: true,
source: {
type: 'query',
name: 'getDynamicData',
arguments: [
{
name: 'key',
value: 'listSpaces',
},
{
name: 'parameters.workspaceId',
value: '{parameters.workspaceId}',
},
],
},
},
],
async run($) {
const dataItem = {
raw: $.request.body,
meta: {
internalId: $.request.body.folder_id,
},
};
$.pushTriggerItem(dataItem);
},
async testRun($) {
const sampleEventData = {
event: 'folderCreated',
folder_id: '90180382912',
webhook_id: Crypto.randomUUID(),
};
const dataItem = {
raw: sampleEventData,
meta: {
internalId: '',
},
};
$.pushTriggerItem(dataItem);
},
async registerHook($) {
const { workspaceId, spaceId } = $.step.parameters;
const payload = {
name: $.flow.id,
endpoint: $.webhookUrl,
events: ['folderCreated'],
};
if (spaceId) {
payload.space_id = spaceId;
}
const { data } = await $.http.post(
`/v2/team/${workspaceId}/webhook`,
payload
);
await $.flow.setRemoteWebhookId(data.id);
},
async unregisterHook($) {
await $.http.delete(`/v2/webhook/${$.flow.remoteWebhookId}`);
},
});

View File

@@ -1,129 +0,0 @@
import Crypto from 'crypto';
import defineTrigger from '../../../../helpers/define-trigger.js';
export default defineTrigger({
name: 'New lists',
key: 'newLists',
type: 'webhook',
description: 'Triggers when a new list is created.',
arguments: [
{
label: 'Workspace',
key: 'workspaceId',
type: 'dropdown',
required: true,
description: '',
variables: true,
source: {
type: 'query',
name: 'getDynamicData',
arguments: [
{
name: 'key',
value: 'listWorkspaces',
},
],
},
},
{
label: 'Space',
key: 'spaceId',
type: 'dropdown',
required: false,
dependsOn: ['parameters.workspaceId'],
description: '',
variables: true,
source: {
type: 'query',
name: 'getDynamicData',
arguments: [
{
name: 'key',
value: 'listSpaces',
},
{
name: 'parameters.workspaceId',
value: '{parameters.workspaceId}',
},
],
},
},
{
label: 'Folder',
key: 'folderId',
type: 'dropdown',
required: false,
dependsOn: ['parameters.spaceId'],
description: '',
variables: true,
source: {
type: 'query',
name: 'getDynamicData',
arguments: [
{
name: 'key',
value: 'listFolders',
},
{
name: 'parameters.spaceId',
value: '{parameters.spaceId}',
},
],
},
},
],
async run($) {
const dataItem = {
raw: $.request.body,
meta: {
internalId: $.request.body.list_id,
},
};
$.pushTriggerItem(dataItem);
},
async testRun($) {
const sampleEventData = {
event: 'listCreated',
list_id: '901800588812',
webhook_id: Crypto.randomUUID(),
};
const dataItem = {
raw: sampleEventData,
meta: {
internalId: sampleEventData.webhook_id,
},
};
$.pushTriggerItem(dataItem);
},
async registerHook($) {
const { workspaceId, spaceId, folderId } = $.step.parameters;
const payload = {
name: $.flow.id,
endpoint: $.webhookUrl,
events: ['listCreated'],
space_id: spaceId,
};
if (folderId) {
payload.folder_id = folderId;
}
const { data } = await $.http.post(
`/v2/team/${workspaceId}/webhook`,
payload
);
await $.flow.setRemoteWebhookId(data.id);
},
async unregisterHook($) {
await $.http.delete(`/v2/webhook/${$.flow.remoteWebhookId}`);
},
});

View File

@@ -1,186 +0,0 @@
import Crypto from 'crypto';
import defineTrigger from '../../../../helpers/define-trigger.js';
export default defineTrigger({
name: 'New tasks',
key: 'newTasks',
type: 'webhook',
description: 'Triggers when a new task is created.',
arguments: [
{
label: 'Workspace',
key: 'workspaceId',
type: 'dropdown',
required: true,
description: '',
variables: true,
source: {
type: 'query',
name: 'getDynamicData',
arguments: [
{
name: 'key',
value: 'listWorkspaces',
},
],
},
},
{
label: 'Space',
key: 'spaceId',
type: 'dropdown',
required: false,
dependsOn: ['parameters.workspaceId'],
description: '',
variables: true,
source: {
type: 'query',
name: 'getDynamicData',
arguments: [
{
name: 'key',
value: 'listSpaces',
},
{
name: 'parameters.workspaceId',
value: '{parameters.workspaceId}',
},
],
},
},
{
label: 'Folder',
key: 'folderId',
type: 'dropdown',
required: false,
dependsOn: ['parameters.spaceId'],
description: '',
variables: true,
source: {
type: 'query',
name: 'getDynamicData',
arguments: [
{
name: 'key',
value: 'listFolders',
},
{
name: 'parameters.spaceId',
value: '{parameters.spaceId}',
},
],
},
},
{
label: 'List',
key: 'listId',
type: 'dropdown',
required: false,
dependsOn: ['parameters.folderId'],
description: '',
variables: true,
source: {
type: 'query',
name: 'getDynamicData',
arguments: [
{
name: 'key',
value: 'listLists',
},
{
name: 'parameters.folderId',
value: '{parameters.folderId}',
},
],
},
},
{
label: 'Task',
key: 'taskId',
type: 'dropdown',
required: false,
dependsOn: ['parameters.listId'],
description:
'Choose an optional task to determine when this flow should be activated. In this scenario, only subtasks will initiate this flow.',
variables: true,
source: {
type: 'query',
name: 'getDynamicData',
arguments: [
{
name: 'key',
value: 'listTasks',
},
{
name: 'parameters.listId',
value: '{parameters.listId}',
},
],
},
},
],
async run($) {
const dataItem = {
raw: $.request.body,
meta: {
internalId: $.request.body.task_id,
},
};
$.pushTriggerItem(dataItem);
},
async testRun($) {
const sampleEventData = {
event: 'taskCreated',
task_id: '86enn7pg7',
webhook_id: Crypto.randomUUID(),
history_items: [],
};
const dataItem = {
raw: sampleEventData,
meta: {
internalId: sampleEventData.webhook_id,
},
};
$.pushTriggerItem(dataItem);
},
async registerHook($) {
const { workspaceId, spaceId, folderId, listId, taskId } =
$.step.parameters;
const payload = {
name: $.flow.id,
endpoint: $.webhookUrl,
events: ['taskCreated'],
space_id: spaceId,
};
if (folderId) {
payload.folder_id = folderId;
}
if (listId) {
payload.list_id = listId;
}
if (taskId) {
payload.task_id = taskId;
}
const { data } = await $.http.post(
`/v2/team/${workspaceId}/webhook`,
payload
);
await $.flow.setRemoteWebhookId(data.id);
},
async unregisterHook($) {
await $.http.delete(`/v2/webhook/${$.flow.remoteWebhookId}`);
},
});

View File

@@ -1,172 +0,0 @@
import Crypto from 'crypto';
import defineTrigger from '../../../../helpers/define-trigger.js';
export default defineTrigger({
name: 'Updated task',
key: 'updatedTask',
type: 'webhook',
description: 'Triggers when a task is updated.',
arguments: [
{
label: 'Workspace',
key: 'workspaceId',
type: 'dropdown',
required: true,
description: '',
variables: true,
source: {
type: 'query',
name: 'getDynamicData',
arguments: [
{
name: 'key',
value: 'listWorkspaces',
},
],
},
},
{
label: 'Space',
key: 'spaceId',
type: 'dropdown',
required: false,
dependsOn: ['parameters.workspaceId'],
description: '',
variables: true,
source: {
type: 'query',
name: 'getDynamicData',
arguments: [
{
name: 'key',
value: 'listSpaces',
},
{
name: 'parameters.workspaceId',
value: '{parameters.workspaceId}',
},
],
},
},
{
label: 'Folder',
key: 'folderId',
type: 'dropdown',
required: false,
dependsOn: ['parameters.spaceId'],
description: '',
variables: true,
source: {
type: 'query',
name: 'getDynamicData',
arguments: [
{
name: 'key',
value: 'listFolders',
},
{
name: 'parameters.spaceId',
value: '{parameters.spaceId}',
},
],
},
},
{
label: 'List',
key: 'listId',
type: 'dropdown',
required: false,
dependsOn: ['parameters.folderId'],
description: '',
variables: true,
source: {
type: 'query',
name: 'getDynamicData',
arguments: [
{
name: 'key',
value: 'listLists',
},
{
name: 'parameters.folderId',
value: '{parameters.folderId}',
},
],
},
},
{
label: 'What Changed?',
key: 'whatChanged',
type: 'dropdown',
required: false,
variables: true,
options: [
{ label: 'Status', value: 'taskStatusUpdated' },
{ label: 'Assignee Added', value: 'taskAssigneeUpdated' },
{ label: 'Priority', value: 'taskPriorityUpdated' },
{ label: 'Tag Added', value: 'taskTagUpdated' },
],
},
],
async run($) {
const dataItem = {
raw: $.request.body,
meta: {
internalId: Crypto.randomUUID(),
},
};
$.pushTriggerItem(dataItem);
},
async testRun($) {
const sampleEventData = {
event: 'taskUpdated',
task_id: '86enn7pg7',
webhook_id: Crypto.randomUUID(),
history_items: [],
};
const dataItem = {
raw: sampleEventData,
meta: {
internalId: sampleEventData.webhook_id,
},
};
$.pushTriggerItem(dataItem);
},
async registerHook($) {
const { workspaceId, spaceId, folderId, listId, whatChanged } =
$.step.parameters;
const payload = {
name: $.flow.id,
endpoint: $.webhookUrl,
space_id: spaceId,
};
payload.events = [whatChanged || 'taskUpdated'];
if (folderId) {
payload.folder_id = folderId;
}
if (listId) {
payload.list_id = listId;
}
const { data } = await $.http.post(
`/v2/team/${workspaceId}/webhook`,
payload
);
await $.flow.setRemoteWebhookId(data.id);
},
async unregisterHook($) {
await $.http.delete(`/v2/webhook/${$.flow.remoteWebhookId}`);
},
});

View File

@@ -1,3 +0,0 @@
import runJavascript from './run-javascript/index.js';
export default [runJavascript];

View File

@@ -1,84 +0,0 @@
import defineAction from '../../../../helpers/define-action.js';
export default defineAction({
name: 'Run Javascript',
key: 'runJavascript',
description:
'Run browser Javascript code. You can not use NodeJS specific features and npm packages.',
arguments: [
{
label: 'Inputs',
key: 'inputs',
type: 'dynamic',
required: false,
description:
'To be able to use data from previous steps, you need to expose them as input entries. You can access these input values in your code by using the `inputs` argument.',
value: [
{
key: '',
value: '',
},
],
fields: [
{
label: 'Key',
key: 'key',
type: 'string',
required: true,
variables: true,
},
{
label: 'Value',
key: 'value',
type: 'string',
required: true,
variables: true,
valueType: 'parse',
},
],
},
{
label: 'Code Snippet',
key: 'codeSnippet',
type: 'code',
required: true,
variables: false,
value:
'const code = async (inputs) => { \n // E.g. if you have an input called username,\n // you can access its value by calling inputs.username\n // Return value will be used as output of this step.\n\n return true;\n};',
},
],
async run($) {
const { inputs = [], codeSnippet } = $.step.parameters;
const objectifiedInput = {};
for (const input of inputs) {
if (input.key) {
objectifiedInput[input.key] = input.value;
}
}
const ivm = (await import('isolated-vm')).default;
const isolate = new ivm.Isolate({ memoryLimit: 128 });
try {
const context = await isolate.createContext();
await context.global.set(
'inputs',
new ivm.ExternalCopy(objectifiedInput).copyInto()
);
const compiledCodeSnippet = await isolate.compileScript(
`${codeSnippet}; code(inputs);`
);
const codeFunction = await compiledCodeSnippet.run(context, {
reference: true,
promise: true,
});
$.setActionItem({ raw: { output: await codeFunction.copy() } });
} finally {
isolate.dispose();
}
},
});

View File

@@ -1,5 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="800px" height="800px" viewBox="0 0 512 512">
<polyline points="160 368 32 256 160 144" style="fill:none;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:32px"/>
<polyline points="352 368 480 256 352 144" style="fill:none;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:32px"/>
<line x1="304" y1="96" x2="208" y2="416" style="fill:none;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:32px"/>
</svg>

Before

Width:  |  Height:  |  Size: 519 B

View File

@@ -1,14 +0,0 @@
import defineApp from '../../helpers/define-app.js';
import actions from './actions/index.js';
export default defineApp({
name: 'Code',
key: 'code',
baseUrl: '',
apiBaseUrl: '',
iconUrl: '{BASE_URL}/apps/code/assets/favicon.svg',
authDocUrl: '{DOCS_URL}/apps/code/connection',
primaryColor: '#000000',
supportsConnections: false,
actions,
});

View File

@@ -1,64 +0,0 @@
import { createHmac } from 'node:crypto';
import defineAction from '../../../../helpers/define-action.js';
export default defineAction({
name: 'Create HMAC',
key: 'createHmac',
description: 'Create a Hash-based Message Authentication Code (HMAC) using the specified algorithm, secret key, and message.',
arguments: [
{
label: 'Algorithm',
key: 'algorithm',
type: 'dropdown',
required: true,
value: 'sha256',
description: 'Specifies the cryptographic hash function to use for HMAC generation.',
options: [
{ label: 'SHA-256', value: 'sha256' },
],
variables: true,
},
{
label: 'Message',
key: 'message',
type: 'string',
required: true,
description: 'The input message to be hashed. This is the value that will be processed to generate the HMAC.',
variables: true,
},
{
label: 'Secret Key',
key: 'secretKey',
type: 'string',
required: true,
description: 'The secret key used to create the HMAC.',
variables: true,
},
{
label: 'Output Encoding',
key: 'outputEncoding',
type: 'dropdown',
required: true,
value: 'hex',
description: 'Specifies the encoding format for the HMAC digest output.',
options: [
{ label: 'base64', value: 'base64' },
{ label: 'base64url', value: 'base64url' },
{ label: 'hex', value: 'hex' },
],
variables: true,
},
],
async run($) {
const hash = createHmac($.step.parameters.algorithm, $.step.parameters.secretKey)
.update($.step.parameters.message)
.digest($.step.parameters.outputEncoding);
$.setActionItem({
raw: {
hash
},
});
},
});

View File

@@ -1,65 +0,0 @@
import crypto from 'node:crypto';
import defineAction from '../../../../helpers/define-action.js';
export default defineAction({
name: 'Create Signature',
key: 'createSignature',
description: 'Create a digital signature using the specified algorithm, secret key, and message.',
arguments: [
{
label: 'Algorithm',
key: 'algorithm',
type: 'dropdown',
required: true,
value: 'RSA-SHA256',
description: 'Specifies the cryptographic hash function to use for HMAC generation.',
options: [
{ label: 'RSA-SHA256', value: 'RSA-SHA256' },
],
variables: true,
},
{
label: 'Message',
key: 'message',
type: 'string',
required: true,
description: 'The input message to be signed.',
variables: true,
},
{
label: 'Private Key',
key: 'privateKey',
type: 'string',
required: true,
description: 'The RSA private key in PEM format used for signing.',
variables: true,
},
{
label: 'Output Encoding',
key: 'outputEncoding',
type: 'dropdown',
required: true,
value: 'hex',
description: 'Specifies the encoding format for the digital signature output. This determines how the generated signature will be represented as a string.',
options: [
{ label: 'base64', value: 'base64' },
{ label: 'base64url', value: 'base64url' },
{ label: 'hex', value: 'hex' },
],
variables: true,
},
],
async run($) {
const signer = crypto.createSign($.step.parameters.algorithm);
signer.update($.step.parameters.message);
signer.end();
const signature = signer.sign($.step.parameters.privateKey, $.step.parameters.outputEncoding);
$.setActionItem({
raw: {
signature
},
});
},
});

View File

@@ -1,4 +0,0 @@
import createHmac from './create-hmac/index.js';
import createRsaSha256Signature from './create-rsa-sha256-signature/index.js';
export default [createHmac, createRsaSha256Signature];

View File

@@ -1,3 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="100pt" height="100pt" version="1.1" viewBox="0 0 100 100">
<path d="m66.012 33h-3.0117v-11c0-7.1719-5.8281-13-13-13s-13 5.8281-13 13v11h-3.0117c-2.75 0-4.9883 2.2383-4.9883 4.9883v28.012c0 2.75 2.2383 4.9883 4.9883 4.9883h32.012c2.75 0 4.9883-2.2383 4.9883-4.9883v-28.012c0.011719-2.75-2.2266-4.9883-4.9766-4.9883zm-27.012-11c0-6.0703 4.9297-11 11-11s11 4.9297 11 11v11h-22zm30 44.012c0 1.6484-1.3398 2.9883-2.9883 2.9883h-32.023c-1.6484 0-2.9883-1.3398-2.9883-2.9883v-28.023c0-1.6484 1.3398-2.9883 2.9883-2.9883h32.023c1.6484 0 2.9883 1.3398 2.9883 2.9883zm-18 9.9883v14c0 0.55078-0.44922 1-1 1s-1-0.44922-1-1v-14c0-0.55078 0.44922-1 1-1s1 0.44922 1 1zm20 8c0 0.55078-0.44922 1-1 1h-8c-0.55078 0-1-0.44922-1-1v-8c0-0.55078 0.44922-1 1-1s1 0.44922 1 1v7h7c0.55078 0 1 0.44922 1 1zm-32-8v8c0 0.55078-0.44922 1-1 1h-8c-0.55078 0-1-0.44922-1-1s0.44922-1 1-1h7v-7c0-0.55078 0.44922-1 1-1s1 0.44922 1 1zm-14-26c0 0.55078-0.44922 1-1 1h-14c-0.55078 0-1-0.44922-1-1s0.44922-1 1-1h14c0.55078 0 1 0.44922 1 1zm0-12c0 0.55078-0.44922 1-1 1h-8c-0.55078 0-1-0.44922-1-1v-8c0-0.55078 0.44922-1 1-1s1 0.44922 1 1v7h7c0.55078 0 1 0.44922 1 1zm0 24c0 0.55078-0.44922 1-1 1h-7v7c0 0.55078-0.44922 1-1 1s-1-0.44922-1-1v-8c0-0.55078 0.44922-1 1-1h8c0.55078 0 1 0.44922 1 1zm66-12c0 0.55078-0.44922 1-1 1h-14c-0.55078 0-1-0.44922-1-1s0.44922-1 1-1h14c0.55078 0 1 0.44922 1 1zm-16-12c0-0.55078 0.44922-1 1-1h7v-7c0-0.55078 0.44922-1 1-1s1 0.44922 1 1v8c0 0.55078-0.44922 1-1 1h-8c-0.55078 0-1-0.44922-1-1zm10 24v8c0 0.55078-0.44922 1-1 1s-1-0.44922-1-1v-7h-7c-0.55078 0-1-0.44922-1-1s0.44922-1 1-1h8c0.55078 0 1 0.44922 1 1zm-35-17c-2.7617 0-5 2.2383-5 5 0 2.4102 1.7188 4.4297 4 4.8984v5.1016c0 0.55078 0.44922 1 1 1s1-0.44922 1-1v-5.1016c2.2812-0.46094 4-2.4805 4-4.8984 0-2.7617-2.2383-5-5-5zm0 8c-1.6484 0-3-1.3516-3-3s1.3516-3 3-3 3 1.3516 3 3-1.3516 3-3 3z"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.9 KiB

View File

@@ -1,14 +0,0 @@
import defineApp from '../../helpers/define-app.js';
import actions from './actions/index.js';
export default defineApp({
name: 'Cryptography',
key: 'cryptography',
iconUrl: '{BASE_URL}/apps/cryptography/assets/favicon.svg',
authDocUrl: '{DOCS_URL}/apps/cryptography/connection',
supportsConnections: false,
baseUrl: '',
apiBaseUrl: '',
primaryColor: '#001F52',
actions,
});

View File

@@ -9,6 +9,6 @@ export default defineApp({
supportsConnections: false,
baseUrl: '',
apiBaseUrl: '',
primaryColor: '#001F52',
primaryColor: '001F52',
actions,
});

View File

@@ -11,7 +11,7 @@ export default defineApp({
supportsConnections: true,
baseUrl: 'https://deepl.com',
apiBaseUrl: 'https://api.deepl.com',
primaryColor: '#0d2d45',
primaryColor: '0d2d45',
beforeRequest: [addAuthHeader],
auth,
actions,

View File

@@ -9,6 +9,6 @@ export default defineApp({
supportsConnections: false,
baseUrl: '',
apiBaseUrl: '',
primaryColor: '#001F52',
primaryColor: '001F52',
actions,
});

View File

@@ -14,7 +14,7 @@ export default defineApp({
supportsConnections: true,
baseUrl: 'https://discord.com',
apiBaseUrl: 'https://discord.com/api',
primaryColor: '#5865f2',
primaryColor: '5865f2',
beforeRequest: [addAuthHeader],
auth,
dynamicData,

View File

@@ -11,7 +11,7 @@ export default defineApp({
apiBaseUrl: 'https://disqus.com/api',
iconUrl: '{BASE_URL}/apps/disqus/assets/favicon.svg',
authDocUrl: '{DOCS_URL}/apps/disqus/connection',
primaryColor: '#2E9FFF',
primaryColor: '2E9FFF',
supportsConnections: true,
beforeRequest: [addAuthHeader],
auth,

View File

@@ -11,7 +11,7 @@ export default defineApp({
supportsConnections: true,
baseUrl: 'https://dropbox.com',
apiBaseUrl: 'https://api.dropboxapi.com',
primaryColor: '#0061ff',
primaryColor: '0061ff',
beforeRequest: [addAuthHeader],
auth,
actions,

View File

@@ -9,6 +9,6 @@ export default defineApp({
supportsConnections: false,
baseUrl: '',
apiBaseUrl: '',
primaryColor: '#001F52',
primaryColor: '001F52',
actions,
});

View File

@@ -10,7 +10,7 @@ export default defineApp({
iconUrl: '{BASE_URL}/apps/flickr/assets/favicon.svg',
authDocUrl: '{DOCS_URL}/apps/flickr/connection',
docUrl: 'https://automatisch.io/docs/flickr',
primaryColor: '#000000',
primaryColor: '000000',
supportsConnections: true,
baseUrl: 'https://www.flickr.com/',
apiBaseUrl: 'https://www.flickr.com/services',

View File

@@ -11,7 +11,7 @@ export default defineApp({
supportsConnections: true,
baseUrl: 'https://flowers-software.com',
apiBaseUrl: 'https://webapp.flowers-software.com/api',
primaryColor: '#02AFC7',
primaryColor: '02AFC7',
beforeRequest: [addAuthHeader],
auth,
triggers,

View File

@@ -1,10 +1,8 @@
import defineAction from '../../../../helpers/define-action.js';
import formatDateTime from './transformers/format-date-time.js';
import getCurrentTimestamp from './transformers/get-current-timestamp.js';
const transformers = {
formatDateTime,
getCurrentTimestamp,
};
export default defineAction({
@@ -18,16 +16,7 @@ export default defineAction({
type: 'dropdown',
required: true,
variables: true,
options: [
{
label: 'Get current timestamp',
value: 'getCurrentTimestamp',
},
{
label: 'Format Date / Time',
value: 'formatDateTime',
},
],
options: [{ label: 'Format Date / Time', value: 'formatDateTime' }],
additionalFields: {
type: 'query',
name: 'getDynamicFields',

View File

@@ -1,5 +0,0 @@
const getCurrentTimestamp = () => {
return Date.now();
};
export default getCurrentTimestamp;

View File

@@ -14,8 +14,6 @@ import stringToBase64 from './transformers/string-to-base64.js';
import encodeUri from './transformers/encode-uri.js';
import trimWhitespace from './transformers/trim-whitespace.js';
import useDefaultValue from './transformers/use-default-value.js';
import parseStringifiedJson from './transformers/parse-stringified-json.js';
import createUuid from './transformers/create-uuid.js';
const transformers = {
base64ToString,
@@ -32,8 +30,6 @@ const transformers = {
encodeUri,
trimWhitespace,
useDefaultValue,
parseStringifiedJson,
createUuid,
};
export default defineAction({
@@ -51,21 +47,19 @@ export default defineAction({
options: [
{ label: 'Base64 to String', value: 'base64ToString' },
{ label: 'Capitalize', value: 'capitalize' },
{ label: 'Convert HTML to Markdown', value: 'htmlToMarkdown' },
{ label: 'Convert Markdown to HTML', value: 'markdownToHtml' },
{ label: 'Create UUID', value: 'createUuid' },
{ label: 'Encode URI', value: 'encodeUri' },
{
label: 'Encode URI Component',
value: 'encodeUriComponent',
},
{ label: 'Convert HTML to Markdown', value: 'htmlToMarkdown' },
{ label: 'Convert Markdown to HTML', value: 'markdownToHtml' },
{ label: 'Extract Email Address', value: 'extractEmailAddress' },
{ label: 'Extract Number', value: 'extractNumber' },
{ label: 'Lowercase', value: 'lowercase' },
{ label: 'Parse stringified JSON', value: 'parseStringifiedJson' },
{ label: 'Pluralize', value: 'pluralize' },
{ label: 'Replace', value: 'replace' },
{ label: 'String to Base64', value: 'stringToBase64' },
{ label: 'Encode URI', value: 'encodeUri' },
{ label: 'Trim Whitespace', value: 'trimWhitespace' },
{ label: 'Use Default Value', value: 'useDefaultValue' },
],

View File

@@ -1,7 +0,0 @@
import { v4 as uuidv4 } from 'uuid';
const createUuidV4 = () => {
return uuidv4();
};
export default createUuidV4;

View File

@@ -1,7 +0,0 @@
const parseStringifiedJson = ($) => {
const input = $.step.parameters.input;
return JSON.parse(input);
};
export default parseStringifiedJson;

View File

@@ -1,26 +1,8 @@
const replace = ($) => {
const input = $.step.parameters.input;
const find = $.step.parameters.find;
const replace = $.step.parameters.replace;
const useRegex = $.step.parameters.useRegex;
if (useRegex) {
const ignoreCase = $.step.parameters.ignoreCase;
const flags = [ignoreCase && 'i', 'g'].filter(Boolean).join('');
const timeoutId = setTimeout(() => {
$.execution.exit();
}, 100);
const regex = new RegExp(find, flags);
const replacedValue = input.replaceAll(regex, replace);
clearTimeout(timeoutId);
return replacedValue;
}
return input.replaceAll(find, replace);
};

View File

@@ -1,4 +1,3 @@
import listTransformOptions from './list-transform-options/index.js';
import listReplaceRegexOptions from './list-replace-regex-options/index.js';
export default [listTransformOptions, listReplaceRegexOptions];
export default [listTransformOptions];

View File

@@ -1,23 +0,0 @@
export default {
name: 'List replace regex options',
key: 'listReplaceRegexOptions',
async run($) {
if (!$.step.parameters.useRegex) return [];
return [
{
label: 'Ignore case',
key: 'ignoreCase',
type: 'dropdown',
required: true,
description: 'Ignore case sensitivity.',
variables: true,
options: [
{ label: 'Yes', value: true },
{ label: 'No', value: false },
],
},
];
},
};

View File

@@ -12,7 +12,6 @@ import stringToBase64 from './text/string-to-base64.js';
import encodeUri from './text/encode-uri.js';
import trimWhitespace from './text/trim-whitespace.js';
import useDefaultValue from './text/use-default-value.js';
import parseStringifiedJson from './text/parse-stringified-json.js';
import performMathOperation from './numbers/perform-math-operation.js';
import randomNumber from './numbers/random-number.js';
import formatNumber from './numbers/format-number.js';
@@ -39,7 +38,6 @@ const options = {
formatNumber,
formatPhoneNumber,
formatDateTime,
parseStringifiedJson,
};
export default {

View File

@@ -1,12 +0,0 @@
const useDefaultValue = [
{
label: 'Input',
key: 'input',
type: 'string',
required: true,
description: 'Stringified JSON you want to parse.',
variables: true,
},
];
export default useDefaultValue;

View File

@@ -23,33 +23,6 @@ const replace = [
description: 'Text that will replace the found text.',
variables: true,
},
{
label: 'Use Regular Expression',
key: 'useRegex',
type: 'dropdown',
required: true,
description: 'Use regex to search values.',
variables: true,
value: false,
options: [
{ label: 'Yes', value: true },
{ label: 'No', value: false },
],
additionalFields: {
type: 'query',
name: 'getDynamicFields',
arguments: [
{
name: 'key',
value: 'listReplaceRegexOptions',
},
{
name: 'parameters.useRegex',
value: '{parameters.useRegex}',
},
],
},
},
];
export default replace;

View File

@@ -10,7 +10,7 @@ export default defineApp({
supportsConnections: false,
baseUrl: '',
apiBaseUrl: '',
primaryColor: '#001F52',
primaryColor: '001F52',
actions,
dynamicFields,
});

View File

@@ -11,7 +11,7 @@ export default defineApp({
apiBaseUrl: '',
iconUrl: '{BASE_URL}/apps/ghost/assets/favicon.svg',
authDocUrl: '{DOCS_URL}/apps/ghost/connection',
primaryColor: '#15171A',
primaryColor: '15171A',
supportsConnections: true,
beforeRequest: [setBaseUrl, addAuthHeader],
auth,

View File

@@ -10,7 +10,7 @@ export default defineAction({
label: 'Repo',
key: 'repo',
type: 'dropdown',
required: true,
required: false,
variables: true,
source: {
type: 'query',

View File

@@ -12,7 +12,7 @@ export default defineApp({
apiBaseUrl: 'https://api.github.com',
iconUrl: '{BASE_URL}/apps/github/assets/favicon.svg',
authDocUrl: '{DOCS_URL}/apps/github/connection',
primaryColor: '#000000',
primaryColor: '000000',
supportsConnections: true,
beforeRequest: [addAuthHeader],
auth,

View File

@@ -12,7 +12,7 @@ export default defineApp({
apiBaseUrl: 'https://gitlab.com',
iconUrl: '{BASE_URL}/apps/gitlab/assets/favicon.svg',
authDocUrl: '{DOCS_URL}/apps/gitlab/connection',
primaryColor: '#FC6D26',
primaryColor: 'FC6D26',
supportsConnections: true,
beforeRequest: [setBaseUrl, addAuthHeader],
auth,

View File

@@ -11,7 +11,7 @@ export default defineApp({
apiBaseUrl: 'https://www.googleapis.com/calendar',
iconUrl: '{BASE_URL}/apps/google-calendar/assets/favicon.svg',
authDocUrl: '{DOCS_URL}/apps/google-calendar/connection',
primaryColor: '#448AFF',
primaryColor: '448AFF',
supportsConnections: true,
beforeRequest: [addAuthHeader],
auth,

View File

@@ -11,7 +11,7 @@ export default defineApp({
apiBaseUrl: 'https://www.googleapis.com/drive',
iconUrl: '{BASE_URL}/apps/google-drive/assets/favicon.svg',
authDocUrl: '{DOCS_URL}/apps/google-drive/connection',
primaryColor: '#1FA463',
primaryColor: '1FA463',
supportsConnections: true,
beforeRequest: [addAuthHeader],
auth,

View File

@@ -11,7 +11,7 @@ export default defineApp({
apiBaseUrl: 'https://forms.googleapis.com',
iconUrl: '{BASE_URL}/apps/google-forms/assets/favicon.svg',
authDocUrl: '{DOCS_URL}/apps/google-forms/connection',
primaryColor: '#673AB7',
primaryColor: '673AB7',
supportsConnections: true,
beforeRequest: [addAuthHeader],
auth,

View File

@@ -1,175 +0,0 @@
import defineAction from '../../../../helpers/define-action.js';
export default defineAction({
name: 'Find worksheet',
key: 'findWorksheet',
description:
'Finds a worksheet by title. Optionally, create a worksheet if none are found.',
arguments: [
{
label: 'Drive',
key: 'driveId',
type: 'dropdown',
required: false,
description:
'The Google Drive where your spreadsheet resides. If nothing is selected, then your personal Google Drive will be used.',
variables: true,
source: {
type: 'query',
name: 'getDynamicData',
arguments: [
{
name: 'key',
value: 'listDrives',
},
],
},
},
{
label: 'Spreadsheet',
key: 'spreadsheetId',
type: 'dropdown',
required: true,
dependsOn: ['parameters.driveId'],
variables: true,
source: {
type: 'query',
name: 'getDynamicData',
arguments: [
{
name: 'key',
value: 'listSpreadsheets',
},
{
name: 'parameters.driveId',
value: '{parameters.driveId}',
},
],
},
},
{
label: 'Title',
key: 'title',
type: 'string',
required: true,
description:
'The worksheet title needs to match exactly, and the search is case-sensitive.',
variables: true,
},
{
label: 'Create worksheet if none are found.',
key: 'createWorksheet',
type: 'dropdown',
required: false,
options: [
{ label: 'Yes', value: true },
{ label: 'No', value: false },
],
additionalFields: {
type: 'query',
name: 'getDynamicFields',
arguments: [
{
name: 'key',
value: 'listCreateWorksheetFields',
},
{
name: 'parameters.createWorksheet',
value: '{parameters.createWorksheet}',
},
],
},
},
],
async run($) {
const createWorksheet = $.step.parameters.createWorksheet;
async function findWorksheet() {
const {
data: { sheets },
} = await $.http.get(`/v4/spreadsheets/${$.step.parameters.spreadsheetId}`);
const selectedSheet = sheets.find(
(sheet) => sheet.properties.title === $.step.parameters.title
);
return selectedSheet;
}
const selectedSheet = await findWorksheet();
if (selectedSheet) {
$.setActionItem({
raw: selectedSheet,
});
return;
}
if (createWorksheet) {
const headers = $.step.parameters.headers;
const headerValues = headers.map((entry) => entry.header);
const body = {
requests: [
{
addSheet: {
properties: {
title: $.step.parameters.title,
},
},
},
],
};
const { data } = await $.http.post(
`/v4/spreadsheets/${$.step.parameters.spreadsheetId}:batchUpdate`,
body
);
if (headerValues.length) {
const body = {
requests: [
{
updateCells: {
rows: [
{
values: headerValues.map((header) => ({
userEnteredValue: { stringValue: header },
})),
},
],
fields: '*',
start: {
sheetId:
data.replies[data.replies.length - 1].addSheet.properties
.sheetId,
rowIndex: 0,
columnIndex: 0,
},
},
},
],
};
await $.http.post(
`/v4/spreadsheets/${$.step.parameters.spreadsheetId}:batchUpdate`,
body
);
const createdSheet = await findWorksheet();
$.setActionItem({
raw: createdSheet,
});
return;
}
}
$.setActionItem({
raw: null,
});
},
});

View File

@@ -1,11 +1,5 @@
import createSpreadsheet from './create-spreadsheet/index.js';
import createSpreadsheetRow from './create-spreadsheet-row/index.js';
import createWorksheet from './create-worksheet/index.js';
import findWorksheet from './find-worksheet/index.js';
export default [
createSpreadsheet,
createSpreadsheetRow,
createWorksheet,
findWorksheet,
];
export default [createSpreadsheet, createSpreadsheetRow, createWorksheet];

View File

@@ -1,4 +1,3 @@
import listSheetHeaders from './list-sheet-headers/index.js';
import listCreateWorksheetFields from './list-create-worksheet-fields/index.js';
export default [listSheetHeaders, listCreateWorksheetFields];
export default [listSheetHeaders];

View File

@@ -1,26 +0,0 @@
export default {
name: 'List create worksheet fields',
key: 'listCreateWorksheetFields',
async run($) {
if ($.step.parameters.createWorksheet) {
return [
{
label: 'Headers',
key: 'headers',
type: 'dynamic',
required: false,
fields: [
{
label: 'Header',
key: 'header',
type: 'string',
required: true,
variables: true,
},
],
},
];
}
},
};

View File

@@ -13,7 +13,7 @@ export default defineApp({
apiBaseUrl: 'https://sheets.googleapis.com',
iconUrl: '{BASE_URL}/apps/google-sheets/assets/favicon.svg',
authDocUrl: '{DOCS_URL}/apps/google-sheets/connection',
primaryColor: '#0F9D58',
primaryColor: '0F9D58',
supportsConnections: true,
beforeRequest: [addAuthHeader],
auth,

View File

@@ -12,7 +12,7 @@ export default defineApp({
apiBaseUrl: 'https://tasks.googleapis.com',
iconUrl: '{BASE_URL}/apps/google-tasks/assets/favicon.svg',
authDocUrl: '{DOCS_URL}/apps/google-tasks/connection',
primaryColor: '#0066DA',
primaryColor: '0066DA',
supportsConnections: true,
beforeRequest: [addAuthHeader],
auth,

View File

@@ -11,7 +11,7 @@ export default defineApp({
apiBaseUrl: 'https://app.tryhelix.ai',
iconUrl: '{BASE_URL}/apps/helix/assets/favicon.svg',
authDocUrl: '{DOCS_URL}/apps/helix/connection',
primaryColor: '#000000',
primaryColor: '000000',
supportsConnections: true,
beforeRequest: [setBaseUrl, addAuthHeader],
auth,

View File

@@ -145,13 +145,6 @@ export default defineAction({
responseData = Buffer.from(responseData).toString('base64');
}
$.setActionItem({
raw: {
data: responseData,
headers: response.headers,
status: response.status,
statusText: response.statusText
}
});
$.setActionItem({ raw: { data: responseData } });
},
});

View File

@@ -9,6 +9,6 @@ export default defineApp({
supportsConnections: false,
baseUrl: '',
apiBaseUrl: '',
primaryColor: '#000000',
primaryColor: '000000',
actions,
});

View File

@@ -11,7 +11,7 @@ export default defineApp({
supportsConnections: true,
baseUrl: 'https://www.hubspot.com',
apiBaseUrl: 'https://api.hubapi.com',
primaryColor: '#F95C35',
primaryColor: 'F95C35',
beforeRequest: [addAuthHeader],
auth,
actions,

View File

@@ -13,7 +13,7 @@ export default defineApp({
apiBaseUrl: 'https://invoicing.co/api',
iconUrl: '{BASE_URL}/apps/invoice-ninja/assets/favicon.svg',
authDocUrl: '{DOCS_URL}/apps/invoice-ninja/connection',
primaryColor: '#000000',
primaryColor: '000000',
supportsConnections: true,
beforeRequest: [setBaseUrl, addAuthHeader],
auth,

View File

@@ -1 +0,0 @@
<svg xmlns:xlink="http://www.w3.org/1999/xlink" class="jff-logo-img" width="53" height="59" viewBox="0 0 53 59" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true"><path d="M14.4509 55.1332C15.5462 56.1951 14.7721 58.0143 13.2168 58.0143H3.4831C1.56265 58.0143 0 56.4995 0 54.6377V45.2017C0 43.6939 1.87664 42.9436 2.97195 44.0054L14.4509 55.1332Z" fill="#0A1551"></path><path d="M29.6655 55.8676C26.7843 53.0052 26.7843 48.3642 29.6655 45.5018L40.0638 35.1713C42.945 32.3089 47.6164 32.3089 50.4976 35.1713C53.3788 38.0338 53.3788 42.6747 50.4976 45.5371L40.0993 55.8676C37.2181 58.73 32.5468 58.73 29.6655 55.8676Z" fill="#FFB629"></path><path d="M2.1968 29.9101C-0.684414 27.0476 -0.684413 22.4067 2.1968 19.5443L19.696 2.14685C22.5772 -0.71559 27.2486 -0.715594 30.1298 2.14685C33.011 5.00929 33.011 9.65022 30.1298 12.5127L12.6306 29.9101C9.74937 32.7725 5.078 32.7725 2.1968 29.9101Z" fill="#0099FF"></path><path d="M16.5015 42.3095C13.6203 39.4471 13.6203 34.8062 16.5015 31.9437L40.1461 8.45322C43.0273 5.59079 47.6986 5.59079 50.5798 8.45322C53.4611 11.3157 53.4611 15.9566 50.5798 18.819L26.9353 42.3095C24.0541 45.1719 19.3827 45.1719 16.5015 42.3095Z" fill="#FF6100"></path></svg>

Before

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -1,30 +0,0 @@
import verifyCredentials from './verify-credentials.js';
import isStillVerified from './is-still-verified.js';
export default {
fields: [
{
key: 'apiUrl',
label: 'API URL',
type: 'string',
required: false,
readOnly: false,
value: 'https://api.jotform.com',
placeholder: 'https://${subdomain}.jotform.com/api',
clickToCopy: true,
},
{
key: 'apiKey',
label: 'API Key',
type: 'string',
required: true,
readOnly: false,
value: null,
placeholder: null,
clickToCopy: false,
},
],
verifyCredentials,
isStillVerified,
};

View File

@@ -1,8 +0,0 @@
import getCurrentUser from '../common/get-current-user.js';
const isStillVerified = async ($) => {
const user = await getCurrentUser($);
return !!user.username;
};
export default isStillVerified;

View File

@@ -1,12 +0,0 @@
import getCurrentUser from '../common/get-current-user.js';
const verifyCredentials = async ($) => {
const user = await getCurrentUser($);
await $.auth.set({
screenName: user.name,
apiKey: $.auth.data.apiKey,
});
};
export default verifyCredentials;

View File

@@ -1,9 +0,0 @@
const addAuthHeader = ($, requestConfig) => {
if ($.auth.data?.apiKey) {
requestConfig.headers['APIKEY'] = `${$.auth.data.apiKey}`;
}
return requestConfig;
};
export default addAuthHeader;

View File

@@ -1,7 +0,0 @@
const getCurrentUser = async ($) => {
const response = await $.http.get('/user');
const currentUser = response.data.content;
return currentUser;
};
export default getCurrentUser;

View File

@@ -1,11 +0,0 @@
const setBaseUrl = ($, requestConfig) => {
if ($.auth.data.apiUrl) {
requestConfig.baseURL = $.auth.data.apiUrl;
} else if ($.app.apiBaseUrl) {
requestConfig.baseURL = $.app.apiBaseUrl;
}
return requestConfig;
};
export default setBaseUrl;

View File

@@ -1,3 +0,0 @@
import listForms from './list-forms/index.js';
export default [listForms];

View File

@@ -1,41 +0,0 @@
export default {
name: 'List forms',
key: 'listForms',
async run($) {
const forms = {
data: [],
};
let hasMore = false;
const params = {
limit: 1000,
offset: 0,
orderby: 'created_at',
};
do {
const { data } = await $.http.get('/user/forms', { params });
params.offset = params.offset + params.limit;
if (data.content?.length) {
for (const form of data.content) {
if (form.status === 'ENABLED') {
forms.data.push({
value: form.id,
name: form.title,
});
}
}
}
if (data.resultSet.count >= data.resultSet.limit) {
hasMore = true;
} else {
hasMore = false;
}
} while (hasMore);
return forms;
},
};

View File

@@ -1,21 +0,0 @@
import defineApp from '../../helpers/define-app.js';
import addAuthHeader from './common/add-auth-header.js';
import auth from './auth/index.js';
import setBaseUrl from './common/set-base-url.js';
import triggers from './triggers/index.js';
import dynamicData from './dynamic-data/index.js';
export default defineApp({
name: 'Jotform',
key: 'jotform',
iconUrl: '{BASE_URL}/apps/jotform/assets/favicon.svg',
authDocUrl: '{DOCS_URL}/apps/jotform/connection',
supportsConnections: true,
baseUrl: 'https://www.jotform.com',
apiBaseUrl: 'https://api.jotform.com',
primaryColor: '#FF6100',
beforeRequest: [setBaseUrl, addAuthHeader],
auth,
triggers,
dynamicData,
});

View File

@@ -1,3 +0,0 @@
import newSubmissions from './new-submissions/index.js';
export default [newSubmissions];

View File

@@ -1,109 +0,0 @@
import Crypto from 'crypto';
import { URLSearchParams } from 'url';
import defineTrigger from '../../../../helpers/define-trigger.js';
export default defineTrigger({
name: 'New submissions',
key: 'newSubmissions',
type: 'webhook',
description:
'Triggers when a new submission has been added to a specific form.',
arguments: [
{
label: 'Form',
key: 'formId',
type: 'dropdown',
required: true,
description: '',
variables: true,
source: {
type: 'query',
name: 'getDynamicData',
arguments: [
{
name: 'key',
value: 'listForms',
},
],
},
},
],
async run($) {
const dataItem = {
raw: $.request.body,
meta: {
internalId: Crypto.randomUUID(),
},
};
$.pushTriggerItem(dataItem);
},
async testRun($) {
const sampleEventData = {
ip: '127.0.0.1',
type: 'WEB',
appID: '',
event: '',
action: '',
formID: Crypto.randomUUID(),
parent: '',
pretty: 'Name:test, E-mail:user@automatisch.io',
teamID: '',
unread: '',
product: '',
subject: '',
isSilent: '',
username: 'username',
deviceIDs: 'Array',
formTitle: 'Opt-In Form-Get Free Email Updates!',
fromTable: '',
customBody: '',
documentID: '',
rawRequest: '',
webhookURL: '',
customTitle: '',
trackAction: 'Array',
customParams: '',
submissionID: Crypto.randomUUID(),
customBodyParams: 'Array',
customTitleParams: 'Array',
};
const dataItem = {
raw: sampleEventData,
meta: {
internalId: sampleEventData.submissionID,
},
};
$.pushTriggerItem(dataItem);
},
async registerHook($) {
const formId = $.step.parameters.formId;
const params = new URLSearchParams({
webhookURL: $.webhookUrl,
});
const { data } = await $.http.post(
`/form/${formId}/webhooks`,
params.toString()
);
await $.flow.setRemoteWebhookId(data.content[0]);
},
async unregisterHook($) {
const formId = $.step.parameters.formId;
const { data } = await $.http.get(`/form/${formId}/webhooks`);
const webhookURLs = Object.values(data.content);
const webhookId = webhookURLs.findIndex((url) => url === $.webhookUrl);
await $.http.delete(`/form/${formId}/webhooks/${webhookId}`);
},
});

Some files were not shown because too many files have changed in this diff Show More