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,13 @@
{
"Google Cloud's event streaming service": "Google-Cloud-Streaming-Dienst",
"Service Key (JSON)": "Service-Schlüssel (JSON)",
"\nYou can get it from the [Google Cloud Console](https://console.cloud.google.com/apis/credentials/serviceaccountkey).\n": "\nDu kannst es von der [Google Cloud Console](https://console.cloud.google.com/apis/credentials/serviceaccountkey).\n",
"Publish to topic": "Im Thema veröffentlichen",
"Publish message to topic": "Nachricht zu Thema veröffentlichen",
"Message": "Nachricht",
"Topic": "Thema",
"New Message": "Neue Nachricht",
"Trigger when a new message is sended.": "Auslösen wenn eine neue Nachricht gesendet wird.",
"Subscription name": "Name des Abonnements",
"Ack Deadline Seconds": "Ack Deadline Sekunden"
}

View File

@@ -0,0 +1,13 @@
{
"Google Cloud's event streaming service": "Servicio de streaming de eventos de Google Cloud",
"Service Key (JSON)": "Clave de servicio (JSON)",
"\nYou can get it from the [Google Cloud Console](https://console.cloud.google.com/apis/credentials/serviceaccountkey).\n": "\nYou can get it from the [Google Cloud Console](https://console.cloud.google.com/apis/credentials/serviceaccountkey).\n",
"Publish to topic": "Publicar en el tema",
"Publish message to topic": "Publicar mensaje al tema",
"Message": "Mensaje",
"Topic": "Tema",
"New Message": "Nuevo mensaje",
"Trigger when a new message is sended.": "Activar cuando se envía un nuevo mensaje.",
"Subscription name": "Nombre de la suscripción",
"Ack Deadline Seconds": "Ack Plazo segundos"
}

View File

@@ -0,0 +1,13 @@
{
"Google Cloud's event streaming service": "Service de streaming d'événements Google Cloud",
"Service Key (JSON)": "Clé de service (JSON)",
"\nYou can get it from the [Google Cloud Console](https://console.cloud.google.com/apis/credentials/serviceaccountkey).\n": "\nYou can get it from the [Google Cloud Console](https://console.cloud.google.com/apis/credentials/serviceaccountkey).\n",
"Publish to topic": "Publier sur le sujet",
"Publish message to topic": "Publier le message sur le sujet",
"Message": "Message",
"Topic": "Sujet",
"New Message": "Nouveau message",
"Trigger when a new message is sended.": "Déclencher lorsqu'un nouveau message est envoyé.",
"Subscription name": "Nom de l'abonnement",
"Ack Deadline Seconds": "Secondes d'échéance Ack"
}

View File

@@ -0,0 +1,13 @@
{
"Google Cloud's event streaming service": "Google Cloudのイベントストリーミングサービス",
"Service Key (JSON)": "サービスキー (JSON)",
"\nYou can get it from the [Google Cloud Console](https://console.cloud.google.com/apis/credentials/serviceaccountkey).\n": "\n[Google Cloud Console](https://console.cloud.google.com/apis/credentials/serviceaccountkey)から入手できます。\n",
"Publish to topic": "トピックに公開",
"Publish message to topic": "メッセージをトピックに公開",
"Message": "メッセージ",
"Topic": "トピック",
"New Message": "新しいメッセージ",
"Trigger when a new message is sended.": "新しいメッセージが送信されたときにトリガーします。",
"Subscription name": "サブスクリプション名",
"Ack Deadline Seconds": "Ack 締切秒"
}

View File

@@ -0,0 +1,13 @@
{
"Google Cloud's event streaming service": "Google Cloud's evenement streaming-service",
"Service Key (JSON)": "Service Key (JSON)",
"\nYou can get it from the [Google Cloud Console](https://console.cloud.google.com/apis/credentials/serviceaccountkey).\n": "\nU kunt het halen uit de [Google Cloud Console](https://console.cloud.google.com/apis/credentials/serviceaccountkey).\n",
"Publish to topic": "Publiceer naar onderwerp",
"Publish message to topic": "Publiceer bericht naar onderwerp",
"Message": "bericht",
"Topic": "Onderwerp",
"New Message": "Nieuw bericht",
"Trigger when a new message is sended.": "Trigger wanneer een nieuw bericht wordt verzonden.",
"Subscription name": "Naam abonnement",
"Ack Deadline Seconds": "Ack Deadline Seconden"
}

