@furystack/rest-service 13.0.0 → 14.1.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 (311) hide show
  1. package/CHANGELOG.md +124 -0
  2. package/README.md +47 -28
  3. package/esm/actions/error-action.d.ts +7 -2
  4. package/esm/actions/error-action.d.ts.map +1 -1
  5. package/esm/actions/error-action.js +7 -2
  6. package/esm/actions/error-action.js.map +1 -1
  7. package/esm/actions/get-current-user.d.ts +1 -4
  8. package/esm/actions/get-current-user.d.ts.map +1 -1
  9. package/esm/actions/get-current-user.js +1 -4
  10. package/esm/actions/get-current-user.js.map +1 -1
  11. package/esm/actions/get-current-user.spec.js +10 -6
  12. package/esm/actions/get-current-user.spec.js.map +1 -1
  13. package/esm/actions/is-authenticated.d.ts +3 -4
  14. package/esm/actions/is-authenticated.d.ts.map +1 -1
  15. package/esm/actions/is-authenticated.js +3 -4
  16. package/esm/actions/is-authenticated.js.map +1 -1
  17. package/esm/actions/is-authenticated.spec.js +10 -6
  18. package/esm/actions/is-authenticated.spec.js.map +1 -1
  19. package/esm/actions/logout-action.spec.js +11 -9
  20. package/esm/actions/logout-action.spec.js.map +1 -1
  21. package/esm/actions/logout.d.ts +2 -6
  22. package/esm/actions/logout.d.ts.map +1 -1
  23. package/esm/actions/logout.js +3 -7
  24. package/esm/actions/logout.js.map +1 -1
  25. package/esm/actions/not-found-action.d.ts +1 -3
  26. package/esm/actions/not-found-action.d.ts.map +1 -1
  27. package/esm/actions/not-found-action.js +1 -3
  28. package/esm/actions/not-found-action.js.map +1 -1
  29. package/esm/actions/password-login-action.d.ts +5 -12
  30. package/esm/actions/password-login-action.d.ts.map +1 -1
  31. package/esm/actions/password-login-action.js +6 -13
  32. package/esm/actions/password-login-action.js.map +1 -1
  33. package/esm/actions/password-login-action.spec.js +23 -28
  34. package/esm/actions/password-login-action.spec.js.map +1 -1
  35. package/esm/authenticate.d.ts +5 -11
  36. package/esm/authenticate.d.ts.map +1 -1
  37. package/esm/authenticate.js +6 -12
  38. package/esm/authenticate.js.map +1 -1
  39. package/esm/authenticate.spec.js +41 -33
  40. package/esm/authenticate.spec.js.map +1 -1
  41. package/esm/authentication-providers/authentication-provider.d.ts +17 -0
  42. package/esm/authentication-providers/authentication-provider.d.ts.map +1 -1
  43. package/esm/authentication-providers/basic-auth-provider.d.ts +7 -0
  44. package/esm/authentication-providers/basic-auth-provider.d.ts.map +1 -1
  45. package/esm/authentication-providers/basic-auth-provider.js +7 -0
  46. package/esm/authentication-providers/basic-auth-provider.js.map +1 -1
  47. package/esm/authentication-providers/cookie-auth-provider.d.ts.map +1 -1
  48. package/esm/authentication-providers/cookie-auth-provider.js +8 -0
  49. package/esm/authentication-providers/cookie-auth-provider.js.map +1 -1
  50. package/esm/authorize.d.ts +5 -17
  51. package/esm/authorize.d.ts.map +1 -1
  52. package/esm/authorize.js +5 -17
  53. package/esm/authorize.js.map +1 -1
  54. package/esm/authorize.spec.js +34 -29
  55. package/esm/authorize.spec.js.map +1 -1
  56. package/esm/endpoint-generators/create-delete-endpoint.d.ts +6 -11
  57. package/esm/endpoint-generators/create-delete-endpoint.d.ts.map +1 -1
  58. package/esm/endpoint-generators/create-delete-endpoint.js +7 -11
  59. package/esm/endpoint-generators/create-delete-endpoint.js.map +1 -1
  60. package/esm/endpoint-generators/create-delete-endpoint.spec.js +14 -21
  61. package/esm/endpoint-generators/create-delete-endpoint.spec.js.map +1 -1
  62. package/esm/endpoint-generators/create-get-collection-endpoint.d.ts +11 -11
  63. package/esm/endpoint-generators/create-get-collection-endpoint.d.ts.map +1 -1
  64. package/esm/endpoint-generators/create-get-collection-endpoint.js +13 -12
  65. package/esm/endpoint-generators/create-get-collection-endpoint.js.map +1 -1
  66. package/esm/endpoint-generators/create-get-collection-endpoint.spec.js +43 -70
  67. package/esm/endpoint-generators/create-get-collection-endpoint.spec.js.map +1 -1
  68. package/esm/endpoint-generators/create-get-entity-endpoint.d.ts +6 -11
  69. package/esm/endpoint-generators/create-get-entity-endpoint.d.ts.map +1 -1
  70. package/esm/endpoint-generators/create-get-entity-endpoint.js +7 -11
  71. package/esm/endpoint-generators/create-get-entity-endpoint.js.map +1 -1
  72. package/esm/endpoint-generators/create-get-entity-endpoint.spec.js +16 -33
  73. package/esm/endpoint-generators/create-get-entity-endpoint.spec.js.map +1 -1
  74. package/esm/endpoint-generators/create-get-openapi-document-action.d.ts +1 -1
  75. package/esm/endpoint-generators/create-get-openapi-document-action.d.ts.map +1 -1
  76. package/esm/endpoint-generators/create-get-openapi-document-action.js +1 -1
  77. package/esm/endpoint-generators/create-get-openapi-document-action.js.map +1 -1
  78. package/esm/endpoint-generators/create-get-schema-action.d.ts +1 -1
  79. package/esm/endpoint-generators/create-get-schema-action.d.ts.map +1 -1
  80. package/esm/endpoint-generators/create-get-schema-action.js.map +1 -1
  81. package/esm/endpoint-generators/create-patch-endpoint.d.ts +7 -13
  82. package/esm/endpoint-generators/create-patch-endpoint.d.ts.map +1 -1
  83. package/esm/endpoint-generators/create-patch-endpoint.js +8 -13
  84. package/esm/endpoint-generators/create-patch-endpoint.js.map +1 -1
  85. package/esm/endpoint-generators/create-patch-endpoint.spec.js +10 -17
  86. package/esm/endpoint-generators/create-patch-endpoint.spec.js.map +1 -1
  87. package/esm/endpoint-generators/create-post-endpoint.d.ts +7 -13
  88. package/esm/endpoint-generators/create-post-endpoint.d.ts.map +1 -1
  89. package/esm/endpoint-generators/create-post-endpoint.js +8 -13
  90. package/esm/endpoint-generators/create-post-endpoint.js.map +1 -1
  91. package/esm/endpoint-generators/create-post-endpoint.spec.js +41 -14
  92. package/esm/endpoint-generators/create-post-endpoint.spec.js.map +1 -1
  93. package/esm/endpoint-generators/utils.d.ts +17 -2
  94. package/esm/endpoint-generators/utils.d.ts.map +1 -1
  95. package/esm/endpoint-generators/utils.js +33 -20
  96. package/esm/endpoint-generators/utils.js.map +1 -1
  97. package/esm/get-schema-from-api.d.ts +1 -1
  98. package/esm/get-schema-from-api.d.ts.map +1 -1
  99. package/esm/get-schema-from-api.js +1 -0
  100. package/esm/get-schema-from-api.js.map +1 -1
  101. package/esm/get-schema-from-api.spec.js.map +1 -1
  102. package/esm/helpers.d.ts +54 -88
  103. package/esm/helpers.d.ts.map +1 -1
  104. package/esm/helpers.js +90 -92
  105. package/esm/helpers.js.map +1 -1
  106. package/esm/helpers.spec.d.ts +2 -1
  107. package/esm/helpers.spec.d.ts.map +1 -1
  108. package/esm/helpers.spec.js +41 -38
  109. package/esm/helpers.spec.js.map +1 -1
  110. package/esm/http-authentication-settings.d.ts +56 -12
  111. package/esm/http-authentication-settings.d.ts.map +1 -1
  112. package/esm/http-authentication-settings.js +27 -29
  113. package/esm/http-authentication-settings.js.map +1 -1
  114. package/esm/http-server-pool.d.ts +64 -0
  115. package/esm/http-server-pool.d.ts.map +1 -0
  116. package/esm/http-server-pool.js +95 -0
  117. package/esm/http-server-pool.js.map +1 -0
  118. package/esm/http-server-pool.spec.d.ts +2 -0
  119. package/esm/http-server-pool.spec.d.ts.map +1 -0
  120. package/esm/http-server-pool.spec.js +193 -0
  121. package/esm/http-server-pool.spec.js.map +1 -0
  122. package/esm/http-user-context.d.ts +34 -44
  123. package/esm/http-user-context.d.ts.map +1 -1
  124. package/esm/http-user-context.js +75 -95
  125. package/esm/http-user-context.js.map +1 -1
  126. package/esm/http-user-context.spec.d.ts +8 -2
  127. package/esm/http-user-context.spec.d.ts.map +1 -1
  128. package/esm/http-user-context.spec.js +226 -332
  129. package/esm/http-user-context.spec.js.map +1 -1
  130. package/esm/identity-cache-keys.d.ts +28 -0
  131. package/esm/identity-cache-keys.d.ts.map +1 -0
  132. package/esm/identity-cache-keys.js +13 -0
  133. package/esm/identity-cache-keys.js.map +1 -0
  134. package/esm/identity-cache-keys.spec.d.ts +2 -0
  135. package/esm/identity-cache-keys.spec.d.ts.map +1 -0
  136. package/esm/identity-cache-keys.spec.js +21 -0
  137. package/esm/identity-cache-keys.spec.js.map +1 -0
  138. package/esm/identity-event-bus.d.ts +102 -0
  139. package/esm/identity-event-bus.d.ts.map +1 -0
  140. package/esm/identity-event-bus.js +151 -0
  141. package/esm/identity-event-bus.js.map +1 -0
  142. package/esm/identity-event-bus.spec.d.ts +2 -0
  143. package/esm/identity-event-bus.spec.d.ts.map +1 -0
  144. package/esm/identity-event-bus.spec.js +392 -0
  145. package/esm/identity-event-bus.spec.js.map +1 -0
  146. package/esm/index.d.ts +9 -4
  147. package/esm/index.d.ts.map +1 -1
  148. package/esm/index.js +9 -4
  149. package/esm/index.js.map +1 -1
  150. package/esm/login-response-strategy.d.ts +11 -10
  151. package/esm/login-response-strategy.d.ts.map +1 -1
  152. package/esm/login-response-strategy.js +7 -6
  153. package/esm/login-response-strategy.js.map +1 -1
  154. package/esm/login-response-strategy.spec.js +25 -29
  155. package/esm/login-response-strategy.spec.js.map +1 -1
  156. package/esm/openapi/generate-openapi-document.spec.js.map +1 -1
  157. package/esm/proxy-manager.spec.js +152 -176
  158. package/esm/proxy-manager.spec.js.map +1 -1
  159. package/esm/proxy-runtime.d.ts +27 -0
  160. package/esm/proxy-runtime.d.ts.map +1 -0
  161. package/esm/proxy-runtime.js +45 -0
  162. package/esm/proxy-runtime.js.map +1 -0
  163. package/esm/proxy-runtime.spec.d.ts +2 -0
  164. package/esm/proxy-runtime.spec.d.ts.map +1 -0
  165. package/esm/proxy-runtime.spec.js +39 -0
  166. package/esm/proxy-runtime.spec.js.map +1 -0
  167. package/esm/request-action-implementation.d.ts +25 -0
  168. package/esm/request-action-implementation.d.ts.map +1 -1
  169. package/esm/request-action-implementation.js +9 -0
  170. package/esm/request-action-implementation.js.map +1 -1
  171. package/esm/rest-api-runtime.d.ts +76 -0
  172. package/esm/rest-api-runtime.d.ts.map +1 -0
  173. package/esm/rest-api-runtime.js +131 -0
  174. package/esm/rest-api-runtime.js.map +1 -0
  175. package/esm/rest-api-runtime.spec.d.ts +2 -0
  176. package/esm/rest-api-runtime.spec.d.ts.map +1 -0
  177. package/esm/rest-api-runtime.spec.js +58 -0
  178. package/esm/rest-api-runtime.spec.js.map +1 -0
  179. package/esm/rest-service.integration.spec.d.ts +1 -1
  180. package/esm/rest-service.integration.spec.d.ts.map +1 -1
  181. package/esm/rest-service.integration.spec.js +57 -80
  182. package/esm/rest-service.integration.spec.js.map +1 -1
  183. package/esm/rest.integration.test.js +26 -84
  184. package/esm/rest.integration.test.js.map +1 -1
  185. package/esm/server-telemetry.d.ts +49 -0
  186. package/esm/server-telemetry.d.ts.map +1 -0
  187. package/esm/server-telemetry.js +25 -0
  188. package/esm/server-telemetry.js.map +1 -0
  189. package/esm/server-telemetry.spec.d.ts +2 -0
  190. package/esm/server-telemetry.spec.d.ts.map +1 -0
  191. package/esm/server-telemetry.spec.js +52 -0
  192. package/esm/server-telemetry.spec.js.map +1 -0
  193. package/esm/static-server-manager.spec.js +60 -125
  194. package/esm/static-server-manager.spec.js.map +1 -1
  195. package/esm/static-site-runtime.d.ts +21 -0
  196. package/esm/static-site-runtime.d.ts.map +1 -0
  197. package/esm/static-site-runtime.js +48 -0
  198. package/esm/static-site-runtime.js.map +1 -0
  199. package/esm/static-site-runtime.spec.d.ts +2 -0
  200. package/esm/static-site-runtime.spec.d.ts.map +1 -0
  201. package/esm/static-site-runtime.spec.js +30 -0
  202. package/esm/static-site-runtime.spec.js.map +1 -0
  203. package/esm/user-resolution-cache.d.ts +65 -0
  204. package/esm/user-resolution-cache.d.ts.map +1 -0
  205. package/esm/user-resolution-cache.js +101 -0
  206. package/esm/user-resolution-cache.js.map +1 -0
  207. package/esm/user-resolution-cache.spec.d.ts +2 -0
  208. package/esm/user-resolution-cache.spec.d.ts.map +1 -0
  209. package/esm/user-resolution-cache.spec.js +220 -0
  210. package/esm/user-resolution-cache.spec.js.map +1 -0
  211. package/esm/user-store.d.ts +39 -0
  212. package/esm/user-store.d.ts.map +1 -0
  213. package/esm/user-store.js +62 -0
  214. package/esm/user-store.js.map +1 -0
  215. package/esm/user-store.spec.d.ts +2 -0
  216. package/esm/user-store.spec.d.ts.map +1 -0
  217. package/esm/user-store.spec.js +72 -0
  218. package/esm/user-store.spec.js.map +1 -0
  219. package/esm/validate.d.ts +13 -12
  220. package/esm/validate.d.ts.map +1 -1
  221. package/esm/validate.integration.spec.js +27 -28
  222. package/esm/validate.integration.spec.js.map +1 -1
  223. package/esm/validate.js +12 -0
  224. package/esm/validate.js.map +1 -1
  225. package/package.json +14 -12
  226. package/src/actions/error-action.ts +7 -3
  227. package/src/actions/get-current-user.spec.ts +11 -10
  228. package/src/actions/get-current-user.ts +1 -4
  229. package/src/actions/is-authenticated.spec.ts +12 -7
  230. package/src/actions/is-authenticated.ts +3 -4
  231. package/src/actions/logout-action.spec.ts +12 -12
  232. package/src/actions/logout.ts +3 -7
  233. package/src/actions/not-found-action.ts +1 -3
  234. package/src/actions/password-login-action.spec.ts +30 -30
  235. package/src/actions/password-login-action.ts +6 -13
  236. package/src/authenticate.spec.ts +45 -51
  237. package/src/authenticate.ts +6 -12
  238. package/src/authentication-providers/authentication-provider.ts +17 -0
  239. package/src/authentication-providers/basic-auth-provider.ts +7 -0
  240. package/src/authentication-providers/cookie-auth-provider.ts +8 -0
  241. package/src/authorize.spec.ts +37 -39
  242. package/src/authorize.ts +6 -17
  243. package/src/endpoint-generators/create-delete-endpoint.spec.ts +16 -24
  244. package/src/endpoint-generators/create-delete-endpoint.ts +11 -17
  245. package/src/endpoint-generators/create-get-collection-endpoint.spec.ts +45 -78
  246. package/src/endpoint-generators/create-get-collection-endpoint.ts +17 -19
  247. package/src/endpoint-generators/create-get-entity-endpoint.spec.ts +17 -33
  248. package/src/endpoint-generators/create-get-entity-endpoint.ts +11 -17
  249. package/src/endpoint-generators/create-get-openapi-document-action.ts +2 -2
  250. package/src/endpoint-generators/create-get-schema-action.ts +1 -1
  251. package/src/endpoint-generators/create-patch-endpoint.spec.ts +11 -18
  252. package/src/endpoint-generators/create-patch-endpoint.ts +12 -23
  253. package/src/endpoint-generators/create-post-endpoint.spec.ts +45 -14
  254. package/src/endpoint-generators/create-post-endpoint.ts +13 -23
  255. package/src/endpoint-generators/utils.ts +36 -28
  256. package/src/get-schema-from-api.spec.ts +1 -1
  257. package/src/get-schema-from-api.ts +2 -1
  258. package/src/helpers.spec.ts +51 -41
  259. package/src/helpers.ts +140 -109
  260. package/src/http-authentication-settings.ts +78 -24
  261. package/src/http-server-pool.spec.ts +220 -0
  262. package/src/http-server-pool.ts +169 -0
  263. package/src/http-user-context.spec.ts +246 -378
  264. package/src/http-user-context.ts +122 -92
  265. package/src/identity-cache-keys.spec.ts +24 -0
  266. package/src/identity-cache-keys.ts +31 -0
  267. package/src/identity-event-bus.spec.ts +285 -0
  268. package/src/identity-event-bus.ts +230 -0
  269. package/src/index.ts +9 -4
  270. package/src/login-response-strategy.spec.ts +32 -31
  271. package/src/login-response-strategy.ts +14 -12
  272. package/src/openapi/generate-openapi-document.spec.ts +2 -2
  273. package/src/proxy-manager.spec.ts +158 -188
  274. package/src/proxy-runtime.spec.ts +50 -0
  275. package/src/proxy-runtime.ts +75 -0
  276. package/src/request-action-implementation.ts +25 -0
  277. package/src/rest-api-runtime.spec.ts +77 -0
  278. package/src/rest-api-runtime.ts +204 -0
  279. package/src/rest-service.integration.spec.ts +65 -85
  280. package/src/rest.integration.test.ts +27 -87
  281. package/src/server-telemetry.spec.ts +56 -0
  282. package/src/server-telemetry.ts +43 -0
  283. package/src/static-server-manager.spec.ts +63 -151
  284. package/src/static-site-runtime.spec.ts +39 -0
  285. package/src/static-site-runtime.ts +75 -0
  286. package/src/user-resolution-cache.spec.ts +241 -0
  287. package/src/user-resolution-cache.ts +164 -0
  288. package/src/user-store.spec.ts +86 -0
  289. package/src/user-store.ts +69 -0
  290. package/src/validate.integration.spec.ts +40 -35
  291. package/src/validate.ts +14 -12
  292. package/esm/api-manager.d.ts +0 -104
  293. package/esm/api-manager.d.ts.map +0 -1
  294. package/esm/api-manager.js +0 -179
  295. package/esm/api-manager.js.map +0 -1
  296. package/esm/proxy-manager.d.ts +0 -53
  297. package/esm/proxy-manager.d.ts.map +0 -1
  298. package/esm/proxy-manager.js +0 -84
  299. package/esm/proxy-manager.js.map +0 -1
  300. package/esm/server-manager.d.ts +0 -48
  301. package/esm/server-manager.d.ts.map +0 -1
  302. package/esm/server-manager.js +0 -100
  303. package/esm/server-manager.js.map +0 -1
  304. package/esm/static-server-manager.d.ts +0 -19
  305. package/esm/static-server-manager.d.ts.map +0 -1
  306. package/esm/static-server-manager.js +0 -65
  307. package/esm/static-server-manager.js.map +0 -1
  308. package/src/api-manager.ts +0 -304
  309. package/src/proxy-manager.ts +0 -102
  310. package/src/server-manager.ts +0 -135
  311. package/src/static-server-manager.ts +0 -90
