Skip to content

WorkflowDescriptor

WorkflowDescriptor registers executable types with the workflow resolver.

Signature

dart
class WorkflowDescriptor {
  const WorkflowDescriptor({
    List<TypeDescriptor<TaskExecutor>> tasks = const [],
    List<TypeDescriptor<UserTaskExecutor>> userTasks = const [],
    List<TypeDescriptor<ConditionExecutor>> conditions = const [],
    List<NodeProcessor> nodeProcessors = const [],
    Map<String, WorkflowLifecycleHooks> lifecycleHooks = const {},
    String? title,
    String? description,
  });
}

Properties

PropertyTypePurpose
tasksList<TypeDescriptor<TaskExecutor>>Service-task executor factories.
userTasksList<TypeDescriptor<UserTaskExecutor>>User-task executor factories.
conditionsList<TypeDescriptor<ConditionExecutor>>Condition executor factories.
nodeProcessorsList<NodeProcessor>Engine-level processors for node types.
lifecycleHooksMap<String, WorkflowLifecycleHooks>Hooks keyed by workflow code.
titleString?Human-readable descriptor title.
descriptionString?Optional description.

Convenience Getters

dart
Set<String> get taskSchemaTypes;
Set<String> get userTaskSchemaTypes;
Set<String> get conditionSchemaTypes;

bool hasTask(String schemaType);
bool hasUserTask(String schemaType);
bool hasCondition(String schemaType);

WorkflowDescriptor merge(WorkflowDescriptor other);

Example

dart
final descriptor = WorkflowDescriptor(
  title: 'Document workflow executors',
  tasks: [
    ValidateDocumentExecutor.typeDescriptor,
    ApplyApprovalOutcomeExecutor.typeDescriptor,
  ],
  userTasks: [
    ApprovalUserTaskExecutor.typeDescriptor,
  ],
  conditions: [
    RequiresManagerCondition.typeDescriptor,
  ],
  lifecycleHooks: {
    'document-approval': WorkflowLifecycleHooks(
      onCancel: (instance, reason) async {
        await documentDrafts.release(instance.correlationId);
      },
    ),
  },
);

final context = RegistryTypeResolver(
  descriptors: [
    DefaultWorkflowDescriptor(),
    descriptor,
  ],
);

final engine = WorkflowEngine(
  context: context,
  storage: InMemoryStorage(),
  executionMode: ExecutionMode.production,
);
await engine.initialize();

TypeDescriptor Example

dart
class ValidateDocumentExecutor extends TaskExecutor {
  static const type = 'task.document.validate';

  static final typeDescriptor = TypeDescriptor<TaskExecutor>(
    schemaType: type,
    fromJson: (_) => ValidateDocumentExecutor(),
    title: 'Validate Document',
  );

  @override
  String get schemaType => type;

  @override
  String get name => 'Validate Document';

  @override
  Future<TaskResult> execute(ExecutionContext context) async {
    return TaskSuccess([
      SetOutputEffect(output: {'validated': true}),
    ]);
  }
}

Descriptor Order

Use defaults first:

dart
final context = RegistryTypeResolver(
  descriptors: [
    DefaultWorkflowDescriptor(),
    appDescriptor,
  ],
);

Descriptors are processed in order. Duplicates should be treated as explicit overrides.

Template Usage

dart
final template = ApprovalTemplate(domains: [approvalDomain]);

final context = RegistryTypeResolver(
  descriptors: [
    DefaultWorkflowDescriptor(),
    template.buildDescriptor(),
  ],
);

See Also