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,71 @@
import { createAction, Property } from '@activepieces/pieces-framework';
import { HttpMethod } from '@activepieces/pieces-common';
import { ibmCognoseAuth } from '../../index';
import { CognosClient } from '../common/cognos-client';
import { contentObjectDropdown } from '../common/content-object-dropdown';
export const copyContentObjectAction = createAction({
auth: ibmCognoseAuth,
name: 'copy_content_object',
displayName: 'Copy Content Object',
description: 'Copy an object optionally with all its descendants',
props: {
sourceId: contentObjectDropdown,
destinationId: {
...contentObjectDropdown,
displayName: 'Destination Container',
description: 'Destination container where the object will be copied',
},
recursive: Property.Checkbox({
displayName: 'Recursive Copy',
description: 'Copy all descendants (child objects)',
required: false,
defaultValue: true,
}),
},
async run({ auth, propsValue }) {
const { sourceId, destinationId, recursive } = propsValue;
if (sourceId === destinationId) {
throw new Error('Source and destination cannot be the same object');
}
try {
const client = new CognosClient(auth.props);
const copyRequest = {
source_id: sourceId,
destination_id: destinationId,
recursive: recursive !== undefined ? recursive : true,
};
const response = await client.makeAuthenticatedRequest(
'/content/copy',
HttpMethod.POST,
copyRequest
);
if (response.status === 201) {
return {
success: true,
message: `Content object copied successfully${recursive ? ' (including descendants)' : ''}`,
copiedObject: response.body,
};
} else if (response.status === 400) {
throw new Error(`Bad request: ${response.body?.message || 'Invalid copy operation'}`);
} else if (response.status === 401) {
throw new Error('Authentication failed. Check your credentials.');
} else if (response.status === 403) {
throw new Error('Permission denied. Insufficient permissions to copy this object.');
} else if (response.status === 404) {
throw new Error('Object or parent object not found.');
} else {
throw new Error(`Failed to copy: ${response.status} ${response.body}`);
}
} catch (error) {
throw new Error(
`Failed to copy content object: ${error instanceof Error ? error.message : 'Unknown error'}`
);
}
},
});

View File

@@ -0,0 +1,98 @@
import { createAction, Property, PieceAuth } from '@activepieces/pieces-framework';
import { HttpMethod } from '@activepieces/pieces-common';
import { ibmCognoseAuth } from '../../index';
import { CognosClient } from '../common/cognos-client';
export const createDataSourceAction = createAction({
auth: ibmCognoseAuth,
name: 'create_data_source',
displayName: 'Create Data Source',
description: 'Create a new data source',
props: {
defaultName: Property.ShortText({
displayName: 'Data Source Name',
description: 'Name for the new data source',
required: true,
}),
connectionString: Property.LongText({
displayName: 'Connection String',
description: 'JDBC URL or database connection string',
required: true,
defaultValue: 'jdbc:db2://localhost:50000/SAMPLE',
}),
driverName: Property.ShortText({
displayName: 'Driver Name',
description: 'Database driver class name',
required: false,
defaultValue: 'com.ibm.db2.jcc.DB2Driver',
}),
username: Property.ShortText({
displayName: 'Database Username',
description: 'Username for database connection',
required: false,
}),
password: Property.ShortText({
displayName: 'Database Password',
description: 'Password for database connection',
required: false,
}),
signonDefaultName: Property.ShortText({
displayName: 'Signon Name',
description: 'Name for the database credentials',
required: false,
}),
},
async run({ auth, propsValue }) {
const { defaultName, connectionString, driverName, username, password, signonDefaultName } = propsValue;
try {
const client = new CognosClient(auth.props);
const dataSourceDefinition: any = {
defaultName,
connections: [
{
connectionString,
defaultName: defaultName + '_connection',
}
]
};
if (driverName) {
dataSourceDefinition.connections[0].connectionString += `;DRIVER_NAME=${driverName}`;
}
if (username && password) {
dataSourceDefinition.connections[0].signons = [
{
defaultName: signonDefaultName || defaultName + '_signon',
credentialsEx: {
username,
password
}
}
];
}
const response = await client.makeAuthenticatedRequest('/dataSources', HttpMethod.POST, dataSourceDefinition);
if (response.status === 201) {
return {
success: true,
message: `Data source '${defaultName}' created successfully`,
dataSource: response.body,
};
} else if (response.status === 400) {
throw new Error(`Data source '${defaultName}' already exists or invalid parameters`);
} else if (response.status === 401) {
throw new Error('Authentication failed. Check your credentials.');
} else {
throw new Error(`Failed to create data source: ${response.status} ${response.body}`);
}
} catch (error) {
throw new Error(
`Failed to create data source: ${error instanceof Error ? error.message : 'Unknown error'}`
);
}
},
});

