@memberjunction/react-runtime 2.70.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/.turbo/turbo-build.log +4 -0
  2. package/CHANGELOG.md +3 -0
  3. package/README.md +224 -0
  4. package/dist/compiler/babel-config.d.ts +40 -0
  5. package/dist/compiler/babel-config.d.ts.map +1 -0
  6. package/dist/compiler/babel-config.js +52 -0
  7. package/dist/compiler/component-compiler.d.ts +22 -0
  8. package/dist/compiler/component-compiler.d.ts.map +1 -0
  9. package/dist/compiler/component-compiler.js +188 -0
  10. package/dist/compiler/index.d.ts +3 -0
  11. package/dist/compiler/index.d.ts.map +1 -0
  12. package/dist/compiler/index.js +13 -0
  13. package/dist/index.d.ts +41 -0
  14. package/dist/index.d.ts.map +1 -0
  15. package/dist/index.js +95 -0
  16. package/dist/registry/component-registry.d.ts +32 -0
  17. package/dist/registry/component-registry.d.ts.map +1 -0
  18. package/dist/registry/component-registry.js +197 -0
  19. package/dist/registry/component-resolver.d.ts +29 -0
  20. package/dist/registry/component-resolver.d.ts.map +1 -0
  21. package/dist/registry/component-resolver.js +112 -0
  22. package/dist/registry/index.d.ts +3 -0
  23. package/dist/registry/index.d.ts.map +1 -0
  24. package/dist/registry/index.js +7 -0
  25. package/dist/runtime/component-hierarchy.d.ts +44 -0
  26. package/dist/runtime/component-hierarchy.d.ts.map +1 -0
  27. package/dist/runtime/component-hierarchy.js +162 -0
  28. package/dist/runtime/component-wrapper.d.ts +18 -0
  29. package/dist/runtime/component-wrapper.d.ts.map +1 -0
  30. package/dist/runtime/component-wrapper.js +108 -0
  31. package/dist/runtime/error-boundary.d.ts +6 -0
  32. package/dist/runtime/error-boundary.d.ts.map +1 -0
  33. package/dist/runtime/error-boundary.js +139 -0
  34. package/dist/runtime/index.d.ts +5 -0
  35. package/dist/runtime/index.d.ts.map +1 -0
  36. package/dist/runtime/index.js +31 -0
  37. package/dist/runtime/prop-builder.d.ts +16 -0
  38. package/dist/runtime/prop-builder.d.ts.map +1 -0
  39. package/dist/runtime/prop-builder.js +161 -0
  40. package/dist/types/index.d.ts +98 -0
  41. package/dist/types/index.d.ts.map +1 -0
  42. package/dist/types/index.js +2 -0
  43. package/package.json +36 -0
  44. package/src/compiler/babel-config.ts +97 -0
  45. package/src/compiler/component-compiler.ts +366 -0
  46. package/src/compiler/index.ts +15 -0
  47. package/src/index.ts +125 -0
  48. package/src/registry/component-registry.ts +379 -0
  49. package/src/registry/component-resolver.ts +275 -0
  50. package/src/registry/index.ts +7 -0
  51. package/src/runtime/component-hierarchy.ts +346 -0
  52. package/src/runtime/component-wrapper.ts +249 -0
  53. package/src/runtime/error-boundary.ts +242 -0
  54. package/src/runtime/index.ts +45 -0
  55. package/src/runtime/prop-builder.ts +290 -0
  56. package/src/types/index.ts +226 -0
  57. package/tsconfig.json +37 -0
  58. package/tsconfig.tsbuildinfo +1 -0
