@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.
Files changed (66) hide show
  1. package/LICENSE +57 -0
  2. package/package.json +1 -1
  3. package/src/__tests__/anonymous-access.integration.ts +7 -7
  4. package/src/__tests__/error-contract.integration.ts +2 -2
  5. package/src/__tests__/field-access.integration.ts +2 -2
  6. package/src/__tests__/full-stack.integration.ts +2 -2
  7. package/src/__tests__/ownership.integration.ts +2 -2
  8. package/src/__tests__/raw-table.integration.ts +128 -0
  9. package/src/__tests__/reference-data.integration.ts +2 -2
  10. package/src/__tests__/transition-guard.integration.ts +4 -4
  11. package/src/api/__tests__/batch.integration.ts +3 -3
  12. package/src/api/__tests__/dispatcher-live.integration.ts +2 -2
  13. package/src/api/__tests__/nested-write.integration.ts +3 -3
  14. package/src/db/__tests__/drizzle-helpers.integration.ts +2 -2
  15. package/src/db/__tests__/event-store-executor-list.integration.ts +2 -2
  16. package/src/db/__tests__/event-store-executor.integration.ts +9 -3
  17. package/src/db/__tests__/implicit-projection-equivalence.integration.ts +3 -3
  18. package/src/db/__tests__/multi-row-insert.integration.ts +3 -3
  19. package/src/db/__tests__/schema-migration.integration.ts +9 -9
  20. package/src/db/__tests__/tenant-db.integration.ts +4 -4
  21. package/src/db/__tests__/unique-violation-mapping.integration.ts +2 -2
  22. package/src/db/schema-inspection.ts +1 -1
  23. package/src/engine/__tests__/raw-table.test.ts +149 -0
  24. package/src/engine/define-feature.ts +38 -0
  25. package/src/engine/registry.ts +46 -0
  26. package/src/engine/types/feature.ts +55 -0
  27. package/src/engine/types/index.ts +3 -0
  28. package/src/event-store/__tests__/upcaster.integration.ts +11 -5
  29. package/src/event-store/archive.ts +2 -2
  30. package/src/event-store/events-schema.ts +2 -2
  31. package/src/event-store/snapshot.ts +2 -2
  32. package/src/event-store/upcaster-dead-letter.ts +2 -2
  33. package/src/files/__tests__/file-field-column.integration.ts +4 -4
  34. package/src/files/__tests__/file-field-pipeline.integration.ts +2 -2
  35. package/src/files/__tests__/files.integration.ts +8 -8
  36. package/src/observability/__tests__/observability.integration.ts +2 -2
  37. package/src/pipeline/__tests__/archive-stream.integration.ts +2 -2
  38. package/src/pipeline/__tests__/cascade-handler.integration.ts +9 -9
  39. package/src/pipeline/__tests__/causation-chain.integration.ts +2 -2
  40. package/src/pipeline/__tests__/ctx-bridge.integration.ts +3 -3
  41. package/src/pipeline/__tests__/domain-events-projections.integration.ts +2 -2
  42. package/src/pipeline/__tests__/event-dedup.integration.ts +2 -2
  43. package/src/pipeline/__tests__/event-define-event-strict.integration.ts +2 -2
  44. package/src/pipeline/__tests__/event-dispatcher-lifecycle.integration.ts +3 -3
  45. package/src/pipeline/__tests__/event-dispatcher-multi-instance.integration.ts +2 -2
  46. package/src/pipeline/__tests__/event-dispatcher-pg-listen.integration.ts +2 -2
  47. package/src/pipeline/__tests__/event-dispatcher-recovery.integration.ts +2 -2
  48. package/src/pipeline/__tests__/event-dispatcher-second-audit.integration.ts +4 -4
  49. package/src/pipeline/__tests__/event-dispatcher.integration.ts +4 -4
  50. package/src/pipeline/__tests__/event-retention.integration.ts +2 -2
  51. package/src/pipeline/__tests__/fetch-for-writing.integration.ts +2 -2
  52. package/src/pipeline/__tests__/load-aggregate-query.integration.ts +2 -2
  53. package/src/pipeline/__tests__/msp-error-mode.integration.ts +2 -2
  54. package/src/pipeline/__tests__/msp-multi-hop.integration.ts +2 -2
  55. package/src/pipeline/__tests__/msp-rebuild.integration.ts +3 -3
  56. package/src/pipeline/__tests__/multi-stream-projection.integration.ts +3 -3
  57. package/src/pipeline/__tests__/perf-rebuild.integration.ts +2 -2
  58. package/src/pipeline/__tests__/projection-rebuild.integration.ts +9 -3
  59. package/src/pipeline/__tests__/query-projection.integration.ts +2 -2
  60. package/src/pipeline/event-consumer-state.ts +2 -2
  61. package/src/pipeline/projection-state.ts +3 -3
  62. package/src/stack/index.ts +4 -3
  63. package/src/stack/push-entity-projection-tables.ts +51 -0
  64. package/src/stack/table-helpers.ts +20 -13
  65. package/src/stack/test-stack.ts +13 -4
  66. 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 pushTables(testDb.db, { fileRefsTable });
