0.0.3 • Published 4 years ago

@skhon/hong-core v0.0.3

Weekly downloads
-
License
ISC
Repository
-
Last release
4 years ago

Hobber

基于 koa2,采用 typescript 开发的 node 框架 with ♥︎ by ke-fe

   _   _  _ ___ _  _     _     _____  _ __
  | |_| || | - | || |--.| |--.| | -  || --|
  |  _| || |   | || -  || -  || |--- ||  \\
  |_| |_||_|_-_|_||____||____||_|_-_ ||   \\

    with ♥︎ by ke-fe

版本变更说明请移步

hobber-cli脚手架使用方式

hobber-cli安装

支持nodemon自定义参数,需要制定hobber lift启动,示例如下

script : {
  "dev": "hobber lift -e 'development'",
},
//配置选项同nodemon配置
"hobber-nodemon": {
  "exec": "ts-node -T -r tsconfig-paths/register"
},

hobber内置nodemon默认配置为

const options = {
  script: path.join(appPath, './src/index.ts'),
  env: {
    NODE_ENV: env,
  },
  ignore: [ path.join(appPath, './src/statics/') ],
  watch: [
    path.join(appPath, './src/'),
    path.join(appPath, './package.json')
  ],
  ext: 'js json ejs pug ts',
  stdout: false,
  exec: "ts-node -T"
}

hobber库开发方式

  1. 分别在根目录core、example执行
$ npm run install
  1. core 目录
$ npx run build
  1. 根目录
$ npm run lerna
  1. example 目录
$ npm run dev

功能及规划

  1. 基础版本,核心功能包含
  • ✅基础server能力
  • ✅接口代理 action -> api
  • login单点登录、hdic登录
  • ✅静态资源
  • Model工具类-Utils、S3、WebShot、UserCenter
  • ✅监控数据上报
  • upassport登录
  • ✅数据库(TypeOrm)
  • ✅企微登录
  • 🚩ssr(react)
  • 🚩signterm信号处理
  • 🚩纯api代理生成器
  • 🚩更多。。。

工具类用法

内置Model用法(用户Model不再支持,当然可以自定义使用)

// 内置Model目前支持四种(UserCenter、S3、Utils、WebShot)
import { Model } from '@ke/hobber-core' //内置model  用户Model不再支持

Model.xxx.xxx() //有对应的TS提示

比如文件上传

// 内置默认配置
const LIANJIA_AWS_CONFIG: AWS.S3.ClientConfiguration = {
  accessKeyId: 'xxxxxxx', // 脱敏
  secretAccessKey: 'xxxxxxxx', // 脱敏
  region: 'cn-north-1',
  s3BucketEndpoint: true,
  s3ForcePathStyle: true,
  endpoint: 'http://storage.lianjia.com/' // 默认存储地址
}

const file = ctx.form.file
    if (file) {
      const ext = file.filename.split('.').pop()
      const s3 = Model.S3(); // 这里可以覆盖上面的配置项
      const data = await s3.uploadAsync({
        Bucket: 'test',
        Key: `${Date.now()}.${ext}`,
        Body: file
      })
      data.Location //则为上传后的地址
    }

全局API用法

注意:为了一些性能的提升,且保证写日志部分的正常解析,目前调用API需要手动传入ctx,不然日志和自定义responseHandler和requestHandler会报错

// 获取global类型
//用户 server/apis/index.d.ts提供,hobber会使用code generator做这个事情
import { HobberGlobal } from "/{path}/apis/index"

const hGlobal: HobberGlobal = global as HobberGlobal

//有对应ts提示,两种方式,
// 注意:为了性能的提升,目前调用API需要手动传入ctx,不然日志和自定义responseHandler和requestHandler会报错
hGlobal.API.xxx.xxx(query, {ctx})
(global as HobberGlobal).API.xxx.xxx(query, {ctx})

🧢 注意:上面使用API的时候,在后面参数中主动传入了ctx,之前bucky框架不是不用传也照样能用么?

🙈 解答:因为之前我们使用async_hooks异步钩子API帮大家临时存下来,但这里有一定的性能消耗和内存消耗,在hobber中我们决定移除

ctx使用

import { HobberGlobal } from "/{path}/apis/index" //用户 server/apis/index.d.ts提供
import { Context } from '@ke/hobber-core/index'

async handler (ctx: Context) {
  // ctx上有对应的hobber提示
  const ucid = String(parseInt(ctx.request.query.ucid) || '1000000020165056')
  const agent = await (global as HobberGlobal).API.userCenter.getAgentByAgentId({
    id: ucid
  });

  // 渲染页面, about 是对应 /views 文件夹下的文件
  ctx.request.id // 有对应TS提示
  ctx.response.render('agent', { agent, ucid })// 有对应TS提示
}

action 示例,可使用hobber-cli创建

import { Context } from "@ke/hobber-core/index"
import { Model } from '@ke/hobber-core' //内置model  用户Model不再支持

