@cosmicdrift/kumiko-bundled-features 0.14.0 → 0.16.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 (269) hide show
  1. package/package.json +2 -2
  2. package/src/__tests__/env-schemas.test.ts +1 -1
  3. package/src/__tests__/es-ops-e2e.integration.ts +10 -9
  4. package/src/audit/__tests__/audit.integration.ts +3 -3
  5. package/src/audit/handlers/list.query.ts +39 -51
  6. package/src/auth-email-password/__tests__/account-lockout-no-redis.integration.ts +4 -3
  7. package/src/auth-email-password/__tests__/account-lockout.integration.ts +4 -3
  8. package/src/auth-email-password/__tests__/auth-claims.integration.ts +5 -4
  9. package/src/auth-email-password/__tests__/auth.integration.ts +4 -3
  10. package/src/auth-email-password/__tests__/confirm-token-flow.test.ts +1 -1
  11. package/src/auth-email-password/__tests__/email-templates.test.ts +1 -1
  12. package/src/auth-email-password/__tests__/email-verification.integration.ts +7 -10
  13. package/src/auth-email-password/__tests__/identity-v3-hash.test.ts +1 -1
  14. package/src/auth-email-password/__tests__/identity-v3-login.integration.ts +4 -3
  15. package/src/auth-email-password/__tests__/invite-flow.integration.ts +16 -43
  16. package/src/auth-email-password/__tests__/multi-roles.integration.ts +6 -9
  17. package/src/auth-email-password/__tests__/password-reset.integration.ts +8 -7
  18. package/src/auth-email-password/__tests__/public-routes-rate-limit.integration.ts +4 -3
  19. package/src/auth-email-password/__tests__/seed-admin.integration.ts +19 -32
  20. package/src/auth-email-password/__tests__/session-callbacks.integration.ts +6 -5
  21. package/src/auth-email-password/__tests__/session-strict-mode.integration.ts +1 -1
  22. package/src/auth-email-password/__tests__/signed-token.test.ts +1 -1
  23. package/src/auth-email-password/__tests__/signup-flow.integration.ts +11 -15
  24. package/src/auth-email-password/handlers/invite-accept-with-login.write.ts +26 -26
  25. package/src/auth-email-password/handlers/invite-accept.write.ts +24 -21
  26. package/src/auth-email-password/handlers/invite-create.write.ts +3 -8
  27. package/src/auth-email-password/handlers/invite-signup-complete.write.ts +20 -17
  28. package/src/auth-email-password/handlers/signup-confirm.write.ts +3 -7
  29. package/src/auth-email-password/seeding.ts +1 -1
  30. package/src/auth-email-password/web/__tests__/auth-gate.test.tsx +1 -2
  31. package/src/auth-email-password/web/__tests__/forgot-password-screen.test.tsx +10 -19
  32. package/src/auth-email-password/web/__tests__/login-screen.test.tsx +12 -18
  33. package/src/auth-email-password/web/__tests__/reset-password-screen.test.tsx +12 -17
  34. package/src/auth-email-password/web/__tests__/session-roles.test.ts +1 -1
  35. package/src/auth-email-password/web/__tests__/tenant-switcher.test.tsx +1 -8
  36. package/src/auth-email-password/web/__tests__/test-utils.tsx +4 -8
  37. package/src/auth-email-password/web/__tests__/user-menu.test.tsx +2 -8
  38. package/src/auth-email-password/web/__tests__/verify-email-screen.test.tsx +10 -15
  39. package/src/billing-foundation/__tests__/billing-foundation.integration.ts +1 -1
  40. package/src/billing-foundation/__tests__/feature.test.ts +1 -1
  41. package/src/billing-foundation/__tests__/webhook-handler.test.ts +6 -5
  42. package/src/billing-foundation/db/queries/subscription-projection.ts +15 -0
  43. package/src/billing-foundation/get-subscription-for-tenant.ts +2 -6
  44. package/src/billing-foundation/handlers/create-portal-session.write.ts +2 -2
  45. package/src/billing-foundation/handlers/list-subscriptions.query.ts +4 -1
  46. package/src/billing-foundation/projection.ts +32 -13
  47. package/src/cap-counter/__tests__/cap-counter.integration.ts +1 -1
  48. package/src/cap-counter/__tests__/enforce-cap.test.ts +37 -32
  49. package/src/cap-counter/__tests__/with-cap-enforcement.integration.ts +1 -1
  50. package/src/cap-counter/enforce-cap.ts +14 -20
  51. package/src/cap-counter/handlers/get-counter.query.ts +7 -13
  52. package/src/cap-counter/handlers/increment.write.ts +2 -2
  53. package/src/cap-counter/handlers/mark-soft-warned.write.ts +2 -2
  54. package/src/channel-in-app/handlers/inbox.query.ts +7 -13
  55. package/src/channel-in-app/handlers/mark-all-read.write.ts +7 -9
  56. package/src/channel-in-app/handlers/mark-read.write.ts +8 -14
  57. package/src/channel-in-app/handlers/unread-count.query.ts +10 -9
  58. package/src/channel-in-app/in-app-channel.ts +10 -12
  59. package/src/channel-in-app/tables.ts +1 -1
  60. package/src/compliance-profiles/__tests__/compliance-profiles.integration.ts +1 -1
  61. package/src/compliance-profiles/__tests__/seeding.integration.ts +1 -1
  62. package/src/compliance-profiles/_internal/parse-override.ts +19 -0
  63. package/src/compliance-profiles/handlers/for-tenant.query.ts +10 -32
  64. package/src/compliance-profiles/handlers/needs-profile.query.ts +4 -7
  65. package/src/compliance-profiles/handlers/set-profile.write.ts +5 -7
  66. package/src/compliance-profiles/resolve-for-tenant.ts +11 -27
  67. package/src/compliance-profiles/schema/profile-selection.ts +2 -2
  68. package/src/compliance-profiles/seeding.ts +4 -7
  69. package/src/config/__tests__/app-overrides.test.ts +1 -1
  70. package/src/config/__tests__/cascade.integration.ts +1 -1
  71. package/src/config/__tests__/config.integration.ts +8 -27
  72. package/src/config/db/queries/resolver.ts +47 -0
  73. package/src/config/handlers/__tests__/prepare-config-write.test.ts +1 -1
  74. package/src/config/resolver.ts +14 -62
  75. package/src/config/table.ts +4 -4
  76. package/src/config/write-helpers.ts +7 -11
  77. package/src/custom-fields/__tests__/audit-integration.integration.ts +6 -6
  78. package/src/custom-fields/__tests__/custom-fields.integration.ts +7 -7
  79. package/src/custom-fields/__tests__/feature.test.ts +1 -1
  80. package/src/custom-fields/__tests__/field-access.integration.ts +6 -6
  81. package/src/custom-fields/__tests__/quota.integration.ts +6 -6
  82. package/src/custom-fields/__tests__/retention.integration.ts +12 -10
  83. package/src/custom-fields/__tests__/user-data-rights.integration.ts +27 -17
  84. package/src/custom-fields/__tests__/wire-for-entity.test.ts +5 -5
  85. package/src/custom-fields/db/queries/field-access.ts +16 -0
  86. package/src/custom-fields/db/queries/projection.ts +43 -0
  87. package/src/custom-fields/db/queries/quota.ts +14 -0
  88. package/src/custom-fields/db/queries/retention.ts +39 -0
  89. package/src/custom-fields/db/queries/user-data-rights.ts +54 -0
  90. package/src/custom-fields/lib/field-access.ts +2 -41
  91. package/src/custom-fields/lib/quota.ts +2 -25
  92. package/src/custom-fields/run-retention.ts +19 -21
  93. package/src/custom-fields/wire-for-entity.ts +30 -23
  94. package/src/custom-fields/wire-user-data-rights.ts +33 -85
  95. package/src/data-retention/__tests__/data-retention.integration.ts +1 -1
  96. package/src/data-retention/__tests__/keep-for.test.ts +1 -1
  97. package/src/data-retention/__tests__/override-schema.test.ts +1 -1
  98. package/src/data-retention/__tests__/policy-for.integration.ts +1 -1
  99. package/src/data-retention/__tests__/resolver.test.ts +1 -1
  100. package/src/data-retention/handlers/policy-for.query.ts +5 -8
  101. package/src/data-retention/resolve-for-tenant.ts +6 -8
  102. package/src/data-retention/schema/tenant-retention-override.ts +2 -2
  103. package/src/delivery/__tests__/delivery-events.integration.ts +8 -21
  104. package/src/delivery/__tests__/delivery.integration.ts +100 -190
  105. package/src/delivery/db/queries/preferences.ts +30 -0
  106. package/src/delivery/delivery-service.ts +8 -36
  107. package/src/delivery/feature.ts +10 -2
  108. package/src/delivery/handlers/log.query.ts +5 -7
  109. package/src/delivery/handlers/preferences.query.ts +2 -5
  110. package/src/delivery/tables.ts +26 -1
  111. package/src/delivery/upsert-preference.ts +8 -14
  112. package/src/feature-toggles/__tests__/feature-toggles.integration.ts +30 -30
  113. package/src/feature-toggles/__tests__/registered-system-tenant.test.ts +7 -6
  114. package/src/feature-toggles/db/queries/toggle-state.ts +25 -0
  115. package/src/feature-toggles/feature.ts +16 -2
  116. package/src/feature-toggles/global-feature-state-table.ts +1 -1
  117. package/src/feature-toggles/handlers/list.query.ts +9 -2
  118. package/src/feature-toggles/handlers/registered.query.ts +3 -7
  119. package/src/feature-toggles/handlers/set.write.ts +37 -25
  120. package/src/feature-toggles/toggle-runtime.ts +3 -6
  121. package/src/file-foundation/__tests__/feature.test.ts +1 -1
  122. package/src/file-foundation/__tests__/file-foundation.integration.ts +1 -1
  123. package/src/file-provider-inmemory/__tests__/feature.test.ts +1 -1
  124. package/src/file-provider-s3/__tests__/feature.test.ts +1 -1
  125. package/src/files/__tests__/files.integration.ts +18 -7
  126. package/src/files/schema/file-ref.ts +1 -1
  127. package/src/files-provider-s3/__tests__/env-helper.test.ts +1 -1
  128. package/src/files-provider-s3/__tests__/s3-provider.integration.ts +1 -1
  129. package/src/files-provider-s3/__tests__/s3-provider.test.ts +1 -1
  130. package/src/jobs/__tests__/job-system-user.integration.ts +1 -1
  131. package/src/jobs/__tests__/jobs-events.integration.ts +8 -21
  132. package/src/jobs/__tests__/jobs-feature.integration.ts +1 -1
  133. package/src/jobs/feature.ts +26 -15
  134. package/src/jobs/handlers/detail.query.ts +10 -8
  135. package/src/jobs/handlers/list.query.ts +9 -21
  136. package/src/jobs/handlers/retry.write.ts +2 -7
  137. package/src/jobs/job-run-logger.ts +3 -9
  138. package/src/jobs/job-run-table.ts +49 -17
  139. package/src/legal-pages/__tests__/legal-pages.integration.ts +1 -1
  140. package/src/mail-foundation/__tests__/feature.test.ts +1 -1
  141. package/src/mail-foundation/__tests__/mail-foundation.integration.ts +1 -1
  142. package/src/mail-transport-inmemory/__tests__/feature.test.ts +1 -1
  143. package/src/mail-transport-smtp/__tests__/feature.test.ts +1 -1
  144. package/src/rate-limiting/__tests__/rate-limiting.integration.ts +1 -1
  145. package/src/renderer-foundation/__tests__/api.test.ts +2 -2
  146. package/src/renderer-foundation/__tests__/collect-plugins.integration.ts +1 -1
  147. package/src/renderer-simple/__tests__/adapter.test.ts +2 -2
  148. package/src/renderer-simple/__tests__/simple-renderer.test.ts +1 -1
  149. package/src/secrets/__tests__/require-secrets-context.test.ts +6 -5
  150. package/src/secrets/__tests__/rotate.integration.ts +6 -9
  151. package/src/secrets/__tests__/secrets-events.integration.ts +6 -12
  152. package/src/secrets/__tests__/secrets.integration.ts +6 -11
  153. package/src/secrets/db/queries/read.ts +16 -0
  154. package/src/secrets/handlers/list.query.ts +16 -17
  155. package/src/secrets/handlers/rotate.job.ts +8 -12
  156. package/src/secrets/secrets-context.ts +9 -21
  157. package/src/secrets/table.ts +1 -1
  158. package/src/sessions/__tests__/cleanup.integration.ts +8 -6
  159. package/src/sessions/__tests__/password-auto-revoke.integration.ts +7 -6
  160. package/src/sessions/__tests__/sessions.integration.ts +23 -38
  161. package/src/sessions/__tests__/test-helpers.ts +1 -1
  162. package/src/sessions/db/queries/cleanup.ts +21 -0
  163. package/src/sessions/handlers/cleanup.job.ts +6 -29
  164. package/src/sessions/handlers/list.query.ts +24 -24
  165. package/src/sessions/handlers/mine.query.ts +24 -23
  166. package/src/sessions/handlers/revoke-all-for-user.write.ts +7 -11
  167. package/src/sessions/handlers/revoke-all-others.write.ts +7 -12
  168. package/src/sessions/handlers/revoke.write.ts +11 -18
  169. package/src/sessions/schema/user-session.ts +2 -2
  170. package/src/sessions/session-callbacks.ts +19 -21
  171. package/src/subscription-mollie/__tests__/feature.test.ts +1 -1
  172. package/src/subscription-mollie/__tests__/mollie-foundation.integration.ts +1 -1
  173. package/src/subscription-mollie/__tests__/verify-webhook.test.ts +8 -7
  174. package/src/subscription-stripe/__tests__/feature.test.ts +1 -1
  175. package/src/subscription-stripe/__tests__/plugin-methods.test.ts +14 -15
  176. package/src/subscription-stripe/__tests__/stripe-foundation.integration.ts +1 -1
  177. package/src/subscription-stripe/__tests__/verify-webhook.test.ts +14 -14
  178. package/src/subscription-stripe/verify-webhook.ts +1 -1
  179. package/src/template-resolver/__tests__/handlers.integration.ts +1 -1
  180. package/src/template-resolver/__tests__/template-resolver.integration.ts +3 -2
  181. package/src/template-resolver/api.ts +7 -13
  182. package/src/template-resolver/handlers/archive.write.ts +4 -7
  183. package/src/template-resolver/handlers/find-by-id.query.ts +4 -7
  184. package/src/template-resolver/handlers/list.query.ts +13 -21
  185. package/src/template-resolver/handlers/publish.write.ts +4 -7
  186. package/src/template-resolver/handlers/upsert-system.write.ts +7 -10
  187. package/src/template-resolver/handlers/upsert-tenant.write.ts +7 -10
  188. package/src/template-resolver/table.ts +2 -5
  189. package/src/tenant/__tests__/multi-tenant.integration.ts +1 -1
  190. package/src/tenant/__tests__/seed-testing.integration.ts +19 -45
  191. package/src/tenant/__tests__/tenant.integration.ts +1 -1
  192. package/src/tenant/handlers/active-tenant-ids.query.ts +3 -8
  193. package/src/tenant/handlers/add-member.write.ts +6 -8
  194. package/src/tenant/handlers/cancel-invitation.write.ts +5 -7
  195. package/src/tenant/handlers/invitations.query.ts +5 -10
  196. package/src/tenant/handlers/me.query.ts +2 -3
  197. package/src/tenant/handlers/members.query.ts +4 -5
  198. package/src/tenant/handlers/memberships.query.ts +2 -5
  199. package/src/tenant/handlers/remove-member.write.ts +6 -8
  200. package/src/tenant/handlers/resolve-user-ids.query.ts +6 -16
  201. package/src/tenant/handlers/update-member-roles.write.ts +6 -8
  202. package/src/tenant/invitation-table.ts +2 -5
  203. package/src/tenant/membership-table.ts +3 -6
  204. package/src/tenant/schema/tenant.ts +2 -2
  205. package/src/tenant/seeding.ts +12 -18
  206. package/src/text-content/README.md +1 -1
  207. package/src/text-content/__tests__/text-content.integration.ts +2 -2
  208. package/src/text-content/api.ts +2 -9
  209. package/src/text-content/handlers/by-slug.query.ts +6 -9
  210. package/src/text-content/handlers/by-tenant.query.ts +2 -2
  211. package/src/text-content/handlers/set.write.ts +7 -9
  212. package/src/text-content/seeding.ts +6 -9
  213. package/src/text-content/table.ts +2 -2
  214. package/src/text-content/web/__tests__/editor-read-only.test.tsx +31 -45
  215. package/src/text-content/web/__tests__/group-blocks.test.ts +1 -18
  216. package/src/text-content/web/client-plugin.tsx +11 -23
  217. package/src/tier-engine/__tests__/auto-default-tier.integration.ts +10 -16
  218. package/src/tier-engine/__tests__/compose-app.test.ts +1 -1
  219. package/src/tier-engine/__tests__/drift.test.ts +1 -1
  220. package/src/tier-engine/__tests__/resolver.integration.ts +6 -6
  221. package/src/tier-engine/__tests__/tier-engine.integration.ts +1 -1
  222. package/src/tier-engine/feature.ts +9 -16
  223. package/src/user/__tests__/seed-testing.integration.ts +10 -22
  224. package/src/user/__tests__/user-status.test.ts +1 -1
  225. package/src/user/__tests__/user.integration.ts +6 -5
  226. package/src/user/handlers/create.write.ts +5 -7
  227. package/src/user/handlers/find-for-auth.query.ts +5 -7
  228. package/src/user/schema/user.ts +2 -2
  229. package/src/user/seeding.ts +2 -3
  230. package/src/user-data-rights/__tests__/audit-log.integration.ts +24 -12
  231. package/src/user-data-rights/__tests__/cross-data-matrix.integration.ts +64 -37
  232. package/src/user-data-rights/__tests__/download.integration.ts +29 -46
  233. package/src/user-data-rights/__tests__/export-job-idempotency.integration.ts +35 -28
  234. package/src/user-data-rights/__tests__/export-job-schema.test.ts +2 -2
  235. package/src/user-data-rights/__tests__/policy-to-strategy.test.ts +1 -1
  236. package/src/user-data-rights/__tests__/request-cancel-deletion.integration.ts +11 -15
  237. package/src/user-data-rights/__tests__/request-deletion-callback.integration.ts +10 -12
  238. package/src/user-data-rights/__tests__/request-export.integration.ts +23 -16
  239. package/src/user-data-rights/__tests__/restriction-flow.integration.ts +24 -32
  240. package/src/user-data-rights/__tests__/run-export-jobs.integration.ts +142 -137
  241. package/src/user-data-rights/__tests__/run-forget-cleanup.integration.ts +46 -28
  242. package/src/user-data-rights/__tests__/run-user-export.integration.ts +20 -14
  243. package/src/user-data-rights/__tests__/token-helpers.test.ts +1 -1
  244. package/src/user-data-rights/__tests__/user-data-rights.integration.ts +1 -1
  245. package/src/user-data-rights/__tests__/zip-path.test.ts +1 -1
  246. package/src/user-data-rights/audit-download.ts +3 -3
  247. package/src/user-data-rights/db/queries/export-jobs.ts +23 -0
  248. package/src/user-data-rights/db/queries/forget-cleanup.ts +13 -0
  249. package/src/user-data-rights/handlers/cancel-deletion.write.ts +28 -22
  250. package/src/user-data-rights/handlers/download-by-job.query.ts +11 -21
  251. package/src/user-data-rights/handlers/download-by-token.query.ts +20 -35
  252. package/src/user-data-rights/handlers/export-status.query.ts +19 -33
  253. package/src/user-data-rights/handlers/lift-restriction.write.ts +7 -12
  254. package/src/user-data-rights/handlers/list-download-attempts.query.ts +14 -23
  255. package/src/user-data-rights/handlers/my-audit-log.query.ts +33 -23
  256. package/src/user-data-rights/handlers/request-deletion.write.ts +15 -15
  257. package/src/user-data-rights/handlers/request-export.write.ts +7 -11
  258. package/src/user-data-rights/handlers/restrict-account.write.ts +12 -12
  259. package/src/user-data-rights/run-export-jobs.ts +20 -60
  260. package/src/user-data-rights/run-forget-cleanup.ts +19 -33
  261. package/src/user-data-rights/run-user-export.ts +4 -6
  262. package/src/user-data-rights/schema/download-attempt.ts +2 -2
  263. package/src/user-data-rights/schema/download-token.ts +2 -2
  264. package/src/user-data-rights/schema/export-job.ts +2 -3
  265. package/src/user-data-rights-defaults/__tests__/user-data-rights-defaults.integration.ts +37 -30
  266. package/src/user-data-rights-defaults/db/queries/user-hook.ts +17 -0
  267. package/src/user-data-rights-defaults/hooks/file-ref.userdata-hook.ts +12 -27
  268. package/src/user-data-rights-defaults/hooks/user.userdata-hook.ts +16 -18
  269. package/CHANGELOG.md +0 -689