68
- await createEntityTable(testDb.db, testTenantEntity);
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 pushTables(isolatedDb.db, { fileRefsTable });
406
- await createEntityTable(isolatedDb.db, testTenantEntity);
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 pushTables(isolatedDb.db, { fileRefsTable });
720
- await createEntityTable(isolatedDb.db, testTenantEntity);
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 createEntityTable(stack.db, todoEntity, "todo");
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 createEntityTable(stack.db, itemEntity, "arch-item");
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 { createEntityTable, createTestDb, type TestDb, TestUsers } from "../../stack";
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 createEntityTable(testDb.db, departmentEntity);
85
- await createEntityTable(testDb.db, userEntity);
86
- await createEntityTable(testDb.db, sessionEntity);
87
- await createEntityTable(testDb.db, groupEntity);
88
- await createEntityTable(testDb.db, userGroupRestrictEntity);
89
- await createEntityTable(testDb.db, userGroupCascadeEntity);
90
- await createEntityTable(testDb.db, teamEntity);
91
- await createEntityTable(testDb.db, memberEntity);
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 createEntityTable(stack.db, orderEntity, "causation-order");
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 { createEntityTable, setupTestStack, type TestStack, TestUsers } from "../../stack";
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 createEntityTable(stack.db, bagEntity);
148
- await createEntityTable(stack.db, secretEntity);
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 createEntityTable(stack.db, shipmentEntity, "domain-shipment");
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 createEntityTable(stack.db, sharedItemEntity, "item");
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 createEntityTable(stack.db, sharedWidgetEntity, "widget");
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 createEntityTable(stack.db, sharedWidgetEntity, "widget");
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 createEntityTable(recStack.db, sharedWidgetEntity, "widget");
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 createEntityTable(stack.db, sharedWidgetEntity, "widget");
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 { createEntityTable, setupTestStack, type TestStack, TestUsers } from "../../stack";
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 createEntityTable(stack.db, sharedWidgetEntity, "widget");
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 createEntityTable(stack.db, sharedWidgetEntity, "widget");
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 createEntityTable(stack.db, sharedWidgetEntity, "widget");
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 createEntityTable(recStack.db, sharedWidgetEntity, "widget");
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 createEntityTable(recStack.db, sharedWidgetEntity, "widget");
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 createEntityTable(stack.db, sharedWidgetEntity, "widget");
102
- await pushTables(stack.db, { subscriberLog: subscriberLogTable });
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 createEntityTable(stack.db, sharedWidgetEntity, "widget");
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 { createEntityTable, setupTestStack, type TestStack, TestUsers } from "../../stack";
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 createEntityTable(stack.db, cartEntity, "f4wCart");
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 createEntityTable(stack.db, invoiceEntity, "asof-invoice");
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 createEntityTable(stack.db, sharedWidgetEntity, "widget");
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 createEntityTable(stack.db, orderEntity, "mmh-order");
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 createEntityTable(stack.db, invoiceEntity, "msp-reb-invoice");
215
- await createEntityTable(stack.db, paymentEntity, "msp-reb-payment");
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 createEntityTable(stack.db, shipmentEntity, "msp-shipment");
166
- await createEntityTable(stack.db, refundEntity, "msp-refund");
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, pushTables, type TestDb, TestUsers } from "../../stack";
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 pushTables(testDb.db, { perf_rebuild_task_count: taskCountTable });
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 { createEntityTable, createTestDb, pushTables, type TestDb, TestUsers } from "../../stack";
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 createEntityTable(testDb.db, itemEntity, "rebuild-item");
112
+ await unsafeCreateEntityTable(testDb.db, itemEntity, "rebuild-item");
107
113
  await createEventsTable(testDb.db);
108
114
  await createProjectionStateTable(testDb.db);
109
- await pushTables(testDb.db, { rebuildItemsPerGroup: itemsPerGroupTable });
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 createEntityTable(stack.db, widgetEntity, "qp-widget");
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 { pushTables } from "../stack";
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 pushTables(db, { kumikoEventConsumers: eventConsumerStateTable });
107
+ await unsafePushTables(db, { kumikoEventConsumers: eventConsumerStateTable });
108
108
  }