View File

@@ -0,0 +1,44 @@
import { createAction } from '@activepieces/pieces-framework';
import { HttpMethod } from '@activepieces/pieces-common';
import { ibmCognoseAuth } from '../../index';
import { CognosClient } from '../common/cognos-client';
import { dataSourceDropdown } from '../common/data-source-dropdown';
export const deleteDataSourceAction = createAction({
auth: ibmCognoseAuth,
name: 'delete_data_source',
displayName: 'Delete Data Source',
description: 'Delete a data source',
props: {
datasourceId: dataSourceDropdown,
},
async run({ auth, propsValue }) {
const { datasourceId } = propsValue;
try {
const client = new CognosClient(auth.props);
const response = await client.makeAuthenticatedRequest(
`/dataSources/${datasourceId}`,
HttpMethod.DELETE
);
if (response.status === 204) {
return {
success: true,
message: `Data source deleted successfully`,
};
} else if (response.status === 401) {
throw new Error('Authentication failed. Check your credentials.');
} else if (response.status === 404) {
throw new Error(`Data source not found`);
} else {
throw new Error(`Failed to delete: ${response.status} ${response.body}`);
}
} catch (error) {
throw new Error(
`Failed to delete data source: ${error instanceof Error ? error.message : 'Unknown error'}`
);
}
},
});

View File

@@ -0,0 +1,53 @@
import { createAction, Property } from '@activepieces/pieces-framework';
import { HttpMethod } from '@activepieces/pieces-common';
import { ibmCognoseAuth } from '../../index';
import { CognosClient } from '../common/cognos-client';
import { contentObjectDropdown } from '../common/content-object-dropdown';
export const getContentObjectAction = createAction({
auth: ibmCognoseAuth,
name: 'get_content_object',
displayName: 'Get Content Object',
description: 'Get content object details',
props: {
objectId: contentObjectDropdown,
fields: Property.ShortText({
displayName: 'Extra Fields',
description: 'Comma-separated list of extra fields (e.g., owner,permissions,children)',
required: false,
}),
},
async run({ auth, propsValue }) {
const { objectId, fields } = propsValue;
try {
const client = new CognosClient(auth.props);
const queryParams = [];
if (fields && fields.trim()) {
queryParams.push(`fields=${encodeURIComponent(fields.trim())}`);
}
const queryString = queryParams.length > 0 ? `?${queryParams.join('&')}` : '';
const response = await client.makeAuthenticatedRequest(
`/content/${objectId}${queryString}`,
HttpMethod.GET
);
if (response.status === 200) {
return response.body;
} else if (response.status === 401) {
throw new Error('Authentication failed. Check your credentials.');
} else if (response.status === 404) {
throw new Error(`Content object not found`);
} else {
throw new Error(`Failed to retrieve: ${response.status} ${response.body}`);
}
} catch (error) {
throw new Error(
`Failed to retrieve content object: ${error instanceof Error ? error.message : 'Unknown error'}`
);
}
},
});

View File

