diff --git a/package.json b/package.json index b0344ae..198a51e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ngn", - "version": "2.0.0-alpha.11", + "version": "2.0.0-alpha.12", "description": "A JavaScript library for building systems and frameworks.", "main": "./src/index.js", "module": "index.js", diff --git a/src/internal.js b/src/internal.js index 7ff3bfc..f25f05f 100644 --- a/src/internal.js +++ b/src/internal.js @@ -36,7 +36,69 @@ export const plugins = new Proxy(globalThis[REFERENCE_ID], { } }) -export const LEDGER = new EventEmitter({ +class LedgerEventEmitter extends EventEmitter { + #events = new Map() + + /** + * Create a custom ledger event type and reference method. + * + * ``` + * // Create the event type and method name + * const [EXAMPLE_EVENT_TYPE, fireCustomEvent] = NGN.LEDGER.createEventType('Custom Event Name') + * + * // Listen for the new event type + * NGN.LEDGER.on(EXAMPLE_EVENT_TYPE, function (payloadData) { + * console.log(`Event: "${this.event}"`) + * console.log(payloadData) + * }) + * + * // Emit an event to the ledger + * fireCustomEvent('my.custom.event', { payload: 'data' }) + * ``` + * @param {string} eventName + * Name of the event reference, such as `EXAMPLE_EVENT`. + */ + registerEventType (eventName) { + if (this.#events.has(eventName)) { + throw new Error(`"${eventName}" already exists.`) + } + + const CUSTOM_EVENT = Symbol(eventName) + const emitterFn = function () { + LEDGER_EVENT(CUSTOM_EVENT)(...arguments) + } + this.#events.set(eventName, emitterFn) + + return [CUSTOM_EVENT, emitterFn] + } + + /** + * @property {object} events + * A collection of ledger events (built-in & custom) + */ + get events () { + return Object.assign({ + INFO_EVENT, + WARN_EVENT, + ERROR_EVENT, + INTERNAL_EVENT + }, Object.fromEntries(this.#events)) + } + + /** + * @property {object} emitters + * A collection of ledger event emitters (by event type). + */ + get emitters () { + const methods = { INFO, WARN, ERROR, INTERNAL } + for (const [name, fn] of Object.entries(this.#events)) { + methods[name] = fn + } + return methods + } +} + +export const LEDGER = new LedgerEventEmitter({ name: 'NGN Ledger', description: 'A ledger of events, outputs, and information produced by the system.' }) diff --git a/tests/04-emitter-basic.js b/tests/04-emitter-basic.js index ada97b3..50e4f79 100644 --- a/tests/04-emitter-basic.js +++ b/tests/04-emitter-basic.js @@ -297,6 +297,22 @@ test('NGN.BUS Special Events', t => { NGN.WARN('message') }) +test('NGN.LEDGER Custom Events', t => { + const [EXAMPLE_EVENT, customLedgerEventEmitter] = NGN.LEDGER.registerEventType('EXAMPLE_EVENT') + + t.expect('symbol', typeof EXAMPLE_EVENT, 'Registered custom event type') + t.expect('function', typeof customLedgerEventEmitter, 'Registered ledger custom event emitter') + + NGN.LEDGER.once(EXAMPLE_EVENT, function (label, payload) { + t.pass('EXAMPLE_EVENT custom ledger event recognized') + t.expect('my.event', label, 'Developer-specified custom label recognized') + t.expect('object', typeof payload, 'Payload recognized') + t.end() + }) + + customLedgerEventEmitter('my.event', { payload: true }) +}) + test('pool()', t => { ee = new EventEmitter() let count = 0