@@ -72,7 +72,7 @@ export function verifyAndParseStripeWebhook(
72
72
  // mapped throw → HTTP 401.
73
73
  let event: Stripe.Event;
74
74
  try {
75
- event = stripe.webhooks.constructEvent(rawBody, sigHeader, options.webhookSecret);
75
+ event = await stripe.webhooks.constructEventAsync(rawBody, sigHeader, options.webhookSecret);
76
76
  } catch (e) {
77
77
  const msg = e instanceof Error ? e.message : String(e);
78
78
  throw new Error(`subscription-stripe: webhook signature verify failed — ${msg}`);
@@ -1,3 +1,4 @@
1
+ import { afterAll, beforeAll, describe, expect, test } from "bun:test";
1
2
  import type { DbConnection } from "@cosmicdrift/kumiko-framework/db";
2
3
  import { SYSTEM_TENANT_ID } from "@cosmicdrift/kumiko-framework/engine";
3
4
  import { createEventsTable } from "@cosmicdrift/kumiko-framework/event-store";
@@ -10,7 +11,6 @@ import {
10
11
  unsafeCreateEntityTable,
11
12
  } from "@cosmicdrift/kumiko-framework/stack";
12
13
  import { expectErrorIncludes } from "@cosmicdrift/kumiko-framework/testing";
13
- import { afterAll, beforeAll, describe, expect, test } from "vitest";
14
14
  import { createTemplateResolverFeature } from "../feature";
15
15
  import { TemplateResolverHandlers, TemplateResolverQueries } from "../qualified-names";
16
16
  import { templateResourceEntity } from "../table";
@@ -1,10 +1,11 @@
1
+ import { afterAll, beforeAll, describe, expect, test } from "bun:test";
2
+ import { insertOne } from "@cosmicdrift/kumiko-framework/bun-db";
1
3
  import type { DbConnection } from "@cosmicdrift/kumiko-framework/db";
2
4
  import {
3
5
  setupTestStack,
4
6
  type TestStack,
5
7
  unsafeCreateEntityTable,
6
8
  } from "@cosmicdrift/kumiko-framework/stack";
7
- import { afterAll, beforeAll, describe, expect, test } from "vitest";
8
9
  import { createTemplateResolverApi, TemplateNotFoundError, type TemplateResolverApi } from "../api";
9
10
  import {
10
11
  type ContentFormat,
@@ -55,7 +56,7 @@ async function seedTemplate(args: {
55
56
  linkedResources?: Record<string, string>;
56
57
  parentTemplateId?: string;
57
58
  }) {
58
- await db.insert(templateResourcesTable).values({
59
+ await insertOne(db, templateResourcesTable, {
59
60
  tenantId: args.tenantId,
60
61
  slug: args.slug,
61
62
  kind: args.kind,
@@ -3,10 +3,10 @@
3
3
  // runtime aus ctx.templateResolver. Pattern symmetrisch zu textContent
4
4
  // (siehe text-content/api.ts).
5
5
 
6
+ import { selectMany } from "@cosmicdrift/kumiko-framework/bun-db";
6
7
  import type { DbConnection } from "@cosmicdrift/kumiko-framework/db";
7
8
  import type { SessionUser, TenantId } from "@cosmicdrift/kumiko-framework/engine";
8
9
  import { InternalError } from "@cosmicdrift/kumiko-framework/errors";
9
- import { and, eq } from "drizzle-orm";
10
10
  import type { ContentFormat, RenderKind } from "./constants";
11
11
  import { FALLBACK_LOCALE, SYSTEM_TENANT_ID } from "./constants";
12
12
  import { type TemplateResourceRow, templateResourcesTable } from "./table";
@@ -111,18 +111,12 @@ async function fetchTemplate(
111
111
  kind: RenderKind,
112
112
  locale: string,
113
113
  ): Promise<TemplateResourceRow | null> {
114
- const rows = await db
115
- .select()
116
- .from(templateResourcesTable)
117
- .where(
118
- and(
119
- eq(templateResourcesTable["tenantId"], tenantId),
120
- eq(templateResourcesTable["slug"], slug),
121
- eq(templateResourcesTable["kind"], kind),
122
- eq(templateResourcesTable["locale"], locale),
123
- ),
124
- )
125
- .limit(1);
114
+ const rows = await selectMany(
115
+ db,
116
+ templateResourcesTable,
117
+ { tenantId, slug, kind, locale },
118
+ { limit: 1 },
119
+ );
126
120
  // @cast-boundary db-row — db.select returnt unbenanntes unknown[],
127
121
  // Row-Shape ist via templateResourcesTable + buildBaseColumns garantiert.
128
122
  return (rows[0] as TemplateResourceRow | undefined) ?? null;
@@ -1,7 +1,6 @@
1
- import { fetchOne } from "@cosmicdrift/kumiko-framework/db";
1
+ import { fetchOne } from "@cosmicdrift/kumiko-framework/bun-db";
2
2
  import { defineWriteHandler } from "@cosmicdrift/kumiko-framework/engine";
3
3
  import { NotFoundError, writeFailure } from "@cosmicdrift/kumiko-framework/errors";
4
- import { eq } from "drizzle-orm";
5
4
  import { z } from "zod";
6
5
  import type { TemplateResourceRow } from "../table";
7
6
  import { templateResourcesTable } from "../table";
@@ -15,11 +14,9 @@ export const archiveWrite = defineWriteHandler({
15
14
  schema: z.object({ id: z.string().min(1) }),
16
15
  access: { roles: ["TenantAdmin", "SystemAdmin"] },
17
16
  handler: async (event, ctx) => {
18
- const existing = await fetchOne<TemplateResourceRow>(
19
- ctx.db,
20
- templateResourcesTable,
21
- eq(templateResourcesTable["id"], event.payload.id),
22
- );
17
+ const existing = await fetchOne<TemplateResourceRow>(ctx.db, templateResourcesTable, {
18
+ id: event.payload.id,
19
+ });
23
20
  // ctx.db ist via createTenantDb tenant-scoped — existing ist null wenn
24
21
  // das Template einem fremden Tenant gehört (SystemAdmin-Cross-Tenant
25
22
  // braucht tenantIdOverride im Schema, M2-Erweiterung).
@@ -1,6 +1,5 @@
1
- import { fetchOne } from "@cosmicdrift/kumiko-framework/db";
1
+ import { fetchOne } from "@cosmicdrift/kumiko-framework/bun-db";
2
2
  import { defineQueryHandler } from "@cosmicdrift/kumiko-framework/engine";
3
- import { eq } from "drizzle-orm";
4
3
  import { z } from "zod";
5
4
  import { type TemplateResourceRow, templateResourcesTable } from "../table";
6
5
 
@@ -14,11 +13,9 @@ export const findByIdQuery = defineQueryHandler({
14
13
  schema: z.object({ id: z.string().min(1) }),
15
14
  access: { roles: ["TenantAdmin", "SystemAdmin", "User"] },
16
15
  handler: async (query, ctx) => {
17
- const row = await fetchOne<TemplateResourceRow>(
18
- ctx.db,
19
- templateResourcesTable,
20
- eq(templateResourcesTable["id"], query.payload.id),
21
- );
16
+ const row = await fetchOne<TemplateResourceRow>(ctx.db, templateResourcesTable, {
17
+ id: query.payload.id,
18
+ });
22
19
  if (!row) return null;
23
20
  const isSystemAdmin = query.user.roles.includes("SystemAdmin");
24
21
  const isOwnTenant = row.tenantId === query.user.tenantId;
@@ -1,5 +1,5 @@
1
+ import { selectMany } from "@cosmicdrift/kumiko-framework/bun-db";
1
2
  import { defineQueryHandler, SYSTEM_TENANT_ID } from "@cosmicdrift/kumiko-framework/engine";
2
- import { and, eq, or, type SQL } from "drizzle-orm";
3
3
  import { z } from "zod";
4
4
  import { RENDER_KINDS, TEMPLATE_STATUSES } from "../constants";
5
5
  import { type TemplateResourceRow, templateResourcesTable } from "../table";
@@ -18,43 +18,35 @@ export const listQuery = defineQueryHandler({
18
18
  access: { roles: ["TenantAdmin", "SystemAdmin", "User"] },
19
19
  handler: async (query, ctx) => {
20
20
  const isSystemAdmin = query.user.roles.includes("SystemAdmin");
21
- const conditions: SQL<unknown>[] = [];
21
+ const where: Record<string, unknown> = {};
22
22
 
23
23
  // Tenant-Scope: SystemAdmin sieht alles, andere nur eigener Tenant + System
24
24
  if (!isSystemAdmin) {
25
25
  if (query.payload.includeSystem) {
26
- const scopeCondition = or(
27
- eq(templateResourcesTable["tenantId"], query.user.tenantId),
28
- eq(templateResourcesTable["tenantId"], SYSTEM_TENANT_ID),
29
- );
30
- if (scopeCondition) conditions.push(scopeCondition);
26
+ where["tenantId"] = [query.user.tenantId, SYSTEM_TENANT_ID];
31
27
  } else {
32
- conditions.push(eq(templateResourcesTable["tenantId"], query.user.tenantId));
28
+ where["tenantId"] = query.user.tenantId;
33
29
  }
34
30
  } else if (!query.payload.includeSystem) {
35
- // SystemAdmin mit includeSystem=false → noch eigener Tenant only
36
- conditions.push(eq(templateResourcesTable["tenantId"], query.user.tenantId));
31
+ // SystemAdmin mit includeSystem=false → nur eigener Tenant
32
+ where["tenantId"] = query.user.tenantId;
37
33
  }
38
34
 
39
35
  if (query.payload.kind) {
40
- conditions.push(eq(templateResourcesTable["kind"], query.payload.kind));
36
+ where["kind"] = query.payload.kind;
41
37
  }
42
38
  if (query.payload.locale) {
43
- conditions.push(eq(templateResourcesTable["locale"], query.payload.locale));
39
+ where["locale"] = query.payload.locale;
44
40
  }
45
41
  if (query.payload.status) {
46
- conditions.push(eq(templateResourcesTable["status"], query.payload.status));
42
+ where["status"] = query.payload.status;
47
43
  }
48
44
 
49
- const whereExpr = conditions.length > 0 ? and(...conditions) : undefined;
50
-
51
- // @cast-boundary db-row — db.select returnt unknown[]; Row-Shape ist
45
+ // @cast-boundary db-row selectMany returnt unknown[]; Row-Shape ist
52
46
  // durch templateResourcesTable + buildBaseColumns garantiert.
53
- const rows = (await ctx.db
54
- .select()
55
- .from(templateResourcesTable)
56
- .where(whereExpr)
57
- .limit(500)) as TemplateResourceRow[];
47
+ const rows = (await selectMany(ctx.db, templateResourcesTable, where, {
48
+ limit: 500,
49
+ })) as TemplateResourceRow[];
58
50
 
59
51
  return rows.map((row) => ({
60
52
  id: String(row.id),
@@ -1,7 +1,6 @@
1
- import { fetchOne } from "@cosmicdrift/kumiko-framework/db";
1
+ import { fetchOne } from "@cosmicdrift/kumiko-framework/bun-db";
2
2
  import { defineWriteHandler } from "@cosmicdrift/kumiko-framework/engine";
3
3
  import { NotFoundError, writeFailure } from "@cosmicdrift/kumiko-framework/errors";
4
- import { eq } from "drizzle-orm";
5
4
  import { z } from "zod";
6
5
  import type { TemplateResourceRow } from "../table";
7
6
  import { templateResourcesTable } from "../table";
@@ -18,11 +17,9 @@ export const publishWrite = defineWriteHandler({
18
17
  schema: z.object({ id: z.string().min(1) }),
19
18
  access: { roles: ["TenantAdmin", "SystemAdmin"] },
20
19
  handler: async (event, ctx) => {
21
- const existing = await fetchOne<TemplateResourceRow>(
22
- ctx.db,
23
- templateResourcesTable,
24
- eq(templateResourcesTable["id"], event.payload.id),
25
- );
20
+ const existing = await fetchOne<TemplateResourceRow>(ctx.db, templateResourcesTable, {
21
+ id: event.payload.id,
22
+ });
26
23
  // ctx.db ist via createTenantDb tenant-scoped — existing ist null wenn
27
24
  // das Template einem fremden Tenant gehört (SystemAdmin-Cross-Tenant
28
25
  // braucht tenantIdOverride im Schema, M2-Erweiterung).
@@ -1,10 +1,9 @@
1
- import { fetchOne } from "@cosmicdrift/kumiko-framework/db";
1
+ import { fetchOne } from "@cosmicdrift/kumiko-framework/bun-db";
2
2
  import {
3
3
  defineWriteHandler,
4
4
  SYSTEM_TENANT_ID,
5
5
  type TenantId,
6
6
  } from "@cosmicdrift/kumiko-framework/engine";
7
- import { eq } from "drizzle-orm";
8
7
  import type { TemplateResourceRow } from "../table";
9
8
  import { templateResourcesTable } from "../table";
10
9
  import { executor, upsertPayloadSchema } from "./shared";
@@ -27,14 +26,12 @@ export const upsertSystemWrite = defineWriteHandler({
27
26
  // Pattern symmetrisch zu text-content setWrite Override-Branch.
28
27
  const executorUser = { ...event.user, tenantId };
29
28
 
30
- const existing = await fetchOne<TemplateResourceRow>(
31
- db,
32
- templateResourcesTable,
33
- eq(templateResourcesTable["tenantId"], tenantId),
34
- eq(templateResourcesTable["slug"], event.payload.slug),
35
- eq(templateResourcesTable["kind"], event.payload.kind),
36
- eq(templateResourcesTable["locale"], event.payload.locale),
37
- );
29
+ const existing = await fetchOne<TemplateResourceRow>(db, templateResourcesTable, {
30
+ tenantId,
31
+ slug: event.payload.slug,
32
+ kind: event.payload.kind,
33
+ locale: event.payload.locale,
34
+ });
38
35
 
39
36
  const fields = {
40
37
  slug: event.payload.slug,
@@ -1,11 +1,10 @@
1
- import { fetchOne } from "@cosmicdrift/kumiko-framework/db";
1
+ import { fetchOne } from "@cosmicdrift/kumiko-framework/bun-db";
2
2
  import {
3
3
  defineWriteHandler,
4
4
  SYSTEM_TENANT_ID,
5
5
  type TenantId,
6
6
  } from "@cosmicdrift/kumiko-framework/engine";
7
7
  import { AccessDeniedError, writeFailure } from "@cosmicdrift/kumiko-framework/errors";
8
- import { eq } from "drizzle-orm";
9
8
  import { z } from "zod";
10
9
  import type { TemplateResourceRow } from "../table";
11
10
  import { templateResourcesTable } from "../table";
@@ -52,14 +51,12 @@ export const upsertTenantWrite = defineWriteHandler({
52
51
  const tenantId = (override ?? event.user.tenantId) as TenantId;
53
52
  const executorUser = override !== undefined ? { ...event.user, tenantId } : event.user;
54
53
 
55
- const existing = await fetchOne<TemplateResourceRow>(
56
- db,
57
- templateResourcesTable,
58
- eq(templateResourcesTable["tenantId"], tenantId),
59
- eq(templateResourcesTable["slug"], event.payload.slug),
60
- eq(templateResourcesTable["kind"], event.payload.kind),
61
- eq(templateResourcesTable["locale"], event.payload.locale),
62
- );
54
+ const existing = await fetchOne<TemplateResourceRow>(db, templateResourcesTable, {
55
+ tenantId,
56
+ slug: event.payload.slug,
57
+ kind: event.payload.kind,
58
+ locale: event.payload.locale,
59
+ });
63
60
 
64
61
  const fields = {
65
62
  slug: event.payload.slug,
@@ -1,4 +1,4 @@
1
- import { buildDrizzleTable } from "@cosmicdrift/kumiko-framework/db";
1
+ import { buildEntityTable } from "@cosmicdrift/kumiko-framework/db";
2
2
  import {
3
3
  createEntity,
4
4
  createLongTextField,
@@ -40,10 +40,7 @@ export const templateResourceEntity = createEntity({
40
40
  ],
41
41
  });
42
42
 
43
- export const templateResourcesTable = buildDrizzleTable(
44
- "template-resource",
45
- templateResourceEntity,
46
- );
43
+ export const templateResourcesTable = buildEntityTable("template-resource", templateResourceEntity);
47
44
 
48
45
  // Concrete Row-Type — single-source dafür dass die unknown-Werte die
49
46
  // Drizzle aus `Record<string, unknown>` liefert genau einmal benannt
@@ -1,3 +1,4 @@
1
+ import { afterAll, beforeAll, describe, expect, test } from "bun:test";
1
2
  import { buildServer, type JwtHelper } from "@cosmicdrift/kumiko-framework/api";
2
3
  import { createTenantDb, type DbConnection } from "@cosmicdrift/kumiko-framework/db";
3
4
  import {
@@ -21,7 +22,6 @@ import {
21
22
  } from "@cosmicdrift/kumiko-framework/stack";
22
23
  import { bridgeStub, sleep } from "@cosmicdrift/kumiko-framework/testing";
23
24
  import type { Hono } from "hono";
24
- import { afterAll, beforeAll, describe, expect, test } from "vitest";
25
25
  import { createConfigFeature } from "../../config/feature";
26
26
  import { createConfigResolver } from "../../config/resolver";
27
27
  import { configValuesTable } from "../../config/table";
@@ -11,6 +11,8 @@
11
11
  // 4. The `by`-user shows up as insertedById on the projection — so
12
12
  // audit-queries that join events→users actually find the actor.
13
13
 
14
+ import { afterAll, beforeAll, beforeEach, describe, expect, test } from "bun:test";
15
+ import { asRawClient, selectMany } from "@cosmicdrift/kumiko-framework/bun-db";
14
16
  import type { TenantId } from "@cosmicdrift/kumiko-framework/engine";
15
17
  import { createEventsTable, eventsTable } from "@cosmicdrift/kumiko-framework/event-store";
16
18
  import {
@@ -21,8 +23,6 @@ import {
21
23
  unsafeCreateEntityTable,
22
24
  unsafePushTables,
23
25
  } from "@cosmicdrift/kumiko-framework/stack";
24
- import { and, eq } from "drizzle-orm";
25
- import { afterAll, beforeAll, beforeEach, describe, expect, test } from "vitest";
26
26
  import { createConfigFeature } from "../../config/feature";
27
27
  import { createConfigResolver } from "../../config/resolver";
28
28
  import { configValuesTable } from "../../config/table";
@@ -53,11 +53,11 @@ afterAll(async () => {
53
53
  });
54
54
 
55
55
  beforeEach(async () => {
56
- await stack.db.delete(tenantMembershipsTable);
57
- await stack.db.delete(tenantTable);
56
+ await asRawClient(stack.db).unsafe(`DELETE FROM "${tenantMembershipsTable.tableName}"`);
57
+ await asRawClient(stack.db).unsafe(`DELETE FROM "${tenantTable.tableName}"`);
58
58
  // Events stay — the idempotency test below inspects how many .created
59
59
  // events exist for the same aggregate-key pair across runs.
60
- await stack.db.delete(eventsTable);
60
+ await asRawClient(stack.db).unsafe(`DELETE FROM "${eventsTable.tableName}"`);
61
61
  });
62
62
 
63
63
  describe("seedTenant", () => {
@@ -69,7 +69,7 @@ describe("seedTenant", () => {
69
69
  });
70
70
  expect(id).toBe(TENANT_A);
71
71
 
72
- const rows = await stack.db.select().from(tenantTable).where(eq(tenantTable["id"], TENANT_A));
72
+ const rows = await selectMany(stack.db, tenantTable, { id: TENANT_A });
73
73
  expect(rows).toHaveLength(1);
74
74
  expect(rows[0]?.["id"]).toBe(TENANT_A);
75
75
  expect(rows[0]?.["key"]).toBe("tenant-a");
@@ -78,10 +78,7 @@ describe("seedTenant", () => {
78
78
 
79
79
  test("emittiert tenant.created-Event auf den Aggregate-Stream", async () => {
80
80
  await seedTenant(stack.db, { id: TENANT_A, key: "tenant-a", name: "Tenant A" });
81
- const events = await stack.db
82
- .select()
83
- .from(eventsTable)
84
- .where(eq(eventsTable.aggregateType, "tenant"));
81
+ const events = await selectMany(stack.db, eventsTable, { aggregateType: "tenant" });
85
82
  const createdEvents = events.filter((e) => e.type === "tenant.created");
86
83
  expect(createdEvents).toHaveLength(1);
87
84
  // Aggregate-id steht im event-row (aggregateId), nicht im payload —
@@ -97,21 +94,18 @@ describe("seedTenant", () => {
97
94
  await seedTenant(stack.db, { id: TENANT_A, key: "tenant-a", name: "Tenant A v2" });
98
95
 
99
96
  // Projection bleibt bei Original-name (zweiter Call wurde geskippt, kein update).
100
- const rows = await stack.db.select().from(tenantTable).where(eq(tenantTable["id"], TENANT_A));
97
+ const rows = await selectMany(stack.db, tenantTable, { id: TENANT_A });
101
98
  expect(rows).toHaveLength(1);
102
99
  expect(rows[0]?.["name"]).toBe("Tenant A");
103
100
 
104
- const events = await stack.db
105
- .select()
106
- .from(eventsTable)
107
- .where(eq(eventsTable.aggregateType, "tenant"));
101
+ const events = await selectMany(stack.db, eventsTable, { aggregateType: "tenant" });
108
102
  expect(events.filter((e) => e.type === "tenant.created")).toHaveLength(1);
109
103
  });
110
104
 
111
105
  test("zwei verschiedene Tenants in einem Test — beide in der Projection", async () => {
112
106
  await seedTenant(stack.db, { id: TENANT_A, key: "a", name: "A" });
113
107
  await seedTenant(stack.db, { id: TENANT_B, key: "b", name: "B" });
114
- const rows = await stack.db.select().from(tenantTable);
108
+ const rows = await selectMany(stack.db, tenantTable);
115
109
  expect(rows.map((r) => r["id"]).sort()).toEqual([TENANT_A, TENANT_B].sort());
116
110
  });
117
111
  });
@@ -124,15 +118,10 @@ describe("seedTenantMembership", () => {
124
118
  roles: ["Admin", "Billing"],
125
119
  });
126
120
 
127
- const rows = await stack.db
128
- .select()
129
- .from(tenantMembershipsTable)
130
- .where(
131
- and(
132
- eq(tenantMembershipsTable.userId, ALICE_ID),
133
- eq(tenantMembershipsTable.tenantId, TENANT_A),
134
- ),
135
- );
121
+ const rows = await selectMany(stack.db, tenantMembershipsTable, {
122
+ userId: ALICE_ID,
123
+ tenantId: TENANT_A,
124
+ });
136
125
  expect(rows).toHaveLength(1);
137
126
  expect(rows[0]?.["userId"]).toBe(ALICE_ID);
138
127
  expect(rows[0]?.["tenantId"]).toBe(TENANT_A);
@@ -146,10 +135,7 @@ describe("seedTenantMembership", () => {
146
135
  roles: ["User"],
147
136
  });
148
137
 
149
- const events = await stack.db
150
- .select()
151
- .from(eventsTable)
152
- .where(eq(eventsTable.aggregateType, "tenant-membership"));
138
+ const events = await selectMany(stack.db, eventsTable, { aggregateType: "tenant-membership" });
153
139
  const createdEvents = events.filter((e) => e.type === "tenant-membership.created");
154
140
  expect(createdEvents).toHaveLength(1);
155
141
  // Payload should carry the seeded data — MSPs/audit rely on this.
@@ -180,16 +166,10 @@ describe("seedTenantMembership", () => {
180
166
  roles: ["User"],
181
167
  });
182
168
 
183
- const projectionRows = await stack.db
184
- .select()
185
- .from(tenantMembershipsTable)
186
- .where(eq(tenantMembershipsTable.userId, ALICE_ID));
169
+ const projectionRows = await selectMany(stack.db, tenantMembershipsTable, { userId: ALICE_ID });
187
170
  expect(projectionRows).toHaveLength(1);
188
171
 
189
- const events = await stack.db
190
- .select()
191
- .from(eventsTable)
192
- .where(eq(eventsTable.aggregateType, "tenant-membership"));
172
+ const events = await selectMany(stack.db, eventsTable, { aggregateType: "tenant-membership" });
193
173
  expect(events.filter((e) => e.type === "tenant-membership.created")).toHaveLength(1);
194
174
  });
195
175
 
@@ -205,10 +185,7 @@ describe("seedTenantMembership", () => {
205
185
  by: seedActor,
206
186
  });
207
187
 
208
- const [row] = await stack.db
209
- .select()
210
- .from(tenantMembershipsTable)
211
- .where(eq(tenantMembershipsTable.userId, ALICE_ID));
188
+ const [row] = await selectMany(stack.db, tenantMembershipsTable, { userId: ALICE_ID });
212
189
  expect(row?.["insertedById"]).toBe(seedActor.id);
213
190
  });
214
191
 
@@ -220,10 +197,7 @@ describe("seedTenantMembership", () => {
220
197
  tenantId: TENANT_A,
221
198
  roles: ["User"],
222
199
  });
223
- const [row] = await stack.db
224
- .select()
225
- .from(tenantMembershipsTable)
226
- .where(eq(tenantMembershipsTable.userId, ALICE_ID));
200
+ const [row] = await selectMany(stack.db, tenantMembershipsTable, { userId: ALICE_ID });
227
201
  expect(row?.["insertedById"]).toBe(TestUsers.systemAdmin.id);
228
202
  });
229
203
  });
@@ -1,3 +1,4 @@
1
+ import { afterAll, beforeAll, describe, expect, test } from "bun:test";
1
2
  import { randomBytes } from "node:crypto";
2
3
  import { createEncryptionProvider, type DbConnection } from "@cosmicdrift/kumiko-framework/db";
3
4
  import { createEventsTable } from "@cosmicdrift/kumiko-framework/event-store";
@@ -10,7 +11,6 @@ import {
10
11
  unsafePushTables,
11
12
  } from "@cosmicdrift/kumiko-framework/stack";
12
13
  import { expectErrorIncludes, rolesOf } from "@cosmicdrift/kumiko-framework/testing";
13
- import { afterAll, beforeAll, describe, expect, test } from "vitest";
14
14
  import { createConfigAccessor, createConfigFeature } from "../../config";
15
15
  import { ConfigHandlers, ConfigQueries } from "../../config/constants";
16
16
  import { type ConfigResolver, createConfigResolver } from "../../config/resolver";
@@ -1,6 +1,5 @@
1
- import type { DbRow } from "@cosmicdrift/kumiko-framework/db";
1
+ import { selectMany } from "@cosmicdrift/kumiko-framework/bun-db";
2
2
  import { defineQueryHandler, SYSTEM_ROLE } from "@cosmicdrift/kumiko-framework/engine";
3
- import { eq } from "drizzle-orm";
4
3
  import { z } from "zod";
5
4
  import { tenantTable } from "../schema/tenant";
6
5
 
@@ -9,11 +8,7 @@ export const activeTenantIdsQuery = defineQueryHandler({
9
8
  schema: z.object({}),
10
9
  access: { roles: [SYSTEM_ROLE, "SystemAdmin"] },
11
10
  handler: async (_query, ctx) => {
12
- const rows = await ctx.db
13
- ?.select({ id: tenantTable["id"] })
14
- .from(tenantTable)
15
- .where(eq(tenantTable["isEnabled"], true));
16
-
17
- return rows.map((row) => (row as DbRow)["id"] as number); // @cast-boundary db-row
11
+ const rows = await selectMany<{ id: number }>(ctx.db, tenantTable, { isEnabled: true });
12
+ return rows.map((r) => r.id);
18
13
  },
19
14
  });
@@ -1,7 +1,7 @@
1
- import { createEventStoreExecutor, fetchOne } from "@cosmicdrift/kumiko-framework/db";
1
+ import { fetchOne } from "@cosmicdrift/kumiko-framework/bun-db";
2
+ import { createEventStoreExecutor } from "@cosmicdrift/kumiko-framework/db";
2
3
  import { defineWriteHandler } from "@cosmicdrift/kumiko-framework/engine";
3
4
  import { ConflictError, writeFailure } from "@cosmicdrift/kumiko-framework/errors";
4
- import { eq } from "drizzle-orm";
5
5
  import { z } from "zod";
6
6
  import { TenantErrors } from "../constants";
7
7
  import { tenantMembershipEntity, tenantMembershipsTable } from "../membership-table";
@@ -20,12 +20,10 @@ export const addMemberWrite = defineWriteHandler({
20
20
  access: { roles: ["SystemAdmin"] },
21
21
  handler: async (event, ctx) => {
22
22
  const db = ctx.db;
23
- const existing = await fetchOne(
24
- db,
25
- tenantMembershipsTable,
26
- eq(tenantMembershipsTable.userId, event.payload.userId),
27
- eq(tenantMembershipsTable.tenantId, event.payload.tenantId),
28
- );
23
+ const existing = await fetchOne(db, tenantMembershipsTable, {
24
+ userId: event.payload.userId,
25
+ tenantId: event.payload.tenantId,
26
+ });
29
27
  if (existing) {
30
28
  return writeFailure(
31
29
  new ConflictError({
@@ -10,10 +10,10 @@
10
10
  // invitation = no-op + 200. Cancellen einer non-existent invitation
11
11
  // = invitation_not_found.
12
12
 
13
- import { createEventStoreExecutor, fetchOne } from "@cosmicdrift/kumiko-framework/db";
13
+ import { fetchOne } from "@cosmicdrift/kumiko-framework/bun-db";
14
+ import { createEventStoreExecutor } from "@cosmicdrift/kumiko-framework/db";
14
15
  import { defineWriteHandler } from "@cosmicdrift/kumiko-framework/engine";
15
16
  import { NotFoundError, writeFailure } from "@cosmicdrift/kumiko-framework/errors";
16
- import { eq } from "drizzle-orm";
17
17
  import { z } from "zod";
18
18
  // kumiko-lint-ignore cross-feature-import cancel needs invite-token-store für Redis-cleanup
19
19
  import {
@@ -39,11 +39,9 @@ export const cancelInvitationWrite = defineWriteHandler({
39
39
  schema: CancelInvitationSchema,
40
40
  access: { roles: ["Admin"] },
41
41
  handler: async (event, ctx) => {
42
- const invitation = await fetchOne(
43
- ctx.db.raw,
44
- tenantInvitationsTable,
45
- eq(tenantInvitationsTable.id, event.payload.invitationId),
46
- );
42
+ const invitation = await fetchOne(ctx.db.raw, tenantInvitationsTable, {
43
+ id: event.payload.invitationId,
44
+ });
47
45
  if (!invitation || invitation["tenantId"] !== event.user.tenantId) {
48
46
  return writeFailure(
49
47
  new NotFoundError("tenantInvitation", event.payload.invitationId, {
@@ -1,5 +1,5 @@
1
+ import { selectMany } from "@cosmicdrift/kumiko-framework/bun-db";
1
2
  import { defineQueryHandler } from "@cosmicdrift/kumiko-framework/engine";
2
- import { and, eq } from "drizzle-orm";
3
3
  import { z } from "zod";
4
4
  import { INVITATION_STATUS, tenantInvitationsTable } from "../invitation-table";
5
5
 
@@ -17,15 +17,10 @@ export const invitationsQuery = defineQueryHandler({
17
17
  schema: z.object({}),
18
18
  access: { roles: ["Admin", "SystemAdmin"] },
19
19
  handler: async (query, ctx) => {
20
- const rows = await ctx.db
21
- ?.select()
22
- .from(tenantInvitationsTable)
23
- .where(
24
- and(
25
- eq(tenantInvitationsTable.tenantId, query.user.tenantId),
26
- eq(tenantInvitationsTable.status, INVITATION_STATUS.pending),
27
- ),
28
- );
20
+ const rows = await selectMany(ctx.db, tenantInvitationsTable, {
21
+ tenantId: query.user.tenantId,
22
+ status: INVITATION_STATUS.pending,
23
+ });
29
24
  return rows ?? [];
30
25
  },
31
26
  });
@@ -1,6 +1,5 @@
1
- import { fetchOne } from "@cosmicdrift/kumiko-framework/db";
1
+ import { fetchOne } from "@cosmicdrift/kumiko-framework/bun-db";
2
2
  import { defineQueryHandler } from "@cosmicdrift/kumiko-framework/engine";
3
- import { eq } from "drizzle-orm";
4
3
  import { z } from "zod";
5
4
  import { tenantTable } from "../schema/tenant";
6
5
 
@@ -11,7 +10,7 @@ export const meQuery = defineQueryHandler({
11
10
  schema: z.object({}),
12
11
  access: { openToAll: true },
13
12
  handler: async (query, ctx) => {
14
- const row = await fetchOne(ctx.db, tenantTable, eq(tenantTable["id"], query.user.tenantId));
13
+ const row = await fetchOne(ctx.db, tenantTable, { id: query.user.tenantId });
15
14
  return row ?? null;
16
15
  },
17
16
  });
@@ -1,6 +1,6 @@
1
+ import { selectMany } from "@cosmicdrift/kumiko-framework/bun-db";
1
2
  import { defineQueryHandler } from "@cosmicdrift/kumiko-framework/engine";
2
3
  import { parseRoles } from "@cosmicdrift/kumiko-framework/utils";
3
- import { eq } from "drizzle-orm";
4
4
  import { z } from "zod";
5
5
  import { tenantMembershipsTable } from "../membership-table";
6
6
 
@@ -9,10 +9,9 @@ export const membersQuery = defineQueryHandler({
9
9
  schema: z.object({}),
10
10
  access: { roles: ["Admin", "SystemAdmin"] },
11
11
  handler: async (query, ctx) => {
12
- const rows = await ctx.db
13
- ?.select()
14
- .from(tenantMembershipsTable)
15
- .where(eq(tenantMembershipsTable.tenantId, query.user.tenantId));
12
+ const rows = await selectMany(ctx.db, tenantMembershipsTable, {
13
+ tenantId: query.user.tenantId,
14
+ });
16
15
 
17
16
  return rows.map((row) => ({
18
17
  ...row,