@cosmicdrift/kumiko-framework 0.13.0 → 0.15.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 (314) hide show
  1. package/package.json +7 -7
  2. package/src/__tests__/{anonymous-access.integration.ts → anonymous-access.integration.test.ts} +12 -9
  3. package/src/__tests__/{error-contract.integration.ts → error-contract.integration.test.ts} +5 -4
  4. package/src/__tests__/{field-access.integration.ts → field-access.integration.test.ts} +3 -3
  5. package/src/__tests__/{full-stack.integration.ts → full-stack.integration.test.ts} +7 -16
  6. package/src/__tests__/{ownership.integration.ts → ownership.integration.test.ts} +3 -2
  7. package/src/__tests__/{raw-table.integration.ts → raw-table.integration.test.ts} +18 -30
  8. package/src/__tests__/{reference-data.integration.ts → reference-data.integration.test.ts} +24 -11
  9. package/src/__tests__/{transition-guard.integration.ts → transition-guard.integration.test.ts} +12 -10
  10. package/src/api/__tests__/api.test.ts +1 -1
  11. package/src/api/__tests__/auth-middleware-transport.test.ts +1 -1
  12. package/src/api/__tests__/auth-routes-cookie.test.ts +1 -1
  13. package/src/api/__tests__/{batch.integration.ts → batch.integration.test.ts} +30 -30
  14. package/src/api/__tests__/body-limit.test.ts +1 -1
  15. package/src/api/__tests__/csrf-middleware.test.ts +1 -1
  16. package/src/api/__tests__/{dispatcher-live.integration.ts → dispatcher-live.integration.test.ts} +10 -9
  17. package/src/api/__tests__/metrics-endpoint.test.ts +1 -1
  18. package/src/api/__tests__/{nested-write.integration.ts → nested-write.integration.test.ts} +13 -16
  19. package/src/api/__tests__/readiness.test.ts +1 -1
  20. package/src/api/__tests__/request-id-middleware.test.ts +1 -1
  21. package/src/api/__tests__/sse-broker.test.ts +12 -12
  22. package/src/api/__tests__/sse-route.test.ts +1 -1
  23. package/src/api/readiness.ts +2 -2
  24. package/src/auth/__tests__/roles.test.ts +2 -2
  25. package/src/bun-db/__tests__/PATTERN.md +73 -0
  26. package/src/bun-db/__tests__/_helpers.ts +103 -0
  27. package/src/bun-db/__tests__/batch-methods.integration.test.ts +143 -0
  28. package/src/bun-db/__tests__/batch-methods.test.ts +20 -0
  29. package/src/bun-db/__tests__/bun-test-db.ts +19 -0
  30. package/src/bun-db/__tests__/bun-test-stack.ts +6 -0
  31. package/src/bun-db/__tests__/column-types.integration.test.ts +132 -0
  32. package/src/bun-db/__tests__/compound-types.integration.test.ts +134 -0
  33. package/src/bun-db/__tests__/jsonb-edge-cases.integration.test.ts +235 -0
  34. package/src/bun-db/__tests__/smoke.integration.test.ts +43 -0
  35. package/src/bun-db/__tests__/sql-methods.integration.test.ts +231 -0
  36. package/src/bun-db/__tests__/where-patterns.integration.test.ts +185 -0
  37. package/src/bun-db/connection.ts +84 -0
  38. package/src/bun-db/index.ts +31 -0
  39. package/src/bun-db/query.ts +845 -0
  40. package/src/compliance/__tests__/duration-spec.test.ts +1 -1
  41. package/src/compliance/__tests__/profiles.test.ts +1 -1
  42. package/src/compliance/__tests__/sub-processors.test.ts +1 -1
  43. package/src/db/__tests__/{apply-entity-event-tenant.integration.ts → apply-entity-event-tenant.integration.test.ts} +13 -11
  44. package/src/db/__tests__/big-int-field.test.ts +15 -14
  45. package/src/db/__tests__/column-ddl.integration.test.ts +113 -0
  46. package/src/db/__tests__/compound-types.test.ts +1 -1
  47. package/src/db/__tests__/{config-seed.integration.ts → config-seed.integration.test.ts} +32 -27
  48. package/src/db/__tests__/connection-options.test.ts +1 -1
  49. package/src/db/__tests__/dialect-instant.test.ts +1 -1
  50. package/src/db/__tests__/encryption.test.ts +1 -1
  51. package/src/db/__tests__/{drizzle-table-types.test.ts → entity-table-types.test.ts} +16 -16
  52. package/src/db/__tests__/{event-store-executor-list.integration.ts → event-store-executor-list.integration.test.ts} +12 -7
  53. package/src/db/__tests__/{event-store-executor.integration.ts → event-store-executor.integration.test.ts} +19 -12
  54. package/src/db/__tests__/{implicit-projection-equivalence.integration.ts → implicit-projection-equivalence.integration.test.ts} +35 -29
  55. package/src/db/__tests__/located-timestamp.test.ts +1 -1
  56. package/src/db/__tests__/money.test.ts +1 -1
  57. package/src/db/__tests__/{multi-row-insert.integration.ts → multi-row-insert.integration.test.ts} +18 -11
  58. package/src/db/__tests__/parse-auto-verb.test.ts +1 -1
  59. package/src/db/__tests__/{required-not-null-migration-safety.integration.ts → required-not-null-migration-safety.integration.test.ts} +28 -24
  60. package/src/db/__tests__/{schema-migration.integration.ts → schema-migration.integration.test.ts} +32 -28
  61. package/src/db/__tests__/sql-inventory.test.ts +56 -0
  62. package/src/db/__tests__/table-builder-indexes.test.ts +30 -11
  63. package/src/db/__tests__/table-builder-required.test.ts +20 -22
  64. package/src/db/__tests__/{tenant-db.integration.ts → tenant-db.integration.test.ts} +106 -144
  65. package/src/db/__tests__/{unique-violation-mapping.integration.ts → unique-violation-mapping.integration.test.ts} +13 -8
  66. package/src/db/api.ts +46 -0
  67. package/src/db/apply-entity-event.ts +45 -36
  68. package/src/db/assert-exists-in.ts +5 -16
  69. package/src/db/bun-provider.ts +37 -0
  70. package/src/db/config-seed.ts +4 -4
  71. package/src/db/connection.ts +14 -57
  72. package/src/db/cursor.ts +5 -56
  73. package/src/db/dialect.ts +472 -99
  74. package/src/db/eagerload.ts +5 -12
  75. package/src/db/entity-table-meta.ts +390 -0
  76. package/src/db/event-store-executor.ts +158 -100
  77. package/src/db/index.ts +33 -5
  78. package/src/db/migrate-generator.ts +350 -0
  79. package/src/db/migrate-runner.ts +206 -0
  80. package/src/db/postgres-provider.ts +25 -0
  81. package/src/db/queries/entity-read.ts +15 -0
  82. package/src/db/queries/es-ops.ts +17 -0
  83. package/src/db/queries/event-consumer.ts +170 -0
  84. package/src/db/queries/event-store-admin.ts +127 -0
  85. package/src/db/queries/event-store.ts +155 -0
  86. package/src/db/queries/projection-rebuild.ts +59 -0
  87. package/src/db/queries/raw-sql.ts +15 -0
  88. package/src/db/queries/schema-drift.ts +35 -0
  89. package/src/db/queries/seed-context.ts +58 -0
  90. package/src/db/queries/table-ops.ts +11 -0
  91. package/src/db/queries/test-stack.ts +56 -0
  92. package/src/db/query-api.ts +22 -0
  93. package/src/db/query.ts +30 -0
  94. package/src/db/reference-data.ts +19 -22
  95. package/src/db/render-ddl.ts +57 -0
  96. package/src/db/row-helpers.ts +3 -52
  97. package/src/db/schema-inspection.ts +17 -4
  98. package/src/db/sql-inventory.ts +208 -0
  99. package/src/db/table-builder.ts +48 -40
  100. package/src/db/tenant-db.ts +105 -326
  101. package/src/engine/__tests__/auth-claims-registrar.test.ts +1 -1
  102. package/src/engine/__tests__/boot-validator-api-exposure.test.ts +3 -3
  103. package/src/engine/__tests__/boot-validator-located-timestamps.test.ts +1 -1
  104. package/src/engine/__tests__/boot-validator-pii-retention.test.ts +5 -5
  105. package/src/engine/__tests__/boot-validator-s0-integration.test.ts +3 -3
  106. package/src/engine/__tests__/boot-validator.test.ts +4 -3
  107. package/src/engine/__tests__/build-app-schema.test.ts +1 -1
  108. package/src/engine/__tests__/build-target.test.ts +1 -1
  109. package/src/engine/__tests__/claim-keys.test.ts +1 -1
  110. package/src/engine/__tests__/codemod-pipeline.test.ts +3 -3
  111. package/src/engine/__tests__/config-helpers.test.ts +1 -1
  112. package/src/engine/__tests__/effective-features.test.ts +1 -1
  113. package/src/engine/__tests__/engine.test.ts +1 -1
  114. package/src/engine/__tests__/entity-handlers.test.ts +3 -3
  115. package/src/engine/__tests__/event-helpers.test.ts +3 -3
  116. package/src/engine/__tests__/extends-registrar.test.ts +4 -4
  117. package/src/engine/__tests__/factories-long-text.test.ts +1 -1
  118. package/src/engine/__tests__/factories-time.test.ts +1 -1
  119. package/src/engine/__tests__/field-predicates.test.ts +1 -1
  120. package/src/engine/__tests__/hook-phases.test.ts +1 -1
  121. package/src/engine/__tests__/identifiers.test.ts +1 -1
  122. package/src/engine/__tests__/lifecycle-hooks.test.ts +1 -1
  123. package/src/engine/__tests__/nav.test.ts +1 -1
  124. package/src/engine/__tests__/ownership.test.ts +10 -11
  125. package/src/engine/__tests__/parse-ref-target.test.ts +1 -1
  126. package/src/engine/__tests__/pipeline-engine.test.ts +1 -1
  127. package/src/engine/__tests__/{pipeline-handler.integration.ts → pipeline-handler.integration.test.ts} +38 -52
  128. package/src/engine/__tests__/{pipeline-observability.integration.ts → pipeline-observability.integration.test.ts} +1 -1
  129. package/src/engine/__tests__/{pipeline-performance.integration.ts → pipeline-performance.integration.test.ts} +1 -1
  130. package/src/engine/__tests__/pipeline-sub-pipelines.test.ts +1 -1
  131. package/src/engine/__tests__/post-query-hook.test.ts +1 -1
  132. package/src/engine/__tests__/projection-helpers.test.ts +25 -17
  133. package/src/engine/__tests__/projection.test.ts +4 -4
  134. package/src/engine/__tests__/qualified-name.test.ts +1 -1
  135. package/src/engine/__tests__/raw-table.test.ts +9 -8
  136. package/src/engine/__tests__/resolve-config-or-param.test.ts +5 -5
  137. package/src/engine/__tests__/run-in.test.ts +1 -1
  138. package/src/engine/__tests__/schema-builder.test.ts +1 -1
  139. package/src/engine/__tests__/screen.test.ts +1 -1
  140. package/src/engine/__tests__/search-payload-extension.test.ts +3 -3
  141. package/src/engine/__tests__/state-machine.test.ts +1 -1
  142. package/src/engine/__tests__/steps-aggregate-append-event.test.ts +7 -7
  143. package/src/engine/__tests__/steps-aggregate-create.test.ts +4 -4
  144. package/src/engine/__tests__/steps-aggregate-update.test.ts +3 -3
  145. package/src/engine/__tests__/steps-call-feature.test.ts +5 -5
  146. package/src/engine/__tests__/steps-mail-send.test.ts +7 -7
  147. package/src/engine/__tests__/steps-read.test.ts +34 -40
  148. package/src/engine/__tests__/steps-resolver-utils.test.ts +6 -6
  149. package/src/engine/__tests__/steps-unsafe-projection-delete.test.ts +24 -19
  150. package/src/engine/__tests__/steps-unsafe-projection-upsert.test.ts +28 -17
  151. package/src/engine/__tests__/steps-webhook-send.test.ts +6 -6
  152. package/src/engine/__tests__/steps-workflow.test.ts +7 -7
  153. package/src/engine/__tests__/system-user.test.ts +1 -1
  154. package/src/engine/__tests__/validate-projection-allowlist.test.ts +4 -5
  155. package/src/engine/__tests__/validation-hooks.test.ts +1 -1
  156. package/src/engine/__tests__/visual-tree-patterns.test.ts +1 -1
  157. package/src/engine/boot-validator/entity-handler.ts +3 -3
  158. package/src/engine/boot-validator/ownership.ts +1 -1
  159. package/src/engine/define-feature.ts +1 -2
  160. package/src/engine/entity-handlers.ts +5 -5
  161. package/src/engine/factories.ts +1 -1
  162. package/src/engine/feature-ast/__tests__/canonical-form.test.ts +1 -1
  163. package/src/engine/feature-ast/__tests__/parse-happy-path.test.ts +1 -1
  164. package/src/engine/feature-ast/__tests__/parse-real-features.test.ts +2 -2
  165. package/src/engine/feature-ast/__tests__/parse.test.ts +1 -1
  166. package/src/engine/feature-ast/__tests__/patch.test.ts +1 -1
  167. package/src/engine/feature-ast/__tests__/patcher.test.ts +1 -1
  168. package/src/engine/feature-ast/__tests__/render-roundtrip.test.ts +1 -1
  169. package/src/engine/feature-ast/__tests__/visual-tree-parse.test.ts +1 -1
  170. package/src/engine/ownership.ts +113 -41
  171. package/src/engine/pattern-library/__tests__/library.test.ts +2 -2
  172. package/src/engine/projection-helpers.ts +2 -11
  173. package/src/engine/registry.ts +2 -2
  174. package/src/engine/steps/read-find-many.ts +13 -13
  175. package/src/engine/steps/read-find-one.ts +7 -9
  176. package/src/engine/steps/unsafe-projection-delete.ts +4 -5
  177. package/src/engine/steps/unsafe-projection-upsert.ts +63 -31
  178. package/src/engine/types/feature.ts +7 -2
  179. package/src/engine/types/fields.ts +4 -5
  180. package/src/engine/types/step.ts +10 -10
  181. package/src/engine/validate-projection-allowlist.ts +23 -3
  182. package/src/entrypoint/__tests__/{entrypoint-job-wiring.integration.ts → entrypoint-job-wiring.integration.test.ts} +4 -3
  183. package/src/entrypoint/__tests__/{split-deploy.integration.ts → split-deploy.integration.test.ts} +4 -3
  184. package/src/env/__tests__/compose-env-schema.test.ts +1 -1
  185. package/src/env/__tests__/dry-run.test.ts +1 -1
  186. package/src/errors/__tests__/classes.test.ts +1 -1
  187. package/src/errors/__tests__/write-failures.test.ts +1 -1
  188. package/src/es-ops/__tests__/{context.integration.ts → context.integration.test.ts} +43 -29
  189. package/src/es-ops/__tests__/{runner.integration.ts → runner.integration.test.ts} +25 -23
  190. package/src/es-ops/__tests__/runner.test.ts +29 -19
  191. package/src/es-ops/context.ts +9 -43
  192. package/src/es-ops/operations-schema.ts +2 -2
  193. package/src/es-ops/runner.ts +12 -26
  194. package/src/event-store/__tests__/{admin-api.integration.ts → admin-api.integration.test.ts} +71 -45
  195. package/src/event-store/__tests__/{event-store.integration.ts → event-store.integration.test.ts} +7 -5
  196. package/src/event-store/__tests__/{get-stream-version-perf.integration.ts → get-stream-version-perf.integration.test.ts} +5 -3
  197. package/src/event-store/__tests__/{perf.integration.ts → perf.integration.test.ts} +24 -16
  198. package/src/event-store/__tests__/{snapshot.integration.ts → snapshot.integration.test.ts} +34 -28
  199. package/src/event-store/__tests__/{upcaster-dead-letter.integration.ts → upcaster-dead-letter.integration.test.ts} +11 -12
  200. package/src/event-store/__tests__/{upcaster.integration.ts → upcaster.integration.test.ts} +19 -32
  201. package/src/event-store/admin-api.ts +55 -83
  202. package/src/event-store/archive.ts +15 -39
  203. package/src/event-store/event-store.ts +92 -86
  204. package/src/event-store/events-schema.ts +2 -1
  205. package/src/event-store/index.ts +1 -0
  206. package/src/event-store/snapshot.ts +26 -24
  207. package/src/event-store/upcaster-dead-letter.ts +19 -18
  208. package/src/files/__tests__/content-disposition.test.ts +1 -1
  209. package/src/files/__tests__/{file-field-pipeline.integration.ts → file-field-pipeline.integration.test.ts} +8 -5
  210. package/src/files/__tests__/file-handle.test.ts +1 -1
  211. package/src/files/__tests__/{files.integration.ts → files.integration.test.ts} +32 -17
  212. package/src/files/__tests__/read-stream.test.ts +1 -1
  213. package/src/files/__tests__/{storage-tracking.integration.ts → storage-tracking.integration.test.ts} +26 -30
  214. package/src/files/__tests__/write-stream.test.ts +1 -1
  215. package/src/files/__tests__/zip-stream.test.ts +1 -1
  216. package/src/files/file-ref-table.ts +2 -2
  217. package/src/files/file-routes.ts +7 -9
  218. package/src/files/storage-tracking.ts +9 -17
  219. package/src/i18n/__tests__/i18n.test.ts +1 -1
  220. package/src/jobs/__tests__/{job-event-trigger.integration.ts → job-event-trigger.integration.test.ts} +6 -3
  221. package/src/jobs/__tests__/{job-multi-trigger.integration.ts → job-multi-trigger.integration.test.ts} +6 -3
  222. package/src/jobs/__tests__/{jobs.integration.ts → jobs.integration.test.ts} +5 -7
  223. package/src/lifecycle/__tests__/{lifecycle-server.integration.ts → lifecycle-server.integration.test.ts} +1 -1
  224. package/src/lifecycle/__tests__/lifecycle.test.ts +6 -6
  225. package/src/lifecycle/__tests__/signal-handlers.test.ts +6 -6
  226. package/src/logging/__tests__/pino-trace-bridge.test.ts +1 -1
  227. package/src/migrations/__tests__/compare-snapshots.test.ts +1 -1
  228. package/src/migrations/__tests__/{detect-drift.integration.ts → detect-drift.integration.test.ts} +34 -26
  229. package/src/migrations/__tests__/{detect-projections-to-rebuild.integration.ts → detect-projections-to-rebuild.integration.test.ts} +1 -1
  230. package/src/migrations/__tests__/rebuild-marker.test.ts +1 -1
  231. package/src/migrations/projection-detection.ts +12 -1
  232. package/src/migrations/schema-drift.ts +7 -23
  233. package/src/observability/__tests__/console-provider.test.ts +1 -1
  234. package/src/observability/__tests__/metric-validator.test.ts +1 -1
  235. package/src/observability/__tests__/noop-provider.test.ts +1 -1
  236. package/src/observability/__tests__/{observability.integration.ts → observability.integration.test.ts} +5 -8
  237. package/src/observability/__tests__/prometheus-meter.test.ts +1 -1
  238. package/src/observability/__tests__/recording-meter.test.ts +1 -1
  239. package/src/observability/__tests__/recording-tracer.test.ts +1 -1
  240. package/src/observability/__tests__/sensitive-filter.test.ts +1 -1
  241. package/src/pipeline/__tests__/{archive-stream.integration.ts → archive-stream.integration.test.ts} +3 -3
  242. package/src/pipeline/__tests__/auth-claims-resolver.test.ts +9 -9
  243. package/src/pipeline/__tests__/{cascade-handler.integration.ts → cascade-handler.integration.test.ts} +18 -15
  244. package/src/pipeline/__tests__/cascade-handler.test.ts +1 -1
  245. package/src/pipeline/__tests__/{causation-chain.integration.ts → causation-chain.integration.test.ts} +12 -13
  246. package/src/pipeline/__tests__/{ctx-bridge.integration.ts → ctx-bridge.integration.test.ts} +12 -11
  247. package/src/pipeline/__tests__/dispatcher.test.ts +2 -2
  248. package/src/pipeline/__tests__/{distributed-lock.integration.ts → distributed-lock.integration.test.ts} +1 -1
  249. package/src/pipeline/__tests__/{domain-events-projections.integration.ts → domain-events-projections.integration.test.ts} +13 -15
  250. package/src/pipeline/__tests__/{event-dedup.integration.ts → event-dedup.integration.test.ts} +1 -1
  251. package/src/pipeline/__tests__/{event-define-event-strict.integration.ts → event-define-event-strict.integration.test.ts} +6 -16
  252. package/src/pipeline/__tests__/{event-dispatcher-lifecycle.integration.ts → event-dispatcher-lifecycle.integration.test.ts} +1 -1
  253. package/src/pipeline/__tests__/{event-dispatcher-multi-instance.integration.ts → event-dispatcher-multi-instance.integration.test.ts} +3 -2
  254. package/src/pipeline/__tests__/{event-dispatcher-pg-listen.integration.ts → event-dispatcher-pg-listen.integration.test.ts} +1 -1
  255. package/src/pipeline/__tests__/{event-dispatcher-recovery.integration.ts → event-dispatcher-recovery.integration.test.ts} +2 -2
  256. package/src/pipeline/__tests__/{event-dispatcher-second-audit.integration.ts → event-dispatcher-second-audit.integration.test.ts} +17 -16
  257. package/src/pipeline/__tests__/event-dispatcher-strict.test.ts +14 -12
  258. package/src/pipeline/__tests__/{event-dispatcher.integration.ts → event-dispatcher.integration.test.ts} +8 -15
  259. package/src/pipeline/__tests__/{event-retention.integration.ts → event-retention.integration.test.ts} +28 -25
  260. package/src/pipeline/__tests__/{fetch-for-writing.integration.ts → fetch-for-writing.integration.test.ts} +6 -6
  261. package/src/pipeline/__tests__/lifecycle-pipeline.test.ts +4 -4
  262. package/src/pipeline/__tests__/{load-aggregate-query.integration.ts → load-aggregate-query.integration.test.ts} +9 -5
  263. package/src/pipeline/__tests__/{msp-error-mode.integration.ts → msp-error-mode.integration.test.ts} +1 -1
  264. package/src/pipeline/__tests__/{msp-multi-hop.integration.ts → msp-multi-hop.integration.test.ts} +9 -8
  265. package/src/pipeline/__tests__/{msp-rebuild.integration.ts → msp-rebuild.integration.test.ts} +47 -55
  266. package/src/pipeline/__tests__/{multi-stream-projection.integration.ts → multi-stream-projection.integration.test.ts} +19 -53
  267. package/src/pipeline/__tests__/{perf-rebuild.integration.ts → perf-rebuild.integration.test.ts} +36 -34
  268. package/src/pipeline/__tests__/{post-query-hook.integration.ts → post-query-hook.integration.test.ts} +1 -1
  269. package/src/pipeline/__tests__/{projection-rebuild.integration.ts → projection-rebuild.integration.test.ts} +21 -30
  270. package/src/pipeline/__tests__/{query-projection.integration.ts → query-projection.integration.test.ts} +6 -5
  271. package/src/pipeline/__tests__/{redis-pipeline.integration.ts → redis-pipeline.integration.test.ts} +3 -1
  272. package/src/pipeline/cascade-handler.ts +13 -21
  273. package/src/pipeline/dispatcher.ts +43 -48
  274. package/src/pipeline/event-consumer-state.ts +11 -2
  275. package/src/pipeline/event-dispatcher.ts +86 -146
  276. package/src/pipeline/event-retention.ts +14 -24
  277. package/src/pipeline/msp-rebuild.ts +54 -78
  278. package/src/pipeline/projection-rebuild.ts +65 -67
  279. package/src/pipeline/projection-state.ts +2 -2
  280. package/src/random/__tests__/generate.test.ts +13 -13
  281. package/src/rate-limit/__tests__/{dispatcher-l3.integration.ts → dispatcher-l3.integration.test.ts} +1 -1
  282. package/src/rate-limit/__tests__/{middleware.integration.ts → middleware.integration.test.ts} +1 -1
  283. package/src/rate-limit/__tests__/{resolver.integration.ts → resolver.integration.test.ts} +1 -1
  284. package/src/redis/__tests__/redis-options.test.ts +1 -1
  285. package/src/search/__tests__/{meilisearch-adapter.integration.ts → meilisearch-adapter.integration.test.ts} +1 -1
  286. package/src/search/__tests__/search-adapter.test.ts +1 -1
  287. package/src/secrets/__tests__/dek-cache.test.ts +1 -3
  288. package/src/secrets/__tests__/env-master-key-provider.test.ts +1 -1
  289. package/src/secrets/__tests__/envelope.test.ts +1 -1
  290. package/src/secrets/__tests__/leak-guard.test.ts +1 -1
  291. package/src/secrets/__tests__/rotation.test.ts +1 -1
  292. package/src/stack/db.ts +25 -48
  293. package/src/stack/push-entity-projection-tables.ts +2 -4
  294. package/src/stack/table-helpers.ts +98 -61
  295. package/src/stack/test-stack.ts +8 -7
  296. package/src/testing/__tests__/db-cleanup.test.ts +40 -0
  297. package/src/testing/__tests__/e2e-generator.test.ts +1 -1
  298. package/src/testing/__tests__/{ensure-entity-table.integration.ts → ensure-entity-table.integration.test.ts} +7 -14
  299. package/src/testing/db-cleanup.ts +44 -0
  300. package/src/testing/expect-error.ts +1 -1
  301. package/src/testing/index.ts +2 -0
  302. package/src/testing/multipart-helper.ts +94 -0
  303. package/src/testing/shared-entities.ts +5 -5
  304. package/src/time/__tests__/polyfill.test.ts +1 -1
  305. package/src/time/__tests__/tz-context.test.ts +1 -1
  306. package/src/utils/__tests__/assert.test.ts +1 -1
  307. package/src/utils/__tests__/env-parse.test.ts +1 -1
  308. package/CHANGELOG.md +0 -472
  309. package/src/db/__tests__/cursor.test.ts +0 -41
  310. package/src/db/__tests__/db-helpers.test.ts +0 -369
  311. package/src/db/__tests__/drizzle-helpers.integration.ts +0 -186
  312. package/src/db/__tests__/row-helpers.test.ts +0 -59
  313. package/src/engine/steps/_drizzle-boundary.ts +0 -19
  314. package/src/files/__tests__/file-field-column.integration.ts +0 -103
