@stratal/testing 0.0.27 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/CHANGELOG.md +562 -0
  2. package/README.md +137 -36
  3. package/dist/database/index.d.mts +2 -2
  4. package/dist/database/index.mjs +2 -2
  5. package/dist/database-Rojs69r3.mjs +453 -0
  6. package/dist/database-Rojs69r3.mjs.map +1 -0
  7. package/dist/{decorate-B7nr7eBl.mjs → decorate-RQD1h28J.mjs} +1 -1
  8. package/dist/feature-flags/index.mjs +1 -1
  9. package/dist/{feature-flags-BiLhfSGh.mjs → feature-flags-CZ1a4M2g.mjs} +2 -2
  10. package/dist/{feature-flags-BiLhfSGh.mjs.map → feature-flags-CZ1a4M2g.mjs.map} +1 -1
  11. package/dist/index-B8Mw1Dxk.d.mts +175 -0
  12. package/dist/index-B8Mw1Dxk.d.mts.map +1 -0
  13. package/dist/{index-CrHzUDKX.d.mts → index-D7FM6EKp.d.mts} +21 -3
  14. package/dist/index-D7FM6EKp.d.mts.map +1 -0
  15. package/dist/index-qgWNJRdC.d.mts.map +1 -1
  16. package/dist/index.d.mts +105 -46
  17. package/dist/index.d.mts.map +1 -1
  18. package/dist/index.mjs +218 -108
  19. package/dist/index.mjs.map +1 -1
  20. package/dist/mocks/cloudflare-workers.d.mts +24 -0
  21. package/dist/mocks/cloudflare-workers.d.mts.map +1 -0
  22. package/dist/mocks/cloudflare-workers.mjs +28 -0
  23. package/dist/mocks/cloudflare-workers.mjs.map +1 -0
  24. package/dist/mocks/index.d.mts +2 -2
  25. package/dist/mocks/index.mjs +2 -2
  26. package/dist/mocks/noop-rate-limiter-store.d.mts +1 -3
  27. package/dist/mocks/noop-rate-limiter-store.d.mts.map +1 -1
  28. package/dist/mocks/zenstack-language.d.mts +26 -29
  29. package/dist/mocks/zenstack-language.d.mts.map +1 -1
  30. package/dist/mocks/zenstack-language.mjs +1 -1
  31. package/dist/mocks/zenstack-language.mjs.map +1 -1
  32. package/dist/storage/index.d.mts +1 -1
  33. package/dist/storage/index.mjs +1 -1
  34. package/dist/{storage-DhoxWqyF.mjs → storage-BiGamMA8.mjs} +73 -6
  35. package/dist/storage-BiGamMA8.mjs.map +1 -0
  36. package/dist/test-worker-exports-dCRARYEc.d.mts +144 -0
  37. package/dist/test-worker-exports-dCRARYEc.d.mts.map +1 -0
  38. package/dist/test-workers-cache-D02Pt_dE.mjs +183 -0
  39. package/dist/test-workers-cache-D02Pt_dE.mjs.map +1 -0
  40. package/dist/vitest-plugin/index.d.mts +14 -28
  41. package/dist/vitest-plugin/index.d.mts.map +1 -1
  42. package/dist/vitest-plugin/index.mjs +32 -20
  43. package/dist/vitest-plugin/index.mjs.map +1 -1
  44. package/package.json +30 -21
  45. package/dist/database-B02eYKhE.mjs +0 -334
  46. package/dist/database-B02eYKhE.mjs.map +0 -1
  47. package/dist/index-BIr5nLof.d.mts +0 -122
  48. package/dist/index-BIr5nLof.d.mts.map +0 -1
  49. package/dist/index-CrHzUDKX.d.mts.map +0 -1
  50. package/dist/storage-DhoxWqyF.mjs.map +0 -1
  51. package/dist/test-email-provider-B7cjj97-.d.mts +0 -21
  52. package/dist/test-email-provider-B7cjj97-.d.mts.map +0 -1
  53. package/dist/test-email-provider-Dr-nhE0x.mjs +0 -34
  54. package/dist/test-email-provider-Dr-nhE0x.mjs.map +0 -1
