@beignet/core 0.0.1 → 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (287) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/README.md +202 -8
  3. package/dist/application/index.d.ts +93 -9
  4. package/dist/application/index.d.ts.map +1 -1
  5. package/dist/application/index.js +11 -11
  6. package/dist/application/index.js.map +1 -1
  7. package/dist/client/client.d.ts +73 -12
  8. package/dist/client/client.d.ts.map +1 -1
  9. package/dist/client/client.js +37 -12
  10. package/dist/client/client.js.map +1 -1
  11. package/dist/client/index.d.ts +12 -0
  12. package/dist/client/index.d.ts.map +1 -1
  13. package/dist/client/index.js +6 -0
  14. package/dist/client/index.js.map +1 -1
  15. package/dist/client/types.d.ts +69 -8
  16. package/dist/client/types.d.ts.map +1 -1
  17. package/dist/config/index.d.ts +84 -0
  18. package/dist/config/index.d.ts.map +1 -1
  19. package/dist/config/index.js +36 -0
  20. package/dist/config/index.js.map +1 -1
  21. package/dist/contracts/contract-builder.d.ts +49 -22
  22. package/dist/contracts/contract-builder.d.ts.map +1 -1
  23. package/dist/contracts/contract-builder.js +48 -21
  24. package/dist/contracts/contract-builder.js.map +1 -1
  25. package/dist/contracts/contract-group.d.ts +35 -19
  26. package/dist/contracts/contract-group.d.ts.map +1 -1
  27. package/dist/contracts/contract-group.js +35 -19
  28. package/dist/contracts/contract-group.js.map +1 -1
  29. package/dist/contracts/contract-like.d.ts +4 -4
  30. package/dist/contracts/contract-like.d.ts.map +1 -1
  31. package/dist/contracts/contract-like.js +2 -1
  32. package/dist/contracts/contract-like.js.map +1 -1
  33. package/dist/contracts/index.d.ts +28 -0
  34. package/dist/contracts/index.d.ts.map +1 -1
  35. package/dist/contracts/index.js +12 -0
  36. package/dist/contracts/index.js.map +1 -1
  37. package/dist/contracts/openapi-meta.d.ts +8 -8
  38. package/dist/contracts/openapi-meta.d.ts.map +1 -1
  39. package/dist/contracts/path-template.d.ts +27 -0
  40. package/dist/contracts/path-template.d.ts.map +1 -1
  41. package/dist/contracts/path-template.js +6 -0
  42. package/dist/contracts/path-template.js.map +1 -1
  43. package/dist/contracts/types.d.ts +104 -10
  44. package/dist/contracts/types.d.ts.map +1 -1
  45. package/dist/contracts/types.js +15 -0
  46. package/dist/contracts/types.js.map +1 -1
  47. package/dist/contracts/utils.d.ts +6 -0
  48. package/dist/contracts/utils.d.ts.map +1 -1
  49. package/dist/contracts/utils.js +6 -0
  50. package/dist/contracts/utils.js.map +1 -1
  51. package/dist/domain/entity.d.ts +22 -11
  52. package/dist/domain/entity.d.ts.map +1 -1
  53. package/dist/domain/entity.js +5 -1
  54. package/dist/domain/entity.js.map +1 -1
  55. package/dist/domain/events.d.ts +5 -2
  56. package/dist/domain/events.d.ts.map +1 -1
  57. package/dist/domain/events.js +4 -1
  58. package/dist/domain/events.js.map +1 -1
  59. package/dist/domain/value-object.d.ts +19 -9
  60. package/dist/domain/value-object.d.ts.map +1 -1
  61. package/dist/domain/value-object.js +5 -1
  62. package/dist/domain/value-object.js.map +1 -1
  63. package/dist/errors/catalog.d.ts +40 -16
  64. package/dist/errors/catalog.d.ts.map +1 -1
  65. package/dist/errors/catalog.js +18 -7
  66. package/dist/errors/catalog.js.map +1 -1
  67. package/dist/errors/response.d.ts +16 -4
  68. package/dist/errors/response.d.ts.map +1 -1
  69. package/dist/errors/response.js +3 -3
  70. package/dist/errors/response.js.map +1 -1
  71. package/dist/errors/validation.d.ts +10 -1
  72. package/dist/errors/validation.d.ts.map +1 -1
  73. package/dist/errors/validation.js +3 -0
  74. package/dist/errors/validation.js.map +1 -1
  75. package/dist/events/index.d.ts +133 -0
  76. package/dist/events/index.d.ts.map +1 -1
  77. package/dist/events/index.js +30 -0
  78. package/dist/events/index.js.map +1 -1
  79. package/dist/idempotency/index.d.ts +355 -0
  80. package/dist/idempotency/index.d.ts.map +1 -0
  81. package/dist/idempotency/index.js +360 -0
  82. package/dist/idempotency/index.js.map +1 -0
  83. package/dist/jobs/index.d.ts +248 -4
  84. package/dist/jobs/index.d.ts.map +1 -1
  85. package/dist/jobs/index.js +183 -1
  86. package/dist/jobs/index.js.map +1 -1
  87. package/dist/mail/index.d.ts +149 -0
  88. package/dist/mail/index.d.ts.map +1 -1
  89. package/dist/mail/index.js +30 -0
  90. package/dist/mail/index.js.map +1 -1
  91. package/dist/notifications/index.d.ts +369 -0
  92. package/dist/notifications/index.d.ts.map +1 -0
  93. package/dist/notifications/index.js +310 -0
  94. package/dist/notifications/index.js.map +1 -0
  95. package/dist/openapi/index.d.ts +132 -16
  96. package/dist/openapi/index.d.ts.map +1 -1
  97. package/dist/openapi/index.js +1 -1
  98. package/dist/openapi/index.js.map +1 -1
  99. package/dist/outbox/index.d.ts +474 -0
  100. package/dist/outbox/index.d.ts.map +1 -0
  101. package/dist/outbox/index.js +538 -0
  102. package/dist/outbox/index.js.map +1 -0
  103. package/dist/pagination/index.d.ts +166 -0
  104. package/dist/pagination/index.d.ts.map +1 -0
  105. package/dist/pagination/index.js +96 -0
  106. package/dist/pagination/index.js.map +1 -0
  107. package/dist/ports/audit.d.ts +271 -0
  108. package/dist/ports/audit.d.ts.map +1 -1
  109. package/dist/ports/audit.js +128 -0
  110. package/dist/ports/audit.js.map +1 -1
  111. package/dist/ports/auth.d.ts +70 -0
  112. package/dist/ports/auth.d.ts.map +1 -1
  113. package/dist/ports/auth.js +30 -0
  114. package/dist/ports/auth.js.map +1 -1
  115. package/dist/ports/cache.d.ts +41 -0
  116. package/dist/ports/cache.d.ts.map +1 -1
  117. package/dist/ports/cache.js +10 -0
  118. package/dist/ports/cache.js.map +1 -1
  119. package/dist/ports/clock.d.ts +38 -0
  120. package/dist/ports/clock.d.ts.map +1 -1
  121. package/dist/ports/clock.js +20 -0
  122. package/dist/ports/clock.js.map +1 -1
  123. package/dist/ports/id-generator.d.ts +37 -0
  124. package/dist/ports/id-generator.d.ts.map +1 -1
  125. package/dist/ports/id-generator.js +22 -0
  126. package/dist/ports/id-generator.js.map +1 -1
  127. package/dist/ports/index.d.ts +83 -0
  128. package/dist/ports/index.d.ts.map +1 -1
  129. package/dist/ports/index.js +41 -5
  130. package/dist/ports/index.js.map +1 -1
  131. package/dist/ports/logger.d.ts +56 -0
  132. package/dist/ports/logger.d.ts.map +1 -1
  133. package/dist/ports/logger.js +17 -0
  134. package/dist/ports/logger.js.map +1 -1
  135. package/dist/ports/policy.d.ts +132 -0
  136. package/dist/ports/policy.d.ts.map +1 -1
  137. package/dist/ports/policy.js +45 -0
  138. package/dist/ports/policy.js.map +1 -1
  139. package/dist/ports/rate-limit.d.ts +25 -0
  140. package/dist/ports/rate-limit.d.ts.map +1 -1
  141. package/dist/ports/rate-limit.js +10 -0
  142. package/dist/ports/rate-limit.js.map +1 -1
  143. package/dist/ports/redaction.d.ts +101 -0
  144. package/dist/ports/redaction.d.ts.map +1 -1
  145. package/dist/ports/redaction.js +59 -0
  146. package/dist/ports/redaction.js.map +1 -1
  147. package/dist/ports/storage.d.ts +100 -0
  148. package/dist/ports/storage.d.ts.map +1 -1
  149. package/dist/ports/storage.js +10 -0
  150. package/dist/ports/storage.js.map +1 -1
  151. package/dist/ports/testing.d.ts +47 -0
  152. package/dist/ports/testing.d.ts.map +1 -1
  153. package/dist/ports/testing.js +23 -0
  154. package/dist/ports/testing.js.map +1 -1
  155. package/dist/ports/unit-of-work.d.ts +60 -3
  156. package/dist/ports/unit-of-work.d.ts.map +1 -1
  157. package/dist/ports/unit-of-work.js +11 -2
  158. package/dist/ports/unit-of-work.js.map +1 -1
  159. package/dist/providers/instrumentation.d.ts +205 -1
  160. package/dist/providers/instrumentation.d.ts.map +1 -1
  161. package/dist/providers/instrumentation.js +14 -0
  162. package/dist/providers/instrumentation.js.map +1 -1
  163. package/dist/providers/provider.d.ts +14 -1
  164. package/dist/providers/provider.d.ts.map +1 -1
  165. package/dist/providers/provider.js.map +1 -1
  166. package/dist/schedules/index.d.ts +246 -0
  167. package/dist/schedules/index.d.ts.map +1 -1
  168. package/dist/schedules/index.js +27 -0
  169. package/dist/schedules/index.js.map +1 -1
  170. package/dist/server/health.d.ts +14 -5
  171. package/dist/server/health.d.ts.map +1 -1
  172. package/dist/server/health.js +5 -2
  173. package/dist/server/health.js.map +1 -1
  174. package/dist/server/hooks/auth.d.ts +68 -26
  175. package/dist/server/hooks/auth.d.ts.map +1 -1
  176. package/dist/server/hooks/auth.js +44 -55
  177. package/dist/server/hooks/auth.js.map +1 -1
  178. package/dist/server/hooks/cors.d.ts +27 -0
  179. package/dist/server/hooks/cors.d.ts.map +1 -1
  180. package/dist/server/hooks/cors.js +12 -0
  181. package/dist/server/hooks/cors.js.map +1 -1
  182. package/dist/server/hooks/errors.d.ts +15 -6
  183. package/dist/server/hooks/errors.d.ts.map +1 -1
  184. package/dist/server/hooks/errors.js.map +1 -1
  185. package/dist/server/hooks/index.d.ts +4 -1
  186. package/dist/server/hooks/index.d.ts.map +1 -1
  187. package/dist/server/hooks/index.js +3 -0
  188. package/dist/server/hooks/index.js.map +1 -1
  189. package/dist/server/hooks/logging.d.ts +36 -0
  190. package/dist/server/hooks/logging.d.ts.map +1 -1
  191. package/dist/server/hooks/logging.js +6 -0
  192. package/dist/server/hooks/logging.js.map +1 -1
  193. package/dist/server/hooks/rate-limit.d.ts +33 -0
  194. package/dist/server/hooks/rate-limit.d.ts.map +1 -1
  195. package/dist/server/hooks/rate-limit.js +11 -0
  196. package/dist/server/hooks/rate-limit.js.map +1 -1
  197. package/dist/server/http.d.ts +222 -0
  198. package/dist/server/http.d.ts.map +1 -1
  199. package/dist/server/http.js +20 -1
  200. package/dist/server/http.js.map +1 -1
  201. package/dist/server/index.d.ts +19 -1
  202. package/dist/server/index.d.ts.map +1 -1
  203. package/dist/server/index.js +7 -1
  204. package/dist/server/index.js.map +1 -1
  205. package/dist/server/openapi.d.ts +5 -3
  206. package/dist/server/openapi.d.ts.map +1 -1
  207. package/dist/server/openapi.js +4 -2
  208. package/dist/server/openapi.js.map +1 -1
  209. package/dist/server/providers/loadProviderConfig.d.ts +9 -0
  210. package/dist/server/providers/loadProviderConfig.d.ts.map +1 -1
  211. package/dist/server/providers/loadProviderConfig.js +9 -0
  212. package/dist/server/providers/loadProviderConfig.js.map +1 -1
  213. package/dist/server/server.d.ts +159 -19
  214. package/dist/server/server.d.ts.map +1 -1
  215. package/dist/server/server.js +72 -31
  216. package/dist/server/server.js.map +1 -1
  217. package/dist/testing/index.d.ts +171 -0
  218. package/dist/testing/index.d.ts.map +1 -0
  219. package/dist/testing/index.js +127 -0
  220. package/dist/testing/index.js.map +1 -0
  221. package/dist/uploads/client.d.ts +278 -0
  222. package/dist/uploads/client.d.ts.map +1 -0
  223. package/dist/uploads/client.js +428 -0
  224. package/dist/uploads/client.js.map +1 -0
  225. package/dist/uploads/index.d.ts +361 -0
  226. package/dist/uploads/index.d.ts.map +1 -0
  227. package/dist/uploads/index.js +543 -0
  228. package/dist/uploads/index.js.map +1 -0
  229. package/package.json +31 -2
  230. package/src/application/index.ts +85 -22
  231. package/src/client/client.ts +73 -12
  232. package/src/client/index.ts +12 -0
  233. package/src/client/types.ts +70 -9
  234. package/src/config/index.ts +86 -0
  235. package/src/contracts/contract-builder.ts +49 -22
  236. package/src/contracts/contract-group.ts +35 -19
  237. package/src/contracts/contract-like.ts +4 -4
  238. package/src/contracts/index.ts +28 -1
  239. package/src/contracts/openapi-meta.ts +8 -8
  240. package/src/contracts/path-template.ts +27 -0
  241. package/src/contracts/types.ts +111 -10
  242. package/src/contracts/utils.ts +6 -0
  243. package/src/domain/entity.ts +22 -11
  244. package/src/domain/events.ts +5 -2
  245. package/src/domain/value-object.ts +19 -9
  246. package/src/errors/catalog.ts +40 -16
  247. package/src/errors/response.ts +16 -4
  248. package/src/errors/validation.ts +10 -1
  249. package/src/events/index.ts +134 -0
  250. package/src/idempotency/index.ts +767 -0
  251. package/src/jobs/index.ts +437 -5
  252. package/src/mail/index.ts +149 -0
  253. package/src/notifications/index.ts +771 -0
  254. package/src/openapi/index.ts +133 -16
  255. package/src/outbox/index.ts +1104 -0
  256. package/src/pagination/index.ts +278 -0
  257. package/src/ports/audit.ts +271 -0
  258. package/src/ports/auth.ts +70 -0
  259. package/src/ports/cache.ts +41 -0
  260. package/src/ports/clock.ts +38 -0
  261. package/src/ports/id-generator.ts +37 -0
  262. package/src/ports/index.ts +106 -11
  263. package/src/ports/logger.ts +56 -0
  264. package/src/ports/policy.ts +133 -0
  265. package/src/ports/rate-limit.ts +25 -0
  266. package/src/ports/redaction.ts +101 -0
  267. package/src/ports/storage.ts +100 -0
  268. package/src/ports/testing.ts +47 -0
  269. package/src/ports/unit-of-work.ts +60 -3
  270. package/src/providers/instrumentation.ts +211 -1
  271. package/src/providers/provider.ts +14 -1
  272. package/src/schedules/index.ts +247 -0
  273. package/src/server/health.ts +14 -5
  274. package/src/server/hooks/auth.ts +105 -120
  275. package/src/server/hooks/cors.ts +27 -0
  276. package/src/server/hooks/errors.ts +15 -6
  277. package/src/server/hooks/index.ts +4 -5
  278. package/src/server/hooks/logging.ts +36 -0
  279. package/src/server/hooks/rate-limit.ts +33 -0
  280. package/src/server/http.ts +249 -1
  281. package/src/server/index.ts +19 -1
  282. package/src/server/openapi.ts +5 -3
  283. package/src/server/providers/loadProviderConfig.ts +9 -0
  284. package/src/server/server.ts +296 -30
  285. package/src/testing/index.ts +348 -0
  286. package/src/uploads/client.ts +861 -0
  287. package/src/uploads/index.ts +1067 -0
