@beignet/core 0.0.1 → 0.0.2
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 +11 -0
- package/README.md +149 -4
- 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 +110 -0
- package/dist/jobs/index.d.ts.map +1 -1
- package/dist/jobs/index.js +22 -0
- 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 +469 -0
- package/dist/outbox/index.d.ts.map +1 -0
- package/dist/outbox/index.js +482 -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 +204 -0
- 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 +57 -0
- package/dist/server/hooks/auth.d.ts.map +1 -1
- 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 +3 -0
- 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 +170 -0
- package/dist/server/http.d.ts.map +1 -1
- package/dist/server/index.d.ts +18 -0
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +6 -0
- 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 +107 -8
- package/dist/server/server.d.ts.map +1 -1
- package/dist/server/server.js +27 -7
- package/dist/server/server.js.map +1 -1
- package/dist/testing/index.d.ts +167 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +119 -0
- package/dist/testing/index.js.map +1 -0
- package/package.json +21 -1
- 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 +111 -0
- 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 +1024 -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 +204 -0
- 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 +58 -0
- package/src/server/hooks/cors.ts +27 -0
- package/src/server/hooks/errors.ts +15 -6
- package/src/server/hooks/index.ts +3 -0
- package/src/server/hooks/logging.ts +36 -0
- package/src/server/hooks/rate-limit.ts +33 -0
- package/src/server/http.ts +170 -1
- package/src/server/index.ts +18 -1
- package/src/server/openapi.ts +5 -3
- package/src/server/providers/loadProviderConfig.ts +9 -0
- package/src/server/server.ts +107 -9
- package/src/testing/index.ts +337 -0
package/src/jobs/index.ts
CHANGED
|
@@ -1,35 +1,84 @@
|
|
|
1
1
|
import type { StandardSchemaV1 } from "@standard-schema/spec";
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Any Standard Schema compatible validator.
|
|
5
|
+
*/
|
|
3
6
|
export type StandardSchema = StandardSchemaV1<unknown, unknown>;
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Value or promise of that value.
|
|
10
|
+
*/
|
|
4
11
|
export type MaybePromise<T> = T | Promise<T>;
|
|
5
12
|
|
|
13
|
+
/**
|
|
14
|
+
* Infer the parsed output type from a Standard Schema.
|
|
15
|
+
*/
|
|
6
16
|
export type InferSchemaOutput<T extends StandardSchemaV1> =
|
|
7
17
|
StandardSchemaV1.InferOutput<T>;
|
|
8
18
|
|
|
19
|
+
/**
|
|
20
|
+
* Job definition created by `defineJob(...)`.
|
|
21
|
+
*/
|
|
9
22
|
export interface JobDef<
|
|
10
23
|
Name extends string = string,
|
|
11
24
|
Payload extends StandardSchema = StandardSchema,
|
|
12
25
|
Ctx = unknown,
|
|
13
26
|
> {
|
|
27
|
+
/**
|
|
28
|
+
* Discriminator for job definitions.
|
|
29
|
+
*/
|
|
14
30
|
readonly kind: "job";
|
|
31
|
+
/**
|
|
32
|
+
* Stable job name used by dispatchers and provider adapters.
|
|
33
|
+
*/
|
|
15
34
|
readonly name: Name;
|
|
35
|
+
/**
|
|
36
|
+
* Standard Schema payload validator.
|
|
37
|
+
*/
|
|
16
38
|
readonly payload: Payload;
|
|
39
|
+
/**
|
|
40
|
+
* Optional human-readable description for docs and tooling.
|
|
41
|
+
*/
|
|
17
42
|
readonly description?: string;
|
|
43
|
+
/**
|
|
44
|
+
* Retry metadata for durable job providers.
|
|
45
|
+
*/
|
|
18
46
|
readonly retry?: JobRetryOptions;
|
|
47
|
+
/**
|
|
48
|
+
* Handle a parsed job payload.
|
|
49
|
+
*/
|
|
19
50
|
handle(
|
|
20
51
|
args: JobHandleArgs<JobDef<Name, Payload, Ctx>, Ctx>,
|
|
21
52
|
): MaybePromise<void>;
|
|
22
53
|
}
|
|
23
54
|
|
|
55
|
+
/**
|
|
56
|
+
* Infer the parsed payload type for a job definition.
|
|
57
|
+
*/
|
|
24
58
|
export type InferJobPayload<J extends JobDef> =
|
|
25
59
|
J["payload"] extends StandardSchemaV1<unknown, infer Output> ? Output : never;
|
|
26
60
|
|
|
61
|
+
/**
|
|
62
|
+
* Arguments passed to a job handler.
|
|
63
|
+
*/
|
|
27
64
|
export interface JobHandleArgs<J extends JobDef, Ctx> {
|
|
65
|
+
/**
|
|
66
|
+
* Job definition being handled.
|
|
67
|
+
*/
|
|
28
68
|
job: J;
|
|
69
|
+
/**
|
|
70
|
+
* Parsed job payload.
|
|
71
|
+
*/
|
|
29
72
|
payload: InferJobPayload<J>;
|
|
73
|
+
/**
|
|
74
|
+
* Handler context.
|
|
75
|
+
*/
|
|
30
76
|
ctx: Ctx;
|
|
31
77
|
}
|
|
32
78
|
|
|
79
|
+
/**
|
|
80
|
+
* Retry metadata that durable job providers can map to their own retry model.
|
|
81
|
+
*/
|
|
33
82
|
export interface JobRetryOptions {
|
|
34
83
|
/**
|
|
35
84
|
* Maximum number of retry attempts a durable job adapter should request.
|
|
@@ -40,43 +89,89 @@ export interface JobRetryOptions {
|
|
|
40
89
|
attempts?: number;
|
|
41
90
|
}
|
|
42
91
|
|
|
92
|
+
/**
|
|
93
|
+
* Options for declaring a typed job.
|
|
94
|
+
*/
|
|
43
95
|
export interface DefineJobOptions<
|
|
44
96
|
Name extends string,
|
|
45
97
|
Payload extends StandardSchema,
|
|
46
98
|
Ctx,
|
|
47
99
|
> {
|
|
100
|
+
/**
|
|
101
|
+
* Standard Schema payload validator.
|
|
102
|
+
*/
|
|
48
103
|
payload: Payload;
|
|
104
|
+
/**
|
|
105
|
+
* Optional human-readable description for docs and tooling.
|
|
106
|
+
*/
|
|
49
107
|
description?: string;
|
|
108
|
+
/**
|
|
109
|
+
* Retry metadata for durable job providers.
|
|
110
|
+
*/
|
|
50
111
|
retry?: JobRetryOptions;
|
|
112
|
+
/**
|
|
113
|
+
* Handle a parsed job payload.
|
|
114
|
+
*/
|
|
51
115
|
handle(
|
|
52
116
|
args: JobHandleArgs<JobDef<Name, Payload, Ctx>, Ctx>,
|
|
53
117
|
): MaybePromise<void>;
|
|
54
118
|
}
|
|
55
119
|
|
|
120
|
+
/**
|
|
121
|
+
* Options for the inline job dispatcher.
|
|
122
|
+
*/
|
|
56
123
|
export interface InlineJobDispatcherOptions<Ctx> {
|
|
124
|
+
/**
|
|
125
|
+
* Static job context or factory evaluated for each dispatched job.
|
|
126
|
+
*/
|
|
57
127
|
ctx?: Ctx | (() => MaybePromise<Ctx>);
|
|
128
|
+
/**
|
|
129
|
+
* Called when a dispatched inline job fails. When omitted, errors are
|
|
130
|
+
* rethrown to the caller.
|
|
131
|
+
*/
|
|
58
132
|
onError?: (error: unknown, job: JobDef<string, StandardSchema, Ctx>) => void;
|
|
59
133
|
}
|
|
60
134
|
|
|
135
|
+
/**
|
|
136
|
+
* Local/test job dispatcher that executes job handlers inline.
|
|
137
|
+
*/
|
|
61
138
|
export interface InlineJobDispatcher<Ctx = unknown> {
|
|
139
|
+
/**
|
|
140
|
+
* Validate a payload and run the job handler immediately.
|
|
141
|
+
*/
|
|
62
142
|
dispatch<J extends JobDef<string, StandardSchema, Ctx>>(
|
|
63
143
|
job: J,
|
|
64
144
|
payload: InferJobPayload<J>,
|
|
65
145
|
): Promise<void>;
|
|
66
146
|
}
|
|
67
147
|
|
|
148
|
+
/**
|
|
149
|
+
* Context-bound job helper factory.
|
|
150
|
+
*/
|
|
68
151
|
export interface JobHandlers<Ctx> {
|
|
152
|
+
/**
|
|
153
|
+
* Define a job with the bound context type.
|
|
154
|
+
*/
|
|
69
155
|
defineJob<Name extends string, Payload extends StandardSchema>(
|
|
70
156
|
name: Name,
|
|
71
157
|
options: DefineJobOptions<Name, Payload, Ctx>,
|
|
72
158
|
): JobDef<Name, Payload, Ctx>;
|
|
73
159
|
|
|
160
|
+
/**
|
|
161
|
+
* Create an inline dispatcher with the bound context type.
|
|
162
|
+
*/
|
|
74
163
|
createInlineJobDispatcher(
|
|
75
164
|
options?: InlineJobDispatcherOptions<Ctx>,
|
|
76
165
|
): InlineJobDispatcher<Ctx>;
|
|
77
166
|
}
|
|
78
167
|
|
|
168
|
+
/**
|
|
169
|
+
* Error thrown when job payload validation fails.
|
|
170
|
+
*/
|
|
79
171
|
export class JobValidationError extends Error {
|
|
172
|
+
/**
|
|
173
|
+
* Raw Standard Schema validation issues.
|
|
174
|
+
*/
|
|
80
175
|
readonly issues: readonly StandardSchemaV1.Issue[];
|
|
81
176
|
|
|
82
177
|
constructor(args: {
|
|
@@ -143,6 +238,13 @@ async function resolveCtx<Ctx>(
|
|
|
143
238
|
return ctx as Ctx;
|
|
144
239
|
}
|
|
145
240
|
|
|
241
|
+
/**
|
|
242
|
+
* Define a typed job.
|
|
243
|
+
*
|
|
244
|
+
* Retry options are provider hints. Inline dispatchers validate payloads and
|
|
245
|
+
* call `handle(...)` immediately; durable providers may enqueue or schedule the
|
|
246
|
+
* job according to their own runtime.
|
|
247
|
+
*/
|
|
146
248
|
export function defineJob<
|
|
147
249
|
Name extends string,
|
|
148
250
|
Payload extends StandardSchema,
|
|
@@ -161,6 +263,9 @@ export function defineJob<
|
|
|
161
263
|
};
|
|
162
264
|
}
|
|
163
265
|
|
|
266
|
+
/**
|
|
267
|
+
* Validate and parse a job payload with the job's Standard Schema.
|
|
268
|
+
*/
|
|
164
269
|
export async function parseJobPayload<J extends JobDef>(
|
|
165
270
|
job: J,
|
|
166
271
|
payload: unknown,
|
|
@@ -170,6 +275,9 @@ export async function parseJobPayload<J extends JobDef>(
|
|
|
170
275
|
})) as InferJobPayload<J>;
|
|
171
276
|
}
|
|
172
277
|
|
|
278
|
+
/**
|
|
279
|
+
* Create a local/test dispatcher that runs job handlers inline.
|
|
280
|
+
*/
|
|
173
281
|
export function createInlineJobDispatcher<Ctx>(
|
|
174
282
|
options: InlineJobDispatcherOptions<Ctx> = {},
|
|
175
283
|
): InlineJobDispatcher<Ctx> {
|
|
@@ -193,6 +301,9 @@ export function createInlineJobDispatcher<Ctx>(
|
|
|
193
301
|
};
|
|
194
302
|
}
|
|
195
303
|
|
|
304
|
+
/**
|
|
305
|
+
* Create job helper methods bound to an application context type.
|
|
306
|
+
*/
|
|
196
307
|
export function createJobHandlers<Ctx>(): JobHandlers<Ctx> {
|
|
197
308
|
return {
|
|
198
309
|
defineJob<Name extends string, Payload extends StandardSchema>(
|
package/src/mail/index.ts
CHANGED
|
@@ -4,27 +4,71 @@
|
|
|
4
4
|
* Shared mail port and test adapters for Beignet applications.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
+
/**
|
|
8
|
+
* Value or promise of that value.
|
|
9
|
+
*/
|
|
7
10
|
export type MaybePromise<T> = T | Promise<T>;
|
|
8
11
|
|
|
12
|
+
/**
|
|
13
|
+
* Email address accepted by Beignet mail helpers.
|
|
14
|
+
*/
|
|
9
15
|
export type MailAddress =
|
|
10
16
|
| string
|
|
11
17
|
| {
|
|
18
|
+
/**
|
|
19
|
+
* Email address.
|
|
20
|
+
*/
|
|
12
21
|
email: string;
|
|
22
|
+
/**
|
|
23
|
+
* Optional display name.
|
|
24
|
+
*/
|
|
13
25
|
name?: string;
|
|
14
26
|
};
|
|
15
27
|
|
|
28
|
+
/**
|
|
29
|
+
* Single address or address list.
|
|
30
|
+
*/
|
|
16
31
|
export type MailAddressList = MailAddress | readonly MailAddress[];
|
|
17
32
|
|
|
33
|
+
/**
|
|
34
|
+
* Common mail message fields shared by all send options.
|
|
35
|
+
*/
|
|
18
36
|
export interface MailBaseMessage {
|
|
37
|
+
/**
|
|
38
|
+
* Required recipients.
|
|
39
|
+
*/
|
|
19
40
|
to: MailAddressList;
|
|
41
|
+
/**
|
|
42
|
+
* Message subject.
|
|
43
|
+
*/
|
|
20
44
|
subject: string;
|
|
45
|
+
/**
|
|
46
|
+
* Sender address. Providers or adapters may supply a default.
|
|
47
|
+
*/
|
|
21
48
|
from?: MailAddress;
|
|
49
|
+
/**
|
|
50
|
+
* Carbon-copy recipients.
|
|
51
|
+
*/
|
|
22
52
|
cc?: MailAddressList;
|
|
53
|
+
/**
|
|
54
|
+
* Blind-carbon-copy recipients.
|
|
55
|
+
*/
|
|
23
56
|
bcc?: MailAddressList;
|
|
57
|
+
/**
|
|
58
|
+
* Reply-to recipients.
|
|
59
|
+
*/
|
|
24
60
|
replyTo?: MailAddressList;
|
|
61
|
+
/**
|
|
62
|
+
* Provider-specific message headers.
|
|
63
|
+
*/
|
|
25
64
|
headers?: Record<string, string>;
|
|
26
65
|
}
|
|
27
66
|
|
|
67
|
+
/**
|
|
68
|
+
* Mail send options.
|
|
69
|
+
*
|
|
70
|
+
* A message must include at least one body format: `text` or `html`.
|
|
71
|
+
*/
|
|
28
72
|
export type SendMailOptions = MailBaseMessage &
|
|
29
73
|
(
|
|
30
74
|
| {
|
|
@@ -37,45 +81,129 @@ export type SendMailOptions = MailBaseMessage &
|
|
|
37
81
|
}
|
|
38
82
|
);
|
|
39
83
|
|
|
84
|
+
/**
|
|
85
|
+
* Normalized mail message with address fields converted to arrays.
|
|
86
|
+
*/
|
|
40
87
|
export interface NormalizedMailMessage extends MailBaseMessage {
|
|
88
|
+
/**
|
|
89
|
+
* Normalized recipients.
|
|
90
|
+
*/
|
|
41
91
|
to: readonly MailAddress[];
|
|
92
|
+
/**
|
|
93
|
+
* Sender address after applying any default.
|
|
94
|
+
*/
|
|
42
95
|
from?: MailAddress;
|
|
96
|
+
/**
|
|
97
|
+
* Normalized carbon-copy recipients.
|
|
98
|
+
*/
|
|
43
99
|
cc?: readonly MailAddress[];
|
|
100
|
+
/**
|
|
101
|
+
* Normalized blind-carbon-copy recipients.
|
|
102
|
+
*/
|
|
44
103
|
bcc?: readonly MailAddress[];
|
|
104
|
+
/**
|
|
105
|
+
* Normalized reply-to recipients.
|
|
106
|
+
*/
|
|
45
107
|
replyTo?: readonly MailAddress[];
|
|
108
|
+
/**
|
|
109
|
+
* Plain text body.
|
|
110
|
+
*/
|
|
46
111
|
text?: string;
|
|
112
|
+
/**
|
|
113
|
+
* HTML body.
|
|
114
|
+
*/
|
|
47
115
|
html?: string;
|
|
48
116
|
}
|
|
49
117
|
|
|
118
|
+
/**
|
|
119
|
+
* Result returned by a mail provider.
|
|
120
|
+
*/
|
|
50
121
|
export interface SendMailResult {
|
|
122
|
+
/**
|
|
123
|
+
* Provider message ID when available.
|
|
124
|
+
*/
|
|
51
125
|
id?: string;
|
|
126
|
+
/**
|
|
127
|
+
* Provider name.
|
|
128
|
+
*/
|
|
52
129
|
provider?: string;
|
|
53
130
|
}
|
|
54
131
|
|
|
132
|
+
/**
|
|
133
|
+
* App-facing mailer port.
|
|
134
|
+
*/
|
|
55
135
|
export interface MailerPort {
|
|
136
|
+
/**
|
|
137
|
+
* Send one mail message.
|
|
138
|
+
*/
|
|
56
139
|
send(message: SendMailOptions): Promise<SendMailResult>;
|
|
57
140
|
}
|
|
58
141
|
|
|
142
|
+
/**
|
|
143
|
+
* Delivery captured by the memory mailer.
|
|
144
|
+
*/
|
|
59
145
|
export interface MemoryMailDelivery {
|
|
146
|
+
/**
|
|
147
|
+
* Generated delivery ID.
|
|
148
|
+
*/
|
|
60
149
|
id: string;
|
|
150
|
+
/**
|
|
151
|
+
* Normalized message that would have been sent.
|
|
152
|
+
*/
|
|
61
153
|
message: NormalizedMailMessage;
|
|
154
|
+
/**
|
|
155
|
+
* Timestamp assigned by the memory mailer.
|
|
156
|
+
*/
|
|
62
157
|
sentAt: Date;
|
|
63
158
|
}
|
|
64
159
|
|
|
160
|
+
/**
|
|
161
|
+
* In-memory mailer port for tests and local examples.
|
|
162
|
+
*/
|
|
65
163
|
export interface MemoryMailerPort extends MailerPort {
|
|
164
|
+
/**
|
|
165
|
+
* Captured deliveries.
|
|
166
|
+
*/
|
|
66
167
|
readonly deliveries: readonly MemoryMailDelivery[];
|
|
168
|
+
/**
|
|
169
|
+
* Clear captured deliveries.
|
|
170
|
+
*/
|
|
67
171
|
clear(): void;
|
|
68
172
|
}
|
|
69
173
|
|
|
174
|
+
/**
|
|
175
|
+
* Options for `createMemoryMailer(...)`.
|
|
176
|
+
*/
|
|
70
177
|
export interface CreateMemoryMailerOptions {
|
|
178
|
+
/**
|
|
179
|
+
* Sender used when a message does not specify `from`.
|
|
180
|
+
*/
|
|
71
181
|
defaultFrom?: MailAddress;
|
|
182
|
+
/**
|
|
183
|
+
* Clock used for captured deliveries.
|
|
184
|
+
*/
|
|
72
185
|
now?: () => Date;
|
|
186
|
+
/**
|
|
187
|
+
* ID factory used for captured deliveries.
|
|
188
|
+
*/
|
|
73
189
|
id?: () => string;
|
|
190
|
+
/**
|
|
191
|
+
* Observer called after a delivery is captured.
|
|
192
|
+
*/
|
|
74
193
|
onSend?: (delivery: MemoryMailDelivery) => MaybePromise<void>;
|
|
75
194
|
}
|
|
76
195
|
|
|
196
|
+
/**
|
|
197
|
+
* Error thrown by mail helpers and provider adapters.
|
|
198
|
+
*/
|
|
77
199
|
export class MailDeliveryError extends Error {
|
|
200
|
+
/**
|
|
201
|
+
* Provider name when known.
|
|
202
|
+
*/
|
|
78
203
|
readonly provider?: string;
|
|
204
|
+
/**
|
|
205
|
+
* Original provider error when available.
|
|
206
|
+
*/
|
|
79
207
|
readonly cause?: unknown;
|
|
80
208
|
|
|
81
209
|
constructor(args: { provider?: string; message: string; cause?: unknown }) {
|
|
@@ -86,6 +214,11 @@ export class MailDeliveryError extends Error {
|
|
|
86
214
|
}
|
|
87
215
|
}
|
|
88
216
|
|
|
217
|
+
/**
|
|
218
|
+
* Normalize a single address or address list into an array.
|
|
219
|
+
*
|
|
220
|
+
* This helper does not validate email syntax.
|
|
221
|
+
*/
|
|
89
222
|
export function normalizeMailAddressList(
|
|
90
223
|
addresses: MailAddressList | undefined,
|
|
91
224
|
): readonly MailAddress[] | undefined {
|
|
@@ -100,6 +233,9 @@ function normalizeOptionalMailAddressList(
|
|
|
100
233
|
return normalized && normalized.length > 0 ? normalized : undefined;
|
|
101
234
|
}
|
|
102
235
|
|
|
236
|
+
/**
|
|
237
|
+
* Format one address for providers that accept RFC-like address strings.
|
|
238
|
+
*/
|
|
103
239
|
export function formatMailAddress(address: MailAddress): string {
|
|
104
240
|
if (typeof address === "string") return address;
|
|
105
241
|
if (!address.name) return address.email;
|
|
@@ -108,6 +244,9 @@ export function formatMailAddress(address: MailAddress): string {
|
|
|
108
244
|
return `"${escapedName}" <${address.email}>`;
|
|
109
245
|
}
|
|
110
246
|
|
|
247
|
+
/**
|
|
248
|
+
* Format one or more addresses for providers that accept string address fields.
|
|
249
|
+
*/
|
|
111
250
|
export function formatMailAddressList(
|
|
112
251
|
addresses: MailAddressList,
|
|
113
252
|
): string | string[] {
|
|
@@ -116,6 +255,11 @@ export function formatMailAddressList(
|
|
|
116
255
|
return formatted.length === 1 ? formatted[0] : formatted;
|
|
117
256
|
}
|
|
118
257
|
|
|
258
|
+
/**
|
|
259
|
+
* Normalize a mail message and apply a default sender.
|
|
260
|
+
*
|
|
261
|
+
* Throws when the message has no recipients.
|
|
262
|
+
*/
|
|
119
263
|
export function normalizeMailMessage(
|
|
120
264
|
message: SendMailOptions,
|
|
121
265
|
options: { defaultFrom?: MailAddress } = {},
|
|
@@ -140,6 +284,11 @@ export function normalizeMailMessage(
|
|
|
140
284
|
};
|
|
141
285
|
}
|
|
142
286
|
|
|
287
|
+
/**
|
|
288
|
+
* Create an in-memory mailer for tests, local development, and examples.
|
|
289
|
+
*
|
|
290
|
+
* The memory mailer does not send real email or validate address syntax.
|
|
291
|
+
*/
|
|
143
292
|
export function createMemoryMailer(
|
|
144
293
|
options: CreateMemoryMailerOptions = {},
|
|
145
294
|
): MemoryMailerPort {
|