UNPKG

@fabrix/spool-broadcast

Version:

Spool: broadcast for Fabrix to implement CQRS and Event Sourcing

240 lines 10.2 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; result["default"] = mod; return result; }; Object.defineProperty(exports, "__esModule", { value: true }); const extension_1 = require("@fabrix/fabrix/dist/common/spools/extension"); const broadcaster_1 = require("./broadcaster"); const validator_1 = require("./validator"); const config = __importStar(require("./config/index")); const api = __importStar(require("./api/index")); const pkg = __importStar(require("../package.json")); const errors_1 = require("./errors"); const errors_2 = require("@fabrix/spool-errors/dist/errors"); class BroadcastSpool extends extension_1.ExtensionSpool { constructor(app) { super(app, { config: config, pkg: pkg, api: api }); this.channelMap = new Map(); this.pipelineMap = new Map(); this.hookMap = new Map(); this.processorMap = new Map(); this.projectorMap = new Map(); this.extensions = { broadcaster: { get: () => { return this.broadcaster; }, set: (newInstances) => { throw new Error('broadcaster can not be set through FabrixApp, check spool-broadcaster instead'); }, enumerable: true, configurable: true }, broadcastSeries: { get: () => { return this.mapSeries; }, set: (newInstances) => { throw new Error('broadcastSeries can not be set through FabrixApp, check spool-broadcast instead'); }, enumerable: true, configurable: true }, broadcastTransaction: { get: () => { return this.transaction; }, set: (newInstances) => { throw new Error('broadcastTransaction can not be set through FabrixApp, check spool-broadcast instead'); }, enumerable: true, configurable: true }, }; } mapSeries(...args) { if (this && this.spools && this.spools.sequelize) { return this.spools.broadcast.Sequelize().Promise.mapSeries(...args); } else { throw new Error('Spool Sequelize is not yet loaded'); } } Sequelize() { const app = this.app || this; if (!app.spools.sequelize) { throw new Error('Spool-sequelize is not loaded!'); } return app.spools.sequelize._datastore; } action(func, req, body, options = {}) { if (typeof func !== 'function') { throw new Error(`action ${func} is not a function`); } return func(req, body, options) .catch(err => { if (!err.code) { const error = new errors_2.GenericError('E_NOT_FOUND', 'Not found', `${func.constructor.name} Action Error`); } else { throw new err; } }); } transaction(func, req, body, options = {}) { const app = this.app || this; if (typeof func !== 'function') { throw new Error(`transaction ${func} is not a function`); } if (options.transaction === false || this.app.config.get('broadcast.auto_transaction') === false) { return func(req, body, options); } else { if (!app.models.BroadcastEvent.sequelize) { throw new Error('Sequelize is not available on BroadcastEvent!'); } if (options.parent && options.parent.transaction) { return app.models.BroadcastEvent.sequelize.transaction({ transaction: options.parent.transaction }, t => { options.transaction = t; app.log.debug(`Broadcast adding transaction ${t.id} to parent ${options.parent.transaction.id}`); return func(req, body, options); }); } else if (options.transaciton) { app.log.debug(`Broadcast on same transaction ${options.transaction.id}`); return func(req, body, options); } else { return app.models.BroadcastEvent.sequelize.transaction({ isolationLevel: this.app.spools.sequelize._datastore.Transaction.ISOLATION_LEVELS.READ_UNCOMMITTED, deferrable: this.app.spools.sequelize._datastore.Deferrable.SET_DEFERRED }, t => { options.transaction = t; app.log.debug(`Broadcast new transaction ${options.transaction.id}`); return func(req, body, options); }); } } } models(name) { if (!name || !this.app.models[name]) { throw new Error(`${name} is not a valid model`); } return this.app.models[name]; } entries(name) { if (!name || !this.app.entries[name]) { throw new Error(`${name} is not a valid entry`); } return this.app.entries[name]; } validate() { return __awaiter(this, void 0, void 0, function* () { const requiredSpools = [ 'sequelize', 'realtime', 'errors' ]; const oneOfSpools = [ 'express', 'polka', 'hapi' ]; const spools = Object.keys(this.app.spools); if (!spools.some(v => requiredSpools.indexOf(v) === -1)) { return Promise.reject(new errors_1.ConfigError('E_PRECONDITION_FAILED', `spool-broadcast requires spools: ${requiredSpools.join(', ')}!`)); } if (!spools.some(v => oneOfSpools.indexOf(v) === -1)) { return Promise.reject(new errors_1.ConfigError('E_PRECONDITION_FAILED', `spool-broadcast requires at least one of spools: ${oneOfSpools.join(', ')}!`)); } if (!this.app.config.get('broadcast')) { return Promise.reject(new errors_1.ConfigError('E_PRECONDITION_FAILED', 'No configuration found at config.broadcast!')); } if (!this.app.config.get('realtime')) { return Promise.reject(new errors_1.ConfigError('E_PRECONDITION_FAILED', 'No configuration found at config.realtime!')); } return Promise.all([ validator_1.Validator.validateBroadcastConfig(this.app.config.get('broadcast')), validator_1.Validator.validateRealtimeConfig(this.app.config.get('realtime')) ]) .catch(err => { return Promise.reject(err); }); }); } configure() { return __awaiter(this, void 0, void 0, function* () { yield Promise.all([ broadcaster_1.broadcaster.configure(this.app), broadcaster_1.broadcaster.discoverChannels(this.app), broadcaster_1.broadcaster.discoverPipelines(this.app), broadcaster_1.broadcaster.discoverHooks(this.app), broadcaster_1.broadcaster.discoverProjectors(this.app), broadcaster_1.broadcaster.discoverProcessors(this.app), broadcaster_1.broadcaster.discoverDispatchers(this.app), broadcaster_1.broadcaster.buildBroadcaster(this.app), broadcaster_1.broadcaster.addModelHooks(this.app), broadcaster_1.broadcaster.copyDefaults(this.app) ]) .catch(err => { return Promise.reject(err); }); }); } initialize() { return __awaiter(this, void 0, void 0, function* () { yield Promise.all([ broadcaster_1.broadcaster.addBroadcasts(this.app), broadcaster_1.broadcaster.makeChannelMap(this.app), broadcaster_1.broadcaster.makePipelineMap(this.app), broadcaster_1.broadcaster.makeHookMap(this.app), broadcaster_1.broadcaster.makeProjectorMap(this.app), broadcaster_1.broadcaster.makeProcessorMap(this.app), ]) .then((maps) => { return broadcaster_1.broadcaster.makeBroadcastChannelResources(this.app); }) .catch(err => { return Promise.reject(err); }); }); } unload() { return __awaiter(this, void 0, void 0, function* () { return broadcaster_1.broadcaster.shutdownBroadcaster(this.app) .catch(err => { return Promise.reject(err); }); }); } sanity() { return __awaiter(this, void 0, void 0, function* () { this.app.log.silly('BroadcastChannel Map', this.channelMap); this.app.log.silly('Pipeline Map', this.pipelineMap); this.app.log.silly('Hook Map', this.hookMap); this.app.log.silly('Projector Map', this.projectorMap); this.app.log.silly('Processor Map', this.processorMap); return Promise.resolve(); }); } } exports.BroadcastSpool = BroadcastSpool; //# sourceMappingURL=BroadcastSpool.js.map