better-ship 0.8.0 → 0.11.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.
Files changed (88) hide show
  1. package/dist/{application-DYfcAy-Q.js → application-CIxo_BpK.js} +32 -3
  2. package/dist/application-CIxo_BpK.js.map +1 -0
  3. package/dist/application.d.ts +3 -3
  4. package/dist/application.js +2 -2
  5. package/dist/better-auth/apple-client-secret.d.ts +11 -4
  6. package/dist/better-auth/apple-client-secret.d.ts.map +1 -1
  7. package/dist/better-auth/apple-client-secret.js +39 -11
  8. package/dist/better-auth/apple-client-secret.js.map +1 -1
  9. package/dist/better-auth/auth-client.js +1 -1
  10. package/dist/better-auth/rate-limit.d.ts +21 -2
  11. package/dist/better-auth/rate-limit.d.ts.map +1 -1
  12. package/dist/better-auth/rate-limit.js +38 -2
  13. package/dist/better-auth/rate-limit.js.map +1 -1
  14. package/dist/better-auth.js +1 -1
  15. package/dist/cloudflare/auth-secondary-storage.d.ts +1 -1
  16. package/dist/cloudflare/auth-secondary-storage.js +1 -1
  17. package/dist/cloudflare/queue.d.ts +1 -1
  18. package/dist/cloudflare/queue.js +2 -2
  19. package/dist/cloudflare/scheduled.d.ts +36 -0
  20. package/dist/cloudflare/scheduled.d.ts.map +1 -0
  21. package/dist/cloudflare/scheduled.js +37 -0
  22. package/dist/cloudflare/scheduled.js.map +1 -0
  23. package/dist/cloudflare.d.ts +3 -3
  24. package/dist/cloudflare.js +3 -3
  25. package/dist/{core-DC_4pOrI.js → core-DG_cC8YT.js} +110 -2
  26. package/dist/{core-DC_4pOrI.js.map → core-DG_cC8YT.js.map} +1 -1
  27. package/dist/core.d.ts +2 -2
  28. package/dist/core.js +2 -2
  29. package/dist/http.d.ts +19 -0
  30. package/dist/http.d.ts.map +1 -0
  31. package/dist/http.js +35 -0
  32. package/dist/http.js.map +1 -0
  33. package/dist/{index-6XMPJu7u.d.ts → index-Bl0K1RQW.d.ts} +90 -2
  34. package/dist/index-Bl0K1RQW.d.ts.map +1 -0
  35. package/dist/{index-_Cihfq1J.d.ts → index-DgDyeR5s.d.ts} +135 -55
  36. package/dist/index-DgDyeR5s.d.ts.map +1 -0
  37. package/dist/postgres.d.ts +3 -3
  38. package/dist/postgres.js +3 -3
  39. package/dist/resend.d.ts +73 -0
  40. package/dist/resend.d.ts.map +1 -0
  41. package/dist/resend.js +284 -0
  42. package/dist/resend.js.map +1 -0
  43. package/dist/tanstack/server.d.ts +8 -0
  44. package/dist/tanstack/server.d.ts.map +1 -0
  45. package/dist/tanstack/server.js +16 -0
  46. package/dist/tanstack/server.js.map +1 -0
  47. package/dist/tanstack.d.ts +18 -14
  48. package/dist/tanstack.d.ts.map +1 -1
  49. package/dist/tanstack.js +17 -23
  50. package/dist/tanstack.js.map +1 -1
  51. package/dist/{unit-of-work-context-BFCmU92Z.js → unit-of-work-context-BPE1In2f.js} +2 -2
  52. package/dist/{unit-of-work-context-BFCmU92Z.js.map → unit-of-work-context-BPE1In2f.js.map} +1 -1
  53. package/dist/{unit-of-work-context-BWTJfYPW.d.ts → unit-of-work-context-BzmnjlDa.d.ts} +3 -3
  54. package/dist/{unit-of-work-context-BWTJfYPW.d.ts.map → unit-of-work-context-BzmnjlDa.d.ts.map} +1 -1
  55. package/dist/webhook-verification-BQ9qZnVK.js +18 -0
  56. package/dist/webhook-verification-BQ9qZnVK.js.map +1 -0
  57. package/dist/webhook-verification-sZtwTI5n.d.ts +29 -0
  58. package/dist/webhook-verification-sZtwTI5n.d.ts.map +1 -0
  59. package/package.json +11 -6
  60. package/src/application/email-service.ts +55 -0
  61. package/src/application/index.ts +16 -0
  62. package/src/application/record-email-event.ts +53 -0
  63. package/src/core/email-address.ts +7 -0
  64. package/src/core/email-deliverability.ts +31 -0
  65. package/src/core/email-idempotency-key.ts +34 -0
  66. package/src/core/email-service.error.ts +51 -0
  67. package/src/core/index.ts +18 -0
  68. package/src/core/record-email-event.ts +23 -0
  69. package/src/infrastructure/better-auth/apple-client-secret.ts +41 -14
  70. package/src/infrastructure/better-auth/rate-limit.ts +44 -1
  71. package/src/infrastructure/cloudflare/scheduled/index.ts +8 -0
  72. package/src/infrastructure/cloudflare/scheduled/scheduled-handler.ts +62 -0
  73. package/src/infrastructure/http/index.ts +6 -0
  74. package/src/infrastructure/http/webhook-handler.ts +35 -0
  75. package/src/infrastructure/http/webhook-verification.ts +27 -0
  76. package/src/infrastructure/resend/email-event.ts +142 -0
  77. package/src/infrastructure/resend/index.ts +3 -0
  78. package/src/infrastructure/resend/resend-email-service.ts +125 -0
  79. package/src/infrastructure/resend/resend-webhook.ts +70 -0
  80. package/src/infrastructure/tanstack/auth.middleware.ts +14 -6
  81. package/src/infrastructure/tanstack/error.middleware.ts +7 -8
  82. package/src/infrastructure/tanstack/index.ts +0 -1
  83. package/src/infrastructure/tanstack/request-context.ts +11 -0
  84. package/src/infrastructure/tanstack/server.ts +7 -0
  85. package/src/infrastructure/tanstack/session-cookies.ts +6 -4
  86. package/dist/application-DYfcAy-Q.js.map +0 -1
  87. package/dist/index-6XMPJu7u.d.ts.map +0 -1
  88. package/dist/index-_Cihfq1J.d.ts.map +0 -1
