@jskit-ai/kernel 0.1.66 → 0.1.68
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/client/moduleBootstrap.js +4 -0
- package/client/moduleBootstrap.test.js +4 -0
- package/client/shellBootstrap.js +2 -0
- package/client/shellBootstrap.test.js +3 -0
- package/client/vite/clientBootstrapPlugin.js +1 -0
- package/client/vite/clientBootstrapPlugin.test.js +3 -3
- package/package.json +2 -1
- package/server/http/lib/httpRuntime.js +3 -1
- package/server/http/lib/kernel.test.js +4 -0
- package/server/runtime/fastifyBootstrap.js +61 -0
- package/server/runtime/fastifyBootstrap.test.js +47 -1
- package/server/support/appConfigFiles.js +3 -2
- package/server/support/appConfigFiles.test.js +15 -0
- package/server/support/index.js +1 -0
- package/server/support/pageTargets.js +24 -8
- package/server/support/pageTargets.test.js +143 -0
- package/server/support/shellOutlets.js +68 -12
- package/server/support/shellOutlets.test.js +31 -0
- package/shared/support/generatedUiContract.js +542 -0
- package/shared/support/generatedUiContract.test.js +208 -0
- package/shared/support/shellLayoutTargets.js +11 -3
- package/shared/support/shellLayoutTargets.test.js +20 -0
|
@@ -70,7 +70,13 @@ function normalizeAppRouteOutletTarget({
|
|
|
70
70
|
});
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
-
function discoverRouteMetaOutletTargetsFromVueSource(
|
|
73
|
+
function discoverRouteMetaOutletTargetsFromVueSource(
|
|
74
|
+
source = "",
|
|
75
|
+
{
|
|
76
|
+
context = "shell layout",
|
|
77
|
+
enforceSingleDefault = true
|
|
78
|
+
} = {}
|
|
79
|
+
) {
|
|
74
80
|
const sourceText = String(source || "");
|
|
75
81
|
const resolvedContext = normalizeText(context) || "shell layout";
|
|
76
82
|
const targetById = new Map();
|
|
@@ -113,12 +119,14 @@ function discoverRouteMetaOutletTargetsFromVueSource(source = "", { context = "s
|
|
|
113
119
|
throw new Error(`${resolvedContext} contains duplicate route meta placement target "${normalizedTarget.id}".`);
|
|
114
120
|
}
|
|
115
121
|
if (normalizedTarget.default === true) {
|
|
116
|
-
if (defaultTargetId && defaultTargetId !== normalizedTarget.id) {
|
|
122
|
+
if (enforceSingleDefault === true && defaultTargetId && defaultTargetId !== normalizedTarget.id) {
|
|
117
123
|
throw new Error(
|
|
118
124
|
`${resolvedContext} defines multiple default route meta placement targets: "${defaultTargetId}" and "${normalizedTarget.id}".`
|
|
119
125
|
);
|
|
120
126
|
}
|
|
121
|
-
defaultTargetId
|
|
127
|
+
if (!defaultTargetId) {
|
|
128
|
+
defaultTargetId = normalizedTarget.id;
|
|
129
|
+
}
|
|
122
130
|
}
|
|
123
131
|
targetById.set(normalizedTarget.id, normalizedTarget);
|
|
124
132
|
}
|
|
@@ -422,9 +430,14 @@ async function resolveSemanticPlacementTargetFromApp({
|
|
|
422
430
|
throw new Error(`${resolvedContext} could not resolve a default semantic placement target.`);
|
|
423
431
|
}
|
|
424
432
|
|
|
425
|
-
async function
|
|
433
|
+
async function collectAppSourceShellOutletTargets({
|
|
434
|
+
appRoot,
|
|
435
|
+
sourceRoot = "src",
|
|
436
|
+
enforceSingleDefault = true,
|
|
437
|
+
context = "discoverShellOutletTargetsFromApp"
|
|
438
|
+
} = {}) {
|
|
426
439
|
const resolvedAppRoot = resolveRequiredAppRoot(appRoot, {
|
|
427
|
-
context
|
|
440
|
+
context
|
|
428
441
|
});
|
|
429
442
|
|
|
430
443
|
const sourceDirectory = path.resolve(resolvedAppRoot, String(sourceRoot || "src"));
|
|
@@ -442,12 +455,14 @@ async function discoverShellOutletTargetsFromApp({ appRoot, sourceRoot = "src" }
|
|
|
442
455
|
|
|
443
456
|
const discoveredShellOutlets = source.includes("<ShellOutlet")
|
|
444
457
|
? discoverShellOutletTargetsFromVueSource(source, {
|
|
445
|
-
context: relativePath
|
|
458
|
+
context: relativePath,
|
|
459
|
+
enforceSingleDefault
|
|
446
460
|
})
|
|
447
461
|
: { targets: [], defaultTargetId: "" };
|
|
448
462
|
const discoveredRouteMetaOutlets = source.includes("<route")
|
|
449
463
|
? discoverRouteMetaOutletTargetsFromVueSource(source, {
|
|
450
|
-
context: relativePath
|
|
464
|
+
context: relativePath,
|
|
465
|
+
enforceSingleDefault
|
|
451
466
|
})
|
|
452
467
|
: { targets: [], defaultTargetId: "" };
|
|
453
468
|
const discoveredTargets = [
|
|
@@ -473,18 +488,37 @@ async function discoverShellOutletTargetsFromApp({ appRoot, sourceRoot = "src" }
|
|
|
473
488
|
normalizeShellOutletTargetId(discoveredRouteMetaOutlets.defaultTargetId)
|
|
474
489
|
].filter(Boolean);
|
|
475
490
|
for (const discoveredDefaultTargetId of discoveredDefaultTargetIds) {
|
|
476
|
-
if (defaultTargetId && discoveredDefaultTargetId !== defaultTargetId) {
|
|
491
|
+
if (enforceSingleDefault === true && defaultTargetId && discoveredDefaultTargetId !== defaultTargetId) {
|
|
477
492
|
throw new Error(
|
|
478
493
|
`Multiple default ShellOutlet targets found in app source: "${defaultTargetId}" (${defaultTargetSource}) and ` +
|
|
479
494
|
`"${discoveredDefaultTargetId}" (${relativePath}).`
|
|
480
495
|
);
|
|
481
496
|
}
|
|
482
497
|
|
|
483
|
-
defaultTargetId
|
|
484
|
-
|
|
498
|
+
if (!defaultTargetId) {
|
|
499
|
+
defaultTargetId = discoveredDefaultTargetId;
|
|
500
|
+
defaultTargetSource = relativePath;
|
|
501
|
+
}
|
|
485
502
|
}
|
|
486
503
|
}
|
|
487
504
|
|
|
505
|
+
return Object.freeze({
|
|
506
|
+
resolvedAppRoot,
|
|
507
|
+
targetById,
|
|
508
|
+
defaultTargetId
|
|
509
|
+
});
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
async function discoverShellOutletTargetsFromApp({ appRoot, sourceRoot = "src" } = {}) {
|
|
513
|
+
const discoveredAppTargets = await collectAppSourceShellOutletTargets({
|
|
514
|
+
appRoot,
|
|
515
|
+
sourceRoot,
|
|
516
|
+
enforceSingleDefault: true,
|
|
517
|
+
context: "discoverShellOutletTargetsFromApp"
|
|
518
|
+
});
|
|
519
|
+
const resolvedAppRoot = discoveredAppTargets.resolvedAppRoot;
|
|
520
|
+
const targetById = new Map(discoveredAppTargets.targetById);
|
|
521
|
+
|
|
488
522
|
const packageTargets = await collectInstalledPackageOutletTargets(resolvedAppRoot);
|
|
489
523
|
for (const target of packageTargets) {
|
|
490
524
|
if (!targetById.has(target.id)) {
|
|
@@ -496,13 +530,34 @@ async function discoverShellOutletTargetsFromApp({ appRoot, sourceRoot = "src" }
|
|
|
496
530
|
const normalizedTargets = targets.map((target) =>
|
|
497
531
|
Object.freeze({
|
|
498
532
|
...target,
|
|
499
|
-
default: target.id === defaultTargetId
|
|
533
|
+
default: target.id === discoveredAppTargets.defaultTargetId
|
|
500
534
|
})
|
|
501
535
|
);
|
|
502
536
|
|
|
503
537
|
return Object.freeze({
|
|
504
538
|
targets: Object.freeze(normalizedTargets),
|
|
505
|
-
defaultTargetId
|
|
539
|
+
defaultTargetId: discoveredAppTargets.defaultTargetId
|
|
540
|
+
});
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
async function discoverShellOutletSourcePathsFromApp({ appRoot, sourceRoot = "src" } = {}) {
|
|
544
|
+
const discoveredAppTargets = await collectAppSourceShellOutletTargets({
|
|
545
|
+
appRoot,
|
|
546
|
+
sourceRoot,
|
|
547
|
+
enforceSingleDefault: false,
|
|
548
|
+
context: "discoverShellOutletSourcePathsFromApp"
|
|
549
|
+
});
|
|
550
|
+
const targetById = new Map(discoveredAppTargets.targetById);
|
|
551
|
+
|
|
552
|
+
const packageTargets = await collectInstalledPackageOutletTargets(discoveredAppTargets.resolvedAppRoot);
|
|
553
|
+
for (const target of packageTargets) {
|
|
554
|
+
if (!targetById.has(target.id)) {
|
|
555
|
+
targetById.set(target.id, target);
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
return Object.freeze({
|
|
560
|
+
targets: Object.freeze([...targetById.values()].sort((left, right) => left.id.localeCompare(right.id)))
|
|
506
561
|
});
|
|
507
562
|
}
|
|
508
563
|
|
|
@@ -550,6 +605,7 @@ async function resolveShellOutletPlacementTargetFromApp({ appRoot, placement = "
|
|
|
550
605
|
|
|
551
606
|
export {
|
|
552
607
|
discoverPlacementTopologyFromApp,
|
|
608
|
+
discoverShellOutletSourcePathsFromApp,
|
|
553
609
|
discoverShellOutletTargetsFromApp,
|
|
554
610
|
resolveSemanticPlacementTargetFromApp,
|
|
555
611
|
resolveShellOutletPlacementTargetFromApp
|
|
@@ -4,6 +4,7 @@ import path from "node:path";
|
|
|
4
4
|
import { tmpdir } from "node:os";
|
|
5
5
|
import test from "node:test";
|
|
6
6
|
import {
|
|
7
|
+
discoverShellOutletSourcePathsFromApp,
|
|
7
8
|
discoverShellOutletTargetsFromApp,
|
|
8
9
|
resolveShellOutletPlacementTargetFromApp
|
|
9
10
|
} from "./shellOutlets.js";
|
|
@@ -296,6 +297,36 @@ test("resolveShellOutletPlacementTargetFromApp throws when multiple default outl
|
|
|
296
297
|
});
|
|
297
298
|
});
|
|
298
299
|
|
|
300
|
+
test("discoverShellOutletSourcePathsFromApp ignores default conflicts while keeping source paths", async () => {
|
|
301
|
+
await withTempApp(async (appRoot) => {
|
|
302
|
+
await writeFileInApp(
|
|
303
|
+
appRoot,
|
|
304
|
+
"src/components/ShellLayout.vue",
|
|
305
|
+
`<template>
|
|
306
|
+
<div>
|
|
307
|
+
<ShellOutlet target="shell-layout:primary-menu" default />
|
|
308
|
+
<ShellOutlet target="shell-layout:primary-bottom-nav" default />
|
|
309
|
+
</div>
|
|
310
|
+
</template>
|
|
311
|
+
`
|
|
312
|
+
);
|
|
313
|
+
|
|
314
|
+
const discovered = await discoverShellOutletSourcePathsFromApp({ appRoot });
|
|
315
|
+
assert.deepEqual(discovered.targets, [
|
|
316
|
+
{
|
|
317
|
+
id: "shell-layout:primary-bottom-nav",
|
|
318
|
+
default: true,
|
|
319
|
+
sourcePath: "src/components/ShellLayout.vue"
|
|
320
|
+
},
|
|
321
|
+
{
|
|
322
|
+
id: "shell-layout:primary-menu",
|
|
323
|
+
default: true,
|
|
324
|
+
sourcePath: "src/components/ShellLayout.vue"
|
|
325
|
+
}
|
|
326
|
+
]);
|
|
327
|
+
});
|
|
328
|
+
});
|
|
329
|
+
|
|
299
330
|
test("resolveShellOutletPlacementTargetFromApp requires appRoot", async () => {
|
|
300
331
|
await assert.rejects(
|
|
301
332
|
() =>
|