@cosmicdrift/kumiko-server-runtime 0.273.0 → 0.275.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-server-runtime",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.275.0",
|
|
4
4
|
"description": "Production server-boot runtime for Kumiko apps: connections, schema-drift-gate, seeds, lifecycle, graceful shutdown. Symmetric to kumiko-dev-server's runDevApp, without dev/scaffold/codegen tooling.",
|
|
5
5
|
"license": "BUSL-1.1",
|
|
6
6
|
"author": "Marc Frost <marc@cosmicdriftgamestudio.com>",
|
|
@@ -80,8 +80,8 @@
|
|
|
80
80
|
}
|
|
81
81
|
},
|
|
82
82
|
"dependencies": {
|
|
83
|
-
"@cosmicdrift/kumiko-bundled-features": "0.
|
|
84
|
-
"@cosmicdrift/kumiko-framework": "0.
|
|
83
|
+
"@cosmicdrift/kumiko-bundled-features": "0.275.0",
|
|
84
|
+
"@cosmicdrift/kumiko-framework": "0.275.0",
|
|
85
85
|
"temporal-polyfill": "^0.3.2"
|
|
86
86
|
},
|
|
87
87
|
"publishConfig": {
|
|
@@ -8,6 +8,8 @@
|
|
|
8
8
|
// dispatched ins Leere → 500.
|
|
9
9
|
|
|
10
10
|
import { describe, expect, spyOn, test } from "bun:test";
|
|
11
|
+
import { securityBaselineFeatures } from "@cosmicdrift/kumiko-bundled-features/presets";
|
|
12
|
+
import { createSessionsFeature } from "@cosmicdrift/kumiko-bundled-features/sessions";
|
|
11
13
|
import { defineFeature, validateBoot } from "@cosmicdrift/kumiko-framework/engine";
|
|
12
14
|
import { composeFeatures } from "../compose-features";
|
|
13
15
|
|
|
@@ -190,4 +192,15 @@ describe("composeFeatures", () => {
|
|
|
190
192
|
if (!auth) return;
|
|
191
193
|
expect(Object.keys(auth.writeHandlers)).toContain("login");
|
|
192
194
|
});
|
|
195
|
+
|
|
196
|
+
test("includeBundled=false → sessions mounted via preset + standalone collapses to one entry", () => {
|
|
197
|
+
const sessionsInstances = securityBaselineFeatures();
|
|
198
|
+
const standaloneSessions = createSessionsFeature();
|
|
199
|
+
const features = composeFeatures([...sessionsInstances, standaloneSessions], {
|
|
200
|
+
includeBundled: false,
|
|
201
|
+
});
|
|
202
|
+
const sessionsEntries = features.filter((f) => f.name === "sessions");
|
|
203
|
+
expect(sessionsEntries).toHaveLength(1);
|
|
204
|
+
expect(sessionsEntries[0]).toBe(sessionsInstances[0]);
|
|
205
|
+
});
|
|
193
206
|
});
|
package/src/compose-features.ts
CHANGED
|
@@ -32,7 +32,7 @@ import {
|
|
|
32
32
|
import { createConfigFeature } from "@cosmicdrift/kumiko-bundled-features/config";
|
|
33
33
|
import { createTenantFeature } from "@cosmicdrift/kumiko-bundled-features/tenant";
|
|
34
34
|
import { createUserFeature } from "@cosmicdrift/kumiko-bundled-features/user";
|
|
35
|
-
import type
|
|
35
|
+
import { dedupeFeatures, type FeatureDefinition } from "@cosmicdrift/kumiko-framework/engine";
|
|
36
36
|
|
|
37
37
|
export type ComposeFeaturesOptions = {
|
|
38
38
|
/** When true, prepends config + user + tenant + auth-email-password
|
|
@@ -58,7 +58,7 @@ export function composeFeatures(
|
|
|
58
58
|
// own createAuthEmailPasswordFeature(...) call, or login silently
|
|
59
59
|
// bypasses MFA. Upgrade if this trips someone: warn here when appFeatures
|
|
60
60
|
// contains AUTH_MFA_FEATURE but includeBundled is false.
|
|
61
|
-
if (!options.includeBundled) return
|
|
61
|
+
if (!options.includeBundled) return dedupeFeatures(appFeatures);
|
|
62
62
|
|
|
63
63
|
// Bundled foundation goes first so its instances carry the runDevApp /
|
|
64
64
|
// runProdApp `authOptions` (passwordReset wiring etc.). App-features that
|
|
@@ -71,7 +71,8 @@ export function composeFeatures(
|
|
|
71
71
|
// via APP_FEATURES) — but if it's there, the login handler needs its
|
|
72
72
|
// status-checker wired in at construction time, since createAuthEmail-
|
|
73
73
|
// PasswordFeature is built right here, before the caller ever sees it.
|
|
74
|
-
const
|
|
74
|
+
const dedupedAppFeatures = dedupeFeatures(appFeatures);
|
|
75
|
+
const mfaFeature = dedupedAppFeatures.find((f) => f.name === AUTH_MFA_FEATURE);
|
|
75
76
|
const authOptions = mfaFeature
|
|
76
77
|
? { ...options.authOptions, mfaStatusChecker: mfaStatusCheckerFromFeature(mfaFeature) }
|
|
77
78
|
: options.authOptions;
|
|
@@ -95,7 +96,7 @@ export function composeFeatures(
|
|
|
95
96
|
];
|
|
96
97
|
const bundledNames = new Set(bundled.map((f) => f.name));
|
|
97
98
|
const filteredApp: FeatureDefinition[] = [];
|
|
98
|
-
for (const f of
|
|
99
|
+
for (const f of dedupedAppFeatures) {
|
|
99
100
|
if (bundledNames.has(f.name)) {
|
|
100
101
|
// biome-ignore lint/suspicious/noConsole: boot-time UX warning
|
|
101
102
|
console.warn(
|