UNPKG

@fleetbase/ember-core

Version:

Provides all the core services, decorators and utilities for building a Fleetbase extension for the Console.

211 lines (195 loc) 5.64 kB
import BaseContract from './base-contract'; import { guidFor } from '@ember/object/internals'; import isObject from '../utils/is-object'; /** * Represents a lifecycle or application hook * * Hooks allow extensions to inject custom logic at specific points in the application lifecycle. * * @class Hook * @extends BaseContract * * @example * // Simple hook with chaining * new Hook('application:before-model', (session, router) => { * if (session.isCustomer) { * router.transitionTo('customer-portal'); * } * }) * * @example * // Full definition object (first-class) * new Hook({ * name: 'application:before-model', * handler: (session, router) => { * if (session.isCustomer) { * router.transitionTo('customer-portal'); * } * }, * priority: 10, * once: false, * id: 'customer-redirect' * }) * * @example * // Hook with method chaining * new Hook('order:before-save') * .withPriority(10) * .once() * .execute(async (order) => { * await validateOrder(order); * }) */ export default class Hook extends BaseContract { /** * Create a new Hook * * @constructor * @param {String|Object} nameOrDefinition Hook name or full definition object * @param {Function} handlerOrOptions Handler function or options object (only used if first param is string) */ constructor(nameOrDefinition, handlerOrOptions = null) { // Prepare options for super const options = typeof handlerOrOptions === 'function' ? { handler: handlerOrOptions } : handlerOrOptions || {}; // Call super FIRST (JavaScript requirement) super(isObject(nameOrDefinition) && nameOrDefinition.name ? nameOrDefinition : { name: nameOrDefinition, ...options }); // THEN set properties if (isObject(nameOrDefinition) && nameOrDefinition.name) { const definition = nameOrDefinition; this.name = definition.name; this.handler = definition.handler || null; this.priority = definition.priority !== undefined ? definition.priority : 0; this.runOnce = definition.once || false; this.id = definition.id || guidFor(this); this.enabled = definition.enabled !== undefined ? definition.enabled : true; } else { this.name = nameOrDefinition; this.handler = options.handler || null; this.priority = options.priority || 0; this.runOnce = options.once || false; this.id = options.id || guidFor(this); this.enabled = options.enabled !== undefined ? options.enabled : true; } // Call setup() to trigger validation after properties are set super.setup(); } /** * Validate the hook * * @method validate * @throws {Error} If name is missing */ validate() { if (!this.name) { throw new Error('Hook requires a name'); } } /** * Set the hook handler function * * @method execute * @param {Function} handler The handler function * @returns {Hook} This instance for chaining */ execute(handler) { this.handler = handler; this._options.handler = handler; return this; } /** * Set the hook priority * Lower numbers execute first * * @method withPriority * @param {Number} priority Priority value * @returns {Hook} This instance for chaining */ withPriority(priority) { this.priority = priority; this._options.priority = priority; return this; } /** * Mark this hook to run only once * After execution, it will be automatically removed * * @method once * @returns {Hook} This instance for chaining */ once() { this.runOnce = true; this._options.once = true; return this; } /** * Set a unique ID for this hook * Useful for removing specific hooks later * * @method withId * @param {String} id Unique identifier * @returns {Hook} This instance for chaining */ withId(id) { this.id = id; this._options.id = id; return this; } /** * Enable or disable the hook * * @method setEnabled * @param {Boolean} enabled Whether the hook is enabled * @returns {Hook} This instance for chaining */ setEnabled(enabled) { this.enabled = enabled; this._options.enabled = enabled; return this; } /** * Disable the hook * * @method disable * @returns {Hook} This instance for chaining */ disable() { return this.setEnabled(false); } /** * Enable the hook * * @method enable * @returns {Hook} This instance for chaining */ enable() { return this.setEnabled(true); } /** * Add metadata to the hook * * @method withMetadata * @param {Object} metadata Metadata object * @returns {Hook} This instance for chaining */ withMetadata(metadata) { this._options.metadata = metadata; return this; } /** * Get the plain object representation * * @method toObject * @returns {Object} Plain object with all hook properties */ toObject() { return { name: this.name, handler: this.handler, priority: this.priority, once: this.runOnce, id: this.id, enabled: this.enabled, ...this._options, }; } }