@stratal/testing 0.0.0-canary-ccb3f17 → 0.0.0-canary-e5681b8

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 (46) hide show
  1. package/CHANGELOG.md +603 -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-DeMI4Igi.mjs → database-Rojs69r3.mjs} +112 -60
  6. package/dist/database-Rojs69r3.mjs.map +1 -0
  7. package/dist/{decorate-ZDdbRmsv.mjs → decorate-RQD1h28J.mjs} +1 -1
  8. package/dist/feature-flags/index.mjs +1 -1
  9. package/dist/{feature-flags-BMYurC1B.mjs → feature-flags-CZ1a4M2g.mjs} +2 -2
  10. package/dist/{feature-flags-BMYurC1B.mjs.map → feature-flags-CZ1a4M2g.mjs.map} +1 -1
  11. package/dist/{index-DUScdrKC.d.mts → index-B8Mw1Dxk.d.mts} +46 -33
  12. package/dist/index-B8Mw1Dxk.d.mts.map +1 -0
  13. package/dist/{index-Dm6e2N61.d.mts → index-D7FM6EKp.d.mts} +21 -2
  14. package/dist/index-D7FM6EKp.d.mts.map +1 -0
  15. package/dist/index.d.mts +55 -28
  16. package/dist/index.d.mts.map +1 -1
  17. package/dist/index.mjs +67 -61
  18. package/dist/index.mjs.map +1 -1
  19. package/dist/mocks/cloudflare-workers.d.mts +6 -7
  20. package/dist/mocks/cloudflare-workers.d.mts.map +1 -1
  21. package/dist/mocks/index.d.mts +1 -1
  22. package/dist/mocks/index.mjs +1 -1
  23. package/dist/mocks/noop-rate-limiter-store.d.mts +1 -2
  24. package/dist/mocks/noop-rate-limiter-store.d.mts.map +1 -1
  25. package/dist/mocks/zenstack-language.d.mts +21 -21
  26. package/dist/mocks/zenstack-language.d.mts.map +1 -1
  27. package/dist/mocks/zenstack-language.mjs +1 -1
  28. package/dist/mocks/zenstack-language.mjs.map +1 -1
  29. package/dist/storage/index.d.mts +1 -1
  30. package/dist/storage/index.mjs +1 -1
  31. package/dist/{storage-q8RFahgU.mjs → storage-BiGamMA8.mjs} +70 -3
  32. package/dist/storage-BiGamMA8.mjs.map +1 -0
  33. package/dist/{test-worker-exports-DMct0Egv.d.mts → test-worker-exports-dCRARYEc.d.mts} +8 -7
  34. package/dist/test-worker-exports-dCRARYEc.d.mts.map +1 -0
  35. package/dist/{test-workers-cache-eiGMw9Yj.mjs → test-workers-cache-D02Pt_dE.mjs} +8 -7
  36. package/dist/{test-workers-cache-eiGMw9Yj.mjs.map → test-workers-cache-D02Pt_dE.mjs.map} +1 -1
  37. package/dist/vitest-plugin/index.d.mts +9 -9
  38. package/dist/vitest-plugin/index.d.mts.map +1 -1
  39. package/dist/vitest-plugin/index.mjs +22 -15
  40. package/dist/vitest-plugin/index.mjs.map +1 -1
  41. package/package.json +22 -19
  42. package/dist/database-DeMI4Igi.mjs.map +0 -1
  43. package/dist/index-DUScdrKC.d.mts.map +0 -1
  44. package/dist/index-Dm6e2N61.d.mts.map +0 -1
  45. package/dist/storage-q8RFahgU.mjs.map +0 -1
  46. package/dist/test-worker-exports-DMct0Egv.d.mts.map +0 -1
