@beignet/core 0.0.1 → 0.0.3
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/CHANGELOG.md +27 -0
- package/README.md +202 -8
- package/dist/application/index.d.ts +93 -9
- package/dist/application/index.d.ts.map +1 -1
- package/dist/application/index.js +11 -11
- package/dist/application/index.js.map +1 -1
- package/dist/client/client.d.ts +73 -12
- package/dist/client/client.d.ts.map +1 -1
- package/dist/client/client.js +37 -12
- package/dist/client/client.js.map +1 -1
- package/dist/client/index.d.ts +12 -0
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +6 -0
- package/dist/client/index.js.map +1 -1
- package/dist/client/types.d.ts +69 -8
- package/dist/client/types.d.ts.map +1 -1
- package/dist/config/index.d.ts +84 -0
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/index.js +36 -0
- package/dist/config/index.js.map +1 -1
- package/dist/contracts/contract-builder.d.ts +49 -22
- package/dist/contracts/contract-builder.d.ts.map +1 -1
- package/dist/contracts/contract-builder.js +48 -21
- package/dist/contracts/contract-builder.js.map +1 -1
- package/dist/contracts/contract-group.d.ts +35 -19
- package/dist/contracts/contract-group.d.ts.map +1 -1
- package/dist/contracts/contract-group.js +35 -19
- package/dist/contracts/contract-group.js.map +1 -1
- package/dist/contracts/contract-like.d.ts +4 -4
- package/dist/contracts/contract-like.d.ts.map +1 -1
- package/dist/contracts/contract-like.js +2 -1
- package/dist/contracts/contract-like.js.map +1 -1
- package/dist/contracts/index.d.ts +28 -0
- package/dist/contracts/index.d.ts.map +1 -1
- package/dist/contracts/index.js +12 -0
- package/dist/contracts/index.js.map +1 -1
- package/dist/contracts/openapi-meta.d.ts +8 -8
- package/dist/contracts/openapi-meta.d.ts.map +1 -1
- package/dist/contracts/path-template.d.ts +27 -0
- package/dist/contracts/path-template.d.ts.map +1 -1
- package/dist/contracts/path-template.js +6 -0
- package/dist/contracts/path-template.js.map +1 -1
- package/dist/contracts/types.d.ts +104 -10
- package/dist/contracts/types.d.ts.map +1 -1
- package/dist/contracts/types.js +15 -0
- package/dist/contracts/types.js.map +1 -1
- package/dist/contracts/utils.d.ts +6 -0
- package/dist/contracts/utils.d.ts.map +1 -1
- package/dist/contracts/utils.js +6 -0
- package/dist/contracts/utils.js.map +1 -1
- package/dist/domain/entity.d.ts +22 -11
- package/dist/domain/entity.d.ts.map +1 -1
- package/dist/domain/entity.js +5 -1
- package/dist/domain/entity.js.map +1 -1
- package/dist/domain/events.d.ts +5 -2
- package/dist/domain/events.d.ts.map +1 -1
- package/dist/domain/events.js +4 -1
- package/dist/domain/events.js.map +1 -1
- package/dist/domain/value-object.d.ts +19 -9
- package/dist/domain/value-object.d.ts.map +1 -1
- package/dist/domain/value-object.js +5 -1
- package/dist/domain/value-object.js.map +1 -1
- package/dist/errors/catalog.d.ts +40 -16
- package/dist/errors/catalog.d.ts.map +1 -1
- package/dist/errors/catalog.js +18 -7
- package/dist/errors/catalog.js.map +1 -1
- package/dist/errors/response.d.ts +16 -4
- package/dist/errors/response.d.ts.map +1 -1
- package/dist/errors/response.js +3 -3
- package/dist/errors/response.js.map +1 -1
- package/dist/errors/validation.d.ts +10 -1
- package/dist/errors/validation.d.ts.map +1 -1
- package/dist/errors/validation.js +3 -0
- package/dist/errors/validation.js.map +1 -1
- package/dist/events/index.d.ts +133 -0
- package/dist/events/index.d.ts.map +1 -1
- package/dist/events/index.js +30 -0
- package/dist/events/index.js.map +1 -1
- package/dist/idempotency/index.d.ts +355 -0
- package/dist/idempotency/index.d.ts.map +1 -0
- package/dist/idempotency/index.js +360 -0
- package/dist/idempotency/index.js.map +1 -0
- package/dist/jobs/index.d.ts +248 -4
- package/dist/jobs/index.d.ts.map +1 -1
- package/dist/jobs/index.js +183 -1
- package/dist/jobs/index.js.map +1 -1
- package/dist/mail/index.d.ts +149 -0
- package/dist/mail/index.d.ts.map +1 -1
- package/dist/mail/index.js +30 -0
- package/dist/mail/index.js.map +1 -1
- package/dist/notifications/index.d.ts +369 -0
- package/dist/notifications/index.d.ts.map +1 -0
- package/dist/notifications/index.js +310 -0
- package/dist/notifications/index.js.map +1 -0
- package/dist/openapi/index.d.ts +132 -16
- package/dist/openapi/index.d.ts.map +1 -1
- package/dist/openapi/index.js +1 -1
- package/dist/openapi/index.js.map +1 -1
- package/dist/outbox/index.d.ts +474 -0
- package/dist/outbox/index.d.ts.map +1 -0
- package/dist/outbox/index.js +538 -0
- package/dist/outbox/index.js.map +1 -0
- package/dist/pagination/index.d.ts +166 -0
- package/dist/pagination/index.d.ts.map +1 -0
- package/dist/pagination/index.js +96 -0
- package/dist/pagination/index.js.map +1 -0
- package/dist/ports/audit.d.ts +271 -0
- package/dist/ports/audit.d.ts.map +1 -1
- package/dist/ports/audit.js +128 -0
- package/dist/ports/audit.js.map +1 -1
- package/dist/ports/auth.d.ts +70 -0
- package/dist/ports/auth.d.ts.map +1 -1
- package/dist/ports/auth.js +30 -0
- package/dist/ports/auth.js.map +1 -1
- package/dist/ports/cache.d.ts +41 -0
- package/dist/ports/cache.d.ts.map +1 -1
- package/dist/ports/cache.js +10 -0
- package/dist/ports/cache.js.map +1 -1
- package/dist/ports/clock.d.ts +38 -0
- package/dist/ports/clock.d.ts.map +1 -1
- package/dist/ports/clock.js +20 -0
- package/dist/ports/clock.js.map +1 -1
- package/dist/ports/id-generator.d.ts +37 -0
- package/dist/ports/id-generator.d.ts.map +1 -1
- package/dist/ports/id-generator.js +22 -0
- package/dist/ports/id-generator.js.map +1 -1
- package/dist/ports/index.d.ts +83 -0
- package/dist/ports/index.d.ts.map +1 -1
- package/dist/ports/index.js +41 -5
- package/dist/ports/index.js.map +1 -1
- package/dist/ports/logger.d.ts +56 -0
- package/dist/ports/logger.d.ts.map +1 -1
- package/dist/ports/logger.js +17 -0
- package/dist/ports/logger.js.map +1 -1
- package/dist/ports/policy.d.ts +132 -0
- package/dist/ports/policy.d.ts.map +1 -1
- package/dist/ports/policy.js +45 -0
- package/dist/ports/policy.js.map +1 -1
- package/dist/ports/rate-limit.d.ts +25 -0
- package/dist/ports/rate-limit.d.ts.map +1 -1
- package/dist/ports/rate-limit.js +10 -0
- package/dist/ports/rate-limit.js.map +1 -1
- package/dist/ports/redaction.d.ts +101 -0
- package/dist/ports/redaction.d.ts.map +1 -1
- package/dist/ports/redaction.js +59 -0
- package/dist/ports/redaction.js.map +1 -1
- package/dist/ports/storage.d.ts +100 -0
- package/dist/ports/storage.d.ts.map +1 -1
- package/dist/ports/storage.js +10 -0
- package/dist/ports/storage.js.map +1 -1
- package/dist/ports/testing.d.ts +47 -0
- package/dist/ports/testing.d.ts.map +1 -1
- package/dist/ports/testing.js +23 -0
- package/dist/ports/testing.js.map +1 -1
- package/dist/ports/unit-of-work.d.ts +60 -3
- package/dist/ports/unit-of-work.d.ts.map +1 -1
- package/dist/ports/unit-of-work.js +11 -2
- package/dist/ports/unit-of-work.js.map +1 -1
- package/dist/providers/instrumentation.d.ts +205 -1
- package/dist/providers/instrumentation.d.ts.map +1 -1
- package/dist/providers/instrumentation.js +14 -0
- package/dist/providers/instrumentation.js.map +1 -1
- package/dist/providers/provider.d.ts +14 -1
- package/dist/providers/provider.d.ts.map +1 -1
- package/dist/providers/provider.js.map +1 -1
- package/dist/schedules/index.d.ts +246 -0
- package/dist/schedules/index.d.ts.map +1 -1
- package/dist/schedules/index.js +27 -0
- package/dist/schedules/index.js.map +1 -1
- package/dist/server/health.d.ts +14 -5
- package/dist/server/health.d.ts.map +1 -1
- package/dist/server/health.js +5 -2
- package/dist/server/health.js.map +1 -1
- package/dist/server/hooks/auth.d.ts +68 -26
- package/dist/server/hooks/auth.d.ts.map +1 -1
- package/dist/server/hooks/auth.js +44 -55
- package/dist/server/hooks/auth.js.map +1 -1
- package/dist/server/hooks/cors.d.ts +27 -0
- package/dist/server/hooks/cors.d.ts.map +1 -1
- package/dist/server/hooks/cors.js +12 -0
- package/dist/server/hooks/cors.js.map +1 -1
- package/dist/server/hooks/errors.d.ts +15 -6
- package/dist/server/hooks/errors.d.ts.map +1 -1
- package/dist/server/hooks/errors.js.map +1 -1
- package/dist/server/hooks/index.d.ts +4 -1
- package/dist/server/hooks/index.d.ts.map +1 -1
- package/dist/server/hooks/index.js +3 -0
- package/dist/server/hooks/index.js.map +1 -1
- package/dist/server/hooks/logging.d.ts +36 -0
- package/dist/server/hooks/logging.d.ts.map +1 -1
- package/dist/server/hooks/logging.js +6 -0
- package/dist/server/hooks/logging.js.map +1 -1
- package/dist/server/hooks/rate-limit.d.ts +33 -0
- package/dist/server/hooks/rate-limit.d.ts.map +1 -1
- package/dist/server/hooks/rate-limit.js +11 -0
- package/dist/server/hooks/rate-limit.js.map +1 -1
- package/dist/server/http.d.ts +222 -0
- package/dist/server/http.d.ts.map +1 -1
- package/dist/server/http.js +20 -1
- package/dist/server/http.js.map +1 -1
- package/dist/server/index.d.ts +19 -1
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +7 -1
- package/dist/server/index.js.map +1 -1
- package/dist/server/openapi.d.ts +5 -3
- package/dist/server/openapi.d.ts.map +1 -1
- package/dist/server/openapi.js +4 -2
- package/dist/server/openapi.js.map +1 -1
- package/dist/server/providers/loadProviderConfig.d.ts +9 -0
- package/dist/server/providers/loadProviderConfig.d.ts.map +1 -1
- package/dist/server/providers/loadProviderConfig.js +9 -0
- package/dist/server/providers/loadProviderConfig.js.map +1 -1
- package/dist/server/server.d.ts +159 -19
- package/dist/server/server.d.ts.map +1 -1
- package/dist/server/server.js +72 -31
- package/dist/server/server.js.map +1 -1
- package/dist/testing/index.d.ts +171 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +127 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/uploads/client.d.ts +278 -0
- package/dist/uploads/client.d.ts.map +1 -0
- package/dist/uploads/client.js +428 -0
- package/dist/uploads/client.js.map +1 -0
- package/dist/uploads/index.d.ts +361 -0
- package/dist/uploads/index.d.ts.map +1 -0
- package/dist/uploads/index.js +543 -0
- package/dist/uploads/index.js.map +1 -0
- package/package.json +31 -2
- package/src/application/index.ts +85 -22
- package/src/client/client.ts +73 -12
- package/src/client/index.ts +12 -0
- package/src/client/types.ts +70 -9
- package/src/config/index.ts +86 -0
- package/src/contracts/contract-builder.ts +49 -22
- package/src/contracts/contract-group.ts +35 -19
- package/src/contracts/contract-like.ts +4 -4
- package/src/contracts/index.ts +28 -1
- package/src/contracts/openapi-meta.ts +8 -8
- package/src/contracts/path-template.ts +27 -0
- package/src/contracts/types.ts +111 -10
- package/src/contracts/utils.ts +6 -0
- package/src/domain/entity.ts +22 -11
- package/src/domain/events.ts +5 -2
- package/src/domain/value-object.ts +19 -9
- package/src/errors/catalog.ts +40 -16
- package/src/errors/response.ts +16 -4
- package/src/errors/validation.ts +10 -1
- package/src/events/index.ts +134 -0
- package/src/idempotency/index.ts +767 -0
- package/src/jobs/index.ts +437 -5
- package/src/mail/index.ts +149 -0
- package/src/notifications/index.ts +771 -0
- package/src/openapi/index.ts +133 -16
- package/src/outbox/index.ts +1104 -0
- package/src/pagination/index.ts +278 -0
- package/src/ports/audit.ts +271 -0
- package/src/ports/auth.ts +70 -0
- package/src/ports/cache.ts +41 -0
- package/src/ports/clock.ts +38 -0
- package/src/ports/id-generator.ts +37 -0
- package/src/ports/index.ts +106 -11
- package/src/ports/logger.ts +56 -0
- package/src/ports/policy.ts +133 -0
- package/src/ports/rate-limit.ts +25 -0
- package/src/ports/redaction.ts +101 -0
- package/src/ports/storage.ts +100 -0
- package/src/ports/testing.ts +47 -0
- package/src/ports/unit-of-work.ts +60 -3
- package/src/providers/instrumentation.ts +211 -1
- package/src/providers/provider.ts +14 -1
- package/src/schedules/index.ts +247 -0
- package/src/server/health.ts +14 -5
- package/src/server/hooks/auth.ts +105 -120
- package/src/server/hooks/cors.ts +27 -0
- package/src/server/hooks/errors.ts +15 -6
- package/src/server/hooks/index.ts +4 -5
- package/src/server/hooks/logging.ts +36 -0
- package/src/server/hooks/rate-limit.ts +33 -0
- package/src/server/http.ts +249 -1
- package/src/server/index.ts +19 -1
- package/src/server/openapi.ts +5 -3
- package/src/server/providers/loadProviderConfig.ts +9 -0
- package/src/server/server.ts +296 -30
- package/src/testing/index.ts +348 -0
- package/src/uploads/client.ts +861 -0
- package/src/uploads/index.ts +1067 -0
|
@@ -0,0 +1,360 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @beignet/core/idempotency
|
|
3
|
+
*
|
|
4
|
+
* Idempotency primitives for retry-safe commands, webhooks, and jobs.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Error thrown when an idempotency key is reused with a different fingerprint.
|
|
8
|
+
*/
|
|
9
|
+
export class IdempotencyConflictError extends Error {
|
|
10
|
+
namespace;
|
|
11
|
+
key;
|
|
12
|
+
scopeKey;
|
|
13
|
+
storedFingerprint;
|
|
14
|
+
receivedFingerprint;
|
|
15
|
+
constructor(args) {
|
|
16
|
+
super(`Idempotency key "${args.key}" conflicts with a different payload in namespace "${args.namespace}".`);
|
|
17
|
+
this.name = "IdempotencyConflictError";
|
|
18
|
+
this.namespace = args.namespace;
|
|
19
|
+
this.key = args.key;
|
|
20
|
+
this.scopeKey = args.scopeKey;
|
|
21
|
+
this.storedFingerprint = args.storedFingerprint;
|
|
22
|
+
this.receivedFingerprint = args.receivedFingerprint;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Error thrown when an idempotency key is already reserved by in-progress work.
|
|
27
|
+
*/
|
|
28
|
+
export class IdempotencyInProgressError extends Error {
|
|
29
|
+
namespace;
|
|
30
|
+
key;
|
|
31
|
+
scopeKey;
|
|
32
|
+
constructor(args) {
|
|
33
|
+
super(`Idempotency key "${args.key}" is already in progress in namespace "${args.namespace}".`);
|
|
34
|
+
this.name = "IdempotencyInProgressError";
|
|
35
|
+
this.namespace = args.namespace;
|
|
36
|
+
this.key = args.key;
|
|
37
|
+
this.scopeKey = args.scopeKey;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Error thrown when replay is disabled for a completed idempotency key.
|
|
42
|
+
*/
|
|
43
|
+
export class IdempotencyReplayError extends Error {
|
|
44
|
+
namespace;
|
|
45
|
+
key;
|
|
46
|
+
scopeKey;
|
|
47
|
+
constructor(args) {
|
|
48
|
+
super(`Idempotency key "${args.key}" already completed in namespace "${args.namespace}".`);
|
|
49
|
+
this.name = "IdempotencyReplayError";
|
|
50
|
+
this.namespace = args.namespace;
|
|
51
|
+
this.key = args.key;
|
|
52
|
+
this.scopeKey = args.scopeKey;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Error thrown when fingerprint input cannot be canonicalized.
|
|
57
|
+
*/
|
|
58
|
+
export class IdempotencyFingerprintError extends Error {
|
|
59
|
+
constructor(message) {
|
|
60
|
+
super(message);
|
|
61
|
+
this.name = "IdempotencyFingerprintError";
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
function assertNonEmptyString(name, value) {
|
|
65
|
+
if (typeof value !== "string" || value.trim().length === 0) {
|
|
66
|
+
throw new Error(`${name} must be a non-empty string`);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
function assertTtl(ttlSec) {
|
|
70
|
+
if (ttlSec === undefined)
|
|
71
|
+
return;
|
|
72
|
+
if (!Number.isInteger(ttlSec) || ttlSec <= 0) {
|
|
73
|
+
throw new Error("ttlSec must be a positive integer when provided");
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
function normalizeScopeValue(value) {
|
|
77
|
+
if (value === undefined)
|
|
78
|
+
return "";
|
|
79
|
+
if (value === null)
|
|
80
|
+
return "null";
|
|
81
|
+
return String(value);
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Normalize an idempotency scope into a stable string.
|
|
85
|
+
*/
|
|
86
|
+
export function normalizeIdempotencyScope(scope) {
|
|
87
|
+
if (scope === undefined)
|
|
88
|
+
return "global";
|
|
89
|
+
if (typeof scope === "string")
|
|
90
|
+
return scope;
|
|
91
|
+
return Object.keys(scope)
|
|
92
|
+
.sort()
|
|
93
|
+
.map((key) => `${key}:${normalizeScopeValue(scope[key])}`)
|
|
94
|
+
.join("|");
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Create the stable storage key for an idempotency operation.
|
|
98
|
+
*/
|
|
99
|
+
export function createIdempotencyStorageKey(input) {
|
|
100
|
+
assertNonEmptyString("namespace", input.namespace);
|
|
101
|
+
assertNonEmptyString("key", input.key);
|
|
102
|
+
return [
|
|
103
|
+
input.namespace,
|
|
104
|
+
normalizeIdempotencyScope(input.scope),
|
|
105
|
+
input.key,
|
|
106
|
+
].join("\u0000");
|
|
107
|
+
}
|
|
108
|
+
function resolveExpiresAt(ttlSec, now) {
|
|
109
|
+
assertTtl(ttlSec);
|
|
110
|
+
return ttlSec === undefined ? null : new Date(now.getTime() + ttlSec * 1000);
|
|
111
|
+
}
|
|
112
|
+
function isExpired(entry, now) {
|
|
113
|
+
return entry.expiresAt !== null && entry.expiresAt.getTime() <= now.getTime();
|
|
114
|
+
}
|
|
115
|
+
function reservationFromRecord(record, receivedFingerprint) {
|
|
116
|
+
if (record.fingerprint !== receivedFingerprint) {
|
|
117
|
+
return {
|
|
118
|
+
status: "conflict",
|
|
119
|
+
namespace: record.namespace,
|
|
120
|
+
key: record.key,
|
|
121
|
+
scopeKey: record.scopeKey,
|
|
122
|
+
storedFingerprint: record.fingerprint,
|
|
123
|
+
receivedFingerprint,
|
|
124
|
+
reservedAt: record.reservedAt,
|
|
125
|
+
completedAt: record.completedAt,
|
|
126
|
+
expiresAt: record.expiresAt,
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
if (record.status === "completed" && record.completedAt) {
|
|
130
|
+
return {
|
|
131
|
+
status: "replay",
|
|
132
|
+
namespace: record.namespace,
|
|
133
|
+
key: record.key,
|
|
134
|
+
scopeKey: record.scopeKey,
|
|
135
|
+
fingerprint: record.fingerprint,
|
|
136
|
+
result: record.result,
|
|
137
|
+
reservedAt: record.reservedAt,
|
|
138
|
+
completedAt: record.completedAt,
|
|
139
|
+
expiresAt: record.expiresAt,
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
return {
|
|
143
|
+
status: "inProgress",
|
|
144
|
+
namespace: record.namespace,
|
|
145
|
+
key: record.key,
|
|
146
|
+
scopeKey: record.scopeKey,
|
|
147
|
+
fingerprint: record.fingerprint,
|
|
148
|
+
reservedAt: record.reservedAt,
|
|
149
|
+
expiresAt: record.expiresAt,
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Create an in-memory idempotency store for tests and local examples.
|
|
154
|
+
*
|
|
155
|
+
* The memory store is process-local and not suitable for multi-process
|
|
156
|
+
* production deployments.
|
|
157
|
+
*/
|
|
158
|
+
export function createMemoryIdempotencyStore() {
|
|
159
|
+
const records = new Map();
|
|
160
|
+
return {
|
|
161
|
+
get entries() {
|
|
162
|
+
return [...records.values()];
|
|
163
|
+
},
|
|
164
|
+
async reserve(input) {
|
|
165
|
+
assertNonEmptyString("namespace", input.namespace);
|
|
166
|
+
assertNonEmptyString("key", input.key);
|
|
167
|
+
assertNonEmptyString("fingerprint", input.fingerprint);
|
|
168
|
+
assertTtl(input.ttlSec);
|
|
169
|
+
const now = new Date();
|
|
170
|
+
const storageKey = createIdempotencyStorageKey(input);
|
|
171
|
+
const existing = records.get(storageKey);
|
|
172
|
+
if (existing && !isExpired(existing, now)) {
|
|
173
|
+
return reservationFromRecord(existing, input.fingerprint);
|
|
174
|
+
}
|
|
175
|
+
if (existing) {
|
|
176
|
+
records.delete(storageKey);
|
|
177
|
+
}
|
|
178
|
+
const record = {
|
|
179
|
+
namespace: input.namespace,
|
|
180
|
+
key: input.key,
|
|
181
|
+
scopeKey: normalizeIdempotencyScope(input.scope),
|
|
182
|
+
fingerprint: input.fingerprint,
|
|
183
|
+
status: "in-progress",
|
|
184
|
+
reservedAt: now,
|
|
185
|
+
expiresAt: resolveExpiresAt(input.ttlSec, now),
|
|
186
|
+
};
|
|
187
|
+
records.set(storageKey, record);
|
|
188
|
+
return {
|
|
189
|
+
status: "reserved",
|
|
190
|
+
namespace: record.namespace,
|
|
191
|
+
key: record.key,
|
|
192
|
+
scopeKey: record.scopeKey,
|
|
193
|
+
fingerprint: record.fingerprint,
|
|
194
|
+
reservedAt: record.reservedAt,
|
|
195
|
+
expiresAt: record.expiresAt,
|
|
196
|
+
};
|
|
197
|
+
},
|
|
198
|
+
async complete(input) {
|
|
199
|
+
assertNonEmptyString("namespace", input.namespace);
|
|
200
|
+
assertNonEmptyString("key", input.key);
|
|
201
|
+
assertNonEmptyString("fingerprint", input.fingerprint);
|
|
202
|
+
const storageKey = createIdempotencyStorageKey(input);
|
|
203
|
+
const existing = records.get(storageKey);
|
|
204
|
+
if (!existing || existing.fingerprint !== input.fingerprint)
|
|
205
|
+
return;
|
|
206
|
+
existing.status = "completed";
|
|
207
|
+
existing.result = input.result;
|
|
208
|
+
existing.completedAt = new Date();
|
|
209
|
+
},
|
|
210
|
+
async fail(input) {
|
|
211
|
+
assertNonEmptyString("namespace", input.namespace);
|
|
212
|
+
assertNonEmptyString("key", input.key);
|
|
213
|
+
assertNonEmptyString("fingerprint", input.fingerprint);
|
|
214
|
+
const storageKey = createIdempotencyStorageKey(input);
|
|
215
|
+
const existing = records.get(storageKey);
|
|
216
|
+
if (!existing || existing.fingerprint !== input.fingerprint)
|
|
217
|
+
return;
|
|
218
|
+
if (existing.status === "completed")
|
|
219
|
+
return;
|
|
220
|
+
records.delete(storageKey);
|
|
221
|
+
},
|
|
222
|
+
clear() {
|
|
223
|
+
records.clear();
|
|
224
|
+
},
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Run an operation behind an idempotency reservation.
|
|
229
|
+
*
|
|
230
|
+
* The flow is: reserve the key, replay completed matching results, reject
|
|
231
|
+
* in-progress/conflicting keys, run the operation for new reservations, then
|
|
232
|
+
* complete or fail the reservation. Callers are responsible for choosing a
|
|
233
|
+
* namespace, scope, key, and fingerprint that match their business operation.
|
|
234
|
+
*/
|
|
235
|
+
export async function runIdempotently(idempotency, options) {
|
|
236
|
+
const operation = {
|
|
237
|
+
namespace: options.namespace,
|
|
238
|
+
key: options.key,
|
|
239
|
+
scope: options.scope,
|
|
240
|
+
fingerprint: options.fingerprint,
|
|
241
|
+
ttlSec: options.ttlSec,
|
|
242
|
+
};
|
|
243
|
+
const reservation = await idempotency.reserve(operation);
|
|
244
|
+
switch (reservation.status) {
|
|
245
|
+
case "replay": {
|
|
246
|
+
if (options.replay === "error") {
|
|
247
|
+
throw new IdempotencyReplayError(reservation);
|
|
248
|
+
}
|
|
249
|
+
return reservation.result;
|
|
250
|
+
}
|
|
251
|
+
case "inProgress": {
|
|
252
|
+
throw new IdempotencyInProgressError(reservation);
|
|
253
|
+
}
|
|
254
|
+
case "conflict": {
|
|
255
|
+
throw new IdempotencyConflictError(reservation);
|
|
256
|
+
}
|
|
257
|
+
case "reserved": {
|
|
258
|
+
try {
|
|
259
|
+
const result = await options.run();
|
|
260
|
+
await idempotency.complete({
|
|
261
|
+
namespace: operation.namespace,
|
|
262
|
+
key: operation.key,
|
|
263
|
+
scope: operation.scope,
|
|
264
|
+
fingerprint: operation.fingerprint,
|
|
265
|
+
result,
|
|
266
|
+
});
|
|
267
|
+
return result;
|
|
268
|
+
}
|
|
269
|
+
catch (error) {
|
|
270
|
+
await idempotency.fail({
|
|
271
|
+
namespace: operation.namespace,
|
|
272
|
+
key: operation.key,
|
|
273
|
+
scope: operation.scope,
|
|
274
|
+
fingerprint: operation.fingerprint,
|
|
275
|
+
error,
|
|
276
|
+
});
|
|
277
|
+
throw error;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
function normalizeOmitPath(path) {
|
|
283
|
+
if (typeof path === "string")
|
|
284
|
+
return path.split(".").filter(Boolean);
|
|
285
|
+
return path.map(String);
|
|
286
|
+
}
|
|
287
|
+
function shouldOmitPath(path, omit) {
|
|
288
|
+
return omit.some((entry) => {
|
|
289
|
+
const omitPath = normalizeOmitPath(entry);
|
|
290
|
+
if (omitPath.length !== path.length)
|
|
291
|
+
return false;
|
|
292
|
+
return omitPath.every((segment, index) => segment === path[index]);
|
|
293
|
+
});
|
|
294
|
+
}
|
|
295
|
+
function canonicalize(value, options, path, seen) {
|
|
296
|
+
if (shouldOmitPath(path, options.omit ?? [])) {
|
|
297
|
+
return undefined;
|
|
298
|
+
}
|
|
299
|
+
if (value === undefined || typeof value === "function") {
|
|
300
|
+
return undefined;
|
|
301
|
+
}
|
|
302
|
+
if (value === null ||
|
|
303
|
+
typeof value === "string" ||
|
|
304
|
+
typeof value === "boolean") {
|
|
305
|
+
return value;
|
|
306
|
+
}
|
|
307
|
+
if (typeof value === "number") {
|
|
308
|
+
if (!Number.isFinite(value)) {
|
|
309
|
+
throw new IdempotencyFingerprintError("Cannot fingerprint non-finite numeric values.");
|
|
310
|
+
}
|
|
311
|
+
return value;
|
|
312
|
+
}
|
|
313
|
+
if (typeof value === "bigint") {
|
|
314
|
+
return value.toString();
|
|
315
|
+
}
|
|
316
|
+
if (value instanceof Date) {
|
|
317
|
+
return value.toISOString();
|
|
318
|
+
}
|
|
319
|
+
if (Array.isArray(value)) {
|
|
320
|
+
return value.map((item, index) => canonicalize(item, options, [...path, String(index)], seen) ?? null);
|
|
321
|
+
}
|
|
322
|
+
if (typeof value === "object") {
|
|
323
|
+
if (seen.has(value)) {
|
|
324
|
+
throw new IdempotencyFingerprintError("Cannot fingerprint circular values.");
|
|
325
|
+
}
|
|
326
|
+
seen.add(value);
|
|
327
|
+
const result = {};
|
|
328
|
+
for (const key of Object.keys(value).sort()) {
|
|
329
|
+
const nestedValue = canonicalize(value[key], options, [...path, key], seen);
|
|
330
|
+
if (nestedValue !== undefined) {
|
|
331
|
+
result[key] = nestedValue;
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
seen.delete(value);
|
|
335
|
+
return result;
|
|
336
|
+
}
|
|
337
|
+
throw new IdempotencyFingerprintError(`Cannot fingerprint value of type "${typeof value}".`);
|
|
338
|
+
}
|
|
339
|
+
function bytesToHex(bytes) {
|
|
340
|
+
return [...new Uint8Array(bytes)]
|
|
341
|
+
.map((byte) => byte.toString(16).padStart(2, "0"))
|
|
342
|
+
.join("");
|
|
343
|
+
}
|
|
344
|
+
/**
|
|
345
|
+
* Create a SHA-256 fingerprint from a canonicalized value.
|
|
346
|
+
*
|
|
347
|
+
* Object keys are sorted, `undefined` and functions are omitted, `Date` values
|
|
348
|
+
* become ISO strings, BigInts become strings, and circular or non-finite values
|
|
349
|
+
* throw. Exact omit paths may be supplied as dotted strings or string arrays.
|
|
350
|
+
*/
|
|
351
|
+
export async function createIdempotencyFingerprint(value, options = {}) {
|
|
352
|
+
if (!globalThis.crypto?.subtle) {
|
|
353
|
+
throw new IdempotencyFingerprintError("Cannot create an idempotency fingerprint because Web Crypto is unavailable.");
|
|
354
|
+
}
|
|
355
|
+
const canonical = canonicalize(value, options, [], new WeakSet());
|
|
356
|
+
const json = JSON.stringify(canonical ?? null);
|
|
357
|
+
const digest = await globalThis.crypto.subtle.digest("SHA-256", new TextEncoder().encode(json));
|
|
358
|
+
return `sha256:${bytesToHex(digest)}`;
|
|
359
|
+
}
|
|
360
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/idempotency/index.ts"],"names":[],"mappings":"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"}
|
package/dist/jobs/index.d.ts
CHANGED
|
@@ -1,56 +1,300 @@
|
|
|
1
1
|
import type { StandardSchemaV1 } from "@standard-schema/spec";
|
|
2
|
+
/**
|
|
3
|
+
* Any Standard Schema compatible validator.
|
|
4
|
+
*/
|
|
2
5
|
export type StandardSchema = StandardSchemaV1<unknown, unknown>;
|
|
6
|
+
/**
|
|
7
|
+
* Value or promise of that value.
|
|
8
|
+
*/
|
|
3
9
|
export type MaybePromise<T> = T | Promise<T>;
|
|
10
|
+
/**
|
|
11
|
+
* Infer the parsed output type from a Standard Schema.
|
|
12
|
+
*/
|
|
4
13
|
export type InferSchemaOutput<T extends StandardSchemaV1> = StandardSchemaV1.InferOutput<T>;
|
|
14
|
+
/**
|
|
15
|
+
* Duration accepted by retry helpers. Numbers are milliseconds.
|
|
16
|
+
*/
|
|
17
|
+
export type JobRetryDuration = number | `${number}ms` | `${number}s` | `${number}m` | `${number}h`;
|
|
18
|
+
/**
|
|
19
|
+
* Retry strategy understood by Beignet job adapters.
|
|
20
|
+
*/
|
|
21
|
+
export type JobRetryStrategy = "none" | "fixed" | "exponential";
|
|
22
|
+
/**
|
|
23
|
+
* Arguments passed to a retry predicate.
|
|
24
|
+
*/
|
|
25
|
+
export interface JobRetryPredicateArgs {
|
|
26
|
+
/**
|
|
27
|
+
* Error thrown by the previous attempt.
|
|
28
|
+
*/
|
|
29
|
+
error: unknown;
|
|
30
|
+
/**
|
|
31
|
+
* One-based attempt number that just failed.
|
|
32
|
+
*/
|
|
33
|
+
attempt: number;
|
|
34
|
+
/**
|
|
35
|
+
* Maximum attempts allowed for this delivery.
|
|
36
|
+
*/
|
|
37
|
+
maxAttempts: number;
|
|
38
|
+
/**
|
|
39
|
+
* Job name when the retry decision is for a job.
|
|
40
|
+
*/
|
|
41
|
+
jobName?: string;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Return whether a failed attempt should be retried.
|
|
45
|
+
*/
|
|
46
|
+
export type JobRetryPredicate = (args: JobRetryPredicateArgs) => boolean;
|
|
47
|
+
/**
|
|
48
|
+
* Job definition created by `defineJob(...)`.
|
|
49
|
+
*/
|
|
5
50
|
export interface JobDef<Name extends string = string, Payload extends StandardSchema = StandardSchema, Ctx = unknown> {
|
|
51
|
+
/**
|
|
52
|
+
* Discriminator for job definitions.
|
|
53
|
+
*/
|
|
6
54
|
readonly kind: "job";
|
|
55
|
+
/**
|
|
56
|
+
* Stable job name used by dispatchers and provider adapters.
|
|
57
|
+
*/
|
|
7
58
|
readonly name: Name;
|
|
59
|
+
/**
|
|
60
|
+
* Standard Schema payload validator.
|
|
61
|
+
*/
|
|
8
62
|
readonly payload: Payload;
|
|
63
|
+
/**
|
|
64
|
+
* Optional human-readable description for docs and tooling.
|
|
65
|
+
*/
|
|
9
66
|
readonly description?: string;
|
|
67
|
+
/**
|
|
68
|
+
* Retry metadata for durable job providers.
|
|
69
|
+
*/
|
|
10
70
|
readonly retry?: JobRetryOptions;
|
|
71
|
+
/**
|
|
72
|
+
* Handle a parsed job payload.
|
|
73
|
+
*/
|
|
11
74
|
handle(args: JobHandleArgs<JobDef<Name, Payload, Ctx>, Ctx>): MaybePromise<void>;
|
|
12
75
|
}
|
|
76
|
+
/**
|
|
77
|
+
* Infer the parsed payload type for a job definition.
|
|
78
|
+
*/
|
|
13
79
|
export type InferJobPayload<J extends JobDef> = J["payload"] extends StandardSchemaV1<unknown, infer Output> ? Output : never;
|
|
80
|
+
/**
|
|
81
|
+
* Arguments passed to a job handler.
|
|
82
|
+
*/
|
|
14
83
|
export interface JobHandleArgs<J extends JobDef, Ctx> {
|
|
84
|
+
/**
|
|
85
|
+
* Job definition being handled.
|
|
86
|
+
*/
|
|
15
87
|
job: J;
|
|
88
|
+
/**
|
|
89
|
+
* Parsed job payload.
|
|
90
|
+
*/
|
|
16
91
|
payload: InferJobPayload<J>;
|
|
92
|
+
/**
|
|
93
|
+
* Handler context.
|
|
94
|
+
*/
|
|
17
95
|
ctx: Ctx;
|
|
18
96
|
}
|
|
97
|
+
/**
|
|
98
|
+
* Retry metadata that durable job providers can map to their own retry model.
|
|
99
|
+
*/
|
|
19
100
|
export interface JobRetryOptions {
|
|
20
101
|
/**
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
|
|
24
|
-
|
|
102
|
+
* Retry strategy. Raw objects without a strategy default to exponential
|
|
103
|
+
* backoff so existing `{ attempts }` style definitions stay meaningful.
|
|
104
|
+
*/
|
|
105
|
+
strategy?: JobRetryStrategy;
|
|
106
|
+
/**
|
|
107
|
+
* Maximum total attempts, including the first attempt.
|
|
25
108
|
*/
|
|
26
109
|
attempts?: number;
|
|
110
|
+
/**
|
|
111
|
+
* Delay between attempts for fixed retry policies.
|
|
112
|
+
*/
|
|
113
|
+
delay?: JobRetryDuration;
|
|
114
|
+
/**
|
|
115
|
+
* Initial delay for exponential retry policies.
|
|
116
|
+
*/
|
|
117
|
+
initialDelay?: JobRetryDuration;
|
|
118
|
+
/**
|
|
119
|
+
* Maximum delay for exponential retry policies.
|
|
120
|
+
*/
|
|
121
|
+
maxDelay?: JobRetryDuration;
|
|
122
|
+
/**
|
|
123
|
+
* Exponential multiplier. Defaults to `2`.
|
|
124
|
+
*/
|
|
125
|
+
factor?: number;
|
|
126
|
+
/**
|
|
127
|
+
* Whether adapters that compute delays should add jitter.
|
|
128
|
+
*/
|
|
129
|
+
jitter?: boolean;
|
|
130
|
+
/**
|
|
131
|
+
* Optional app-owned retry classifier.
|
|
132
|
+
*/
|
|
133
|
+
retryIf?: JobRetryPredicate;
|
|
27
134
|
}
|
|
135
|
+
/**
|
|
136
|
+
* Options for declaring a typed job.
|
|
137
|
+
*/
|
|
28
138
|
export interface DefineJobOptions<Name extends string, Payload extends StandardSchema, Ctx> {
|
|
139
|
+
/**
|
|
140
|
+
* Standard Schema payload validator.
|
|
141
|
+
*/
|
|
29
142
|
payload: Payload;
|
|
143
|
+
/**
|
|
144
|
+
* Optional human-readable description for docs and tooling.
|
|
145
|
+
*/
|
|
30
146
|
description?: string;
|
|
147
|
+
/**
|
|
148
|
+
* Retry metadata for durable job providers.
|
|
149
|
+
*/
|
|
31
150
|
retry?: JobRetryOptions;
|
|
151
|
+
/**
|
|
152
|
+
* Handle a parsed job payload.
|
|
153
|
+
*/
|
|
32
154
|
handle(args: JobHandleArgs<JobDef<Name, Payload, Ctx>, Ctx>): MaybePromise<void>;
|
|
33
155
|
}
|
|
156
|
+
/**
|
|
157
|
+
* Options for a fixed job retry policy.
|
|
158
|
+
*/
|
|
159
|
+
export interface FixedJobRetryOptions {
|
|
160
|
+
/**
|
|
161
|
+
* Maximum total attempts, including the first attempt.
|
|
162
|
+
*/
|
|
163
|
+
attempts: number;
|
|
164
|
+
/**
|
|
165
|
+
* Delay between attempts.
|
|
166
|
+
*/
|
|
167
|
+
delay: JobRetryDuration;
|
|
168
|
+
/**
|
|
169
|
+
* Optional app-owned retry classifier.
|
|
170
|
+
*/
|
|
171
|
+
retryIf?: JobRetryPredicate;
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Options for an exponential job retry policy.
|
|
175
|
+
*/
|
|
176
|
+
export interface ExponentialJobRetryOptions {
|
|
177
|
+
/**
|
|
178
|
+
* Maximum total attempts, including the first attempt.
|
|
179
|
+
*/
|
|
180
|
+
attempts: number;
|
|
181
|
+
/**
|
|
182
|
+
* Initial delay. Defaults to `1s`.
|
|
183
|
+
*/
|
|
184
|
+
initialDelay?: JobRetryDuration;
|
|
185
|
+
/**
|
|
186
|
+
* Maximum delay. Defaults to `1m`.
|
|
187
|
+
*/
|
|
188
|
+
maxDelay?: JobRetryDuration;
|
|
189
|
+
/**
|
|
190
|
+
* Exponential multiplier. Defaults to `2`.
|
|
191
|
+
*/
|
|
192
|
+
factor?: number;
|
|
193
|
+
/**
|
|
194
|
+
* Whether computed delays should include jitter.
|
|
195
|
+
*/
|
|
196
|
+
jitter?: boolean;
|
|
197
|
+
/**
|
|
198
|
+
* Optional app-owned retry classifier.
|
|
199
|
+
*/
|
|
200
|
+
retryIf?: JobRetryPredicate;
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Retry helper namespace for job definitions.
|
|
204
|
+
*/
|
|
205
|
+
export declare const retry: {
|
|
206
|
+
/**
|
|
207
|
+
* Disable retries. The first failure is terminal.
|
|
208
|
+
*/
|
|
209
|
+
readonly none: () => JobRetryOptions;
|
|
210
|
+
/**
|
|
211
|
+
* Retry with the same delay between attempts.
|
|
212
|
+
*/
|
|
213
|
+
readonly fixed: (options: FixedJobRetryOptions) => JobRetryOptions;
|
|
214
|
+
/**
|
|
215
|
+
* Retry with exponential backoff.
|
|
216
|
+
*/
|
|
217
|
+
readonly exponential: (options: ExponentialJobRetryOptions) => JobRetryOptions;
|
|
218
|
+
};
|
|
219
|
+
/**
|
|
220
|
+
* Options for the inline job dispatcher.
|
|
221
|
+
*/
|
|
34
222
|
export interface InlineJobDispatcherOptions<Ctx> {
|
|
223
|
+
/**
|
|
224
|
+
* Static job context or factory evaluated for each dispatched job.
|
|
225
|
+
*/
|
|
35
226
|
ctx?: Ctx | (() => MaybePromise<Ctx>);
|
|
227
|
+
/**
|
|
228
|
+
* Called when a dispatched inline job fails. When omitted, errors are
|
|
229
|
+
* rethrown to the caller.
|
|
230
|
+
*/
|
|
36
231
|
onError?: (error: unknown, job: JobDef<string, StandardSchema, Ctx>) => void;
|
|
37
232
|
}
|
|
233
|
+
/**
|
|
234
|
+
* Local/test job dispatcher that executes job handlers inline.
|
|
235
|
+
*/
|
|
38
236
|
export interface InlineJobDispatcher<Ctx = unknown> {
|
|
237
|
+
/**
|
|
238
|
+
* Validate a payload and run the job handler immediately.
|
|
239
|
+
*/
|
|
39
240
|
dispatch<J extends JobDef<string, StandardSchema, Ctx>>(job: J, payload: InferJobPayload<J>): Promise<void>;
|
|
40
241
|
}
|
|
242
|
+
/**
|
|
243
|
+
* Context-bound job helper factory.
|
|
244
|
+
*/
|
|
41
245
|
export interface JobHandlers<Ctx> {
|
|
246
|
+
/**
|
|
247
|
+
* Define a job with the bound context type.
|
|
248
|
+
*/
|
|
42
249
|
defineJob<Name extends string, Payload extends StandardSchema>(name: Name, options: DefineJobOptions<Name, Payload, Ctx>): JobDef<Name, Payload, Ctx>;
|
|
250
|
+
/**
|
|
251
|
+
* Create an inline dispatcher with the bound context type.
|
|
252
|
+
*/
|
|
43
253
|
createInlineJobDispatcher(options?: InlineJobDispatcherOptions<Ctx>): InlineJobDispatcher<Ctx>;
|
|
44
254
|
}
|
|
255
|
+
/**
|
|
256
|
+
* Error thrown when job payload validation fails.
|
|
257
|
+
*/
|
|
45
258
|
export declare class JobValidationError extends Error {
|
|
259
|
+
/**
|
|
260
|
+
* Raw Standard Schema validation issues.
|
|
261
|
+
*/
|
|
46
262
|
readonly issues: readonly StandardSchemaV1.Issue[];
|
|
47
263
|
constructor(args: {
|
|
48
264
|
name: string;
|
|
49
265
|
issues: readonly StandardSchemaV1.Issue[];
|
|
50
266
|
});
|
|
51
267
|
}
|
|
268
|
+
/**
|
|
269
|
+
* Return the maximum total attempts configured by a retry policy.
|
|
270
|
+
*/
|
|
271
|
+
export declare function getJobRetryMaxAttempts(options: JobRetryOptions | undefined): number | undefined;
|
|
272
|
+
/**
|
|
273
|
+
* Return whether a failed job attempt should be retried.
|
|
274
|
+
*/
|
|
275
|
+
export declare function shouldRetryJob(options: JobRetryOptions | undefined, args: JobRetryPredicateArgs): boolean;
|
|
276
|
+
/**
|
|
277
|
+
* Compute the next retry delay in milliseconds for a failed job attempt.
|
|
278
|
+
*/
|
|
279
|
+
export declare function getJobRetryDelayMs(options: JobRetryOptions | undefined, args: Pick<JobRetryPredicateArgs, "attempt" | "error" | "jobName">): number;
|
|
280
|
+
/**
|
|
281
|
+
* Define a typed job.
|
|
282
|
+
*
|
|
283
|
+
* Retry options are provider hints. Inline dispatchers validate payloads and
|
|
284
|
+
* call `handle(...)` immediately; durable providers may enqueue or schedule the
|
|
285
|
+
* job according to their own runtime.
|
|
286
|
+
*/
|
|
52
287
|
export declare function defineJob<Name extends string, Payload extends StandardSchema, Ctx = unknown>(name: Name, options: DefineJobOptions<Name, Payload, Ctx>): JobDef<Name, Payload, Ctx>;
|
|
288
|
+
/**
|
|
289
|
+
* Validate and parse a job payload with the job's Standard Schema.
|
|
290
|
+
*/
|
|
53
291
|
export declare function parseJobPayload<J extends JobDef>(job: J, payload: unknown): Promise<InferJobPayload<J>>;
|
|
292
|
+
/**
|
|
293
|
+
* Create a local/test dispatcher that runs job handlers inline.
|
|
294
|
+
*/
|
|
54
295
|
export declare function createInlineJobDispatcher<Ctx>(options?: InlineJobDispatcherOptions<Ctx>): InlineJobDispatcher<Ctx>;
|
|
296
|
+
/**
|
|
297
|
+
* Create job helper methods bound to an application context type.
|
|
298
|
+
*/
|
|
55
299
|
export declare function createJobHandlers<Ctx>(): JobHandlers<Ctx>;
|
|
56
300
|
//# sourceMappingURL=index.d.ts.map
|