0
# Core Models & Utilities
1
2
This module provides the foundational infrastructure classes and utility functions that power the entire @superset-ui/core ecosystem. It includes the registry system for managing extensible collections, the plugin architecture, and essential utility functions for common operations.
3
4
## Overview
5
6
The core models and utilities are designed around the principle of extensibility and type safety. The Registry system provides a flexible foundation for managing collections of items with support for lazy loading, while the Plugin and Preset classes enable modular architecture patterns.
7
8
## Registry System
9
10
The Registry system is the backbone of @superset-ui/core's extensible architecture, providing type-safe collections with support for synchronous values, asynchronous loaders, and change notifications.
11
12
### Registry { .api }
13
14
Generic registry for storing and retrieving items by key with support for lazy loading:
15
16
```typescript
17
import { Registry, OverwritePolicy } from '@superset-ui/core';
18
19
interface RegistryConfig {
20
name?: string;
21
overwritePolicy?: OverwritePolicy;
22
}
23
24
class Registry<V, W extends InclusiveLoaderResult<V> = InclusiveLoaderResult<V>> {
25
constructor(config?: RegistryConfig);
26
27
// Registration methods
28
registerValue(key: string, value: V): this;
29
registerLoader(key: string, loader: () => W): this;
30
31
// Retrieval methods
32
get(key: string): V | W | undefined;
33
getAsPromise(key: string): Promise<V>;
34
getMap(): { [key: string]: V | W | undefined };
35
getMapAsPromise(): Promise<{ [key: string]: V }>;
36
37
// Collection methods
38
has(key: string): boolean;
39
keys(): string[];
40
values(): RegistryValue<V, W>[];
41
valuesAsPromise(): Promise<V[]>;
42
entries(): RegistryEntry<V, W>[];
43
entriesAsPromise(): Promise<{ key: string; value: V }[]>;
44
45
// Management methods
46
clear(): this;
47
remove(key: string): this;
48
49
// Event handling
50
addListener(listener: (keys: Set<string>) => void): void;
51
removeListener(listener: (keys: Set<string>) => void): void;
52
53
// Properties
54
readonly name: string;
55
readonly overwritePolicy: OverwritePolicy;
56
}
57
58
type InclusiveLoaderResult<V> = V | Promise<V>;
59
60
type RegistryValue<V, W extends InclusiveLoaderResult<V>> = V | W | undefined;
61
62
interface RegistryEntry<V, W extends InclusiveLoaderResult<V>> {
63
key: string;
64
value: RegistryValue<V, W>;
65
}
66
```
67
68
#### OverwritePolicy { .api }
69
70
Enumeration defining how the registry handles key overwrites:
71
72
```typescript
73
enum OverwritePolicy {
74
ALLOW = 'ALLOW', // Allow overwrites silently
75
PROHIBIT = 'PROHIBIT', // Throw error on overwrite
76
WARN = 'WARN' // Log warning on overwrite
77
}
78
```
79
80
### RegistryWithDefaultKey { .api }
81
82
Extended registry that supports a default key for simplified retrieval:
83
84
```typescript
85
import { RegistryWithDefaultKey } from '@superset-ui/core';
86
87
interface RegistryWithDefaultKeyConfig extends RegistryConfig {
88
initialDefaultKey?: string;
89
setFirstItemAsDefault?: boolean;
90
}
91
92
class RegistryWithDefaultKey<V, W extends InclusiveLoaderResult<V> = InclusiveLoaderResult<V>>
93
extends Registry<V, W> {
94
95
constructor(config?: RegistryWithDefaultKeyConfig);
96
97
// Override get to use default key when no key provided
98
get(key?: string): V | W | undefined;
99
100
// Default key management
101
getDefaultKey(): string | undefined;
102
setDefaultKey(key: string): this;
103
clearDefaultKey(): this;
104
105
// Properties
106
readonly initialDefaultKey?: string;
107
readonly setFirstItemAsDefault: boolean;
108
}
109
```
110
111
### Usage Examples
112
113
#### Basic Registry Usage
114
115
```typescript
116
import { Registry, OverwritePolicy } from '@superset-ui/core';
117
118
// Create a registry for string values
119
const messageRegistry = new Registry<string>({
120
name: 'messages',
121
overwritePolicy: OverwritePolicy.WARN
122
});
123
124
// Register values
125
messageRegistry.registerValue('greeting', 'Hello World');
126
messageRegistry.registerValue('farewell', 'Goodbye');
127
128
// Retrieve values
129
const greeting = messageRegistry.get('greeting'); // "Hello World"
130
const keys = messageRegistry.keys(); // ["greeting", "farewell"]
131
```
132
133
#### Lazy Loading with Loaders
134
135
```typescript
136
// Registry with lazy-loaded components
137
const componentRegistry = new Registry<React.ComponentType>();
138
139
// Register a loader function
140
componentRegistry.registerLoader('MyChart', () =>
141
import('./charts/MyChart').then(module => module.default)
142
);
143
144
// Get component asynchronously
145
const MyChart = await componentRegistry.getAsPromise('MyChart');
146
```
147
148
#### Registry with Default Key
149
150
```typescript
151
import { RegistryWithDefaultKey } from '@superset-ui/core';
152
153
const formatterRegistry = new RegistryWithDefaultKey<NumberFormatter>({
154
initialDefaultKey: 'default',
155
setFirstItemAsDefault: true
156
});
157
158
formatterRegistry.registerValue('percent', percentFormatter);
159
formatterRegistry.registerValue('currency', currencyFormatter);
160
161
// Get default formatter (first registered)
162
const defaultFormatter = formatterRegistry.get(); // percentFormatter
163
```
164
165
## Plugin Architecture
166
167
The Plugin and Preset classes provide the foundation for building modular, configurable applications.
168
169
### Plugin { .api }
170
171
Base class for creating extensible plugins with configurable options:
172
173
```typescript
174
import { Plugin } from '@superset-ui/core';
175
176
interface PlainObject {
177
[key: string]: any;
178
}
179
180
class Plugin {
181
config: PlainObject;
182
183
constructor();
184
185
// Configuration methods
186
configure(config: PlainObject, replace?: boolean): this;
187
resetConfig(): this;
188
189
// Lifecycle methods
190
register(): this;
191
unregister(): this;
192
}
193
```
194
195
### Preset { .api }
196
197
Container for grouping and managing multiple presets and plugins:
198
199
```typescript
200
import { Preset, Plugin } from '@superset-ui/core';
201
202
interface PresetConfig {
203
name?: string;
204
description?: string;
205
presets?: Preset[];
206
plugins?: Plugin[];
207
}
208
209
class Preset {
210
readonly name: string;
211
readonly description: string;
212
readonly presets: Preset[];
213
readonly plugins: Plugin[];
214
215
constructor(config?: PresetConfig);
216
217
// Register all nested presets and plugins
218
register(): this;
219
}
220
```
221
222
### ExtensibleFunction { .api }
223
224
Utility class that extends Function to enable creating extensible function objects:
225
226
```typescript
227
import { ExtensibleFunction } from '@superset-ui/core';
228
229
class ExtensibleFunction {
230
constructor(fn: Function);
231
}
232
```
233
234
### Usage Examples
235
236
#### Creating Custom Plugins
237
238
```typescript
239
import { Plugin } from '@superset-ui/core';
240
241
class ChartPlugin extends Plugin {
242
constructor(config: { chartType: string; metadata: any }) {
243
super();
244
this.configure(config);
245
}
246
247
register() {
248
// Register chart with global registry
249
getChartRegistry().registerValue(this.config.chartType, this);
250
return this;
251
}
252
}
253
254
// Usage
255
const barChartPlugin = new ChartPlugin({
256
chartType: 'bar',
257
metadata: { name: 'Bar Chart', description: 'Simple bar chart' }
258
});
259
260
barChartPlugin.register();
261
```
262
263
#### Organizing with Presets
264
265
```typescript
266
import { Preset } from '@superset-ui/core';
267
268
const chartPreset = new Preset({
269
name: 'StandardCharts',
270
description: 'Standard chart collection',
271
plugins: [
272
new BarChartPlugin(),
273
new LineChartPlugin(),
274
new PieChartPlugin()
275
]
276
});
277
278
// Register all charts at once
279
chartPreset.register();
280
```
281
282
## Utility Functions
283
284
Essential utility functions for common operations throughout the Superset ecosystem.
285
286
### Type Utilities { .api }
287
288
Functions for type checking and conversion:
289
290
```typescript
291
import {
292
isDefined,
293
ensureIsArray,
294
ensureIsInt,
295
isEqualArray
296
} from '@superset-ui/core';
297
298
// Type guards and checks
299
function isDefined(value: unknown): boolean;
300
function isRequired(fieldName: string): never;
301
302
// Array utilities
303
function ensureIsArray<T>(value?: T[] | T | null): T[];
304
function isEqualArray<T extends unknown[] | undefined | null>(
305
arrA: T,
306
arrB: T
307
): boolean;
308
309
// Number conversion
310
function ensureIsInt<T>(value: T, defaultValue?: number): number;
311
```
312
313
### Object Utilities { .api }
314
315
Functions for object manipulation and transformation:
316
317
```typescript
318
import {
319
convertKeysToCamelCase,
320
removeDuplicates
321
} from '@superset-ui/core';
322
323
// Object key transformation
324
function convertKeysToCamelCase<T>(object: T): T;
325
326
// Array deduplication
327
function removeDuplicates<T>(
328
items: T[],
329
hash?: (item: T) => unknown
330
): T[];
331
```
332
333
### Async Utilities { .api }
334
335
Functions for asynchronous operations and timing:
336
337
```typescript
338
import { promiseTimeout, makeSingleton } from '@superset-ui/core';
339
340
// Promise-based setTimeout
341
function promiseTimeout<T>(
342
func: (...args: unknown[]) => T,
343
delay?: number
344
): Promise<T>;
345
346
// Singleton pattern helper
347
function makeSingleton<T, Args extends unknown[]>(
348
BaseClass: new (...args: Args) => T,
349
...args: Args
350
): () => T;
351
```
352
353
### Logging Utilities { .api }
354
355
Safe logging interface with console method fallbacks:
356
357
```typescript
358
import { logging } from '@superset-ui/core';
359
360
interface Logger {
361
log: (...args: unknown[]) => void;
362
debug: (...args: unknown[]) => void;
363
info: (...args: unknown[]) => void;
364
warn: (...args: unknown[]) => void;
365
error: (...args: unknown[]) => void;
366
trace: (...args: unknown[]) => void;
367
table: (...args: unknown[]) => void;
368
}
369
370
const logging: Logger;
371
```
372
373
### Feature Flags { .api }
374
375
Feature flag system for conditional functionality:
376
377
```typescript
378
import { FeatureFlag, isFeatureEnabled } from '@superset-ui/core';
379
380
enum FeatureFlag {
381
ALLOW_DASHBOARD_DOMAIN_SHARDING = 'ALLOW_DASHBOARD_DOMAIN_SHARDING',
382
ALERT_REPORTS = 'ALERT_REPORTS',
383
OMNIBAR = 'OMNIBAR',
384
// ... 30+ additional flags
385
}
386
387
function isFeatureEnabled(feature: FeatureFlag): boolean;
388
```
389
390
### Random Number Generation { .api }
391
392
Seeded random number generation for consistent results:
393
394
```typescript
395
import { seed, seedRandom } from '@superset-ui/core';
396
397
// Create seeded PRNG
398
function seed(seedValue: string): () => number;
399
400
// Pre-seeded random function
401
function seedRandom(): number;
402
```
403
404
## Usage Examples
405
406
### Complete Registry Setup
407
408
```typescript
409
import {
410
Registry,
411
OverwritePolicy,
412
Plugin,
413
logging
414
} from '@superset-ui/core';
415
416
// Create formatter registry
417
const formatterRegistry = new Registry<NumberFormatter>({
418
name: 'NumberFormatters',
419
overwritePolicy: OverwritePolicy.WARN
420
});
421
422
// Add change listener
423
formatterRegistry.addListener((changedKeys) => {
424
logging.info('Formatters updated:', Array.from(changedKeys));
425
});
426
427
// Register formatters
428
formatterRegistry.registerValue('percent', new PercentFormatter());
429
formatterRegistry.registerLoader('currency', () =>
430
import('./formatters/CurrencyFormatter').then(m => new m.default())
431
);
432
```
433
434
### Plugin Development Pattern
435
436
```typescript
437
import { Plugin, Registry, isFeatureEnabled, FeatureFlag } from '@superset-ui/core';
438
439
class CustomVisualizationPlugin extends Plugin {
440
constructor(config: { name: string; component: React.ComponentType }) {
441
super();
442
this.configure(config);
443
}
444
445
register() {
446
if (!isFeatureEnabled(FeatureFlag.CUSTOM_VISUALIZATIONS)) {
447
return this;
448
}
449
450
// Register with visualization registry
451
getVisualizationRegistry().registerValue(
452
this.config.name,
453
this.config.component
454
);
455
456
return this;
457
}
458
}
459
```
460
461
## Related Documentation
462
463
- [Plugin System](./plugin-system.md) - Chart plugins and dynamic loading
464
- [Data Formatting](./data-formatting.md) - Formatter registries and usage
465
- [UI & Styling](./ui-styling.md) - Theme system architecture