package/CHANGELOG.md ADDED
@@ -0,0 +1,603 @@
1
+ # @stratal/testing
2
+
3
+ ## 0.0.0-canary-e5681b8
4
+
5
+ ### Minor Changes
6
+
7
+ - e5681b8: 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 [e5681b8]
40
+ - Updated dependencies [e5681b8]
41
+ - stratal@0.0.0-canary-e5681b8
42
+ - @stratal/framework@0.0.0-canary-e5681b8
43
+
44
+ ## 0.1.0
45
+
46
+ ### Minor Changes
47
+
48
+ - 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.
49
+
50
+ ### Database isolation
51
+ - 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.
52
+ - 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.
53
+ - `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.
54
+ - `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.
55
+ - `truncateDb(name?, opts?)` accepts a `ResetOptions` preserve-list; migration tables matching `_prisma%` are always preserved.
56
+ - 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.
57
+ - 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".
58
+
59
+ ### Bindings and lifecycle
60
+ - 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.
61
+ - 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.
62
+ - 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.
63
+ - 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.
64
+
65
+ ### Testing surface
66
+ - `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.
67
+ - 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.
68
+ - 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' })`.
69
+ - 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.
70
+ - 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`.
71
+
72
+ ### Breaking Changes
73
+ - **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.
74
+ - **`stratalTest({ database })` now requires `isolate: true`** and throws on `isolate: false`.
75
+ - **`createTestDatabaseGlobalSetup` now requires `schema`.** Add it if you were relying on the previous default.
76
+ - **`@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.
77
+
78
+ ### Patch Changes
79
+
80
+ - Updated dependencies [a753e55]
81
+ - Updated dependencies [a753e55]
82
+ - stratal@0.1.0
83
+ - @stratal/framework@0.1.0
84
+
85
+ ## 0.0.27
86
+
87
+ ### Patch Changes
88
+
89
+ - Updated dependencies [41a9140]
90
+ - stratal@0.0.27
91
+ - @stratal/framework@0.0.27
92
+
93
+ ## 0.0.26
94
+
95
+ ### Patch Changes
96
+
97
+ - ab95f52: Safer-by-default test harness: rate limiting off, in-memory email, eager routing
98
+
99
+ ### Details
100
+ - 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`)
101
+ - 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`
102
+ - 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
103
+ - `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
104
+
105
+ - Updated dependencies [ab95f52]
106
+ - Updated dependencies [ab95f52]
107
+ - Updated dependencies [bb6d3b9]
108
+ - stratal@0.0.26
109
+ - @stratal/framework@0.0.26
110
+
111
+ ## 0.0.25
112
+
113
+ ### Patch Changes
114
+
115
+ - Updated dependencies [e93db60]
116
+ - Updated dependencies [e93db60]
117
+ - stratal@0.0.25
118
+ - @stratal/framework@0.0.25
119
+
120
+ ## 0.0.24
121
+
122
+ ### Patch Changes
123
+
124
+ - stratal@0.0.24
125
+ - @stratal/framework@0.0.24
126
+
127
+ ## 0.0.23
128
+
129
+ ### Patch Changes
130
+
131
+ - 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.
132
+ - 13b0e8d: Add opt-in database isolation for parallel test execution
133
+
134
+ 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.
135
+ - 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`).
136
+ - New `@stratal/testing/database` entry point exposing helpers to wire up the template-database lifecycle in a Vitest `globalSetup`.
137
+ - 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.
138
+ - Isolation is opt-in — existing tests are unaffected. `pg` is an optional peer dependency, required only when isolation is enabled.
139
+
140
+ - 13b0e8d: Fix correctness and security issues found in review.
141
+
142
+ Queue:
143
+ - 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.
144
+ - Honor the documented retry budget: `maxRetries` now counts retries correctly against Cloudflare's 1-based `message.attempts` (previously gave one fewer retry than configured).
145
+ - Derive idempotency keys from an order-stable serialization of `type` + `payload`, so payloads that differ only in key order dedupe correctly.
146
+ - `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.
147
+ - 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.
148
+
149
+ Email (SMTP):
150
+ - 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).
151
+ - 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.
152
+ - AUTH is gated on the server's advertised mechanisms and supports both `PLAIN` and `LOGIN`; usernames are percent-decoded like passwords.
153
+ - 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.
154
+ - 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).
155
+
156
+ Inertia SEO:
157
+ - `titleTemplate` substitutes every `%s` and treats `$`-sequences in the title literally.
158
+ - 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.
159
+ - 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).
160
+
161
+ Feature flags:
162
+ - `FeatureFlagService.use()` binds the target app exactly once.
163
+
164
+ Database (framework):
165
+ - The reentrant `$transaction` proxy forwards the receiver for non-transaction property access.
166
+
167
+ Testing:
168
+ - `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.
169
+
170
+ DI:
171
+ - 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.
172
+ - Detect circular dependencies and throw a clear error naming the cycle instead of overflowing the stack.
173
+ - `tryResolve` only swallows "no provider"; a registered provider that throws while constructing now surfaces the real error instead of injecting `undefined`.
174
+ - Request-cache invalidation tracks transitive constructor dependencies, so re-registering a value rebuilds cached services that depend on it through a transient intermediary.
175
+
176
+ Quarry dev runtime:
177
+ - 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.
178
+ - The `cloudflare:sockets` STARTTLS shim re-attaches the stream error handler to the upgraded socket, so post-upgrade connection errors still surface.
179
+
180
+ - be813bc: Update bundled runtime dependencies to their latest patch releases (`@cloudflare/vitest-pool-workers`, MSW)
181
+ - Updated dependencies [13b0e8d]
182
+ - Updated dependencies [13b0e8d]
183
+ - Updated dependencies [13b0e8d]
184
+ - Updated dependencies [13b0e8d]
185
+ - Updated dependencies [13b0e8d]
186
+ - Updated dependencies [13b0e8d]
187
+ - Updated dependencies [13b0e8d]
188
+ - Updated dependencies [13b0e8d]
189
+ - Updated dependencies [13b0e8d]
190
+ - Updated dependencies [13b0e8d]
191
+ - Updated dependencies [13b0e8d]
192
+ - Updated dependencies [be813bc]
193
+ - stratal@0.0.23
194
+ - @stratal/framework@0.0.23
195
+
196
+ ## 0.0.22
197
+
198
+ ### Patch Changes
199
+
200
+ - 1658945: Add `fixNobleHashesCjs` Vitest plugin to resolve `@noble/hashes` CJS compatibility issues with `@zenstackhq/orm`
201
+ - 4b273ea: Update Vitest plugin tslib alias to use the direct tslib package instead of the tsyringe-bundled copy
202
+ - Updated dependencies [1658945]
203
+ - Updated dependencies [1658945]
204
+ - Updated dependencies [4b273ea]
205
+ - Updated dependencies [4b273ea]
206
+ - stratal@0.0.22
207
+ - @stratal/framework@0.0.22
208
+
209
+ ## 0.0.21
210
+
211
+ ### Patch Changes
212
+
213
+ - 3489cfd: Allow tests to install a custom `ExceptionHandler` via `TestingModuleConfig`
214
+
215
+ `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.
216
+
217
+ - Updated dependencies [3489cfd]
218
+ - Updated dependencies [3489cfd]
219
+ - Updated dependencies [3489cfd]
220
+ - @stratal/framework@0.0.21
221
+ - stratal@0.0.21
222
+
223
+ ## 0.0.20
224
+
225
+ ### Patch Changes
226
+
227
+ - Updated dependencies [f8c61e1]
228
+ - Updated dependencies [f8c61e1]
229
+ - Updated dependencies [f8c61e1]
230
+ - Updated dependencies [f8c61e1]
231
+ - Updated dependencies [f8c61e1]
232
+ - Updated dependencies [f8c61e1]
233
+ - Updated dependencies [f8c61e1]
234
+ - Updated dependencies [f8c61e1]
235
+ - Updated dependencies [f8c61e1]
236
+ - @stratal/framework@0.0.20
237
+ - stratal@0.0.20
238
+
239
+ ## 0.0.19
240
+
241
+ ### Patch Changes
242
+
243
+ - 3b16f5b: Make `TestHttpClient` immutable and extend test classes with `Macroable`
244
+ - `TestHttpClient.forHost()`, `withHeaders()`, and `withLocale()` now return new instances instead of mutating `this`, preventing shared state between tests.
245
+ - `TestHttpRequest` and `TestResponse` now extend `Macroable`, allowing apps to register custom assertion methods and helpers at runtime.
246
+ - Add `TestingModule.inertia` getter for convenient Inertia request testing.
247
+
248
+ - Updated dependencies [3b16f5b]
249
+ - Updated dependencies [3b16f5b]
250
+ - Updated dependencies [3b16f5b]
251
+ - Updated dependencies [5d26c24]
252
+ - Updated dependencies [3b16f5b]
253
+ - Updated dependencies [3b16f5b]
254
+ - Updated dependencies [5d26c24]
255
+ - Updated dependencies [5d26c24]
256
+ - Updated dependencies [3b16f5b]
257
+ - @stratal/framework@0.0.19
258
+ - stratal@0.0.19
259
+
260
+ ## 0.0.18
261
+
262
+ ### Patch Changes
263
+
264
+ - c9176ea: Add locale support to test HTTP client, SSE, and WebSocket requests
265
+
266
+ ### Details
267
+ - Add `withLocale()` method to `TestHttpClient`, `TestHttpRequest`, `TestSseRequest`, and `TestWsRequest`
268
+ - Automatically resolves locale detection strategy from the module's I18n configuration
269
+ - Export `getValueAtPath` and `hasValueAtPath` path utility functions
270
+
271
+ - Updated dependencies [fcb71c4]
272
+ - Updated dependencies [c9176ea]
273
+ - Updated dependencies [17f8675]
274
+ - Updated dependencies [c9176ea]
275
+ - Updated dependencies [c9176ea]
276
+ - stratal@0.0.18
277
+ - @stratal/framework@0.0.18
278
+
279
+ ## 0.0.17
280
+
281
+ ### Patch Changes
282
+
283
+ - 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)]:
284
+ - stratal@0.0.17
285
+ - @stratal/framework@0.0.17
286
+
287
+ ## 0.0.16
288
+
289
+ ### Patch Changes
290
+
291
+ - [#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
292
+
293
+ ### Details
294
+ - `FakeStorageService` and `StoredFile` are no longer exported from the main entry point — import from `@stratal/testing/storage` instead
295
+ - Add `reflect-metadata` as a peer dependency
296
+
297
+ - 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)]:
298
+ - stratal@0.0.16
299
+ - @stratal/framework@0.0.16
300
+
301
+ ## 0.0.15
302
+
303
+ ### Patch Changes
304
+
305
+ - [#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
306
+
307
+ ### Details
308
+ - Add `TestCommandRequest` fluent builder for constructing command inputs in tests
309
+ - Add `TestCommandResult` assertion wrapper for command output, exit codes, and errors
310
+ - Add `quarry(name)` method to `TestingModule` for convenient command testing
311
+ - Export new utilities from `@stratal/testing` main entry point
312
+
313
+ - Updated dependencies [[`0731e99`](https://github.com/strataljs/stratal/commit/0731e99c3e0c96f988387611f0ef8559b63d7bd8), [`52f1daa`](https://github.com/strataljs/stratal/commit/52f1daa981f5a38b983bb3c14abfefb663eb6941)]:
314
+ - stratal@0.0.15
315
+ - @stratal/framework@0.0.15
316
+
317
+ ## 0.0.14
318
+
319
+ ### Patch Changes
320
+
321
+ - [#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
322
+
323
+ ### Details
324
+ - Replace the `@cloudflare/vitest-pool-workers` yarn patch with a dedicated `fixPgCjs()` Vite plugin
325
+ - `fixPgCjs()` must be applied at the root `defineConfig` level for the module fallback resolver to work correctly
326
+ - `stratalTest()` does NOT automatically apply `fixPgCjs()` — it must be registered separately at the root level
327
+ - Upgrade `@cloudflare/vitest-pool-workers` to ^0.13.2 (unpinned)
328
+
329
+ - [#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
330
+
331
+ - 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)]:
332
+ - stratal@0.0.14
333
+ - @stratal/framework@0.0.14
334
+
335
+ ## 0.0.13
336
+
337
+ ### Patch Changes
338
+
339
+ - [#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`
340
+
341
+ ### Details
342
+ - `TestingModule.sse(path)` creates an SSE test request builder
343
+ - `TestSseRequest` supports custom headers, authentication via `actingAs()`, and automatic `Accept: text/event-stream` header
344
+ - `TestSseConnection` wraps a live SSE stream with assertion helpers: `assertEvent()`, `assertEventData()`, `assertJsonEventData()`, `waitForEvent()`, `waitForEnd()`, `collectEvents()`
345
+ - Replace dynamic `import('vitest')` with static imports in `TestWsConnection`, `TestWsRequest`, and `TestingModule`
346
+
347
+ - [#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`
348
+
349
+ ### Details
350
+ - `TestingModule.ws(path)` creates a WebSocket test request builder
351
+ - `TestWsRequest` supports custom headers, authentication via `actingAs()`, and WebSocket upgrade handshake
352
+ - `TestWsConnection` wraps a live WebSocket with assertion helpers: `assertMessage()`, `assertClosed()`, `waitForMessage()`, `waitForClose()`
353
+
354
+ - 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)]:
355
+ - stratal@0.0.13
356
+ - @stratal/framework@0.0.13
357
+
358
+ ## 0.0.12
359
+
360
+ ### Patch Changes
361
+
362
+ - [#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
363
+
364
+ ### Details
365
+ - **@stratal/testing**
366
+ - Add `@stratal/testing/vitest-plugin` sub-export with `stratalTest()` — wraps `cloudflareTest` with Stratal defaults (tslib alias, ZenStack mocks, SSR externals)
367
+ - Replace `FetchMock`/`createFetchMock` with `MockFetch`/`createMockFetch` backed by MSW (`setupServer`)
368
+ - Re-export `http` and `HttpResponse` from `msw` for convenience
369
+ - Update `cloudflare:test` imports to `cloudflare:workers`
370
+ - Bump vitest peer dependency from `^3.2.0` to `^4.1.0`
371
+
372
+ - **stratal**
373
+ - Update test mocks to use class syntax for Vitest 4 compatibility
374
+ - Bump dependencies: `@intlify/*`, `@scalar/hono-api-reference`, `hono`, `@aws-sdk/*`, `vitest`
375
+
376
+ - **@stratal/framework**
377
+ - Refactor vitest config to use `stratalTest()` plugin, removing manual pool/alias config
378
+ - Bump dependencies: `better-auth`, `@zenstackhq/*`, `wrangler`, `vitest`
379
+
380
+ ### Breaking Changes
381
+ - **@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`.
382
+ - **@stratal/testing**: Vitest peer dependency is now `^4.1.0` (was `^3.2.0`).
383
+
384
+ - 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)]:
385
+ - stratal@0.0.12
386
+ - @stratal/framework@0.0.12
387
+
388
+ ## 0.0.11
389
+
390
+ ### Patch Changes
391
+
392
+ - Updated dependencies [[`87581af`](https://github.com/strataljs/stratal/commit/87581af263eb74c059966650fbd5c1b849d36dfc), [`bae01ef`](https://github.com/strataljs/stratal/commit/bae01eff7cb7f520ad00206377d9f5f4968076b6)]:
393
+ - @stratal/framework@0.0.11
394
+ - stratal@0.0.11
395
+
396
+ ## 0.0.10
397
+
398
+ ### Patch Changes
399
+
400
+ - Updated dependencies [[`3329d20`](https://github.com/strataljs/stratal/commit/3329d20658ea6a6f7cadbbb3efb7630b1cca9ad2)]:
401
+ - stratal@0.0.10
402
+ - @stratal/framework@0.0.10
403
+
404
+ ## 0.0.9
405
+
406
+ ### Patch Changes
407
+
408
+ - Updated dependencies [[`c0d9313`](https://github.com/strataljs/stratal/commit/c0d9313b30272eece8a4596718b7d4c1b442c221)]:
409
+ - stratal@0.0.9
410
+ - @stratal/framework@0.0.9
411
+
412
+ ## 0.0.8
413
+
414
+ ### Patch Changes
415
+
416
+ - Updated dependencies [[`3b38b81`](https://github.com/strataljs/stratal/commit/3b38b8184428dc0f79ffbe9dc55ba782d46dea03)]:
417
+ - @stratal/framework@0.0.8
418
+ - stratal@0.0.8
419
+
420
+ ## 0.0.7
421
+
422
+ ### Patch Changes
423
+
424
+ - [#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
425
+
426
+ ### Breaking Changes
427
+
428
+ **`stratal` (core)**
429
+ - **Removed `RequestContextStore`** — The `AsyncLocalStorage`-based request context propagation is eliminated. This removes the dependency on the `nodejs_als` compatibility flag in Cloudflare Workers.
430
+ - **Removed `RouterService` and `RequestScopeService`** — Replaced by `HonoApp`, a subclass of `OpenAPIHono` that directly integrates request scoping, middleware class support, and global error handling.
431
+ - **Removed `RouterAlreadyConfiguredError` and `RouterNotConfiguredError`** — Replaced by `HonoAppAlreadyConfiguredError`.
432
+ - **`Container` no longer accepts `env` or `ctx` in options** — These are now registered as values in the container by `Application` directly.
433
+ - **`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.
434
+ - **`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.
435
+ - **`queue()` and `scheduled()` no longer accept `env` and `ctx` parameters** — These are obtained from `cloudflare:workers` during eager init.
436
+ - **New `StratalExecutionContext` interface** — A minimal abstraction over Cloudflare's `ExecutionContext` with only `waitUntil()`.
437
+ - **New `HonoApp` class** — Extends `OpenAPIHono` with Stratal concerns; supports `Constructor<Middleware>` in `use()` via module augmentation.
438
+
439
+ **`@stratal/framework`**
440
+ - **`DatabaseConnectionConfig.dialect` changed from `Dialect` to `() => Dialect`** — Database connections now take a factory function for lazy dialect/pool creation.
441
+ - **Caching strategy changed from `instancePerContainerCachingFactory` to `instanceCachingFactory`**.
442
+
443
+ **`@stratal/testing`**
444
+ - **`TestingModule.runInRequestScope()` callback now receives a `container` parameter** — Update all callbacks to use the passed container for service resolution.
445
+ - **`TestingModule.fetch()` now routes through `HonoApp`** instead of `RouterService`.
446
+ - **`TestingModuleBuilder.compile()` now applies overrides before `initialize()`** — Fixes issue where overrides were applied after initialization.
447
+
448
+ ### Minor Changes
449
+
450
+ **`@stratal/seeders`**
451
+ - Updated `executeSeeder()` to use the explicit `requestContainer` parameter from `runInRequestScope()`.
452
+
453
+ - [#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
454
+
455
+ ### New Package
456
+
457
+ **`@stratal/zenstack-plugin`**
458
+ - ZenStack plugin for multi-connection database support with schema slicing
459
+ - Generates connection-specific schema types and `StratalDatabase` augmentation
460
+ - CLI commands: `stratal-db migrate` and `stratal-db push` for per-connection database management
461
+ - Plugin model (`plugin.zmodel`) for ZenStack integration
462
+
463
+ ### Breaking Changes
464
+
465
+ **`stratal` (core)**
466
+ - Re-exports `delay` from tsyringe via `stratal/di`
467
+
468
+ **`@stratal/framework`**
469
+ - **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.
470
+ - **`schema` moved from `DatabaseConnectionConfig` to `DatabaseModuleConfig`** — All connections now share a single schema; per-connection schema is no longer supported.
471
+ - **Added `slicing` option to `DatabaseConnectionConfig`** — Connections can narrow available models via ZenStack slicing options.
472
+ - **Database services are now lazily created** — Dialect factories are not called during module initialization; services are instantiated on first resolve within a request scope.
473
+ - **Database services are now request-scoped** — Each request gets its own database client instance via tsyringe's `delay()` + `Scope.Request`.
474
+ - **`DatabaseEvents` type no longer parameterized by connection** — Event types (`ModelName`, `DatabaseEventName`, `GetData`, `GetResult`, etc.) derive from the shared schema instead of per-connection schemas.
475
+ - **Removed `InferConnectionSchema` type** — Replaced by `InferDatabaseSchema` (shared) and `InferConnectionSlicing` (per-connection slicing).
476
+
477
+ **`@stratal/testing`**
478
+ - **`TestingModule.getDb()` is now synchronous** — Returns `DatabaseService` directly instead of `Promise<DatabaseService>`.
479
+ - **`TestingModule` creates a single request-scoped container at construction** — `container` property now returns the request-scoped container. The `runInRequestScope` pattern is removed.
480
+ - **`TestingModule.close()` now disposes the request container** before shutting down the application.
481
+
482
+ - Updated dependencies [[`89e06b5`](https://github.com/strataljs/stratal/commit/89e06b57f8aca553f60cbefab8f931cf5554f1b3), [`bcb3556`](https://github.com/strataljs/stratal/commit/bcb3556a6e1f185e088286f202c605c73799e63f)]:
483
+ - stratal@0.0.7
484
+ - @stratal/framework@0.0.7
485
+
486
+ ## 0.0.6
487
+
488
+ ### Patch Changes
489
+
490
+ - Updated dependencies [[`6542f78`](https://github.com/strataljs/stratal/commit/6542f78fda2bf851df7ee5d88d6f7c7d04ea6388)]:
491
+ - stratal@0.0.6
492
+ - @stratal/framework@0.0.6
493
+
494
+ ## 0.0.5
495
+
496
+ ### Patch Changes
497
+
498
+ - [#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.
499
+
500
+ - Updated dependencies [[`c8ea964`](https://github.com/strataljs/stratal/commit/c8ea964e272b09ebc6619843e77d2b51178f9423), [`c8ea964`](https://github.com/strataljs/stratal/commit/c8ea964e272b09ebc6619843e77d2b51178f9423)]:
501
+ - stratal@0.0.5
502
+ - @stratal/framework@0.0.5
503
+
504
+ ## 0.0.4
505
+
506
+ ### Patch Changes
507
+
508
+ - **Build cleanup** — Removed redundant polyfills export and cleaned up the build configuration.
509
+ - **Relaxed vitest version** — Loosened the vitest peer dependency version constraint.
510
+
511
+ - Updated dependencies []:
512
+ - stratal@0.0.4
513
+
514
+ ## 0.0.3
515
+
516
+ ### Patch Changes
517
+
518
+ - - **Build cleanup** — Removed redundant polyfills export and cleaned up the build configuration.
519
+ - **Relaxed vitest version** — Loosened the vitest peer dependency version constraint.
520
+ - Updated dependencies []:
521
+ - stratal@0.0.3
522
+
523
+ ## 0.0.2
524
+
525
+ ### Patch Changes
526
+
527
+ #### `stratal` (core)
528
+
529
+ ##### Breaking Changes
530
+
531
+ - **`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))
532
+
533
+ - **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))
534
+
535
+ ##### Features
536
+
537
+ - **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))
538
+
539
+ - **Benchmark suite** — Added benchmark functionality for measuring framework performa30438`](https://github.com/strataljs/stratal/commit/7230438))
540
+
541
+ ##### Security
542
+
543
+ - **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))
544
+
545
+ ##### Bug Fixes
546
+
547
+ - **`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))
548
+
549
+ ---
550
+
551
+ #### `@stratal/testing`
552
+
553
+ ##### Breaking Changes
554
+
555
+ - **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))
556
+
557
+ - Updated dependencies []:
558
+ - @stratal/testing@0.0.2
559
+
560
+ ## 0.0.1
561
+
562
+ ### Patch Changes
563
+
564
+ - Initial release of the Stratal framework — a modular Cloudflare Workers framework built on Hono and tsyringe.
565
+
566
+ **Core Infrastructure**
567
+ - NestJS-style module system with `@Module()` decorator, dynamic modules (`forRoot`, `forRootAsync`), and lifecycle hooks (`OnInitialize`, `OnShutdown`)
568
+ - Two-tier dependency injection container (global singletons + request-scoped) powered by tsyringe with conditional registration and service decoration
569
+ - `StratalWorker` entry point extending Cloudflare's `WorkerEntrypoint` for HTTP fetch, queue batches, and scheduled cron triggers
570
+
571
+ **Routing & API**
572
+ - Hono-based routing with `@Controller()` and `@Route()` decorators, automatic controller discovery, and route guards via `@UseGuards()`
573
+ - OpenAPI schema generation with `@hono/zod-openapi` and Scalar API reference integration
574
+ - NestJS-like middleware configuration with route-specific application and exclusion
575
+
576
+ **Background Processing**
577
+ - Queue consumerfor Cloudflare Queues with `@Consumer()` and `@QueueJob()` decorators and batch processing
578
+ - Cron job scheduling via `CronManager` integrated with Cloudflare's scheduled events
579
+
580
+ **Services & Integrations**
581
+ - Email module with pluggable providers (Nodemailer, Resend) and queue-based sending
582
+ - Storage module with AWS S3 / Cloudflare R2 support, multipart uploads, presigned URLs, and TUS resumable uploads
583
+ - Internationalization (i18n) module with locale detection, message compilation, and request-scoped translations
584
+ - Cache module with pluggable providers and Cloudflare KV integration
585
+ - Configuration module with `registerAs()` namespaces and Zod-based validation
586
+ - Structured logging with JSON and pretty formatters
587
+
588
+ **Developer Experience**
589
+ - Zod-powered request/response validation with type inference
590
+ - Custom `ApplicationError` class with HTTP status mapping
591
+ - ESM-only with full TypeScript decorator support (`emitDecoratorMetadata`)
592
+ - Sub-path exports for tree-shakeable imports (`stratal/di`, `stratal/router`, `stratal/cache`, etc.)
593
+
594
+ - `TestingModule` and `TestingModuleBuilder` for bootstrapping isolated module environments in tests
595
+ - `TestHttpClient` with request builder and response wrapper for integration testing
596
+ - `FetchMock` for mocking HTTP fetch calls
597
+ - `FakeStorageService` for in-memory storage testing without S3/R2
598
+ - `ProviderOverrideBuilder` for replacing providers with test doubles
599
+ - Nodemailer mock for email testing
600
+ - Test environment utilities via `getTestEnv()`
601
+
602
+ - Updated dependencies []:
603
+ - stratal@0.0.1