View File

@@ -0,0 +1,13 @@
{
"Google Cloud's event streaming service": "Serviço de streaming de eventos do Google Cloud",
"Service Key (JSON)": "Chave de Serviço (JSON)",
"\nYou can get it from the [Google Cloud Console](https://console.cloud.google.com/apis/credentials/serviceaccountkey).\n": "\nYou can get it from the [Google Cloud Console](https://console.cloud.google.com/apis/credentials/serviceaccountkey).\n",
"Publish to topic": "Publicar no tópico",
"Publish message to topic": "Publicar mensagem no tópico",
"Message": "mensagem",
"Topic": "Tópico",
"New Message": "Nova mensagem",
"Trigger when a new message is sended.": "Ativar quando uma nova mensagem for enviada.",
"Subscription name": "Nome da assinatura",
"Ack Deadline Seconds": "Segundos de Prazo Ak"
}

View File

@@ -0,0 +1,14 @@
{
"GCloud Pub/Sub": "GCloud Pub/Sub",
"Google Cloud's event streaming service": "Потоковая служба событий Google Cloud",
"Service Key (JSON)": "Ключ службы (JSON)",
"\nYou can get it from the [Google Cloud Console](https://console.cloud.google.com/apis/credentials/serviceaccountkey).\n": "\nYou can get it from the [Google Cloud Console](https://console.cloud.google.com/apis/credentials/serviceaccountkey).\n",
"Publish to topic": "Опубликовать в теме",
"Publish message to topic": "Опубликовать сообщение в теме",
"Message": "Сообщение",
"Topic": "Тема",
"New Message": "Новое сообщение",
"Trigger when a new message is sended.": "Срабатывать при отправке нового сообщения.",
"Subscription name": "Название подписки",
"Ack Deadline Seconds": "Секунды срока действия Ack"
}

View File

@@ -0,0 +1,13 @@
{
"Google Cloud's event streaming service": "Google Cloud's event streaming service",
"Service Key (JSON)": "Service Key (JSON)",
"\nYou can get it from the [Google Cloud Console](https://console.cloud.google.com/apis/credentials/serviceaccountkey).\n": "\nYou can get it from the [Google Cloud Console](https://console.cloud.google.com/apis/credentials/serviceaccountkey).\n",
"Publish to topic": "Publish to topic",
"Publish message to topic": "Publish message to topic",
"Message": "Message",
"Topic": "Topic",
"New Message": "New Message",
"Trigger when a new message is sended.": "Trigger when a new message is sended.",
"Subscription name": "Subscription name",
"Ack Deadline Seconds": "Ack Deadline Seconds"
}

View File

@@ -0,0 +1,14 @@
{
"GCloud Pub/Sub": "GCloud Pub/Sub",
"Google Cloud's event streaming service": "Google Cloud's event streaming service",
"Service Key (JSON)": "Service Key (JSON)",
"\nYou can get it from the [Google Cloud Console](https://console.cloud.google.com/apis/credentials/serviceaccountkey).\n": "\nYou can get it from the [Google Cloud Console](https://console.cloud.google.com/apis/credentials/serviceaccountkey).\n",
"Publish to topic": "Publish to topic",
"Publish message to topic": "Publish message to topic",
"Message": "Message",
"Topic": "Topic",
"New Message": "New Message",
"Trigger when a new message is sended.": "Trigger when a new message is sended.",
"Subscription name": "Subscription name",
"Ack Deadline Seconds": "Ack Deadline Seconds"
}

View File

