# Basic | basic Hydro 后端使用 NodeJS 编写,前端使用 JQuery + React。 代码风格遵循 airbnb 标准(详见 .eslintrc.js)。 由于模块中不能使用 require() 引入 Hydro 的文件,因此需要从 global.Hydro 中取出需要的模块。 例: ```js const { db } = global.Hydro.service; const { problem } = global.Hydro.model; ``` # Module | module ## 文件架构 Hydro 的模块由以下几个部分组成: service: 服务 script: 脚本 handler: 访问路由 lib: 库 model: 数据库模型 file: 额外文件 locale: 多国化 template: UI 模板 README.md: 介绍 hydro.json: 声明文件(必须) ## 模块编译 使用 `hydro-build` 进行编译。 安装:`yarn add hydro-build -D` 编译:`hydro-build` 如果命运的齿轮没有出差错,您应该可以找到生成的.hydro文件了。 # Hydro.json | hydro Hydro.json 是模块的声明文件,格式如下。 ```json { "id": "模块ID", "version": "模块版本", "description": "模块描述" } ``` # Handler | handler 通常用于提供页面路由。 例:注册新路由: ```js const { Handler, Route } = global.Hydro.service.server; const { user, builtin } = global.Hydro.model; class CustomHandler extends Handler { async prepare() { this.checkPriv(builtin.PRIV.PRIV_USER_PROFILE); // this.checkPerm(), this.user.hasPerm(), this.user.hasPriv(), etc. } async get(){ this.response.template = 'user_login.html'; } async post({ username, password }) { const udoc = await user.getByUname(username); udoc.checkPassword(password); this.response.body = { udoc }; } async postConfirm() { // 当提交表单并存在 operation 值为 confirm 时执行。 } } async function apply() { Route('/route/:username', CustomHandler); } global.Hydro.handler.handlerName = apply; ``` 在路由中定义所有的函数应均为异步函数,支持的函数如下: prepare, get, post, post[Operation], cleanup 具体流程如下: 先执行 prepare(args) (如果存在) args 为传入的参数集合(包括 QueryString, Body, Path)中的全部参数, 再执行 prepare(args) (如果存在) 检查请求类型: ``` 为 GET ? -> 执行 get(args) 为 POST ? -> 执行 post(args) -> 含有 operation 字段? -> 执行 post[Operation] ``` 执行 cleanup() 如果在 this.response.template 指定模板则渲染,否则直接返回 this.response.body 中的内容。 * 在表单提交时的 operation 字段使用下划线,函数名使用驼峰命名。 如 `` 对应 `postConfirmDelete` 函数。 应当提供 `apply` 函数,并与定义的 Handler 一同挂载到 `global.Hydro.handler[模块名]` 位置。 `apply` 函数将在初始化阶段被调用。 ### 表单验证 若使用 Typescript 开发插件,可使用 Hydro 提供的验证工具。 `@param` 会修改 arguments,首个参数为请求所在的 domainId,剩余参数为指定的内容。 ```ts const { Handler, Route, Types, param } = global.Hydro.service.server; const { user, builtin } = global.Hydro.model; class CustomHandler extends Handler { async prepare() { this.checkPriv(builtin.PRIV.PRIV_USER_PROFILE); } async get(){ this.response.template = 'user_login.html'; } @param('username', Types.String) @param('password', Types.String) async post(domainId:string, username:string, password:string) { const udoc = await user.getByUname(username); udoc.checkPassword(password); this.response.body = { udoc }; } } export async function apply() { Route('/route/:username', CustomHandler); } global.Hydro.handler.handlerName = apply; ``` 若使用 Javascript 开发插件,则可使用 `global.Hydro.lib.validator` 中提供的相关工具。 # Service | service 通常用于提供与其他程序对接的接口或启动其他外部程序。(如内置的 MongoDB / 外置的沙箱模块等) # Lib | lib 库文件。通常用于提供一些功能(废话)。 # File | file file 文件夹下的所有文件将被自动解压到 `$TMPDIR/hydro/模块ID/路径` 的位置(权限755,通常用于启动子进程)。 # Locale | locale 用于提供多国翻译。格式与 Hydro 的 locale 文件夹格式相同。 # Template | template 页面模板,使用 [nunjucks](https://mozilla.github.io/nunjucks/cn/templating.html) 语法。 传入了 _ 翻译函数与 model 等。 ```html {% set page_name = "page_name" %} {% extends "layout/basic.html" %} {% block content %}

{{ _('Oops!') }}

{{ _(error.message).format(error.params) }}

{{ _('Technical Information') }}:

{{ _('Type') }}: {{ error.code }}

{{ _('Arguments') }}:

    {% for param in error.params %}
  1. {{ param }}
  2. {% endfor %}

{% endblock %} ```
请不要覆盖已有模板。
# README.md | readme 项目的说明文件。