@cosmicdrift/kumiko-renderer-web 0.269.1 → 0.270.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-renderer-web",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.270.0",
|
|
4
4
|
"description": "Web-platform bindings for @cosmicdrift/kumiko-renderer. HTML default-primitives, browser history-based navigation, EventSource-backed live events, and a one-call createKumikoApp that mounts the whole stack via react-dom.",
|
|
5
5
|
"license": "BUSL-1.1",
|
|
6
6
|
"author": "Marc Frost <marc@cosmicdriftgamestudio.com>",
|
|
@@ -16,9 +16,9 @@
|
|
|
16
16
|
"./styles.css": "./src/styles.css"
|
|
17
17
|
},
|
|
18
18
|
"dependencies": {
|
|
19
|
-
"@cosmicdrift/kumiko-dispatcher-live": "0.
|
|
20
|
-
"@cosmicdrift/kumiko-headless": "0.
|
|
21
|
-
"@cosmicdrift/kumiko-renderer": "0.
|
|
19
|
+
"@cosmicdrift/kumiko-dispatcher-live": "0.270.0",
|
|
20
|
+
"@cosmicdrift/kumiko-headless": "0.270.0",
|
|
21
|
+
"@cosmicdrift/kumiko-renderer": "0.270.0",
|
|
22
22
|
"@radix-ui/react-dialog": "^1.1.15",
|
|
23
23
|
"@radix-ui/react-dropdown-menu": "^2.1.16",
|
|
24
24
|
"@radix-ui/react-label": "^2.1.8",
|
|
@@ -66,7 +66,7 @@
|
|
|
66
66
|
"@types/react-dom": "^19.2.3",
|
|
67
67
|
"jsdom": "^29.1.1",
|
|
68
68
|
"tailwindcss": "^4.3.0",
|
|
69
|
-
"@cosmicdrift/kumiko-locale-de": "0.
|
|
69
|
+
"@cosmicdrift/kumiko-locale-de": "0.270.0"
|
|
70
70
|
},
|
|
71
71
|
"repository": {
|
|
72
72
|
"type": "git",
|
|
@@ -183,7 +183,12 @@ describe("createKumikoApp", () => {
|
|
|
183
183
|
const openFeature: FeatureSchema = {
|
|
184
184
|
featureName: "tasks",
|
|
185
185
|
entities: { task: taskEntity },
|
|
186
|
-
screens: [
|
|
186
|
+
screens: [
|
|
187
|
+
{
|
|
188
|
+
...listScreen,
|
|
189
|
+
access: { openToAll: { reason: "test handler callable by any signed-in test user" } },
|
|
190
|
+
},
|
|
191
|
+
],
|
|
187
192
|
navs: [{ id: "task-list", label: "tasks:nav.task-list", screen: "tasks:screen:task-list" }],
|
|
188
193
|
};
|
|
189
194
|
const schema: AppSchema = { features: [restrictedFeature, openFeature] };
|
|
@@ -282,7 +287,7 @@ describe("createKumikoApp", () => {
|
|
|
282
287
|
id: "privacy-center",
|
|
283
288
|
type: "custom",
|
|
284
289
|
renderer: { react: { __component: "PrivacyCenterScreen" } },
|
|
285
|
-
access: { openToAll:
|
|
290
|
+
access: { openToAll: { reason: "test handler callable by any signed-in test user" } },
|
|
286
291
|
dormant: true,
|
|
287
292
|
},
|
|
288
293
|
],
|
|
@@ -539,7 +539,7 @@ const sessionsSchema: FeatureSchema = {
|
|
|
539
539
|
type: "projectionList",
|
|
540
540
|
query: "sessions:query:user-session:mine",
|
|
541
541
|
columns: [{ field: "userAgent", label: "sessions.mine.col.userAgent" }],
|
|
542
|
-
access: { openToAll:
|
|
542
|
+
access: { openToAll: { reason: "test handler callable by any signed-in test user" } },
|
|
543
543
|
},
|
|
544
544
|
{
|
|
545
545
|
id: "session-list",
|
|
@@ -563,7 +563,7 @@ const mfaSchema: FeatureSchema = {
|
|
|
563
563
|
layout: { sections: [] },
|
|
564
564
|
submitLabel: "mfa.enable.start",
|
|
565
565
|
reveal: { fields: [{ field: "recoveryCodes", label: "codes", display: "list" }] },
|
|
566
|
-
access: { openToAll:
|
|
566
|
+
access: { openToAll: { reason: "test handler callable by any signed-in test user" } },
|
|
567
567
|
},
|
|
568
568
|
{
|
|
569
569
|
id: "auth-mfa-disable",
|
|
@@ -572,7 +572,7 @@ const mfaSchema: FeatureSchema = {
|
|
|
572
572
|
fields: { code: { type: "text", required: true } },
|
|
573
573
|
layout: { sections: [{ fields: ["code"] }] },
|
|
574
574
|
submitLabel: "mfa.disable.submit",
|
|
575
|
-
access: { openToAll:
|
|
575
|
+
access: { openToAll: { reason: "test handler callable by any signed-in test user" } },
|
|
576
576
|
},
|
|
577
577
|
],
|
|
578
578
|
};
|
|
@@ -74,7 +74,7 @@ function ws(
|
|
|
74
74
|
} = {},
|
|
75
75
|
): WorkspaceSchema {
|
|
76
76
|
const access = options.openToAll
|
|
77
|
-
? ({ openToAll:
|
|
77
|
+
? ({ openToAll: { reason: "test handler callable by any signed-in test user" } } as const)
|
|
78
78
|
: options.roles !== undefined
|
|
79
79
|
? ({ roles: options.roles } as const)
|
|
80
80
|
: undefined;
|
|
@@ -121,9 +121,18 @@ describe("filterByAccess", () => {
|
|
|
121
121
|
|
|
122
122
|
test("sorts by order then insertion order", () => {
|
|
123
123
|
const list = [
|
|
124
|
-
ws("c", {
|
|
125
|
-
|
|
126
|
-
|
|
124
|
+
ws("c", {
|
|
125
|
+
openToAll: true,
|
|
126
|
+
order: 3,
|
|
127
|
+
}),
|
|
128
|
+
ws("a", {
|
|
129
|
+
openToAll: true,
|
|
130
|
+
order: 1,
|
|
131
|
+
}),
|
|
132
|
+
ws("b", {
|
|
133
|
+
openToAll: true,
|
|
134
|
+
order: 2,
|
|
135
|
+
}),
|
|
127
136
|
ws("d", { openToAll: true }), // no order — sorts last
|
|
128
137
|
];
|
|
129
138
|
expect(filterByAccess(list, []).map((w) => w.definition.id)).toEqual(["a", "b", "c", "d"]);
|
|
@@ -133,7 +142,10 @@ describe("filterByAccess", () => {
|
|
|
133
142
|
describe("resolveDefaultId", () => {
|
|
134
143
|
const visible = [
|
|
135
144
|
ws("admin", { openToAll: true }),
|
|
136
|
-
ws("dispatch", {
|
|
145
|
+
ws("dispatch", {
|
|
146
|
+
openToAll: true,
|
|
147
|
+
isDefault: true,
|
|
148
|
+
}),
|
|
137
149
|
ws("driver", { openToAll: true }),
|
|
138
150
|
];
|
|
139
151
|
|
|
@@ -234,8 +246,14 @@ describe("WorkspaceSwitcher", () => {
|
|
|
234
246
|
renderWithSidebar(
|
|
235
247
|
<WorkspaceSwitcher
|
|
236
248
|
workspaces={[
|
|
237
|
-
ws("admin", {
|
|
238
|
-
|
|
249
|
+
ws("admin", {
|
|
250
|
+
label: "Admin",
|
|
251
|
+
openToAll: true,
|
|
252
|
+
}),
|
|
253
|
+
ws("driver", {
|
|
254
|
+
label: "Driver",
|
|
255
|
+
openToAll: true,
|
|
256
|
+
}),
|
|
239
257
|
]}
|
|
240
258
|
activeId="admin"
|
|
241
259
|
onSelect={() => {}}
|
|
@@ -253,8 +271,14 @@ describe("WorkspaceSwitcher", () => {
|
|
|
253
271
|
renderWithSidebar(
|
|
254
272
|
<WorkspaceSwitcher
|
|
255
273
|
workspaces={[
|
|
256
|
-
ws("admin", {
|
|
257
|
-
|
|
274
|
+
ws("admin", {
|
|
275
|
+
label: "Admin",
|
|
276
|
+
openToAll: true,
|
|
277
|
+
}),
|
|
278
|
+
ws("driver", {
|
|
279
|
+
label: "Driver",
|
|
280
|
+
openToAll: true,
|
|
281
|
+
}),
|
|
258
282
|
]}
|
|
259
283
|
activeId="admin"
|
|
260
284
|
onSelect={onSelect}
|
|
@@ -31,7 +31,12 @@ describe("firstOpenScreenQn", () => {
|
|
|
31
31
|
const features: readonly FeatureSchema[] = [
|
|
32
32
|
feature({
|
|
33
33
|
featureName: "auth-mfa",
|
|
34
|
-
screens: [
|
|
34
|
+
screens: [
|
|
35
|
+
customScreen({
|
|
36
|
+
id: "auth-mfa-enable",
|
|
37
|
+
access: { openToAll: { reason: "test handler callable by any signed-in test user" } },
|
|
38
|
+
}),
|
|
39
|
+
],
|
|
35
40
|
// No nav entry — this is auth-mfa's dormant custom-screen convention.
|
|
36
41
|
}),
|
|
37
42
|
feature({
|
|
@@ -58,7 +63,12 @@ describe("firstOpenScreenQn", () => {
|
|
|
58
63
|
const features: readonly FeatureSchema[] = [
|
|
59
64
|
feature({
|
|
60
65
|
featureName: "auth-mfa",
|
|
61
|
-
screens: [
|
|
66
|
+
screens: [
|
|
67
|
+
customScreen({
|
|
68
|
+
id: "auth-mfa-enable",
|
|
69
|
+
access: { openToAll: { reason: "test handler callable by any signed-in test user" } },
|
|
70
|
+
}),
|
|
71
|
+
],
|
|
62
72
|
}),
|
|
63
73
|
];
|
|
64
74
|
expect(firstOpenScreenQn(features)).toBeUndefined();
|
package/src/app/create-app.tsx
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { createLiveDispatcher } from "@cosmicdrift/kumiko-dispatcher-live";
|
|
2
2
|
import type { TreeChildrenSubscribe } from "@cosmicdrift/kumiko-framework/engine";
|
|
3
|
+
import { isOpenToAllGranted } from "@cosmicdrift/kumiko-framework/ui-types";
|
|
3
4
|
import type {
|
|
4
5
|
Dispatcher,
|
|
5
6
|
ListRowViewModel,
|
|
@@ -236,7 +237,7 @@ export function firstOpenScreenQn(features: readonly FeatureSchema[]): string |
|
|
|
236
237
|
for (const feature of features) {
|
|
237
238
|
const openScreen = feature.screens.find(
|
|
238
239
|
(s) =>
|
|
239
|
-
(s.access === undefined ||
|
|
240
|
+
(s.access === undefined || isOpenToAllGranted(s.access)) &&
|
|
240
241
|
navScreenQns.has(qualifyScreenId(feature.featureName, s.id)),
|
|
241
242
|
);
|
|
242
243
|
if (openScreen !== undefined) return qualifyScreenId(feature.featureName, openScreen.id);
|