glasswork 1.0.1 → 1.2.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 (247) hide show
  1. package/CHANGELOG.md +48 -1
  2. package/README.md +37 -2
  3. package/dist/audit/audit-logger.d.ts +22 -0
  4. package/dist/audit/audit-logger.d.ts.map +1 -0
  5. package/dist/audit/audit-logger.js +44 -0
  6. package/dist/audit/audit-logger.js.map +1 -0
  7. package/dist/audit/context.d.ts +13 -0
  8. package/dist/audit/context.d.ts.map +1 -0
  9. package/dist/audit/context.js +66 -0
  10. package/dist/audit/context.js.map +1 -0
  11. package/dist/audit/index.d.ts +8 -0
  12. package/dist/audit/index.d.ts.map +1 -0
  13. package/dist/audit/index.js +7 -0
  14. package/dist/audit/index.js.map +1 -0
  15. package/dist/audit/types.d.ts +74 -0
  16. package/dist/audit/types.d.ts.map +1 -0
  17. package/dist/audit/types.js +2 -0
  18. package/dist/audit/types.js.map +1 -0
  19. package/dist/auth/abilities.d.ts +1 -1
  20. package/dist/auth/abilities.d.ts.map +1 -1
  21. package/dist/auth/abilities.js.map +1 -1
  22. package/dist/auth/better-auth-provider.d.ts +17 -6
  23. package/dist/auth/better-auth-provider.d.ts.map +1 -1
  24. package/dist/auth/better-auth-provider.js +16 -9
  25. package/dist/auth/better-auth-provider.js.map +1 -1
  26. package/dist/auth/index.d.ts +2 -2
  27. package/dist/auth/index.d.ts.map +1 -1
  28. package/dist/auth/index.js.map +1 -1
  29. package/dist/auth/middleware.d.ts +10 -8
  30. package/dist/auth/middleware.d.ts.map +1 -1
  31. package/dist/auth/middleware.js +27 -11
  32. package/dist/auth/middleware.js.map +1 -1
  33. package/dist/auth/types.d.ts +13 -2
  34. package/dist/auth/types.d.ts.map +1 -1
  35. package/dist/config/config-service.d.ts.map +1 -1
  36. package/dist/config/config-service.js.map +1 -1
  37. package/dist/config/providers.js.map +1 -1
  38. package/dist/core/bootstrap.d.ts.map +1 -1
  39. package/dist/core/bootstrap.js +16 -7
  40. package/dist/core/bootstrap.js.map +1 -1
  41. package/dist/core/module-graph.js +3 -0
  42. package/dist/core/module-graph.js.map +1 -1
  43. package/dist/core/request-scope.d.ts +12 -0
  44. package/dist/core/request-scope.d.ts.map +1 -0
  45. package/dist/core/request-scope.js +86 -0
  46. package/dist/core/request-scope.js.map +1 -0
  47. package/dist/core/route-factory.d.ts +1 -0
  48. package/dist/core/route-factory.d.ts.map +1 -1
  49. package/dist/core/types.d.ts +6 -1
  50. package/dist/core/types.d.ts.map +1 -1
  51. package/dist/email/compiler/compiler.d.ts.map +1 -1
  52. package/dist/email/compiler/compiler.js +72 -20
  53. package/dist/email/compiler/compiler.js.map +1 -1
  54. package/dist/email/compiler/tokenizer.js +4 -2
  55. package/dist/email/compiler/tokenizer.js.map +1 -1
  56. package/dist/email/compiler/types.d.ts +2 -0
  57. package/dist/email/compiler/types.d.ts.map +1 -1
  58. package/dist/email/email-service.d.ts.map +1 -1
  59. package/dist/email/template-registry.d.ts.map +1 -1
  60. package/dist/email/templated-email-service.d.ts.map +1 -1
  61. package/dist/email/transports/mock-transport.d.ts.map +1 -1
  62. package/dist/email/transports/ses-transport.d.ts +8 -0
  63. package/dist/email/transports/ses-transport.d.ts.map +1 -1
  64. package/dist/email/transports/ses-transport.js +132 -25
  65. package/dist/email/transports/ses-transport.js.map +1 -1
  66. package/dist/email/webhooks/handler-factory.d.ts +1 -0
  67. package/dist/email/webhooks/handler-factory.d.ts.map +1 -1
  68. package/dist/email/webhooks/handler-factory.js +40 -38
  69. package/dist/email/webhooks/handler-factory.js.map +1 -1
  70. package/dist/email/webhooks/notification-parser.d.ts +1 -1
  71. package/dist/email/webhooks/notification-parser.js +1 -1
  72. package/dist/email/webhooks/signature-verification.d.ts +4 -2
  73. package/dist/email/webhooks/signature-verification.d.ts.map +1 -1
  74. package/dist/email/webhooks/signature-verification.js +63 -8
  75. package/dist/email/webhooks/signature-verification.js.map +1 -1
  76. package/dist/email/webhooks/subscription-handler.d.ts +4 -2
  77. package/dist/email/webhooks/subscription-handler.d.ts.map +1 -1
  78. package/dist/email/webhooks/subscription-handler.js +42 -6
  79. package/dist/email/webhooks/subscription-handler.js.map +1 -1
  80. package/dist/email/webhooks/types.d.ts +17 -2
  81. package/dist/email/webhooks/types.d.ts.map +1 -1
  82. package/dist/hono-context.d.ts +1 -1
  83. package/dist/hono-context.d.ts.map +1 -1
  84. package/dist/http/error-handler.js.map +1 -1
  85. package/dist/http/errors.d.ts.map +1 -1
  86. package/dist/http/errors.js.map +1 -1
  87. package/dist/http/route-authorization.d.ts +1 -2
  88. package/dist/http/route-authorization.d.ts.map +1 -1
  89. package/dist/http/route-authorization.js.map +1 -1
  90. package/dist/http/route-context.d.ts +4 -2
  91. package/dist/http/route-context.d.ts.map +1 -1
  92. package/dist/http/route-context.js +7 -2
  93. package/dist/http/route-context.js.map +1 -1
  94. package/dist/http/route-helpers.d.ts +3 -3
  95. package/dist/http/route-helpers.d.ts.map +1 -1
  96. package/dist/http/route-helpers.js.map +1 -1
  97. package/dist/http/route-openapi.d.ts +1 -1
  98. package/dist/http/route-openapi.d.ts.map +1 -1
  99. package/dist/http/route-openapi.js.map +1 -1
  100. package/dist/http/route-types.d.ts +26 -23
  101. package/dist/http/route-types.d.ts.map +1 -1
  102. package/dist/jobs/drivers/eventbridge-scheduler-driver.d.ts.map +1 -1
  103. package/dist/jobs/drivers/eventbridge-scheduler-driver.js.map +1 -1
  104. package/dist/jobs/drivers/mock-driver.d.ts.map +1 -1
  105. package/dist/jobs/drivers/mock-driver.js.map +1 -1
  106. package/dist/jobs/drivers/sqs-driver.d.ts.map +1 -1
  107. package/dist/jobs/drivers/sqs-driver.js.map +1 -1
  108. package/dist/jobs/errors.d.ts.map +1 -1
  109. package/dist/jobs/job-registry.d.ts.map +1 -1
  110. package/dist/jobs/job-registry.js.map +1 -1
  111. package/dist/jobs/job-service.d.ts.map +1 -1
  112. package/dist/jobs/job-service.js.map +1 -1
  113. package/dist/jobs/observability/client.d.ts +26 -0
  114. package/dist/jobs/observability/client.d.ts.map +1 -0
  115. package/dist/jobs/observability/client.js +286 -0
  116. package/dist/jobs/observability/client.js.map +1 -0
  117. package/dist/jobs/observability/dashboard.d.ts +19 -0
  118. package/dist/jobs/observability/dashboard.d.ts.map +1 -0
  119. package/dist/jobs/observability/dashboard.js +144 -0
  120. package/dist/jobs/observability/dashboard.js.map +1 -0
  121. package/dist/jobs/observability/emf.d.ts +24 -0
  122. package/dist/jobs/observability/emf.d.ts.map +1 -0
  123. package/dist/jobs/observability/emf.js +100 -0
  124. package/dist/jobs/observability/emf.js.map +1 -0
  125. package/dist/jobs/observability/index.d.ts +5 -0
  126. package/dist/jobs/observability/index.d.ts.map +1 -0
  127. package/dist/jobs/observability/index.js +4 -0
  128. package/dist/jobs/observability/index.js.map +1 -0
  129. package/dist/jobs/observability/types.d.ts +234 -0
  130. package/dist/jobs/observability/types.d.ts.map +1 -0
  131. package/dist/jobs/observability/types.js +2 -0
  132. package/dist/jobs/observability/types.js.map +1 -0
  133. package/dist/jobs/worker.d.ts +3 -1
  134. package/dist/jobs/worker.d.ts.map +1 -1
  135. package/dist/jobs/worker.js +2 -0
  136. package/dist/jobs/worker.js.map +1 -1
  137. package/dist/list-query/builder.d.ts +13 -3
  138. package/dist/list-query/builder.d.ts.map +1 -1
  139. package/dist/list-query/builder.js +45 -17
  140. package/dist/list-query/builder.js.map +1 -1
  141. package/dist/list-query/filter-mapping.d.ts +89 -0
  142. package/dist/list-query/filter-mapping.d.ts.map +1 -0
  143. package/dist/list-query/filter-mapping.js +254 -0
  144. package/dist/list-query/filter-mapping.js.map +1 -0
  145. package/dist/list-query/filter-value-schemas.d.ts +3 -3
  146. package/dist/list-query/filter-value-schemas.d.ts.map +1 -1
  147. package/dist/list-query/filter-value-schemas.js +13 -3
  148. package/dist/list-query/filter-value-schemas.js.map +1 -1
  149. package/dist/list-query/index.d.ts +4 -2
  150. package/dist/list-query/index.d.ts.map +1 -1
  151. package/dist/list-query/index.js +3 -1
  152. package/dist/list-query/index.js.map +1 -1
  153. package/dist/list-query/parse-filter-values.d.ts.map +1 -1
  154. package/dist/list-query/parse-filter-values.js +2 -2
  155. package/dist/list-query/parse-filter-values.js.map +1 -1
  156. package/dist/list-query/parser.d.ts +3 -2
  157. package/dist/list-query/parser.d.ts.map +1 -1
  158. package/dist/list-query/parser.js.map +1 -1
  159. package/dist/list-query/prisma-executor.d.ts +44 -29
  160. package/dist/list-query/prisma-executor.d.ts.map +1 -1
  161. package/dist/list-query/prisma-executor.js +48 -33
  162. package/dist/list-query/prisma-executor.js.map +1 -1
  163. package/dist/list-query/query-schema.d.ts +8 -13
  164. package/dist/list-query/query-schema.d.ts.map +1 -1
  165. package/dist/list-query/query-schema.js +11 -12
  166. package/dist/list-query/query-schema.js.map +1 -1
  167. package/dist/list-query/schema-helpers.d.ts +17 -17
  168. package/dist/list-query/schema-helpers.d.ts.map +1 -1
  169. package/dist/list-query/schema-helpers.js +11 -11
  170. package/dist/list-query/schema-helpers.js.map +1 -1
  171. package/dist/list-query/sort-mapping.d.ts +37 -0
  172. package/dist/list-query/sort-mapping.d.ts.map +1 -0
  173. package/dist/list-query/sort-mapping.js +88 -0
  174. package/dist/list-query/sort-mapping.js.map +1 -0
  175. package/dist/list-query/types.d.ts +3 -10
  176. package/dist/list-query/types.d.ts.map +1 -1
  177. package/dist/list-query/validator.d.ts.map +1 -1
  178. package/dist/list-query/validator.js +28 -10
  179. package/dist/list-query/validator.js.map +1 -1
  180. package/dist/middleware/rate-limit.d.ts.map +1 -1
  181. package/dist/middleware/rate-limit.js +60 -92
  182. package/dist/middleware/rate-limit.js.map +1 -1
  183. package/dist/observability/exception-tracking.d.ts.map +1 -1
  184. package/dist/observability/exception-tracking.js.map +1 -1
  185. package/dist/observability/index.d.ts +1 -1
  186. package/dist/observability/index.d.ts.map +1 -1
  187. package/dist/observability/index.js +1 -1
  188. package/dist/observability/index.js.map +1 -1
  189. package/dist/observability/pino-logger.d.ts +0 -28
  190. package/dist/observability/pino-logger.d.ts.map +1 -1
  191. package/dist/observability/pino-logger.js +21 -12
  192. package/dist/observability/pino-logger.js.map +1 -1
  193. package/dist/observability/request-context.d.ts +36 -1
  194. package/dist/observability/request-context.d.ts.map +1 -1
  195. package/dist/observability/request-context.js +43 -0
  196. package/dist/observability/request-context.js.map +1 -1
  197. package/dist/openapi/openapi.d.ts +1 -4
  198. package/dist/openapi/openapi.d.ts.map +1 -1
  199. package/dist/openapi/openapi.js +15 -35
  200. package/dist/openapi/openapi.js.map +1 -1
  201. package/dist/rls/configuration.d.ts +3 -0
  202. package/dist/rls/configuration.d.ts.map +1 -0
  203. package/dist/rls/configuration.js +13 -0
  204. package/dist/rls/configuration.js.map +1 -0
  205. package/dist/rls/context.d.ts +37 -0
  206. package/dist/rls/context.d.ts.map +1 -0
  207. package/dist/rls/context.js +56 -0
  208. package/dist/rls/context.js.map +1 -0
  209. package/dist/rls/extension.d.ts +7 -0
  210. package/dist/rls/extension.d.ts.map +1 -0
  211. package/dist/rls/extension.js +91 -0
  212. package/dist/rls/extension.js.map +1 -0
  213. package/dist/rls/generator.d.ts +17 -0
  214. package/dist/rls/generator.d.ts.map +1 -0
  215. package/dist/rls/generator.js +47 -0
  216. package/dist/rls/generator.js.map +1 -0
  217. package/dist/rls/index.d.ts +7 -0
  218. package/dist/rls/index.d.ts.map +1 -0
  219. package/dist/rls/index.js +7 -0
  220. package/dist/rls/index.js.map +1 -0
  221. package/dist/rls/middleware.d.ts +17 -0
  222. package/dist/rls/middleware.d.ts.map +1 -0
  223. package/dist/rls/middleware.js +51 -0
  224. package/dist/rls/middleware.js.map +1 -0
  225. package/dist/rls/testing.d.ts +24 -0
  226. package/dist/rls/testing.d.ts.map +1 -0
  227. package/dist/rls/testing.js +31 -0
  228. package/dist/rls/testing.js.map +1 -0
  229. package/dist/rls/types.d.ts +51 -0
  230. package/dist/rls/types.d.ts.map +1 -0
  231. package/dist/rls/types.js +16 -0
  232. package/dist/rls/types.js.map +1 -0
  233. package/dist/sse/index.d.ts +6 -0
  234. package/dist/sse/index.d.ts.map +1 -0
  235. package/dist/sse/index.js +18 -0
  236. package/dist/sse/index.js.map +1 -0
  237. package/dist/sse/sse-broadcaster.d.ts +38 -0
  238. package/dist/sse/sse-broadcaster.d.ts.map +1 -0
  239. package/dist/sse/sse-broadcaster.js +118 -0
  240. package/dist/sse/sse-broadcaster.js.map +1 -0
  241. package/dist/uploads/uploads.service.d.ts.map +1 -1
  242. package/dist/uploads/validators.d.ts.map +1 -1
  243. package/dist/utils/get-client-ip.d.ts.map +1 -1
  244. package/dist/utils/get-client-ip.js +22 -13
  245. package/dist/utils/get-client-ip.js.map +1 -1
  246. package/dist/utils/serialize-prisma-types.js.map +1 -1
  247. package/package.json +56 -35
