Add Activepieces integration for workflow automation

- Add Activepieces fork with SmoothSchedule custom piece
- Create integrations app with Activepieces service layer
- Add embed token endpoint for iframe integration
- Create Automations page with embedded workflow builder
- Add sidebar visibility fix for embed mode
- Add list inactive customers endpoint to Public API
- Include SmoothSchedule triggers: event created/updated/cancelled
- Include SmoothSchedule actions: create/update/cancel events, list resources/services/customers

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
poduck
2025-12-18 22:59:37 -05:00
parent 9848268d34
commit 3aa7199503
16292 changed files with 1284892 additions and 4708 deletions

View File

@@ -0,0 +1,33 @@
{
"extends": [
"../../../../.eslintrc.base.json"
],
"ignorePatterns": [
"!**/*"
],
"overrides": [
{
"files": [
"*.ts",
"*.tsx",
"*.js",
"*.jsx"
],
"rules": {}
},
{
"files": [
"*.ts",
"*.tsx"
],
"rules": {}
},
{
"files": [
"*.js",
"*.jsx"
],
"rules": {}
}
]
}

View File

@@ -0,0 +1,7 @@
# pieces-webling
This library was generated with [Nx](https://nx.dev).
## Building
Run `nx build pieces-webling` to build the library.

View File

@@ -0,0 +1,4 @@
{
"name": "@activepieces/piece-webling",
"version": "0.0.7"
}

View File

@@ -0,0 +1,65 @@
{
"name": "pieces-webling",
"$schema": "../../../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "packages/pieces/community/webling/src",
"projectType": "library",
"release": {
"version": {
"currentVersionResolver": "git-tag",
"preserveLocalDependencyProtocols": false,
"manifestRootsToUpdate": [
"dist/{projectRoot}"
]
}
},
"tags": [],
"targets": {
"build": {
"executor": "@nx/js:tsc",
"outputs": [
"{options.outputPath}"
],
"options": {
"outputPath": "dist/packages/pieces/community/webling",
"tsConfig": "packages/pieces/community/webling/tsconfig.lib.json",
"packageJson": "packages/pieces/community/webling/package.json",
"main": "packages/pieces/community/webling/src/index.ts",
"assets": [
"packages/pieces/community/webling/*.md",
{
"input": "packages/pieces/community/webling/src/i18n",
"output": "./src/i18n",
"glob": "**/!(i18n.json)"
}
],
"buildableProjectDepsInPackageJsonType": "dependencies",
"updateBuildableProjectDepsInPackageJson": true
},
"dependsOn": [
"^build",
"prebuild"
]
},
"nx-release-publish": {
"options": {
"packageRoot": "dist/{projectRoot}"
}
},
"lint": {
"executor": "@nx/eslint:lint",
"outputs": [
"{options.outputFile}"
]
},
"prebuild": {
"executor": "nx:run-commands",
"options": {
"cwd": "packages/pieces/community/webling",
"command": "bun install --no-save --silent"
},
"dependsOn": [
"^build"
]
}
}
}

View File

@@ -0,0 +1,14 @@
{
"Base URL": "Basis-URL",
"API Key": "API-Schlüssel",
"Get Events by ID": "Events per ID abrufen",
"Gets event data by a list of event IDs and optional calendar ID to filter.": "Ruft Ereignisdaten durch eine Liste von Ereignis-IDs und optionale Kalender-ID zum Filtern ab.",
"Event ID list": "Ereignis-ID-Liste",
"Calendar": "Kalender",
"Comma separated list of event IDs (e.g. '536,525,506,535'). When at least one ID doesn't exist the whole query return a 404 error.": "Durch Komma getrennte Liste von Ereignis-IDs (z.B. '536,525,506,535'). Wenn mindestens eine ID nicht existiert, gibt die ganze Abfrage einen 404-Fehler zurück.",
"Calendar to filter the events by.": "Kalender zum Filtern der Ereignisse.",
"New or Updated Event": "Neues oder aktualisiertes Ereignis",
"On Changed Data": "Bei geänderten Daten",
"Triggers when an event is added or updated.": "Wird ausgelöst, wenn ein Ereignis hinzugefügt oder aktualisiert wird.",
"Triggers when anything was added, updated or deleted since last request.": "Wird ausgelöst, wenn seit der letzten Anfrage etwas hinzugefügt, aktualisiert oder gelöscht wurde."
}

View File

@@ -0,0 +1,14 @@
{
"Base URL": "URL base",
"API Key": "Clave API",
"Get Events by ID": "Obtener eventos por ID",
"Gets event data by a list of event IDs and optional calendar ID to filter.": "Obtiene los datos del evento por una lista de IDs de eventos y el ID de calendario opcional para filtrar.",
"Event ID list": "Lista de eventos ID",
"Calendar": "Calendario",
"Comma separated list of event IDs (e.g. '536,525,506,535'). When at least one ID doesn't exist the whole query return a 404 error.": "Lista separada por comas de IDs de eventos (por ejemplo, '536,525,506,535'). Cuando al menos un ID no existe la consulta completa devuelve un error 404.",
"Calendar to filter the events by.": "Calendario para filtrar los eventos.",
"New or Updated Event": "Evento nuevo o actualizado",
"On Changed Data": "Al cambiar los datos",
"Triggers when an event is added or updated.": "Dispara cuando se agrega o actualiza un evento.",
"Triggers when anything was added, updated or deleted since last request.": "Dispara cuando algo fue añadido, actualizado o eliminado desde la última petición."
}

View File

@@ -0,0 +1,14 @@
{
"Base URL": "URL de base",
"API Key": "Clé API",
"Get Events by ID": "Obtenir des événements par ID",
"Gets event data by a list of event IDs and optional calendar ID to filter.": "Récupère les données d'événement par une liste d'ID d'événements et l'ID de calendrier facultatif à filtrer.",
"Event ID list": "Liste des ID d'événements",
"Calendar": "Calendrier",
"Comma separated list of event IDs (e.g. '536,525,506,535'). When at least one ID doesn't exist the whole query return a 404 error.": "Liste des ID d'événements séparés par des virgules (par exemple '536,525,506,535'). Quand au moins un ID n'existe pas, la requête entière renvoie une erreur 404.",
"Calendar to filter the events by.": "Calendrier pour filtrer les événements.",
"New or Updated Event": "Nouvel événement ou mise à jour",
"On Changed Data": "Sur les données modifiées",
"Triggers when an event is added or updated.": "Se déclenche lorsqu'un événement est ajouté ou mis à jour.",
"Triggers when anything was added, updated or deleted since last request.": "Déclenche quand quelque chose a été ajouté, mis à jour ou supprimé depuis la dernière requête."
}

View File

@@ -0,0 +1,14 @@
{
"Base URL": "ベースURL",
"API Key": "API キー",
"Get Events by ID": "イベントを ID で取得する",
"Gets event data by a list of event IDs and optional calendar ID to filter.": "イベント ID と任意のカレンダー ID のリストからフィルターを取得します。",
"Event ID list": "イベントIDリスト",
"Calendar": "カレンダー",
"Comma separated list of event IDs (e.g. '536,525,506,535'). When at least one ID doesn't exist the whole query return a 404 error.": "イベントIDのカンマ区切りのリスト'536,525,506,535'。少なくとも1つのIDが存在しない場合、クエリ全体が404エラーを返します。",
"Calendar to filter the events by.": "イベントをフィルタリングするカレンダーです。",
"New or Updated Event": "新規または更新されたイベント",
"On Changed Data": "変更されたデータ",
"Triggers when an event is added or updated.": "イベントが追加または更新されたときにトリガーします.",
"Triggers when anything was added, updated or deleted since last request.": "前回のリクエストから何かが追加されたとき、更新または削除されたときにトリガーします。"
}

View File

@@ -0,0 +1,14 @@
{
"Base URL": "Basis URL",
"API Key": "API Sleutel",
"Get Events by ID": "Events ophalen via ID",
"Gets event data by a list of event IDs and optional calendar ID to filter.": "Haalt gegevens van afspraken op met een lijst van event IDs en optionele kalender ID om te filteren.",
"Event ID list": "Event ID lijst",
"Calendar": "Kalender",
"Comma separated list of event IDs (e.g. '536,525,506,535'). When at least one ID doesn't exist the whole query return a 404 error.": "Kommagescheiden lijst met event IDs (bijv. '536,525,506,535'). Wanneer ten minste één ID niet bestaat geeft de hele query een 404 fout.",
"Calendar to filter the events by.": "Kalender om gebeurtenissen op te filteren.",
"New or Updated Event": "Nieuwe of Bijgewerkte gebeurtenis",
"On Changed Data": "Bij Gewijzigde gegevens",
"Triggers when an event is added or updated.": "Triggert wanneer een gebeurtenis wordt toegevoegd of bijgewerkt.",
"Triggers when anything was added, updated or deleted since last request.": "Triggers wanneer er iets is toegevoegd, bijgewerkt of verwijderd sinds de laatste aanvraag."
}

View File

@@ -0,0 +1,14 @@
{
"Base URL": "URL Base",
"API Key": "Chave de API",
"Get Events by ID": "Obter eventos por ID",
"Gets event data by a list of event IDs and optional calendar ID to filter.": "Obtém dados de evento por uma lista de IDs de evento e ID de calendário opcional para filtrar.",
"Event ID list": "Lista de ID",
"Calendar": "calendário",
"Comma separated list of event IDs (e.g. '536,525,506,535'). When at least one ID doesn't exist the whole query return a 404 error.": "Lista separada por vírgulas de IDs de eventos (por exemplo, '536,525,506,535'). Quando pelo menos um ID não existe, toda a consulta retorna um erro 404.",
"Calendar to filter the events by.": "Calendário para filtrar os eventos.",
"New or Updated Event": "Evento novo ou atualizado",
"On Changed Data": "Em Dados Alterados",
"Triggers when an event is added or updated.": "Dispara quando um evento é adicionado ou atualizado.",
"Triggers when anything was added, updated or deleted since last request.": "Dispara quando qualquer coisa foi adicionada, atualizada ou excluída desde a última solicitação."
}

View File

@@ -0,0 +1,15 @@
{
"Webling": "Ветер",
"Base URL": "Базовый URL",
"API Key": "Ключ API",
"Get Events by ID": "Получить события по ID",
"Gets event data by a list of event IDs and optional calendar ID to filter.": "Получает данные событий списком идентификаторов событий и необязательным идентификатором календаря для фильтрации.",
"Event ID list": "Список событий",
"Calendar": "Календарь",
"Comma separated list of event IDs (e.g. '536,525,506,535'). When at least one ID doesn't exist the whole query return a 404 error.": "Разделенный запятыми список идентификаторов событий (например, '536,525,506,535'). Если хотя бы один ID не существует весь запрос возвращает ошибку 404.",
"Calendar to filter the events by.": "Календарь для фильтрации событий.",
"New or Updated Event": "Новое или обновленное событие",
"On Changed Data": "При изменении данных",
"Triggers when an event is added or updated.": "Триггеры при добавлении или обновлении события.",
"Triggers when anything was added, updated or deleted since last request.": "Включает при добавлении, обновлении или удалении с момента последнего запроса."
}

View File

@@ -0,0 +1,14 @@
{
"Base URL": "Base URL",
"API Key": "API Key",
"Get Events by ID": "Get Events by ID",
"Gets event data by a list of event IDs and optional calendar ID to filter.": "Gets event data by a list of event IDs and optional calendar ID to filter.",
"Event ID list": "Event ID list",
"Calendar": "Calendar",
"Comma separated list of event IDs (e.g. '536,525,506,535'). When at least one ID doesn't exist the whole query return a 404 error.": "Comma separated list of event IDs (e.g. '536,525,506,535'). When at least one ID doesn't exist the whole query return a 404 error.",
"Calendar to filter the events by.": "Calendar to filter the events by.",
"New or Updated Event": "New or Updated Event",
"On Changed Data": "On Changed Data",
"Triggers when an event is added or updated.": "Triggers when an event is added or updated.",
"Triggers when anything was added, updated or deleted since last request.": "Triggers when anything was added, updated or deleted since last request."
}

View File

@@ -0,0 +1,15 @@
{
"Webling": "Webling",
"Base URL": "Base URL",
"API Key": "API Key",
"Get Events by ID": "Get Events by ID",
"Gets event data by a list of event IDs and optional calendar ID to filter.": "Gets event data by a list of event IDs and optional calendar ID to filter.",
"Event ID list": "Event ID list",
"Calendar": "Calendar",
"Comma separated list of event IDs (e.g. '536,525,506,535'). When at least one ID doesn't exist the whole query return a 404 error.": "Comma separated list of event IDs (e.g. '536,525,506,535'). When at least one ID doesn't exist the whole query return a 404 error.",
"Calendar to filter the events by.": "Calendar to filter the events by.",
"New or Updated Event": "New or Updated Event",
"On Changed Data": "On Changed Data",
"Triggers when an event is added or updated.": "Triggers when an event is added or updated.",
"Triggers when anything was added, updated or deleted since last request.": "Triggers when anything was added, updated or deleted since last request."
}

View File

@@ -0,0 +1,14 @@
{
"Base URL": "基本网址",
"API Key": "API 密钥",
"Get Events by ID": "Get Events by ID",
"Gets event data by a list of event IDs and optional calendar ID to filter.": "Gets event data by a list of event IDs and optional calendar ID to filter.",
"Event ID list": "Event ID list",
"Calendar": "Calendar",
"Comma separated list of event IDs (e.g. '536,525,506,535'). When at least one ID doesn't exist the whole query return a 404 error.": "Comma separated list of event IDs (e.g. '536,525,506,535'). When at least one ID doesn't exist the whole query return a 404 error.",
"Calendar to filter the events by.": "Calendar to filter the events by.",
"New or Updated Event": "New or Updated Event",
"On Changed Data": "On Changed Data",
"Triggers when an event is added or updated.": "Triggers when an event is added or updated.",
"Triggers when anything was added, updated or deleted since last request.": "Triggers when anything was added, updated or deleted since last request."
}

View File

@@ -0,0 +1,60 @@
import {
httpClient,
HttpMethod,
HttpRequest,
} from '@activepieces/pieces-common';
import {
createPiece,
PieceAuth,
Property,
} from '@activepieces/pieces-framework';
import { onEventChanged } from './lib/triggers/calendar-event';
import { onChangedData } from './lib/triggers/on-changed-data';
import { PieceCategory } from '@activepieces/shared';
import { eventsById } from './lib/actions/get-events-by-id';
export const weblingAuth = PieceAuth.CustomAuth({
required: true,
props: {
baseUrl: Property.ShortText({
displayName: 'Base URL',
required: true,
defaultValue: 'example.webling.ch',
}),
apikey: PieceAuth.SecretText({
displayName: 'API Key',
required: true,
}),
},
validate: async ({ auth }) => {
try {
const request: HttpRequest = {
method: HttpMethod.GET,
url: `https://${auth.baseUrl}/api/1/member`,
headers: {
apikey: auth.apikey,
},
};
await httpClient.sendRequest(request);
return {
valid: true,
};
} catch (e: any) {
return {
valid: false,
error: e?.message,
};
}
},
});
export const webling = createPiece({
displayName: 'Webling',
auth: weblingAuth,
minimumSupportedRelease: '0.30.0',
logoUrl: 'https://cdn.activepieces.com/pieces/webling.png',
categories: [PieceCategory.PRODUCTIVITY],
authors: ['felifluid'],
actions: [eventsById],
triggers: [onEventChanged, onChangedData],
});

View File

@@ -0,0 +1,62 @@
import { weblingAuth } from '../../index';
import { createAction, PiecePropValueSchema, Property } from '@activepieces/pieces-framework';
import { getCalendars, getEventsById } from '../common/helpers';
import { z } from 'zod';
import { propsValidation } from '@activepieces/pieces-common';
export const eventsById = createAction({
auth: weblingAuth,
name: 'EventsById',
displayName: 'Get Events by ID',
description:
'Gets event data by a list of event IDs and optional calendar ID to filter.',
props: {
eventIds: Property.ShortText({
displayName: 'Event ID list',
required: true,
description:
"Comma separated list of event IDs (e.g. '536,525,506,535'). When at least one ID doesn't exist the whole query return a 404 error.",
}),
calendarId: Property.Dropdown<string,false,typeof weblingAuth>({
auth: weblingAuth,
displayName: 'Calendar',
description: 'Calendar to filter the events by.',
refreshers: [],
required: false,
options: async ({ auth }) => {
if (!auth) {
return {
disabled: true,
placeholder: 'connect your account first',
options: [],
};
}
const authProp = auth;
const calendars = await getCalendars(authProp);
return {
disabled: false,
options: calendars.map((calendar) => {
return {
label: calendar.properties.title,
value: calendar.id,
};
}),
};
},
}),
},
async run(configValue) {
const { eventIds: eventIds, calendarId: calendarId } =
configValue.propsValue;
await propsValidation.validateZod(configValue.propsValue, {
eventIds: z.string().regex(/^\d+(,\d+)*$/),
});
const events = await getEventsById(configValue.auth, eventIds);
if (calendarId) {
return events.filter((event) => event.parents.includes(calendarId));
}
return events;
},
});

View File

@@ -0,0 +1,111 @@
import { weblingAuth } from '../../index';
import {
httpClient,
HttpMethod,
HttpRequest,
} from '@activepieces/pieces-common';
import { AppConnectionValueForAuthProperty, PiecePropValueSchema } from '@activepieces/pieces-framework';
import { CalendarObject, WeblingCalendarEvent, WeblingChanges } from './types';
export async function callApi<Type>(
authProp: AppConnectionValueForAuthProperty<typeof weblingAuth>,
request: string,
) {
const httpRequest: HttpRequest = {
method: HttpMethod.GET,
url: `https://${authProp.props.baseUrl}/api/1/${request}`,
headers: {
apikey: authProp.props.apikey,
},
};
const response = await httpClient.sendRequest<Type>(httpRequest);
return response;
}
export async function getChanges(
authProp: AppConnectionValueForAuthProperty<typeof weblingAuth>,
lastFetchEpochMS: number,
): Promise<WeblingChanges> {
// Webling API breaks if unix timestamp is too far in the past
if (lastFetchEpochMS === 0) {
const today = new Date();
const minUpdated = new Date();
minUpdated.setDate(today.getDate() - 7);
lastFetchEpochMS = minUpdated.getTime();
}
const response = await callApi<WeblingChanges>(
authProp,
`/changes/${lastFetchEpochMS / 1000}` // webling uses seconds instead of milliseconds
);
return response.body;
}
export async function getCalendars(
authProp: AppConnectionValueForAuthProperty<typeof weblingAuth>
): Promise<CalendarObject[]> {
const response = await callApi<CalendarObject[]>(
authProp,
'calendar?format=full'
);
return response.body;
}
export async function getAllEvents(
authProp: AppConnectionValueForAuthProperty<typeof weblingAuth>,
calendarId: string,
): Promise<WeblingCalendarEvent[]> {
const response = await callApi<WeblingCalendarEvent[]>(
authProp,
`calendarevent?filter=$parents.$id=${calendarId}&format=full`
);
return response.body;
}
export async function getEventsById(
authProp: AppConnectionValueForAuthProperty<typeof weblingAuth>,
eventIds: string,
): Promise<WeblingCalendarEvent[]> {
const request = `calendarevent/${eventIds}`
const response = await callApi<WeblingCalendarEvent[]>(
authProp,
request
);
return response.body;
};
export async function getUpdatedOrNewEvents(
authProp: AppConnectionValueForAuthProperty<typeof weblingAuth>,
calendarId: string,
lastFetchEpochMS: number
): Promise<WeblingCalendarEvent[]> {
// get changes since last call
const weblingChanges: WeblingChanges = await getChanges(
authProp,
lastFetchEpochMS / 1000
);
// this will also include ids of deleted objects
const changedEvents: string[] = weblingChanges.objects.calendarevents ?? [];
const deletedObjects: string[] = weblingChanges.deleted ?? [];
// filter out already deleted objects to treat seperately
// including a deleted event in a query list will result in a 404 response for the whole query
const updatedOrNewEvents: string[] = changedEvents.filter(
(event) => !deletedObjects.includes(event)
);
const response = await callApi<WeblingCalendarEvent[]>(
authProp,
`calendarevent/${updatedOrNewEvents.join(
','
)}?format=full&filter=$parents.$id=${calendarId}`
);
return response.body;
}

View File

@@ -0,0 +1,33 @@
import { PiecePropValueSchema, Property } from '@activepieces/pieces-framework';
import { getCalendars } from './helpers';
import { weblingAuth } from '../../index';
export const weblingCommon = {
calendarDropdown: () => {
return Property.Dropdown<string,true,typeof weblingAuth>({
auth: weblingAuth,
displayName: 'Calendar',
refreshers: [],
required: true,
options: async ({ auth }) => {
if (!auth) {
return {
disabled: true,
placeholder: 'connect your account first',
options: [],
};
}
const calendars = await getCalendars(auth);
return {
disabled: false,
options: calendars.map((calendar) => {
return {
label: calendar.properties.title,
value: calendar.id,
};
}),
};
},
});
},
};

View File

@@ -0,0 +1,111 @@
export interface MetaObject {
created: string;
createuser: {
label: string;
type: string;
};
lastmodified: string;
lastmodifieduser: {
label: string;
type: string;
};
}
export interface CalendarObject {
type: string;
meta: MetaObject;
readonly: boolean;
properties: {
title: string;
color: string;
isPublic: boolean;
publicHash: string;
icsHash: string;
};
parents: [];
children: {
calendarevent: string[];
};
links: object;
id: string;
}
export interface CalendarList {
objects: CalendarObject[];
}
export interface WeblingCalendarEvent {
type: 'calendarevent';
meta: MetaObject;
readonly: boolean;
properties: {
title: string;
description: string;
place: string;
begin: string;
end: string;
duration: string;
isAllDay: boolean;
isRecurring: boolean;
status: string;
recurrencePattern: string | null;
enableParticipantSignup: boolean;
enableParticipantMaybeState: boolean;
isSignupBinding: boolean;
maxParticipants: string | null;
signedupParticipants: string;
signupAllowedUntil: string | null;
doAutoAcceptParticipants: boolean;
questionSchema: string | null;
showParticipationsInPortal: boolean;
showAllAnswersInPortal: boolean;
};
parents: string[];
children: object;
links: object;
}
export interface WeblingChanges {
objects: WeblingObjectTypes;
deleted: string[];
context: object[];
definitions: object[];
settings: boolean;
quota: boolean;
subscription: boolean;
revision: string;
version: string;
}
// this list might be incomplete
export interface WeblingObjectTypes {
account?: string[];
accountgroup?: string[];
accountgrouptemplate?: string[];
accounttemplate?: string[];
apikey?: string[];
article?: string[];
articlegroup?: string[];
calendar?: string[];
calendarevents?: string[];
comment?: string[];
debitor?: string[];
debitorcategory?: string[];
document?: string[];
domain?: string[];
email?: string[];
entry?: string[];
entrygroup?: string[];
file?: string[];
member?: string[];
memberform?: string[];
membergroup?: string[];
page?: string[];
participant?: string[];
period?: string[];
periodchain?: string[];
periodgroup?: string[];
settings?: string[];
template?: string[];
user?: string[];
}

View File

@@ -0,0 +1,87 @@
import {
createTrigger,
TriggerStrategy,
PiecePropValueSchema,
AppConnectionValueForAuthProperty,
} from '@activepieces/pieces-framework';
import {
DedupeStrategy,
Polling,
pollingHelper,
} from '@activepieces/pieces-common';
import { weblingAuth } from '../../index';
import { weblingCommon } from '../common';
import { WeblingCalendarEvent } from '../common/types';
import { getUpdatedOrNewEvents } from '../common/helpers';
const polling: Polling<
AppConnectionValueForAuthProperty<typeof weblingAuth>,
{ calendarId?: string }
> = {
strategy: DedupeStrategy.TIMEBASED,
items: async ({ auth, propsValue: { calendarId }, lastFetchEpochMS }) => {
// implement the logic to fetch the items
const items: WeblingCalendarEvent[] =
(await getUpdatedOrNewEvents(auth, calendarId!, lastFetchEpochMS)) ?? [];
return items.map((item) => ({
epochMilliSeconds: new Date(item.meta.lastmodified).getTime(),
data: item,
}));
},
};
export const onEventChanged = createTrigger({
auth: weblingAuth,
name: 'onEventChanged',
displayName: 'New or Updated Event',
description: 'Triggers when an event is added or updated.',
props: {
calendarId: weblingCommon.calendarDropdown(),
},
sampleData: {},
type: TriggerStrategy.POLLING,
async test(context) {
const { store, auth, propsValue } = context;
return await pollingHelper.test(polling, {
store,
auth,
propsValue: {
calendarId: propsValue.calendarId,
},
files: context.files,
});
},
async onEnable(context) {
const { store, auth, propsValue } = context;
await pollingHelper.onEnable(polling, {
store,
auth,
propsValue: {
calendarId: propsValue.calendarId,
},
});
},
async onDisable(context) {
const { store, auth, propsValue } = context;
await pollingHelper.onDisable(polling, {
store,
auth,
propsValue: {
calendarId: propsValue.calendarId,
},
});
},
async run(context) {
const { store, auth, propsValue } = context;
return await pollingHelper.poll(polling, {
store,
auth,
propsValue: {
calendarId: propsValue.calendarId,
},
files: context.files,
});
},
});

View File

@@ -0,0 +1,119 @@
import {
createTrigger,
TriggerStrategy,
PiecePropValueSchema,
AppConnectionValueForAuthProperty,
} from '@activepieces/pieces-framework';
import {
DedupeStrategy,
Polling,
pollingHelper,
} from '@activepieces/pieces-common';
import { weblingAuth } from '../../index';
import { WeblingChanges } from '../common/types';
import { getChanges } from '../common/helpers';
const polling: Polling<
AppConnectionValueForAuthProperty<typeof weblingAuth>,
{ calendarId?: string }
> = {
strategy: DedupeStrategy.TIMEBASED,
items: async ({ auth, propsValue, lastFetchEpochMS }) => {
const changes: WeblingChanges = await getChanges(auth, lastFetchEpochMS);
const items = [
{
epochMilliSeconds: Date.now(), // maybe use revision instead?
data: changes,
},
];
return items;
},
};
export const onChangedData = createTrigger({
auth: weblingAuth,
name: 'onChangedData',
displayName: 'On Changed Data',
description:
'Triggers when anything was added, updated or deleted since last request.',
props: {},
sampleData: {
objects: {
account: [244, 246],
accountgroup: [242],
accountgrouptemplate: [241],
accounttemplate: [243, 245, 247, 248, 250],
apikey: [5241],
article: [4579, 4580],
articlegroup: [4578],
calendar: [235, 4428],
calendarevent: [4431, 4434, 4435, 4436],
comment: [4423],
debitor: [1205, 1208],
debitorcategory: [650],
document: [4506],
documentgroup: [114],
domain: [1771],
email: [5085],
entry: [321, 323, 338],
entrygroup: [320, 322, 337],
file: [4525],
member: [4270, 4271, 398, 399],
memberform: [4491],
membergroup: [100],
page: [4495],
participant: [4460],
period: [240],
periodchain: [239],
periodgroup: [238],
settings: [233],
template: [228],
user: [120, 343, 345],
},
deleted: [235],
context: [],
definitions: ['member'],
settings: false,
quota: true,
subscription: true,
revision: 4758,
version: 2560,
},
type: TriggerStrategy.POLLING,
async test(context) {
const { store, auth, propsValue } = context;
return await pollingHelper.test(polling, {
store,
auth,
propsValue,
files: context.files,
});
},
async onEnable(context) {
const { store, auth, propsValue } = context;
await pollingHelper.onEnable(polling, {
store,
auth,
propsValue,
});
},
async onDisable(context) {
const { store, auth, propsValue } = context;
await pollingHelper.onDisable(polling, {
store,
auth,
propsValue,
});
},
async run(context) {
const { store, auth, propsValue } = context;
return await pollingHelper.poll(polling, {
store,
auth,
propsValue,
files: context.files,
});
},
});

View File

@@ -0,0 +1,19 @@
{
"extends": "../../../../tsconfig.base.json",
"compilerOptions": {
"module": "commonjs",
"forceConsistentCasingInFileNames": true,
"strict": true,
"noImplicitOverride": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"noPropertyAccessFromIndexSignature": true
},
"files": [],
"include": [],
"references": [
{
"path": "./tsconfig.lib.json"
}
]
}

View File

@@ -0,0 +1,11 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"module": "commonjs",
"outDir": "../../../../dist/out-tsc",
"declaration": true,
"types": ["node"]
},
"exclude": ["jest.config.ts", "src/**/*.spec.ts", "src/**/*.test.ts"],
"include": ["src/**/*.ts"]
}