export default {

  // 是否需要跨域
  cors: true,
  // 是否页面需要登陆
  needLogin: true,

  async handler (ctx: Context) {
    //通过 ctx.request.user 获取用户信息
    const user = ctx.request.user
    // 渲染页面, about 是对应 views 文件夹下的文件
    const result = await ctx.checkLogin({
      redirectLogin: false,
      source: 'xxx',
      signature: 'xxxxx'
    })
    // 内置model调用,有对应TS提示
    const valet = await Model.UserCenter.getValetInfo({
      ucid: "10000000xxxxxxxx",
      env: "testing",
      appid: Number(xxx)
    });

    ctx.response.render("about", { user, result, valet });
  }
}

api 示例,可使用hobber-cli创建

import { _i_object_any } from "@ke/hobber-core/interface/interface_base.impl";
import { _i_api_config, _i_api_fn_opt, _i_api } from '@ke/hobber-core/interface/hobber_hooks/interface_api'
import { Context } from "@ke/hobber-core/index"


export default (api: _i_api) => {

  api.config = {
    // 接口超时时间
    timeout: 10000,

    // 默认的返回值简单约定, {code: , data:, msg:} 的形式返回
    // 如果是这种返回形式的话,那么通过下面参数,做接口检查
    codeKey: 'code',
    dataKey: 'data',
    messageKey: 'msg',
    successCode: 1,

    // 可自定义
    requestHandler (requestOptions, ctx: Context) {
      return requestOptions
    },

    // 可自定义
    responseHandler (res, ctx: Context): _i_object_any | undefined {
      // res 是 node-fetch 的返回值
      let errors: string = null as unknown as string
      if (res.statusCode === 200) {
        const json = JSON.parse(res.body)
        if (json.errors) {
          errors = json.errors
        } else {
          return json
        }
      }
      if (errors) {
        try { errors = JSON.stringify(errors) } catch (e) {}
        throw new Error(JSON.stringify({ message: errors, url: res.url}))
      }
    },

    // 接口的协议,域名,端口
    base: 'https://api.github.com',

    // 接口请求数据格式
    // 以下可选
    // multipart/form-data
    // application/json
    // application/x-www-form-urlencoded
    contentType: 'application/x-www-form-urlencoded',

    // query 参数的值是否需要 encode
    queryEncode: false,
  }

  // 定义接口
  api('searchRepositories', {

    // 接口 path
    uri: '{search}/repositories',

    // 接口访问方式
    method: 'get',

    // 接口参数检查
    // parameters: {
    //   q: api.type.string.required,
    //   sort: api.type.string.required,
    //   order: api.type.string.required
    // },
  })

  // api(....) 继续定义下一个接口
}

// 下面的特定环境可以深度合并到上面的默认环境
// 线上环境是上面的默认环境,不要乱改哦

// 开发环境配置
export const development = api => {}

// 测试环境配置
export const testing = api => {}

service configs 复写

重写config.api.xxx

这里需要注意,如果你在service中重写了config.api.defaultRequestHandler,同时又重写了某个api下的requestHandler,但你又想service中重写的会生效,那么请在某个apirequestHandler中主动调用,例如

service示例

export const configs = (config: ServiceConfig) => {
  const defaultRequestHandler = config.api.defaultRequestHandler;
  config.api.defaultRequestHandler = function(options, ctx) {
    options = defaultRequestHandler.call(this, options, ctx);
    options.headers["x-ke-trace"] = 11111;
    return options;
  };

  return config;
};

api示例

requestHandler (req: _i_api_fn_config, ctx: Context) {
  req.headers.trace_id = 123
  return this.defaultRequestHandler(req, ctx)
},

上面示例表示在service中重写了api.defaultRequestHandler和某个具体apirequestHandler,这样就能两个重写都生效

🧢 注意:如果你的多个插件中都修改了传入的config配置,比如A、B、C中都修改了config.api.defaultRequestHandler,并且你的插件顺序是C、B、A,那么最后修改后的只会是A中对应的 defaultRequestHandler

所以对于多个插件configs都对全局统一配置进行修改,强烈不建议

并且我们建议在service插件中只做非做不可且相对逻辑简单的事情

config

https登录跳转https失效?

  • 配置app.ts
proxy: {
   'x-forwarded-proto': 'x-ssl-header',
   'x-forwarded-for': 'x-real-ip'
}

login登录

  • cas 用户服务项目(团队)提供的登录,目前支持B/C端
  • hdic 楼盘字典登录
  • general 以前的C端登录,目前废弃

cas登录分两种体系:

export default {

  enable: true,    // 是否使用登录
  type: 'cas', // 选择需要的登录方式

  cas: {
    ...
    env: 'production-ke', //production-lianjia  两种体系
    ...
  },
}

