@ironflow/core 0.7.1 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1865 -101
- package/dist/schemas.d.ts +5 -5
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,181 +1,1945 @@
|
|
|
1
1
|
# @ironflow/core
|
|
2
2
|
|
|
3
|
-
Shared types, schemas, constants, and utilities for the Ironflow JavaScript SDK.
|
|
3
|
+
Shared types, Zod schemas, error classes, constants, and utilities for the Ironflow JavaScript SDK. This package is the foundation that both `@ironflow/browser` and `@ironflow/node` depend on. It contains zero platform-specific code and runs in any JavaScript environment.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
**This is a private npm package.** External npm docs are not available. Use this README as the sole reference.
|
|
6
|
+
|
|
7
|
+
- Source: `sdk/js/core/src/`
|
|
8
|
+
- Entry point: `@ironflow/core` (re-exports everything from `index.ts`)
|
|
9
|
+
- Sub-path exports: `@ironflow/core/schemas`, `@ironflow/core/protocol`, `@ironflow/core/gen`
|
|
10
|
+
- Runtime dependency: `zod` (v4+)
|
|
11
|
+
- Optional dependencies: `@bufbuild/protobuf`, `@connectrpc/connect` (only for `/gen` sub-path)
|
|
12
|
+
|
|
13
|
+
Docs: <https://github.com/sahina/ironflow/tree/main/docs>
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Table of Contents
|
|
18
|
+
|
|
19
|
+
1. [Installation](#installation)
|
|
20
|
+
2. [Branded Types](#branded-types)
|
|
21
|
+
3. [Function Types](#function-types)
|
|
22
|
+
4. [Event Types](#event-types)
|
|
23
|
+
5. [Step Types](#step-types)
|
|
24
|
+
6. [Run Types](#run-types)
|
|
25
|
+
7. [Subscription Types](#subscription-types)
|
|
26
|
+
8. [Entity Stream Types](#entity-stream-types)
|
|
27
|
+
9. [Pub/Sub Types](#pubsub-types)
|
|
28
|
+
10. [KV Types](#kv-types)
|
|
29
|
+
11. [Config Types](#config-types)
|
|
30
|
+
12. [Auth Types](#auth-types)
|
|
31
|
+
13. [Audit Types](#audit-types)
|
|
32
|
+
14. [Webhook Types](#webhook-types)
|
|
33
|
+
15. [Projection Types](#projection-types)
|
|
34
|
+
16. [Error Classes](#error-classes)
|
|
35
|
+
17. [Schemas](#schemas)
|
|
36
|
+
18. [Protocol Types](#protocol-types)
|
|
37
|
+
19. [Constants](#constants)
|
|
38
|
+
20. [Utilities](#utilities)
|
|
39
|
+
21. [Upcasters](#upcasters)
|
|
40
|
+
22. [Logger](#logger)
|
|
41
|
+
23. [SecretsClient](#secretsclient)
|
|
42
|
+
|
|
43
|
+
---
|
|
6
44
|
|
|
7
45
|
## Installation
|
|
8
46
|
|
|
9
|
-
```bash
|
|
10
|
-
npm install @ironflow/core
|
|
47
|
+
```bash
|
|
48
|
+
npm install @ironflow/core
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Most users do not install this package directly. It is included as a dependency of `@ironflow/browser` (browser client, subscriptions) and `@ironflow/node` (worker, serve, projections), both of which re-export core types.
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## Branded Types
|
|
56
|
+
|
|
57
|
+
Branded types provide compile-time type safety for ID strings. A `RunId` cannot be accidentally passed where a `FunctionId` is expected.
|
|
58
|
+
|
|
59
|
+
```typescript
|
|
60
|
+
import type {
|
|
61
|
+
RunId, FunctionId, StepId, EventId, JobId, WorkerId, SubscriptionId,
|
|
62
|
+
Branded,
|
|
63
|
+
} from '@ironflow/core';
|
|
64
|
+
|
|
65
|
+
import {
|
|
66
|
+
createRunId, createFunctionId, createStepId,
|
|
67
|
+
createEventId, createJobId, createWorkerId, createSubscriptionId,
|
|
68
|
+
} from '@ironflow/core';
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### Factory Functions
|
|
72
|
+
|
|
73
|
+
Each factory casts a plain string to the branded type at zero runtime cost:
|
|
74
|
+
|
|
75
|
+
```typescript
|
|
76
|
+
const runId: RunId = createRunId('run_abc123');
|
|
77
|
+
const fnId: FunctionId = createFunctionId('my-workflow');
|
|
78
|
+
const stepId: StepId = createStepId('step_001');
|
|
79
|
+
const eventId: EventId = createEventId('evt_xyz');
|
|
80
|
+
const jobId: JobId = createJobId('job_456');
|
|
81
|
+
const workerId: WorkerId = createWorkerId('wkr_789');
|
|
82
|
+
const subId: SubscriptionId = createSubscriptionId('sub_012');
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### Branded Helper
|
|
86
|
+
|
|
87
|
+
You can create your own branded types:
|
|
88
|
+
|
|
89
|
+
```typescript
|
|
90
|
+
type OrderId = Branded<string, 'OrderId'>;
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
## Function Types
|
|
96
|
+
|
|
97
|
+
### FunctionConfig
|
|
98
|
+
|
|
99
|
+
Full configuration for a workflow function.
|
|
100
|
+
|
|
101
|
+
```typescript
|
|
102
|
+
import type { FunctionConfig } from '@ironflow/core';
|
|
103
|
+
|
|
104
|
+
interface FunctionConfig<TEventSchema extends z.ZodType = z.ZodType> {
|
|
105
|
+
/** Unique function identifier */
|
|
106
|
+
id: string;
|
|
107
|
+
/** Display name for the function */
|
|
108
|
+
name?: string;
|
|
109
|
+
/** Event triggers that invoke this function */
|
|
110
|
+
triggers: Trigger[];
|
|
111
|
+
/** Retry configuration for failed steps */
|
|
112
|
+
retry?: RetryConfig;
|
|
113
|
+
/** Function timeout in milliseconds (default: 600000 = 10 minutes) */
|
|
114
|
+
timeout?: number;
|
|
115
|
+
/** Concurrency control configuration */
|
|
116
|
+
concurrency?: ConcurrencyConfig;
|
|
117
|
+
/** Execution mode: "push" for serverless, "pull" for workers */
|
|
118
|
+
mode?: ExecutionMode;
|
|
119
|
+
/** JSON path for actor-based sticky routing */
|
|
120
|
+
actorKey?: string;
|
|
121
|
+
/** Zod schema for type-safe event validation */
|
|
122
|
+
schema?: TEventSchema;
|
|
123
|
+
/** Secret names this function requires (resolved by engine at execution time) */
|
|
124
|
+
secrets?: string[];
|
|
125
|
+
/** Default timeout for all step.run() calls ("30s", "5m", "1h") */
|
|
126
|
+
stepTimeout?: string;
|
|
127
|
+
/** Enable audit recording for this function */
|
|
128
|
+
recording?: boolean;
|
|
129
|
+
/** Retention period for audit events ("7d", "30d", "90d", "forever") */
|
|
130
|
+
recordingRetention?: string;
|
|
131
|
+
}
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### Trigger
|
|
135
|
+
|
|
136
|
+
```typescript
|
|
137
|
+
interface Trigger {
|
|
138
|
+
/** Event name pattern to match (e.g., "order.placed") */
|
|
139
|
+
event: string;
|
|
140
|
+
/** Optional CEL expression for filtering */
|
|
141
|
+
expression?: string;
|
|
142
|
+
/** Cron schedule expression (e.g., "0 9 * * *" for 9am daily) */
|
|
143
|
+
cron?: string;
|
|
144
|
+
}
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### RetryConfig
|
|
148
|
+
|
|
149
|
+
```typescript
|
|
150
|
+
interface RetryConfig {
|
|
151
|
+
/** Maximum number of retry attempts (default: 3) */
|
|
152
|
+
maxAttempts?: number;
|
|
153
|
+
/** Initial delay between retries in ms (default: 1000) */
|
|
154
|
+
initialDelayMs?: number;
|
|
155
|
+
/** Backoff multiplier (default: 2.0) */
|
|
156
|
+
backoffFactor?: number;
|
|
157
|
+
/** Maximum delay between retries in ms (default: 300000) */
|
|
158
|
+
maxDelayMs?: number;
|
|
159
|
+
}
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
### ConcurrencyConfig
|
|
163
|
+
|
|
164
|
+
```typescript
|
|
165
|
+
interface ConcurrencyConfig {
|
|
166
|
+
/** Maximum concurrent executions */
|
|
167
|
+
limit: number;
|
|
168
|
+
/** JSON path for grouping (e.g., "event.data.customerId") */
|
|
169
|
+
key?: string;
|
|
170
|
+
}
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
### ExecutionMode
|
|
174
|
+
|
|
175
|
+
```typescript
|
|
176
|
+
type ExecutionMode = "push" | "pull";
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
- `"push"` -- HTTP POST to serverless functions (Next.js, Lambda). For tasks under 10 seconds.
|
|
180
|
+
- `"pull"` -- gRPC/HTTP polling for long-running workers. No timeout limits.
|
|
181
|
+
|
|
182
|
+
### FunctionContext
|
|
183
|
+
|
|
184
|
+
Context object passed to every function handler.
|
|
185
|
+
|
|
186
|
+
```typescript
|
|
187
|
+
interface FunctionContext<TEvent = unknown> {
|
|
188
|
+
/** The triggering event */
|
|
189
|
+
event: IronflowEvent<TEvent>;
|
|
190
|
+
/** Step execution client */
|
|
191
|
+
step: StepClient;
|
|
192
|
+
/** Run information */
|
|
193
|
+
run: RunInfo;
|
|
194
|
+
/** Logger instance */
|
|
195
|
+
logger: Logger;
|
|
196
|
+
/** Resolved environment secrets (read-only) */
|
|
197
|
+
secrets: SecretsClient;
|
|
198
|
+
}
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
### FunctionHandler and IronflowFunction
|
|
202
|
+
|
|
203
|
+
```typescript
|
|
204
|
+
type FunctionHandler<TEvent = unknown, TResult = unknown> = (
|
|
205
|
+
ctx: FunctionContext<TEvent>
|
|
206
|
+
) => Promise<TResult>;
|
|
207
|
+
|
|
208
|
+
interface IronflowFunction<TEvent = unknown, TResult = unknown> {
|
|
209
|
+
config: FunctionConfig;
|
|
210
|
+
handler: FunctionHandler<TEvent, TResult>;
|
|
211
|
+
}
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
Usage (typically via `@ironflow/node`'s `createFunction()`):
|
|
215
|
+
|
|
216
|
+
```typescript
|
|
217
|
+
import { createFunction } from '@ironflow/node';
|
|
218
|
+
|
|
219
|
+
const myWorkflow = createFunction({
|
|
220
|
+
id: 'process-order',
|
|
221
|
+
triggers: [{ event: 'order.placed' }],
|
|
222
|
+
retry: { maxAttempts: 5 },
|
|
223
|
+
concurrency: { limit: 10, key: 'event.data.customerId' },
|
|
224
|
+
mode: 'pull',
|
|
225
|
+
secrets: ['STRIPE_KEY'],
|
|
226
|
+
stepTimeout: '30s',
|
|
227
|
+
}, async ({ event, step, logger, secrets }) => {
|
|
228
|
+
const charge = await step.run('charge', async () => {
|
|
229
|
+
return stripe.charges.create({ amount: event.data.amount });
|
|
230
|
+
});
|
|
231
|
+
return { chargeId: charge.id };
|
|
232
|
+
});
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
---
|
|
236
|
+
|
|
237
|
+
## Event Types
|
|
238
|
+
|
|
239
|
+
### IronflowEvent
|
|
240
|
+
|
|
241
|
+
```typescript
|
|
242
|
+
interface IronflowEvent<T = unknown> {
|
|
243
|
+
/** Unique event ID */
|
|
244
|
+
id: string;
|
|
245
|
+
/** Event name (e.g., "order.placed") */
|
|
246
|
+
name: string;
|
|
247
|
+
/** Event schema version */
|
|
248
|
+
version: number;
|
|
249
|
+
/** Event payload data */
|
|
250
|
+
data: T;
|
|
251
|
+
/** Event timestamp */
|
|
252
|
+
timestamp: Date;
|
|
253
|
+
/** Optional idempotency key for deduplication */
|
|
254
|
+
idempotencyKey?: string;
|
|
255
|
+
/** Event source (e.g., "webhook", "sdk", "api") */
|
|
256
|
+
source?: string;
|
|
257
|
+
/** Additional metadata */
|
|
258
|
+
metadata?: Record<string, unknown>;
|
|
259
|
+
}
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
### EventSource Constants
|
|
263
|
+
|
|
264
|
+
```typescript
|
|
265
|
+
import { EventSource } from '@ironflow/core';
|
|
266
|
+
|
|
267
|
+
EventSource.API // "api"
|
|
268
|
+
EventSource.CRON // "cron"
|
|
269
|
+
EventSource.WEBHOOK // "webhook"
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
### EventFilter
|
|
273
|
+
|
|
274
|
+
Used with `step.waitForEvent()`.
|
|
275
|
+
|
|
276
|
+
```typescript
|
|
277
|
+
interface EventFilter {
|
|
278
|
+
/** Event name to wait for */
|
|
279
|
+
event: string;
|
|
280
|
+
/** JSON path for matching (e.g., "data.orderId") */
|
|
281
|
+
match?: string;
|
|
282
|
+
/** Timeout duration (default: "7d") */
|
|
283
|
+
timeout?: Duration;
|
|
284
|
+
}
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
### EmitOptions and EmitResult
|
|
288
|
+
|
|
289
|
+
```typescript
|
|
290
|
+
interface EmitOptions {
|
|
291
|
+
/** Event schema version (default 1) */
|
|
292
|
+
version?: number;
|
|
293
|
+
/** Optional deduplication key */
|
|
294
|
+
idempotencyKey?: string;
|
|
295
|
+
/** Optional metadata (headers, etc.) */
|
|
296
|
+
metadata?: Record<string, unknown>;
|
|
297
|
+
/** Namespace (default: "default") */
|
|
298
|
+
namespace?: string;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
interface EmitResult {
|
|
302
|
+
/** IDs of runs created by this event */
|
|
303
|
+
runIds: string[];
|
|
304
|
+
/** ID of the stored event */
|
|
305
|
+
eventId: string;
|
|
306
|
+
}
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
---
|
|
310
|
+
|
|
311
|
+
## Step Types
|
|
312
|
+
|
|
313
|
+
### StepClient
|
|
314
|
+
|
|
315
|
+
The durable step execution interface. All methods are memoized -- on retry, previously completed steps return their stored result without re-executing.
|
|
316
|
+
|
|
317
|
+
```typescript
|
|
318
|
+
interface StepClient {
|
|
319
|
+
/**
|
|
320
|
+
* Execute a step with memoization.
|
|
321
|
+
* Use for any non-idempotent operation (API calls, payments, emails).
|
|
322
|
+
*/
|
|
323
|
+
run<T>(name: string, fn: () => Promise<T>, options?: StepRunOptions): Promise<T>;
|
|
324
|
+
|
|
325
|
+
/**
|
|
326
|
+
* Durable sleep. Worker can restart; workflow resumes after duration.
|
|
327
|
+
* @param duration - "1h", "30m", "7d" or milliseconds as number
|
|
328
|
+
*/
|
|
329
|
+
sleep(name: string, duration: Duration): Promise<void>;
|
|
330
|
+
|
|
331
|
+
/**
|
|
332
|
+
* Durable sleep until a specific time.
|
|
333
|
+
* @param until - Date object or ISO 8601 string
|
|
334
|
+
*/
|
|
335
|
+
sleepUntil(name: string, until: Date | string): Promise<void>;
|
|
336
|
+
|
|
337
|
+
/**
|
|
338
|
+
* Wait for an external event. Used for human-in-the-loop and async callbacks.
|
|
339
|
+
*/
|
|
340
|
+
waitForEvent<T = unknown>(name: string, filter: EventFilter): Promise<IronflowEvent<T>>;
|
|
341
|
+
|
|
342
|
+
/**
|
|
343
|
+
* Execute multiple branches in parallel.
|
|
344
|
+
* "failFast" (default): first failure cancels pending branches.
|
|
345
|
+
* "allSettled": all branches complete, errors in results.
|
|
346
|
+
*/
|
|
347
|
+
parallel<T extends unknown[]>(
|
|
348
|
+
name: string,
|
|
349
|
+
branches: { [K in keyof T]: (step: StepClient) => Promise<T[K]> },
|
|
350
|
+
options?: ParallelOptions
|
|
351
|
+
): Promise<T>;
|
|
352
|
+
|
|
353
|
+
/** allSettled overload -- results contain T[K] | Error */
|
|
354
|
+
parallel<T extends unknown[]>(
|
|
355
|
+
name: string,
|
|
356
|
+
branches: { [K in keyof T]: (step: StepClient) => Promise<T[K]> },
|
|
357
|
+
options: ParallelOptions & { onError: "allSettled" }
|
|
358
|
+
): Promise<{ [K in keyof T]: T[K] | Error }>;
|
|
359
|
+
|
|
360
|
+
/**
|
|
361
|
+
* Map over items executing steps in parallel.
|
|
362
|
+
*/
|
|
363
|
+
map<T, R>(
|
|
364
|
+
name: string,
|
|
365
|
+
items: T[],
|
|
366
|
+
fn: (item: T, step: StepClient, index: number) => Promise<R>,
|
|
367
|
+
options?: ParallelOptions
|
|
368
|
+
): Promise<R[]>;
|
|
369
|
+
|
|
370
|
+
/**
|
|
371
|
+
* Register a compensation handler (Saga pattern).
|
|
372
|
+
* On failure, compensations run in reverse order.
|
|
373
|
+
*/
|
|
374
|
+
compensate(stepName: string, fn: () => Promise<void>): void;
|
|
375
|
+
|
|
376
|
+
/**
|
|
377
|
+
* Invoke another function and wait for its result (durable).
|
|
378
|
+
* Target function must have no event triggers.
|
|
379
|
+
*/
|
|
380
|
+
invoke<T = unknown>(
|
|
381
|
+
functionId: string,
|
|
382
|
+
input?: unknown,
|
|
383
|
+
options?: { timeout?: string }
|
|
384
|
+
): Promise<T>;
|
|
385
|
+
|
|
386
|
+
/**
|
|
387
|
+
* Fire-and-forget invoke. Returns the child run ID immediately.
|
|
388
|
+
*/
|
|
389
|
+
invokeAsync(functionId: string, input?: unknown): Promise<{ runId: string }>;
|
|
390
|
+
|
|
391
|
+
/**
|
|
392
|
+
* Publish to a developer pub/sub topic (durable, memoized).
|
|
393
|
+
* Does NOT trigger workflow functions -- use emit for that.
|
|
394
|
+
*/
|
|
395
|
+
publish(topic: string, data: unknown): Promise<PublishResult>;
|
|
396
|
+
}
|
|
397
|
+
```
|
|
398
|
+
|
|
399
|
+
### StepRunOptions
|
|
400
|
+
|
|
401
|
+
```typescript
|
|
402
|
+
interface StepRunOptions {
|
|
403
|
+
/** Timeout for this step ("30s", "5m", "1h"). Overrides function-level stepTimeout. */
|
|
404
|
+
timeout?: string;
|
|
405
|
+
}
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
### Duration
|
|
409
|
+
|
|
410
|
+
```typescript
|
|
411
|
+
type Duration = string | number;
|
|
412
|
+
// String: "1s", "30s", "5m", "2h", "7d"
|
|
413
|
+
// Number: milliseconds
|
|
414
|
+
```
|
|
415
|
+
|
|
416
|
+
### ParallelOptions
|
|
417
|
+
|
|
418
|
+
```typescript
|
|
419
|
+
interface ParallelOptions {
|
|
420
|
+
/** Maximum concurrent branches (default: unlimited) */
|
|
421
|
+
concurrency?: number;
|
|
422
|
+
/** Error handling: "failFast" (default) or "allSettled" */
|
|
423
|
+
onError?: "failFast" | "allSettled";
|
|
424
|
+
}
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
---
|
|
428
|
+
|
|
429
|
+
## Run Types
|
|
430
|
+
|
|
431
|
+
### RunStatus
|
|
432
|
+
|
|
433
|
+
```typescript
|
|
434
|
+
type RunStatus = "pending" | "running" | "completed" | "failed" | "cancelled" | "paused";
|
|
435
|
+
```
|
|
436
|
+
|
|
437
|
+
### RunInfo
|
|
438
|
+
|
|
439
|
+
Minimal run context passed inside `FunctionContext`.
|
|
440
|
+
|
|
441
|
+
```typescript
|
|
442
|
+
interface RunInfo {
|
|
443
|
+
id: string;
|
|
444
|
+
functionId: string;
|
|
445
|
+
attempt: number;
|
|
446
|
+
startedAt: Date;
|
|
447
|
+
}
|
|
448
|
+
```
|
|
449
|
+
|
|
450
|
+
### Run
|
|
451
|
+
|
|
452
|
+
Full run details returned by API queries.
|
|
453
|
+
|
|
454
|
+
```typescript
|
|
455
|
+
interface Run {
|
|
456
|
+
id: string;
|
|
457
|
+
functionId: string;
|
|
458
|
+
eventId: string;
|
|
459
|
+
status: RunStatus;
|
|
460
|
+
attempt: number;
|
|
461
|
+
maxAttempts: number;
|
|
462
|
+
input?: unknown;
|
|
463
|
+
output?: unknown;
|
|
464
|
+
error?: { message: string; code?: string };
|
|
465
|
+
startedAt?: Date;
|
|
466
|
+
endedAt?: Date;
|
|
467
|
+
createdAt: Date;
|
|
468
|
+
updatedAt: Date;
|
|
469
|
+
}
|
|
470
|
+
```
|
|
471
|
+
|
|
472
|
+
### ListRunsOptions and ListRunsResult
|
|
473
|
+
|
|
474
|
+
```typescript
|
|
475
|
+
interface ListRunsOptions {
|
|
476
|
+
functionId?: string;
|
|
477
|
+
status?: RunStatus;
|
|
478
|
+
limit?: number;
|
|
479
|
+
cursor?: string;
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
interface ListRunsResult {
|
|
483
|
+
runs: Run[];
|
|
484
|
+
nextCursor?: string;
|
|
485
|
+
totalCount: number;
|
|
486
|
+
}
|
|
487
|
+
```
|
|
488
|
+
|
|
489
|
+
### TriggerResult, TriggerSyncOptions, TriggerSyncResult
|
|
490
|
+
|
|
491
|
+
```typescript
|
|
492
|
+
interface TriggerResult {
|
|
493
|
+
runIds: string[];
|
|
494
|
+
eventId: string;
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
interface TriggerSyncOptions {
|
|
498
|
+
/** Maximum wait time in ms (default: 30000) */
|
|
499
|
+
timeout?: number;
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
interface TriggerSyncResult {
|
|
503
|
+
runId: string;
|
|
504
|
+
functionId: string;
|
|
505
|
+
status: RunStatus;
|
|
506
|
+
output?: unknown;
|
|
507
|
+
error?: { message: string; code?: string };
|
|
508
|
+
durationMs: number;
|
|
509
|
+
}
|
|
510
|
+
```
|
|
511
|
+
|
|
512
|
+
---
|
|
513
|
+
|
|
514
|
+
## Subscription Types
|
|
515
|
+
|
|
516
|
+
### SubscribeOptions
|
|
517
|
+
|
|
518
|
+
```typescript
|
|
519
|
+
interface SubscribeOptions {
|
|
520
|
+
/** Number of historical events to replay (0 = no replay) */
|
|
521
|
+
replay?: number;
|
|
522
|
+
/** Include event metadata (timestamp, sequence) */
|
|
523
|
+
includeMetadata?: boolean;
|
|
524
|
+
/** CEL expression for content-based filtering */
|
|
525
|
+
filter?: string;
|
|
526
|
+
/** Namespace for the subscription (default: "default") */
|
|
527
|
+
namespace?: string;
|
|
528
|
+
/** Consumer group to join for load-balanced delivery */
|
|
529
|
+
consumerGroup?: string;
|
|
530
|
+
/** Acknowledgment mode for consumer group (default: "auto") */
|
|
531
|
+
ackMode?: AckMode;
|
|
532
|
+
/** Backpressure handling mode (default: "buffer") */
|
|
533
|
+
backpressure?: BackpressureMode;
|
|
534
|
+
}
|
|
535
|
+
```
|
|
536
|
+
|
|
537
|
+
### AckMode, BackpressureMode, AckType
|
|
538
|
+
|
|
539
|
+
```typescript
|
|
540
|
+
type AckMode = "auto" | "manual";
|
|
541
|
+
type BackpressureMode = "drop" | "block" | "buffer";
|
|
542
|
+
type AckType = "ack" | "nak" | "term";
|
|
543
|
+
```
|
|
544
|
+
|
|
545
|
+
### SubscriptionEvent
|
|
546
|
+
|
|
547
|
+
```typescript
|
|
548
|
+
interface SubscriptionEvent<T = unknown> {
|
|
549
|
+
/** Event topic (e.g., "system.run.abc123.updated") */
|
|
550
|
+
topic: string;
|
|
551
|
+
/** Event payload data */
|
|
552
|
+
data: T;
|
|
553
|
+
/** Event metadata (if includeMetadata was true) */
|
|
554
|
+
meta?: EventMetadata;
|
|
555
|
+
/** Event ID (for consumer group ack/nak/term) */
|
|
556
|
+
eventId?: string;
|
|
557
|
+
}
|
|
558
|
+
```
|
|
559
|
+
|
|
560
|
+
### EventMetadata
|
|
561
|
+
|
|
562
|
+
```typescript
|
|
563
|
+
interface EventMetadata {
|
|
564
|
+
timestamp: string; // ISO 8601
|
|
565
|
+
sequence?: number; // Stream sequence number
|
|
566
|
+
}
|
|
567
|
+
```
|
|
568
|
+
|
|
569
|
+
### Subscription
|
|
570
|
+
|
|
571
|
+
```typescript
|
|
572
|
+
interface Subscription {
|
|
573
|
+
id: string;
|
|
574
|
+
pattern: string;
|
|
575
|
+
connectionState: ConnectionState;
|
|
576
|
+
lastEvent?: SubscriptionEvent<unknown>;
|
|
577
|
+
unsubscribe(): void;
|
|
578
|
+
}
|
|
579
|
+
```
|
|
580
|
+
|
|
581
|
+
### AckableSubscription
|
|
582
|
+
|
|
583
|
+
Extends `Subscription` with manual acknowledgment methods for consumer groups.
|
|
584
|
+
|
|
585
|
+
```typescript
|
|
586
|
+
interface AckableSubscription extends Subscription {
|
|
587
|
+
ack(eventId: string): Promise<void>;
|
|
588
|
+
nak(eventId: string, delay?: number): Promise<void>;
|
|
589
|
+
term(eventId: string): Promise<void>;
|
|
590
|
+
}
|
|
591
|
+
```
|
|
592
|
+
|
|
593
|
+
### AckHandle
|
|
594
|
+
|
|
595
|
+
```typescript
|
|
596
|
+
interface AckHandle {
|
|
597
|
+
ack(): void;
|
|
598
|
+
nak(): void;
|
|
599
|
+
}
|
|
600
|
+
```
|
|
601
|
+
|
|
602
|
+
### ConnectionState
|
|
603
|
+
|
|
604
|
+
```typescript
|
|
605
|
+
type ConnectionState = "connecting" | "connected" | "disconnected" | "reconnecting";
|
|
606
|
+
```
|
|
607
|
+
|
|
608
|
+
### SubscriptionCallbacks
|
|
609
|
+
|
|
610
|
+
```typescript
|
|
611
|
+
interface SubscriptionCallbacks<T = unknown> {
|
|
612
|
+
onEvent?: (event: SubscriptionEvent<T>) => void;
|
|
613
|
+
onError?: (error: SubscriptionErrorInfo) => void;
|
|
614
|
+
onStateChange?: (state: ConnectionState) => void;
|
|
615
|
+
}
|
|
616
|
+
```
|
|
617
|
+
|
|
618
|
+
### SubscriptionErrorInfo
|
|
619
|
+
|
|
620
|
+
```typescript
|
|
621
|
+
interface SubscriptionErrorInfo {
|
|
622
|
+
subscriptionId?: string;
|
|
623
|
+
code: string;
|
|
624
|
+
message: string;
|
|
625
|
+
retrying?: boolean;
|
|
626
|
+
}
|
|
627
|
+
```
|
|
628
|
+
|
|
629
|
+
### BufferConfig
|
|
630
|
+
|
|
631
|
+
```typescript
|
|
632
|
+
interface BufferConfig {
|
|
633
|
+
size: number;
|
|
634
|
+
strategy: "drop-oldest" | "drop-newest" | "block";
|
|
635
|
+
}
|
|
636
|
+
```
|
|
637
|
+
|
|
638
|
+
### ConsumerGroupConfig and ConsumerGroup
|
|
639
|
+
|
|
640
|
+
```typescript
|
|
641
|
+
interface ConsumerGroupConfig {
|
|
642
|
+
name: string;
|
|
643
|
+
pattern: string;
|
|
644
|
+
namespace?: string; // default: "default"
|
|
645
|
+
filterExpr?: string; // CEL expression
|
|
646
|
+
ackMode?: AckMode; // default: "auto"
|
|
647
|
+
backpressure?: BackpressureMode; // default: "buffer"
|
|
648
|
+
maxInflight?: number; // default: 100
|
|
649
|
+
maxRedeliveries?: number; // default: 3
|
|
650
|
+
redeliverDelayMs?: number; // default: 5000
|
|
651
|
+
metadata?: Record<string, unknown>;
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
interface ConsumerGroup {
|
|
655
|
+
id: string;
|
|
656
|
+
namespace: string;
|
|
657
|
+
name: string;
|
|
658
|
+
pattern: string;
|
|
659
|
+
filterExpr?: string;
|
|
660
|
+
ackMode: AckMode;
|
|
661
|
+
backpressure: BackpressureMode;
|
|
662
|
+
maxInflight: number;
|
|
663
|
+
maxRedeliveries: number;
|
|
664
|
+
redeliverDelayMs: number;
|
|
665
|
+
metadata?: Record<string, unknown>;
|
|
666
|
+
status: ConsumerGroupStatus;
|
|
667
|
+
memberCount: number;
|
|
668
|
+
createdAt: Date;
|
|
669
|
+
updatedAt: Date;
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
type ConsumerGroupStatus = "active" | "paused" | "deleted";
|
|
673
|
+
```
|
|
674
|
+
|
|
675
|
+
---
|
|
676
|
+
|
|
677
|
+
## Entity Stream Types
|
|
678
|
+
|
|
679
|
+
Entity streams implement event sourcing per entity with optimistic concurrency.
|
|
680
|
+
|
|
681
|
+
### AppendEventInput
|
|
682
|
+
|
|
683
|
+
```typescript
|
|
684
|
+
interface AppendEventInput {
|
|
685
|
+
/** Event name (e.g., "order.created") */
|
|
686
|
+
name: string;
|
|
687
|
+
/** Event payload data */
|
|
688
|
+
data: Record<string, unknown>;
|
|
689
|
+
/** Entity type (e.g., "order", "user") */
|
|
690
|
+
entityType: string;
|
|
691
|
+
}
|
|
692
|
+
```
|
|
693
|
+
|
|
694
|
+
### AppendOptions
|
|
695
|
+
|
|
696
|
+
```typescript
|
|
697
|
+
interface AppendOptions {
|
|
698
|
+
/** Expected entity version for optimistic concurrency control (-1 to skip) */
|
|
699
|
+
expectedVersion?: number;
|
|
700
|
+
/** Idempotency key to prevent duplicate appends */
|
|
701
|
+
idempotencyKey?: string;
|
|
702
|
+
/** Event schema version (default: 1) */
|
|
703
|
+
version?: number;
|
|
704
|
+
}
|
|
705
|
+
```
|
|
706
|
+
|
|
707
|
+
### AppendResult
|
|
708
|
+
|
|
709
|
+
```typescript
|
|
710
|
+
interface AppendResult {
|
|
711
|
+
entityVersion: number;
|
|
712
|
+
eventId: string;
|
|
713
|
+
}
|
|
714
|
+
```
|
|
715
|
+
|
|
716
|
+
### ReadStreamOptions
|
|
717
|
+
|
|
718
|
+
```typescript
|
|
719
|
+
interface ReadStreamOptions {
|
|
720
|
+
/** Start reading from this version (inclusive, default: 0) */
|
|
721
|
+
fromVersion?: number;
|
|
722
|
+
/** Maximum number of events to return (0 = all) */
|
|
723
|
+
limit?: number;
|
|
724
|
+
/** Read direction (default: "forward") */
|
|
725
|
+
direction?: "forward" | "backward";
|
|
726
|
+
}
|
|
727
|
+
```
|
|
728
|
+
|
|
729
|
+
### StreamEvent
|
|
730
|
+
|
|
731
|
+
```typescript
|
|
732
|
+
interface StreamEvent {
|
|
733
|
+
id: string;
|
|
734
|
+
name: string;
|
|
735
|
+
data: Record<string, unknown>;
|
|
736
|
+
entityVersion: number;
|
|
737
|
+
version: number; // Schema version
|
|
738
|
+
timestamp: string; // ISO 8601
|
|
739
|
+
source?: string;
|
|
740
|
+
metadata?: Record<string, unknown>;
|
|
741
|
+
}
|
|
742
|
+
```
|
|
743
|
+
|
|
744
|
+
### StreamInfo
|
|
745
|
+
|
|
746
|
+
```typescript
|
|
747
|
+
interface StreamInfo {
|
|
748
|
+
entityId: string;
|
|
749
|
+
entityType: string;
|
|
750
|
+
version: number;
|
|
751
|
+
eventCount: number;
|
|
752
|
+
createdAt: string;
|
|
753
|
+
updatedAt: string;
|
|
754
|
+
}
|
|
755
|
+
```
|
|
756
|
+
|
|
757
|
+
### EntitySubscribeOptions
|
|
758
|
+
|
|
759
|
+
```typescript
|
|
760
|
+
interface EntitySubscribeOptions {
|
|
761
|
+
/** Entity type (e.g., "order") -- required to construct NATS subject pattern */
|
|
762
|
+
entityType: string;
|
|
763
|
+
onEvent: (event: StreamEvent) => void;
|
|
764
|
+
onError?: (error: Error) => void;
|
|
765
|
+
/** Number of historical events to replay from NATS stream (0 = live only) */
|
|
766
|
+
replay?: number;
|
|
767
|
+
}
|
|
768
|
+
```
|
|
769
|
+
|
|
770
|
+
---
|
|
771
|
+
|
|
772
|
+
## Pub/Sub Types
|
|
773
|
+
|
|
774
|
+
Developer pub/sub for topic-based messaging. Unlike `emit()`, publishing to a topic does NOT trigger workflow functions.
|
|
775
|
+
|
|
776
|
+
### PublishOptions
|
|
777
|
+
|
|
778
|
+
```typescript
|
|
779
|
+
interface PublishOptions {
|
|
780
|
+
idempotencyKey?: string;
|
|
781
|
+
}
|
|
782
|
+
```
|
|
783
|
+
|
|
784
|
+
### PublishResult
|
|
785
|
+
|
|
786
|
+
```typescript
|
|
787
|
+
interface PublishResult {
|
|
788
|
+
eventId: string;
|
|
789
|
+
sequence: number; // JetStream sequence number
|
|
790
|
+
}
|
|
791
|
+
```
|
|
792
|
+
|
|
793
|
+
### TopicInfo
|
|
794
|
+
|
|
795
|
+
```typescript
|
|
796
|
+
interface TopicInfo {
|
|
797
|
+
name: string;
|
|
798
|
+
messageCount: number;
|
|
799
|
+
consumerCount: number;
|
|
800
|
+
firstMessageAt?: string;
|
|
801
|
+
lastMessageAt?: string;
|
|
802
|
+
}
|
|
803
|
+
```
|
|
804
|
+
|
|
805
|
+
### TopicStats
|
|
806
|
+
|
|
807
|
+
```typescript
|
|
808
|
+
interface TopicStats {
|
|
809
|
+
name: string;
|
|
810
|
+
messageCount: number;
|
|
811
|
+
consumerCount: number;
|
|
812
|
+
lag: number;
|
|
813
|
+
firstSeq: number;
|
|
814
|
+
lastSeq: number;
|
|
815
|
+
}
|
|
816
|
+
```
|
|
817
|
+
|
|
818
|
+
---
|
|
819
|
+
|
|
820
|
+
## KV Types
|
|
821
|
+
|
|
822
|
+
Key-value store backed by NATS JetStream KV.
|
|
823
|
+
|
|
824
|
+
### KVBucketConfig
|
|
825
|
+
|
|
826
|
+
```typescript
|
|
827
|
+
interface KVBucketConfig {
|
|
828
|
+
name: string;
|
|
829
|
+
description?: string;
|
|
830
|
+
ttlSeconds?: number; // 0 = no expiry
|
|
831
|
+
maxValueSize?: number; // bytes
|
|
832
|
+
maxBytes?: number; // total bucket size in bytes
|
|
833
|
+
history?: number; // historical values per key (default: 1)
|
|
834
|
+
}
|
|
835
|
+
```
|
|
836
|
+
|
|
837
|
+
### KVBucketInfo
|
|
838
|
+
|
|
839
|
+
```typescript
|
|
840
|
+
interface KVBucketInfo {
|
|
841
|
+
name: string;
|
|
842
|
+
description?: string;
|
|
843
|
+
ttl_seconds?: number;
|
|
844
|
+
values: number;
|
|
845
|
+
bytes: number;
|
|
846
|
+
history: number;
|
|
847
|
+
created_at: string;
|
|
848
|
+
}
|
|
849
|
+
```
|
|
850
|
+
|
|
851
|
+
### KVEntry
|
|
852
|
+
|
|
853
|
+
```typescript
|
|
854
|
+
interface KVEntry {
|
|
855
|
+
key: string;
|
|
856
|
+
value: unknown; // raw bytes as base64 or string
|
|
857
|
+
revision: number;
|
|
858
|
+
created_at: string;
|
|
859
|
+
operation: string; // "put" or "delete"
|
|
860
|
+
}
|
|
861
|
+
```
|
|
862
|
+
|
|
863
|
+
### KVPutResult
|
|
864
|
+
|
|
865
|
+
```typescript
|
|
866
|
+
interface KVPutResult {
|
|
867
|
+
revision: number;
|
|
868
|
+
}
|
|
869
|
+
```
|
|
870
|
+
|
|
871
|
+
### KVListKeysResult
|
|
872
|
+
|
|
873
|
+
```typescript
|
|
874
|
+
interface KVListKeysResult {
|
|
875
|
+
keys: string[];
|
|
876
|
+
count: number;
|
|
877
|
+
}
|
|
878
|
+
```
|
|
879
|
+
|
|
880
|
+
### KVListBucketsResult
|
|
881
|
+
|
|
882
|
+
```typescript
|
|
883
|
+
interface KVListBucketsResult {
|
|
884
|
+
buckets: KVBucketInfo[];
|
|
885
|
+
count: number;
|
|
886
|
+
}
|
|
887
|
+
```
|
|
888
|
+
|
|
889
|
+
### KVWatchEvent
|
|
890
|
+
|
|
891
|
+
```typescript
|
|
892
|
+
interface KVWatchEvent {
|
|
893
|
+
type: "kv_update";
|
|
894
|
+
key: string;
|
|
895
|
+
value: string;
|
|
896
|
+
revision: number;
|
|
897
|
+
operation: "put" | "delete";
|
|
898
|
+
bucket: string;
|
|
899
|
+
}
|
|
900
|
+
```
|
|
901
|
+
|
|
902
|
+
### KVWatchCallbacks
|
|
903
|
+
|
|
904
|
+
```typescript
|
|
905
|
+
interface KVWatchCallbacks {
|
|
906
|
+
onUpdate: (event: KVWatchEvent) => void;
|
|
907
|
+
onError?: (error: Error) => void;
|
|
908
|
+
onClose?: () => void;
|
|
909
|
+
}
|
|
910
|
+
```
|
|
911
|
+
|
|
912
|
+
### KVWatchOptions
|
|
913
|
+
|
|
914
|
+
```typescript
|
|
915
|
+
interface KVWatchOptions {
|
|
916
|
+
/** Key pattern to watch (e.g., "user.*", "session.>"). Empty = all keys. */
|
|
917
|
+
key?: string;
|
|
918
|
+
}
|
|
919
|
+
```
|
|
920
|
+
|
|
921
|
+
### KVWatcher
|
|
922
|
+
|
|
923
|
+
```typescript
|
|
924
|
+
interface KVWatcher {
|
|
925
|
+
stop: () => void;
|
|
926
|
+
}
|
|
927
|
+
```
|
|
928
|
+
|
|
929
|
+
---
|
|
930
|
+
|
|
931
|
+
## Config Types
|
|
932
|
+
|
|
933
|
+
Environment-scoped configuration management built on the KV store.
|
|
934
|
+
|
|
935
|
+
### ConfigResponse
|
|
936
|
+
|
|
937
|
+
```typescript
|
|
938
|
+
interface ConfigResponse {
|
|
939
|
+
name: string;
|
|
940
|
+
data: Record<string, unknown>;
|
|
941
|
+
revision: number;
|
|
942
|
+
updatedAt: string;
|
|
943
|
+
}
|
|
944
|
+
```
|
|
945
|
+
|
|
946
|
+
### ConfigEntry
|
|
947
|
+
|
|
948
|
+
Summary (without full data), used in list responses.
|
|
949
|
+
|
|
950
|
+
```typescript
|
|
951
|
+
interface ConfigEntry {
|
|
952
|
+
name: string;
|
|
953
|
+
revision: number;
|
|
954
|
+
updatedAt: string;
|
|
955
|
+
}
|
|
956
|
+
```
|
|
957
|
+
|
|
958
|
+
### ConfigSetResult
|
|
959
|
+
|
|
960
|
+
```typescript
|
|
961
|
+
interface ConfigSetResult {
|
|
962
|
+
name: string;
|
|
963
|
+
revision: number;
|
|
964
|
+
}
|
|
965
|
+
```
|
|
966
|
+
|
|
967
|
+
### ConfigWatchCallbacks
|
|
968
|
+
|
|
969
|
+
```typescript
|
|
970
|
+
interface ConfigWatchCallbacks {
|
|
971
|
+
onEvent: (config: ConfigResponse) => void;
|
|
972
|
+
onError?: (error: Error) => void;
|
|
973
|
+
}
|
|
974
|
+
```
|
|
975
|
+
|
|
976
|
+
---
|
|
977
|
+
|
|
978
|
+
## Auth Types
|
|
979
|
+
|
|
980
|
+
Types for API key, organization, role, and policy management.
|
|
981
|
+
|
|
982
|
+
### API Keys
|
|
983
|
+
|
|
984
|
+
```typescript
|
|
985
|
+
interface APIKey {
|
|
986
|
+
id: string;
|
|
987
|
+
name: string;
|
|
988
|
+
key_prefix: string;
|
|
989
|
+
role_ids?: string[];
|
|
990
|
+
created_at: string;
|
|
991
|
+
expires_at?: string;
|
|
992
|
+
last_used_at?: string;
|
|
993
|
+
}
|
|
994
|
+
|
|
995
|
+
interface APIKeyWithSecret extends APIKey {
|
|
996
|
+
/** Full API key -- only returned on creation */
|
|
997
|
+
key: string;
|
|
998
|
+
}
|
|
999
|
+
|
|
1000
|
+
interface CreateAPIKeyInput {
|
|
1001
|
+
name: string;
|
|
1002
|
+
env_id?: string;
|
|
1003
|
+
role_ids?: string[];
|
|
1004
|
+
expires_in?: string;
|
|
1005
|
+
}
|
|
1006
|
+
```
|
|
1007
|
+
|
|
1008
|
+
### Organizations
|
|
1009
|
+
|
|
1010
|
+
```typescript
|
|
1011
|
+
interface Organization {
|
|
1012
|
+
id: string;
|
|
1013
|
+
name: string;
|
|
1014
|
+
created_at: string;
|
|
1015
|
+
updated_at: string;
|
|
1016
|
+
}
|
|
1017
|
+
|
|
1018
|
+
interface CreateOrgInput {
|
|
1019
|
+
name: string;
|
|
1020
|
+
}
|
|
1021
|
+
|
|
1022
|
+
interface UpdateOrgInput {
|
|
1023
|
+
name?: string;
|
|
1024
|
+
}
|
|
1025
|
+
```
|
|
1026
|
+
|
|
1027
|
+
### Roles
|
|
1028
|
+
|
|
1029
|
+
```typescript
|
|
1030
|
+
interface Role {
|
|
1031
|
+
id: string;
|
|
1032
|
+
org_id: string;
|
|
1033
|
+
name: string;
|
|
1034
|
+
is_default: boolean;
|
|
1035
|
+
created_at: string;
|
|
1036
|
+
}
|
|
1037
|
+
|
|
1038
|
+
interface CreateRoleInput {
|
|
1039
|
+
name: string;
|
|
1040
|
+
org_id: string;
|
|
1041
|
+
}
|
|
1042
|
+
|
|
1043
|
+
interface UpdateRoleInput {
|
|
1044
|
+
name?: string;
|
|
1045
|
+
}
|
|
1046
|
+
```
|
|
1047
|
+
|
|
1048
|
+
### Policies
|
|
1049
|
+
|
|
1050
|
+
```typescript
|
|
1051
|
+
interface Policy {
|
|
1052
|
+
id: string;
|
|
1053
|
+
org_id: string;
|
|
1054
|
+
name: string;
|
|
1055
|
+
effect: "allow" | "deny";
|
|
1056
|
+
actions: string;
|
|
1057
|
+
resources: string;
|
|
1058
|
+
condition?: string;
|
|
1059
|
+
created_at: string;
|
|
1060
|
+
updated_at: string;
|
|
1061
|
+
}
|
|
1062
|
+
|
|
1063
|
+
interface CreatePolicyInput {
|
|
1064
|
+
name: string;
|
|
1065
|
+
effect: "allow" | "deny";
|
|
1066
|
+
actions: string;
|
|
1067
|
+
resources: string;
|
|
1068
|
+
condition?: string;
|
|
1069
|
+
org_id: string;
|
|
1070
|
+
}
|
|
1071
|
+
|
|
1072
|
+
interface UpdatePolicyInput {
|
|
1073
|
+
name?: string;
|
|
1074
|
+
effect?: "allow" | "deny";
|
|
1075
|
+
actions?: string;
|
|
1076
|
+
resources?: string;
|
|
1077
|
+
condition?: string;
|
|
1078
|
+
}
|
|
1079
|
+
```
|
|
1080
|
+
|
|
1081
|
+
---
|
|
1082
|
+
|
|
1083
|
+
## Audit Types
|
|
1084
|
+
|
|
1085
|
+
Audit trail for function execution recording (enterprise feature).
|
|
1086
|
+
|
|
1087
|
+
```typescript
|
|
1088
|
+
interface AuditEvent {
|
|
1089
|
+
id: string;
|
|
1090
|
+
runId: string;
|
|
1091
|
+
functionId: string;
|
|
1092
|
+
stepId?: string;
|
|
1093
|
+
eventType: string;
|
|
1094
|
+
payload: Record<string, unknown>;
|
|
1095
|
+
metadata?: Record<string, string>;
|
|
1096
|
+
createdAt: string;
|
|
1097
|
+
}
|
|
1098
|
+
|
|
1099
|
+
interface GetAuditTrailOptions {
|
|
1100
|
+
eventType?: string;
|
|
1101
|
+
fromTimestamp?: string;
|
|
1102
|
+
toTimestamp?: string;
|
|
1103
|
+
limit?: number;
|
|
1104
|
+
cursor?: string;
|
|
1105
|
+
}
|
|
1106
|
+
|
|
1107
|
+
interface AuditTrailResult {
|
|
1108
|
+
events: AuditEvent[];
|
|
1109
|
+
totalCount: number;
|
|
1110
|
+
nextCursor?: string;
|
|
1111
|
+
}
|
|
1112
|
+
```
|
|
1113
|
+
|
|
1114
|
+
---
|
|
1115
|
+
|
|
1116
|
+
## Webhook Types
|
|
1117
|
+
|
|
1118
|
+
Types for defining webhook sources that transform inbound HTTP requests into Ironflow events.
|
|
1119
|
+
|
|
1120
|
+
```typescript
|
|
1121
|
+
interface WebhookRequest {
|
|
1122
|
+
body: string;
|
|
1123
|
+
headers: Record<string, string>;
|
|
1124
|
+
}
|
|
1125
|
+
|
|
1126
|
+
interface WebhookEvent {
|
|
1127
|
+
name: string;
|
|
1128
|
+
data: unknown;
|
|
1129
|
+
idempotencyKey?: string;
|
|
1130
|
+
}
|
|
1131
|
+
|
|
1132
|
+
interface WebhookConfig {
|
|
1133
|
+
id: string;
|
|
1134
|
+
/** Verify the webhook signature. Return the parsed payload or throw. */
|
|
1135
|
+
verify: (req: WebhookRequest) => unknown | Promise<unknown>;
|
|
1136
|
+
/** Transform the verified payload into an Ironflow event. */
|
|
1137
|
+
transform: (payload: unknown) => WebhookEvent | Promise<WebhookEvent>;
|
|
1138
|
+
}
|
|
1139
|
+
|
|
1140
|
+
interface IronflowWebhook {
|
|
1141
|
+
config: WebhookConfig;
|
|
1142
|
+
}
|
|
11
1143
|
```
|
|
12
1144
|
|
|
13
|
-
|
|
1145
|
+
---
|
|
1146
|
+
|
|
1147
|
+
## Projection Types
|
|
14
1148
|
|
|
15
|
-
|
|
1149
|
+
Projections build read models from event streams.
|
|
1150
|
+
|
|
1151
|
+
### ProjectionMode and ProjectionStatus
|
|
16
1152
|
|
|
17
1153
|
```typescript
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
1154
|
+
type ProjectionMode = "managed" | "external";
|
|
1155
|
+
// "managed": pure reducer, state stored by Ironflow
|
|
1156
|
+
// "external": side-effect handler, you manage storage
|
|
21
1157
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
1158
|
+
type ProjectionStatus = "active" | "rebuilding" | "paused" | "error";
|
|
1159
|
+
```
|
|
1160
|
+
|
|
1161
|
+
### ProjectionConfig
|
|
1162
|
+
|
|
1163
|
+
```typescript
|
|
1164
|
+
interface ProjectionConfig<TState = unknown, TEvent = unknown> {
|
|
1165
|
+
/** Unique projection name */
|
|
1166
|
+
name: string;
|
|
1167
|
+
/** Event names to subscribe to (supports wildcards like "order.*") */
|
|
1168
|
+
events: string[];
|
|
1169
|
+
/** Execution mode -- auto-detected from initialState if omitted */
|
|
1170
|
+
mode?: ProjectionMode;
|
|
1171
|
+
/** Handler function */
|
|
1172
|
+
handler: ManagedProjectionHandler<TState, TEvent> | ExternalProjectionHandler<TEvent>;
|
|
1173
|
+
/** Initial state factory (required for managed, absent for external) */
|
|
1174
|
+
initialState?: () => TState;
|
|
1175
|
+
/** JSONPath for partition key extraction (e.g., "$.data.customerId") */
|
|
1176
|
+
partitionKey?: string;
|
|
1177
|
+
/** Max retries per event (default 3) */
|
|
1178
|
+
maxRetries?: number;
|
|
1179
|
+
/** Batch size for polling (default 100) */
|
|
1180
|
+
batchSize?: number;
|
|
1181
|
+
}
|
|
1182
|
+
```
|
|
25
1183
|
|
|
26
|
-
|
|
27
|
-
|
|
1184
|
+
### ProjectionContext
|
|
1185
|
+
|
|
1186
|
+
```typescript
|
|
1187
|
+
interface ProjectionContext {
|
|
1188
|
+
event: { id: string; name: string; seq: number; timestamp: Date };
|
|
1189
|
+
projection: { name: string; version: number };
|
|
1190
|
+
logger: Logger;
|
|
1191
|
+
}
|
|
1192
|
+
```
|
|
28
1193
|
|
|
29
|
-
|
|
30
|
-
StepClient, Duration, ParallelOptions,
|
|
1194
|
+
### Handlers
|
|
31
1195
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
1196
|
+
```typescript
|
|
1197
|
+
/** Managed: pure reducer. Returns new state. */
|
|
1198
|
+
type ManagedProjectionHandler<TState = unknown, TEvent = unknown> = (
|
|
1199
|
+
state: TState,
|
|
1200
|
+
event: TEvent & { name: string; data: unknown },
|
|
1201
|
+
ctx: ProjectionContext
|
|
1202
|
+
) => TState;
|
|
35
1203
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
1204
|
+
/** External: side effects. Return void or Promise<void>. */
|
|
1205
|
+
type ExternalProjectionHandler<TEvent = unknown> = (
|
|
1206
|
+
event: TEvent & { name: string; data: unknown },
|
|
1207
|
+
ctx: ProjectionContext
|
|
1208
|
+
) => void | Promise<void>;
|
|
1209
|
+
```
|
|
39
1210
|
|
|
40
|
-
|
|
41
|
-
ProjectionConfig, ProjectionContext, ProjectionStatus,
|
|
42
|
-
ManagedProjectionHandler, ExternalProjectionHandler,
|
|
1211
|
+
### IronflowProjection
|
|
43
1212
|
|
|
44
|
-
|
|
45
|
-
|
|
1213
|
+
```typescript
|
|
1214
|
+
interface IronflowProjection<TState = unknown, TEvent = unknown> {
|
|
1215
|
+
config: ProjectionConfig<TState, TEvent>;
|
|
1216
|
+
}
|
|
1217
|
+
```
|
|
46
1218
|
|
|
47
|
-
|
|
48
|
-
ConfigResponse, ConfigEntry, ConfigSetResult,
|
|
1219
|
+
### ProjectionStatusInfo
|
|
49
1220
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
1221
|
+
```typescript
|
|
1222
|
+
interface ProjectionStatusInfo {
|
|
1223
|
+
name: string;
|
|
1224
|
+
status: ProjectionStatus;
|
|
1225
|
+
mode: ProjectionMode;
|
|
1226
|
+
lastEventSeq: number;
|
|
1227
|
+
lag: number;
|
|
1228
|
+
errorMessage?: string;
|
|
1229
|
+
updatedAt: Date;
|
|
1230
|
+
}
|
|
1231
|
+
```
|
|
1232
|
+
|
|
1233
|
+
### ProjectionStateResult
|
|
1234
|
+
|
|
1235
|
+
```typescript
|
|
1236
|
+
interface ProjectionStateResult<TState = unknown> {
|
|
1237
|
+
name: string;
|
|
1238
|
+
partition: string;
|
|
1239
|
+
state: TState;
|
|
1240
|
+
lastEventId: string;
|
|
1241
|
+
lastEventTime: Date;
|
|
1242
|
+
version: number;
|
|
1243
|
+
mode: ProjectionMode;
|
|
1244
|
+
}
|
|
1245
|
+
```
|
|
1246
|
+
|
|
1247
|
+
### GetProjectionOptions and RebuildProjectionOptions
|
|
1248
|
+
|
|
1249
|
+
```typescript
|
|
1250
|
+
interface GetProjectionOptions {
|
|
1251
|
+
partition?: string;
|
|
1252
|
+
}
|
|
1253
|
+
|
|
1254
|
+
interface RebuildProjectionOptions {
|
|
1255
|
+
partition?: string;
|
|
1256
|
+
fromEventId?: string;
|
|
1257
|
+
dryRun?: boolean;
|
|
1258
|
+
}
|
|
1259
|
+
```
|
|
1260
|
+
|
|
1261
|
+
### ProjectionSubscriptionCallbacks
|
|
1262
|
+
|
|
1263
|
+
```typescript
|
|
1264
|
+
interface ProjectionSubscriptionCallbacks<TState = unknown> {
|
|
1265
|
+
onUpdate: (state: TState, event: { id: string; name: string }) => void;
|
|
1266
|
+
onError?: (error: Error) => void;
|
|
1267
|
+
}
|
|
1268
|
+
```
|
|
1269
|
+
|
|
1270
|
+
Usage example (via `@ironflow/node`):
|
|
1271
|
+
|
|
1272
|
+
```typescript
|
|
1273
|
+
import { createProjection } from '@ironflow/node';
|
|
1274
|
+
|
|
1275
|
+
const orderStats = createProjection({
|
|
1276
|
+
name: 'order-stats',
|
|
1277
|
+
events: ['order.placed', 'order.cancelled'],
|
|
1278
|
+
initialState: () => ({ total: 0, cancelled: 0 }),
|
|
1279
|
+
handler: (state, event) => {
|
|
1280
|
+
if (event.name === 'order.placed') return { ...state, total: state.total + 1 };
|
|
1281
|
+
if (event.name === 'order.cancelled') return { ...state, cancelled: state.cancelled + 1 };
|
|
1282
|
+
return state;
|
|
1283
|
+
},
|
|
1284
|
+
});
|
|
53
1285
|
```
|
|
54
1286
|
|
|
55
|
-
|
|
1287
|
+
---
|
|
1288
|
+
|
|
1289
|
+
## Error Classes
|
|
56
1290
|
|
|
57
|
-
|
|
1291
|
+
All errors extend `IronflowError`. Each has a `code` string and a `retryable` boolean.
|
|
58
1292
|
|
|
59
1293
|
```typescript
|
|
60
1294
|
import {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
1295
|
+
IronflowError, ConnectionError, SubscriptionError, TimeoutError,
|
|
1296
|
+
ValidationError, SchemaValidationError, SignatureError,
|
|
1297
|
+
FunctionNotFoundError, RunNotFoundError, StepError, NonRetryableError,
|
|
1298
|
+
NotConfiguredError, InvokeError, InvokeTimeoutError, StepTimeoutError,
|
|
1299
|
+
UnauthenticatedError, EnterpriseRequiredError, UnauthorizedError,
|
|
1300
|
+
isRetryable, isIronflowError, toError,
|
|
1301
|
+
} from '@ironflow/core';
|
|
1302
|
+
```
|
|
1303
|
+
|
|
1304
|
+
### IronflowError (base class)
|
|
1305
|
+
|
|
1306
|
+
```typescript
|
|
1307
|
+
class IronflowError extends Error {
|
|
1308
|
+
readonly code: string;
|
|
1309
|
+
readonly retryable: boolean;
|
|
1310
|
+
readonly details?: Record<string, unknown>;
|
|
1311
|
+
|
|
1312
|
+
constructor(message: string, options?: {
|
|
1313
|
+
code?: string; // default: "UNKNOWN_ERROR"
|
|
1314
|
+
retryable?: boolean; // default: false
|
|
1315
|
+
details?: Record<string, unknown>;
|
|
1316
|
+
cause?: Error;
|
|
1317
|
+
});
|
|
1318
|
+
}
|
|
1319
|
+
```
|
|
1320
|
+
|
|
1321
|
+
### Error Reference Table
|
|
1322
|
+
|
|
1323
|
+
| Class | Code | Retryable | When Thrown |
|
|
1324
|
+
|---|---|---|---|
|
|
1325
|
+
| `ConnectionError` | `CONNECTION_LOST` | true | WebSocket/HTTP connection lost |
|
|
1326
|
+
| `SubscriptionError` | `SUBSCRIPTION_ERROR` | true | Subscription setup or delivery failure |
|
|
1327
|
+
| `TimeoutError` | `TIMEOUT` | true | HTTP request or sync trigger timeout |
|
|
1328
|
+
| `ValidationError` | `VALIDATION_ERROR` | false | Invalid input data |
|
|
1329
|
+
| `SchemaValidationError` | `VALIDATION_ERROR` | false | Zod schema validation failure |
|
|
1330
|
+
| `SignatureError` | `SIGNATURE_INVALID` | false | Invalid webhook signature |
|
|
1331
|
+
| `FunctionNotFoundError` | `FUNCTION_NOT_FOUND` | false | Function ID not in registry |
|
|
1332
|
+
| `RunNotFoundError` | `RUN_NOT_FOUND` | false | Run ID not found in store |
|
|
1333
|
+
| `StepError` | `STEP_FAILED` | true | Step execution failure (has `stepId`, `stepName`) |
|
|
1334
|
+
| `NonRetryableError` | `NON_RETRYABLE` | false | Permanent failure, skip retries |
|
|
1335
|
+
| `NotConfiguredError` | `NOT_CONFIGURED` | false | Client used before `configure()` |
|
|
1336
|
+
| `InvokeError` | `INVOKE_FAILED` | false | `step.invoke()` target failed (has `functionId`, `childRunId`) |
|
|
1337
|
+
| `InvokeTimeoutError` | `INVOKE_FAILED` | false | `step.invoke()` timed out (has `timeoutMs`) |
|
|
1338
|
+
| `StepTimeoutError` | `STEP_TIMEOUT` | true | `step.run()` exceeded its timeout (has `stepName`, `timeout`) |
|
|
1339
|
+
| `UnauthenticatedError` | `UNAUTHENTICATED` | false | No/invalid API key (HTTP 401) |
|
|
1340
|
+
| `EnterpriseRequiredError` | `ENTERPRISE_REQUIRED` | false | Enterprise license needed (HTTP 402) |
|
|
1341
|
+
| `UnauthorizedError` | `UNAUTHORIZED` | false | Insufficient permissions (HTTP 403) |
|
|
1342
|
+
|
|
1343
|
+
### Utility Functions
|
|
1344
|
+
|
|
1345
|
+
```typescript
|
|
1346
|
+
// Check if an error is retryable (also returns true for fetch TypeErrors)
|
|
1347
|
+
isRetryable(error: unknown): boolean
|
|
1348
|
+
|
|
1349
|
+
// Type guard for IronflowError
|
|
1350
|
+
isIronflowError(error: unknown): error is IronflowError
|
|
1351
|
+
|
|
1352
|
+
// Normalize any thrown value to an Error instance
|
|
1353
|
+
toError(error: unknown): Error
|
|
1354
|
+
```
|
|
1355
|
+
|
|
1356
|
+
Usage:
|
|
1357
|
+
|
|
1358
|
+
```typescript
|
|
1359
|
+
try {
|
|
1360
|
+
await client.trigger('order.placed', { amount: 100 });
|
|
1361
|
+
} catch (err) {
|
|
1362
|
+
if (isRetryable(err)) {
|
|
1363
|
+
// Safe to retry
|
|
1364
|
+
}
|
|
1365
|
+
if (err instanceof FunctionNotFoundError) {
|
|
1366
|
+
console.error(`Function ${err.functionId} not registered`);
|
|
1367
|
+
}
|
|
1368
|
+
}
|
|
1369
|
+
```
|
|
1370
|
+
|
|
1371
|
+
---
|
|
1372
|
+
|
|
1373
|
+
## Schemas
|
|
1374
|
+
|
|
1375
|
+
Zod schemas for runtime validation of API responses, WebSocket messages, and webhook payloads. All schemas are exported from `@ironflow/core` or the `@ironflow/core/schemas` sub-path.
|
|
1376
|
+
|
|
1377
|
+
### Validation Helpers
|
|
1378
|
+
|
|
1379
|
+
```typescript
|
|
1380
|
+
import { parseAndValidate, validate, RunResponseSchema } from '@ironflow/core';
|
|
1381
|
+
|
|
1382
|
+
// Parse JSON string and validate against schema
|
|
1383
|
+
// Throws SchemaValidationError on failure
|
|
1384
|
+
const run = parseAndValidate(RunResponseSchema, jsonString, 'GetRun response');
|
|
1385
|
+
|
|
1386
|
+
// Validate already-parsed data against schema
|
|
1387
|
+
// Throws SchemaValidationError on failure
|
|
1388
|
+
const run = validate(RunResponseSchema, parsedData, 'GetRun response');
|
|
1389
|
+
```
|
|
1390
|
+
|
|
1391
|
+
### Available Schemas
|
|
1392
|
+
|
|
1393
|
+
**Run & Status:**
|
|
1394
|
+
- `RunStatusSchema` -- `z.enum(["pending", "running", "completed", "failed", "cancelled", "paused"])`
|
|
1395
|
+
|
|
1396
|
+
**Push Request (serve.ts):**
|
|
1397
|
+
- `PushRequestSchema` -- Full push mode request from engine to SDK
|
|
1398
|
+
- `PushRequestEventSchema` -- Event portion of push request
|
|
1399
|
+
- `CompletedStepSchema` -- Memoized step from previous execution
|
|
1400
|
+
- `ResumeContextSchema` -- Resume context for sleep/waitForEvent/invoke
|
|
1401
|
+
|
|
1402
|
+
**API Responses:**
|
|
1403
|
+
- `TriggerResponseSchema` -- `{ runIds?, eventId }`
|
|
1404
|
+
- `TriggerSyncResultItemSchema` -- Individual sync trigger result
|
|
1405
|
+
- `TriggerSyncResponseSchema` -- `{ results?, eventId }`
|
|
1406
|
+
- `RunResponseSchema` -- Full run details
|
|
1407
|
+
- `ListRunsResponseSchema` -- `{ runs?, nextCursor?, totalCount? }`
|
|
1408
|
+
- `RegisterFunctionResponseSchema` -- `{ created? }`
|
|
1409
|
+
- `HealthResponseSchema` -- `{ status }`
|
|
1410
|
+
- `ErrorResponseSchema` -- `{ code?, message? }`
|
|
1411
|
+
- `EmptyResponseSchema` -- `{}`
|
|
1412
|
+
|
|
1413
|
+
**Consumer Groups:**
|
|
1414
|
+
- `AckModeSchema` -- `z.enum(["ACK_MODE_AUTO", "ACK_MODE_MANUAL", "ACK_MODE_UNSPECIFIED"])`
|
|
1415
|
+
- `BackpressureModeSchema`
|
|
1416
|
+
- `ConsumerGroupStatusSchema`
|
|
1417
|
+
- `ConsumerGroupResponseSchema`
|
|
1418
|
+
- `ListConsumerGroupsResponseSchema`
|
|
1419
|
+
|
|
1420
|
+
**Worker Job Assignment:**
|
|
1421
|
+
- `JobAssignmentSchema` -- Full job assignment for pull-mode workers
|
|
1422
|
+
- `JobEventSchema`, `JobCompletedStepSchema`, `JobContextSchema`
|
|
1423
|
+
|
|
1424
|
+
**WebSocket Messages:**
|
|
1425
|
+
- `WSServerMessageSchema` -- Discriminated union of all server messages
|
|
1426
|
+
- `WSEventMessageSchema` -- Event delivery
|
|
1427
|
+
- `WSSubscriptionResultSchema` -- Subscribe confirmation
|
|
1428
|
+
- `WSSubscriptionErrorSchema` -- Subscription error
|
|
1429
|
+
- `WSErrorSchema` -- General error
|
|
1430
|
+
- `EventMetadataSchema`
|
|
1431
|
+
|
|
1432
|
+
**Audit:**
|
|
1433
|
+
- `AuditEventSchema`
|
|
1434
|
+
|
|
1435
|
+
### Inferred Types
|
|
1436
|
+
|
|
1437
|
+
```typescript
|
|
1438
|
+
import type {
|
|
1439
|
+
ValidatedPushRequest,
|
|
1440
|
+
ValidatedRunResponse,
|
|
1441
|
+
ValidatedJobAssignment,
|
|
1442
|
+
ValidatedWSServerMessage,
|
|
70
1443
|
} from '@ironflow/core';
|
|
1444
|
+
```
|
|
1445
|
+
|
|
1446
|
+
These are `z.infer<>` types derived from the corresponding schemas.
|
|
1447
|
+
|
|
1448
|
+
---
|
|
1449
|
+
|
|
1450
|
+
## Protocol Types
|
|
1451
|
+
|
|
1452
|
+
Low-level protocol types for SDK authors building custom transports. Import from `@ironflow/core` or `@ironflow/core/protocol`.
|
|
1453
|
+
|
|
1454
|
+
### Push Mode (HTTP)
|
|
1455
|
+
|
|
1456
|
+
```typescript
|
|
1457
|
+
interface PushRequest {
|
|
1458
|
+
run_id: string;
|
|
1459
|
+
function_id: string;
|
|
1460
|
+
attempt: number;
|
|
1461
|
+
event: {
|
|
1462
|
+
id: string; name: string; data: unknown; timestamp: string;
|
|
1463
|
+
version?: number; idempotency_key?: string; source?: string;
|
|
1464
|
+
metadata?: Record<string, unknown>;
|
|
1465
|
+
};
|
|
1466
|
+
steps: CompletedStep[];
|
|
1467
|
+
resume?: ResumeContext;
|
|
1468
|
+
}
|
|
1469
|
+
|
|
1470
|
+
interface PushResponse {
|
|
1471
|
+
status: "completed" | "yielded" | "failed";
|
|
1472
|
+
steps: StepResult[];
|
|
1473
|
+
result?: unknown;
|
|
1474
|
+
error?: {
|
|
1475
|
+
message: string; code?: string; step_id?: string;
|
|
1476
|
+
retryable: boolean; stack?: string;
|
|
1477
|
+
};
|
|
1478
|
+
yield?: YieldInfo;
|
|
1479
|
+
}
|
|
1480
|
+
|
|
1481
|
+
interface CompletedStep {
|
|
1482
|
+
id: string; name: string;
|
|
1483
|
+
status: "completed" | "failed" | "timed_out";
|
|
1484
|
+
output?: unknown; error?: string;
|
|
1485
|
+
}
|
|
1486
|
+
|
|
1487
|
+
interface ResumeContext {
|
|
1488
|
+
step_id: string;
|
|
1489
|
+
type: "sleep" | "wait_for_event" | "invoke_function" | "invoke_function_async";
|
|
1490
|
+
data?: unknown;
|
|
1491
|
+
}
|
|
1492
|
+
|
|
1493
|
+
interface StepResult {
|
|
1494
|
+
id: string; name: string;
|
|
1495
|
+
type: "invoke" | "sleep" | "wait_for_event" | "compensate";
|
|
1496
|
+
status: "completed" | "failed";
|
|
1497
|
+
started_at: string; ended_at?: string; duration_ms?: number;
|
|
1498
|
+
output?: unknown;
|
|
1499
|
+
error?: { message: string; retryable: boolean; stack?: string };
|
|
1500
|
+
compensation_for?: string;
|
|
1501
|
+
}
|
|
1502
|
+
```
|
|
1503
|
+
|
|
1504
|
+
### Yield Types
|
|
1505
|
+
|
|
1506
|
+
```typescript
|
|
1507
|
+
type YieldInfo = SleepYield | WaitEventYield | InvokeFunctionYield | InvokeFunctionAsyncYield;
|
|
1508
|
+
|
|
1509
|
+
interface SleepYield { step_id: string; type: "sleep"; until: string; }
|
|
1510
|
+
interface WaitEventYield { step_id: string; type: "wait_for_event"; event_filter: { event: string; match?: string; timeout?: string; }; }
|
|
1511
|
+
interface InvokeFunctionYield { step_id: string; type: "invoke_function"; function_id: string; input?: unknown; invoke_timeout_ms?: number; }
|
|
1512
|
+
interface InvokeFunctionAsyncYield { step_id: string; type: "invoke_function_async"; function_id: string; input?: unknown; }
|
|
1513
|
+
```
|
|
1514
|
+
|
|
1515
|
+
### WebSocket Protocol
|
|
1516
|
+
|
|
1517
|
+
**Client to server:**
|
|
1518
|
+
|
|
1519
|
+
```typescript
|
|
1520
|
+
interface WSSubscribeRequest {
|
|
1521
|
+
type: "subscribe";
|
|
1522
|
+
subscription: {
|
|
1523
|
+
pattern: string;
|
|
1524
|
+
options?: {
|
|
1525
|
+
replay?: number; includeMetadata?: boolean; filter?: string;
|
|
1526
|
+
consumerGroup?: string; ackMode?: AckMode;
|
|
1527
|
+
backpressure?: BackpressureMode; namespace?: string;
|
|
1528
|
+
};
|
|
1529
|
+
};
|
|
1530
|
+
}
|
|
71
1531
|
|
|
72
|
-
|
|
73
|
-
|
|
1532
|
+
interface WSUnsubscribeRequest { type: "unsubscribe"; subscriptionId: string; }
|
|
1533
|
+
interface WSAckRequest { type: "ack"; eventId: string; ackType: AckType; redeliverDelay?: number; }
|
|
1534
|
+
|
|
1535
|
+
type WSClientMessage = WSSubscribeRequest | WSUnsubscribeRequest | WSAckRequest;
|
|
1536
|
+
```
|
|
1537
|
+
|
|
1538
|
+
**Server to client:**
|
|
1539
|
+
|
|
1540
|
+
```typescript
|
|
1541
|
+
interface WSSubscriptionResult {
|
|
1542
|
+
type: "subscription_result";
|
|
1543
|
+
results: Array<{ pattern: string; status: "ok" | "error"; subscriptionId?: string; code?: string; message?: string; }>;
|
|
1544
|
+
}
|
|
1545
|
+
interface WSEventMessage { type: "event"; subscriptionId: string; topic: string; data: unknown; meta?: EventMetadata; eventId?: string; }
|
|
1546
|
+
interface WSSubscriptionError { type: "subscription_error"; subscriptionId: string; code: string; message: string; retrying: boolean; }
|
|
1547
|
+
interface WSError { type: "error"; code: string; message: string; }
|
|
1548
|
+
|
|
1549
|
+
type WSServerMessage = WSSubscriptionResult | WSEventMessage | WSSubscriptionError | WSError;
|
|
1550
|
+
```
|
|
1551
|
+
|
|
1552
|
+
### Retry Types
|
|
1553
|
+
|
|
1554
|
+
```typescript
|
|
1555
|
+
interface RetryEvent { attempt: number; maxAttempts: number; error: Error; delayMs: number; }
|
|
1556
|
+
interface RetryInfo { eventId: string; attempt: number; maxAttempts: number; delayMs?: number; }
|
|
1557
|
+
|
|
1558
|
+
interface ClientRetryConfig {
|
|
1559
|
+
maxAttempts?: number; // default: 3
|
|
1560
|
+
initialDelayMs?: number; // default: 100
|
|
1561
|
+
maxDelayMs?: number; // default: 10000
|
|
1562
|
+
backoffMultiplier?: number; // default: 2.0
|
|
1563
|
+
connectionRetryDelayMs?: number; // default: 2000
|
|
1564
|
+
onRetry?: (event: RetryEvent) => void;
|
|
1565
|
+
}
|
|
74
1566
|
```
|
|
75
1567
|
|
|
76
|
-
|
|
1568
|
+
---
|
|
1569
|
+
|
|
1570
|
+
## Constants
|
|
77
1571
|
|
|
78
1572
|
```typescript
|
|
79
1573
|
import {
|
|
80
|
-
|
|
1574
|
+
DEFAULT_PORT, // 9123
|
|
1575
|
+
DEFAULT_HOST, // "localhost"
|
|
1576
|
+
DEFAULT_SERVER_URL, // "http://localhost:9123"
|
|
1577
|
+
DEFAULT_WS_URL, // "ws://localhost:9123/ws"
|
|
1578
|
+
DEFAULT_ENVIRONMENT, // "default"
|
|
1579
|
+
|
|
1580
|
+
DEFAULT_TIMEOUTS,
|
|
1581
|
+
// { CLIENT: 30_000, FUNCTION: 600_000, TRIGGER_SYNC: 30_000 }
|
|
1582
|
+
|
|
1583
|
+
DEFAULT_RETRY,
|
|
1584
|
+
// { MAX_ATTEMPTS: 3, INITIAL_DELAY_MS: 1000, BACKOFF_FACTOR: 2.0, MAX_DELAY_MS: 300_000 }
|
|
1585
|
+
|
|
1586
|
+
DEFAULT_CLIENT_RETRY,
|
|
1587
|
+
// { MAX_ATTEMPTS: 3, INITIAL_DELAY_MS: 100, BACKOFF_MULTIPLIER: 2.0,
|
|
1588
|
+
// MAX_DELAY_MS: 10_000, CONNECTION_RETRY_DELAY_MS: 2_000 }
|
|
1589
|
+
|
|
1590
|
+
DEFAULT_WORKER,
|
|
1591
|
+
// { MAX_CONCURRENT_JOBS: 10, HEARTBEAT_INTERVAL_MS: 30_000, RECONNECT_DELAY_MS: 5_000 }
|
|
1592
|
+
|
|
1593
|
+
DEFAULT_RECONNECT,
|
|
1594
|
+
// { ENABLED: true, MAX_ATTEMPTS: 10, INITIAL_DELAY_MS: 1_000,
|
|
1595
|
+
// MAX_DELAY_MS: 30_000, MULTIPLIER: 2 }
|
|
1596
|
+
|
|
1597
|
+
ENV_VARS,
|
|
1598
|
+
// { SERVER_URL: "IRONFLOW_SERVER_URL", SIGNING_KEY: "IRONFLOW_SIGNING_KEY",
|
|
1599
|
+
// API_KEY: "IRONFLOW_API_KEY", LOG_LEVEL: "IRONFLOW_LOG_LEVEL" }
|
|
1600
|
+
|
|
1601
|
+
STEP_TYPES,
|
|
1602
|
+
// { INVOKE: "invoke", SLEEP: "sleep", WAIT_FOR_EVENT: "wait_for_event" }
|
|
1603
|
+
|
|
81
1604
|
STEP_STATUS,
|
|
1605
|
+
// { COMPLETED: "completed", FAILED: "failed", WAITING: "waiting" }
|
|
1606
|
+
|
|
82
1607
|
RUN_STATUS,
|
|
83
|
-
|
|
1608
|
+
// { PENDING: "pending", RUNNING: "running", COMPLETED: "completed",
|
|
1609
|
+
// FAILED: "failed", CANCELLED: "cancelled", PAUSED: "paused" }
|
|
1610
|
+
|
|
84
1611
|
API_ENDPOINTS,
|
|
85
|
-
|
|
86
|
-
|
|
1612
|
+
// ConnectRPC paths: TRIGGER, TRIGGER_SYNC, GET_RUN, LIST_RUNS, CANCEL_RUN,
|
|
1613
|
+
// RETRY_RUN, REGISTER_FUNCTION, HEALTH, EMIT, CREATE_CONSUMER_GROUP,
|
|
1614
|
+
// GET_CONSUMER_GROUP, LIST_CONSUMER_GROUPS, DELETE_CONSUMER_GROUP
|
|
1615
|
+
|
|
1616
|
+
TIMING,
|
|
1617
|
+
// { POLL_INTERVAL_MS: 1000, ERROR_RETRY_DELAY_MS: 5000,
|
|
1618
|
+
// RECONNECT_DELAY_MS: 1000, WS_CLOSE_NORMAL: 1000 }
|
|
1619
|
+
|
|
1620
|
+
ACK_TYPES,
|
|
1621
|
+
// { ACK: "ack", NAK: "nak", TERM: "term" }
|
|
1622
|
+
|
|
1623
|
+
ERROR_CODES,
|
|
1624
|
+
// FUNCTION_NOT_FOUND, VALIDATION_ERROR, SIGNATURE_INVALID, NETWORK_ERROR,
|
|
1625
|
+
// SERVER_ERROR, TIMEOUT_ERROR, CONNECTION_LOST, CONNECTION_REFUSED,
|
|
1626
|
+
// SUBSCRIPTION_ERROR, NOT_CONFIGURED
|
|
1627
|
+
|
|
1628
|
+
HEADERS,
|
|
1629
|
+
// { ENVIRONMENT: "X-Ironflow-Environment" }
|
|
1630
|
+
|
|
1631
|
+
WS_MESSAGE_TYPES,
|
|
1632
|
+
// { SUBSCRIBE, UNSUBSCRIBE, ACK, EVENT, SUBSCRIPTION_RESULT,
|
|
1633
|
+
// SUBSCRIPTION_ERROR, ERROR }
|
|
1634
|
+
|
|
1635
|
+
HTTP_HEADERS,
|
|
1636
|
+
// { CONTENT_TYPE_JSON: "application/json" }
|
|
1637
|
+
|
|
1638
|
+
JSON_HEADERS,
|
|
1639
|
+
// { "Content-Type": "application/json" }
|
|
1640
|
+
|
|
1641
|
+
getServerUrl, // () => string (reads IRONFLOW_SERVER_URL or returns default)
|
|
1642
|
+
getWebSocketUrl, // (serverUrl?) => string (converts http->ws, appends /ws)
|
|
87
1643
|
} from '@ironflow/core';
|
|
88
1644
|
```
|
|
89
1645
|
|
|
90
|
-
###
|
|
1646
|
+
### Environment Variables
|
|
1647
|
+
|
|
1648
|
+
| Variable | Purpose |
|
|
1649
|
+
|---|---|
|
|
1650
|
+
| `IRONFLOW_SERVER_URL` | Server URL (default: `http://localhost:9123`) |
|
|
1651
|
+
| `IRONFLOW_SIGNING_KEY` | Webhook signature verification key |
|
|
1652
|
+
| `IRONFLOW_API_KEY` | API key for authenticated requests |
|
|
1653
|
+
| `IRONFLOW_LOG_LEVEL` | Log level: `debug`, `info`, `warn`, `error`, `silent` |
|
|
1654
|
+
|
|
1655
|
+
---
|
|
1656
|
+
|
|
1657
|
+
## Utilities
|
|
91
1658
|
|
|
92
1659
|
```typescript
|
|
93
1660
|
import {
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
StepError,
|
|
97
|
-
NonRetryableError,
|
|
98
|
-
TimeoutError,
|
|
99
|
-
ValidationError,
|
|
100
|
-
FunctionNotFoundError,
|
|
101
|
-
RunNotFoundError,
|
|
102
|
-
isRetryable,
|
|
103
|
-
isIronflowError,
|
|
104
|
-
toError,
|
|
1661
|
+
parseDuration, calculateBackoff, sleep, createDeferred,
|
|
1662
|
+
generateId, safeJsonParse, isObject, deepMerge,
|
|
105
1663
|
} from '@ironflow/core';
|
|
1664
|
+
```
|
|
1665
|
+
|
|
1666
|
+
### parseDuration
|
|
1667
|
+
|
|
1668
|
+
Convert a duration string to milliseconds.
|
|
1669
|
+
|
|
1670
|
+
```typescript
|
|
1671
|
+
parseDuration('30s'); // 30000
|
|
1672
|
+
parseDuration('5m'); // 300000
|
|
1673
|
+
parseDuration('2h'); // 7200000
|
|
1674
|
+
parseDuration('7d'); // 604800000
|
|
1675
|
+
parseDuration('500ms'); // 500
|
|
1676
|
+
parseDuration(1000); // 1000 (passthrough)
|
|
1677
|
+
// Throws Error for invalid format
|
|
1678
|
+
```
|
|
1679
|
+
|
|
1680
|
+
### calculateBackoff
|
|
1681
|
+
|
|
1682
|
+
```typescript
|
|
1683
|
+
calculateBackoff(
|
|
1684
|
+
attempt: number, // 1-based attempt number
|
|
1685
|
+
initialDelay: number, // initial delay in ms
|
|
1686
|
+
maxDelay: number, // maximum delay cap in ms
|
|
1687
|
+
multiplier?: number // default: 2
|
|
1688
|
+
): number;
|
|
1689
|
+
|
|
1690
|
+
calculateBackoff(1, 1000, 30000); // 1000
|
|
1691
|
+
calculateBackoff(2, 1000, 30000); // 2000
|
|
1692
|
+
calculateBackoff(3, 1000, 30000); // 4000
|
|
1693
|
+
calculateBackoff(10, 1000, 30000); // 30000 (capped)
|
|
1694
|
+
```
|
|
106
1695
|
|
|
107
|
-
|
|
108
|
-
|
|
1696
|
+
### sleep
|
|
1697
|
+
|
|
1698
|
+
```typescript
|
|
1699
|
+
await sleep(1000); // sleep 1 second
|
|
1700
|
+
```
|
|
1701
|
+
|
|
1702
|
+
### createDeferred
|
|
1703
|
+
|
|
1704
|
+
Create a promise with externally accessible resolve/reject.
|
|
1705
|
+
|
|
1706
|
+
```typescript
|
|
1707
|
+
interface Deferred<T> {
|
|
1708
|
+
promise: Promise<T>;
|
|
1709
|
+
resolve: (value: T) => void;
|
|
1710
|
+
reject: (error: Error) => void;
|
|
109
1711
|
}
|
|
1712
|
+
|
|
1713
|
+
const deferred = createDeferred<string>();
|
|
1714
|
+
// later:
|
|
1715
|
+
deferred.resolve('done');
|
|
1716
|
+
// or:
|
|
1717
|
+
deferred.reject(new Error('failed'));
|
|
1718
|
+
// consumer:
|
|
1719
|
+
const result = await deferred.promise;
|
|
1720
|
+
```
|
|
1721
|
+
|
|
1722
|
+
### generateId
|
|
1723
|
+
|
|
1724
|
+
```typescript
|
|
1725
|
+
const id = generateId(); // e.g., "m1abc23-x4y5z6"
|
|
1726
|
+
```
|
|
1727
|
+
|
|
1728
|
+
### safeJsonParse
|
|
1729
|
+
|
|
1730
|
+
Returns `undefined` on parse failure instead of throwing.
|
|
1731
|
+
|
|
1732
|
+
```typescript
|
|
1733
|
+
safeJsonParse('{"a":1}'); // { a: 1 }
|
|
1734
|
+
safeJsonParse('invalid'); // undefined
|
|
1735
|
+
```
|
|
1736
|
+
|
|
1737
|
+
### isObject
|
|
1738
|
+
|
|
1739
|
+
Type guard for non-null, non-array objects.
|
|
1740
|
+
|
|
1741
|
+
```typescript
|
|
1742
|
+
isObject({}); // true
|
|
1743
|
+
isObject(null); // false
|
|
1744
|
+
isObject([]); // false
|
|
1745
|
+
isObject('string'); // false
|
|
1746
|
+
```
|
|
1747
|
+
|
|
1748
|
+
### deepMerge
|
|
1749
|
+
|
|
1750
|
+
Recursively merge two objects. Source values overwrite target values; nested objects are merged.
|
|
1751
|
+
|
|
1752
|
+
```typescript
|
|
1753
|
+
deepMerge({ a: 1, b: { c: 2 } }, { b: { d: 3 } });
|
|
1754
|
+
// { a: 1, b: { c: 2, d: 3 } }
|
|
110
1755
|
```
|
|
111
1756
|
|
|
112
1757
|
### Pattern Helpers
|
|
113
1758
|
|
|
114
|
-
Pre-built
|
|
1759
|
+
Pre-built subscription patterns using NATS-style wildcards (`*` = single token, `>` = one or more tokens at end).
|
|
115
1760
|
|
|
116
1761
|
```typescript
|
|
117
1762
|
import { patterns } from '@ironflow/core';
|
|
118
1763
|
|
|
119
|
-
|
|
120
|
-
patterns.
|
|
121
|
-
patterns.
|
|
122
|
-
patterns.
|
|
123
|
-
patterns.
|
|
124
|
-
patterns.
|
|
125
|
-
patterns.
|
|
126
|
-
|
|
1764
|
+
// System events
|
|
1765
|
+
patterns.allRuns(); // "system.run.>"
|
|
1766
|
+
patterns.run('run_abc'); // "system.run.run_abc.>"
|
|
1767
|
+
patterns.runLifecycle('run_abc');// "system.run.run_abc.*"
|
|
1768
|
+
patterns.runSteps('run_abc'); // "system.run.run_abc.step.>"
|
|
1769
|
+
patterns.allFunctions(); // "system.function.>"
|
|
1770
|
+
patterns.function('my-fn'); // "system.function.my-fn.>"
|
|
1771
|
+
|
|
1772
|
+
// User events
|
|
1773
|
+
patterns.userEvent('order.*'); // "events:order.*"
|
|
1774
|
+
patterns.allUserEvents(); // "events:>"
|
|
1775
|
+
|
|
1776
|
+
// Developer pub/sub topics
|
|
1777
|
+
patterns.topic('notifications'); // "topic:notifications"
|
|
1778
|
+
patterns.allTopics(); // "topic:>"
|
|
1779
|
+
|
|
1780
|
+
// Secrets
|
|
1781
|
+
patterns.allSecrets(); // "system.secret.*"
|
|
1782
|
+
patterns.secret('db-password'); // "system.secret.db-password.*"
|
|
1783
|
+
patterns.secretAction('updated');// "system.secret.*.updated"
|
|
127
1784
|
```
|
|
128
1785
|
|
|
129
|
-
|
|
1786
|
+
---
|
|
1787
|
+
|
|
1788
|
+
## Upcasters
|
|
1789
|
+
|
|
1790
|
+
Upcasters transform event data between schema versions. They run SDK-side when reading events.
|
|
130
1791
|
|
|
131
|
-
|
|
1792
|
+
### Low-Level: UpcasterRegistry
|
|
132
1793
|
|
|
133
1794
|
```typescript
|
|
134
|
-
import { createUpcasterRegistry,
|
|
1795
|
+
import { createUpcasterRegistry, type UpcasterFn } from '@ironflow/core';
|
|
1796
|
+
|
|
1797
|
+
type UpcasterFn = (data: unknown) => unknown;
|
|
135
1798
|
|
|
136
|
-
// Low-level: register individual upcasters
|
|
137
1799
|
const registry = createUpcasterRegistry();
|
|
138
|
-
|
|
1800
|
+
|
|
1801
|
+
// Register: eventName, fromVersion, toVersion, transform function
|
|
1802
|
+
registry.register('order.placed', 1, 2, (data: any) => ({
|
|
139
1803
|
...data,
|
|
140
1804
|
currency: data.currency ?? 'USD',
|
|
141
1805
|
}));
|
|
142
|
-
|
|
1806
|
+
registry.register('order.placed', 2, 3, (data: any) => ({
|
|
1807
|
+
...data,
|
|
1808
|
+
items: data.items ?? [],
|
|
1809
|
+
}));
|
|
1810
|
+
|
|
1811
|
+
// Upcast through the chain: v1 -> v2 -> v3
|
|
1812
|
+
const migrated = registry.upcast('order.placed', oldData, 1, 3);
|
|
1813
|
+
|
|
1814
|
+
// Get the latest registered version
|
|
1815
|
+
registry.getLatestVersion('order.placed'); // 3
|
|
1816
|
+
```
|
|
1817
|
+
|
|
1818
|
+
The chain must be complete. If v2->v3 is missing, upcasting from v1->v3 throws.
|
|
143
1819
|
|
|
144
|
-
|
|
145
|
-
|
|
1820
|
+
### High-Level: defineEvent and EventDefinitionRegistry
|
|
1821
|
+
|
|
1822
|
+
```typescript
|
|
1823
|
+
import { defineEvent, createEventDefinitionRegistry } from '@ironflow/core';
|
|
1824
|
+
import type { EventDefinition, EventDefinitionOptions, EventDefinitionRegistry } from '@ironflow/core';
|
|
1825
|
+
|
|
1826
|
+
interface EventDefinitionOptions {
|
|
1827
|
+
name: string;
|
|
1828
|
+
version: number;
|
|
1829
|
+
upcast?: UpcasterFn; // transforms from version-1 to this version
|
|
1830
|
+
}
|
|
1831
|
+
|
|
1832
|
+
interface EventDefinition {
|
|
1833
|
+
name: string;
|
|
1834
|
+
version: number;
|
|
1835
|
+
upcast?: UpcasterFn;
|
|
1836
|
+
}
|
|
1837
|
+
|
|
1838
|
+
// Define event versions
|
|
1839
|
+
const OrderPlacedV2 = defineEvent({
|
|
146
1840
|
name: 'order.placed',
|
|
147
1841
|
version: 2,
|
|
148
|
-
upcast: (data) => ({ ...data, currency: data.currency ?? 'USD' }),
|
|
1842
|
+
upcast: (data: any) => ({ ...data, currency: data.currency ?? 'USD' }),
|
|
1843
|
+
});
|
|
1844
|
+
|
|
1845
|
+
const OrderPlacedV3 = defineEvent({
|
|
1846
|
+
name: 'order.placed',
|
|
1847
|
+
version: 3,
|
|
1848
|
+
upcast: (data: any) => ({ ...data, items: data.items ?? [] }),
|
|
149
1849
|
});
|
|
150
1850
|
|
|
1851
|
+
// Register all versions
|
|
151
1852
|
const eventRegistry = createEventDefinitionRegistry();
|
|
152
|
-
eventRegistry.register(
|
|
1853
|
+
eventRegistry.register(OrderPlacedV2);
|
|
1854
|
+
eventRegistry.register(OrderPlacedV3);
|
|
1855
|
+
|
|
1856
|
+
// Auto-upcast from any version to latest
|
|
1857
|
+
const latest = eventRegistry.upcastEvent('order.placed', oldData, 1);
|
|
1858
|
+
|
|
1859
|
+
// Query latest version
|
|
1860
|
+
eventRegistry.getLatestVersion('order.placed'); // 3
|
|
153
1861
|
```
|
|
154
1862
|
|
|
155
|
-
|
|
1863
|
+
---
|
|
1864
|
+
|
|
1865
|
+
## Logger
|
|
156
1866
|
|
|
157
1867
|
```typescript
|
|
158
|
-
import {
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
}
|
|
1868
|
+
import { createLogger, createNoopLogger } from '@ironflow/core';
|
|
1869
|
+
import type { LogLevel, LoggerConfig, Logger } from '@ironflow/core';
|
|
1870
|
+
|
|
1871
|
+
type LogLevel = "debug" | "info" | "warn" | "error" | "silent";
|
|
1872
|
+
|
|
1873
|
+
interface LoggerConfig {
|
|
1874
|
+
/** Minimum log level to output (default: "info", or IRONFLOW_LOG_LEVEL env var) */
|
|
1875
|
+
level?: LogLevel;
|
|
1876
|
+
/** Prefix for log messages (default: "[ironflow]") */
|
|
1877
|
+
prefix?: string;
|
|
1878
|
+
}
|
|
1879
|
+
|
|
1880
|
+
interface Logger {
|
|
1881
|
+
debug(message: string, data?: Record<string, unknown>): void;
|
|
1882
|
+
info(message: string, data?: Record<string, unknown>): void;
|
|
1883
|
+
warn(message: string, data?: Record<string, unknown>): void;
|
|
1884
|
+
error(message: string, data?: Record<string, unknown>): void;
|
|
1885
|
+
}
|
|
1886
|
+
```
|
|
1887
|
+
|
|
1888
|
+
Usage:
|
|
1889
|
+
|
|
1890
|
+
```typescript
|
|
1891
|
+
const logger = createLogger({ prefix: '[myapp]', level: 'debug' });
|
|
1892
|
+
logger.info('Processing order', { orderId: '123' });
|
|
1893
|
+
// Output: [myapp] Processing order {"orderId":"123"}
|
|
169
1894
|
|
|
170
|
-
|
|
171
|
-
const
|
|
172
|
-
const delay = calculateBackoff(3, 1000); // Exponential backoff
|
|
173
|
-
const logger = createLogger({ prefix: '[myapp]' });
|
|
1895
|
+
// Silent logger for tests
|
|
1896
|
+
const noop = createNoopLogger();
|
|
174
1897
|
```
|
|
175
1898
|
|
|
176
|
-
|
|
1899
|
+
The default log level reads from `IRONFLOW_LOG_LEVEL` environment variable, falling back to `"info"`.
|
|
1900
|
+
|
|
1901
|
+
---
|
|
1902
|
+
|
|
1903
|
+
## SecretsClient
|
|
1904
|
+
|
|
1905
|
+
Read-only interface for accessing resolved secrets inside function handlers. Secrets are declared in `FunctionConfig.secrets` and resolved by the engine at execution time.
|
|
1906
|
+
|
|
1907
|
+
```typescript
|
|
1908
|
+
interface SecretsClient {
|
|
1909
|
+
/** Get a secret value by name. Throws if not found. */
|
|
1910
|
+
get(name: string): string;
|
|
1911
|
+
/** Check if a secret exists. */
|
|
1912
|
+
has(name: string): boolean;
|
|
1913
|
+
}
|
|
1914
|
+
```
|
|
1915
|
+
|
|
1916
|
+
Usage inside a function handler:
|
|
1917
|
+
|
|
1918
|
+
```typescript
|
|
1919
|
+
const myFn = createFunction({
|
|
1920
|
+
id: 'charge-card',
|
|
1921
|
+
triggers: [{ event: 'order.placed' }],
|
|
1922
|
+
secrets: ['STRIPE_KEY'],
|
|
1923
|
+
}, async ({ secrets, step }) => {
|
|
1924
|
+
const stripeKey = secrets.get('STRIPE_KEY');
|
|
1925
|
+
// ...
|
|
1926
|
+
});
|
|
1927
|
+
```
|
|
1928
|
+
|
|
1929
|
+
---
|
|
1930
|
+
|
|
1931
|
+
## Sub-Path Exports
|
|
1932
|
+
|
|
1933
|
+
The package provides additional entry points for selective imports:
|
|
1934
|
+
|
|
1935
|
+
| Path | What it exports |
|
|
1936
|
+
|---|---|
|
|
1937
|
+
| `@ironflow/core` | Everything (types, schemas, errors, constants, utils, protocol, patterns) |
|
|
1938
|
+
| `@ironflow/core/schemas` | Zod schemas and validation helpers only |
|
|
1939
|
+
| `@ironflow/core/protocol` | Protocol types and pattern helpers only |
|
|
1940
|
+
| `@ironflow/core/gen` | Generated protobuf/ConnectRPC code (requires optional deps) |
|
|
177
1941
|
|
|
178
|
-
|
|
1942
|
+
---
|
|
179
1943
|
|
|
180
1944
|
## License
|
|
181
1945
|
|