@lorion-org/react 1.0.0-beta.1 → 1.0.0-beta.3
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/README.md +349 -20
- package/dist/index.cjs +72 -10
- package/dist/index.d.cts +23 -1
- package/dist/index.d.ts +23 -1
- package/dist/index.js +67 -9
- package/dist/vite.cjs +336 -45
- package/dist/vite.d.cts +69 -7
- package/dist/vite.d.ts +69 -7
- package/dist/vite.js +335 -49
- package/package.json +27 -10
- package/src/index.ts +225 -0
- package/src/relations.ts +8 -0
- package/src/runtime-config.ts +63 -0
- package/src/vite.ts +891 -0
package/README.md
CHANGED
|
@@ -1,8 +1,15 @@
|
|
|
1
1
|
# @lorion-org/react
|
|
2
2
|
|
|
3
|
+
[](https://www.npmjs.com/package/@lorion-org/react)
|
|
4
|
+
[](https://github.com/lorion-org/lorion/actions/workflows/ci.yml)
|
|
5
|
+
|
|
3
6
|
React capability runtime and Vite helpers for LORION descriptor-based applications.
|
|
4
7
|
|
|
5
|
-
Use this package when a React application is assembled from local capability
|
|
8
|
+
Use this package when a React application is assembled from local capability
|
|
9
|
+
packages that each expose a `capability.json` descriptor. It supports two
|
|
10
|
+
deliberate consumption models over the same LORION discovery and composition
|
|
11
|
+
graph, and both are first-class: pick one per product (see Two Composition
|
|
12
|
+
Models).
|
|
6
13
|
|
|
7
14
|
## Install
|
|
8
15
|
|
|
@@ -10,15 +17,42 @@ Use this package when a React application is assembled from local capability pac
|
|
|
10
17
|
pnpm add @lorion-org/react react
|
|
11
18
|
```
|
|
12
19
|
|
|
20
|
+
Host configs that import selection helpers from `@lorion-org/composition-graph`
|
|
21
|
+
should declare that package directly too.
|
|
22
|
+
|
|
13
23
|
Add Vite, TanStack Router, or another router in the host application as needed.
|
|
14
24
|
The runtime helpers do not own routing; the Vite entry point only prepares
|
|
15
25
|
capability discovery and TanStack-compatible virtual route config.
|
|
16
26
|
|
|
27
|
+
## Quick start
|
|
28
|
+
|
|
29
|
+
Add the Vite capability loader, then consume the resolved capabilities with your
|
|
30
|
+
own runtime (this is the loader-only path, Model B):
|
|
31
|
+
|
|
32
|
+
```ts
|
|
33
|
+
// vite.config.ts
|
|
34
|
+
import { capabilityLoader } from '@lorion-org/react/vite';
|
|
35
|
+
|
|
36
|
+
export default defineConfig({
|
|
37
|
+
plugins: [capabilityLoader({ workspaceRoot: import.meta.dirname })],
|
|
38
|
+
});
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
```ts
|
|
42
|
+
// main.ts
|
|
43
|
+
import { capabilityModules } from 'virtual:capabilities';
|
|
44
|
+
// register the pre-resolved capabilities with your own plugin runtime
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
For a batteries-included React runtime and file-based routing instead, use
|
|
48
|
+
`lorionReact()` (Model A). Both are described under Two Composition Models.
|
|
49
|
+
|
|
17
50
|
## What It Is
|
|
18
51
|
|
|
19
52
|
- a small React binding for immutable capability contributions
|
|
20
53
|
- a Vite virtual module helper for active capability activation exports
|
|
21
54
|
- a TanStack virtual route config helper for capability-owned route folders
|
|
55
|
+
- scoped public runtime config for active capabilities
|
|
22
56
|
- a React adapter over LORION descriptor discovery and composition graph packages
|
|
23
57
|
|
|
24
58
|
## What It Is Not
|
|
@@ -28,7 +62,41 @@ capability discovery and TanStack-compatible virtual route config.
|
|
|
28
62
|
- not a package manager
|
|
29
63
|
- not an application naming convention
|
|
30
64
|
|
|
31
|
-
##
|
|
65
|
+
## Two Composition Models
|
|
66
|
+
|
|
67
|
+
Both models build on the same LORION discovery, composition graph, provider
|
|
68
|
+
selection, and `virtual:capabilities` build output. They differ only in how much
|
|
69
|
+
of the React side the host delegates to this package. Neither is a special case;
|
|
70
|
+
choose one per product.
|
|
71
|
+
|
|
72
|
+
### Model A: React capability runtime and routing
|
|
73
|
+
|
|
74
|
+
`lorionReact()` wires the Vite capability loader, the React capability runtime
|
|
75
|
+
(`createCapabilityRuntime`), and TanStack file-based route composition together.
|
|
76
|
+
Capabilities activate through the `./capability` convention and own route
|
|
77
|
+
folders. Use this when the product wants a batteries-included React runtime and
|
|
78
|
+
file-based routing from LORION.
|
|
79
|
+
|
|
80
|
+
### Model B: capability loader with your own runtime
|
|
81
|
+
|
|
82
|
+
`capabilityLoader()` on its own resolves the descriptor graph at build time and
|
|
83
|
+
emits `virtual:capabilities`; the host consumes that pre-resolved module list
|
|
84
|
+
with its own plugin registry, its own routing, and its own lifecycle. Nothing
|
|
85
|
+
from the React runtime or route config is required. Capabilities activate through
|
|
86
|
+
an explicit `activation` resolver against their existing package exports, and
|
|
87
|
+
dependency-only libraries stay graph-only. Use this when the product already owns
|
|
88
|
+
a plugin system, or when one package set ships as several product distributions,
|
|
89
|
+
and only needs LORION for selection and activation.
|
|
90
|
+
|
|
91
|
+
| | Model A | Model B |
|
|
92
|
+
| ------------- | ---------------------------------------- | ---------------------------------------------------- |
|
|
93
|
+
| Vite entry | `lorionReact()` | `capabilityLoader()` |
|
|
94
|
+
| React runtime | `createCapabilityRuntime` (this package) | host-owned |
|
|
95
|
+
| Routing | TanStack file-based via `routeConfig` | host-owned (for example code-based) |
|
|
96
|
+
| Activation | `./capability` convention | explicit `activation` resolver, graph-only otherwise |
|
|
97
|
+
| Host consumes | provider and contribution contracts | `capabilityModules` from `virtual:capabilities` |
|
|
98
|
+
|
|
99
|
+
## React Capability Runtime (Model A)
|
|
32
100
|
|
|
33
101
|
```ts
|
|
34
102
|
import { CapabilityRuntimeProvider, createCapabilityRuntime } from '@lorion-org/react';
|
|
@@ -111,19 +179,19 @@ to TanStack Router as a capability-owned route subtree.
|
|
|
111
179
|
## Vite
|
|
112
180
|
|
|
113
181
|
```ts
|
|
114
|
-
import { lorionReact } from '@lorion-org/react/vite';
|
|
182
|
+
import { capabilityLoader, lorionReact } from '@lorion-org/react/vite';
|
|
115
183
|
```
|
|
116
184
|
|
|
117
|
-
|
|
185
|
+
`capabilityLoader` is the standalone loader used by Model B. `lorionReact()`
|
|
186
|
+
bundles that loader with the Model A route config.
|
|
187
|
+
|
|
188
|
+
The Vite helper discovers `capabilities/*/capability.json`, validates the descriptor shape with LORION, resolves selected descriptors through the LORION composition graph, resolves each active capability's activation entry, and exposes `virtual:capabilities`.
|
|
118
189
|
|
|
119
190
|
```ts
|
|
120
|
-
const capabilityComposition = {
|
|
121
|
-
selected: ['default'],
|
|
122
|
-
};
|
|
123
191
|
const lorion = lorionReact({
|
|
124
192
|
workspaceRoot,
|
|
125
193
|
routesDirectory,
|
|
126
|
-
|
|
194
|
+
defaultSelection: ['default'],
|
|
127
195
|
});
|
|
128
196
|
|
|
129
197
|
export default defineConfig({
|
|
@@ -138,32 +206,260 @@ export default defineConfig({
|
|
|
138
206
|
});
|
|
139
207
|
```
|
|
140
208
|
|
|
141
|
-
|
|
209
|
+
By default the Vite helper reads the shared capability seed from
|
|
210
|
+
`--capabilities`, `npm_config_capabilities`, and `LORION_CAPABILITIES` before it
|
|
211
|
+
falls back to `defaultSelection`. No `selectionSeed.key` option is required for
|
|
212
|
+
that default. Pass `selectionSeed` only to override the seed names, inject custom
|
|
213
|
+
`argv`/`env` for tests, or set `selectionSeed: false` to disable CLI/env lookup.
|
|
214
|
+
|
|
215
|
+
Route config generation stays TanStack-focused and only includes enabled,
|
|
216
|
+
selected capability route directories. If no `selected`, seed value,
|
|
217
|
+
`defaultSelection`, or `baseDescriptors` are provided, every enabled local
|
|
218
|
+
capability remains active.
|
|
219
|
+
Use `indexRouteFile: false` when `/` is owned by a capability route.
|
|
220
|
+
|
|
221
|
+
The virtual module exports `capabilityModules`, `selectedCapabilityIds`, and
|
|
222
|
+
`resolvedCapabilityIds` so host code can distinguish the seed from the final
|
|
223
|
+
graph resolution.
|
|
224
|
+
|
|
225
|
+
### Activation
|
|
226
|
+
|
|
227
|
+
Activation binds a resolved descriptor to the module the host imports. LORION
|
|
228
|
+
supports two models, chosen by the host.
|
|
229
|
+
|
|
230
|
+
Convention (default): each capability activates through a `./capability` package
|
|
231
|
+
export with a `capability` named export. No option is required.
|
|
232
|
+
|
|
233
|
+
Explicit resolver: pass an `activation` resolver to bind against an existing
|
|
234
|
+
package export, so capabilities that already expose their contribution from
|
|
235
|
+
another entry point need no dedicated activation file:
|
|
236
|
+
|
|
237
|
+
```ts
|
|
238
|
+
capabilityLoader({
|
|
239
|
+
workspaceRoot,
|
|
240
|
+
activation: ({ descriptor }) => ({
|
|
241
|
+
exportSubpath: './web',
|
|
242
|
+
exportName: `${descriptor.id}WebPlugin`,
|
|
243
|
+
}),
|
|
244
|
+
});
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
The generated import then uses the resolved subpath and export name (for example
|
|
248
|
+
`import { homeWebPlugin as homeCapability } from '@scope/home/web'`), and
|
|
249
|
+
specifier resolution is left to the host bundler rather than self-resolved by
|
|
250
|
+
LORION.
|
|
251
|
+
|
|
252
|
+
Graph-only: when the resolver returns a nullish activation for a descriptor, that
|
|
253
|
+
capability still takes part in dependency resolution but activates nothing. No
|
|
254
|
+
import is emitted and it never reaches `capabilityModules`. Use this for
|
|
255
|
+
dependency-only libraries that shape the graph without contributing a runtime
|
|
256
|
+
plugin.
|
|
257
|
+
|
|
258
|
+
## Bring Your Own Runtime (Model B)
|
|
259
|
+
|
|
260
|
+
In Model B the host uses only the Vite capability loader and composes the
|
|
261
|
+
resolved modules with its own runtime. The build resolves the descriptor graph
|
|
262
|
+
(base, selected features, transitive dependencies, and exactly one provider per
|
|
263
|
+
capability) and emits `capabilityModules` already ordered and filtered.
|
|
264
|
+
|
|
265
|
+
```ts
|
|
266
|
+
// vite.config.ts
|
|
267
|
+
capabilityLoader({
|
|
268
|
+
workspaceRoot,
|
|
269
|
+
capabilitiesDir: 'packages',
|
|
270
|
+
baseDescriptors: ['shell', 'auth'], // always-on platform base
|
|
271
|
+
defaultSelection: ['home', 'reports'], // default feature set
|
|
272
|
+
selectionSeed: { cliKeys: ['features'], envKeys: ['APP_FEATURES'] },
|
|
273
|
+
// Read a host-defined descriptor field; return undefined to keep a package
|
|
274
|
+
// graph-only. LORION descriptors carry host keys unchanged, so annotate the read.
|
|
275
|
+
activation: ({ descriptor }) =>
|
|
276
|
+
(descriptor as { surfaces?: { web?: { exportName?: string; exportSubpath?: string } } })
|
|
277
|
+
.surfaces?.web,
|
|
278
|
+
});
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
To reuse the framework-free surface convention from
|
|
282
|
+
[`@lorion-org/surface-activation`](../surface-activation) directly — without a
|
|
283
|
+
per-host adapter — pass `surface` instead of `activation`. Pass exactly one of the
|
|
284
|
+
two (passing both throws). The `fileSurfaceConvention` preset detects a surface by a
|
|
285
|
+
file marker and derives its export name and import subpath (here the canonical
|
|
286
|
+
`@scope/<id>/web/plugin` entry); the raw `SurfaceConvention` object stays available
|
|
287
|
+
for cases the preset does not cover:
|
|
288
|
+
|
|
289
|
+
```ts
|
|
290
|
+
import { existsSync } from 'node:fs';
|
|
291
|
+
import { join } from 'node:path';
|
|
292
|
+
import { conventionActivation, fileSurfaceConvention } from '@lorion-org/surface-activation';
|
|
293
|
+
|
|
294
|
+
capabilityLoader({
|
|
295
|
+
workspaceRoot,
|
|
296
|
+
capabilitiesDir: 'packages',
|
|
297
|
+
baseDescriptors: ['shell', 'auth'],
|
|
298
|
+
defaultSelection: ['home', 'reports'],
|
|
299
|
+
surface: {
|
|
300
|
+
name: 'web',
|
|
301
|
+
resolver: conventionActivation({
|
|
302
|
+
web: fileSurfaceConvention({
|
|
303
|
+
files: ['src/web/plugin.ts'],
|
|
304
|
+
exportSuffix: 'WebPlugin',
|
|
305
|
+
exportSubpath: './web/plugin',
|
|
306
|
+
exists: existsSync, // injected — surface-activation itself touches no filesystem
|
|
307
|
+
join,
|
|
308
|
+
}),
|
|
309
|
+
}),
|
|
310
|
+
},
|
|
311
|
+
});
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
Migrating from a hand-written adapter: replace
|
|
315
|
+
`activation: ({ capabilityDir, descriptor }) => resolver('web', { directory: capabilityDir, id: descriptor.id })`
|
|
316
|
+
with `surface: { name: 'web', resolver }`.
|
|
317
|
+
|
|
318
|
+
```ts
|
|
319
|
+
// main.ts: consume the pre-resolved list with your own registry
|
|
320
|
+
import { capabilityModules } from 'virtual:capabilities';
|
|
321
|
+
import { createRegistry } from './my-plugin-system';
|
|
322
|
+
|
|
323
|
+
const registry = createRegistry();
|
|
324
|
+
for (const plugin of capabilityModules) registry.register(plugin);
|
|
325
|
+
await registry.setup();
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
The host runtime lists no capability by hand and makes no provider decision.
|
|
329
|
+
Adding or removing a package changes only the descriptor graph, not the runtime
|
|
330
|
+
wiring. Route ownership, i18n merging, and lifecycle hooks stay in the host's own
|
|
331
|
+
plugin system.
|
|
332
|
+
|
|
333
|
+
## Runtime Config
|
|
334
|
+
|
|
335
|
+
React runtime config follows the same LORION ownership model as other
|
|
336
|
+
capability data: a capability owns its config contract, deployment inputs provide
|
|
337
|
+
values, and the framework adapter exposes only the safe runtime view.
|
|
338
|
+
|
|
339
|
+
By default the React Vite adapter looks for:
|
|
340
|
+
|
|
341
|
+
```text
|
|
342
|
+
capabilities/<capability>/capability.schema.json
|
|
343
|
+
.data/runtime-config/<capability>/capability.runtime.json
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
Hosts can configure the convention once:
|
|
347
|
+
|
|
348
|
+
```ts
|
|
349
|
+
const lorion = lorionReact({
|
|
350
|
+
workspaceRoot,
|
|
351
|
+
routesDirectory,
|
|
352
|
+
runtimeConfig: {
|
|
353
|
+
configFileName: 'capability.runtime.json',
|
|
354
|
+
schemaFileName: 'capability.schema.json',
|
|
355
|
+
},
|
|
356
|
+
});
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
By default, file-backed config is read from `<workspaceRoot>/.data`. Hosts that
|
|
360
|
+
need a deployment-controlled var dir can configure an env key:
|
|
361
|
+
|
|
362
|
+
```ts
|
|
363
|
+
const lorion = lorionReact({
|
|
364
|
+
workspaceRoot,
|
|
365
|
+
routesDirectory,
|
|
366
|
+
runtimeConfig: {
|
|
367
|
+
varDir: {
|
|
368
|
+
envKey: 'REACT_VAR_DIR',
|
|
369
|
+
},
|
|
370
|
+
},
|
|
371
|
+
});
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
Runtime files use unprefixed capability-local sections:
|
|
375
|
+
|
|
376
|
+
```json
|
|
377
|
+
{
|
|
378
|
+
"public": {
|
|
379
|
+
"url": "https://id.example.test",
|
|
380
|
+
"realm": "demo",
|
|
381
|
+
"clientId": "web"
|
|
382
|
+
},
|
|
383
|
+
"private": {
|
|
384
|
+
"clientSecret": "server-only"
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
The adapter also reads Vite env files and process env. Public keys use the
|
|
390
|
+
`VITE_<CAPABILITY>_<KEY>` convention, while private keys use
|
|
391
|
+
`<CAPABILITY>_<KEY>`:
|
|
392
|
+
|
|
393
|
+
```text
|
|
394
|
+
VITE_AUTH_OIDC_URL=https://id.example.test
|
|
395
|
+
VITE_AUTH_OIDC_REALM=demo
|
|
396
|
+
VITE_AUTH_OIDC_CLIENT_ID=web
|
|
397
|
+
AUTH_OIDC_CLIENT_SECRET=server-only
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
Env values override runtime files. Only `public` config is emitted through
|
|
401
|
+
`virtual:capability-runtime-config`; server code can opt into
|
|
402
|
+
`virtual:capability-runtime-config/server`. The server virtual module is
|
|
403
|
+
SSR-only and fails during client builds to prevent private config from being
|
|
404
|
+
bundled.
|
|
405
|
+
|
|
406
|
+
Render the config provider near the capability runtime provider:
|
|
407
|
+
|
|
408
|
+
```tsx
|
|
409
|
+
import { CapabilityRuntimeConfigProvider } from '@lorion-org/react';
|
|
410
|
+
import { capabilityRuntimeConfig } from 'virtual:capability-runtime-config';
|
|
411
|
+
|
|
412
|
+
<CapabilityRuntimeConfigProvider runtimeConfig={capabilityRuntimeConfig}>
|
|
413
|
+
<App />
|
|
414
|
+
</CapabilityRuntimeConfigProvider>;
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
Capability code reads scoped public config:
|
|
418
|
+
|
|
419
|
+
```ts
|
|
420
|
+
import { useCapabilityRuntimeConfig } from '@lorion-org/react';
|
|
421
|
+
|
|
422
|
+
const authOidc = useCapabilityRuntimeConfig('auth-oidc');
|
|
423
|
+
console.log(authOidc.public.url);
|
|
424
|
+
```
|
|
142
425
|
|
|
143
426
|
## Provider Selection
|
|
144
427
|
|
|
145
|
-
Capabilities that implement another capability can declare `providesFor
|
|
428
|
+
Capabilities that implement another capability can declare `providesFor`.
|
|
429
|
+
Provider-owned defaults use `defaultFor` on the provider descriptor:
|
|
146
430
|
|
|
147
431
|
```json
|
|
148
432
|
{
|
|
149
433
|
"id": "payment-provider-stripe",
|
|
150
434
|
"version": "1.0.0",
|
|
151
|
-
"providesFor": "
|
|
435
|
+
"providesFor": "checkout",
|
|
436
|
+
"defaultFor": "checkout"
|
|
152
437
|
}
|
|
153
438
|
```
|
|
154
439
|
|
|
155
|
-
|
|
440
|
+
`providesFor` and `defaultFor` both accept a string or string array. If a
|
|
441
|
+
capability descriptor exists, `defaultFor` also creates the composition relation
|
|
442
|
+
from that capability to the default provider.
|
|
443
|
+
|
|
444
|
+
Profiles can still declare descriptor preferences with `providerPreferences`.
|
|
445
|
+
Use this when the profile, not the provider package, owns the default choice:
|
|
156
446
|
|
|
157
447
|
```json
|
|
158
448
|
{
|
|
159
449
|
"id": "web",
|
|
160
450
|
"version": "1.0.0",
|
|
161
451
|
"providerPreferences": {
|
|
162
|
-
"
|
|
452
|
+
"checkout": "payment-provider-stripe"
|
|
163
453
|
}
|
|
164
454
|
}
|
|
165
455
|
```
|
|
166
456
|
|
|
457
|
+
When a provider capability is explicitly selected through the normal selection
|
|
458
|
+
seed, the Vite helper removes lower-priority `defaultFor` and
|
|
459
|
+
`providerPreferences` relations for that capability before graph resolution.
|
|
460
|
+
That selected provider wins over descriptor defaults and preferences. A losing
|
|
461
|
+
provider is only present if another hard dependency still requires it.
|
|
462
|
+
|
|
167
463
|
Read the resolved provider selection from the runtime:
|
|
168
464
|
|
|
169
465
|
```ts
|
|
@@ -172,24 +468,57 @@ import { getCapabilityProviderSelection } from '@lorion-org/react';
|
|
|
172
468
|
const selection = getCapabilityProviderSelection(capabilityRuntime);
|
|
173
469
|
```
|
|
174
470
|
|
|
175
|
-
Explicit `configuredProviders` passed to `getCapabilityProviderSelection()`
|
|
471
|
+
Explicit `configuredProviders` passed to `getCapabilityProviderSelection()`
|
|
472
|
+
override selected providers, provider-owned defaults, and descriptor
|
|
473
|
+
preferences. `selectedProviders` can mirror the descriptor seed at runtime, and
|
|
474
|
+
`fallbackProviders` are merged with descriptor defaults and only used when no
|
|
475
|
+
configured or selected provider exists.
|
|
476
|
+
|
|
477
|
+
The React example uses the first variant by default: Stripe declares
|
|
478
|
+
`defaultFor: "checkout"` and is selected as the fallback provider. Selecting
|
|
479
|
+
`web payment-provider-invoice` through the seed switches checkout to Invoice and
|
|
480
|
+
leaves Stripe out of the resolved capabilities.
|
|
176
481
|
|
|
177
482
|
## API
|
|
178
483
|
|
|
179
484
|
The package exposes two public entry points:
|
|
180
485
|
|
|
181
|
-
- `@lorion-org/react` for runtime, contribution contracts, provider selection, and React context helpers
|
|
182
|
-
- `@lorion-org/react/vite` for capability discovery,
|
|
486
|
+
- `@lorion-org/react` for runtime, contribution contracts, provider selection, runtime config, and React context helpers
|
|
487
|
+
- `@lorion-org/react/vite` for capability discovery, runtime-config virtual modules, and TanStack-compatible route config
|
|
488
|
+
|
|
489
|
+
## Example apps
|
|
490
|
+
|
|
491
|
+
Two runnable examples (at the repo root under `examples/`) demonstrate the two
|
|
492
|
+
models. Both run with Lorion's `lorion-source` export condition so local
|
|
493
|
+
workspace imports resolve to `src` instead of stale `dist` output.
|
|
494
|
+
|
|
495
|
+
Model A, `examples/react-runtime`, mirrors the Nuxt example with a demo shop,
|
|
496
|
+
checkout providers, and a tech monitor (composition runtime and file-based
|
|
497
|
+
routing):
|
|
498
|
+
|
|
499
|
+
```sh
|
|
500
|
+
pnpm --filter @lorion-examples/react-runtime dev
|
|
501
|
+
```
|
|
183
502
|
|
|
184
|
-
|
|
503
|
+
It runs on `http://localhost:3200` with capabilities under
|
|
504
|
+
`examples/react-runtime/capabilities`. Select a different profile or provider with
|
|
505
|
+
`--capabilities=admin`, `--capabilities=web,payment-provider-invoice`, or
|
|
506
|
+
`LORION_CAPABILITIES="web payment-provider-invoice"`.
|
|
185
507
|
|
|
186
|
-
|
|
508
|
+
Model B, `examples/react-loader`, shows the capability-loader-only path: explicit
|
|
509
|
+
activation, a graph-only library, a base plus seed selection, provider selection,
|
|
510
|
+
and a small hand-written registry that consumes `virtual:capabilities` with no
|
|
511
|
+
LORION React runtime and no route config:
|
|
187
512
|
|
|
188
513
|
```sh
|
|
189
|
-
pnpm --filter @lorion-
|
|
514
|
+
pnpm --filter @lorion-examples/react-loader dev
|
|
190
515
|
```
|
|
191
516
|
|
|
192
|
-
|
|
517
|
+
It runs on `http://localhost:3201` with capabilities under
|
|
518
|
+
`examples/react-loader/capabilities`. The seed replaces the default selection, while
|
|
519
|
+
the base and providers resolve through the graph: switch the auth provider with
|
|
520
|
+
`--features=dashboard,auth-oidc`, or change the feature set with
|
|
521
|
+
`LORION_FEATURES="dashboard reports"`.
|
|
193
522
|
|
|
194
523
|
## Local Commands
|
|
195
524
|
|
package/dist/index.cjs
CHANGED
|
@@ -20,19 +20,62 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/index.ts
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
|
+
CapabilityRuntimeConfigProvider: () => CapabilityRuntimeConfigProvider,
|
|
23
24
|
CapabilityRuntimeProvider: () => CapabilityRuntimeProvider,
|
|
25
|
+
createCapabilityCompositionPolicy: () => import_descriptor_selection.descriptorSelectionPolicy,
|
|
24
26
|
createCapabilityRuntime: () => createCapabilityRuntime,
|
|
25
27
|
createContributionContract: () => createContributionContract,
|
|
28
|
+
defaultCapabilityRelationDescriptors: () => import_descriptor_selection.providerRelationDescriptors,
|
|
29
|
+
defaultCapabilityResolutionRelations: () => import_descriptor_selection.defaultResolutionRelations,
|
|
26
30
|
defineCapability: () => defineCapability,
|
|
27
31
|
defineContribution: () => defineContribution,
|
|
28
32
|
defineExtensionPoint: () => defineExtensionPoint,
|
|
29
33
|
getCapabilityProviderSelection: () => getCapabilityProviderSelection,
|
|
30
|
-
|
|
34
|
+
getCapabilityRuntimeConfig: () => getCapabilityRuntimeConfig,
|
|
35
|
+
getCapabilityRuntimeConfigScope: () => getCapabilityRuntimeConfigScope,
|
|
36
|
+
useCapabilityRuntime: () => useCapabilityRuntime,
|
|
37
|
+
useCapabilityRuntimeConfig: () => useCapabilityRuntimeConfig,
|
|
38
|
+
useCapabilityRuntimeConfigRoot: () => useCapabilityRuntimeConfigRoot,
|
|
39
|
+
useCapabilityRuntimeConfigScope: () => useCapabilityRuntimeConfigScope
|
|
31
40
|
});
|
|
32
41
|
module.exports = __toCommonJS(index_exports);
|
|
33
|
-
var
|
|
42
|
+
var import_react2 = require("react");
|
|
34
43
|
var import_composition_graph = require("@lorion-org/composition-graph");
|
|
35
44
|
var import_provider_selection = require("@lorion-org/provider-selection");
|
|
45
|
+
|
|
46
|
+
// src/relations.ts
|
|
47
|
+
var import_descriptor_selection = require("@lorion-org/descriptor-selection");
|
|
48
|
+
|
|
49
|
+
// src/runtime-config.ts
|
|
50
|
+
var import_react = require("react");
|
|
51
|
+
var emptyRuntimeConfig = Object.freeze({ public: Object.freeze({}) });
|
|
52
|
+
var CapabilityRuntimeConfigContext = (0, import_react.createContext)(emptyRuntimeConfig);
|
|
53
|
+
function CapabilityRuntimeConfigProvider({
|
|
54
|
+
children,
|
|
55
|
+
runtimeConfig
|
|
56
|
+
}) {
|
|
57
|
+
return (0, import_react.createElement)(CapabilityRuntimeConfigContext.Provider, { value: runtimeConfig }, children);
|
|
58
|
+
}
|
|
59
|
+
function useCapabilityRuntimeConfigScope(capabilityId) {
|
|
60
|
+
return getCapabilityRuntimeConfigScope(useCapabilityRuntimeConfigRoot(), capabilityId);
|
|
61
|
+
}
|
|
62
|
+
function useCapabilityRuntimeConfig(capabilityId) {
|
|
63
|
+
return getCapabilityRuntimeConfig(useCapabilityRuntimeConfigRoot(), capabilityId);
|
|
64
|
+
}
|
|
65
|
+
function useCapabilityRuntimeConfigRoot() {
|
|
66
|
+
return (0, import_react.useContext)(CapabilityRuntimeConfigContext);
|
|
67
|
+
}
|
|
68
|
+
function getCapabilityRuntimeConfigScope(runtimeConfig, capabilityId) {
|
|
69
|
+
const publicConfig = runtimeConfig.public[capabilityId];
|
|
70
|
+
return publicConfig && typeof publicConfig === "object" && !Array.isArray(publicConfig) ? publicConfig : {};
|
|
71
|
+
}
|
|
72
|
+
function getCapabilityRuntimeConfig(runtimeConfig, capabilityId) {
|
|
73
|
+
return {
|
|
74
|
+
public: getCapabilityRuntimeConfigScope(runtimeConfig, capabilityId)
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// src/index.ts
|
|
36
79
|
function defineExtensionPoint(id) {
|
|
37
80
|
return { id };
|
|
38
81
|
}
|
|
@@ -54,16 +97,25 @@ function getCapabilityProviderSelection(runtime, options = {}) {
|
|
|
54
97
|
items: descriptors,
|
|
55
98
|
getProviderPreferences: (descriptor) => descriptor.providerPreferences
|
|
56
99
|
});
|
|
57
|
-
const
|
|
100
|
+
const providerDefaults = (0, import_provider_selection.collectProviderDefaults)({
|
|
101
|
+
items: descriptors,
|
|
102
|
+
getDefaultFor: (descriptor) => descriptor.defaultFor,
|
|
103
|
+
getProviderId: (descriptor) => descriptor.id
|
|
104
|
+
});
|
|
105
|
+
const configuredProviders = options.configuredProviders ?? {};
|
|
106
|
+
const selectedProviders = options.selectedProviders ?? {};
|
|
107
|
+
const fallbackProviders = {
|
|
108
|
+
...providerDefaults,
|
|
58
109
|
...descriptorPreferences,
|
|
59
|
-
...options.
|
|
110
|
+
...options.fallbackProviders ?? {}
|
|
60
111
|
};
|
|
61
112
|
const resolution = (0, import_provider_selection.resolveItemProviderSelection)({
|
|
62
113
|
items: descriptors,
|
|
63
114
|
getCapabilityId: (descriptor) => descriptor.providesFor,
|
|
64
115
|
getProviderId: (descriptor) => descriptor.id,
|
|
65
116
|
configuredProviders,
|
|
66
|
-
|
|
117
|
+
fallbackProviders,
|
|
118
|
+
selectedProviders
|
|
67
119
|
});
|
|
68
120
|
return {
|
|
69
121
|
excludedProviderIds: resolution.excludedProviderIds,
|
|
@@ -93,15 +145,15 @@ function createCapabilityRuntime(capabilities) {
|
|
|
93
145
|
getContributions: (extensionPoint) => [...contributions.get(extensionPoint.id) ?? []]
|
|
94
146
|
};
|
|
95
147
|
}
|
|
96
|
-
var CapabilityRuntimeContext = (0,
|
|
148
|
+
var CapabilityRuntimeContext = (0, import_react2.createContext)(null);
|
|
97
149
|
function CapabilityRuntimeProvider({
|
|
98
150
|
children,
|
|
99
151
|
runtime
|
|
100
152
|
}) {
|
|
101
|
-
return (0,
|
|
153
|
+
return (0, import_react2.createElement)(CapabilityRuntimeContext.Provider, { value: runtime }, children);
|
|
102
154
|
}
|
|
103
155
|
function useCapabilityRuntime() {
|
|
104
|
-
const runtime = (0,
|
|
156
|
+
const runtime = (0, import_react2.useContext)(CapabilityRuntimeContext);
|
|
105
157
|
if (!runtime) {
|
|
106
158
|
throw new Error("useCapabilityRuntime must be used inside CapabilityRuntimeProvider.");
|
|
107
159
|
}
|
|
@@ -138,17 +190,27 @@ function collectContributions(capabilities) {
|
|
|
138
190
|
}
|
|
139
191
|
function createCapabilityCatalog(capabilities) {
|
|
140
192
|
return (0, import_composition_graph.createDescriptorCatalog)({
|
|
141
|
-
descriptors: capabilities.map((capability) => capability.manifest)
|
|
193
|
+
descriptors: capabilities.map((capability) => capability.manifest),
|
|
194
|
+
relationDescriptors: import_descriptor_selection.providerRelationDescriptors
|
|
142
195
|
});
|
|
143
196
|
}
|
|
144
197
|
// Annotate the CommonJS export names for ESM import in node:
|
|
145
198
|
0 && (module.exports = {
|
|
199
|
+
CapabilityRuntimeConfigProvider,
|
|
146
200
|
CapabilityRuntimeProvider,
|
|
201
|
+
createCapabilityCompositionPolicy,
|
|
147
202
|
createCapabilityRuntime,
|
|
148
203
|
createContributionContract,
|
|
204
|
+
defaultCapabilityRelationDescriptors,
|
|
205
|
+
defaultCapabilityResolutionRelations,
|
|
149
206
|
defineCapability,
|
|
150
207
|
defineContribution,
|
|
151
208
|
defineExtensionPoint,
|
|
152
209
|
getCapabilityProviderSelection,
|
|
153
|
-
|
|
210
|
+
getCapabilityRuntimeConfig,
|
|
211
|
+
getCapabilityRuntimeConfigScope,
|
|
212
|
+
useCapabilityRuntime,
|
|
213
|
+
useCapabilityRuntimeConfig,
|
|
214
|
+
useCapabilityRuntimeConfigRoot,
|
|
215
|
+
useCapabilityRuntimeConfigScope
|
|
154
216
|
});
|
package/dist/index.d.cts
CHANGED
|
@@ -1,10 +1,31 @@
|
|
|
1
1
|
import { ReactNode, ReactElement } from 'react';
|
|
2
2
|
import { Descriptor, DescriptorCatalog } from '@lorion-org/composition-graph';
|
|
3
3
|
import { ProviderPreferenceMap, ProviderSelectionResolution } from '@lorion-org/provider-selection';
|
|
4
|
+
import { RuntimeConfigSection, RuntimeConfigValidationPolicy } from '@lorion-org/runtime-config';
|
|
5
|
+
export { descriptorSelectionPolicy as createCapabilityCompositionPolicy, providerRelationDescriptors as defaultCapabilityRelationDescriptors, defaultResolutionRelations as defaultCapabilityResolutionRelations } from '@lorion-org/descriptor-selection';
|
|
6
|
+
|
|
7
|
+
type CapabilityRuntimeConfig = {
|
|
8
|
+
public: Record<string, RuntimeConfigSection>;
|
|
9
|
+
};
|
|
10
|
+
type CapabilityRuntimeConfigFragment<T extends RuntimeConfigSection = RuntimeConfigSection> = {
|
|
11
|
+
public: T;
|
|
12
|
+
};
|
|
13
|
+
type CapabilityRuntimeConfigProviderProps = {
|
|
14
|
+
children: ReactNode;
|
|
15
|
+
runtimeConfig: CapabilityRuntimeConfig;
|
|
16
|
+
};
|
|
17
|
+
declare function CapabilityRuntimeConfigProvider({ children, runtimeConfig, }: CapabilityRuntimeConfigProviderProps): ReactElement;
|
|
18
|
+
declare function useCapabilityRuntimeConfigScope<T extends RuntimeConfigSection = RuntimeConfigSection>(capabilityId: string): T;
|
|
19
|
+
declare function useCapabilityRuntimeConfig<T extends RuntimeConfigSection = RuntimeConfigSection>(capabilityId: string): CapabilityRuntimeConfigFragment<T>;
|
|
20
|
+
declare function useCapabilityRuntimeConfigRoot(): CapabilityRuntimeConfig;
|
|
21
|
+
declare function getCapabilityRuntimeConfigScope<T extends RuntimeConfigSection = RuntimeConfigSection>(runtimeConfig: CapabilityRuntimeConfig, capabilityId: string): T;
|
|
22
|
+
declare function getCapabilityRuntimeConfig<T extends RuntimeConfigSection = RuntimeConfigSection>(runtimeConfig: CapabilityRuntimeConfig, capabilityId: string): CapabilityRuntimeConfigFragment<T>;
|
|
4
23
|
|
|
5
24
|
type CapabilityManifest = Descriptor & {
|
|
25
|
+
defaultFor?: string | string[];
|
|
6
26
|
description?: string;
|
|
7
27
|
providerPreferences?: ProviderPreferenceMap;
|
|
28
|
+
runtimeConfig?: RuntimeConfigValidationPolicy;
|
|
8
29
|
};
|
|
9
30
|
type ExtensionPoint<T> = {
|
|
10
31
|
id: string;
|
|
@@ -36,6 +57,7 @@ declare function createContributionContract<T>(id: string): ContributionContract
|
|
|
36
57
|
type CapabilityProviderSelectionOptions = {
|
|
37
58
|
configuredProviders?: ProviderPreferenceMap;
|
|
38
59
|
fallbackProviders?: ProviderPreferenceMap;
|
|
60
|
+
selectedProviders?: ProviderPreferenceMap;
|
|
39
61
|
};
|
|
40
62
|
declare function getCapabilityProviderSelection(runtime: CapabilityRuntime, options?: CapabilityProviderSelectionOptions): ProviderSelectionResolution;
|
|
41
63
|
declare function defineCapability(capability: RuntimeCapability): RuntimeCapability;
|
|
@@ -47,4 +69,4 @@ type CapabilityRuntimeProviderProps = {
|
|
|
47
69
|
declare function CapabilityRuntimeProvider({ children, runtime, }: CapabilityRuntimeProviderProps): ReactElement;
|
|
48
70
|
declare function useCapabilityRuntime(): CapabilityRuntime;
|
|
49
71
|
|
|
50
|
-
export { type CapabilityContribution, type CapabilityManifest, type CapabilityProviderSelectionOptions, type CapabilityRuntime, CapabilityRuntimeProvider, type CapabilityRuntimeProviderProps, type ContributionContract, type ExtensionPoint, type RuntimeCapability, createCapabilityRuntime, createContributionContract, defineCapability, defineContribution, defineExtensionPoint, getCapabilityProviderSelection, useCapabilityRuntime };
|
|
72
|
+
export { type CapabilityContribution, type CapabilityManifest, type CapabilityProviderSelectionOptions, type CapabilityRuntime, type CapabilityRuntimeConfig, type CapabilityRuntimeConfigFragment, CapabilityRuntimeConfigProvider, type CapabilityRuntimeConfigProviderProps, CapabilityRuntimeProvider, type CapabilityRuntimeProviderProps, type ContributionContract, type ExtensionPoint, type RuntimeCapability, createCapabilityRuntime, createContributionContract, defineCapability, defineContribution, defineExtensionPoint, getCapabilityProviderSelection, getCapabilityRuntimeConfig, getCapabilityRuntimeConfigScope, useCapabilityRuntime, useCapabilityRuntimeConfig, useCapabilityRuntimeConfigRoot, useCapabilityRuntimeConfigScope };
|