@getstrata/core 0.5.101 → 0.7.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +63 -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 +839 -252
- package/package.json +56 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,36 @@
|
|
|
1
1
|
# @getstrata/core changelog
|
|
2
2
|
|
|
3
|
+
## 0.7.3
|
|
4
|
+
|
|
5
|
+
- `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.
|
|
6
|
+
|
|
7
|
+
## 0.7.2
|
|
8
|
+
|
|
9
|
+
- `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.
|
|
10
|
+
|
|
11
|
+
## 0.7.1
|
|
12
|
+
|
|
13
|
+
- `readSpaPrefix` / `normalizeSpaPrefix` own `SPA_PREFIX` (default `/app`). Apps set the env value. They do not copy a second static-file server.
|
|
14
|
+
- The log mail driver records `htmlBytes` instead of dumping the HTML document onto stdout.
|
|
15
|
+
|
|
16
|
+
## 0.7.0
|
|
17
|
+
|
|
18
|
+
- `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`.
|
|
19
|
+
- `parseFrontendMode`, `FRONTEND_MODES`, and `FRONTEND_MODE_PATTERN` are the allowed-value list. Apps should reuse that pattern in env schemas.
|
|
20
|
+
- Named database connections: `registerNamedConnection`, `runOnNamedConnection`, SQLite (`bun:sqlite`), and MySQL (`mysql2`). `runWithSqlDialect` keeps the dialect across `await` via AsyncLocalStorage.
|
|
21
|
+
- New subpaths: `database/namedConnections`, `database/sqliteConnection`, `database/mysqlConnection`, `database/connectionContext`.
|
|
22
|
+
- OpenAPI treats `POST /api/apply/login` as unauthenticated.
|
|
23
|
+
|
|
24
|
+
## 0.6.0
|
|
25
|
+
|
|
26
|
+
- **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.
|
|
27
|
+
- **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.
|
|
28
|
+
- 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.
|
|
29
|
+
- OpenAPI treats HiroApp login, JWT mint (`POST /api/auth/token`), and public careers as unauthenticated. Partner ping and audit export require credentials.
|
|
30
|
+
- 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.
|
|
31
|
+
- HiroApp is the only in-repo example product. The leftover `src/db` schema is a test fixture, not a second app.
|
|
32
|
+
- New subpaths: `auth/jwt`, `auth/jwtGuard`, `auth/basicAuthGuard`, `auth/tokenAbilityChecker`, `database/dialect`, `http/statelessAuth`.
|
|
33
|
+
|
|
3
34
|
## 0.5.101
|
|
4
35
|
|
|
5
36
|
- 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 +47,12 @@ Still non-conforming (honest): Bun cannot infer `morphTo()` method names. `hashe
|
|
|
16
47
|
|
|
17
48
|
## 0.5.99
|
|
18
49
|
|
|
19
|
-
HiroApp dogfood of 0.5.98 found lookalike APIs. This release matches
|
|
50
|
+
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
51
|
|
|
21
52
|
- Relation queries are thenable: `await user.applications()` delegates to `get()`.
|
|
22
53
|
- `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
54
|
- `belongsTo.where()` threads constraints into `whereHas` EXISTS (HiroApp application search).
|
|
24
|
-
- `{ ilike }` uses the value as-is (
|
|
55
|
+
- `{ ilike }` uses the value as-is (the previous PHP framework). Pass `%term%` yourself; the operator no longer wraps extra `%`.
|
|
25
56
|
- 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
57
|
- `primaryKey()` defaults to the table PK (`id`).
|
|
27
58
|
- Nested `load("a.b")` / `with("a.b")` skip already-loaded heads and batch the next level.
|
|
@@ -41,7 +72,7 @@ Still non-conforming (honest): Bun cannot infer `morphTo()` method names (`debug
|
|
|
41
72
|
- `Model.where()`, `firstOrNew()`, `firstOrCreate()`, and `updateOrCreate()`.
|
|
42
73
|
- Factory `count`/`state`/`sequence`/`for`/`has`/`recycle` plus `afterMaking`/`afterCreating`.
|
|
43
74
|
- `JsonResource` (`wrap`, `whenLoaded`, `additional`, `collection`).
|
|
44
|
-
-
|
|
75
|
+
- the previous PHP framework aliases: container `make`/`instance`, EventBus `on`/`emit`, query `whereNull`/`whereIn`/`whereExists`.
|
|
45
76
|
- Parity audit reports design score separately. Horizon/Nova/CLI stay Bun-native stand-ins.
|
|
46
77
|
|
|
47
78
|
## 0.5.97
|
|
@@ -59,10 +90,10 @@ Still non-conforming (honest): Bun cannot infer `morphTo()` method names (`debug
|
|
|
59
90
|
|
|
60
91
|
## 0.5.90
|
|
61
92
|
|
|
62
|
-
- **Breaking identity defaults:** `appKeyPrefix()` is `strata` and `appDisplayName()` is `Strata` when `APP_KEY_PREFIX` / `APP_NAME` are unset (were `
|
|
93
|
+
- **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
94
|
- `Schedule.command()` rejects cron strings other than `* * * * *` and `*/N * * * *` instead of silently never running them.
|
|
64
95
|
- OpenAPI marks `GET /users/me/*` as bearer-authenticated.
|
|
65
|
-
- OpenAPI `/users/me/current-organization` summaries no longer say
|
|
96
|
+
- OpenAPI `/users/me/current-organization` summaries no longer say team invitations.
|
|
66
97
|
|
|
67
98
|
## 0.5.89
|
|
68
99
|
|
|
@@ -70,16 +101,16 @@ Still non-conforming (honest): Bun cannot infer `morphTo()` method names (`debug
|
|
|
70
101
|
|
|
71
102
|
## 0.5.88
|
|
72
103
|
|
|
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
|
|
104
|
+
- 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.
|
|
105
|
+
- `@getstrata/core/jobs/dispatchWebhookJob` is a deprecated compatibility re-export of the the previous in-repo app webhook job.
|
|
75
106
|
|
|
76
107
|
## 0.5.87
|
|
77
108
|
|
|
78
|
-
- `AuthUserDirectory.hasActiveBrowserSession?(userId, issuedAt)` is optional. `SessionGuard` calls it after `session_valid_after` and rejects the HMAC cookie when it returns false so
|
|
109
|
+
- `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
110
|
|
|
80
111
|
## 0.5.86
|
|
81
112
|
|
|
82
|
-
- `createSessionCookieDetails()` returns the HMAC session header plus `issuedAt` / `ttlSeconds` so apps can persist
|
|
113
|
+
- `createSessionCookieDetails()` returns the HMAC session header plus `issuedAt` / `ttlSeconds` so apps can persist team invitations browser-session rows without changing the cookie format.
|
|
83
114
|
|
|
84
115
|
## 0.5.85
|
|
85
116
|
|
|
@@ -91,24 +122,24 @@ Still non-conforming (honest): Bun cannot infer `morphTo()` method names (`debug
|
|
|
91
122
|
|
|
92
123
|
## 0.5.83
|
|
93
124
|
|
|
94
|
-
- `MEMBER_ABILITIES` includes `auth:tokens:delete` so
|
|
125
|
+
- `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
126
|
- `buildOtpauthUrl()` defaults the issuer through `appDisplayName()` (`APP_NAME`).
|
|
96
127
|
|
|
97
128
|
## 0.5.82
|
|
98
129
|
|
|
99
|
-
- `MEMBER_ABILITIES` includes `organizations:create` so
|
|
130
|
+
- `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
131
|
|
|
101
132
|
## 0.5.81
|
|
102
133
|
|
|
103
|
-
- `@getstrata/core/auth/intendedUrlCookie` (`createIntendedUrlCookie`, `readIntendedUrl`, `clearIntendedUrlCookie`, `createIntendedUrlCookieFromRequest`).
|
|
134
|
+
- `@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
135
|
|
|
105
136
|
## 0.5.80
|
|
106
137
|
|
|
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` (
|
|
138
|
+
- `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
139
|
|
|
109
140
|
## 0.5.79
|
|
110
141
|
|
|
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` (
|
|
142
|
+
- `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
143
|
|
|
113
144
|
## 0.5.78
|
|
114
145
|
|
|
@@ -116,7 +147,7 @@ Still non-conforming (honest): Bun cannot infer `morphTo()` method names (`debug
|
|
|
116
147
|
|
|
117
148
|
## 0.5.77
|
|
118
149
|
|
|
119
|
-
- `@getstrata/core/security/recoveryCodes` (`generateRecoveryCodes`, `hashRecoveryCode`, `recoveryCodeMatches`).
|
|
150
|
+
- `@getstrata/core/security/recoveryCodes` (`generateRecoveryCodes`, `hashRecoveryCode`, `recoveryCodeMatches`). HTML auth-style one-time MFA backup codes (`abcd-efgh`).
|
|
120
151
|
|
|
121
152
|
## 0.5.76
|
|
122
153
|
|
|
@@ -124,12 +155,12 @@ Still non-conforming (honest): Bun cannot infer `morphTo()` method names (`debug
|
|
|
124
155
|
|
|
125
156
|
## 0.5.75
|
|
126
157
|
|
|
127
|
-
-
|
|
158
|
+
- 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
159
|
|
|
129
160
|
## 0.5.74
|
|
130
161
|
|
|
131
162
|
- `AuthUser.emailVerifiedAt` and `@getstrata/core/auth/emailVerification` (`isEmailVerificationRequired`, `hasVerifiedEmail`). `null` means unverified; missing is treated as verified (GuestGuard / legacy).
|
|
132
|
-
- `createRequireVerifiedMiddleware()` is
|
|
163
|
+
- `createRequireVerifiedMiddleware()` is the previous PHP framework `verified` (HTML 302 `/email/verify`, JSON 403).
|
|
133
164
|
|
|
134
165
|
## 0.5.73
|
|
135
166
|
|
|
@@ -154,40 +185,40 @@ Still non-conforming (honest): Bun cannot infer `morphTo()` method names (`debug
|
|
|
154
185
|
|
|
155
186
|
## 0.5.68
|
|
156
187
|
|
|
157
|
-
- Published core no longer imports
|
|
188
|
+
- 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
189
|
- `@getstrata/core/runtime/frontendMode` exports `readFrontendMode` / `isViewsEnabled` / `isSpaEnabled`.
|
|
159
190
|
|
|
160
191
|
## 0.5.67
|
|
161
192
|
|
|
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
|
|
193
|
+
- 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`.
|
|
194
|
+
- `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
195
|
|
|
165
196
|
## 0.5.66
|
|
166
197
|
|
|
167
|
-
- `createValidateSignatureMiddleware()` on `@getstrata/core/http/signedUrl` is
|
|
198
|
+
- `createValidateSignatureMiddleware()` on `@getstrata/core/http/signedUrl` is the previous PHP framework's `signed` / `ValidateSignature` middleware. Invalid or expired links throw `ForbiddenError`.
|
|
168
199
|
|
|
169
200
|
## 0.5.65
|
|
170
201
|
|
|
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 `
|
|
202
|
+
- 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.
|
|
203
|
+
- SIEM `event_type` and CEF vendor follow `SIEM_EVENT_TYPE` / `APP_NAME` (defaults stay `strata.audit` / `the previous in-repo app`).
|
|
173
204
|
|
|
174
205
|
## 0.5.64
|
|
175
206
|
|
|
176
|
-
- `APP_KEY_PREFIX` (default `
|
|
177
|
-
- `DispatchWebhookJob` implementation lives in the
|
|
207
|
+
- `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.
|
|
208
|
+
- `DispatchWebhookJob` implementation lives in the the previous in-repo app webhook module. `@getstrata/core/jobs/dispatchWebhookJob` remains a compatibility re-export.
|
|
178
209
|
|
|
179
210
|
## 0.5.63
|
|
180
211
|
|
|
181
|
-
- Flash cookies honor `FLASH_COOKIE_NAME` (default `
|
|
212
|
+
- Flash cookies honor `FLASH_COOKIE_NAME` (default `strata_flash`) so sibling apps do not inherit the previous in-repo app's cookie name.
|
|
182
213
|
|
|
183
214
|
## 0.5.62
|
|
184
215
|
|
|
185
|
-
|
|
216
|
+
the previous PHP framework URL signing, Bun-native markdown mail, and session-auth cleanup.
|
|
186
217
|
|
|
187
218
|
- `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
219
|
- `markdownToHtml()` uses `Bun.markdown.html()` plus `sanitizeMailHtml` (allowlist). Scripts, `javascript:` links, and unknown tags are stripped.
|
|
189
220
|
- `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
|
|
221
|
+
- `DispatchWebhookJob` reads `APP_ENV` and `WEBHOOK_SIGNATURE_HEADER` instead of the previous in-repo app `appConfig`.
|
|
191
222
|
- `createRequireWebAuthMiddleware` runs the handler inside `runWithAuthUser` so `currentAuthUser()` works on HTMX session routes.
|
|
192
223
|
- `generateTotpSecret()` / `buildOtpauthUrl()` on `@getstrata/core/security/totp`.
|
|
193
224
|
- `createRequireAbilityMiddleware` rethrows `ForbiddenError` for HTML views so HTMX routes render a styled 403 instead of JSON.
|
|
@@ -211,13 +242,13 @@ HTMX HTML kernel gaps that sibling apps could not work around without weakening
|
|
|
211
242
|
|
|
212
243
|
## 0.5.59
|
|
213
244
|
|
|
214
|
-
Sibling HTMX apps can consume published packages without
|
|
245
|
+
Sibling HTMX apps can consume published packages without the previous in-repo app-only glue.
|
|
215
246
|
|
|
216
247
|
- 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 `
|
|
248
|
+
- 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
249
|
- 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.
|
|
250
|
+
- `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
251
|
- `redirectResponse`, `notFoundHtmlResponse`, `textResponse`, and `xmlResponse` join `htmlResponse` / `isHtmxRequest` on `@getstrata/core/view`.
|
|
221
252
|
- `LOGIN_RATE_LIMIT_WINDOW_MS` is a deprecated alias for `LOGIN_RATE_LIMIT_WINDOW_SECONDS`.
|
|
222
253
|
|
|
223
|
-
HMAC `SessionGuard` is unchanged for
|
|
254
|
+
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.3 && git push origin v0.7.3`
|
|
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 };
|
|
@@ -1,6 +1,14 @@
|
|
|
1
|
-
|
|
1
|
+
declare const FRONTEND_MODES: readonly ["api", "server-htmx", "spa-react", "hybrid"];
|
|
2
|
+
declare const DEFAULT_SPA_PREFIX = "/app";
|
|
3
|
+
type FrontendMode = (typeof FRONTEND_MODES)[number];
|
|
4
|
+
declare const FRONTEND_MODE_PATTERN: RegExp;
|
|
5
|
+
declare function parseFrontendMode(value: string | undefined): FrontendMode;
|
|
2
6
|
declare function readFrontendMode(): FrontendMode;
|
|
7
|
+
declare function isViewsMode(mode: FrontendMode): boolean;
|
|
8
|
+
declare function isSpaMode(mode: FrontendMode): boolean;
|
|
3
9
|
declare function isViewsEnabled(): boolean;
|
|
4
10
|
declare function isSpaEnabled(): boolean;
|
|
11
|
+
declare function normalizeSpaPrefix(value: string | undefined): string;
|
|
12
|
+
declare function readSpaPrefix(): string;
|
|
5
13
|
export type { FrontendMode };
|
|
6
|
-
export { isSpaEnabled, isViewsEnabled, readFrontendMode };
|
|
14
|
+
export { DEFAULT_SPA_PREFIX, FRONTEND_MODE_PATTERN, FRONTEND_MODES, isSpaEnabled, isSpaMode, isViewsEnabled, isViewsMode, normalizeSpaPrefix, parseFrontendMode, readFrontendMode, readSpaPrefix, };
|