@lorion-org/react 1.0.0-beta.2 → 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/dist/index.js CHANGED
@@ -1,11 +1,5 @@
1
- import {
2
- createCapabilityCompositionPolicy,
3
- defaultCapabilityRelationDescriptors,
4
- defaultCapabilityResolutionRelations
5
- } from "./chunk-5FUI4JPB.js";
6
-
7
1
  // src/index.ts
8
- import { createContext, createElement, useContext } from "react";
2
+ import { createContext as createContext2, createElement as createElement2, useContext as useContext2 } from "react";
9
3
  import {
10
4
  assertKnownDescriptorIds,
11
5
  createDescriptorCatalog
@@ -15,6 +9,44 @@ import {
15
9
  collectProviderPreferences,
16
10
  resolveItemProviderSelection
17
11
  } from "@lorion-org/provider-selection";
12
+
13
+ // src/relations.ts
14
+ import {
15
+ providerRelationDescriptors,
16
+ descriptorSelectionPolicy,
17
+ defaultResolutionRelations
18
+ } from "@lorion-org/descriptor-selection";
19
+
20
+ // src/runtime-config.ts
21
+ import { createContext, createElement, useContext } from "react";
22
+ var emptyRuntimeConfig = Object.freeze({ public: Object.freeze({}) });
23
+ var CapabilityRuntimeConfigContext = createContext(emptyRuntimeConfig);
24
+ function CapabilityRuntimeConfigProvider({
25
+ children,
26
+ runtimeConfig
27
+ }) {
28
+ return createElement(CapabilityRuntimeConfigContext.Provider, { value: runtimeConfig }, children);
29
+ }
30
+ function useCapabilityRuntimeConfigScope(capabilityId) {
31
+ return getCapabilityRuntimeConfigScope(useCapabilityRuntimeConfigRoot(), capabilityId);
32
+ }
33
+ function useCapabilityRuntimeConfig(capabilityId) {
34
+ return getCapabilityRuntimeConfig(useCapabilityRuntimeConfigRoot(), capabilityId);
35
+ }
36
+ function useCapabilityRuntimeConfigRoot() {
37
+ return useContext(CapabilityRuntimeConfigContext);
38
+ }
39
+ function getCapabilityRuntimeConfigScope(runtimeConfig, capabilityId) {
40
+ const publicConfig = runtimeConfig.public[capabilityId];
41
+ return publicConfig && typeof publicConfig === "object" && !Array.isArray(publicConfig) ? publicConfig : {};
42
+ }
43
+ function getCapabilityRuntimeConfig(runtimeConfig, capabilityId) {
44
+ return {
45
+ public: getCapabilityRuntimeConfigScope(runtimeConfig, capabilityId)
46
+ };
47
+ }
48
+
49
+ // src/index.ts
18
50
  function defineExtensionPoint(id) {
19
51
  return { id };
20
52
  }
@@ -84,15 +116,15 @@ function createCapabilityRuntime(capabilities) {
84
116
  getContributions: (extensionPoint) => [...contributions.get(extensionPoint.id) ?? []]
85
117
  };
86
118
  }
87
- var CapabilityRuntimeContext = createContext(null);
119
+ var CapabilityRuntimeContext = createContext2(null);
88
120
  function CapabilityRuntimeProvider({
89
121
  children,
90
122
  runtime
91
123
  }) {
92
- return createElement(CapabilityRuntimeContext.Provider, { value: runtime }, children);
124
+ return createElement2(CapabilityRuntimeContext.Provider, { value: runtime }, children);
93
125
  }
