@lorion-org/nuxt 1.0.0-beta.1 → 1.0.0-beta.2

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 CHANGED
@@ -19,6 +19,9 @@ variants, optional providers, or profile-based feature sets.
19
19
  pnpm add @lorion-org/nuxt
20
20
  ```
21
21
 
22
+ Host configs that import selection helpers from `@lorion-org/composition-graph`
23
+ should declare that package directly too.
24
+
22
25
  ## What it is
23
26
 
24
27
  - a Nuxt 4 adapter for LORION layer orchestration
@@ -122,7 +125,7 @@ test/
122
125
  - `src/extensions.ts` contains descriptor discovery, selection, bootstrap, and extension-owned runtime config.
123
126
  - `src/runtime-config.ts` contains universal runtime-config adapter helpers.
124
127
  - `src/runtime-config-node.ts` contains Node-only source loading helpers.
125
- - The published package exports only the root Nuxt module. Runtime-config composables are generated and auto-imported by the module.
128
+ - The published package exports the root Nuxt module, runtime-config subpaths, the descriptor schema, and runtime-safe extension helpers under `@lorion-org/nuxt/extensions`. Runtime-config composables are generated and auto-imported by the module.
126
129
  - `examples/` contains Nuxt-focused config and server-route snippets.
127
130
  - `playground/` is a runnable Nuxt app for manual module development.
128
131
  - `test/fixtures/` contains Nuxt applications used by end-to-end tests, and `test/unit/` contains package unit tests.
@@ -182,16 +185,23 @@ config object and public values below `runtimeConfig.public`. Set
182
185
  `privateOutput: 'section'` when the target runtime should keep private values
183
186
  below `runtimeConfig.private`.
184
187
 
185
- The module also auto-imports runtime-config composables unless
186
- `runtimeConfig.imports` is `false`.
188
+ The module also auto-imports runtime-config composables when
189
+ `runtimeConfig.imports` is `true`, or when it is omitted and the host Nuxt app
190
+ keeps import scanning enabled. Hosts that set `imports.scan: false` can import
191
+ the generated composables explicitly instead:
187
192
 
188
193
  ```ts
194
+ import { usePublicRuntimeConfigScope } from '#build/lorion/runtime-config-composables';
195
+
189
196
  const checkout = usePublicRuntimeConfigScope('checkout');
190
197
 
191
198
  checkout.successPath;
192
199
  // => '/orders/confirmed'
193
200
  ```
194
201
 
202
+ Nitro server plugins can import from
203
+ `#internal/lorion-runtime-config-composables.mjs`.
204
+
195
205
  Configured module options such as `contextOutputKey` and `privateOutput` are
196
206
  used by these composables automatically.
197
207
 
@@ -296,9 +306,26 @@ export default defineNuxtConfig({
296
306
  });
297
307
  ```
298
308
 
299
- Applications that want CLI or env driven selection should normalize those
300
- inputs locally and pass the resulting seed ids through `options.selected`.
301
- The LORION bootstrap only receives canonical selection ids and resolves the graph.
309
+ Applications that want CLI or env driven selection can use the shared
310
+ capability seed directly. By default the Nuxt bootstrap reads `--capabilities`,
311
+ `npm_config_capabilities`, and `LORION_CAPABILITIES` before falling back to
312
+ `defaultSelection`.
313
+
314
+ ```ts
315
+ const extensionBootstrap = createNuxtExtensionBootstrap({
316
+ rootDir: __dirname,
317
+ options: {
318
+ defaultSelection: 'default',
319
+ },
320
+ });
321
+ ```
322
+
323
+ No `selectionSeed.key` option is required for the default capability seed. Pass
324
+ `selectionSeed` only when the host needs to override the seed names, inject
325
+ custom `argv`/`env` for tests, or set `selectionSeed: false` to disable CLI/env
326
+ lookup.
327
+
328
+ The LORION bootstrap receives canonical selection ids and resolves the graph.
302
329
 
303
330
  ## Provider Selection
304
331
 
@@ -308,25 +335,38 @@ Provider extensions can declare the capability they implement:
308
335
  {
309
336
  "id": "payment-provider-stripe",
310
337
  "version": "1.0.0",
311
- "providesFor": "payment-checkout"
338
+ "providesFor": "checkout",
339
+ "defaultFor": "checkout"
312
340
  }
313
341
  ```
314
342
 
