@dazejs/framework
Version:
Daze.js - A powerful web framework for Node.js
430 lines • 16.2 kB
JavaScript
"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(`/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