UNPKG

@onehilltech/blueprint

Version:

lightweight, simple, elegant framework for building mean applications

121 lines (96 loc) 3.29 kB
/* * Copyright (c) 2018 One Hill Technologies, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ const assert = require ('assert'); const path = require ('path'); const Loader = require ('./loader'); const { stat, readdir } = require ('fs-extra'); const { forOwn } = require ('lodash'); const LegacyListener = require ('./messaging/legacy-listener'); /** * @class ListenerLoader * * Loader class designed for loading application listeners. */ module.exports = Loader.extend ({ /// The target messenger where the listeners are loaded. The messenger /// must support the following interface/methods: /// /// * emit /// * on /// * once /// app: null, init () { this._super.call (this, ...arguments); assert (!!this.app, "You must define the 'app' property"); }, load (opts) { let {dirname} = opts; assert (!!dirname, 'Your options must have a `dirname` property'); return stat (dirname).then (stats => { return stats.isDirectory () ? readdir (dirname) : {}; }).then (eventNames => { // The name of each directory represents the name of an event. Each file // inside the directory is a listener for the event. let promises = []; let listeners = {}; // Load the listeners for each event in parallel. eventNames.forEach (eventName => { const eventPath = path.join (dirname, eventName); promises.push (this._loadListenersFromPath (eventPath)); }); // Merge the loaded listeners into a single object. return Promise.all (promises).then (results => { eventNames.forEach ((eventName, i) => { let loaded = results[i]; listeners[eventName] = loaded; forOwn (loaded, (listener, name) => { listener.name = name; this.app.on (eventName, listener); }) }); return listeners; }); }).catch (err => { if (err.code && err.code === 'ENOENT') return {}; return Promise.reject (err); }); }, _loadListenersFromPath (eventPath) { const app = this.app; return stat (eventPath).then (stats => { if (!stats.isDirectory ()) return {}; let loader = new Loader (); return loader.load ({ dirname: eventPath, recursive: false, resolve (listener) { // The listener exported from this module is a Listener class. We need to // instantiate the type and store it. Otherwise, we are working with a legacy // listener and need to wrap it in a LegacyListener object. return listener.prototype && !!listener.prototype.handleEvent ? new listener ({app}) : new LegacyListener ({app, listener}); } }); }); } });