import { TailorEnv, TailorPrincipal } from "../../../runtime/types.mjs"; import { JsonCompatible, TypeLevelError } from "../../../types/helpers.mjs"; import { ExecJobFunctionOptions } from "../../../runtime/workflow.mjs"; //#region src/configure/services/workflow/job.d.ts /** * Context object passed as the second argument to workflow job body functions. */ export type WorkflowJobContext = { env: TailorEnv; invoker: TailorPrincipal | null; }; /** * The body function type for a workflow job. * Resolves to the callable signature when `I` / `O` are JsonValue-compatible, * or to a type-level error that surfaces at the `body:` property. */ type JobBody = [null] extends [I] ? TypeLevelError<"Input cannot be null at the top level"> : [I] extends [undefined] ? [O] extends [JsonCompatible | undefined | void] ? (input: I, context: WorkflowJobContext) => O | Promise : TypeLevelError<"Output must be JsonValue-compatible (plain objects/arrays; no class instances or functions)"> : [undefined] extends [I] ? TypeLevelError<"Input cannot include undefined at the top level"> : [I] extends [JsonCompatible] ? [O] extends [JsonCompatible | undefined | void] ? (input: I, context: WorkflowJobContext) => O | Promise : TypeLevelError<"Output must be JsonValue-compatible (plain objects/arrays; no class instances or functions)"> : TypeLevelError<"Input must be JsonValue-compatible (plain objects/arrays; no class instances or functions)">; /** * WorkflowJob represents a job that can be started from a workflow. * * Type constraints: * - Input: Must be JsonValue-compatible (plain objects/arrays; no class instances or functions) or undefined. * - Output: Must be JsonValue-compatible (plain objects/arrays; no class instances or functions), undefined, or void. * - Start returns `Awaited` as-is (no Promise or Jsonify transformation). */ export interface WorkflowJob { name: Name; /** * Start this job with the given input and return the job's output value. * Accepts an optional second argument to pass `executionPolicyKey` for * platform-side concurrency enforcement. * * Must be called from within another job's `body` (a function defined * inside `body` may call it too) — not from a function defined outside * `body`. The build cannot see through that indirection to find the call, * and fails instead of silently dropping it. * @example * body: async (input) => { * const a = jobA.start({ id: input.id }); * const b = jobB.start({ id: input.id }, { * executionPolicyKey: `tenant-api.${input.tenantId}`, * }); * return { a, b }; * } */ start: [Input] extends [undefined] ? (input?: undefined, options?: ExecJobFunctionOptions) => Awaited : (input: Input, options?: ExecJobFunctionOptions) => Awaited; body: (input: Input, context: WorkflowJobContext) => Output | Promise; publishEvents?: boolean; } interface CreateWorkflowJobConfig { readonly name: Name; readonly body: JobBody; /** * Enable publishing this job's execution events, letting executors with a * `workflowJobExecution*` trigger observe them. * * Left unset, it is enabled automatically when an executor in the project * subscribes to the job execution events of a workflow that runs this job. */ readonly publishEvents?: boolean; } /** * Create a workflow job definition. * * All jobs must be named exports from the workflow file. * Job names must be unique across the entire project. * * Input and output must be JsonValue-compatible (primitives, plain objects, arrays). * Functions and objects with a `toJSON` method are rejected at the type level; * class instances exposing methods are rejected via the property walk. * `name` and `body` must be written directly in this call — as a string literal and an * inline function expression, respectively — not as a reference to a variable or the * result of another function call. The build cannot see through that indirection to find * the job, and fails instead of silently leaving it out. * @param config - Job configuration with name and body function. * @param config.name - Unique job name across the project. Must be a string literal. * @param config.body - Function that processes the job input. Must be an inline function * expression, not a reference to a separately-defined function. * @returns A WorkflowJob that can be started from other jobs. * @example * // Simple job with async body: * export const fetchData = createWorkflowJob({ * name: "fetch-data", * body: async (input: { id: string }) => { * const db = getDB("tailordb"); * return await db.selectFrom("Table").selectAll().where("id", "=", input.id).executeTakeFirst(); * }, * }); * @example * // Orchestrator job that fans out to other jobs. * export const orchestrate = createWorkflowJob({ * name: "orchestrate", * body: (input: { orderId: string }) => { * const inventory = checkInventory.start({ orderId: input.orderId }); * const payment = processPayment.start({ orderId: input.orderId }); * return { inventory, payment }; * }, * }); */ export declare function createWorkflowJob(config: CreateWorkflowJobConfig): WorkflowJob>; //#endregion