package/CHANGELOG.md CHANGED
@@ -7,17 +7,62 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [1.2.0] - 2026-09-29
11
+
10
12
  ### Added
11
13
 
14
+ - **`glasswork/sse`** — in-process server-sent event notifications for long-running Node.js deployments, with bounded connection buffers, heartbeats, and automatic cleanup. The broadcaster does not provide cross-instance delivery or work with the standard Lambda handler.
15
+
16
+ ### Fixed
17
+
18
+ - Load the optional Swagger UI peer on the first UI request so minimal core consumers can import and bootstrap without it.
19
+
20
+ - Enable partial batch responses in every SQS worker deployment example so failed jobs remain retryable.
21
+
22
+ - Preserve SES webhook error responses and return a retryable status when event processing fails.
23
+
24
+ - Secure the Better Auth role example with `input: false` and document the migration check for existing authorization data.
25
+ - Enforce `allowGuest: false` for every unauthenticated request, including routes without an authorization rule, while still clearing invalid session cookies.
26
+ - Resolve `SCOPED` route services from an isolated Awilix child container for each HTTP request and dispose the scope after handling.
27
+ - Preserve trusted list-query scopes in every facet aggregation, including scopes on the aggregated field and nested logical conditions.
28
+ - Verify SNS webhook signatures in every environment by default and restrict automatic subscription confirmation to bounded, non-redirecting AWS SNS requests.
29
+ - Require an explicit SNS topic allowlist for verified webhooks and support AWS SNS signature versions 1 and 2.
30
+ - Revoke Better Auth sessions with the authenticated session token and use Better Auth's standard cookie name by default.
31
+ - Consume rate-limit capacity atomically, require complete DynamoDB configuration, and resolve client IPs from Lambda and Node adapter context.
32
+ - HTML-escape email template variables by default, restrict dynamic URL schemes, and require triple braces for trusted raw HTML.
33
+ - Encode raw SES messages from UTF-8 bytes and reject header or attachment metadata that could alter the MIME structure.
34
+ - Export OpenAPI documents directly after route registration without mounting a temporary public endpoint or using a timer.
35
+
36
+ ## [1.1.0] - 2026-09-16
37
+
38
+ ### Added
39
+
40
+ - **`glasswork/rls`** — PostgreSQL tenant isolation through Prisma Client Extensions, AsyncLocalStorage, Hono middleware, and a policy generator; includes transaction-scoped context, explicit bypass, and PostgreSQL integration tests.
41
+
12
42
  - **`parseFilterLiteral`**, **`parseFilterValue`**, **`parseWhereFilterValues`** — centralized filter value parsing for query params and Prisma `where` clauses
