@cosmicdrift/kumiko-server-runtime 0.210.0 → 0.211.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.210.0",
3
+ "version": "0.211.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.210.0",
84
- "@cosmicdrift/kumiko-framework": "0.210.0",
83
+ "@cosmicdrift/kumiko-bundled-features": "0.211.0",
84
+ "@cosmicdrift/kumiko-framework": "0.211.0",
85
85
  "temporal-polyfill": "^0.3.2"
86
86
  },
87
87
  "publishConfig": {
@@ -8,7 +8,7 @@
8
8
  // dispatched ins Leere → 500.
9
9
 
10
10
  import { describe, expect, spyOn, test } from "bun:test";
11
- import { defineFeature } from "@cosmicdrift/kumiko-framework/engine";
11
+ import { defineFeature, validateBoot } from "@cosmicdrift/kumiko-framework/engine";
12
12
  import { composeFeatures } from "../compose-features";
13
13
 
14
14
  const noopFeature = defineFeature("noop-app", () => {});
@@ -130,6 +130,38 @@ describe("composeFeatures", () => {
130
130
  expect(handlerNames).toContain("logout");
131
131
  });
132
132
 
133
+ // fw#2223 regression: without this wiring, includeBundled apps that DO
134
+ // configure authOptions.invite still got /members with no invite button —
135
+ // the screen is bound to auth-email-password's invite-create handler,
136
+ // which only exists when opts.invite is set (feature.ts:238-239).
137
+ test("authOptions.invite → tenant bekommt invite-Screen + Toolbar-Action; ohne invite bootet sauber ohne beides", () => {
138
+ const withInvite = composeFeatures([noopFeature], {
139
+ includeBundled: true,
140
+ authOptions: { invite: { appUrl: "https://app/invite" } },
141
+ });
142
+ const tenantWith = withInvite.find((f) => f.name === "tenant");
143
+ expect(tenantWith).toBeDefined();
144
+ if (!tenantWith) return;
145
+ const membersScreenWith = tenantWith.screens["members"];
146
+ if (membersScreenWith?.type !== "projectionList") {
147
+ throw new Error("expected members screen to be projectionList");
148
+ }
149
+ expect(membersScreenWith.toolbarActions?.some((a) => a.id === "invite")).toBe(true);
150
+ expect(tenantWith.screens["invite-create"]).toBeDefined();
151
+
152
+ const withoutInvite = composeFeatures([noopFeature], { includeBundled: true });
153
+ const tenantWithout = withoutInvite.find((f) => f.name === "tenant");
154
+ expect(tenantWithout).toBeDefined();
155
+ if (!tenantWithout) return;
156
+ const membersScreenWithout = tenantWithout.screens["members"];
157
+ if (membersScreenWithout?.type !== "projectionList") {
158
+ throw new Error("expected members screen to be projectionList");
159
+ }
160
+ expect(membersScreenWithout.toolbarActions ?? []).toHaveLength(0);
161
+ expect(tenantWithout.screens["invite-create"]).toBeUndefined();
162
+ expect(() => validateBoot(withoutInvite)).not.toThrow();
163
+ });
164
+
133
165
  test("app feature duplicating a bundled name is dropped (no createRegistry crash)", () => {
134
166
  // create-kumiko-app's picker hands back createAuthEmailPasswordFeature()
135
167
  // because the user ticked it in the recommended set; runDevApp then adds
@@ -78,7 +78,11 @@ export function composeFeatures(
78
78
  const bundled = [
79
79
  createConfigFeature(),
80
80
  createUserFeature(),
81
- createTenantFeature(),
81
+ // inviteScreen mirrors authOptions.invite: that's the exact option that
82
+ // makes auth-email-password register the invite-create write-handler
83
+ // the /members invite drawer is bound to — without this, includeBundled
84
+ // apps that DO configure invite still get /members with no invite button.
85
+ createTenantFeature({ inviteScreen: Boolean(authOptions?.invite) }),
82
86
  createAuthEmailPasswordFeature(authOptions ?? {}),
83
87
  // signup-request/signup-confirm are registered whenever authOptions.signup
84
88
  // is set (see above), but the handler itself no-ops unless the companion