@@ -1,147 +1,132 @@
1
- import {
2
- type AuthPort,
3
- type AuthSession,
4
- AuthUnauthorizedError,
5
- } from "../../ports";
6
- import type { HttpRequestLike, HttpResponse, ServerHook } from "../types";
1
+ import { AuthUnauthorizedError } from "../../ports";
2
+ import type { HttpRequestLike, RouteHook } from "../types";
7
3
 
8
4
  type MaybePromise<T> = T | Promise<T>;
9
5
 
10
- export type AuthHookMode = "public" | "optional" | "required";
11
- export type AuthHookModeInput = AuthHookMode | boolean | null | undefined;
12
-
13
- export type CtxWithAuthPort = {
14
- ports: {
15
- auth: AuthPort;
16
- };
17
- };
18
-
6
+ /**
7
+ * Arguments passed to auth route-hook callbacks.
8
+ */
19
9
  export type AuthHookArgs<Ctx> = {
10
+ /**
11
+ * Framework-neutral request.
12
+ */
20
13
  req: HttpRequestLike;
14
+ /**
15
+ * Current route handler context.
16
+ */
21
17
  ctx: Ctx;
18
+ /**
19
+ * Matched contract metadata and schemas.
20
+ */
22
21
  contract: {
23
22
  metadata?: Record<string, unknown>;
24
23
  };
24
+ /**
25
+ * Parsed path parameters.
26
+ */
25
27
  path: unknown;
28
+ /**
29
+ * Parsed query parameters.
30
+ */
26
31
  query: unknown;
32
+ /**
33
+ * Parsed request headers.
34
+ */
27
35
  headers: unknown;
36
+ /**
37
+ * Parsed request body.
38
+ */
28
39
  body: unknown;
29
40
  };