94
126
  function useCapabilityRuntime() {
95
- const runtime = useContext(CapabilityRuntimeContext);
127
+ const runtime = useContext2(CapabilityRuntimeContext);
96
128
  if (!runtime) {
97
129
  throw new Error("useCapabilityRuntime must be used inside CapabilityRuntimeProvider.");
98
130
  }
@@ -130,19 +162,25 @@ function collectContributions(capabilities) {
130
162
  function createCapabilityCatalog(capabilities) {
131
163
  return createDescriptorCatalog({
132
164
  descriptors: capabilities.map((capability) => capability.manifest),
133
- relationDescriptors: defaultCapabilityRelationDescriptors
165
+ relationDescriptors: providerRelationDescriptors
134
166
  });
135
167
  }
136
168
  export {
169
+ CapabilityRuntimeConfigProvider,
137
170
  CapabilityRuntimeProvider,
138
- createCapabilityCompositionPolicy,
171
+ descriptorSelectionPolicy as createCapabilityCompositionPolicy,
139
172
  createCapabilityRuntime,
140
173
  createContributionContract,
141
- defaultCapabilityRelationDescriptors,
142
- defaultCapabilityResolutionRelations,
174
+ providerRelationDescriptors as defaultCapabilityRelationDescriptors,
175
+ defaultResolutionRelations as defaultCapabilityResolutionRelations,
143
176
  defineCapability,
144
177
  defineContribution,
145
178
  defineExtensionPoint,
146
179
  getCapabilityProviderSelection,
147
- useCapabilityRuntime
180
+ getCapabilityRuntimeConfig,
181
+ getCapabilityRuntimeConfigScope,
182
+ useCapabilityRuntime,
183
+ useCapabilityRuntimeConfig,
184
+ useCapabilityRuntimeConfigRoot,
185
+ useCapabilityRuntimeConfigScope
148
186
  };
package/dist/vite.cjs CHANGED
@@ -32,58 +32,36 @@ var vite_exports = {};
32
32
  __export(vite_exports, {
33
33
  capabilityLoader: () => capabilityLoader,
34
34
  createCapabilityRouteConfig: () => createCapabilityRouteConfig,
35
+ createReactRuntimeConfig: () => createReactRuntimeConfig,
35
36
  discoverCapabilities: () => discoverCapabilities,
36
37
  discoverSelectedCapabilities: () => discoverSelectedCapabilities,
37
38
  lorionReact: () => lorionReact,
38
- renderCapabilityModule: () => renderCapabilityModule
39
+ renderCapabilityModule: () => renderCapabilityModule,
40
+ renderRuntimeConfigModule: () => renderRuntimeConfigModule,
41
+ renderServerRuntimeConfigModule: () => renderServerRuntimeConfigModule
39
42
  });
40
43
  module.exports = __toCommonJS(vite_exports);
41
44
  var import_node_fs = require("fs");
42
45
  var import_node_path = require("path");
43
46
  var import_node_process = __toESM(require("process"), 1);
44
- var import_composition_graph = require("@lorion-org/composition-graph");
47
+ var import_vite = require("vite");
45
48
  var import_descriptor_discovery = require("@lorion-org/descriptor-discovery");
46
- var import_provider_selection = require("@lorion-org/provider-selection");
47
-
48
- // src/relations.ts
49
- var defaultCapabilityResolutionRelations = [
50
- "dependencies",
51
- "defaultProviders",
52
- "providerPreferences"
53
- ];
54
- var defaultCapabilityRelationDescriptors = [
55
- {
56
- direction: "incoming",
57
- field: "defaultFor",
58
- id: "defaultProviders"
59
- },
60
- {
61
- field: "providerPreferences",
62
- id: "providerPreferences",
63
- targetMode: "values"
64
- }
65
- ];
66
- function createCapabilityCompositionPolicy(policy) {
67
- return {
68
- ...policy,
69
- inspectionRelationIds: policy?.inspectionRelationIds ?? [
70
- ...defaultCapabilityResolutionRelations
71
- ],
72
- provenanceRelationIds: policy?.provenanceRelationIds ?? [
73
- ...defaultCapabilityResolutionRelations
74
- ],
75
- resolutionRelationIds: policy?.resolutionRelationIds ?? [
76
- ...defaultCapabilityResolutionRelations
77
- ]
78
- };
79
- }
80
-
81
- // src/vite.ts
49
+ var import_descriptor_selection = require("@lorion-org/descriptor-selection");
50
+ var import_runtime_config = require("@lorion-org/runtime-config");
51
+ var import_runtime_config_node = require("@lorion-org/runtime-config-node");
52
+ var import_surface_activation = require("@lorion-org/surface-activation");
82
53
  var virtualModuleId = "virtual:capabilities";
83
54
  var resolvedVirtualModuleId = `\0${virtualModuleId}`;
55
+ var runtimeConfigModuleId = "virtual:capability-runtime-config";
56
+ var resolvedRuntimeConfigModuleId = `\0${runtimeConfigModuleId}`;
57
+ var serverRuntimeConfigModuleId = "virtual:capability-runtime-config/server";
58
+ var resolvedServerRuntimeConfigModuleId = `\0${serverRuntimeConfigModuleId}`;
59
+ var defaultRuntimeConfigFileName = "capability.runtime.json";
60
+ var defaultRuntimeConfigSchemaFileName = "capability.schema.json";
84
61
  function capabilityLoader(options = {}) {
85
62
  let config;
86
63
  let capabilities = [];
64
+ let runtimeConfig = { private: {}, public: {} };
87
65
  return {
88
66
  name: "lorion-react-capability-loader",
89
67
  enforce: "pre",
@@ -93,107 +71,110 @@ function capabilityLoader(options = {}) {
93
71
  resolveWorkspaceRoot(config.root, options),
94
72
  options
95
73
  );
74
+ runtimeConfig = createReactRuntimeConfig(
75
+ capabilities,
76
+ resolveWorkspaceRoot(config.root, options),
77
+ options.runtimeConfig,
78
+ config
79
+ );
96
80
  },
97
81
  resolveId(id) {
98
82
  if (id === virtualModuleId) return resolvedVirtualModuleId;
83
+ if (id === runtimeConfigModuleId) return resolvedRuntimeConfigModuleId;
84
+ if (id === serverRuntimeConfigModuleId) return resolvedServerRuntimeConfigModuleId;
99
85
  return capabilities.find((capability) => capability.importSpecifier === id)?.entryFile;
100
86
  },
101
- load(id) {
87
+ load(id, loadOptions) {
88
+ if (id === resolvedRuntimeConfigModuleId) return renderRuntimeConfigModule(runtimeConfig);
89
+ if (id === resolvedServerRuntimeConfigModuleId) {
90
+ if (!loadOptions?.ssr) {
91
+ throw new Error(
92
+ "virtual:capability-runtime-config/server may only be imported from SSR/server code."
93
+ );
94
+ }
95
+ return renderServerRuntimeConfigModule(runtimeConfig);
96
+ }
102
97
  if (id !== resolvedVirtualModuleId) return null;
103
98
  return renderCapabilityModule(capabilities, resolveSelectionSeed(options));
104
99
  }
105
100
  };
106
101
  }
102
+ function createReactRuntimeConfig(capabilities, workspaceRoot, options = {}, viteConfig = {}) {
103
+ const normalizedOptions = normalizeRuntimeConfigOptions(options);
104
+ if (!normalizedOptions.enabled) return { private: {}, public: {} };
105
+ const runtimeEnv = resolveRuntimeConfigEnv(viteConfig, normalizedOptions.env ?? {});
106
+ const sourceFragments = normalizedOptions.source ? (0, import_runtime_config_node.loadRuntimeConfigSourceTree)(
107
+ resolveRuntimeConfigPatternSource(workspaceRoot, normalizedOptions, runtimeEnv)
108
+ ) : /* @__PURE__ */ new Map();
109
+ const schemaEntries = readRuntimeConfigSchemas(capabilities, normalizedOptions.schemaFileName);
110
+ const envFragments = normalizedOptions.env === false ? /* @__PURE__ */ new Map() : createRuntimeConfigEnvFragments(
111
+ createRuntimeConfigEnvFragmentOptions(
112
+ capabilities,
113
+ schemaEntries.schemas,
114
+ runtimeEnv,
115
+ normalizedOptions.env
116
+ )
117
+ );
118
+ const fragments = mergeRuntimeConfigFragmentMaps(sourceFragments, envFragments);
119
+ validateReactRuntimeConfig(capabilities, fragments, schemaEntries, normalizedOptions.validation);
120
+ const projected = (0, import_runtime_config.projectRuntimeConfigNamespaces)(fragments, {
121
+ namespaceStrategy: "nested",
122
+ scopeIds: capabilities.map((capability) => capability.id)
123
+ });
124
+ const { public: publicConfig, ...privateConfig } = projected;
125
+ return {
126
+ public: publicConfig,
127
+ private: privateConfig
128
+ };
129
+ }
107
130
  function lorionReact(options) {
108
131
  return {
109
132
  capabilityLoader: capabilityLoader(options),
110
133
  routeConfig: createCapabilityRouteConfig(options)
111
134
  };
112
135
  }
136
+ function toResolveActivation(options) {
137
+ if (options.surface) {
138
+ if (options.activation) {
139
+ throw new Error("capabilityLoader: pass either `surface` or `activation`, not both.");
140
+ }
141
+ const { name, resolver } = options.surface;
142
+ return ({ capabilityDir, descriptor }) => resolver(name, { directory: capabilityDir, id: descriptor.id });
143
+ }
144
+ return options.activation;
145
+ }
113
146
  function discoverCapabilities(workspaceRoot, options = {}) {
114
147
  const capabilitiesRoot = (0, import_node_path.resolve)(workspaceRoot, options.capabilitiesDir ?? "capabilities");
115
148
  if (!(0, import_node_fs.existsSync)(capabilitiesRoot)) {
116
149
  throw new Error(`Capabilities directory not found: ${capabilitiesRoot}`);
117
150
  }
118
- return discoverCapabilityDescriptors(workspaceRoot, options).map(discoverCapability).sort((left, right) => left.id.localeCompare(right.id));
151
+ const resolveActivation = toResolveActivation(options);
152
+ return discoverCapabilityDescriptors(workspaceRoot, options).map((entry) => discoverCapability(entry, resolveActivation)).sort((left, right) => left.id.localeCompare(right.id));
119
153
  }
120
154
  function discoverSelectedCapabilities(workspaceRoot, options = {}) {
121
155
  return selectCapabilities(discoverCapabilities(workspaceRoot, options), options);
122
156
  }
123
157
  function selectCapabilities(capabilities, options = {}) {
124
- const enabledCapabilities = capabilities.filter((capability) => capability.disabled !== true);
125
- const selected = resolveCapabilitySelectionSeed(options);
126
- if (!selected.length && !options.baseDescriptors?.length) {
127
- return [...enabledCapabilities];
128
- }
129
- const selectedProviders = (0, import_provider_selection.collectSelectedProviderPreferences)({
130
- items: enabledCapabilities,
131
- getCapabilityId: (capability) => capability.manifest.providesFor,
132
- getProviderId: (capability) => capability.id,
133
- selectedProviderIds: selected
134
- });
135
- const selectionCapabilities = createProviderSelectionAwareCapabilities(
136
- enabledCapabilities,
137
- selectedProviders
138
- );
139
- const catalog = (0, import_composition_graph.createDescriptorCatalog)({
140
- descriptors: selectionCapabilities.map((capability) => capability.manifest),
141
- relationDescriptors: [
142
- ...defaultCapabilityRelationDescriptors,
143
- ...options.relationDescriptors ?? []
144
- ]
145
- });
146
- const selection = (0, import_composition_graph.createCompositionSelection)({
147
- catalog,
148
- selected: [...selected],
149
- baseDescriptors: [...options.baseDescriptors ?? []],
150
- policy: createCapabilityCompositionPolicy(options.policy)
151
- });
152
- const selectedIds = new Set(selection.getResolved());
153
- return selectionCapabilities.filter((capability) => selectedIds.has(capability.id));
154
- }
155
- function createProviderSelectionAwareCapabilities(capabilities, selectedProviders) {
156
- if (!Object.keys(selectedProviders).length) return [...capabilities];
157
- return capabilities.map((capability) => {
158
- const manifest = { ...capability.manifest };
159
- const preferences = (0, import_provider_selection.resolveSelectedProviderRelationPreferences)({
160
- providerId: capability.id,
161
- defaultFor: manifest.defaultFor,
162
- providerPreferences: manifest.providerPreferences,
163
- selectedProviders
164
- });
165
- delete manifest.defaultFor;
166
- delete manifest.providerPreferences;
167
- return {
168
- ...capability,
169
- manifest: {
170
- ...manifest,
171
- ...preferences
172
- }
173
- };
158
+ return (0, import_descriptor_selection.selectDescriptors)({
159
+ items: capabilities,
160
+ getDescriptor: (capability) => capability.manifest,
161
+ withDescriptor: (capability, manifest) => ({ ...capability, manifest }),
162
+ seed: options,
163
+ ...options.relationDescriptors ? { relationDescriptors: options.relationDescriptors } : {},
164
+ ...options.policy ? { policy: options.policy } : {}
174
165
  });
175
166
  }
176
167
  function resolveSelectionSeed(options) {
177
- return resolveCapabilitySelectionSeed(options);
178
- }
179
- function resolveCapabilitySelectionSeed(options) {
180
- if (options.selected?.length) return [...options.selected];
181
- if (options.selectionSeed === false) return [...options.defaultSelection ?? []];
182
- const seedOptions = options.selectionSeed ?? {};
183
- const selected = (0, import_composition_graph.resolveDescriptorSelectionSeed)({
184
- argv: seedOptions.argv ?? import_node_process.default.argv,
185
- env: seedOptions.env ?? import_node_process.default.env,
186
- key: seedOptions.key ?? "capability",
187
- ...seedOptions.cliKeys ? { cliKeys: seedOptions.cliKeys } : {},
188
- ...seedOptions.envKeys ? { envKeys: seedOptions.envKeys } : {}
189
- });
190
- return selected.length ? selected : [...options.defaultSelection ?? []];
168
+ return (0, import_descriptor_selection.resolveDescriptorSelection)(options);
191
169
  }
192
170
  function renderCapabilityModule(capabilities, selected = []) {
193
- const imports = capabilities.map(
194
- (capability) => `import { capability as ${capability.variableName} } from '${capability.importSpecifier}'`
171
+ const activated = capabilities.filter(
172
+ (capability) => capability.exportName && capability.importSpecifier
173
+ );
174
+ const imports = activated.map(
175
+ (capability) => `import { ${capability.exportName} as ${capability.variableName} } from '${capability.importSpecifier}'`
195
176
  ).join("\n");
196
- const variables = capabilities.map((capability) => ` ${capability.variableName},`).join("\n");
177
+ const variables = activated.map((capability) => ` ${capability.variableName},`).join("\n");
197
178
  const capabilityIds = capabilities.map((capability) => capability.id);
198
179
  return `${imports}
199
180
 
@@ -206,6 +187,16 @@ ${variables}
206
187
  ]
207
188
  `;
208
189
  }
190
+ function renderRuntimeConfigModule(runtimeConfig) {
191
+ return `export const capabilityRuntimeConfig = ${JSON.stringify({ public: runtimeConfig.public })}
192
+
193
+ export const publicCapabilityRuntimeConfig = capabilityRuntimeConfig.public
194
+ `;
195
+ }
196
+ function renderServerRuntimeConfigModule(runtimeConfig) {
197
+ return `export const capabilityServerRuntimeConfig = ${JSON.stringify(runtimeConfig)}
198
+ `;
199
+ }
209
200
  function createCapabilityRouteConfig(options) {
210
201
  if (!options?.workspaceRoot) {
211
202
  throw new Error("createCapabilityRouteConfig requires a workspaceRoot option.");
@@ -244,7 +235,7 @@ function discoverCapabilityDescriptors(workspaceRoot, options) {
244
235
  }
245
236
  });
246
237
  }
247
- function discoverCapability(entry) {
238
+ function discoverCapability(entry, resolveActivation) {
248
239
  const capabilityDir = entry.cwd;
249
240
  const packagePath = (0, import_node_path.resolve)(capabilityDir, "package.json");
250
241
  if (!(0, import_node_fs.existsSync)(packagePath)) {
@@ -253,43 +244,236 @@ function discoverCapability(entry) {
253
244
  );
254
245
  }
255
246
  const packageJson = readJson(packagePath);
256
- const packageName = packageJson.name;
257
- if (typeof packageName !== "string") {
258
- throw new Error(`Capability package is missing "name": ${packagePath}`);
259
- }
260
- const activationEntry = resolveActivationEntry(capabilityDir, packageJson);
247
+ const packageName = (0, import_descriptor_discovery.requirePackageName)(packageJson, packagePath);
248
+ const activationEntry = resolveActivationEntry(
249
+ capabilityDir,
250
+ packageJson,
251
+ packageName,
252
+ entry.descriptor,
253
+ resolveActivation
254
+ );
261
255
  const routesDirectory = resolveRouteDirectory(capabilityDir);
262
256
  return {
257
+ capabilityDir,
263
258
  id: entry.descriptor.id,
264
259
  disabled: entry.descriptor.disabled === true,
265
- entryFile: activationEntry.entryFile,
266
- importSpecifier: activationEntry.importSpecifier,
267
260
  manifest: entry.descriptor,
268
261
  packageName,
262
+ ...activationEntry ? {
263
+ exportName: activationEntry.exportName,
264
+ importSpecifier: activationEntry.importSpecifier,
265
+ ...activationEntry.entryFile ? { entryFile: activationEntry.entryFile } : {}
266
+ } : {},
269
267
  ...routesDirectory ? { routesDirectory } : {},
270
268
  variableName: toVariableName(entry.descriptor.id)
271
269
  };
272
270
  }
273
- function resolveRouteDirectory(capabilityDir) {
274
- const routesDirectory = (0, import_node_path.resolve)(capabilityDir, "src", "routes");
275
- return (0, import_node_fs.existsSync)(routesDirectory) ? routesDirectory : void 0;
271
+ function normalizeRuntimeConfigOptions(options) {
272
+ if (options === false) {
273
+ return {
274
+ configFileName: defaultRuntimeConfigFileName,
275
+ enabled: false,
276
+ env: false,
277
+ schemaFileName: defaultRuntimeConfigSchemaFileName,
278
+ validation: false
279
+ };
280
+ }
281
+ const configFileName = options.configFileName ?? defaultRuntimeConfigFileName;
282
+ return {
283
+ configFileName,
284
+ enabled: options.enabled !== false,
285
+ env: options.env ?? {},
286
+ schemaFileName: options.schemaFileName ?? defaultRuntimeConfigSchemaFileName,
287
+ ...options.source === false ? {} : {
288
+ source: options.source ?? { paths: [] }
289
+ },
290
+ validation: options.validation === false ? false : options.validation ?? {},
291
+ ...options.varDir ? { varDir: options.varDir } : {}
292
+ };
276
293
  }
277
- function resolveActivationEntry(capabilityDir, packageJson) {
278
- const packageName = packageJson.name;
279
- const packageExports = packageJson.exports;
280
- if (typeof packageName !== "string") {
281
- throw new Error(
282
- `Capability package is missing "name": ${(0, import_node_path.resolve)(capabilityDir, "package.json")}`
283
- );
294
+ function resolveRuntimeConfigPatternSource(workspaceRoot, options, env) {
295
+ if (!options.source?.paths.length) {
296
+ const varDir = resolveRuntimeConfigVarDir(workspaceRoot, options.varDir, env);
297
+ return {
298
+ paths: [(0, import_node_path.join)(varDir, "runtime-config", "*", options.configFileName)]
299
+ };
300
+ }
301
+ return {
302
+ paths: options.source.paths.map(
303
+ (entry) => (0, import_node_path.isAbsolute)(entry) ? entry : (0, import_node_path.resolve)(workspaceRoot, entry)
304
+ )
305
+ };
306
+ }
307
+ function resolveRuntimeConfigVarDir(workspaceRoot, options, env) {
308
+ const rawVarDir = typeof options === "string" ? options : (0, import_runtime_config_node.resolveRuntimeConfigSource)({
309
+ defaultVarDir: (0, import_node_path.resolve)(workspaceRoot, ".data"),
310
+ env: options?.env ?? env,
311
+ envKey: options?.envKey ?? "RUNTIME_CONFIG_VAR_DIR",
312
+ ...options?.value ? { varDir: options.value } : {},
313
+ ...options?.defaultValue ? { defaultVarDir: options.defaultValue } : {}
314
+ }).varDir;
315
+ return (0, import_node_path.isAbsolute)(rawVarDir) ? rawVarDir : (0, import_node_path.resolve)(workspaceRoot, rawVarDir);
316
+ }
317
+ function resolveRuntimeConfigEnv(viteConfig, options) {
318
+ if (options === false) return {};
319
+ if (options.env) return options.env;
320
+ const mode = viteConfig.mode ?? import_node_process.default.env.NODE_ENV ?? "development";
321
+ const envDir = typeof viteConfig.envDir === "string" ? viteConfig.envDir : viteConfig.root ?? import_node_process.default.cwd();
322
+ return {
323
+ ...(0, import_vite.loadEnv)(mode, envDir, ""),
324
+ ...import_node_process.default.env,
325
+ ...viteConfig.env ?? {}
326
+ };
327
+ }
328
+ function readRuntimeConfigSchemas(capabilities, schemaFileName) {
329
+ const paths = /* @__PURE__ */ new Map();
330
+ const schemas = {};
331
+ for (const capability of capabilities) {
332
+ const schemaPath = (0, import_node_path.resolve)(capability.capabilityDir, schemaFileName);
333
+ const schema = (0, import_runtime_config_node.readJsonFile)(schemaPath, {
334
+ onParseError: (error, filePath) => {
335
+ throw new Error(`RuntimeConfig schema JSON parse error in "${filePath}": ${String(error)}`);
336
+ }
337
+ });
338
+ if (!schema) continue;
339
+ paths.set(capability.id, schemaPath);
340
+ schemas[capability.id] = schema;
284
341
  }
285
- if (!isRecord(packageExports) || typeof packageExports["./capability"] !== "string") {
286
- throw new Error(`Capability package is missing a "./capability" export: ${capabilityDir}`);
342
+ return { paths, schemas };
343
+ }
344
+ function isJsonSchemaObject(value) {
345
+ return typeof value === "object" && value !== null && !Array.isArray(value);
346
+ }
347
+ function getRuntimeConfigSchemaSectionKeys(schema, visibility) {
348
+ if (!isJsonSchemaObject(schema)) return [];
349
+ const section = schema.properties?.[visibility];
350
+ if (!isJsonSchemaObject(section) || !isJsonSchemaObject(section.properties)) return [];
351
+ return Object.keys(section.properties).sort();
352
+ }
353
+ function createRuntimeConfigEnvKey(input) {
354
+ return (0, import_runtime_config.toSnakeUpperCase)([input.prefix, input.scopeId, input.key].filter(Boolean).join("_"));
355
+ }
356
+ function createRuntimeConfigEnvFragments(input) {
357
+ const fragments = /* @__PURE__ */ new Map();
358
+ for (const capability of input.capabilities) {
359
+ const schema = input.schemas[capability.id];
360
+ const publicConfig = {};
361
+ const privateConfig = {};
362
+ for (const key of getRuntimeConfigSchemaSectionKeys(schema, "public")) {
363
+ const envKey = createRuntimeConfigEnvKey({
364
+ key,
365
+ prefix: input.publicPrefix ?? "VITE",
366
+ scopeId: capability.id
367
+ });
368
+ const value = input.env[envKey];
369
+ if (value !== void 0) publicConfig[key] = value;
370
+ }
371
+ for (const key of getRuntimeConfigSchemaSectionKeys(schema, "private")) {
372
+ const envKey = createRuntimeConfigEnvKey({
373
+ key,
374
+ scopeId: capability.id,
375
+ ...input.privatePrefix !== void 0 ? { prefix: input.privatePrefix } : {}
376
+ });
377
+ const value = input.env[envKey];
378
+ if (value !== void 0) privateConfig[key] = value;
379
+ }
380
+ if (Object.keys(publicConfig).length || Object.keys(privateConfig).length) {
381
+ fragments.set(capability.id, {
382
+ ...Object.keys(publicConfig).length ? { public: publicConfig } : {},
383
+ ...Object.keys(privateConfig).length ? { private: privateConfig } : {}
384
+ });
385
+ }
287
386
  }
387
+ return fragments;
388
+ }
389
+ function createRuntimeConfigEnvFragmentOptions(capabilities, schemas, env, options) {
288
390
  return {
289
- entryFile: (0, import_node_path.resolve)(capabilityDir, packageExports["./capability"]),
290
- importSpecifier: `${packageName}/capability`
391
+ capabilities,
392
+ env,
393
+ ...options.privatePrefix !== void 0 ? { privatePrefix: options.privatePrefix } : {},
394
+ ...options.publicPrefix !== void 0 ? { publicPrefix: options.publicPrefix } : {},
395
+ schemas
291
396
  };
292
397
  }
398
+ function mergeRuntimeConfigSections(left, right) {
399
+ const section = {
400
+ ...left ?? {},
401
+ ...right ?? {}
402
+ };
403
+ return Object.keys(section).length ? section : void 0;
404
+ }
405
+ function mergeRuntimeConfigFragment(left, right) {
406
+ const publicConfig = mergeRuntimeConfigSections(left?.public, right?.public);
407
+ const privateConfig = mergeRuntimeConfigSections(left?.private, right?.private);
408
+ return (0, import_runtime_config.toRuntimeConfigFragment)({
409
+ ...publicConfig ? { public: publicConfig } : {},
410
+ ...privateConfig ? { private: privateConfig } : {}
411
+ });
412
+ }
413
+ function mergeRuntimeConfigFragmentMaps(left, right) {
414
+ const fragments = new Map(left);
415
+ for (const [scopeId, config] of right.entries()) {
416
+ fragments.set(scopeId, mergeRuntimeConfigFragment(fragments.get(scopeId), config));
417
+ }
418
+ return fragments;
419
+ }
420
+ function getCapabilityRuntimeConfigPolicy(capability, validation) {
421
+ return capability.manifest.runtimeConfig ?? validation.policy ?? "optional";
422
+ }
423
+ function shouldValidateRuntimeConfigFragment(input) {
424
+ if (!input.schema) return false;
425
+ const mode = (0, import_runtime_config.resolveRuntimeConfigValidationMode)(
426
+ getCapabilityRuntimeConfigPolicy(input.capability, input.validation)
427
+ );
428
+ if (mode === "none" || mode === "onUse") return false;
429
+ if (mode === "startup") return true;
430
+ return Boolean(input.fragment);
431
+ }
432
+ function validateReactRuntimeConfig(capabilities, fragments, schemas, validation) {
433
+ if (validation === false) return;
434
+ const registry = (0, import_runtime_config.createRuntimeConfigValidatorRegistry)(schemas.schemas, {
435
+ ...validation.formatError ? {
436
+ formatError: (target, validationError) => validation.formatError(
437
+ {
438
+ configPath: `${target.scopeId} runtime config`,
439
+ schemaPath: schemas.paths.get(target.scopeId) ?? "",
440
+ scopeId: target.scopeId
441
+ },
442
+ validationError
443
+ )
444
+ } : {}
445
+ });
446
+ for (const capability of capabilities) {
447
+ const fragment = fragments.get(capability.id);
448
+ const schema = schemas.schemas[capability.id];
449
+ if (!shouldValidateRuntimeConfigFragment({ capability, fragment, schema, validation })) {
450
+ continue;
451
+ }
452
+ registry.assert(capability.id, fragment ?? {});
453
+ }
454
+ }
455
+ function resolveRouteDirectory(capabilityDir) {
456
+ const routesDirectory = (0, import_node_path.resolve)(capabilityDir, "src", "routes");
457
+ return (0, import_node_fs.existsSync)(routesDirectory) ? routesDirectory : void 0;
458
+ }
459
+ function resolveActivationEntry(capabilityDir, packageJson, packageName, descriptor, resolveActivation) {
460
+ if (!resolveActivation) {
461
+ const packageExports = packageJson.exports;
462
+ if (!isRecord(packageExports) || typeof packageExports["./capability"] !== "string") {
463
+ throw new Error(`Capability package is missing a "./capability" export: ${capabilityDir}`);
464
+ }
465
+ return {
466
+ entryFile: (0, import_node_path.resolve)(capabilityDir, packageExports["./capability"]),
467
+ exportName: "capability",
468
+ importSpecifier: (0, import_surface_activation.capabilitySpecifier)(packageName, "./capability")
469
+ };
470
+ }
471
+ const activation = resolveActivation({ capabilityDir, descriptor, packageJson, packageName });
472
+ if (!activation) return null;
473
+ const exportName = activation.exportName ?? "capability";
474
+ const exportSubpath = activation.exportSubpath ?? "./capability";
475
+ return { exportName, importSpecifier: (0, import_surface_activation.capabilitySpecifier)(packageName, exportSubpath) };
476
+ }
293
477
  function hasRouteDirectory(capability) {
294
478
  return typeof capability.routesDirectory === "string";
295
479
  }
@@ -326,8 +510,11 @@ function toPosixPath(path) {
326
510
  0 && (module.exports = {
327
511
  capabilityLoader,
328
512
  createCapabilityRouteConfig,
513
+ createReactRuntimeConfig,
329
514
  discoverCapabilities,
330
515
  discoverSelectedCapabilities,
331
516
  lorionReact,
332
- renderCapabilityModule
517
+ renderCapabilityModule,
518
+ renderRuntimeConfigModule,
519
+ renderServerRuntimeConfigModule
333
520
  });