@cosmicdrift/kumiko-bundled-features 0.14.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.
- package/package.json +2 -2
- package/src/__tests__/env-schemas.test.ts +1 -1
- package/src/__tests__/es-ops-e2e.integration.ts +10 -9
- package/src/audit/__tests__/audit.integration.ts +3 -3
- package/src/audit/handlers/list.query.ts +39 -51
- package/src/auth-email-password/__tests__/account-lockout-no-redis.integration.ts +4 -3
- package/src/auth-email-password/__tests__/account-lockout.integration.ts +4 -3
- package/src/auth-email-password/__tests__/auth-claims.integration.ts +5 -4
- package/src/auth-email-password/__tests__/auth.integration.ts +4 -3
- package/src/auth-email-password/__tests__/confirm-token-flow.test.ts +1 -1
- package/src/auth-email-password/__tests__/email-templates.test.ts +1 -1
- package/src/auth-email-password/__tests__/email-verification.integration.ts +7 -10
- package/src/auth-email-password/__tests__/identity-v3-hash.test.ts +1 -1
- package/src/auth-email-password/__tests__/identity-v3-login.integration.ts +4 -3
- package/src/auth-email-password/__tests__/invite-flow.integration.ts +16 -43
- package/src/auth-email-password/__tests__/multi-roles.integration.ts +6 -9
- package/src/auth-email-password/__tests__/password-reset.integration.ts +8 -7
- package/src/auth-email-password/__tests__/public-routes-rate-limit.integration.ts +4 -3
- package/src/auth-email-password/__tests__/seed-admin.integration.ts +19 -32
- package/src/auth-email-password/__tests__/session-callbacks.integration.ts +6 -5
- package/src/auth-email-password/__tests__/session-strict-mode.integration.ts +1 -1
- package/src/auth-email-password/__tests__/signed-token.test.ts +1 -1
- package/src/auth-email-password/__tests__/signup-flow.integration.ts +11 -15
- package/src/auth-email-password/handlers/invite-accept-with-login.write.ts +26 -26
- package/src/auth-email-password/handlers/invite-accept.write.ts +24 -21
- package/src/auth-email-password/handlers/invite-create.write.ts +3 -8
- package/src/auth-email-password/handlers/invite-signup-complete.write.ts +20 -17
- package/src/auth-email-password/handlers/signup-confirm.write.ts +3 -7
- package/src/auth-email-password/seeding.ts +1 -1
- package/src/auth-email-password/web/__tests__/auth-gate.test.tsx +1 -2
- package/src/auth-email-password/web/__tests__/forgot-password-screen.test.tsx +10 -19
- package/src/auth-email-password/web/__tests__/login-screen.test.tsx +12 -18
- package/src/auth-email-password/web/__tests__/reset-password-screen.test.tsx +12 -17
- package/src/auth-email-password/web/__tests__/session-roles.test.ts +1 -1
- package/src/auth-email-password/web/__tests__/tenant-switcher.test.tsx +1 -8
- package/src/auth-email-password/web/__tests__/test-utils.tsx +4 -8
- package/src/auth-email-password/web/__tests__/user-menu.test.tsx +2 -8
- package/src/auth-email-password/web/__tests__/verify-email-screen.test.tsx +10 -15
- package/src/billing-foundation/__tests__/billing-foundation.integration.ts +1 -1
- package/src/billing-foundation/__tests__/feature.test.ts +1 -1
- package/src/billing-foundation/__tests__/webhook-handler.test.ts +6 -5
- package/src/billing-foundation/db/queries/subscription-projection.ts +15 -0
- package/src/billing-foundation/get-subscription-for-tenant.ts +2 -6
- package/src/billing-foundation/handlers/create-portal-session.write.ts +2 -2
- package/src/billing-foundation/handlers/list-subscriptions.query.ts +4 -1
- package/src/billing-foundation/projection.ts +32 -13
- package/src/cap-counter/__tests__/cap-counter.integration.ts +1 -1
- package/src/cap-counter/__tests__/enforce-cap.test.ts +37 -32
- package/src/cap-counter/__tests__/with-cap-enforcement.integration.ts +1 -1
- package/src/cap-counter/enforce-cap.ts +14 -20
- package/src/cap-counter/handlers/get-counter.query.ts +7 -13
- package/src/cap-counter/handlers/increment.write.ts +2 -2
- package/src/cap-counter/handlers/mark-soft-warned.write.ts +2 -2
- package/src/channel-in-app/handlers/inbox.query.ts +7 -13
- package/src/channel-in-app/handlers/mark-all-read.write.ts +7 -9
- package/src/channel-in-app/handlers/mark-read.write.ts +8 -14
- package/src/channel-in-app/handlers/unread-count.query.ts +10 -9
- package/src/channel-in-app/in-app-channel.ts +10 -12
- package/src/channel-in-app/tables.ts +1 -1
- package/src/compliance-profiles/__tests__/compliance-profiles.integration.ts +1 -1
- package/src/compliance-profiles/__tests__/seeding.integration.ts +1 -1
- package/src/compliance-profiles/handlers/for-tenant.query.ts +4 -7
- package/src/compliance-profiles/handlers/needs-profile.query.ts +4 -7
- package/src/compliance-profiles/handlers/set-profile.write.ts +5 -7
- package/src/compliance-profiles/resolve-for-tenant.ts +5 -7
- package/src/compliance-profiles/schema/profile-selection.ts +2 -2
- package/src/compliance-profiles/seeding.ts +4 -7
- package/src/config/__tests__/app-overrides.test.ts +1 -1
- package/src/config/__tests__/cascade.integration.ts +1 -1
- package/src/config/__tests__/config.integration.ts +8 -27
- package/src/config/db/queries/resolver.ts +47 -0
- package/src/config/handlers/__tests__/prepare-config-write.test.ts +1 -1
- package/src/config/resolver.ts +14 -62
- package/src/config/table.ts +4 -4
- package/src/config/write-helpers.ts +7 -11
- package/src/custom-fields/__tests__/audit-integration.integration.ts +6 -6
- package/src/custom-fields/__tests__/custom-fields.integration.ts +7 -7
- package/src/custom-fields/__tests__/feature.test.ts +1 -1
- package/src/custom-fields/__tests__/field-access.integration.ts +6 -6
- package/src/custom-fields/__tests__/quota.integration.ts +6 -6
- package/src/custom-fields/__tests__/retention.integration.ts +12 -10
- package/src/custom-fields/__tests__/user-data-rights.integration.ts +27 -17
- package/src/custom-fields/__tests__/wire-for-entity.test.ts +5 -5
- package/src/custom-fields/db/queries/field-access.ts +16 -0
- package/src/custom-fields/db/queries/projection.ts +43 -0
- package/src/custom-fields/db/queries/quota.ts +14 -0
- package/src/custom-fields/db/queries/retention.ts +39 -0
- package/src/custom-fields/db/queries/user-data-rights.ts +54 -0
- package/src/custom-fields/lib/field-access.ts +2 -41
- package/src/custom-fields/lib/quota.ts +2 -25
- package/src/custom-fields/run-retention.ts +19 -21
- package/src/custom-fields/wire-for-entity.ts +30 -23
- package/src/custom-fields/wire-user-data-rights.ts +33 -85
- package/src/data-retention/__tests__/data-retention.integration.ts +1 -1
- package/src/data-retention/__tests__/keep-for.test.ts +1 -1
- package/src/data-retention/__tests__/override-schema.test.ts +1 -1
- package/src/data-retention/__tests__/policy-for.integration.ts +1 -1
- package/src/data-retention/__tests__/resolver.test.ts +1 -1
- package/src/data-retention/handlers/policy-for.query.ts +5 -8
- package/src/data-retention/resolve-for-tenant.ts +6 -8
- package/src/data-retention/schema/tenant-retention-override.ts +2 -2
- package/src/delivery/__tests__/delivery-events.integration.ts +8 -21
- package/src/delivery/__tests__/delivery.integration.ts +100 -190
- package/src/delivery/db/queries/preferences.ts +30 -0
- package/src/delivery/delivery-service.ts +8 -36
- package/src/delivery/feature.ts +2 -1
- package/src/delivery/handlers/log.query.ts +5 -7
- package/src/delivery/handlers/preferences.query.ts +2 -5
- package/src/delivery/tables.ts +26 -1
- package/src/delivery/upsert-preference.ts +8 -14
- package/src/feature-toggles/__tests__/feature-toggles.integration.ts +30 -30
- package/src/feature-toggles/__tests__/registered-system-tenant.test.ts +7 -6
- package/src/feature-toggles/db/queries/toggle-state.ts +25 -0
- package/src/feature-toggles/feature.ts +16 -2
- package/src/feature-toggles/global-feature-state-table.ts +1 -1
- package/src/feature-toggles/handlers/list.query.ts +9 -2
- package/src/feature-toggles/handlers/registered.query.ts +3 -7
- package/src/feature-toggles/handlers/set.write.ts +37 -25
- package/src/feature-toggles/toggle-runtime.ts +3 -6
- package/src/file-foundation/__tests__/feature.test.ts +1 -1
- package/src/file-foundation/__tests__/file-foundation.integration.ts +1 -1
- package/src/file-provider-inmemory/__tests__/feature.test.ts +1 -1
- package/src/file-provider-s3/__tests__/feature.test.ts +1 -1
- package/src/files/__tests__/files.integration.ts +18 -7
- package/src/files/schema/file-ref.ts +1 -1
- package/src/files-provider-s3/__tests__/env-helper.test.ts +1 -1
- package/src/files-provider-s3/__tests__/s3-provider.integration.ts +1 -1
- package/src/files-provider-s3/__tests__/s3-provider.test.ts +1 -1
- package/src/jobs/__tests__/job-system-user.integration.ts +1 -1
- package/src/jobs/__tests__/jobs-events.integration.ts +8 -21
- package/src/jobs/__tests__/jobs-feature.integration.ts +1 -1
- package/src/jobs/feature.ts +22 -14
- package/src/jobs/handlers/detail.query.ts +10 -8
- package/src/jobs/handlers/list.query.ts +9 -21
- package/src/jobs/handlers/retry.write.ts +2 -7
- package/src/jobs/job-run-logger.ts +3 -9
- package/src/jobs/job-run-table.ts +49 -17
- package/src/legal-pages/__tests__/legal-pages.integration.ts +1 -1
- package/src/mail-foundation/__tests__/feature.test.ts +1 -1
- package/src/mail-foundation/__tests__/mail-foundation.integration.ts +1 -1
- package/src/mail-transport-inmemory/__tests__/feature.test.ts +1 -1
- package/src/mail-transport-smtp/__tests__/feature.test.ts +1 -1
- package/src/rate-limiting/__tests__/rate-limiting.integration.ts +1 -1
- package/src/renderer-foundation/__tests__/api.test.ts +2 -2
- package/src/renderer-foundation/__tests__/collect-plugins.integration.ts +1 -1
- package/src/renderer-simple/__tests__/adapter.test.ts +2 -2
- package/src/renderer-simple/__tests__/simple-renderer.test.ts +1 -1
- package/src/secrets/__tests__/require-secrets-context.test.ts +6 -5
- package/src/secrets/__tests__/rotate.integration.ts +6 -9
- package/src/secrets/__tests__/secrets-events.integration.ts +6 -12
- package/src/secrets/__tests__/secrets.integration.ts +6 -11
- package/src/secrets/db/queries/read.ts +16 -0
- package/src/secrets/handlers/list.query.ts +16 -17
- package/src/secrets/handlers/rotate.job.ts +8 -12
- package/src/secrets/secrets-context.ts +9 -21
- package/src/secrets/table.ts +1 -1
- package/src/sessions/__tests__/cleanup.integration.ts +8 -6
- package/src/sessions/__tests__/password-auto-revoke.integration.ts +7 -6
- package/src/sessions/__tests__/sessions.integration.ts +23 -38
- package/src/sessions/__tests__/test-helpers.ts +1 -1
- package/src/sessions/db/queries/cleanup.ts +21 -0
- package/src/sessions/handlers/cleanup.job.ts +6 -29
- package/src/sessions/handlers/list.query.ts +24 -24
- package/src/sessions/handlers/mine.query.ts +24 -23
- package/src/sessions/handlers/revoke-all-for-user.write.ts +7 -11
- package/src/sessions/handlers/revoke-all-others.write.ts +7 -12
- package/src/sessions/handlers/revoke.write.ts +11 -18
- package/src/sessions/schema/user-session.ts +2 -2
- package/src/sessions/session-callbacks.ts +19 -21
- package/src/subscription-mollie/__tests__/feature.test.ts +1 -1
- package/src/subscription-mollie/__tests__/mollie-foundation.integration.ts +1 -1
- package/src/subscription-mollie/__tests__/verify-webhook.test.ts +8 -7
- package/src/subscription-stripe/__tests__/feature.test.ts +1 -1
- package/src/subscription-stripe/__tests__/plugin-methods.test.ts +14 -15
- package/src/subscription-stripe/__tests__/stripe-foundation.integration.ts +1 -1
- package/src/subscription-stripe/__tests__/verify-webhook.test.ts +14 -14
- package/src/subscription-stripe/verify-webhook.ts +1 -1
- package/src/template-resolver/__tests__/handlers.integration.ts +1 -1
- package/src/template-resolver/__tests__/template-resolver.integration.ts +3 -2
- package/src/template-resolver/api.ts +7 -13
- package/src/template-resolver/handlers/archive.write.ts +4 -7
- package/src/template-resolver/handlers/find-by-id.query.ts +4 -7
- package/src/template-resolver/handlers/list.query.ts +13 -21
- package/src/template-resolver/handlers/publish.write.ts +4 -7
- package/src/template-resolver/handlers/upsert-system.write.ts +7 -10
- package/src/template-resolver/handlers/upsert-tenant.write.ts +7 -10
- package/src/template-resolver/table.ts +2 -5
- package/src/tenant/__tests__/multi-tenant.integration.ts +1 -1
- package/src/tenant/__tests__/seed-testing.integration.ts +19 -45
- package/src/tenant/__tests__/tenant.integration.ts +1 -1
- package/src/tenant/handlers/active-tenant-ids.query.ts +3 -8
- package/src/tenant/handlers/add-member.write.ts +6 -8
- package/src/tenant/handlers/cancel-invitation.write.ts +5 -7
- package/src/tenant/handlers/invitations.query.ts +5 -10
- package/src/tenant/handlers/me.query.ts +2 -3
- package/src/tenant/handlers/members.query.ts +4 -5
- package/src/tenant/handlers/memberships.query.ts +2 -5
- package/src/tenant/handlers/remove-member.write.ts +6 -8
- package/src/tenant/handlers/resolve-user-ids.query.ts +6 -16
- package/src/tenant/handlers/update-member-roles.write.ts +6 -8
- package/src/tenant/invitation-table.ts +2 -5
- package/src/tenant/membership-table.ts +3 -6
- package/src/tenant/schema/tenant.ts +2 -2
- package/src/tenant/seeding.ts +12 -18
- package/src/text-content/README.md +1 -1
- package/src/text-content/__tests__/text-content.integration.ts +2 -2
- package/src/text-content/api.ts +2 -9
- package/src/text-content/handlers/by-slug.query.ts +6 -9
- package/src/text-content/handlers/by-tenant.query.ts +2 -2
- package/src/text-content/handlers/set.write.ts +7 -9
- package/src/text-content/seeding.ts +6 -9
- package/src/text-content/table.ts +2 -2
- package/src/text-content/web/__tests__/editor-read-only.test.tsx +31 -45
- package/src/text-content/web/__tests__/group-blocks.test.ts +1 -18
- package/src/text-content/web/client-plugin.tsx +11 -23
- package/src/tier-engine/__tests__/auto-default-tier.integration.ts +10 -16
- package/src/tier-engine/__tests__/compose-app.test.ts +1 -1
- package/src/tier-engine/__tests__/drift.test.ts +1 -1
- package/src/tier-engine/__tests__/resolver.integration.ts +6 -6
- package/src/tier-engine/__tests__/tier-engine.integration.ts +1 -1
- package/src/tier-engine/feature.ts +9 -16
- package/src/user/__tests__/seed-testing.integration.ts +10 -22
- package/src/user/__tests__/user-status.test.ts +1 -1
- package/src/user/__tests__/user.integration.ts +6 -5
- package/src/user/handlers/create.write.ts +5 -7
- package/src/user/handlers/find-for-auth.query.ts +5 -7
- package/src/user/schema/user.ts +2 -2
- package/src/user/seeding.ts +2 -3
- package/src/user-data-rights/__tests__/audit-log.integration.ts +24 -12
- package/src/user-data-rights/__tests__/cross-data-matrix.integration.ts +64 -37
- package/src/user-data-rights/__tests__/download.integration.ts +29 -46
- package/src/user-data-rights/__tests__/export-job-idempotency.integration.ts +35 -28
- package/src/user-data-rights/__tests__/export-job-schema.test.ts +2 -2
- package/src/user-data-rights/__tests__/policy-to-strategy.test.ts +1 -1
- package/src/user-data-rights/__tests__/request-cancel-deletion.integration.ts +11 -15
- package/src/user-data-rights/__tests__/request-deletion-callback.integration.ts +10 -12
- package/src/user-data-rights/__tests__/request-export.integration.ts +23 -16
- package/src/user-data-rights/__tests__/restriction-flow.integration.ts +24 -32
- package/src/user-data-rights/__tests__/run-export-jobs.integration.ts +142 -137
- package/src/user-data-rights/__tests__/run-forget-cleanup.integration.ts +46 -28
- package/src/user-data-rights/__tests__/run-user-export.integration.ts +20 -14
- package/src/user-data-rights/__tests__/token-helpers.test.ts +1 -1
- package/src/user-data-rights/__tests__/user-data-rights.integration.ts +1 -1
- package/src/user-data-rights/__tests__/zip-path.test.ts +1 -1
- package/src/user-data-rights/audit-download.ts +3 -3
- package/src/user-data-rights/db/queries/export-jobs.ts +23 -0
- package/src/user-data-rights/db/queries/forget-cleanup.ts +13 -0
- package/src/user-data-rights/handlers/cancel-deletion.write.ts +28 -22
- package/src/user-data-rights/handlers/download-by-job.query.ts +11 -21
- package/src/user-data-rights/handlers/download-by-token.query.ts +20 -35
- package/src/user-data-rights/handlers/export-status.query.ts +19 -33
- package/src/user-data-rights/handlers/lift-restriction.write.ts +7 -12
- package/src/user-data-rights/handlers/list-download-attempts.query.ts +14 -23
- package/src/user-data-rights/handlers/my-audit-log.query.ts +33 -23
- package/src/user-data-rights/handlers/request-deletion.write.ts +15 -15
- package/src/user-data-rights/handlers/request-export.write.ts +7 -11
- package/src/user-data-rights/handlers/restrict-account.write.ts +12 -12
- package/src/user-data-rights/run-export-jobs.ts +20 -60
- package/src/user-data-rights/run-forget-cleanup.ts +19 -33
- package/src/user-data-rights/run-user-export.ts +4 -6
- package/src/user-data-rights/schema/download-attempt.ts +2 -2
- package/src/user-data-rights/schema/download-token.ts +2 -2
- package/src/user-data-rights/schema/export-job.ts +2 -3
- package/src/user-data-rights-defaults/__tests__/user-data-rights-defaults.integration.ts +37 -30
- package/src/user-data-rights-defaults/db/queries/user-hook.ts +17 -0
- package/src/user-data-rights-defaults/hooks/file-ref.userdata-hook.ts +12 -27
- package/src/user-data-rights-defaults/hooks/user.userdata-hook.ts +16 -18
- package/CHANGELOG.md +0 -689
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { ROLES } from "@cosmicdrift/kumiko-framework/auth";
|
|
2
|
+
import { fetchOne } from "@cosmicdrift/kumiko-framework/bun-db";
|
|
2
3
|
import {
|
|
3
4
|
complianceProfileOverrideSchema,
|
|
4
5
|
SELECTABLE_PROFILE_KEYS,
|
|
5
6
|
} from "@cosmicdrift/kumiko-framework/compliance";
|
|
6
|
-
import { createEventStoreExecutor
|
|
7
|
+
import { createEventStoreExecutor } from "@cosmicdrift/kumiko-framework/db";
|
|
7
8
|
import { defineWriteHandler, type TenantId } from "@cosmicdrift/kumiko-framework/engine";
|
|
8
9
|
import {
|
|
9
10
|
AccessDeniedError,
|
|
@@ -11,7 +12,6 @@ import {
|
|
|
11
12
|
validationErrorFromZod,
|
|
12
13
|
writeFailure,
|
|
13
14
|
} from "@cosmicdrift/kumiko-framework/errors";
|
|
14
|
-
import { eq } from "drizzle-orm";
|
|
15
15
|
import { z } from "zod";
|
|
16
16
|
import {
|
|
17
17
|
tenantComplianceProfileEntity,
|
|
@@ -100,11 +100,9 @@ export const setProfileWrite = defineWriteHandler({
|
|
|
100
100
|
}
|
|
101
101
|
|
|
102
102
|
// Upsert: existierenden Eintrag suchen
|
|
103
|
-
const existing = (await fetchOne(
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
eq(tenantComplianceProfileTable["tenantId"], tenantId),
|
|
107
|
-
)) as { id: string; version: number } | null; // @cast-boundary db-runner
|
|
103
|
+
const existing = (await fetchOne(ctx.db, tenantComplianceProfileTable, {
|
|
104
|
+
tenantId: tenantId,
|
|
105
|
+
})) as { id: string; version: number } | null; // @cast-boundary db-runner
|
|
108
106
|
|
|
109
107
|
if (existing) {
|
|
110
108
|
const result = await crud.update(
|
|
@@ -8,15 +8,15 @@
|
|
|
8
8
|
// Beide Pfade nutzen `resolveComplianceProfile` aus framework/compliance,
|
|
9
9
|
// also kein Drift zwischen Query-API und Worker-Pfad.
|
|
10
10
|
|
|
11
|
+
import { fetchOne } from "@cosmicdrift/kumiko-framework/bun-db";
|
|
11
12
|
import {
|
|
12
13
|
type ComplianceProfileKey,
|
|
13
14
|
type ComplianceProfileOverride,
|
|
14
15
|
type EffectiveComplianceProfile,
|
|
15
16
|
resolveComplianceProfile,
|
|
16
17
|
} from "@cosmicdrift/kumiko-framework/compliance";
|
|
17
|
-
import {
|
|
18
|
+
import type { DbRunner } from "@cosmicdrift/kumiko-framework/db";
|
|
18
19
|
import type { TenantId } from "@cosmicdrift/kumiko-framework/engine";
|
|
19
|
-
import { eq } from "drizzle-orm";
|
|
20
20
|
import { tenantComplianceProfileTable } from "./schema/profile-selection";
|
|
21
21
|
|
|
22
22
|
export interface ResolveProfileForTenantArgs {
|
|
@@ -27,11 +27,9 @@ export interface ResolveProfileForTenantArgs {
|
|
|
27
27
|
export async function resolveProfileForTenant(
|
|
28
28
|
args: ResolveProfileForTenantArgs,
|
|
29
29
|
): Promise<EffectiveComplianceProfile> {
|
|
30
|
-
const row = (await fetchOne(
|
|
31
|
-
args.
|
|
32
|
-
|
|
33
|
-
eq(tenantComplianceProfileTable["tenantId"], args.tenantId),
|
|
34
|
-
)) as { profileKey: string; override: string | null } | null; // @cast-boundary db-runner
|
|
30
|
+
const row = (await fetchOne(args.db, tenantComplianceProfileTable, {
|
|
31
|
+
tenantId: args.tenantId,
|
|
32
|
+
})) as { profileKey: string; override: string | null } | null; // @cast-boundary db-runner
|
|
35
33
|
|
|
36
34
|
if (!row) {
|
|
37
35
|
return resolveComplianceProfile({});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { buildEntityTable } from "@cosmicdrift/kumiko-framework/db";
|
|
2
2
|
import {
|
|
3
3
|
createEntity,
|
|
4
4
|
createLongTextField,
|
|
@@ -46,7 +46,7 @@ export const tenantComplianceProfileEntity = createEntity({
|
|
|
46
46
|
],
|
|
47
47
|
});
|
|
48
48
|
|
|
49
|
-
export const tenantComplianceProfileTable =
|
|
49
|
+
export const tenantComplianceProfileTable = buildEntityTable(
|
|
50
50
|
"tenantComplianceProfile",
|
|
51
51
|
tenantComplianceProfileEntity,
|
|
52
52
|
);
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
//
|
|
11
11
|
// Pattern matched seedTextBlock aus text-content.
|
|
12
12
|
|
|
13
|
+
import { fetchOne } from "@cosmicdrift/kumiko-framework/bun-db";
|
|
13
14
|
import type {
|
|
14
15
|
ComplianceProfileKey,
|
|
15
16
|
ComplianceProfileOverride,
|
|
@@ -18,11 +19,9 @@ import {
|
|
|
18
19
|
createEventStoreExecutor,
|
|
19
20
|
createTenantDb,
|
|
20
21
|
type DbConnection,
|
|
21
|
-
fetchOne,
|
|
22
22
|
} from "@cosmicdrift/kumiko-framework/db";
|
|
23
23
|
import type { SessionUser, TenantId } from "@cosmicdrift/kumiko-framework/engine";
|
|
24
24
|
import { TestUsers } from "@cosmicdrift/kumiko-framework/stack";
|
|
25
|
-
import { eq } from "drizzle-orm";
|
|
26
25
|
import {
|
|
27
26
|
tenantComplianceProfileEntity,
|
|
28
27
|
tenantComplianceProfileTable,
|
|
@@ -52,11 +51,9 @@ export async function seedComplianceProfile(
|
|
|
52
51
|
const tdb = createTenantDb(db, opts.tenantId, "system");
|
|
53
52
|
const overrideJson = opts.override !== undefined ? JSON.stringify(opts.override) : null;
|
|
54
53
|
|
|
55
|
-
const existing = (await fetchOne(
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
eq(tenantComplianceProfileTable["tenantId"], opts.tenantId),
|
|
59
|
-
)) as { id: string; version: number } | null; // @cast-boundary db-runner
|
|
54
|
+
const existing = (await fetchOne(db, tenantComplianceProfileTable, {
|
|
55
|
+
tenantId: opts.tenantId,
|
|
56
|
+
})) as { id: string; version: number } | null; // @cast-boundary db-runner
|
|
60
57
|
|
|
61
58
|
if (existing) {
|
|
62
59
|
const result = await executor.update(
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
import { describe, expect, test } from "bun:test";
|
|
1
2
|
import { createTenantConfig, createUserConfig } from "@cosmicdrift/kumiko-framework/engine";
|
|
2
|
-
import { describe, expect, test } from "vitest";
|
|
3
3
|
import { validateAppOverrides } from "../resolver";
|
|
4
4
|
|
|
5
5
|
// Minimal registry stub — validateAppOverrides only reads getConfigKey.
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { afterAll, beforeAll, describe, expect, test } from "bun:test";
|
|
1
2
|
import { seedConfigValues } from "@cosmicdrift/kumiko-framework/db";
|
|
2
3
|
import type {
|
|
3
4
|
ConfigCascade,
|
|
@@ -20,7 +21,6 @@ import {
|
|
|
20
21
|
TestUsers,
|
|
21
22
|
unsafePushTables,
|
|
22
23
|
} from "@cosmicdrift/kumiko-framework/stack";
|
|
23
|
-
import { afterAll, beforeAll, describe, expect, test } from "vitest";
|
|
24
24
|
import { ConfigHandlers, ConfigQueries } from "../constants";
|
|
25
25
|
import { createConfigAccessorFactory, createConfigFeature } from "../feature";
|
|
26
26
|
import { type ConfigResolver, createConfigResolver } from "../resolver";
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import { afterAll, beforeAll, describe, expect, test } from "bun:test";
|
|
1
2
|
import { randomBytes } from "node:crypto";
|
|
3
|
+
import { selectMany } from "@cosmicdrift/kumiko-framework/bun-db";
|
|
2
4
|
import {
|
|
3
5
|
createEncryptionProvider,
|
|
4
6
|
type DbConnection,
|
|
@@ -23,8 +25,6 @@ import {
|
|
|
23
25
|
unsafePushTables,
|
|
24
26
|
} from "@cosmicdrift/kumiko-framework/stack";
|
|
25
27
|
import { expectErrorIncludes } from "@cosmicdrift/kumiko-framework/testing";
|
|
26
|
-
import { eq } from "drizzle-orm";
|
|
27
|
-
import { afterAll, beforeAll, describe, expect, test } from "vitest";
|
|
28
28
|
import { z } from "zod";
|
|
29
29
|
import { ConfigHandlers, ConfigQueries } from "../constants";
|
|
30
30
|
import { createConfigAccessor, createConfigAccessorFactory, createConfigFeature } from "../feature";
|
|
@@ -756,11 +756,7 @@ describe("encrypted config", () => {
|
|
|
756
756
|
expect(value).toBe("sk-super-secret-key-12345");
|
|
757
757
|
|
|
758
758
|
// Verify raw DB value is NOT plaintext
|
|
759
|
-
const
|
|
760
|
-
const [raw] = await db
|
|
761
|
-
.select({ value: configValuesTable.value })
|
|
762
|
-
.from(configValuesTable)
|
|
763
|
-
.where(eq(configValuesTable.key, "integration:config:api-secret"));
|
|
759
|
+
const [raw] = await selectMany(db, configValuesTable, { key: "integration:config:api-secret" });
|
|
764
760
|
const rawValue = raw?.value as string;
|
|
765
761
|
expect(rawValue).not.toBe("sk-super-secret-key-12345");
|
|
766
762
|
expect(rawValue).not.toContain("sk-super-secret");
|
|
@@ -814,10 +810,7 @@ describe("configValue lifecycle events", () => {
|
|
|
814
810
|
{ key: "orders:config:max-order-count", value: 250 },
|
|
815
811
|
tenantAdmin,
|
|
816
812
|
);
|
|
817
|
-
const events = await db
|
|
818
|
-
.select()
|
|
819
|
-
.from(eventsTable)
|
|
820
|
-
.where(eq(eventsTable.aggregateType, "config-value"));
|
|
813
|
+
const events = await selectMany(db, eventsTable, { aggregateType: "config-value" });
|
|
821
814
|
// The first set in the suite created the row; subsequent sets update it.
|
|
822
815
|
// Look at the most recent update carrying our value to verify the
|
|
823
816
|
// serialized JSON lands in the event payload (key stays on the row,
|
|
@@ -848,10 +841,7 @@ describe("configValue lifecycle events", () => {
|
|
|
848
841
|
{ key: "invoicing:config:mail-signature" },
|
|
849
842
|
tenantAdmin,
|
|
850
843
|
);
|
|
851
|
-
const events = await db
|
|
852
|
-
.select()
|
|
853
|
-
.from(eventsTable)
|
|
854
|
-
.where(eq(eventsTable.aggregateType, "config-value"));
|
|
844
|
+
const events = await selectMany(db, eventsTable, { aggregateType: "config-value" });
|
|
855
845
|
const deletes = events.filter(
|
|
856
846
|
(e) =>
|
|
857
847
|
e.type === "config-value.deleted" &&
|
|
@@ -871,10 +861,7 @@ describe("configValue lifecycle events", () => {
|
|
|
871
861
|
{ key: "integration:config:lifecycle-probe", value: "alpha" },
|
|
872
862
|
tenantAdmin,
|
|
873
863
|
);
|
|
874
|
-
const events = await db
|
|
875
|
-
.select()
|
|
876
|
-
.from(eventsTable)
|
|
877
|
-
.where(eq(eventsTable.aggregateType, "config-value"));
|
|
864
|
+
const events = await selectMany(db, eventsTable, { aggregateType: "config-value" });
|
|
878
865
|
const created = events.filter(
|
|
879
866
|
(e) =>
|
|
880
867
|
e.type === "config-value.created" &&
|
|
@@ -898,10 +885,7 @@ describe("configValue lifecycle events", () => {
|
|
|
898
885
|
{ key: "integration:config:lifecycle-probe", value: "beta" },
|
|
899
886
|
tenantAdmin,
|
|
900
887
|
);
|
|
901
|
-
const events = await db
|
|
902
|
-
.select()
|
|
903
|
-
.from(eventsTable)
|
|
904
|
-
.where(eq(eventsTable.aggregateType, "config-value"));
|
|
888
|
+
const events = await selectMany(db, eventsTable, { aggregateType: "config-value" });
|
|
905
889
|
const updates = events.filter(
|
|
906
890
|
(e) =>
|
|
907
891
|
e.type === "config-value.updated" &&
|
|
@@ -925,10 +909,7 @@ describe("configValue lifecycle events", () => {
|
|
|
925
909
|
{ key: "integration:config:api-secret", value: "rotated-secret-987" },
|
|
926
910
|
systemAdmin,
|
|
927
911
|
);
|
|
928
|
-
const events = await db
|
|
929
|
-
.select()
|
|
930
|
-
.from(eventsTable)
|
|
931
|
-
.where(eq(eventsTable.aggregateType, "config-value"));
|
|
912
|
+
const events = await selectMany(db, eventsTable, { aggregateType: "config-value" });
|
|
932
913
|
const created = events.filter(
|
|
933
914
|
(e) =>
|
|
934
915
|
e.type === "config-value.created" &&
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { asRawClient } from "@cosmicdrift/kumiko-framework/bun-db";
|
|
2
|
+
import type { DbRunner } from "@cosmicdrift/kumiko-framework/db";
|
|
3
|
+
import type { TenantId } from "@cosmicdrift/kumiko-framework/engine";
|
|
4
|
+
|
|
5
|
+
export type ConfigRow = {
|
|
6
|
+
readonly id: string;
|
|
7
|
+
readonly key: string;
|
|
8
|
+
readonly value: string | null;
|
|
9
|
+
readonly tenantId: TenantId;
|
|
10
|
+
readonly userId: string | null;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export async function selectConfigRowsForScope(
|
|
14
|
+
db: DbRunner,
|
|
15
|
+
systemTenantId: TenantId,
|
|
16
|
+
tenantId: TenantId,
|
|
17
|
+
userId: string,
|
|
18
|
+
): Promise<readonly ConfigRow[]> {
|
|
19
|
+
return asRawClient(db).unsafe<ConfigRow>(
|
|
20
|
+
`SELECT id, key, value, tenant_id AS "tenantId", user_id AS "userId"
|
|
21
|
+
FROM read_config_values
|
|
22
|
+
WHERE (tenant_id = $1 AND user_id IS NULL)
|
|
23
|
+
OR (tenant_id = $2 AND user_id IS NULL)
|
|
24
|
+
OR (tenant_id = $2 AND user_id = $3)`,
|
|
25
|
+
[systemTenantId, tenantId, userId],
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export async function selectConfigRowsForKeys(
|
|
30
|
+
db: DbRunner,
|
|
31
|
+
keys: readonly string[],
|
|
32
|
+
systemTenantId: TenantId,
|
|
33
|
+
tenantId: TenantId,
|
|
34
|
+
userId: string,
|
|
35
|
+
): Promise<readonly ConfigRow[]> {
|
|
36
|
+
return asRawClient(db).unsafe<ConfigRow>(
|
|
37
|
+
`SELECT id, key, value, tenant_id AS "tenantId", user_id AS "userId"
|
|
38
|
+
FROM read_config_values
|
|
39
|
+
WHERE key = ANY($1)
|
|
40
|
+
AND (
|
|
41
|
+
(tenant_id = $2 AND user_id IS NULL)
|
|
42
|
+
OR (tenant_id = $3 AND user_id IS NULL)
|
|
43
|
+
OR (tenant_id = $3 AND user_id = $4)
|
|
44
|
+
)`,
|
|
45
|
+
[[...keys], systemTenantId, tenantId, userId],
|
|
46
|
+
);
|
|
47
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { describe, expect, test } from "bun:test";
|
|
1
2
|
import {
|
|
2
3
|
access,
|
|
3
4
|
type ConfigKeyDefinition,
|
|
@@ -11,7 +12,6 @@ import {
|
|
|
11
12
|
SYSTEM_TENANT_ID,
|
|
12
13
|
type TenantId,
|
|
13
14
|
} from "@cosmicdrift/kumiko-framework/engine";
|
|
14
|
-
import { describe, expect, test } from "vitest";
|
|
15
15
|
import { prepareConfigWrite, validateBounds } from "../../write-helpers";
|
|
16
16
|
|
|
17
17
|
// Minimal Registry stub — only getConfigKey is exercised by prepareConfigWrite.
|
package/src/config/resolver.ts
CHANGED
|
@@ -1,9 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
type EncryptionProvider,
|
|
4
|
-
fetchOne,
|
|
5
|
-
type TenantDb,
|
|
6
|
-
} from "@cosmicdrift/kumiko-framework/db";
|
|
1
|
+
import { fetchOne } from "@cosmicdrift/kumiko-framework/bun-db";
|
|
2
|
+
import type { DbConnection, EncryptionProvider, TenantDb } from "@cosmicdrift/kumiko-framework/db";
|
|
7
3
|
import type {
|
|
8
4
|
ConfigCascade,
|
|
9
5
|
ConfigCascadeLevel,
|
|
@@ -15,7 +11,7 @@ import type {
|
|
|
15
11
|
} from "@cosmicdrift/kumiko-framework/engine";
|
|
16
12
|
import { SYSTEM_TENANT_ID } from "@cosmicdrift/kumiko-framework/engine";
|
|
17
13
|
import { assertUnreachable, parseJsonOrThrow } from "@cosmicdrift/kumiko-framework/utils";
|
|
18
|
-
import {
|
|
14
|
+
import { selectConfigRowsForKeys, selectConfigRowsForScope } from "./db/queries/resolver";
|
|
19
15
|
import { configValuesTable } from "./table";
|
|
20
16
|
|
|
21
17
|
type ConfigRow = {
|
|
@@ -219,16 +215,11 @@ export function createConfigResolver(options: ConfigResolverOptions = {}): Confi
|
|
|
219
215
|
userId: string | null,
|
|
220
216
|
db: DbConnection | TenantDb,
|
|
221
217
|
): Promise<ConfigRow | null> {
|
|
222
|
-
const
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
configValuesTable,
|
|
228
|
-
eq(configValuesTable.key, key),
|
|
229
|
-
eq(configValuesTable.tenantId, tenantId),
|
|
230
|
-
userCond,
|
|
231
|
-
);
|
|
218
|
+
const row = await fetchOne<ConfigRow>(db, configValuesTable, {
|
|
219
|
+
key,
|
|
220
|
+
tenantId,
|
|
221
|
+
userId,
|
|
222
|
+
});
|
|
232
223
|
|
|
233
224
|
return row ?? null;
|
|
234
225
|
}
|
|
@@ -308,23 +299,10 @@ export function createConfigResolver(options: ConfigResolverOptions = {}): Confi
|
|
|
308
299
|
|
|
309
300
|
async getAll(tenantId, userId, db) {
|
|
310
301
|
// Only load rows relevant to this user/tenant (system + tenant + user scope)
|
|
311
|
-
const rows = await db
|
|
312
|
-
.select()
|
|
313
|
-
.from(configValuesTable)
|
|
314
|
-
.where(
|
|
315
|
-
or(
|
|
316
|
-
// System-level values
|
|
317
|
-
and(eq(configValuesTable.tenantId, SYSTEM_TENANT_ID), isNull(configValuesTable.userId)),
|
|
318
|
-
// Tenant-level values
|
|
319
|
-
and(eq(configValuesTable.tenantId, tenantId), isNull(configValuesTable.userId)),
|
|
320
|
-
// User-level values
|
|
321
|
-
and(eq(configValuesTable.tenantId, tenantId), eq(configValuesTable.userId, userId)),
|
|
322
|
-
),
|
|
323
|
-
);
|
|
302
|
+
const rows = await selectConfigRowsForScope(db, SYSTEM_TENANT_ID, tenantId, userId);
|
|
324
303
|
|
|
325
304
|
const result = new Map<string, ConfigRow>();
|
|
326
|
-
for (const
|
|
327
|
-
const r = row as ConfigRow; // @cast-boundary db-row
|
|
305
|
+
for (const r of rows) {
|
|
328
306
|
// Higher specificity wins: user > tenant > system. Under the ES
|
|
329
307
|
// schema system rows carry SYSTEM_TENANT_ID instead of NULL, so the
|
|
330
308
|
// "tenant set" check compares against the sentinel rather than null.
|
|
@@ -341,23 +319,13 @@ export function createConfigResolver(options: ConfigResolverOptions = {}): Confi
|
|
|
341
319
|
|
|
342
320
|
async getAllWithSource(tenantId, userId, db) {
|
|
343
321
|
// Load ALL potentially relevant rows (user + tenant + system)
|
|
344
|
-
const rows = await db
|
|
345
|
-
.select()
|
|
346
|
-
.from(configValuesTable)
|
|
347
|
-
.where(
|
|
348
|
-
or(
|
|
349
|
-
and(eq(configValuesTable.tenantId, SYSTEM_TENANT_ID), isNull(configValuesTable.userId)),
|
|
350
|
-
and(eq(configValuesTable.tenantId, tenantId), isNull(configValuesTable.userId)),
|
|
351
|
-
and(eq(configValuesTable.tenantId, tenantId), eq(configValuesTable.userId, userId)),
|
|
352
|
-
),
|
|
353
|
-
);
|
|
322
|
+
const rows = await selectConfigRowsForScope(db, SYSTEM_TENANT_ID, tenantId, userId);
|
|
354
323
|
|
|
355
324
|
const result = new Map<string, ConfigStoredRowWithSource>();
|
|
356
325
|
|
|
357
326
|
// Group rows by key so we can determine the winner and its source
|
|
358
327
|
const groups = new Map<string, ConfigRow[]>();
|
|
359
|
-
for (const
|
|
360
|
-
const r = row as ConfigRow; // @cast-boundary db-row
|
|
328
|
+
for (const r of rows) {
|
|
361
329
|
const g = groups.get(r.key) ?? [];
|
|
362
330
|
g.push(r);
|
|
363
331
|
groups.set(r.key, g);
|
|
@@ -418,26 +386,10 @@ export function createConfigResolver(options: ConfigResolverOptions = {}): Confi
|
|
|
418
386
|
// One SQL query for all keys + every scope (user-row,
|
|
419
387
|
// tenant-row, system-row). The cascade-builder then matches
|
|
420
388
|
// per-key from this preloaded set instead of querying again.
|
|
421
|
-
const rows = await db
|
|
422
|
-
.select()
|
|
423
|
-
.from(configValuesTable)
|
|
424
|
-
.where(
|
|
425
|
-
and(
|
|
426
|
-
inArray(configValuesTable.key, [...keys]),
|
|
427
|
-
or(
|
|
428
|
-
and(
|
|
429
|
-
eq(configValuesTable.tenantId, SYSTEM_TENANT_ID),
|
|
430
|
-
isNull(configValuesTable.userId),
|
|
431
|
-
),
|
|
432
|
-
and(eq(configValuesTable.tenantId, tenantId), isNull(configValuesTable.userId)),
|
|
433
|
-
and(eq(configValuesTable.tenantId, tenantId), eq(configValuesTable.userId, userId)),
|
|
434
|
-
),
|
|
435
|
-
),
|
|
436
|
-
);
|
|
389
|
+
const rows = await selectConfigRowsForKeys(db, keys, SYSTEM_TENANT_ID, tenantId, userId);
|
|
437
390
|
|
|
438
391
|
const grouped = new Map<string, ConfigRow[]>();
|
|
439
|
-
for (const
|
|
440
|
-
const r = row as ConfigRow; // @cast-boundary db-row
|
|
392
|
+
for (const r of rows) {
|
|
441
393
|
const g = grouped.get(r.key) ?? [];
|
|
442
394
|
g.push(r);
|
|
443
395
|
grouped.set(r.key, g);
|
package/src/config/table.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { buildEntityTable } from "@cosmicdrift/kumiko-framework/db";
|
|
2
2
|
import { createEntity, createTextField } from "@cosmicdrift/kumiko-framework/engine";
|
|
3
3
|
|
|
4
4
|
// Config values are event-sourced. Each (key, scope) is its own aggregate
|
|
@@ -7,13 +7,13 @@ import { createEntity, createTextField } from "@cosmicdrift/kumiko-framework/eng
|
|
|
7
7
|
// projection in one TX. Reads stay O(1) against the projection.
|
|
8
8
|
//
|
|
9
9
|
// System-scope rows use SYSTEM_TENANT_ID (not null) — buildBaseColumns
|
|
10
|
-
// (via
|
|
10
|
+
// (via buildEntityTable) forces tenant_id NOT NULL, so die pre-ES "NULL
|
|
11
11
|
// means system" convention is replaced with a fixed sentinel. Der unique
|
|
12
12
|
// index über (key, tenant_id, user_id) prevent duplicate writes at the DB
|
|
13
13
|
// level — deklariert via entity.indexes.
|
|
14
14
|
//
|
|
15
15
|
// Single-Source-of-Truth: `configValueEntity`. Die DB-Tabelle wird über
|
|
16
|
-
//
|
|
16
|
+
// buildEntityTable aus der EntityDefinition abgeleitet, der unique-Index
|
|
17
17
|
// ist via entity.indexes deklariert. Plural-Re-Export `configValuesTable`
|
|
18
18
|
// dient handlers (`reset.write.ts` etc.) als typisierte Drizzle-Table-Ref.
|
|
19
19
|
export const configValueEntity = createEntity({
|
|
@@ -32,4 +32,4 @@ export const configValueEntity = createEntity({
|
|
|
32
32
|
],
|
|
33
33
|
});
|
|
34
34
|
|
|
35
|
-
export const configValuesTable =
|
|
35
|
+
export const configValuesTable = buildEntityTable("config-value", configValueEntity);
|
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
// Extracted from set.write.ts so reset.write.ts + values.query.ts don't
|
|
3
3
|
// have to cross-import from another handler file.
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import { fetchOne } from "@cosmicdrift/kumiko-framework/bun-db";
|
|
6
|
+
import type { DbConnection, TenantDb } from "@cosmicdrift/kumiko-framework/db";
|
|
6
7
|
import {
|
|
7
8
|
type ConfigKeyDefinition,
|
|
8
9
|
type ConfigScope,
|
|
@@ -23,7 +24,6 @@ import {
|
|
|
23
24
|
writeFailure,
|
|
24
25
|
} from "@cosmicdrift/kumiko-framework/errors";
|
|
25
26
|
import { assertUnreachable } from "@cosmicdrift/kumiko-framework/utils";
|
|
26
|
-
import { eq, isNull } from "drizzle-orm";
|
|
27
27
|
import { ConfigErrors } from "./constants";
|
|
28
28
|
import { configValuesTable } from "./table";
|
|
29
29
|
|
|
@@ -44,15 +44,11 @@ export async function findConfigRow(
|
|
|
44
44
|
tenantId: TenantId,
|
|
45
45
|
userId: string | null,
|
|
46
46
|
): Promise<ConfigRowLookup | null> {
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
eq(configValuesTable.key, key),
|
|
53
|
-
eq(configValuesTable.tenantId, tenantId),
|
|
54
|
-
userCond,
|
|
55
|
-
);
|
|
47
|
+
const row = await fetchOne<ConfigRowLookup>(db, configValuesTable, {
|
|
48
|
+
key,
|
|
49
|
+
tenantId,
|
|
50
|
+
userId,
|
|
51
|
+
});
|
|
56
52
|
if (!row) return null;
|
|
57
53
|
return {
|
|
58
54
|
id: row.id,
|
|
@@ -10,7 +10,9 @@
|
|
|
10
10
|
// directly) picks them up automatically. This suite is the evidence that
|
|
11
11
|
// the promise holds end-to-end.
|
|
12
12
|
|
|
13
|
-
import {
|
|
13
|
+
import { afterAll, beforeAll, beforeEach, describe, expect, test } from "bun:test";
|
|
14
|
+
import { asRawClient } from "@cosmicdrift/kumiko-framework/bun-db";
|
|
15
|
+
import { buildEntityTable } from "@cosmicdrift/kumiko-framework/db";
|
|
14
16
|
import {
|
|
15
17
|
createEntity,
|
|
16
18
|
createEntityExecutor,
|
|
@@ -26,8 +28,6 @@ import {
|
|
|
26
28
|
TestUsers,
|
|
27
29
|
unsafeCreateEntityTable,
|
|
28
30
|
} from "@cosmicdrift/kumiko-framework/stack";
|
|
29
|
-
import { sql } from "drizzle-orm";
|
|
30
|
-
import { afterAll, beforeAll, beforeEach, describe, expect, test } from "vitest";
|
|
31
31
|
import { z } from "zod";
|
|
32
32
|
import { AuditQueries } from "../../audit/constants";
|
|
33
33
|
import { createAuditFeature } from "../../audit/feature";
|
|
@@ -42,7 +42,7 @@ const propertyEntity = createEntity({
|
|
|
42
42
|
customFields: customFieldsField(),
|
|
43
43
|
},
|
|
44
44
|
});
|
|
45
|
-
const propertyTable =
|
|
45
|
+
const propertyTable = buildEntityTable("property", propertyEntity);
|
|
46
46
|
|
|
47
47
|
const propertyFeature = defineFeature("property-t15a", (r) => {
|
|
48
48
|
r.entity("property", propertyEntity);
|
|
@@ -92,8 +92,8 @@ afterAll(async () => {
|
|
|
92
92
|
|
|
93
93
|
beforeEach(async () => {
|
|
94
94
|
await resetEventStore(stack);
|
|
95
|
-
await stack.db.
|
|
96
|
-
await stack.db.
|
|
95
|
+
await asRawClient(stack.db).unsafe(`DELETE FROM read_t15a_properties`);
|
|
96
|
+
await asRawClient(stack.db).unsafe(`DELETE FROM read_custom_field_definitions`);
|
|
97
97
|
});
|
|
98
98
|
|
|
99
99
|
type AuditRow = {
|
|
@@ -10,7 +10,9 @@
|
|
|
10
10
|
// Pattern follows cap-counter.integration.ts: probe-feature mit own entity,
|
|
11
11
|
// wired via wireCustomFieldsFor.
|
|
12
12
|
|
|
13
|
-
import {
|
|
13
|
+
import { afterAll, beforeAll, beforeEach, describe, expect, test } from "bun:test";
|
|
14
|
+
import { asRawClient } from "@cosmicdrift/kumiko-framework/bun-db";
|
|
15
|
+
import { buildEntityTable } from "@cosmicdrift/kumiko-framework/db";
|
|
14
16
|
import {
|
|
15
17
|
createEntity,
|
|
16
18
|
createEntityExecutor,
|
|
@@ -25,8 +27,6 @@ import {
|
|
|
25
27
|
type TestStack,
|
|
26
28
|
unsafeCreateEntityTable,
|
|
27
29
|
} from "@cosmicdrift/kumiko-framework/stack";
|
|
28
|
-
import { sql } from "drizzle-orm";
|
|
29
|
-
import { afterAll, beforeAll, beforeEach, describe, expect, test } from "vitest";
|
|
30
30
|
import { z } from "zod";
|
|
31
31
|
import { fieldDefinitionEntity } from "../entity";
|
|
32
32
|
import { createCustomFieldsFeature } from "../feature";
|
|
@@ -41,7 +41,7 @@ const propertyEntity = createEntity({
|
|
|
41
41
|
customFields: customFieldsField(),
|
|
42
42
|
},
|
|
43
43
|
});
|
|
44
|
-
const propertyTable =
|
|
44
|
+
const propertyTable = buildEntityTable("property", propertyEntity);
|
|
45
45
|
|
|
46
46
|
const propertyFeature = defineFeature("property-test", (r) => {
|
|
47
47
|
r.entity("property", propertyEntity);
|
|
@@ -91,9 +91,9 @@ afterAll(async () => {
|
|
|
91
91
|
|
|
92
92
|
beforeEach(async () => {
|
|
93
93
|
// Clean slate per test — event-log + entity-rows.
|
|
94
|
-
await stack.db.
|
|
95
|
-
await stack.db.
|
|
96
|
-
await stack.db.
|
|
94
|
+
await asRawClient(stack.db).unsafe(`DELETE FROM kumiko_events`);
|
|
95
|
+
await asRawClient(stack.db).unsafe(`DELETE FROM read_t1_properties`);
|
|
96
|
+
await asRawClient(stack.db).unsafe(`DELETE FROM read_custom_field_definitions`);
|
|
97
97
|
});
|
|
98
98
|
|
|
99
99
|
// --- Helpers ---
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { describe, expect, test } from "
|
|
1
|
+
import { describe, expect, test } from "bun:test";
|
|
2
2
|
import { fieldDefinitionAggregateId } from "../aggregate-id";
|
|
3
3
|
import { SUPPORTED_FIELD_TYPES } from "../constants";
|
|
4
4
|
import { createCustomFieldsFeature } from "../feature";
|
|
@@ -9,7 +9,9 @@
|
|
|
9
9
|
// exactly as in B2 (no extra gate) — the existing roundtrip-test suite
|
|
10
10
|
// stays green, and we add an explicit covers-the-no-op-path test here too.
|
|
11
11
|
|
|
12
|
-
import {
|
|
12
|
+
import { afterAll, beforeAll, beforeEach, describe, expect, test } from "bun:test";
|
|
13
|
+
import { asRawClient } from "@cosmicdrift/kumiko-framework/bun-db";
|
|
14
|
+
import { buildEntityTable } from "@cosmicdrift/kumiko-framework/db";
|
|
13
15
|
import {
|
|
14
16
|
createEntity,
|
|
15
17
|
createEntityExecutor,
|
|
@@ -24,8 +26,6 @@ import {
|
|
|
24
26
|
type TestStack,
|
|
25
27
|
unsafeCreateEntityTable,
|
|
26
28
|
} from "@cosmicdrift/kumiko-framework/stack";
|
|
27
|
-
import { sql } from "drizzle-orm";
|
|
28
|
-
import { afterAll, beforeAll, beforeEach, describe, expect, test } from "vitest";
|
|
29
29
|
import { z } from "zod";
|
|
30
30
|
import { fieldDefinitionEntity } from "../entity";
|
|
31
31
|
import { createCustomFieldsFeature } from "../feature";
|
|
@@ -38,7 +38,7 @@ const propertyEntity = createEntity({
|
|
|
38
38
|
customFields: customFieldsField(),
|
|
39
39
|
},
|
|
40
40
|
});
|
|
41
|
-
const propertyTable =
|
|
41
|
+
const propertyTable = buildEntityTable("property", propertyEntity);
|
|
42
42
|
|
|
43
43
|
const propertyFeature = defineFeature("property-t15b", (r) => {
|
|
44
44
|
r.entity("property", propertyEntity);
|
|
@@ -84,8 +84,8 @@ afterAll(async () => {
|
|
|
84
84
|
|
|
85
85
|
beforeEach(async () => {
|
|
86
86
|
await resetEventStore(stack);
|
|
87
|
-
await stack.db.
|
|
88
|
-
await stack.db.
|
|
87
|
+
await asRawClient(stack.db).unsafe(`DELETE FROM read_t15b_properties`);
|
|
88
|
+
await asRawClient(stack.db).unsafe(`DELETE FROM read_custom_field_definitions`);
|
|
89
89
|
});
|
|
90
90
|
|
|
91
91
|
async function defineField(fieldKey: string, serializedField: Record<string, unknown>) {
|
|
@@ -5,7 +5,9 @@
|
|
|
5
5
|
// rejects with `unprocessable` + reason `cap_exceeded` when the
|
|
6
6
|
// tenant already has >= N definitions.
|
|
7
7
|
|
|
8
|
-
import {
|
|
8
|
+
import { afterAll, beforeAll, beforeEach, describe, expect, test } from "bun:test";
|
|
9
|
+
import { asRawClient } from "@cosmicdrift/kumiko-framework/bun-db";
|
|
10
|
+
import { buildEntityTable } from "@cosmicdrift/kumiko-framework/db";
|
|
9
11
|
import {
|
|
10
12
|
createEntity,
|
|
11
13
|
createEntityExecutor,
|
|
@@ -20,8 +22,6 @@ import {
|
|
|
20
22
|
type TestStack,
|
|
21
23
|
unsafeCreateEntityTable,
|
|
22
24
|
} from "@cosmicdrift/kumiko-framework/stack";
|
|
23
|
-
import { sql } from "drizzle-orm";
|
|
24
|
-
import { afterAll, beforeAll, beforeEach, describe, expect, test } from "vitest";
|
|
25
25
|
import { z } from "zod";
|
|
26
26
|
import { fieldDefinitionEntity } from "../entity";
|
|
27
27
|
import { createCustomFieldsFeature } from "../feature";
|
|
@@ -34,7 +34,7 @@ const propertyEntity = createEntity({
|
|
|
34
34
|
customFields: customFieldsField(),
|
|
35
35
|
},
|
|
36
36
|
});
|
|
37
|
-
const propertyTable =
|
|
37
|
+
const propertyTable = buildEntityTable("property", propertyEntity);
|
|
38
38
|
|
|
39
39
|
const propertyFeature = defineFeature("property-t15e", (r) => {
|
|
40
40
|
r.entity("property", propertyEntity);
|
|
@@ -74,8 +74,8 @@ afterAll(async () => {
|
|
|
74
74
|
|
|
75
75
|
beforeEach(async () => {
|
|
76
76
|
await resetEventStore(stack);
|
|
77
|
-
await stack.db.
|
|
78
|
-
await stack.db.
|
|
77
|
+
await asRawClient(stack.db).unsafe(`DELETE FROM read_t15e_properties`);
|
|
78
|
+
await asRawClient(stack.db).unsafe(`DELETE FROM read_custom_field_definitions`);
|
|
79
79
|
});
|
|
80
80
|
|
|
81
81
|
async function defineField(fieldKey: string) {
|