@pyck/workflow-sdk
v0.3.0
Published
Pyck Workflow SDK — TypeScript primitives for building Temporal workflows.
Downloads
282
Keywords
Readme
@pyck/workflow-sdk
TypeScript primitives for building Temporal workflows on the Pyck platform.
The SDK gives you a thin, opinionated layer over the Temporal SDK: a registry for wiring workflows and activities, a setup → runDefaultWorker lifecycle, NATS-backed signal bindings registered with the Pyck gateway, typed user-input updates, workflow search-attribute helpers (title, assignee, targets, grouping, sort key), and GraphQL/HTTP clients for talking to Pyck services.
Status: Alpha. APIs may change between minor versions.
Features
- Worker lifecycle —
setup()to register at module load,runDefaultWorker()to connect, sync with the Pyck gateway, and block until shutdown. - Registry — declare workflows and activities; task queues are derived automatically.
- Signals — bind NATS topics to Temporal workflows as
startorintermediatesignals, with optional filter rules. - Updates —
WorkflowUpdatebase class that pauses a workflow until typed, schema-validated user input arrives. - Search-attribute helpers — set/get workflow title, assignee, targets, group-by, group title, and sort key.
- Clients — GraphQL and HTTP clients plus query/update helpers for the Pyck Workflow API.
- Config from env — one
loadEnv()call populates a process-wideConfig.
Installation
# bun
bun add @pyck/workflow-sdk
# npm
npm install @pyck/workflow-sdk
# pnpm
pnpm add @pyck/workflow-sdkPeer dependencies
Install the Temporal packages your runtime needs (peers, not bundled):
npm install \
@temporalio/activity@^1.15.0 \
@temporalio/client@^1.15.0 \
@temporalio/envconfig@^1.15.0 \
@temporalio/worker@^1.15.0 \
@temporalio/workflow@^1.15.0 \
graphql@^16Requirements: Node.js 24+, TypeScript 5.6+.
Quick start
import { setup, runDefaultWorker } from '@pyck/workflow-sdk'
import { newStartSignal, MutationEventTopic } from '@pyck/workflow-sdk'
import { pickOrder } from './workflows'
import * as activities from './activities'
// Register at module load.
setup((registry) => {
registry.registerWorkflow({
workflow: pickOrder,
taskQueue: 'picking',
signals: [newStartSignal(new MutationEventTopic({ serviceName: 'orders', operationName: 'create' }))],
})
registry.registerActivities('picking', activities)
})
// Connect to Temporal, sync workflows with the Pyck gateway, run until SIGINT/SIGTERM.
await runDefaultWorker({
bundleOptions: { workflowsPath: './src/workflows' },
})Configuration
Configuration is read from the process environment. Call loadEnv() once at startup (runDefaultWorker does this for you), then read from the Config singleton.
import { Config, loadEnv } from '@pyck/workflow-sdk'
await loadEnv()
console.log(Config.environmentName, Config.gatewayUrl)Environment variables
| Variable | Default | Purpose |
|---|---|---|
| TEMPORAL_ADDRESS / TEMPORAL_HOST_URL | localhost:7233 | Temporal frontend address (:7233 appended if no port). |
| TEMPORAL_NAMESPACE | default | Temporal namespace. |
| TEMPORAL_TLS | false | Set true to enable TLS. |
| TEMPORAL_API_KEY | — | Temporal Cloud API key. |
| TEMPORAL_WORKFLOWS_PATH | — | Path to workflow code for bundling (or pass bundleOptions.workflowsPath). |
| PYCK_ENVIRONMENT_NAME | development | Logical environment name. |
| PYCK_GATEWAY_URL | — | Pyck gateway base URL. |
| PYCK_API_TOKEN | — | Token for GraphQL/HTTP clients. |
| PYCK_API_TENANT_ID | — | Tenant id for GraphQL/HTTP clients. |
| PYCK_LOG_LEVEL | info | Log level. |
| PYCK_LOG_FORMAT | json | Log format (json / text). |
Core concepts
Registry & setup
setup() collects registration callbacks invoked when a worker starts. Each callback receives a Registry:
setup((registry) => {
registry.registerWorkflow({ workflow: pickOrder, taskQueue: 'picking' })
registry.registerActivities('picking', activities)
})namedefaults to the workflow function's name.taskQueuedefaults to the lowercased name.- The worker spins up one Temporal worker per distinct task queue.
Worker
runDefaultWorker(options?)— full lifecycle: load env, connect, sync workflows with the gateway, install SIGINT/SIGTERM handlers, run until stopped.newWorker(options?, logger?)— build a worker without auto-running or signal handlers (for tests or multi-tenant hosts); returns{ run(), stop() }.
const w = await newWorker({ namespace: 'pyck' })
const running = w.run()
// ... later
await w.stop()
await runningSignals
Signals bind a NATS topic to a workflow. A start signal launches a new workflow; an intermediate signal is delivered to a running one.
import {
newStartSignal,
newIntermediateSignal,
withFilterRule,
MutationEventTopic,
} from '@pyck/workflow-sdk'
const topic = new MutationEventTopic({ serviceName: 'orders', operationName: 'create' })
const start = newStartSignal(topic, withFilterRule('event.payload.status == "ready"'))
const cancel = newIntermediateSignal(topic, 'cancelOrder')Topic builders (MutationEventTopic, MutationEventWithReplyTopic) collapse empty fields to * wildcards, so a signal can match any tenant, entity, or operation.
Updates (user input)
WorkflowUpdate pauses a workflow until typed user input arrives, optionally validated against a TypeBox schema.
import { WorkflowUpdate } from '@pyck/workflow-sdk'
import { Type } from '@sinclair/typebox'
class ConfirmPick extends WorkflowUpdate<{ qty: number }, MyState> {
readonly typeId = 'confirm-pick'
override jsonSchema() {
return Type.Object({ qty: Type.Number() })
}
}
const confirm = new ConfirmPick()
await confirm.await(state.userDataInput, state)
console.log(confirm.value().qty)Reject malformed input from a validator with validationError('reason'), which throws a non-retryable ValidationError application failure.
Workflow search-attribute helpers
Set and read Pyck search attributes from inside a workflow:
import {
setWorkflowTitle, getWorkflowTitle,
setWorkflowAssignee, getWorkflowAssignee,
setWorkflowTargets, getWorkflowTargets,
setGroupBy, getGroupBy,
setWorkflowGroupTitle, getWorkflowGroupTitle,
setWorkflowSortKey, getWorkflowSortKey,
} from '@pyck/workflow-sdk'
setWorkflowTitle('Pick order #42')
setWorkflowSortKey('2026-06-10')Clients
Query a running workflow's pending user input, or use the GraphQL client for the Pyck Workflow API:
import { queryUserDataInput } from '@pyck/workflow-sdk/client'
import { createGraphQLClient } from '@pyck/workflow-sdk/graphql'
const input = await queryUserDataInput(handle)
const gql = createGraphQLClient({ /* token, tenantId, url */ })Entry points
The package exposes subpath exports for tree-friendly imports:
| Import | Contents |
|---|---|
| @pyck/workflow-sdk | Everything (setup, config, signals, updates, workflow helpers). |
| @pyck/workflow-sdk/worker | runDefaultWorker, newWorker, worker options. |
| @pyck/workflow-sdk/workflow | Search-attribute helpers, user-data input, targets. |
| @pyck/workflow-sdk/signal | Signal builders and topics. |
| @pyck/workflow-sdk/registry | Registry, workflow/activity registries. |
| @pyck/workflow-sdk/client | Query/update client helpers. |
| @pyck/workflow-sdk/graphql | GraphQL client and types. |
Development
bun install
bun run build # tsc --build
bun run check # biome check --write
bun run lint # biome lint
bun run format # biome format --writeLicense
MIT © Pyck
