SDK reference
The shiftlabs module is what a TypeScript workflow imports. Every deploy includes it. This page is generated from its TypeScript source.
DurationUnit
The unit of a duration string, singular or plural.
type DurationUnit = "second" | "minute" | "hour" | "day" | "week" | "month" | "year";
Duration
A number of milliseconds or a string such as "30 seconds" or "10 minutes", with units from second to year.
type Duration = number | `${number} ${DurationUnit}` | `${number} ${DurationUnit}s`;
StepConfig
Retries and a timeout for one step, given as step.run(name, config, fn).
retries?: { limit: number; delay: Duration; backoff?: "constant" | "linear" | "exponential" }limit: how many times to retry a failing step.delay: a duration between attempts.backoff:"constant","linear"or"exponential".timeout?: DurationA duration after which an attempt fails.
Step
Durable steps and sleeps: ctx.step.
run<T>(name: string, fn: () => T | Promise<T>): Promise<T>
run<T>(name: string, config: StepConfig, fn: () => T | Promise<T>): Promise<T>Runs
fnonce and stores its result. When the run resumes, the step returns the stored result instead of running again.sleep(name: string, duration: Duration): Promise<void>Durable sleep. The run resumes after
duration, on the same version.sleepUntil(name: string, until: Date | number): Promise<void>Durable sleep until a
Dateor an epoch-milliseconds number.
Log
ctx.log: one log line per call, shown with the run. fields, if given, follow message as JSON.
debug(message: string, fields?: Record<string, unknown>): voidA line at level
debug.info(message: string, fields?: Record<string, unknown>): voidA line at level
log.warn(message: string, fields?: Record<string, unknown>): voidA line at level
warn.error(message: string, fields?: Record<string, unknown>): voidA line at level
error.
Context
The run context: the one object your function receives. Destructure what you need. Payload is the payload type you give workflow.
payload: PayloadThe webhook body: parsed JSON when the request is sent as
application/json, the raw text otherwise.runId: stringThis run's id.
step: StepDurable steps and sleeps.
vars: Readonly<Record<string, string>> vars.NAME: the workspace value, overridden per workflow. A name that is not set reads asundefined.secrets: Readonly<Record<string, string>> secrets.NAMEfor each secret with hosts. It's a stand-in string that the gateway replaces with the real value on requests to those hosts. An unknown name throws.reveal(secret: string): stringThe value of a secret marked
readable. Every load is audited. Wherever the value shows up in logs, in the run's output or in an error, it is replaced by[redacted].sign(secret: string, data: string, encoding?: "hex" | "base64"): Promise<string>HMAC-SHA256 of
datawith a secret markedhmac. Returns only the signature (hex by default). The secret never enters your code.log: Loglog.info(message, fields?), anddebug,warn,error: one log line each, shown with the run.
WorkflowDefinition
What workflow returns. The module's default export must be one.
readonly kind: "shiftlabs.workflow"Marks the default export as a workflow.
readonly run: (ctx: Context<Payload>) => Promise<Result>The function given to
workflow.
workflow
The module's default export must be workflow(…). run receives the run context; Payload is the type of the webhook payload and Result of the value run returns. Code outside step.run runs again each time the run resumes, after a sleep or a retry. Only step results are stored. Put side effects inside steps.
function workflow<Payload = unknown, Result = unknown>(
run: (ctx: Context<Payload>) => Promise<Result>,
): WorkflowDefinition<Payload, Result>;