@@ -0,0 +1,53 @@
import { createAction, Property } from '@activepieces/pieces-framework';
import { HttpMethod } from '@activepieces/pieces-common';
import { ibmCognoseAuth } from '../../index';
import { CognosClient } from '../common/cognos-client';
import { dataSourceDropdown } from '../common/data-source-dropdown';
export const getDataSourceAction = createAction({
auth: ibmCognoseAuth,
name: 'get_data_source',
displayName: 'Get Data Source',
description: 'Retrieve data source details',
props: {
datasourceId: dataSourceDropdown,
fields: Property.ShortText({
displayName: 'Extra Fields',
description: 'Comma-separated list of extra fields (e.g., connections,signons)',
required: false,
}),
},
async run({ auth, propsValue }) {
const { datasourceId, fields } = propsValue;
try {
const client = new CognosClient(auth.props);
const queryParams = [];
if (fields && fields.trim()) {
queryParams.push(`fields=${encodeURIComponent(fields.trim())}`);
}
const queryString = queryParams.length > 0 ? `?${queryParams.join('&')}` : '';
const response = await client.makeAuthenticatedRequest(
`/dataSources/${datasourceId}${queryString}`,
HttpMethod.GET
);
if (response.status === 200) {
return response.body;
} else if (response.status === 401) {
throw new Error('Authentication failed. Check your credentials.');
} else if (response.status === 404) {
throw new Error(`Data source not found`);
} else {
throw new Error(`Failed to retrieve: ${response.status} ${response.body}`);
}
} catch (error) {
throw new Error(
`Failed to retrieve data source: ${error instanceof Error ? error.message : 'Unknown error'}`
);
}
},
});

View File

@@ -0,0 +1,63 @@
import { createAction } from '@activepieces/pieces-framework';
import { HttpMethod } from '@activepieces/pieces-common';
import { ibmCognoseAuth } from '../../index';
import { CognosClient } from '../common/cognos-client';
import { contentObjectDropdown } from '../common/content-object-dropdown';
export const moveContentObjectAction = createAction({
auth: ibmCognoseAuth,
name: 'move_content_object',
displayName: 'Move Content Object',
description: 'Move an object with all its descendants',
props: {
sourceId: contentObjectDropdown,
destinationId: {
...contentObjectDropdown,
displayName: 'Destination Container',
description: 'Destination container where the object will be moved',
},
},
async run({ auth, propsValue }) {
const { sourceId, destinationId } = propsValue;
if (sourceId === destinationId) {
throw new Error('Source and destination cannot be the same object');
}
try {
const client = new CognosClient(auth.props);
const moveRequest = {
source_id: sourceId,
destination_id: destinationId,
};
const response = await client.makeAuthenticatedRequest(
'/content/move',
HttpMethod.PUT,
moveRequest
);
if (response.status === 204) {
return {
success: true,
message: `Content object moved successfully`,
};
} else if (response.status === 400) {
throw new Error(`Bad request: ${response.body?.message || 'Invalid move operation'}`);
} else if (response.status === 401) {
throw new Error('Authentication failed. Check your credentials.');
} else if (response.status === 403) {
throw new Error('Permission denied. Insufficient permissions to move this object.');
} else if (response.status === 404) {
throw new Error('Object or parent object not found.');
} else {
throw new Error(`Failed to move: ${response.status} ${response.body}`);
}
} catch (error) {
throw new Error(
`Failed to move content object: ${error instanceof Error ? error.message : 'Unknown error'}`
);
}
},
});

View File

