@getstrata/core 0.5.101 → 0.7.4

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 (61) hide show
  1. package/CHANGELOG.md +67 -32
  2. package/README.md +16 -35
  3. package/dist/core/auth/abilityCatalog.d.ts +2 -2
  4. package/dist/core/auth/basicAuthGuard.d.ts +9 -0
  5. package/dist/core/auth/guard.d.ts +6 -0
  6. package/dist/core/auth/jwt.d.ts +19 -0
  7. package/dist/core/auth/jwtGuard.d.ts +14 -0
  8. package/dist/core/auth/tokenAbilityChecker.d.ts +5 -0
  9. package/dist/core/cache/tags.d.ts +6 -0
  10. package/dist/core/contracts/authUserDirectory.d.ts +4 -0
  11. package/dist/core/database/dialect.d.ts +18 -0
  12. package/dist/core/database/factory.d.ts +1 -0
  13. package/dist/core/database/index.d.ts +8 -0
  14. package/dist/core/database/mysqlConnection.d.ts +12 -0
  15. package/dist/core/database/namedConnections.d.ts +15 -0
  16. package/dist/core/database/repositoryQuery.d.ts +1 -0
  17. package/dist/core/database/sqliteConnection.d.ts +7 -0
  18. package/dist/core/http/loginThrottleMiddleware.d.ts +5 -2
  19. package/dist/core/http/resources.d.ts +2 -2
  20. package/dist/core/http/response.d.ts +2 -1
  21. package/dist/core/http/statelessAuth.d.ts +8 -0
  22. package/dist/core/http/throttleResponse.d.ts +2 -0
  23. package/dist/core/runtime/frontendMode.d.ts +10 -2
  24. package/dist/entries/auth/basicAuthGuard.js +137 -0
  25. package/dist/entries/auth/jwt.js +135 -0
  26. package/dist/entries/auth/jwtGuard.js +203 -0
  27. package/dist/entries/auth/sessionGuard.js +3 -21
  28. package/dist/entries/auth/tokenAbilityChecker.js +24 -0
  29. package/dist/entries/cache/tags.js +7 -1
  30. package/dist/entries/database/connectionContext.js +1 -0
  31. package/dist/entries/database/dialect.js +1 -0
  32. package/dist/entries/database/factory.js +5 -4
  33. package/dist/entries/database/model.js +49 -32
  34. package/dist/entries/database/mysqlConnection.js +35 -0
  35. package/dist/entries/database/namedConnections.js +1 -0
  36. package/dist/entries/database/query.js +28 -15
  37. package/dist/entries/database/relationships.js +14 -6
  38. package/dist/entries/database/repositoryQuery.js +96 -81
  39. package/dist/entries/database/schema.js +28 -15
  40. package/dist/entries/database/sqliteConnection.js +34 -0
  41. package/dist/entries/facades.js +1 -1
  42. package/dist/entries/http/contentNegotiation.js +5 -2
  43. package/dist/entries/http/csrfMiddleware.js +45 -0
  44. package/dist/entries/http/loginThrottleMiddleware.js +246 -7
  45. package/dist/entries/http/memoryThrottleMiddleware.js +208 -6
  46. package/dist/entries/http/requireAbilityMiddleware.js +35 -11
  47. package/dist/entries/http/requirePasswordConfirmMiddleware.js +5 -2
  48. package/dist/entries/http/requireVerifiedMiddleware.js +5 -2
  49. package/dist/entries/http/requireWebAuthMiddleware.js +12 -3
  50. package/dist/entries/http/resources.js +4 -1
  51. package/dist/entries/http/response.js +46 -12
  52. package/dist/entries/http/statelessAuth.js +48 -0
  53. package/dist/entries/http/throttleMiddleware.js +208 -6
  54. package/dist/entries/http/webErrorResponse.js +35 -11
  55. package/dist/entries/http/webFormRequest.js +5 -2
  56. package/dist/entries/mail/mailer.js +1 -1
  57. package/dist/entries/openapi/generator.js +26 -3
  58. package/dist/entries/runtime/frontendMode.js +39 -10
  59. package/dist/framework/public-api.d.ts +11 -1
  60. package/dist/index.js +873 -270
  61. package/package.json +56 -5
package/CHANGELOG.md CHANGED
@@ -1,5 +1,40 @@
1
1
  # @getstrata/core changelog
2
2
 
3
+ ## 0.7.4
4
+
5
+ - Default database pool and query handles live on `globalThis`, so the published `@getstrata/core` bundle and `src/core` share one pool in the same process.
6
+
7
+ ## 0.7.3
8
+
9
+ - `JsonResource.whenLoaded` returns `null` when a relation is loaded but empty. It does not call the transform, so `new PositionResource(value).toArray()` cannot crash on a missing belongsTo.
10
+
11
+ ## 0.7.2
12
+
13
+ - `withJsonErrorHandling` always maps thrown errors to JSON. `requestPrefersJson` treats `/api/` as JSON even when `Accept` is HTML, so hybrid staff HTML cannot remap JSON API errors.
14
+
15
+ ## 0.7.1
16
+
17
+ - `readSpaPrefix` / `normalizeSpaPrefix` own `SPA_PREFIX` (default `/app`). Apps set the env value. They do not copy a second static-file server.
18
+ - The log mail driver records `htmlBytes` instead of dumping the HTML document onto stdout.
19
+
20
+ ## 0.7.0
21
+
22
+ - `FRONTEND_MODE=hybrid` turns on staff HTML and the candidate SPA together. Views are on for `server-htmx` and `hybrid`. The SPA is on for `spa-react` and `hybrid`.
23
+ - `parseFrontendMode`, `FRONTEND_MODES`, and `FRONTEND_MODE_PATTERN` are the allowed-value list. Apps should reuse that pattern in env schemas.
24
+ - Named database connections: `registerNamedConnection`, `runOnNamedConnection`, SQLite (`bun:sqlite`), and MySQL (`mysql2`). `runWithSqlDialect` keeps the dialect across `await` via AsyncLocalStorage.
25
+ - New subpaths: `database/namedConnections`, `database/sqliteConnection`, `database/mysqlConnection`, `database/connectionContext`.
26
+ - OpenAPI treats `POST /api/apply/login` as unauthenticated.
27
+
28
+ ## 0.6.0
29
+
30
+ - **Breaking:** cookie session signatures use HMAC-SHA256. Existing HMAC cookies signed with the previous digest will not verify. Rotate `SESSION_SECRET` or sign users in again.
31
+ - **Breaking:** default `MEMBER_ABILITIES` are profile and token scopes (`profile:read`, `auth:tokens:*`), not org/project/task. Apps replace the catalog with `configureAbilityCatalog`. HiroApp maps admin / recruiter / candidate.
32
+ - Named auth guards: opaque Bearer tokens, JWT HS256, HTTP Basic, and cookie sessions. `AuthManager` picks a guard from the `Authorization` scheme. CSRF is skipped for Bearer and Basic.
33
+ - OpenAPI treats HiroApp login, JWT mint (`POST /api/auth/token`), and public careers as unauthenticated. Partner ping and audit export require credentials.
34
+ - SQL dialect helpers (`pgsql`, `mysql`, `sqlite`) for placeholders, quoting, `ILIKE`/`LIKE`, `RETURNING`, and `NULLS LAST`. Full-text `tsMatch` stays Postgres-only and throws on other engines.
35
+ - HiroApp is the only in-repo example product. The leftover `src/db` schema is a test fixture, not a second app.
36
+ - New subpaths: `auth/jwt`, `auth/jwtGuard`, `auth/basicAuthGuard`, `auth/tokenAbilityChecker`, `database/dialect`, `http/statelessAuth`.
37
+
3
38
  ## 0.5.101
