@cosmicdrift/kumiko-framework 0.1.0 → 0.2.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/LICENSE +57 -0
- package/package.json +1 -1
- package/src/__tests__/anonymous-access.integration.ts +7 -7
- package/src/__tests__/error-contract.integration.ts +2 -2
- package/src/__tests__/field-access.integration.ts +2 -2
- package/src/__tests__/full-stack.integration.ts +2 -2
- package/src/__tests__/ownership.integration.ts +2 -2
- package/src/__tests__/raw-table.integration.ts +128 -0
- package/src/__tests__/reference-data.integration.ts +2 -2
- package/src/__tests__/transition-guard.integration.ts +4 -4
- package/src/api/__tests__/batch.integration.ts +3 -3
- package/src/api/__tests__/dispatcher-live.integration.ts +2 -2
- package/src/api/__tests__/nested-write.integration.ts +3 -3
- package/src/db/__tests__/drizzle-helpers.integration.ts +2 -2
- package/src/db/__tests__/event-store-executor-list.integration.ts +2 -2
- package/src/db/__tests__/event-store-executor.integration.ts +9 -3
- package/src/db/__tests__/implicit-projection-equivalence.integration.ts +3 -3
- package/src/db/__tests__/multi-row-insert.integration.ts +3 -3
- package/src/db/__tests__/schema-migration.integration.ts +9 -9
- package/src/db/__tests__/tenant-db.integration.ts +4 -4
- package/src/db/__tests__/unique-violation-mapping.integration.ts +2 -2
- package/src/db/schema-inspection.ts +1 -1
- package/src/engine/__tests__/raw-table.test.ts +149 -0
- package/src/engine/define-feature.ts +38 -0
- package/src/engine/registry.ts +46 -0
- package/src/engine/types/feature.ts +55 -0
- package/src/engine/types/index.ts +3 -0
- package/src/event-store/__tests__/upcaster.integration.ts +11 -5
- package/src/event-store/archive.ts +2 -2
- package/src/event-store/events-schema.ts +2 -2
- package/src/event-store/snapshot.ts +2 -2
- package/src/event-store/upcaster-dead-letter.ts +2 -2
- package/src/files/__tests__/file-field-column.integration.ts +4 -4
- package/src/files/__tests__/file-field-pipeline.integration.ts +2 -2
- package/src/files/__tests__/files.integration.ts +8 -8
- package/src/observability/__tests__/observability.integration.ts +2 -2
- package/src/pipeline/__tests__/archive-stream.integration.ts +2 -2
- package/src/pipeline/__tests__/cascade-handler.integration.ts +9 -9
- package/src/pipeline/__tests__/causation-chain.integration.ts +2 -2
- package/src/pipeline/__tests__/ctx-bridge.integration.ts +3 -3
- package/src/pipeline/__tests__/domain-events-projections.integration.ts +2 -2
- package/src/pipeline/__tests__/event-dedup.integration.ts +2 -2
- package/src/pipeline/__tests__/event-define-event-strict.integration.ts +2 -2
- package/src/pipeline/__tests__/event-dispatcher-lifecycle.integration.ts +3 -3
- package/src/pipeline/__tests__/event-dispatcher-multi-instance.integration.ts +2 -2
- package/src/pipeline/__tests__/event-dispatcher-pg-listen.integration.ts +2 -2
- package/src/pipeline/__tests__/event-dispatcher-recovery.integration.ts +2 -2
- package/src/pipeline/__tests__/event-dispatcher-second-audit.integration.ts +4 -4
- package/src/pipeline/__tests__/event-dispatcher.integration.ts +4 -4
- package/src/pipeline/__tests__/event-retention.integration.ts +2 -2
- package/src/pipeline/__tests__/fetch-for-writing.integration.ts +2 -2
- package/src/pipeline/__tests__/load-aggregate-query.integration.ts +2 -2
- package/src/pipeline/__tests__/msp-error-mode.integration.ts +2 -2
- package/src/pipeline/__tests__/msp-multi-hop.integration.ts +2 -2
- package/src/pipeline/__tests__/msp-rebuild.integration.ts +3 -3
- package/src/pipeline/__tests__/multi-stream-projection.integration.ts +3 -3
- package/src/pipeline/__tests__/perf-rebuild.integration.ts +2 -2
- package/src/pipeline/__tests__/projection-rebuild.integration.ts +9 -3
- package/src/pipeline/__tests__/query-projection.integration.ts +2 -2
- package/src/pipeline/event-consumer-state.ts +2 -2
- package/src/pipeline/projection-state.ts +3 -3
- package/src/stack/index.ts +4 -3
- package/src/stack/push-entity-projection-tables.ts +51 -0
- package/src/stack/table-helpers.ts +20 -13
- package/src/stack/test-stack.ts +13 -4
- package/src/testing/__tests__/ensure-entity-table.integration.ts +16 -11
|
@@ -15,12 +15,12 @@ import {
|
|
|
15
15
|
} from "../../engine";
|
|
16
16
|
import { createEventsTable, loadAggregate } from "../../event-store";
|
|
17
17
|
import {
|
|
18
|
-
createEntityTable,
|
|
19
18
|
createTestDb,
|
|
20
19
|
createTestUser,
|
|
21
|
-
pushTables,
|
|
22
20
|
type TestDb,
|
|
23
21
|
TestUsers,
|
|
22
|
+
unsafeCreateEntityTable,
|
|
23
|
+
unsafePushTables,
|
|
24
24
|
} from "../../stack";
|
|
25
25
|
import { expectErrorIncludes } from "../../testing";
|
|
26
26
|
import { fileRefsTable } from "../file-ref-table";
|
|
@@ -64,8 +64,8 @@ beforeAll(async () => {
|
|
|
64
64
|
storagePath = await mkdtemp(join(tmpdir(), "kumiko-files-test-"));
|
|
65
65
|
|
|
66
66
|
// Create tables
|
|
67
|
-
await
|
|
68
|
-
await
|
|
67
|
+
await unsafePushTables(testDb.db, { fileRefsTable });
|
|
68
|
+
await unsafeCreateEntityTable(testDb.db, testTenantEntity);
|
|
69
69
|
// Event-store table: the upload route appends files:event:uploaded in the
|
|
70
70
|
// same tx as the FileRef insert. Without events, upload would 500.
|
|
71
71
|
await createEventsTable(testDb.db);
|
|
@@ -402,8 +402,8 @@ describe("custom file access guard", () => {
|
|
|
402
402
|
): Promise<void> {
|
|
403
403
|
const { storageProvider: providerOverride, ...routeOptions } = options;
|
|
404
404
|
const isolatedDb = await createTestDb();
|
|
405
|
-
await
|
|
406
|
-
await
|
|
405
|
+
await unsafePushTables(isolatedDb.db, { fileRefsTable });
|
|
406
|
+
await unsafeCreateEntityTable(isolatedDb.db, testTenantEntity);
|
|
407
407
|
const storagePath = await mkdtemp(join(tmpdir(), "kumiko-files-custom-"));
|
|
408
408
|
const provider = providerOverride ?? createLocalProvider(storagePath);
|
|
409
409
|
const isolatedRegistry = createRegistry([tenantFeature]);
|
|
@@ -716,8 +716,8 @@ describe("download-url endpoint", () => {
|
|
|
716
716
|
}) => Promise<void>,
|
|
717
717
|
): Promise<void> {
|
|
718
718
|
const isolatedDb = await createTestDb();
|
|
719
|
-
await
|
|
720
|
-
await
|
|
719
|
+
await unsafePushTables(isolatedDb.db, { fileRefsTable });
|
|
720
|
+
await unsafeCreateEntityTable(isolatedDb.db, testTenantEntity);
|
|
721
721
|
const isolatedRegistry = createRegistry([tenantFeature]);
|
|
722
722
|
const isolatedServer = buildServer({
|
|
723
723
|
registry: isolatedRegistry,
|
|
@@ -6,11 +6,11 @@ import type { AppContext, SaveContext } from "../../engine/types";
|
|
|
6
6
|
import { createJobRunner } from "../../jobs";
|
|
7
7
|
import { createLogger } from "../../logging/pino-logger";
|
|
8
8
|
import {
|
|
9
|
-
createEntityTable,
|
|
10
9
|
createTestRedis,
|
|
11
10
|
setupTestStack,
|
|
12
11
|
type TestRedis,
|
|
13
12
|
type TestStack,
|
|
13
|
+
unsafeCreateEntityTable,
|
|
14
14
|
} from "../../stack";
|
|
15
15
|
import { createRecordingProvider, type RecordingProvider, waitFor } from "../../testing";
|
|
16
16
|
|
|
@@ -194,7 +194,7 @@ describe("Observability (integration) — DB + pipeline hook spans", () => {
|
|
|
194
194
|
observability: provider,
|
|
195
195
|
systemHooks: [],
|
|
196
196
|
});
|
|
197
|
-
await
|
|
197
|
+
await unsafeCreateEntityTable(stack.db, todoEntity, "todo");
|
|
198
198
|
});
|
|
199
199
|
|
|
200
200
|
afterEach(async () => {
|
|
@@ -16,11 +16,11 @@ import {
|
|
|
16
16
|
loadAggregate as loadAggregateRaw,
|
|
17
17
|
} from "../../event-store";
|
|
18
18
|
import {
|
|
19
|
-
createEntityTable,
|
|
20
19
|
resetEventStore,
|
|
21
20
|
setupTestStack,
|
|
22
21
|
type TestStack,
|
|
23
22
|
TestUsers,
|
|
23
|
+
unsafeCreateEntityTable,
|
|
24
24
|
} from "../../stack";
|
|
25
25
|
|
|
26
26
|
const itemEntity = createEntity({
|
|
@@ -103,7 +103,7 @@ const admin = TestUsers.admin;
|
|
|
103
103
|
|
|
104
104
|
beforeAll(async () => {
|
|
105
105
|
stack = await setupTestStack({ features: [archFeature], systemHooks: [] });
|
|
106
|
-
await
|
|
106
|
+
await unsafeCreateEntityTable(stack.db, itemEntity, "arch-item");
|
|
107
107
|
});
|
|
108
108
|
|
|
109
109
|
afterAll(async () => {
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
type Registry,
|
|
12
12
|
} from "../../engine";
|
|
13
13
|
import { createEventsTable } from "../../event-store";
|
|
14
|
-
import {
|
|
14
|
+
import { createTestDb, type TestDb, TestUsers, unsafeCreateEntityTable } from "../../stack";
|
|
15
15
|
import { createCascadeDeleteHook } from "../cascade-handler";
|
|
16
16
|
|
|
17
17
|
// biome-ignore lint/suspicious/noExplicitAny: Drizzle dynamic tables
|
|
@@ -81,14 +81,14 @@ beforeAll(async () => {
|
|
|
81
81
|
await createEventsTable(testDb.db);
|
|
82
82
|
tdb = createTenantDb(testDb.db, admin.tenantId);
|
|
83
83
|
|
|
84
|
-
await
|
|
85
|
-
await
|
|
86
|
-
await
|
|
87
|
-
await
|
|
88
|
-
await
|
|
89
|
-
await
|
|
90
|
-
await
|
|
91
|
-
await
|
|
84
|
+
await unsafeCreateEntityTable(testDb.db, departmentEntity);
|
|
85
|
+
await unsafeCreateEntityTable(testDb.db, userEntity);
|
|
86
|
+
await unsafeCreateEntityTable(testDb.db, sessionEntity);
|
|
87
|
+
await unsafeCreateEntityTable(testDb.db, groupEntity);
|
|
88
|
+
await unsafeCreateEntityTable(testDb.db, userGroupRestrictEntity);
|
|
89
|
+
await unsafeCreateEntityTable(testDb.db, userGroupCascadeEntity);
|
|
90
|
+
await unsafeCreateEntityTable(testDb.db, teamEntity);
|
|
91
|
+
await unsafeCreateEntityTable(testDb.db, memberEntity);
|
|
92
92
|
|
|
93
93
|
departmentTable = buildDrizzleTable("department", departmentEntity);
|
|
94
94
|
userTable = buildDrizzleTable("user", userEntity);
|
|
@@ -23,11 +23,11 @@ import { buildDrizzleTable } from "../../db/table-builder";
|
|
|
23
23
|
import { createEntity, createTextField, defineFeature } from "../../engine";
|
|
24
24
|
import { eventsTable } from "../../event-store";
|
|
25
25
|
import {
|
|
26
|
-
createEntityTable,
|
|
27
26
|
resetEventStore,
|
|
28
27
|
setupTestStack,
|
|
29
28
|
type TestStack,
|
|
30
29
|
TestUsers,
|
|
30
|
+
unsafeCreateEntityTable,
|
|
31
31
|
} from "../../stack";
|
|
32
32
|
|
|
33
33
|
// --- Feature ---
|
|
@@ -104,7 +104,7 @@ beforeAll(async () => {
|
|
|
104
104
|
features: [causationFeature],
|
|
105
105
|
systemHooks: [],
|
|
106
106
|
});
|
|
107
|
-
await
|
|
107
|
+
await unsafeCreateEntityTable(stack.db, orderEntity, "causation-order");
|
|
108
108
|
});
|
|
109
109
|
|
|
110
110
|
afterAll(async () => {
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
defineFeature,
|
|
12
12
|
} from "../../engine";
|
|
13
13
|
import { UnprocessableError, writeFailure } from "../../errors";
|
|
14
|
-
import {
|
|
14
|
+
import { setupTestStack, type TestStack, TestUsers, unsafeCreateEntityTable } from "../../stack";
|
|
15
15
|
|
|
16
16
|
// Two entities: `bag` (outer) + `secret` (inner). The outer handler calls
|
|
17
17
|
// the inner via ctx.queryAs / ctx.writeAs. We verify:
|
|
@@ -144,8 +144,8 @@ const bridgeFeature = defineFeature("ctxbridge", (r) => {
|
|
|
144
144
|
|
|
145
145
|
beforeAll(async () => {
|
|
146
146
|
stack = await setupTestStack({ features: [bridgeFeature] });
|
|
147
|
-
await
|
|
148
|
-
await
|
|
147
|
+
await unsafeCreateEntityTable(stack.db, bagEntity);
|
|
148
|
+
await unsafeCreateEntityTable(stack.db, secretEntity);
|
|
149
149
|
});
|
|
150
150
|
|
|
151
151
|
afterAll(async () => {
|
|
@@ -24,11 +24,11 @@ import { buildDrizzleTable } from "../../db/table-builder";
|
|
|
24
24
|
import { createEntity, createTextField, defineFeature } from "../../engine";
|
|
25
25
|
import { loadAggregate } from "../../event-store";
|
|
26
26
|
import {
|
|
27
|
-
createEntityTable,
|
|
28
27
|
resetEventStore,
|
|
29
28
|
setupTestStack,
|
|
30
29
|
type TestStack,
|
|
31
30
|
TestUsers,
|
|
31
|
+
unsafeCreateEntityTable,
|
|
32
32
|
} from "../../stack";
|
|
33
33
|
|
|
34
34
|
// --- Entity ---
|
|
@@ -175,7 +175,7 @@ beforeAll(async () => {
|
|
|
175
175
|
features: [shippingFeature],
|
|
176
176
|
systemHooks: [],
|
|
177
177
|
});
|
|
178
|
-
await
|
|
178
|
+
await unsafeCreateEntityTable(stack.db, shipmentEntity, "domain-shipment");
|
|
179
179
|
});
|
|
180
180
|
|
|
181
181
|
afterAll(async () => {
|
|
@@ -3,12 +3,12 @@ import { z } from "zod";
|
|
|
3
3
|
import { createEventStoreExecutor } from "../../db/event-store-executor";
|
|
4
4
|
import { defineFeature, type SaveContext } from "../../engine";
|
|
5
5
|
import {
|
|
6
|
-
createEntityTable,
|
|
7
6
|
createTestRedis,
|
|
8
7
|
setupTestStack,
|
|
9
8
|
type TestRedis,
|
|
10
9
|
type TestStack,
|
|
11
10
|
TestUsers,
|
|
11
|
+
unsafeCreateEntityTable,
|
|
12
12
|
} from "../../stack";
|
|
13
13
|
import { sharedItemEntity, sharedItemTable } from "../../testing";
|
|
14
14
|
import { createEventDedup } from "../event-dedup";
|
|
@@ -71,7 +71,7 @@ beforeAll(async () => {
|
|
|
71
71
|
systemHooks: [],
|
|
72
72
|
});
|
|
73
73
|
|
|
74
|
-
await
|
|
74
|
+
await unsafeCreateEntityTable(stack.db, sharedItemEntity, "item");
|
|
75
75
|
});
|
|
76
76
|
|
|
77
77
|
afterAll(async () => {
|
|
@@ -17,11 +17,11 @@ import { z } from "zod";
|
|
|
17
17
|
import { defineFeature } from "../../engine";
|
|
18
18
|
import { eventsTable } from "../../event-store";
|
|
19
19
|
import {
|
|
20
|
-
createEntityTable,
|
|
21
20
|
resetEventStore,
|
|
22
21
|
setupTestStack,
|
|
23
22
|
type TestStack,
|
|
24
23
|
TestUsers,
|
|
24
|
+
unsafeCreateEntityTable,
|
|
25
25
|
} from "../../stack";
|
|
26
26
|
import { sharedWidgetEntity } from "../../testing";
|
|
27
27
|
import { generateId } from "../../utils";
|
|
@@ -120,7 +120,7 @@ beforeAll(async () => {
|
|
|
120
120
|
features: [emitterFeature, neighborFeature],
|
|
121
121
|
systemHooks: [],
|
|
122
122
|
});
|
|
123
|
-
await
|
|
123
|
+
await unsafeCreateEntityTable(stack.db, sharedWidgetEntity, "widget");
|
|
124
124
|
});
|
|
125
125
|
|
|
126
126
|
afterEach(async () => {
|
|
@@ -25,11 +25,11 @@ import {
|
|
|
25
25
|
RecordingTracer,
|
|
26
26
|
} from "../../observability";
|
|
27
27
|
import {
|
|
28
|
-
createEntityTable,
|
|
29
28
|
resetEventStore,
|
|
30
29
|
setupTestStack,
|
|
31
30
|
type TestStack,
|
|
32
31
|
TestUsers,
|
|
32
|
+
unsafeCreateEntityTable,
|
|
33
33
|
} from "../../stack";
|
|
34
34
|
import { sharedWidgetEntity, sharedWidgetTable } from "../../testing";
|
|
35
35
|
|
|
@@ -85,7 +85,7 @@ beforeAll(async () => {
|
|
|
85
85
|
features: [wiringFeature],
|
|
86
86
|
systemHooks: [],
|
|
87
87
|
});
|
|
88
|
-
await
|
|
88
|
+
await unsafeCreateEntityTable(stack.db, sharedWidgetEntity, "widget");
|
|
89
89
|
tdb = createTenantDb(stack.db, admin.tenantId);
|
|
90
90
|
});
|
|
91
91
|
|
|
@@ -181,7 +181,7 @@ describe("E.1 — consumer-lag metric", () => {
|
|
|
181
181
|
observability: recordingProvider,
|
|
182
182
|
});
|
|
183
183
|
try {
|
|
184
|
-
await
|
|
184
|
+
await unsafeCreateEntityTable(recStack.db, sharedWidgetEntity, "widget");
|
|
185
185
|
const recTdb = createTenantDb(recStack.db, admin.tenantId);
|
|
186
186
|
await executor.create({ name: "lag-check" }, admin, recTdb);
|
|
187
187
|
|
|
@@ -30,11 +30,11 @@ import {
|
|
|
30
30
|
getConsumerState,
|
|
31
31
|
} from "../../pipeline";
|
|
32
32
|
import {
|
|
33
|
-
createEntityTable,
|
|
34
33
|
resetEventStore,
|
|
35
34
|
setupTestStack,
|
|
36
35
|
type TestStack,
|
|
37
36
|
TestUsers,
|
|
37
|
+
unsafeCreateEntityTable,
|
|
38
38
|
} from "../../stack";
|
|
39
39
|
import { sharedWidgetEntity, sharedWidgetTable } from "../../testing";
|
|
40
40
|
import { generateId } from "../../utils";
|
|
@@ -63,7 +63,7 @@ beforeAll(async () => {
|
|
|
63
63
|
features: [multiFeature],
|
|
64
64
|
systemHooks: [],
|
|
65
65
|
});
|
|
66
|
-
await
|
|
66
|
+
await unsafeCreateEntityTable(stack.db, sharedWidgetEntity, "widget");
|
|
67
67
|
tdb = createTenantDb(stack.db, admin.tenantId);
|
|
68
68
|
});
|
|
69
69
|
|
|
@@ -15,7 +15,7 @@ import { afterAll, beforeAll, describe, expect, test } from "vitest";
|
|
|
15
15
|
import { createEventStoreExecutor } from "../../db/event-store-executor";
|
|
16
16
|
import { createTenantDb, type TenantDb } from "../../db/tenant-db";
|
|
17
17
|
import { defineFeature } from "../../engine";
|
|
18
|
-
import {
|
|
18
|
+
import { setupTestStack, type TestStack, TestUsers, unsafeCreateEntityTable } from "../../stack";
|
|
19
19
|
import { sharedWidgetEntity, sharedWidgetTable } from "../../testing";
|
|
20
20
|
|
|
21
21
|
// --- Fixture ---
|
|
@@ -48,7 +48,7 @@ beforeAll(async () => {
|
|
|
48
48
|
features: [listenFeature],
|
|
49
49
|
systemHooks: [],
|
|
50
50
|
});
|
|
51
|
-
await
|
|
51
|
+
await unsafeCreateEntityTable(stack.db, sharedWidgetEntity, "widget");
|
|
52
52
|
tdb = createTenantDb(stack.db, admin.tenantId);
|
|
53
53
|
});
|
|
54
54
|
|
|
@@ -26,11 +26,11 @@ import {
|
|
|
26
26
|
skipPoisonEvent,
|
|
27
27
|
} from "../../pipeline";
|
|
28
28
|
import {
|
|
29
|
-
createEntityTable,
|
|
30
29
|
resetEventStore,
|
|
31
30
|
setupTestStack,
|
|
32
31
|
type TestStack,
|
|
33
32
|
TestUsers,
|
|
33
|
+
unsafeCreateEntityTable,
|
|
34
34
|
} from "../../stack";
|
|
35
35
|
import { sharedWidgetEntity, sharedWidgetTable } from "../../testing";
|
|
36
36
|
|
|
@@ -71,7 +71,7 @@ beforeAll(async () => {
|
|
|
71
71
|
features: [recoveryFeature],
|
|
72
72
|
systemHooks: [],
|
|
73
73
|
});
|
|
74
|
-
await
|
|
74
|
+
await unsafeCreateEntityTable(stack.db, sharedWidgetEntity, "widget");
|
|
75
75
|
tdb = createTenantDb(stack.db, admin.tenantId);
|
|
76
76
|
});
|
|
77
77
|
|
|
@@ -27,11 +27,11 @@ import {
|
|
|
27
27
|
} from "../../observability";
|
|
28
28
|
import { ConsumerLagError, eventConsumerStateTable, pruneEvents } from "../../pipeline";
|
|
29
29
|
import {
|
|
30
|
-
createEntityTable,
|
|
31
30
|
resetEventStore,
|
|
32
31
|
setupTestStack,
|
|
33
32
|
type TestStack,
|
|
34
33
|
TestUsers,
|
|
34
|
+
unsafeCreateEntityTable,
|
|
35
35
|
} from "../../stack";
|
|
36
36
|
import { sharedWidgetEntity } from "../../testing";
|
|
37
37
|
import { generateId } from "../../utils";
|
|
@@ -62,7 +62,7 @@ beforeAll(async () => {
|
|
|
62
62
|
features: [auditFeature],
|
|
63
63
|
systemHooks: [],
|
|
64
64
|
});
|
|
65
|
-
await
|
|
65
|
+
await unsafeCreateEntityTable(stack.db, sharedWidgetEntity, "widget");
|
|
66
66
|
});
|
|
67
67
|
|
|
68
68
|
afterEach(async () => {
|
|
@@ -179,7 +179,7 @@ describe("Second audit — LISTEN gauge", () => {
|
|
|
179
179
|
observability: recordingProvider,
|
|
180
180
|
});
|
|
181
181
|
try {
|
|
182
|
-
await
|
|
182
|
+
await unsafeCreateEntityTable(recStack.db, sharedWidgetEntity, "widget");
|
|
183
183
|
|
|
184
184
|
await recStack.eventDispatcher?.start();
|
|
185
185
|
try {
|
|
@@ -233,7 +233,7 @@ describe("Second audit — LISTEN gauge", () => {
|
|
|
233
233
|
observability: recordingProvider,
|
|
234
234
|
});
|
|
235
235
|
try {
|
|
236
|
-
await
|
|
236
|
+
await unsafeCreateEntityTable(recStack.db, sharedWidgetEntity, "widget");
|
|
237
237
|
|
|
238
238
|
await recStack.eventDispatcher?.start();
|
|
239
239
|
try {
|
|
@@ -26,12 +26,12 @@ import { defineFeature, type FeatureDefinition } from "../../engine";
|
|
|
26
26
|
import type { StoredEvent } from "../../event-store";
|
|
27
27
|
import { eventConsumerStateTable, getAllConsumerProgress, getConsumerState } from "../../pipeline";
|
|
28
28
|
import {
|
|
29
|
-
createEntityTable,
|
|
30
|
-
pushTables,
|
|
31
29
|
resetEventStore,
|
|
32
30
|
setupTestStack,
|
|
33
31
|
type TestStack,
|
|
34
32
|
TestUsers,
|
|
33
|
+
unsafeCreateEntityTable,
|
|
34
|
+
unsafePushTables,
|
|
35
35
|
} from "../../stack";
|
|
36
36
|
import { sharedWidgetEntity, sharedWidgetTable } from "../../testing";
|
|
37
37
|
|
|
@@ -98,8 +98,8 @@ beforeAll(async () => {
|
|
|
98
98
|
// hook chain. SSE / search are irrelevant to cursor behaviour.
|
|
99
99
|
systemHooks: [],
|
|
100
100
|
});
|
|
101
|
-
await
|
|
102
|
-
await
|
|
101
|
+
await unsafeCreateEntityTable(stack.db, sharedWidgetEntity, "widget");
|
|
102
|
+
await unsafePushTables(stack.db, { subscriberLog: subscriberLogTable });
|
|
103
103
|
tdb = createTenantDb(stack.db, admin.tenantId);
|
|
104
104
|
});
|
|
105
105
|
|
|
@@ -23,11 +23,11 @@ import {
|
|
|
23
23
|
pruneEvents,
|
|
24
24
|
} from "../../pipeline";
|
|
25
25
|
import {
|
|
26
|
-
createEntityTable,
|
|
27
26
|
resetEventStore,
|
|
28
27
|
setupTestStack,
|
|
29
28
|
type TestStack,
|
|
30
29
|
TestUsers,
|
|
30
|
+
unsafeCreateEntityTable,
|
|
31
31
|
} from "../../stack";
|
|
32
32
|
import { sharedWidgetEntity, sharedWidgetTable } from "../../testing";
|
|
33
33
|
import { generateId } from "../../utils";
|
|
@@ -61,7 +61,7 @@ beforeAll(async () => {
|
|
|
61
61
|
features: [retentionFeature],
|
|
62
62
|
systemHooks: [],
|
|
63
63
|
});
|
|
64
|
-
await
|
|
64
|
+
await unsafeCreateEntityTable(stack.db, sharedWidgetEntity, "widget");
|
|
65
65
|
tdb = createTenantDb(stack.db, admin.tenantId);
|
|
66
66
|
});
|
|
67
67
|
|
|
@@ -15,7 +15,7 @@ import { buildDrizzleTable } from "../../db/table-builder";
|
|
|
15
15
|
import { createEntity, createTextField, defineFeature } from "../../engine";
|
|
16
16
|
import { UnprocessableError, writeFailure } from "../../errors";
|
|
17
17
|
import { loadAggregate } from "../../event-store";
|
|
18
|
-
import {
|
|
18
|
+
import { setupTestStack, type TestStack, TestUsers, unsafeCreateEntityTable } from "../../stack";
|
|
19
19
|
|
|
20
20
|
// --- Feature ---
|
|
21
21
|
|
|
@@ -136,7 +136,7 @@ const admin = TestUsers.admin;
|
|
|
136
136
|
|
|
137
137
|
beforeAll(async () => {
|
|
138
138
|
stack = await setupTestStack({ features: [cartFeature], systemHooks: [] });
|
|
139
|
-
await
|
|
139
|
+
await unsafeCreateEntityTable(stack.db, cartEntity, "f4wCart");
|
|
140
140
|
});
|
|
141
141
|
|
|
142
142
|
afterAll(async () => {
|
|
@@ -13,11 +13,11 @@ import { buildDrizzleTable } from "../../db/table-builder";
|
|
|
13
13
|
import { createEntity, createTextField, defineFeature } from "../../engine";
|
|
14
14
|
import { append, loadAggregate as loadAggregateRaw } from "../../event-store";
|
|
15
15
|
import {
|
|
16
|
-
createEntityTable,
|
|
17
16
|
resetEventStore,
|
|
18
17
|
setupTestStack,
|
|
19
18
|
type TestStack,
|
|
20
19
|
TestUsers,
|
|
20
|
+
unsafeCreateEntityTable,
|
|
21
21
|
} from "../../stack";
|
|
22
22
|
|
|
23
23
|
// --- Fixture entity ---
|
|
@@ -131,7 +131,7 @@ const admin = TestUsers.admin;
|
|
|
131
131
|
|
|
132
132
|
beforeAll(async () => {
|
|
133
133
|
stack = await setupTestStack({ features: [asOfFeature], systemHooks: [] });
|
|
134
|
-
await
|
|
134
|
+
await unsafeCreateEntityTable(stack.db, invoiceEntity, "asof-invoice");
|
|
135
135
|
});
|
|
136
136
|
|
|
137
137
|
afterAll(async () => {
|
|
@@ -15,11 +15,11 @@ import { createTenantDb, type TenantDb } from "../../db/tenant-db";
|
|
|
15
15
|
import { defineFeature } from "../../engine";
|
|
16
16
|
import { getConsumerState } from "../../pipeline";
|
|
17
17
|
import {
|
|
18
|
-
createEntityTable,
|
|
19
18
|
resetEventStore,
|
|
20
19
|
setupTestStack,
|
|
21
20
|
type TestStack,
|
|
22
21
|
TestUsers,
|
|
22
|
+
unsafeCreateEntityTable,
|
|
23
23
|
} from "../../stack";
|
|
24
24
|
import { sharedWidgetEntity, sharedWidgetTable } from "../../testing";
|
|
25
25
|
|
|
@@ -80,7 +80,7 @@ beforeAll(async () => {
|
|
|
80
80
|
features: [z2Feature],
|
|
81
81
|
systemHooks: [],
|
|
82
82
|
});
|
|
83
|
-
await
|
|
83
|
+
await unsafeCreateEntityTable(stack.db, sharedWidgetEntity, "widget");
|
|
84
84
|
tdb = createTenantDb(stack.db, admin.tenantId);
|
|
85
85
|
});
|
|
86
86
|
|
|
@@ -17,11 +17,11 @@ import { buildDrizzleTable } from "../../db/table-builder";
|
|
|
17
17
|
import { createEntity, createTextField, defineFeature } from "../../engine";
|
|
18
18
|
import { eventsTable } from "../../event-store";
|
|
19
19
|
import {
|
|
20
|
-
createEntityTable,
|
|
21
20
|
resetEventStore,
|
|
22
21
|
setupTestStack,
|
|
23
22
|
type TestStack,
|
|
24
23
|
TestUsers,
|
|
24
|
+
unsafeCreateEntityTable,
|
|
25
25
|
} from "../../stack";
|
|
26
26
|
|
|
27
27
|
// --- Feature ---
|
|
@@ -109,7 +109,7 @@ const admin = TestUsers.admin;
|
|
|
109
109
|
|
|
110
110
|
beforeAll(async () => {
|
|
111
111
|
stack = await setupTestStack({ features: [mmhFeature], systemHooks: [] });
|
|
112
|
-
await
|
|
112
|
+
await unsafeCreateEntityTable(stack.db, orderEntity, "mmh-order");
|
|
113
113
|
});
|
|
114
114
|
|
|
115
115
|
afterAll(async () => {
|
|
@@ -28,11 +28,11 @@ import {
|
|
|
28
28
|
rebuildMultiStreamProjection,
|
|
29
29
|
} from "../../pipeline";
|
|
30
30
|
import {
|
|
31
|
-
createEntityTable,
|
|
32
31
|
resetEventStore,
|
|
33
32
|
setupTestStack,
|
|
34
33
|
type TestStack,
|
|
35
34
|
TestUsers,
|
|
35
|
+
unsafeCreateEntityTable,
|
|
36
36
|
} from "../../stack";
|
|
37
37
|
|
|
38
38
|
// --- Fixtures: two aggregates feeding one MSP + two cornered MSPs ---
|
|
@@ -211,8 +211,8 @@ beforeAll(async () => {
|
|
|
211
211
|
features: [feature],
|
|
212
212
|
systemHooks: [],
|
|
213
213
|
});
|
|
214
|
-
await
|
|
215
|
-
await
|
|
214
|
+
await unsafeCreateEntityTable(stack.db, invoiceEntity, "msp-reb-invoice");
|
|
215
|
+
await unsafeCreateEntityTable(stack.db, paymentEntity, "msp-reb-payment");
|
|
216
216
|
});
|
|
217
217
|
|
|
218
218
|
afterAll(async () => {
|
|
@@ -14,12 +14,12 @@ import { createEventStoreExecutor } from "../../db/event-store-executor";
|
|
|
14
14
|
import { buildDrizzleTable } from "../../db/table-builder";
|
|
15
15
|
import { createEntity, createTextField, defineFeature } from "../../engine";
|
|
16
16
|
import {
|
|
17
|
-
createEntityTable,
|
|
18
17
|
createTestUser,
|
|
19
18
|
resetEventStore,
|
|
20
19
|
setupTestStack,
|
|
21
20
|
type TestStack,
|
|
22
21
|
TestUsers,
|
|
22
|
+
unsafeCreateEntityTable,
|
|
23
23
|
} from "../../stack";
|
|
24
24
|
|
|
25
25
|
// --- Two aggregate types that feed one MSP ---
|
|
@@ -162,8 +162,8 @@ const admin = TestUsers.admin;
|
|
|
162
162
|
|
|
163
163
|
beforeAll(async () => {
|
|
164
164
|
stack = await setupTestStack({ features: [mspFeature], systemHooks: [] });
|
|
165
|
-
await
|
|
166
|
-
await
|
|
165
|
+
await unsafeCreateEntityTable(stack.db, shipmentEntity, "msp-shipment");
|
|
166
|
+
await unsafeCreateEntityTable(stack.db, refundEntity, "msp-refund");
|
|
167
167
|
});
|
|
168
168
|
|
|
169
169
|
afterAll(async () => {
|
|
@@ -24,7 +24,7 @@ import { createEntity, createRegistry, createTextField, defineFeature } from "..
|
|
|
24
24
|
import type { ProjectionDefinition } from "../../engine/types";
|
|
25
25
|
import { createEventsTable } from "../../event-store";
|
|
26
26
|
import { createProjectionStateTable, rebuildProjection } from "../../pipeline";
|
|
27
|
-
import { createTestDb,
|
|
27
|
+
import { createTestDb, type TestDb, TestUsers, unsafePushTables } from "../../stack";
|
|
28
28
|
import { generateId as uuid } from "../../utils";
|
|
29
29
|
|
|
30
30
|
// Counter projection: every task.created bumps a counter, every
|
|
@@ -77,7 +77,7 @@ beforeAll(async () => {
|
|
|
77
77
|
testDb = await createTestDb();
|
|
78
78
|
await createEventsTable(testDb.db);
|
|
79
79
|
await createProjectionStateTable(testDb.db);
|
|
80
|
-
await
|
|
80
|
+
await unsafePushTables(testDb.db, { perf_rebuild_task_count: taskCountTable });
|
|
81
81
|
});
|
|
82
82
|
|
|
83
83
|
afterAll(async () => {
|
|
@@ -36,7 +36,13 @@ import {
|
|
|
36
36
|
listProjectionsWithState,
|
|
37
37
|
rebuildProjection,
|
|
38
38
|
} from "../../pipeline";
|
|
39
|
-
import {
|
|
39
|
+
import {
|
|
40
|
+
createTestDb,
|
|
41
|
+
type TestDb,
|
|
42
|
+
TestUsers,
|
|
43
|
+
unsafeCreateEntityTable,
|
|
44
|
+
unsafePushTables,
|
|
45
|
+
} from "../../stack";
|
|
40
46
|
|
|
41
47
|
// --- Test fixtures ---
|
|
42
48
|
|
|
@@ -103,10 +109,10 @@ const executor = createEventStoreExecutor(itemTable, itemEntity, { entityName: "
|
|
|
103
109
|
|
|
104
110
|
beforeAll(async () => {
|
|
105
111
|
testDb = await createTestDb();
|
|
106
|
-
await
|
|
112
|
+
await unsafeCreateEntityTable(testDb.db, itemEntity, "rebuild-item");
|
|
107
113
|
await createEventsTable(testDb.db);
|
|
108
114
|
await createProjectionStateTable(testDb.db);
|
|
109
|
-
await
|
|
115
|
+
await unsafePushTables(testDb.db, { rebuildItemsPerGroup: itemsPerGroupTable });
|
|
110
116
|
tdb = createTenantDb(testDb.db, admin.tenantId);
|
|
111
117
|
});
|
|
112
118
|
|
|
@@ -15,11 +15,11 @@ import { createEventStoreExecutor } from "../../db/event-store-executor";
|
|
|
15
15
|
import { buildDrizzleTable } from "../../db/table-builder";
|
|
16
16
|
import { createEntity, createTextField, defineFeature } from "../../engine";
|
|
17
17
|
import {
|
|
18
|
-
createEntityTable,
|
|
19
18
|
resetEventStore,
|
|
20
19
|
setupTestStack,
|
|
21
20
|
type TestStack,
|
|
22
21
|
TestUsers,
|
|
22
|
+
unsafeCreateEntityTable,
|
|
23
23
|
} from "../../stack";
|
|
24
24
|
|
|
25
25
|
const widgetEntity = createEntity({
|
|
@@ -121,7 +121,7 @@ const otherTenantAdmin = {
|
|
|
121
121
|
|
|
122
122
|
beforeAll(async () => {
|
|
123
123
|
stack = await setupTestStack({ features: [qpFeature], systemHooks: [] });
|
|
124
|
-
await
|
|
124
|
+
await unsafeCreateEntityTable(stack.db, widgetEntity, "qp-widget");
|
|
125
125
|
});
|
|
126
126
|
|
|
127
127
|
afterAll(async () => {
|
|
@@ -2,7 +2,7 @@ import { sql } from "drizzle-orm";
|
|
|
2
2
|
import type { DbConnection } from "../db/connection";
|
|
3
3
|
import { bigint, index, instant, integer, table as pgTable, primaryKey, text } from "../db/dialect";
|
|
4
4
|
import { tableExists } from "../db/schema-inspection";
|
|
5
|
-
import {
|
|
5
|
+
import { unsafePushTables } from "../stack";
|
|
6
6
|
|
|
7
7
|
// Reserved sentinel used in the instance_id column for consumers whose
|
|
8
8
|
// delivery is "shared" — i.e. one cursor across all dispatcher instances
|
|
@@ -104,5 +104,5 @@ export const CONSUMER_STATUSES = [
|
|
|
104
104
|
export async function createEventConsumerStateTable(db: DbConnection): Promise<void> {
|
|
105
105
|
// skip: table already exists — bootstrap is called from multiple paths
|
|
106
106
|
if (await tableExists(db, "public.kumiko_event_consumers")) return;
|
|
107
|
-
await
|
|
107
|
+
await unsafePushTables(db, { kumikoEventConsumers: eventConsumerStateTable });
|
|
108
108
|
}
|