@jskit-ai/kernel 0.1.159 → 0.1.161

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.
Files changed (102) hide show
  1. package/_testable/index.js +1 -3
  2. package/client/componentRegistry.js +44 -0
  3. package/client/componentRegistry.test.js +16 -0
  4. package/client/moduleBootstrap.js +54 -97
  5. package/client/moduleBootstrap.test.js +47 -32
  6. package/client/vite/clientBootstrapPlugin.test.js +2 -2
  7. package/internal/node/installedPackages.js +2 -7
  8. package/internal/node/installedPackages.test.js +26 -5
  9. package/package.json +3 -5
  10. package/server/actions/actionCatalogue.js +162 -0
  11. package/server/actions/actionEvents.js +66 -0
  12. package/server/actions/actionProvider.js +23 -0
  13. package/server/actions/index.js +3 -6
  14. package/server/features/defineFeature.js +131 -0
  15. package/server/features/defineFeature.test.js +238 -0
  16. package/server/features/index.js +1 -0
  17. package/server/http/HttpProvider.js +23 -0
  18. package/server/http/_testable/index.js +0 -1
  19. package/server/http/capabilityHttpRuntime.js +123 -0
  20. package/server/http/capabilityHttpRuntime.test.js +161 -0
  21. package/server/http/directRequestActionExecutor.js +78 -0
  22. package/server/http/index.js +2 -1
  23. package/server/http/lib/index.js +1 -13
  24. package/server/http/lib/routeRegistration.js +9 -25
  25. package/server/platform/index.js +2 -2
  26. package/server/platform/installedRuntime.js +122 -0
  27. package/server/platform/installedRuntime.test.js +103 -0
  28. package/server/platform/providerRuntime/capabilityProviderLoader.js +100 -0
  29. package/server/platform/providerRuntime/capabilityProviderLoader.test.js +80 -0
  30. package/server/platform/providerRuntime/packageCatalog.js +4 -1
  31. package/server/platform/surfaceRuntime.js +1 -15
  32. package/server/runtime/BootstrapProvider.js +69 -0
  33. package/server/runtime/EventProvider.js +74 -0
  34. package/server/runtime/EventProvider.test.js +32 -0
  35. package/server/runtime/entityChangeEvents.js +7 -7
  36. package/server/runtime/entityChangeEvents.test.js +2 -2
  37. package/server/runtime/fastifyBootstrap.js +0 -40
  38. package/server/runtime/index.js +2 -3
  39. package/server/surface/index.js +0 -1
  40. package/shared/actions/actionDefinitions.js +20 -0
  41. package/shared/actions/pipeline.js +22 -0
  42. package/shared/actions/policies.js +1 -1
  43. package/shared/actions/registry.js +3 -0
  44. package/shared/capabilities/defineProvider.js +99 -0
  45. package/shared/capabilities/index.js +2 -0
  46. package/shared/capabilities/runtime.js +243 -0
  47. package/shared/capabilities/runtime.test.js +170 -0
  48. package/test/barrelExposure.test.js +36 -13
  49. package/test/exportsContract.test.js +8 -3
  50. package/server/actions/ActionRuntimeServiceProvider.js +0 -304
  51. package/server/actions/ActionRuntimeServiceProvider.test.js +0 -558
  52. package/server/container/ContainerCoreServiceProvider.js +0 -27
  53. package/server/container/index.js +0 -10
  54. package/server/http/HttpFastifyServiceProvider.js +0 -25
  55. package/server/http/lib/httpRuntime.js +0 -83
  56. package/server/http/lib/kernel.js +0 -15
  57. package/server/http/lib/kernel.test.js +0 -1565
  58. package/server/http/lib/requestActionExecutor.js +0 -265
  59. package/server/http/lib/requestScope.js +0 -57
  60. package/server/kernel/KernelCoreServiceProvider.js +0 -27
  61. package/server/kernel/index.js +0 -10
  62. package/server/platform/PlatformServerRuntimeServiceProvider.js +0 -30
  63. package/server/platform/providerRuntime/providerLoader.js +0 -283
  64. package/server/platform/providerRuntime.js +0 -146
  65. package/server/platform/providerRuntime.test.js +0 -214
  66. package/server/platform/runtime.js +0 -40
  67. package/server/registries/actionSurfaceSourceRegistry.js +0 -148
  68. package/server/registries/bootstrapPayloadContributorRegistry.js +0 -51
  69. package/server/registries/domainEventListenerRegistry.js +0 -58
  70. package/server/registries/index.js +0 -32
  71. package/server/registries/primitives.js +0 -63
  72. package/server/registries/routeVisibilityResolverRegistry.js +0 -84
  73. package/server/registries/serviceRegistrationRegistry.js +0 -488
  74. package/server/runtime/ServerRuntimeCoreServiceProvider.js +0 -64
  75. package/server/runtime/ServerRuntimeCoreServiceProvider.test.js +0 -53
  76. package/server/runtime/apiRoutePolicyParity.test.js +0 -109
  77. package/server/runtime/apiRouteRegistration.js +0 -65
  78. package/server/runtime/bootBootstrapRoutes.js +0 -29
  79. package/server/runtime/bootBootstrapRoutes.test.js +0 -69
  80. package/server/runtime/bootstrapContributors.test.js +0 -166
  81. package/server/runtime/composition.js +0 -142
  82. package/server/runtime/domainEvents.test.js +0 -114
  83. package/server/runtime/domainRules.js +0 -50
  84. package/server/runtime/domainRules.test.js +0 -87
  85. package/server/runtime/runtimeAssembly.js +0 -113
  86. package/server/runtime/runtimeKernel.js +0 -55
  87. package/server/runtime/serviceRegistration.test.js +0 -251
  88. package/server/support/SupportCoreServiceProvider.js +0 -27
  89. package/server/surface/SurfaceRoutingServiceProvider.js +0 -27
  90. package/shared/actions/index.js +0 -2
  91. package/shared/runtime/application.js +0 -324
  92. package/shared/runtime/container.js +0 -261
  93. package/shared/runtime/containerErrors.js +0 -22
  94. package/shared/runtime/index.js +0 -18
  95. package/shared/runtime/kernelErrors.js +0 -25
  96. package/shared/runtime/kernelErrors.test.js +0 -120
  97. package/shared/runtime/serviceProvider.js +0 -13
  98. package/shared/support/containerToken.js +0 -8
  99. package/shared/support/generatedUiContract.js +0 -542
  100. package/shared/support/generatedUiContract.test.js +0 -218
  101. package/shared/support/tokens.js +0 -1
  102. package/shared/support/tokens.test.js +0 -17
