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,17 @@
import { Property, createAction } from '@activepieces/pieces-framework';
export const base64Decode = createAction({
name: 'base64-decode',
displayName: 'Base64 Decode',
description:'Converts base64 text back to plain text.',
props: {
text: Property.ShortText({
displayName: 'Text',
description: 'The text to be decoded.',
required: true,
}),
},
async run(context) {
return Buffer.from(context.propsValue.text, 'base64').toString();
},
});

View File

@@ -0,0 +1,17 @@
import { Property, createAction } from '@activepieces/pieces-framework';
export const base64Encode = createAction({
name: 'base64-encode',
displayName: 'Base64 Encode',
description: 'Converts plain text into base64 format.',
props: {
text: Property.ShortText({
displayName: 'Text',
description: 'The text to be encoded.',
required: true,
}),
},
async run(context) {
return Buffer.from(context.propsValue.text).toString('base64');
},
});

View File

@@ -0,0 +1,50 @@
import {
Property,
createAction,
} from '@activepieces/pieces-framework';
import { z } from 'zod';
import { propsValidation } from '@activepieces/pieces-common';
export const generatePassword = createAction({
name: 'generate-password',
description: 'Generates a random password with the specified length',
displayName: 'Generate Password',
props: {
length: Property.Number({
displayName: 'Password Length',
description: 'The length of the password (maximum 256)',
required: true,
}),
characterSet: Property.StaticDropdown({
displayName: 'Character Set',
description: 'The character set to use when generating the password',
required: true,
defaultValue: 'alphanumeric',
options: {
options: [
{ label: 'Alphanumeric', value: 'alphanumeric' },
{ label: 'Alphanumeric + Symbols', value: 'alphanumeric-symbols' },
],
},
}),
},
async run(context) {
await propsValidation.validateZod(context.propsValue, {
length: z.number().max(256),
});
const charset = context.propsValue.characterSet === 'alphanumeric'
? 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
: 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()_+~`|}{[]:;?><,./-=';
let password = '';
const length = context.propsValue.length;
for (let i = 0; i < length; i++) {
const randomIndex = Math.floor(Math.random() * charset.length);
password += charset[randomIndex];
}
return password;
},
});

View File

@@ -0,0 +1,39 @@
import { Property, createAction } from '@activepieces/pieces-framework';
import Crypto from 'crypto';
export const hashText = createAction({
name: 'hash-text',
description: 'Converts text to a hash value using various hashing algorithms',
displayName: 'Text to Hash',
props: {
method: Property.StaticDropdown({
displayName: 'Method',
description: 'The hashing algorithm to use',
required: true,
options: {
options: [
{ label: 'MD5', value: 'md5' },
{ label: 'SHA256', value: 'sha256' },
{ label: 'SHA512', value: 'sha512' },
{ label: 'SHA3-512', value: 'sha3-512' },
],
},
}),
text: Property.ShortText({
displayName: 'Text',
description: 'The text to be hashed',
required: true,
}),
},
async run(context) {
const hashAlgorithm = Crypto.createHash(context.propsValue.method);
const text = context.propsValue.text;
hashAlgorithm.update(text);
const hashedString = hashAlgorithm.digest('hex');
return hashedString;
},
});

View File

@@ -0,0 +1,62 @@
import { createAction, Property } from '@activepieces/pieces-framework';
import Crypto from 'crypto';
import { Buffer } from 'buffer';
export const hmacSignature = createAction({
name: 'hmac-signature',
description:
'Converts text to a HMAC signed hash value using various hashing algorithms',
displayName: 'Generate HMAC Signature',
props: {
secretKey: Property.ShortText({
displayName: 'Secret key',
description: 'The secret key to encrypt',
required: true,
}),
secretKeyEncoding: Property.StaticDropdown<'utf-8' | 'hex' | 'base64'>({
displayName: 'Secret key encoding',
description: 'The secret key encoding to use',
required: true,
options: {
options: [
{ label: 'UTF-8', value: 'utf-8' },
{ label: 'Hex', value: 'hex' },
{ label: 'Base64', value: 'base64' },
],
},
}),
method: Property.StaticDropdown({
displayName: 'Method',
description: 'The hashing algorithm to use',
required: true,
options: {
options: [
{ label: 'MD5', value: 'md5' },
{ label: 'SHA256', value: 'sha256' },
{ label: 'SHA512', value: 'sha512' },
],
},
}),
text: Property.ShortText({
displayName: 'Text',
description: 'The text to be hashed and encrypted',
required: true,
}),
},
async run(context) {
const hashAlgorithm = Crypto.createHmac(
context.propsValue.method,
Buffer.from(
context.propsValue.secretKey,
context.propsValue.secretKeyEncoding
)
);
const text = context.propsValue.text;
hashAlgorithm.update(text);
const hashedString = hashAlgorithm.digest('hex');
return hashedString;
},
});

View File

@@ -0,0 +1,51 @@
import { createAction, Property } from '@activepieces/pieces-framework';
import * as openpgp from 'openpgp';
export const openpgpEncrypt = createAction({
name: 'openpgpEncrypt',
displayName: 'OpenPGP Encrypt',
description: 'Encrypt a file using OpenPGP public key',
props: {
file: Property.File({
displayName: 'File',
description: 'The file to encrypt',
required: true,
}),
publicKey: Property.LongText({
displayName: 'Public Key',
description: 'The PGP public key in ASCII armor format',
required: true,
}),
},
async run(context) {
try {
if (!context.propsValue.publicKey) {
throw new Error('Public key is required');
}
const publicKey = await openpgp.readKey({ armoredKey: context.propsValue.publicKey });
const encrypted = await openpgp.encrypt({
message: await openpgp.createMessage({
binary: context.propsValue.file.data
}),
encryptionKeys: publicKey,
format: 'armored',
});
return {
success: true,
filename: context.propsValue.file.filename + '.pgp',
file: await context.files.write({
fileName: context.propsValue.file.filename + '.pgp',
data: Buffer.from(encrypted)
})
};
} catch (error) {
return {
success: false,
error: error instanceof Error ? error.message : 'Encryption failed'
};
}
},
});