better-ship 0.5.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/dist/{application-DEerezCl.js → application-DjsQtpgw.js} +2 -2
  2. package/dist/application-DjsQtpgw.js.map +1 -0
  3. package/dist/application.d.ts +3 -2
  4. package/dist/application.js +1 -1
  5. package/dist/better-auth/apple-client-secret.d.ts +1 -1
  6. package/dist/better-auth/apple-client-secret.js +1 -1
  7. package/dist/better-auth/auth-client.js +1 -1
  8. package/dist/better-auth/rate-limit.d.ts +1 -1
  9. package/dist/better-auth/rate-limit.js +1 -1
  10. package/dist/better-auth.js +2 -2
  11. package/dist/cloudflare/auth-secondary-storage.d.ts +1 -1
  12. package/dist/cloudflare/auth-secondary-storage.js +1 -1
  13. package/dist/cloudflare.d.ts +7 -7
  14. package/dist/cloudflare.d.ts.map +1 -1
  15. package/dist/cloudflare.js +3 -3
  16. package/dist/cloudflare.js.map +1 -1
  17. package/dist/{core-CnwWj4MY.js → core-Cx5SeyKV.js} +91 -2
  18. package/dist/core-Cx5SeyKV.js.map +1 -0
  19. package/dist/core.d.ts +2 -2
  20. package/dist/core.js +2 -2
  21. package/dist/{index-B9Y1hVh6.d.ts → index-BStnggQO.d.ts} +126 -2
  22. package/dist/index-BStnggQO.d.ts.map +1 -0
  23. package/dist/{index-Bdyh3_xC.d.ts → index-DWIRrJMP.d.ts} +21 -50
  24. package/dist/index-DWIRrJMP.d.ts.map +1 -0
  25. package/dist/postgres.d.ts +7 -7
  26. package/dist/postgres.d.ts.map +1 -1
  27. package/dist/postgres.js +3 -3
  28. package/dist/postgres.js.map +1 -1
  29. package/dist/tanstack.d.ts +8 -1
  30. package/dist/tanstack.d.ts.map +1 -1
  31. package/dist/tanstack.js +13 -2
  32. package/dist/tanstack.js.map +1 -1
  33. package/dist/{unit-of-work-context-ml9L9cyY.d.ts → unit-of-work-context-CPz9rdSS.d.ts} +3 -2
  34. package/dist/unit-of-work-context-CPz9rdSS.d.ts.map +1 -0
  35. package/dist/{unit-of-work-context-C7vz5OYS.js → unit-of-work-context-DToDpAkv.js} +2 -2
  36. package/dist/unit-of-work-context-DToDpAkv.js.map +1 -0
  37. package/package.json +1 -1
  38. package/src/application/event-collector.ts +3 -3
  39. package/src/application/handlers.ts +7 -4
  40. package/src/application/index.ts +1 -1
  41. package/src/application/message-already-processed.error.ts +1 -3
  42. package/src/application/message-bus.ts +14 -8
  43. package/src/application/message-store.ts +2 -2
  44. package/src/application/registry.ts +14 -13
  45. package/src/application/unit-of-work.ts +2 -1
  46. package/src/core/define-messages.ts +136 -0
  47. package/src/core/entity.ts +33 -0
  48. package/src/core/identity.ts +29 -0
  49. package/src/core/index.ts +19 -0
  50. package/src/{application → core}/messages.ts +4 -4
  51. package/src/infrastructure/cloudflare/base-d1-repository.ts +2 -2
  52. package/src/infrastructure/cloudflare/d1-message-store.ts +3 -7
  53. package/src/infrastructure/cloudflare/d1-schema.ts +2 -2
  54. package/src/infrastructure/postgres/base-postgres-repository.ts +2 -2
  55. package/src/infrastructure/postgres/postgres-message-store.ts +3 -7
  56. package/src/infrastructure/postgres/postgres-schema.ts +2 -2
  57. package/src/infrastructure/tanstack/index.ts +1 -0
  58. package/src/infrastructure/tanstack/last-login-method.ts +13 -0
  59. package/src/infrastructure/unit-of-work-context.ts +3 -2
  60. package/dist/application-DEerezCl.js.map +0 -1
  61. package/dist/core-CnwWj4MY.js.map +0 -1
  62. package/dist/index-B9Y1hVh6.d.ts.map +0 -1
  63. package/dist/index-Bdyh3_xC.d.ts.map +0 -1
  64. package/dist/unit-of-work-context-C7vz5OYS.js.map +0 -1
  65. package/dist/unit-of-work-context-ml9L9cyY.d.ts.map +0 -1
@@ -325,6 +325,130 @@ declare function unreachable(value: never): never;
325
325
  */
326
326
  declare function notImplemented(what: string): never;
327
327
  //#endregion
328
+ //#region src/core/identity.d.ts
329
+ /** A string only `create()` or `schema.parse()` of the same kind can produce. */
330
+ type Id<Brand extends string> = string & z.core.$brand<Brand>;
331
+ /** One id kind the application mints. `schema` parses untrusted input; `create` mints a uuid v7. */
332
+ type IdDefinition<Brand extends string> = {
333
+ readonly schema: z.core.$ZodBranded<z.ZodUUID, Brand>;
334
+ /** Mint a new time-ordered id. No parse: we produced it, so it is valid by construction. */
335
+ create(): Id<Brand>;
336
+ };
337
+ /** The id type of a definition: `type CallId = IdOf<typeof CallId>`. */
338
+ type IdOf<Definition extends IdDefinition<string>> = z.output<Definition['schema']>;
339
+ /**
340
+ * Define an id kind the application mints: `export const CallId = defineId('CallId')`.
341
+ * An id another system mints, such as a provider's call id, stays a plain branded schema.
342
+ */
343
+ declare function defineId<const Brand extends string>(brand: Brand): IdDefinition<Brand>;
344
+ //#endregion
345
+ //#region src/core/messages.d.ts
346
+ /**
347
+ * The identity of a command or event. Receipts and the outbox are keyed by it.
348
+ *
349
+ * Internal messages use UUID v7, so receipts sort by creation. External messages use the
350
+ * provider's own key, `stripe:event:evt_123`, so a redelivered webhook is a duplicate by
351
+ * construction. The app parses and generates ids; this package only carries them.
352
+ */
353
+ type MessageId = string;
354
+ /** An action to perform. One handler, returns a value. The product adds its payload. */
355
+ type DomainCommand<Name extends string = string> = {
356
+ readonly type: 'command';
357
+ readonly name: Name;
358
+ readonly id: MessageId;
359
+ };
360
+ /** A request for data. One handler, returns a value. No id: nothing claims a read. */
361
+ type DomainQuery<Name extends string = string> = {
362
+ readonly type: 'query';
363
+ readonly name: Name;
364
+ };
365
+ /** A fact that happened. Zero or more subscribers, returns nothing. The product adds its payload. */
366
+ type DomainEvent<Name extends string = string> = {
367
+ readonly type: 'event';
368
+ readonly name: Name;
369
+ readonly id: MessageId;
370
+ };
371
+ /** The routing fields the bus reads. `type` selects the table, `name` selects the slot. */
372
+ type DomainMessage = DomainCommand | DomainEvent | DomainQuery;
373
+ //#endregion
374
+ //#region src/core/define-messages.d.ts
375
+ /** Payload schemas keyed by message name. A payload never carries `type`, `name`, or `id`. */
376
+ type PayloadSchemas = Readonly<Record<string, z.ZodType<object>>>;
377
+ /** An application's messages: one list of payload schemas per kind. */
378
+ type MessageDefinition = {
379
+ readonly commands: PayloadSchemas;
380
+ readonly events: PayloadSchemas;
381
+ readonly queries: PayloadSchemas;
382
+ };
383
+ type AnyMessages = {
384
+ readonly definition: MessageDefinition;
385
+ };
386
+ type Def<Messages extends AnyMessages> = Messages['definition'];
387
+ type Payload<Schemas extends PayloadSchemas, Name extends keyof Schemas> = z.output<Schemas[Name]>;
388
+ /** Every command of an application: `CommandOf<typeof messages>`. */
389
+ type CommandOf<Messages extends AnyMessages> = { [Name in keyof Def<Messages>['commands'] & string]: DomainCommand<Name> & Payload<Def<Messages>['commands'], Name>; }[keyof Def<Messages>['commands'] & string];
390
+ /** Every event of an application: `EventOf<typeof messages>`. */
391
+ type EventOf<Messages extends AnyMessages> = { [Name in keyof Def<Messages>['events'] & string]: DomainEvent<Name> & Payload<Def<Messages>['events'], Name>; }[keyof Def<Messages>['events'] & string];
392
+ /** Every query of an application: `QueryOf<typeof messages>`. */
393
+ type QueryOf<Messages extends AnyMessages> = { [Name in keyof Def<Messages>['queries'] & string]: DomainQuery<Name> & Payload<Def<Messages>['queries'], Name>; }[keyof Def<Messages>['queries'] & string];
394
+ /** Every message of an application: what the registry and the bus are typed with. */
395
+ type MessageOf<Messages extends AnyMessages> = CommandOf<Messages> | EventOf<Messages> | QueryOf<Messages>;
396
+ /**
397
+ * What `defineMessages` returns. The factories build messages for in-process dispatch without
398
+ * parsing; the data is already typed. The schemas parse untrusted input at a boundary.
399
+ */
400
+ type AppMessages<Definition extends MessageDefinition> = {
401
+ readonly definition: Definition;
402
+ /** Build a command. `id` defaults to a uuid v7; a webhook passes the provider's key, `stripe:event:evt_123`. */
403
+ createCommand<Name extends keyof Definition['commands'] & string>(name: Name, payload: Payload<Definition['commands'], Name>, id?: MessageId): DomainCommand<Name> & Payload<Definition['commands'], Name>;
404
+ /** Build an event. `id` defaults to a uuid v7, which also orders it in time. */
405
+ createEvent<Name extends keyof Definition['events'] & string>(name: Name, payload: Payload<Definition['events'], Name>, id?: MessageId): DomainEvent<Name> & Payload<Definition['events'], Name>;
406
+ /** Build a query. No id: nothing claims a read. */
407
+ createQuery<Name extends keyof Definition['queries'] & string>(name: Name, payload: Payload<Definition['queries'], Name>): DomainQuery<Name> & Payload<Definition['queries'], Name>;
408
+ readonly commandSchema: z.ZodType<CommandOf<AppMessages<Definition>>>;
409
+ readonly eventSchema: z.ZodType<EventOf<AppMessages<Definition>>>;
410
+ readonly querySchema: z.ZodType<QueryOf<AppMessages<Definition>>>;
411
+ /** What a queue body may be: a command or an event. Queries never cross a queue. */
412
+ readonly queueSchema: z.ZodType<CommandOf<AppMessages<Definition>> | EventOf<AppMessages<Definition>>>;
413
+ };
414
+ type RoutingField = 'type' | 'name' | 'id';
415
+ /** A payload that declares a routing field maps to `never`, so `defineMessages` rejects it. */
416
+ type WithoutRoutingFields<Schemas extends PayloadSchemas> = { readonly [Name in keyof Schemas]: keyof z.output<Schemas[Name]> & RoutingField extends never ? Schemas[Name] : never; };
417
+ /** The compile-time rule: no payload of any kind declares `type`, `name`, or `id`. */
418
+ type ValidDefinition<Definition extends MessageDefinition> = {
419
+ readonly commands: WithoutRoutingFields<Definition['commands']>;
420
+ readonly events: WithoutRoutingFields<Definition['events']>;
421
+ readonly queries: WithoutRoutingFields<Definition['queries']>;
422
+ };
423
+ /**
424
+ * Define an application's messages once. The key is the name; the factories add the routing
425
+ * fields `type`, `name`, and `id`. A payload that declares one of them is a compile error.
426
+ */
427
+ declare function defineMessages<const Definition extends MessageDefinition>(definition: Definition & ValidDefinition<Definition>): AppMessages<Definition>;
428
+ //#endregion
429
+ //#region src/core/entity.d.ts
430
+ /** What an aggregate's plain data must have: an identity. A branded id keeps its brand. */
431
+ type EntityData = {
432
+ readonly id: string;
433
+ };
434
+ /**
435
+ * The base of an aggregate: its identity, the events it raised, and the plain data a repository
436
+ * stores. The subclass keeps its constructor private and declares `static restore(data: Data)`,
437
+ * the one door a repository rebuilds it through. A repository drains the events after `save`.
438
+ */
439
+ declare abstract class Entity<Data extends EntityData, TEvent extends DomainEvent = DomainEvent> {
440
+ private events;
441
+ abstract readonly id: Data['id'];
442
+ /** Record one event with the state change that caused it. The unit of work commits both. */
443
+ protected addEvent(event: TEvent): void;
444
+ /** A copy of the events raised since the last `clearEvents`. */
445
+ collectEvents(): ReadonlyArray<TEvent>;
446
+ /** Forget the raised events once the boundary has taken them. */
447
+ clearEvents(): void;
448
+ /** Plain data for the repository. The subclass's `restore(data)` accepts exactly this. */
449
+ abstract toPlainObject(): Data;
450
+ }
451
+ //#endregion
328
452
  //#region src/core/transport-classification.d.ts
