Framework.Transaction.DSL (Framework v0.5.0)

View Source

DSL functions available inside plan blocks.

All functions are pure and produce data structures that are resolved during the commit phase.

Summary

Functions

Declare a bounded READ node for multiple row lookup with required safety constraints.

Generate deterministic values from context for Clock.now/1.

Complete a successful operation path.

Declare a WRITE node for deleting data.

Declare email effect with deterministic idempotency key.

Assert a validation constraint in plan functions.

Fail an operation with a typed error.

Declare a READ node for a single row lookup.

Declare a locked READ node for shared row access.

Generate deterministic IDs from context for Id.new/1.

Declare a READ node for multiple row lookup.

Declare a locked READ node for multiple rows with shared access.

Get verified routes helper for navigation.

Translate a message key with optional bindings.

Translate a message key with pluralization support.

Declare a WRITE node for upserting data.

Declare webhook effect with deterministic idempotency key.

Functions

bounded_list(table, index_fields, opts)

Declare a bounded READ node for multiple row lookup with required safety constraints.

Clean ergonomic API:

  • bounded_list(:orders, [user_id: value], opts) - Keyword syntax for filtering
  • bounded_list(:orders, [], opts) - Empty list for all records

Requires limit, stable order_by, and index hints to prevent unbounded queries. Returns an opaque read handle that is resolved during commit.

clock_now(ctx)

Generate deterministic values from context for Clock.now/1.

Provides deterministic timestamps from hydrated context.

commit(opts)

Complete a successful operation path.

Must specify writes, results, and optionally nav and effects. Per transaction-dsl.md: successful paths must produce at least one typed result variant.

delete(table, id_value)

Declare a WRITE node for deleting data.

Clean ergonomic API:

  • delete(:todos, id_value) - Delete by :id field (most common)
  • delete(:todos, custom_field: value) - Keyword syntax for any field

Uses natural key fields for safe deletion.

email(template, opts)

Declare email effect with deterministic idempotency key.

ensure(condition)

Assert a validation constraint in plan functions.

Per transaction-dsl.md: guards must be pure and deterministic. If the constraint is false, fails the operation with :validation_failed.

fail(error_type, opts \\ [])

Fail an operation with a typed error.

Error types from transaction-dsl.md: :validation_failed | :not_authorized | :conflict | :precondition_failed

get(table, id_value)

Declare a READ node for a single row lookup.

Clean ergonomic API:

  • get(:todos, id_value) - Read by :id field (most common)
  • get(:todos, custom_field: value) - Keyword syntax for any field

Returns an opaque read handle that is resolved during commit. Guards can evaluate over resolved row fields.

get_locked(table, id_value)

Declare a locked READ node for shared row access.

Per transaction-dsl.md: "Check-then-act on shared rows MUST lock: SELECT … FOR UPDATE"

Clean ergonomic API:

  • get_locked(:users, id_value) - Lock by :id field (most common)
  • get_locked(:users, custom_field: value) - Keyword syntax for any field

Returns an opaque read handle with locking that is resolved during commit.

id_new(ctx)

Generate deterministic IDs from context for Id.new/1.

Provides deterministic IDs from hydrated context.

list(table, index_fields)

Declare a READ node for multiple row lookup.

Clean ergonomic API:

  • list(:orders, user_id: value) - Keyword syntax for filtering
  • list(:orders, []) - Empty list for all records

Returns an opaque read handle that is resolved during commit. Guards can evaluate over resolved rows.

list_locked(table, index_fields)

Declare a locked READ node for multiple rows with shared access.

Clean ergonomic API:

  • list_locked(:orders, user_id: value) - Keyword syntax for filtering
  • list_locked(:orders, []) - Empty list for all records

Returns an opaque read handle with locking for multiple rows.

routes()

Get verified routes helper for navigation.

Routes are provided by the application's AppSpec configuration. This is a generic interface that delegates to the configured route provider.

t(ctx, key, bindings \\ [])

Translate a message key with optional bindings.

Pure function for use in plan functions - no I/O, reads locale from context.

Examples

plan fn input, ctx ->
  user = get(:users, input.user_id)

  result = compute fn ->
    %{
      # Pure translation - reads from ctx.locale
      greeting: t(ctx, "user.greeting", name: user.name),
      title: t(ctx, "dashboard.title")
    }
  end
end

Arguments

  • ctx - Context map containing :locale key (hydrated by Kernel)
  • key - Translation key (e.g., "user.greeting", "errors.not_found")
  • bindings - Keyword list of variable bindings for interpolation

tn(ctx, singular, plural, count, bindings \\ [])

Translate a message key with pluralization support.

Pure function for use in plan functions - no I/O, reads locale from context.

Examples

plan fn input, ctx ->
  items = list(:items, user_id: input.user_id)

  result = compute fn ->
    %{
      count_message: tn(ctx, "item.count", "item.counts", length(items))
    }
  end
end

upsert(table, attrs, opts)

Declare a WRITE node for upserting data.

Requires natural-key conflict target for retry safety. Per transaction-dsl.md: must specify conflict_target with natural keys.

webhook(name, opts)

Declare webhook effect with deterministic idempotency key.