@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/dist/vite.js
CHANGED
|
@@ -1,19 +1,39 @@
|
|
|
1
1
|
// src/vite.ts
|
|
2
2
|
import { existsSync, readFileSync } from "fs";
|
|
3
|
-
import { dirname, join, relative, resolve, sep } from "path";
|
|
4
|
-
import
|
|
5
|
-
|
|
6
|
-
createDescriptorCatalog
|
|
7
|
-
} from "@lorion-org/composition-graph";
|
|
3
|
+
import { dirname, isAbsolute, join, relative, resolve, sep } from "path";
|
|
4
|
+
import process from "process";
|
|
5
|
+
import { loadEnv } from "vite";
|
|
8
6
|
import {
|
|
9
7
|
descriptorSchema,
|
|
10
|
-
discoverDescriptors
|
|
8
|
+
discoverDescriptors,
|
|
9
|
+
requirePackageName
|
|
11
10
|
} from "@lorion-org/descriptor-discovery";
|
|
11
|
+
import { resolveDescriptorSelection, selectDescriptors } from "@lorion-org/descriptor-selection";
|
|
12
|
+
import {
|
|
13
|
+
createRuntimeConfigValidatorRegistry,
|
|
14
|
+
projectRuntimeConfigNamespaces,
|
|
15
|
+
resolveRuntimeConfigValidationMode,
|
|
16
|
+
toRuntimeConfigFragment,
|
|
17
|
+
toSnakeUpperCase
|
|
18
|
+
} from "@lorion-org/runtime-config";
|
|
19
|
+
import {
|
|
20
|
+
loadRuntimeConfigSourceTree,
|
|
21
|
+
readJsonFile,
|
|
22
|
+
resolveRuntimeConfigSource as resolveRuntimeConfigVarDirSource
|
|
23
|
+
} from "@lorion-org/runtime-config-node";
|
|
24
|
+
import { capabilitySpecifier } from "@lorion-org/surface-activation";
|
|
12
25
|
var virtualModuleId = "virtual:capabilities";
|
|
13
26
|
var resolvedVirtualModuleId = `\0${virtualModuleId}`;
|
|
27
|
+
var runtimeConfigModuleId = "virtual:capability-runtime-config";
|
|
28
|
+
var resolvedRuntimeConfigModuleId = `\0${runtimeConfigModuleId}`;
|
|
29
|
+
var serverRuntimeConfigModuleId = "virtual:capability-runtime-config/server";
|
|
30
|
+
var resolvedServerRuntimeConfigModuleId = `\0${serverRuntimeConfigModuleId}`;
|
|
31
|
+
var defaultRuntimeConfigFileName = "capability.runtime.json";
|
|
32
|
+
var defaultRuntimeConfigSchemaFileName = "capability.schema.json";
|
|
14
33
|
function capabilityLoader(options = {}) {
|
|
15
34
|
let config;
|
|
16
35
|
let capabilities = [];
|
|
36
|
+
let runtimeConfig = { private: {}, public: {} };
|
|
17
37
|
return {
|
|
18
38
|
name: "lorion-react-capability-loader",
|
|
19
39
|
enforce: "pre",
|
|
@@ -23,62 +43,132 @@ function capabilityLoader(options = {}) {
|
|
|
23
43
|
resolveWorkspaceRoot(config.root, options),
|
|
24
44
|
options
|
|
25
45
|
);
|
|
46
|
+
runtimeConfig = createReactRuntimeConfig(
|
|
47
|
+
capabilities,
|
|
48
|
+
resolveWorkspaceRoot(config.root, options),
|
|
49
|
+
options.runtimeConfig,
|
|
50
|
+
config
|
|
51
|
+
);
|
|
26
52
|
},
|
|
27
53
|
resolveId(id) {
|
|
28
54
|
if (id === virtualModuleId) return resolvedVirtualModuleId;
|
|
55
|
+
if (id === runtimeConfigModuleId) return resolvedRuntimeConfigModuleId;
|
|
56
|
+
if (id === serverRuntimeConfigModuleId) return resolvedServerRuntimeConfigModuleId;
|
|
29
57
|
return capabilities.find((capability) => capability.importSpecifier === id)?.entryFile;
|
|
30
58
|
},
|
|
31
|
-
load(id) {
|
|
59
|
+
load(id, loadOptions) {
|
|
60
|
+
if (id === resolvedRuntimeConfigModuleId) return renderRuntimeConfigModule(runtimeConfig);
|
|
61
|
+
if (id === resolvedServerRuntimeConfigModuleId) {
|
|
62
|
+
if (!loadOptions?.ssr) {
|
|
63
|
+
throw new Error(
|
|
64
|
+
"virtual:capability-runtime-config/server may only be imported from SSR/server code."
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
return renderServerRuntimeConfigModule(runtimeConfig);
|
|
68
|
+
}
|
|
32
69
|
if (id !== resolvedVirtualModuleId) return null;
|
|
33
|
-
return renderCapabilityModule(capabilities);
|
|
70
|
+
return renderCapabilityModule(capabilities, resolveSelectionSeed(options));
|
|
34
71
|
}
|
|
35
72
|
};
|
|
36
73
|
}
|
|
74
|
+
function createReactRuntimeConfig(capabilities, workspaceRoot, options = {}, viteConfig = {}) {
|
|
75
|
+
const normalizedOptions = normalizeRuntimeConfigOptions(options);
|
|
76
|
+
if (!normalizedOptions.enabled) return { private: {}, public: {} };
|
|
77
|
+
const runtimeEnv = resolveRuntimeConfigEnv(viteConfig, normalizedOptions.env ?? {});
|
|
78
|
+
const sourceFragments = normalizedOptions.source ? loadRuntimeConfigSourceTree(
|
|
79
|
+
resolveRuntimeConfigPatternSource(workspaceRoot, normalizedOptions, runtimeEnv)
|
|
80
|
+
) : /* @__PURE__ */ new Map();
|
|
81
|
+
const schemaEntries = readRuntimeConfigSchemas(capabilities, normalizedOptions.schemaFileName);
|
|
82
|
+
const envFragments = normalizedOptions.env === false ? /* @__PURE__ */ new Map() : createRuntimeConfigEnvFragments(
|
|
83
|
+
createRuntimeConfigEnvFragmentOptions(
|
|
84
|
+
capabilities,
|
|
85
|
+
schemaEntries.schemas,
|
|
86
|
+
runtimeEnv,
|
|
87
|
+
normalizedOptions.env
|
|
88
|
+
)
|
|
89
|
+
);
|
|
90
|
+
const fragments = mergeRuntimeConfigFragmentMaps(sourceFragments, envFragments);
|
|
91
|
+
validateReactRuntimeConfig(capabilities, fragments, schemaEntries, normalizedOptions.validation);
|
|
92
|
+
const projected = projectRuntimeConfigNamespaces(fragments, {
|
|
93
|
+
namespaceStrategy: "nested",
|
|
94
|
+
scopeIds: capabilities.map((capability) => capability.id)
|
|
95
|
+
});
|
|
96
|
+
const { public: publicConfig, ...privateConfig } = projected;
|
|
97
|
+
return {
|
|
98
|
+
public: publicConfig,
|
|
99
|
+
private: privateConfig
|
|
100
|
+
};
|
|
101
|
+
}
|
|
37
102
|
function lorionReact(options) {
|
|
38
103
|
return {
|
|
39
104
|
capabilityLoader: capabilityLoader(options),
|
|
40
105
|
routeConfig: createCapabilityRouteConfig(options)
|
|
41
106
|
};
|
|
42
107
|
}
|
|
108
|
+
function toResolveActivation(options) {
|
|
109
|
+
if (options.surface) {
|
|
110
|
+
if (options.activation) {
|
|
111
|
+
throw new Error("capabilityLoader: pass either `surface` or `activation`, not both.");
|
|
112
|
+
}
|
|
113
|
+
const { name, resolver } = options.surface;
|
|
114
|
+
return ({ capabilityDir, descriptor }) => resolver(name, { directory: capabilityDir, id: descriptor.id });
|
|
115
|
+
}
|
|
116
|
+
return options.activation;
|
|
117
|
+
}
|
|
43
118
|
function discoverCapabilities(workspaceRoot, options = {}) {
|
|
44
119
|
const capabilitiesRoot = resolve(workspaceRoot, options.capabilitiesDir ?? "capabilities");
|
|
45
120
|
if (!existsSync(capabilitiesRoot)) {
|
|
46
121
|
throw new Error(`Capabilities directory not found: ${capabilitiesRoot}`);
|
|
47
122
|
}
|
|
48
|
-
|
|
123
|
+
const resolveActivation = toResolveActivation(options);
|
|
124
|
+
return discoverCapabilityDescriptors(workspaceRoot, options).map((entry) => discoverCapability(entry, resolveActivation)).sort((left, right) => left.id.localeCompare(right.id));
|
|
49
125
|
}
|
|
50
126
|
function discoverSelectedCapabilities(workspaceRoot, options = {}) {
|
|
51
127
|
return selectCapabilities(discoverCapabilities(workspaceRoot, options), options);
|
|
52
128
|
}
|
|
53
129
|
function selectCapabilities(capabilities, options = {}) {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
});
|
|
61
|
-
const selection = createCompositionSelection({
|
|
62
|
-
catalog,
|
|
63
|
-
selected: [...options.selected ?? []],
|
|
64
|
-
baseDescriptors: [...options.baseDescriptors ?? []],
|
|
130
|
+
return selectDescriptors({
|
|
131
|
+
items: capabilities,
|
|
132
|
+
getDescriptor: (capability) => capability.manifest,
|
|
133
|
+
withDescriptor: (capability, manifest) => ({ ...capability, manifest }),
|
|
134
|
+
seed: options,
|
|
135
|
+
...options.relationDescriptors ? { relationDescriptors: options.relationDescriptors } : {},
|
|
65
136
|
...options.policy ? { policy: options.policy } : {}
|
|
66
137
|
});
|
|
67
|
-
const selectedIds = new Set(selection.getResolved());
|
|
68
|
-
return enabledCapabilities.filter((capability) => selectedIds.has(capability.id));
|
|
69
138
|
}
|
|
70
|
-
function
|
|
71
|
-
|
|
72
|
-
|
|
139
|
+
function resolveSelectionSeed(options) {
|
|
140
|
+
return resolveDescriptorSelection(options);
|
|
141
|
+
}
|
|
142
|
+
function renderCapabilityModule(capabilities, selected = []) {
|
|
143
|
+
const activated = capabilities.filter(
|
|
144
|
+
(capability) => capability.exportName && capability.importSpecifier
|
|
145
|
+
);
|
|
146
|
+
const imports = activated.map(
|
|
147
|
+
(capability) => `import { ${capability.exportName} as ${capability.variableName} } from '${capability.importSpecifier}'`
|
|
73
148
|
).join("\n");
|
|
74
|
-
const variables =
|
|
149
|
+
const variables = activated.map((capability) => ` ${capability.variableName},`).join("\n");
|
|
150
|
+
const capabilityIds = capabilities.map((capability) => capability.id);
|
|
75
151
|
return `${imports}
|
|
76
152
|
|
|
153
|
+
export const selectedCapabilityIds = ${JSON.stringify([...selected])}
|
|
154
|
+
|
|
155
|
+
export const resolvedCapabilityIds = ${JSON.stringify(capabilityIds)}
|
|
156
|
+
|
|
77
157
|
export const capabilityModules = [
|
|
78
158
|
${variables}
|
|
79
159
|
]
|
|
80
160
|
`;
|
|
81
161
|
}
|
|
162
|
+
function renderRuntimeConfigModule(runtimeConfig) {
|
|
163
|
+
return `export const capabilityRuntimeConfig = ${JSON.stringify({ public: runtimeConfig.public })}
|
|
164
|
+
|
|
165
|
+
export const publicCapabilityRuntimeConfig = capabilityRuntimeConfig.public
|
|
166
|
+
`;
|
|
167
|
+
}
|
|
168
|
+
function renderServerRuntimeConfigModule(runtimeConfig) {
|
|
169
|
+
return `export const capabilityServerRuntimeConfig = ${JSON.stringify(runtimeConfig)}
|
|
170
|
+
`;
|
|
171
|
+
}
|
|
82
172
|
function createCapabilityRouteConfig(options) {
|
|
83
173
|
if (!options?.workspaceRoot) {
|
|
84
174
|
throw new Error("createCapabilityRouteConfig requires a workspaceRoot option.");
|
|
@@ -117,7 +207,7 @@ function discoverCapabilityDescriptors(workspaceRoot, options) {
|
|
|
117
207
|
}
|
|
118
208
|
});
|
|
119
209
|
}
|
|
120
|
-
function discoverCapability(entry) {
|
|
210
|
+
function discoverCapability(entry, resolveActivation) {
|
|
121
211
|
const capabilityDir = entry.cwd;
|
|
122
212
|
const packagePath = resolve(capabilityDir, "package.json");
|
|
123
213
|
if (!existsSync(packagePath)) {
|
|
@@ -126,42 +216,235 @@ function discoverCapability(entry) {
|
|
|
126
216
|
);
|
|
127
217
|
}
|
|
128
218
|
const packageJson = readJson(packagePath);
|
|
129
|
-
const packageName = packageJson
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
219
|
+
const packageName = requirePackageName(packageJson, packagePath);
|
|
220
|
+
const activationEntry = resolveActivationEntry(
|
|
221
|
+
capabilityDir,
|
|
222
|
+
packageJson,
|
|
223
|
+
packageName,
|
|
224
|
+
entry.descriptor,
|
|
225
|
+
resolveActivation
|
|
226
|
+
);
|
|
134
227
|
const routesDirectory = resolveRouteDirectory(capabilityDir);
|
|
135
228
|
return {
|
|
229
|
+
capabilityDir,
|
|
136
230
|
id: entry.descriptor.id,
|
|
137
231
|
disabled: entry.descriptor.disabled === true,
|
|
138
|
-
entryFile: activationEntry.entryFile,
|
|
139
|
-
importSpecifier: activationEntry.importSpecifier,
|
|
140
232
|
manifest: entry.descriptor,
|
|
141
233
|
packageName,
|
|
234
|
+
...activationEntry ? {
|
|
235
|
+
exportName: activationEntry.exportName,
|
|
236
|
+
importSpecifier: activationEntry.importSpecifier,
|
|
237
|
+
...activationEntry.entryFile ? { entryFile: activationEntry.entryFile } : {}
|
|
238
|
+
} : {},
|
|
142
239
|
...routesDirectory ? { routesDirectory } : {},
|
|
143
240
|
variableName: toVariableName(entry.descriptor.id)
|
|
144
241
|
};
|
|
145
242
|
}
|
|
146
|
-
function
|
|
147
|
-
|
|
148
|
-
|
|
243
|
+
function normalizeRuntimeConfigOptions(options) {
|
|
244
|
+
if (options === false) {
|
|
245
|
+
return {
|
|
246
|
+
configFileName: defaultRuntimeConfigFileName,
|
|
247
|
+
enabled: false,
|
|
248
|
+
env: false,
|
|
249
|
+
schemaFileName: defaultRuntimeConfigSchemaFileName,
|
|
250
|
+
validation: false
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
const configFileName = options.configFileName ?? defaultRuntimeConfigFileName;
|
|
254
|
+
return {
|
|
255
|
+
configFileName,
|
|
256
|
+
enabled: options.enabled !== false,
|
|
257
|
+
env: options.env ?? {},
|
|
258
|
+
schemaFileName: options.schemaFileName ?? defaultRuntimeConfigSchemaFileName,
|
|
259
|
+
...options.source === false ? {} : {
|
|
260
|
+
source: options.source ?? { paths: [] }
|
|
261
|
+
},
|
|
262
|
+
validation: options.validation === false ? false : options.validation ?? {},
|
|
263
|
+
...options.varDir ? { varDir: options.varDir } : {}
|
|
264
|
+
};
|
|
149
265
|
}
|
|
150
|
-
function
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
);
|
|
266
|
+
function resolveRuntimeConfigPatternSource(workspaceRoot, options, env) {
|
|
267
|
+
if (!options.source?.paths.length) {
|
|
268
|
+
const varDir = resolveRuntimeConfigVarDir(workspaceRoot, options.varDir, env);
|
|
269
|
+
return {
|
|
270
|
+
paths: [join(varDir, "runtime-config", "*", options.configFileName)]
|
|
271
|
+
};
|
|
157
272
|
}
|
|
158
|
-
|
|
159
|
-
|
|
273
|
+
return {
|
|
274
|
+
paths: options.source.paths.map(
|
|
275
|
+
(entry) => isAbsolute(entry) ? entry : resolve(workspaceRoot, entry)
|
|
276
|
+
)
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
function resolveRuntimeConfigVarDir(workspaceRoot, options, env) {
|
|
280
|
+
const rawVarDir = typeof options === "string" ? options : resolveRuntimeConfigVarDirSource({
|
|
281
|
+
defaultVarDir: resolve(workspaceRoot, ".data"),
|
|
282
|
+
env: options?.env ?? env,
|
|
283
|
+
envKey: options?.envKey ?? "RUNTIME_CONFIG_VAR_DIR",
|
|
284
|
+
...options?.value ? { varDir: options.value } : {},
|
|
285
|
+
...options?.defaultValue ? { defaultVarDir: options.defaultValue } : {}
|
|
286
|
+
}).varDir;
|
|
287
|
+
return isAbsolute(rawVarDir) ? rawVarDir : resolve(workspaceRoot, rawVarDir);
|
|
288
|
+
}
|
|
289
|
+
function resolveRuntimeConfigEnv(viteConfig, options) {
|
|
290
|
+
if (options === false) return {};
|
|
291
|
+
if (options.env) return options.env;
|
|
292
|
+
const mode = viteConfig.mode ?? process.env.NODE_ENV ?? "development";
|
|
293
|
+
const envDir = typeof viteConfig.envDir === "string" ? viteConfig.envDir : viteConfig.root ?? process.cwd();
|
|
294
|
+
return {
|
|
295
|
+
...loadEnv(mode, envDir, ""),
|
|
296
|
+
...process.env,
|
|
297
|
+
...viteConfig.env ?? {}
|
|
298
|
+
};
|
|
299
|
+
}
|
|
300
|
+
function readRuntimeConfigSchemas(capabilities, schemaFileName) {
|
|
301
|
+
const paths = /* @__PURE__ */ new Map();
|
|
302
|
+
const schemas = {};
|
|
303
|
+
for (const capability of capabilities) {
|
|
304
|
+
const schemaPath = resolve(capability.capabilityDir, schemaFileName);
|
|
305
|
+
const schema = readJsonFile(schemaPath, {
|
|
306
|
+
onParseError: (error, filePath) => {
|
|
307
|
+
throw new Error(`RuntimeConfig schema JSON parse error in "${filePath}": ${String(error)}`);
|
|
308
|
+
}
|
|
309
|
+
});
|
|
310
|
+
if (!schema) continue;
|
|
311
|
+
paths.set(capability.id, schemaPath);
|
|
312
|
+
schemas[capability.id] = schema;
|
|
313
|
+
}
|
|
314
|
+
return { paths, schemas };
|
|
315
|
+
}
|
|
316
|
+
function isJsonSchemaObject(value) {
|
|
317
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
318
|
+
}
|
|
319
|
+
function getRuntimeConfigSchemaSectionKeys(schema, visibility) {
|
|
320
|
+
if (!isJsonSchemaObject(schema)) return [];
|
|
321
|
+
const section = schema.properties?.[visibility];
|
|
322
|
+
if (!isJsonSchemaObject(section) || !isJsonSchemaObject(section.properties)) return [];
|
|
323
|
+
return Object.keys(section.properties).sort();
|
|
324
|
+
}
|
|
325
|
+
function createRuntimeConfigEnvKey(input) {
|
|
326
|
+
return toSnakeUpperCase([input.prefix, input.scopeId, input.key].filter(Boolean).join("_"));
|
|
327
|
+
}
|
|
328
|
+
function createRuntimeConfigEnvFragments(input) {
|
|
329
|
+
const fragments = /* @__PURE__ */ new Map();
|
|
330
|
+
for (const capability of input.capabilities) {
|
|
331
|
+
const schema = input.schemas[capability.id];
|
|
332
|
+
const publicConfig = {};
|
|
333
|
+
const privateConfig = {};
|
|
334
|
+
for (const key of getRuntimeConfigSchemaSectionKeys(schema, "public")) {
|
|
335
|
+
const envKey = createRuntimeConfigEnvKey({
|
|
336
|
+
key,
|
|
337
|
+
prefix: input.publicPrefix ?? "VITE",
|
|
338
|
+
scopeId: capability.id
|
|
339
|
+
});
|
|
340
|
+
const value = input.env[envKey];
|
|
341
|
+
if (value !== void 0) publicConfig[key] = value;
|
|
342
|
+
}
|
|
343
|
+
for (const key of getRuntimeConfigSchemaSectionKeys(schema, "private")) {
|
|
344
|
+
const envKey = createRuntimeConfigEnvKey({
|
|
345
|
+
key,
|
|
346
|
+
scopeId: capability.id,
|
|
347
|
+
...input.privatePrefix !== void 0 ? { prefix: input.privatePrefix } : {}
|
|
348
|
+
});
|
|
349
|
+
const value = input.env[envKey];
|
|
350
|
+
if (value !== void 0) privateConfig[key] = value;
|
|
351
|
+
}
|
|
352
|
+
if (Object.keys(publicConfig).length || Object.keys(privateConfig).length) {
|
|
353
|
+
fragments.set(capability.id, {
|
|
354
|
+
...Object.keys(publicConfig).length ? { public: publicConfig } : {},
|
|
355
|
+
...Object.keys(privateConfig).length ? { private: privateConfig } : {}
|
|
356
|
+
});
|
|
357
|
+
}
|
|
160
358
|
}
|
|
359
|
+
return fragments;
|
|
360
|
+
}
|
|
361
|
+
function createRuntimeConfigEnvFragmentOptions(capabilities, schemas, env, options) {
|
|
161
362
|
return {
|
|
162
|
-
|
|
163
|
-
|
|
363
|
+
capabilities,
|
|
364
|
+
env,
|
|
365
|
+
...options.privatePrefix !== void 0 ? { privatePrefix: options.privatePrefix } : {},
|
|
366
|
+
...options.publicPrefix !== void 0 ? { publicPrefix: options.publicPrefix } : {},
|
|
367
|
+
schemas
|
|
368
|
+
};
|
|
369
|
+
}
|
|
370
|
+
function mergeRuntimeConfigSections(left, right) {
|
|
371
|
+
const section = {
|
|
372
|
+
...left ?? {},
|
|
373
|
+
...right ?? {}
|
|
164
374
|
};
|
|
375
|
+
return Object.keys(section).length ? section : void 0;
|
|
376
|
+
}
|
|
377
|
+
function mergeRuntimeConfigFragment(left, right) {
|
|
378
|
+
const publicConfig = mergeRuntimeConfigSections(left?.public, right?.public);
|
|
379
|
+
const privateConfig = mergeRuntimeConfigSections(left?.private, right?.private);
|
|
380
|
+
return toRuntimeConfigFragment({
|
|
381
|
+
...publicConfig ? { public: publicConfig } : {},
|
|
382
|
+
...privateConfig ? { private: privateConfig } : {}
|
|
383
|
+
});
|
|
384
|
+
}
|
|
385
|
+
function mergeRuntimeConfigFragmentMaps(left, right) {
|
|
386
|
+
const fragments = new Map(left);
|
|
387
|
+
for (const [scopeId, config] of right.entries()) {
|
|
388
|
+
fragments.set(scopeId, mergeRuntimeConfigFragment(fragments.get(scopeId), config));
|
|
389
|
+
}
|
|
390
|
+
return fragments;
|
|
391
|
+
}
|
|
392
|
+
function getCapabilityRuntimeConfigPolicy(capability, validation) {
|
|
393
|
+
return capability.manifest.runtimeConfig ?? validation.policy ?? "optional";
|
|
394
|
+
}
|
|
395
|
+
function shouldValidateRuntimeConfigFragment(input) {
|
|
396
|
+
if (!input.schema) return false;
|
|
397
|
+
const mode = resolveRuntimeConfigValidationMode(
|
|
398
|
+
getCapabilityRuntimeConfigPolicy(input.capability, input.validation)
|
|
399
|
+
);
|
|
400
|
+
if (mode === "none" || mode === "onUse") return false;
|
|
401
|
+
if (mode === "startup") return true;
|
|
402
|
+
return Boolean(input.fragment);
|
|
403
|
+
}
|
|
404
|
+
function validateReactRuntimeConfig(capabilities, fragments, schemas, validation) {
|
|
405
|
+
if (validation === false) return;
|
|
406
|
+
const registry = createRuntimeConfigValidatorRegistry(schemas.schemas, {
|
|
407
|
+
...validation.formatError ? {
|
|
408
|
+
formatError: (target, validationError) => validation.formatError(
|
|
409
|
+
{
|
|
410
|
+
configPath: `${target.scopeId} runtime config`,
|
|
411
|
+
schemaPath: schemas.paths.get(target.scopeId) ?? "",
|
|
412
|
+
scopeId: target.scopeId
|
|
413
|
+
},
|
|
414
|
+
validationError
|
|
415
|
+
)
|
|
416
|
+
} : {}
|
|
417
|
+
});
|
|
418
|
+
for (const capability of capabilities) {
|
|
419
|
+
const fragment = fragments.get(capability.id);
|
|
420
|
+
const schema = schemas.schemas[capability.id];
|
|
421
|
+
if (!shouldValidateRuntimeConfigFragment({ capability, fragment, schema, validation })) {
|
|
422
|
+
continue;
|
|
423
|
+
}
|
|
424
|
+
registry.assert(capability.id, fragment ?? {});
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
function resolveRouteDirectory(capabilityDir) {
|
|
428
|
+
const routesDirectory = resolve(capabilityDir, "src", "routes");
|
|
429
|
+
return existsSync(routesDirectory) ? routesDirectory : void 0;
|
|
430
|
+
}
|
|
431
|
+
function resolveActivationEntry(capabilityDir, packageJson, packageName, descriptor, resolveActivation) {
|
|
432
|
+
if (!resolveActivation) {
|
|
433
|
+
const packageExports = packageJson.exports;
|
|
434
|
+
if (!isRecord(packageExports) || typeof packageExports["./capability"] !== "string") {
|
|
435
|
+
throw new Error(`Capability package is missing a "./capability" export: ${capabilityDir}`);
|
|
436
|
+
}
|
|
437
|
+
return {
|
|
438
|
+
entryFile: resolve(capabilityDir, packageExports["./capability"]),
|
|
439
|
+
exportName: "capability",
|
|
440
|
+
importSpecifier: capabilitySpecifier(packageName, "./capability")
|
|
441
|
+
};
|
|
442
|
+
}
|
|
443
|
+
const activation = resolveActivation({ capabilityDir, descriptor, packageJson, packageName });
|
|
444
|
+
if (!activation) return null;
|
|
445
|
+
const exportName = activation.exportName ?? "capability";
|
|
446
|
+
const exportSubpath = activation.exportSubpath ?? "./capability";
|
|
447
|
+
return { exportName, importSpecifier: capabilitySpecifier(packageName, exportSubpath) };
|
|
165
448
|
}
|
|
166
449
|
function hasRouteDirectory(capability) {
|
|
167
450
|
return typeof capability.routesDirectory === "string";
|
|
@@ -198,8 +481,11 @@ function toPosixPath(path) {
|
|
|
198
481
|
export {
|
|
199
482
|
capabilityLoader,
|
|
200
483
|
createCapabilityRouteConfig,
|
|
484
|
+
createReactRuntimeConfig,
|
|
201
485
|
discoverCapabilities,
|
|
202
486
|
discoverSelectedCapabilities,
|
|
203
487
|
lorionReact,
|
|
204
|
-
renderCapabilityModule
|
|
488
|
+
renderCapabilityModule,
|
|
489
|
+
renderRuntimeConfigModule,
|
|
490
|
+
renderServerRuntimeConfigModule
|
|
205
491
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lorion-org/react",
|
|
3
|
-
"version": "1.0.0-beta.
|
|
3
|
+
"version": "1.0.0-beta.3",
|
|
4
4
|
"description": "React capability runtime and Vite helpers for LORION descriptor-based applications.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -22,6 +22,10 @@
|
|
|
22
22
|
},
|
|
23
23
|
"exports": {
|
|
24
24
|
".": {
|
|
25
|
+
"lorion-source": {
|
|
26
|
+
"types": "./src/index.ts",
|
|
27
|
+
"default": "./src/index.ts"
|
|
28
|
+
},
|
|
25
29
|
"import": {
|
|
26
30
|
"types": "./dist/index.d.ts",
|
|
27
31
|
"default": "./dist/index.js"
|
|
@@ -32,6 +36,10 @@
|
|
|
32
36
|
}
|
|
33
37
|
},
|
|
34
38
|
"./vite": {
|
|
39
|
+
"lorion-source": {
|
|
40
|
+
"types": "./src/vite.ts",
|
|
41
|
+
"default": "./src/vite.ts"
|
|
42
|
+
},
|
|
35
43
|
"import": {
|
|
36
44
|
"types": "./dist/vite.d.ts",
|
|
37
45
|
"default": "./dist/vite.js"
|
|
@@ -44,15 +52,27 @@
|
|
|
44
52
|
},
|
|
45
53
|
"files": [
|
|
46
54
|
"dist",
|
|
47
|
-
"LICENSE"
|
|
55
|
+
"LICENSE",
|
|
56
|
+
"src/**/*.ts",
|
|
57
|
+
"!src/**/*.spec.ts"
|
|
48
58
|
],
|
|
49
59
|
"dependencies": {
|
|
50
|
-
"@lorion-org/composition-graph": "^1.0.0-beta.
|
|
51
|
-
"@lorion-org/
|
|
52
|
-
"@lorion-org/descriptor-
|
|
60
|
+
"@lorion-org/composition-graph": "^1.0.0-beta.2",
|
|
61
|
+
"@lorion-org/descriptor-discovery": "^1.0.0-beta.3",
|
|
62
|
+
"@lorion-org/descriptor-selection": "^1.0.0-beta.3",
|
|
63
|
+
"@lorion-org/provider-selection": "^1.0.0-beta.2",
|
|
64
|
+
"@lorion-org/runtime-config": "^1.0.0-beta.1",
|
|
65
|
+
"@lorion-org/runtime-config-node": "^1.0.0-beta.1",
|
|
66
|
+
"@lorion-org/surface-activation": "^1.0.0-beta.3"
|
|
53
67
|
},
|
|
54
68
|
"peerDependencies": {
|
|
55
|
-
"react": "^19.0.0"
|
|
69
|
+
"react": "^19.0.0",
|
|
70
|
+
"vite": "^7.0.0"
|
|
71
|
+
},
|
|
72
|
+
"peerDependenciesMeta": {
|
|
73
|
+
"vite": {
|
|
74
|
+
"optional": true
|
|
75
|
+
}
|
|
56
76
|
},
|
|
57
77
|
"devDependencies": {
|
|
58
78
|
"@tanstack/react-router": "^1.168.25",
|
|
@@ -80,10 +100,7 @@
|
|
|
80
100
|
"clean": "rimraf coverage dist tsconfig.tsbuildinfo",
|
|
81
101
|
"lint": "eslint src --ext .ts",
|
|
82
102
|
"package:check": "pnpm build && pnpm pack --dry-run && publint",
|
|
83
|
-
"build:playground": "vite build --config playground/vite.config.ts",
|
|
84
|
-
"dev:playground": "vite dev --config playground/vite.config.ts --host 0.0.0.0",
|
|
85
103
|
"test": "vitest run --root ../.. --config vitest.config.mts packages/react/src/index.spec.ts packages/react/src/vite.spec.ts",
|
|
86
|
-
"typecheck": "tsc -p tsconfig.json --noEmit"
|
|
87
|
-
"typecheck:playground": "tsc -p playground/tsconfig.json --noEmit"
|
|
104
|
+
"typecheck": "tsc -p tsconfig.json --noEmit"
|
|
88
105
|
}
|
|
89
106
|
}
|