13
43
  - **`filter-value-schemas`** — Valibot operand schemas with transforms for typed Prisma filters
44
+ - **`executePrismaList`** — direct execution of `findMany`, `count`, and optional `groupBy` aggregations on any Prisma model delegate, with optional `map` row-transformation callback
45
+ - **`createPrismaListExecutor` row mapping** — added optional `map: (item: TItem) => TResult` callback to transform raw Prisma records into domain models or DTOs
46
+ - **Virtual filter mapping (`mapFilters`)** — transform virtual/composite API filter fields into real database columns prior to search and scope merging; includes `mapPresenceFilter`, `mapBooleanFilter`, `mapValueFilter`, `renameFilter`, `nestFilter`, and `composeFilterMappers`
47
+ - **Sort mapping (`mapSorts`)** — transform public API sort fields to nested relation paths (`'user.name'`) or custom sort clauses via `nestSort`, `renameSort`, or custom mapper functions in `createListQuery`
48
+ - **`glasswork/audit`** — impersonation-aware auditing subsystem with ambient actor and tenant resolution, pluggable `AuditSink<TTx>` transactional sinks, and dual-logging
14
49
 
15
50
  ### Changed
16
51
 
52
+ - Build and typecheck with stable TypeScript 7.0.2; verify published declarations and route inference with TypeScript 5.9, 6, and 7 in isolated npm consumers.
53
+ - Propagate concrete authentication types through route contexts.
54
+ - Update development dependencies, including Biome 2.5, AWS SDK clients, Hono, CASL, MJML, and documentation tooling. Keep Prisma on stable 7.10 and Vitest on the latest 4.x release compatible with Better Auth's testing peer range.
55
+ - Add Node.js 26 to the CI test matrix alongside Node.js 20, 22, and 24; check packed-package imports and types on Node.js 20.
56
+ - Make `ListQuerySchema` strict and bounded; malformed pagination, oversized strings, and unknown query parameters now return 422 instead of being clamped or ignored.
57
+ - Reject unknown list-query filter fields, filter operators, and sort fields; validate date operands as existing calendar dates.
17
58
  - Typed filter schemas (`dateFilterSchema`, `intFilterSchema`, `numberFilterSchema`, `booleanFilterSchema`) parse string operands to Prisma types via Valibot transforms
18
59
  - `parseWhereFilterValues` reuses those schemas with `parse()` instead of custom coercion logic
19
60
  - List-query `where` deep copy uses `structuredClone` so parsed `Date` values are preserved
20
61
 
62
+ ### Fixed
63
+
64
+ - Correctly escape end and else control flow markers in compiled email templates.
65
+
21
66
  ## [1.0.0] - 2026-06-10
22
67
 
23
68
  Major release: subpath exports, dependency upgrades (CASL 7, MJML 5, Valibot 1.4, Prisma 7), Prisma list-query helpers, and internal refactors. Breaking changes when upgrading from 0.x.
