- Compute the context the selected step had access to during its execution and display it with the `<JsonNestedNode />` component - Ensure several steps with the same name can be displayed in order - Prevent access to the input tab in a few cases - Hide the input tab when the trigger node is selected as this node takes no input - Hide the input tab when the selected node has not been executed yet or is currently executed - Fallback to the Node tab when the Input tab can't be accessed ## Successful workflow execution https://github.com/user-attachments/assets/4a2bb5f5-450c-46ed-b2d7-a14d3b1e5c1f ## Failed workflow execution https://github.com/user-attachments/assets/3be2784e-e76c-48ab-aef5-17f63410898e Closes https://github.com/twentyhq/core-team-issues/issues/433
213 lines
5.6 KiB
TypeScript
213 lines
5.6 KiB
TypeScript
import { z } from 'zod';
|
|
|
|
// Base schemas
|
|
export const objectRecordSchema = z.record(z.any());
|
|
|
|
export const baseWorkflowActionSettingsSchema = z.object({
|
|
input: z.object({}).passthrough(),
|
|
outputSchema: z.object({}).passthrough(),
|
|
errorHandlingOptions: z.object({
|
|
retryOnFailure: z.object({
|
|
value: z.boolean(),
|
|
}),
|
|
continueOnFailure: z.object({
|
|
value: z.boolean(),
|
|
}),
|
|
}),
|
|
});
|
|
|
|
export const baseWorkflowActionSchema = z.object({
|
|
id: z.string(),
|
|
name: z.string(),
|
|
valid: z.boolean(),
|
|
});
|
|
|
|
export const baseTriggerSchema = z.object({
|
|
name: z.string().optional(),
|
|
type: z.string(),
|
|
});
|
|
|
|
// Action settings schemas
|
|
export const workflowCodeActionSettingsSchema =
|
|
baseWorkflowActionSettingsSchema.extend({
|
|
input: z.object({
|
|
serverlessFunctionId: z.string(),
|
|
serverlessFunctionVersion: z.string(),
|
|
serverlessFunctionInput: z.record(z.any()),
|
|
}),
|
|
});
|
|
|
|
export const workflowSendEmailActionSettingsSchema =
|
|
baseWorkflowActionSettingsSchema.extend({
|
|
input: z.object({
|
|
connectedAccountId: z.string(),
|
|
email: z.string(),
|
|
subject: z.string().optional(),
|
|
body: z.string().optional(),
|
|
}),
|
|
});
|
|
|
|
export const workflowCreateRecordActionSettingsSchema =
|
|
baseWorkflowActionSettingsSchema.extend({
|
|
input: z.object({
|
|
objectName: z.string(),
|
|
objectRecord: objectRecordSchema,
|
|
}),
|
|
});
|
|
|
|
export const workflowUpdateRecordActionSettingsSchema =
|
|
baseWorkflowActionSettingsSchema.extend({
|
|
input: z.object({
|
|
objectName: z.string(),
|
|
objectRecord: objectRecordSchema,
|
|
objectRecordId: z.string(),
|
|
fieldsToUpdate: z.array(z.string()),
|
|
}),
|
|
});
|
|
|
|
export const workflowDeleteRecordActionSettingsSchema =
|
|
baseWorkflowActionSettingsSchema.extend({
|
|
input: z.object({
|
|
objectName: z.string(),
|
|
objectRecordId: z.string(),
|
|
}),
|
|
});
|
|
|
|
export const workflowFindRecordsActionSettingsSchema =
|
|
baseWorkflowActionSettingsSchema.extend({
|
|
input: z.object({
|
|
objectName: z.string(),
|
|
limit: z.number().optional(),
|
|
}),
|
|
});
|
|
|
|
// Action schemas
|
|
export const workflowCodeActionSchema = baseWorkflowActionSchema.extend({
|
|
type: z.literal('CODE'),
|
|
settings: workflowCodeActionSettingsSchema,
|
|
});
|
|
|
|
export const workflowSendEmailActionSchema = baseWorkflowActionSchema.extend({
|
|
type: z.literal('SEND_EMAIL'),
|
|
settings: workflowSendEmailActionSettingsSchema,
|
|
});
|
|
|
|
export const workflowCreateRecordActionSchema = baseWorkflowActionSchema.extend(
|
|
{
|
|
type: z.literal('CREATE_RECORD'),
|
|
settings: workflowCreateRecordActionSettingsSchema,
|
|
},
|
|
);
|
|
|
|
export const workflowUpdateRecordActionSchema = baseWorkflowActionSchema.extend(
|
|
{
|
|
type: z.literal('UPDATE_RECORD'),
|
|
settings: workflowUpdateRecordActionSettingsSchema,
|
|
},
|
|
);
|
|
|
|
export const workflowDeleteRecordActionSchema = baseWorkflowActionSchema.extend(
|
|
{
|
|
type: z.literal('DELETE_RECORD'),
|
|
settings: workflowDeleteRecordActionSettingsSchema,
|
|
},
|
|
);
|
|
|
|
export const workflowFindRecordsActionSchema = baseWorkflowActionSchema.extend({
|
|
type: z.literal('FIND_RECORDS'),
|
|
settings: workflowFindRecordsActionSettingsSchema,
|
|
});
|
|
|
|
// Combined action schema
|
|
export const workflowActionSchema = z.discriminatedUnion('type', [
|
|
workflowCodeActionSchema,
|
|
workflowSendEmailActionSchema,
|
|
workflowCreateRecordActionSchema,
|
|
workflowUpdateRecordActionSchema,
|
|
workflowDeleteRecordActionSchema,
|
|
workflowFindRecordsActionSchema,
|
|
]);
|
|
|
|
// Trigger schemas
|
|
export const workflowDatabaseEventTriggerSchema = baseTriggerSchema.extend({
|
|
type: z.literal('DATABASE_EVENT'),
|
|
settings: z.object({
|
|
eventName: z.string(),
|
|
input: z.object({}).passthrough().optional(),
|
|
outputSchema: z.object({}).passthrough(),
|
|
objectType: z.string().optional(),
|
|
}),
|
|
});
|
|
|
|
export const workflowManualTriggerSchema = baseTriggerSchema.extend({
|
|
type: z.literal('MANUAL'),
|
|
settings: z.object({
|
|
objectType: z.string().optional(),
|
|
outputSchema: z.object({}).passthrough(),
|
|
}),
|
|
});
|
|
|
|
export const workflowCronTriggerSchema = baseTriggerSchema.extend({
|
|
type: z.literal('CRON'),
|
|
settings: z.discriminatedUnion('type', [
|
|
z.object({
|
|
type: z.literal('HOURS'),
|
|
schedule: z.object({ hour: z.number(), minute: z.number() }),
|
|
outputSchema: z.object({}).passthrough(),
|
|
}),
|
|
z.object({
|
|
type: z.literal('MINUTES'),
|
|
schedule: z.object({ minute: z.number() }),
|
|
outputSchema: z.object({}).passthrough(),
|
|
}),
|
|
z.object({
|
|
type: z.literal('CUSTOM'),
|
|
pattern: z.string(),
|
|
outputSchema: z.object({}).passthrough(),
|
|
}),
|
|
]),
|
|
});
|
|
|
|
// Combined trigger schema
|
|
export const workflowTriggerSchema = z.discriminatedUnion('type', [
|
|
workflowDatabaseEventTriggerSchema,
|
|
workflowManualTriggerSchema,
|
|
workflowCronTriggerSchema,
|
|
]);
|
|
|
|
// Step output schemas
|
|
const workflowExecutorOutputSchema = z.object({
|
|
result: z.any().optional(),
|
|
error: z.string().optional(),
|
|
});
|
|
|
|
export const workflowRunOutputStepsOutputSchema = z.record(
|
|
workflowExecutorOutputSchema,
|
|
);
|
|
|
|
// Final workflow run output schema
|
|
export const workflowRunOutputSchema = z.object({
|
|
flow: z.object({
|
|
trigger: workflowTriggerSchema,
|
|
steps: z.array(workflowActionSchema),
|
|
}),
|
|
stepsOutput: workflowRunOutputStepsOutputSchema.optional(),
|
|
error: z.string().optional(),
|
|
});
|
|
|
|
export const workflowRunContextSchema = z.record(z.any());
|
|
|
|
export const workflowRunSchema = z
|
|
.object({
|
|
__typename: z.literal('WorkflowRun'),
|
|
id: z.string(),
|
|
workflowVersionId: z.string(),
|
|
output: workflowRunOutputSchema.nullable(),
|
|
context: workflowRunContextSchema.nullable(),
|
|
createdAt: z.string(),
|
|
deletedAt: z.string().nullable(),
|
|
endedAt: z.string().nullable(),
|
|
name: z.string(),
|
|
})
|
|
.passthrough();
|