登录配置中 maxAge 单位毫秒(ms

数据库配置

如果不跳链接,直接看下面

  • 数据库种类 https://github.com/typeorm/typeorm/blob/master/docs/zh_CN/connection-options.md
  • 数据实体 https://github.com/typeorm/typeorm/blob/master/docs/entities.md
  • 实体管理器API https://github.com/typeorm/typeorm/blob/master/docs/entity-manager-api.md

🧢 typeorm 维持数据库链接是在当前modules下,所以只能使用创建链接时使用的node_modules,如果你要覆盖当前typeorm,则hobber内置版本的链接将无效,需要注意~ 🌝 hobber-cli@0.0.15支持创建项目中增加orm文件,配置项见 数据库配置 🌝 hobber entity mysql/User创建数据库实例 用法见 数据库实例 🌝 hobber model mysql/User创建操作实例的封装 实例管理器

静态文件服务器

映射关系如下

  • 我们将statics下默认做public的关系映射
  • 如果想自定义请在启动参数中传入,如下,会将newstatics下映射到newpublic,但这种自定义情况需要注意,hobber默认只会打包statics下的文件,所以如果自定义,请修改提供的默认Makefile脚本
var appPath = path.resolve(__dirname)
var app = Hobber({
  appPath: appPath,
  staticDir: '/newstatics',
  getStaticPath: () => '/newpublic', })
`{servername}/public/*` -> `{servername}/statics/*`

自定义打印日志

hobber内部重写 console.logconsole.error两种标准流

  • console.log 走的标准stdout,同时存入当前机器日志文件
  • console.error 走的标准stderr,同时存入当前机器日志文件和上报kafka监控平台

日志配置

access日志可配置项:

{ 
    filename: 'access.log', //文件名
    type: 'dateFile', //日志类型,具体参考log4js官网
    pattern: '-yyyy-MM-dd', //日志文件的格式pattern
    alwaysIncludePattern: false, //是否始终包含pattern格式
    ignore: false, //是否忽略 ['/path/path1', /\path.*/] 字符串和正则
    loggingResponseBody: true, //记录response body
    loggingResponseBodyLimit: Infinity, //记录body 大小限制
    loggingRequestHeaders: true, //记录请求headers
    formatter ({ ctx, type }) { //自定义需要记录的内容格式
      return this.defaultFormatter({ ctx, type })
    },
}

api日志可配置项:

{
    filename: 'api.log', //文件名
    type: 'dateFile', //日志类型,具体参考log4js官网
    pattern: '-yyyy-MM-dd', //日志文件的格式pattern
    alwaysIncludePattern: false, //是否始终包含pattern格式
    loggingResponseBody: true, //记录response body
    loggingRequestBody: true, //记录request body
    loggingRequestHeaders: false, // 记录request headers
    loggingResponseHeaders: false, //记录response headers
    formatter ({ ctx, requestOptions, response }) { //自定义需要记录的内容格式
      return this.defaultFormatter({ ctx, requestOptions, response })
    },
}

运行多环境

hobber 内置默认三种环境即developmenttestingproduction,其中testing对应optest

如果需要新增环境,做对应的环境配置,则在对应文件对应环境(有环境区分的文件)下做相应的环境配置导出即可,比如在preview环境导出api的配置

export const preview  = api => {
    api.config.base = 'http://api-preview.ke.com/'
}

同时需要修改run.sh脚本配置,添加preview

{
    ...
    if [[ -z $PROJECT_ENV ]];then
        case $ENVTYPE in
            "test" )    PROJECT_ENV=testing          ;;
            "preview" )    PROJECT_ENV=preview       ;;
            * )         PROJECT_ENV=production       ;;
        esac
    fi
    ...
}

hobber内部链路日志

hobber采用log4js打印内部链路日志,日志支持自定义formatter,及其附属参数 log4js官网 https://github.com/log4js-node/log4js-node

// API
api: {
  filename: 'api.log', //日志名 default=api.log
  loggingResponseBody: true, //是否记录返回响应body default=true
  loggingRequestBody: true, //是否记录请求body default=true
  loggingRequestHeaders: false, //是否记录请求headers default=false
  loggingResponseHeaders: false, //是否记录响应headers default=false
},

//  ACCESS
access: {
  filename: 'access.log', //日志名 default=access.log
  ignore: [/\/public\/.*/, '/favicon.ico'], //支持正则、字符串
  loggingResponseBody: true, //是否记录响应body default=true
  loggingResponseBodyLimit: 500, //响应body大小限制,超出部分记为 `'<trimmed>'`
  loggingRequestHeaders: true //是否记录请求headers default=true
  // 其余字段遵循 log4js 规则 https://github.com/log4js-node/log4js-node
},

// ERROR
error: {
  filename: 'error.log'
},

// APPLICATION
application: {
  filename: 'application.log'
}

单测

目前单测部分,hobber采用的测试build后的产物,所以如果你要运行单测查看,请

  • cd core && npm run build
  • cd .. && npm run test

监控

  1. 🌲 新增 watcher 监控模块(0.0.7
  • action、api、service、rewrite、redirect、login等调用异常
  • 运行时机器内存、服务内存、机器cpu占比、服务cpu占比
  • 启动上报-机器相关信息、端口、ip、域名、npm包信息

打包

目前通过脚手架生成的产物中自带make脚本,该脚本只会打包server端的代码,直接执行make命令,会生成releases目录,该目录下包含可执行运行的server产物的tar包 如果只是本地构建,直接npm run build即可

其他ctx及其挂载功能

可借助TS的类型提示

直接hobber上帝群吼