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,28 @@
import { createAction, Property } from '@activepieces/pieces-framework';
import { parseurAuth, parseurCommon } from '../common';
import { parserDropdown } from '../common/properties';
export const createDocumentFromFile = createAction({
auth: parseurAuth,
name: 'createDocumentFromFile',
displayName: 'Create Document from File',
description: 'Creates new document in mailbox from file.',
props: {
parserId: parserDropdown({ required: true }),
file: Property.File({
displayName: 'File',
description: 'Select the file to upload',
required: true,
}),
},
async run({ auth: apiKey, propsValue: { parserId, file } }) {
if (!parserId) {
throw new Error('Parser is required');
}
return await parseurCommon.createDocumentFromFile({
apiKey: apiKey.secret_text,
parserId,
file,
});
},
});

View File

@@ -0,0 +1,69 @@
import { createAction, Property } from '@activepieces/pieces-framework';
import { parseurAuth, parseurCommon } from '../common';
export const createDocument = createAction({
auth: parseurAuth,
name: 'createDocument',
displayName: 'Create Document',
description: 'Creates a new document.',
props: {
subject: Property.ShortText({
displayName: 'Subject',
description: 'The subject of the document/email.',
required: true,
}),
from: Property.ShortText({
displayName: 'From',
description: 'The sender email address.',
required: true,
}),
recipient: Property.ShortText({
displayName: 'Recipient',
description: 'The recipient email address.',
required: true,
}),
to: Property.ShortText({
displayName: 'To',
description: 'The "To" email address.',
required: false,
}),
cc: Property.ShortText({
displayName: 'CC',
description: 'The "CC" email address.',
required: false,
}),
bcc: Property.ShortText({
displayName: 'BCC',
description: 'The "BCC" email address.',
required: false,
}),
body_html: Property.LongText({
displayName: 'Body HTML',
description: 'The HTML content of the document/email.',
required: false,
}),
body_plain: Property.LongText({
displayName: 'Body Plain',
description: 'The plain text content of the document/email.',
required: false,
}),
message_headers: Property.Object({
displayName: 'Message Headers',
description:
'A JSON object representing the email headers (key-value pairs).',
required: false,
}),
},
async run({ auth: apiKey, propsValue }) {
const { message_headers, ...rest } = propsValue;
return await parseurCommon.createDocument({
apiKey:apiKey.secret_text,
...rest,
message_headers: message_headers
? Object.fromEntries(
Object.entries(message_headers).map(([k, v]) => [k, String(v)])
)
: undefined,
});
},
});

View File

@@ -0,0 +1,29 @@
import { createAction, Property } from '@activepieces/pieces-framework';
import { parseurAuth, parseurCommon } from '../common';
import { parserDropdown } from '../common/properties';
export const findDocument = createAction({
auth: parseurAuth,
name: 'findDocument',
displayName: 'Find Document',
description: 'Finds a document based on search param.',
props: {
parserId: parserDropdown({ required: true }),
search: Property.ShortText({
displayName: 'Search',
description:
'The search term to filter documents by name. Case insensitive. If empty, all documents are returned.',
required: false,
}),
},
async run({ auth: apiKey, propsValue: { parserId, search } }) {
if (!parserId) {
throw new Error('Parser ID is required');
}
return await parseurCommon.listDocuments({
apiKey:apiKey.secret_text,
parserId,
search,
});
},
});

View File

@@ -0,0 +1,20 @@
import { createAction } from '@activepieces/pieces-framework';
import { parseurAuth, parseurCommon } from '../common';
import { documentDropdown, parserDropdown } from '../common/properties';
export const getParsedDocumentById = createAction({
auth: parseurAuth,
name: 'getParsedDocumentById',
displayName: 'Get Parsed Document by ID',
description: 'Fetch parsed JSON / structured output for a given document ID',
props: {
parserId: parserDropdown({ required: true }),
documentId: documentDropdown({ required: true }),
},
async run({ auth: apiKey, propsValue: { documentId } }) {
if (!documentId) {
throw new Error('Document ID is required');
}
return await parseurCommon.getDocument({ apiKey: apiKey.secret_text, documentId });
},
});

View File

