@jskit-ai/shell-web 0.1.9 → 0.1.10
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.descriptor.mjs +2 -2
- package/package.json +2 -2
- package/src/client/components/useShellLayout.js +31 -22
- package/src/client/error/normalize.js +7 -6
- package/src/client/error/runtime.js +2 -11
- package/src/client/error/store.js +2 -11
- package/src/client/placement/runtime.js +2 -10
- package/src/client/providers/ShellWebClientProvider.js +3 -21
package/package.descriptor.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export default Object.freeze({
|
|
2
2
|
packageVersion: 1,
|
|
3
3
|
packageId: "@jskit-ai/shell-web",
|
|
4
|
-
version: "0.1.
|
|
4
|
+
version: "0.1.10",
|
|
5
5
|
description: "Web shell layout runtime with outlet-based placement contributions.",
|
|
6
6
|
dependsOn: [],
|
|
7
7
|
capabilities: {
|
|
@@ -85,7 +85,7 @@ export default Object.freeze({
|
|
|
85
85
|
dependencies: {
|
|
86
86
|
runtime: {
|
|
87
87
|
"@tanstack/vue-query": "^5.90.5",
|
|
88
|
-
"@jskit-ai/kernel": "0.1.
|
|
88
|
+
"@jskit-ai/kernel": "0.1.10",
|
|
89
89
|
"vuetify": "^4.0.0"
|
|
90
90
|
},
|
|
91
91
|
dev: {}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jskit-ai/shell-web",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.10",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"test": "node --test"
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
},
|
|
18
18
|
"dependencies": {
|
|
19
19
|
"@tanstack/vue-query": "^5.90.5",
|
|
20
|
-
"@jskit-ai/kernel": "0.1.
|
|
20
|
+
"@jskit-ai/kernel": "0.1.10",
|
|
21
21
|
"vuetify": "^4.0.0"
|
|
22
22
|
}
|
|
23
23
|
}
|
|
@@ -14,40 +14,49 @@ const DEFAULT_MENU_FALLBACK = Object.freeze({
|
|
|
14
14
|
icon: "$menu"
|
|
15
15
|
});
|
|
16
16
|
|
|
17
|
-
function
|
|
18
|
-
const source = normalizeObject(
|
|
17
|
+
function normalizeLabeledItem(item, fallback, buildItem) {
|
|
18
|
+
const source = normalizeObject(item);
|
|
19
19
|
const fallbackSource = normalizeObject(fallback);
|
|
20
20
|
const label = String(source.label || fallbackSource.label || "").trim();
|
|
21
21
|
if (!label) {
|
|
22
22
|
return null;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
|
|
26
|
-
label,
|
|
27
|
-
to: String(source.to || fallbackSource.to || "").trim(),
|
|
28
|
-
variant: String(source.variant || fallbackSource.variant || "text").trim(),
|
|
29
|
-
color: String(source.color || fallbackSource.color || "secondary").trim()
|
|
30
|
-
};
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
function normalizeMenuItem(item, fallback) {
|
|
34
|
-
const source = normalizeObject(item);
|
|
35
|
-
const fallbackSource = normalizeObject(fallback);
|
|
36
|
-
const label = String(source.label || fallbackSource.label || "").trim();
|
|
37
|
-
if (!label) {
|
|
25
|
+
if (typeof buildItem !== "function") {
|
|
38
26
|
return null;
|
|
39
27
|
}
|
|
40
28
|
|
|
41
|
-
return {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
};
|
|
29
|
+
return buildItem({
|
|
30
|
+
source,
|
|
31
|
+
fallbackSource,
|
|
32
|
+
label
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function normalizeAction(action, fallback) {
|
|
37
|
+
return normalizeLabeledItem(action, fallback, ({ source, fallbackSource, label }) => {
|
|
38
|
+
return {
|
|
39
|
+
label,
|
|
40
|
+
to: String(source.to || fallbackSource.to || "").trim(),
|
|
41
|
+
variant: String(source.variant || fallbackSource.variant || "text").trim(),
|
|
42
|
+
color: String(source.color || fallbackSource.color || "secondary").trim()
|
|
43
|
+
};
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function normalizeMenuItem(item, fallback) {
|
|
48
|
+
return normalizeLabeledItem(item, fallback, ({ source, fallbackSource, label }) => {
|
|
49
|
+
return {
|
|
50
|
+
label,
|
|
51
|
+
to: String(source.to || fallbackSource.to || "").trim() || "/",
|
|
52
|
+
icon: String(source.icon || fallbackSource.icon || "$menu").trim() || "$menu"
|
|
53
|
+
};
|
|
54
|
+
});
|
|
46
55
|
}
|
|
47
56
|
|
|
48
57
|
function normalizeActionList(actions) {
|
|
49
|
-
const
|
|
50
|
-
return
|
|
58
|
+
const sourceActions = Array.isArray(actions) ? actions : [];
|
|
59
|
+
return sourceActions
|
|
51
60
|
.map((item) => normalizeAction(item, DEFAULT_ACTION_FALLBACK))
|
|
52
61
|
.filter(Boolean);
|
|
53
62
|
}
|
|
@@ -1,14 +1,15 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
isRecord,
|
|
3
|
+
normalizeText as normalizeKernelText
|
|
4
|
+
} from "@jskit-ai/kernel/shared/support/normalize";
|
|
2
5
|
|
|
3
6
|
const ERROR_CHANNELS = Object.freeze(["snackbar", "banner", "dialog", "silent"]);
|
|
4
7
|
const ERROR_SEVERITIES = Object.freeze(["info", "success", "warning", "error", "critical"]);
|
|
5
8
|
|
|
6
9
|
function normalizeText(value, fallback = "") {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
}
|
|
11
|
-
return String(fallback || "").trim();
|
|
10
|
+
return normalizeKernelText(value, {
|
|
11
|
+
fallback: String(fallback || "").trim()
|
|
12
|
+
});
|
|
12
13
|
}
|
|
13
14
|
|
|
14
15
|
function normalizeChannel(value, fallback = "") {
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
normalizeSeverity,
|
|
7
7
|
normalizeText
|
|
8
8
|
} from "./normalize.js";
|
|
9
|
+
import { createListenerSubscription } from "@jskit-ai/kernel/shared/support/listenerSet";
|
|
9
10
|
import { createDefaultErrorPolicy } from "./policy.js";
|
|
10
11
|
|
|
11
12
|
function createRuntimeLogger(logger = null) {
|
|
@@ -108,6 +109,7 @@ function createErrorRuntime({
|
|
|
108
109
|
const runtimeLogger = createRuntimeLogger(logger);
|
|
109
110
|
const byPresenterId = new Map();
|
|
110
111
|
const listeners = new Set();
|
|
112
|
+
const subscribe = createListenerSubscription(listeners);
|
|
111
113
|
const dedupeWindowByKey = new Map();
|
|
112
114
|
let activePolicy = typeof policy === "function" ? policy : createDefaultErrorPolicy();
|
|
113
115
|
let activeAppDefaultPresenterId = normalizeText(defaultPresenterId);
|
|
@@ -177,17 +179,6 @@ function createErrorRuntime({
|
|
|
177
179
|
return activeAppDefaultPresenterId;
|
|
178
180
|
}
|
|
179
181
|
|
|
180
|
-
function subscribe(listener) {
|
|
181
|
-
if (typeof listener !== "function") {
|
|
182
|
-
return () => {};
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
listeners.add(listener);
|
|
186
|
-
return () => {
|
|
187
|
-
listeners.delete(listener);
|
|
188
|
-
};
|
|
189
|
-
}
|
|
190
|
-
|
|
191
182
|
function notify(event = {}) {
|
|
192
183
|
const payload = Object.freeze({ ...event });
|
|
193
184
|
for (const listener of listeners) {
|
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
normalizeSeverity,
|
|
4
4
|
normalizeText
|
|
5
5
|
} from "./normalize.js";
|
|
6
|
+
import { createListenerSubscription } from "@jskit-ai/kernel/shared/support/listenerSet";
|
|
6
7
|
|
|
7
8
|
const PRESENTATION_CHANNELS = Object.freeze(["snackbar", "banner", "dialog"]);
|
|
8
9
|
const SINGLETON_CHANNELS = new Set(["banner"]);
|
|
@@ -33,6 +34,7 @@ function createErrorPresentationStore({
|
|
|
33
34
|
now = () => Date.now()
|
|
34
35
|
} = {}) {
|
|
35
36
|
const listeners = new Set();
|
|
37
|
+
const subscribe = createListenerSubscription(listeners);
|
|
36
38
|
const channelState = createEmptyChannelState();
|
|
37
39
|
let sequence = 0;
|
|
38
40
|
let revision = 0;
|
|
@@ -66,17 +68,6 @@ function createErrorPresentationStore({
|
|
|
66
68
|
}
|
|
67
69
|
}
|
|
68
70
|
|
|
69
|
-
function subscribe(listener) {
|
|
70
|
-
if (typeof listener !== "function") {
|
|
71
|
-
return () => {};
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
listeners.add(listener);
|
|
75
|
-
return () => {
|
|
76
|
-
listeners.delete(listener);
|
|
77
|
-
};
|
|
78
|
-
}
|
|
79
|
-
|
|
80
71
|
function present(channel, payload = {}) {
|
|
81
72
|
const normalizedChannel = String(channel || "").trim();
|
|
82
73
|
const entries = getChannelEntries(normalizedChannel);
|
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
WEB_PLACEMENT_SURFACE_ANY
|
|
4
4
|
} from "./tokens.js";
|
|
5
5
|
import { DEFAULT_DEBUG_DEPTH, explodePayload } from "./debug.js";
|
|
6
|
+
import { createListenerSubscription } from "@jskit-ai/kernel/shared/support/listenerSet";
|
|
6
7
|
import { isRecord } from "@jskit-ai/kernel/shared/support/normalize";
|
|
7
8
|
import {
|
|
8
9
|
isRenderableComponent,
|
|
@@ -227,6 +228,7 @@ function createWebPlacementRuntime({ app, logger = null } = {}) {
|
|
|
227
228
|
const invalidComponentTokens = new Set();
|
|
228
229
|
const failedTokens = new Set();
|
|
229
230
|
const listeners = new Set();
|
|
231
|
+
const subscribe = createListenerSubscription(listeners);
|
|
230
232
|
let placementDefinitions = Object.freeze([]);
|
|
231
233
|
let sharedContext = Object.freeze({});
|
|
232
234
|
let revision = 0;
|
|
@@ -300,16 +302,6 @@ function createWebPlacementRuntime({ app, logger = null } = {}) {
|
|
|
300
302
|
return sharedContext;
|
|
301
303
|
}
|
|
302
304
|
|
|
303
|
-
function subscribe(listener) {
|
|
304
|
-
if (typeof listener !== "function") {
|
|
305
|
-
return () => {};
|
|
306
|
-
}
|
|
307
|
-
listeners.add(listener);
|
|
308
|
-
return () => {
|
|
309
|
-
listeners.delete(listener);
|
|
310
|
-
};
|
|
311
|
-
}
|
|
312
|
-
|
|
313
305
|
function getRevision() {
|
|
314
306
|
return revision;
|
|
315
307
|
}
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
shouldRetryTransientQueryFailure,
|
|
10
10
|
transientQueryRetryDelay
|
|
11
11
|
} from "@jskit-ai/kernel/shared/support";
|
|
12
|
+
import { createProviderLogger as createSharedProviderLogger } from "@jskit-ai/kernel/shared/support/providerLogger";
|
|
12
13
|
import { QueryClient, VueQueryPlugin } from "@tanstack/vue-query";
|
|
13
14
|
import {
|
|
14
15
|
createDefaultErrorPolicy
|
|
@@ -60,25 +61,6 @@ function createShellWebQueryClient() {
|
|
|
60
61
|
});
|
|
61
62
|
}
|
|
62
63
|
|
|
63
|
-
function createProviderLogger(app) {
|
|
64
|
-
return Object.freeze({
|
|
65
|
-
warn: (...args) => {
|
|
66
|
-
if (isRecord(app) && typeof app.warn === "function") {
|
|
67
|
-
app.warn(...args);
|
|
68
|
-
return;
|
|
69
|
-
}
|
|
70
|
-
console.warn(...args);
|
|
71
|
-
},
|
|
72
|
-
error: (...args) => {
|
|
73
|
-
if (isRecord(app) && typeof app.error === "function") {
|
|
74
|
-
app.error(...args);
|
|
75
|
-
return;
|
|
76
|
-
}
|
|
77
|
-
console.error(...args);
|
|
78
|
-
}
|
|
79
|
-
});
|
|
80
|
-
}
|
|
81
|
-
|
|
82
64
|
function isMissingDynamicModule(error, moduleSpecifier) {
|
|
83
65
|
const message = String(error?.message || error || "");
|
|
84
66
|
return (
|
|
@@ -270,7 +252,7 @@ class ShellWebClientProvider {
|
|
|
270
252
|
throw new Error("ShellWebClientProvider requires application singleton().");
|
|
271
253
|
}
|
|
272
254
|
|
|
273
|
-
const logger =
|
|
255
|
+
const logger = createSharedProviderLogger(isRecord(app) ? app : null);
|
|
274
256
|
app.singleton(WEB_PLACEMENT_RUNTIME_CLIENT_TOKEN, () => createWebPlacementRuntime({ app, logger }));
|
|
275
257
|
app.singleton(SHELL_WEB_QUERY_CLIENT_TOKEN, () => createShellWebQueryClient());
|
|
276
258
|
app.singleton(SHELL_WEB_ERROR_PRESENTATION_STORE_CLIENT_TOKEN, () => createErrorPresentationStore());
|
|
@@ -291,7 +273,7 @@ class ShellWebClientProvider {
|
|
|
291
273
|
throw new Error("ShellWebClientProvider requires application make()/has().");
|
|
292
274
|
}
|
|
293
275
|
|
|
294
|
-
const logger =
|
|
276
|
+
const logger = createSharedProviderLogger(isRecord(app) ? app : null);
|
|
295
277
|
const placementRuntime = app.make(WEB_PLACEMENT_RUNTIME_CLIENT_TOKEN);
|
|
296
278
|
if (placementRuntime && typeof placementRuntime.replacePlacements === "function") {
|
|
297
279
|
const placements = await loadAppPlacementDefinitions(logger);
|