UNPKG

@kitmi/jacaranda

Version:

JavaScript application framework

233 lines (232 loc) 9.16 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); function _export(target, all) { for(var name in all)Object.defineProperty(target, name, { enumerable: true, get: all[name] }); } _export(exports, { createWebServer: function() { return createWebServer; }, default: function() { return _default; } }); const _nodepath = /*#__PURE__*/ _interop_require_default(require("node:path")); const _utils = require("@kitmi/utils"); const _types = require("@kitmi/types"); const _Runnable = /*#__PURE__*/ _interop_require_default(require("./Runnable")); const _Routable = /*#__PURE__*/ _interop_require_default(require("./Routable")); const _ServiceContainer = /*#__PURE__*/ _interop_require_default(require("./ServiceContainer")); const _defaultServerOpts = /*#__PURE__*/ _interop_require_default(require("./defaultServerOpts")); const _middlewares = /*#__PURE__*/ _interop_require_wildcard(require("./middlewares")); function _interop_require_default(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); } function _interop_require_wildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = { __proto__: null }; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for(var key in obj){ if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } const isEsm = (0, _utils.isRunAsEsm)(); function createWebServer(Base) { /** * Web server class. * @class * @extends Routable(App) */ return class extends (0, _Routable.default)(Base) { async stop_() { let stopByThis = false; if (this.started) { stopByThis = true; if (this.appModules) { await (0, _utils.batchAsync_)(this.appModules, (app)=>app.stop_()); delete this.appModules; delete this.appModulesByAlias; } } if (stopByThis && this.httpServer) { await new Promise((resolve, reject)=>{ this.httpServer.close((err)=>{ if (err) return reject(err); resolve(); }); }); delete this.httpServer; this.log('info', `The http service is stopped.`); } return super.stop_(); } visitChildModules(vistor) { super.visitChildModules(vistor); if (this.appModules) { _utils._.each(this.appModules, vistor); } } /** * Mount an app at specified route. * @param {WebModule} app */ mountApp(app) { if (!this.appModules) { this.appModules = {}; this.appModulesByAlias = {}; } if (app.route in this.appModules) { throw new Error(`The route "${app.route}" is already mounted by another app.`); } this.engine.mount(app.route, app.router); this.appModules[app.route] = app; if (app.name in this.appModulesByAlias) { const existingApp = this.appModulesByAlias[app.name]; existingApp.alias = `${existingApp.name}@${existingApp.route}]`; //move bucket this.appModulesByAlias[existingApp.alias] = existingApp; delete this.appModulesByAlias[app.name]; app.alias = `${app.name}@${app.route}]`; } else { app.alias = app.name; } this.appModulesByAlias[app.alias] = app; this.log('verbose', `All routes from app [${app.alias}] are mounted under "${app.route}".`); } /** * Get the app module object by base route * @param {string} p - App module base route started with "/" */ getAppByRoute(p) { return this.appModules[p]; } /** * Get the app module object by app alias, usually the app name if no duplicate entry * @param {string} a - App module alias */ getAppByAlias(a) { return this.appModulesByAlias[a]; } /** * Get a registered service * @param {string} name * * @example * // Get service from a lib module * const service = app.getService('<lib name>/<service name>'); * // e.g const service = app.getService('data/mysql.mydb'); * * // Get service from a web app module * const service = app.getService('<app name>:<service name>'); * // e.g const service = app.getService('admin:mysql.mydb'); */ getService(name) { let pos = name.indexOf(':'); if (pos === -1) { return super.getService(name); } let modAlias = name.substring(0, pos); name = name.substring(pos + 1); let app = this.getAppByAlias(modAlias); return app && app.getService(name, true); } _getFeatureFallbackPath() { let pathArray = super._getFeatureFallbackPath(); pathArray.splice(1, 0, _nodepath.default.resolve(__dirname, 'serverFeatures')); return pathArray; } /** * @param {string} [name='server'] - The name of the server. * @param {object} [options] - The app module's extra options defined in its parent's configuration. * @property {object} [options.logger] - Logger options * @property {bool} [options.verbose=false] - Flag to output trivial information for diagnostics * @property {string} [options.workingPath] - App's working path, default to process.cwd() * @property {string} [options.configPath] - App's config path, default to "conf" under workingPath * @property {string} [options.configName] - App's config basename, default to "app" * @property {string} [options.sourcePath='./src'] - Relative path of back-end server source files * @property {string} [options.appModulesPath=app_modules] - Relative path of child modules */ constructor(name, options){ if (typeof options === 'undefined' && (0, _utils.isPlainObject)(name)) { options = name; name = undefined; } super(name || 'server', { ..._defaultServerOpts.default, sourcePath: isEsm ? './src' : './cjs', ...options }); /** * Whether it is running as ESM. * @member {boolean} */ this.isEsm = isEsm; /** * Hosting server. * @member {WebServer} **/ this.server = this; /** * Whether it is a server. * @member {boolean} **/ this.isServer = true; /** * App modules path. * @member {string} */ this.appModulesPath = this.toAbsolutePath(this.options.appModulesPath); /** * Base route. * @member {string} */ this.route = '/'; // add built-in middlewares this.registry.middlewares = { ..._middlewares, ...this.registry.middlewares }; this.once('after:Initial', ()=>{ if (this.engine == null) { throw new _types.InvalidConfiguration('Missing server engine feature, e.g. koa or hono.', this); } }); process.once('SIGINT', ()=>{ this.stop_().then(()=>{})// eslint-disable-next-line no-undef .catch((error)=>console.error(error.message || error)); }); } }; } const WebServer = createWebServer((0, _Runnable.default)(_ServiceContainer.default)); const _default = WebServer; //# sourceMappingURL=WebServer.js.map