@object-ui/core 3.3.1 → 3.3.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/CHANGELOG.md +6 -0
- package/dist/registry/Registry.d.ts +47 -0
- package/dist/registry/Registry.js +92 -0
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -55,8 +55,23 @@ export type ComponentConfig<T = any> = ComponentMeta & {
|
|
|
55
55
|
type: string;
|
|
56
56
|
component: ComponentRenderer<T>;
|
|
57
57
|
};
|
|
58
|
+
/**
|
|
59
|
+
* Lazy loader function used by `Registry.registerLazy`. The loader is invoked
|
|
60
|
+
* the first time a missing component type is requested through `getAsync`/the
|
|
61
|
+
* SchemaRenderer fallback path, and is expected to perform a dynamic
|
|
62
|
+
* `import()` of a plugin module whose top-level side-effects call
|
|
63
|
+
* `register()` for that type.
|
|
64
|
+
*/
|
|
65
|
+
export type LazyComponentLoader = () => Promise<unknown>;
|
|
58
66
|
export declare class Registry<T = any> {
|
|
59
67
|
private components;
|
|
68
|
+
private lazyEntries;
|
|
69
|
+
/**
|
|
70
|
+
* Notifies subscribers that the registry has changed (new components
|
|
71
|
+
* registered). Used by SchemaRenderer to re-render after a lazy plugin
|
|
72
|
+
* load completes.
|
|
73
|
+
*/
|
|
74
|
+
private listeners;
|
|
60
75
|
/**
|
|
61
76
|
* Register a component with optional namespace support.
|
|
62
77
|
* If namespace is provided in meta, the component will be registered as "namespace:type".
|
|
@@ -76,6 +91,38 @@ export declare class Registry<T = any> {
|
|
|
76
91
|
* // Accessible as 'button'
|
|
77
92
|
*/
|
|
78
93
|
register(type: string, component: ComponentRenderer<T>, meta?: ComponentMeta): void;
|
|
94
|
+
/**
|
|
95
|
+
* Register a lazy-loaded component. The `loader` is a function returning a
|
|
96
|
+
* dynamic `import()` whose target module performs `register()` calls for
|
|
97
|
+
* the given `type` as a top-level side effect.
|
|
98
|
+
*
|
|
99
|
+
* The loader will be invoked the first time `loadLazy(type)` is called (or
|
|
100
|
+
* the first time the SchemaRenderer encounters an unknown component that
|
|
101
|
+
* matches a registered lazy type). Subsequent registrations are idempotent.
|
|
102
|
+
*
|
|
103
|
+
* @example
|
|
104
|
+
* ComponentRegistry.registerLazy('object-map', () => import('@object-ui/plugin-map'), { namespace: 'plugin-map' });
|
|
105
|
+
*/
|
|
106
|
+
registerLazy(type: string, loader: LazyComponentLoader, meta?: ComponentMeta): void;
|
|
107
|
+
/**
|
|
108
|
+
* Returns true if `type` (or its namespaced form) has a registered lazy
|
|
109
|
+
* loader awaiting first use.
|
|
110
|
+
*/
|
|
111
|
+
hasLazy(type: string, namespace?: string): boolean;
|
|
112
|
+
/**
|
|
113
|
+
* Trigger the lazy loader for `type`, if any. Resolves once the loader
|
|
114
|
+
* completes (whether or not the loaded module actually registered the
|
|
115
|
+
* expected type — caller should re-check the registry afterwards).
|
|
116
|
+
* Returns `undefined` if no lazy entry matches.
|
|
117
|
+
*/
|
|
118
|
+
loadLazy(type: string, namespace?: string): Promise<unknown> | undefined;
|
|
119
|
+
/**
|
|
120
|
+
* Subscribe to registry changes (component registrations). Returns an
|
|
121
|
+
* unsubscribe function. Used by React renderers to re-render when a
|
|
122
|
+
* lazy-loaded plugin finishes registering its components.
|
|
123
|
+
*/
|
|
124
|
+
subscribe(listener: () => void): () => void;
|
|
125
|
+
private notify;
|
|
79
126
|
/**
|
|
80
127
|
* Get a component by type. Supports both namespaced and non-namespaced lookups.
|
|
81
128
|
*
|
|
@@ -13,6 +13,23 @@ export class Registry {
|
|
|
13
13
|
writable: true,
|
|
14
14
|
value: new Map()
|
|
15
15
|
});
|
|
16
|
+
Object.defineProperty(this, "lazyEntries", {
|
|
17
|
+
enumerable: true,
|
|
18
|
+
configurable: true,
|
|
19
|
+
writable: true,
|
|
20
|
+
value: new Map()
|
|
21
|
+
});
|
|
22
|
+
/**
|
|
23
|
+
* Notifies subscribers that the registry has changed (new components
|
|
24
|
+
* registered). Used by SchemaRenderer to re-render after a lazy plugin
|
|
25
|
+
* load completes.
|
|
26
|
+
*/
|
|
27
|
+
Object.defineProperty(this, "listeners", {
|
|
28
|
+
enumerable: true,
|
|
29
|
+
configurable: true,
|
|
30
|
+
writable: true,
|
|
31
|
+
value: new Set()
|
|
32
|
+
});
|
|
16
33
|
}
|
|
17
34
|
/**
|
|
18
35
|
* Register a component with optional namespace support.
|
|
@@ -65,6 +82,81 @@ export class Registry {
|
|
|
65
82
|
...meta
|
|
66
83
|
});
|
|
67
84
|
}
|
|
85
|
+
// A real component is now available — clear any matching lazy stub so we
|
|
86
|
+
// don't keep holding the loader reference, and notify subscribers.
|
|
87
|
+
this.lazyEntries.delete(fullType);
|
|
88
|
+
this.lazyEntries.delete(type);
|
|
89
|
+
this.notify();
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Register a lazy-loaded component. The `loader` is a function returning a
|
|
93
|
+
* dynamic `import()` whose target module performs `register()` calls for
|
|
94
|
+
* the given `type` as a top-level side effect.
|
|
95
|
+
*
|
|
96
|
+
* The loader will be invoked the first time `loadLazy(type)` is called (or
|
|
97
|
+
* the first time the SchemaRenderer encounters an unknown component that
|
|
98
|
+
* matches a registered lazy type). Subsequent registrations are idempotent.
|
|
99
|
+
*
|
|
100
|
+
* @example
|
|
101
|
+
* ComponentRegistry.registerLazy('object-map', () => import('@object-ui/plugin-map'), { namespace: 'plugin-map' });
|
|
102
|
+
*/
|
|
103
|
+
registerLazy(type, loader, meta) {
|
|
104
|
+
const fullType = meta?.namespace ? `${meta.namespace}:${type}` : type;
|
|
105
|
+
const entry = { loader, meta };
|
|
106
|
+
this.lazyEntries.set(fullType, entry);
|
|
107
|
+
if (meta?.namespace && !meta?.skipFallback) {
|
|
108
|
+
this.lazyEntries.set(type, entry);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Returns true if `type` (or its namespaced form) has a registered lazy
|
|
113
|
+
* loader awaiting first use.
|
|
114
|
+
*/
|
|
115
|
+
hasLazy(type, namespace) {
|
|
116
|
+
if (namespace)
|
|
117
|
+
return this.lazyEntries.has(`${namespace}:${type}`);
|
|
118
|
+
return this.lazyEntries.has(type);
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Trigger the lazy loader for `type`, if any. Resolves once the loader
|
|
122
|
+
* completes (whether or not the loaded module actually registered the
|
|
123
|
+
* expected type — caller should re-check the registry afterwards).
|
|
124
|
+
* Returns `undefined` if no lazy entry matches.
|
|
125
|
+
*/
|
|
126
|
+
loadLazy(type, namespace) {
|
|
127
|
+
const key = namespace ? `${namespace}:${type}` : type;
|
|
128
|
+
const entry = this.lazyEntries.get(key);
|
|
129
|
+
if (!entry)
|
|
130
|
+
return undefined;
|
|
131
|
+
if (!entry.pending) {
|
|
132
|
+
entry.pending = entry.loader().catch((err) => {
|
|
133
|
+
// Allow retries on failure by clearing the cached promise.
|
|
134
|
+
entry.pending = undefined;
|
|
135
|
+
throw err;
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
return entry.pending;
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Subscribe to registry changes (component registrations). Returns an
|
|
142
|
+
* unsubscribe function. Used by React renderers to re-render when a
|
|
143
|
+
* lazy-loaded plugin finishes registering its components.
|
|
144
|
+
*/
|
|
145
|
+
subscribe(listener) {
|
|
146
|
+
this.listeners.add(listener);
|
|
147
|
+
return () => {
|
|
148
|
+
this.listeners.delete(listener);
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
notify() {
|
|
152
|
+
for (const listener of this.listeners) {
|
|
153
|
+
try {
|
|
154
|
+
listener();
|
|
155
|
+
}
|
|
156
|
+
catch (err) {
|
|
157
|
+
console.error('[Registry] listener error', err);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
68
160
|
}
|
|
69
161
|
/**
|
|
70
162
|
* Get a component by type. Supports both namespaced and non-namespaced lookups.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@object-ui/core",
|
|
3
|
-
"version": "3.3.
|
|
3
|
+
"version": "3.3.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"license": "MIT",
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"@objectstack/spec": "^4.0.4",
|
|
29
29
|
"lodash": "^4.18.1",
|
|
30
30
|
"zod": "^4.4.3",
|
|
31
|
-
"@object-ui/types": "3.3.
|
|
31
|
+
"@object-ui/types": "3.3.2"
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|
|
34
34
|
"typescript": "^6.0.3",
|