329
453
  /** Cancellation is a decision, not a failure to repeat. */
330
454
  declare function isAbortError(cause: unknown): boolean;
@@ -456,5 +580,5 @@ declare class Logger {
456
580
  /** Create a logger for one module. */
457
581
  declare function createLogger(module: string, config?: LoggerConfig): Logger;
458
582
  //#endregion
459
- export { AppError as $, ErrorTable as A, ValidationIssue as B, unreachable as C, ErrorEntries as D, DatabaseFailure as E, MalformedRequestError as F, ValidationProblemError as G, ProblemDetailsSchema as H, RequestTimeoutError as I, ServiceUnavailableError as J, ValidationProblemErrorSchema as K, ResourceNotFoundError as L, ResolvedError as M, defineErrors as N, ErrorEntry as O, sharedErrors as P, AuthenticationError as Q, UpgradeRequiredError as R, notImplemented as S, DatabaseError as T, ValidationProblemDetails as U, ProblemDetails as V, ValidationProblemDetailsSchema as W, StaleSessionError as X, NotAuthorizedError as Y, RateLimitError as Z, createLogger as _, LogFormat as a, isAbortError as b, LogThreshold as c, LoggerConfig as d, FailureClassification as et, LoggerErrorHook as f, consoleSink as g, configureLogger as h, LogFields as i, ErrorTagOf as j, ErrorPayloadOf as k, LogValue as l, SerializedError as m, ErrorLogContext as n, shouldRetryFailure as nt, LogLevel as o, LoggerSettings as p, InternalServerError as q, LogEntry as r, LogSink as s, ErrorCaptureEntry as t, RetryOwner as tt, Logger as u, setLogSink as v, D1ConstraintKind as w, isTransientTransportError as x, setLoggerErrorHook as y, ValidationError as z };
460
- //# sourceMappingURL=index-B9Y1hVh6.d.ts.map
583
+ export { sharedErrors as $, QueryOf as A, defineId as B, EntityData as C, MessageDefinition as D, EventOf as E, DomainQuery as F, DatabaseFailure as G, unreachable as H, MessageId as I, ErrorPayloadOf as J, ErrorEntries as K, Id as L, DomainCommand as M, DomainEvent as N, MessageOf as O, DomainMessage as P, defineErrors as Q, IdDefinition as R, Entity as S, CommandOf as T, D1ConstraintKind as U, notImplemented as V, DatabaseError as W, ErrorTagOf as X, ErrorTable as Y, ResolvedError as Z, createLogger as _, AuthenticationError as _t, LogFormat as a, ValidationIssue as at, isAbortError as b, RetryOwner as bt, LogThreshold as c, ValidationProblemDetails as ct, LoggerConfig as d, ValidationProblemErrorSchema as dt, MalformedRequestError as et, LoggerErrorHook as f, InternalServerError as ft, consoleSink as g, RateLimitError as gt, configureLogger as h, StaleSessionError as ht, LogFields as i, ValidationError as it, defineMessages as j, PayloadSchemas as k, LogValue as l, ValidationProblemDetailsSchema as lt, SerializedError as m, NotAuthorizedError as mt, ErrorLogContext as n, ResourceNotFoundError as nt, LogLevel as o, ProblemDetails as ot, LoggerSettings as p, ServiceUnavailableError as pt, ErrorEntry as q, LogEntry as r, UpgradeRequiredError as rt, LogSink as s, ProblemDetailsSchema as st, ErrorCaptureEntry as t, RequestTimeoutError as tt, Logger as u, ValidationProblemError as ut, setLogSink as v, AppError as vt, AppMessages as w, isTransientTransportError as x, shouldRetryFailure as xt, setLoggerErrorHook as y, FailureClassification as yt, IdOf as z };
584
+ //# sourceMappingURL=index-BStnggQO.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-BStnggQO.d.ts","names":[],"sources":["../src/core/failure-classification.ts","../src/core/app-error.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/logger.ts"],"mappings":"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"}
@@ -1,46 +1,17 @@
1
- import { $ as AppError } from "./index-B9Y1hVh6.js";
2
- //#region src/application/messages.d.ts
3
- /**
4
- * The identity of a command or event. Receipts and the outbox are keyed by it.
5
- *
6
- * Internal messages use UUID v7, so receipts sort by creation. External messages use the
7
- * provider's own key, `stripe:event:evt_123`, so a redelivered webhook is a duplicate by
8
- * construction. The app parses and generates ids; this package only carries them.
9
- */
10
- type MessageId = string;
11
- /** An action to perform. One handler, returns a value. The product adds its payload. */
12
- type Command<Name extends string = string> = {
13
- readonly type: 'command';
14
- readonly name: Name;
15
- readonly id: MessageId;
16
- };
17
- /** A request for data. One handler, returns a value. No id: nothing claims a read. */
18
- type Query<Name extends string = string> = {
19
- readonly type: 'query';
20
- readonly name: Name;
21
- };
22
- /** A fact that happened. Zero or more subscribers, returns nothing. The product adds its payload. */
23
- type Event<Name extends string = string> = {
24
- readonly type: 'event';
25
- readonly name: Name;
26
- readonly id: MessageId;
27
- };
28
- /** The routing fields the bus reads. `type` selects the table, `name` selects the slot. */
29
- type Message = Command | Event | Query;
30
- //#endregion
1
+ import { F as DomainQuery, I as MessageId, M as DomainCommand, N as DomainEvent, P as DomainMessage, vt as AppError } from "./index-BStnggQO.js";
31
2
  //#region src/application/handlers.d.ts
32
3
  /**
33
4
  * Handles one command with the dependency container and returns the caller's value.
34
5
  * A handler that writes inside a transaction opens the unit of work itself. Failures throw.
35
6
  */
36
- type CommandHandler<TCommand extends Command, Deps, Value> = (command: TCommand, deps: Deps) => Promise<Value>;
7
+ type CommandHandler<TCommand extends DomainCommand, Deps, Value> = (command: TCommand, deps: Deps) => Promise<Value>;
37
8
  /**
38
9
  * Handles one query with the read-only view of the container.
39
10
  * The view is a type over the same object, so a query cannot name a write capability.
40
11
  */
41
- type QueryHandler<TQuery extends Query, QueryDeps, Value> = (query: TQuery, deps: QueryDeps) => Promise<Value>;
12
+ type QueryHandler<TQuery extends DomainQuery, QueryDeps, Value> = (query: TQuery, deps: QueryDeps) => Promise<Value>;
42
13
  /** Completes one subscriber's work for an event. Failures throw. */
43
- type EventHandler<TEvent extends Event, Deps> = (event: TEvent, deps: Deps) => Promise<void>;
14
+ type EventHandler<TEvent extends DomainEvent, Deps> = (event: TEvent, deps: Deps) => Promise<void>;
44
15
  //#endregion
45
16
  //#region src/application/message-store.d.ts
46
17
  /**
@@ -51,34 +22,34 @@ interface IMessageStore {
51
22
  /** Record this message in the transaction; reject an existing record with `MessageAlreadyProcessedError`. */
52
23
  claim(messageId: MessageId): Promise<void>;
53
24
  /** Write the events to the outbox, inside the same boundary as the state change. */
54
- persistEvents(events: ReadonlyArray<Event>): Promise<void>;
25
+ persistEvents(events: ReadonlyArray<DomainEvent>): Promise<void>;
55
26
  }
56
27
  //#endregion
57
28
  //#region src/application/registry.d.ts
58
29
  /** One slot per command. `unknown` keeps the slot covariant; `MessageResult` recovers the value. */
59
- type CommandRegistry<TCommand extends Command, Deps> = { readonly [M in TCommand as M['name']]: CommandHandler<M, Deps, unknown>; };
30
+ type CommandRegistry<TCommand extends DomainCommand, Deps> = { readonly [M in TCommand as M['name']]: CommandHandler<M, Deps, unknown>; };
60
31
  /** One slot per query, typed with the read-only view of the container. */
61
- type QueryRegistry<TQuery extends Query, QueryDeps> = { readonly [M in TQuery as M['name']]: QueryHandler<M, QueryDeps, unknown>; };
32
+ type QueryRegistry<TQuery extends DomainQuery, QueryDeps> = { readonly [M in TQuery as M['name']]: QueryHandler<M, QueryDeps, unknown>; };
62
33
  /**
63
34
  * Zero or more subscribers per event. Annotate the object with this type rather than
64
35
  * `satisfies`, so an event with no subscribers is still a message the bus accepts.
65
36
  */
66
- type EventRegistry<TEvent extends Event, Deps> = { readonly [M in TEvent as M['name']]?: ReadonlyArray<EventHandler<M, Deps>>; };
37
+ type EventRegistry<TEvent extends DomainEvent, Deps> = { readonly [M in TEvent as M['name']]?: ReadonlyArray<EventHandler<M, Deps>>; };
67
38
  /**
68
39
  * The app's three tables. `satisfies MessageRegistry<AppMessage, AppDeps, AppQueryDeps>`
69
40
  * makes a missing handler a compile error. `Deps extends QueryDeps` is checked here, the one
70
41
  * place both types meet: the read view must be a subset of the container.
71
42
  */