4
39
 
5
40
  - Tenant middleware falls back with explicit branches when a member, admin, or guest tenant lookup misses, so the request still scopes to the default tenant.
@@ -16,12 +51,12 @@ Still non-conforming (honest): Bun cannot infer `morphTo()` method names. `hashe
16
51
 
17
52
  ## 0.5.99
18
53
 
19
- HiroApp dogfood of 0.5.98 found lookalike APIs. This release matches Laravel call shape and SQL, not just export names.
54
+ HiroApp dogfood of 0.5.98 found lookalike APIs. This release matches the previous PHP framework call shape and SQL, not just export names.
20
55
 
21
56
  - Relation queries are thenable: `await user.applications()` delegates to `get()`.
22
57
  - `Model.with()` / `where()` / `whereHas()` return a `ModelQuery` that hydrates models and chains into `where` / `find` / `findOrFail` / `first` / `get`. `first()` / `find()` use `LIMIT` / PK lookup.
23
58
  - `belongsTo.where()` threads constraints into `whereHas` EXISTS (HiroApp application search).
24
- - `{ ilike }` uses the value as-is (Laravel). Pass `%term%` yourself; the operator no longer wraps extra `%`.
59
+ - `{ ilike }` uses the value as-is (the previous PHP framework). Pass `%term%` yourself; the operator no longer wraps extra `%`.
25
60
  - Morph type defaults to `$morphClass` / class name, not `table.name`. Override with `$morphClass = "App\\Models\\User"` or the last `morphMany` argument. `morphTo()` no longer silently defaults to `imageable_*`.
26
61
  - `primaryKey()` defaults to the table PK (`id`).
27
62
  - Nested `load("a.b")` / `with("a.b")` skip already-loaded heads and batch the next level.
@@ -41,7 +76,7 @@ Still non-conforming (honest): Bun cannot infer `morphTo()` method names (`debug
41
76
  - `Model.where()`, `firstOrNew()`, `firstOrCreate()`, and `updateOrCreate()`.
42
77
  - Factory `count`/`state`/`sequence`/`for`/`has`/`recycle` plus `afterMaking`/`afterCreating`.
43
78
  - `JsonResource` (`wrap`, `whenLoaded`, `additional`, `collection`).
44
- - Laravel aliases: container `make`/`instance`, EventBus `on`/`emit`, query `whereNull`/`whereIn`/`whereExists`.
79
+ - the previous PHP framework aliases: container `make`/`instance`, EventBus `on`/`emit`, query `whereNull`/`whereIn`/`whereExists`.
45
80
  - Parity audit reports design score separately. Horizon/Nova/CLI stay Bun-native stand-ins.
46
81
 
47
82
  ## 0.5.97
