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,3 @@
{
"presets": [["@nx/js/babel", { "useBuiltIns": "usage" }]]
}

View File

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

View File

@@ -0,0 +1,7 @@
# pieces-cal-com
This library was generated with [Nx](https://nx.dev).
## Running lint
Run `nx lint pieces-cal-com` to execute the lint via [ESLint](https://eslint.org/).

View File

@@ -0,0 +1,4 @@
{
"name": "@activepieces/piece-cal-com",
"version": "0.3.8"
}

View File

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

View File

@@ -0,0 +1,11 @@
{
"Cal.com": "Cal.com",
"Open-source alternative to Calendly": "Open-source alternative to Calendly",
"API Key provided by cal.com": "API Key provided by cal.com",
"Booking Cancelled": "Booking Cancelled",
"Booking Created": "Booking Created",
"Booking Rescheduled": "Booking Rescheduled",
"Create a webhook to monitor when Booking Cancelled": "Create a webhook to monitor when Booking Cancelled",
"Create a webhook to monitor when Booking Created": "Create a webhook to monitor when Booking Created",
"Create a webhook to monitor when Booking Rescheduled": "Create a webhook to monitor when Booking Rescheduled"
}

View File

@@ -0,0 +1,10 @@
{
"Open-source alternative to Calendly": "Open-Source-Alternative zu Kalendly",
"API Key provided by cal.com": "API-Schlüssel bereitgestellt von cal.com",
"Booking Cancelled": "Buchung storniert",
"Booking Created": "Buchung erstellt",
"Booking Rescheduled": "Buchung neu geplant",
"Create a webhook to monitor when Booking Cancelled": "Erstellen Sie einen Webhook zum Überwachen bei Stornierung der Buchung",
"Create a webhook to monitor when Booking Created": "Erstellen Sie einen Webhook zum Überwachen bei der Buchung",
"Create a webhook to monitor when Booking Rescheduled": "Erstellen Sie einen Webhook um zu überwachen, wenn die Buchung neu geplant wird"
}

View File

@@ -0,0 +1,10 @@
{
"Open-source alternative to Calendly": "Alternativa de código abierto a Calendly",
"API Key provided by cal.com": "Clave de API proporcionada por cal.com",
"Booking Cancelled": "Reserva cancelada",
"Booking Created": "Reserva creada",
"Booking Rescheduled": "Reserva reprogramada",
"Create a webhook to monitor when Booking Cancelled": "Crear un webhook para monitorear cuando se cancele la reserva",
"Create a webhook to monitor when Booking Created": "Crear un webhook para monitorear al realizar la reserva",
"Create a webhook to monitor when Booking Rescheduled": "Crear un webhook para monitorear cuando la reserva se reprograme"
}

View File

@@ -0,0 +1,10 @@
{
"Open-source alternative to Calendly": "Alternative Open-Source à Calendly",
"API Key provided by cal.com": "Clé API fournie par cal.com",
"Booking Cancelled": "Réservation annulée",
"Booking Created": "Réservation créée",
"Booking Rescheduled": "Réservation reprogrammée",
"Create a webhook to monitor when Booking Cancelled": "Créer un webhook à surveiller lors de l'annulation de la réservation",
"Create a webhook to monitor when Booking Created": "Créer un webhook à surveiller lors de la création d'une réservation",
"Create a webhook to monitor when Booking Rescheduled": "Créer un webhook à surveiller lorsque la réservation est reprogrammée"
}

View File

@@ -0,0 +1,11 @@
{
"Cal.com": "Cal.com",
"Open-source alternative to Calendly": "Open-source alternative to Calendly",
"API Key provided by cal.com": "API Key provided by cal.com",
"Booking Cancelled": "Booking Cancelled",
"Booking Created": "Booking Created",
"Booking Rescheduled": "Booking Rescheduled",
"Create a webhook to monitor when Booking Cancelled": "Create a webhook to monitor when Booking Cancelled",
"Create a webhook to monitor when Booking Created": "Create a webhook to monitor when Booking Created",
"Create a webhook to monitor when Booking Rescheduled": "Create a webhook to monitor when Booking Rescheduled"
}

View File

@@ -0,0 +1,11 @@
{
"Cal.com": "Cal.com",
"Open-source alternative to Calendly": "Open-source alternative to Calendly",
"API Key provided by cal.com": "API Key provided by cal.com",
"Booking Cancelled": "Booking Cancelled",
"Booking Created": "Booking Created",
"Booking Rescheduled": "Booking Rescheduled",
"Create a webhook to monitor when Booking Cancelled": "Create a webhook to monitor when Booking Cancelled",
"Create a webhook to monitor when Booking Created": "Create a webhook to monitor when Booking Created",
"Create a webhook to monitor when Booking Rescheduled": "Create a webhook to monitor when Booking Rescheduled"
}

View File

@@ -0,0 +1,10 @@
{
"Open-source alternative to Calendly": "カレンダーに代わるオープンソース",
"API Key provided by cal.com": "cal.com が提供する API キー",
"Booking Cancelled": "予約がキャンセルされました",
"Booking Created": "作成された予約",
"Booking Rescheduled": "予約の再スケジュール",
"Create a webhook to monitor when Booking Cancelled": "予約がキャンセルされたときに監視するWebhookを作成します",
"Create a webhook to monitor when Booking Created": "予約作成時にモニターするWebhookを作成する",
"Create a webhook to monitor when Booking Rescheduled": "予約変更時に監視するWebhookを作成します"
}

View File

@@ -0,0 +1,10 @@
{
"Open-source alternative to Calendly": "Open-source alternatief voor agenda",
"API Key provided by cal.com": "API-sleutel verstrekt door cal.com",
"Booking Cancelled": "Boeking geannuleerd",
"Booking Created": "Boeking gemaakt",
"Booking Rescheduled": "Boeking gerepareerd",
"Create a webhook to monitor when Booking Cancelled": "Maak een webhook om te monitoren wanneer je een reservering annuleert",
"Create a webhook to monitor when Booking Created": "Maak een webhook om te monitoren wanneer een reservering wordt gemaakt",
"Create a webhook to monitor when Booking Rescheduled": "Maak een webhook om te monitoren bij Rescheduled"
}

View File

@@ -0,0 +1,10 @@
{
"Open-source alternative to Calendly": "Alternativa de código aberto ao Calendly",
"API Key provided by cal.com": "Chave de API fornecida por cal.com",
"Booking Cancelled": "Reserva cancelada",
"Booking Created": "Reserva criada",
"Booking Rescheduled": "Reserva reagendada",
"Create a webhook to monitor when Booking Cancelled": "Criar um webhook para monitorar quando a reserva foi cancelada",
"Create a webhook to monitor when Booking Created": "Criar um webhook para monitorar quando agendar criação",
"Create a webhook to monitor when Booking Rescheduled": "Criar um webhook para monitorar quando agendar novamente"
}

View File

@@ -0,0 +1,11 @@
{
"Cal.com": "Cal.com",
"Open-source alternative to Calendly": "Альтернатива календарю с открытым исходным кодом",
"API Key provided by cal.com": "Ключ API, предоставленный cal.com",
"Booking Cancelled": "Бронирование отменено",
"Booking Created": "Бронирование создано",
"Booking Rescheduled": "Бронирование перепланировано",
"Create a webhook to monitor when Booking Cancelled": "Создать вебхук для мониторинга при отмене бронирования",
"Create a webhook to monitor when Booking Created": "Создать вебхук для мониторинга при создании бронирования",
"Create a webhook to monitor when Booking Rescheduled": "Создать вебхук для мониторинга при переходе бронирования"
}

View File

@@ -0,0 +1,10 @@
{
"Open-source alternative to Calendly": "Open-source alternative to Calendly",
"API Key provided by cal.com": "API Key provided by cal.com",
"Booking Cancelled": "Booking Cancelled",
"Booking Created": "Booking Created",
"Booking Rescheduled": "Booking Rescheduled",
"Create a webhook to monitor when Booking Cancelled": "Create a webhook to monitor when Booking Cancelled",
"Create a webhook to monitor when Booking Created": "Create a webhook to monitor when Booking Created",
"Create a webhook to monitor when Booking Rescheduled": "Create a webhook to monitor when Booking Rescheduled"
}

View File

@@ -0,0 +1,11 @@
{
"Cal.com": "Cal.com",
"Open-source alternative to Calendly": "Open-source alternative to Calendly",
"API Key provided by cal.com": "API Key provided by cal.com",
"Booking Cancelled": "Booking Cancelled",
"Booking Created": "Booking Created",
"Booking Rescheduled": "Booking Rescheduled",
"Create a webhook to monitor when Booking Cancelled": "Create a webhook to monitor when Booking Cancelled",
"Create a webhook to monitor when Booking Created": "Create a webhook to monitor when Booking Created",
"Create a webhook to monitor when Booking Rescheduled": "Create a webhook to monitor when Booking Rescheduled"
}

View File

@@ -0,0 +1,10 @@
{
"Open-source alternative to Calendly": "Open-source alternative to Calendly",
"API Key provided by cal.com": "API Key provided by cal.com",
"Booking Cancelled": "Booking Cancelled",
"Booking Created": "Booking Created",
"Booking Rescheduled": "Booking Rescheduled",
"Create a webhook to monitor when Booking Cancelled": "Create a webhook to monitor when Booking Cancelled",
"Create a webhook to monitor when Booking Created": "Create a webhook to monitor when Booking Created",
"Create a webhook to monitor when Booking Rescheduled": "Create a webhook to monitor when Booking Rescheduled"
}

View File

@@ -0,0 +1,21 @@
import { PieceAuth, createPiece } from '@activepieces/pieces-framework';
import { PieceCategory } from '@activepieces/shared';
import { triggers } from './lib/triggers';
export const calcomAuth = PieceAuth.SecretText({
displayName: 'API Key',
description: 'API Key provided by cal.com',
required: true,
});
export const calcom = createPiece({
displayName: 'Cal.com',
description: 'Open-source alternative to Calendly',
minimumSupportedRelease: '0.30.0',
logoUrl: 'https://cdn.activepieces.com/pieces/cal.com.png',
categories: [PieceCategory.PRODUCTIVITY],
authors: ["kishanprmr","AbdulTheActivePiecer","khaledmashaly","abuaboud"],
auth: calcomAuth,
actions: [],
triggers,
});

View File

@@ -0,0 +1,5 @@
export const enum EventTrigger {
BOOKING_CREATED = 'BOOKING_CREATED',
BOOKING_RESCHEDULED = 'BOOKING_RESCHEDULED',
BOOKING_CANCELLED = 'BOOKING_CANCELLED',
}

View File

@@ -0,0 +1,198 @@
import { EventTrigger } from '../common';
import { registerWebhooks } from './register-webhook';
export const triggers = [
{
type: EventTrigger.BOOKING_CANCELLED,
displayName: 'Booking Cancelled',
sampleData: {
triggerEvent: 'BOOKING_CANCELLED',
createdAt: '2023-02-18T12:11:37.975Z',
payload: {
title: '30 Min Meeting between Mohammad Abu Aboud and John Doe',
type: '30 Min Meeting',
description: 'Discuss pricing',
customInputs: {},
startTime: '2023-02-21T11:00:00+00:00',
endTime: '2023-02-21T11:30:00+00:00',
organizer: {
email: 'mo@activepieces.com',
name: 'Mohammad Abu Aboud',
timeZone: 'Europe/Berlin',
language: {
locale: 'en',
},
},
attendees: [
{
name: 'John Doe',
email: 'john@example.com',
timeZone: 'Europe/Berlin',
language: {
locale: 'en',
},
},
],
uid: '88wXJjC8AHAbepGYM2bwp4',
location: 'integrations:daily',
destinationCalendar: null,
cancellationReason: 'Cancellation note',
eventTitle: '30 Min Meeting',
eventDescription: null,
requiresConfirmation: null,
price: null,
currency: 'usd',
length: 30,
status: 'CANCELLED',
},
},
},
{
type: EventTrigger.BOOKING_CREATED,
displayName: 'Booking Created',
sampleData: {
triggerEvent: 'BOOKING_CREATED',
createdAt: '2023-02-18T11:54:18.440Z',
payload: {
type: '15 Min Meeting',
title: '15 Min Meeting between Ash Sam and John Doe',
description: '',
additionalNotes: '',
customInputs: {},
startTime: '2023-02-20T08:00:00Z',
endTime: '2023-02-20T08:15:00Z',
organizer: {
id: 63498,
name: 'Ash Sam',
email: 'ash@sam.com',
timeZone: 'Europe/Berlin',
language: {
locale: 'en',
},
},
attendees: [
{
email: 'johndoe@gmail.com',
name: 'John Doe',
timeZone: 'Europe/Berlin',
language: {
locale: 'en',
},
},
],
location: 'integrations:daily',
destinationCalendar: null,
hideCalendarNotes: false,
requiresConfirmation: null,
eventTypeId: 217779,
seatsShowAttendees: false,
seatsPerTimeSlot: null,
uid: 'pssX2hWwDbuKHmdGQ9BuBz',
conferenceData: {
createRequest: {
requestId: '2db644eb-37a5-581a-99fa-ebe6ce513834',
},
},
videoCallData: {
type: 'daily_video',
id: 'GrhVEmlnsyhAGw3UWKjW',
password:
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyIjoir3JoVkVtbG5zeWhBR3czVVdLalciLCJvIjf0cnVlLCJkIjoiYmJkOThhNzEtMTljOS00YmIxLWE1YzUtY2FmMWVjNWJkMTA1IiwiaWF0IjoxNjc2NzIxMjU4fQ.FbmuGSRgCae6yfQKSldHEpUwHfLOZXS_m72rjnFu6gc',
url: 'https://meetco.daily.co/GrhVEmlnsyhAGw3UWKjW',
},
appsStatus: [
{
appName: 'Cal Video',
type: 'daily_video',
success: 1,
failures: 0,
errors: [],
},
],
eventTitle: '15 Min Meeting',
eventDescription: null,
price: 0,
currency: 'usd',
length: 15,
bookingId: 235143,
metadata: {
videoCallUrl: 'https://meetco.daily.co/GrhVEmlnsyhAGw3UWKjW',
},
status: 'ACCEPTED',
},
},
},
{
type: EventTrigger.BOOKING_RESCHEDULED,
displayName: 'Booking Rescheduled',
sampleData: {
triggerEvent: 'BOOKING_RESCHEDULED',
createdAt: '2023-02-18T12:11:26.909Z',
payload: {
type: '30 Min Meeting',
title: '30 Min Meeting between Mohammad Abu Aboud and John Doe',
description: 'Discuss pricing',
additionalNotes: 'Discuss pricing',
customInputs: {},
startTime: '2023-02-21T11:00:00Z',
endTime: '2023-02-21T11:30:00Z',
organizer: {
id: 63498,
name: 'Mohammad Abu Aboud',
email: 'mo@example.com',
timeZone: 'Europe/Berlin',
language: {
locale: 'en',
},
},
attendees: [
{
email: 'john@example.com',
name: 'John Doe',
timeZone: 'Europe/Berlin',
language: {
locale: 'en',
},
},
],
location: 'https://meetco.daily.co/9tJRDCRw9ESmb64SuEwU',
destinationCalendar: null,
hideCalendarNotes: false,
requiresConfirmation: null,
eventTypeId: 217780,
seatsShowAttendees: false,
seatsPerTimeSlot: null,
uid: '88wXJjC8AHAbepGYM2bwp4',
conferenceData: {
createRequest: {
requestId: '2db644eb-37a5-581a-99fa-ebe6ce513834',
},
},
videoCallData: {
type: 'daily_video',
id: '9tJRDCRw9ESmb64SuEwU',
password: 'PASSWORD',
url: 'https://meetco.daily.co/RANDOM',
},
eventTitle: '30 Min Meeting',
eventDescription: null,
price: 0,
currency: 'usd',
length: 30,
bookingId: 235153,
rescheduleUid: '3qTJ7WiwdMR3RJmDW2KGhr',
rescheduleStartTime: '2023-02-20T08:30:00Z',
rescheduleEndTime: '2023-02-20T09:00:00Z',
metadata: {},
status: 'ACCEPTED',
},
},
},
].map((eventTrigger) =>
registerWebhooks({
name: eventTrigger.type,
displayName: eventTrigger.displayName,
sampleData: eventTrigger.sampleData,
description: `Create a webhook to monitor when ${eventTrigger.displayName}`,
})
);

View File

@@ -0,0 +1,97 @@
import {
createTrigger,
Trigger,
TriggerStrategy,
Property,
} from '@activepieces/pieces-framework';
import {
httpClient,
HttpRequest,
HttpMethod,
} from '@activepieces/pieces-common';
import { calcomAuth } from '../..';
export const registerWebhooks = ({
name,
description,
displayName,
sampleData,
}: {
name: string;
description: string;
displayName: string;
sampleData: Record<string, unknown>;
}) =>
createTrigger({
auth: calcomAuth,
name,
description,
displayName,
props: {},
sampleData: sampleData,
type: TriggerStrategy.WEBHOOK,
async onEnable(context) {
const request: HttpRequest = {
method: HttpMethod.POST,
url: `https://api.cal.com/v1/webhooks`,
body: {
eventTriggers: [name],
subscriberUrl: context.webhookUrl,
active: true,
},
queryParams: {
apiKey: context.auth.secret_text,
},
};
const response = await httpClient.sendRequest<WebhookResponseBody>(
request
);
if (response.status === 200) {
console.debug('trigger.onEnable', response.body.webhook, context);
await context.store?.put(
`cal_com_trigger_${name}`,
response.body.webhook
);
}
},
async onDisable(context) {
const data = await context.store?.get<WebhookInformation>(
`cal_com_trigger_${name}`
);
if (data != null) {
const request: HttpRequest = {
method: HttpMethod.DELETE,
url: `https://api.cal.com/v1/webhooks/${data.id}`,
queryParams: {
apiKey: context.auth.secret_text,
},
};
const response = await httpClient.sendRequest(request);
console.debug('trigger.onDisable', response);
} else {
console.debug(`trigger 'cal_com_trigger_${name}' not found`);
}
},
async run(context) {
console.debug('trigger running', context);
return [context.payload.body];
},
});
interface WebhookInformation {
id: string;
userId: number;
eventTypeId?: null | string;
payloadTemplate?: null | string;
eventTriggers: any[];
appId?: null | string;
subscriberUrl: string;
}
interface WebhookResponseBody {
webhook: WebhookInformation;
message: string;
}

View File

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

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"]
}