@@ -36,6 +36,94 @@ declare abstract class AppError extends Error {
36
36
  get name(): string;
37
37
  }
38
38
  //#endregion
39
+ //#region src/core/email-address.d.ts
40
+ /** A parsed email address for message payloads and webhook recipients. Ported from Typist's `EmailSchema`. */
41
+ declare const EmailAddressSchema: z.core.$ZodBranded<z.ZodEmail, "EmailAddress", "out">;
42
+ /** An address the schema accepted. */
43
+ type EmailAddress = z.infer<typeof EmailAddressSchema>;
44
+ //#endregion
45
+ //#region src/core/email-idempotency-key.d.ts
46
+ /** A key only `emailIdempotencyKey` mints, so every send carries one built by its rules. */
47
+ type EmailIdempotencyKey = string & z.core.$brand<'EmailIdempotencyKey'>;
48
+ /** A key outside 1 to 256 characters. Keys come from stable ids, so this is a defect, not a retry. */
49
+ declare class InvalidEmailIdempotencyKeyError extends AppError {
50
+ readonly length: number;
51
+ readonly _tag = "InvalidEmailIdempotencyKeyError";
52
+ readonly classification = "terminal";
53
+ constructor(length: number);
54
+ }
55
+ /**
56
+ * `<scope>/<id>` for one logical send. Resend deduplicates it for 24 hours.
57
+ * Derive `id` from a stable identity: a message id, a job id, a user id with a template name.
58
+ * The same key must map to an identical payload; a changed body is rejected as terminal.
59
+ * A random `id` means every request is a deliberate new send, as a sign-in code resend is.
60
+ * Source: https://resend.com/docs/dashboard/emails/idempotency-keys
61
+ */
62
+ declare function emailIdempotencyKey(scope: string, id: string): EmailIdempotencyKey;
63
+ //#endregion
64
+ //#region src/core/email-service.error.d.ts
65
+ /** Why the provider rejected a send. The reason owns the classification, so the two never disagree. */
66
+ type EmailSendFailureReason = 'rate_limited' | 'idempotency_conflict' | 'provider_error' | 'quota_exceeded' | 'invalid_request' | 'configuration';
67
+ /**
68
+ * The provider rejected a send. The boundary that awaited the send logs once; the adapter never does.
69
+ * `retryAfter` is the server's delay in seconds when it sent one, so `retryAfterSecondsOf` reads it.
70
+ */
71
+ declare class EmailServiceError extends AppError {
72
+ readonly _tag = "EmailServiceError";
73
+ readonly classification: FailureClassification;
74
+ readonly reason: EmailSendFailureReason;
75
+ readonly provider: string;
76
+ readonly providerCode: string;
77
+ readonly statusCode: number | null;
78
+ readonly retryAfter: number | null;
79
+ constructor(args: {
80
+ readonly reason: EmailSendFailureReason;
81
+ readonly provider: string;
82
+ readonly providerCode: string;
83
+ readonly statusCode: number | null;
84
+ readonly retryAfter: number | null;
85
+ readonly cause: unknown;
86
+ });
87
+ }
88
+ //#endregion
89
+ //#region src/core/email-deliverability.d.ts
90
+ /** The bounce classes Resend reports, ported from Typist's comm-eligibility.ts. */
91
+ declare const BounceTypeSchema: z.ZodEnum<{
92
+ Permanent: "Permanent";
93
+ Transient: "Transient";
94
+ Undetermined: "Undetermined";
95
+ }>;
96
+ /** One bounce class. */
97
+ type BounceType = z.infer<typeof BounceTypeSchema>;
98
+ /** Parse a provider's bounce type. An unknown value is `Undetermined`, which suppresses. */
99
+ declare function parseBounceType(value: string | undefined): BounceType;
100
+ /** Keep the higher severity. Equal severity permits replacement; callers own timestamp ordering. */
101
+ declare function shouldUpdateBounce(incoming: BounceType, current: BounceType | null): boolean;
102
+ /** Typist's send policy: no complaint, and either no bounce or a transient one. Delivery is not guaranteed. */
103
+ declare function isEmailDeliverable(bounceType: BounceType | null, complained: boolean): boolean;
104
+ //#endregion
105
+ //#region src/core/record-email-event.d.ts
106
+ /**
107
+ * The payload of the command an application registers to record a bounce or a complaint.
108
+ * Register it under a name of the application's choice in `defineMessages`; `recordEmailEvent` handles it.
109
+ */
110
+ declare const RecordEmailEventPayloadSchema: z.ZodObject<{
111
+ recipients: z.ZodArray<z.core.$ZodBranded<z.ZodEmail, "EmailAddress", "out">>;
112
+ event: z.ZodDiscriminatedUnion<[z.ZodObject<{
113
+ type: z.ZodLiteral<"bounced">;
114
+ bounceType: z.ZodEnum<{
115
+ Permanent: "Permanent";
116
+ Transient: "Transient";
117
+ Undetermined: "Undetermined";
118
+ }>;
119
+ bounceSubType: z.ZodNullable<z.ZodString>;
120
+ }, z.core.$strip>, z.ZodObject<{
121
+ type: z.ZodLiteral<"complained">;
122
+ }, z.core.$strip>], "type">;
123
+ }, z.core.$strip>;
124
+ /** A parsed payload. */
125
+ type RecordEmailEventPayload = z.infer<typeof RecordEmailEventPayloadSchema>;
126
+ //#endregion
39
127
  //#region src/core/authentication.error.d.ts
