@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.
- package/CHANGELOG.md +67 -32
- package/README.md +16 -35
- package/dist/core/auth/abilityCatalog.d.ts +2 -2
- package/dist/core/auth/basicAuthGuard.d.ts +9 -0
- package/dist/core/auth/guard.d.ts +6 -0
- package/dist/core/auth/jwt.d.ts +19 -0
- package/dist/core/auth/jwtGuard.d.ts +14 -0
- package/dist/core/auth/tokenAbilityChecker.d.ts +5 -0
- package/dist/core/cache/tags.d.ts +6 -0
- package/dist/core/contracts/authUserDirectory.d.ts +4 -0
- package/dist/core/database/dialect.d.ts +18 -0
- package/dist/core/database/factory.d.ts +1 -0
- package/dist/core/database/index.d.ts +8 -0
- package/dist/core/database/mysqlConnection.d.ts +12 -0
- package/dist/core/database/namedConnections.d.ts +15 -0
- package/dist/core/database/repositoryQuery.d.ts +1 -0
- package/dist/core/database/sqliteConnection.d.ts +7 -0
- package/dist/core/http/loginThrottleMiddleware.d.ts +5 -2
- package/dist/core/http/resources.d.ts +2 -2
- package/dist/core/http/response.d.ts +2 -1
- package/dist/core/http/statelessAuth.d.ts +8 -0
- package/dist/core/http/throttleResponse.d.ts +2 -0
- package/dist/core/runtime/frontendMode.d.ts +10 -2
- package/dist/entries/auth/basicAuthGuard.js +137 -0
- package/dist/entries/auth/jwt.js +135 -0
- package/dist/entries/auth/jwtGuard.js +203 -0
- package/dist/entries/auth/sessionGuard.js +3 -21
- package/dist/entries/auth/tokenAbilityChecker.js +24 -0
- package/dist/entries/cache/tags.js +7 -1
- package/dist/entries/database/connectionContext.js +1 -0
- package/dist/entries/database/dialect.js +1 -0
- package/dist/entries/database/factory.js +5 -4
- package/dist/entries/database/model.js +49 -32
- package/dist/entries/database/mysqlConnection.js +35 -0
- package/dist/entries/database/namedConnections.js +1 -0
- package/dist/entries/database/query.js +28 -15
- package/dist/entries/database/relationships.js +14 -6
- package/dist/entries/database/repositoryQuery.js +96 -81
- package/dist/entries/database/schema.js +28 -15
- package/dist/entries/database/sqliteConnection.js +34 -0
- package/dist/entries/facades.js +1 -1
- package/dist/entries/http/contentNegotiation.js +5 -2
- package/dist/entries/http/csrfMiddleware.js +45 -0
- package/dist/entries/http/loginThrottleMiddleware.js +246 -7
- package/dist/entries/http/memoryThrottleMiddleware.js +208 -6
- package/dist/entries/http/requireAbilityMiddleware.js +35 -11
- package/dist/entries/http/requirePasswordConfirmMiddleware.js +5 -2
- package/dist/entries/http/requireVerifiedMiddleware.js +5 -2
- package/dist/entries/http/requireWebAuthMiddleware.js +12 -3
- package/dist/entries/http/resources.js +4 -1
- package/dist/entries/http/response.js +46 -12
- package/dist/entries/http/statelessAuth.js +48 -0
- package/dist/entries/http/throttleMiddleware.js +208 -6
- package/dist/entries/http/webErrorResponse.js +35 -11
- package/dist/entries/http/webFormRequest.js +5 -2
- package/dist/entries/mail/mailer.js +1 -1
- package/dist/entries/openapi/generator.js +26 -3
- package/dist/entries/runtime/frontendMode.js +39 -10
- package/dist/framework/public-api.d.ts +11 -1
- package/dist/index.js +873 -270
- 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
|
|
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 (
|
|
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
|
-
-
|
|
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 `
|
|
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
|
|
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 `
|
|
74
|
-
- `@getstrata/core/jobs/dispatchWebhookJob` is a deprecated compatibility re-export of the
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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`).
|
|
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` (
|
|
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` (
|
|
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`).
|
|
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
|
-
-
|
|
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
|
|
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
|
|
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
|
|
163
|
-
- `appEnv()`, `appUrl()`, `apiPrefix()`, and `sdkClientClassName()` live on `@getstrata/core/runtime/appKeyPrefix`. SIEM export, HSTS, and `safeFetch` DNS resolve use `appEnv()` instead of
|
|
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
|
|
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
|
|
172
|
-
- SIEM `event_type` and CEF vendor follow `SIEM_EVENT_TYPE` / `APP_NAME` (defaults stay `
|
|
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 `
|
|
177
|
-
- `DispatchWebhookJob` implementation lives in the
|
|
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 `
|
|
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
|
-
|
|
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
|
|
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
|
|
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 `
|
|
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.
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
48
|
-
bun run verify:shared-subpaths
|
|
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
|
|
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
|
|
57
|
-
|
|
58
|
-
`instanceof
|
|
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.
|
|
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
|
-
|
|
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 ["
|
|
2
|
-
declare const ADMIN_ABILITIES: readonly ["
|
|
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, };
|
|
@@ -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
|
|
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
|
-
|
|
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 };
|