@@ -0,0 +1,13 @@
{
"Google Cloud's event streaming service": "Google Cloud's event streaming service",
"Service Key (JSON)": "Service Key (JSON)",
"\nYou can get it from the [Google Cloud Console](https://console.cloud.google.com/apis/credentials/serviceaccountkey).\n": "\nYou can get it from the [Google Cloud Console](https://console.cloud.google.com/apis/credentials/serviceaccountkey).\n",
"Publish to topic": "Publish to topic",
"Publish message to topic": "Publish message to topic",
"Message": "Message",
"Topic": "Topic",
"New Message": "New Message",
"Trigger when a new message is sended.": "Trigger when a new message is sended.",
"Subscription name": "Subscription name",
"Ack Deadline Seconds": "Ack Deadline Seconds"
}

View File

@@ -0,0 +1,63 @@
import {
PieceAuth,
Property,
createPiece,
} from '@activepieces/pieces-framework';
import { PieceCategory } from '@activepieces/shared';
import { publishToTopic } from './lib/action/publish-to-topic';
import { common } from './lib/common';
import { newMessageInTopic } from './lib/trigger/new-message-in-topic';
const authDescription = `
You can get it from the [Google Cloud Console](https://console.cloud.google.com/apis/credentials/serviceaccountkey).
`;
export const googlePubsubAuth = PieceAuth.CustomAuth({
description: authDescription,
required: true,
props: {
json: Property.LongText({
displayName: 'Service Key (JSON)',
required: true,
}),
},
validate: async ({ auth }) => {
try {
const client = common.getClient(auth.json);
await client.request({
url: `https://pubsub.googleapis.com/v1/projects/${common.getProjectId(
auth.json
)}/topics`,
});
return {
valid: true,
};
} catch (e: any) {
if ('response' in e) {
console.debug(
`Auth Gcloud pubsub status: ${
e.response.status
}, data: ${JSON.stringify(e.response.data)}`
);
}
return {
valid: false,
error:
'Connection failed. Please check your Private Key, Email or Project ID.',
};
}
},
});
export const gcloudPubsub = createPiece({
displayName: 'GCloud Pub/Sub',
description: "Google Cloud's event streaming service",
minimumSupportedRelease: '0.30.0',
logoUrl: 'https://cdn.activepieces.com/pieces/gcloud-pubsub.png',
categories: [PieceCategory.DEVELOPER_TOOLS],
auth: googlePubsubAuth,
authors: ["DGurskij","kishanprmr","khaledmashaly","abuaboud"],
actions: [publishToTopic],
triggers: [newMessageInTopic],
});

View File

@@ -0,0 +1,54 @@
import { createAction, Property } from '@activepieces/pieces-framework';
import { common } from '../common';
import { googlePubsubAuth } from '../..';
export const publishToTopic = createAction({
name: 'publish_to_topic',
auth: googlePubsubAuth,
displayName: 'Publish to topic',
description: 'Publish message to topic',
props: {
message: Property.Object({
displayName: 'Message',
required: true,
}),
topic: Property.Dropdown({
displayName: 'Topic',
required: true,
refreshers: ['auth'],
auth: googlePubsubAuth,
options: async ({ auth }) => {
if (!auth) {
return {
disabled: true,
options: [],
placeholder: 'Please authenticate first',
};
}
const json = auth.props.json;
return common.getTopics(json);
},
}),
},
async run(context) {
const client = common.getClient(context.auth.props.json);
const topic = context.propsValue.topic;
const url = `https://pubsub.googleapis.com/v1/${topic}:publish`;
const json = JSON.stringify(context.propsValue.message);
const body = JSON.stringify({
messages: [{ data: Buffer.from(json).toString('base64') }],
});
const { data } = await client.request<{ messageIds: string[] }>({
url,
method: 'POST',
body,
});
console.debug(
`Message sended to topic[${topic}]: ${json}, ack: ${data.messageIds[0]}`
);
return json;
},
});

View File