@@ -0,0 +1,24 @@
import { createAction } from '@activepieces/pieces-framework';
import { parseurAuth, parseurCommon } from '../common';
import { documentDropdown, parserDropdown } from '../common/properties';
export const reprocessDocument = createAction({
auth: parseurAuth,
name: 'reprocessDocument',
displayName: 'Reprocess Document',
description:
'Send an existing document back through parsing (e.g. after updating template).',
props: {
parserId: parserDropdown({ required: true }),
documentId: documentDropdown({ required: true }),
},
async run({ auth: apiKey, propsValue: { documentId } }) {
if (!documentId) {
throw new Error('Document ID is required');
}
return await parseurCommon.reprocessDocument({
apiKey:apiKey.secret_text,
documentId,
});
},
});

View File

@@ -0,0 +1,189 @@
import { httpClient, HttpMethod } from '@activepieces/pieces-common';
import { PieceAuth } from '@activepieces/pieces-framework';
import {
CreateDocumentFromFileParams,
CreateDocumentFromFileResponse,
CreateDocumentParams,
CreateDocumentResponse,
CreateWebhookParams,
CreateWebhookResponse,
DeleteWebhookParams,
EnableWebhookParams,
GetParsedDocumentByIdParams,
GetParsedDocumentByIdResponse,
ListDocumentsParams,
ListDocumentsResponse,
ListMailboxesParams,
ListMailboxesResponse,
ReprocessDocumentParams,
ReprocessDocumentResponse,
} from './types';
export const parseurAuth = PieceAuth.SecretText({
displayName: 'API Key',
description:
'Create a new API key in Account → API keys in the Parseur app: https://app.parseur.com/account/api-keys',
required: true,
});
export const parseurCommon = {
baseUrl: 'https://api.parseur.com',
endpoints: {
listDocuments: (parserId: number) => `/parser/${parserId}/document_set`,
getParsedDocumentById: (documentId: string) => `/document/${documentId}`,
createDocument: '/email',
createDocumentFromFile: (parserId: number) => `/parser/${parserId}/upload`,
reprocessDocument: (documentId: string) =>
`/document/${documentId}/process`,
listMailboxes: '/parser',
createWebhook: '/webhook',
enableWebhook: (webhookId: number, mailboxId: number) =>
`/parser/${mailboxId}/webhook_set/${webhookId}`,
deleteWebhook: (webhookId: number) => `/webhook/${webhookId}`,
},
getHeaders: (apiKey: string) => {
return {
Authorization: apiKey,
'Content-Type': 'application/json',
};
},
// API methods
listDocuments: async ({
apiKey,
parserId,
...queryParams
}: ListDocumentsParams) => {
const { page, page_size, with_result, ...rest } = queryParams;
const parsedQuery = {
...(page != undefined ? { page: String(page) } : {}),
...(page_size != undefined ? { page_size: String(page_size) } : {}),
...(with_result != undefined ? { with_result: String(with_result) } : {}),
...rest,
};
const response = await httpClient.sendRequest<ListDocumentsResponse>({
method: HttpMethod.GET,
url:
parseurCommon.baseUrl + parseurCommon.endpoints.listDocuments(parserId),
headers: parseurCommon.getHeaders(apiKey),
queryParams: parsedQuery,
});
return response.body;
},
getDocument: async ({ apiKey, documentId }: GetParsedDocumentByIdParams) => {
const response =
await httpClient.sendRequest<GetParsedDocumentByIdResponse>({
method: HttpMethod.GET,
url:
parseurCommon.baseUrl +
parseurCommon.endpoints.getParsedDocumentById(documentId),
headers: parseurCommon.getHeaders(apiKey),
});
return response.body;
},
createDocument: async ({
apiKey,
...documentParams
}: CreateDocumentParams) => {
const response = await httpClient.sendRequest<CreateDocumentResponse>({
method: HttpMethod.POST,
url: parseurCommon.baseUrl + parseurCommon.endpoints.createDocument,
headers: parseurCommon.getHeaders(apiKey),
body: documentParams,
});
return response.body;
},
createDocumentFromFile: async ({
apiKey,
file,
parserId,
}: CreateDocumentFromFileParams) => {
const data = new FormData();
const uint8 = new Uint8Array(file.data);
data.append('file', new Blob([uint8]), file.filename);
data.append('parserId', String(parserId));
const response =
await httpClient.sendRequest<CreateDocumentFromFileResponse>({
method: HttpMethod.POST,
url:
parseurCommon.baseUrl +
parseurCommon.endpoints.createDocumentFromFile(parserId),
headers: {
...parseurCommon.getHeaders(apiKey),
'Content-Type': 'multipart/form-data',
},
body: data,
});
return response.body;
},
reprocessDocument: async ({
apiKey,
documentId,
}: ReprocessDocumentParams) => {
const response = await httpClient.sendRequest<ReprocessDocumentResponse>({
method: HttpMethod.POST,
url:
parseurCommon.baseUrl +
parseurCommon.endpoints.reprocessDocument(documentId),
headers: parseurCommon.getHeaders(apiKey),
});
return response.body;
},
listMailboxes: async ({ apiKey, ...queryParams }: ListMailboxesParams) => {
const { page, page_size, ...rest } = queryParams;
const parsedQuery = {
...(page != undefined ? { page: String(page) } : {}),
...(page_size != undefined ? { page_size: String(page_size) } : {}),
...rest,
};
const response = await httpClient.sendRequest<ListMailboxesResponse>({
method: HttpMethod.GET,
url: parseurCommon.baseUrl + parseurCommon.endpoints.listMailboxes,
headers: parseurCommon.getHeaders(apiKey),
queryParams: parsedQuery,
});
return response.body;
},
createWebhook: async ({ apiKey, ...webhookParams }: CreateWebhookParams) => {
const reponse = await httpClient.sendRequest<CreateWebhookResponse>({
method: HttpMethod.POST,
url: parseurCommon.baseUrl + parseurCommon.endpoints.createWebhook,
headers: parseurCommon.getHeaders(apiKey),
body: webhookParams,
});
return reponse.body;
},
enableWebhook: async ({
apiKey,
webhookId,
mailboxId,
}: EnableWebhookParams) => {
const response = await httpClient.sendRequest<void>({
method: HttpMethod.POST,
url:
parseurCommon.baseUrl +
parseurCommon.endpoints.enableWebhook(webhookId, mailboxId),
headers: parseurCommon.getHeaders(apiKey),
});
if (response.status === 200 || response.status === 204) {
return { success: true };
} else {
return { success: false };
}
},
deleteWebhook: async ({ apiKey, webhookId }: DeleteWebhookParams) => {
const response = await httpClient.sendRequest<void>({
method: HttpMethod.DELETE,
url:
parseurCommon.baseUrl +
parseurCommon.endpoints.deleteWebhook(webhookId),
headers: parseurCommon.getHeaders(apiKey),
});
if (response.status === 200 || response.status === 204) {
return { success: true };
} else {
return { success: false };
}
},
};
// Common Properties

