All files / src/platform/workflows/schemas workflow.schema.ts

0% Statements 0/57
0% Branches 0/8
100% Functions 0/0
0% Lines 0/47

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146                                                                                                                                                                                                                                                                                                   
import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
import { Document, Schema as MongooseSchema } from 'mongoose';
 
// ============================================================
// WORKFLOW DEFINITION
// ============================================================
@Schema({ timestamps: true, collection: 'workflow_definitions' })
export class WorkflowDefinition extends Document {
  @Prop({ required: true, index: true })
  tenantId: string;
 
  @Prop({ required: true })
  name: string;
 
  @Prop({ default: null })
  description: string;
 
  @Prop({ required: true })
  triggerType: string; // 'EVENT' | 'SCHEDULED' | 'MANUAL' | 'WEBHOOK' | 'RECORD_CREATED' | 'RECORD_UPDATED' | 'FIELD_CHANGED'
 
  @Prop({ default: null })
  eventKey: string; // e.g. 'platform.invoice.created.v1'
 
  @Prop({ default: null })
  cron: string; // cron expression if scheduled
 
  @Prop({ default: false })
  isActive: boolean;
 
  @Prop({ default: 'DRAFT', index: true })
  status: string; // 'DRAFT' | 'PUBLISHED'
 
  @Prop({ default: 1 })
  version: number;
 
  @Prop({ default: 100 })
  maxNodes: number;
 
  @Prop({ default: 300000 }) // 5 minutes
  maxExecutionDurationMs: number;
 
  @Prop({ default: null })
  createdBy: string;
}
export const WorkflowDefinitionSchema =
  SchemaFactory.createForClass(WorkflowDefinition);
WorkflowDefinitionSchema.index({ tenantId: 1, triggerType: 1 });
 
// ============================================================
// WORKFLOW NODE — individual steps within a workflow
// ============================================================
@Schema({ timestamps: true, collection: 'workflow_nodes' })
export class WorkflowNode extends Document {
  @Prop({ required: true, index: true })
  workflowDefinitionId: string;
 
  @Prop({ required: true })
  nodeId: string; // Unique within workflow, e.g. 'node_1'
 
  @Prop({ required: true })
  type: string; // 'CONDITION' | 'BRANCH' | 'DELAY' | 'NOTIFICATION' | 'APPROVAL_REQUEST' | 'CREATE_RECORD' | 'UPDATE_RECORD' | 'CREATE_TASK' | 'HTTP_WEBHOOK' | 'TRANSFORM_DATA' | 'STOP'
 
  @Prop({ type: MongooseSchema.Types.Mixed, default: {} })
  config: any; // Node-specific configuration
}
export const WorkflowNodeSchema = SchemaFactory.createForClass(WorkflowNode);
 
// ============================================================
// WORKFLOW CONNECTION — edges between nodes
// ============================================================
@Schema({ timestamps: true, collection: 'workflow_connections' })
export class WorkflowConnection extends Document {
  @Prop({ required: true, index: true })
  workflowDefinitionId: string;
 
  @Prop({ required: true })
  fromNodeId: string;
 
  @Prop({ required: true })
  toNodeId: string;
 
  @Prop({ default: null })
  conditionExpression: string; // Safe expression for conditional routing
}
export const WorkflowConnectionSchema =
  SchemaFactory.createForClass(WorkflowConnection);
 
// ============================================================
// WORKFLOW EXECUTION — runtime instance
// ============================================================
@Schema({ timestamps: true, collection: 'workflow_executions' })
export class WorkflowExecution extends Document {
  @Prop({ required: true, index: true })
  workflowDefinitionId: string;
 
  @Prop({ required: true, index: true })
  tenantId: string;
 
  @Prop({ required: true, default: 'RUNNING', index: true })
  status: string; // 'RUNNING' | 'COMPLETED' | 'FAILED' | 'TIMED_OUT' | 'CANCELLED'
 
  @Prop({ default: null })
  error: string;
 
  @Prop({ default: null })
  correlationId: string;
 
  @Prop({ type: MongooseSchema.Types.Mixed, default: {} })
  triggerPayload: any;
 
  @Prop({ default: null })
  startedAt: Date;
 
  @Prop({ default: null })
  completedAt: Date;
}
export const WorkflowExecutionSchema =
  SchemaFactory.createForClass(WorkflowExecution);
 
// ============================================================
// WORKFLOW EXECUTION STEP — per-node runtime log
// ============================================================
@Schema({ timestamps: true, collection: 'workflow_execution_steps' })
export class WorkflowExecutionStep extends Document {
  @Prop({ required: true, index: true })
  executionId: string;
 
  @Prop({ required: true })
  nodeId: string;
 
  @Prop({ required: true, default: 'PENDING' })
  status: string; // 'PENDING' | 'RUNNING' | 'COMPLETED' | 'FAILED' | 'SKIPPED'
 
  @Prop({ default: 0 })
  executionTimeMs: number;
 
  @Prop({ type: MongooseSchema.Types.Mixed, default: null })
  output: any;
 
  @Prop({ default: null })
  error: string;
}
export const WorkflowExecutionStepSchema = SchemaFactory.createForClass(
  WorkflowExecutionStep,
);