@@ -0,0 +1,71 @@
import { JWT } from 'google-auth-library';
export const common = {
getClient(authJson: string) {
const email = common.getEmail(authJson);
const privateKey = common.getPrivateKey(authJson);
const gaxios = new JWT({
email,
key: privateKey.replace(/\\n/g, '\n'), // remove duplicate '\' from client side
scopes: ['https://www.googleapis.com/auth/pubsub'],
});
return gaxios;
},
getProjectId(json: string) {
return JSON.parse(json).project_id;
},
getPrivateKey(json: string) {
return JSON.parse(json).private_key;
},
getEmail(json: string) {
return JSON.parse(json).client_email;
},
/**
* @returns options topics, topic value contain project name: projects/{pname}/topics/{tname}
*/
async getTopics(json: string) {
const client = common.getClient(json);
const topics = {
disabled: true,
options: [] as { label: string; value: string }[],
placeholder: 'Need authentication' as string | undefined,
};
try {
const response = await client.request<ITopicsInfo>({
url: `https://pubsub.googleapis.com/v1/projects/${this.getProjectId(
json
)}/topics`,
method: 'GET',
});
topics.options = response.data.topics.map((topic) => {
const topicName = topic.name.split('topics/')[1];
return { label: `${topicName}`, value: topic.name };
});
delete topics.placeholder;
topics.disabled = false;
} catch (e: any) {
if ('response' in e) {
topics.placeholder = `Get topics error: ${e.response.data.error}`;
console.debug(e.response.data.error);
}
}
return topics;
},
};
export interface IAuth {
email: string;
privateKey: string;
projectId: string;
}
export interface ITopicsInfo {
topics: { name: string }[];
}

View File

@@ -0,0 +1,110 @@
import { Property, createTrigger } from '@activepieces/pieces-framework';
import { TriggerStrategy } from '@activepieces/pieces-framework';
import { googlePubsubAuth } from '../..';
import { common } from '../common';
export const newMessageInTopic = createTrigger({
auth: googlePubsubAuth,
name: 'new_message_in_topic',
displayName: 'New Message',
description: 'Trigger when a new message is sended.',
props: {
subscription: Property.ShortText({
displayName: 'Subscription name',
required: true,
}),
topic: Property.Dropdown({
displayName: 'Topic',
required: true,
auth: googlePubsubAuth,
refreshers: ['auth'],
options: async ({ auth }) => {
if (!auth) {
return {
disabled: true,
options: [],
placeholder: 'Please authenticate first',
};
}
const json = auth.props.json;
return common.getTopics(json);
},
}),
ackDeadlineSeconds: Property.Number({
displayName: 'Ack Deadline Seconds',
required: true,
defaultValue: 100,
}),
},
type: TriggerStrategy.WEBHOOK,
onEnable: async (context) => {
const json = context.auth.props.json;
const client = common.getClient(json);
const { topic, subscription } = context.propsValue;
const project = common.getProjectId(context.auth.props.json);
const url = `https://pubsub.googleapis.com/v1/projects/${project}/subscriptions/${subscription}`;
const body = {
topic,
pushConfig: {
pushEndpoint: context.webhookUrl,
attributes: {},
},
ackDeadlineSeconds: context.propsValue.ackDeadlineSeconds,
};
await client.request({
url,
method: 'PUT',
data: JSON.stringify(body),
});
await context.store.put<ISubscriptionInfo>('_trigger', {
project,
subscription,
});
},
onDisable: async (context) => {
const response = await context.store.get<ISubscriptionInfo>('_trigger');
if (response !== null && response !== undefined) {
const json = context.auth.props.json;
const client = common.getClient(json);
const { project, subscription } = response;
const url = `https://pubsub.googleapis.com/v1/projects/${project}/subscriptions/${subscription}`;
await client.request({
url,
method: 'DELETE',
});
}
},
async run(context) {
console.debug('payload received', context.payload.body);
const payloadBody = context.payload.body as PayloadBody;
const { data } = payloadBody.message;
const object = data
? JSON.parse(Buffer.from(data, 'base64').toString())
: {};
return [object];
},
sampleData: {
x: 1.0,
y: -1.0,
text: 'Just text sample',
},
});
interface ISubscriptionInfo {
project: string;
subscription: string;
}
type PayloadBody = {
message: {
data: string;
};
};