40
128
  /** A protected operation requires a session that the caller did not provide. */
41
129
  declare class AuthenticationError extends AppError {
@@ -627,5 +715,5 @@ declare class Logger {
627
715
  /** Create a logger for one module. */
628
716
  declare function createLogger(module: string, config?: LoggerConfig): Logger;
629
717
  //#endregion
630
- export { unreachable as $, isTransientCloudflareRuntimeError as A, FailureClassification as At, PayloadSchemas as B, classifyBoundaryError as C, InternalServerError as Ct, isCloudflareObjectResetError as D, RateLimitError as Dt, CLOUDFLARE_TRANSIENT_ERROR_PATTERNS as E, StaleSessionError as Et, AppMessages as F, DomainMessage as G, defineMessages as H, CommandOf as I, Id as J, DomainQuery as K, EventOf as L, isTransientTransportError as M, shouldRetryFailure as Mt, Entity as N, isCloudflareOverloadedError as O, AuthenticationError as Ot, EntityData as P, notImplemented as Q, MessageDefinition as R, BoundaryErrorClassifier as S, ValidationProblemErrorSchema as St, retryAfterSecondsOf as T, NotAuthorizedError as Tt, DomainCommand as U, QueryOf as V, DomainEvent as W, IdOf as X, IdDefinition as Y, defineId as Z, createLogger as _, ProblemDetails as _t, LogFormat as a, ErrorPayloadOf as at, exponentialEqualJitterMs as b, ValidationProblemDetailsSchema as bt, LogThreshold as c, ResolvedError as ct, LoggerConfig as d, MalformedRequestError as dt, D1ConstraintKind as et, LoggerErrorHook as f, RequestTimeoutError as ft, consoleSink as g, ValidationIssue as gt, configureLogger as h, ValidationError as ht, LogFields as i, ErrorEntry as it, isAbortError as j, RetryOwner as jt, isCloudflareRetryableError as k, AppError as kt, LogValue as l, defineErrors as lt, SerializedError as m, UpgradeRequiredError as mt, ErrorLogContext as n, DatabaseFailure as nt, LogLevel as o, ErrorTable as ot, LoggerSettings as p, ResourceNotFoundError as pt, MessageId as q, LogEntry as r, ErrorEntries as rt, LogSink as s, ErrorTagOf as st, ErrorCaptureEntry as t, DatabaseError as tt, Logger as u, sharedErrors as ut, setLogSink as v, ProblemDetailsSchema as vt, classifyFailure as w, ServiceUnavailableError as wt, spreadJitterMs as x, ValidationProblemError as xt, setLoggerErrorHook as y, ValidationProblemDetails as yt, MessageOf as z };
631
- //# sourceMappingURL=index-6XMPJu7u.d.ts.map
718
+ export { unreachable as $, isTransientCloudflareRuntimeError as A, RecordEmailEventPayloadSchema as At, PayloadSchemas as B, emailIdempotencyKey as Bt, classifyBoundaryError as C, InternalServerError as Ct, isCloudflareObjectResetError as D, RateLimitError as Dt, CLOUDFLARE_TRANSIENT_ERROR_PATTERNS as E, StaleSessionError as Et, AppMessages as F, shouldUpdateBounce as Ft, DomainMessage as G, RetryOwner as Gt, defineMessages as H, EmailAddressSchema as Ht, CommandOf as I, EmailSendFailureReason as It, Id as J, DomainQuery as K, shouldRetryFailure as Kt, EventOf as L, EmailServiceError as Lt, isTransientTransportError as M, BounceTypeSchema as Mt, Entity as N, isEmailDeliverable as Nt, isCloudflareOverloadedError as O, AuthenticationError as Ot, EntityData as P, parseBounceType as Pt, notImplemented as Q, MessageDefinition as R, EmailIdempotencyKey as Rt, BoundaryErrorClassifier as S, ValidationProblemErrorSchema as St, retryAfterSecondsOf as T, NotAuthorizedError as Tt, DomainCommand as U, AppError as Ut, QueryOf as V, EmailAddress as Vt, DomainEvent as W, FailureClassification as Wt, IdOf as X, IdDefinition as Y, defineId as Z, createLogger as _, ProblemDetails as _t, LogFormat as a, ErrorPayloadOf as at, exponentialEqualJitterMs as b, ValidationProblemDetailsSchema as bt, LogThreshold as c, ResolvedError as ct, LoggerConfig as d, MalformedRequestError as dt, D1ConstraintKind as et, LoggerErrorHook as f, RequestTimeoutError as ft, consoleSink as g, ValidationIssue as gt, configureLogger as h, ValidationError as ht, LogFields as i, ErrorEntry as it, isAbortError as j, BounceType as jt, isCloudflareRetryableError as k, RecordEmailEventPayload as kt, LogValue as l, defineErrors as lt, SerializedError as m, UpgradeRequiredError as mt, ErrorLogContext as n, DatabaseFailure as nt, LogLevel as o, ErrorTable as ot, LoggerSettings as p, ResourceNotFoundError as pt, MessageId as q, LogEntry as r, ErrorEntries as rt, LogSink as s, ErrorTagOf as st, ErrorCaptureEntry as t, DatabaseError as tt, Logger as u, sharedErrors as ut, setLogSink as v, ProblemDetailsSchema as vt, classifyFailure as w, ServiceUnavailableError as wt, spreadJitterMs as x, ValidationProblemError as xt, setLoggerErrorHook as y, ValidationProblemDetails as yt, MessageOf as z, InvalidEmailIdempotencyKeyError as zt };
719
+ //# sourceMappingURL=index-Bl0K1RQW.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-Bl0K1RQW.d.ts","names":[],"sources":["../src/core/failure-classification.ts","../src/core/app-error.ts","../src/core/email-address.ts","../src/core/email-idempotency-key.ts","../src/core/email-service.error.ts","../src/core/email-deliverability.ts","../src/core/record-email-event.ts","../src/core/authentication.error.ts","../src/core/rate-limit.error.ts","../src/core/stale-session.error.ts","../src/core/not-authorized.error.ts","../src/core/internal.errors.ts","../src/core/problem-details.ts","../src/core/request.errors.ts","../src/core/error-table.ts","../src/core/database.error.ts","../src/core/defects.ts","../src/core/identity.ts","../src/core/messages.ts","../src/core/define-messages.ts","../src/core/entity.ts","../src/core/transport-classification.ts","../src/core/cloudflare-classification.ts","../src/core/classify-failure.ts","../src/core/backoff.ts","../src/core/logger.ts"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { G as DomainMessage, K as DomainQuery, U as DomainCommand, W as DomainEvent, kt as AppError, q as MessageId } from "./index-6XMPJu7u.js";
1
+ import { G as DomainMessage, K as DomainQuery, Rt as EmailIdempotencyKey, U as DomainCommand, Ut as AppError, Vt as EmailAddress, W as DomainEvent, jt as BounceType, kt as RecordEmailEventPayload, q as MessageId } from "./index-Bl0K1RQW.js";
2
2
  //#region src/application/handlers.d.ts
3
3
  /**
4
4
  * Handles one command with the dependency container and returns the caller's value.
@@ -13,6 +13,61 @@ type QueryHandler<TQuery extends DomainQuery, QueryDeps, Value> = (query: TQuery
13
13
  /** Completes one subscriber's work for an event. Failures throw. */
14
14
  type EventHandler<TEvent extends DomainEvent, Deps> = (event: TEvent, deps: Deps) => Promise<void>;
15
15
  //#endregion
16
+ //#region src/application/email-service.d.ts
17
+ /** A media type such as `application/pdf`. */
18
+ type MimeType = `${string}/${string}`;
19
+ /** A file to attach. Binary content is bytes; the adapter encodes it for the provider. */
20
+ type EmailAttachment = {
21
+ readonly filename: string;
22
+ readonly content: string | Uint8Array;
23
+ /** Optional MIME metadata; Resend accepts filename and content without it. */
24
+ readonly contentType?: MimeType;
25
+ };
26
+ /**
27
+ * One transactional email. Resend accepts 50 recipients, 75 tags with ASCII names and values,
28
+ * and 40 MB of attachments after base64. Sources: https://resend.com/docs/api-reference/emails/send-email
29
+ * and https://resend.com/docs/dashboard/emails/tags
30
+ */
31
+ type OutboundEmail = {
32
+ readonly to: string | readonly string[];
33
+ readonly subject: string;
34
+ readonly html: string;
35
+ /** The stable identity of this send. Resend deduplicates it for 24 hours. */
36
+ readonly idempotencyKey: EmailIdempotencyKey;
37
+ /** Resend generates plain text from html when omitted. An empty string disables that generation. */
38
+ readonly text?: string;
39
+ readonly replyTo?: string;
40
+ /** Labels the provider stores with the email and returns on every delivery event. */
41
+ readonly tags?: Readonly<Record<string, string>>;
42
+ readonly attachments?: readonly EmailAttachment[];
43
+ };
44
+ /** The provider accepted the email and assigned its id. */
45
+ type EmailAccepted = {
46
+ readonly providerId: string;
47
+ };
48
+ /**
49
+ * The port a handler sends through. The adapter owns the sender address and the provider error mapping.
50
+ * A provider rejection throws `EmailServiceError`; unexpected SDK rejections propagate unchanged.
51
+ */
52
+ interface IEmailService {
53
+ /** Resolve after provider acceptance; this does not confirm delivery to the recipient. */
54
+ sendEmail(email: OutboundEmail): Promise<EmailAccepted>;
55
+ }
56
+ /** Records every send for a test. Provider ids count up as `recorded-1`, `recorded-2`. */
57
+ declare class RecordingEmailService implements IEmailService {
58
+ /** Sends in call order, including repeated idempotency keys. */
59
+ readonly sent: OutboundEmail[];
60
+ /** Record the send before returning its provider id. */
61
+ sendEmail(email: OutboundEmail): Promise<EmailAccepted>;
62
+ }
63
+ //#endregion
64
+ //#region src/application/event-collector.d.ts
65
+ /** Records events in the current unit of work; the unit of work collects a snapshot for outbox persistence. */
66
+ interface IEventCollector {
67
+ emit(event: DomainEvent): void;
68
+ collect(): ReadonlyArray<DomainEvent>;
69
+ }
70
+ //#endregion
16
71
  //#region src/application/message-store.d.ts
17
72
  /**
18
73
  * Stores processed messages and outgoing events in the same transaction as application writes.
@@ -25,6 +80,83 @@ interface IMessageStore {
25
80
  persistEvents(events: ReadonlyArray<DomainEvent>): Promise<void>;
26
81
  }
27
82
  //#endregion
83
+ //#region src/application/outbox-relay.d.ts
84
+ /**
85
+ * Delivers committed outbox rows. The unit of work only wakes it after a commit that wrote
86
+ * events; the app decides what a wake is: `waitUntil`, a Durable Object alarm, nothing.
87
+ * The sweep is the source of truth, so a lost wake loses no events.
88
+ */
89
+ interface IOutboxRelay {
90
+ wake(): void;
91
+ }
92
+ //#endregion
93
+ //#region src/application/transaction.d.ts
94
+ /**
95
+ * Supplies `Tx` to participating repositories and resolves after their writes commit. Failure rolls back or discards writes.
96
+ * Nested calls reject with `UnitOfWorkAlreadyActiveError` before opening another boundary.
97
+ * Independent concurrent calls are allowed.
98
+ */
99
+ interface ITransaction<Tx> {
100
+ transaction<T>(work: (tx: Tx) => Promise<T>): Promise<T>;
101
+ }
102
+ //#endregion
103
+ //#region src/application/unit-of-work.d.ts
104
+ /**
105
+ * Commits the processed-message record, repository writes, and emitted events together before resolving.
106
+ * An existing record rejects with `MessageAlreadyProcessedError`; external effects must run through the outbox after commit.
107
+ * Nested calls reject with `UnitOfWorkAlreadyActiveError`; independent concurrent calls are allowed.
108
+ */
109
+ interface IUnitOfWork<Repos> {
110
+ run<T>(messageId: MessageId, work: (repos: Repos) => Promise<T>): Promise<T>;
111
+ }
112
+ type UnitOfWorkDeps<Tx, Repos> = {
113
+ readonly transaction: ITransaction<Tx>;
114
+ /** The processed-messages and outbox repository for this transaction. */
115
+ readonly messageStore: (tx: Tx) => IMessageStore;
116
+ /** Repositories participate in the current transaction. */
117
+ readonly createRepositories: (tx: Tx) => Repos;
118
+ readonly eventCollector: IEventCollector;
119
+ readonly relay: IOutboxRelay;
120
+ };
121
+ /** The unit of work: the boundary, the repositories, the events. Every database call is a port. */
122
+ declare class UnitOfWork<Tx, Repos> implements IUnitOfWork<Repos> {
123
+ private readonly deps;
124
+ constructor(deps: UnitOfWorkDeps<Tx, Repos>);
125
+ run<T>(messageId: MessageId, work: (repos: Repos) => Promise<T>): Promise<T>;
126
+ }
127
+ //#endregion
128
+ //#region src/application/record-email-event.d.ts
129
+ /** What a bounce records for one address. */
130
+ type EmailBounceRecord = {
131
+ readonly type: BounceType;
132
+ readonly subType: string | null;
133
+ };
134
+ /**
135
+ * The application's deliverability state per address. An implementation keeps the higher bounce
136
+ * severity with `shouldUpdateBounce`, and treats an unknown address as nothing to record.
137
+ */
138
+ interface IEmailDeliverabilityStore {
139
+ /** Keep the higher severity atomically. Equal severity permits replacement; the store owns timestamp ordering. */
140
+ recordBounce(address: EmailAddress, bounce: EmailBounceRecord): Promise<void>;
141
+ /** Record a complaint without clearing existing suppression state. */
142
+ recordComplaint(address: EmailAddress): Promise<void>;
143
+ }
144
+ /** The repositories the handler needs from the unit of work. */
145
+ type RecordEmailEventRepos = {
146
+ readonly emailDeliverability: IEmailDeliverabilityStore;
147
+ };
148
+ /** The container slice the handler reads. */
149
+ type RecordEmailEventDeps = {
150
+ readonly uow: IUnitOfWork<RecordEmailEventRepos>;
151
+ };
152
+ /** The command, under whatever name the application registered the payload. */
153
+ type RecordEmailEventCommand = DomainCommand & RecordEmailEventPayload;
154
+ /**
155
+ * Record a bounce or a complaint for every recipient inside the command's unit of work.
156
+ * The command id is the provider's event id, so a redelivered webhook is `MessageAlreadyProcessedError`.
157
+ */
158
+ declare function recordEmailEvent(command: RecordEmailEventCommand, deps: RecordEmailEventDeps): Promise<void>;
159
+ //#endregion
28
160
  //#region src/application/registry.d.ts
29
161
  /** One slot per command. `unknown` keeps the slot covariant; `MessageResult` recovers the value. */
30
162
  type CommandRegistry<TCommand extends DomainCommand, Deps> = { readonly [M in TCommand as M['name']]: CommandHandler<M, Deps, unknown>; };
@@ -94,58 +226,6 @@ declare class MessageBus<Deps, TRegistry extends Handlers<Deps>> implements IMes
94
226
  private handleEvent;
95
227
  }
96
228
  //#endregion
97
- //#region src/application/outbox-relay.d.ts
98
- /**
99
- * Delivers committed outbox rows. The unit of work only wakes it after a commit that wrote
100
- * events; the app decides what a wake is: `waitUntil`, a Durable Object alarm, nothing.
101
- * The sweep is the source of truth, so a lost wake loses no events.
102
- */
103
- interface IOutboxRelay {
104
- wake(): void;
105
- }
106
- //#endregion
107
- //#region src/application/transaction.d.ts
108
- /**
109
- * Supplies `Tx` to participating repositories and resolves after their writes commit. Failure rolls back or discards writes.
110
- * Nested calls reject with `UnitOfWorkAlreadyActiveError` before opening another boundary.
111
- * Independent concurrent calls are allowed.
112
- */
113
- interface ITransaction<Tx> {
114
- transaction<T>(work: (tx: Tx) => Promise<T>): Promise<T>;
115
- }
116
- //#endregion
117
- //#region src/application/event-collector.d.ts
118
- /** Records events in the current unit of work; the unit of work collects a snapshot for outbox persistence. */
119
- interface IEventCollector {
120
- emit(event: DomainEvent): void;
121
- collect(): ReadonlyArray<DomainEvent>;
122
- }
123
- //#endregion
124
- //#region src/application/unit-of-work.d.ts
125
- /**
126
- * Commits the processed-message record, repository writes, and emitted events together before resolving.
127
- * An existing record rejects with `MessageAlreadyProcessedError`; external effects must run through the outbox after commit.
128
- * Nested calls reject with `UnitOfWorkAlreadyActiveError`; independent concurrent calls are allowed.
129
- */
130
- interface IUnitOfWork<Repos> {
131
- run<T>(messageId: MessageId, work: (repos: Repos) => Promise<T>): Promise<T>;
132
- }
133
- type UnitOfWorkDeps<Tx, Repos> = {
134
- readonly transaction: ITransaction<Tx>;
135
- /** The processed-messages and outbox repository for this transaction. */
136
- readonly messageStore: (tx: Tx) => IMessageStore;
137
- /** Repositories participate in the current transaction. */
138
- readonly createRepositories: (tx: Tx) => Repos;
139
- readonly eventCollector: IEventCollector;
140
- readonly relay: IOutboxRelay;
141
- };
142
- /** The unit of work: the boundary, the repositories, the events. Every database call is a port. */
143
- declare class UnitOfWork<Tx, Repos> implements IUnitOfWork<Repos> {
144
- private readonly deps;
145
- constructor(deps: UnitOfWorkDeps<Tx, Repos>);
146
- run<T>(messageId: MessageId, work: (repos: Repos) => Promise<T>): Promise<T>;
147
- }
148
- //#endregion
149
229
  //#region src/application/message-already-processed.error.d.ts
150
230
  /** The message's effects already committed. A caller can skip duplicate delivery without repeating those effects. */
151
231
  declare class MessageAlreadyProcessedError extends AppError {
@@ -167,5 +247,5 @@ declare class UnitOfWorkAlreadyActiveError extends AppError {
167
247
  constructor();
168
248
  }
169
249
  //#endregion
170
- export { RegistryMessage as _, UnitOfWorkDeps as a, EventHandler as b, IOutboxRelay as c, CommandRegistry as d, EventRegistry as f, QueryRegistry as g, MessageResult as h, UnitOfWork as i, IMessageBus as l, MessageRegistry as m, MessageAlreadyProcessedError as n, IEventCollector as o, Handlers as p, IUnitOfWork as r, ITransaction as s, UnitOfWorkAlreadyActiveError as t, MessageBus as u, IMessageStore as v, QueryHandler as x, CommandHandler as y };
171
- //# sourceMappingURL=index-_Cihfq1J.d.ts.map
250
+ export { RecordingEmailService as A, IMessageStore as C, IEmailService as D, EmailAttachment as E, EventHandler as M, QueryHandler as N, MimeType as O, IOutboxRelay as S, EmailAccepted as T, recordEmailEvent as _, CommandRegistry as a, UnitOfWorkDeps as b, MessageRegistry as c, RegistryMessage as d, EmailBounceRecord as f, RecordEmailEventRepos as g, RecordEmailEventDeps as h, MessageBus as i, CommandHandler as j, OutboundEmail as k, MessageResult as l, RecordEmailEventCommand as m, MessageAlreadyProcessedError as n, EventRegistry as o, IEmailDeliverabilityStore as p, IMessageBus as r, Handlers as s, UnitOfWorkAlreadyActiveError as t, QueryRegistry as u, IUnitOfWork as v, IEventCollector as w, ITransaction as x, UnitOfWork as y };
251
+ //# sourceMappingURL=index-DgDyeR5s.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-DgDyeR5s.d.ts","names":[],"sources":["../src/application/handlers.ts","../src/application/email-service.ts","../src/application/event-collector.ts","../src/application/message-store.ts","../src/application/outbox-relay.ts","../src/application/transaction.ts","../src/application/unit-of-work.ts","../src/application/record-email-event.ts","../src/application/registry.ts","../src/application/message-bus.ts","../src/application/message-already-processed.error.ts","../src/application/unit-of-work.errors.ts"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
- import { W as DomainEvent, nt as DatabaseFailure, q as MessageId, tt as DatabaseError } from "./index-6XMPJu7u.js";
2
- import { s as ITransaction, v as IMessageStore } from "./index-_Cihfq1J.js";
3
- import { n as DrizzleSchema, t as eventCollector } from "./unit-of-work-context-BWTJfYPW.js";
1
+ import { W as DomainEvent, nt as DatabaseFailure, q as MessageId, tt as DatabaseError } from "./index-Bl0K1RQW.js";
2
+ import { C as IMessageStore, x as ITransaction } from "./index-DgDyeR5s.js";
3
+ import { n as DrizzleSchema, t as eventCollector } from "./unit-of-work-context-BzmnjlDa.js";
4
4
  import { ExtractTablesWithRelations } from "drizzle-orm";
5
5
  import { PostgresJsDatabase, PostgresJsTransaction, drizzle } from "drizzle-orm/postgres-js";
6
6
  //#region src/infrastructure/postgres/postgres-database-types.d.ts
package/dist/postgres.js CHANGED
@@ -1,6 +1,6 @@
1
- import { E as DatabaseError, U as AppError } from "./core-DC_4pOrI.js";
2
- import { i as MessageAlreadyProcessedError } from "./application-DYfcAy-Q.js";
3
- import { n as eventCollector, r as runWithUnitOfWorkContext } from "./unit-of-work-context-BFCmU92Z.js";
1
+ import { E as DatabaseError, Q as AppError } from "./core-DG_cC8YT.js";
2
+ import { i as MessageAlreadyProcessedError } from "./application-CIxo_BpK.js";
3
+ import { n as eventCollector, r as runWithUnitOfWorkContext } from "./unit-of-work-context-BPE1In2f.js";
4
4
  import { DrizzleQueryError } from "drizzle-orm/errors";
5
5
  import { isNull } from "drizzle-orm";
6
6
  import { index, integer, jsonb, pgTable, text, timestamp } from "drizzle-orm/pg-core";
@@ -0,0 +1,73 @@
1
+ import { jt as BounceType } from "./index-Bl0K1RQW.js";
2
+ import { D as IEmailService, T as EmailAccepted, k as OutboundEmail } from "./index-DgDyeR5s.js";
3
+ import { r as WebhookVerifier, t as WebhookVerification } from "./webhook-verification-sZtwTI5n.js";
4
+ import { Resend } from "resend";
5
+ //#region src/infrastructure/resend/resend-email-service.d.ts
6
+ /** The SDK operations required by the adapter; a test factory can return a plain object. */
7
+ type ResendEmailClient = {
8
+ readonly emails: Pick<Resend['emails'], 'send'>;
9
+ };
10
+ /**
11
+ * Send without package retries or logs. Ported from Suparelay's resend-email-service.ts.
12
+ * The Resend SDK itself logs API errors outside production.
13
+ */
14
+ export declare class ResendEmailService implements IEmailService {
15
+ private readonly createClient;
16
+ private readonly fromAddress;
17
+ /** Load the SDK on the first send. Constructing the service does not load it. */
18
+ static create(apiKey: string, fromAddress: string): ResendEmailService;
19
+ private client;
20
+ /** Supply an async factory. The service calls it once, on the first send, and keeps its promise. */
21
+ constructor(createClient: () => Promise<ResendEmailClient>, fromAddress: string);
22
+ /** Resolve after acceptance. Provider failures throw EmailServiceError; SDK defects retain their identity. */
23
+ sendEmail(email: OutboundEmail): Promise<EmailAccepted>;
24
+ }
25
+ //#endregion
26
+ //#region src/infrastructure/resend/email-event.d.ts
27
+ declare const SIMPLE_EMAIL_TYPES: readonly ['email.sent', 'email.scheduled', 'email.delivered', 'email.delivery_delayed', 'email.complained', 'email.opened', 'email.received', 'email.suppressed'];
28
+ /** Resend email event names supported by this module. */
29
+ type EmailEventType = (typeof SIMPLE_EMAIL_TYPES)[number] | 'email.bounced' | 'email.failed' | 'email.clicked';
30
+ type EmailEventBase = {
31
+ readonly id: string;
32
+ readonly emailId: string;
33
+ readonly recipients: readonly string[];
34
+ readonly subject: string;
35
+ readonly tags: Readonly<Record<string, string>>;
36
+ readonly occurredAt: string;
37
+ };
38
+ /** A verified event. `id` is the Svix identity; use `resend:event:${id}` as the command id. */
39
+ type EmailEvent = (EmailEventBase & {
40
+ readonly type: 'email.bounced';
41
+ readonly bounce: {
42
+ readonly type: BounceType;
43
+ readonly subType: string | null;
44
+ readonly message: string;
45
+ };
46
+ }) | (EmailEventBase & {
47
+ readonly type: 'email.failed';
48
+ readonly reason: string;
49
+ }) | (EmailEventBase & {
50
+ readonly type: 'email.clicked';
51
+ readonly link: string;
52
+ }) | (EmailEventBase & {
53
+ readonly type: (typeof SIMPLE_EMAIL_TYPES)[number];
54
+ });
55
+ //#endregion
56
+ //#region src/infrastructure/resend/resend-webhook.d.ts
57
+ /** The SDK's local signature verifier. It makes no API request. */
58
+ type ResendWebhookClient = Pick<Resend['webhooks'], 'verify'>;
59
+ /** Verify Svix signatures and map Resend email events. Ported from Typist's Resend route. */
60
+ export declare class ResendWebhook implements WebhookVerifier<EmailEvent> {
61
+ private readonly webhookSecret;
62
+ private readonly verifier;
63
+ /** Load the SDK on the first verification. Only the webhook secret is required. */
64
+ static create(webhookSecret: string): ResendWebhook;
65
+ private client;
66
+ /** Inject the local SDK verifier when testing. */
67
+ constructor(webhookSecret: string, verifier: () => Promise<ResendWebhookClient>);
68
+ /** Verify the raw body and Svix headers. Invalid requests return rejected; configuration and SDK defects propagate. */
69
+ verify(body: string, headers: Headers): Promise<WebhookVerification<EmailEvent>>;
70
+ }
71
+ //#endregion
72
+ export type { EmailEvent, EmailEventType, ResendEmailClient, ResendWebhookClient };
73
+ //# sourceMappingURL=resend.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resend.d.ts","names":[],"sources":["../src/infrastructure/resend/resend-email-service.ts","../src/infrastructure/resend/email-event.ts","../src/infrastructure/resend/resend-webhook.ts"],"mappings":";;;;;;KAsEY;WAA+B,QAAQ,KAAK;;;;;;qBAM3C,8BAA8B;mBAatB;mBACA;;SAZZ,OAAO,gBAAgB,sBAAsB;UAO5C;;EAGR,YACmB,oBAAoB,QAAQ,oBAC5B;;EAIb,UAAU,OAAO,gBAAgB,QAAQ;;;;cCzF3C;;KAYM,yBACA;KAgDP;WACM;WACA;WACA;WACA;WACA,MAAM,SAAS;WACf;;;KAIC,cACP;WACU;WACA;aACE,MAAM;aACN;aACA;;MAGZ;WAA4B;WAA+B;MAC3D;WAA4B;WAAgC;MAC5D;WAA4B,cAAc;;;;;KCvEnC,sBAAsB,KAAK;;qBAG1B,yBAAyB,gBAAgB;mBAcjC;mBACA;;SAbZ,OAAO,wBAAwB;UAQ9B;;EAGR,YACmB,uBACA,gBAAgB,QAAQ;;EAIrC,OAAO,cAAc,SAAS,UAAU,QAAQ,oBAAoB"}