/** * Only instances that are children of a Registerable can be registered into the * registry. */ export class Registerable { constructor({ app } = {}) { this.app = app } /** * Must return a string with the unique name, this must be the same as the * type used in the backend. */ static getType() { throw new Error('The type of a registry must be set.') } getType() { return this.constructor.getType() } get type() { return this.constructor.getType() } set type(newType) { // Does nothing as the type shouldn't be modifiable } /** * Returns a weight to order the registerable. Used when you want an ordered list * of all registered items. * @returns order weight. Lower value first in the list. */ getSort() { return 0 } $t(key) { const { i18n } = this.app return i18n.t(key) } } /** * The registry is an class where Registerable instances can be registered under a * namespace. This is used for plugins to register extra functionality to Baserow. For * example the database plugin registers itself as an application to the core, but * it is also possible to register fields and views to the database plugin. */ export class Registry { constructor() { this.registry = {} } /** * Registers an empty namespace. */ registerNamespace(namespace) { this.registry[namespace] = {} } /** * Registers a new Registerable object under the provided namespace in the registry. * If the namespace doesn't exist it will be created. It is common to register * instantiated classes here. */ register(namespace, object) { if (!(object instanceof Registerable)) { throw new TypeError( 'The registered object must be an instance of Registrable.' ) } const type = object.getType() if (!Object.prototype.hasOwnProperty.call(this.registry, namespace)) { this.registry[namespace] = {} } this.registry[namespace][type] = object } /** * Un-registers a registered type from the provided namespace in the * registry. Throws an error if the registry does not exist. Returns true if the * type was found and deleted successfully, or false if the type did not exist in * the namespace. */ unregister(namespace, type) { if (!Object.prototype.hasOwnProperty.call(this.registry, namespace)) { throw new Error( `The namespace ${namespace} is not found in the registry.` ) } return delete this.registry[namespace][type] } /** * Returns a registered object with the given type in the provided namespace. */ get(namespace, type) { if (!Object.prototype.hasOwnProperty.call(this.registry, namespace)) { throw new Error( `The namespace ${namespace} is not found in the registry.` ) } if (!Object.prototype.hasOwnProperty.call(this.registry[namespace], type)) { throw new Error( `The type ${type} is not found under namespace ${namespace} in the registry.` ) } return this.registry[namespace][type] } /** * Returns all the objects that are in the given namespace. */ getAll(namespace) { if (!Object.prototype.hasOwnProperty.call(this.registry, namespace)) { throw new Error( `The namespace ${namespace} is not found in the registry.` ) } return this.registry[namespace] } /** * Returns a list of the objects that are in the given namespace ordered by their * `.getOrder()` value. Lower value first then for equality, the insertion order is * considered. */ getOrderedList(namespace) { return Object.values(this.getAll(namespace)).sort( (typeA, typeB) => typeA.getOrder() - typeB.getOrder() ) } /** * Returns true if the object of the given type exists in the namespace. */ exists(namespace, type) { if (!Object.prototype.hasOwnProperty.call(this.registry, namespace)) { return false } if (!Object.prototype.hasOwnProperty.call(this.registry[namespace], type)) { return false } return true } }