Eddy Dev Handbook
Technical reference

Workflow Export

Design and behavior of the workflow export feature in Eddy

Workflow Export Functionality

Source: This page is based on docs/WORKFLOW_EXPORT.md

Last Updated: January 1, 2026

This document outlines the design and behavior of the workflow export feature in Eddy. The feature allows users to export a complete workflow definition into a structured JSON file. This file can be used for backups, migrating workflows between environments, or as a basis for a templating system.


Overview

The export process packages a single, non-archived workflow and all its constituent parts into a versioned JSON object. The process is designed to be robust, ensuring data integrity and excluding irrelevant or archived data.

The core logic is handled by the exportWorkflow service, exposed via a secure API endpoint.


API Endpoint

Route: POST /api/workflows/export

Authorization: The requesting user must be a member of the group that owns the workflow.

Request Body:

{
  "workflow_id": "string (uuid)",
  "include_sheets": "boolean (optional, default: false)"
}

Response:

  • On success, it returns a 200 OK status with a JSON payload
  • HTTP headers are set to prompt a file download in the browser:
    • Content-Type: application/json
    • Content-Disposition: attachment; filename="eddy-workflow-export-<workflow-name>-<date>.json"
  • On failure (e.g., workflow not found, archived, or unauthorized), it returns an appropriate 4xx error code

Exported Data Structure

The exported JSON file has a top-level structure containing metadata and arrays of the workflow's components. The structure is strictly validated by EddyWorkflowExportZ.

// High-level structure from app/types/export.ts
type EddyWorkflowExportT = {
  version: number // Currently 1
  exportedAt: Date
  sourceWorkflowId: string

  // Core Workflow Components
  workflow: WorkflowDatabaseT
  pages: PageDatabaseT[]
  sections: SectionDatabaseT[]
  blocks: BlockDatabaseT[]
  blockOptions: BlockOptionT[]
  pageTransitions: PageTransitionT[]
  workflowRoles: WorkflowRoleT[]
  stageRoleAssignments: StageRoleAssignmentBaseDatabaseT[]

  // Optional Components
  sheets?: SheetT[]
  columns?: ColumnT[]
}

Core Logic & Data Integrity

The export service (app/services/workflows/export.ts) follows several key principles to ensure a clean and valid export.

1. Transactional Read

All database queries are wrapped in a single knex.transaction, ensuring a consistent snapshot of the data is read.

2. Exclusion of Archived Data

This is a fundamental rule:

  • The export will fail if the target workflow itself is archived
  • Any related entity (Page, Section, Block, Block Option, Sheet, Column) with a non-null archived_at timestamp is filtered out of the export
  • The logic also correctly excludes children of archived parents. For instance, if a Page is archived, all of its Sections and Blocks will be excluded, even if they are not archived themselves
  • Similarly, if a Section is archived, its Blocks are also excluded
  • Page Transitions and Stage Role Assignments are excluded if they reference an archived page

3. Sheet & Column Export (include_sheets: true)

When include_sheets is true, the service gathers a unique set of sheet IDs referenced by the workflow.

Sheets are included if they are linked from:

  • The workflow's scaffold_sheet_id
  • A section's sheet_id
  • A block's sheet_id

Columns have stricter inclusion criteria. They are only included if they meet two conditions:

  1. They are directly referenced by a non-archived block's column_id
  2. Their parent sheet is also being exported (i.e., it is not archived)

This means that other columns belonging to an exported sheet will not be included unless they are explicitly linked to a block, and columns referenced by blocks will not be included if their parent sheet is archived.

4. Final Validation

Before returning the data, the entire assembled object is parsed and validated against the EddyWorkflowExportZ schema. This Zod schema includes a .refine() check that programmatically verifies no archived entities are present, providing a final layer of defense for data integrity.


Edge Cases and Behavior

The integration tests (app/__tests__/integration/workflowExport.test.ts) cover numerous scenarios:

  • Empty Workflow: A workflow with no pages, sections, or blocks can be exported successfully. The corresponding arrays in the JSON file will simply be empty.
  • No Sheet References: If include_sheets is true but no sheets are linked to the workflow, the sheets and columns arrays will be present but empty.
  • Orphaned Entities: The system is robust against orphaned data. For example, a block_option whose parent block is archived will not be included because the parent block is filtered out first.
  • Data Isolation: The export is strictly scoped to the provided workflowId. No data from other workflows, even within the same group, will be included.
  • Deduplication: Sheets referenced by multiple sources (e.g., as a scaffold sheet and by a block) will only be included once in the sheets array.

Use Cases

1. Workflow Backup

Export workflows regularly to create backups that can be restored if needed.

2. Environment Migration

Export a workflow from a development environment and import it into staging or production.

3. Workflow Templates

Export a well-designed workflow and share it as a template for others to import and customize.

4. Version Control

Store exported workflows in version control systems to track changes over time.


On this page