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,88 @@
import { createTrigger, TriggerStrategy } from '@activepieces/pieces-framework';
import { systemeIoAuth } from '../common/auth';
import { systemeIoCommon } from '../common/client';
import { randomBytes } from 'crypto';
export const newContact = createTrigger({
auth: systemeIoAuth,
name: 'newContact',
displayName: 'New Contact',
description: 'Fires when a new contact is created',
props: {},
sampleData: {
contact: {
id: 12345,
email: "email@example.com",
registeredAt: "2024-01-01T00:00:00+00:00",
locale: "en",
sourceURL: null,
unsubscribed: false,
bounced: false,
needsConfirmation: false,
fields: [
{
fieldName: "first_name",
slug: "first_name",
value: "John"
},
{
fieldName: "last_name",
slug: "last_name",
value: "Doe"
},
{
fieldName: "phone_number",
slug: "phone_number",
value: "+1234567890"
}
],
tags: [
{
id: 1,
name: "new_customer"
},
{
id: 2,
name: "email_subscriber"
}
]
}
},
type: TriggerStrategy.WEBHOOK,
async onEnable(context) {
const secret = randomBytes(32).toString('hex');
const response = await systemeIoCommon.createWebhook({
eventType: 'CONTACT_CREATED',
webhookUrl: context.webhookUrl,
auth: context.auth.secret_text,
secret: secret,
});
await context.store.put('new_contact_webhook_id', response.id);
await context.store.put('new_contact_webhook_secret', secret);
},
async onDisable(context) {
const webhookId = await context.store.get<string>('new_contact_webhook_id');
if (webhookId) {
await systemeIoCommon.deleteWebhook({
webhookId,
auth: context.auth.secret_text,
});
await context.store.put('new_contact_webhook_id', null);
await context.store.put('new_contact_webhook_secret', null);
}
},
async run(context) {
const webhookSecret = await context.store.get<string>('new_contact_webhook_secret');
const webhookSignatureHeader = context.payload.headers['x-webhook-signature'];
const rawBody = context.payload.rawBody;
if (!systemeIoCommon.verifyWebhookSignature(webhookSecret || undefined, webhookSignatureHeader, rawBody)) {
console.warn('Systeme.io webhook signature verification failed');
return [];
}
const payload = context.payload.body as any;
return [payload.contact || payload];
}
});

View File

@@ -0,0 +1,84 @@
import { createTrigger, TriggerStrategy } from '@activepieces/pieces-framework';
import { systemeIoAuth } from '../common/auth';
import { systemeIoCommon } from '../common/client';
import { randomBytes } from 'crypto';
export const newSale = createTrigger({
auth: systemeIoAuth,
name: 'newSale',
displayName: 'New Sale',
description: 'Fires when a new purchase is made within a funnel',
props: {},
sampleData: {
sale: {
id: 67890,
amount: 99.99,
currency: "USD",
status: "completed",
createdAt: "2024-01-01T00:00:00+00:00",
updatedAt: "2024-01-01T00:00:00+00:00",
product: {
id: 123,
name: "Premium Course",
type: "digital_product"
},
funnel: {
id: 456,
name: "Sales Funnel",
step: "checkout"
},
contact: {
id: 12345,
email: "customer@example.com",
firstName: "John",
lastName: "Doe"
},
payment: {
method: "stripe",
transactionId: "txn_1234567890",
gateway: "stripe"
},
affiliate: {
id: null,
commission: null
}
}
},
type: TriggerStrategy.WEBHOOK,
async onEnable(context) {
const secret = randomBytes(32).toString('hex');
const response = await systemeIoCommon.createWebhook({
eventType: 'SALE_NEW',
webhookUrl: context.webhookUrl,
auth: context.auth.secret_text,
secret: secret,
});
await context.store.put('new_sale_webhook_id', response.id);
await context.store.put('new_sale_webhook_secret', secret);
},
async onDisable(context) {
const webhookId = await context.store.get<string>('new_sale_webhook_id');
if (webhookId) {
await systemeIoCommon.deleteWebhook({
webhookId,
auth: context.auth.secret_text,
});
await context.store.put('new_sale_webhook_id', null);
await context.store.put('new_sale_webhook_secret', null);
}
},
async run(context) {
const webhookSecret = await context.store.get<string>('new_sale_webhook_secret');
const webhookSignatureHeader = context.payload.headers['x-webhook-signature'];
const rawBody = context.payload.rawBody;
if (!systemeIoCommon.verifyWebhookSignature(webhookSecret || undefined, webhookSignatureHeader, rawBody)) {
console.warn('Systeme.io webhook signature verification failed');
return [];
}
const payload = context.payload.body as any;
return [payload.sale || payload];
}
});

View File

@@ -0,0 +1,93 @@
import { createTrigger, TriggerStrategy } from '@activepieces/pieces-framework';
import { systemeIoAuth } from '../common/auth';
import { systemeIoCommon } from '../common/client';
import { randomBytes } from 'crypto';
export const newTagAddedToContact = createTrigger({
auth: systemeIoAuth,
name: 'newTagAddedToContact',
displayName: 'New Tag Added to Contact',
description: 'Fires when a specific tag is assigned to a contact',
props: {},
sampleData: {
contact: {
id: 12345,
email: "customer@example.com",
registeredAt: "2024-01-01T00:00:00+00:00",
locale: "en",
sourceURL: null,
unsubscribed: false,
bounced: false,
needsConfirmation: false,
fields: [
{
fieldName: "first_name",
slug: "first_name",
value: "John"
},
{
fieldName: "last_name",
slug: "last_name",
value: "Doe"
},
{
fieldName: "phone_number",
slug: "phone_number",
value: "+1234567890"
}
],
tags: [
{
id: 1,
name: "existing_customer"
},
{
id: 2,
name: "VIP Customer"
}
]
},
tag: {
id: 2,
name: "VIP Customer"
},
addedAt: "2024-01-01T10:30:00+00:00"
},
type: TriggerStrategy.WEBHOOK,
async onEnable(context) {
const secret = randomBytes(32).toString('hex');
const response = await systemeIoCommon.createWebhook({
eventType: 'CONTACT_TAG_ADDED',
webhookUrl: context.webhookUrl,
auth: context.auth.secret_text ,
secret: secret,
});
await context.store.put('new_tag_added_webhook_id', response.id);
await context.store.put('new_tag_added_webhook_secret', secret);
},
async onDisable(context) {
const webhookId = await context.store.get<string>('new_tag_added_webhook_id');
if (webhookId) {
await systemeIoCommon.deleteWebhook({
webhookId,
auth: context.auth.secret_text,
});
await context.store.put('new_tag_added_webhook_id', null);
await context.store.put('new_tag_added_webhook_secret', null);
}
},
async run(context) {
const webhookSecret = await context.store.get<string>('new_tag_added_webhook_secret');
const webhookSignatureHeader = context.payload.headers['x-webhook-signature'];
const rawBody = context.payload.rawBody;
if (!systemeIoCommon.verifyWebhookSignature(webhookSecret || undefined, webhookSignatureHeader, rawBody)) {
console.warn('Systeme.io webhook signature verification failed');
return [];
}
const payload = context.payload.body as any;
return [payload];
}
});