@@ -0,0 +1,379 @@
1
+ /**
2
+ * @fileoverview Platform-agnostic component registry for managing compiled React components.
3
+ * Provides storage, retrieval, and lifecycle management for components with namespace support.
4
+ * @module @memberjunction/react-runtime/registry
5
+ */
6
+
7
+ import {
8
+ RegistryEntry,
9
+ ComponentMetadata,
10
+ RegistryConfig
11
+ } from '../types';
12
+
13
+ /**
14
+ * Default registry configuration
15
+ */
16
+ const DEFAULT_REGISTRY_CONFIG: RegistryConfig = {
17
+ maxComponents: 1000,
18
+ cleanupInterval: 60000, // 1 minute
19
+ useLRU: true,
20
+ enableNamespaces: true
21
+ };
22
+
23
+ /**
24
+ * Platform-agnostic component registry.
25
+ * Manages compiled React components with namespace isolation and lifecycle management.
26
+ */
27
+ export class ComponentRegistry {
28
+ private registry: Map<string, RegistryEntry>;
29
+ private config: RegistryConfig;
30
+ private cleanupTimer?: NodeJS.Timeout | number;
31
+
32
+ /**
33
+ * Creates a new ComponentRegistry instance
34
+ * @param config - Optional registry configuration
35
+ */
36
+ constructor(config?: Partial<RegistryConfig>) {
37
+ this.config = { ...DEFAULT_REGISTRY_CONFIG, ...config };
38
+ this.registry = new Map();
39
+
40
+ // Start cleanup timer if configured
41
+ if (this.config.cleanupInterval > 0) {
42
+ this.startCleanupTimer();
43
+ }
44
+ }
45
+
46
+ /**
47
+ * Registers a compiled component
48
+ * @param name - Component name
49
+ * @param component - Compiled component
50
+ * @param namespace - Component namespace (default: 'Global')
51
+ * @param version - Component version (default: 'v1')
52
+ * @param tags - Optional tags for categorization
53
+ * @returns The registered component's metadata
54
+ */
55
+ register(
56
+ name: string,
57
+ component: any,
58
+ namespace: string = 'Global',
59
+ version: string = 'v1',
60
+ tags?: string[]
61
+ ): ComponentMetadata {
62
+ const id = this.generateRegistryKey(name, namespace, version);
63
+
64
+ // Create metadata
65
+ const metadata: ComponentMetadata = {
66
+ id,
67
+ name,
68
+ version,
69
+ namespace,
70
+ registeredAt: new Date(),
71
+ tags
72
+ };
73
+
74
+ // Create registry entry
75
+ const entry: RegistryEntry = {
76
+ component,
77
+ metadata,
78
+ lastAccessed: new Date(),
79
+ refCount: 0
80
+ };
81
+
82
+ // Check capacity
83
+ if (this.registry.size >= this.config.maxComponents && this.config.useLRU) {
84
+ this.evictLRU();
85
+ }
86
+
87
+ // Store in registry
88
+ this.registry.set(id, entry);
89
+
90
+ return metadata;
91
+ }
92
+
93
+ /**
94
+ * Gets a component from the registry
95
+ * @param name - Component name
96
+ * @param namespace - Component namespace
97
+ * @param version - Component version
98
+ * @returns The component if found, undefined otherwise
99
+ */
100
+ get(name: string, namespace: string = 'Global', version?: string): any {
101
+ const id = version
102
+ ? this.generateRegistryKey(name, namespace, version)
103
+ : this.findLatestVersion(name, namespace);
104
+
105
+ if (!id) return undefined;
106
+
107
+ const entry = this.registry.get(id);
108
+ if (entry) {
109
+ // Update access time and increment ref count
110
+ entry.lastAccessed = new Date();
111
+ entry.refCount++;
112
+ return entry.component;
113
+ }
114
+
115
+ return undefined;
116
+ }
117
+
118
+ /**
119
+ * Checks if a component exists in the registry
120
+ * @param name - Component name
121
+ * @param namespace - Component namespace
122
+ * @param version - Component version
123
+ * @returns true if the component exists
124
+ */
125
+ has(name: string, namespace: string = 'Global', version?: string): boolean {
126
+ const id = version
127
+ ? this.generateRegistryKey(name, namespace, version)
128
+ : this.findLatestVersion(name, namespace);
129
+
130
+ return id ? this.registry.has(id) : false;
131
+ }
132
+
133
+ /**
134
+ * Removes a component from the registry
135
+ * @param name - Component name
136
+ * @param namespace - Component namespace
137
+ * @param version - Component version
138
+ * @returns true if the component was removed
139
+ */
140
+ unregister(name: string, namespace: string = 'Global', version?: string): boolean {
141
+ const id = version
142
+ ? this.generateRegistryKey(name, namespace, version)
143
+ : this.findLatestVersion(name, namespace);
144
+
145
+ if (!id) return false;
146
+
147
+ return this.registry.delete(id);
148
+ }
149
+
150
+ /**
151
+ * Gets all components in a namespace
152
+ * @param namespace - Namespace to query
153
+ * @returns Array of components in the namespace
154
+ */
155
+ getNamespace(namespace: string): ComponentMetadata[] {
156
+ const components: ComponentMetadata[] = [];
157
+
158
+ for (const entry of this.registry.values()) {
159
+ if (entry.metadata.namespace === namespace) {
160
+ components.push(entry.metadata);
161
+ }
162
+ }
163
+
164
+ return components;
165
+ }
166
+
167
+ /**
168
+ * Gets all registered namespaces
169
+ * @returns Array of unique namespace names
170
+ */
171
+ getNamespaces(): string[] {
172
+ const namespaces = new Set<string>();
173
+
174
+ for (const entry of this.registry.values()) {
175
+ namespaces.add(entry.metadata.namespace);
176
+ }
177
+
178
+ return Array.from(namespaces);
179
+ }
180
+
181
+ /**
182
+ * Gets components by tags
183
+ * @param tags - Tags to search for
184
+ * @returns Array of components matching any of the tags
185
+ */
186
+ getByTags(tags: string[]): ComponentMetadata[] {
187
+ const components: ComponentMetadata[] = [];
188
+
189
+ for (const entry of this.registry.values()) {
190
+ if (entry.metadata.tags?.some(tag => tags.includes(tag))) {
191
+ components.push(entry.metadata);
192
+ }
193
+ }
194
+
195
+ return components;
196
+ }
197
+
198
+ /**
199
+ * Decrements reference count for a component
200
+ * @param name - Component name
201
+ * @param namespace - Component namespace
202
+ * @param version - Component version
203
+ */
204
+ release(name: string, namespace: string = 'Global', version?: string): void {
205
+ const id = version
206
+ ? this.generateRegistryKey(name, namespace, version)
207
+ : this.findLatestVersion(name, namespace);
208
+
209
+ if (!id) return;
210
+
211
+ const entry = this.registry.get(id);
212
+ if (entry && entry.refCount > 0) {
213
+ entry.refCount--;
214
+ }
215
+ }
216
+
217
+ /**
218
+ * Clears all components from the registry
219
+ */
220
+ clear(): void {
221
+ this.registry.clear();
222
+ }
223
+
224
+ /**
225
+ * Gets the current size of the registry
226
+ * @returns Number of registered components
227
+ */
228
+ size(): number {
229
+ return this.registry.size;
230
+ }
231
+
232
+ /**
233
+ * Performs cleanup of unused components
234
+ * @param force - Force cleanup regardless of reference count
235
+ * @returns Number of components removed
236
+ */
237
+ cleanup(force: boolean = false): number {
238
+ const toRemove: string[] = [];
239
+ const now = Date.now();
240
+
241
+ for (const [id, entry] of this.registry) {
242
+ // Remove if no references and hasn't been accessed recently
243
+ const timeSinceAccess = now - entry.lastAccessed.getTime();
244
+ const isUnused = entry.refCount === 0 && timeSinceAccess > this.config.cleanupInterval;
245
+
246
+ if (force || isUnused) {
247
+ toRemove.push(id);
248
+ }
249
+ }
250
+
251
+ for (const id of toRemove) {
252
+ this.registry.delete(id);
253
+ }
254
+
255
+ return toRemove.length;
256
+ }
257
+
258
+ /**
259
+ * Gets registry statistics
260
+ * @returns Object containing registry stats
261
+ */
262
+ getStats(): {
263
+ totalComponents: number;
264
+ namespaces: number;
265
+ totalRefCount: number;
266
+ oldestComponent?: Date;
267
+ newestComponent?: Date;
268
+ } {
269
+ let totalRefCount = 0;
270
+ let oldest: Date | undefined;
271
+ let newest: Date | undefined;
272
+
273
+ for (const entry of this.registry.values()) {
274
+ totalRefCount += entry.refCount;
275
+
276
+ if (!oldest || entry.metadata.registeredAt < oldest) {
277
+ oldest = entry.metadata.registeredAt;
278
+ }
279
+
280
+ if (!newest || entry.metadata.registeredAt > newest) {
281
+ newest = entry.metadata.registeredAt;
282
+ }
283
+ }
284
+
285
+ return {
286
+ totalComponents: this.registry.size,
287
+ namespaces: this.getNamespaces().length,
288
+ totalRefCount,
289
+ oldestComponent: oldest,
290
+ newestComponent: newest
291
+ };
292
+ }
293
+
294
+ /**
295
+ * Destroys the registry and cleans up resources
296
+ */
297
+ destroy(): void {
298
+ this.stopCleanupTimer();
299
+ this.clear();
300
+ }
301
+
302
+ /**
303
+ * Generates a unique registry key
304
+ * @param name - Component name
305
+ * @param namespace - Component namespace
306
+ * @param version - Component version
307
+ * @returns Registry key
308
+ */
309
+ private generateRegistryKey(name: string, namespace: string, version: string): string {
310
+ if (this.config.enableNamespaces) {
311
+ return `${namespace}::${name}@${version}`;
312
+ }
313
+ return `${name}@${version}`;
314
+ }
315
+
316
+ /**
317
+ * Finds the latest version of a component
318
+ * @param name - Component name
319
+ * @param namespace - Component namespace
320
+ * @returns Registry key of latest version or undefined
321
+ */
322
+ private findLatestVersion(name: string, namespace: string): string | undefined {
323
+ let latestKey: string | undefined;
324
+ let latestDate: Date | undefined;
325
+
326
+ for (const [key, entry] of this.registry) {
327
+ if (entry.metadata.name === name &&
328
+ entry.metadata.namespace === namespace) {
329
+ if (!latestDate || entry.metadata.registeredAt > latestDate) {
330
+ latestDate = entry.metadata.registeredAt;
331
+ latestKey = key;
332
+ }
333
+ }
334
+ }
335
+
336
+ return latestKey;
337
+ }
338
+
339
+ /**
340
+ * Evicts the least recently used component
341
+ */
342
+ private evictLRU(): void {
343
+ let lruKey: string | undefined;
344
+ let lruTime: Date | undefined;
345
+
346
+ for (const [key, entry] of this.registry) {
347
+ // Skip components with active references
348
+ if (entry.refCount > 0) continue;
349
+
350
+ if (!lruTime || entry.lastAccessed < lruTime) {
351
+ lruTime = entry.lastAccessed;
352
+ lruKey = key;
353
+ }
354
+ }
355
+
356
+ if (lruKey) {
357
+ this.registry.delete(lruKey);
358
+ }
359
+ }
360
+
361
+ /**
362
+ * Starts the automatic cleanup timer
363
+ */
364
+ private startCleanupTimer(): void {
365
+ this.cleanupTimer = setInterval(() => {
366
+ this.cleanup();
367
+ }, this.config.cleanupInterval);
368
+ }
369
+
370
+ /**
371
+ * Stops the automatic cleanup timer
372
+ */
373
+ private stopCleanupTimer(): void {
374
+ if (this.cleanupTimer) {
375
+ clearInterval(this.cleanupTimer as any);
376
+ this.cleanupTimer = undefined;
377
+ }
378
+ }
379
+ }
@@ -0,0 +1,275 @@
1
+ /**
2
+ * @fileoverview Component dependency resolver for managing component relationships.
3
+ * Handles resolution of child components and dependency graphs.
4
+ * @module @memberjunction/react-runtime/registry
5
+ */
6
+
7
+ import { ComponentRegistry } from './component-registry';
8
+
9
+ /**
10
+ * Component specification interface matching Skip component structure
11
+ */
12
+ export interface ComponentSpec {
13
+ componentName: string;
14
+ componentCode?: string;
15
+ childComponents?: ComponentSpec[];
16
+ components?: ComponentSpec[]; // Alternative property name for children
17
+ }
18
+
19
+ /**
20
+ * Resolved component map for passing to React components
21
+ */
22
+ export interface ResolvedComponents {
23
+ [componentName: string]: any;
24
+ }
25
+
26
+ /**
27
+ * Component dependency resolver.
28
+ * Resolves component hierarchies and manages dependencies between components.
29
+ */
30
+ export class ComponentResolver {
31
+ private registry: ComponentRegistry;
32
+
33
+ /**
34
+ * Creates a new ComponentResolver instance
35
+ * @param registry - Component registry to use for resolution
36
+ */
37
+ constructor(registry: ComponentRegistry) {
38
+ this.registry = registry;
39
+ }
40
+
41
+ /**
42
+ * Resolves all components for a given component specification
43
+ * @param spec - Root component specification
44
+ * @param namespace - Namespace for component resolution
45
+ * @returns Map of component names to resolved components
46
+ */
47
+ resolveComponents(spec: ComponentSpec, namespace: string = 'Global'): ResolvedComponents {
48
+ const resolved: ResolvedComponents = {};
49
+
50
+ // Resolve the component hierarchy
51
+ this.resolveComponentHierarchy(spec, resolved, namespace);
52
+
53
+ return resolved;
54
+ }
55
+
56
+ /**
57
+ * Recursively resolves a component hierarchy
58
+ * @param spec - Component specification
59
+ * @param resolved - Map to store resolved components
60
+ * @param namespace - Namespace for resolution
61
+ * @param visited - Set of visited component names to prevent cycles
62
+ */
63
+ private resolveComponentHierarchy(
64
+ spec: ComponentSpec,
65
+ resolved: ResolvedComponents,
66
+ namespace: string,
67
+ visited: Set<string> = new Set()
68
+ ): void {
69
+ // Prevent circular dependencies
70
+ if (visited.has(spec.componentName)) {
71
+ console.warn(`Circular dependency detected for component: ${spec.componentName}`);
72
+ return;
73
+ }
74
+ visited.add(spec.componentName);
75
+
76
+ // Try to get component from registry
77
+ const component = this.registry.get(spec.componentName, namespace);
78
+ if (component) {
79
+ resolved[spec.componentName] = component;
80
+ }
81
+
82
+ // Process child components (handle both property names)
83
+ const children = spec.childComponents || spec.components || [];
84
+ for (const child of children) {
85
+ this.resolveComponentHierarchy(child, resolved, namespace, visited);
86
+ }
87
+ }
88
+
89
+ /**
90
+ * Validates that all required components are available
91
+ * @param spec - Component specification to validate
92
+ * @param namespace - Namespace for validation
93
+ * @returns Array of missing component names
94
+ */
95
+ validateDependencies(spec: ComponentSpec, namespace: string = 'Global'): string[] {
96
+ const missing: string[] = [];
97
+ const checked = new Set<string>();
98
+
99
+ this.checkDependencies(spec, namespace, missing, checked);
100
+
101
+ return missing;
102
+ }
103
+
104
+ /**
105
+ * Recursively checks for missing dependencies
106
+ * @param spec - Component specification
107
+ * @param namespace - Namespace for checking
108
+ * @param missing - Array to collect missing components
109
+ * @param checked - Set of already checked components
110
+ */
111
+ private checkDependencies(
112
+ spec: ComponentSpec,
113
+ namespace: string,
114
+ missing: string[],
115
+ checked: Set<string>
116
+ ): void {
117
+ if (checked.has(spec.componentName)) return;
118
+ checked.add(spec.componentName);
119
+
120
+ // Check if component exists in registry
121
+ if (!this.registry.has(spec.componentName, namespace)) {
122
+ missing.push(spec.componentName);
123
+ }
124
+
125
+ // Check children
126
+ const children = spec.childComponents || spec.components || [];
127
+ for (const child of children) {
128
+ this.checkDependencies(child, namespace, missing, checked);
129
+ }
130
+ }
131
+
132
+ /**
133
+ * Gets the dependency graph for a component specification
134
+ * @param spec - Component specification
135
+ * @returns Dependency graph as adjacency list
136
+ */
137
+ getDependencyGraph(spec: ComponentSpec): Map<string, string[]> {
138
+ const graph = new Map<string, string[]>();
139
+ const visited = new Set<string>();
140
+
141
+ this.buildDependencyGraph(spec, graph, visited);
142
+
143
+ return graph;
144
+ }
145
+
146
+ /**
147
+ * Recursively builds the dependency graph
148
+ * @param spec - Component specification
149
+ * @param graph - Graph to build
150
+ * @param visited - Set of visited components
151
+ */
152
+ private buildDependencyGraph(
153
+ spec: ComponentSpec,
154
+ graph: Map<string, string[]>,
155
+ visited: Set<string>
156
+ ): void {
157
+ if (visited.has(spec.componentName)) return;
158
+ visited.add(spec.componentName);
159
+
160
+ const children = spec.childComponents || spec.components || [];
161
+ const dependencies = children.map(child => child.componentName);
162
+
163
+ graph.set(spec.componentName, dependencies);
164
+
165
+ // Recursively process children
166
+ for (const child of children) {
167
+ this.buildDependencyGraph(child, graph, visited);
168
+ }
169
+ }
170
+
171
+ /**
172
+ * Performs topological sort on component dependencies
173
+ * @param spec - Root component specification
174
+ * @returns Array of component names in dependency order
175
+ */
176
+ getLoadOrder(spec: ComponentSpec): string[] {
177
+ const graph = this.getDependencyGraph(spec);
178
+ const visited = new Set<string>();
179
+ const stack: string[] = [];
180
+
181
+ // Perform DFS on all nodes
182
+ for (const node of graph.keys()) {
183
+ if (!visited.has(node)) {
184
+ this.topologicalSortDFS(node, graph, visited, stack);
185
+ }
186
+ }
187
+
188
+ // Reverse to get correct load order
189
+ return stack.reverse();
190
+ }
191
+
192
+ /**
193
+ * DFS helper for topological sort
194
+ * @param node - Current node
195
+ * @param graph - Dependency graph
196
+ * @param visited - Set of visited nodes
197
+ * @param stack - Result stack
198
+ */
199
+ private topologicalSortDFS(
200
+ node: string,
201
+ graph: Map<string, string[]>,
202
+ visited: Set<string>,
203
+ stack: string[]
204
+ ): void {
205
+ visited.add(node);
206
+
207
+ const dependencies = graph.get(node) || [];
208
+ for (const dep of dependencies) {
209
+ if (!visited.has(dep)) {
210
+ this.topologicalSortDFS(dep, graph, visited, stack);
211
+ }
212
+ }
213
+
214
+ stack.push(node);
215
+ }
216
+
217
+ /**
218
+ * Resolves components in the correct dependency order
219
+ * @param spec - Root component specification
220
+ * @param namespace - Namespace for resolution
221
+ * @returns Ordered array of resolved components
222
+ */
223
+ resolveInOrder(spec: ComponentSpec, namespace: string = 'Global'): Array<{
224
+ name: string;
225
+ component: any;
226
+ }> {
227
+ const loadOrder = this.getLoadOrder(spec);
228
+ const resolved: Array<{ name: string; component: any }> = [];
229
+
230
+ for (const name of loadOrder) {
231
+ const component = this.registry.get(name, namespace);
232
+ if (component) {
233
+ resolved.push({ name, component });
234
+ }
235
+ }
236
+
237
+ return resolved;
238
+ }
239
+
240
+ /**
241
+ * Creates a flattened list of all component specifications
242
+ * @param spec - Root component specification
243
+ * @returns Array of all component specs in the hierarchy
244
+ */
245
+ flattenComponentSpecs(spec: ComponentSpec): ComponentSpec[] {
246
+ const flattened: ComponentSpec[] = [];
247
+ const visited = new Set<string>();
248
+
249
+ this.collectComponentSpecs(spec, flattened, visited);
250
+
251
+ return flattened;
252
+ }
253
+
254
+ /**
255
+ * Recursively collects component specifications
256
+ * @param spec - Current component specification
257
+ * @param collected - Array to collect specs
258
+ * @param visited - Set of visited component names
259
+ */
260
+ private collectComponentSpecs(
261
+ spec: ComponentSpec,
262
+ collected: ComponentSpec[],
263
+ visited: Set<string>
264
+ ): void {
265
+ if (visited.has(spec.componentName)) return;
266
+ visited.add(spec.componentName);
267
+
268
+ collected.push(spec);
269
+
270
+ const children = spec.childComponents || spec.components || [];
271
+ for (const child of children) {
272
+ this.collectComponentSpecs(child, collected, visited);
273
+ }
274
+ }
275
+ }
@@ -0,0 +1,7 @@
1
+ /**
2
+ * @fileoverview Registry module exports
3
+ * @module @memberjunction/react-runtime/registry
4
+ */
5
+
6
+ export { ComponentRegistry } from './component-registry';
7
+ export { ComponentResolver, ComponentSpec, ResolvedComponents } from './component-resolver';