@cosmicdrift/kumiko-framework 0.45.0 → 0.45.1

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cosmicdrift/kumiko-framework",
3
- "version": "0.45.0",
3
+ "version": "0.45.1",
4
4
  "description": "Framework core — engine, pipeline, API, DB, and every other bit that makes Kumiko go.",
5
5
  "license": "BUSL-1.1",
6
6
  "author": "Marc Frost <marc@cosmicdriftgamestudio.com>",
@@ -3,6 +3,7 @@ import { existsSync, mkdirSync, readdirSync, readFileSync, rmSync, writeFileSync
3
3
  import { tmpdir } from "node:os";
4
4
  import { join } from "node:path";
5
5
  import { type BunTestDb, createTestDb } from "../bun-db/__tests__/bun-test-db";
6
+ import { createDbConnection, tableExists } from "../db";
6
7
  import { runSchemaCli, type SchemaCliOut } from "../schema-cli";
7
8
  import { ensureTemporalPolyfill } from "../time/polyfill";
8
9
 
@@ -186,6 +187,33 @@ describe("runSchemaCli — DB-backed paths", () => {
186
187
  rmSync(appCwd, { recursive: true, force: true });
187
188
  });
188
189
 
190
+ test("apply creates the framework-infra tables on a greenfield DB", async () => {
191
+ // Regression-pin: a brand-new app (no legacy-drizzle cutover) only had its
192
+ // entity-read tables after `apply`, so runProdApp's first event-store access
193
+ // hit "relation kumiko_events does not exist". `apply` now ensures the
194
+ // framework-infra tables (idempotent) so a greenfield deploy boots.
195
+ const appCwd = freshAppCwd();
196
+ writeSchemaFile(appCwd, "tbl_infra");
197
+ await runSchemaCli(["generate", "infra_test"], appCwd, captureOut().out);
198
+ await runSchemaCli(["apply"], appCwd, captureOut().out);
199
+
200
+ const { db, close } = createDbConnection(dbUrl);
201
+ try {
202
+ for (const table of [
203
+ "public.kumiko_events",
204
+ "public.kumiko_snapshots",
205
+ "public.kumiko_archived_streams",
206
+ "public.kumiko_event_consumers",
207
+ "public.kumiko_projections",
208
+ ]) {
209
+ expect(await tableExists(db, table)).toBe(true);
210
+ }
211
+ } finally {
212
+ await close();
213
+ }
214
+ rmSync(appCwd, { recursive: true, force: true });
215
+ });
216
+
189
217
  test("status with pending migrations exits 1 (regression-pin: CI-gating signal)", async () => {
190
218
  const appCwd = freshAppCwd();
191
219
  writeSchemaFile(appCwd, "tbl_pending");
package/src/schema-cli.ts CHANGED
@@ -24,6 +24,8 @@ import {
24
24
  writeRebuildMarker,
25
25
  writeSnapshotJson,
26
26
  } from "./db";
27
+ import { createEventsTable } from "./event-store";
28
+ import { createEventConsumerStateTable, createProjectionStateTable } from "./pipeline";
27
29
 
28
30
  export type SchemaCliOut = {
29
31
  readonly log: (line: string) => void;
@@ -143,6 +145,14 @@ export async function runSchemaCli(
143
145
  const { db, close } = createDbConnection(dbUrl);
144
146
  try {
145
147
  const result = await runMigrationsFromDir(db, migrationsDir);
148
+ // Framework-Infra-Tabellen (event-store + pipeline-state) — die erfasst
149
+ // `generate` nicht (nur Entity-read-Tabellen). Bestehende DBs haben sie
150
+ // aus dem legacy-drizzle-Fundament; eine Greenfield-DB (erste App ohne
151
+ // Cutover) hätte sonst kein kumiko_events → runProdApp-Boot scheitert.
152
+ // Alle drei sind idempotent (tableExists-Gate), also no-op für Bestands-DBs.
153
+ await createEventsTable(db);
154
+ await createEventConsumerStateTable(db);
155
+ await createProjectionStateTable(db);
146
156
  out.log("");
147
157
  if (result.applied.length === 0) {
148
158
  out.log(` ✓ All ${result.skipped.length} migrations already applied.`);