@@ -59,10 +94,10 @@ Still non-conforming (honest): Bun cannot infer `morphTo()` method names (`debug
59
94
 
60
95
  ## 0.5.90
61
96
 
62
- - **Breaking identity defaults:** `appKeyPrefix()` is `strata` and `appDisplayName()` is `Strata` when `APP_KEY_PREFIX` / `APP_NAME` are unset (were `workhub` / `WorkHub`). WorkHub pins those env vars.
97
+ - **Breaking identity defaults:** `appKeyPrefix()` is `strata` and `appDisplayName()` is `Strata` when `APP_KEY_PREFIX` / `APP_NAME` are unset (were `strata` / `the previous in-repo app`). the previous in-repo app pins those env vars.
63
98
  - `Schedule.command()` rejects cron strings other than `* * * * *` and `*/N * * * *` instead of silently never running them.
64
99
  - OpenAPI marks `GET /users/me/*` as bearer-authenticated.
65
- - OpenAPI `/users/me/current-organization` summaries no longer say Jetstream.
100
+ - OpenAPI `/users/me/current-organization` summaries no longer say team invitations.
66
101
 
67
102
  ## 0.5.89
68
103
 
@@ -70,16 +105,16 @@ Still non-conforming (honest): Bun cannot infer `morphTo()` method names (`debug
70
105
 
71
106
  ## 0.5.88
72
107
 
73
- - Exported cookie name constants (`SESSION_COOKIE`, `CSRF_COOKIE`, `FLASH_COOKIE`, `INTENDED_URL_COOKIE`, `PASSWORD_CONFIRM_COOKIE`) are `appCookieName(...)` so they match the default prefix instead of a hardcoded `workhub_` string.
74
- - `@getstrata/core/jobs/dispatchWebhookJob` is a deprecated compatibility re-export of the WorkHub webhook job.
108
+ - Exported cookie name constants (`SESSION_COOKIE`, `CSRF_COOKIE`, `FLASH_COOKIE`, `INTENDED_URL_COOKIE`, `PASSWORD_CONFIRM_COOKIE`) are `appCookieName(...)` so they match the default prefix instead of a hardcoded `strata_` string.
109
+ - `@getstrata/core/jobs/dispatchWebhookJob` is a deprecated compatibility re-export of the the previous in-repo app webhook job.
75
110
 
76
111
  ## 0.5.87
77
112
 
78
- - `AuthUserDirectory.hasActiveBrowserSession?(userId, issuedAt)` is optional. `SessionGuard` calls it after `session_valid_after` and rejects the HMAC cookie when it returns false so WorkHub can revoke a single browser session by deleting the `sessions` row.
113
+ - `AuthUserDirectory.hasActiveBrowserSession?(userId, issuedAt)` is optional. `SessionGuard` calls it after `session_valid_after` and rejects the HMAC cookie when it returns false so the previous in-repo app can revoke a single browser session by deleting the `sessions` row.
79
114
 
80
115
  ## 0.5.86
81
116
 
82
- - `createSessionCookieDetails()` returns the HMAC session header plus `issuedAt` / `ttlSeconds` so apps can persist Jetstream browser-session rows without changing the cookie format.
117
+ - `createSessionCookieDetails()` returns the HMAC session header plus `issuedAt` / `ttlSeconds` so apps can persist team invitations browser-session rows without changing the cookie format.
83
118
 
84
119
  ## 0.5.85
85
120
 
@@ -91,24 +126,24 @@ Still non-conforming (honest): Bun cannot infer `morphTo()` method names (`debug
91
126
 
92
127
  ## 0.5.83
93
128
 
94
- - `MEMBER_ABILITIES` includes `auth:tokens:delete` so Jetstream-style personal access token revoke works for members (`DELETE /auth/tokens/:id`). HTML `/account/tokens/:id/revoke` was already authenticated-only.
129
+ - `MEMBER_ABILITIES` includes `auth:tokens:delete` so team invitations-style personal access token revoke works for members (`DELETE /auth/tokens/:id`). HTML `/account/tokens/:id/revoke` was already authenticated-only.
95
130
  - `buildOtpauthUrl()` defaults the issuer through `appDisplayName()` (`APP_NAME`).
96
131
 
97
132
  ## 0.5.82
98
133
 
99
- - `MEMBER_ABILITIES` includes `organizations:create` so Jetstream-style extra teams work for members (HTML `POST /organizations` and JSON `POST /organizations`). `OrganizationPolicy.create` already allowed any authenticated user.
134
+ - `MEMBER_ABILITIES` includes `organizations:create` so team invitations-style extra teams work for members (HTML `POST /organizations` and JSON `POST /organizations`). `OrganizationPolicy.create` already allowed any authenticated user.
100
135
 
101
136
  ## 0.5.81
102
137
 
103
- - `@getstrata/core/auth/intendedUrlCookie` (`createIntendedUrlCookie`, `readIntendedUrl`, `clearIntendedUrlCookie`, `createIntendedUrlCookieFromRequest`). Fortify intended URL after HTML email verification: register with `redirect=` and Laravel `verified` HTML redirects stash `${APP_KEY_PREFIX}_intended` (`INTENDED_URL_COOKIE_NAME`, default `workhub_intended`; TTL `INTENDED_URL_TTL_SECONDS`, default 86400s). `GET /verify-email` honors and clears it.
138
+ - `@getstrata/core/auth/intendedUrlCookie` (`createIntendedUrlCookie`, `readIntendedUrl`, `clearIntendedUrlCookie`, `createIntendedUrlCookieFromRequest`). HTML auth intended URL after HTML email verification: register with `redirect=` and the previous PHP framework `verified` HTML redirects stash `${APP_KEY_PREFIX}_intended` (`INTENDED_URL_COOKIE_NAME`, default `strata_intended`; TTL `INTENDED_URL_TTL_SECONDS`, default 86400s). `GET /verify-email` honors and clears it.
104
139
 
105
140
  ## 0.5.80
106
141
 
107
- - `appCookieName()` / `appDevSecret()` on `@getstrata/core/runtime/appKeyPrefix`. HMAC session, CSRF, flash, password-confirm, signed-URL, OAuth-state, and token-pepper fallbacks follow `APP_KEY_PREFIX` (WorkHub defaults unchanged).
142
+ - `appCookieName()` / `appDevSecret()` on `@getstrata/core/runtime/appKeyPrefix`. HMAC session, CSRF, flash, password-confirm, signed-URL, OAuth-state, and token-pepper fallbacks follow `APP_KEY_PREFIX` (the previous in-repo app defaults unchanged).
108
143
 
109
144
  ## 0.5.79
110
145
 
111
- - `readSession()` returns `{ userId, issuedAt }` from the HMAC session cookie. `isSessionInvalidated(issuedAt, session_valid_after)` lets `SessionGuard` reject cookies issued before `AuthUserRecord.session_valid_after` (Jetstream logout-other-devices / password change).
146
+ - `readSession()` returns `{ userId, issuedAt }` from the HMAC session cookie. `isSessionInvalidated(issuedAt, session_valid_after)` lets `SessionGuard` reject cookies issued before `AuthUserRecord.session_valid_after` (team invitations logout-other-devices / password change).
112
147
 
113
148
  ## 0.5.78
114
149
 
@@ -116,7 +151,7 @@ Still non-conforming (honest): Bun cannot infer `morphTo()` method names (`debug
116
151
 
117
152
  ## 0.5.77
118
153
 
119
- - `@getstrata/core/security/recoveryCodes` (`generateRecoveryCodes`, `hashRecoveryCode`, `recoveryCodeMatches`). Fortify-style one-time MFA backup codes (`abcd-efgh`).
154
+ - `@getstrata/core/security/recoveryCodes` (`generateRecoveryCodes`, `hashRecoveryCode`, `recoveryCodeMatches`). HTML auth-style one-time MFA backup codes (`abcd-efgh`).
120
155
 
121
156
  ## 0.5.76
122
157
 
@@ -124,12 +159,12 @@ Still non-conforming (honest): Bun cannot infer `morphTo()` method names (`debug
124
159
 
125
160
  ## 0.5.75
126
161
 
127
- - Laravel `password.confirm`: `@getstrata/core/auth/passwordConfirmCookie` (`createPasswordConfirmCookie`, `hasFreshPasswordConfirmation`, `clearPasswordConfirmCookie`) and `createRequirePasswordConfirmMiddleware()` (HTML 302 `/confirm-password`, JSON 423). Cookie name `PASSWORD_CONFIRM_COOKIE_NAME` (default `workhub_password_confirmed`), TTL `PASSWORD_CONFIRM_TIMEOUT` (default 10800s).
162
+ - the previous PHP framework `password.confirm`: `@getstrata/core/auth/passwordConfirmCookie` (`createPasswordConfirmCookie`, `hasFreshPasswordConfirmation`, `clearPasswordConfirmCookie`) and `createRequirePasswordConfirmMiddleware()` (HTML 302 `/confirm-password`, JSON 423). Cookie name `PASSWORD_CONFIRM_COOKIE_NAME` (default `strata_password_confirmed`), TTL `PASSWORD_CONFIRM_TIMEOUT` (default 10800s).
128
163
 
129
164
  ## 0.5.74
130
165
 
131
166
  - `AuthUser.emailVerifiedAt` and `@getstrata/core/auth/emailVerification` (`isEmailVerificationRequired`, `hasVerifiedEmail`). `null` means unverified; missing is treated as verified (GuestGuard / legacy).
132
- - `createRequireVerifiedMiddleware()` is Laravel `verified` (HTML 302 `/email/verify`, JSON 403).
167
+ - `createRequireVerifiedMiddleware()` is the previous PHP framework `verified` (HTML 302 `/email/verify`, JSON 403).
133
168
 
134
169
  ## 0.5.73
135
170
 
@@ -154,40 +189,40 @@ Still non-conforming (honest): Bun cannot infer `morphTo()` method names (`debug
154
189
 
155
190
  ## 0.5.68
156
191
 
157
- - Published core no longer imports WorkHub `src/config`. Frontend mode, queue retries, CORS, and upload limits read env (`FRONTEND_MODE`, `QUEUE_*`, `CORS_ALLOWED_ORIGINS`, `MAX_UPLOAD_BYTES`).
192
+ - Published core no longer imports the previous in-repo app `src/config`. Frontend mode, queue retries, CORS, and upload limits read env (`FRONTEND_MODE`, `QUEUE_*`, `CORS_ALLOWED_ORIGINS`, `MAX_UPLOAD_BYTES`).
158
193
  - `@getstrata/core/runtime/frontendMode` exports `readFrontendMode` / `isViewsEnabled` / `isSpaEnabled`.
159
194
 
160
195
  ## 0.5.67
161
196
 
162
- - OpenAPI title, server URLs, and generated SDK class name come from `APP_NAME` / `APP_URL` / `API_PREFIX` / `APP_SDK_CLASS` instead of importing WorkHub `src/config/app`.
163
- - `appEnv()`, `appUrl()`, `apiPrefix()`, and `sdkClientClassName()` live on `@getstrata/core/runtime/appKeyPrefix`. SIEM export, HSTS, and `safeFetch` DNS resolve use `appEnv()` instead of WorkHub `appConfig`.
197
+ - OpenAPI title, server URLs, and generated SDK class name come from `APP_NAME` / `APP_URL` / `API_PREFIX` / `APP_SDK_CLASS` instead of importing the previous in-repo app `src/config/app`.
198
+ - `appEnv()`, `appUrl()`, `apiPrefix()`, and `sdkClientClassName()` live on `@getstrata/core/runtime/appKeyPrefix`. SIEM export, HSTS, and `safeFetch` DNS resolve use `appEnv()` instead of the previous in-repo app `appConfig`.
164
199
 
165
200
  ## 0.5.66
166
201
 
167
- - `createValidateSignatureMiddleware()` on `@getstrata/core/http/signedUrl` is Laravel’s `signed` / `ValidateSignature` middleware. Invalid or expired links throw `ForbiddenError`.
202
+ - `createValidateSignatureMiddleware()` on `@getstrata/core/http/signedUrl` is the previous PHP framework's `signed` / `ValidateSignature` middleware. Invalid or expired links throw `ForbiddenError`.
168
203
 
169
204
  ## 0.5.65
170
205
 
171
- - Identity helpers on `@getstrata/core/runtime/appKeyPrefix` (`smtpEhloHost`, `siemEventType`, `appUserAgent`, `otelServiceName`, `appDisplayName`, `webhookSignatureHeader`) so sibling apps are not stuck with WorkHub SMTP/SIEM/OTEL/OAuth names.
172
- - SIEM `event_type` and CEF vendor follow `SIEM_EVENT_TYPE` / `APP_NAME` (defaults stay `workhub.audit` / `WorkHub`).
206
+ - Identity helpers on `@getstrata/core/runtime/appKeyPrefix` (`smtpEhloHost`, `siemEventType`, `appUserAgent`, `otelServiceName`, `appDisplayName`, `webhookSignatureHeader`) so sibling apps are not stuck with the previous in-repo app SMTP/SIEM/OTEL/OAuth names.
207
+ - SIEM `event_type` and CEF vendor follow `SIEM_EVENT_TYPE` / `APP_NAME` (defaults stay `strata.audit` / `the previous in-repo app`).
173
208
 
174
209
  ## 0.5.64
175
210
 
176
- - `APP_KEY_PREFIX` (default `workhub`) namespaces Redis cache, queue, and throttle keys so sibling apps do not share WorkHub’s keyspace.
177
- - `DispatchWebhookJob` implementation lives in the WorkHub webhook module. `@getstrata/core/jobs/dispatchWebhookJob` remains a compatibility re-export.
211
+ - `APP_KEY_PREFIX` (default `strata`) namespaces Redis cache, queue, and throttle keys so sibling apps do not share the previous in-repo app's keyspace.
212
+ - `DispatchWebhookJob` implementation lives in the the previous in-repo app webhook module. `@getstrata/core/jobs/dispatchWebhookJob` remains a compatibility re-export.
178
213
 
179
214
  ## 0.5.63
180
215
 
181
- - Flash cookies honor `FLASH_COOKIE_NAME` (default `workhub_flash`) so sibling apps do not inherit WorkHub’s cookie name.
216
+ - Flash cookies honor `FLASH_COOKIE_NAME` (default `strata_flash`) so sibling apps do not inherit the previous in-repo app's cookie name.
182
217
 
183
218
  ## 0.5.62
184
219
 
185
- Laravel URL signing, Bun-native markdown mail, and session-auth cleanup.
220
+ the previous PHP framework URL signing, Bun-native markdown mail, and session-auth cleanup.
186
221
 
187
222
  - `temporarySignedUrl` / `signedUrl` / `hasValidSignature` / `assertValidSignature` on `@getstrata/core/http/signedUrl`. HMAC uses `SIGNED_URL_SECRET` or `SESSION_SECRET`. Paths must be same-origin (`/` only; reject `//` and `://`).
188
223
  - `markdownToHtml()` uses `Bun.markdown.html()` plus `sanitizeMailHtml` (allowlist). Scripts, `javascript:` links, and unknown tags are stripped.
189
224
  - `ExportAuditLogsJob` (`@getstrata/core/jobs/exportAuditLogsJob`) wraps SIEM export so the scheduler can dispatch a real job.
190
- - `DispatchWebhookJob` reads `APP_ENV` and `WEBHOOK_SIGNATURE_HEADER` instead of WorkHub `appConfig`.
225
+ - `DispatchWebhookJob` reads `APP_ENV` and `WEBHOOK_SIGNATURE_HEADER` instead of the previous in-repo app `appConfig`.
191
226
  - `createRequireWebAuthMiddleware` runs the handler inside `runWithAuthUser` so `currentAuthUser()` works on HTMX session routes.
192
227
  - `generateTotpSecret()` / `buildOtpauthUrl()` on `@getstrata/core/security/totp`.
193
228
  - `createRequireAbilityMiddleware` rethrows `ForbiddenError` for HTML views so HTMX routes render a styled 403 instead of JSON.
@@ -211,13 +246,13 @@ HTMX HTML kernel gaps that sibling apps could not work around without weakening
211
246
 
212
247
  ## 0.5.59
213
248
 
214
- Sibling HTMX apps can consume published packages without WorkHub-only glue.
249
+ Sibling HTMX apps can consume published packages without the previous in-repo app-only glue.
215
250
 
216
251
  - Emit `@getstrata/core/facades` types at `dist/core/facades/index.d.ts` (CI checks every `exports.*.types` path after build).
217
- - Session and CSRF cookie names are configurable (`SESSION_COOKIE_NAME`, `CSRF_COOKIE_NAME`). Defaults remain `workhub_session` and `workhub_csrf` for WorkHub.
252
+ - Session and CSRF cookie names are configurable (`SESSION_COOKIE_NAME`, `CSRF_COOKIE_NAME`). Defaults remain `strata_session` and `strata_csrf` for the previous in-repo app.
218
253
  - Split `CORE_ABILITY_CHECKER_TOKEN` and `CORE_AUTH_USER_DIRECTORY_TOKEN` from `CORE_TOKEN_SERVICE_TOKEN`. HttpKernel prefers the ability-checker token; HMAC `SessionGuard` / layout data prefer the user directory. A compatibility shim uses `CORE_TOKEN_SERVICE_TOKEN` only when the bound value matches the requested type.
219
- - `configureWebLayoutData` lets apps choose `currentUser` vs `authUser`, a custom user loader, and extra template fields. WorkHub still gets `{ authUser, csrfToken, flash }`.
254
+ - `configureWebLayoutData` lets apps choose `currentUser` vs `authUser`, a custom user loader, and extra template fields. the previous in-repo app still gets `{ authUser, csrfToken, flash }`.
220
255
  - `redirectResponse`, `notFoundHtmlResponse`, `textResponse`, and `xmlResponse` join `htmlResponse` / `isHtmxRequest` on `@getstrata/core/view`.
221
256
  - `LOGIN_RATE_LIMIT_WINDOW_MS` is a deprecated alias for `LOGIN_RATE_LIMIT_WINDOW_SECONDS`.
222
257
 
223
- HMAC `SessionGuard` is unchanged for WorkHub API/token apps. Sibling HTMX apps should use `@getstrata/bootstrap` `CookieSessionStore` + `createCookieSessionAuthManager`.
258
+ HMAC `SessionGuard` is unchanged for the previous in-repo app API/token apps. Sibling HTMX apps should use `@getstrata/bootstrap` `CookieSessionStore` + `createCookieSessionAuthManager`.
package/README.md CHANGED
@@ -2,73 +2,56 @@
2
2
 
3
3
  Stable **Strata** framework surface for application modules.
4
4
 
5
- **Source:** `src/framework/public-api.ts` (monorepo)
5
+ **Source:** `src/framework/public-api.ts` (monorepo)
6
6
  **Repository:** [EyK-26/strata](https://github.com/EyK-26/strata), directory `packages/strata-core`
7
7
 
8
- WorkHub is the reference application built on Strata; import the framework from this package in your own modules. Sibling HTMX apps (Eta, cookie sessions, no API tokens) should follow [docs/SIBLING-HTMX.md](../../docs/SIBLING-HTMX.md).
8
+ HiroApp is the example product. Import this package from your own modules. HTML cookie apps: [docs/BUILDING-APPS.md](../../docs/BUILDING-APPS.md). Auth choices: [docs/AUTH.md](../../docs/AUTH.md). SQL engines: [docs/DATABASE.md](../../docs/DATABASE.md).
9
9
 
10
10
  ## Usage
11
11
 
12
- Set `DATABASE_URL` before importing (connection is created lazily on first query):
12
+ Set `DATABASE_URL` before importing (the connection is created lazily on first query):
13
13
 
14
14
  ```typescript
15
15
  process.env.DATABASE_URL ??= "postgresql://postgres:postgres@localhost:5432/myapp";
16
16
 
17
- import { AdminResourceRegistry } from "@getstrata/core/admin/registry";
18
- import { formatAdminValue } from "@getstrata/core/admin/formatValue";
19
17
  import { Policy } from "@getstrata/core/auth/policy";
20
18
  import { BaseRepository } from "@getstrata/core/database/baseRepository";
21
- import { mail } from "@getstrata/core/facades";
22
19
  import { FormRequest } from "@getstrata/core/http/formRequest";
23
20
  import { withErrorHandling } from "@getstrata/core/http/response";
24
- import { mailer } from "@getstrata/core/mail/mailer";
25
- import { storage } from "@getstrata/core/facades";
26
21
  import { EtaViewEngine } from "@getstrata/core/view";
27
22
  ```
28
23
 
29
- `.eta` files are **HTML + Eta tags** (`<% %>`, `<%= %>`, `<%~ include() %>`), not Pug. Class/attribute shorthand such as `section.section` or `a href=` fails at render time with the template name.
24
+ `.eta` files are **HTML + Eta tags** (`<% %>`, `<%= %>`, `<%~ include() %>`), not another template language. Class/attribute shorthand such as `section.section` or `a href=` fails at render time with the template name.
30
25
 
31
- **Dependency:** `eta` is bundled as a direct dependency of `@getstrata/core`. Apps do not need to list it separately. The database driver is your app's choice. WorkHub and getstrata use **Bun's built-in `Bun.sql`** client; create and bind it with `createBunSqlPool()` / `bindBunSql()`, or call `bindDatabaseConnection()` yourself.
26
+ **Dependency:** `eta` is a direct dependency of `@getstrata/core`. Apps do not need to list it separately. The database **engine** is your choice. HiroApp uses **Bun's built-in `Bun.sql`** (Postgres). Create and bind it with `createBunSqlPool()` / `bindBunSql()`, or call `bindDatabaseConnection()` yourself. Extra engines register with `registerNamedConnection` (`database/namedConnections`, `database/sqliteConnection`, `database/mysqlConnection`).
32
27
 
33
- `orderBy` accepts explicit `{ column, direction }` objects or column shorthand such as `{ published_at: "desc" }`.
28
+ `orderBy` accepts `{ column, direction }` objects or column shorthand such as `{ published_at: "desc" }`. `{ ilike }` uses the value as-is. Pass `%term%` yourself.
34
29
 
35
30
  ## Admin and queue helpers
36
31
 
37
- Exports for admin dashboards and queue recovery:
38
-
39
32
  - `AdminResourceRegistry`, `formatAdminValue`: read-only resource browsers
40
33
  - `createFailedJobService`, `FailedJobService.delete()`: failed job persistence and cleanup
41
34
  - `runQueueJob`, `jobRegistry`: dispatch retried jobs from admin UIs
42
35
 
36
+ HiroApp uses failed-job recovery in the staff dashboard. You do not have to use the admin registry.
37
+
43
38
  ## Build and verify (monorepo root)
44
39
 
45
40
  ```bash
46
41
  bun run build:framework
47
- bun run verify:framework # build + public API tests
48
- bun run verify:shared-subpaths # after build: confirm singleton shims
42
+ bun run verify:framework
43
+ bun run verify:shared-subpaths
49
44
  ```
50
45
 
51
46
  ## Subpath imports
52
47
 
53
- `@getstrata/core` publishes **144+ subpaths** (for example `@getstrata/core/http/authMiddleware`,
54
- `@getstrata/core/database/migrations`). Prefer subpaths over the root import in apps, bootstrap, and tests.
48
+ `@getstrata/core` publishes many subpaths (for example `@getstrata/core/http/authMiddleware`, `@getstrata/core/database/migrations`). Prefer subpaths over the root import in apps, bootstrap, and tests.
55
49
 
56
- Some subpaths **re-export the main bundle** so singleton state stays shared (database pool binding,
57
- `AsyncLocalStorage` auth/tenant context, global registries, `HttpError` / `Notification` classes for
58
- `instanceof`). The canonical list lives in `scripts/core-shared-subpaths.ts` and is verified by
59
- `scripts/verify-core-shared-subpaths.ts` after each framework build.
50
+ Some subpaths **re-export the main bundle** so singleton state stays shared (database pool, dialect override, async-local auth/tenant, `HttpError` for `instanceof`). The list lives in `scripts/core-shared-subpaths.ts`.
51
+
52
+ When adding a subpath that owns process-wide state or base classes used with `instanceof`, append it to `CORE_SHARED_SUBPATHS`, run `bun scripts/sync-package-subpaths.ts`, and rebuild.
60
53
 
61
- When adding a subpath that owns process-wide state or base classes used with `instanceof`, append it to
62
- `CORE_SHARED_SUBPATHS`, run `bun scripts/sync-package-subpaths.ts`, and rebuild. Non-shared subpath
63
- bundles are built with generated `--external @getstrata/core/*` flags (all 144+ subpaths) so framework
64
- source can import shared modules via package self-imports (`scripts/codemod-core-self-imports.ts`).
65
- Bootstrap subpath builds externalize all `@getstrata/bootstrap/*` and `@getstrata/core/*` entries.
66
54
  `scripts/verify-no-root-imports.ts` blocks root `@getstrata/core` imports in application source.
67
- `scripts/verify-no-shared-barrel-imports.ts` blocks `@getstrata/core/database` and
68
- `@getstrata/core/http` barrel imports in application source.
69
- `scripts/audit-public-api-surface.ts` reports root exports with no in-repo root import usage.
70
- `scripts/verify-bundled-subpaths.ts` ensures entries like `http/webFormRequest` do not inline
71
- `ValidationError`.
72
55
 
73
56
  ```typescript
74
57
  import { createAuthMiddleware } from "@getstrata/core/http/authMiddleware";
@@ -82,9 +65,7 @@ import type { Migration } from "@getstrata/core/database/migrations/types";
82
65
  Package name: **`@getstrata/core`** (npm org [`@getstrata`](https://www.npmjs.com/org/getstrata)).
83
66
 
84
67
  1. Add `NPM_TOKEN` to GitHub repository secrets.
85
- 2. Tag a release: `git tag v0.5.96 && git push origin v0.5.96`
68
+ 2. Tag a release: `git tag v0.7.4 && git push origin v0.7.4`
86
69
  3. [Release workflow](../../.github/workflows/release.yml) builds and runs `npm publish --access public`.
87
70
 
88
- Previously published as `@eyk-workhub/framework@0.1.0`, deprecated in favor of this package.
89
-
90
- See [docs/PACKAGING.md](../../docs/PACKAGING.md) for boundaries and future extraction.
71
+ See [docs/PACKAGING.md](../../docs/PACKAGING.md).
@@ -1,5 +1,5 @@
1
- declare const MEMBER_ABILITIES: readonly ["organizations:read", "organizations:create", "projects:read", "projects:create", "tasks:read", "tasks:create", "comments:read", "comments:create", "attachments:read", "attachments:create", "auth:tokens:read", "auth:tokens:write", "auth:tokens:delete"];
2
- declare const ADMIN_ABILITIES: readonly ["organizations:read", "organizations:create", "projects:read", "projects:create", "tasks:read", "tasks:create", "comments:read", "comments:create", "attachments:read", "attachments:create", "auth:tokens:read", "auth:tokens:write", "auth:tokens:delete", "organizations:create", "organizations:update", "organizations:delete", "projects:update", "projects:delete", "tasks:update", "tasks:delete", "comments:update", "comments:delete", "attachments:delete", "webhooks:read", "webhooks:write", "audit:read"];
1
+ declare const MEMBER_ABILITIES: readonly ["profile:read", "auth:tokens:read", "auth:tokens:write", "auth:tokens:delete"];
2
+ declare const ADMIN_ABILITIES: readonly ["profile:read", "auth:tokens:read", "auth:tokens:write", "auth:tokens:delete", "webhooks:read", "webhooks:write", "audit:read", "audit:export"];
3
3
  declare const PLATFORM_ADMIN_ABILITIES: readonly ["*"];
4
4
  interface AbilityCatalog {
5
5
  member: readonly string[];
@@ -0,0 +1,9 @@
1
+ import type { ServiceContainerLike } from "../contracts/serviceContainer";
2
+ import type { AuthUser } from "./authContext";
3
+ import type { AuthGuard } from "./guard";
4
+ declare class BasicAuthGuard implements AuthGuard {
5
+ private readonly container;
6
+ constructor(container: ServiceContainerLike);
7
+ resolve(request: Request): Promise<AuthUser | null>;
8
+ }
9
+ export { BasicAuthGuard };
@@ -26,11 +26,17 @@ declare class CompositeGuard implements AuthGuard {
26
26
  }
27
27
  declare class AuthManager {
28
28
  private readonly guard;
29
+ private readonly namedGuards;
29
30
  constructor(guard: AuthGuard);
31
+ registerGuard(name: string, next: AuthGuard): this;
32
+ use(name?: string): AuthGuard;
33
+ guardNames(): string[];
30
34
  resolve(request?: Request): Promise<AuthUser | null>;
31
35
  user(request?: Request): Promise<AuthUser | null>;
32
36
  check(request?: Request): Promise<boolean>;
33
37
  requireUser(request?: Request): Promise<AuthUser>;
38
+ private authenticateRequest;
39
+ private tryNamedGuards;
34
40
  }
35
41
  export type { AuthGuard, AuthUser };
36
42
  export { ApiTokenGuard, AuthManager, CompositeGuard, DatabaseTokenGuard, GuestGuard };
@@ -0,0 +1,19 @@
1
+ interface JwtPayload {
2
+ sub: string | number;
3
+ role?: string;
4
+ abilities?: string[];
5
+ emailVerifiedAt?: Date | string | null;
6
+ iat?: number;
7
+ exp?: number;
8
+ [key: string]: unknown;
9
+ }
10
+ interface SignJwtOptions {
11
+ secret?: string;
12
+ ttlSeconds?: number;
13
+ }
14
+ declare function resolveJwtSecret(secret?: string): string;
15
+ declare function jwtTtlSeconds(override?: number): number;
16
+ declare function signJwt(payload: JwtPayload, options?: SignJwtOptions): string;
17
+ declare function verifyJwt(token: string, secret?: string): JwtPayload | null;
18
+ export type { JwtPayload, SignJwtOptions };
19
+ export { jwtTtlSeconds, resolveJwtSecret, signJwt, verifyJwt };
@@ -0,0 +1,14 @@
1
+ import type { AuthUser } from "./authContext";
2
+ import type { AuthGuard } from "./guard";
3
+ import { type JwtPayload } from "./jwt";
4
+ interface JwtGuardOptions {
5
+ secret?: string;
6
+ }
7
+ declare function authUserFromJwt(payload: JwtPayload): AuthUser;
8
+ declare class JwtGuard implements AuthGuard {
9
+ private readonly options;
10
+ constructor(options?: JwtGuardOptions);
11
+ resolve(request: Request): AuthUser | null;
12
+ }
13
+ export type { JwtGuardOptions };
14
+ export { authUserFromJwt, JwtGuard };
@@ -0,0 +1,5 @@
1
+ import type { AbilityChecker } from "./abilityChecker";
2
+ import type { AuthUser } from "./authContext";
3
+ declare function tokenCan(user: AuthUser | null, ability: string): boolean;
4
+ declare function createTokenAbilityChecker(): AbilityChecker;
5
+ export { createTokenAbilityChecker, tokenCan };
@@ -5,6 +5,12 @@ declare const CACHE_TAGS: {
5
5
  readonly comments: "comments";
6
6
  readonly attachments: "attachments";
7
7
  readonly reports: "reports";
8
+ readonly users: "users";
9
+ readonly departments: "departments";
10
+ readonly positions: "positions";
11
+ readonly applications: "applications";
12
+ readonly careers: "careers";
13
+ readonly offers: "offers";
8
14
  };
9
15
  type CacheTag = (typeof CACHE_TAGS)[keyof typeof CACHE_TAGS];
10
16
  export type { CacheTag };
@@ -10,5 +10,9 @@ interface AuthUserDirectory {
10
10
  resolveUserFromToken(token: string): Promise<AuthUser | null>;
11
11
  findByIdOrThrow(id: number): Promise<AuthUserRecord>;
12
12
  hasActiveBrowserSession?(userId: number, issuedAt: number): Promise<boolean>;
13
+ findByEmail?(email: string): Promise<(AuthUserRecord & {
14
+ password?: string | null;
15
+ }) | null>;
16
+ verifyCredentials?(email: string, password: string): Promise<AuthUser | null>;
13
17
  }
14
18
  export type { AuthUserDirectory, AuthUserRecord };
@@ -0,0 +1,18 @@
1
+ import { type DatabaseDriver } from "./schema/driver.ts";
2
+ interface SqlDialect {
3
+ readonly driver: DatabaseDriver;
4
+ placeholder(index: number): string;
5
+ quoteIdentifier(identifier: string): string;
6
+ nowExpression(): string;
7
+ returningClause(columns: string): string;
8
+ ilikeOperator(): "ILIKE" | "LIKE";
9
+ nullsLastSuffix(): string;
10
+ castToText(expression: string): string;
11
+ }
12
+ declare function dialectFor(driver: DatabaseDriver): SqlDialect;
13
+ declare function currentSqlDialect(): SqlDialect;
14
+ declare function useSqlDialect(driver: DatabaseDriver): SqlDialect;
15
+ declare function resetSqlDialect(): void;
16
+ declare function runWithSqlDialect<T>(driver: DatabaseDriver, callback: () => T | Promise<T>): T | Promise<T>;
17
+ export type { SqlDialect };
18
+ export { currentSqlDialect, dialectFor, resetSqlDialect, runWithSqlDialect, useSqlDialect };
@@ -44,6 +44,7 @@ declare class Factory<TRecord extends object, Counted extends boolean = false> {
44
44
  create(overrides?: Partial<TRecord>): Promise<FactoryMakeResult<TRecord, Counted>>;
45
45
  protected makeOne(overrides?: Partial<TRecord>): TRecord;
46
46
  protected createOne(overrides?: Partial<TRecord>): Promise<TRecord>;
47
+ protected persistCreated(record: TRecord): Promise<TRecord>;
47
48
  protected insertable(record: TRecord): Partial<TRecord>;
48
49
  protected persist(values: Partial<TRecord>): Promise<TRecord>;
49
50
  }
@@ -1,17 +1,25 @@
1
1
  export type { DatabaseConnection } from "./baseRepository.ts";
2
2
  export { default as BaseRepository } from "./baseRepository.ts";
3
3
  export { createDatabaseConnection } from "./connection.ts";
4
+ export type { ActiveDatabaseHandle } from "./connectionContext.ts";
5
+ export { getActiveDatabaseConnection, hasActiveDatabaseConnection, runWithDatabaseConnection, } from "./connectionContext.ts";
6
+ export type { SqlDialect } from "./dialect.ts";
7
+ export { currentSqlDialect, dialectFor, resetSqlDialect, runWithSqlDialect, useSqlDialect, } from "./dialect.ts";
4
8
  export { mapDatabaseError, withDatabaseErrorHandling } from "./errors.ts";
5
9
  export { Factory } from "./factory.ts";
6
10
  export { foreignKeyFromTable, pivotTableName, singularize } from "./inflection.ts";
7
11
  export type { CastType, GlobalScopeFn, ModelConstructor } from "./model.ts";
8
12
  export { applyCasts, BelongsToManyRelationQuery, BelongsToRelationQuery, dehydrateValue, filterMassAssignable, HasManyRelationQuery, HasManyThroughRelationQuery, HasOneRelationQuery, hydrateValue, Model, ModelQuery, MorphManyRelationQuery, MorphOneRelationQuery, MorphToRelationQuery, registerModelClass, registerModelRepository, } from "./model.ts";
13
+ export { createMysqlConnection, createMysqlConnectionFromPool } from "./mysqlConnection.ts";
14
+ export type { NamedConnectionEntry } from "./namedConnections.ts";
15
+ export { getNamedConnection, hasNamedConnection, registerNamedConnection, resetNamedConnections, runOnNamedConnection, unregisterNamedConnection, } from "./namedConnections.ts";
9
16
  export { buildAdvancedWhereClause, buildCountQuery, buildDeleteByIdQuery, buildGroupedCountQuery, buildInsertQuery, buildJoinClause, buildOrderByClause, buildProjectionQuery, buildQueryWhereClause, buildRestoreByIdQuery, buildSelectQuery, buildSoftDeleteByIdQuery, buildUpdateQuery, buildWhereClause, parseQualifiedColumn, qualifyColumn, quoteIdentifier, resolveQualifiedColumn, resolveSoftDeleteColumn, } from "./query.ts";
10
17
  export type { BelongsToManyRelation, BelongsToRelation, HasManyRelation, HasManyThroughRelation, HasOneRelation, MorphManyRelation, MorphOneRelation, MorphToRelation, } from "./relationships.ts";
11
18
  export { belongsTo, belongsToMany, hasMany, hasManyThrough, hasOne, indexBelongsToManyRelation, indexBelongsToRelation, indexHasManyRelation, indexHasManyThroughRelation, indexHasOneRelation, indexMorphManyRelation, indexMorphOneRelation, indexMorphToRelation, morphMany, morphOne, morphTo, } from "./relationships.ts";
12
19
  export { RepositoryQuery } from "./repositoryQuery.ts";
13
20
  export type { BlueprintAction, BlueprintCallback, ColumnKind, DatabaseDriver, ForeignKeyOptions, Grammar, IndexDefinition, IndexKind, ResolveDatabaseDriverOptions, SchemaBuilder, } from "./schema/index.ts";
14
21
  export { Blueprint, ColumnDefinition, compileBlueprint, createSchemaBuilder, ForeignIdColumnDefinition, grammarForDriver, inferReferencedTable, MySqlGrammar, PostgresGrammar, resolveDatabaseDriver, Schema, SqliteGrammar, UnsupportedSchemaFeatureError, } from "./schema/index.ts";
22
+ export { createSqliteConnection } from "./sqliteConnection.ts";
15
23
  export type { TableDefinition } from "./table.ts";
16
24
  export { defineTable } from "./table.ts";
17
25
  export { runInTransaction } from "./transaction.ts";
@@ -0,0 +1,12 @@
1
+ import type { ActiveDatabaseHandle } from "./connectionContext.ts";
2
+ type MysqlExecutable = {
3
+ execute: (sql: string, params?: unknown[]) => Promise<[unknown, unknown]>;
4
+ end?: () => Promise<void>;
5
+ };
6
+ type MysqlConnection = ActiveDatabaseHandle & {
7
+ close(): Promise<void>;
8
+ };
9
+ declare function createMysqlConnectionFromPool(pool: MysqlExecutable): MysqlConnection;
10
+ declare function createMysqlConnection(url: string): MysqlConnection;
11
+ export type { MysqlConnection, MysqlExecutable };
12
+ export { createMysqlConnection, createMysqlConnectionFromPool };
@@ -0,0 +1,15 @@
1
+ import { type ActiveDatabaseHandle } from "./connectionContext.ts";
2
+ import type { DatabaseDriver } from "./schema/driver.ts";
3
+ type NamedConnectionEntry = {
4
+ name: string;
5
+ driver: DatabaseDriver;
6
+ connection: ActiveDatabaseHandle;
7
+ };
8
+ declare function registerNamedConnection(name: string, driver: DatabaseDriver, connection: ActiveDatabaseHandle): void;
9
+ declare function unregisterNamedConnection(name: string): boolean;
10
+ declare function hasNamedConnection(name: string): boolean;
11
+ declare function getNamedConnection(name: string): NamedConnectionEntry;
12
+ declare function resetNamedConnections(): void;
13
+ declare function runOnNamedConnection<T>(name: string, callback: () => T | Promise<T>): T | Promise<T>;
14
+ export type { NamedConnectionEntry };
15
+ export { getNamedConnection, hasNamedConnection, registerNamedConnection, resetNamedConnections, runOnNamedConnection, unregisterNamedConnection, };
@@ -45,5 +45,6 @@ declare class RepositoryQuery<TEntity extends object, PrimaryKey extends keyof T
45
45
  private buildOptions;
46
46
  private addJoin;
47
47
  private attach;
48
+ private hydrateEagerLoad;
48
49
  }
49
50
  export { RepositoryQuery };
@@ -0,0 +1,7 @@
1
+ import type { ActiveDatabaseHandle } from "./connectionContext.ts";
2
+ type SqliteConnection = ActiveDatabaseHandle & {
3
+ close(): void;
4
+ };
5
+ declare function createSqliteConnection(filename: string): SqliteConnection;
6
+ export type { SqliteConnection };
7
+ export { createSqliteConnection };
@@ -1,11 +1,14 @@
1
1
  import type { Middleware } from "./middleware";
2
2
  interface LoginThrottleOptions {
3
- redisUrl: string;
3
+ redisUrl?: string;
4
4
  maxAttempts: number;
5
5
  decaySeconds: number;
6
6
  keyPrefix?: string;
7
7
  }
8
8
  declare function resolveLoginIdentity(request: Request): string;
9
+ declare function resolveLoginEmail(request: Request): Promise<string>;
10
+ declare function createMemoryLoginThrottleMiddleware(options: LoginThrottleOptions): Middleware;
9
11
  declare function createLoginThrottleMiddleware(options: LoginThrottleOptions): Middleware;
12
+ declare function resetMemoryLoginThrottleForTests(): void;
10
13
  export type { LoginThrottleOptions };
11
- export { createLoginThrottleMiddleware, resolveLoginIdentity };
14
+ export { createLoginThrottleMiddleware, createMemoryLoginThrottleMiddleware, resetMemoryLoginThrottleForTests, resolveLoginEmail, resolveLoginIdentity, };
@@ -1,7 +1,7 @@
1
1
  declare function serializeDate(value: Date | string): string;
2
2
  declare function whenLoaded<T>(model: {
3
3
  loaded: (name: string) => unknown;
4
- }, relation: string, transform?: (value: unknown) => T): T | undefined;
4
+ }, relation: string, transform?: (value: unknown) => T): T | undefined | null;
5
5
  declare class JsonResource<T = unknown> {
6
6
  protected readonly resource: T;
7
7
  static wrap: string | null;
@@ -11,7 +11,7 @@ declare class JsonResource<T = unknown> {
11
11
  static collection<TResource>(items: readonly TResource[]): ResourceCollection<TResource>;
12
12
  additional(data: Record<string, unknown>): this;
13
13
  when<TValue>(condition: boolean, value: TValue): TValue | undefined;
14
- whenLoaded<TValue = unknown>(relation: string, transform?: (value: unknown) => TValue): TValue | undefined;
14
+ whenLoaded<TValue = unknown>(relation: string, transform?: (value: unknown) => TValue): TValue | undefined | null;
15
15
  toArray(): Record<string, unknown>;
16
16
  toResponse(): Record<string, unknown>;
17
17
  }
@@ -3,4 +3,5 @@ declare function createdResponse(data: unknown, init?: ResponseInit): Response;
3
3
  declare function noContentResponse(): Response;
4
4
  declare function errorResponse(error: unknown): Response;
5
5
  declare function withErrorHandling<TArgs extends unknown[]>(handler: (...args: TArgs) => Response | Promise<Response>): (...args: TArgs) => Promise<Response>;
6
- export { createdResponse, errorResponse, jsonResponse, noContentResponse, withErrorHandling };
6
+ declare function withJsonErrorHandling<TArgs extends unknown[]>(handler: (...args: TArgs) => Response | Promise<Response>): (...args: TArgs) => Promise<Response>;
7
+ export { createdResponse, errorResponse, jsonResponse, noContentResponse, withErrorHandling, withJsonErrorHandling, };
@@ -0,0 +1,8 @@
1
+ declare function authorizationScheme(request: Request): string;
2
+ declare function requestUsesHeaderCredentials(request: Request): boolean;
3
+ declare function readBearerToken(request: Request): string | null;
4
+ declare function readBasicCredentials(request: Request): {
5
+ username: string;
6
+ password: string;
7
+ } | null;
8
+ export { authorizationScheme, readBasicCredentials, readBearerToken, requestUsesHeaderCredentials };
@@ -0,0 +1,2 @@
1
+ declare function tooManyRequestsResponse(request: Request, message: string, decaySeconds: number): Promise<Response>;
2
+ export { tooManyRequestsResponse };