@jskit-ai/shell-web 0.1.86 → 0.1.87
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 +3 -2
- package/src/client/asyncModuleRecovery/index.js +4 -0
- package/src/client/asyncModuleRecovery/inject.js +30 -0
- package/src/client/index.js +4 -0
- package/src/client/providers/ShellWebClientProvider.js +4 -1
- package/test/asyncModuleRecoveryInject.test.js +49 -0
- package/test/provider.test.js +5 -2
- package/test/settingsPlacementContract.test.js +23 -0
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.87",
|
|
5
5
|
kind: "runtime",
|
|
6
6
|
description: "Web shell layout runtime with outlet-based placement contributions.",
|
|
7
7
|
dependsOn: [],
|
|
@@ -294,7 +294,7 @@ export default Object.freeze({
|
|
|
294
294
|
dependencies: {
|
|
295
295
|
runtime: {
|
|
296
296
|
"@mdi/js": "^7.4.47",
|
|
297
|
-
"@jskit-ai/kernel": "0.1.
|
|
297
|
+
"@jskit-ai/kernel": "0.1.88"
|
|
298
298
|
},
|
|
299
299
|
dev: {}
|
|
300
300
|
},
|
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.87",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"test": "node --test"
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
"./client": "./src/client/index.js",
|
|
10
10
|
"./client/error": "./src/client/error/index.js",
|
|
11
11
|
"./client/placement": "./src/client/placement/index.js",
|
|
12
|
+
"./client/asyncModuleRecovery": "./src/client/asyncModuleRecovery/index.js",
|
|
12
13
|
"./client/bootstrap": "./src/client/bootstrap/index.js",
|
|
13
14
|
"./server/support/localLinkItemScaffolds": "./src/server/support/localLinkItemScaffolds.js",
|
|
14
15
|
"./client/navigation/linkResolver": "./src/client/navigation/linkResolver.js",
|
|
@@ -26,7 +27,7 @@
|
|
|
26
27
|
},
|
|
27
28
|
"dependencies": {
|
|
28
29
|
"@mdi/js": "^7.4.47",
|
|
29
|
-
"@jskit-ai/kernel": "0.1.
|
|
30
|
+
"@jskit-ai/kernel": "0.1.88"
|
|
30
31
|
},
|
|
31
32
|
"peerDependencies": {
|
|
32
33
|
"pinia": "^3.0.4",
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import {
|
|
2
|
+
hasInjectionContext,
|
|
3
|
+
inject
|
|
4
|
+
} from "vue";
|
|
5
|
+
|
|
6
|
+
const SHELL_ASYNC_MODULE_RECOVERY_RUNTIME_KEY =
|
|
7
|
+
"jskit.shell-web.runtime.web-async-module-recovery.client";
|
|
8
|
+
|
|
9
|
+
function isShellAsyncModuleRecoveryRuntime(value) {
|
|
10
|
+
return Boolean(
|
|
11
|
+
value &&
|
|
12
|
+
typeof value.notify === "function" &&
|
|
13
|
+
typeof value.reload === "function"
|
|
14
|
+
);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function useShellAsyncModuleRecoveryRuntime() {
|
|
18
|
+
if (!hasInjectionContext()) {
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const runtime = inject(SHELL_ASYNC_MODULE_RECOVERY_RUNTIME_KEY, null);
|
|
23
|
+
return isShellAsyncModuleRecoveryRuntime(runtime) ? runtime : null;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export {
|
|
27
|
+
SHELL_ASYNC_MODULE_RECOVERY_RUNTIME_KEY,
|
|
28
|
+
isShellAsyncModuleRecoveryRuntime,
|
|
29
|
+
useShellAsyncModuleRecoveryRuntime
|
|
30
|
+
};
|
package/src/client/index.js
CHANGED
|
@@ -17,6 +17,10 @@ export { default as ShellTabLinkItem } from "./components/ShellTabLinkItem.vue";
|
|
|
17
17
|
export { useShellLayoutState } from "./composables/useShellLayoutState.js";
|
|
18
18
|
export { useShellLayoutStore } from "./stores/useShellLayoutStore.js";
|
|
19
19
|
export { useShellErrorPresentationStore } from "./stores/useShellErrorPresentationStore.js";
|
|
20
|
+
export {
|
|
21
|
+
SHELL_ASYNC_MODULE_RECOVERY_RUNTIME_KEY,
|
|
22
|
+
useShellAsyncModuleRecoveryRuntime
|
|
23
|
+
} from "./asyncModuleRecovery/index.js";
|
|
20
24
|
export {
|
|
21
25
|
BOOTSTRAP_PAYLOAD_HANDLER_TAG,
|
|
22
26
|
registerBootstrapPayloadHandler,
|
|
@@ -10,6 +10,9 @@ import {
|
|
|
10
10
|
isMissingDynamicModule,
|
|
11
11
|
notifyDynamicImportFailure
|
|
12
12
|
} from "./appModuleLoadFailure.js";
|
|
13
|
+
import {
|
|
14
|
+
SHELL_ASYNC_MODULE_RECOVERY_RUNTIME_KEY
|
|
15
|
+
} from "../asyncModuleRecovery/inject.js";
|
|
13
16
|
import {
|
|
14
17
|
isRecord
|
|
15
18
|
} from "@jskit-ai/kernel/shared/support";
|
|
@@ -654,7 +657,7 @@ class ShellWebClientProvider {
|
|
|
654
657
|
vueApp.provide("jskit.shell-web.runtime.web-placement.client", placementRuntime);
|
|
655
658
|
vueApp.provide("jskit.shell-web.runtime.web-refresh.client", refreshRuntime);
|
|
656
659
|
vueApp.provide("jskit.shell-web.runtime.web-error.client", errorRuntime);
|
|
657
|
-
vueApp.provide(
|
|
660
|
+
vueApp.provide(SHELL_ASYNC_MODULE_RECOVERY_RUNTIME_KEY, asyncModuleRecoveryRuntime);
|
|
658
661
|
vueApp.provide(
|
|
659
662
|
"jskit.shell-web.runtime.web-error.presentation-store.client",
|
|
660
663
|
errorPresentationStore
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import test from "node:test";
|
|
3
|
+
import { createApp } from "vue";
|
|
4
|
+
import {
|
|
5
|
+
SHELL_ASYNC_MODULE_RECOVERY_RUNTIME_KEY,
|
|
6
|
+
useShellAsyncModuleRecoveryRuntime
|
|
7
|
+
} from "../src/client/asyncModuleRecovery/index.js";
|
|
8
|
+
|
|
9
|
+
test("shell async module recovery runtime composable returns null outside Vue injection context", () => {
|
|
10
|
+
assert.equal(useShellAsyncModuleRecoveryRuntime(), null);
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
test("shell async module recovery runtime composable resolves the provided public runtime", async () => {
|
|
14
|
+
const runtime = {
|
|
15
|
+
notify(error, options) {
|
|
16
|
+
return { error, options };
|
|
17
|
+
},
|
|
18
|
+
async reload() {
|
|
19
|
+
return true;
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
const app = createApp({
|
|
23
|
+
render() {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
app.provide(SHELL_ASYNC_MODULE_RECOVERY_RUNTIME_KEY, runtime);
|
|
28
|
+
|
|
29
|
+
assert.equal(
|
|
30
|
+
app.runWithContext(() => useShellAsyncModuleRecoveryRuntime()),
|
|
31
|
+
runtime
|
|
32
|
+
);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
test("shell async module recovery runtime composable rejects incomplete runtimes", () => {
|
|
36
|
+
const app = createApp({
|
|
37
|
+
render() {
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
app.provide(SHELL_ASYNC_MODULE_RECOVERY_RUNTIME_KEY, {
|
|
42
|
+
notify() {}
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
assert.equal(
|
|
46
|
+
app.runWithContext(() => useShellAsyncModuleRecoveryRuntime()),
|
|
47
|
+
null
|
|
48
|
+
);
|
|
49
|
+
});
|
package/test/provider.test.js
CHANGED
|
@@ -8,6 +8,9 @@ import {
|
|
|
8
8
|
import {
|
|
9
9
|
isMissingDynamicModule
|
|
10
10
|
} from "../src/client/providers/appModuleLoadFailure.js";
|
|
11
|
+
import {
|
|
12
|
+
SHELL_ASYNC_MODULE_RECOVERY_RUNTIME_KEY
|
|
13
|
+
} from "../src/client/asyncModuleRecovery/index.js";
|
|
11
14
|
import { useShellErrorPresentationStore } from "../src/client/stores/useShellErrorPresentationStore.js";
|
|
12
15
|
const CLIENT_APP_CONFIG_GLOBAL_KEY = "__JSKIT_CLIENT_APP_CONFIG__";
|
|
13
16
|
|
|
@@ -229,7 +232,7 @@ test("shell web client provider binds runtime and injects it into Vue app", asyn
|
|
|
229
232
|
assert.equal(providedByKey.has("jskit.shell-web.runtime.web-placement.client"), true);
|
|
230
233
|
assert.equal(providedByKey.has("jskit.shell-web.runtime.web-refresh.client"), true);
|
|
231
234
|
assert.equal(providedByKey.has("jskit.shell-web.runtime.web-error.client"), true);
|
|
232
|
-
assert.equal(providedByKey.has(
|
|
235
|
+
assert.equal(providedByKey.has(SHELL_ASYNC_MODULE_RECOVERY_RUNTIME_KEY), true);
|
|
233
236
|
assert.equal(providedByKey.has("jskit.shell-web.runtime.web-error.presentation-store.client"), true);
|
|
234
237
|
|
|
235
238
|
const placementRuntime = providedByKey.get("jskit.shell-web.runtime.web-placement.client");
|
|
@@ -245,7 +248,7 @@ test("shell web client provider binds runtime and injects it into Vue app", asyn
|
|
|
245
248
|
const refreshRuntime = providedByKey.get("jskit.shell-web.runtime.web-refresh.client");
|
|
246
249
|
assert.equal(typeof refreshRuntime.refresh, "function");
|
|
247
250
|
|
|
248
|
-
const asyncModuleRecoveryRuntime = providedByKey.get(
|
|
251
|
+
const asyncModuleRecoveryRuntime = providedByKey.get(SHELL_ASYNC_MODULE_RECOVERY_RUNTIME_KEY);
|
|
249
252
|
assert.equal(typeof asyncModuleRecoveryRuntime.install, "function");
|
|
250
253
|
assert.equal(typeof asyncModuleRecoveryRuntime.notify, "function");
|
|
251
254
|
assert.equal(typeof asyncModuleRecoveryRuntime.reload, "function");
|
|
@@ -148,6 +148,29 @@ test("shell-web installs generated adaptive shell Playwright smoke coverage", as
|
|
|
148
148
|
assert.equal(packageJson?.exports?.["./test/adaptiveShellSmoke"], "./src/test/adaptiveShellSmoke.js");
|
|
149
149
|
});
|
|
150
150
|
|
|
151
|
+
test("shell-web exports async module recovery runtime access as a public client API", async () => {
|
|
152
|
+
const packageJson = JSON.parse(await readFile(path.join(PACKAGE_DIR, "package.json"), "utf8"));
|
|
153
|
+
const clientIndex = await readFile(path.join(PACKAGE_DIR, "src", "client", "index.js"), "utf8");
|
|
154
|
+
const recoveryIndex = await readFile(
|
|
155
|
+
path.join(PACKAGE_DIR, "src", "client", "asyncModuleRecovery", "index.js"),
|
|
156
|
+
"utf8"
|
|
157
|
+
);
|
|
158
|
+
const providerSource = await readFile(
|
|
159
|
+
path.join(PACKAGE_DIR, "src", "client", "providers", "ShellWebClientProvider.js"),
|
|
160
|
+
"utf8"
|
|
161
|
+
);
|
|
162
|
+
|
|
163
|
+
assert.equal(
|
|
164
|
+
packageJson?.exports?.["./client/asyncModuleRecovery"],
|
|
165
|
+
"./src/client/asyncModuleRecovery/index.js"
|
|
166
|
+
);
|
|
167
|
+
assert.match(clientIndex, /useShellAsyncModuleRecoveryRuntime/);
|
|
168
|
+
assert.match(clientIndex, /SHELL_ASYNC_MODULE_RECOVERY_RUNTIME_KEY/);
|
|
169
|
+
assert.match(recoveryIndex, /useShellAsyncModuleRecoveryRuntime/);
|
|
170
|
+
assert.match(recoveryIndex, /SHELL_ASYNC_MODULE_RECOVERY_RUNTIME_KEY/);
|
|
171
|
+
assert.match(providerSource, /SHELL_ASYNC_MODULE_RECOVERY_RUNTIME_KEY/);
|
|
172
|
+
});
|
|
173
|
+
|
|
151
174
|
test("shell-web route transition keeps mobile route motion placement-driven", async () => {
|
|
152
175
|
const source = await readFile(
|
|
153
176
|
path.join(PACKAGE_DIR, "src", "client", "components", "ShellRouteTransition.vue"),
|