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,18 @@
{
"extends": ["../../../../.eslintrc.base.json"],
"ignorePatterns": ["!**/*"],
"overrides": [
{
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
"rules": {}
},
{
"files": ["*.ts", "*.tsx"],
"rules": {}
},
{
"files": ["*.js", "*.jsx"],
"rules": {}
}
]
}

View File

@@ -0,0 +1,7 @@
# pieces-subflows
This library was generated with [Nx](https://nx.dev).
## Building
Run `nx build pieces-subflows` to build the library.

View File

@@ -0,0 +1,4 @@
{
"name": "@activepieces/piece-subflows",
"version": "0.4.7"
}

View File

@@ -0,0 +1,65 @@
{
"name": "pieces-subflows",
"$schema": "../../../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "packages/pieces/community/subflows/src",
"projectType": "library",
"release": {
"version": {
"currentVersionResolver": "git-tag",
"preserveLocalDependencyProtocols": false,
"manifestRootsToUpdate": [
"dist/{projectRoot}"
]
}
},
"tags": [],
"targets": {
"build": {
"executor": "@nx/js:tsc",
"outputs": [
"{options.outputPath}"
],
"options": {
"outputPath": "dist/packages/pieces/community/subflows",
"tsConfig": "packages/pieces/community/subflows/tsconfig.lib.json",
"packageJson": "packages/pieces/community/subflows/package.json",
"main": "packages/pieces/community/subflows/src/index.ts",
"assets": [
"packages/pieces/community/subflows/*.md",
{
"input": "packages/pieces/community/subflows/src/i18n",
"output": "./src/i18n",
"glob": "**/!(i18n.json)"
}
],
"buildableProjectDepsInPackageJsonType": "dependencies",
"updateBuildableProjectDepsInPackageJson": true
},
"dependsOn": [
"^build",
"prebuild"
]
},
"nx-release-publish": {
"options": {
"packageRoot": "dist/{projectRoot}"
}
},
"lint": {
"executor": "@nx/eslint:lint",
"outputs": [
"{options.outputFile}"
]
},
"prebuild": {
"executor": "nx:run-commands",
"options": {
"cwd": "packages/pieces/community/subflows",
"command": "bun install --no-save --silent"
},
"dependsOn": [
"^build"
]
}
}
}

View File

@@ -0,0 +1,20 @@
{
"Sub Flows": "Sub Flows",
"Trigger and call another sub flow.": "Trigger and call another sub flow.",
"Call Flow": "Call Flow",
"Return Response": "Return Response",
"Call a flow that has \"Callable Flow\" trigger": "Call a flow that has \"Callable Flow\" trigger",
"Return response to the original flow": "Return response to the original flow",
"Flow": "Flow",
"Mode": "Mode",
"Wait for Response": "Wait for Response",
"Response": "Response",
"The flow to execute": "The flow to execute",
"Choose Simple for key-value or Advanced for JSON.": "Choose Simple for key-value or Advanced for JSON.",
"Simple": "Simple",
"Advanced": "Advanced",
"Callable Flow": "Callable Flow",
"Waiting to be triggered from another flow": "Waiting to be triggered from another flow",
"Sample Data": "Sample Data",
"The schema to be passed to the flow": "The schema to be passed to the flow"
}

View File

@@ -0,0 +1,19 @@
{
"Trigger and call another sub flow.": "Trigger und rufen Sie einen anderen Subfluss.",
"Call Flow": "Anruffluss",
"Return Response": "Rückgabeantwort",
"Call a flow that has \"Callable Flow\" trigger": "Rufe einen Fluss auf, der \"Callable Flow\" auslöst",
"Return response to the original flow": "Zurück zur Antwort auf den ursprünglichen Fluss",
"Flow": "Ablauf",
"Mode": "Modus",
"Wait for Response": "Warte auf Antwort",
"Response": "Antwort",
"The flow to execute": "Der auszuführende Flow",
"Choose Simple for key-value or Advanced for JSON.": "Wählen Sie Einfache für den Schlüsselwert oder Erweitert für JSON.",
"Simple": "Einfach",
"Advanced": "Erweitert",
"Callable Flow": "Anrufbarer Flow",
"Waiting to be triggered from another flow": "Warte auf Auslösung von einem anderen Fluss",
"Sample Data": "Beispieldaten",
"The schema to be passed to the flow": "Das Schema, das an den Fluss übergeben werden soll"
}

View File

@@ -0,0 +1,19 @@
{
"Trigger and call another sub flow.": "Activa y llama a otro sub-flujo.",
"Call Flow": "Llamada Flow",
"Return Response": "Respuesta de retorno",
"Call a flow that has \"Callable Flow\" trigger": "Llamar a un flujo que tiene activado \"flujo llamable\"",
"Return response to the original flow": "Devuelve la respuesta al flujo original",
"Flow": "Flujo",
"Mode": "Modo",
"Wait for Response": "Espere a la respuesta",
"Response": "Respuesta",
"The flow to execute": "El flujo a ejecutar",
"Choose Simple for key-value or Advanced for JSON.": "Elija Simple para el valor de clave o avanzado para JSON.",
"Simple": "Simple",
"Advanced": "Avanzado",
"Callable Flow": "Flujo Llamable",
"Waiting to be triggered from another flow": "Esperando a ser activado desde otro flujo",
"Sample Data": "Datos de ejemplo",
"The schema to be passed to the flow": "El esquema a pasar al flujo"
}

View File

@@ -0,0 +1,19 @@
{
"Trigger and call another sub flow.": "Déclenchez et appelez un autre sous-flux.",
"Call Flow": "Flux d'appel",
"Return Response": "Réponse de retour",
"Call a flow that has \"Callable Flow\" trigger": "Appeler un flux qui a le déclencheur \"Callable Flow\"",
"Return response to the original flow": "Renvoyer la réponse au flux d'origine",
"Flow": "Flow",
"Mode": "Mode",
"Wait for Response": "Attendre la réponse",
"Response": "Réponse",
"The flow to execute": "Le flux à exécuter",
"Choose Simple for key-value or Advanced for JSON.": "Choisissez Simple pour la valeur de la clé ou Advanced pour JSON.",
"Simple": "Simple",
"Advanced": "Avancé",
"Callable Flow": "Flux appelable",
"Waiting to be triggered from another flow": "En attente d'être déclenchée à partir d'un autre flux",
"Sample Data": "Données d'échantillonnage",
"The schema to be passed to the flow": "Le schéma à passer au flux"
}

View File

@@ -0,0 +1,20 @@
{
"Sub Flows": "Sub Flows",
"Trigger and call another sub flow.": "Trigger and call another sub flow.",
"Call Flow": "Call Flow",
"Return Response": "Return Response",
"Call a flow that has \"Callable Flow\" trigger": "Call a flow that has \"Callable Flow\" trigger",
"Return response to the original flow": "Return response to the original flow",
"Flow": "Flow",
"Mode": "Mode",
"Wait for Response": "Wait for Response",
"Response": "Response",
"The flow to execute": "The flow to execute",
"Choose Simple for key-value or Advanced for JSON.": "Choose Simple for key-value or Advanced for JSON.",
"Simple": "Simple",
"Advanced": "Advanced",
"Callable Flow": "Callable Flow",
"Waiting to be triggered from another flow": "Waiting to be triggered from another flow",
"Sample Data": "Sample Data",
"The schema to be passed to the flow": "The schema to be passed to the flow"
}

View File

@@ -0,0 +1,20 @@
{
"Sub Flows": "Sub Flows",
"Trigger and call another sub flow.": "Trigger and call another sub flow.",
"Call Flow": "Call Flow",
"Return Response": "Return Response",
"Call a flow that has \"Callable Flow\" trigger": "Call a flow that has \"Callable Flow\" trigger",
"Return response to the original flow": "Return response to the original flow",
"Flow": "Flow",
"Mode": "Mode",
"Wait for Response": "Wait for Response",
"Response": "Response",
"The flow to execute": "The flow to execute",
"Choose Simple for key-value or Advanced for JSON.": "Choose Simple for key-value or Advanced for JSON.",
"Simple": "Simple",
"Advanced": "Advanced",
"Callable Flow": "Callable Flow",
"Waiting to be triggered from another flow": "Waiting to be triggered from another flow",
"Sample Data": "Sample Data",
"The schema to be passed to the flow": "The schema to be passed to the flow"
}

View File

@@ -0,0 +1,19 @@
{
"Trigger and call another sub flow.": "別のサブフローをトリガーして呼び出します。",
"Call Flow": "コールフロー",
"Return Response": "返品対応",
"Call a flow that has \"Callable Flow\" trigger": "\"Callable Flow\" トリガーがあるフローを呼び出します。",
"Return response to the original flow": "元のフローに返信する",
"Flow": "Flow",
"Mode": "モード",
"Wait for Response": "応答待ち",
"Response": "回答",
"The flow to execute": "実行するフロー",
"Choose Simple for key-value or Advanced for JSON.": "JSONの場合は「単純」、または「高度」を選択します。",
"Simple": "単純な",
"Advanced": "高度な設定",
"Callable Flow": "呼び出し可能なフロー",
"Waiting to be triggered from another flow": "別のフローからのトリガーを待機しています",
"Sample Data": "サンプルデータ",
"The schema to be passed to the flow": "フローに渡されるスキーマ"
}

View File

@@ -0,0 +1,19 @@
{
"Trigger and call another sub flow.": "Trigger en bel een andere sub-stroom.",
"Call Flow": "Bel Flow",
"Return Response": "Antwoord retour",
"Call a flow that has \"Callable Flow\" trigger": "Bel een stroom aan die \"Callable Flow\" trigger heeft",
"Return response to the original flow": "Retourneer reactie op de originele stroom",
"Flow": "Stroom",
"Mode": "Modus",
"Wait for Response": "Wacht op reactie",
"Response": "Antwoord",
"The flow to execute": "De stroom om uit te voeren",
"Choose Simple for key-value or Advanced for JSON.": "Kies Simpel voor sleutelwaarde of Geavanceerd voor JSON.",
"Simple": "Eenvoudig",
"Advanced": "Geavanceerd",
"Callable Flow": "Kalmerbare Stroom",
"Waiting to be triggered from another flow": "Wachten om geactiveerd te worden via een andere stroom",
"Sample Data": "Voorbeeld gegevens",
"The schema to be passed to the flow": "Het schema dat aan de stroom moet worden doorgegeven"
}

View File

@@ -0,0 +1,19 @@
{
"Trigger and call another sub flow.": "Disparar e chamar outro sub fluxo.",
"Call Flow": "Ligar para Flow",
"Return Response": "Retornar Resposta",
"Call a flow that has \"Callable Flow\" trigger": "Chamar um fluxo com o gatilho \"Flow Callable\"",
"Return response to the original flow": "Retornar a resposta ao fluxo original",
"Flow": "Fluxo",
"Mode": "Modo",
"Wait for Response": "Aguarda Resposta",
"Response": "Resposta",
"The flow to execute": "Fluxo para executar",
"Choose Simple for key-value or Advanced for JSON.": "Escolha Simples para o valor-chave ou Avançado para JSON.",
"Simple": "Simples",
"Advanced": "Avançado",
"Callable Flow": "Fluxo de chamada",
"Waiting to be triggered from another flow": "Esperando para ser acionado de outro fluxo",
"Sample Data": "Conteúdo de Exemplo",
"The schema to be passed to the flow": "O esquema a ser passado ao fluxo"
}

View File

@@ -0,0 +1,20 @@
{
"Sub Flows": "Под-потоки",
"Trigger and call another sub flow.": "Запустите и вызовите другой подпоток.",
"Call Flow": "Вызов по тесту",
"Return Response": "Ответ на возврат",
"Call a flow that has \"Callable Flow\" trigger": "Вызов потока, который имеет триггер \"Callable Flow\"",
"Return response to the original flow": "Возврат ответа на исходный поток",
"Flow": "Поток",
"Mode": "Режим",
"Wait for Response": "Ожидание ответа",
"Response": "Замечание",
"The flow to execute": "Выполняемый поток",
"Choose Simple for key-value or Advanced for JSON.": "Выберите простую для ключевого значения или Расширенные для JSON.",
"Simple": "Простой",
"Advanced": "Расширенные",
"Callable Flow": "Вызываемый поток",
"Waiting to be triggered from another flow": "Ожидание срабатывания из другого потока",
"Sample Data": "Образцы данных",
"The schema to be passed to the flow": "Схема передается потоку"
}

View File

@@ -0,0 +1,19 @@
{
"Trigger and call another sub flow.": "Trigger and call another sub flow.",
"Call Flow": "Call Flow",
"Return Response": "Return Response",
"Call a flow that has \"Callable Flow\" trigger": "Call a flow that has \"Callable Flow\" trigger",
"Return response to the original flow": "Return response to the original flow",
"Flow": "Flow",
"Mode": "Mode",
"Wait for Response": "Wait for Response",
"Response": "Response",
"The flow to execute": "The flow to execute",
"Choose Simple for key-value or Advanced for JSON.": "Choose Simple for key-value or Advanced for JSON.",
"Simple": "Simple",
"Advanced": "Advanced",
"Callable Flow": "Callable Flow",
"Waiting to be triggered from another flow": "Waiting to be triggered from another flow",
"Sample Data": "Sample Data",
"The schema to be passed to the flow": "The schema to be passed to the flow"
}

View File

@@ -0,0 +1,20 @@
{
"Sub Flows": "Sub Flows",
"Trigger and call another sub flow.": "Trigger and call another sub flow.",
"Call Flow": "Call Flow",
"Return Response": "Return Response",
"Call a flow that has \"Callable Flow\" trigger": "Call a flow that has \"Callable Flow\" trigger",
"Return response to the original flow": "Return response to the original flow",
"Flow": "Flow",
"Mode": "Mode",
"Wait for Response": "Wait for Response",
"Response": "Response",
"The flow to execute": "The flow to execute",
"Choose Simple for key-value or Advanced for JSON.": "Choose Simple for key-value or Advanced for JSON.",
"Simple": "Simple",
"Advanced": "Advanced",
"Callable Flow": "Callable Flow",
"Waiting to be triggered from another flow": "Waiting to be triggered from another flow",
"Sample Data": "Sample Data",
"The schema to be passed to the flow": "The schema to be passed to the flow"
}

View File

@@ -0,0 +1,19 @@
{
"Trigger and call another sub flow.": "Trigger and call another sub flow.",
"Call Flow": "Call Flow",
"Return Response": "退货回复",
"Call a flow that has \"Callable Flow\" trigger": "Call a flow that has \"Callable Flow\" trigger",
"Return response to the original flow": "Return response to the original flow",
"Flow": "流",
"Mode": "Mode",
"Wait for Response": "Wait for Response",
"Response": "答复",
"The flow to execute": "The flow to execute",
"Choose Simple for key-value or Advanced for JSON.": "Choose Simple for key-value or Advanced for JSON.",
"Simple": "Simple",
"Advanced": "Advanced",
"Callable Flow": "Callable Flow",
"Waiting to be triggered from another flow": "Waiting to be triggered from another flow",
"Sample Data": "Sample Data",
"The schema to be passed to the flow": "The schema to be passed to the flow"
}

View File

@@ -0,0 +1,17 @@
import { createPiece, PieceAuth } from '@activepieces/pieces-framework';
import { callFlow } from './lib/actions/call-flow';
import { callableFlow } from './lib/triggers/callable-flow';
import { response } from './lib/actions/respond';
import { PieceCategory } from '@activepieces/shared';
export const flows = createPiece({
displayName: 'Sub Flows',
description: 'Trigger and call another sub flow.',
auth: PieceAuth.None(),
minimumSupportedRelease: '0.67.1',
categories: [PieceCategory.CORE, PieceCategory.FLOW_CONTROL],
logoUrl: 'https://cdn.activepieces.com/pieces/flows.svg',
authors: ['hazemadelkhalel'],
actions: [callFlow, response],
triggers: [callableFlow],
});

View File

@@ -0,0 +1,153 @@
import {
createAction,
DynamicPropsValue,
PieceAuth,
Property,
} from '@activepieces/pieces-framework';
import { httpClient, HttpMethod } from '@activepieces/pieces-common';
import { ExecutionType, FAIL_PARENT_ON_FAILURE_HEADER, isNil, PauseType, PARENT_RUN_ID_HEADER } from '@activepieces/shared';
import { CallableFlowRequest, CallableFlowResponse, findFlowByExternalIdOrThrow, listEnabledFlowsWithSubflowTrigger } from '../common';
type FlowValue = {
externalId: string;
exampleData: unknown;
};
export const callFlow = createAction({
name: 'callFlow',
displayName: 'Call Flow',
description: 'Call a flow that has "Callable Flow" trigger',
props: {
flow: Property.Dropdown<FlowValue>({
auth: PieceAuth.None(),
displayName: 'Flow',
description: 'The flow to execute',
required: true,
options: async (_, context) => {
const flows = await listEnabledFlowsWithSubflowTrigger({
flowsContext: context.flows,
});
return {
options: flows.map((flow) => ({
value: {
externalId: flow.externalId ?? flow.id,
exampleData: flow.version.trigger.settings.input.exampleData,
},
label: flow.version.displayName,
})),
};
},
refreshers: [],
}),
mode: Property.StaticDropdown({
displayName: 'Mode',
required: true,
description: 'Choose Simple for key-value or Advanced for JSON.',
defaultValue: 'simple',
options: {
disabled: false,
options: [
{
label: 'Simple',
value: 'simple',
},
{
label: 'Advanced',
value: 'advanced',
},
],
},
}),
flowProps: Property.DynamicProperties({
auth: PieceAuth.None(),
description: '',
displayName: '',
required: true,
refreshers: ['flow', 'mode'],
props: async (propsValue) => {
const castedFlowValue = propsValue['flow'] as unknown as FlowValue;
const mode = propsValue['mode'] as unknown as string;
const fields: DynamicPropsValue = {};
if (!isNil(castedFlowValue)) {
if (mode === 'simple') {
fields['payload'] = Property.Object({
displayName: 'Payload',
required: true,
defaultValue: (castedFlowValue.exampleData as unknown as { sampleData: object }).sampleData,
});
}
else{
fields['payload'] = Property.Json({
displayName: 'Payload',
description:
'Provide the data to be passed to the flow',
required: true,
defaultValue: (castedFlowValue.exampleData as unknown as { sampleData: object }).sampleData,
});
}
}
return fields;
},
}),
waitForResponse: Property.Checkbox({
displayName: 'Wait for Response',
required: false,
defaultValue: false,
}),
},
async run(context) {
if (context.executionType === ExecutionType.RESUME) {
const response = context.resumePayload.body as CallableFlowResponse;
const shouldFailParentRun = response.status === 'error' && context.propsValue.waitForResponse
if (shouldFailParentRun) {
throw new Error(JSON.stringify(response.data, null, 2))
}
return {
status: response.status,
data: response.data
}
}
const payload = context.propsValue.flowProps['payload'];
const flow = await findFlowByExternalIdOrThrow({
flowsContext: context.flows,
externalId: context.propsValue.flow?.externalId,
});
const response = await httpClient.sendRequest<CallableFlowRequest>({
method: HttpMethod.POST,
url: `${context.server.apiUrl}v1/webhooks/${flow?.id}`,
headers: {
'Content-Type': 'application/json',
[PARENT_RUN_ID_HEADER]: context.run.id,
[FAIL_PARENT_ON_FAILURE_HEADER]: context.propsValue.waitForResponse ? 'true' : 'false',
},
body: {
data: payload,
callbackUrl: context.propsValue.waitForResponse ? context.generateResumeUrl({
queryParams: {}
}) : undefined,
},
});
if (context.propsValue.waitForResponse) {
context.run.pause({
pauseMetadata: {
type: PauseType.WEBHOOK,
response: {},
}
})
}
return response.body;
},
errorHandlingOptions: {
continueOnFailure: {
defaultValue:false,
hide:false,
},
retryOnFailure: {
defaultValue:false,
hide:false,
}
}
});

View File

@@ -0,0 +1,74 @@
import { DynamicPropsValue, PieceAuth, Property, StoreScope, createAction } from '@activepieces/pieces-framework';
import { callableFlowKey, CallableFlowResponse, MOCK_CALLBACK_IN_TEST_FLOW_URL } from '../common';
import { httpClient, HttpMethod } from '@activepieces/pieces-common';
import { isNil } from '@activepieces/shared';
export const response = createAction({
name: 'returnResponse',
displayName: 'Return Response',
description: 'Return response to the original flow',
props: {
mode: Property.StaticDropdown({
displayName: 'Mode',
description: 'Choose Simple for key-value or Advanced for JSON.',
required: true,
defaultValue: 'simple',
options: {
disabled: false,
options: [
{
label: 'Simple',
value: 'simple',
},
{
label: 'Advanced',
value: 'advanced',
},
],
},
}),
response: Property.DynamicProperties({
auth: PieceAuth.None(),
displayName: 'Response',
required: true,
refreshers: ['mode'],
props: async (propsValue) => {
const mode = propsValue['mode'] as unknown as string;
const fields: DynamicPropsValue = {};
if (mode === 'simple') {
fields['response'] = Property.Object({
displayName: 'Response',
required: true,
});
} else {
fields['response'] = Property.Json({
displayName: 'Response',
required: true,
});
}
return fields;
},
}),
},
async test(context) {
return context.propsValue.response['response'];
},
async run(context) {
const response = context.propsValue.response['response'];
const callbackUrl = await context.store.get<string>(callableFlowKey(context.run.id), StoreScope.FLOW);
const isNotTestFlow = callbackUrl !== MOCK_CALLBACK_IN_TEST_FLOW_URL;
if (isNotTestFlow && !isNil(callbackUrl)) {
await httpClient.sendRequest<CallableFlowResponse>({
method: HttpMethod.POST,
url: callbackUrl,
body: {
status: 'success',
data: response
},
retries: 10,
});
}
return response;
},
});

View File

@@ -0,0 +1,64 @@
import { FlowStatus, FlowTriggerType, isNil, PopulatedFlow } from "@activepieces/shared";
import { FlowsContext, ListFlowsContextParams } from "@activepieces/pieces-framework";
export const callableFlowKey = (runId: string) => `callableFlow_${runId}`;
export type CallableFlowRequest = {
data: unknown;
callbackUrl: string;
}
export type CallableFlowResponse = {
status: 'success' | 'error';
data: unknown;
}
export const MOCK_CALLBACK_IN_TEST_FLOW_URL = 'MOCK';
export async function listEnabledFlowsWithSubflowTrigger({
flowsContext,
params,
}: ListParams) {
const allFlows = (await flowsContext.list(params)).data;
const flows = allFlows.filter(
(flow) =>
flow.status === FlowStatus.ENABLED &&
flow.version.trigger.type === FlowTriggerType.PIECE &&
flow.version.trigger.settings.pieceName ==
'@activepieces/piece-subflows'
);
return flows;
}
export async function findFlowByExternalIdOrThrow({
flowsContext,
externalId,
}: {
flowsContext: FlowsContext;
externalId: string | undefined;
}): Promise<PopulatedFlow> {
if (isNil(externalId)) {
throw new Error(JSON.stringify({
message: 'Please select a flow',
}));
}
const externalIds = [externalId];
const allFlows = await listEnabledFlowsWithSubflowTrigger({
flowsContext,
params: {
externalIds
}
});
if (allFlows.length === 0) {
throw new Error(JSON.stringify({
message: 'Flow not found',
externalId,
}));
}
return allFlows[0];
}
type ListParams = {
flowsContext: FlowsContext,
params?: ListFlowsContextParams
}

View File

@@ -0,0 +1,83 @@
import {
createTrigger,
DynamicPropsValue,
PieceAuth,
Property,
StoreScope,
TriggerStrategy,
} from '@activepieces/pieces-framework';
import { callableFlowKey, CallableFlowRequest, MOCK_CALLBACK_IN_TEST_FLOW_URL } from '../common';
export const callableFlow = createTrigger({
name: 'callableFlow',
displayName: 'Callable Flow',
description: 'Waiting to be triggered from another flow',
props: {
mode: Property.StaticDropdown({
displayName: 'Mode',
required: true,
description: 'Choose Simple for key-value or Advanced for JSON.',
defaultValue: 'simple',
options: {
disabled: false,
options: [
{
label: 'Simple',
value: 'simple',
},
{
label: 'Advanced',
value: 'advanced',
},
],
},
}),
exampleData: Property.DynamicProperties({
auth: PieceAuth.None(),
displayName: 'Sample Data',
description: 'The schema to be passed to the flow',
required: true,
refreshers: ['mode'],
props: async (propsValue) => {
const mode = propsValue['mode'] as unknown as string;
const fields: DynamicPropsValue = {};
if (mode === 'simple') {
fields['sampleData'] = Property.Object({
displayName: 'Sample Data',
required: true,
});
} else {
fields['sampleData'] = Property.Json({
displayName: 'Sample Data',
required: true,
});
}
return fields;
},
}),
},
sampleData: null,
type: TriggerStrategy.WEBHOOK,
async onEnable() {
// ignore
},
async onDisable() {
// ignore
},
async test(context) {
const request: CallableFlowRequest = {
data: context.propsValue.exampleData['sampleData'],
callbackUrl: MOCK_CALLBACK_IN_TEST_FLOW_URL
}
return [request];
},
async run(context) {
return [context.payload.body];
},
async onStart(context) {
const request = context.payload as CallableFlowRequest;
if (request.callbackUrl) {
await context.store.put(callableFlowKey(context.run.id), request.callbackUrl, StoreScope.FLOW);
}
}
});

View File

@@ -0,0 +1,19 @@
{
"extends": "../../../../tsconfig.base.json",
"compilerOptions": {
"module": "commonjs",
"forceConsistentCasingInFileNames": true,
"strict": true,
"noImplicitOverride": true,
"noPropertyAccessFromIndexSignature": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true
},
"files": [],
"include": [],
"references": [
{
"path": "./tsconfig.lib.json"
}
]
}

View File

@@ -0,0 +1,11 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"module": "commonjs",
"outDir": "../../../../dist/out-tsc",
"declaration": true,
"types": ["node"]
},
"exclude": ["jest.config.ts", "src/**/*.spec.ts", "src/**/*.test.ts"],
"include": ["src/**/*.ts"]
}