@@ -1,18 +1,11 @@
1
1
  import type { LoginResponseStrategy } from '../login-response-strategy.js';
2
2
  import type { RequestAction } from '../request-action-implementation.js';
3
3
  /**
4
- * Creates a login {@link RequestAction} that authenticates a user by
5
- * username + password, then delegates session/token creation to the
6
- * provided {@link LoginResponseStrategy}.
7
- *
8
- * The return type is inferred from the strategy:
9
- * - Cookie strategy -> `ActionResult<User>`
10
- * - JWT strategy -> `ActionResult<{ accessToken: string; refreshToken: string }>`
11
- *
12
- * A random delay (0-1 s) is added on failure to mitigate timing attacks.
13
- *
14
- * @param strategy The login response strategy that produces the session/token result
15
- * @returns A `RequestAction` that can be wired into a REST API route
4
+ * Username + password login action. Authenticates via {@link HttpUserContext},
5
+ * then delegates session/token creation to `strategy`. The result type is
6
+ * inferred from the strategy (e.g. `User` for cookies, `{ accessToken,
7
+ * refreshToken }` for JWT). Adds a 0–1 s random delay on failure to mitigate
8
+ * timing attacks; rethrows as `RequestError(400)`.
16
9
  */
17
10
  export declare const createPasswordLoginAction: <TResult>(strategy: LoginResponseStrategy<TResult>) => RequestAction<{
18
11
  result: TResult;
@@ -1 +1 @@
1
- {"version":3,"file":"password-login-action.d.ts","sourceRoot":"","sources":["../../src/actions/password-login-action.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAA;AAC1E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qCAAqC,CAAA;AAExE;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,yBAAyB,GAAI,OAAO,EAC/C,UAAU,qBAAqB,CAAC,OAAO,CAAC,KACvC,aAAa,CAAC;IAAE,MAAM,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,CAWjF,CAAA"}
1
+ {"version":3,"file":"password-login-action.d.ts","sourceRoot":"","sources":["../../src/actions/password-login-action.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAA;AAC1E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qCAAqC,CAAA;AAExE;;;;;;GAMG;AACH,eAAO,MAAM,yBAAyB,GAAI,OAAO,EAC/C,UAAU,qBAAqB,CAAC,OAAO,CAAC,KACvC,aAAa,CAAC;IAAE,MAAM,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,CAWjF,CAAA"}
@@ -2,24 +2,17 @@ import { RequestError } from '@furystack/rest';
2
2
  import { sleepAsync } from '@furystack/utils';
3
3
  import { HttpUserContext } from '../http-user-context.js';
4
4
  /**
5
- * Creates a login {@link RequestAction} that authenticates a user by
6
- * username + password, then delegates session/token creation to the
7
- * provided {@link LoginResponseStrategy}.
8
- *
9
- * The return type is inferred from the strategy:
10
- * - Cookie strategy -> `ActionResult<User>`
11
- * - JWT strategy -> `ActionResult<{ accessToken: string; refreshToken: string }>`
12
- *
13
- * A random delay (0-1 s) is added on failure to mitigate timing attacks.
14
- *
15
- * @param strategy The login response strategy that produces the session/token result
16
- * @returns A `RequestAction` that can be wired into a REST API route
5
+ * Username + password login action. Authenticates via {@link HttpUserContext},
6
+ * then delegates session/token creation to `strategy`. The result type is
7
+ * inferred from the strategy (e.g. `User` for cookies, `{ accessToken,
8
+ * refreshToken }` for JWT). Adds a 0–1 s random delay on failure to mitigate
9
+ * timing attacks; rethrows as `RequestError(400)`.
17
10
  */
18
11
  export const createPasswordLoginAction = (strategy) => {
19
12
  return async ({ injector, getBody }) => {
20
13
  const body = await getBody();
21
14
  try {
22
- const user = await injector.getInstance(HttpUserContext).authenticateUser(body.username, body.password);
15
+ const user = await injector.get(HttpUserContext).authenticateUser(body.username, body.password);
23
16
  return strategy.createLoginResponse(user, injector);
24
17
  }
25
18
  catch {
@@ -1 +1 @@
1
- {"version":3,"file":"password-login-action.js","sourceRoot":"","sources":["../../src/actions/password-login-action.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAE7C,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAA;AAIzD;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,CACvC,QAAwC,EAC0C,EAAE;IACpF,OAAO,KAAK,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,EAAE;QACrC,MAAM,IAAI,GAAG,MAAM,OAAO,EAAE,CAAA;QAC5B,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,WAAW,CAAC,eAAe,CAAC,CAAC,gBAAgB,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAA;YACvG,OAAO,QAAQ,CAAC,mBAAmB,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAA;QACrD,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,UAAU,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,CAAA;YACtC,MAAM,IAAI,YAAY,CAAC,cAAc,EAAE,GAAG,CAAC,CAAA;QAC7C,CAAC;IACH,CAAC,CAAA;AACH,CAAC,CAAA"}
1
+ {"version":3,"file":"password-login-action.js","sourceRoot":"","sources":["../../src/actions/password-login-action.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAE7C,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAA;AAIzD;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,CACvC,QAAwC,EAC0C,EAAE;IACpF,OAAO,KAAK,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,EAAE;QACrC,MAAM,IAAI,GAAG,MAAM,OAAO,EAAE,CAAA;QAC5B,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC,gBAAgB,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAA;YAC/F,OAAO,QAAQ,CAAC,mBAAmB,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAA;QACrD,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,UAAU,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,CAAA;YACtC,MAAM,IAAI,YAAY,CAAC,cAAc,EAAE,GAAG,CAAC,CAAA;QAC7C,CAAC;IACH,CAAC,CAAA;AACH,CAAC,CAAA"}
@@ -1,30 +1,25 @@
1
- import { InMemoryStore, StoreManager, User, addStore } from '@furystack/core';
2
- import { Injector } from '@furystack/inject';
3
- import { getRepository } from '@furystack/repository';
4
- import { PasswordAuthenticator, PasswordCredential, PasswordResetToken, usePasswordPolicy } from '@furystack/security';
1
+ import { InMemoryStore, User as UserModel } from '@furystack/core';
2
+ import { createInjector } from '@furystack/inject';
3
+ import { PasswordCredential, PasswordCredentialStore, PasswordResetToken, PasswordResetTokenStore, usePasswordPolicy, } from '@furystack/security';
5
4
  import { usingAsync } from '@furystack/utils';
6
5
  import { describe, expect, it, vi } from 'vitest';
7
6
  import { useHttpAuthentication } from '../helpers.js';
8
7
  import { DefaultSession } from '../models/default-session.js';
9
8
  import { JsonResult } from '../request-action-implementation.js';
9
+ import { SessionStore, UserStore } from '../user-store.js';
10
+ import { PasswordAuthenticator } from '@furystack/security';
10
11
  import { createPasswordLoginAction } from './password-login-action.js';
11
12
  const setupInjector = async (i, username, password) => {
12
- addStore(i, new InMemoryStore({ model: User, primaryKey: 'username' }))
13
- .addStore(new InMemoryStore({ model: DefaultSession, primaryKey: 'sessionId' }))
14
- .addStore(new InMemoryStore({ model: PasswordCredential, primaryKey: 'userName' }))
15
- .addStore(new InMemoryStore({ model: PasswordResetToken, primaryKey: 'token' }));
16
- const repo = getRepository(i);
17
- repo.createDataSet(User, 'username');
18
- repo.createDataSet(DefaultSession, 'sessionId');
19
- repo.createDataSet(PasswordCredential, 'userName');
20
- repo.createDataSet(PasswordResetToken, 'token');
13
+ i.bind(UserStore, () => new InMemoryStore({ model: UserModel, primaryKey: 'username' }));
14
+ i.bind(SessionStore, () => new InMemoryStore({ model: DefaultSession, primaryKey: 'sessionId' }));
15
+ i.bind(PasswordCredentialStore, () => new InMemoryStore({ model: PasswordCredential, primaryKey: 'userName' }));
16
+ i.bind(PasswordResetTokenStore, () => new InMemoryStore({ model: PasswordResetToken, primaryKey: 'token' }));
21
17
  usePasswordPolicy(i);
22
18
  useHttpAuthentication(i);
23
- const sm = i.getInstance(StoreManager);
24
- const pw = i.getInstance(PasswordAuthenticator);
25
- const cred = await pw.hasher.createCredential(username, password);
26
- await sm.getStoreFor(PasswordCredential, 'userName').add(cred);
27
- await sm.getStoreFor(User, 'username').add({ username, roles: ['admin'] });
19
+ const authenticator = i.get(PasswordAuthenticator);
20
+ const cred = await authenticator.hasher.createCredential(username, password);
21
+ await i.get(PasswordCredentialStore).add(cred);
22
+ await i.get(UserStore).add({ username, roles: ['admin'] });
28
23
  };
29
24
  const mockStrategy = {
30
25
  createLoginResponse: vi.fn(async (user) => JsonResult(user, 200)),
@@ -32,8 +27,8 @@ const mockStrategy = {
32
27
  describe('createPasswordLoginAction', () => {
33
28
  const request = {};
34
29
  const response = {};
35
- it('Should delegate to the strategy on successful authentication', async () => {
36
- await usingAsync(new Injector(), async (i) => {
30
+ it('delegates to the strategy on successful authentication', async () => {
31
+ await usingAsync(createInjector(), async (i) => {
37
32
  await setupInjector(i, 'testuser', 'testpass');
38
33
  const action = createPasswordLoginAction(mockStrategy);
39
34
  const result = await action({
@@ -46,8 +41,8 @@ describe('createPasswordLoginAction', () => {
46
41
  expect(result.chunk.username).toBe('testuser');
47
42
  });
48
43
  });
49
- it('Should pass the correct user to the strategy', async () => {
50
- await usingAsync(new Injector(), async (i) => {
44
+ it('passes the authenticated user to the strategy', async () => {
45
+ await usingAsync(createInjector(), async (i) => {
51
46
  await setupInjector(i, 'testuser', 'testpass');
52
47
  const strategyFn = vi.fn(async (user) => JsonResult(user, 200));
53
48
  const strategy = { createLoginResponse: strategyFn };
@@ -61,8 +56,8 @@ describe('createPasswordLoginAction', () => {
61
56
  expect(strategyFn).toHaveBeenCalledWith(expect.objectContaining({ username: 'testuser', roles: ['admin'] }), i);
62
57
  });
63
58
  });
64
- it('Should throw RequestError on invalid credentials', async () => {
65
- await usingAsync(new Injector(), async (i) => {
59
+ it('throws RequestError on invalid password', async () => {
60
+ await usingAsync(createInjector(), async (i) => {
66
61
  await setupInjector(i, 'testuser', 'testpass');
67
62
  const action = createPasswordLoginAction(mockStrategy);
68
63
  await expect(action({
@@ -73,8 +68,8 @@ describe('createPasswordLoginAction', () => {
73
68
  })).rejects.toThrow('Login Failed');
74
69
  });
75
70
  });
76
- it('Should throw RequestError for nonexistent user', async () => {
77
- await usingAsync(new Injector(), async (i) => {
71
+ it('throws RequestError for an unknown user', async () => {
72
+ await usingAsync(createInjector(), async (i) => {
78
73
  await setupInjector(i, 'testuser', 'testpass');
79
74
  const action = createPasswordLoginAction(mockStrategy);
80
75
  await expect(action({
@@ -85,8 +80,8 @@ describe('createPasswordLoginAction', () => {
85
80
  })).rejects.toThrow('Login Failed');
86
81
  });
87
82
  });
88
- it('Should work with a custom result type from strategy', async () => {
89
- await usingAsync(new Injector(), async (i) => {
83
+ it('supports strategies returning custom result shapes', async () => {
84
+ await usingAsync(createInjector(), async (i) => {
90
85
  await setupInjector(i, 'testuser', 'testpass');
91
86
  const tokenStrategy = {
92
87
  createLoginResponse: async () => JsonResult({ accessToken: 'tok123' }, 200),
@@ -1 +1 @@
1
- {"version":3,"file":"password-login-action.spec.js","sourceRoot":"","sources":["../../src/actions/password-login-action.spec.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"password-login-action.spec.js","sourceRoot":"","sources":["../../src/actions/password-login-action.spec.ts"],"names":[],"mappings":"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"}
@@ -1,20 +1,14 @@
1
1
  import type { RequestAction } from './request-action-implementation.js';
2
2
  /**
3
- * Higher-order function that wraps a request action to require authentication.
4
- * If the user is not authenticated, returns a 401 Unauthorized response.
5
- * Includes a random delay on unauthorized requests to mitigate timing attacks.
3
+ * Wraps a {@link RequestAction} to require authentication. Unauthenticated
4
+ * requests return `401 Unauthorized` (with `WWW-Authenticate: Basic` when
5
+ * the chain includes Basic Auth). Adds a 0–1 s random delay on rejection to
6
+ * mitigate timing attacks.
6
7
  *
7
- * @returns A function that wraps the provided action with authentication check
8
8
  * @example
9
9
  * ```ts
10
- * // Wrap an endpoint to require authentication
11
- * const protectedEndpoint = Authenticate()(myEndpoint)
12
- *
13
- * // Or use directly in API definition
14
10
  * api: {
15
- * GET: {
16
- * '/users': Authenticate()(getUsersEndpoint)
17
- * }
11
+ * GET: { '/users': Authenticate()(getUsersEndpoint) },
18
12
  * }
19
13
  * ```
20
14
  */
@@ -1 +1 @@
1
- {"version":3,"file":"authenticate.d.ts","sourceRoot":"","sources":["../src/authenticate.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAgB,aAAa,EAAwB,MAAM,oCAAoC,CAAA;AAG3G;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,YAAY,SAEtB,CAAC,SAAS;IAAE,MAAM,EAAE,OAAO,CAAA;CAAE,EAAE,QAAQ,aAAa,CAAC,CAAC,CAAC,KAAG,aAAa,CAAC,CAAC,CAqBzE,CAAA"}
1
+ {"version":3,"file":"authenticate.d.ts","sourceRoot":"","sources":["../src/authenticate.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAgB,aAAa,EAAwB,MAAM,oCAAoC,CAAA;AAG3G;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,YAAY,SAEtB,CAAC,SAAS;IAAE,MAAM,EAAE,OAAO,CAAA;CAAE,EAAE,QAAQ,aAAa,CAAC,CAAC,CAAC,KAAG,aAAa,CAAC,CAAC,CAqBzE,CAAA"}
@@ -3,21 +3,15 @@ import { sleepAsync } from '@furystack/utils';
3
3
  import { HttpUserContext } from './http-user-context.js';
4
4
  import { JsonResult } from './request-action-implementation.js';
5
5
  /**
6
- * Higher-order function that wraps a request action to require authentication.
7
- * If the user is not authenticated, returns a 401 Unauthorized response.
8
- * Includes a random delay on unauthorized requests to mitigate timing attacks.
6
+ * Wraps a {@link RequestAction} to require authentication. Unauthenticated
7
+ * requests return `401 Unauthorized` (with `WWW-Authenticate: Basic` when
8
+ * the chain includes Basic Auth). Adds a 0–1 s random delay on rejection to
9
+ * mitigate timing attacks.
9
10
  *
10
- * @returns A function that wraps the provided action with authentication check
11
11
  * @example
12
12
  * ```ts
13
- * // Wrap an endpoint to require authentication
14
- * const protectedEndpoint = Authenticate()(myEndpoint)
15
- *
16
- * // Or use directly in API definition
17
13
  * api: {
18
- * GET: {
19
- * '/users': Authenticate()(getUsersEndpoint)
20
- * }
14
+ * GET: { '/users': Authenticate()(getUsersEndpoint) },
21
15
  * }
22
16
  * ```
23
17
  */
@@ -28,7 +22,7 @@ export const Authenticate = () => (action) => {
28
22
  if (!authenticated) {
29
23
  await sleepAsync(Math.random() * 1000);
30
24
  const hasBasicAuth = injector
31
- .getInstance(HttpUserContext)
25
+ .get(HttpUserContext)
32
26
  .authentication.authenticationProviders.some((p) => p.name === 'basic-auth');
33
27
  return JsonResult({ error: 'unauthorized' }, 401, hasBasicAuth ? { 'WWW-Authenticate': 'Basic' } : {});
34
28
  }
@@ -1 +1 @@
1
- {"version":3,"file":"authenticate.js","sourceRoot":"","sources":["../src/authenticate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAC7C,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AAExD,OAAO,EAAE,UAAU,EAAE,MAAM,oCAAoC,CAAA;AAE/D;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,CAAC,MAAM,YAAY,GACvB,GAAG,EAAE,CACL,CAAgC,MAAwB,EAAoB,EAAE;IAC5E,MAAM,OAAO,GAAG,KAAK,EAAE,IAA6B,EAA4B,EAAE;QAChF,MAAM,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAA;QACzB,MAAM,aAAa,GAAG,MAAM,eAAe,CAAC,QAAQ,CAAC,CAAA;QACrD,IAAI,CAAC,aAAa,EAAE,CAAC;YACnB,MAAM,UAAU,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,CAAA;YACtC,MAAM,YAAY,GAAG,QAAQ;iBAC1B,WAAW,CAAC,eAAe,CAAC;iBAC5B,cAAc,CAAC,uBAAuB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,YAAY,CAAC,CAAA;YAC9E,OAAO,UAAU,CACf,EAAE,KAAK,EAAE,cAAc,EAAE,EACzB,GAAG,EACH,YAAY,CAAC,CAAC,CAAC,EAAE,kBAAkB,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CACtB,CAAA;QACjC,CAAC;QACD,OAAO,CAAC,MAAM,MAAM,CAAC,IAAI,CAAC,CAAoB,CAAA;IAChD,CAAC,CAAA;IAED,OAAO,CAAC,eAAe,GAAG,IAAI,CAAA;IAE9B,OAAO,OAAO,CAAA;AAChB,CAAC,CAAA"}
1
+ {"version":3,"file":"authenticate.js","sourceRoot":"","sources":["../src/authenticate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAC7C,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AAExD,OAAO,EAAE,UAAU,EAAE,MAAM,oCAAoC,CAAA;AAE/D;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,MAAM,YAAY,GACvB,GAAG,EAAE,CACL,CAAgC,MAAwB,EAAoB,EAAE;IAC5E,MAAM,OAAO,GAAG,KAAK,EAAE,IAA6B,EAA4B,EAAE;QAChF,MAAM,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAA;QACzB,MAAM,aAAa,GAAG,MAAM,eAAe,CAAC,QAAQ,CAAC,CAAA;QACrD,IAAI,CAAC,aAAa,EAAE,CAAC;YACnB,MAAM,UAAU,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,CAAA;YACtC,MAAM,YAAY,GAAG,QAAQ;iBAC1B,GAAG,CAAC,eAAe,CAAC;iBACpB,cAAc,CAAC,uBAAuB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,YAAY,CAAC,CAAA;YAC9E,OAAO,UAAU,CACf,EAAE,KAAK,EAAE,cAAc,EAAE,EACzB,GAAG,EACH,YAAY,CAAC,CAAC,CAAC,EAAE,kBAAkB,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CACtB,CAAA;QACjC,CAAC;QACD,OAAO,CAAC,MAAM,MAAM,CAAC,IAAI,CAAC,CAAoB,CAAA;IAChD,CAAC,CAAA;IAED,OAAO,CAAC,eAAe,GAAG,IAAI,CAAA;IAE9B,OAAO,OAAO,CAAA;AAChB,CAAC,CAAA"}
@@ -1,58 +1,66 @@
1
1
  import { IdentityContext } from '@furystack/core';
2
- import { Injector } from '@furystack/inject';
3
- import { usingAsync } from '@furystack/utils';
2
+ import { createInjector } from '@furystack/inject';
3
+ import { EventHub, usingAsync } from '@furystack/utils';
4
4
  import { describe, expect, it, vi } from 'vitest';
5
5
  import { Authenticate } from './authenticate.js';
6
- import { HttpUserContext } from './http-user-context.js';
6
+ import { HttpUserContext as HttpUserContextToken } from './http-user-context.js';
7
7
  import { EmptyResult } from './request-action-implementation.js';
8
+ const makeHttpUserContextStub = (providers) => Object.assign(new EventHub(), {
9
+ authentication: { authenticationProviders: providers },
10
+ });
8
11
  describe('Authenticate', () => {
9
12
  const response = {};
10
13
  const request = { url: 'http://google.com' };
11
- it('Should return 401 without WWW-Authenticate header when no basic-auth provider is registered', async () => {
12
- await usingAsync(new Injector(), async (i) => {
13
- const isAuthenticatedAction = vi.fn(async () => false);
14
- i.setExplicitInstance({ isAuthenticated: isAuthenticatedAction, getCurrentUser: async () => Promise.reject(new Error(':(')) }, IdentityContext);
15
- i.setExplicitInstance({
16
- authentication: { authenticationProviders: [] },
17
- }, HttpUserContext);
18
- const exampleAuthenticatedAction = vi.fn(async () => EmptyResult());
19
- const authorized = Authenticate()(exampleAuthenticatedAction);
14
+ it('returns 401 without WWW-Authenticate when no basic-auth provider is registered', async () => {
15
+ await usingAsync(createInjector(), async (i) => {
16
+ const isAuthenticated = vi.fn(async () => false);
17
+ i.bind(IdentityContext, () => ({
18
+ isAuthenticated,
19
+ getCurrentUser: () => Promise.reject(new Error(':(')),
20
+ isAuthorized: () => Promise.resolve(false),
21
+ }));
22
+ i.bind(HttpUserContextToken, () => makeHttpUserContextStub([]));
23
+ const exampleAction = vi.fn(async () => EmptyResult());
24
+ const authorized = Authenticate()(exampleAction);
20
25
  const result = await authorized({ injector: i, request, response });
21
26
  expect(result.statusCode).toBe(401);
22
27
  expect(result.chunk).toEqual({ error: 'unauthorized' });
23
28
  expect(result.headers).toEqual({ 'Content-Type': 'application/json' });
24
- expect(exampleAuthenticatedAction).not.toBeCalled();
29
+ expect(exampleAction).not.toHaveBeenCalled();
25
30
  });
26
31
  });
27
- it('Should return 401 with WWW-Authenticate: Basic header when basic-auth provider is registered', async () => {
28
- await usingAsync(new Injector(), async (i) => {
29
- const isAuthenticatedAction = vi.fn(async () => false);
30
- i.setExplicitInstance({ isAuthenticated: isAuthenticatedAction, getCurrentUser: async () => Promise.reject(new Error(':(')) }, IdentityContext);
31
- i.setExplicitInstance({
32
- authentication: {
33
- authenticationProviders: [{ name: 'basic-auth', authenticate: async () => null }],
34
- },
35
- }, HttpUserContext);
36
- const exampleAuthenticatedAction = vi.fn(async () => EmptyResult());
37
- const authorized = Authenticate()(exampleAuthenticatedAction);
32
+ it('returns 401 with WWW-Authenticate: Basic when a basic-auth provider is registered', async () => {
33
+ await usingAsync(createInjector(), async (i) => {
34
+ const isAuthenticated = vi.fn(async () => false);
35
+ i.bind(IdentityContext, () => ({
36
+ isAuthenticated,
37
+ getCurrentUser: () => Promise.reject(new Error(':(')),
38
+ isAuthorized: () => Promise.resolve(false),
39
+ }));
40
+ i.bind(HttpUserContextToken, () => makeHttpUserContextStub([{ name: 'basic-auth' }]));
41
+ const exampleAction = vi.fn(async () => EmptyResult());
42
+ const authorized = Authenticate()(exampleAction);
38
43
  const result = await authorized({ injector: i, request, response });
39
44
  expect(result.statusCode).toBe(401);
40
45
  expect(result.chunk).toEqual({ error: 'unauthorized' });
41
46
  expect(result.headers).toEqual({ 'Content-Type': 'application/json', 'WWW-Authenticate': 'Basic' });
42
- expect(exampleAuthenticatedAction).not.toBeCalled();
47
+ expect(exampleAction).not.toHaveBeenCalled();
43
48
  });
44
49
  });
45
- it('Should exec the original action if authorized', async () => {
46
- await usingAsync(new Injector(), async (i) => {
47
- const isAuthenticatedAction = vi.fn(async () => true);
48
- i.setExplicitInstance({ isAuthenticated: isAuthenticatedAction, getCurrentUser: async () => Promise.reject(new Error(':(')) }, IdentityContext);
49
- const exampleAuthenticatedAction = vi.fn(async () => EmptyResult());
50
- const authorized = Authenticate()(exampleAuthenticatedAction);
51
- const params = { injector: i, body: undefined, query: undefined, request, response };
50
+ it('invokes the wrapped action when the caller is authenticated', async () => {
51
+ await usingAsync(createInjector(), async (i) => {
52
+ i.bind(IdentityContext, () => ({
53
+ isAuthenticated: () => Promise.resolve(true),
54
+ getCurrentUser: () => Promise.reject(new Error(':(')),
55
+ isAuthorized: () => Promise.resolve(true),
56
+ }));
57
+ const exampleAction = vi.fn(async () => EmptyResult());
58
+ const authorized = Authenticate()(exampleAction);
59
+ const params = { injector: i, request, response };
52
60
  const result = await authorized(params);
53
61
  expect(result.statusCode).toBe(200);
54
62
  expect(result.chunk).toBe(undefined);
55
- expect(exampleAuthenticatedAction).toBeCalledWith(params);
63
+ expect(exampleAction).toHaveBeenCalledWith(params);
56
64
  });
57
65
  });
58
66
  });
@@ -1 +1 @@
1
- {"version":3,"file":"authenticate.spec.js","sourceRoot":"","sources":["../src/authenticate.spec.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"authenticate.spec.js","sourceRoot":"","sources":["../src/authenticate.spec.ts"],"names":[],"mappings":"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"}
@@ -21,5 +21,22 @@ export type AuthenticationProvider = {
21
21
  */
22
22
  readonly name: string;
23
23
  authenticate: (request: Pick<IncomingMessage, 'headers'>) => Promise<User | null>;
24
+ /**
25
+ * Optional cache-key resolver consulted by the user-resolution cache before
26
+ * the provider chain is walked.
27
+ *
28
+ * Returns a stable, opaque string identifying the authenticated principal
29
+ * for the given request, or `null` when this provider does not apply to
30
+ * the request (or refuses to participate in caching — e.g. Basic Auth,
31
+ * which must verify the password on every request).
32
+ *
33
+ * The first non-null key returned by the configured providers is used as
34
+ * the cache key. Keys returned by different providers must not collide;
35
+ * built-in providers prefix their keys (`cookie:`, `jwt:`).
36
+ *
37
+ * If no provider returns a key, the request bypasses the cache entirely
38
+ * and the provider chain is walked on every call.
39
+ */
40
+ readonly getCacheKey?: (request: Pick<IncomingMessage, 'headers'>) => string | null;
24
41
  };
25
42
  //# sourceMappingURL=authentication-provider.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"authentication-provider.d.ts","sourceRoot":"","sources":["../../src/authentication-providers/authentication-provider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAA;AAC3C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,MAAM,CAAA;AAE3C;;;;;;;;;;;;;GAaG;AACH,MAAM,MAAM,sBAAsB,GAAG;IACnC;;;OAGG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,YAAY,EAAE,CAAC,OAAO,EAAE,IAAI,CAAC,eAAe,EAAE,SAAS,CAAC,KAAK,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC,CAAA;CAClF,CAAA"}
1
+ {"version":3,"file":"authentication-provider.d.ts","sourceRoot":"","sources":["../../src/authentication-providers/authentication-provider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAA;AAC3C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,MAAM,CAAA;AAE3C;;;;;;;;;;;;;GAaG;AACH,MAAM,MAAM,sBAAsB,GAAG;IACnC;;;OAGG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,YAAY,EAAE,CAAC,OAAO,EAAE,IAAI,CAAC,eAAe,EAAE,SAAS,CAAC,KAAK,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC,CAAA;IACjF;;;;;;;;;;;;;;;OAeG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC,OAAO,EAAE,IAAI,CAAC,eAAe,EAAE,SAAS,CAAC,KAAK,MAAM,GAAG,IAAI,CAAA;CACpF,CAAA"}
@@ -2,6 +2,13 @@ import type { User } from '@furystack/core';
2
2
  import type { AuthenticationProvider } from './authentication-provider.js';
3
3
  /**
4
4
  * Creates an authentication provider for HTTP Basic Authentication.
5
+ *
6
+ * **Caching note:** this provider intentionally does **not** implement
7
+ * `getCacheKey`. Caching authenticated users by username would bypass
8
+ * password verification on every cache hit — the cache cannot revalidate the
9
+ * password without re-running the authenticator. Basic Auth requests
10
+ * therefore always walk the provider chain, which is also where the password
11
+ * is verified.
5
12
  * @param authenticateUser Callback that verifies credentials and returns a User or throws
6
13
  */
7
14
  export declare const createBasicAuthProvider: (authenticateUser: (username: string, password: string) => Promise<User>) => AuthenticationProvider;
@@ -1 +1 @@
1
- {"version":3,"file":"basic-auth-provider.d.ts","sourceRoot":"","sources":["../../src/authentication-providers/basic-auth-provider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAA;AAC3C,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,8BAA8B,CAAA;AAE1E;;;GAGG;AACH,eAAO,MAAM,uBAAuB,GAClC,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,KACtE,sBAWD,CAAA"}
1
+ {"version":3,"file":"basic-auth-provider.d.ts","sourceRoot":"","sources":["../../src/authentication-providers/basic-auth-provider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAA;AAC3C,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,8BAA8B,CAAA;AAE1E;;;;;;;;;;GAUG;AACH,eAAO,MAAM,uBAAuB,GAClC,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,KACtE,sBAWD,CAAA"}
@@ -1,5 +1,12 @@
1
1
  /**
2
2
  * Creates an authentication provider for HTTP Basic Authentication.
3
+ *
4
+ * **Caching note:** this provider intentionally does **not** implement
5
+ * `getCacheKey`. Caching authenticated users by username would bypass
6
+ * password verification on every cache hit — the cache cannot revalidate the
7
+ * password without re-running the authenticator. Basic Auth requests
8
+ * therefore always walk the provider chain, which is also where the password
9
+ * is verified.
3
10
  * @param authenticateUser Callback that verifies credentials and returns a User or throws
4
11
  */
5
12
  export const createBasicAuthProvider = (authenticateUser) => ({
@@ -1 +1 @@
1
- {"version":3,"file":"basic-auth-provider.js","sourceRoot":"","sources":["../../src/authentication-providers/basic-auth-provider.ts"],"names":[],"mappings":"AAGA;;;GAGG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,CACrC,gBAAuE,EAC/C,EAAE,CAAC,CAAC;IAC5B,IAAI,EAAE,YAAY;IAClB,YAAY,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE;QAC9B,MAAM,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,aAAa,CAAA;QAChD,IAAI,CAAC,UAAU,EAAE,UAAU,CAAC,QAAQ,CAAC;YAAE,OAAO,IAAI,CAAA;QAClD,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,QAAQ,EAAE,CAAA;QAC1E,MAAM,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;QACvC,MAAM,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,UAAU,CAAC,CAAA;QAC7C,MAAM,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,UAAU,GAAG,CAAC,CAAC,CAAA;QAC9C,OAAO,MAAM,gBAAgB,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAA;IACnD,CAAC;CACF,CAAC,CAAA"}
1
+ {"version":3,"file":"basic-auth-provider.js","sourceRoot":"","sources":["../../src/authentication-providers/basic-auth-provider.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,CACrC,gBAAuE,EAC/C,EAAE,CAAC,CAAC;IAC5B,IAAI,EAAE,YAAY;IAClB,YAAY,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE;QAC9B,MAAM,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,aAAa,CAAA;QAChD,IAAI,CAAC,UAAU,EAAE,UAAU,CAAC,QAAQ,CAAC;YAAE,OAAO,IAAI,CAAA;QAClD,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,QAAQ,EAAE,CAAA;QAC1E,MAAM,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;QACvC,MAAM,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,UAAU,CAAC,CAAA;QAC7C,MAAM,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,UAAU,GAAG,CAAC,CAAC,CAAA;QAC9C,OAAO,MAAM,gBAAgB,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAA;IACnD,CAAC;CACF,CAAC,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"cookie-auth-provider.d.ts","sourceRoot":"","sources":["../../src/authentication-providers/cookie-auth-provider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAA;AAE3C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAA;AAClE,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,8BAA8B,CAAA;AAG1E;;;;;GAKG;AACH,eAAO,MAAM,wBAAwB,GACnC,YAAY,MAAM,EAClB,gBAAgB,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,EACrE,eAAe,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,KACjD,sBASD,CAAA"}
1
+ {"version":3,"file":"cookie-auth-provider.d.ts","sourceRoot":"","sources":["../../src/authentication-providers/cookie-auth-provider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAA;AAG3C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAA;AAClE,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,8BAA8B,CAAA;AAG1E;;;;;GAKG;AACH,eAAO,MAAM,wBAAwB,GACnC,YAAY,MAAM,EAClB,gBAAgB,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,EACrE,eAAe,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,KACjD,sBAgBD,CAAA"}
@@ -1,4 +1,5 @@
1
1
  import { UnauthenticatedError } from '@furystack/security';
2
+ import { sessionCacheKey } from '../identity-cache-keys.js';
2
3
  import { extractSessionIdFromCookies } from './helpers.js';
3
4
  /**
4
5
  * Creates an authentication provider for cookie-based session authentication.
@@ -17,5 +18,12 @@ export const createCookieAuthProvider = (cookieName, getSessionById, getUserByNa
17
18
  throw new UnauthenticatedError();
18
19
  return await getUserByName(session.username);
19
20
  },
21
+ // The session id alone uniquely identifies the principal — caching by it is
22
+ // safe because session invalidation (logout, expiry) drops the session row,
23
+ // and the TTL on the user-resolution cache bounds staleness across nodes.
24
+ getCacheKey: (request) => {
25
+ const sessionId = extractSessionIdFromCookies(request, cookieName);
26
+ return sessionId ? sessionCacheKey(sessionId) : null;
27
+ },
20
28
  });
21
29
  //# sourceMappingURL=cookie-auth-provider.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"cookie-auth-provider.js","sourceRoot":"","sources":["../../src/authentication-providers/cookie-auth-provider.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAA;AAG1D,OAAO,EAAE,2BAA2B,EAAE,MAAM,cAAc,CAAA;AAE1D;;;;;GAKG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG,CACtC,UAAkB,EAClB,cAAqE,EACrE,aAAkD,EAC1B,EAAE,CAAC,CAAC;IAC5B,IAAI,EAAE,aAAa;IACnB,YAAY,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE;QAC9B,MAAM,SAAS,GAAG,2BAA2B,CAAC,OAAO,EAAE,UAAU,CAAC,CAAA;QAClE,IAAI,CAAC,SAAS;YAAE,OAAO,IAAI,CAAA;QAC3B,MAAM,OAAO,GAAG,MAAM,cAAc,CAAC,SAAS,CAAC,CAAA;QAC/C,IAAI,CAAC,OAAO;YAAE,MAAM,IAAI,oBAAoB,EAAE,CAAA;QAC9C,OAAO,MAAM,aAAa,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAA;IAC9C,CAAC;CACF,CAAC,CAAA"}
1
+ {"version":3,"file":"cookie-auth-provider.js","sourceRoot":"","sources":["../../src/authentication-providers/cookie-auth-provider.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAA;AAC1D,OAAO,EAAE,eAAe,EAAwB,MAAM,2BAA2B,CAAA;AAGjF,OAAO,EAAE,2BAA2B,EAAE,MAAM,cAAc,CAAA;AAE1D;;;;;GAKG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG,CACtC,UAAkB,EAClB,cAAqE,EACrE,aAAkD,EAC1B,EAAE,CAAC,CAAC;IAC5B,IAAI,EAAE,aAAa;IACnB,YAAY,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE;QAC9B,MAAM,SAAS,GAAG,2BAA2B,CAAC,OAAO,EAAE,UAAU,CAAC,CAAA;QAClE,IAAI,CAAC,SAAS;YAAE,OAAO,IAAI,CAAA;QAC3B,MAAM,OAAO,GAAG,MAAM,cAAc,CAAC,SAAS,CAAC,CAAA;QAC/C,IAAI,CAAC,OAAO;YAAE,MAAM,IAAI,oBAAoB,EAAE,CAAA;QAC9C,OAAO,MAAM,aAAa,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAA;IAC9C,CAAC;IACD,4EAA4E;IAC5E,4EAA4E;IAC5E,0EAA0E;IAC1E,WAAW,EAAE,CAAC,OAAO,EAA0B,EAAE;QAC/C,MAAM,SAAS,GAAG,2BAA2B,CAAC,OAAO,EAAE,UAAU,CAAC,CAAA;QAClE,OAAO,SAAS,CAAC,CAAC,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;IACtD,CAAC;CACF,CAAC,CAAA"}
@@ -1,22 +1,10 @@
1
1
  import type { RequestAction } from './request-action-implementation.js';
2
2
  /**
3
- * Higher-order function that wraps a request action to require specific roles.
4
- * If the user does not have the required roles, throws an AuthorizationError.
5
- * Includes a random delay on unauthorized requests to mitigate timing attacks.
6
- *
7
- * @param roles - The roles required to access the endpoint
8
- * @returns A function that wraps the provided action with authorization check
9
- * @example
10
- * ```ts
11
- * // Require 'admin' role
12
- * const adminEndpoint = Authorize('admin')(myEndpoint)
13
- *
14
- * // Require multiple roles (user must have ALL specified roles)
15
- * const superAdminEndpoint = Authorize('admin', 'superuser')(myEndpoint)
16
- *
17
- * // Chain with Authenticate for authentication + authorization
18
- * const protectedEndpoint = Authenticate()(Authorize('admin')(myEndpoint))
19
- * ```
3
+ * Wraps a {@link RequestAction} to require **all** specified roles. Throws
4
+ * {@link AuthorizationError} (translated to 403 by `ErrorAction`) when any
5
+ * role is missing. Adds a 0–1 s random delay on rejection to mitigate
6
+ * timing attacks. Compose with {@link Authenticate} to require both:
7
+ * `Authenticate()(Authorize('admin')(myEndpoint))`.
20
8
  */
21
9
  export declare const Authorize: (...roles: string[]) => <T extends {
22
10
  result: unknown;
@@ -1 +1 @@
1
- {"version":3,"file":"authorize.d.ts","sourceRoot":"","sources":["../src/authorize.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAgB,aAAa,EAAwB,MAAM,oCAAoC,CAAA;AAE3G;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,SAAS,GACnB,GAAG,OAAO,MAAM,EAAE,MAClB,CAAC,SAAS;IAAE,MAAM,EAAE,OAAO,CAAA;CAAE,EAAE,QAAQ,aAAa,CAAC,CAAC,CAAC,KAAG,aAAa,CAAC,CAAC,CAazE,CAAA"}
1
+ {"version":3,"file":"authorize.d.ts","sourceRoot":"","sources":["../src/authorize.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAgB,aAAa,EAAwB,MAAM,oCAAoC,CAAA;AAE3G;;;;;;GAMG;AACH,eAAO,MAAM,SAAS,GACnB,GAAG,OAAO,MAAM,EAAE,MAClB,CAAC,SAAS;IAAE,MAAM,EAAE,OAAO,CAAA;CAAE,EAAE,QAAQ,aAAa,CAAC,CAAC,CAAC,KAAG,aAAa,CAAC,CAAC,CAazE,CAAA"}
package/esm/authorize.js CHANGED
@@ -1,23 +1,11 @@
1
1
  import { AuthorizationError, isAuthorized } from '@furystack/core';
2
2
  import { sleepAsync } from '@furystack/utils';
3
3
  /**
4
- * Higher-order function that wraps a request action to require specific roles.
5
- * If the user does not have the required roles, throws an AuthorizationError.
6
- * Includes a random delay on unauthorized requests to mitigate timing attacks.
7
- *
8
- * @param roles - The roles required to access the endpoint
9
- * @returns A function that wraps the provided action with authorization check
10
- * @example
11
- * ```ts
12
- * // Require 'admin' role
13
- * const adminEndpoint = Authorize('admin')(myEndpoint)
14
- *
15
- * // Require multiple roles (user must have ALL specified roles)
16
- * const superAdminEndpoint = Authorize('admin', 'superuser')(myEndpoint)
17
- *
18
- * // Chain with Authenticate for authentication + authorization
19
- * const protectedEndpoint = Authenticate()(Authorize('admin')(myEndpoint))
20
- * ```
4
+ * Wraps a {@link RequestAction} to require **all** specified roles. Throws
5
+ * {@link AuthorizationError} (translated to 403 by `ErrorAction`) when any
6
+ * role is missing. Adds a 0–1 s random delay on rejection to mitigate
7
+ * timing attacks. Compose with {@link Authenticate} to require both:
8
+ * `Authenticate()(Authorize('admin')(myEndpoint))`.
21
9
  */
22
10
  export const Authorize = (...roles) => (action) => {
23
11
  return async (options) => {
@@ -1 +1 @@
1
- {"version":3,"file":"authorize.js","sourceRoot":"","sources":["../src/authorize.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAClE,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAG7C;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,CAAC,MAAM,SAAS,GACpB,CAAC,GAAG,KAAe,EAAE,EAAE,CACvB,CAAgC,MAAwB,EAAoB,EAAE;IAC5E,OAAO,KAAK,EAAE,OAAgC,EAA4B,EAAE;QAC1E,IAAI,CAAC;YACH,MAAM,UAAU,GAAG,MAAM,YAAY,CAAC,OAAO,CAAC,QAAQ,EAAE,GAAG,KAAK,CAAC,CAAA;YACjE,IAAI,CAAC,UAAU,EAAE,CAAC;gBAChB,MAAM,UAAU,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,CAAA;gBACtC,MAAM,IAAI,kBAAkB,CAAC,WAAW,CAAC,CAAA;YAC3C,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,IAAI,kBAAkB,CAAC,WAAW,CAAC,CAAA;QAC3C,CAAC;QACD,OAAO,CAAC,MAAM,MAAM,CAAC,OAAO,CAAC,CAAoB,CAAA;IACnD,CAAC,CAAA;AACH,CAAC,CAAA"}
1
+ {"version":3,"file":"authorize.js","sourceRoot":"","sources":["../src/authorize.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAClE,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAI7C;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,SAAS,GACpB,CAAC,GAAG,KAAe,EAAE,EAAE,CACvB,CAAgC,MAAwB,EAAoB,EAAE;IAC5E,OAAO,KAAK,EAAE,OAAgC,EAA4B,EAAE;QAC1E,IAAI,CAAC;YACH,MAAM,UAAU,GAAG,MAAM,YAAY,CAAC,OAAO,CAAC,QAAQ,EAAE,GAAG,KAAK,CAAC,CAAA;YACjE,IAAI,CAAC,UAAU,EAAE,CAAC;gBAChB,MAAM,UAAU,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,CAAA;gBACtC,MAAM,IAAI,kBAAkB,CAAC,WAAW,CAAC,CAAA;YAC3C,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,IAAI,kBAAkB,CAAC,WAAW,CAAC,CAAA;QAC3C,CAAC;QACD,OAAO,CAAC,MAAM,MAAM,CAAC,OAAO,CAAC,CAAoB,CAAA;IACnD,CAAC,CAAA;AACH,CAAC,CAAA"}