@@ -1,4 +1,2 @@
1
- export { createContainer } from "../server/container/index.js";
2
- export { createApplication } from "../server/kernel/index.js";
3
- export { createHttpRuntime, compileRouteValidator } from "../server/http/_testable/index.js";
1
+ export { compileRouteValidator } from "../server/http/_testable/index.js";
4
2
  export { deriveResourceRequiredMetadata } from "../shared/validators/index.js";
@@ -0,0 +1,44 @@
1
+ function normalizeComponentId(value) {
2
+ const id = String(value || "").trim();
3
+ if (!id) {
4
+ throw new TypeError("Client component id is required.");
5
+ }
6
+ return id;
7
+ }
8
+
9
+ function createClientComponentRegistry() {
10
+ const components = new Map();
11
+
12
+ function register(id, component) {
13
+ const componentId = normalizeComponentId(id);
14
+ if (component == null) {
15
+ throw new TypeError(`Client component "${componentId}" is required.`);
16
+ }
17
+ if (components.has(componentId)) {
18
+ throw new Error(`Client component "${componentId}" is duplicated.`);
19
+ }
20
+ components.set(componentId, component);
21
+ return api;
22
+ }
23
+
24
+ function has(id) {
25
+ return components.has(normalizeComponentId(id));
26
+ }
27
+
28
+ function get(id) {
29
+ const componentId = normalizeComponentId(id);
30
+ if (!components.has(componentId)) {
31
+ throw new Error(`Client component "${componentId}" is not registered.`);
32
+ }
33
+ return components.get(componentId);
34
+ }
35
+
36
+ function ids() {
37
+ return Object.freeze([...components.keys()].sort());
38
+ }
39
+
40
+ const api = Object.freeze({ register, has, get, ids });
41
+ return api;
42
+ }
43
+
44
+ export { createClientComponentRegistry };
@@ -0,0 +1,16 @@
1
+ import assert from "node:assert/strict";
2
+ import test from "node:test";
3
+ import { createClientComponentRegistry } from "./componentRegistry.js";
4
+
5
+ test("client component registry exposes named UI components without a service locator", () => {
6
+ const registry = createClientComponentRegistry();
7
+ const component = Object.freeze({ name: "ExampleWidget" });
8
+
9
+ registry.register("example.widget", component);
10
+
11
+ assert.equal(registry.has("example.widget"), true);
12
+ assert.equal(registry.get("example.widget"), component);
13
+ assert.deepEqual(registry.ids(), ["example.widget"]);
14
+ assert.throws(() => registry.register("example.widget", {}), /duplicated/);
15
+ assert.throws(() => registry.get("missing.widget"), /not registered/);
16
+ });
@@ -1,6 +1,7 @@
1
- import { createApplication } from "../shared/runtime/application.js";
1
+ import { createCapabilityRuntime, defineProvider } from "../shared/capabilities/index.js";
2
2
  import { filterRoutesBySurface } from "../shared/surface/runtime.js";
