项目结构

项目布局、YAML 定义文件和命名规范。

目录结构

myapp/
├── .wippy.yaml          # 运行时配置
├── wippy.lock           # 源目录与锁定的模块
├── .wippy/              # 已安装的模块
└── src/                 # 应用源代码
    ├── _index.yaml      # 记录定义
    ├── api/
    │   ├── _index.yaml
    │   └── *.lua
    └── workers/
        ├── _index.yaml
        └── *.lua

YAML 定义文件

YAML 定义在启动时加载到注册表中。注册表是唯一的数据源——YAML 文件只是填充它的一种方式。记录也可以来自其他来源或通过编程方式创建。

文件结构

任何包含 namespace、且带有 entries 数组或顶层 name+kind 的 YAML 文件都是有效的定义文件。version 是可选的:

version: "1.0"
namespace: app.api

entries:
  - name: get_user
    kind: function.lua
    meta:
      comment: 根据 ID 获取用户
    source: file://get_user.lua
    method: handler
    modules:
      - sql
      - json

  - name: get_user.endpoint
    kind: http.endpoint
    meta:
      comment: 用户 API 端点
    method: GET
    path: /users/{id}
    func: get_user
字段 必需 描述
version 否 架构版本(当前为 "1.0")
namespace 是 此文件中记录的命名空间
entries 是 记录定义数组

命名规范

使用点(.)分隔语义部分,使用下划线(_)分隔单词:

# 函数及其端点
- name: get_user              # 函数
- name: get_user.endpoint     # 其 HTTP 端点

# 同一函数的多个端点
- name: list_orders
- name: list_orders.endpoint.get
- name: list_orders.endpoint.post

# 路由器
- name: api.public            # 公共 API 路由器
- name: api.admin             # 管理 API 路由器
模式:base_name.variant — 点分隔语义部分,下划线分隔部分内的单词。

命名空间

命名空间是点分隔的标识符:

app
app.api
app.api.v2
app.workers

记录完整 ID 由命名空间和名称组成:app.api:get_user

锁文件

wippy.lock 记录 Wippy 从哪里加载定义,以及选定了哪些模块版本:

directories:
  modules: .wippy
  src: ./src
options:
  unpack_modules: false
modules:
  - name: acme/http
    version: v1.2.0
    hash: 4ea816fe84ca58a1f0869e5ca6afa93d6ddd72fa09e1162d9e600a7fbf39f0a2
字段 说明
directories.src 应用源目录,递归扫描其中的 YAML 定义文件
directories.modules vendored 模块的基准目录;包会放在 <modules>/vendor/ 下
options.unpack_modules 把每个 .wapp 解压到其旁边的目录中,而不是直接加载该包(默认 false)
modules[].name org/module 形式的模块标识符
modules[].version 选定的版本
modules[].hash vendored 包必须匹配的制品摘要
modules[].root 标记选定的部署根;最多只能有一个模块带有它

vendored 包以 .wapp 文件形式保存。当 unpack_modules: true 时,每个模块还会被解压到一个目录中,且经过校验的 .wapp 仍保留在其旁边——安装会去查找该包,因此包缺失的目录会被重新下载。

wippy.lock 中的 replacements: 段已弃用。它仍可加载,但会发出警告;请改为在运行时配置文件中的 workspace.replacements 下声明本地模块覆盖。参见 依赖管理。

记录定义

每个记录在 entries 数组中。属性位于根级别(无 data: 包装):

entries:
  - name: hello
    kind: function.lua
    meta:
      comment: 返回 hello world
    source: file://hello.lua
    method: handler
    modules:
      - http
      - json

  - name: hello.endpoint
    kind: http.endpoint
    meta:
      comment: Hello 端点
    method: GET
    path: /hello
    func: hello

元数据

使用 meta 存储界面友好的信息:

- name: payment_handler
  kind: function.lua
  meta:
    title: 支付处理器
    comment: 处理 Stripe 支付
  source: file://payment.lua

约定:meta.title 和 meta.comment 在管理界面中显示良好。

应用记录

使用 registry.entry 类型存储应用级配置:

- name: config
  kind: registry.entry
  meta:
    title: 应用设置
    type: application
  environment: production
  features:
    dark_mode: true
    beta_access: false

常见记录类型

类型 用途
registry.entry 通用数据
function.lua 可调用的 Lua 函数
process.lua 长时间运行的进程
http.service HTTP 服务器
http.router 路由组
http.endpoint HTTP 处理器
process.host 进程监管器

详见 记录类型指南。

配置文件

.wippy.yaml

项目根目录的运行时配置:

version: "1.0"

logger:
  encoding: json

logmanager:
  min_level: 0

supervisor:
  host:
    worker_count: 16

详见 配置指南。

wippy.lock

源目录与选定的模块图——参见上文的 锁文件。

引用记录

通过完整 ID 或相对名称引用记录。子记录通过 meta 挂接到父记录,而不是由父记录一侧维护列表:

# 路由器声明自己所属的服务器
- name: api
  kind: http.router
  meta:
    server: app:gateway
  prefix: /api

# 端点通过注册表 ID 引用路由器(跨命名空间的方式相同)
- name: get_user.endpoint
  kind: http.endpoint
  meta:
    router: app.api:api
  method: GET
  path: /users/{id}
  func: app.api:get_user

示例项目

myapp/
├── .wippy.yaml
├── wippy.lock
└── src/
    ├── _index.yaml           # namespace: app
    ├── api/
    │   ├── _index.yaml       # namespace: app.api
    │   ├── users.lua
    │   └── orders.lua
    ├── lib/
    │   ├── _index.yaml       # namespace: app.lib
    │   └── database.lua
    └── workers/
        ├── _index.yaml       # namespace: app.workers
        └── email_sender.lua

另请参阅