@@ -6,9 +6,10 @@
6
6
  // - die throw-Policy bleibt unverändert (Regression-Guard)
7
7
  // - listDeadLetters filtert per eventType
8
8
 
9
- import { eq, sql } from "drizzle-orm";
10
- import { afterAll, afterEach, beforeAll, describe, expect, test } from "vitest";
11
- import { createTestDb, type TestDb } from "../../stack";
9
+ import { afterAll, afterEach, beforeAll, describe, expect, test } from "bun:test";
10
+ import { type BunTestDb, createTestDb } from "../../bun-db/__tests__/bun-test-db";
11
+ import { asRawClient, insertOne, selectMany } from "../../db/query";
12
+ import { ensureTemporalPolyfill } from "../../time/polyfill";
12
13
  import type { StoredEvent } from "../event-store";
13
14
  import { createEventsTable, eventsTable } from "../events-schema";
14
15
  import { type EventUpcasters, makeUpcastCtx, upcastStoredEvents } from "../upcaster";
@@ -18,7 +19,7 @@ import {
18
19
  upcasterDeadLetterTable,
19
20
  } from "../upcaster-dead-letter";
20
21
 
21
- let testDb: TestDb;
22
+ let testDb: BunTestDb;
22
23
 
23
24
  const TENANT_ID = "00000000-0000-4000-8000-0000000000aa";
