Sanity Library Reference Docs
    Preparing search index...

    Module @sanity/workflow-blueprint - v0.32.0

    @sanity/workflow-blueprint

    Sanity Blueprints integration for Workflows. This one package owns both halves of the sanity.workflow contract: the manifest definer and the provider that the Blueprints API runs.

    Note

    The package contains the complete resource implementation, but publishing it does not register a new resource type. sanity.workflow becomes deployable only after the Blueprints API imports and registers workflowProvider. Until that server change ships, deploy definitions with sanity workflows deploy instead of adding this resource to a live stack.

    The public package is intentionally the single Workflows-owned implementation:

    1. Authors currently import defineWorkflows from this package. After the downstream Blueprints release, @sanity/blueprints becomes the discoverable import and delegates here without duplicating Workflows validation.
    2. sanity blueprints deploy evaluates sanity.blueprint.ts and sends the resulting sanity.workflow resource to the existing Blueprints API.
    3. The Blueprints API registers workflowProvider directly from this package. During pre-deploy, the server calls the provider's write-free init and atomically reserves the returned external ID for the Stack. The provider's requiresInitialization: true flag requires the server to reject an ordinary create that has no initialized resource record.
    4. The provider creates a Sanity client for the resource target and uses the deployment caller's token during normal deploy to write definition versions in the Content Lake. Read, update, rollback, and retain continue through the same server-coordinated lifecycle.

    There is no separate Workflows provider package. The implementation uses only public @sanity/client and @sanity/workflow-engine APIs, so keeping it public does not expose Blueprints server internals. The private Blueprints provider SDK stays in the Blueprints API repository, where TypeScript verifies that this package's structural provider contract still matches the server contract.

    defineWorkflows takes the same authoring shape as one deployments[] entry of a sanity.workflow.ts config (WorkflowDeploymentInput — the reader-floor acknowledgement is required). Share that authored object with defineWorkflowConfig; do not pass a parsed config.deployments[n] (that type leaves the floor unverified so commands that do not submit definitions can load a missing entry):

    // shared.ts
    import type {WorkflowDeploymentInput} from '@sanity/workflow-engine'

    export const prod = {
    expectedMinReaderModel: 4,
    name: 'prod',
    tag: 'prod',
    workflowResource: {type: 'dataset', id: 'acme.workflows'},
    definitions: [articleReview],
    } satisfies WorkflowDeploymentInput

    // sanity.workflow.ts
    import {defineWorkflowConfig} from '@sanity/workflow-engine/define'
    import {prod} from './shared'

    export default defineWorkflowConfig({deployments: [prod]})

    // sanity.blueprint.ts
    import {defineBlueprint} from '@sanity/blueprints'
    import {defineWorkflows} from '@sanity/workflow-blueprint'
    import {prod} from './shared'

    export default defineBlueprint({
    resources: [defineWorkflows(prod)],
    })

    The definer validates eagerly — definition structure, GROQ, and @<handle>: alias bindings all fail at manifest evaluation, in the author's terminal, never as a failed stack operation. The resulting resource is pure data: the deployment rides the manifest verbatim, definitions in authored form (alias expansion happens at provision).

    Blueprints matches resources by name (default: workflows-<deployment name>). Keep it stable after deployment: a retained resource cannot be renamed because removing the old name is rejected. Definitions are retain-only through blueprints: the default lifecycle is {deletionPolicy: 'retain'}. Destroying the stack detaches the resource and leaves every definition version in place; removing the resource from a deployed blueprint fails instead of deleting it. Removing one definition from the resource's deployment.definitions list stops managing that name but leaves its deployed versions in place. Policies that promise deletion (allow, replace) and every unsupported lifecycle key (including ownershipAction) are rejected at manifest evaluation and again at the provider JSON boundary.

    workflowProvider is the factory the Blueprints API registers. It owns the full server-facing lifecycle adapter and delegates the engine operations to the same exported primitives:

    import {
    workflowProvider,
    provisionWorkflowResource,
    readWorkflowResource,
    rollbackWorkflowResource,
    } from '@sanity/workflow-blueprint'

    // Registered by the Blueprints API under workflowProvider.resourceType
    // (`sanity.workflow`). Authors never call the provider directly.
    void workflowProvider

    // create and update are the same operation: the engine's definition deploy is
    // content-addressed and create-only, so identical content is a no-op and any
    // change mints the next immutable version.
    const receipt = await provisionWorkflowResource({resource, client})

    // Read returns the physical (workflowResource, tag) external ID and the latest
    // deployed version of each definition name still managed by this manifest.
    const snapshot = await readWorkflowResource({resource, client})

    // When a later stack action fails, rollback removes only versions this
    // successful provision created. Earlier and unchanged versions survive.
    await rollbackWorkflowResource({resource, client, receipt})

    The host lifecycle has two distinct phases:

    1. Pre-deploy calls workflowProvider.init. It validates the resource and returns its deterministic (workflowResource, tag) external ID without creating a Sanity client or reading from or writing to the Content Lake. The Blueprints API reserves (resource type, external ID) for the Stack.
    2. Normal deploy loads that initialized resource and calls the existing update path to provision definitions. A competing Stack must fail the ownership reservation before this phase can run.

    workflowProvider.requiresInitialization is true. A Blueprints API host must therefore reject ordinary create when no initialized resource record exists; calling create directly would bypass the ownership guarantee.

    client must be bound to the deployment's workflowResource with a token that can write definition documents there. Provisioning parses and validates the incoming resource at the boundary (parseWorkflowResource) — provider input is JSON from the stack, never a typed value. The Blueprints retain path must detach a destroyed stack without calling destroyWorkflowResource; that function deliberately throws if a caller attempts physical destruction.

    Rollback is compensation for a failed, uncommitted stack deployment, not a definition-history tool. It consumes the exact deploy receipt, ignores unchanged results, and deletes created versions in reverse dependency order without cascading into instances. A rollback replay is deliberately fail-closed: an absent receipt version and every engine cleanup failure are surfaced because the engine cannot prove a prior delete completed every phase.

    Interfaces

    DefineWorkflowsOptions
    NormalizedWorkflowsResourceLifecycle
    ResolvedWorkflowResource
    WorkflowProvisionReceipt
    WorkflowResourceDefinitionSnapshot
    WorkflowResourceRollbackScope
    WorkflowResourceScope
    WorkflowResourceSnapshot
    WorkflowsResource
    WorkflowsResourceLifecycle

    Variables

    WORKFLOW_RESOURCE_TYPE
    workflowProvider

    Functions

    defineWorkflows
    destroyWorkflowResource
    parseWorkflowDeployment
    parseWorkflowResource
    provisionWorkflowResource
    readWorkflowResource
    rollbackWorkflowResource
    workflowResourceExternalId