3
3
  import { isRecord } from "../shared/support/normalize.js";
4
+ import { createClientComponentRegistry } from "./componentRegistry.js";
4
5
  import { normalizePackageMetadataClientProviders, normalizePackageMetadataUiRoutes } from "./packageMetadataSections.js";
5
6
  import { createStructuredLogger, summarizeRouterRoutes } from "./logging.js";
6
7
 
@@ -187,44 +188,7 @@ function registerClientModuleRoutes({
187
188
  });
188
189
  }
189
190
 
190
- function isProviderClass(candidate) {
191
- if (typeof candidate !== "function") {
192
- return false;
193
- }
194
-
195
- const providerId = String(candidate.id || "").trim();
196
- if (!providerId) {
197
- return false;
198
- }
199
-
200
- const prototype = candidate.prototype;
201
- if (!prototype || typeof prototype !== "object") {
202
- return false;
203
- }
204
-
205
- return (
206
- typeof prototype.register === "function" ||
207
- typeof prototype.boot === "function" ||
208
- typeof prototype.shutdown === "function"
209
- );
210
- }
211
-
212
- function normalizeExplicitProviderClasses(value, packageId) {
213
- if (!Array.isArray(value)) {
214
- return null;
215
- }
216
-
217
- const providers = [];
218
- for (const candidate of value) {
219
- if (!isProviderClass(candidate)) {
220
- throw new TypeError(`Client module ${packageId} exports invalid clientProviders entry.`);
221
- }
222
- providers.push(candidate);
223
- }
224
- return providers;
225
- }
226
-
227
- function resolvePackageMetadataProviderClasses(moduleNamespace, packageId, packageMetadataClientProviders = []) {
191
+ function resolvePackageMetadataProviders(moduleNamespace, packageId, packageMetadataClientProviders = []) {
228
192
  const providers = [];
229
193
  const seenProviderIds = new Set();
230
194
 
@@ -234,42 +198,34 @@ function resolvePackageMetadataProviderClasses(moduleNamespace, packageId, packa
234
198
  continue;
235
199
  }
236
200
 
237
- const providerClass = moduleNamespace?.[exportName];
238
- if (!isProviderClass(providerClass)) {
201
+ const providerValue = moduleNamespace?.[exportName];
202
+ let provider = null;
203
+ try {
204
+ provider = defineProvider(providerValue);
205
+ } catch (error) {
239
206
  throw new TypeError(
240
- `Client module ${packageId} packageMetadata provider export "${exportName}" is missing or invalid in "${packageId}/client".`
207
+ `Client module ${packageId} packageMetadata provider export "${exportName}" must be a capability provider: ${error.message}`,
208
+ { cause: error }
241
209
  );
242
210
  }
243
211
 
244
- const providerId = String(providerClass.id || "").trim();
245
- if (!providerId) {
246
- throw new TypeError(`Client module ${packageId} packageMetadata provider "${exportName}" requires static id.`);
247
- }
212
+ const providerId = provider.id;
248
213
 
249
214
  if (seenProviderIds.has(providerId)) {
250
215
  continue;
251
216
  }
252
217
  seenProviderIds.add(providerId);
253
- providers.push(providerClass);
218
+ providers.push(provider);
254
219
  }
255
220
 
256
221
  return providers;
257
222
  }
258
223
 
259
- function resolveModuleProviderClasses(moduleNamespace, packageId, packageMetadataClientProviders = []) {
224
+ function resolveModuleProviders(moduleNamespace, packageId, packageMetadataClientProviders = []) {
260
225
  if (!isRecord(moduleNamespace)) {
261
226
  return [];
262
227
  }
263
-
264
- const explicitProviders = normalizeExplicitProviderClasses(moduleNamespace.clientProviders, packageId);
265
- if (explicitProviders) {
266
- return explicitProviders;
267
- }
268
-
269
- if (Array.isArray(packageMetadataClientProviders) && packageMetadataClientProviders.length > 0) {
270
- return resolvePackageMetadataProviderClasses(moduleNamespace, packageId, packageMetadataClientProviders);
271
- }
272
- return [];
228
+ return resolvePackageMetadataProviders(moduleNamespace, packageId, packageMetadataClientProviders);
273
229
  }
274
230
 
275
231
  function buildPackageMetadataRouteDeclarationIndex({ packageId, packageMetadataUiRoutes = [] } = {}) {
@@ -479,8 +435,9 @@ function normalizeClientModuleEntries(clientModules) {
479
435
  .sort((left, right) => left.packageId.localeCompare(right.packageId));
480
436
  }
481
437
 
482
- function createClientRuntimeApp({
438
+ function createClientRuntime({
483
439
  profile = "client",
440
+ providers = [],
484
441
  app,
485
442
  pinia = null,
486
443
  queryClient = null,
@@ -490,22 +447,23 @@ function createClientRuntimeApp({
490
447
  surfaceRuntime,
491
448
  surfaceMode
492
449
  } = {}) {
493
- const runtimeApp = createApplication({
450
+ const components = createClientComponentRegistry();
451
+ const runtime = createCapabilityRuntime({
494
452
  profile,
495
- strict: true
453
+ providers,
454
+ inputs: {
455
+ "client.vue": app || null,
456
+ "client.router": router || null,
457
+ "client.pinia": pinia,
458
+ "client.query": queryClient,
459
+ "client.env": Object.freeze({ ...(isRecord(env) ? env : {}) }),
460
+ "client.surface": surfaceRuntime || null,
461
+ "client.surface-mode": String(surfaceMode || "").trim(),
462
+ "client.logger": logger,
463
+ "client.components": components
464
+ }
496
465
  });
497
-
498
- runtimeApp.instance("jskit.client.runtime.app", runtimeApp);
499
- runtimeApp.instance("jskit.client.router", router || null);
500
- runtimeApp.instance("jskit.client.vue.app", app || null);
501
- runtimeApp.instance("jskit.client.pinia", pinia);
502
- runtimeApp.instance("jskit.client.query-client", queryClient);
503
- runtimeApp.instance("jskit.client.env", isRecord(env) ? { ...env } : {});
504
- runtimeApp.instance("jskit.client.surface.runtime", surfaceRuntime || null);
505
- runtimeApp.instance("jskit.client.surface.mode", String(surfaceMode || "").trim());
506
- runtimeApp.instance("jskit.client.logger", logger);
507
-
508
- return runtimeApp;
466
+ return Object.freeze({ runtime, components });
509
467
  }
510
468
 
511
469
  async function bootClientModules({
@@ -528,19 +486,7 @@ async function bootClientModules({
528
486
 
529
487
  const log = createStructuredLogger(logger);
530
488
  const moduleEntries = normalizeClientModuleEntries(clientModules);
531
- const runtimeApp = createClientRuntimeApp({
532
- profile: String(surfaceRuntime.normalizeSurfaceMode(surfaceMode) || "client"),
533
- app,
534
- pinia,
535
- queryClient,
536
- router,
537
- env,
538
- logger: log,
539
- surfaceRuntime,
540
- surfaceMode
541
- });
542
-
543
- const providerClasses = [];
489
+ const providers = [];
544
490
  const seenProviderIds = new Set();
545
491
  log.debug(
546
492
  {
@@ -552,28 +498,38 @@ async function bootClientModules({
552
498
  "Starting JSKIT client module bootstrap."
553
499
  );
554
500
  for (const entry of moduleEntries) {
555
- const providers = resolveModuleProviderClasses(entry.module, entry.packageId, entry.packageMetadataClientProviders);
501
+ const moduleProviders = resolveModuleProviders(entry.module, entry.packageId, entry.packageMetadataClientProviders);
556
502
  log.debug(
557
503
  {
558
504
  packageId: entry.packageId,
559
- providerExports: providers.map((providerClass) => String(providerClass.id || providerClass.name || "").trim()),
505
+ providerExports: moduleProviders.map((provider) => provider.id),
560
506
  hasClientRoutes: Array.isArray(entry.module.clientRoutes) && entry.module.clientRoutes.length > 0
561
507
  },
562
508
  "Discovered client module capabilities."
563
509
  );
564
- for (const providerClass of providers) {
565
- const providerId = String(providerClass.id || "").trim();
510
+ for (const provider of moduleProviders) {
511
+ const providerId = provider.id;
566
512
  if (seenProviderIds.has(providerId)) {
567
513
  throw new Error(`Client provider id "${providerId}" is duplicated.`);
568
514
  }
569
515
  seenProviderIds.add(providerId);
570
- providerClasses.push(providerClass);
516
+ providers.push(provider);
571
517
  }
572
518
  }
573
519
 
574
- if (providerClasses.length > 0) {
575
- await runtimeApp.start({ providers: providerClasses });
576
- }
520
+ const clientRuntime = createClientRuntime({
521
+ profile: String(surfaceRuntime.normalizeSurfaceMode(surfaceMode) || "client"),
522
+ providers,
523
+ app,
524
+ pinia,
525
+ queryClient,
526
+ router,
527
+ env,
528
+ logger: log,
529
+ surfaceRuntime,
530
+ surfaceMode
531
+ });
532
+ await clientRuntime.runtime.start();
577
533
 
578
534
  const seenRoutePaths = new Set();
579
535
  const seenRouteNames = new Set();
@@ -638,7 +594,7 @@ async function bootClientModules({
638
594
  log.debug(
639
595
  {
640
596
  modules: moduleEntries.map((entry) => entry.packageId),
641
- providerCount: providerClasses.length,
597
+ providerCount: providers.length,
642
598
  routeCount: registeredRouteCount
643
599
  },
644
600
  "Booted JSKIT client modules."
@@ -653,9 +609,10 @@ async function bootClientModules({
653
609
  }
654
610
 
655
611
  return Object.freeze({
656
- runtimeApp,
612
+ runtime: clientRuntime.runtime,
613
+ components: clientRuntime.components,
657
614
  modules: Object.freeze(moduleEntries.map((entry) => entry.packageId)),
658
- providerCount: providerClasses.length,
615
+ providerCount: providers.length,
659
616
  routeResults: Object.freeze(routeResults),
660
617
  routeCount: registeredRouteCount
661
618
  });
@@ -1,5 +1,6 @@
1
1
  import assert from "node:assert/strict";
2
2
  import test from "node:test";
3
+ import { defineProvider } from "../shared/capabilities/index.js";
3
4
  import { createSurfaceRuntime } from "../shared/surface/runtime.js";
4
5
  import { bootClientModules } from "./moduleBootstrap.js";
5
6
 
@@ -115,25 +116,37 @@ test("bootClientModules registers packageMetadata and clientRoutes with provider
115
116
  const pinia = { id: "pinia-instance" };
116
117
  const queryClient = { id: "query-client-instance" };
117
118
  const implicitPinia = { id: "implicit-vue-global-pinia" };
118
- class ExampleClientProvider {
119
- static id = "example.client";
120
- register(app) {
121
- events.push("register");
122
- app.instance("example.value", 42);
123
- app.instance("example.pinia", app.make("jskit.client.pinia"));
124
- app.instance("example.queryClient", app.make("jskit.client.query-client"));
125
- }
119
+ let receivedPinia = null;
120
+ let receivedQueryClient = null;
121
+ const ExampleClientProvider = defineProvider({
122
+ id: "example.client",
123
+ requires: {
124
+ components: "client.components",
125
+ pinia: "client.pinia",
126
+ queryClient: "client.query"
127
+ },
128
+ setup({ components, pinia: runtimePinia, queryClient: runtimeQueryClient }) {
129
+ events.push("setup");
130
+ components.register("example.login", loginComponent);
131
+ receivedPinia = runtimePinia;
132
+ receivedQueryClient = runtimeQueryClient;
133
+ },
126
134
  boot() {
127
135
  events.push("boot");
128
136
  }
129
- }
137
+ });
130
138
 
131
139
  const result = await bootClientModules({
132
140
  clientModules: [
133
141
  {
134
142
  packageId: "@example/alpha",
143
+ packageMetadataClientProviders: [
144
+ {
145
+ entrypoint: "src/client/providers/ExampleClientProvider.js",
146
+ export: "ExampleClientProvider"
147
+ }
148
+ ],
135
149
  module: {
136
- clientProviders: [ExampleClientProvider],
137
150
  ExampleClientProvider
138
151
  }
139
152
  },
@@ -199,7 +212,7 @@ test("bootClientModules registers packageMetadata and clientRoutes with provider
199
212
  logger: { info() {}, warn() {}, error() {} }
200
213
  });
201
214
 
202
- assert.deepEqual(events, ["register", "boot"]);
215
+ assert.deepEqual(events, ["setup", "boot"]);
203
216
  assert.equal(result.providerCount, 1);
204
217
  assert.equal(result.routeCount, 2);
205
218
  assert.equal(router.routes.length, 2);
@@ -207,10 +220,11 @@ test("bootClientModules registers packageMetadata and clientRoutes with provider
207
220
  assert.equal(router.routes[0].component, loginComponent);
208
221
  assert.equal(router.routes[1].path, "/auth/login");
209
222
  assert.equal(router.routes[1].component, loginComponent);
210
- assert.equal(result.runtimeApp.make("example.value"), 42);
211
- assert.equal(result.runtimeApp.make("example.pinia"), pinia);
212
- assert.equal(result.runtimeApp.make("example.queryClient"), queryClient);
213
- assert.notEqual(result.runtimeApp.make("example.pinia"), implicitPinia);
223
+ assert.equal(result.components.get("example.login"), loginComponent);
224
+ assert.equal(receivedPinia, pinia);
225
+ assert.equal(receivedQueryClient, queryClient);
226
+ assert.notEqual(receivedPinia, implicitPinia);
227
+ assert.equal(result.runtime.diagnostics().lifecycleState, "started");
214
228
  });
215
229
 
216
230
  test("bootClientModules does not auto-discover providers from module exports", async () => {
@@ -218,15 +232,15 @@ test("bootClientModules does not auto-discover providers from module exports", a
218
232
  const surfaceRuntime = createSurfaceRuntimeFixture();
219
233
  const events = [];
220
234
 
221
- class ExampleClientProvider {
222
- static id = "example.client";
223
- register() {
224
- events.push("register");
225
- }
235
+ const ExampleClientProvider = defineProvider({
236
+ id: "example.client",
237
+ setup() {
238
+ events.push("setup");
239
+ },
226
240
  boot() {
227
241
  events.push("boot");
228
242
  }
229
- }
243
+ });
230
244
 
231
245
  const result = await bootClientModules({
232
246
  clientModules: [
@@ -359,6 +373,15 @@ test("bootClientModules loads client providers declared in packageMetadataClient
359
373
  const router = createRouterStub();
360
374
  const surfaceRuntime = createSurfaceRuntimeFixture();
361
375
  const events = [];
376
+ const ExampleProvider = defineProvider({
377
+ id: "example.packageMetadata.provider",
378
+ setup() {
379
+ events.push("setup");
380
+ },
381
+ boot() {
382
+ events.push("boot");
383
+ }
384
+ });
362
385
 
363
386
  await bootClientModules({
364
387
  clientModules: [
@@ -371,15 +394,7 @@ test("bootClientModules loads client providers declared in packageMetadataClient
371
394
  }
372
395
  ],
373
396
  module: {
374
- ExampleProvider: class {
375
- static id = "example.packageMetadata.provider";
376
- register() {
377
- events.push("register");
378
- }
379
- boot() {
380
- events.push("boot");
381
- }
382
- }
397
+ ExampleProvider
383
398
  }
384
399
  }
385
400
  ],
@@ -389,7 +404,7 @@ test("bootClientModules loads client providers declared in packageMetadataClient
389
404
  logger: { info() {}, warn() {}, error() {} }
390
405
  });
391
406
 
392
- assert.deepEqual(events, ["register", "boot"]);
407
+ assert.deepEqual(events, ["setup", "boot"]);
393
408
  });
394
409
 
395
410
  test("bootClientModules throws when packageMetadataClientProviders export is missing", async () => {
@@ -415,6 +430,6 @@ test("bootClientModules throws when packageMetadataClientProviders export is mis
415
430
  surfaceMode: "all",
416
431
  logger: { info() {}, warn() {}, error() {} }
417
432
  }),
418
- /packageMetadata provider export "MissingProvider" is missing or invalid/
433
+ /packageMetadata provider export "MissingProvider" must be a capability provider/
419
434
  );
420
435
  });
@@ -504,7 +504,7 @@ test("resolveInstalledViteProxyEntries rejects malformed package proxy metadata"
504
504
  );
505
505
  });
506
506
 
507
- test("resolveLocalScopePackageIds reads @local packages from package.json", async () => {
507
+ test("resolveLocalScopePackageIds excludes development-only local packages from runtime composition", async () => {
508
508
  const tempRoot = await mkdtemp(path.join(os.tmpdir(), "jskit-client-bootstrap-local-scope-"));
509
509
  await writeJson(path.join(tempRoot, "package.json"), {
510
510
  name: "fixture-app",
@@ -519,7 +519,7 @@ test("resolveLocalScopePackageIds reads @local packages from package.json", asyn
519
519
 
520
520
  const packageIds = await resolveLocalScopePackageIds({ appRoot: tempRoot });
521
521
 
522
- assert.deepEqual(packageIds, ["@local/dev-only", "@local/feature"]);
522
+ assert.deepEqual(packageIds, ["@local/feature"]);
523
523
  });
524
524
 
525
525
  test("createJskitClientBootstrapPlugin resolves and loads virtual module", async () => {
@@ -7,18 +7,13 @@ import { fileExists } from "./fileSystem.js";
7
7
  const ROOT_DEPENDENCY_SECTIONS = Object.freeze([
8
8
  "dependencies",
9
9
  "optionalDependencies",
10
- "peerDependencies",
11
- "devDependencies"
10
+ "peerDependencies"
12
11
  ]);
13
12
  const JSKIT_PACKAGE_CONFIG_KEYS = Object.freeze([
14
13
  "capabilities",
15
- "ci",
16
14
  "kind",
17
- "lifecycle",
18
15
  "metadata",
19
- "mutations",
20
- "optionPolicies",
21
- "options",
16
+ "migrations",
22
17
  "runtime",
23
18
  "vite"
24
19
  ]);
@@ -32,13 +32,9 @@ test("createPackageMetadata derives package identity from package.json", () => {
32
32
  test("createPackageMetadata accepts only the canonical package.json.jskit fields", () => {
33
33
  assert.deepEqual(JSKIT_PACKAGE_CONFIG_KEYS, [
34
34
  "capabilities",
35
- "ci",
36
35
  "kind",
37
- "lifecycle",
38
36
  "metadata",
39
- "mutations",
40
- "optionPolicies",
41
- "options",
37
+ "migrations",
42
38
  "runtime",
43
39
  "vite"
44
40
  ]);
@@ -94,3 +90,28 @@ test("discoverInstalledPackages resolves file tarballs from node_modules", async
94
90
  assert.equal(packages[0].packageRoot, installedPackageRoot);
95
91
  assert.equal(packages[0].sourceType, "npm-package");
96
92
  });
93
+
94
+ test("discoverInstalledPackages excludes development-only packages from runtime composition", async (context) => {
95
+ const appRoot = await mkdtemp(path.join(tmpdir(), "jskit-installed-package-dev-"));
96
+ context.after(() => rm(appRoot, { recursive: true, force: true }));
97
+ const runtimeRoot = path.join(appRoot, "node_modules", "@example", "runtime");
98
+ const docsRoot = path.join(appRoot, "node_modules", "@example", "docs");
99
+ await mkdir(runtimeRoot, { recursive: true });
100
+ await mkdir(docsRoot, { recursive: true });
101
+ await writeFile(
102
+ path.join(appRoot, "package.json"),
103
+ JSON.stringify({
104
+ dependencies: { "@example/runtime": "1.0.0" },
105
+ devDependencies: { "@example/docs": "1.0.0" }
106
+ })
107
+ );
108
+ for (const [packageRoot, name] of [[runtimeRoot, "@example/runtime"], [docsRoot, "@example/docs"]]) {
109
+ await writeFile(
110
+ path.join(packageRoot, "package.json"),
111
+ JSON.stringify({ name, version: "1.0.0", jskit: { kind: "runtime" } })
112
+ );
113
+ }
114
+
115
+ const packages = await discoverInstalledPackages({ appRoot });
116
+ assert.deepEqual(packages.map((entry) => entry.packageId), ["@example/runtime"]);
117
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jskit-ai/kernel",
3
- "version": "0.1.159",
3
+ "version": "0.1.161",
4
4
  "type": "module",
5
5
  "dependencies": {
6
6
  "json-rest-schema": "^1.0.17"
@@ -25,27 +25,25 @@
25
25
  "./client/moduleBootstrap": "./client/moduleBootstrap.js",
26
26
  "./client/vite": "./client/vite/index.js",
27
27
  "./server/actions": "./server/actions/index.js",
28
+ "./server/features": "./server/features/index.js",
28
29
  "./server/http": "./server/http/index.js",
29
30
  "./server/platform": "./server/platform/index.js",
30
- "./server/registries": "./server/registries/index.js",
31
31
  "./server/runtime": "./server/runtime/index.js",
32
32
  "./server/runtime/entityChangeEvents": "./server/runtime/entityChangeEvents.js",
33
33
  "./server/runtime/errors": "./server/runtime/errors.js",
34
34
  "./server/runtime/requestUrl": "./server/runtime/requestUrl.js",
35
35
  "./server/support": "./server/support/index.js",
36
36
  "./shared": "./shared/index.js",
37
- "./shared/actions": "./shared/actions/index.js",
37
+ "./shared/capabilities": "./shared/capabilities/index.js",
38
38
  "./shared/actions/actionContributorHelpers": "./shared/actions/actionContributorHelpers.js",
39
39
  "./shared/actions/textNormalization": "./shared/actions/textNormalization.js",
40
40
  "./shared/validators": "./shared/validators/index.js",
41
41
  "./shared/validators/inputNormalization": "./shared/validators/inputNormalization.js",
42
42
  "./shared/support": "./shared/support/index.js",
43
43
  "./shared/support/stringCase": "./shared/support/stringCase.js",
44
- "./shared/support/tokens": "./shared/support/tokens.js",
45
44
  "./shared/support/normalize": "./shared/support/normalize.js",
46
45
  "./shared/support/permissions": "./shared/support/permissions.js",
47
46
  "./shared/support/jsonApiFieldsets": "./shared/support/jsonApiFieldsets.js",
48
- "./shared/support/generatedUiContract": "./shared/support/generatedUiContract.js",
49
47
  "./shared/support/deepFreeze": "./shared/support/deepFreeze.js",
50
48
  "./shared/support/listenerSet": "./shared/support/listenerSet.js",
51
49
  "./shared/support/shellLayoutTargets": "./shared/support/shellLayoutTargets.js",