View File

@@ -0,0 +1,97 @@
import { Property } from '@activepieces/pieces-framework';
import { parseurAuth, parseurCommon } from '.';
export const parserDropdown = ({ required = true }) =>
Property.Dropdown({
auth: parseurAuth,
displayName: 'Parser',
description: 'Select the parser',
required,
refreshers: ['auth'],
refreshOnSearch: true,
options: async ({ auth: apiKey }, { searchValue: search }) => {
if (!apiKey) {
return {
disabled: true,
placeholder: 'Please select an API Key first',
options: [],
};
}
if (search != undefined) {
const response = await parseurCommon.listMailboxes({
apiKey: apiKey.secret_text,
search,
});
return {
disabled: false,
options: response.results.map((parser) => ({
label: parser.name,
value: parser.id,
})),
};
} else {
const response = await parseurCommon.listMailboxes({
apiKey: apiKey.secret_text,
});
return {
disabled: false,
options: response.results.map((parser) => ({
label: parser.name,
value: parser.id,
})),
};
}
},
});
export const documentDropdown = ({ required = true }) =>
Property.Dropdown({
auth: parseurAuth,
displayName: 'Document',
description: 'Select the document',
required,
refreshers: ['auth', 'parserId'],
refreshOnSearch: true,
options: async ({ auth: apiKey, parserId }, { searchValue: search }) => {
if (!apiKey) {
return {
disabled: true,
placeholder: 'Please select an API Key first',
options: [],
};
}
if (!parserId) {
return {
disabled: true,
placeholder: 'Please select a Parser first',
options: [],
};
}
if (search != undefined) {
const response = await parseurCommon.listDocuments({
apiKey: apiKey.secret_text,
parserId: parserId as number,
search,
});
return {
disabled: false,
options: response.results.map((document) => ({
label: document.name,
value: document.id.toString(),
})),
};
} else {
const response = await parseurCommon.listDocuments({
apiKey: apiKey.secret_text,
parserId: parserId as number,
});
return {
disabled: false,
options: response.results.map((document) => ({
label: document.name,
value: document.id.toString(),
})),
};
}
},
});

