@cosmicdrift/kumiko-framework 0.122.3 → 0.122.4
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.122.
|
|
3
|
+
"version": "0.122.4",
|
|
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>",
|
|
@@ -189,7 +189,7 @@
|
|
|
189
189
|
"zod": "^4.4.3"
|
|
190
190
|
},
|
|
191
191
|
"devDependencies": {
|
|
192
|
-
"@cosmicdrift/kumiko-dispatcher-live": "0.122.
|
|
192
|
+
"@cosmicdrift/kumiko-dispatcher-live": "0.122.4",
|
|
193
193
|
"bun-types": "^1.3.13",
|
|
194
194
|
"pino-pretty": "^13.1.3"
|
|
195
195
|
},
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { afterEach, describe, expect, spyOn, test } from "bun:test";
|
|
2
|
+
import { mkdirSync, mkdtempSync, rmSync } from "node:fs";
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import { runSchemaCli, type SchemaCliOut } from "../schema-cli";
|
|
6
|
+
import * as timeModule from "../time";
|
|
7
|
+
|
|
8
|
+
function captureOut(): { out: SchemaCliOut; log: string[]; err: string[] } {
|
|
9
|
+
const log: string[] = [];
|
|
10
|
+
const err: string[] = [];
|
|
11
|
+
return { out: { log: (l) => log.push(l), err: (l) => err.push(l) }, log, err };
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
describe("runSchemaCli — Temporal polyfill", () => {
|
|
15
|
+
let appCwd: string;
|
|
16
|
+
|
|
17
|
+
afterEach(() => {
|
|
18
|
+
if (appCwd) rmSync(appCwd, { recursive: true, force: true });
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
test("calls ensureTemporalPolyfill on every invocation", async () => {
|
|
22
|
+
// runProdApp/runDevApp call ensureTemporalPolyfill() at boot; the
|
|
23
|
+
// standalone CLI (migrate-db initContainer, `bun kumiko.js schema apply`)
|
|
24
|
+
// never goes through that boot path. Without this, a projection rebuild's
|
|
25
|
+
// tz/timestamp coercion throws "Temporal is not defined" on any runtime
|
|
26
|
+
// that lacks native Temporal — deterministically, since the crashed
|
|
27
|
+
// process still records the migration as applied and the rebuild is
|
|
28
|
+
// never retried on the next run.
|
|
29
|
+
//
|
|
30
|
+
// Asserting on globalThis.Temporal directly doesn't work here: the test
|
|
31
|
+
// harness's own preload (test-setup/base.preload.ts) already calls
|
|
32
|
+
// ensureTemporalPolyfill() once per process, and its idempotency cache
|
|
33
|
+
// (a module-level flag, not re-derived from globalThis) short-circuits
|
|
34
|
+
// any later call regardless of what a test does to globalThis.Temporal in
|
|
35
|
+
// between. Spying on the imported binding sidesteps that cache entirely.
|
|
36
|
+
appCwd = mkdtempSync(join(tmpdir(), "kumiko-schema-cli-temporal-"));
|
|
37
|
+
mkdirSync(join(appCwd, "kumiko"), { recursive: true });
|
|
38
|
+
const spy = spyOn(timeModule, "ensureTemporalPolyfill");
|
|
39
|
+
try {
|
|
40
|
+
const cap = captureOut();
|
|
41
|
+
const code = await runSchemaCli([], appCwd, cap.out);
|
|
42
|
+
expect(code).toBe(0);
|
|
43
|
+
expect(spy).toHaveBeenCalled();
|
|
44
|
+
} finally {
|
|
45
|
+
spy.mockRestore();
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
});
|
package/src/schema-cli.ts
CHANGED
|
@@ -36,6 +36,7 @@ import {
|
|
|
36
36
|
createProjectionStateTable,
|
|
37
37
|
rebuildProjection,
|
|
38
38
|
} from "./pipeline";
|
|
39
|
+
import { ensureTemporalPolyfill } from "./time";
|
|
39
40
|
|
|
40
41
|
export type SchemaCliOut = {
|
|
41
42
|
readonly log: (line: string) => void;
|
|
@@ -126,6 +127,13 @@ export async function runSchemaCli(
|
|
|
126
127
|
out: SchemaCliOut,
|
|
127
128
|
options: RunSchemaCliOptions = {},
|
|
128
129
|
): Promise<number> {
|
|
130
|
+
// runProdApp/runDevApp install this at boot; the standalone CLI (the
|
|
131
|
+
// migrate-db initContainer, `bun kumiko.js schema apply`) never goes through
|
|
132
|
+
// that boot path, so a projection rebuild's tz/timestamp coercion throws
|
|
133
|
+
// "Temporal is not defined" — deterministically, on every rebuild-marker
|
|
134
|
+
// migration, since the crashed process still records the migration as
|
|
135
|
+
// applied and the rebuild is never retried.
|
|
136
|
+
await ensureTemporalPolyfill();
|
|
129
137
|
const sub = argv[0];
|
|
130
138
|
const schemaFile = resolvePath(appCwd, "kumiko/schema.ts");
|
|
131
139
|
const migrationsDir = resolvePath(appCwd, "kumiko/migrations");
|