@cosmicdrift/kumiko-dev-server 0.112.0 → 0.113.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
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cosmicdrift/kumiko-dev-server",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.113.0",
|
|
4
4
|
"description": "Development server bootstrap for Kumiko apps. Bundles the client, mints dev-JWTs, injects the resolved AppSchema, and seeds an admin. Not for production.",
|
|
5
5
|
"license": "BUSL-1.1",
|
|
6
6
|
"author": "Marc Frost <marc@cosmicdriftgamestudio.com>",
|
|
@@ -50,8 +50,8 @@
|
|
|
50
50
|
"kumiko-schema-check": "./bin/kumiko-schema-check.ts"
|
|
51
51
|
},
|
|
52
52
|
"dependencies": {
|
|
53
|
-
"@cosmicdrift/kumiko-bundled-features": "0.
|
|
54
|
-
"@cosmicdrift/kumiko-framework": "0.
|
|
53
|
+
"@cosmicdrift/kumiko-bundled-features": "0.113.0",
|
|
54
|
+
"@cosmicdrift/kumiko-framework": "0.113.0",
|
|
55
55
|
"ts-morph": "^28.0.0"
|
|
56
56
|
},
|
|
57
57
|
"publishConfig": {
|
|
@@ -98,12 +98,11 @@ describe("composeFeatures", () => {
|
|
|
98
98
|
});
|
|
99
99
|
|
|
100
100
|
test("app feature duplicating a bundled name is dropped (no createRegistry crash)", () => {
|
|
101
|
-
//
|
|
102
|
-
//
|
|
103
|
-
//
|
|
104
|
-
//
|
|
105
|
-
//
|
|
106
|
-
// instance (it carries authOptions wiring) and drops the app stub.
|
|
101
|
+
// create-kumiko-app's picker hands back createAuthEmailPasswordFeature()
|
|
102
|
+
// because the user ticked it in the recommended set; runDevApp then adds
|
|
103
|
+
// its OWN bundled copy via includeBundled:true, and createRegistry throws
|
|
104
|
+
// "Duplicate feature: auth-email-password". The dedupe path keeps the
|
|
105
|
+
// bundled instance (it carries authOptions wiring) and drops the app stub.
|
|
107
106
|
const warnSpy = spyOn(console, "warn").mockImplementation(() => {});
|
|
108
107
|
const features = composeFeatures([pickerAuthDupe, noopFeature], {
|
|
109
108
|
includeBundled: true,
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
// `relation "kumiko_events" does not exist`. Dieser Test fährt den echten
|
|
7
7
|
// Pfad gegen eine leere DB + den idempotenten Re-Run.
|
|
8
8
|
|
|
9
|
-
import { afterAll, beforeAll, describe, expect, test } from "bun:test";
|
|
9
|
+
import { afterAll, beforeAll, describe, expect, spyOn, test } from "bun:test";
|
|
10
10
|
import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
|
11
11
|
import { tmpdir } from "node:os";
|
|
12
12
|
import { join } from "node:path";
|
|
@@ -76,7 +76,7 @@ describe("runSchemaApply", () => {
|
|
|
76
76
|
expect(await tableExists(conn.db, "public.read_thing")).toBe(true);
|
|
77
77
|
});
|
|
78
78
|
|
|
79
|
-
test("rebuild-Marker für nicht-registrierte Tabelle → kein Crash, 0", async () => {
|
|
79
|
+
test("rebuild-Marker für nicht-registrierte Tabelle → kein Crash, 0, aber laut warnen (522/3)", async () => {
|
|
80
80
|
writeFileSync(
|
|
81
81
|
join(migDir, "0002_more.sql"),
|
|
82
82
|
`CREATE TABLE "read_more" ("id" text PRIMARY KEY);`,
|
|
@@ -86,7 +86,10 @@ describe("runSchemaApply", () => {
|
|
|
86
86
|
JSON.stringify({ version: 1, tables: ["read_more"] }),
|
|
87
87
|
);
|
|
88
88
|
|
|
89
|
+
const warn = spyOn(console, "warn").mockImplementation(() => {});
|
|
89
90
|
expect(await runSchemaApply({ ...APPLY, appCwd })).toBe(0);
|
|
90
91
|
expect(await tableExists(conn.db, "public.read_more")).toBe(true);
|
|
92
|
+
expect(warn).toHaveBeenCalledWith(expect.stringContaining('Table "read_more"'));
|
|
93
|
+
warn.mockRestore();
|
|
91
94
|
});
|
|
92
95
|
});
|
package/src/run-dev-app.ts
CHANGED
|
@@ -238,8 +238,13 @@ export async function runDevApp(options: RunDevAppOptions): Promise<KumikoServer
|
|
|
238
238
|
});
|
|
239
239
|
|
|
240
240
|
// An explicitly wired file provider (options.files) satisfies the
|
|
241
|
-
// FILE_STORAGE_PROVIDER boot gate — set it before validateBoot runs.
|
|
242
|
-
if (
|
|
241
|
+
// FILE_STORAGE_PROVIDER boot gate — set it before validateBoot runs. Only
|
|
242
|
+
// if WE set it (532/2): deleting it after use instead of leaving a
|
|
243
|
+
// permanent process.env mutation, so a second runDevApp call in the same
|
|
244
|
+
// process (no files this time) doesn't fall through the gate falsely.
|
|
245
|
+
const setFileStorageProviderEnv =
|
|
246
|
+
options.files !== undefined && process.env["FILE_STORAGE_PROVIDER"] === undefined;
|
|
247
|
+
if (setFileStorageProviderEnv) {
|
|
243
248
|
process.env["FILE_STORAGE_PROVIDER"] = "configured";
|
|
244
249
|
}
|
|
245
250
|
|
|
@@ -248,7 +253,11 @@ export async function runDevApp(options: RunDevAppOptions): Promise<KumikoServer
|
|
|
248
253
|
// die früher nur runProdApp fing und sonst erst den Prod-Pod im
|
|
249
254
|
// CrashLoopBackOff sterben ließ (#359). Wirft synchron, bevor ein
|
|
250
255
|
// Socket oder Watcher (codegen-Write) aufgeht.
|
|
251
|
-
|
|
256
|
+
try {
|
|
257
|
+
validateBoot(features);
|
|
258
|
+
} finally {
|
|
259
|
+
if (setFileStorageProviderEnv) delete process.env["FILE_STORAGE_PROVIDER"];
|
|
260
|
+
}
|
|
252
261
|
warnIfNonUtcServerTimeZone();
|
|
253
262
|
validateAppCustomScreenWriteQns(process.cwd(), collectWriteHandlerQns(features));
|
|
254
263
|
|
package/src/schema-apply.ts
CHANGED
|
@@ -100,7 +100,16 @@ async function rebuildAffectedProjections(
|
|
|
100
100
|
const projections = new Set<string>();
|
|
101
101
|
for (const table of changedTables) {
|
|
102
102
|
const name = tableToProjection.get(table);
|
|
103
|
-
if (name)
|
|
103
|
+
if (name) {
|
|
104
|
+
projections.add(name);
|
|
105
|
+
} else {
|
|
106
|
+
// 522/3: a table in a .rebuild.json marker that no longer matches any
|
|
107
|
+
// registered projection would otherwise rebuild nothing and exit 0 —
|
|
108
|
+
// indistinguishable from "nothing needed a rebuild".
|
|
109
|
+
console.warn(
|
|
110
|
+
` ⚠ Table "${table}" is in a rebuild marker but matches no registered projection — skipped.`,
|
|
111
|
+
);
|
|
112
|
+
}
|
|
104
113
|
}
|
|
105
114
|
if (projections.size === 0) return;
|
|
106
115
|
|
package/src/welcome-banner.ts
CHANGED
|
@@ -37,10 +37,7 @@ export function renderWelcomeBanner(input: WelcomeBannerInput): string {
|
|
|
37
37
|
return [top, ...padded, bottom].join("\n");
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
-
//
|
|
41
|
-
// enough for ASCII + the small set of arrows/checkmarks used above; if a
|
|
42
|
-
// real wide-char ever lands in the banner the row alignment will drift,
|
|
43
|
-
// caught visually by the snapshot test.
|
|
40
|
+
// ponytail: codepoint width; ok for ASCII + arrows, add a width-lib if CJK ever lands here.
|
|
44
41
|
function stringWidth(s: string): number {
|
|
45
42
|
return [...s].length;
|
|
46
43
|
}
|