72
- type MessageRegistry<TMessage extends Message, Deps extends QueryDeps, QueryDeps> = {
73
- readonly commands: CommandRegistry<Extract<TMessage, Command>, Deps>;
74
- readonly queries: QueryRegistry<Extract<TMessage, Query>, QueryDeps>;
75
- readonly events: EventRegistry<Extract<TMessage, Event>, Deps>;
43
+ type MessageRegistry<TMessage extends DomainMessage, Deps extends QueryDeps, QueryDeps> = {
44
+ readonly commands: CommandRegistry<Extract<TMessage, DomainCommand>, Deps>;
45
+ readonly queries: QueryRegistry<Extract<TMessage, DomainQuery>, QueryDeps>;
46
+ readonly events: EventRegistry<Extract<TMessage, DomainEvent>, Deps>;
76
47
  };
77
48
  type Slot<Deps> = {
78
- handle(message: Message, deps: Deps): Promise<unknown>;
49
+ handle(message: DomainMessage, deps: Deps): Promise<unknown>;
79
50
  }['handle'];
80
51
  type Subscription<Deps> = {
81
- handle(event: Event, deps: Deps): Promise<void>;
52
+ handle(event: DomainEvent, deps: Deps): Promise<void>;
82
53
  }['handle'];
83
54
  /**
84
55
  * The registry as the bus routes it: each table keyed by name. The app's names are unknown
@@ -95,12 +66,12 @@ type SubscriptionMessage<TSlots> = NonNullable<TSlots[keyof TSlots]> extends Rea
95
66
  type RegistryMessage<TRegistry extends Handlers<never>> = SlotMessage<TRegistry['commands']> | SlotMessage<TRegistry['queries']> | SubscriptionMessage<TRegistry['events']>;
96
67
  type SlotValue<TSlots, TName extends string> = TName extends keyof TSlots ? Awaited<ReturnType<Extract<TSlots[TName], Slot<never>>>> : never;
97
68
  /** The value `bus.handle(message)` resolves to: the slot's own return type, or void for an event. */
98
- type MessageResult<TMessage extends Message, TRegistry extends Handlers<never>> = TMessage extends Command ? SlotValue<TRegistry['commands'], TMessage['name']> : TMessage extends Query ? SlotValue<TRegistry['queries'], TMessage['name']> : void;
69
+ type MessageResult<TMessage extends DomainMessage, TRegistry extends Handlers<never>> = TMessage extends DomainCommand ? SlotValue<TRegistry['commands'], TMessage['name']> : TMessage extends DomainQuery ? SlotValue<TRegistry['queries'], TMessage['name']> : void;
99
70
  //#endregion
100
71
  //#region src/application/message-bus.d.ts
101
72
  /** The port an entrypoint dispatches through. `AppDeps` names this as `IMessageBus<typeof registry>`. */
102
73
  interface IMessageBus<TRegistry extends Handlers<never>> {
103
- handle<TMessage extends Message & RegistryMessage<TRegistry>>(message: TMessage): Promise<MessageResult<TMessage, TRegistry>>;
74
+ handle<TMessage extends DomainMessage & RegistryMessage<TRegistry>>(message: TMessage): Promise<MessageResult<TMessage, TRegistry>>;
104
75
  }
105
76
  /**
106
77
  * Routes one message to its slot. The bus opens no transaction and keeps no outbox:
@@ -111,7 +82,7 @@ declare class MessageBus<Deps, TRegistry extends Handlers<Deps>> implements IMes
111
82
  private readonly registry;
112
83
  constructor(deps: Deps, registry: TRegistry);
113
84
  /** Resolves to the handler's own value for a command or query, and to void for an event. */
114
- handle<TMessage extends Message & RegistryMessage<TRegistry>>(message: TMessage): Promise<MessageResult<TMessage, TRegistry>>;
85
+ handle<TMessage extends DomainMessage & RegistryMessage<TRegistry>>(message: TMessage): Promise<MessageResult<TMessage, TRegistry>>;
115
86
  private dispatch;
116
87
  private handleCommand;
117
88
  private handleQuery;
@@ -146,8 +117,8 @@ interface ITransaction<Tx> {
146
117
  //#region src/application/event-collector.d.ts
147
118
  /** Records events in the current unit of work; the unit of work collects a snapshot for outbox persistence. */
148
119
  interface IEventCollector {
149
- emit(event: Event): void;
150
- collect(): ReadonlyArray<Event>;
120
+ emit(event: DomainEvent): void;
121
+ collect(): ReadonlyArray<DomainEvent>;
151
122
  }
152
123
  //#endregion
153
124
  //#region src/application/unit-of-work.d.ts
@@ -196,5 +167,5 @@ declare class UnitOfWorkAlreadyActiveError extends AppError {
196
167
  constructor();
197
168
  }
198
169
  //#endregion
199
- export { Event as C, Query as E, Command as S, MessageId as T, 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, Message as w, QueryHandler as x, CommandHandler as y };
200
- //# sourceMappingURL=index-Bdyh3_xC.d.ts.map
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-DWIRrJMP.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-DWIRrJMP.d.ts","names":[],"sources":["../src/application/handlers.ts","../src/application/message-store.ts","../src/application/registry.ts","../src/application/message-bus.ts","../src/application/outbox-relay.ts","../src/application/transaction.ts","../src/application/event-collector.ts","../src/application/unit-of-work.ts","../src/application/message-already-processed.error.ts","../src/application/unit-of-work.errors.ts"],"mappings":";;;;;;KAMY,eAAe,iBAAiB,eAAe,MAAM,UAC/D,SAAS,UACT,MAAM,SACH,QAAQ;;;;;KAMD,aAAa,eAAe,aAAa,WAAW,UAC9D,OAAO,QACP,MAAM,cACH,QAAQ;;KAGD,aAAa,eAAe,aAAa,SACnD,OAAO,QACP,MAAM,SACH;;;;;;;UClBY;;EAEf,MAAM,WAAW,YAAY;;EAE7B,cAAc,QAAQ,cAAc,eAAe;;;;;KCLzC,gBAAgB,iBAAiB,eAAe,oBAChD,KAAK,YAAY,YAAY,eAAe,GAAG;;KAI/C,cAAc,eAAe,aAAa,yBAC1C,KAAK,UAAU,YAAY,aAAa,GAAG;;;;;KAO3C,cAAc,eAAe,aAAa,oBAC1C,KAAK,UAAU,aAAa,cAAc,aAAa,GAAG;;;;;;KAQ1D,gBAAgB,iBAAiB,eAAe,aAAa,WAAW;WACzE,UAAU,gBAAgB,QAAQ,UAAU,gBAAgB;WAC5D,SAAS,cAAc,QAAQ,UAAU,cAAc;WACvD,QAAQ,cAAc,QAAQ,UAAU,cAAc;;KAK5D,KAAK;EAAU,OAAO,SAAS,eAAe,MAAM,OAAO;;KAC3D,aAAa;EAAU,OAAO,OAAO,aAAa,MAAM,OAAO;;;;;;KAMxD,SAAS;WACV,UAAU,SAAS,eAAe,KAAK;WACvC,SAAS,SAAS,eAAe,KAAK;WACtC,QAAQ,SAAS,QAAQ,eAAe,cAAc,aAAa;;KAGzE,YAAY,UAAU,WAAW,QAAQ,aAAa,SAAS;KAE/D,oBAAoB,UACvB,YAAY,aAAa,iBAAiB,oBAAoB,iBAC1D,WAAW,QAAQ,eAAe;;KAI5B,gBAAgB,kBAAkB,mBAC1C,YAAY,yBACZ,YAAY,wBACZ,oBAAoB;KAEnB,UAAU,QAAQ,wBAAwB,oBAAoB,SAC/D,QAAQ,WAAW,QAAQ,OAAO,QAAQ;;KAIlC,cACV,iBAAiB,eACjB,kBAAkB,mBAChB,iBAAiB,gBACjB,UAAU,uBAAuB,oBACjC,iBAAiB,cACf,UAAU,sBAAsB;;;;UCvDrB,YAAY,kBAAkB;EAC7C,OAAO,iBAAiB,gBAAgB,gBAAgB,YACtD,SAAS,WACR,QAAQ,cAAc,UAAU;;;;;;cAOxB,WAAW,MAAM,kBAAkB,SAAS,kBAAkB,YAAY;mBAElE;mBACA;EAFnB,YACmB,MAAM,MACN,UAAU;;EAIvB,OAAO,iBAAiB,gBAAgB,gBAAgB,YAC5D,SAAS,WACR,QAAQ,cAAc,UAAU;UAM3B;UASA;UASA;;;;;;UAWM;;;;;;;;;UClEC;EACf;;;;;;;;;UCDe,aAAa;EAC5B,YAAY,GAAG,OAAO,IAAI,OAAO,QAAQ,KAAK,QAAQ;;;;;UCHvC;EACf,KAAK,OAAO;EACZ,WAAW,cAAc;;;;;;;;;UCQV,YAAY;EAC3B,IAAI,GAAG,WAAW,WAAW,OAAO,OAAO,UAAU,QAAQ,KAAK,QAAQ;;KAGhE,eAAe,IAAI;WACpB,aAAa,aAAa;;WAE1B,eAAe,IAAI,OAAO;;WAE1B,qBAAqB,IAAI,OAAO;WAChC,gBAAgB;WAChB,OAAO;;;cAIL,WAAW,IAAI,kBAAkB,YAAY;mBAC3B;EAA7B,YAA6B,MAAM,eAAe,IAAI;EAEhD,IAAI,GAAG,WAAW,WAAW,OAAO,OAAO,UAAU,QAAQ,KAAK,QAAQ;;;;;cC5BrE,qCAAqC;WAKrC,WAAW;WAJb;WACA;EAET,YACW,WAAW,WACpB;aAAqB;;;SAMhB,KAAK,gBAAgB,WAAW,YAAY;;;;;cCZxC,qCAAqC;WACvC;WACA;EAET"}
@@ -1,6 +1,6 @@
1
- import { C as Event, T as MessageId, s as ITransaction, v as IMessageStore } from "./index-Bdyh3_xC.js";
2
- import { E as DatabaseFailure, T as DatabaseError } from "./index-B9Y1hVh6.js";
3
- import { n as DrizzleSchema, t as eventCollector } from "./unit-of-work-context-ml9L9cyY.js";
1
+ import { G as DatabaseFailure, I as MessageId, N as DomainEvent, W as DatabaseError } from "./index-BStnggQO.js";
2
+ import { s as ITransaction, v as IMessageStore } from "./index-DWIRrJMP.js";
3
+ import { n as DrizzleSchema, t as eventCollector } from "./unit-of-work-context-CPz9rdSS.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
@@ -20,7 +20,7 @@ type PostgresTx<Schema extends DrizzleSchema> = {
20
20
  //#region src/infrastructure/postgres/base-postgres-repository.d.ts
21
21
  /** A domain aggregate that accumulates events for the unit of work to drain. */
22
22
  interface AggregateEvents {
23
- collectEvents(): ReadonlyArray<Event>;
23
+ collectEvents(): ReadonlyArray<DomainEvent>;
24
24
  clearEvents(): void;
25
25
  }
26
26
  /** Shared plumbing for a repository that writes inside a Postgres unit of work. */
@@ -39,7 +39,7 @@ export declare class PostgresMessageStore<Schema extends DrizzleSchema> implemen
39
39
  private readonly db;
40
40
  constructor(db: PostgresDbTransaction<Schema>);
41
41
  claim(messageId: MessageId): Promise<void>;
42
- persistEvents(events: ReadonlyArray<Event>): Promise<void>;
42
+ persistEvents(events: ReadonlyArray<DomainEvent>): Promise<void>;
43
43
  }
44
44
  //#endregion
45
45
  //#region src/infrastructure/postgres/postgres-schema.d.ts
@@ -112,7 +112,7 @@ export declare const messageOutbox: import("drizzle-orm/pg-core").PgTableWithCol
112
112
  tableName: "message_outbox";
113
113
  dataType: "json";
114
114
  columnType: "PgJsonb";
115
- data: Event;
115
+ data: DomainEvent;
116
116
  driverParam: unknown;
117
117
  notNull: true;
118
118
  hasDefault: false;
@@ -124,7 +124,7 @@ export declare const messageOutbox: import("drizzle-orm/pg-core").PgTableWithCol
124
124
  identity: undefined;
125
125
  generated: undefined;
126
126
  }, {}, {
127
- $type: Event;
127
+ $type: DomainEvent;
128
128
  }>;
129
129
  createdAt: import("drizzle-orm/pg-core").PgColumn<{
130
130
  name: "created_at";
@@ -1 +1 @@
1
- {"version":3,"file":"postgres.d.ts","names":[],"sources":["../src/infrastructure/postgres/postgres-database-types.ts","../src/infrastructure/postgres/base-postgres-repository.ts","../src/infrastructure/postgres/postgres-message-store.ts","../src/infrastructure/postgres/postgres-schema.ts","../src/infrastructure/postgres/postgres-transaction.ts","../src/infrastructure/postgres/postgres-database-execution.ts","../src/infrastructure/postgres/classify-postgres-error.ts"],"mappings":";;;;;;;KAMY,qBAAqB,kBAAkB;;KAGvC,WAAW,eAAe,iBAAiB,mBAAmB;;KAG9D,eAAe,eAAe,iBAAiB,KACzD,WAAW;;KAKD,sBAAsB,eAAe,iBAAiB,sBAChE,QACA,2BAA2B;;KAIjB,WAAW,eAAe;WAC3B,IAAI,sBAAsB;;;;;UCjBpB;EACf,iBAAiB,cAAc;EAC/B;;;8BAIoB,uBAAuB,eAAe;qBAC3B,IAAI,sBAAsB;EAAzD,YAA+B,IAAI,sBAAsB;;YAG/C,KAAK,GAAG,mBAAmB,aAAa,YAAY,KAAK,QAAQ;;YAKjE,eAAe,WAAW;;;;;qBCXzB,qBAAqB,eAAe,0BAA0B;mBAC5C;EAA7B,YAA6B,IAAI,sBAAsB;EAEjD,MAAM,WAAW,YAAY;EAU7B,cAAc,QAAQ,cAAc,SAAS;;;;;qBCnBxC,iDAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;YAAjB;;;;;;;;;;;;;;;;qBAMA,6CAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qBCDb,oBAAoB,eAAe,0BAA0B,aACxE,WAAW;mBAEkB;EAA7B,YAA6B,IAAI,WAAW;EAE5C,YAAY,GAAG,OAAO,IAAI,WAAW,YAAY,QAAQ,KAAK,QAAQ;;;;;wBCblD,gBAAgB,GACpC,mBACA,YAAY,YAAY,KACvB,QAAQ;;;;wBC2BK,sBACd,gBACA,oBACC"}
1
+ {"version":3,"file":"postgres.d.ts","names":[],"sources":["../src/infrastructure/postgres/postgres-database-types.ts","../src/infrastructure/postgres/base-postgres-repository.ts","../src/infrastructure/postgres/postgres-message-store.ts","../src/infrastructure/postgres/postgres-schema.ts","../src/infrastructure/postgres/postgres-transaction.ts","../src/infrastructure/postgres/postgres-database-execution.ts","../src/infrastructure/postgres/classify-postgres-error.ts"],"mappings":";;;;;;;KAMY,qBAAqB,kBAAkB;;KAGvC,WAAW,eAAe,iBAAiB,mBAAmB;;KAG9D,eAAe,eAAe,iBAAiB,KACzD,WAAW;;KAKD,sBAAsB,eAAe,iBAAiB,sBAChE,QACA,2BAA2B;;KAIjB,WAAW,eAAe;WAC3B,IAAI,sBAAsB;;;;;UCjBpB;EACf,iBAAiB,cAAc;EAC/B;;;8BAIoB,uBAAuB,eAAe;qBAC3B,IAAI,sBAAsB;EAAzD,YAA+B,IAAI,sBAAsB;;YAG/C,KAAK,GAAG,mBAAmB,aAAa,YAAY,KAAK,QAAQ;;YAKjE,eAAe,WAAW;;;;;qBCfzB,qBAAqB,eAAe,0BAA0B;mBAC5C;EAA7B,YAA6B,IAAI,sBAAsB;EAEjD,MAAM,WAAW,YAAY;EAU7B,cAAc,QAAQ,cAAc,eAAe;;;;;qBCf9C,iDAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;YAAjB;;;;;;;;;;;;;;;;qBAMA,6CAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qBCDb,oBAAoB,eAAe,0BAA0B,aACxE,WAAW;mBAEkB;EAA7B,YAA6B,IAAI,WAAW;EAE5C,YAAY,GAAG,OAAO,IAAI,WAAW,YAAY,QAAQ,KAAK,QAAQ;;;;;wBCblD,gBAAgB,GACpC,mBACA,YAAY,YAAY,KACvB,QAAQ;;;;wBC2BK,sBACd,gBACA,oBACC"}
package/dist/postgres.js CHANGED
@@ -1,6 +1,6 @@
1
- import { A as AppError, p as DatabaseError } from "./core-CnwWj4MY.js";
2
- import { i as MessageAlreadyProcessedError } from "./application-DEerezCl.js";
3
- import { n as eventCollector, r as runWithUnitOfWorkContext } from "./unit-of-work-context-C7vz5OYS.js";
1
+ import { N as AppError, g as DatabaseError } from "./core-Cx5SeyKV.js";
2
+ import { i as MessageAlreadyProcessedError } from "./application-DjsQtpgw.js";
3
+ import { n as eventCollector, r as runWithUnitOfWorkContext } from "./unit-of-work-context-DToDpAkv.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";
@@ -1 +1 @@
1
- {"version":3,"file":"postgres.js","names":[],"sources":["../src/infrastructure/postgres/classify-postgres-error.ts","../src/infrastructure/postgres/postgres-database-execution.ts","../src/infrastructure/postgres/base-postgres-repository.ts","../src/infrastructure/postgres/postgres-schema.ts","../src/infrastructure/postgres/postgres-message-store.ts","../src/infrastructure/postgres/postgres-transaction.ts"],"sourcesContent":["import { DrizzleQueryError } from 'drizzle-orm/errors'\n\nimport { AppError, DatabaseError, type FailureClassification } from '@/core'\n\nconst TRANSIENT_CODES = new Set([\n '40001',\n '40P01',\n '08000',\n '08001',\n '08003',\n '08006',\n '57P01',\n '57P02',\n '57P03',\n 'CONNECT_TIMEOUT',\n 'CONNECTION_CLOSED',\n 'ECONNRESET',\n 'ECONNREFUSED',\n 'EPIPE',\n 'ETIMEDOUT',\n 'EAI_AGAIN',\n])\nconst TERMINAL_CODES = new Set(['57014', 'CONNECTION_ENDED', 'CONNECTION_DESTROYED', 'ECANCELED'])\nconst DRIVER_CODES = new Set([\n 'CONNECT_TIMEOUT',\n 'CONNECTION_CLOSED',\n 'CONNECTION_ENDED',\n 'CONNECTION_DESTROYED',\n])\nconst TERMINAL_CLASSES = new Set(['0A', '22', '23', '25', '28', '3D', '3F', '42', '54'])\n\n/* oxlint-disable anti-slop/no-runtime-typeof -- Raw driver exceptions have no shared schema; this boundary validates the fields it exposes. */\n/** Read SQLSTATE or driver codes; unknown callback exceptions remain unchanged. */\nexport function classifyPostgresError(\n cause: unknown,\n operation: string,\n): DatabaseError | undefined {\n let error = cause\n const seen = new Set<unknown>()\n while (error instanceof DrizzleQueryError && !seen.has(error)) {\n seen.add(error)\n error = error.cause\n }\n if (error instanceof AppError || (error instanceof Error && error.name === 'AbortError'))\n return undefined\n const code =\n error instanceof Error && 'code' in error && typeof error.code === 'string'\n ? error.code\n : undefined\n const serverError =\n error instanceof Error &&\n error.name === 'PostgresError' &&\n code !== undefined &&\n /^[0-9A-Z]{5}$/.test(code)\n const driverError = code !== undefined && DRIVER_CODES.has(code)\n if (!(cause instanceof DrizzleQueryError) && !serverError && !driverError) return undefined\n\n return new DatabaseError(\n operation,\n classificationOf(code),\n {\n database: 'postgres',\n code,\n table_name:\n error instanceof Error && 'table_name' in error && typeof error.table_name === 'string'\n ? error.table_name\n : undefined,\n column_name:\n error instanceof Error && 'column_name' in error && typeof error.column_name === 'string'\n ? error.column_name\n : undefined,\n constraint_name:\n error instanceof Error &&\n 'constraint_name' in error &&\n typeof error.constraint_name === 'string'\n ? error.constraint_name\n : undefined,\n },\n { cause },\n )\n}\n\n/* oxlint-enable anti-slop/no-runtime-typeof */\n\nfunction classificationOf(code: string | undefined): FailureClassification {\n if (code === undefined) return 'unknown'\n if (TRANSIENT_CODES.has(code)) return 'transient'\n if (TERMINAL_CODES.has(code) || TERMINAL_CLASSES.has(code.slice(0, 2))) return 'terminal'\n return 'unknown'\n}\n","import { classifyPostgresError } from './classify-postgres-error.ts'\n\n/** Execute once without retries; convert recognized Postgres failures and preserve other exceptions unchanged. */\nexport async function executeDatabase<T>(\n operation: string,\n work: () => PromiseLike<T>,\n): Promise<T> {\n try {\n return await work()\n } catch (cause) {\n throw classifyPostgresError(cause, operation) ?? cause\n }\n}\n","import type { Event } from '@/application'\n\nimport type { DrizzleSchema } from '../drizzle-schema.ts'\nimport { eventCollector } from '../unit-of-work-context.ts'\nimport { executeDatabase } from './postgres-database-execution.ts'\nimport type { PostgresDbTransaction } from './postgres-database-types.ts'\n\n/** A domain aggregate that accumulates events for the unit of work to drain. */\nexport interface AggregateEvents {\n collectEvents(): ReadonlyArray<Event>\n clearEvents(): void\n}\n\n/** Shared plumbing for a repository that writes inside a Postgres unit of work. */\nexport abstract class BasePostgresRepository<Schema extends DrizzleSchema> {\n constructor(protected readonly db: PostgresDbTransaction<Schema>) {}\n\n /** Execute one read with database error conversion and no automatic retries. */\n protected read<T>(operation: string, query: () => PromiseLike<T>): Promise<T> {\n return executeDatabase(operation, query)\n }\n\n /** Drain an aggregate's pending events into the active boundary. */\n protected dispatchEvents(aggregate: AggregateEvents): void {\n const events = aggregate.collectEvents()\n if (events.length === 0) return\n for (const event of events) eventCollector.emit(event)\n aggregate.clearEvents()\n }\n}\n","import { isNull } from 'drizzle-orm'\nimport { index, integer, jsonb, pgTable, text, timestamp } from 'drizzle-orm/pg-core'\n\nimport type { Event } from '@/application'\n\n/** One row per committed message. The primary key is the idempotency claim. */\nexport const processedMessages = pgTable('processed_messages', {\n messageId: text('message_id').primaryKey(),\n processedAt: timestamp('processed_at', { withTimezone: true }).notNull().defaultNow(),\n})\n\n/** Events committed with their state change, waiting for the relay to deliver them. */\nexport const messageOutbox = pgTable(\n 'message_outbox',\n {\n id: text('id').primaryKey(),\n payload: jsonb('payload').$type<Event>().notNull(),\n createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),\n availableAt: timestamp('available_at', { withTimezone: true }).notNull().defaultNow(),\n attempts: integer('attempts').notNull().default(0),\n claimToken: text('claim_token'),\n claimExpiresAt: timestamp('claim_expires_at', { withTimezone: true }),\n publishedAt: timestamp('published_at', { withTimezone: true }),\n failedAt: timestamp('failed_at', { withTimezone: true }),\n lastError: text('last_error'),\n },\n (table) => [\n index('idx_message_outbox_due')\n .on(table.availableAt, table.createdAt)\n .where(isNull(table.publishedAt)),\n index('idx_message_outbox_claim_token').on(table.claimToken),\n ],\n)\n","import {\n MessageAlreadyProcessedError,\n type Event,\n type IMessageStore,\n type MessageId,\n} from '@/application'\n\nimport type { DrizzleSchema } from '../drizzle-schema.ts'\nimport type { PostgresDbTransaction } from './postgres-database-types.ts'\nimport { messageOutbox, processedMessages } from './postgres-schema.ts'\n\n/** Processed messages and outbox events share the active Postgres transaction; the insert result establishes the claim. */\nexport class PostgresMessageStore<Schema extends DrizzleSchema> implements IMessageStore {\n constructor(private readonly db: PostgresDbTransaction<Schema>) {}\n\n async claim(messageId: MessageId): Promise<void> {\n const claimed = await this.db\n .insert(processedMessages)\n .values({ messageId })\n .onConflictDoNothing()\n .returning({ messageId: processedMessages.messageId })\n // Thrown inside the transaction, so drizzle rolls back everything written before the claim.\n if (claimed.length === 0) throw new MessageAlreadyProcessedError(messageId)\n }\n\n async persistEvents(events: ReadonlyArray<Event>): Promise<void> {\n if (events.length === 0) return\n await this.db\n .insert(messageOutbox)\n .values(events.map((event) => ({ id: event.id, payload: event })))\n }\n}\n","import type { ITransaction } from '@/application'\n\nimport type { DrizzleSchema } from '../drizzle-schema.ts'\nimport { runWithUnitOfWorkContext } from '../unit-of-work-context.ts'\nimport { executeDatabase } from './postgres-database-execution.ts'\nimport type { PostgresDb, PostgresTx } from './postgres-database-types.ts'\n\n/**\n * The Postgres transaction boundary uses native Drizzle transactions through postgres.js.\n * Drizzle commits when `work` returns and rolls back when it throws.\n */\nexport class PostgresTransaction<Schema extends DrizzleSchema> implements ITransaction<\n PostgresTx<Schema>\n> {\n constructor(private readonly db: PostgresDb<Schema>) {}\n\n transaction<T>(work: (tx: PostgresTx<Schema>) => Promise<T>): Promise<T> {\n return runWithUnitOfWorkContext('postgres', () =>\n executeDatabase('unit of work transaction', () => this.db.transaction((db) => work({ db }))),\n )\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"postgres.js","names":[],"sources":["../src/infrastructure/postgres/classify-postgres-error.ts","../src/infrastructure/postgres/postgres-database-execution.ts","../src/infrastructure/postgres/base-postgres-repository.ts","../src/infrastructure/postgres/postgres-schema.ts","../src/infrastructure/postgres/postgres-message-store.ts","../src/infrastructure/postgres/postgres-transaction.ts"],"sourcesContent":["import { DrizzleQueryError } from 'drizzle-orm/errors'\n\nimport { AppError, DatabaseError, type FailureClassification } from '@/core'\n\nconst TRANSIENT_CODES = new Set([\n '40001',\n '40P01',\n '08000',\n '08001',\n '08003',\n '08006',\n '57P01',\n '57P02',\n '57P03',\n 'CONNECT_TIMEOUT',\n 'CONNECTION_CLOSED',\n 'ECONNRESET',\n 'ECONNREFUSED',\n 'EPIPE',\n 'ETIMEDOUT',\n 'EAI_AGAIN',\n])\nconst TERMINAL_CODES = new Set(['57014', 'CONNECTION_ENDED', 'CONNECTION_DESTROYED', 'ECANCELED'])\nconst DRIVER_CODES = new Set([\n 'CONNECT_TIMEOUT',\n 'CONNECTION_CLOSED',\n 'CONNECTION_ENDED',\n 'CONNECTION_DESTROYED',\n])\nconst TERMINAL_CLASSES = new Set(['0A', '22', '23', '25', '28', '3D', '3F', '42', '54'])\n\n/* oxlint-disable anti-slop/no-runtime-typeof -- Raw driver exceptions have no shared schema; this boundary validates the fields it exposes. */\n/** Read SQLSTATE or driver codes; unknown callback exceptions remain unchanged. */\nexport function classifyPostgresError(\n cause: unknown,\n operation: string,\n): DatabaseError | undefined {\n let error = cause\n const seen = new Set<unknown>()\n while (error instanceof DrizzleQueryError && !seen.has(error)) {\n seen.add(error)\n error = error.cause\n }\n if (error instanceof AppError || (error instanceof Error && error.name === 'AbortError'))\n return undefined\n const code =\n error instanceof Error && 'code' in error && typeof error.code === 'string'\n ? error.code\n : undefined\n const serverError =\n error instanceof Error &&\n error.name === 'PostgresError' &&\n code !== undefined &&\n /^[0-9A-Z]{5}$/.test(code)\n const driverError = code !== undefined && DRIVER_CODES.has(code)\n if (!(cause instanceof DrizzleQueryError) && !serverError && !driverError) return undefined\n\n return new DatabaseError(\n operation,\n classificationOf(code),\n {\n database: 'postgres',\n code,\n table_name:\n error instanceof Error && 'table_name' in error && typeof error.table_name === 'string'\n ? error.table_name\n : undefined,\n column_name:\n error instanceof Error && 'column_name' in error && typeof error.column_name === 'string'\n ? error.column_name\n : undefined,\n constraint_name:\n error instanceof Error &&\n 'constraint_name' in error &&\n typeof error.constraint_name === 'string'\n ? error.constraint_name\n : undefined,\n },\n { cause },\n )\n}\n\n/* oxlint-enable anti-slop/no-runtime-typeof */\n\nfunction classificationOf(code: string | undefined): FailureClassification {\n if (code === undefined) return 'unknown'\n if (TRANSIENT_CODES.has(code)) return 'transient'\n if (TERMINAL_CODES.has(code) || TERMINAL_CLASSES.has(code.slice(0, 2))) return 'terminal'\n return 'unknown'\n}\n","import { classifyPostgresError } from './classify-postgres-error.ts'\n\n/** Execute once without retries; convert recognized Postgres failures and preserve other exceptions unchanged. */\nexport async function executeDatabase<T>(\n operation: string,\n work: () => PromiseLike<T>,\n): Promise<T> {\n try {\n return await work()\n } catch (cause) {\n throw classifyPostgresError(cause, operation) ?? cause\n }\n}\n","import type { DomainEvent } from '@/core'\n\nimport type { DrizzleSchema } from '../drizzle-schema.ts'\nimport { eventCollector } from '../unit-of-work-context.ts'\nimport { executeDatabase } from './postgres-database-execution.ts'\nimport type { PostgresDbTransaction } from './postgres-database-types.ts'\n\n/** A domain aggregate that accumulates events for the unit of work to drain. */\nexport interface AggregateEvents {\n collectEvents(): ReadonlyArray<DomainEvent>\n clearEvents(): void\n}\n\n/** Shared plumbing for a repository that writes inside a Postgres unit of work. */\nexport abstract class BasePostgresRepository<Schema extends DrizzleSchema> {\n constructor(protected readonly db: PostgresDbTransaction<Schema>) {}\n\n /** Execute one read with database error conversion and no automatic retries. */\n protected read<T>(operation: string, query: () => PromiseLike<T>): Promise<T> {\n return executeDatabase(operation, query)\n }\n\n /** Drain an aggregate's pending events into the active boundary. */\n protected dispatchEvents(aggregate: AggregateEvents): void {\n const events = aggregate.collectEvents()\n if (events.length === 0) return\n for (const event of events) eventCollector.emit(event)\n aggregate.clearEvents()\n }\n}\n","import { isNull } from 'drizzle-orm'\nimport { index, integer, jsonb, pgTable, text, timestamp } from 'drizzle-orm/pg-core'\n\nimport type { DomainEvent } from '@/core'\n\n/** One row per committed message. The primary key is the idempotency claim. */\nexport const processedMessages = pgTable('processed_messages', {\n messageId: text('message_id').primaryKey(),\n processedAt: timestamp('processed_at', { withTimezone: true }).notNull().defaultNow(),\n})\n\n/** Events committed with their state change, waiting for the relay to deliver them. */\nexport const messageOutbox = pgTable(\n 'message_outbox',\n {\n id: text('id').primaryKey(),\n payload: jsonb('payload').$type<DomainEvent>().notNull(),\n createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),\n availableAt: timestamp('available_at', { withTimezone: true }).notNull().defaultNow(),\n attempts: integer('attempts').notNull().default(0),\n claimToken: text('claim_token'),\n claimExpiresAt: timestamp('claim_expires_at', { withTimezone: true }),\n publishedAt: timestamp('published_at', { withTimezone: true }),\n failedAt: timestamp('failed_at', { withTimezone: true }),\n lastError: text('last_error'),\n },\n (table) => [\n index('idx_message_outbox_due')\n .on(table.availableAt, table.createdAt)\n .where(isNull(table.publishedAt)),\n index('idx_message_outbox_claim_token').on(table.claimToken),\n ],\n)\n","import { MessageAlreadyProcessedError, type IMessageStore, type MessageId } from '@/application'\nimport type { DomainEvent } from '@/core'\n\nimport type { DrizzleSchema } from '../drizzle-schema.ts'\nimport type { PostgresDbTransaction } from './postgres-database-types.ts'\nimport { messageOutbox, processedMessages } from './postgres-schema.ts'\n\n/** Processed messages and outbox events share the active Postgres transaction; the insert result establishes the claim. */\nexport class PostgresMessageStore<Schema extends DrizzleSchema> implements IMessageStore {\n constructor(private readonly db: PostgresDbTransaction<Schema>) {}\n\n async claim(messageId: MessageId): Promise<void> {\n const claimed = await this.db\n .insert(processedMessages)\n .values({ messageId })\n .onConflictDoNothing()\n .returning({ messageId: processedMessages.messageId })\n // Thrown inside the transaction, so drizzle rolls back everything written before the claim.\n if (claimed.length === 0) throw new MessageAlreadyProcessedError(messageId)\n }\n\n async persistEvents(events: ReadonlyArray<DomainEvent>): Promise<void> {\n if (events.length === 0) return\n await this.db\n .insert(messageOutbox)\n .values(events.map((event) => ({ id: event.id, payload: event })))\n }\n}\n","import type { ITransaction } from '@/application'\n\nimport type { DrizzleSchema } from '../drizzle-schema.ts'\nimport { runWithUnitOfWorkContext } from '../unit-of-work-context.ts'\nimport { executeDatabase } from './postgres-database-execution.ts'\nimport type { PostgresDb, PostgresTx } from './postgres-database-types.ts'\n\n/**\n * The Postgres transaction boundary uses native Drizzle transactions through postgres.js.\n * Drizzle commits when `work` returns and rolls back when it throws.\n */\nexport class PostgresTransaction<Schema extends DrizzleSchema> implements ITransaction<\n PostgresTx<Schema>\n> {\n constructor(private readonly db: PostgresDb<Schema>) {}\n\n transaction<T>(work: (tx: PostgresTx<Schema>) => Promise<T>): Promise<T> {\n return runWithUnitOfWorkContext('postgres', () =>\n executeDatabase('unit of work transaction', () => this.db.transaction((db) => work({ db }))),\n )\n }\n}\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { A as ErrorTable } from "./index-B9Y1hVh6.js";
1
+ import { Y as ErrorTable } from "./index-BStnggQO.js";
2
2
  import { Register, RequestServerOptions } from "@tanstack/react-start";
3
3
  import { AnyRedirect } from "@tanstack/react-router";
4
4
  import { BetterAuthCookies } from "better-auth";
@@ -77,5 +77,12 @@ export declare function createErrorMiddleware<Entries>(options: ErrorMiddlewareO
77
77
  toHttpErrorResponse: (cause: unknown) => Response;
78
78
  };
79
79
  //#endregion
80
+ //#region src/infrastructure/tanstack/last-login-method.d.ts
81
+ /**
82
+ * Read the method this browser last signed in with from the current request, for the sign-in loader on the server.
83
+ * Pass `cookieName` only when `integrations.lastLoginMethod.cookieName` is set. Returns `null` when the cookie is absent.
84
+ */
85
+ export declare function getLastUsedLoginMethod(cookieName?: string): string | null;
86
+ //#endregion
80
87
  export type { AuthContext, AuthCookieSource, AuthMiddlewareOptions, AuthSession, ErrorMiddlewareOptions, RequiredAuthContext };
81
88
  //# sourceMappingURL=tanstack.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"tanstack.d.ts","names":[],"sources":["../src/infrastructure/tanstack/auth.middleware.ts","../src/infrastructure/tanstack/error.middleware.ts"],"mappings":";;;;;;KASY;WACD;aAAiB;;WACjB;aAAoB;;;;KAInB,oBAAoB,gBAAgB;WACrC,MAAM;WACN,SAAS;;;KAIR,YAAY,gBAAgB,eACpC,oBAAoB;WAET;WACA;;;KAIH,sBAAsB,gBAAgB;WACvC,UAAU,SAAS,qBAAqB;aACtC;eACE,aAAa;QAAW,SAAS;YAAc,QAAQ;;;;;;;;wBAStD,qBAAqB,gBAAgB,aACnD,SAAS,sBAAsB;;;;;;;KChC5B,iBAAiB,qBAAqB;;KAG/B;WACD,UAAU;aAAmB,aAAa;;;;KAIzC,uBAAuB;WACxB,QAAQ,WAAW;;WAEnB,cAAc;;WAEd,UAAU,SAAS,mBAAmB;;;;;;wBAOjC,sBAAsB,SAAS,SAAS,uBAAuB"}
1
+ {"version":3,"file":"tanstack.d.ts","names":[],"sources":["../src/infrastructure/tanstack/auth.middleware.ts","../src/infrastructure/tanstack/error.middleware.ts","../src/infrastructure/tanstack/last-login-method.ts"],"mappings":";;;;;;KASY;WACD;aAAiB;;WACjB;aAAoB;;;;KAInB,oBAAoB,gBAAgB;WACrC,MAAM;WACN,SAAS;;;KAIR,YAAY,gBAAgB,eACpC,oBAAoB;WAET;WACA;;;KAIH,sBAAsB,gBAAgB;WACvC,UAAU,SAAS,qBAAqB;aACtC;eACE,aAAa;QAAW,SAAS;YAAc,QAAQ;;;;;;;;wBAStD,qBAAqB,gBAAgB,aACnD,SAAS,sBAAsB;;;;;;;KChC5B,iBAAiB,qBAAqB;;KAG/B;WACD,UAAU;aAAmB,aAAa;;;;KAIzC,uBAAuB;WACxB,QAAQ,WAAW;;WAEnB,cAAc;;WAEd,UAAU,SAAS,mBAAmB;;;;;;wBAOjC,sBAAsB,SAAS,SAAS,uBAAuB;;;;;;;;;;;;;;;;;;;;wBCpB/D,uBAAuB"}
package/dist/tanstack.js CHANGED
@@ -1,4 +1,4 @@
1
- import { A as AppError, C as ValidationError, D as StaleSessionError, a as createLogger, k as AuthenticationError } from "./core-CnwWj4MY.js";
1
+ import { A as StaleSessionError, E as ValidationError, M as AuthenticationError, N as AppError, a as createLogger } from "./core-Cx5SeyKV.js";
2
2
  import { z } from "zod";
3
3
  import { createMiddleware } from "@tanstack/react-start";
4
4
  import { deleteCookie, getRequestHeaders } from "@tanstack/react-start/server";
@@ -210,5 +210,16 @@ function createErrorMiddleware(options) {
210
210
  }
211
211
 
212
212
  //#endregion
213
- export { createAuthMiddleware, createErrorMiddleware };
213
+ //#region src/infrastructure/tanstack/last-login-method.ts
214
+ const DEFAULT_COOKIE_NAME = "better-auth.last_used_login_method";
215
+ /**
216
+ * Read the method this browser last signed in with from the current request, for the sign-in loader on the server.
217
+ * Pass `cookieName` only when `integrations.lastLoginMethod.cookieName` is set. Returns `null` when the cookie is absent.
218
+ */
219
+ function getLastUsedLoginMethod(cookieName = DEFAULT_COOKIE_NAME) {
220
+ return parseCookies(getRequestHeaders().get("cookie") ?? "").get(cookieName) ?? null;
221
+ }
222
+
223
+ //#endregion
224
+ export { createAuthMiddleware, createErrorMiddleware, getLastUsedLoginMethod };
214
225
  //# sourceMappingURL=tanstack.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"tanstack.js","names":["logger"],"sources":["../src/infrastructure/tanstack/auth.middleware.ts","../src/infrastructure/tanstack/resolve-failure.ts","../src/infrastructure/tanstack/http-error-response.ts","../src/infrastructure/tanstack/session-cookies.ts","../src/infrastructure/tanstack/to-error-payload.ts","../src/infrastructure/tanstack/error.middleware.ts"],"sourcesContent":["import { createMiddleware, type Register, type RequestServerOptions } from '@tanstack/react-start'\nimport { getRequestHeaders } from '@tanstack/react-start/server'\nimport { getSessionCookie } from 'better-auth/cookies'\n\nimport { AuthenticationError, StaleSessionError, createLogger } from '@/core'\n\nconst logger = createLogger('auth-middleware')\n\n/** The fields middleware reads; generic callers retain every additional session and user field. */\nexport type AuthSession = {\n readonly user: { readonly id: string }\n readonly session: { readonly id: string }\n}\n\n/** Authenticated context retains the application's complete user and session types. */\nexport type RequiredAuthContext<Session extends AuthSession> = {\n readonly user: Session['user']\n readonly session: Session['session']\n}\n\n/** Optional authentication supplies both fields together or neither field. */\nexport type AuthContext<Session extends AuthSession> =\n | RequiredAuthContext<Session>\n | {\n readonly user: undefined\n readonly session: undefined\n }\n\n/** Select the current request's Better Auth instance from TanStack's registered context. */\nexport type AuthMiddlewareOptions<Session extends AuthSession> = {\n readonly getAuth: (context: RequestServerOptions<Register, undefined>['context']) => {\n readonly api: {\n readonly getSession: (options: { headers: Headers }) => Promise<Session | null>\n }\n }\n}\n\n/**\n * Preserve Porte's function and request middleware contracts with application-owned services.\n * Optional lookup failures log once and continue as guests. Required lookup failures propagate.\n */\nexport function createAuthMiddleware<Session extends AuthSession>(\n options: AuthMiddlewareOptions<Session>,\n) {\n const extractAuth = createMiddleware({ type: 'function' }).server<AuthContext<Session>>(\n async ({ next, context }) => {\n let resolved: Session | null\n try {\n resolved = await options.getAuth(context).api.getSession({ headers: getRequestHeaders() })\n } catch (error) {\n logger.error('get_session_failed', { error })\n resolved = null\n }\n if (resolved === null)\n return next<AuthContext<Session>>({ context: { user: undefined, session: undefined } })\n return next<AuthContext<Session>>({\n context: { user: resolved.user, session: resolved.session },\n })\n },\n )\n\n async function resolveRequiredSession(\n context: RequestServerOptions<Register, undefined>['context'],\n headers: Headers,\n ): Promise<Session> {\n const resolved = await options.getAuth(context).api.getSession({ headers })\n if (resolved === null) {\n if (getSessionCookie(headers)) throw new StaleSessionError()\n throw new AuthenticationError()\n }\n return resolved\n }\n\n const requireAuth = createMiddleware({ type: 'function' }).server(async ({ next, context }) => {\n const resolved = await resolveRequiredSession(context, getRequestHeaders())\n return next<RequiredAuthContext<Session>>({\n context: { user: resolved.user, session: resolved.session },\n })\n })\n const requireAuthRequest = createMiddleware({ type: 'request' }).server(\n async ({ request, next, context }) => {\n const resolved = await resolveRequiredSession(context, request.headers)\n return next<RequiredAuthContext<Session>>({\n context: { user: resolved.user, session: resolved.session },\n })\n },\n )\n return { extractAuth, requireAuth, requireAuthRequest }\n}\n","import { AppError, createLogger, type ErrorTable, type ResolvedError } from '@/core'\nimport type { ErrorPayloadOf } from '@/core'\n\nconst logger = createLogger('error-boundary')\n\n/**\n * Resolve one failure through the table or fall back to the generic replacement, and log it once.\n * Both transport converters call this, so one rule decides the log level: mapped is a warning, unmapped is an error with the cause.\n */\nexport function resolveFailure<Entries>(\n table: ErrorTable<Entries>,\n cause: unknown,\n): ResolvedError<ErrorPayloadOf<ErrorTable<Entries>>> {\n const resolved = table.resolve(cause)\n if (resolved !== null) {\n logger.warn('handled_error', {\n details: { tag: resolved.payload._tag, status: resolved.status },\n })\n return resolved\n }\n const classification = cause instanceof AppError ? cause.classification : 'unknown'\n logger.error('unexpected_error', { error: cause, details: { classification } })\n return table.fallback(cause)\n}\n","import { getReasonPhrase } from 'http-status-codes'\nimport { z } from 'zod'\n\nimport type { ErrorTable, ProblemDetails } from '@/core'\n\nimport { resolveFailure } from './resolve-failure.ts'\n\n// A known delay becomes the header; a null delay sends no header.\nconst RetryAfterSchema = z.object({ retryAfter: z.number() })\n\n/**\n * Build the API route converter for one error table.\n * The body is RFC 9457 problem details; public fields become extension members.\n */\nexport function createHttpErrorResponseConverter<Entries>(table: ErrorTable<Entries>) {\n return function toHttpErrorResponse(cause: unknown): Response {\n const { status, payload } = resolveFailure(table, cause)\n const { _tag, message, ...fields } = payload\n const body: ProblemDetails = {\n type: 'about:blank',\n title: getReasonPhrase(status),\n detail: message,\n ...fields,\n }\n const headers = new Headers({ 'Content-Type': 'application/problem+json' })\n const retry = RetryAfterSchema.safeParse(payload)\n if (retry.success) headers.set('Retry-After', String(retry.data.retryAfter))\n return Response.json(body, { status, headers })\n }\n}\n","import { deleteCookie, getRequestHeaders } from '@tanstack/react-start/server'\nimport type { BetterAuthCookies } from 'better-auth'\nimport { parseCookies } from 'better-auth/cookies'\n\ntype AuthCookie = BetterAuthCookies['sessionToken']\ntype DeleteCookieOptions = NonNullable<Parameters<typeof deleteCookie>[1]>\n\n/**\n * Delete the session, session cache, account cache, and remember-me cookies of one instance.\n * Chunks present on the request go too. Names and attributes come from the instance, so custom prefixes and domain cookies clear.\n */\nexport function clearStaleSessionCookies(cookies: BetterAuthCookies): void {\n const present = [...parseCookies(getRequestHeaders().get('cookie') ?? '').keys()]\n const definitions = [\n cookies.sessionToken,\n cookies.sessionData,\n cookies.accountData,\n cookies.dontRememberToken,\n ]\n for (const cookie of definitions) {\n // Better Auth names a chunk `${name}.${index}`, so a missed chunk would resurrect the value.\n const chunks = present.filter((name) => name.startsWith(`${cookie.name}.`))\n for (const name of new Set([cookie.name, ...chunks]))\n deleteCookie(name, deletionOf(cookie.attributes))\n }\n}\n\nfunction deletionOf(attributes: AuthCookie['attributes']): DeleteCookieOptions {\n // Better Auth sets `/` and the secure flag at runtime; the types leave both optional.\n const options: DeleteCookieOptions = {\n path: attributes.path ?? '/',\n secure: attributes.secure ?? false,\n }\n if (attributes.domain !== undefined) options.domain = attributes.domain\n return options\n}\n","import { z } from 'zod'\n\nimport { ValidationError, type ErrorPayloadOf, type ErrorTable } from '@/core'\n\nimport { resolveFailure } from './resolve-failure.ts'\n\n// TanStack serializes a validator's issues into `Error.message` as JSON.\nconst SerializedIssuesSchema = z\n .array(z.object({ message: z.string(), path: z.array(z.union([z.string(), z.number()])) }))\n .min(1)\n\nfunction reconstructValidationError(cause: unknown): ValidationError | null {\n if (!(cause instanceof Error)) return null\n let message: unknown\n try {\n message = JSON.parse(cause.message)\n } catch {\n return null\n }\n const parsed = SerializedIssuesSchema.safeParse(message)\n return parsed.success ? ValidationError.fromIssues(parsed.data) : null\n}\n\n/**\n * Build the server-function converter for one error table.\n * The result is a plain object, because only own data survives serialization.\n */\nexport function createErrorPayloadConverter<Entries>(table: ErrorTable<Entries>) {\n return function toErrorPayload(cause: unknown): ErrorPayloadOf<ErrorTable<Entries>> {\n return resolveFailure(table, reconstructValidationError(cause) ?? cause).payload\n }\n}\n","import { isNotFound, isRedirect, type AnyRedirect } from '@tanstack/react-router'\nimport { createMiddleware, type Register, type RequestServerOptions } from '@tanstack/react-start'\nimport type { BetterAuthCookies } from 'better-auth'\n\nimport { StaleSessionError, type ErrorTable } from '@/core'\n\nimport { createHttpErrorResponseConverter } from './http-error-response.ts'\nimport { clearStaleSessionCookies } from './session-cookies.ts'\nimport { createErrorPayloadConverter } from './to-error-payload.ts'\n\ntype RequestContext = RequestServerOptions<Register, undefined>['context']\n\n/** The part of a Better Auth instance the boundary reads: its computed cookie definitions. */\nexport type AuthCookieSource = {\n readonly $context: Promise<{ readonly authCookies: BetterAuthCookies }>\n}\n\n/** The application's error table, its stale-session redirect, and its Better Auth instance. */\nexport type ErrorMiddlewareOptions<Entries> = {\n readonly errors: ErrorTable<Entries>\n /** Build the redirect a server function throws for a stale session. */\n readonly signIn: () => AnyRedirect\n /** Select the request's Better Auth instance; its cookie definitions say what to clear. */\n readonly getAuth: (context: RequestContext) => AuthCookieSource\n}\n\n/**\n * Build both transport boundaries from one error table.\n * Register `functionErrorMiddleware` globally. Put `routeErrorMiddleware` first in an API route's `server.middleware`.\n */\nexport function createErrorMiddleware<Entries>(options: ErrorMiddlewareOptions<Entries>) {\n const toErrorPayload = createErrorPayloadConverter(options.errors)\n const toHttpErrorResponse = createHttpErrorResponseConverter(options.errors)\n\n async function clearSession(context: RequestContext): Promise<void> {\n const { authCookies } = await options.getAuth(context).$context\n clearStaleSessionCookies(authCookies)\n }\n\n async function handleFunctionError(cause: unknown, context: RequestContext): Promise<never> {\n // oxlint-disable-next-line typescript/only-throw-error -- TanStack uses throwable control-flow objects.\n if (isNotFound(cause) || isRedirect(cause)) throw cause\n if (cause instanceof StaleSessionError) {\n await clearSession(context)\n // oxlint-disable-next-line typescript/only-throw-error -- Router redirects by throwing this.\n throw options.signIn()\n }\n // oxlint-disable-next-line typescript/only-throw-error -- The client rejects with this and reads its tag.\n throw toErrorPayload(cause)\n }\n\n // A route answers 401 instead of a redirect because fetch would follow it into the HTML shell.\n async function handleRouteError(cause: unknown, context: RequestContext): Promise<Response> {\n // oxlint-disable-next-line typescript/only-throw-error -- TanStack uses throwable control-flow objects.\n if (isNotFound(cause) || isRedirect(cause)) throw cause\n if (cause instanceof StaleSessionError) await clearSession(context)\n return toHttpErrorResponse(cause)\n }\n\n const functionErrorMiddleware = createMiddleware({ type: 'function' }).server(\n async ({ next, context }) => {\n try {\n return await next()\n } catch (cause) {\n return handleFunctionError(cause, context)\n }\n },\n )\n\n const routeErrorMiddleware = createMiddleware({ type: 'request' }).server(\n async ({ next, context }) => {\n try {\n return await next()\n } catch (cause) {\n return handleRouteError(cause, context)\n }\n },\n )\n\n return { functionErrorMiddleware, routeErrorMiddleware, toErrorPayload, toHttpErrorResponse }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"tanstack.js","names":["logger"],"sources":["../src/infrastructure/tanstack/auth.middleware.ts","../src/infrastructure/tanstack/resolve-failure.ts","../src/infrastructure/tanstack/http-error-response.ts","../src/infrastructure/tanstack/session-cookies.ts","../src/infrastructure/tanstack/to-error-payload.ts","../src/infrastructure/tanstack/error.middleware.ts","../src/infrastructure/tanstack/last-login-method.ts"],"sourcesContent":["import { createMiddleware, type Register, type RequestServerOptions } from '@tanstack/react-start'\nimport { getRequestHeaders } from '@tanstack/react-start/server'\nimport { getSessionCookie } from 'better-auth/cookies'\n\nimport { AuthenticationError, StaleSessionError, createLogger } from '@/core'\n\nconst logger = createLogger('auth-middleware')\n\n/** The fields middleware reads; generic callers retain every additional session and user field. */\nexport type AuthSession = {\n readonly user: { readonly id: string }\n readonly session: { readonly id: string }\n}\n\n/** Authenticated context retains the application's complete user and session types. */\nexport type RequiredAuthContext<Session extends AuthSession> = {\n readonly user: Session['user']\n readonly session: Session['session']\n}\n\n/** Optional authentication supplies both fields together or neither field. */\nexport type AuthContext<Session extends AuthSession> =\n | RequiredAuthContext<Session>\n | {\n readonly user: undefined\n readonly session: undefined\n }\n\n/** Select the current request's Better Auth instance from TanStack's registered context. */\nexport type AuthMiddlewareOptions<Session extends AuthSession> = {\n readonly getAuth: (context: RequestServerOptions<Register, undefined>['context']) => {\n readonly api: {\n readonly getSession: (options: { headers: Headers }) => Promise<Session | null>\n }\n }\n}\n\n/**\n * Preserve Porte's function and request middleware contracts with application-owned services.\n * Optional lookup failures log once and continue as guests. Required lookup failures propagate.\n */\nexport function createAuthMiddleware<Session extends AuthSession>(\n options: AuthMiddlewareOptions<Session>,\n) {\n const extractAuth = createMiddleware({ type: 'function' }).server<AuthContext<Session>>(\n async ({ next, context }) => {\n let resolved: Session | null\n try {\n resolved = await options.getAuth(context).api.getSession({ headers: getRequestHeaders() })\n } catch (error) {\n logger.error('get_session_failed', { error })\n resolved = null\n }\n if (resolved === null)\n return next<AuthContext<Session>>({ context: { user: undefined, session: undefined } })\n return next<AuthContext<Session>>({\n context: { user: resolved.user, session: resolved.session },\n })\n },\n )\n\n async function resolveRequiredSession(\n context: RequestServerOptions<Register, undefined>['context'],\n headers: Headers,\n ): Promise<Session> {\n const resolved = await options.getAuth(context).api.getSession({ headers })\n if (resolved === null) {\n if (getSessionCookie(headers)) throw new StaleSessionError()\n throw new AuthenticationError()\n }\n return resolved\n }\n\n const requireAuth = createMiddleware({ type: 'function' }).server(async ({ next, context }) => {\n const resolved = await resolveRequiredSession(context, getRequestHeaders())\n return next<RequiredAuthContext<Session>>({\n context: { user: resolved.user, session: resolved.session },\n })\n })\n const requireAuthRequest = createMiddleware({ type: 'request' }).server(\n async ({ request, next, context }) => {\n const resolved = await resolveRequiredSession(context, request.headers)\n return next<RequiredAuthContext<Session>>({\n context: { user: resolved.user, session: resolved.session },\n })\n },\n )\n return { extractAuth, requireAuth, requireAuthRequest }\n}\n","import { AppError, createLogger, type ErrorTable, type ResolvedError } from '@/core'\nimport type { ErrorPayloadOf } from '@/core'\n\nconst logger = createLogger('error-boundary')\n\n/**\n * Resolve one failure through the table or fall back to the generic replacement, and log it once.\n * Both transport converters call this, so one rule decides the log level: mapped is a warning, unmapped is an error with the cause.\n */\nexport function resolveFailure<Entries>(\n table: ErrorTable<Entries>,\n cause: unknown,\n): ResolvedError<ErrorPayloadOf<ErrorTable<Entries>>> {\n const resolved = table.resolve(cause)\n if (resolved !== null) {\n logger.warn('handled_error', {\n details: { tag: resolved.payload._tag, status: resolved.status },\n })\n return resolved\n }\n const classification = cause instanceof AppError ? cause.classification : 'unknown'\n logger.error('unexpected_error', { error: cause, details: { classification } })\n return table.fallback(cause)\n}\n","import { getReasonPhrase } from 'http-status-codes'\nimport { z } from 'zod'\n\nimport type { ErrorTable, ProblemDetails } from '@/core'\n\nimport { resolveFailure } from './resolve-failure.ts'\n\n// A known delay becomes the header; a null delay sends no header.\nconst RetryAfterSchema = z.object({ retryAfter: z.number() })\n\n/**\n * Build the API route converter for one error table.\n * The body is RFC 9457 problem details; public fields become extension members.\n */\nexport function createHttpErrorResponseConverter<Entries>(table: ErrorTable<Entries>) {\n return function toHttpErrorResponse(cause: unknown): Response {\n const { status, payload } = resolveFailure(table, cause)\n const { _tag, message, ...fields } = payload\n const body: ProblemDetails = {\n type: 'about:blank',\n title: getReasonPhrase(status),\n detail: message,\n ...fields,\n }\n const headers = new Headers({ 'Content-Type': 'application/problem+json' })\n const retry = RetryAfterSchema.safeParse(payload)\n if (retry.success) headers.set('Retry-After', String(retry.data.retryAfter))\n return Response.json(body, { status, headers })\n }\n}\n","import { deleteCookie, getRequestHeaders } from '@tanstack/react-start/server'\nimport type { BetterAuthCookies } from 'better-auth'\nimport { parseCookies } from 'better-auth/cookies'\n\ntype AuthCookie = BetterAuthCookies['sessionToken']\ntype DeleteCookieOptions = NonNullable<Parameters<typeof deleteCookie>[1]>\n\n/**\n * Delete the session, session cache, account cache, and remember-me cookies of one instance.\n * Chunks present on the request go too. Names and attributes come from the instance, so custom prefixes and domain cookies clear.\n */\nexport function clearStaleSessionCookies(cookies: BetterAuthCookies): void {\n const present = [...parseCookies(getRequestHeaders().get('cookie') ?? '').keys()]\n const definitions = [\n cookies.sessionToken,\n cookies.sessionData,\n cookies.accountData,\n cookies.dontRememberToken,\n ]\n for (const cookie of definitions) {\n // Better Auth names a chunk `${name}.${index}`, so a missed chunk would resurrect the value.\n const chunks = present.filter((name) => name.startsWith(`${cookie.name}.`))\n for (const name of new Set([cookie.name, ...chunks]))\n deleteCookie(name, deletionOf(cookie.attributes))\n }\n}\n\nfunction deletionOf(attributes: AuthCookie['attributes']): DeleteCookieOptions {\n // Better Auth sets `/` and the secure flag at runtime; the types leave both optional.\n const options: DeleteCookieOptions = {\n path: attributes.path ?? '/',\n secure: attributes.secure ?? false,\n }\n if (attributes.domain !== undefined) options.domain = attributes.domain\n return options\n}\n","import { z } from 'zod'\n\nimport { ValidationError, type ErrorPayloadOf, type ErrorTable } from '@/core'\n\nimport { resolveFailure } from './resolve-failure.ts'\n\n// TanStack serializes a validator's issues into `Error.message` as JSON.\nconst SerializedIssuesSchema = z\n .array(z.object({ message: z.string(), path: z.array(z.union([z.string(), z.number()])) }))\n .min(1)\n\nfunction reconstructValidationError(cause: unknown): ValidationError | null {\n if (!(cause instanceof Error)) return null\n let message: unknown\n try {\n message = JSON.parse(cause.message)\n } catch {\n return null\n }\n const parsed = SerializedIssuesSchema.safeParse(message)\n return parsed.success ? ValidationError.fromIssues(parsed.data) : null\n}\n\n/**\n * Build the server-function converter for one error table.\n * The result is a plain object, because only own data survives serialization.\n */\nexport function createErrorPayloadConverter<Entries>(table: ErrorTable<Entries>) {\n return function toErrorPayload(cause: unknown): ErrorPayloadOf<ErrorTable<Entries>> {\n return resolveFailure(table, reconstructValidationError(cause) ?? cause).payload\n }\n}\n","import { isNotFound, isRedirect, type AnyRedirect } from '@tanstack/react-router'\nimport { createMiddleware, type Register, type RequestServerOptions } from '@tanstack/react-start'\nimport type { BetterAuthCookies } from 'better-auth'\n\nimport { StaleSessionError, type ErrorTable } from '@/core'\n\nimport { createHttpErrorResponseConverter } from './http-error-response.ts'\nimport { clearStaleSessionCookies } from './session-cookies.ts'\nimport { createErrorPayloadConverter } from './to-error-payload.ts'\n\ntype RequestContext = RequestServerOptions<Register, undefined>['context']\n\n/** The part of a Better Auth instance the boundary reads: its computed cookie definitions. */\nexport type AuthCookieSource = {\n readonly $context: Promise<{ readonly authCookies: BetterAuthCookies }>\n}\n\n/** The application's error table, its stale-session redirect, and its Better Auth instance. */\nexport type ErrorMiddlewareOptions<Entries> = {\n readonly errors: ErrorTable<Entries>\n /** Build the redirect a server function throws for a stale session. */\n readonly signIn: () => AnyRedirect\n /** Select the request's Better Auth instance; its cookie definitions say what to clear. */\n readonly getAuth: (context: RequestContext) => AuthCookieSource\n}\n\n/**\n * Build both transport boundaries from one error table.\n * Register `functionErrorMiddleware` globally. Put `routeErrorMiddleware` first in an API route's `server.middleware`.\n */\nexport function createErrorMiddleware<Entries>(options: ErrorMiddlewareOptions<Entries>) {\n const toErrorPayload = createErrorPayloadConverter(options.errors)\n const toHttpErrorResponse = createHttpErrorResponseConverter(options.errors)\n\n async function clearSession(context: RequestContext): Promise<void> {\n const { authCookies } = await options.getAuth(context).$context\n clearStaleSessionCookies(authCookies)\n }\n\n async function handleFunctionError(cause: unknown, context: RequestContext): Promise<never> {\n // oxlint-disable-next-line typescript/only-throw-error -- TanStack uses throwable control-flow objects.\n if (isNotFound(cause) || isRedirect(cause)) throw cause\n if (cause instanceof StaleSessionError) {\n await clearSession(context)\n // oxlint-disable-next-line typescript/only-throw-error -- Router redirects by throwing this.\n throw options.signIn()\n }\n // oxlint-disable-next-line typescript/only-throw-error -- The client rejects with this and reads its tag.\n throw toErrorPayload(cause)\n }\n\n // A route answers 401 instead of a redirect because fetch would follow it into the HTML shell.\n async function handleRouteError(cause: unknown, context: RequestContext): Promise<Response> {\n // oxlint-disable-next-line typescript/only-throw-error -- TanStack uses throwable control-flow objects.\n if (isNotFound(cause) || isRedirect(cause)) throw cause\n if (cause instanceof StaleSessionError) await clearSession(context)\n return toHttpErrorResponse(cause)\n }\n\n const functionErrorMiddleware = createMiddleware({ type: 'function' }).server(\n async ({ next, context }) => {\n try {\n return await next()\n } catch (cause) {\n return handleFunctionError(cause, context)\n }\n },\n )\n\n const routeErrorMiddleware = createMiddleware({ type: 'request' }).server(\n async ({ next, context }) => {\n try {\n return await next()\n } catch (cause) {\n return handleRouteError(cause, context)\n }\n },\n )\n\n return { functionErrorMiddleware, routeErrorMiddleware, toErrorPayload, toHttpErrorResponse }\n}\n","import { getRequestHeaders } from '@tanstack/react-start/server'\nimport { parseCookies } from 'better-auth/cookies'\n\n// Better Auth keeps the plugin default private; this is the value LastLoginMethodOptions.cookieName documents.\nconst DEFAULT_COOKIE_NAME = 'better-auth.last_used_login_method'\n\n/**\n * Read the method this browser last signed in with from the current request, for the sign-in loader on the server.\n * Pass `cookieName` only when `integrations.lastLoginMethod.cookieName` is set. Returns `null` when the cookie is absent.\n */\nexport function getLastUsedLoginMethod(cookieName = DEFAULT_COOKIE_NAME): string | null {\n return parseCookies(getRequestHeaders().get('cookie') ?? '').get(cookieName) ?? null\n}\n"],"mappings":"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"}
@@ -1,4 +1,5 @@
1
- import { o as IEventCollector } from "./index-Bdyh3_xC.js";
1
+ import "./index-BStnggQO.js";
2
+ import { o as IEventCollector } from "./index-DWIRrJMP.js";
2
3
  import { BatchItem } from "drizzle-orm/batch";
3
4
  //#region src/infrastructure/drizzle-schema.d.ts
4
5
  /**
@@ -12,4 +13,4 @@ type DrizzleSchema = Record<string, unknown>;
12
13
  declare const eventCollector: IEventCollector;
13
14
  //#endregion
14
15
  export { DrizzleSchema as n, eventCollector as t };
15
- //# sourceMappingURL=unit-of-work-context-ml9L9cyY.d.ts.map
16
+ //# sourceMappingURL=unit-of-work-context-CPz9rdSS.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"unit-of-work-context-CPz9rdSS.d.ts","names":[],"sources":["../src/infrastructure/drizzle-schema.ts","../src/infrastructure/unit-of-work-context.ts"],"mappings":";;;;;;;;KAKY,gBAAgB;;;;cCuBf,gBAAgB"}
@@ -1,4 +1,4 @@
1
- import { t as UnitOfWorkAlreadyActiveError } from "./application-DEerezCl.js";
1
+ import { t as UnitOfWorkAlreadyActiveError } from "./application-DjsQtpgw.js";
2
2
  import { panic } from "better-result";
3
3
  import { AsyncLocalStorage } from "node:async_hooks";
4
4
 
@@ -45,4 +45,4 @@ function currentContext() {
45
45
 
46
46
  //#endregion
47
47
  export { stageD1Statement as i, eventCollector as n, runWithUnitOfWorkContext as r, collectD1Statements as t };
48
- //# sourceMappingURL=unit-of-work-context-C7vz5OYS.js.map
48
+ //# sourceMappingURL=unit-of-work-context-DToDpAkv.js.map