24
25
 
@@ -78,6 +79,7 @@ const passthroughUpcasters: EventUpcasters = new Map([
78
79
  ]);
79
80
 
80
81
  beforeAll(async () => {
82
+ await ensureTemporalPolyfill();
81
83
  testDb = await createTestDb();
82
84
  await createEventsTable(testDb.db);
83
85
  await createUpcasterDeadLetterTable(testDb.db);
@@ -88,8 +90,8 @@ afterAll(async () => {
88
90
  });
89
91
 
90
92
  afterEach(async () => {
91
- await testDb.db.delete(upcasterDeadLetterTable);
92
- await testDb.db.delete(eventsTable);
93
+ await asRawClient(testDb.db).unsafe(`DELETE FROM "${upcasterDeadLetterTable.tableName}"`);
94
+ await asRawClient(testDb.db).unsafe(`DELETE FROM "${eventsTable.tableName}"`);
93
95
  });
94
96
 
95
97
  describe("upcaster error-policy: throw (default)", () => {
@@ -165,7 +167,7 @@ describe("upcaster error-policy: quarantine", () => {
165
167
  );
166
168
 
167
169
  // Drop one directly to add noise of a different type.
168
- await testDb.db.insert(upcasterDeadLetterTable).values({
170
+ await insertOne(testDb.db, upcasterDeadLetterTable, {
169
171
  eventId: "99",
170
172
  tenantId: TENANT_ID,
171
173
  aggregateId: "other",
@@ -195,10 +197,7 @@ describe("upcaster error-policy: quarantine", () => {
195
197
  errorPolicy: "quarantine",
196
198
  });
197
199
 
198
- const rows = await testDb.db
199
- .select({ c: sql<number>`count(*)::int` })
200
- .from(upcasterDeadLetterTable)
201
- .where(eq(upcasterDeadLetterTable.eventId, "30"));
202
- expect(rows[0]?.c).toBe(2);
200
+ const rows = await selectMany(testDb.db, upcasterDeadLetterTable, { eventId: "30" });
201
+ expect(rows).toHaveLength(2);
203
202
  });
204
203
  });
@@ -8,12 +8,12 @@
8
8
  // with only a 1→2 migration fails immediately, so a missing upcaster
9
9
  // can never silently hand half-migrated data to consumers.
10
10
 
11
- import { sql } from "drizzle-orm";
12
- import { afterAll, beforeAll, beforeEach, describe, expect, test } from "vitest";
11
+ import { afterAll, beforeAll, beforeEach, describe, expect, test } from "bun:test";
13
12
  import { z } from "zod";
14
13
  import { integer as pgInteger, table as pgTable, text as pgText } from "../../db/dialect";
15
14
  import { createEventStoreExecutor } from "../../db/event-store-executor";
16
- import { buildDrizzleTable } from "../../db/table-builder";
15
+ import { asRawClient, insertOne, selectMany } from "../../db/query";
16
+ import { buildEntityTable } from "../../db/table-builder";
17
17
  import { createTenantDb, type TenantDb } from "../../db/tenant-db";
18
18
  import { createEntity, createRegistry, createTextField, defineFeature } from "../../engine";
19
19
  import type { StoredEvent } from "../../event-store";
@@ -36,7 +36,7 @@ const orderEntity = createEntity({
36
36
  customer: createTextField({ required: true }),
37
37
  },
38
38
  });
39
- const orderTable = buildDrizzleTable("upcast-order", orderEntity);
39
+ const orderTable = buildEntityTable("upcast-order", orderEntity);
40
40
 
41
41
  // Projection stores the UPCAST view: the v3 shape expects `totalCents` (int)
42
42
  // even though the earliest writes might have stored `totalEuros` (string).
@@ -78,18 +78,10 @@ const orderFeature = defineFeature("upcastshop", (r) => {
78
78
  apply: {
79
79
  [orderPriced.name]: async (event, tx) => {
80
80
  const p = event.payload as { totalCents: number; currency: string };
81
- await tx
82
- .insert(orderSummaryTable)
83
- .values({
84
- orderId: event.aggregateId,
85
- tenantId: event.tenantId,
86
- totalCents: p.totalCents,
87
- currency: p.currency,
88
- })
89
- .onConflictDoUpdate({
90
- target: orderSummaryTable.orderId,
91
- set: { totalCents: p.totalCents, currency: p.currency },
92
- });
81
+ await asRawClient(tx).unsafe(
82
+ `INSERT INTO "read_upcast_order_summary" (order_id, tenant_id, total_cents, currency) VALUES ($1, $2, $3, $4) ON CONFLICT (order_id) DO UPDATE SET total_cents = $3, currency = $4`,
83
+ [event.aggregateId, event.tenantId, p.totalCents, p.currency],
84
+ );
93
85
  },
94
86
  },
95
87
  });
@@ -121,8 +113,8 @@ afterAll(async () => {
121
113
  });
122
114
 
123
115
  beforeEach(async () => {
124
- await testDb.db.execute(
125
- sql`TRUNCATE kumiko_events, read_upcast_orders, read_upcast_order_summary, kumiko_projections RESTART IDENTITY CASCADE`,
116
+ await asRawClient(testDb.db).unsafe(
117
+ `TRUNCATE kumiko_events, read_upcast_orders, read_upcast_order_summary, kumiko_projections RESTART IDENTITY CASCADE`,
126
118
  );
127
119
  });
128
120
 
@@ -280,10 +272,7 @@ describe("upcaster: projection rebuild walks the chain on replay", () => {
280
272
  });
281
273
  expect(result.eventsProcessed).toBe(3);
282
274
 
283
- const rows = await testDb.db
284
- .select()
285
- .from(orderSummaryTable)
286
- .orderBy(orderSummaryTable.orderId);
275
+ const rows = await selectMany(testDb.db, orderSummaryTable);
287
276
 
288
277
  // Ordered by orderId → ord1 (10€ = 1000¢), ord2 ($25.50 = 2550¢), ord3 (9900¢)
289
278
  expect(rows).toHaveLength(3);
@@ -305,9 +294,7 @@ describe("upcaster: async (Marten AsyncOnlyEventUpcaster — DB-Lookups)", () =>
305
294
  segment: pgText("segment").notNull(),
306
295
  });
307
296
  await unsafePushTables(testDb.db, { upcastAsyncCustomerSegments: customerSegments });
308
- await testDb.db
309
- .insert(customerSegments)
310
- .values({ customerId: "c-async-1", segment: "PREMIUM" });
297
+ await insertOne(testDb.db, customerSegments, { customerId: "c-async-1", segment: "PREMIUM" });
311
298
 
312
299
  const asyncSummary = pgTable("upcast_async_summary", {
313
300
  orderId: pgText("order_id").primaryKey(),
@@ -327,11 +314,11 @@ describe("upcaster: async (Marten AsyncOnlyEventUpcaster — DB-Lookups)", () =>
327
314
 
328
315
  r.eventMigration("placed", 1, 2, async (payload, ctx) => {
329
316
  const p = payload as { customerId: string };
330
- const [row] = await ctx.db
331
- .select()
332
- .from(customerSegments)
333
- .where(sql`${customerSegments.customerId} = ${p.customerId}`);
334
- return { customerId: p.customerId, segment: row?.segment ?? "UNKNOWN" };
317
+ const [row] = await selectMany(ctx.db, customerSegments, { customerId: p.customerId });
318
+ return {
319
+ customerId: p.customerId,
320
+ segment: (row as { segment?: string } | undefined)?.segment ?? "UNKNOWN",
321
+ };
335
322
  });
336
323
 
337
324
  r.projection({
@@ -341,7 +328,7 @@ describe("upcaster: async (Marten AsyncOnlyEventUpcaster — DB-Lookups)", () =>
341
328
  apply: {
342
329
  [placed.name]: async (event, tx) => {
343
330
  const p = event.payload as { customerId: string; segment: string };
344
- await tx.insert(asyncSummary).values({
331
+ await insertOne(tx, asyncSummary, {
345
332
  orderId: event.aggregateId,
346
333
  customerId: p.customerId,
347
334
  segment: p.segment,
@@ -384,7 +371,7 @@ describe("upcaster: async (Marten AsyncOnlyEventUpcaster — DB-Lookups)", () =>
384
371
  });
385
372
  expect(result.eventsProcessed).toBe(2);
386
373
 
387
- const rows = await testDb.db.select().from(asyncSummary).orderBy(asyncSummary.orderId);
374
+ const rows = await selectMany(testDb.db, asyncSummary);
388
375
  expect(rows).toHaveLength(2);
389
376
  const byId = new Map(rows.map((r) => [r.orderId, r]));
390
377
  // v1 → v2 via async DB lookup → segment from customer_segments.
@@ -7,13 +7,18 @@
7
7
  // Allowlist: samples/*/migration/, scripts/migrations/, die Definition
8
8
  // selbst, das Guard-Script selbst.
9
9
 
10
- import { sql } from "drizzle-orm";
11
10
  import type { DbRunner } from "../db";
12
11
  import { isUniqueViolation } from "../db/pg-error";
12
+ import {
13
+ eventPredecessorExists,
14
+ findExistingEventVersion,
15
+ insertRawEventBatch,
16
+ insertRawFirstEvent,
17
+ insertRawSubsequentEvent,
18
+ } from "../db/queries/event-store-admin";
13
19
  import type { TenantId } from "../engine/types";
14
20
  import { VersionConflictError } from "./errors";
15
21
  import type { EventMetadata } from "./event-store";
16
- import { eventsTable } from "./events-schema";
17
22
 
18
23
  export type RawEventToAppend = {
19
24
  readonly aggregateId: string;
@@ -55,30 +60,28 @@ export async function appendRaw(runner: DbRunner, event: RawEventToAppend): Prom
55
60
  }
56
61
  }
57
62
 
63
+ function rawEventParams(event: RawEventToAppend, newVersion: number, eventVersion: number) {
64
+ return {
65
+ aggregateId: event.aggregateId,
66
+ aggregateType: event.aggregateType,
67
+ tenantId: event.tenantId,
68
+ newVersion,
69
+ type: event.type,
70
+ eventVersion,
71
+ payloadJson: JSON.stringify(event.payload),
72
+ metadataJson: JSON.stringify(event.metadata),
73
+ createdAt: event.createdAt.toString(),
74
+ createdBy: event.createdBy,
75
+ };
76
+ }
77
+
58
78
  async function insertRawFirst(
59
79
  runner: DbRunner,
60
80
  event: RawEventToAppend,
61
81
  newVersion: number,
62
82
  eventVersion: number,
63
83
  ): Promise<void> {
64
- await runner.execute(sql`
65
- INSERT INTO ${eventsTable} (
66
- aggregate_id, aggregate_type, tenant_id, version,
67
- type, event_version, payload, metadata, created_at, created_by
68
- )
69
- VALUES (
70
- ${event.aggregateId}::uuid,
71
- ${event.aggregateType},
72
- ${event.tenantId}::uuid,
73
- ${newVersion},
74
- ${event.type},
75
- ${eventVersion},
76
- ${JSON.stringify(event.payload)}::jsonb,
77
- ${JSON.stringify(event.metadata)}::jsonb,
78
- ${event.createdAt.toString()}::timestamptz,
79
- ${event.createdBy}
80
- )
81
- `);
84
+ await insertRawFirstEvent(runner, rawEventParams(event, newVersion, eventVersion));
82
85
  }
83
86
 
84
87
  async function insertRawSubsequent(
@@ -87,30 +90,11 @@ async function insertRawSubsequent(
87
90
  newVersion: number,
88
91
  eventVersion: number,
89
92
  ): Promise<void> {
90
- const rows = await runner.execute<{ id: string }>(sql`
91
- INSERT INTO ${eventsTable} (
92
- aggregate_id, aggregate_type, tenant_id, version,
93
- type, event_version, payload, metadata, created_at, created_by
94
- )
95
- SELECT ${event.aggregateId}::uuid,
96
- ${event.aggregateType},
97
- ${event.tenantId}::uuid,
98
- ${newVersion},
99
- ${event.type},
100
- ${eventVersion},
101
- ${JSON.stringify(event.payload)}::jsonb,
102
- ${JSON.stringify(event.metadata)}::jsonb,
103
- ${event.createdAt.toString()}::timestamptz,
104
- ${event.createdBy}
105
- WHERE EXISTS (
106
- SELECT 1 FROM ${eventsTable}
107
- WHERE aggregate_id = ${event.aggregateId}::uuid
108
- AND version = ${event.expectedVersion}
109
- AND tenant_id = ${event.tenantId}::uuid
110
- )
111
- RETURNING id
112
- `);
113
- if (rows.length === 0) {
93
+ const inserted = await insertRawSubsequentEvent(runner, {
94
+ ...rawEventParams(event, newVersion, eventVersion),
95
+ expectedVersion: event.expectedVersion,
96
+ });
97
+ if (!inserted) {
114
98
  throw new VersionConflictError(event.aggregateId, event.expectedVersion);
115
99
  }
116
100
  }
@@ -133,31 +117,28 @@ export async function appendRawBatch(
133
117
  await verifyPredecessors(runner, events);
134
118
  await verifyNoDuplicates(runner, events);
135
119
 
136
- const rows = events.map((e) => {
120
+ const params: unknown[] = [];
121
+ const valuesClauses = events.map((e) => {
137
122
  const newVersion = e.expectedVersion + 1;
138
123
  const eventVersion = e.eventVersion ?? 1;
139
- return sql`(
140
- ${e.aggregateId}::uuid,
141
- ${e.aggregateType},
142
- ${e.tenantId}::uuid,
143
- ${newVersion},
144
- ${e.type},
145
- ${eventVersion},
146
- ${JSON.stringify(e.payload)}::jsonb,
147
- ${JSON.stringify(e.metadata)}::jsonb,
148
- ${e.createdAt.toString()}::timestamptz,
149
- ${e.createdBy}
150
- )`;
124
+ const baseIdx = params.length;
125
+ params.push(
126
+ e.aggregateId,
127
+ e.aggregateType,
128
+ e.tenantId,
129
+ newVersion,
130
+ e.type,
131
+ eventVersion,
132
+ JSON.stringify(e.payload),
133
+ JSON.stringify(e.metadata),
134
+ e.createdAt.toString(),
135
+ e.createdBy,
136
+ );
137
+ return `($${baseIdx + 1}::uuid, $${baseIdx + 2}, $${baseIdx + 3}::uuid, $${baseIdx + 4}, $${baseIdx + 5}, $${baseIdx + 6}, $${baseIdx + 7}::jsonb, $${baseIdx + 8}::jsonb, $${baseIdx + 9}::timestamptz, $${baseIdx + 10})`;
151
138
  });
152
139
 
153
140
  try {
154
- await runner.execute(sql`
155
- INSERT INTO ${eventsTable} (
156
- aggregate_id, aggregate_type, tenant_id, version,
157
- type, event_version, payload, metadata, created_at, created_by
158
- )
159
- VALUES ${sql.join(rows, sql`, `)}
160
- `);
141
+ await insertRawEventBatch(runner, valuesClauses.join(", "), params);
161
142
  } catch (e) {
162
143
  if (isUniqueViolation(e)) {
163
144
  // Pre-flight ran but lost a race against a concurrent writer. Rare for
@@ -221,15 +202,8 @@ async function verifyPredecessors(
221
202
 
222
203
  for (const g of groups.values()) {
223
204
  if (g.minExpected === 0) continue;
224
- const rows = await runner.execute<{ present: boolean }>(sql`
225
- SELECT EXISTS(
226
- SELECT 1 FROM ${eventsTable}
227
- WHERE aggregate_id = ${g.aggregateId}::uuid
228
- AND tenant_id = ${g.tenantId}::uuid
229
- AND version = ${g.minExpected}
230
- ) AS present
231
- `);
232
- if (!rows[0]?.present) {
205
+ const present = await eventPredecessorExists(runner, g.aggregateId, g.tenantId, g.minExpected);
206
+ if (!present) {
233
207
  throw new VersionConflictError(g.aggregateId, g.minExpected);
234
208
  }
235
209
  }
@@ -242,16 +216,14 @@ async function verifyNoDuplicates(
242
216
  runner: DbRunner,
243
217
  events: readonly RawEventToAppend[],
244
218
  ): Promise<void> {
245
- const triples = events.map(
246
- (e) => sql`(${e.tenantId}::uuid, ${e.aggregateId}::uuid, ${e.expectedVersion + 1})`,
247
- );
248
- const rows = await runner.execute<{ aggregate_id: string; version: number }>(sql`
249
- SELECT aggregate_id, version FROM ${eventsTable}
250
- WHERE (tenant_id, aggregate_id, version) IN (${sql.join(triples, sql`, `)})
251
- LIMIT 1
252
- `);
253
- const conflict = rows[0];
219
+ const params: unknown[] = [];
220
+ const tripleClauses = events.map((e) => {
221
+ const baseIdx = params.length;
222
+ params.push(e.tenantId, e.aggregateId, e.expectedVersion + 1);
223
+ return `($${baseIdx + 1}::uuid, $${baseIdx + 2}::uuid, $${baseIdx + 3})`;
224
+ });
225
+ const conflict = await findExistingEventVersion(runner, tripleClauses.join(", "), params);
254
226
  if (conflict) {
255
- throw new VersionConflictError(conflict.aggregate_id, conflict.version - 1);
227
+ throw new VersionConflictError(conflict.aggregateId, conflict.version - 1);
256
228
  }
257
229
  }
@@ -1,6 +1,9 @@
1
- import { and, eq, sql } from "drizzle-orm";
1
+ // sql now comes from native dialect
2
+
2
3
  import type { DbConnection, DbRunner } from "../db/connection";
3
- import { instant, table as pgTable, text, uniqueIndex, uuid } from "../db/dialect";
4
+ import { instant, table as pgTable, sql, text, uniqueIndex, uuid } from "../db/dialect";
5
+ import { upsertArchivedStream } from "../db/queries/event-store";
6
+ import { deleteMany, fetchOne } from "../db/query";
4
7
  import { tableExists } from "../db/schema-inspection";
5
8
  import type { TenantId } from "../engine/types";
6
9
  import { unsafePushTables } from "../stack";
@@ -46,24 +49,13 @@ export type ArchiveStreamArgs = {
46
49
  // aggregate) updates archivedAt/archivedBy to the latest call instead of
47
50
  // failing. That matches Marten's "archive is a state, not an event" model.
48
51
  export async function archiveStream(db: DbRunner, args: ArchiveStreamArgs): Promise<void> {
49
- await db
50
- .insert(archivedStreamsTable)
51
- .values({
52
- tenantId: args.tenantId,
53
- aggregateId: args.aggregateId,
54
- aggregateType: args.aggregateType,
55
- archivedBy: args.archivedBy,
56
- reason: args.reason ?? null,
57
- })
58
- .onConflictDoUpdate({
59
- target: [archivedStreamsTable.tenantId, archivedStreamsTable.aggregateId],
60
- set: {
61
- archivedAt: sql`now()`,
62
- archivedBy: args.archivedBy,
63
- aggregateType: args.aggregateType,
64
- reason: args.reason ?? null,
65
- },
66
- });
52
+ await upsertArchivedStream(db, {
53
+ tenantId: args.tenantId,
54
+ aggregateId: args.aggregateId,
55
+ aggregateType: args.aggregateType,
56
+ archivedBy: args.archivedBy,
57
+ reason: args.reason ?? null,
58
+ });
67
59
  }
68
60
 
69
61
  // Cheap existence probe — issued in the hot read path, so keep the query to
@@ -73,17 +65,8 @@ export async function isStreamArchived(
73
65
  tenantId: TenantId,
74
66
  aggregateId: string,
75
67
  ): Promise<boolean> {
76
- const rows = await db
77
- .select({ one: sql`1` })
78
- .from(archivedStreamsTable)
79
- .where(
80
- and(
81
- eq(archivedStreamsTable.tenantId, tenantId),
82
- eq(archivedStreamsTable.aggregateId, aggregateId),
83
- ),
84
- )
85
- .limit(1);
86
- return rows.length > 0;
68
+ const row = await fetchOne(db, archivedStreamsTable, { tenantId, aggregateId });
69
+ return row !== undefined;
87
70
  }
88
71
 
89
72
  // Undo an archive — restores the stream to writable state. Ops tool. The
@@ -95,12 +78,5 @@ export async function restoreStream(
95
78
  tenantId: TenantId,
96
79
  aggregateId: string,
97
80
  ): Promise<void> {
98
- await db
99
- .delete(archivedStreamsTable)
100
- .where(
101
- and(
102
- eq(archivedStreamsTable.tenantId, tenantId),
103
- eq(archivedStreamsTable.aggregateId, aggregateId),
104
- ),
105
- );
81
+ await deleteMany(db, archivedStreamsTable, { tenantId, aggregateId });
106
82
  }