343
+ `providesFor` and `defaultFor` both accept a string or string array. Use
344
+ `defaultFor` when the provider package owns the normal/default provider choice.
345
+ If a descriptor exists for that capability, the Nuxt bootstrap also treats
346
+ `defaultFor` as a composition relation from the capability to the provider.
347
+
315
348
  The module writes a public `providerSelection` object with selected providers,
316
- candidates, excluded providers, configured providers, and mismatches. Profiles
317
- can declare provider preferences in descriptor metadata:
349
+ candidates, excluded providers, configured providers, fallback providers, and
350
+ mismatches. Profiles can declare provider preferences in descriptor metadata
351
+ when the profile owns the default choice:
318
352
 
319
353
  ```json
320
354
  {
321
355
  "id": "checkout-profile",
322
356
  "version": "1.0.0",
323
357
  "providerPreferences": {
324
- "payment-checkout": "payment-provider-invoice"
358
+ "checkout": "payment-provider-invoice"
325
359
  }
326
360
  }
327
361
  ```
328
362
 
329
- Module options can still override the selected provider when a host app needs a
363
+ If a provider descriptor is explicitly selected through the normal selection
364
+ seed, that provider wins for its capability over descriptor preferences and
365
+ `defaultFor` relations. This affects composition resolution too: a losing
366
+ provider is not activated only because it declared `defaultFor`, unless another
367
+ hard dependency still pulls it into the graph.
368
+
369
+ Module options override the selected provider when a host app needs a
330
370
  deployment-specific choice:
331
371
 
332
372
  ```ts
@@ -339,7 +379,7 @@ export default defineNuxtConfig({
339
379
  extensionBootstrap,
340
380
  providers: {
341
381
  configuredProviders: {
342
- 'payment-checkout': 'payment-provider-invoice',
382
+ checkout: 'payment-provider-invoice',
343
383
  },
344
384
  },
345
385
  },
@@ -348,6 +388,10 @@ export default defineNuxtConfig({
348
388
  });
349
389
  ```
350
390
 
391
+ Hosts that resolve provider choices outside the extension bootstrap can pass
392
+ `providers.selectedProviders`; `providers.configuredProviders` remains the
393
+ higher-priority deployment override.
394
+
351
395
  ## Runtime Config
352
396
 
353
397
  Runtime-config projection does not require extension discovery. It can be used
@@ -432,7 +476,15 @@ Run the local playground from this package:
432
476
  pnpm dev:playground
433
477
  ```
434
478
 
435
- Select a playground composition by passing `extensions.selected` in Nuxt config:
479
+ The playground scripts run with Lorion's `lorion-source` export condition so
480
+ local workspace package imports resolve to `src` instead of stale `dist` output.
481
+
482
+ Select a playground composition through the seed CLI or environment:
483
+
484
+ ```shell
485
+ pnpm dev:playground -- --capabilities=web,payment-provider-invoice
486
+ LORION_CAPABILITIES="web payment-provider-invoice" pnpm dev:playground
487
+ ```
436
488
 
437
489
  The playground uses the module with no manual extension list in `nuxt.config.ts`.
438
490
  It configures only the presentation-specific descriptor paths, loads runtime
@@ -443,23 +495,23 @@ The playground intentionally overrides the default extension root to make the
443
495
  demo concept visible:
444
496
 
445
497
  ```ts
446
- import LorionNuxtModule from '../src/module';
498
+ import LorionNuxtModule, {
499
+ createNuxtExtensionBootstrap,
500
+ createNuxtExtensionLayerPaths,
501
+ } from '@lorion-org/nuxt';
447
502
 