View File

@@ -0,0 +1,382 @@
import { ApFile } from '@activepieces/pieces-framework';
// Common Types
export interface AuthenticationParams {
apiKey: string;
}
type TemplateSample = {
template_id: number;
name: string;
sample_count: number;
};
type OcrPage = {
image: {
url: string;
width: number;
height: number;
content_type: string;
};
position: number;
included_in_range: boolean;
};
type Webhook = {
id: number;
event:
| 'document.processed'
| 'document.processed.flattened'
| 'document.template_needed'
| 'document.export_failed'
| 'table.processed';
target: string;
name: string;
headers: Record<string, string>;
category: 'CUSTOM' | 'ZAPIER' | 'MAKE' | 'FLOW' | 'N8N';
parser_field_set: string[];
};
interface BaseParser {
account_uuid: string;
ai_engine: string;
attachments_only: boolean;
attachments_only_override: null;
can_transform: boolean;
disable_deskew: boolean;
enable_layouted_text: boolean;
enable_image_ocr: boolean;
document_count: number;
document_per_status_count: {
INCOMING: number;
ANALYZING: number;
PROGRESS: number;
PARSEDOK: number;
PARSEDKO: number;
QUOTAEXC: number;
SKIPPED: number;
SPLIT: number;
DELETED: number;
EXPORTKO: number;
TRANSKO: number;
INVALID: number;
};
email_prefix: string;
even_pages: boolean;
force_ocr: boolean;
id: number;
is_master: boolean;
last_activity: string;
name: string;
odd_pages: boolean;
page_range_set: string[];
parser_object_count: number;
parser_object_set_last_modified: null;
process_attachments: boolean;
retention_policy: number;
template_count: number;
webhook_count: number;
attachments_field: boolean;
original_document_field: boolean;
searchable_pdf_field: boolean;
headers_field: boolean;
received_field: boolean;
received_date_field: boolean;
received_time_field: boolean;
processed_field: boolean;
processed_date_field: boolean;
processed_time_field: boolean;
sender_field: boolean;
sender_name_field: boolean;
split_page_range_field: boolean;
recipient_field: boolean;
to_field: boolean;
cc_field: boolean;
bcc_field: boolean;
reply_to_field: boolean;
recipient_suffix_field: boolean;
original_recipient_field: boolean;
subject_field: boolean;
template_field: boolean;
html_document_field: boolean;
text_document_field: boolean;
content_field: boolean;
last_reply_field: boolean;
document_id_field: boolean;
parent_id_field: boolean;
document_url_field: boolean;
public_document_url_field: boolean;
page_count_field: boolean;
credit_count_field: boolean;
mailbox_id_field: boolean;
parsing_engine_field: boolean;
}
interface Parser extends BaseParser {
split_keywords: null;
split_page: null;
split_page_range_set: string[];
available_webhook_set: string[];
webhook_set: string[];
table_set: string[];
}
interface ParserDiet extends BaseParser {
split_keywords: { keyword: string; is_before: boolean }[] | null;
split_page: number | null;
split_page_range_set: { start_index: number; end_index: number }[];
template_count: number;
webhook_count: number;
attachments_field: boolean;
original_document_field: boolean;
available_webhook_set: Webhook[];
webhook_set: Webhook[];
table_set: { id: string; name: string }[];
}
interface Document {
attached_to: null;
id: number;
match_master_template: boolean;
name: string;
ocr_ready_url: null;
original_document_url: string;
parser: number;
processed: string;
received: string;
sample_set: string[];
status_source: string;
status: string;
template: null;
credits_used: number;
conventional_credits_used: number;
ai_credits_used: number;
is_ai_ready: boolean;
is_ocr_ready: boolean;
is_processable: boolean;
is_splittable: boolean;
is_split: boolean;
json_download_url: string;
csv_download_url: string;
xls_download_url: string;
}
interface DocumentDiet {
attached_to: number | null;
id: number;
name: string;
match_master_template: boolean;
ocr_ready_url: string | null;
original_document_url: string;
parser: number;
processed: string;
received: string;
sample_set: TemplateSample[];
status_source: 'AI' | 'AUTO' | 'CSV' | 'METADATA' | 'TEMPLATE' | 'TRANSFORM';
status:
| 'INCOMING'
| 'ANALYZING'
| 'PROGRESS'
| 'PARSEDOK'
| 'PARSEDKO'
| 'SKIPPED'
| 'SPLIT'
| 'EXPORTKO'
| 'TRANSKO'
| 'INVALID';
template: number | null;
credits_used: number;
conventional_credits_used: number;
ai_credits_used: number;
is_ai_ready: boolean;
is_ocr_ready: boolean;
is_processable: boolean;
is_splittable: boolean;
is_split: boolean;
json_download_url: string;
csv_download_url: string;
xls_download_url: string;
result: string | null;
}
export interface WebhookInformation {
webhookId: number;
}
// API Types
export interface ListDocumentsParams extends AuthenticationParams {
parserId: number;
page?: number;
page_size?: number;
search?: string;
ordering?:
| 'name'
| '-name'
| 'created'
| '-created'
| 'processed'
| '-processed'
| 'status'
| '-status';
received_after?: string; // yyyy-mm-dd
received_before?: string; // yyyy-mm-dd
tz?: string; // Example: "Asia/Singapore"
with_result?: boolean;
}
export interface ListDocumentsResponse {
count: number;
current: number;
total: number;
results: (DocumentDiet | Document)[];
}
export interface GetParsedDocumentByIdParams extends AuthenticationParams {
documentId: string;
}
export interface GetParsedDocumentByIdResponse {
attached_to: number | null;
id: number;
match_master_template: boolean;
name: string;
ocr_ready_url: string | null;
original_document_url: string;
parser: number;
processed: string;
received: string;
sample_set: TemplateSample[];
status_source: 'AI' | 'AUTO' | 'CSV' | 'METADATA' | 'TEMPLATE' | 'TRANSFORM';
status:
| 'INCOMING'
| 'ANALYZING'
| 'PROGRESS'
| 'PARSEDOK'
| 'PARSEDKO'
| 'SKIPPED'
| 'SPLIT'
| 'EXPORTKO'
| 'TRANSKO'
| 'INVALID';
template: number | null;
credits_used: number;
conventional_credits_used: number;
ai_credits_used: number;
is_ai_ready: boolean;
is_ocr_ready: boolean;
is_processable: boolean;
is_splittable: boolean;
json_download_url: string;
csv_download_url: string;
xls_download_url: string;
result: string | null;
content: string;
next_id: number | null;
previous_id: number | null;
ocr_page_set: OcrPage[];
}
export interface CreateDocumentParams extends AuthenticationParams {
subject: string;
from: string;
recipient: string;
to?: string;
cc?: string;
bcc?: string;
body_html?: string;
body_plain?: string;
message_headers?: Record<string, string>;
}
export interface CreateDocumentResponse {
message: string;
}
export interface CreateDocumentFromFileParams extends AuthenticationParams {
parserId: number;
file: ApFile;
}
export interface CreateDocumentFromFileResponse {
message: string;
attachments: { name: string; DocumentID: string }[];
}
export interface ReprocessDocumentParams extends AuthenticationParams {
documentId: string;
}
export interface ReprocessDocumentResponse {
notification_set: {
info: string[];
};
}
export interface ListMailboxesParams extends AuthenticationParams {
page?: number;
page_size?: number;
search?: string;
ordering?:
| 'name'
| '-name'
| 'document_count'
| '-document_count'
| 'template_count'
| '-template_count'
| 'PARSEDOK_count'
| '-PARSEDOK_count'
| 'PARSEDKO_count'
| '-PARSEDKO_count'
| 'QUOTAEXC_count'
| '-QUOTAEXC_count'
| 'EXPORTKO_count'
| '-EXPORTKO_count'
| 'TRANSKO_count'
| '-TRANSKO_count';
}
export interface ListMailboxesResponse {
count: number;
current: number;
total: number;
results: (ParserDiet | Parser)[];
}
export interface CreateWebhookParams extends AuthenticationParams {
event:
| 'document.processed'
| 'document.processed.flattened'
| 'document.template_needed'
| 'document.export_failed'
| 'table.processed';
target: string;
name?: string;
headers?: Record<string, string>;
category: 'CUSTOM' | 'ZAPIER' | 'MAKE' | 'FLOW' | 'N8N';
parser_field_set?: string[];
}
export interface CreateWebhookResponse {
id: number;
event:
| 'document.processed'
| 'document.processed.flattened'
| 'document.template_needed'
| 'document.export_failed'
| 'table.processed';
target: string;
name: string;
headers: Record<string, string>;
category: 'CUSTOM' | 'ZAPIER' | 'MAKE' | 'FLOW' | 'N8N';
parser_field_set: string[];
}
export interface EnableWebhookParams extends AuthenticationParams {
webhookId: number;
mailboxId: number;
}
export interface DeleteWebhookParams extends AuthenticationParams {
webhookId: number;
};