@@ -0,0 +1,81 @@
import { createAction, Property } from '@activepieces/pieces-framework';
import { HttpMethod } from '@activepieces/pieces-common';
import { ibmCognoseAuth } from '../../index';
import { CognosClient } from '../common/cognos-client';
import { contentObjectDropdown } from '../common/content-object-dropdown';
export const updateContentObjectAction = createAction({
auth: ibmCognoseAuth,
name: 'update_content_object',
displayName: 'Update Content Object',
description: 'Update an existing content object',
props: {
objectId: contentObjectDropdown,
type: Property.ShortText({
displayName: 'Type',
description: 'Object type (e.g., report, dashboard, folder)',
required: true,
}),
defaultName: Property.ShortText({
displayName: 'Name',
description: 'New name for the object',
required: false,
}),
defaultDescriptions: Property.LongText({
displayName: 'Description',
description: 'New description for the object',
required: false,
}),
version: Property.Number({
displayName: 'Version',
description: 'Current version for optimistic concurrency',
required: false,
}),
},
async run({ auth, propsValue }) {
const { objectId, defaultName, defaultDescriptions, type, version } = propsValue;
try {
const client = new CognosClient(auth.props);
const updateDefinition: any = { type };
if (defaultName) {
updateDefinition.defaultName = defaultName;
}
if (defaultDescriptions) {
updateDefinition.defaultDescriptions = defaultDescriptions;
}
if (version !== undefined && version !== null) {
updateDefinition.version = version;
}
const response = await client.makeAuthenticatedRequest(
`/content/${objectId}`,
HttpMethod.PUT,
updateDefinition
);
if (response.status === 204 || response.status === 200) {
return {
success: true,
message: `Content object updated successfully`,
};
} else if (response.status === 401) {
throw new Error('Authentication failed. Check your credentials.');
} else if (response.status === 404) {
throw new Error(`Content object not found`);
} else if (response.status === 409) {
throw new Error('Object has changed since you fetched it. Refresh and try again.');
} else {
throw new Error(`Failed to update: ${response.status} ${response.body}`);
}
} catch (error) {
throw new Error(
`Failed to update content object: ${error instanceof Error ? error.message : 'Unknown error'}`
);
}
},
});

View File

@@ -0,0 +1,81 @@
import { createAction, Property } from '@activepieces/pieces-framework';
import { HttpMethod } from '@activepieces/pieces-common';
import { ibmCognoseAuth } from '../../index';
import { CognosClient } from '../common/cognos-client';
import { dataSourceDropdown } from '../common/data-source-dropdown';
export const updateDataSourceAction = createAction({
auth: ibmCognoseAuth,
name: 'update_data_source',
displayName: 'Update Data Source',
description: 'Update an existing data source',
props: {
datasourceId: dataSourceDropdown,
defaultName: Property.ShortText({
displayName: 'Data Source Name',
description: 'New name for the data source',
required: false,
}),
disabled: Property.Checkbox({
displayName: 'Disabled',
description: 'Disable the data source',
required: false,
defaultValue: false,
}),
hidden: Property.Checkbox({
displayName: 'Hidden',
description: 'Hide the data source',
required: false,
defaultValue: false,
}),
},
async run({ auth, propsValue }) {
const { datasourceId, defaultName, disabled, hidden } = propsValue;
try {
const client = new CognosClient(auth.props);
const updateDefinition: any = {};
if (defaultName) {
updateDefinition.defaultName = defaultName;
}
if (disabled !== undefined) {
updateDefinition.disabled = disabled;
}
if (hidden !== undefined) {
updateDefinition.hidden = hidden;
}
if (Object.keys(updateDefinition).length === 0) {
throw new Error('At least one field must be provided to update');
}
const response = await client.makeAuthenticatedRequest(
`/dataSources/${datasourceId}`,
HttpMethod.PUT,
updateDefinition
);
if (response.status === 204 || response.status === 200) {
return {
success: true,
message: `Data source updated successfully`,
updatedFields: updateDefinition,
};
} else if (response.status === 401) {
throw new Error('Authentication failed. Check your credentials.');
} else if (response.status === 404) {
throw new Error(`Data source not found`);
} else {
throw new Error(`Failed to update: ${response.status} ${response.body}`);
}
} catch (error) {
throw new Error(
`Failed to update data source: ${error instanceof Error ? error.message : 'Unknown error'}`
);
}
},
});

View File