@@ -75,6 +120,8 @@ Major release: subpath exports, dependency upgrades (CASL 7, MJML 5, Valibot 1.4
75
120
 
76
121
  Last 0.x release before the 1.0 breaking changes. Earlier 0.x history is available on [GitHub releases](https://github.com/rolandboon/glasswork/releases).
77
122
 
78
- [Unreleased]: https://github.com/rolandboon/glasswork/compare/v1.0.0...HEAD
123
+ [Unreleased]: https://github.com/rolandboon/glasswork/compare/v1.2.0...HEAD
124
+ [1.2.0]: https://github.com/rolandboon/glasswork/compare/v1.1.0...v1.2.0
125
+ [1.1.0]: https://github.com/rolandboon/glasswork/compare/v1.0.0...v1.1.0
79
126
  [1.0.0]: https://github.com/rolandboon/glasswork/compare/v0.13.3...v1.0.0
80
127
  [0.13.3]: https://github.com/rolandboon/glasswork/compare/v0.13.2...v0.13.3
package/README.md CHANGED
@@ -53,6 +53,9 @@ Glasswork combines the best patterns from NestJS (modules, DI, OpenAPI) with the
53
53
  npm install glasswork hono awilix valibot hono-openapi
54
54
  ```
55
55
 
56
+ To use Swagger UI at `/api`, also install `@hono/swagger-ui`. It is loaded on the
57
+ first UI request; API routes and OpenAPI JSON generation do not require it.
58
+
56
59
  Glasswork 1.0 uses **subpath exports** (`glasswork/core`, `glasswork/http`, `glasswork/auth`, …). The root `glasswork` import covers core and HTTP only; optional subsystems use their own subpath. See [Package Exports](https://glasswork.dev/getting-started/package-exports).
57
60
 
58
61
  ## Quick Start
@@ -170,12 +173,44 @@ export default app; // Ready for Lambda or local server
170
173
  ## Requirements
171
174
 
172
175
  - Node.js 20+
173
- - TypeScript 5+
176
+ - TypeScript 5.9, 6, or 7 (verified against the published declarations)
174
177
 
175
178
  ## Contributing
176
179
 
177
180
  Glasswork is in active development. Feedback, issues, and contributions are welcome!
178
181
 
182
+ Builds and typechecks use stable TypeScript 7. Vitest stays on the latest 4.x
183
+ release to remain compatible with Better Auth's testing peer range. CI runs the
184
+ full test suite on Node.js 20, 22, 24, and 26, and checks the packed package's
185
+ TypeScript 5.9, 6, and 7 consumer inference on Node.js 20.
186
+
187
+ The repository can be developed and verified independently with npm:
188
+
189
+ ```sh
190
+ npm ci
191
+ npm run verify
192
+ npm run docs:build
193
+ ```
194
+
195
+ `npm run smoke:pack` installs the tarball in an isolated npm project, checks its
196
+ published types, and imports its public entry points. Set `TYPESCRIPT_VERSION`
197
+ to test another supported compiler, for example
198
+ `TYPESCRIPT_VERSION=5.9.3 npm run smoke:pack` after building. Prisma's development
199
+ tooling requires Node.js 20.19+, 22.12+, or 24+ on the respective supported lines.
200
+
201
+ The RLS integration suite creates a temporary schema and restricted role in an
202
+ existing PostgreSQL **test database**, then removes them afterwards. Set
203
+ `RLS_TEST_DATABASE_URL` to a test administrator connection allowed to create schemas
204
+ and roles; the actual isolation checks run as the restricted role:
205
+
206
+ ```sh
207
+ RLS_TEST_DATABASE_URL=postgresql://test_admin:password@localhost:5432/test_db npm run verify
208
+ ```
209
+
210
+ Without this variable, the PostgreSQL suite is skipped. CI sets it for both tests
211
+ and coverage. To run coverage locally, use the same variable with
212
+ `npm run test:coverage`.
213
+
179
214
  ## License
180
215
 
181
216
  MIT
@@ -191,5 +226,5 @@ MIT
191
226
  [build-href]: https://github.com/rolandboon/glasswork/actions/workflows/ci.yml
192
227
  [license-src]: https://img.shields.io/github/license/rolandboon/glasswork.svg?flat&colorA=1b1b1f&colorB=3e63dd
193
228
  [license-href]: https://opensource.org/licenses/MIT
194
- [type-script-src]: https://img.shields.io/badge/TypeScript-5.0%2B-blue?style=flat&labelColor=1b1b1f&color=3e63dd
229
+ [type-script-src]: https://img.shields.io/badge/TypeScript-5.9%20%7C%206%20%7C%207-blue?style=flat&labelColor=1b1b1f&color=3e63dd
195
230
  [type-script-href]: https://www.typescriptlang.org/
@@ -0,0 +1,22 @@
1
+ import type { Logger } from '../utils/logger.js';
2
+ import type { AuditingLogger, AuditRecordInput, AuditSink } from './types.js';
3
+ export interface CreateAuditLoggerOptions<TTx = unknown> {
4
+ /** Persistence sink for audit records */
5
+ sink: AuditSink<TTx>;
6
+ /** Underlying logger (e.g. Pino logger) */
7
+ logger: Logger;
8
+ /** Service name to tag audit events with */
9
+ service?: string;
10
+ /** Custom formatter for the structured log payload */
11
+ formatLogPayload?: (record: AuditRecordInput) => Record<string, unknown>;
12
+ }
13
+ /**
14
+ * Creates an AuditingLogger that combines structured logging with persistence via an AuditSink.
15
+ *
16
+ * Each call to `logger.audit(message, entry, options)`:
17
+ * 1. Resolves ambient request context (actor, impersonation, tenant, correlation ID).
18
+ * 2. Emits a structured log (`audit: true` with audit attributes) via the underlying logger.
19
+ * 3. Persists the resolved audit record atomically using the provided sink.
20
+ */
21
+ export declare function createAuditLogger<TTx = unknown>(options: CreateAuditLoggerOptions<TTx>): AuditingLogger<TTx>;
22
+ //# sourceMappingURL=audit-logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audit-logger.d.ts","sourceRoot":"","sources":["../../src/audit/audit-logger.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAEjD,OAAO,KAAK,EAAmB,cAAc,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE/F,MAAM,WAAW,wBAAwB,CAAC,GAAG,GAAG,OAAO;IACrD,yCAAyC;IACzC,IAAI,EAAE,SAAS,CAAC,GAAG,CAAC,CAAC;IACrB,2CAA2C;IAC3C,MAAM,EAAE,MAAM,CAAC;IACf,4CAA4C;IAC5C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,sDAAsD;IACtD,gBAAgB,CAAC,EAAE,CAAC,MAAM,EAAE,gBAAgB,KAAK,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC1E;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,GAAG,OAAO,EAC7C,OAAO,EAAE,wBAAwB,CAAC,GAAG,CAAC,GACrC,cAAc,CAAC,GAAG,CAAC,CA6CrB"}
@@ -0,0 +1,44 @@
1
+ import { resolveAuditRecord } from './context.js';
2
+ /**
3
+ * Creates an AuditingLogger that combines structured logging with persistence via an AuditSink.
4
+ *
5
+ * Each call to `logger.audit(message, entry, options)`:
6
+ * 1. Resolves ambient request context (actor, impersonation, tenant, correlation ID).
7
+ * 2. Emits a structured log (`audit: true` with audit attributes) via the underlying logger.
8
+ * 3. Persists the resolved audit record atomically using the provided sink.
9
+ */
10
+ export function createAuditLogger(options) {
11
+ const { sink, logger, service, formatLogPayload } = options;
12
+ const audit = async (message, entry, auditOptions) => {
13
+ const record = resolveAuditRecord({
14
+ ...entry,
15
+ message: entry.message ?? message,
16
+ }, service);
17
+ const logPayload = formatLogPayload
18
+ ? formatLogPayload(record)
19
+ : {
20
+ audit: true,
21
+ action: record.action,
22
+ category: record.category,
23
+ subjectType: record.subjectType,
24
+ subjectId: record.subjectId,
25
+ actorUserId: record.actorUserId,
26
+ effectiveUserId: record.effectiveUserId,
27
+ isImpersonating: record.isImpersonating,
28
+ tenantId: record.tenantId,
29
+ service: record.service,
30
+ metadata: record.metadata,
31
+ };
32
+ logger.info(message, logPayload);
33
+ await sink.record(record, auditOptions);
34
+ };
35
+ return {
36
+ debug: logger.debug.bind(logger),
37
+ info: logger.info.bind(logger),
38
+ warn: logger.warn.bind(logger),
39
+ error: logger.error.bind(logger),
40
+ child: logger.child?.bind(logger),
41
+ audit,
42
+ };
43
+ }
44
+ //# sourceMappingURL=audit-logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audit-logger.js","sourceRoot":"","sources":["../../src/audit/audit-logger.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAclD;;;;;;;GAOG;AACH,MAAM,UAAU,iBAAiB,CAC/B,OAAsC;IAEtC,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,gBAAgB,EAAE,GAAG,OAAO,CAAC;IAE5D,MAAM,KAAK,GAAG,KAAK,EACjB,OAAe,EACf,KAAsB,EACtB,YAA2B,EACZ,EAAE;QACjB,MAAM,MAAM,GAAG,kBAAkB,CAC/B;YACE,GAAG,KAAK;YACR,OAAO,EAAE,KAAK,CAAC,OAAO,IAAI,OAAO;SAClC,EACD,OAAO,CACR,CAAC;QAEF,MAAM,UAAU,GAAG,gBAAgB;YACjC,CAAC,CAAC,gBAAgB,CAAC,MAAM,CAAC;YAC1B,CAAC,CAAC;gBACE,KAAK,EAAE,IAAI;gBACX,MAAM,EAAE,MAAM,CAAC,MAAM;gBACrB,QAAQ,EAAE,MAAM,CAAC,QAAQ;gBACzB,WAAW,EAAE,MAAM,CAAC,WAAW;gBAC/B,SAAS,EAAE,MAAM,CAAC,SAAS;gBAC3B,WAAW,EAAE,MAAM,CAAC,WAAW;gBAC/B,eAAe,EAAE,MAAM,CAAC,eAAe;gBACvC,eAAe,EAAE,MAAM,CAAC,eAAe;gBACvC,QAAQ,EAAE,MAAM,CAAC,QAAQ;gBACzB,OAAO,EAAE,MAAM,CAAC,OAAO;gBACvB,QAAQ,EAAE,MAAM,CAAC,QAAQ;aAC1B,CAAC;QAEN,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;QAEjC,MAAM,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IAC1C,CAAC,CAAC;IAEF,OAAO;QACL,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC;QAChC,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC;QAC9B,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC;QAC9B,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC;QAChC,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC;QACjC,KAAK;KACN,CAAC;AACJ,CAAC"}
@@ -0,0 +1,13 @@
1
+ import type { AuditContext, AuditEntryInput, AuditRecordInput } from './types.js';
2
+ /**
3
+ * Get contextual information about the current actor and request for auditing.
4
+ * Returns undefined if called outside an authenticated request lifecycle.
5
+ */
6
+ export declare function getAuditContext(): AuditContext | undefined;
7
+ /**
8
+ * Resolve an audit entry input with ambient request context to produce a complete AuditRecordInput.
9
+ *
10
+ * @throws Error if no actorUserId can be resolved from either the entry or the request context.
11
+ */
12
+ export declare function resolveAuditRecord(entry: AuditEntryInput, service?: string): AuditRecordInput;
13
+ //# sourceMappingURL=context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/audit/context.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAElF;;;GAGG;AACH,wBAAgB,eAAe,IAAI,YAAY,GAAG,SAAS,CAU1D;AAyCD;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,eAAe,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,gBAAgB,CAgB7F"}
@@ -0,0 +1,66 @@
1
+ import { getRequestActor, getRequestId } from '../observability/request-context.js';
2
+ /**
3
+ * Get contextual information about the current actor and request for auditing.
4
+ * Returns undefined if called outside an authenticated request lifecycle.
5
+ */
6
+ export function getAuditContext() {
7
+ const actor = getRequestActor();
8
+ if (!actor?.actorUserId)
9
+ return undefined;
10
+ return {
11
+ actorUserId: actor.actorUserId,
12
+ effectiveUserId: actor.effectiveUserId,
13
+ isImpersonating: actor.isImpersonating,
14
+ tenantId: actor.tenantId,
15
+ requestId: getRequestId(),
16
+ };
17
+ }
18
+ function resolveActor(entry, ctx) {
19
+ if (ctx?.isImpersonating) {
20
+ return {
21
+ actorUserId: ctx.actorUserId,
22
+ effectiveUserId: ctx.effectiveUserId ?? null,
23
+ isImpersonating: Boolean(ctx.effectiveUserId && ctx.effectiveUserId !== ctx.actorUserId),
24
+ tenantId: ctx.tenantId ?? entry.tenantId ?? null,
25
+ };
26
+ }
27
+ const actorUserId = entry.actorUserId ?? ctx?.actorUserId;
28
+ if (!actorUserId) {
29
+ throw new Error(`Audit entry '${entry.action}' requires an actorUserId, but none was provided or available in request context`);
30
+ }
31
+ const effectiveUserId = entry.effectiveUserId ?? ctx?.effectiveUserId ?? null;
32
+ return {
33
+ actorUserId,
34
+ effectiveUserId,
35
+ isImpersonating: Boolean(effectiveUserId && effectiveUserId !== actorUserId),
36
+ tenantId: entry.tenantId ?? ctx?.tenantId ?? null,
37
+ };
38
+ }
39
+ function formatAuditMessage(entry) {
40
+ if (entry.message)
41
+ return entry.message;
42
+ const target = entry.subjectId ? ` ${entry.subjectId}` : '';
43
+ return `Audit: ${entry.action} on ${entry.subjectType}${target}`;
44
+ }
45
+ /**
46
+ * Resolve an audit entry input with ambient request context to produce a complete AuditRecordInput.
47
+ *
48
+ * @throws Error if no actorUserId can be resolved from either the entry or the request context.
49
+ */
50
+ export function resolveAuditRecord(entry, service) {
51
+ const ctx = getAuditContext();
52
+ const actors = resolveActor(entry, ctx);
53
+ return {
54
+ ...actors,
55
+ requestId: ctx?.requestId ?? null,
56
+ action: entry.action,
57
+ category: entry.category ?? 'DATA',
58
+ subjectType: entry.subjectType,
59
+ subjectId: entry.subjectId ?? null,
60
+ message: formatAuditMessage(entry),
61
+ metadata: entry.metadata ?? null,
62
+ service: service ?? null,
63
+ createdAt: new Date(),
64
+ };
65
+ }
66
+ //# sourceMappingURL=context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/audit/context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,qCAAqC,CAAC;AAGpF;;;GAGG;AACH,MAAM,UAAU,eAAe;IAC7B,MAAM,KAAK,GAAG,eAAe,EAAE,CAAC;IAChC,IAAI,CAAC,KAAK,EAAE,WAAW;QAAE,OAAO,SAAS,CAAC;IAC1C,OAAO;QACL,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,eAAe,EAAE,KAAK,CAAC,eAAe;QACtC,eAAe,EAAE,KAAK,CAAC,eAAe;QACtC,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,SAAS,EAAE,YAAY,EAAE;KAC1B,CAAC;AACJ,CAAC;AASD,SAAS,YAAY,CAAC,KAAsB,EAAE,GAAkB;IAC9D,IAAI,GAAG,EAAE,eAAe,EAAE,CAAC;QACzB,OAAO;YACL,WAAW,EAAE,GAAG,CAAC,WAAW;YAC5B,eAAe,EAAE,GAAG,CAAC,eAAe,IAAI,IAAI;YAC5C,eAAe,EAAE,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,GAAG,CAAC,eAAe,KAAK,GAAG,CAAC,WAAW,CAAC;YACxF,QAAQ,EAAE,GAAG,CAAC,QAAQ,IAAI,KAAK,CAAC,QAAQ,IAAI,IAAI;SACjD,CAAC;IACJ,CAAC;IAED,MAAM,WAAW,GAAG,KAAK,CAAC,WAAW,IAAI,GAAG,EAAE,WAAW,CAAC;IAC1D,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CACb,gBAAgB,KAAK,CAAC,MAAM,kFAAkF,CAC/G,CAAC;IACJ,CAAC;IAED,MAAM,eAAe,GAAG,KAAK,CAAC,eAAe,IAAI,GAAG,EAAE,eAAe,IAAI,IAAI,CAAC;IAC9E,OAAO;QACL,WAAW;QACX,eAAe;QACf,eAAe,EAAE,OAAO,CAAC,eAAe,IAAI,eAAe,KAAK,WAAW,CAAC;QAC5E,QAAQ,EAAE,KAAK,CAAC,QAAQ,IAAI,GAAG,EAAE,QAAQ,IAAI,IAAI;KAClD,CAAC;AACJ,CAAC;AAED,SAAS,kBAAkB,CAAC,KAAsB;IAChD,IAAI,KAAK,CAAC,OAAO;QAAE,OAAO,KAAK,CAAC,OAAO,CAAC;IACxC,MAAM,MAAM,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IAC5D,OAAO,UAAU,KAAK,CAAC,MAAM,OAAO,KAAK,CAAC,WAAW,GAAG,MAAM,EAAE,CAAC;AACnE,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CAAC,KAAsB,EAAE,OAAgB;IACzE,MAAM,GAAG,GAAG,eAAe,EAAE,CAAC;IAC9B,MAAM,MAAM,GAAG,YAAY,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAExC,OAAO;QACL,GAAG,MAAM;QACT,SAAS,EAAE,GAAG,EAAE,SAAS,IAAI,IAAI;QACjC,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,QAAQ,EAAE,KAAK,CAAC,QAAQ,IAAI,MAAM;QAClC,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,SAAS,EAAE,KAAK,CAAC,SAAS,IAAI,IAAI;QAClC,OAAO,EAAE,kBAAkB,CAAC,KAAK,CAAC;QAClC,QAAQ,EAAE,KAAK,CAAC,QAAQ,IAAI,IAAI;QAChC,OAAO,EAAE,OAAO,IAAI,IAAI;QACxB,SAAS,EAAE,IAAI,IAAI,EAAE;KACtB,CAAC;AACJ,CAAC"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * @module glasswork/audit
3
+ * Audit logging, impersonation correlation, and audit sink abstraction.
4
+ */
5
+ export { type CreateAuditLoggerOptions, createAuditLogger, } from './audit-logger.js';
6
+ export { getAuditContext, resolveAuditRecord } from './context.js';
7
+ export type { AuditContext, AuditEntryInput, AuditingLogger, AuditRecordInput, AuditSink, } from './types.js';
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/audit/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACL,KAAK,wBAAwB,EAC7B,iBAAiB,GAClB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AACnE,YAAY,EACV,YAAY,EACZ,eAAe,EACf,cAAc,EACd,gBAAgB,EAChB,SAAS,GACV,MAAM,YAAY,CAAC"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * @module glasswork/audit
3
+ * Audit logging, impersonation correlation, and audit sink abstraction.
4
+ */
5
+ export { createAuditLogger, } from './audit-logger.js';
6
+ export { getAuditContext, resolveAuditRecord } from './context.js';
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/audit/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAEL,iBAAiB,GAClB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC"}
@@ -0,0 +1,74 @@
1
+ import type { Logger } from '../utils/logger.js';
2
+ /**
3
+ * Contextual information about the actor and request for an audit event.
4
+ */
5
+ export interface AuditContext {
6
+ /** Physical authenticated user who initiated the request */
7
+ actorUserId: string;
8
+ /** Effective user identity when acting via impersonation */
9
+ effectiveUserId?: string;
10
+ /** Whether the request is being executed via impersonation */
11
+ isImpersonating: boolean;
12
+ /** Tenant / organization identifier */
13
+ tenantId?: string;
14
+ /** Request identifier for distributed correlation */
15
+ requestId?: string;
16
+ }
17
+ /**
18
+ * Input for creating an audit event from business logic.
19
+ */
20
+ export interface AuditEntryInput {
21
+ /** Unique action identifier (e.g. 'poll.create', 'member.archive') */
22
+ action: string;
23
+ /** Audit category (defaults to 'DATA') */
24
+ category?: string;
25
+ /** Target entity type (e.g. 'Poll', 'User', 'MedicalGroup') */
26
+ subjectType: string;
27
+ /** Target entity ID */
28
+ subjectId?: string | null;
29
+ /** Human-readable description of the event */
30
+ message?: string;
31
+ /** Additional structured metadata or changed fields */
32
+ metadata?: Record<string, unknown> | null;
33
+ /** Explicit actor override (e.g. for background jobs / seeders) */
34
+ actorUserId?: string | null;
35
+ /** Explicit effective user override */
36
+ effectiveUserId?: string | null;
37
+ /** Explicit tenant override */
38
+ tenantId?: string | null;
39
+ }
40
+ /**
41
+ * Fully resolved audit record ready for persistence and structured logging.
42
+ */
43
+ export interface AuditRecordInput {
44
+ actorUserId: string;
45
+ effectiveUserId: string | null;
46
+ isImpersonating: boolean;
47
+ tenantId: string | null;
48
+ requestId: string | null;
49
+ action: string;
50
+ category: string;
51
+ subjectType: string;
52
+ subjectId: string | null;
53
+ message: string;
54
+ metadata: Record<string, unknown> | null;
55
+ service: string | null;
56
+ createdAt: Date;
57
+ }
58
+ /**
59
+ * Pluggable persistence sink for audit records (e.g. Prisma, DynamoDB, CloudWatch).
60
+ */
61
+ export interface AuditSink<TTx = unknown> {
62
+ record(entry: AuditRecordInput, options?: {
63
+ tx?: TTx;
64
+ }): Promise<void>;
65
+ }
66
+ /**
67
+ * Logger extended with an `.audit()` method that writes structured logs and persists via a sink.
68
+ */
69
+ export type AuditingLogger<TTx = unknown> = Logger & {
70
+ audit(message: string, entry: AuditEntryInput, options?: {
71
+ tx?: TTx;
72
+ }): Promise<void>;
73
+ };
74
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/audit/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAEjD;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,4DAA4D;IAC5D,WAAW,EAAE,MAAM,CAAC;IACpB,4DAA4D;IAC5D,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,8DAA8D;IAC9D,eAAe,EAAE,OAAO,CAAC;IACzB,uCAAuC;IACvC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,qDAAqD;IACrD,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,sEAAsE;IACtE,MAAM,EAAE,MAAM,CAAC;IACf,0CAA0C;IAC1C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,+DAA+D;IAC/D,WAAW,EAAE,MAAM,CAAC;IACpB,uBAAuB;IACvB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,8CAA8C;IAC9C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,uDAAuD;IACvD,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC1C,mEAAmE;IACnE,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,uCAAuC;IACvC,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,+BAA+B;IAC/B,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,eAAe,EAAE,OAAO,CAAC;IACzB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IACzC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,SAAS,EAAE,IAAI,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,SAAS,CAAC,GAAG,GAAG,OAAO;IACtC,MAAM,CAAC,KAAK,EAAE,gBAAgB,EAAE,OAAO,CAAC,EAAE;QAAE,EAAE,CAAC,EAAE,GAAG,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACxE;AAED;;GAEG;AACH,MAAM,MAAM,cAAc,CAAC,GAAG,GAAG,OAAO,IAAI,MAAM,GAAG;IACnD,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,eAAe,EAAE,OAAO,CAAC,EAAE;QAAE,EAAE,CAAC,EAAE,GAAG,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACvF,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/audit/types.ts"],"names":[],"mappings":""}
@@ -24,7 +24,7 @@ export type AuthorizedAbility<TActions extends string, TSubjects extends string>
24
24
  *
25
25
  * const ability = defineAbility(currentUser);
26
26
  */
27
- export declare function createAbilityFactory<TSubjects extends string, TActions extends string = 'create' | 'read' | 'update' | 'delete' | 'manage'>(): (define: (can: AbilityBuilder<AuthorizedAbility<TActions, TSubjects>>["can"], cannot: AbilityBuilder<AuthorizedAbility<TActions, TSubjects>>["cannot"], user: AuthUser) => void) => (user: AuthUser) => AuthorizedAbility<TActions, TSubjects>;
27
+ export declare function createAbilityFactory<TSubjects extends string, TActions extends string = 'create' | 'read' | 'update' | 'delete' | 'manage'>(): (define: (can: AbilityBuilder<AuthorizedAbility<TActions, TSubjects>>['can'], cannot: AbilityBuilder<AuthorizedAbility<TActions, TSubjects>>['cannot'], user: AuthUser) => void) => (user: AuthUser) => AuthorizedAbility<TActions, TSubjects>;
28
28
  /**
29
29
  * Define abilities using a declarative role-based configuration.
30
30
  */
@@ -1 +1 @@
1
- {"version":3,"file":"abilities.d.ts","sourceRoot":"","sources":["../../src/auth/abilities.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,KAAK,aAAa,EAAE,MAAM,eAAe,CAAC;AACnE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAGlD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C;;GAEG;AACH,MAAM,MAAM,iBAAiB,CAAC,QAAQ,SAAS,MAAM,EAAE,SAAS,SAAS,MAAM,IAAI,aAAa,CAC9F;IAAC,QAAQ;IAAE,SAAS,GAAG,aAAa,CAAC,SAAS,CAAC;CAAC,CACjD,GAAG;IACF,SAAS,EAAE,CACT,MAAM,EAAE,QAAQ,EAChB,OAAO,EAAE,SAAS,GAAG,aAAa,CAAC,SAAS,CAAC,EAC7C,OAAO,CAAC,EAAE,MAAM,KACb,IAAI,CAAC;CACX,CAAC;AAqBF;;;;;;;;;;;;;GAaG;AACH,wBAAgB,oBAAoB,CAClC,SAAS,SAAS,MAAM,EACxB,QAAQ,SAAS,MAAM,GAAG,QAAQ,GAAG,MAAM,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,MAK1E,QAAQ,CACN,GAAG,EAAE,cAAc,wCAAY,CAAC,KAAK,CAAC,EACtC,MAAM,EAAE,cAAc,wCAAY,CAAC,QAAQ,CAAC,EAC5C,IAAI,EAAE,QAAQ,KACX,IAAI,MAED,MAAM,QAAQ,4CAOzB;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,SAAS,SAAS,MAAM,EACxB,QAAQ,SAAS,MAAM,EACvB,MAAM,SAAS,MAAM,EAErB,MAAM,EAAE,MAAM,CACZ,MAAM,EACN,CAAC,GAAG,EAAE;IACJ,GAAG,EAAE,cAAc,CAAC,aAAa,CAAC,CAAC,QAAQ,EAAE,SAAS,GAAG,aAAa,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;IAC5F,MAAM,EAAE,cAAc,CACpB,aAAa,CAAC,CAAC,QAAQ,EAAE,SAAS,GAAG,aAAa,CAAC,SAAS,CAAC,CAAC,CAAC,CAChE,CAAC,QAAQ,CAAC,CAAC;IACZ,IAAI,EAAE,QAAQ,CAAC;CAChB,KAAK,IAAI,CACX;cAKW,QAAQ;IAelB,4DAA4D;kBAC9C,MAAM,SAAQ,OAAO,CAAC,QAAQ,CAAC;EAIhD;AAED;;GAEG;AACH,MAAM,MAAM,YAAY,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,QAAQ,KAAK,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC"}
1
+ {"version":3,"file":"abilities.d.ts","sourceRoot":"","sources":["../../src/auth/abilities.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,KAAK,aAAa,EAAE,MAAM,eAAe,CAAC;AACnE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAGlD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C;;GAEG;AACH,MAAM,MAAM,iBAAiB,CAAC,QAAQ,SAAS,MAAM,EAAE,SAAS,SAAS,MAAM,IAAI,aAAa,CAC9F;IAAC,QAAQ;IAAE,SAAS,GAAG,aAAa,CAAC,SAAS,CAAC;CAAC,CACjD,GAAG;IACF,SAAS,EAAE,CACT,MAAM,EAAE,QAAQ,EAChB,OAAO,EAAE,SAAS,GAAG,aAAa,CAAC,SAAS,CAAC,EAC7C,OAAO,CAAC,EAAE,MAAM,KACb,IAAI,CAAC;CACX,CAAC;AAqBF;;;;;;;;;;;;;GAaG;AACH,wBAAgB,oBAAoB,CAClC,SAAS,SAAS,MAAM,EACxB,QAAQ,SAAS,MAAM,GAAG,QAAQ,GAAG,MAAM,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,cAKlE,CACN,GAAG,EAAE,cAAc,wCAAY,CAAC,KAAK,CAAC,EACtC,MAAM,EAAE,cAAc,wCAAY,CAAC,QAAQ,CAAC,EAC5C,IAAI,EAAE,QAAQ,KACX,IAAI,YAEK,QAAQ,4CAOzB;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,SAAS,SAAS,MAAM,EACxB,QAAQ,SAAS,MAAM,EACvB,MAAM,SAAS,MAAM,EAErB,MAAM,EAAE,MAAM,CACZ,MAAM,EACN,CAAC,GAAG,EAAE;IACJ,GAAG,EAAE,cAAc,CAAC,aAAa,CAAC,CAAC,QAAQ,EAAE,SAAS,GAAG,aAAa,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;IAC5F,MAAM,EAAE,cAAc,CACpB,aAAa,CAAC,CAAC,QAAQ,EAAE,SAAS,GAAG,aAAa,CAAC,SAAS,CAAC,CAAC,CAAC,CAChE,CAAC,QAAQ,CAAC,CAAC;IACZ,IAAI,EAAE,QAAQ,CAAC;CAChB,KAAK,IAAI,CACX;IAKC,GAAG,OAAO,QAAQ;IAelB,4DAA4D;IAC5D,OAAO,OAAO,MAAM,SAAQ,OAAO,CAAC,QAAQ,CAAC;EAIhD;AAED;;GAEG;AACH,MAAM,MAAM,YAAY,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,QAAQ,KAAK,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"abilities.js","sourceRoot":"","sources":["../../src/auth/abilities.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAsB,MAAM,eAAe,CAAC;AAEnE,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,uBAAuB,EAAE,MAAM,kBAAkB,CAAC;AAgB3D,SAAS,eAAe,CACtB,OAAwE;IAExE,OAAO,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE;QAC5B,SAAS,CACP,MAAgB,EAChB,OAA6C,EAC7C,OAAgB;YAEhB,sHAAsH;YACtH,IAAI,CAAE,OAAe,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;gBAC3C,MAAM,IAAI,kBAAkB,CAC1B,OAAO,IAAI,gCAAgC,MAAM,gBAAgB,CAClE,CAAC;YACJ,CAAC;QACH,CAAC;KACF,CAA2C,CAAC;AAC/C,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,oBAAoB;IAMlC,OAAO,SAAS,aAAa,CAC3B,MAIS;QAET,OAAO,CAAC,IAAc,EAAc,EAAE;YACpC,MAAM,mBAAmB,GAAG,uBAAuB,EAAE,CAAC;YACtD,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,IAAI,cAAc,CAAa,mBAAmB,CAAC,CAAC;YACnF,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC;YAC1B,OAAO,eAAe,CAAC,KAAK,EAAE,CAAC,CAAC;QAClC,CAAC,CAAC;IACJ,CAAC,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,mBAAmB,CAKjC,MASC;IAID,OAAO;QACL,GAAG,CAAC,IAAc;YAChB,MAAM,mBAAmB,GAAG,uBAAuB,EAAE,CAAC;YACtD,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,IAAI,cAAc,CAE/C,mBAAmB,CAAC,CAAC;YAEvB,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,IAAc,CAAC,CAAC;YAE/C,IAAI,UAAU,EAAE,CAAC;gBACf,UAAU,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;YACpC,CAAC;YAED,OAAO,eAAe,CAAC,KAAK,EAAE,CAAC,CAAC;QAClC,CAAC;QAED,4DAA4D;QAC5D,OAAO,CAAC,IAAY,EAAE,OAA0B,EAAE;YAChD,OAAO,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,IAAI,EAAc,CAAC,CAAC;QAC7D,CAAC;KACF,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"abilities.js","sourceRoot":"","sources":["../../src/auth/abilities.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAsB,MAAM,eAAe,CAAC;AAEnE,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,uBAAuB,EAAE,MAAM,kBAAkB,CAAC;AAgB3D,SAAS,eAAe,CACtB,OAAwE;IAExE,OAAO,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE;QAC5B,SAAS,CACP,MAAgB,EAChB,OAA6C,EAC7C,OAAgB;YAEhB,sHAAsH;YACtH,IAAI,CAAE,OAAe,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;gBAC3C,MAAM,IAAI,kBAAkB,CAC1B,OAAO,IAAI,gCAAgC,MAAM,gBAAgB,CAClE,CAAC;YACJ,CAAC;QACH,CAAC;KACF,CAA2C,CAAC;AAC/C,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,oBAAoB;IAMlC,OAAO,SAAS,aAAa,CAC3B,MAIS;QAET,OAAO,CAAC,IAAc,EAAc,EAAE;YACpC,MAAM,mBAAmB,GAAG,uBAAuB,EAAE,CAAC;YACtD,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,IAAI,cAAc,CAAa,mBAAmB,CAAC,CAAC;YACnF,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC;YAC1B,OAAO,eAAe,CAAC,KAAK,EAAE,CAAC,CAAC;QAClC,CAAC,CAAC;IACJ,CAAC,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,mBAAmB,CAKjC,MASC;IAID,OAAO;QACL,GAAG,CAAC,IAAc;YAChB,MAAM,mBAAmB,GAAG,uBAAuB,EAAE,CAAC;YACtD,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,IAAI,cAAc,CAE/C,mBAAmB,CAAC,CAAC;YAEvB,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,IAAc,CAAC,CAAC;YAE/C,IAAI,UAAU,EAAE,CAAC;gBACf,UAAU,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;YACpC,CAAC;YAED,OAAO,eAAe,CAAC,KAAK,EAAE,CAAC,CAAC;QAClC,CAAC;QAED,4DAA4D;QAC5D,OAAO,CAAC,IAAY,EAAE,IAAI,GAAsB,EAAE;YAChD,OAAO,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,IAAI,EAAc,CAAC,CAAC;QAC7D,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -1,5 +1,12 @@
1
1
  import type { AuthProvider, AuthUser } from './types.js';
2
2
  export interface BetterAuthClient {
3
+ $context?: Promise<{
4
+ authCookies: {
5
+ sessionToken: {
6
+ name: string;
7
+ };
8
+ };
9
+ }>;
3
10
  api: {
4
11
  getSession: (options: {
5
12
  headers?: Record<string, string>;
@@ -9,9 +16,10 @@ export interface BetterAuthClient {
9
16
  } | null>;
10
17
  revokeSession: (options: {
11
18
  body: {
12
- id: string;
19
+ token: string;
13
20
  };
14
- }) => Promise<void>;
21
+ headers: Record<string, string>;
22
+ }) => Promise<unknown>;
15
23
  signInEmail?: (options: {
16
24
  body: {
17
25
  email: string;
@@ -31,12 +39,12 @@ export interface BetterAuthClient {
31
39
  };
32
40
  handler?: (request: Request) => Promise<Response>;
33
41
  }
34
- export interface BetterAuthProviderConfig {
42
+ export interface BetterAuthProviderConfig<TUser extends AuthUser = AuthUser> {
35
43
  /** better-auth client instance */
36
44
  auth: BetterAuthClient;
37
45
  /** Map better-auth user to AuthUser */
38
- mapUser?: (user: Record<string, unknown>) => AuthUser;
39
- /** Cookie name for session token (default: 'session') */
46
+ mapUser?: (user: Record<string, unknown>) => TUser;
47
+ /** Override the cookie name. Otherwise use Better Auth's resolved cookie configuration. */
40
48
  cookieName?: string;
41
49
  }
42
50
  interface BetterAuthSession {
@@ -51,6 +59,9 @@ interface BetterAuthSession {
51
59
  /**
52
60
  * Wrap better-auth as a Glasswork AuthProvider.
53
61
  */
54
- export declare function createBetterAuthProvider(config: BetterAuthProviderConfig): AuthProvider;
62
+ export declare function createBetterAuthProvider<TUser extends AuthUser>(config: BetterAuthProviderConfig<TUser> & {
63
+ mapUser: (user: Record<string, unknown>) => TUser;
64
+ }): AuthProvider<TUser>;
65
+ export declare function createBetterAuthProvider(config: BetterAuthProviderConfig<AuthUser>): AuthProvider<AuthUser>;
55
66
  export {};
56
67
  //# sourceMappingURL=better-auth-provider.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"better-auth-provider.d.ts","sourceRoot":"","sources":["../../src/auth/better-auth-provider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAe,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEtE,MAAM,WAAW,gBAAgB;IAC/B,GAAG,EAAE;QACH,UAAU,EAAE,CAAC,OAAO,EAAE;YAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;SAAE,KAAK,OAAO,CAAC;YACrE,OAAO,CAAC,EAAE,iBAAiB,GAAG,IAAI,CAAC;YACnC,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;SACvC,GAAG,IAAI,CAAC,CAAC;QACV,aAAa,EAAE,CAAC,OAAO,EAAE;YAAE,IAAI,EAAE;gBAAE,EAAE,EAAE,MAAM,CAAA;aAAE,CAAA;SAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;QACpE,WAAW,CAAC,EAAE,CAAC,OAAO,EAAE;YAAE,IAAI,EAAE;gBAAE,KAAK,EAAE,MAAM,CAAC;gBAAC,QAAQ,EAAE,MAAM,CAAA;aAAE,CAAA;SAAE,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;QAC3F,WAAW,CAAC,EAAE,CAAC,OAAO,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;SAAE,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;QAC/E,YAAY,CAAC,EACT,CAAC,CAAC,OAAO,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;SAAE,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC,GAClE,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG;YAClB,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE;gBAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;aAAE,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;SAC9E,CAAC,CAAC;KACR,CAAC;IACF,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;CACnD;AAED,MAAM,WAAW,wBAAwB;IACvC,kCAAkC;IAClC,IAAI,EAAE,gBAAgB,CAAC;IACvB,uCAAuC;IACvC,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,QAAQ,CAAC;IACtD,yDAAyD;IACzD,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,UAAU,iBAAiB;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAID;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,wBAAwB,GAAG,YAAY,CAgDvF"}
1
+ {"version":3,"file":"better-auth-provider.d.ts","sourceRoot":"","sources":["../../src/auth/better-auth-provider.ts"],"names":[],"mappings":"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"}
@@ -1,9 +1,7 @@
1
- const DEFAULT_COOKIE_NAME = 'session';
2
- /**
3
- * Wrap better-auth as a Glasswork AuthProvider.
4
- */
1
+ const DEFAULT_COOKIE_NAME = 'better-auth.session_token';
5
2
  export function createBetterAuthProvider(config) {
6
- const { auth, mapUser, cookieName = DEFAULT_COOKIE_NAME } = config;
3
+ const { auth, mapUser, cookieName } = config;
4
+ const getSessionCookieName = async () => cookieName ?? (await auth.$context)?.authCookies.sessionToken.name ?? DEFAULT_COOKIE_NAME;
7
5
  const defaultMapUser = (user) => ({
8
6
  ...user,
9
7
  id: String(user.id ?? user.userId ?? ''),
@@ -13,10 +11,12 @@ export function createBetterAuthProvider(config) {
13
11
  });
14
12
  return {
15
13
  name: 'better-auth',
14
+ sessionCookieName: cookieName ?? DEFAULT_COOKIE_NAME,
15
+ getSessionCookieName,
16
16
  async validateSession(token) {
17
17
  try {
18
18
  const result = await auth.api.getSession({
19
- headers: { cookie: `${cookieName}=${token}` },
19
+ headers: { cookie: `${await getSessionCookieName()}=${token}` },
20
20
  });
21
21
  if (!result?.session || !result.user) {
22
22
  return null;
@@ -30,13 +30,19 @@ export function createBetterAuthProvider(config) {
30
30
  return null;
31
31
  }
32
32
  },
33
- async invalidateSession(sessionId) {
34
- await auth.api.revokeSession({ body: { id: sessionId } });
33
+ async invalidateSession(token) {
34
+ const headers = { cookie: `${await getSessionCookieName()}=${token}` };
35
+ const result = await auth.api.getSession({ headers });
36
+ const sessionToken = result?.session?.token;
37
+ if (typeof sessionToken !== 'string' || sessionToken.length === 0) {
38
+ return;
39
+ }
40
+ await auth.api.revokeSession({ body: { token: sessionToken }, headers });
35
41
  },
36
42
  async refreshSession(token) {
37
43
  try {
38
44
  const result = await auth.api.getSession({
39
- headers: { cookie: `${cookieName}=${token}` },
45
+ headers: { cookie: `${await getSessionCookieName()}=${token}` },
40
46
  });
41
47
  return result?.session ? mapSession(result.session) : null;
42
48
  }
@@ -53,6 +59,7 @@ function mapSession(session) {
53
59
  expiresAt: toDate(session.expiresAt),
54
60
  createdAt: toDate(session.createdAt),
55
61
  lastAccessedAt: session.lastAccessedAt ? toDate(session.lastAccessedAt) : undefined,
62
+ impersonatedBy: typeof session.impersonatedBy === 'string' ? session.impersonatedBy : undefined,
56
63
  metadata: session,
57
64
  };
58
65
  }
@@ -1 +1 @@
1
- {"version":3,"file":"better-auth-provider.js","sourceRoot":"","sources":["../../src/auth/better-auth-provider.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"better-auth-provider.js","sourceRoot":"","sources":["../../src/auth/better-auth-provider.ts"],"names":[],"mappings":"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"}
@@ -2,6 +2,6 @@ export { createAbilityFactory, defineRoleAbilities, type InferAbility, } from '.
2
2
  export { assertCan, can, subject } from './assert.js';
3
3
  export { type BetterAuthClient, type BetterAuthProviderConfig, createBetterAuthProvider, } from './better-auth-provider.js';
4
4
  export { type PrismaAbilityFactory, registerAuthCasl } from './casl-bridge.js';
5
- export { type AuthMiddlewareConfig, createAuthMiddleware, } from './middleware.js';
6
- export type { AuthContext, AuthProvider, AuthSession, AuthUser } from './types.js';
5
+ export { type AuthAuthorizeConfig, type AuthMiddleware, type AuthMiddlewareConfig, createAuthMiddleware, } from './middleware.js';
6
+ export type { AuthContext, AuthenticatedAuthContext, AuthProvider, AuthSession, AuthUser, } from './types.js';
7
7
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,oBAAoB,EACpB,mBAAmB,EACnB,KAAK,YAAY,GAClB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,SAAS,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,EACL,KAAK,gBAAgB,EACrB,KAAK,wBAAwB,EAC7B,wBAAwB,GACzB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,KAAK,oBAAoB,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAE/E,OAAO,EACL,KAAK,oBAAoB,EACzB,oBAAoB,GACrB,MAAM,iBAAiB,CAAC;AACzB,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,oBAAoB,EACpB,mBAAmB,EACnB,KAAK,YAAY,GAClB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,SAAS,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,EACL,KAAK,gBAAgB,EACrB,KAAK,wBAAwB,EAC7B,wBAAwB,GACzB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,KAAK,oBAAoB,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAE/E,OAAO,EACL,KAAK,mBAAmB,EACxB,KAAK,cAAc,EACnB,KAAK,oBAAoB,EACzB,oBAAoB,GACrB,MAAM,iBAAiB,CAAC;AACzB,YAAY,EACV,WAAW,EACX,wBAAwB,EACxB,YAAY,EACZ,WAAW,EACX,QAAQ,GACT,MAAM,YAAY,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,oBAAoB,EACpB,mBAAmB,GAEpB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,SAAS,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,EAGL,wBAAwB,GACzB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAA6B,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAE/E,OAAO,EAEL,oBAAoB,GACrB,MAAM,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,oBAAoB,EACpB,mBAAmB,GAEpB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,SAAS,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,EAGL,wBAAwB,GACzB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAA6B,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAE/E,OAAO,EAIL,oBAAoB,GACrB,MAAM,iBAAiB,CAAC"}