View File

@@ -0,0 +1,47 @@
import { createTrigger, TriggerStrategy } from '@activepieces/pieces-framework';
import { parseurAuth, parseurCommon } from '../common';
import { parserDropdown } from '../common/properties';
import { WebhookInformation } from '../common/types';
export const newDocumentExportFailed = createTrigger({
auth: parseurAuth,
name: 'newDocumentExportFailed',
displayName: 'New Document Export Failed',
description:
'Fires when an automated export endpoint (webhook / integration) fails for a processed document.',
props: { mailboxId: parserDropdown({ required: true }) },
sampleData: {},
type: TriggerStrategy.WEBHOOK,
async onEnable(context) {
const response = await parseurCommon.createWebhook({
apiKey: context.auth.secret_text,
event: 'document.export_failed',
target: context.webhookUrl,
category: 'CUSTOM',
});
await parseurCommon.enableWebhook({
apiKey: context.auth.secret_text,
webhookId: response.id,
mailboxId: context.propsValue.mailboxId as number,
});
await context.store.put<WebhookInformation>('_newDocumentExportFailed', {
webhookId: response.id,
});
},
async onDisable(context) {
const webhookInfo = await context.store.get<WebhookInformation>(
'_newDocumentExportFailed'
);
if (!webhookInfo) {
return;
}
await parseurCommon.deleteWebhook({
apiKey: context.auth.secret_text,
webhookId: webhookInfo.webhookId,
});
await context.store.delete('_newDocumentExportFailed');
},
async run(context) {
return [context.payload.body];
},
});

