UNPKG

@antv/x6

Version:

JavaScript diagramming library that uses SVG and HTML for rendering.

148 lines (129 loc) 3.81 kB
import { KeyValue } from '../types' import { StringExt, FunctionExt, Platform } from '../util' export class Registry< Entity, Presets = KeyValue<Entity>, OptionalType = never, > { public readonly data: KeyValue<Entity> public readonly options: Registry.Options<Entity | OptionalType> constructor(options: Registry.Options<Entity | OptionalType>) { this.options = { ...options } this.data = (this.options.data as KeyValue<Entity>) || {} this.register = this.register.bind(this) this.unregister = this.unregister.bind(this) } get names() { return Object.keys(this.data) } register( entities: { [name: string]: Entity | OptionalType }, force?: boolean, ): void register<K extends keyof Presets>( name: K, entity: Presets[K], force?: boolean, ): Entity register(name: string, entity: Entity | OptionalType, force?: boolean): Entity register( name: string | { [name: string]: Entity | OptionalType }, options: any, force = false, ) { if (typeof name === 'object') { Object.keys(name).forEach((key) => { this.register(key, name[key], options) }) return } if (this.exist(name) && !force && !Platform.isApplyingHMR()) { this.onDuplicated(name) } const process = this.options.process const entity = process ? FunctionExt.call(process, this as any, name, options) : options this.data[name] = entity return entity } unregister<K extends keyof Presets>(name: K): Entity | null unregister(name: string): Entity | null unregister(name: string): Entity | null { const entity = name ? this.data[name] : null delete this.data[name] return entity } get<K extends keyof Presets>(name: K): Entity | null get(name: string): Entity | null get(name: string): Entity | null { return name ? this.data[name] : null } exist<K extends keyof Presets>(name: K): boolean exist(name: string): boolean exist(name: string): boolean { return name ? this.data[name] != null : false } onDuplicated(name: string) { // eslint-disable-next-line no-useless-catch try { // race if (this.options.onConflict) { FunctionExt.call(this.options.onConflict, this as any, name) } throw new Error( `${StringExt.upperFirst( this.options.type, )} with name '${name}' already registered.`, ) } catch (err) { throw err } } onNotFound(name: string, prefix?: string): never { throw new Error(this.getSpellingSuggestion(name, prefix)) } getSpellingSuggestion(name: string, prefix?: string) { const suggestion = this.getSpellingSuggestionForName(name) const prefixed = prefix ? `${prefix} ${StringExt.lowerFirst(this.options.type)}` : this.options.type return ( // eslint-disable-next-line `${StringExt.upperFirst(prefixed)} with name '${name}' does not exist.${ suggestion ? ` Did you mean '${suggestion}'?` : '' }` ) } protected getSpellingSuggestionForName(name: string) { return StringExt.getSpellingSuggestion( name, Object.keys(this.data), (candidate) => candidate, ) } } export namespace Registry { export interface Options<Entity> { type: string data?: KeyValue<Entity> process?: <T, Context extends Registry<any>>( this: Context, name: string, entity: Entity, ) => T onConflict?: <Context extends Registry<any>>( this: Context, name: string, ) => void } } export namespace Registry { export function create< Entity, Presets = KeyValue<Entity>, OptionalType = never, >(options: Options<Entity | OptionalType>) { return new Registry<Entity, Presets, OptionalType>(options) } }