@coji/durably 0.3.0 → 0.6.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 +15 -44
- package/dist/index.d.ts +281 -22
- package/dist/index.js +683 -63
- package/dist/index.js.map +1 -1
- package/docs/llms.md +151 -22
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -4,65 +4,36 @@ Step-oriented resumable batch execution for Node.js and browsers using SQLite.
|
|
|
4
4
|
|
|
5
5
|
**[Documentation](https://coji.github.io/durably/)** | **[GitHub](https://github.com/coji/durably)** | **[Live Demo](https://durably-demo.vercel.app)**
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
- Resumable batch processing with step-level persistence
|
|
10
|
-
- Works in both Node.js and browsers
|
|
11
|
-
- Uses SQLite for state management (better-sqlite3/libsql for Node.js, SQLite WASM for browsers)
|
|
12
|
-
- Minimal dependencies - just Kysely and Zod as peer dependencies
|
|
13
|
-
- Event system for monitoring and extensibility
|
|
14
|
-
- Type-safe input/output with Zod schemas
|
|
7
|
+
> **Note:** This package is ESM-only. CommonJS is not supported.
|
|
15
8
|
|
|
16
9
|
## Installation
|
|
17
10
|
|
|
18
11
|
```bash
|
|
19
|
-
# Node.js with better-sqlite3
|
|
20
12
|
npm install @coji/durably kysely zod better-sqlite3
|
|
21
|
-
|
|
22
|
-
# Node.js with libsql
|
|
23
|
-
npm install @coji/durably kysely zod @libsql/client @libsql/kysely-libsql
|
|
24
|
-
|
|
25
|
-
# Browser with SQLocal
|
|
26
|
-
npm install @coji/durably kysely zod sqlocal
|
|
27
13
|
```
|
|
28
14
|
|
|
29
|
-
|
|
15
|
+
See the [Getting Started Guide](https://coji.github.io/durably/guide/getting-started) for other SQLite backends (libsql, SQLocal for browsers).
|
|
16
|
+
|
|
17
|
+
## Quick Start
|
|
30
18
|
|
|
31
19
|
```ts
|
|
32
|
-
import { createDurably } from '@coji/durably'
|
|
33
|
-
import SQLite from 'better-sqlite3'
|
|
34
|
-
import { SqliteDialect } from 'kysely'
|
|
20
|
+
import { createDurably, defineJob } from '@coji/durably'
|
|
35
21
|
import { z } from 'zod'
|
|
36
22
|
|
|
37
|
-
const
|
|
38
|
-
|
|
39
|
-
})
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
const syncUsers = durably.defineJob(
|
|
44
|
-
{
|
|
45
|
-
name: 'sync-users',
|
|
46
|
-
input: z.object({ orgId: z.string() }),
|
|
47
|
-
output: z.object({ syncedCount: z.number() }),
|
|
48
|
-
},
|
|
49
|
-
async (step, payload) => {
|
|
50
|
-
const users = await step.run('fetch-users', async () => {
|
|
51
|
-
return api.fetchUsers(payload.orgId)
|
|
52
|
-
})
|
|
53
|
-
|
|
54
|
-
await step.run('save-to-db', async () => {
|
|
55
|
-
await db.upsertUsers(users)
|
|
23
|
+
const myJob = defineJob({
|
|
24
|
+
name: 'my-job',
|
|
25
|
+
input: z.object({ id: z.string() }),
|
|
26
|
+
run: async (step, payload) => {
|
|
27
|
+
await step.run('step-1', async () => {
|
|
28
|
+
/* ... */
|
|
56
29
|
})
|
|
57
|
-
|
|
58
|
-
return { syncedCount: users.length }
|
|
59
30
|
},
|
|
60
|
-
)
|
|
31
|
+
})
|
|
61
32
|
|
|
62
|
-
|
|
63
|
-
durably.start()
|
|
33
|
+
const durably = createDurably({ dialect }).register({ myJob })
|
|
64
34
|
|
|
65
|
-
await
|
|
35
|
+
await durably.init() // migrate + start
|
|
36
|
+
await durably.jobs.myJob.trigger({ id: '123' })
|
|
66
37
|
```
|
|
67
38
|
|
|
68
39
|
## Documentation
|
package/dist/index.d.ts
CHANGED
|
@@ -9,6 +9,15 @@ interface BaseEvent {
|
|
|
9
9
|
timestamp: string;
|
|
10
10
|
sequence: number;
|
|
11
11
|
}
|
|
12
|
+
/**
|
|
13
|
+
* Run trigger event (emitted when a job is triggered, before worker picks it up)
|
|
14
|
+
*/
|
|
15
|
+
interface RunTriggerEvent extends BaseEvent {
|
|
16
|
+
type: 'run:trigger';
|
|
17
|
+
runId: string;
|
|
18
|
+
jobName: string;
|
|
19
|
+
payload: unknown;
|
|
20
|
+
}
|
|
12
21
|
/**
|
|
13
22
|
* Run start event
|
|
14
23
|
*/
|
|
@@ -38,6 +47,35 @@ interface RunFailEvent extends BaseEvent {
|
|
|
38
47
|
error: string;
|
|
39
48
|
failedStepName: string;
|
|
40
49
|
}
|
|
50
|
+
/**
|
|
51
|
+
* Run cancel event
|
|
52
|
+
*/
|
|
53
|
+
interface RunCancelEvent extends BaseEvent {
|
|
54
|
+
type: 'run:cancel';
|
|
55
|
+
runId: string;
|
|
56
|
+
jobName: string;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Run retry event (emitted when a failed run is retried)
|
|
60
|
+
*/
|
|
61
|
+
interface RunRetryEvent extends BaseEvent {
|
|
62
|
+
type: 'run:retry';
|
|
63
|
+
runId: string;
|
|
64
|
+
jobName: string;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Run progress event
|
|
68
|
+
*/
|
|
69
|
+
interface RunProgressEvent extends BaseEvent {
|
|
70
|
+
type: 'run:progress';
|
|
71
|
+
runId: string;
|
|
72
|
+
jobName: string;
|
|
73
|
+
progress: {
|
|
74
|
+
current: number;
|
|
75
|
+
total?: number;
|
|
76
|
+
message?: string;
|
|
77
|
+
};
|
|
78
|
+
}
|
|
41
79
|
/**
|
|
42
80
|
* Step start event
|
|
43
81
|
*/
|
|
@@ -94,7 +132,7 @@ interface WorkerErrorEvent extends BaseEvent {
|
|
|
94
132
|
/**
|
|
95
133
|
* All event types as discriminated union
|
|
96
134
|
*/
|
|
97
|
-
type DurablyEvent = RunStartEvent | RunCompleteEvent | RunFailEvent | StepStartEvent | StepCompleteEvent | StepFailEvent | LogWriteEvent | WorkerErrorEvent;
|
|
135
|
+
type DurablyEvent = RunTriggerEvent | RunStartEvent | RunCompleteEvent | RunFailEvent | RunCancelEvent | RunRetryEvent | RunProgressEvent | StepStartEvent | StepCompleteEvent | StepFailEvent | LogWriteEvent | WorkerErrorEvent;
|
|
98
136
|
/**
|
|
99
137
|
* Event types for type-safe event names
|
|
100
138
|
*/
|
|
@@ -112,7 +150,7 @@ type EventInput<T extends EventType> = Omit<EventByType<T>, 'timestamp' | 'seque
|
|
|
112
150
|
/**
|
|
113
151
|
* All possible event inputs as a union (properly distributed)
|
|
114
152
|
*/
|
|
115
|
-
type AnyEventInput = EventInput<'run:start'> | EventInput<'run:complete'> | EventInput<'run:fail'> | EventInput<'step:start'> | EventInput<'step:complete'> | EventInput<'step:fail'> | EventInput<'log:write'> | EventInput<'worker:error'>;
|
|
153
|
+
type AnyEventInput = EventInput<'run:trigger'> | EventInput<'run:start'> | EventInput<'run:complete'> | EventInput<'run:fail'> | EventInput<'run:cancel'> | EventInput<'run:retry'> | EventInput<'run:progress'> | EventInput<'step:start'> | EventInput<'step:complete'> | EventInput<'step:fail'> | EventInput<'log:write'> | EventInput<'worker:error'>;
|
|
116
154
|
/**
|
|
117
155
|
* Event listener function
|
|
118
156
|
*/
|
|
@@ -195,6 +233,7 @@ interface Run {
|
|
|
195
233
|
idempotencyKey: string | null;
|
|
196
234
|
concurrencyKey: string | null;
|
|
197
235
|
currentStepIndex: number;
|
|
236
|
+
stepCount: number;
|
|
198
237
|
progress: {
|
|
199
238
|
current: number;
|
|
200
239
|
total?: number;
|
|
@@ -323,18 +362,6 @@ interface StepContext {
|
|
|
323
362
|
error(message: string, data?: unknown): void;
|
|
324
363
|
};
|
|
325
364
|
}
|
|
326
|
-
/**
|
|
327
|
-
* Job function type
|
|
328
|
-
*/
|
|
329
|
-
type JobFunction<TInput, TOutput> = (step: StepContext, payload: TInput) => Promise<TOutput>;
|
|
330
|
-
/**
|
|
331
|
-
* Job definition options
|
|
332
|
-
*/
|
|
333
|
-
interface JobDefinition<TName extends string, TInputSchema extends z.ZodType, TOutputSchema extends z.ZodType | undefined> {
|
|
334
|
-
name: TName;
|
|
335
|
-
input: TInputSchema;
|
|
336
|
-
output?: TOutputSchema;
|
|
337
|
-
}
|
|
338
365
|
/**
|
|
339
366
|
* Trigger options
|
|
340
367
|
*/
|
|
@@ -348,8 +375,12 @@ interface TriggerOptions {
|
|
|
348
375
|
* Run filter options
|
|
349
376
|
*/
|
|
350
377
|
interface RunFilter {
|
|
351
|
-
status?: 'pending' | 'running' | 'completed' | 'failed';
|
|
378
|
+
status?: 'pending' | 'running' | 'completed' | 'failed' | 'cancelled';
|
|
352
379
|
jobName?: string;
|
|
380
|
+
/** Maximum number of runs to return */
|
|
381
|
+
limit?: number;
|
|
382
|
+
/** Number of runs to skip (for pagination) */
|
|
383
|
+
offset?: number;
|
|
353
384
|
}
|
|
354
385
|
/**
|
|
355
386
|
* Typed run with output type
|
|
@@ -400,6 +431,66 @@ interface JobHandle<TName extends string, TInput, TOutput> {
|
|
|
400
431
|
getRuns(filter?: Omit<RunFilter, 'jobName'>): Promise<TypedRun<TOutput>[]>;
|
|
401
432
|
}
|
|
402
433
|
|
|
434
|
+
/**
|
|
435
|
+
* Job run function type
|
|
436
|
+
*/
|
|
437
|
+
type JobRunFunction<TInput, TOutput> = (step: StepContext, payload: TInput) => Promise<TOutput>;
|
|
438
|
+
/**
|
|
439
|
+
* Job definition - a standalone description of a job
|
|
440
|
+
* This is the result of calling defineJob() and can be passed to durably.register()
|
|
441
|
+
*/
|
|
442
|
+
interface JobDefinition<TName extends string, TInput, TOutput> {
|
|
443
|
+
readonly name: TName;
|
|
444
|
+
readonly input: z.ZodType<TInput>;
|
|
445
|
+
readonly output: z.ZodType<TOutput> | undefined;
|
|
446
|
+
readonly run: JobRunFunction<TInput, TOutput>;
|
|
447
|
+
}
|
|
448
|
+
/**
|
|
449
|
+
* Extract input type from a JobDefinition
|
|
450
|
+
* @example
|
|
451
|
+
* ```ts
|
|
452
|
+
* type Input = JobInput<typeof myJob> // { userId: string }
|
|
453
|
+
* ```
|
|
454
|
+
*/
|
|
455
|
+
type JobInput<T> = T extends JobDefinition<string, infer TInput, unknown> ? TInput : never;
|
|
456
|
+
/**
|
|
457
|
+
* Extract output type from a JobDefinition
|
|
458
|
+
* @example
|
|
459
|
+
* ```ts
|
|
460
|
+
* type Output = JobOutput<typeof myJob> // { count: number }
|
|
461
|
+
* ```
|
|
462
|
+
*/
|
|
463
|
+
type JobOutput<T> = T extends JobDefinition<string, unknown, infer TOutput> ? TOutput : never;
|
|
464
|
+
/**
|
|
465
|
+
* Configuration for defining a job
|
|
466
|
+
*/
|
|
467
|
+
interface DefineJobConfig<TName extends string, TInputSchema extends z.ZodType, TOutputSchema extends z.ZodType | undefined> {
|
|
468
|
+
name: TName;
|
|
469
|
+
input: TInputSchema;
|
|
470
|
+
output?: TOutputSchema;
|
|
471
|
+
run: JobRunFunction<z.infer<TInputSchema>, TOutputSchema extends z.ZodType ? z.infer<TOutputSchema> : void>;
|
|
472
|
+
}
|
|
473
|
+
/**
|
|
474
|
+
* Define a job - creates a JobDefinition that can be registered with durably.register()
|
|
475
|
+
*
|
|
476
|
+
* @example
|
|
477
|
+
* ```ts
|
|
478
|
+
* import { defineJob } from '@coji/durably'
|
|
479
|
+
* import { z } from 'zod'
|
|
480
|
+
*
|
|
481
|
+
* export const syncUsers = defineJob({
|
|
482
|
+
* name: 'sync-users',
|
|
483
|
+
* input: z.object({ orgId: z.string() }),
|
|
484
|
+
* output: z.object({ syncedCount: z.number() }),
|
|
485
|
+
* run: async (step, payload) => {
|
|
486
|
+
* const users = await step.run('fetch-users', () => fetchUsers(payload.orgId))
|
|
487
|
+
* return { syncedCount: users.length }
|
|
488
|
+
* },
|
|
489
|
+
* })
|
|
490
|
+
* ```
|
|
491
|
+
*/
|
|
492
|
+
declare function defineJob<TName extends string, TInputSchema extends z.ZodType, TOutputSchema extends z.ZodType | undefined = undefined>(config: DefineJobConfig<TName, TInputSchema, TOutputSchema>): JobDefinition<TName, z.infer<TInputSchema>, TOutputSchema extends z.ZodType ? z.infer<TOutputSchema> : void>;
|
|
493
|
+
|
|
403
494
|
/**
|
|
404
495
|
* Options for creating a Durably instance
|
|
405
496
|
*/
|
|
@@ -414,12 +505,33 @@ interface DurablyOptions {
|
|
|
414
505
|
*/
|
|
415
506
|
interface DurablyPlugin {
|
|
416
507
|
name: string;
|
|
417
|
-
install(durably: Durably): void;
|
|
508
|
+
install(durably: Durably<any>): void;
|
|
418
509
|
}
|
|
419
510
|
/**
|
|
420
|
-
*
|
|
511
|
+
* Helper type to transform JobDefinition record to JobHandle record
|
|
512
|
+
*/
|
|
513
|
+
type TransformToHandles<TJobs extends Record<string, JobDefinition<string, unknown, unknown>>> = {
|
|
514
|
+
[K in keyof TJobs]: TJobs[K] extends JobDefinition<infer TName, infer TInput, infer TOutput> ? JobHandle<TName & string, TInput, TOutput> : never;
|
|
515
|
+
};
|
|
516
|
+
/**
|
|
517
|
+
* Durably instance with type-safe jobs
|
|
421
518
|
*/
|
|
422
|
-
interface Durably {
|
|
519
|
+
interface Durably<TJobs extends Record<string, JobHandle<string, unknown, unknown>> = Record<string, never>> {
|
|
520
|
+
/**
|
|
521
|
+
* Registered job handles (type-safe)
|
|
522
|
+
*/
|
|
523
|
+
readonly jobs: TJobs;
|
|
524
|
+
/**
|
|
525
|
+
* Initialize Durably: run migrations and start the worker
|
|
526
|
+
* This is the recommended way to start Durably.
|
|
527
|
+
* Equivalent to calling migrate() then start().
|
|
528
|
+
* @example
|
|
529
|
+
* ```ts
|
|
530
|
+
* const durably = createDurably({ dialect }).register({ ... })
|
|
531
|
+
* await durably.init()
|
|
532
|
+
* ```
|
|
533
|
+
*/
|
|
534
|
+
init(): Promise<void>;
|
|
423
535
|
/**
|
|
424
536
|
* Run database migrations
|
|
425
537
|
* This is idempotent and safe to call multiple times
|
|
@@ -448,9 +560,19 @@ interface Durably {
|
|
|
448
560
|
*/
|
|
449
561
|
onError(handler: ErrorHandler): void;
|
|
450
562
|
/**
|
|
451
|
-
*
|
|
563
|
+
* Register job definitions and return a new Durably instance with type-safe jobs
|
|
564
|
+
* @example
|
|
565
|
+
* ```ts
|
|
566
|
+
* const durably = createDurably({ dialect })
|
|
567
|
+
* .register({
|
|
568
|
+
* importCsv: importCsvJob,
|
|
569
|
+
* syncUsers: syncUsersJob,
|
|
570
|
+
* })
|
|
571
|
+
* await durably.migrate()
|
|
572
|
+
* // Usage: durably.jobs.importCsv.trigger({ rows: [...] })
|
|
573
|
+
* ```
|
|
452
574
|
*/
|
|
453
|
-
|
|
575
|
+
register<TNewJobs extends Record<string, JobDefinition<string, any, any>>>(jobDefs: TNewJobs): Durably<TJobs & TransformToHandles<TNewJobs>>;
|
|
454
576
|
/**
|
|
455
577
|
* Start the worker polling loop
|
|
456
578
|
*/
|
|
@@ -486,11 +608,21 @@ interface Durably {
|
|
|
486
608
|
* Register a plugin
|
|
487
609
|
*/
|
|
488
610
|
use(plugin: DurablyPlugin): void;
|
|
611
|
+
/**
|
|
612
|
+
* Get a registered job handle by name
|
|
613
|
+
* Returns undefined if job is not registered
|
|
614
|
+
*/
|
|
615
|
+
getJob<TName extends string = string>(name: TName): JobHandle<TName, Record<string, unknown>, unknown> | undefined;
|
|
616
|
+
/**
|
|
617
|
+
* Subscribe to events for a specific run
|
|
618
|
+
* Returns a ReadableStream that can be used for SSE
|
|
619
|
+
*/
|
|
620
|
+
subscribe(runId: string): ReadableStream<DurablyEvent>;
|
|
489
621
|
}
|
|
490
622
|
/**
|
|
491
623
|
* Create a Durably instance
|
|
492
624
|
*/
|
|
493
|
-
declare function createDurably(options: DurablyOptions): Durably
|
|
625
|
+
declare function createDurably(options: DurablyOptions): Durably<Record<string, never>>;
|
|
494
626
|
|
|
495
627
|
/**
|
|
496
628
|
* Plugin that persists log events to the database
|
|
@@ -506,4 +638,131 @@ declare class CancelledError extends Error {
|
|
|
506
638
|
constructor(runId: string);
|
|
507
639
|
}
|
|
508
640
|
|
|
509
|
-
|
|
641
|
+
/**
|
|
642
|
+
* Request body for triggering a job
|
|
643
|
+
*/
|
|
644
|
+
interface TriggerRequest {
|
|
645
|
+
jobName: string;
|
|
646
|
+
input: Record<string, unknown>;
|
|
647
|
+
idempotencyKey?: string;
|
|
648
|
+
concurrencyKey?: string;
|
|
649
|
+
}
|
|
650
|
+
/**
|
|
651
|
+
* Response for trigger endpoint
|
|
652
|
+
*/
|
|
653
|
+
interface TriggerResponse {
|
|
654
|
+
runId: string;
|
|
655
|
+
}
|
|
656
|
+
/**
|
|
657
|
+
* Handler interface for HTTP endpoints
|
|
658
|
+
*/
|
|
659
|
+
interface DurablyHandler {
|
|
660
|
+
/**
|
|
661
|
+
* Handle all Durably HTTP requests with automatic routing
|
|
662
|
+
*
|
|
663
|
+
* Routes:
|
|
664
|
+
* - GET {basePath}/subscribe?runId=xxx - SSE stream
|
|
665
|
+
* - GET {basePath}/runs - List runs
|
|
666
|
+
* - GET {basePath}/run?runId=xxx - Get single run
|
|
667
|
+
* - POST {basePath}/trigger - Trigger a job
|
|
668
|
+
* - POST {basePath}/retry?runId=xxx - Retry a failed run
|
|
669
|
+
* - POST {basePath}/cancel?runId=xxx - Cancel a run
|
|
670
|
+
*
|
|
671
|
+
* @param request - The incoming HTTP request
|
|
672
|
+
* @param basePath - The base path to strip from the URL (e.g., '/api/durably')
|
|
673
|
+
* @returns Response or null if route not matched
|
|
674
|
+
*
|
|
675
|
+
* @example
|
|
676
|
+
* ```ts
|
|
677
|
+
* // React Router / Remix
|
|
678
|
+
* export async function loader({ request }) {
|
|
679
|
+
* return durablyHandler.handle(request, '/api/durably')
|
|
680
|
+
* }
|
|
681
|
+
* export async function action({ request }) {
|
|
682
|
+
* return durablyHandler.handle(request, '/api/durably')
|
|
683
|
+
* }
|
|
684
|
+
* ```
|
|
685
|
+
*/
|
|
686
|
+
handle(request: Request, basePath: string): Promise<Response>;
|
|
687
|
+
/**
|
|
688
|
+
* Handle job trigger request
|
|
689
|
+
* Expects POST with JSON body: { jobName, input, idempotencyKey?, concurrencyKey? }
|
|
690
|
+
* Returns JSON: { runId }
|
|
691
|
+
*/
|
|
692
|
+
trigger(request: Request): Promise<Response>;
|
|
693
|
+
/**
|
|
694
|
+
* Handle subscription request
|
|
695
|
+
* Expects GET with query param: runId
|
|
696
|
+
* Returns SSE stream of events
|
|
697
|
+
*/
|
|
698
|
+
subscribe(request: Request): Response;
|
|
699
|
+
/**
|
|
700
|
+
* Handle runs list request
|
|
701
|
+
* Expects GET with optional query params: jobName, status, limit, offset
|
|
702
|
+
* Returns JSON array of runs
|
|
703
|
+
*/
|
|
704
|
+
runs(request: Request): Promise<Response>;
|
|
705
|
+
/**
|
|
706
|
+
* Handle single run request
|
|
707
|
+
* Expects GET with query param: runId
|
|
708
|
+
* Returns JSON run object or 404
|
|
709
|
+
*/
|
|
710
|
+
run(request: Request): Promise<Response>;
|
|
711
|
+
/**
|
|
712
|
+
* Handle retry request
|
|
713
|
+
* Expects POST with query param: runId
|
|
714
|
+
* Returns JSON: { success: true }
|
|
715
|
+
*/
|
|
716
|
+
retry(request: Request): Promise<Response>;
|
|
717
|
+
/**
|
|
718
|
+
* Handle cancel request
|
|
719
|
+
* Expects POST with query param: runId
|
|
720
|
+
* Returns JSON: { success: true }
|
|
721
|
+
*/
|
|
722
|
+
cancel(request: Request): Promise<Response>;
|
|
723
|
+
/**
|
|
724
|
+
* Handle delete request
|
|
725
|
+
* Expects DELETE with query param: runId
|
|
726
|
+
* Returns JSON: { success: true }
|
|
727
|
+
*/
|
|
728
|
+
delete(request: Request): Promise<Response>;
|
|
729
|
+
/**
|
|
730
|
+
* Handle steps request
|
|
731
|
+
* Expects GET with query param: runId
|
|
732
|
+
* Returns JSON array of steps
|
|
733
|
+
*/
|
|
734
|
+
steps(request: Request): Promise<Response>;
|
|
735
|
+
/**
|
|
736
|
+
* Handle runs subscription request
|
|
737
|
+
* Expects GET with optional query param: jobName
|
|
738
|
+
* Returns SSE stream of run update notifications
|
|
739
|
+
*/
|
|
740
|
+
runsSubscribe(request: Request): Response;
|
|
741
|
+
}
|
|
742
|
+
/**
|
|
743
|
+
* Options for createDurablyHandler
|
|
744
|
+
*/
|
|
745
|
+
interface CreateDurablyHandlerOptions {
|
|
746
|
+
/**
|
|
747
|
+
* Called before handling each request.
|
|
748
|
+
* Use this to initialize Durably (migrate, start worker, etc.)
|
|
749
|
+
*
|
|
750
|
+
* @example
|
|
751
|
+
* ```ts
|
|
752
|
+
* const durablyHandler = createDurablyHandler(durably, {
|
|
753
|
+
* onRequest: async () => {
|
|
754
|
+
* await durably.migrate()
|
|
755
|
+
* durably.start()
|
|
756
|
+
* }
|
|
757
|
+
* })
|
|
758
|
+
* ```
|
|
759
|
+
*/
|
|
760
|
+
onRequest?: () => Promise<void> | void;
|
|
761
|
+
}
|
|
762
|
+
/**
|
|
763
|
+
* Create HTTP handlers for Durably
|
|
764
|
+
* Uses Web Standard Request/Response for framework-agnostic usage
|
|
765
|
+
*/
|
|
766
|
+
declare function createDurablyHandler(durably: Durably, options?: CreateDurablyHandlerOptions): DurablyHandler;
|
|
767
|
+
|
|
768
|
+
export { CancelledError, type Database, type Durably, type DurablyEvent, type DurablyHandler, type DurablyOptions, type DurablyPlugin, type ErrorHandler, type EventType, type JobDefinition, type JobHandle, type JobInput, type JobOutput, type Log, type LogWriteEvent, type LogsTable, type Run, type RunCompleteEvent, type RunFailEvent, type RunFilter$1 as RunFilter, type RunProgressEvent, type RunStartEvent, type RunsTable, type SchemaVersionsTable, type Step, type StepCompleteEvent, type StepContext, type StepFailEvent, type StepStartEvent, type StepsTable, type TriggerAndWaitResult, type TriggerRequest, type TriggerResponse, type WorkerErrorEvent, createDurably, createDurablyHandler, defineJob, withLogPersistence };
|