UNPKG

@dazejs/framework

Version:

Daze.js - A powerful web framework for Node.js

430 lines 16.2 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.Application = void 0; const cluster_1 = __importDefault(require("cluster")); const debug_1 = __importDefault(require("debug")); const fs_1 = __importDefault(require("fs")); const keygrip_1 = __importDefault(require("keygrip")); const path = __importStar(require("path")); const require_main_filename_1 = __importDefault(require("require-main-filename")); const cluster_2 = require("../cluster"); const config_1 = require("../config"); const container_1 = require("../container"); const middleware_1 = require("../http/middleware"); const loader_1 = require("../loader"); const provider_1 = require("../provider"); const auto_providers_1 = require("./auto-providers"); const DEFAULT_PORT = 8080; const envMap = new Map([ ['development', 'dev'], ['test', 'test'], ['production', 'prod'], ]); const debug = (0, debug_1.default)('@dazejs/framework:application'); class Application extends container_1.Container { constructor(option) { super(); this.rootPath = ''; this.appPath = ''; this.configPath = ''; this.viewPath = ''; this.publicPath = ''; this.storeagePath = ''; this.logPath = ''; this.keys = []; this.port = 0; this.isDebug = false; this.needsParseBody = true; this.needsSession = true; this.middlewares = []; this.needsStaticServer = true; this.launchCalls = []; this.isHttps = false; this.initDirectoryStructure(option === null || option === void 0 ? void 0 : option.rootPath, option === null || option === void 0 ? void 0 : option.paths); this.initContainer(); this.initConfig(); this.initProvider(); } initDirectoryStructure(rootPath, paths) { if (!rootPath) { const _filename = (0, require_main_filename_1.default)(); if (_filename) { this.rootPath = path.dirname(_filename); } else { throw new Error('Application: 无法找到默认应用根目录,请显式的传入应用根目录参数'); } } else { this.rootPath = rootPath; } this.appPath = path.resolve(this.rootPath, (paths === null || paths === void 0 ? void 0 : paths.app) || 'app'); this.configPath = path.resolve(this.rootPath, (paths === null || paths === void 0 ? void 0 : paths.config) || 'config'); this.viewPath = path.resolve(this.rootPath, (paths === null || paths === void 0 ? void 0 : paths.view) || '../views'); this.publicPath = path.resolve(this.rootPath, (paths === null || paths === void 0 ? void 0 : paths.public) || '../public'); this.storeagePath = path.resolve(this.rootPath, (paths === null || paths === void 0 ? void 0 : paths.storeage) || '../storeage'); this.logPath = path.resolve(this.rootPath, (paths === null || paths === void 0 ? void 0 : paths.log) || '../logs'); return this; } initContainer() { container_1.Container.setInstance(this); this.bind('app', this); this.bind(Application, () => this.get('app'), true, true); } initConfig() { this.singleton(config_1.Config, config_1.Config); this.singleton('config', () => { return this.get(config_1.Config); }, true); } initProvider() { this.singleton('loader', () => { return new loader_1.Loader(); }, true); this.singleton(loader_1.Loader, () => { return this.get('loader'); }, true); this.singleton('provider', provider_1.Provider); } async setupApp() { debug(`准备配置应用程序`); this.config = this.get('config'); await this.config.initialize(); if (!this.port) this.port = this.config.get('app.port', DEFAULT_PORT); if (process.env.NODE_ENV === 'development' || process.env.DAZE_ENV === 'dev') { this.isDebug = this.config.get('app.debug', false); } if (this.isCluster) this.make('messenger'); debug(`配置应用程序已完成`); return this; } disableBodyParser() { this.needsParseBody = false; } disableSession() { this.needsSession = false; } disableStaticServer() { this.needsStaticServer = false; } getAgent() { return this.agent; } getWorkers() { return this.workers; } async registerVendorProviders() { const _providers = this.config.get('app.providers', []); for (const Provider of _providers) { if (!this.has(Provider)) { await this.register(Provider); } } } async register(Provider) { if (Reflect.getMetadata('type', Provider) !== 'provider') return; await this.get('provider').resolve(Provider); } async fireLaunchCalls(...args) { for (const launch of this.launchCalls) { await launch(...args, this); } return this; } get isCluster() { return this.config.get('app.cluster', false); } get isAgent() { return !cluster_1.default.isMaster && process.env.DAZE_PROCESS_TYPE === 'agent'; } get isWorker() { return !cluster_1.default.isMaster && process.env.DAZE_PROCESS_TYPE === 'worker'; } get isMaster() { return cluster_1.default.isMaster; } getClusterMaterInstance() { return new cluster_2.Master({ port: this.port, workers: this.config.get('app.workers', 0), sticky: this.config.get('app.sticky', false) }); } getClusterWorkerInstance() { return new cluster_2.Worker({ port: this.port, sticky: this.config.get('app.sticky', false), createServer: (...args) => { const server = this.listen(...args); return server; }, }); } loadEnv() { const nodeEnv = process.env.NODE_ENV; const dazeEnv = process.env.DAZE_ENV; if (!nodeEnv) { switch (dazeEnv) { case 'dev': process.env.NODE_ENV = 'development'; break; case 'test': process.env.NODE_ENV = 'test'; break; default: process.env.NODE_ENV = 'production'; break; } } return this; } get env() { return process.env.DAZE_ENV || (process.env.NODE_ENV && envMap.get(process.env.NODE_ENV)) || process.env.NODE_ENV; } getEnv() { return this.env; } registerKeys() { const keys = this.config.get('app.keys', ['DAZE_KEY_1']); const algorithm = this.config.get('app.algorithm', 'sha1'); const encoding = this.config.get('app.encoding', 'base64'); this.keys = new keygrip_1.default(keys, algorithm, encoding); } async fireAgentResolves() { const agents = this.get('loader').getComponentsByType('agent') || []; for (const Agent of agents) { const agent = new Agent(); await agent.resolve(this); } return this; } async registerCommonProviders() { debug(`准备注册框架运行必须的组件`); await this.register(auto_providers_1.CommonProvider); debug(`已成功注册框架运行必须的组件`); } async registerAutoProviders() { var _a; const packageJsonPath = path.join(this.rootPath, '../package.json'); if (!fs_1.default.existsSync(packageJsonPath)) return; const json = await (_a = `${packageJsonPath}`, Promise.resolve().then(() => __importStar(require(_a)))); if (!(json === null || json === void 0 ? void 0 : json.dependencies)) return; const dependencies = Object.keys(json.dependencies); await this.registerAutoProviderDependencies(dependencies); } async registerAutoProviderDependencies(dependencies) { var _a, _b; for (const depend of dependencies) { const dependPackagePath = path.join(this.rootPath, '../node_modules', depend, 'package.json'); if (fs_1.default.existsSync(dependPackagePath)) { const dependJson = await (_a = `${dependPackagePath}`, Promise.resolve().then(() => __importStar(require(_a)))); if ((dependJson === null || dependJson === void 0 ? void 0 : dependJson['dazeProviders']) && Array.isArray(dependJson['dazeProviders'])) { for (const providerPath of dependJson['dazeProviders']) { const providerAbsolutPath = path.join(this.rootPath, '../node_modules', depend, providerPath); try { const AutoThridProvider = await (_b = `${providerAbsolutPath}`, Promise.resolve().then(() => __importStar(require(_b)))); const keys = Object.keys(AutoThridProvider).filter((k) => typeof AutoThridProvider[k] === 'function'); for (const k of keys) { if (!this.has(AutoThridProvider[k])) { await this.register(AutoThridProvider[k]); } } } catch (err) { console.warn(`@dazejs/framework: 自动加载依赖[${depend}]失败,请手动加载`, err); } } } } } } async registerWorkerProvider() { await this.register(auto_providers_1.WorkerProvider); } use(Middleware, args) { if (!this.has(Middleware)) { this.singleton(Middleware, Middleware); } this.middlewares.push({ middleware: Middleware, args: args !== null && args !== void 0 ? args : [] }); return this; } loadGlobalMiddlewares() { if (this.isCluster && this.isMaster) return; for (const m of this.middlewares) { this.get(middleware_1.MiddlewareService).register(m.middleware, m.args); } } async initializeForCli() { this.loadEnv(); await this.setupApp(); this.registerKeys(); await this.registerCommonProviders(); } async initialize() { this.loadEnv(); await this.setupApp(); this.registerKeys(); await this.registerCommonProviders(); if (!this.isCluster || !cluster_1.default.isMaster) { if (this.isCluster && process.env.TIGER_PROCESS_TYPE === 'agent') { debug('当前进程为 Agent 进程,执行 Agent 操作'); await this.registerVendorProviders(); await this.registerAutoProviders(); await this.fireLaunchCalls(); await this.fireAgentResolves(); } else { await this.registerWorkerProvider(); await this.registerVendorProviders(); await this.registerAutoProviders(); await this.fireLaunchCalls(); if (!this.isCluster) { await this.fireAgentResolves(); } this.loadGlobalMiddlewares(); } } else if (this.isCluster && cluster_1.default.isMaster) { await this.registerVendorProviders(); await this.registerAutoProviders(); await this.fireLaunchCalls(); this.loadGlobalMiddlewares(); } } enableHttps(httpsOptions) { this.isHttps = true; this.httpsOptions = httpsOptions; return this; } async run(port) { await this.initialize(); if (port) { this.port = port; } else { const configPort = this.config.get('app.port'); if (configPort) { this.port = configPort; } } debug(`准备启动应用程序, 端口号: ${this.port}`); if (this.isCluster) { debug(`当前为 cluster模式, 使用 cluster 模式启动应用程序`); if (cluster_1.default.isMaster) { const master = this.getClusterMaterInstance(); master.forkAgent(); await master.run(); } else { if (process.env.DAZE_PROCESS_TYPE === 'worker') { const worker = this.getClusterWorkerInstance(); this._server = await worker.run(); } return; } } else { debug(`当前为单线程模式, 使用单线程模式启动应用程序`); this._server = this.listen(this.port, () => { if (this.listenerCount('ready') > 0) { this.emit('ready'); } else { console.log(`服务已启动, 监听端口号为: ${this.port}`); } }); } return this._server; } close() { return new Promise((resolve, reject) => { if (!this._server) return reject(new Error('app does not running!')); return this._server.close((error) => { if (error) return reject(error); return resolve(); }); }); } listen(...args) { if (!this.listenerCount('error')) this.handleEarsError(); const server = this.get('appServer'); return server.listen(...args); } handleEarsError() { if (this.listenerCount('error') > 0) return; this.on('error', (err) => { console.error(err); }); } call(abstract, args = []) { const concrete = this.make(abstract); if (typeof concrete !== 'function') return undefined; return concrete(...args); } tagged(tag) { if (!this.tags[tag]) return []; return this.tags[tag]; } tag(abstract, tag) { if (!abstract || !tag) return undefined; if (!this.tags[tag]) this.tags[tag] = []; this.tags[tag].push(abstract); return this; } get(abstract, args = [], force = false) { return this.make(abstract, args, force); } bind(abstract, concrete = null, shared = true, callable = false) { return shared ? this.singleton(abstract, concrete, callable) : this.multiton(abstract, concrete, callable); } has(abstract) { return this.bound(abstract); } } exports.Application = Application; //# sourceMappingURL=application.js.map