View File

@@ -0,0 +1,49 @@
import { createTrigger, TriggerStrategy } from '@activepieces/pieces-framework';
import { parseurAuth, parseurCommon } from '../common';
import { parserDropdown } from '../common/properties';
import { WebhookInformation } from '../common/types';
export const newDocumentNotProcessed = createTrigger({
auth: parseurAuth,
name: 'newDocumentNotProcessed',
displayName: 'New Document Not Processed',
description:
'Fires when Parseur fails to parse a document (e.g. no matching template).',
props: {
mailboxId: parserDropdown({ required: false }),
},
sampleData: {},
type: TriggerStrategy.WEBHOOK,
async onEnable(context) {
const response = await parseurCommon.createWebhook({
apiKey: context.auth.secret_text,
event: 'document.template_needed',
target: context.webhookUrl,
category: 'CUSTOM',
});
await parseurCommon.enableWebhook({
apiKey: context.auth.secret_text,
webhookId: response.id,
mailboxId: context.propsValue.mailboxId as number,
});
await context.store.put<WebhookInformation>('_newDocumentNotProcessed', {
webhookId: response.id,
});
},
async onDisable(context) {
const webhookInfo = await context.store.get<WebhookInformation>(
'_newDocumentNotProcessed'
);
if (!webhookInfo) {
return;
}
await parseurCommon.deleteWebhook({
apiKey: context.auth.secret_text,
webhookId: webhookInfo.webhookId,
});
await context.store.delete('_newDocumentNotProcessed');
},
async run(context) {
return [context.payload.body];
},
});

View File