@@ -0,0 +1,84 @@
import { HttpMethod, httpClient } from '@activepieces/pieces-common';
export interface CognosAuth {
baseurl: string;
CAMNamespace: string;
username: string;
password: string;
}
export class CognosClient {
private auth: CognosAuth;
private sessionCookies?: string;
constructor(auth: CognosAuth) {
this.auth = auth;
}
async createSession(): Promise<string> {
const parameters = [
{ name: 'CAMNamespace', value: this.auth.CAMNamespace },
{ name: 'CAMUsername', value: this.auth.username },
{ name: 'CAMPassword', value: this.auth.password },
];
try {
const response = await httpClient.sendRequest({
method: HttpMethod.PUT,
url: `${this.auth.baseurl}/api/v1/session`,
headers: {
'Content-Type': 'application/json',
},
body: {
parameters,
},
});
if (response.status >= 200 && response.status < 300) {
const cookies = response.headers?.['set-cookie'];
this.sessionCookies = cookies
? Array.isArray(cookies)
? cookies.join('; ')
: cookies
: '';
return this.sessionCookies;
} else {
throw new Error(
`Authentication failed: ${response.status} ${response.body}`
);
}
} catch (error) {
throw new Error(
`Failed to create session: ${error instanceof Error ? error.message : 'Unknown error'}`
);
}
}
async makeAuthenticatedRequest(
endpoint: string,
method: HttpMethod = HttpMethod.GET,
body?: any
) {
try {
if (!this.sessionCookies) {
await this.createSession();
}
const response = await httpClient.sendRequest({
method,
url: `${this.auth.baseurl}/api/v1${endpoint}`,
headers: {
'Content-Type': 'application/json',
Cookie: this.sessionCookies || '',
},
body,
});
return response;
} catch (error) {
throw new Error(
`Request failed: ${error instanceof Error ? error.message : 'Unknown error'}`
);
}
}
}

View File

@@ -0,0 +1,59 @@
import { Property } from '@activepieces/pieces-framework';
import { HttpMethod } from '@activepieces/pieces-common';
import { CognosClient } from './cognos-client';
import { ibmCognoseAuth } from '../..';
export const contentObjectDropdown = Property.Dropdown({
auth: ibmCognoseAuth,
displayName: 'Content Object',
description: 'Select a content object',
required: true,
refreshers: [],
options: async ({ auth }) => {
if (!auth) {
return {
disabled: true,
options: [],
placeholder: 'Connect your account first'
};
}
try {
const client = new CognosClient(auth.props);
const response = await client.makeAuthenticatedRequest('/content', HttpMethod.GET);
if (response.status === 200) {
const data = response.body;
const contentObjects = data.content || [];
if (contentObjects.length === 0) {
return {
disabled: true,
options: [],
placeholder: 'No content objects found'
};
}
return {
disabled: false,
options: contentObjects.map((obj: any) => ({
label: `${obj.defaultName || 'Unnamed'} (${obj.type || 'Unknown'})`,
value: obj.id
}))
};
} else {
return {
disabled: true,
options: [],
placeholder: 'Failed to load content objects'
};
}
} catch (error) {
return {
disabled: true,
options: [],
placeholder: 'Error loading content objects'
};
}
}
});

View File

@@ -0,0 +1,59 @@
import { Property } from '@activepieces/pieces-framework';
import { HttpMethod } from '@activepieces/pieces-common';
import { CognosClient } from './cognos-client';
import { ibmCognoseAuth } from '../..';
export const dataSourceDropdown = Property.Dropdown({
auth: ibmCognoseAuth,
displayName: 'Data Source',
description: 'Select a data source',
required: true,
refreshers: [],
options: async ({ auth }) => {
if (!auth) {
return {
disabled: true,
options: [],
placeholder: 'Connect your account first'
};
}
try {
const client = new CognosClient(auth.props);
const response = await client.makeAuthenticatedRequest('/dataSources', HttpMethod.GET);
if (response.status === 200) {
const data = response.body;
const dataSources = data.dataSources || [];
if (dataSources.length === 0) {
return {
disabled: true,
options: [],
placeholder: 'No data sources found'
};
}
return {
disabled: false,
options: dataSources.map((ds: any) => ({
label: ds.defaultName || ds.id,
value: ds.id
}))
};
} else {
return {
disabled: true,
options: [],
placeholder: 'Failed to load data sources'
};
}
} catch (error) {
return {
disabled: true,
options: [],
placeholder: 'Error loading data sources'
};
}
}
});