UNPKG

node-web-mvc

Version:
179 lines (178 loc) 9 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const src_1 = __importDefault(require("../hmr/src")); const WebMvcConfigurationSupport_1 = __importDefault(require("./config/WebMvcConfigurationSupport")); const ModuleLoader_1 = __importDefault(require("./util/ModuleLoader")); const GenericApplicationContext_1 = __importDefault(require("./context/GenericApplicationContext")); const BeanDefinition_1 = __importDefault(require("../ioc/factory/BeanDefinition")); const FilterDispatcher_1 = __importDefault(require("./filter/FilterDispatcher")); const HttpServletRequest_1 = __importDefault(require("./http/HttpServletRequest")); const HttpServletResponse_1 = __importDefault(require("./http/HttpServletResponse")); const FilterHandlerAdapter_1 = __importDefault(require("./filter/FilterHandlerAdapter")); const HttpStatus_1 = __importDefault(require("./http/HttpStatus")); const DefaultListableBeanFactory_1 = __importDefault(require("../ioc/factory/DefaultListableBeanFactory")); const Javascript_1 = __importDefault(require("../interface/Javascript")); const RuntimeAnnotation_1 = __importDefault(require("./annotations/annotation/RuntimeAnnotation")); const Configuration_1 = __importDefault(require("../ioc/annotations/Configuration")); const NodeNativeConnector_1 = __importDefault(require("./connector/NodeNativeConnector")); const RequestBodyReader_1 = __importDefault(require("./http/body/RequestBodyReader")); const ApplicationDispatcher_1 = __importDefault(require("./http/ApplicationDispatcher")); const BootConfiguration_1 = __importDefault(require("./BootConfiguration")); const Tracer_1 = __importDefault(require("./annotations/annotation/Tracer")); const HotUpdaterReleaseManager_1 = __importDefault(require("../hmr/src/HotUpdaterReleaseManager")); class SpringApplication { constructor(...primarySources) { this.primarySources = primarySources; registerHotUpdate(this, this.initializeApplication.bind(this)); } static run(primarySource, connect) { return new SpringApplication(primarySource).run(connect); } /** * 尝试注入配置 */ tryInjectDefaultConfiguration(context) { const beanFactory = context.getBeanFactory(); const configAnnos = RuntimeAnnotation_1.default.getAnnotations(Configuration_1.default); const configAnno = configAnnos.find((m) => Javascript_1.default.createTyper(m.ctor).isType(WebMvcConfigurationSupport_1.default)); const SpringConfig = configAnno === null || configAnno === void 0 ? void 0 : configAnno.ctor; if (!SpringConfig) { // 如果没有自定义配置,则使用默认配置对象 const definition = new BeanDefinition_1.default(WebMvcConfigurationSupport_1.default, null, 'singleton'); const beanName = BeanDefinition_1.default.toBeanName(WebMvcConfigurationSupport_1.default); beanFactory.registerBeanDefinition(beanName, definition); } } /** * 加载所有模块 */ readyWorkprogress(cwd, exclude) { // 存储cacheKeys const cache = {}; Object.keys(require.cache).forEach((k) => cache[k.replace(/\\/g, '/').toLowerCase()] = true); // 加载controller等 cwd .filter(Boolean) .forEach((dir) => new ModuleLoader_1.default(dir, cache, exclude)); } /** * 顶层异常兜底 */ onError(status, res, ex) { const response = res.nativeResponse; ex && console.error(ex); if (!res.headersSent) { const content = `HTTP Status ${status.code} - ${status.message}`; response.setHeader('content-type', 'text/html'); response .writeHead(status.code, status.message).end(`<html lang="en"> <head> <title>${content}</title> <style type="text/css">body {font-family:Tahoma,Arial,sans-serif;} h1, h2, h3, b {color:white;background-color:#525D76;} h1 {font-size:22px;} h2 {font-size:16px;} h3 {font-size:14px;} p {font-size:12px;} a {color:black;} .line {height:1px;background-color:#525D76;border:none;}</style> </head> <body> <h1>${content}</h1> </body> </html>`); } } initBootConfigs() { var _a, _b; const bootConfig = this.bootConfig = new BootConfiguration_1.default(this.primarySources); const hotOptions = bootConfig.getHotOptions(); (_b = (_a = this.hotUpdater) === null || _a === void 0 ? void 0 : _a.close) === null || _b === void 0 ? void 0 : _b.call(_a); if (hotOptions) { // 启动热更新 this.hotUpdater = src_1.default.run(hotOptions); } if (bootConfig.getLaunchLogOff() !== true) { const port = bootConfig.getPort(); console.log(` ----------------------------------------------------------- ====> Start Node-Mvc Server ====> Enviroment: development ====> Listening: port ${port} ====> Hot Module Update: ${this.hotUpdater ? 'eanbled' : 'disabled'} ====> Url: http://localhost:${port}/ ====> Swagger: ${bootConfig.getEanbleSwagger() ? `http://localhost:${port}/swagger-ui/index.html` : 'disabled'} ----------------------------------------------------------- `.split('\n').map((m) => m.trim()).join('\n')); } // 装载所有模块 this.readyWorkprogress(bootConfig.getScanBasePackages(), bootConfig.getExcludeScan()); } initializeApplication() { // 创建应用上下文 const context = this.context = new GenericApplicationContext_1.default(this.bootConfig); const beanFactory = context.getBeanFactory(); if (beanFactory instanceof DefaultListableBeanFactory_1.default) { beanFactory.setAllowBeanDefinitionOverridable(false); } // 默认配置处理 this.tryInjectDefaultConfiguration(context); // 应用上下文刷新 context.refresh(); // 构建过滤器处理适配器 this.filterAdapter = new FilterHandlerAdapter_1.default(beanFactory); this.filterAdapter.addFilter(new FilterDispatcher_1.default(context)); this.configurer = beanFactory.getBeansOfType(WebMvcConfigurationSupport_1.default)[0]; } handleRequest(nativeRequest, nativeResponse, next) { const serverOptions = this.bootConfig.getServerOptions(); const base = serverOptions.base || '/'; const configurer = this.configurer; if (nativeRequest.url.indexOf(base) !== 0) { return next(); } const filterAdapter = this.filterAdapter; const reader = new RequestBodyReader_1.default(configurer.multipart); const createDispatcher = (path) => new ApplicationDispatcher_1.default(filterAdapter, path); const request = new HttpServletRequest_1.default(nativeRequest, base, createDispatcher, reader); const response = new HttpServletResponse_1.default(nativeResponse); filterAdapter .doFilter(request, response) // 尝试404处理 .then(() => this.onError(HttpStatus_1.default.NOT_FOUND, response, null)) // 尝试500处理 .catch((ex) => this.onError(HttpStatus_1.default.INTERNAL_SERVER_ERROR, response, ex)); } /** * 启动服务 */ run(connect) { this.initBootConfigs(); this.initializeApplication(); const serverOptions = this.bootConfig.getServerOptions(); const handleRequest = this.handleRequest.bind(this); if (connect) { // 自定义服务链接 connect(handleRequest, serverOptions).then(this.onConnected.bind(this)); } else { // 默认使用node服务链接 (new NodeNativeConnector_1.default()).connect(handleRequest, serverOptions).then(this.onConnected.bind(this)); } return this.context; } onConnected(server) { HotUpdaterReleaseManager_1.default.push(() => server.close()); } } exports.default = SpringApplication; function registerHotUpdate(app, refreshLifecycle) { src_1.default .create(module) .clean() .postend((m) => { var _a, _b, _c; const tracer = Tracer_1.default.getTracer(app.configurer.constructor); if ((tracer === null || tracer === void 0 ? void 0 : tracer.id) === m.filename) { (_c = (_b = (_a = app.context) === null || _a === void 0 ? void 0 : _a.getBeanFactory()) === null || _b === void 0 ? void 0 : _b.destory) === null || _c === void 0 ? void 0 : _c.call(_b); // 如果是配置文件更新,则需要重新初始化(并非重启服务,而是刷新掉上下文) refreshLifecycle(); } }); }