UNPKG

ayanami

Version:
118 lines (117 loc) 5.81 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.emitSSREffects = void 0; var tslib_1 = require("tslib"); var rxjs_1 = require("rxjs"); var operators_1 = require("rxjs/operators"); var di_1 = require("@asuka/di"); var ikari_1 = require("../core/ikari"); var utils_1 = require("../core/scope/utils"); var constants_1 = require("./constants"); var ssr_module_1 = require("./ssr-module"); var express_1 = require("./express"); var skipFn = function () { return express_1.SKIP_SYMBOL; }; /** * Run all @SSREffect decorated effects of given modules and extract latest states. * `cleanup` function returned must be called before end of responding * * @param req express request object * @param modules used ayanami modules * @param timeout seconds to wait before all effects stream out TERMINATE_ACTION * @returns object contains ayanami state and cleanup function */ var emitSSREffects = function (req, modules, timeout) { if (timeout === void 0) { timeout = 3; } var stateToSerialize = {}; var cleanup = function () { // non-scope ayanami if (utils_1.ayanamiInstances.has(req)) { utils_1.ayanamiInstances.get(req).forEach(function (instance) { instance[constants_1.CleanupSymbol].call(); }); utils_1.ayanamiInstances.delete(req); } // scoped ayanami if (express_1.reqMap.has(req)) { Array.from(express_1.reqMap.get(req).values()).forEach(function (s) { utils_1.ayanamiInstances.get(s).forEach(function (instance) { instance[constants_1.CleanupSymbol].call(); }); utils_1.ayanamiInstances.delete(s); }); express_1.reqMap.delete(req); } }; return modules.length === 0 ? Promise.resolve({ state: stateToSerialize, cleanup: cleanup }) : rxjs_1.race(rxjs_1.from(modules).pipe(operators_1.flatMap(function (m) { return tslib_1.__awaiter(void 0, void 0, void 0, function () { var constructor, scope, metas, ayanamiInstance, moduleName, ikari, skipCount, _i, metas_1, meta, dispatcher, param, state, existedAyanami, existedIkari; var _a; return tslib_1.__generator(this, function (_b) { switch (_b.label) { case 0: scope = constants_1.DEFAULT_SCOPE_NAME; if ('scope' in m) { constructor = m.module; scope = m.scope; } else { constructor = m; } metas = Reflect.getMetadata(constants_1.SSRSymbol, constructor.prototype); if (!metas) return [3 /*break*/, 7]; ayanamiInstance = di_1.InjectableFactory.initialize(constructor); moduleName = ayanamiInstance[ssr_module_1.moduleNameKey]; ikari = ikari_1.combineWithIkari(ayanamiInstance); skipCount = metas.length - 1; _i = 0, metas_1 = metas; _b.label = 1; case 1: if (!(_i < metas_1.length)) return [3 /*break*/, 5]; meta = metas_1[_i]; dispatcher = ikari.triggerActions[meta.action]; if (!meta.middleware) return [3 /*break*/, 3]; return [4 /*yield*/, meta.middleware(req, skipFn)]; case 2: param = _b.sent(); if (param !== express_1.SKIP_SYMBOL) { dispatcher(param); } else { skipCount -= 1; } return [3 /*break*/, 4]; case 3: dispatcher(void 0); _b.label = 4; case 4: _i++; return [3 /*break*/, 1]; case 5: if (!(skipCount > -1)) return [3 /*break*/, 7]; return [4 /*yield*/, ikari.terminate$ .pipe(operators_1.skip(skipCount), operators_1.take(1)) .toPromise()]; case 6: _b.sent(); ikari.terminate$.next(null); state = ikari.state.getState(); if (stateToSerialize[moduleName]) { stateToSerialize[moduleName][scope] = state; } else { stateToSerialize[moduleName] = (_a = {}, _a[scope] = state, _a); } existedAyanami = utils_1.createOrGetInstanceInScope(constructor, utils_1.createScopeWithRequest(req, scope === constants_1.DEFAULT_SCOPE_NAME ? undefined : scope)); existedIkari = ikari_1.combineWithIkari(existedAyanami); existedIkari.state.setState(state); ayanamiInstance.destroy(); _b.label = 7; case 7: return [2 /*return*/, { state: stateToSerialize, cleanup: cleanup }]; } }); }); })), rxjs_1.timer(timeout * 1000).pipe(operators_1.tap(cleanup), operators_1.flatMap(function () { return rxjs_1.throwError(new Error('Terminate timeout')); }))).toPromise(); }; exports.emitSSREffects = emitSSREffects;