features
@particular/orchestrator
Reusable workflow engine with blueprints, flows, phase gates, lifecycle hooks, and composable UI components
Installation
bun add @particular/orchestrator
Subpath Imports
| Import Path | Description |
|---|---|
| @particular/orchestrator | Types-only barrel (safe for client bundles) |
| @particular/orchestrator/schema | Drizzle schema: blueprints, flows, phases, steps, actions |
| @particular/orchestrator/config | initializeOrchestrator() singleton and label config |
| @particular/orchestrator/handlers | OrchestratorHandlers class — blueprint CRUD, flow ops |
| @particular/orchestrator/snapshot | snapshotBlueprint() — deep-copy blueprint into live flow |
| @particular/orchestrator/advancement | Phase advancement, step completion, action fulfillment |
| @particular/orchestrator/hooks | Guard and hook orchestration with HookContext |
| @particular/orchestrator/rules | JSON rule evaluator for phase gates |
| @particular/orchestrator/metadata | Zod metadata schemas and parser |
| @particular/orchestrator/api | REST API route handler factories |
| @particular/orchestrator/server | Server component helpers (getFlowState, getFlowForEntity) |
| @particular/orchestrator/ui | Full UI barrel — components, hooks, and styles |
| @particular/orchestrator/ui/components | All component categories (shared, flow, fulfillment, blueprint) |
| @particular/orchestrator/ui/components/shared | Cross-cutting atoms: StatusBadge, StatusIcon, ActionTypeIcon, etc. |
| @particular/orchestrator/ui/components/flow | Flow viewer: FlowTimeline, FlowPhaseCard, FlowStepCard, FlowActionRow, etc. |
| @particular/orchestrator/ui/components/fulfillment | Action fulfillment UIs per type: Document, Note, Reminder, Checklist |
| @particular/orchestrator/ui/components/blueprint | Blueprint builder: BlueprintTreeView, PhaseCard, StepItem, ActionItem, etc. |
| @particular/orchestrator/ui/hooks | Headless hooks: useFlow, useBlueprint, useFlowActions, useFlowInspector, etc. |
| @particular/orchestrator/ui/styles | Style utilities: status configs, classNames defaults, mergeStyles |
Key Exports
| Export | Type | Description |
|---|---|---|
| OrchestratorHandlers | class | Blueprint CRUD, flow start/cancel/pause, step/action ops |
| initializeOrchestrator | function | Initialize with db, labels, hooks, and guards |
| snapshotBlueprint | function | Deep-copy a blueprint into live flow tables |
| advancePhase | function | Advance to next phase (auto or manual gate) |
| completeStep | function | Mark a flow step as completed |
| fulfillAction | function | Fulfill a typed action (document, note, etc.) |
| buildHookContext | function | Build HookContext for lifecycle events |
| FlowTimeline | component | Vertical phase timeline with connectors and renderPhase override |
| FlowPhaseCard | component | Collapsible phase card with color bar, status, and gate approval |
| FlowStepCard | component | Collapsible step card with status, due date, and action buttons |
| FlowActionRow | component | Action row with type icon, status badge, and fulfill/waive controls |
| FlowProgressBar | component | CVA progress bar with size and color variants |
| FlowSummaryDashboard | component | 3-column summary with phase/step/action progress |
| FlowInspectorPanel | component | Ready actions, blocked actions, and suggestions panel |
| BlueprintTreeView | component | Hierarchical blueprint editor: phases > steps > actions |
| FulfillmentRouter | component | Routes to Document/Note/Reminder/Checklist fulfillment UIs |
| StatusBadge | component | Pill badge with icon and label for any status type |
| useFlow | hook | Fetch and cache flow data by ID |
| useBlueprint | hook | Fetch and cache blueprint data by ID |
| useBlueprintEditor | hook | Full CRUD mutations for blueprint editing |
| useFlowActions | hook | Fulfill, waive, complete, skip, and advance mutations |
| useFlowInspector | hook | Fetch ready/blocked actions and suggestions |
| useFlowEvents | hook | Paginated event log with loadMore |
Usage Examples
Initialize orchestrator
import { initializeOrchestrator } from "@particular/orchestrator/config";
import { OrchestratorHandlers } from "@particular/orchestrator/handlers";
import { db } from "./db";
initializeOrchestrator({
db,
labels: { phase: "Stage", step: "Milestone", action: "Task" },
hooks: {
onFlowComplete: async (flow, ctx) => {
console.log(`Flow ${flow.id} completed for ${ctx.entityType}`);
},
},
});
const handlers = new OrchestratorHandlers(db);Create blueprint and start flow
// Create a reusable blueprint
const blueprint = await handlers.createBlueprint({
name: "onboarding",
label: "User Onboarding",
workflowType: "onboarding",
ownerId: orgId,
ownerType: "organization",
createdBy: userId,
});
// Add phases, steps, actions
const phase = await handlers.addPhase(blueprint.id, {
name: "setup", label: "Account Setup", sortOrder: 0, advanceMode: "auto",
});
await handlers.addStep(phase.id, {
name: "profile", label: "Complete Profile", sortOrder: 0,
});
// Start a live flow from the blueprint
const flow = await handlers.startFlow({
blueprintId: blueprint.id,
entityType: "user",
entityId: userId,
ownedBy: userId,
});Render flow timeline (React)
import { FlowTimeline } from "@particular/orchestrator/ui/components/flow";
import { useFlow } from "@particular/orchestrator/ui/hooks";
export function WorkflowView({ flowId }: { flowId: string }) {
const { flow, isLoading } = useFlow(flowId, { basePath: "/api/flows" });
if (isLoading || !flow) return null;
return (
<FlowTimeline
phases={flow.phases}
currentPhaseId={flow.currentPhaseId}
flowStatus={flow.status}
/>
);
}Blueprint editor with hooks
import { BlueprintTreeView } from "@particular/orchestrator/ui/components/blueprint";
import { useBlueprint, useBlueprintEditor } from "@particular/orchestrator/ui/hooks";
export function Editor({ id }: { id: string }) {
const { blueprint } = useBlueprint(id, { basePath: "/api/blueprints" });
const editor = useBlueprintEditor({ basePath: "/api/blueprints", blueprintId: id });
if (!blueprint) return null;
return (
<BlueprintTreeView
blueprint={blueprint}
mode="edit"
onAddPhase={editor.addPhase}
onUpdatePhase={editor.updatePhase}
onDeletePhase={editor.deletePhase}
/>
);
}