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:
@@ -0,0 +1,62 @@
|
||||
import { createAction, Property } from '@activepieces/pieces-framework';
|
||||
import { rabbitmqAuth } from '../..';
|
||||
import { rabbitmqConnect } from '../common';
|
||||
|
||||
export const sendMessageToExchange = createAction({
|
||||
auth: rabbitmqAuth,
|
||||
name: 'sendMessageToExchange',
|
||||
displayName: 'sendMessageToExchange',
|
||||
description: 'Send a message on a RabbitMQ exchange',
|
||||
props: {
|
||||
exchange: Property.ShortText({
|
||||
displayName: 'Exchange',
|
||||
description: 'The name of the exchange to send the message to',
|
||||
required: true,
|
||||
}),
|
||||
routingKey: Property.ShortText({
|
||||
displayName: 'Routing Key (Optional)',
|
||||
description: 'The routing key to use when sending the message',
|
||||
required: false,
|
||||
defaultValue: '',
|
||||
}),
|
||||
data: Property.Json({
|
||||
displayName: 'Data',
|
||||
description: 'The data to send',
|
||||
required: true,
|
||||
defaultValue: {
|
||||
"key": "value",
|
||||
"nested": { "key": "value" },
|
||||
"array": ["value1", "value2"]
|
||||
},
|
||||
}),
|
||||
},
|
||||
async run(context) {
|
||||
let connection;
|
||||
let channel;
|
||||
try {
|
||||
const exchange = context.propsValue.exchange;
|
||||
const routingKey = context.propsValue.routingKey || '';
|
||||
|
||||
connection = await rabbitmqConnect(context.auth.props);
|
||||
channel = await connection.createChannel();
|
||||
|
||||
await channel.checkExchange(exchange);
|
||||
|
||||
const result = channel.publish(
|
||||
exchange,
|
||||
routingKey,
|
||||
Buffer.from(JSON.stringify(context.propsValue.data))
|
||||
);
|
||||
|
||||
if (!result) {
|
||||
throw new Error('Failed to send message to exchange');
|
||||
}
|
||||
return result;
|
||||
} finally {
|
||||
if (channel)
|
||||
await channel.close();
|
||||
if (connection)
|
||||
await connection.close();
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,55 @@
|
||||
import { createAction, Property } from '@activepieces/pieces-framework';
|
||||
import { rabbitmqAuth } from '../..';
|
||||
import { rabbitmqConnect } from '../common';
|
||||
|
||||
export const sendMessageToQueue = createAction({
|
||||
auth: rabbitmqAuth,
|
||||
name: 'sendMessageToQueue',
|
||||
displayName: 'sendMessageToQueue',
|
||||
description: 'Send a message on a RabbitMQ queue',
|
||||
props: {
|
||||
queue: Property.ShortText({
|
||||
displayName: 'Queue',
|
||||
description: 'The name of the exchange to send the message to',
|
||||
required: true,
|
||||
}),
|
||||
data: Property.Json({
|
||||
displayName: 'Data',
|
||||
description: 'The data to send',
|
||||
required: true,
|
||||
defaultValue: {
|
||||
"key": "value",
|
||||
"nested": { "key": "value" },
|
||||
"array": ["value1", "value2"]
|
||||
},
|
||||
}),
|
||||
},
|
||||
async run(context) {
|
||||
const queue = context.propsValue.queue;
|
||||
let connection;
|
||||
let channel;
|
||||
try {
|
||||
connection = await rabbitmqConnect(context.auth.props);
|
||||
channel = await connection.createChannel();
|
||||
|
||||
await channel.checkQueue(queue);
|
||||
|
||||
const result = channel.sendToQueue(
|
||||
queue,
|
||||
Buffer.from(JSON.stringify(context.propsValue.data))
|
||||
);
|
||||
|
||||
if (!result) {
|
||||
throw new Error('Failed to send message to exchange');
|
||||
}
|
||||
return result;
|
||||
} finally {
|
||||
if (channel) {
|
||||
await channel.close();
|
||||
}
|
||||
if (connection) {
|
||||
await connection.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,24 @@
|
||||
import { PiecePropValueSchema } from '@activepieces/pieces-framework';
|
||||
import { rabbitmqAuth } from '../..';
|
||||
import amqp, { ChannelModel, Connection } from 'amqplib';
|
||||
|
||||
export async function rabbitmqConnect(
|
||||
auth: PiecePropValueSchema<typeof rabbitmqAuth>,
|
||||
): Promise<ChannelModel> {
|
||||
return amqp.connect(createAmqpURI(auth), (err: Error, conn: Connection) => {
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
|
||||
return conn;
|
||||
});
|
||||
}
|
||||
|
||||
function createAmqpURI(auth: PiecePropValueSchema<typeof rabbitmqAuth>): string {
|
||||
const uri = `amqp://${auth.username}:${auth.password}@${auth.host}:${auth.port}`;
|
||||
|
||||
if (!auth.vhost) {
|
||||
return uri;
|
||||
}
|
||||
return `${uri}/${auth.vhost}`;
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
import {
|
||||
createTrigger,
|
||||
TriggerStrategy,
|
||||
PiecePropValueSchema,
|
||||
Property,
|
||||
AppConnectionValueForAuthProperty,
|
||||
} from '@activepieces/pieces-framework';
|
||||
import { DedupeStrategy, Polling, pollingHelper } from '@activepieces/pieces-common';
|
||||
import { rabbitmqAuth } from '../../index';
|
||||
import { rabbitmqConnect } from '../common';
|
||||
import dayjs from 'dayjs';
|
||||
|
||||
const polling: Polling<AppConnectionValueForAuthProperty<typeof rabbitmqAuth>, {
|
||||
queue: string,
|
||||
maxMessagesPerPoll: number,
|
||||
}> = {
|
||||
strategy: DedupeStrategy.LAST_ITEM,
|
||||
items: async ({ auth, propsValue }) => {
|
||||
const connection = await rabbitmqConnect(auth.props);
|
||||
const channel = await connection.createChannel();
|
||||
const messages = [];
|
||||
|
||||
try {
|
||||
const queueInfo = await channel.checkQueue(propsValue.queue);
|
||||
|
||||
if (queueInfo.messageCount === 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
for (let i = 0; i < propsValue.maxMessagesPerPoll; i++) {
|
||||
const message = await channel.get(propsValue.queue);
|
||||
if (!message) {
|
||||
break;
|
||||
}
|
||||
messages.push({
|
||||
id: dayjs().toISOString(),
|
||||
data: JSON.parse(message.content.toString()),
|
||||
});
|
||||
channel.ack(message);
|
||||
}
|
||||
} finally {
|
||||
await channel.close();
|
||||
await connection.close();
|
||||
}
|
||||
|
||||
return messages;
|
||||
},
|
||||
};
|
||||
|
||||
export const messageReceived = createTrigger({
|
||||
auth: rabbitmqAuth,
|
||||
name: 'messageReceived',
|
||||
displayName: 'Message Received',
|
||||
description: 'Triggers when a message is received on a RabbitMQ queue',
|
||||
props: {
|
||||
queue: Property.ShortText({
|
||||
displayName: 'Queue',
|
||||
description: 'The name of the queue to listen to',
|
||||
required: true,
|
||||
}),
|
||||
maxMessagesPerPoll: Property.Number({
|
||||
displayName: 'Max Messages Per Poll',
|
||||
description: 'The maximum number of messages to fetch per poll',
|
||||
required: true,
|
||||
defaultValue: 50,
|
||||
}),
|
||||
},
|
||||
sampleData: {},
|
||||
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 });
|
||||
},
|
||||
});
|
||||
Reference in New Issue
Block a user