package/CHANGELOG.md ADDED
@@ -0,0 +1,562 @@
1
+ # @stratal/testing
2
+
3
+ ## 0.1.0
4
+
5
+ ### Minor Changes
6
+
7
+ - a753e55: Give each test file its own leased database, drain deferred work before a test finishes, and supply the cache and gateway bindings the runtime never populates.
8
+
9
+ ### Database isolation
10
+ - Give every test **file** its own database, leased from a fixed pool of worker slots rather than created per file. Each file takes the lowest free slot, `<base>_w_<slot>`, and gets a fresh clone of the migrated template in it; the slot frees when the pool disposes the file's isolate. A run therefore holds at most as many databases as it runs files at once, so a long suite no longer piles up one database per file until Postgres runs out of disk mid-run.
11
+ - Per-file isolation is deliberate: the Workers test pool isolates storage per file and can run a worker's files concurrently, so any database shared across files corrupts under CI latency. Within a file, tests reset state through `truncateDb` or the reset engine.
12
+ - `createTestDatabaseGlobalSetup` accepts a one-time `prepare` hook to bake expensive baseline state — seed data, a default tenant schema — into the template once, so every file's database inherits it through the clone instead of rebuilding it per test.
13
+ - `createTestDatabaseGlobalSetup` now returns a teardown, so a run reclaims what it created instead of leaving the leftovers for the next run's setup to find. Consumers pass it to `globalSetup` exactly as before and need no change. The sweep is connection-guarded and skips a slot that is currently leased, so a database cloned but not yet connected to is never dropped by a concurrent process.
14
+ - `truncateDb(name?, opts?)` accepts a `ResetOptions` preserve-list; migration tables matching `_prisma%` are always preserved.
15
+ - Default database-isolation projects to a 30 second hook timeout, since cloning a template under a full worker slot routinely exceeds Vitest's 10 second default and fails with "Hook timed out in 10000ms". This is a floor, not a ceiling: an explicit `hookTimeout`, `fileParallelism` or `isolate` on the consuming project is now respected instead of being overwritten.
16
+ - Share one database pool per connection in the harness and tear it down exactly once. The harness runs against a direct Postgres with no Hyperdrive to multiplex, so a fresh pool per resolution accumulated until parallel files exhausted the server's connection limit with "sorry, too many clients already". Disposing a connection no longer logs "Called end on pool more than once".
17
+
18
+ ### Bindings and lifecycle
19
+ - Supply the `ctx.cache` binding so cache-decorated routes are testable with no configuration. Neither Miniflare nor workerd populates it, so without this a single `@Cacheable` or `@PurgesCache` route would fail an app's entire suite on the first request. `Test.createTestingModule()` installs a stub by default: `@Cacheable` routes return real `Cache-Control` and `Cache-Tag` headers, and purges succeed, recording each `PurgeSpec` in call order on `module.cache.purges`. Pass `cache: false` to opt back into the unconfigured runtime.
20
+ - Supply a `ctx.exports` stub by default so adopting the response-cache gateway does not break existing suites. Assert forwarded requests and their resolved partitions through `module.gateway.loopbacks`. The stub answers to any export name, so a passing suite is not what proves your configured entrypoint is correct — the type check against your Worker's exports is.
21
+ - Drain work a request defers through `ctx.waitUntil` before `fetch()` resolves, mirroring the Workers runtime. A non-blocking listener's deferred database write previously stayed in flight past the response and could still be running at the next request or at teardown, where disposing that resource hung the suite past the hook timeout.
22
+ - Drain deferred work in `close()` before tearing the app down. `fetch()` already drained per call, but the websocket, SSE and Quarry helpers share the same queue, so a suite using only those could reach teardown with writes still in flight and race the connection pool's disposal.
23
+
24
+ ### Testing surface
25
+ - `Test.createTestingModule()` accepts `trailingSlash` and `versioning` and passes both to the `Application` it builds, taking the same shapes as on the `Stratal` constructor. A testing module never runs the app's entry file, so an app configuring either there previously had it in production only — its suite asserted URL shapes that configuration would never emit. Both stay unset by default.
26
+ - Support `head()`, `list()` and `deleteMany()` in fake storage, so the new storage methods are exercisable without R2. `list()` returns **one object per page** unless a `limit` is passed, so a caller that ignores `cursor` fails in tests instead of undercounting against a real bucket, and `contentType` and `metadata` are omitted unless `includeMetadata: true`, matching what R2 returns.
27
+ - Stop `module.inertia` sending a hard-coded `X-Inertia-Version`. It sent `'1'`, so any app configuring a real asset version had every request read as a stale client and answered with a 409 — an entire Inertia suite failing on a value the tests never chose. A test that wants the mismatch path can ask for it with `module.inertia.withHeaders({ 'X-Inertia-Version': 'stale' })`.
28
+ - Fix chunked uploads to the fake storage service failing with `ReadableStream is disturbed` when the body is a single-use stream, which is the shape a chunked upload delivers.
29
+ - Keep `stratalTest()` typed against a single Vite instance. Vitest and `@stratal/inertia` resolved two different copies, which surfaced as a `Plugin` that would not assign to `Plugin`, an "excessive stack depth" comparison, and a missing `test` key on `UserConfig`.
30
+
31
+ ### Breaking Changes
32
+ - **There is now a single database isolation model.** The `shared` and `database` isolation toggle is gone, along with the `isolation` option on both `stratalTest({ database })` and `createTestDatabaseGlobalSetup`. Pass `stratalTest({ database: {} })` to enable isolation and delete any `isolation:` option.
33
+ - **`stratalTest({ database })` now requires `isolate: true`** and throws on `isolate: false`.
34
+ - **`createTestDatabaseGlobalSetup` now requires `schema`.** Add it if you were relying on the previous default.
35
+ - **`@cloudflare/vitest-pool-workers` is now `@cloudflare/vitest-plugin`.** Update the dependency, any direct import of it, and the `types` entry in your test `tsconfig.json`. `npx @cloudflare/codemods vitest:pool-workers-to-vitest-plugin` does all three. A config that only calls `stratalTest()` needs no change beyond the dependency. `stratalTest()` and its options are unchanged, and the integration supports Vitest 4.1 and later.
36
+
37
+ ### Patch Changes
38
+
39
+ - Updated dependencies [a753e55]
40
+ - Updated dependencies [a753e55]
41
+ - stratal@0.1.0
42
+ - @stratal/framework@0.1.0
43
+
44
+ ## 0.0.27
45
+
46
+ ### Patch Changes
47
+
48
+ - Updated dependencies [41a9140]
49
+ - stratal@0.0.27
50
+ - @stratal/framework@0.0.27
51
+
52
+ ## 0.0.26
53
+
54
+ ### Patch Changes
55
+
56
+ - ab95f52: Safer-by-default test harness: rate limiting off, in-memory email, eager routing
57
+
58
+ ### Details
59
+ - Rate limiting is now disabled by default (`NoopRateLimiterStore`) — suites fire many requests from one "IP" in seconds and tripped production limiter budgets (including Better Auth's built-in per-path limits). Suites testing limiter behavior must override `RATE_LIMITER_TOKENS.Store` back to a real store (e.g. `InMemoryRateLimiterStore`)
60
+ - A `TestEmailProvider` is installed by default so the sync queue provider's inline `EmailConsumer` no longer opens real SMTP connections from the test worker; assert on sent messages via `module.sentEmails`
61
+ - Routing is initialized eagerly during `compile()` — configuration errors (e.g. mixing `@Route()` with HTTP method decorators) now surface as a `compile()` rejection instead of on the first request, and request-scoped router services resolve regardless of test ordering
62
+ - `compile()` now tears down the partially built `Application` when it fails, so module-held resources (DB pools, timers) don't leak from a failed build
63
+
64
+ - Updated dependencies [ab95f52]
65
+ - Updated dependencies [ab95f52]
66
+ - Updated dependencies [bb6d3b9]
67
+ - stratal@0.0.26
68
+ - @stratal/framework@0.0.26
69
+
70
+ ## 0.0.25
71
+
72
+ ### Patch Changes
73
+
74
+ - Updated dependencies [e93db60]
75
+ - Updated dependencies [e93db60]
76
+ - stratal@0.0.25
77
+ - @stratal/framework@0.0.25
78
+
79
+ ## 0.0.24
80
+
81
+ ### Patch Changes
82
+
83
+ - stratal@0.0.24
84
+ - @stratal/framework@0.0.24
85
+
86
+ ## 0.0.23
87
+
88
+ ### Patch Changes
89
+
90
+ - 13b0e8d: Auto-apply an in-memory `FakeFeatureFlagService` in tests (like the fake storage service). Feature-gated code now resolves without a real Cloudflare Flagship binding — no provider override needed. Configure flags via `module.featureFlags.set(key, value)` and import the fake from `@stratal/testing/feature-flags` for direct use.
91
+ - 13b0e8d: Add opt-in database isolation for parallel test execution
92
+
93
+ Run test files in parallel against PostgreSQL without lock or data collisions: each file gets its own database cloned from a migrated template and dropped on teardown.
94
+ - Enable per-file isolation by passing `database: { isolation: 'database' }` to the Vitest plugin (and optionally `binding` to target a specific Hyperdrive binding, defaulting to `DB`).
95
+ - New `@stratal/testing/database` entry point exposing helpers to wire up the template-database lifecycle in a Vitest `globalSetup`.
96
+ - The migrated template is **reused across runs**: `createTestDatabaseGlobalSetup` fingerprints the `schema` source(s) + the `migrate` routine and stores it as the template's database COMMENT, so `migrate` runs only on the first run after a schema change (or against a fresh database) — subsequent runs clone the existing template directly. `schema` (a file or directory path, or a list) is now **required** in `database` mode. Reuse is purely fingerprint-driven — there is no force/skip flag.
97
+ - Isolation is opt-in — existing tests are unaffected. `pg` is an optional peer dependency, required only when isolation is enabled.
98
+
99
+ - 13b0e8d: Fix correctness and security issues found in review.
100
+
101
+ Queue:
102
+ - Retry the correct binding: dispatch stamps the producer binding into message metadata and failed jobs record it, so `queue:retry` re-enqueues through the Cloudflare binding instead of the queue name (which is not a valid binding key and broke retry whenever the two differed). A message with no binding metadata is logged and acked rather than stored as an unretryable job.
103
+ - Honor the documented retry budget: `maxRetries` now counts retries correctly against Cloudflare's 1-based `message.attempts` (previously gave one fewer retry than configured).
104
+ - Derive idempotency keys from an order-stable serialization of `type` + `payload`, so payloads that differ only in key order dedupe correctly.
105
+ - `queue:retry --all` / `queue:purge --all --queue` collect matching keys before deleting, so cursor pagination no longer skips jobs; `queue:failed --queue --limit` now counts matching jobs rather than scanned keys.
106
+ - Documented that delivery is at-least-once with best-effort de-duplication (not exactly-once), since the processed marker is written only after a handler succeeds and KV is eventually consistent — handlers must be idempotent.
107
+
108
+ Email (SMTP):
109
+ - Upgrade STARTTLS onto the socket `startTls()` returns: the original socket is closed by the runtime, so the post-upgrade reader/writer are re-derived from the new secure socket and any pre-handshake bytes are discarded (fixes a broken `smtp://` STARTTLS path on real Workers and closes the STARTTLS plaintext-injection vector).
110
+ - Refuse to send credentials over an unencrypted connection: an `smtp://` server that doesn't offer STARTTLS now fails loudly instead of leaking the password (blocks STARTTLS-stripping downgrades). Credential-free connections (e.g. local Mailpit) are unaffected.
111
+ - AUTH is gated on the server's advertised mechanisms and supports both `PLAIN` and `LOGIN`; usernames are percent-decoded like passwords.
112
+ - Add a response timeout so a hung SMTP server can't wedge the worker; QUIT/socket close are now best-effort and never mask a successful send.
113
+ - MIME builder strips CR/LF from headers, escapes/RFC 2231-encodes attachment filenames (prevents header injection), base64-encodes message bodies (fixes long-line corruption), and rejects envelope addresses containing whitespace or angle brackets (prevents `MAIL FROM`/`RCPT TO` desync).
114
+
115
+ Inertia SEO:
116
+ - `titleTemplate` substitutes every `%s` and treats `$`-sequences in the title literally.
117
+ - Inject head/body content via function replacements, so SEO/page content containing `$`-sequences (`$$`, `$&`, `` $` ``, `$'`) is no longer corrupted or able to splice a template placeholder back into the output.
118
+ - Drop unsafe attribute names — including inline event handlers (`on*`) — from custom `meta`/`link` entries (prevents tag breakout server-side, `setAttribute` errors during client head-sync, and developer-supplied event-handler attributes).
119
+
120
+ Feature flags:
121
+ - `FeatureFlagService.use()` binds the target app exactly once.
122
+
123
+ Database (framework):
124
+ - The reentrant `$transaction` proxy forwards the receiver for non-transaction property access.
125
+
126
+ Testing:
127
+ - `TestingModule.close()` drops the isolated per-file database even if shutdown throws; the stale-database sweep escapes LIKE metacharacters so a prefix containing `_` can't over-match.
128
+
129
+ DI:
130
+ - Construct singletons against the root container so they can never capture a request-scoped dependency (which would leak one request's state across every later request); an illegal singleton→request dependency now throws loudly.
131
+ - Detect circular dependencies and throw a clear error naming the cycle instead of overflowing the stack.
132
+ - `tryResolve` only swallows "no provider"; a registered provider that throws while constructing now surfaces the real error instead of injecting `undefined`.
133
+ - Request-cache invalidation tracks transitive constructor dependencies, so re-registering a value rebuilds cached services that depend on it through a transient intermediary.
134
+
135
+ Quarry dev runtime:
136
+ - Persist every durable plugin (KV, D1, R2, Durable Objects, cache) under `.wrangler/state/v3`, matching `wrangler dev` (previously only R2 was persisted); load `.env.local` / `.env.<env>.local` into `process.env` for full parity.
137
+ - The `cloudflare:sockets` STARTTLS shim re-attaches the stream error handler to the upgraded socket, so post-upgrade connection errors still surface.
138
+
139
+ - be813bc: Update bundled runtime dependencies to their latest patch releases (`@cloudflare/vitest-pool-workers`, MSW)
140
+ - Updated dependencies [13b0e8d]
141
+ - Updated dependencies [13b0e8d]
142
+ - Updated dependencies [13b0e8d]
143
+ - Updated dependencies [13b0e8d]
144
+ - Updated dependencies [13b0e8d]
145
+ - Updated dependencies [13b0e8d]
146
+ - Updated dependencies [13b0e8d]
147
+ - Updated dependencies [13b0e8d]
148
+ - Updated dependencies [13b0e8d]
149
+ - Updated dependencies [13b0e8d]
150
+ - Updated dependencies [13b0e8d]
151
+ - Updated dependencies [be813bc]
152
+ - stratal@0.0.23
153
+ - @stratal/framework@0.0.23
154
+
155
+ ## 0.0.22
156
+
157
+ ### Patch Changes
158
+
159
+ - 1658945: Add `fixNobleHashesCjs` Vitest plugin to resolve `@noble/hashes` CJS compatibility issues with `@zenstackhq/orm`
160
+ - 4b273ea: Update Vitest plugin tslib alias to use the direct tslib package instead of the tsyringe-bundled copy
161
+ - Updated dependencies [1658945]
162
+ - Updated dependencies [1658945]
163
+ - Updated dependencies [4b273ea]
164
+ - Updated dependencies [4b273ea]
165
+ - stratal@0.0.22
166
+ - @stratal/framework@0.0.22
167
+
168
+ ## 0.0.21
169
+
170
+ ### Patch Changes
171
+
172
+ - 3489cfd: Allow tests to install a custom `ExceptionHandler` via `TestingModuleConfig`
173
+
174
+ `TestingModuleBuilder` now accepts `exceptionHandler` on its config, mirroring `ApplicationConfig.exceptionHandler`. This is the only way to swap the handler in tests because the framework resolves it during `app.initialize()`, which runs before `overrideProvider(DI_TOKENS.ExceptionHandler)` can take effect.
175
+
176
+ - Updated dependencies [3489cfd]
177
+ - Updated dependencies [3489cfd]
178
+ - Updated dependencies [3489cfd]
179
+ - @stratal/framework@0.0.21
180
+ - stratal@0.0.21
181
+
182
+ ## 0.0.20
183
+
184
+ ### Patch Changes
185
+
186
+ - Updated dependencies [f8c61e1]
187
+ - Updated dependencies [f8c61e1]
188
+ - Updated dependencies [f8c61e1]
189
+ - Updated dependencies [f8c61e1]
190
+ - Updated dependencies [f8c61e1]
191
+ - Updated dependencies [f8c61e1]
192
+ - Updated dependencies [f8c61e1]
193
+ - Updated dependencies [f8c61e1]
194
+ - Updated dependencies [f8c61e1]
195
+ - @stratal/framework@0.0.20
196
+ - stratal@0.0.20
197
+
198
+ ## 0.0.19
199
+
200
+ ### Patch Changes
201
+
202
+ - 3b16f5b: Make `TestHttpClient` immutable and extend test classes with `Macroable`
203
+ - `TestHttpClient.forHost()`, `withHeaders()`, and `withLocale()` now return new instances instead of mutating `this`, preventing shared state between tests.
204
+ - `TestHttpRequest` and `TestResponse` now extend `Macroable`, allowing apps to register custom assertion methods and helpers at runtime.
205
+ - Add `TestingModule.inertia` getter for convenient Inertia request testing.
206
+
207
+ - Updated dependencies [3b16f5b]
208
+ - Updated dependencies [3b16f5b]
209
+ - Updated dependencies [3b16f5b]
210
+ - Updated dependencies [5d26c24]
211
+ - Updated dependencies [3b16f5b]
212
+ - Updated dependencies [3b16f5b]
213
+ - Updated dependencies [5d26c24]
214
+ - Updated dependencies [5d26c24]
215
+ - Updated dependencies [3b16f5b]
216
+ - @stratal/framework@0.0.19
217
+ - stratal@0.0.19
218
+
219
+ ## 0.0.18
220
+
221
+ ### Patch Changes
222
+
223
+ - c9176ea: Add locale support to test HTTP client, SSE, and WebSocket requests
224
+
225
+ ### Details
226
+ - Add `withLocale()` method to `TestHttpClient`, `TestHttpRequest`, `TestSseRequest`, and `TestWsRequest`
227
+ - Automatically resolves locale detection strategy from the module's I18n configuration
228
+ - Export `getValueAtPath` and `hasValueAtPath` path utility functions
229
+
230
+ - Updated dependencies [fcb71c4]
231
+ - Updated dependencies [c9176ea]
232
+ - Updated dependencies [17f8675]
233
+ - Updated dependencies [c9176ea]
234
+ - Updated dependencies [c9176ea]
235
+ - stratal@0.0.18
236
+ - @stratal/framework@0.0.18
237
+
238
+ ## 0.0.17
239
+
240
+ ### Patch Changes
241
+
242
+ - Updated dependencies [[`7f2772b`](https://github.com/strataljs/stratal/commit/7f2772ba90a9b6a91603f79293d384e972864125), [`6cccfef`](https://github.com/strataljs/stratal/commit/6cccfefdde703c5c6eaba199d05307ab9fe36085), [`79e05de`](https://github.com/strataljs/stratal/commit/79e05de7482c925323a2f37a00e47929133a979f), [`cbfce8b`](https://github.com/strataljs/stratal/commit/cbfce8b3a3517b60d94f500c5dc1ef68d8ee76f4), [`7f2772b`](https://github.com/strataljs/stratal/commit/7f2772ba90a9b6a91603f79293d384e972864125), [`3c89c14`](https://github.com/strataljs/stratal/commit/3c89c147fca366382c0771bb442f29a6fc73601e), [`916fd90`](https://github.com/strataljs/stratal/commit/916fd90727a06b5ce7c0397467fe9dc1f859f841), [`cbfce8b`](https://github.com/strataljs/stratal/commit/cbfce8b3a3517b60d94f500c5dc1ef68d8ee76f4)]:
243
+ - stratal@0.0.17
244
+ - @stratal/framework@0.0.17
245
+
246
+ ## 0.0.16
247
+
248
+ ### Patch Changes
249
+
250
+ - [#142](https://github.com/strataljs/stratal/pull/142) [`4b958e2`](https://github.com/strataljs/stratal/commit/4b958e250c99681a99a34a398fbf706546f556cc) Thanks [@adesege](https://github.com/adesege)! - Add dedicated `@stratal/testing/storage` sub-path export and add `reflect-metadata` as peer dependency
251
+
252
+ ### Details
253
+ - `FakeStorageService` and `StoredFile` are no longer exported from the main entry point — import from `@stratal/testing/storage` instead
254
+ - Add `reflect-metadata` as a peer dependency
255
+
256
+ - Updated dependencies [[`3dd0bc8`](https://github.com/strataljs/stratal/commit/3dd0bc84c8638db30db7b70f3532a44aa187ace8), [`4b958e2`](https://github.com/strataljs/stratal/commit/4b958e250c99681a99a34a398fbf706546f556cc), [`4b958e2`](https://github.com/strataljs/stratal/commit/4b958e250c99681a99a34a398fbf706546f556cc)]:
257
+ - stratal@0.0.16
258
+ - @stratal/framework@0.0.16
259
+
260
+ ## 0.0.15
261
+
262
+ ### Patch Changes
263
+
264
+ - [#125](https://github.com/strataljs/stratal/pull/125) [`0731e99`](https://github.com/strataljs/stratal/commit/0731e99c3e0c96f988387611f0ef8559b63d7bd8) Thanks [@adesege](https://github.com/adesege)! - Add test utilities for Quarry command framework
265
+
266
+ ### Details
267
+ - Add `TestCommandRequest` fluent builder for constructing command inputs in tests
268
+ - Add `TestCommandResult` assertion wrapper for command output, exit codes, and errors
269
+ - Add `quarry(name)` method to `TestingModule` for convenient command testing
270
+ - Export new utilities from `@stratal/testing` main entry point
271
+
272
+ - Updated dependencies [[`0731e99`](https://github.com/strataljs/stratal/commit/0731e99c3e0c96f988387611f0ef8559b63d7bd8), [`52f1daa`](https://github.com/strataljs/stratal/commit/52f1daa981f5a38b983bb3c14abfefb663eb6941)]:
273
+ - stratal@0.0.15
274
+ - @stratal/framework@0.0.15
275
+
276
+ ## 0.0.14
277
+
278
+ ### Patch Changes
279
+
280
+ - [#124](https://github.com/strataljs/stratal/pull/124) [`59251d3`](https://github.com/strataljs/stratal/commit/59251d32743cbd461f952985f192a68cb7ccdb91) Thanks [@adesege](https://github.com/adesege)! - Add `fixPgCjs()` Vite plugin for CJS resolution of pg sub-dependencies in workerd
281
+
282
+ ### Details
283
+ - Replace the `@cloudflare/vitest-pool-workers` yarn patch with a dedicated `fixPgCjs()` Vite plugin
284
+ - `fixPgCjs()` must be applied at the root `defineConfig` level for the module fallback resolver to work correctly
285
+ - `stratalTest()` does NOT automatically apply `fixPgCjs()` — it must be registered separately at the root level
286
+ - Upgrade `@cloudflare/vitest-pool-workers` to ^0.13.2 (unpinned)
287
+
288
+ - [#122](https://github.com/strataljs/stratal/pull/122) [`47530bd`](https://github.com/strataljs/stratal/commit/47530bd31bc91329788b4ba7b03a389f0e722f46) Thanks [@adesege](https://github.com/adesege)! - Migrate build system from tsc to tsdown for faster builds and code-splitting support
289
+
290
+ - Updated dependencies [[`59251d3`](https://github.com/strataljs/stratal/commit/59251d32743cbd461f952985f192a68cb7ccdb91), [`59251d3`](https://github.com/strataljs/stratal/commit/59251d32743cbd461f952985f192a68cb7ccdb91), [`47530bd`](https://github.com/strataljs/stratal/commit/47530bd31bc91329788b4ba7b03a389f0e722f46), [`47530bd`](https://github.com/strataljs/stratal/commit/47530bd31bc91329788b4ba7b03a389f0e722f46)]:
291
+ - stratal@0.0.14
292
+ - @stratal/framework@0.0.14
293
+
294
+ ## 0.0.13
295
+
296
+ ### Patch Changes
297
+
298
+ - [#120](https://github.com/strataljs/stratal/pull/120) [`8d0df50`](https://github.com/strataljs/stratal/commit/8d0df506411bc725ef4e4eaf4efdb314b3384d98) Thanks [@adesege](https://github.com/adesege)! - Add SSE testing utilities with `TestSseRequest` and `TestSseConnection`
299
+
300
+ ### Details
301
+ - `TestingModule.sse(path)` creates an SSE test request builder
302
+ - `TestSseRequest` supports custom headers, authentication via `actingAs()`, and automatic `Accept: text/event-stream` header
303
+ - `TestSseConnection` wraps a live SSE stream with assertion helpers: `assertEvent()`, `assertEventData()`, `assertJsonEventData()`, `waitForEvent()`, `waitForEnd()`, `collectEvents()`
304
+ - Replace dynamic `import('vitest')` with static imports in `TestWsConnection`, `TestWsRequest`, and `TestingModule`
305
+
306
+ - [#120](https://github.com/strataljs/stratal/pull/120) [`8d0df50`](https://github.com/strataljs/stratal/commit/8d0df506411bc725ef4e4eaf4efdb314b3384d98) Thanks [@adesege](https://github.com/adesege)! - Add WebSocket testing utilities with `TestWsRequest` and `TestWsConnection`
307
+
308
+ ### Details
309
+ - `TestingModule.ws(path)` creates a WebSocket test request builder
310
+ - `TestWsRequest` supports custom headers, authentication via `actingAs()`, and WebSocket upgrade handshake
311
+ - `TestWsConnection` wraps a live WebSocket with assertion helpers: `assertMessage()`, `assertClosed()`, `waitForMessage()`, `waitForClose()`
312
+
313
+ - Updated dependencies [[`8d0df50`](https://github.com/strataljs/stratal/commit/8d0df506411bc725ef4e4eaf4efdb314b3384d98), [`527f675`](https://github.com/strataljs/stratal/commit/527f675ea3b4cdb98165cbe1f81e820fa9e79490), [`bb99119`](https://github.com/strataljs/stratal/commit/bb991196dbcc55963d16ee1a6f5db580c18c796a), [`957de6e`](https://github.com/strataljs/stratal/commit/957de6e88684344bf26e95d03187345bf77f4f52), [`0ade941`](https://github.com/strataljs/stratal/commit/0ade94162f9058e9230039fa72efbbf3e57cf572)]:
314
+ - stratal@0.0.13
315
+ - @stratal/framework@0.0.13
316
+
317
+ ## 0.0.12
318
+
319
+ ### Patch Changes
320
+
321
+ - [#97](https://github.com/strataljs/stratal/pull/97) [`d58b878`](https://github.com/strataljs/stratal/commit/d58b8782848562a50b79cd558eaf01978aa77f26) Thanks [@adesege](https://github.com/adesege)! - Add `stratalTest()` vitest plugin and migrate fetch mocking from Cloudflare's undici-based `fetchMock` to MSW
322
+
323
+ ### Details
324
+ - **@stratal/testing**
325
+ - Add `@stratal/testing/vitest-plugin` sub-export with `stratalTest()` — wraps `cloudflareTest` with Stratal defaults (tslib alias, ZenStack mocks, SSR externals)
326
+ - Replace `FetchMock`/`createFetchMock` with `MockFetch`/`createMockFetch` backed by MSW (`setupServer`)
327
+ - Re-export `http` and `HttpResponse` from `msw` for convenience
328
+ - Update `cloudflare:test` imports to `cloudflare:workers`
329
+ - Bump vitest peer dependency from `^3.2.0` to `^4.1.0`
330
+
331
+ - **stratal**
332
+ - Update test mocks to use class syntax for Vitest 4 compatibility
333
+ - Bump dependencies: `@intlify/*`, `@scalar/hono-api-reference`, `hono`, `@aws-sdk/*`, `vitest`
334
+
335
+ - **@stratal/framework**
336
+ - Refactor vitest config to use `stratalTest()` plugin, removing manual pool/alias config
337
+ - Bump dependencies: `better-auth`, `@zenstackhq/*`, `wrangler`, `vitest`
338
+
339
+ ### Breaking Changes
340
+ - **@stratal/testing**: `FetchMock` and `createFetchMock` are removed. Use `MockFetch`/`createMockFetch` instead. The new API uses MSW lifecycle methods (`listen`/`reset`/`close`) instead of `activate`/`disableNetConnect`/`deactivate`.
341
+ - **@stratal/testing**: Vitest peer dependency is now `^4.1.0` (was `^3.2.0`).
342
+
343
+ - Updated dependencies [[`11b0da9`](https://github.com/strataljs/stratal/commit/11b0da97ef436bffef592fbc34685bbcc85d7ef7), [`e1a2ba2`](https://github.com/strataljs/stratal/commit/e1a2ba2da883481d192a15b8015456705982d683), [`d58b878`](https://github.com/strataljs/stratal/commit/d58b8782848562a50b79cd558eaf01978aa77f26)]:
344
+ - stratal@0.0.12
345
+ - @stratal/framework@0.0.12
346
+
347
+ ## 0.0.11
348
+
349
+ ### Patch Changes
350
+
351
+ - Updated dependencies [[`87581af`](https://github.com/strataljs/stratal/commit/87581af263eb74c059966650fbd5c1b849d36dfc), [`bae01ef`](https://github.com/strataljs/stratal/commit/bae01eff7cb7f520ad00206377d9f5f4968076b6)]:
352
+ - @stratal/framework@0.0.11
353
+ - stratal@0.0.11
354
+
355
+ ## 0.0.10
356
+
357
+ ### Patch Changes
358
+
359
+ - Updated dependencies [[`3329d20`](https://github.com/strataljs/stratal/commit/3329d20658ea6a6f7cadbbb3efb7630b1cca9ad2)]:
360
+ - stratal@0.0.10
361
+ - @stratal/framework@0.0.10
362
+
363
+ ## 0.0.9
364
+
365
+ ### Patch Changes
366
+
367
+ - Updated dependencies [[`c0d9313`](https://github.com/strataljs/stratal/commit/c0d9313b30272eece8a4596718b7d4c1b442c221)]:
368
+ - stratal@0.0.9
369
+ - @stratal/framework@0.0.9
370
+
371
+ ## 0.0.8
372
+
373
+ ### Patch Changes
374
+
375
+ - Updated dependencies [[`3b38b81`](https://github.com/strataljs/stratal/commit/3b38b8184428dc0f79ffbe9dc55ba782d46dea03)]:
376
+ - @stratal/framework@0.0.8
377
+ - stratal@0.0.8
378
+
379
+ ## 0.0.7
380
+
381
+ ### Patch Changes
382
+
383
+ - [#81](https://github.com/strataljs/stratal/pull/81) [`89e06b5`](https://github.com/strataljs/stratal/commit/89e06b57f8aca553f60cbefab8f931cf5554f1b3) Thanks [@adesege](https://github.com/adesege)! - Rearchitect core internals: replace AsyncLocalStorage-based request context with explicit container passing, and replace RouterService with HonoApp
384
+
385
+ ### Breaking Changes
386
+
387
+ **`stratal` (core)**
388
+ - **Removed `RequestContextStore`** — The `AsyncLocalStorage`-based request context propagation is eliminated. This removes the dependency on the `nodejs_als` compatibility flag in Cloudflare Workers.
389
+ - **Removed `RouterService` and `RequestScopeService`** — Replaced by `HonoApp`, a subclass of `OpenAPIHono` that directly integrates request scoping, middleware class support, and global error handling.
390
+ - **Removed `RouterAlreadyConfiguredError` and `RouterNotConfiguredError`** — Replaced by `HonoAppAlreadyConfiguredError`.
391
+ - **`Container` no longer accepts `env` or `ctx` in options** — These are now registered as values in the container by `Application` directly.
392
+ - **`runInRequestScope()` callback signature changed** — The callback now receives `(requestContainer: Container) => T | Promise<T>` instead of `() => T | Promise<T>`. Callers must use the passed container for resolution.
393
+ - **`Stratal` initialization changed from lazy to eager** — `Stratal` now eagerly bootstraps by dynamically importing `cloudflare:workers` for `env` and `waitUntil`, instead of lazily initializing on first request.
394
+ - **`queue()` and `scheduled()` no longer accept `env` and `ctx` parameters** — These are obtained from `cloudflare:workers` during eager init.
395
+ - **New `StratalExecutionContext` interface** — A minimal abstraction over Cloudflare's `ExecutionContext` with only `waitUntil()`.
396
+ - **New `HonoApp` class** — Extends `OpenAPIHono` with Stratal concerns; supports `Constructor<Middleware>` in `use()` via module augmentation.
397
+
398
+ **`@stratal/framework`**
399
+ - **`DatabaseConnectionConfig.dialect` changed from `Dialect` to `() => Dialect`** — Database connections now take a factory function for lazy dialect/pool creation.
400
+ - **Caching strategy changed from `instancePerContainerCachingFactory` to `instanceCachingFactory`**.
401
+
402
+ **`@stratal/testing`**
403
+ - **`TestingModule.runInRequestScope()` callback now receives a `container` parameter** — Update all callbacks to use the passed container for service resolution.
404
+ - **`TestingModule.fetch()` now routes through `HonoApp`** instead of `RouterService`.
405
+ - **`TestingModuleBuilder.compile()` now applies overrides before `initialize()`** — Fixes issue where overrides were applied after initialization.
406
+
407
+ ### Minor Changes
408
+
409
+ **`@stratal/seeders`**
410
+ - Updated `executeSeeder()` to use the explicit `requestContainer` parameter from `runInRequestScope()`.
411
+
412
+ - [#83](https://github.com/strataljs/stratal/pull/83) [`bcb3556`](https://github.com/strataljs/stratal/commit/bcb3556a6e1f185e088286f202c605c73799e63f) Thanks [@adesege](https://github.com/adesege)! - Introduce @stratal/zenstack-plugin and rearchitect database module to use shared schema with per-connection slicing
413
+
414
+ ### New Package
415
+
416
+ **`@stratal/zenstack-plugin`**
417
+ - ZenStack plugin for multi-connection database support with schema slicing
418
+ - Generates connection-specific schema types and `StratalDatabase` augmentation
419
+ - CLI commands: `stratal-db migrate` and `stratal-db push` for per-connection database management
420
+ - Plugin model (`plugin.zmodel`) for ZenStack integration
421
+
422
+ ### Breaking Changes
423
+
424
+ **`stratal` (core)**
425
+ - Re-exports `delay` from tsyringe via `stratal/di`
426
+
427
+ **`@stratal/framework`**
428
+ - **Replaced `DatabaseSchemaRegistry` and `DefaultDatabaseConnection` with unified `StratalDatabase` interface** — Consumers must update their type augmentations to use the new single interface with `schema`, `defaultConnection`, and `slicing` properties.
429
+ - **`schema` moved from `DatabaseConnectionConfig` to `DatabaseModuleConfig`** — All connections now share a single schema; per-connection schema is no longer supported.
430
+ - **Added `slicing` option to `DatabaseConnectionConfig`** — Connections can narrow available models via ZenStack slicing options.
431
+ - **Database services are now lazily created** — Dialect factories are not called during module initialization; services are instantiated on first resolve within a request scope.
432
+ - **Database services are now request-scoped** — Each request gets its own database client instance via tsyringe's `delay()` + `Scope.Request`.
433
+ - **`DatabaseEvents` type no longer parameterized by connection** — Event types (`ModelName`, `DatabaseEventName`, `GetData`, `GetResult`, etc.) derive from the shared schema instead of per-connection schemas.
434
+ - **Removed `InferConnectionSchema` type** — Replaced by `InferDatabaseSchema` (shared) and `InferConnectionSlicing` (per-connection slicing).
435
+
436
+ **`@stratal/testing`**
437
+ - **`TestingModule.getDb()` is now synchronous** — Returns `DatabaseService` directly instead of `Promise<DatabaseService>`.
438
+ - **`TestingModule` creates a single request-scoped container at construction** — `container` property now returns the request-scoped container. The `runInRequestScope` pattern is removed.
439
+ - **`TestingModule.close()` now disposes the request container** before shutting down the application.
440
+
441
+ - Updated dependencies [[`89e06b5`](https://github.com/strataljs/stratal/commit/89e06b57f8aca553f60cbefab8f931cf5554f1b3), [`bcb3556`](https://github.com/strataljs/stratal/commit/bcb3556a6e1f185e088286f202c605c73799e63f)]:
442
+ - stratal@0.0.7
443
+ - @stratal/framework@0.0.7
444
+
445
+ ## 0.0.6
446
+
447
+ ### Patch Changes
448
+
449
+ - Updated dependencies [[`6542f78`](https://github.com/strataljs/stratal/commit/6542f78fda2bf851df7ee5d88d6f7c7d04ea6388)]:
450
+ - stratal@0.0.6
451
+ - @stratal/framework@0.0.6
452
+
453
+ ## 0.0.5
454
+
455
+ ### Patch Changes
456
+
457
+ - [#66](https://github.com/strataljs/stratal/pull/66) [`c8ea964`](https://github.com/strataljs/stratal/commit/c8ea964e272b09ebc6619843e77d2b51178f9423) Thanks [@adesege](https://github.com/adesege)! - Add `actingAs` auth test helper, `TestHttpRequest` builder, ZenStack language mock, and enhanced `TestingModule` utilities with new exports and types.
458
+
459
+ - Updated dependencies [[`c8ea964`](https://github.com/strataljs/stratal/commit/c8ea964e272b09ebc6619843e77d2b51178f9423), [`c8ea964`](https://github.com/strataljs/stratal/commit/c8ea964e272b09ebc6619843e77d2b51178f9423)]:
460
+ - stratal@0.0.5
461
+ - @stratal/framework@0.0.5
462
+
463
+ ## 0.0.4
464
+
465
+ ### Patch Changes
466
+
467
+ - **Build cleanup** — Removed redundant polyfills export and cleaned up the build configuration.
468
+ - **Relaxed vitest version** — Loosened the vitest peer dependency version constraint.
469
+
470
+ - Updated dependencies []:
471
+ - stratal@0.0.4
472
+
473
+ ## 0.0.3
474
+
475
+ ### Patch Changes
476
+
477
+ - - **Build cleanup** — Removed redundant polyfills export and cleaned up the build configuration.
478
+ - **Relaxed vitest version** — Loosened the vitest peer dependency version constraint.
479
+ - Updated dependencies []:
480
+ - stratal@0.0.3
481
+
482
+ ## 0.0.2
483
+
484
+ ### Patch Changes
485
+
486
+ #### `stratal` (core)
487
+
488
+ ##### Breaking Changes
489
+
490
+ - **`withRoot`/`withRootAsync` renamed to `forRoot`/`forRootAsync`** — All dynamic module configuration methods have been renamed for consistency. Update every `SomeModule.withRoot(...)` call to `SomeModule.forRoot(...)` and `SomeModule.withRootAsync(...)` to `SomeModule.forRootAsync(...)`. ([`152913a`](https://github.com/strataljs/stratal/commit/152913a))
491
+
492
+ - **Barrel export removed — use sub-path imports** — The top-level `stratal` barrel export has been removed. Consumers must now import from sub-paths (`stratal/di`, `stratal/router`, `stratal/cache`, `stratal/validation`, etc.). ([`af073d8`](https://github.com/strataljs/stratal/commit/af073d8))
493
+
494
+ ##### Features
495
+
496
+ - **DOM polyfill for Cloudflare Workers** — Added a DOM polyfill to support AWS SDK v3 XML parsing in Cloudflare Workers environments. ([`f3b2cb9`](https://github.com/strataljs/stratal/commit/f3b2cb9))
497
+
498
+ - **Benchmark suite** — Added benchmark functionality for measuring framework performa30438`](https://github.com/strataljs/stratal/commit/7230438))
499
+
500
+ ##### Security
501
+
502
+ - **ConfigService blocks prototype pollution** — `ConfigService` now rejects dangerous keys (`__proto__`, `constructor`, `prototype`) to prevent prototype pollution attacks. ([`567139c`](https://github.com/strataljs/stratal/commit/567139c), [`e64b4e7`](https://github.com/strataljs/stratal/commit/e64b4e7))
503
+
504
+ ##### Bug Fixes
505
+
506
+ - **`reflect-metadata` import moved to vitest setup** — Removed unused `reflect-metadata` imports from example files and centralized the import in `vitest.setup.ts`. ([`f3b2cb9`](https://github.com/strataljs/stratal/commit/f3b2cb9))
507
+
508
+ ---
509
+
510
+ #### `@stratal/testing`
511
+
512
+ ##### Breaking Changes
513
+
514
+ - **Import paths updated** — Import paths updated to match the new core sub-path exports (e.g. `stratal/di` instead of the barrel `stratal`). ([`af073d8`](https://github.com/strataljs/stratal/commit/af073d8))
515
+
516
+ - Updated dependencies []:
517
+ - @stratal/testing@0.0.2
518
+
519
+ ## 0.0.1
520
+
521
+ ### Patch Changes
522
+
523
+ - Initial release of the Stratal framework — a modular Cloudflare Workers framework built on Hono and tsyringe.
524
+
525
+ **Core Infrastructure**
526
+ - NestJS-style module system with `@Module()` decorator, dynamic modules (`forRoot`, `forRootAsync`), and lifecycle hooks (`OnInitialize`, `OnShutdown`)
527
+ - Two-tier dependency injection container (global singletons + request-scoped) powered by tsyringe with conditional registration and service decoration
528
+ - `StratalWorker` entry point extending Cloudflare's `WorkerEntrypoint` for HTTP fetch, queue batches, and scheduled cron triggers
529
+
530
+ **Routing & API**
531
+ - Hono-based routing with `@Controller()` and `@Route()` decorators, automatic controller discovery, and route guards via `@UseGuards()`
532
+ - OpenAPI schema generation with `@hono/zod-openapi` and Scalar API reference integration
533
+ - NestJS-like middleware configuration with route-specific application and exclusion
534
+
535
+ **Background Processing**
536
+ - Queue consumerfor Cloudflare Queues with `@Consumer()` and `@QueueJob()` decorators and batch processing
537
+ - Cron job scheduling via `CronManager` integrated with Cloudflare's scheduled events
538
+
539
+ **Services & Integrations**
540
+ - Email module with pluggable providers (Nodemailer, Resend) and queue-based sending
541
+ - Storage module with AWS S3 / Cloudflare R2 support, multipart uploads, presigned URLs, and TUS resumable uploads
542
+ - Internationalization (i18n) module with locale detection, message compilation, and request-scoped translations
543
+ - Cache module with pluggable providers and Cloudflare KV integration
544
+ - Configuration module with `registerAs()` namespaces and Zod-based validation
545
+ - Structured logging with JSON and pretty formatters
546
+
547
+ **Developer Experience**
548
+ - Zod-powered request/response validation with type inference
549
+ - Custom `ApplicationError` class with HTTP status mapping
550
+ - ESM-only with full TypeScript decorator support (`emitDecoratorMetadata`)
551
+ - Sub-path exports for tree-shakeable imports (`stratal/di`, `stratal/router`, `stratal/cache`, etc.)
552
+
553
+ - `TestingModule` and `TestingModuleBuilder` for bootstrapping isolated module environments in tests
554
+ - `TestHttpClient` with request builder and response wrapper for integration testing
555
+ - `FetchMock` for mocking HTTP fetch calls
556
+ - `FakeStorageService` for in-memory storage testing without S3/R2
557
+ - `ProviderOverrideBuilder` for replacing providers with test doubles
558
+ - Nodemailer mock for email testing
559
+ - Test environment utilities via `getTestEnv()`
560
+
561
+ - Updated dependencies []:
562
+ - stratal@0.0.1