30
41
 
31
- export type AuthHookAssignArgs<Ctx, Session> = AuthHookArgs<Ctx> & {
32
- session: Session | null;
33
- };
34
-
35
- export type AuthHookUnauthorizedArgs<Ctx, Session> = AuthHookArgs<Ctx> & {
36
- session: Session | null;
37
- };
38
-
39
- export type AuthHooksOptions<Ctx, Session> = {
42
+ /**
43
+ * Options for route-scoped auth hooks.
44
+ */
45
+ export type AuthHooksOptions<Ctx, AddedCtx extends object> = {
46
+ /**
47
+ * Hook name prefix used in diagnostics.
48
+ */
40
49
  name?: string;
41
- mode?: (args: AuthHookArgs<Ctx>) => MaybePromise<AuthHookModeInput>;
42
- getSession?: (args: AuthHookArgs<Ctx>) => MaybePromise<Session | null>;
43
- isAuthenticated?: (session: Session | null) => boolean;
44
- assign?: (args: AuthHookAssignArgs<Ctx, Session>) => MaybePromise<Ctx>;
45
- unauthorized?: (
46
- args: AuthHookUnauthorizedArgs<Ctx, Session>,
47
- ) => MaybePromise<HttpResponse>;
50
+ /**
51
+ * Resolve authenticated context additions for the current request.
52
+ *
53
+ * Return `null` when the request is unauthenticated. Required hooks will
54
+ * reject that request; optional hooks will add no auth context.
55
+ */
56
+ resolve: (args: AuthHookArgs<Ctx>) => MaybePromise<AddedCtx | null>;
48
57
  };
49
58
 
50
- type InferAuthSession<TAuth> =
51
- TAuth extends AuthPort<infer User, infer SessionMetadata>
52
- ? AuthSession<User, SessionMetadata>
53
- : unknown;
54
-
55
- function modeFromInput(input: AuthHookModeInput): AuthHookMode {
56
- if (input === true || input === "required") return "required";
57
- if (input === "optional") return "optional";
58
- return "public";
59
- }
60
-
61
- function defaultMode<Ctx>(args: AuthHookArgs<Ctx>): AuthHookMode {
62
- return modeFromInput(args.contract.metadata?.auth as AuthHookModeInput);
63
- }
64
-
65
- async function defaultGetSession<Ctx>(
66
- args: AuthHookArgs<Ctx>,
67
- ): Promise<unknown | null> {
68
- const auth = (args.ctx as { ports?: { auth?: AuthPort } }).ports?.auth;
69
- if (!auth) {
70
- throw new Error(
71
- "createAuthHooks requires ctx.ports.auth or an explicit getSession option.",
72
- );
73
- }
59
+ /**
60
+ * Route-scoped auth hook set.
61
+ */
62
+ export type AuthRouteHooks<Ctx, AddedCtx extends object> = {
63
+ /**
64
+ * Mark a route as intentionally public.
65
+ */
66
+ public: () => RouteHook<Ctx, Record<string, never>>;
67
+ /**
68
+ * Resolve auth when present and add optional auth fields to the handler ctx.
69
+ */
70
+ optional: () => RouteHook<Ctx, Partial<AddedCtx>>;
71
+ /**
72
+ * Require auth and add authenticated fields to the handler ctx.
73
+ */
74
+ required: () => RouteHook<Ctx, AddedCtx>;
75
+ };
74
76
 
75
- return auth.getSession(args.req);
77
+ function toAuthArgs<Ctx>(
78
+ args: Parameters<RouteHook<Ctx, object>["resolve"]>[0],
79
+ ): AuthHookArgs<Ctx> {
80
+ return {
81
+ req: args.req,
82
+ ctx: args.ctx,
83
+ contract: args.contract,
84
+ path: args.path,
85
+ query: args.query,
86
+ headers: args.headers,
87
+ body: args.body,
88
+ };
76
89
  }
77
90
 
78
- function defaultIsAuthenticated<Session>(session: Session | null): boolean {
79
- return session !== null;
80
- }
91
+ /**
92
+ * Create route-scoped authentication hooks.
93
+ *
94
+ * Use `auth.required()` on routes that require an authenticated actor and
95
+ * `auth.optional()` where handlers can use auth when present. The returned
96
+ * route hooks enrich handler `ctx`; business authorization still belongs in
97
+ * feature policies or use cases.
98
+ *
99
+ * @param options - Auth resolution callback and optional diagnostic name.
100
+ * @returns Public, optional, and required route-hook factories.
101
+ */
102
+ export function createAuthHooks<Ctx, AddedCtx extends object>(
103
+ options: AuthHooksOptions<Ctx, AddedCtx>,
104
+ ): AuthRouteHooks<Ctx, AddedCtx> {
105
+ const name = options.name ?? "auth";
81
106
 
82
- export function createAuthHooks<Ctx extends CtxWithAuthPort>(
83
- options?: AuthHooksOptions<Ctx, InferAuthSession<Ctx["ports"]["auth"]>>,
84
- ): ServerHook<Ctx, Ctx["ports"]>;
85
- export function createAuthHooks<Ctx, Session>(
86
- options: AuthHooksOptions<Ctx, Session> & {
87
- getSession: (args: AuthHookArgs<Ctx>) => MaybePromise<Session | null>;
88
- },
89
- ): ServerHook<Ctx>;
90
- export function createAuthHooks<Ctx, Session>(
91
- options: AuthHooksOptions<Ctx, Session> = {},
92
- ): ServerHook<Ctx> {
93
107
  return {
94
- name: options.name ?? "auth",
95
- beforeHandle: async ({
96
- req,
97
- ctx,
98
- contract,
99
- path,
100
- query,
101
- headers,
102
- body,
103
- }) => {
104
- const args: AuthHookArgs<Ctx> = {
105
- req,
106
- ctx,
107
- contract,
108
- path,
109
- query,
110
- headers,
111
- body,
112
- };
113
- const mode = modeFromInput(
114
- options.mode ? await options.mode(args) : defaultMode(args),
115
- );
116
-
117
- if (mode === "public") {
118
- return undefined;
119
- }
120
-
121
- const session = options.getSession
122
- ? await options.getSession(args)
123
- : ((await defaultGetSession(args)) as Session | null);
124
- const isAuthenticated =
125
- options.isAuthenticated?.(session) ?? defaultIsAuthenticated(session);
126
-
127
- if (mode === "required" && !isAuthenticated) {
128
- if (options.unauthorized) {
129
- return {
130
- ctx,
131
- response: await options.unauthorized({ ...args, session }),
132
- };
108
+ public: () => ({
109
+ name: `${name}.public`,
110
+ resolve: () => undefined,
111
+ }),
112
+ optional: () => ({
113
+ name: `${name}.optional`,
114
+ resolve: async (args) => {
115
+ const additions = await options.resolve(toAuthArgs(args));
116
+
117
+ return additions ?? undefined;
118
+ },
119
+ }),
120
+ required: () => ({
121
+ name: `${name}.required`,
122
+ resolve: async (args) => {
123
+ const additions = await options.resolve(toAuthArgs(args));
124
+ if (!additions) {
125
+ throw new AuthUnauthorizedError();
133
126
  }
134
127
 
135
- throw new AuthUnauthorizedError();
136
- }
137
-
138
- if (!options.assign) {
139
- return undefined;
140
- }
141
-
142
- return {
143
- ctx: await options.assign({ ...args, session }),
144
- };
145
- },
128
+ return additions;
129
+ },
130
+ }),
146
131
  };
147
132
  }
@@ -4,10 +4,25 @@
4
4
 
5
5
  import type { HttpRequestLike, ServerHook } from "../types";
6
6
 
7
+ /**
8
+ * CORS configuration for `createCorsHooks(...)`.
9
+ */
7
10
  export interface CorsConfig {
11
+ /**
12
+ * Allowed origins. Use `"*"` to allow any origin.
13
+ */
8
14
  origins?: string[] | "*";
15
+ /**
16
+ * Allowed HTTP methods.
17
+ */
9
18
  methods?: string[];
19
+ /**
20
+ * Allowed request headers.
21
+ */
10
22
  headers?: string[];
23
+ /**
24
+ * Whether credentialed requests are allowed.
25
+ */
11
26
  credentials?: boolean;
12
27
  }
13
28
 
@@ -28,6 +43,12 @@ function appendVaryOrigin(headers: Record<string, string>): void {
28
43
  headers[varyKey] = current ? `${current}, Origin` : "Origin";
29
44
  }
30
45
 
46
+ /**
47
+ * Apply CORS response headers to a mutable header record.
48
+ *
49
+ * When credentials are enabled with wildcard origins, the request origin is
50
+ * reflected and `Vary: Origin` is appended.
51
+ */
31
52
  export function applyCorsHeaders(
32
53
  headers: Record<string, string>,
33
54
  req: HttpRequestLike,
@@ -62,6 +83,12 @@ export function applyCorsHeaders(
62
83
  }
63
84
  }
64
85
 
86
+ /**
87
+ * Create CORS hooks for preflight and regular responses.
88
+ *
89
+ * `OPTIONS` requests short-circuit with a 204 response. All other responses are
90
+ * decorated in `beforeSend`.
91
+ */
65
92
  export function createCorsHooks<Ctx>(config: CorsConfig): ServerHook<Ctx> {
66
93
  return {
67
94
  name: "cors",
@@ -7,30 +7,39 @@ import type { AppEnvironment } from "../health";
7
7
  import { getRequestIdFromContext } from "./utils";
8
8
 
9
9
  /**
10
- * Re-export AppEnvironment for convenience
10
+ * Re-export `AppEnvironment` for convenience.
11
11
  */
12
12
  export type { AppEnvironment } from "../health";
13
13
 
14
14
  /**
15
- * Error mapping result
15
+ * Framework-neutral response produced by an error mapper.
16
16
  */
17
17
  export interface ErrorMappingResult {
18
+ /**
19
+ * HTTP status code.
20
+ */
18
21
  status: number;
22
+ /**
23
+ * Response body.
24
+ */
19
25
  body: unknown;
26
+ /**
27
+ * Response headers.
28
+ */
20
29
  headers?: Record<string, string>;
21
30
  }
22
31
 
23
32
  /**
24
- * Error mapping configuration
33
+ * Error mapping configuration.
25
34
  */
26
35
  export interface ErrorMappingConfig<Ctx> {
27
- /** Custom error mapper function */
36
+ /** Custom error mapper function. */
28
37
  mapErrorToResponse?: (err: unknown, ctx: Ctx) => ErrorMappingResult;
29
38
 
30
- /** Include stack traces in error responses (default: true in dev/test, false in production) */
39
+ /** Include stack traces in error responses. Defaults to true in dev/test. */
31
40
  includeStackInResponse?: boolean;
32
41
 
33
- /** Application environment */
42
+ /** Application environment. */
34
43
  env?: AppEnvironment;
35
44
  }
36
45
 
@@ -7,12 +7,8 @@ import type { ServerHook } from "../http";
7
7
 
8
8
  export {
9
9
  type AuthHookArgs,
10
- type AuthHookAssignArgs,
11
- type AuthHookMode,
12
- type AuthHookModeInput,
13
10
  type AuthHooksOptions,
14
- type AuthHookUnauthorizedArgs,
15
- type CtxWithAuthPort,
11
+ type AuthRouteHooks,
16
12
  createAuthHooks,
17
13
  } from "./auth";
18
14
  export {
@@ -36,6 +32,9 @@ export {
36
32
  type RateLimitOptions,
37
33
  } from "./rate-limit";
38
34
 
35
+ /**
36
+ * Flatten hook arrays into a single hook list.
37
+ */
39
38
  export function composeHooks<Ctx, Ports extends AnyPorts = AnyPorts>(
40
39
  ...hooks: (ServerHook<Ctx, Ports> | readonly ServerHook<Ctx, Ports>[])[]
41
40
  ): ServerHook<Ctx, Ports>[] {
@@ -6,21 +6,51 @@ import type { HttpContractConfig } from "../../contracts";
6
6
  import type { HttpRequestLike, ServerHook } from "../types";
7
7
  import { getRequestIdFromContext } from "./utils";
8
8
 
9
+ /**
10
+ * Minimal logger shape accepted by `createLoggingHooks(...)`.
11
+ */
9
12
  export interface Logger {
13
+ /**
14
+ * Log an informational event.
15
+ */
10
16
  info: (...args: unknown[]) => void;
17
+ /**
18
+ * Log an error event.
19
+ */
11
20
  error: (...args: unknown[]) => void;
21
+ /**
22
+ * Log a warning event.
23
+ */
12
24
  warn?: (...args: unknown[]) => void;
25
+ /**
26
+ * Log a debug event.
27
+ */
13
28
  debug?: (...args: unknown[]) => void;
14
29
  }
15
30
 
31
+ /**
32
+ * Logging hook configuration.
33
+ */
16
34
  export interface LoggingConfig<Ctx> {
35
+ /**
36
+ * Logger used when custom lifecycle callbacks are not provided.
37
+ */
17
38
  logger?: Logger;
39
+ /**
40
+ * Response header name used to expose `ctx.requestId` when present.
41
+ */
18
42
  requestIdHeader?: string;
43
+ /**
44
+ * Custom request-start observer.
45
+ */
19
46
  onRequestStart?: (args: {
20
47
  ctx?: Ctx;
21
48
  req: HttpRequestLike;
22
49
  contract?: HttpContractConfig;
23
50
  }) => void;
51
+ /**
52
+ * Custom request-end observer.
53
+ */
24
54
  onRequestEnd?: (args: {
25
55
  ctx?: Ctx;
26
56
  req: HttpRequestLike;
@@ -31,6 +61,12 @@ export interface LoggingConfig<Ctx> {
31
61
  }) => void;
32
62
  }
33
63
 
64
+ /**
65
+ * Create request logging hooks.
66
+ *
67
+ * Logging observer errors are intentionally ignored so logging cannot break
68
+ * request handling.
69
+ */
34
70
  export function createLoggingHooks<Ctx>(
35
71
  config: LoggingConfig<Ctx>,
36
72
  ): ServerHook<Ctx> {
@@ -7,10 +7,16 @@ import { AppError, httpErrors } from "../../errors";
7
7
  import type { ActivityActor, RateLimitPort } from "../../ports";
8
8
  import type { HttpRequestLike, ServerHook } from "../types";
9
9
 
10
+ /**
11
+ * Ports required by rate-limit hooks.
12
+ */
10
13
  export type RateLimitPorts = {
11
14
  rateLimit: RateLimitPort;
12
15
  };
13
16
 
17
+ /**
18
+ * Minimal context shape required for user-scoped rate limits.
19
+ */
14
20
  export type CtxWithRateLimit = {
15
21
  ports: RateLimitPorts;
16
22
  actor?: ActivityActor;
@@ -18,16 +24,32 @@ export type CtxWithRateLimit = {
18
24
 
19
25
  type EarlyRateLimitScope = Exclude<RateLimitScope, "user">;
20
26
 
27
+ /**
28
+ * Options for `createRateLimitHooks(...)`.
29
+ */
21
30
  export interface RateLimitOptions<Ctx> {
31
+ /**
32
+ * Build a rate-limit key after context exists.
33
+ *
34
+ * This is used for user-scoped limits and any late key strategy.
35
+ */
22
36
  key?: (args: {
23
37
  ctx: Ctx;
24
38
  req: HttpRequestLike;
25
39
  scope: RateLimitScope;
26
40
  }) => string;
41
+ /**
42
+ * Build a rate-limit key before request parsing and context creation.
43
+ *
44
+ * This is used for global and IP-scoped limits.
45
+ */
27
46
  earlyKey?: (args: {
28
47
  req: HttpRequestLike;
29
48
  scope: EarlyRateLimitScope;
30
49
  }) => string;
50
+ /**
51
+ * Resolve a client IP from the raw request.
52
+ */
31
53
  getClientIp?: (req: HttpRequestLike) => string | undefined;
32
54
  }
33
55
 
@@ -112,6 +134,17 @@ async function enforceRateLimit(
112
134
  );
113
135
  }
114
136
 
137
+ /**
138
+ * Create metadata-driven rate-limit hooks.
139
+ *
140
+ * The hook reads `contract.metadata.rateLimit`. Global and IP-scoped limits run
141
+ * in `onRequest` before context creation; user-scoped limits run in
142
+ * `beforeHandle` after `ctx.actor` is available. Exceeded limits throw the
143
+ * framework `TooManyRequests` app error.
144
+ *
145
+ * @param options - Optional key builders and client-IP resolver.
146
+ * @returns A server hook backed by `ctx.ports.rateLimit`.
147
+ */
115
148
  export function createRateLimitHooks<Ctx extends CtxWithRateLimit>(
116
149
  options: RateLimitOptions<Ctx> = {},
117
150
  ): ServerHook<Ctx, RateLimitPorts> {