448
- export default defineNuxtConfig({
449
- modules: [LorionNuxtModule],
450
- lorion: {
451
- extensions: {
452
- defaultSelection: 'default',
453
- descriptorPaths: ['layer-extensions/*/extension.json'],
454
- selected: 'default',
455
- },
456
- providers: {
457
- configuredProviders: {
458
- 'payment-checkout': 'payment-provider-stripe',
459
- },
460
- },
503
+ const extensionBootstrap = createNuxtExtensionBootstrap({
504
+ rootDir: __dirname,
505
+ options: {
506
+ defaultSelection: 'default',
507
+ descriptorPaths: ['layer-extensions/*/extension.json'],
461
508
  },
462
509
  });
510
+
511
+ export default defineNuxtConfig({
512
+ extends: createNuxtExtensionLayerPaths(extensionBootstrap),
513
+ modules: [[LorionNuxtModule, { extensionBootstrap, logging: true }]],
514
+ });
463
515
  ```
464
516
 
465
517
  The playground shape is:
@@ -491,17 +543,19 @@ routes. The `admin` layer extension provides the admin home route at
491
543
  `/` for admin profiles. The technical integration monitor lives at `/tech`.
492
544
 
493
545
  The default profile points to a neutral `web` profile. It starts the shop home
494
- with both payment-provider extensions mounted as candidates. The playground
495
- config selects Stripe through `lorion.providers.configuredProviders`, and
496
- `@lorion-org/provider-selection` publishes the selected provider. `admin` starts
497
- the admin home without loading the shop or payment-provider extensions.
546
+ with Stripe as the checkout provider because the Stripe provider descriptor
547
+ declares `defaultFor: "checkout"`. Selecting `web payment-provider-invoice`
548
+ overrides that default and leaves Stripe out of the resolved graph. `admin`
549
+ starts the admin home without loading the shop or payment-provider extensions.
498
550
 
499
- To run variants side by side, select the profile in playground config and pass
500
- different Nuxt ports:
551
+ To run variants side by side, select the seed on the CLI and pass different
552
+ Nuxt ports:
501
553
 
502
554
  ```shell
503
555
  pnpm dev:playground -- --port 3037
504
556
  pnpm dev:playground -- --port 3039
557
+ pnpm dev:playground -- --capabilities=admin --port 3041
558
+ pnpm dev:playground -- --capabilities=web,payment-provider-invoice --port 3043
505
559
  ```
506
560
 
507
561
  Each extension contributes only the Nuxt layer content it needs. The module
@@ -509,9 +563,10 @@ registers selected extensions as Nuxt layers; the playground does not list them
509
563
  in `nuxt.config.ts`.
510
564
  Provider extensions contribute checkout pages, register a small checkout
511
565
  provider implementation through the payments layer interface, and expose server
512
- routes. They declare `providesFor: "payment-checkout"`, while the Nuxt module
513
- options provide the selected preference. Runtime config for checkout, payments,
514
- and providers is loaded from
566
+ routes. They declare `providesFor: "checkout"`; Stripe additionally
567
+ declares `defaultFor: "checkout"` so the playground demonstrates the
568
+ provider-owned default pattern. Runtime config for checkout, payments, and
569
+ providers is loaded from
515
570
  `.runtimeconfig/runtime-config/<scope>/runtime.config.json`.
516
571
 
517
572
  The module also exposes a public `extensionSelection` runtime-config object with
@@ -21,8 +21,19 @@ var extension_descriptor_schema_default = {
21
21
  },
22
22
  version: { $ref: "#/$defs/semver" },
23
23
  providesFor: {
24
- type: "string",
25
- minLength: 1
24
+ oneOf: [
25
+ {
26
+ type: "string",
27
+ minLength: 1
28
+ },
29
+ {
30
+ type: "array",
31
+ items: {
32
+ type: "string",
33
+ minLength: 1
34
+ }
35
+ }
36
+ ]
26
37
  },
27
38
  capabilities: {
28
39
  type: "array",
@@ -34,6 +45,21 @@ var extension_descriptor_schema_default = {
34
45
  dependencies: { $ref: "#/$defs/dependencyMap" },
35
46
  disabled: { type: "boolean" },
36
47
  location: { type: "string" },
48
+ defaultFor: {
49
+ oneOf: [
50
+ {
51
+ type: "string",
52
+ minLength: 1
53
+ },
54
+ {
55
+ type: "array",
56
+ items: {
57
+ type: "string",
58
+ minLength: 1
59
+ }
60
+ }
61
+ ]
62
+ },
37
63
  providerPreferences: {
38
64
  type: "object",
39
65
  additionalProperties: {
@@ -45,6 +71,16 @@ var extension_descriptor_schema_default = {
45
71
  type: "object",
46
72
  additionalProperties: true
47
73
  },
74
+ runtimeConfig: {
75
+ type: "object",
76
+ properties: {
77
+ validation: {
78
+ type: "string",
79
+ enum: ["none", "optional", "startup", "onUse"]
80
+ }
81
+ },
82
+ additionalProperties: false
83
+ },
48
84
  bundles: {
49
85
  type: "array",
50
86
  items: { $ref: "#/$defs/extension" }
@@ -1,8 +1,8 @@
1
- import { Descriptor, RelationDescriptor, DescriptorCatalog } from '@lorion-org/composition-graph';
1
+ import { Descriptor, RelationDescriptor, DescriptorSelectionSeedInput, DescriptorCatalog } from '@lorion-org/composition-graph';
2
2
  import { ProviderPreferenceMap, ProviderSelection } from '@lorion-org/provider-selection';
3
- import { JsonSchemaObject } from '@lorion-org/descriptor-discovery';
4
- import { RuntimeConfigSection, ProjectSectionedRuntimeConfigOptions, RuntimeConfigFragmentMap, NamedRuntimeConfigFragment, RuntimeConfigFragment, SectionedRuntimeConfig } from '@lorion-org/runtime-config';
3
+ import { RuntimeConfigSection, ProjectSectionedRuntimeConfigOptions, RuntimeConfigFragmentMap, NamedRuntimeConfigFragment, RuntimeConfigFragment, SectionedRuntimeConfig, RuntimeConfigValidationPolicy } from '@lorion-org/runtime-config';
5
4
  import { RuntimeConfigPathPatternSource, ValidateRuntimeConfigPatternSourceScopesOptions } from '@lorion-org/runtime-config-node';
5
+ import { JsonSchemaObject } from './descriptor-schema.js';
6
6
 
7
7
  type RuntimeConfigNuxtFragmentInput = RuntimeConfigFragment & Record<string, unknown>;
8
8
  type RuntimeConfigNuxtFragments = RuntimeConfigFragmentMap | NamedRuntimeConfigFragment[] | Record<string, RuntimeConfigNuxtFragmentInput>;
@@ -36,10 +36,13 @@ type NuxtRuntimeConfigValidationOptions = Pick<ValidateRuntimeConfigPatternSourc
36
36
  type NuxtProviderSelectionModuleOptions = {
37
37
  configuredProviders?: ProviderPreferenceMap;
38
38
  enabled?: boolean;
39
+ fallbackProviders?: ProviderPreferenceMap;
40
+ selectedProviders?: ProviderPreferenceMap;
39
41
  };
40
42
  type NuxtProviderSelectionRuntimeConfig = {
41
43
  configuredProviders: ProviderPreferenceMap;
42
44
  excludedProviderIds: string[];
45
+ fallbackProviders: ProviderPreferenceMap;
43
46
  mismatches: Array<{
44
47
  capabilityId: string;
45
48
  configuredProviderId: string;
@@ -64,6 +67,7 @@ type NuxtBaseExtensionSelectionInput = {
64
67
  selectedExtensions: string[];
65
68
  };
66
69
  type NuxtBaseExtensionSelection = string | string[] | ((input: NuxtBaseExtensionSelectionInput) => string[]);
70
+ type NuxtExtensionSelectionSeedOptions = Omit<DescriptorSelectionSeedInput, 'defaultValue'>;
67
71
  type NuxtExtensionModuleOptions = {
68
72
  baseExtensions?: NuxtBaseExtensionSelection;
69
73
  defaultSelection?: string | string[];
@@ -72,6 +76,7 @@ type NuxtExtensionModuleOptions = {
72
76
  enabled?: boolean;
73
77
  relationDescriptors?: RelationDescriptor[];
74
78
  selected?: string | string[];
79
+ selectionSeed?: false | NuxtExtensionSelectionSeedOptions;
75
80
  };
76
81
  type LorionNuxtModuleOptions = {
77
82
  extensionBootstrap?: NuxtExtensionBootstrap;
@@ -89,8 +94,10 @@ declare module 'nuxt/schema' {
89
94
  }
90
95
 
91
96
  type NuxtExtensionDescriptor = Descriptor & {
97
+ defaultFor?: string | string[];
92
98
  providerPreferences?: ProviderPreferenceMap;
93
99
  publicRuntimeConfig?: NuxtRuntimeConfig['public'];
100
+ runtimeConfig?: RuntimeConfigValidationPolicy;
94
101
  };
95
102
  type NuxtExtensionEntry = {
96
103
  appDir?: string;
@@ -117,6 +124,19 @@ declare function resolveExtensionSelection(input?: {
117
124
  defaultSelection?: string | string[];
118
125
  selected?: string | string[];
119
126
  }): string[];
127
+ declare function discoverNuxtExtensionEntries(input: {
128
+ projectRootDir: string;
129
+ options: NuxtExtensionModuleOptions;
130
+ }): NuxtExtensionEntry[];
131
+ declare function createNuxtExtensionCatalog(input: {
132
+ entries: NuxtExtensionEntry[];
133
+ relationDescriptors?: RelationDescriptor[];
134
+ }): DescriptorCatalog;
135
+ declare function createNuxtExtensionEntryMap(entries: NuxtExtensionEntry[]): Map<string, NuxtExtensionEntry>;
136
+ declare function createNuxtSelectedProviderPreferences(input: {
137
+ entries: NuxtExtensionEntry[];
138
+ selectedExtensions: string[];
139
+ }): ProviderPreferenceMap;
120
140
  declare function createNuxtExtensionBootstrap(input: {
121
141
  options?: NuxtExtensionModuleOptions;
122
142
  rootDir: string;
@@ -124,4 +144,4 @@ declare function createNuxtExtensionBootstrap(input: {
124
144
  declare function createNuxtExtensionLayerPaths(bootstrap: NuxtExtensionBootstrap): string[];
125
145
  declare function createNuxtProviderSelectionRuntimeConfig(extensions: NuxtExtensionEntry[], options?: NuxtProviderSelectionOptions): NuxtRuntimeConfig;
126
146
 
127
- export { type CreateNuxtRuntimeConfigOptions as C, type LorionNuxtModuleOptions as L, type NuxtExtensionBootstrap as N, type RuntimeConfigNuxtModuleOptions as R, type NuxtRuntimeConfig as a, type NuxtExtensionBootstrapLogEvent as b, type NuxtBaseExtensionSelection as c, type NuxtBaseExtensionSelectionInput as d, type NuxtExtensionBootstrapReporter as e, type NuxtExtensionDescriptor as f, type NuxtExtensionEntry as g, type NuxtExtensionModuleOptions as h, type NuxtProviderSelectionModuleOptions as i, type NuxtProviderSelectionRuntimeConfig as j, createNuxtExtensionBootstrap as k, createNuxtExtensionLayerPaths as l, createNuxtProviderSelectionRuntimeConfig as m, type RuntimeConfigNuxtSourceOptions as n, type NuxtRuntimeConfigInput as o, type ReadNuxtRuntimeConfigOptions as p, type NuxtExtensionSelection as q, resolveExtensionSelection as r, type RuntimeConfigNuxtFragments as s, type NuxtExtensionSelectionRuntimeConfig as t, type NuxtPrivateRuntimeConfigMode as u };
147
+ export { type CreateNuxtRuntimeConfigOptions as C, type LorionNuxtModuleOptions as L, type NuxtExtensionBootstrap as N, type RuntimeConfigNuxtModuleOptions as R, type NuxtRuntimeConfig as a, type NuxtExtensionBootstrapLogEvent as b, type NuxtBaseExtensionSelection as c, type NuxtBaseExtensionSelectionInput as d, type NuxtExtensionBootstrapReporter as e, type NuxtExtensionDescriptor as f, type NuxtExtensionEntry as g, type NuxtExtensionModuleOptions as h, type NuxtExtensionSelectionSeedOptions as i, type NuxtProviderSelectionModuleOptions as j, type NuxtProviderSelectionRuntimeConfig as k, createNuxtExtensionBootstrap as l, createNuxtExtensionCatalog as m, createNuxtExtensionEntryMap as n, createNuxtExtensionLayerPaths as o, createNuxtProviderSelectionRuntimeConfig as p, discoverNuxtExtensionEntries as q, resolveExtensionSelection as r, type RuntimeConfigNuxtSourceOptions as s, type NuxtRuntimeConfigInput as t, type ReadNuxtRuntimeConfigOptions as u, type NuxtExtensionSelection as v, type RuntimeConfigNuxtFragments as w, type NuxtExtensionSelectionRuntimeConfig as x, type NuxtPrivateRuntimeConfigMode as y, createNuxtSelectedProviderPreferences as z };
@@ -0,0 +1,6 @@
1
+ import '@lorion-org/composition-graph';
2
+ import '@lorion-org/provider-selection';
3
+ import '@lorion-org/runtime-config';
4
+ export { L as LorionNuxtModuleOptions, N as NuxtExtensionBootstrap, f as NuxtExtensionDescriptor, g as NuxtExtensionEntry, h as NuxtExtensionModuleOptions, i as NuxtExtensionSelectionSeedOptions, R as RuntimeConfigNuxtModuleOptions, l as createNuxtExtensionBootstrap, m as createNuxtExtensionCatalog, n as createNuxtExtensionEntryMap, o as createNuxtExtensionLayerPaths, p as createNuxtProviderSelectionRuntimeConfig, z as createNuxtSelectedProviderPreferences, q as discoverNuxtExtensionEntries, r as resolveExtensionSelection } from './extensions-DlFRz22Q.js';
5
+ import '@lorion-org/runtime-config-node';
6
+ import './descriptor-schema.js';