@@ -0,0 +1,49 @@
import { createTrigger, TriggerStrategy } from '@activepieces/pieces-framework';
import { parseurAuth, parseurCommon } from '../common';
import { parserDropdown } from '../common/properties';
import { WebhookInformation } from '../common/types';
export const newDocumentProcessed = createTrigger({
auth: parseurAuth,
name: 'newDocumentProcessed',
displayName: 'New Document Processed',
description:
'Fires when a new document is successfully processed and parsed by Parseur.',
props: {
mailboxId: parserDropdown({ required: true }),
},
sampleData: {},
type: TriggerStrategy.WEBHOOK,
async onEnable(context) {
const webhookCreateResponse = await parseurCommon.createWebhook({
apiKey: context.auth.secret_text,
event: 'document.processed',
target: context.webhookUrl,
category: 'CUSTOM',
});
await parseurCommon.enableWebhook({
apiKey: context.auth.secret_text,
webhookId: webhookCreateResponse.id,
mailboxId: context.propsValue.mailboxId as number,
});
await context.store.put<WebhookInformation>('_newDocumentProcessed', {
webhookId: webhookCreateResponse.id,
});
},
async onDisable(context) {
const webhookInfo = await context.store.get<WebhookInformation>(
'_newDocumentProcessed'
);
if (!webhookInfo) {
return;
}
await parseurCommon.deleteWebhook({
apiKey: context.auth.secret_text,
webhookId: webhookInfo.webhookId,
});
await context.store.delete('_newDocumentProcessed');
},
async run(context) {
return [context.payload.body];
},
});

View File

@@ -0,0 +1,55 @@
import {
DedupeStrategy,
Polling,
pollingHelper,
} from '@activepieces/pieces-common';
import {
AppConnectionValueForAuthProperty,
createTrigger,
PiecePropValueSchema,
TriggerStrategy,
} from '@activepieces/pieces-framework';
import { parseurAuth, parseurCommon } from '../common';
const polling: Polling<
AppConnectionValueForAuthProperty<typeof parseurAuth>,
Record<string, never>
> = {
strategy: DedupeStrategy.LAST_ITEM,
items: async ({ auth: apiKey }) => {
const response = await parseurCommon.listMailboxes({
apiKey: apiKey.secret_text,
});
const items = response.results;
return items.map((item) => ({
id: item.id,
data: item,
}));
},
};
export const newMailbox = createTrigger({
auth: parseurAuth,
name: 'newMailbox',
displayName: 'New Mailbox',
description: 'Fires when a new mailbox is created in the Parseur account.',
props: {},
sampleData: {},
type: TriggerStrategy.POLLING,
async test(context) {
return await pollingHelper.test(polling, context);
},
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) {
return await pollingHelper.poll(polling, context);
},
});

View File

@@ -0,0 +1,49 @@
import { createTrigger, TriggerStrategy } from '@activepieces/pieces-framework';
import { parseurAuth, parseurCommon } from '../common';
import { parserDropdown } from '../common/properties';
import { WebhookInformation } from '../common/types';
export const newTableFieldProcessed = createTrigger({
auth: parseurAuth,
name: 'newTableFieldProcessed',
displayName: 'New Table Field Processed',
description:
'Fires when a document with table fields is processed, and triggers for each row (table field) separately.',
props: {
mailboxId: parserDropdown({ required: true }),
},
sampleData: {},
type: TriggerStrategy.WEBHOOK,
async onEnable(context) {
const response = await parseurCommon.createWebhook({
apiKey: context.auth.secret_text,
event: 'table.processed',
target: context.webhookUrl,
category: 'CUSTOM',
});
await parseurCommon.enableWebhook({
apiKey: context.auth.secret_text,
webhookId: response.id,
mailboxId: context.propsValue.mailboxId as number,
});
await context.store.put<WebhookInformation>('_newTableFieldProcessed', {
webhookId: response.id,
});
},
async onDisable(context) {
const webhookInfo = await context.store.get<WebhookInformation>(
'_newTableFieldProcessed'
);
if (!webhookInfo) {
return;
}
await parseurCommon.deleteWebhook({
apiKey: context.auth.secret_text,
webhookId: webhookInfo.webhookId,
});
await context.store.delete('_newTableFieldProcessed');
},
async run(context) {
return [context.payload.body];
},
});