feat: unify source and skills for Dever 0.1.2 installation
This commit is contained in:
1 parent
a2e0436ed4
commit
19f122b4b4
47 files changed
+1951
-63
No files matched your search
@@ -0,0 +1,67 @@
|
||||
# 应用接口、数据与后台任务
|
||||
|
||||
## API 和 CMD
|
||||
|
||||
`module/news/article/api/admin/manage.dever`:
|
||||
|
||||
```dever
|
||||
get list = app.list
|
||||
get detail = app.detail
|
||||
post create = app.create
|
||||
put replace = app.replace
|
||||
delete remove = app.remove
|
||||
post publish = app.publish
|
||||
```
|
||||
|
||||
API 无函数体,继承 App 输入/输出签名。支持 get/post/put/delete,当前没有 patch、旧 get_ 前缀或源码内 site 声明。`cmd greet = app.greet` 生成 `component.domain.greet` 命令,参数来自单个 JSON 对象;main.dever 不存在,也不读取命令行参数。
|
||||
|
||||
GET/DELETE 从 query 读标量参数,POST/PUT 从 JSON body 读参数;额外、重复或缺少必填字段均拒绝。无需自己读 body 或构造 dever.http.Response。成功统一为 `{"code":0,"message":"ok","data":...}`;错误 data 为 null,code 对应状态码。接口必须绑定一个可序列化输出,输出名可自定。
|
||||
|
||||
`dever.api.Error` 中 Invalid/Unauthorized/Forbidden/NotFound/Conflict/TooManyRequests 对应 400/401/403/404/409/429;未知内部失败记录脱敏日志并返回安全的 500。
|
||||
|
||||
写 HTTP/CMD/Job 调用链由入口建立事务;GET 调用链不能写库或入队。密码 hash/verify 是例外:不能让昂贵密码运算占用入口长事务,实际写入必须放显式短 transaction,并在其中重新检查依赖状态。不能为了“默认有事务”而删除这种短事务。
|
||||
|
||||
## 站点、身份与权限
|
||||
|
||||
`sites.admin.path = "admin"` 匹配领域内 `api/admin/**`,front 同理。文件名 topic 也进入 URL;上述 publish 是 `/news/article/admin/manage/publish`。每条 HTTP 声明只能匹配一个站点,重叠或遗漏配置会失败;path 不改写 URL,也不匹配 `api/admin.dever`。
|
||||
|
||||
所有 HTTP 默认鉴权并校验精确权限。只有明确匿名操作写 `public post login = app.login` 等单条 public 声明;没有 public rest、public cmd、auth.require 或每个业务文件的权限注册代码。
|
||||
|
||||
配置的 auth provider 引用一个项目自己的 `verify` App 方法,验证账号、会话、成员和租户关系。输入是 `dever.auth.Claims`,输出 record 必须且只能包含 `id: Text`、`user_id: <UserModelId>?`、`tenant_id: <TenantModelId>?`;只能读 global Model,不能写库、拿原始 Header 或返回自报权限。
|
||||
|
||||
认证成功的受保护 App 可读取 `dever.auth.id()`、`session()`、`user_id()`、`tenant_id()`、`dever.site.key()`;来源是隐藏可信上下文,不能让客户端提交 user_id/tenant_id 当作身份。名义 ID 必须与站点 verify 的类型对应,可空 ID 经分句处理后才能使用。public/CMD/Job/普通测试不会自动获得身份读取能力。
|
||||
|
||||
核心生成 `component.domain.site.action` 权限目录,method 是元数据,不额外拼进权限键。REST 的 action 固定为 read/create/replace/delete。核心维护角色、用户角色、角色权限;项目无需重建这些表。App 用 `dever.auth.permissions/save_role/grant_role/revoke_role/disable_role` 实现后台授权入口,具体参数查当前库签名。它们只能从受保护写 API 到达。资源所有权可用 `dever.auth.owns_user(id)`,不等同于接口角色权限。
|
||||
|
||||
Cookie 登录/退出用 `dever.auth.issue_cookie(subject, session, tenant)` 与 `clear_cookie()`。Header/Cookie 使用 `dever.api` 读取/设置,无需显式 context 参数。密钥来自部署配置;Cookie 写入和 Cookie 认证的写请求需要精确同源校验,站点配置 origin。敏感头不能当普通 Text 读取。
|
||||
|
||||
## Model、CRUD 与业务编排
|
||||
|
||||
`module/news/article/model.dever` 的主记录应为 Article:
|
||||
|
||||
```dever
|
||||
type Article {
|
||||
title: Text(1, 200)
|
||||
body: Text
|
||||
}
|
||||
```
|
||||
|
||||
自动有只读 `id` 与 `created_at`。字段支持 default、private、unique、index;范围和长度在存储边界验证。关系使用目标 Model 专有 id 字段,不用 Int 代替外键。
|
||||
|
||||
同领域 App 可用 `model.create({...})`、`model.get(id)`、`model.update(id,{...})`、`model.delete(id)`、`model.list({where=...,order=[created_at.desc,id.desc],page=1,size=20})`。这是编译器静态 DSL,不是动态字典 SQL;不用手写 repository。聚合、关联和插入流程仍由 App 明确编排,不能自动推测关联图级联写入。
|
||||
|
||||
纯粹 CRUD 可在 API 写 `rest model`,多 Model 时指定 `rest model.<topic>`。Model 中 `create = expr`、`replace = expr`、`search = expr` 控制 REST 字段来源/查询;引用 input 表示客户端同名输入转换,不引用 input 表示服务端提供且禁止客户端提交。不要改成 post/put/get 字段关键字。
|
||||
|
||||
`private owner user_id: ... = dever.auth.user_id()` 在创建时赋值,并将所有权条件加入全部读写 SQL;不是只在输出隐藏 user_id。这种静态 owner 隔离可由 Model 直接声明,无需仅为它增加 App。关联操作、超出字段合同的业务校验、复杂输入输出或发布状态机由 App 编排,不能藏在 API 里。App 对外用明确 View,别泄漏 Model 私有字段。
|
||||
|
||||
不为每个 CRUD 机械建立 App、Domain、Port 和 Adapter;Model 的数据库操作无需再套一层 Port/repository。实际新增业务合同或编排时才增加对应实现。完整反重复、反硬编码及检查边界见 [项目开发](development.md)。
|
||||
|
||||
## 租户、任务与部署配置
|
||||
|
||||
配置只有 database 租户隔离:`tenant.database` 选控制连接,`global type` 使用平台库,其余持久 Model 与 Job 使用租户库。没有 field/table/mode 配置。租户缺失、未迁移或 schema 过期明确失败,不回退平台库。
|
||||
|
||||
运维命令:`dever tenant migrate <root> <id>`;`dever tenant owner <root> <id> <site> <user-id>` 建立核心 Owner;`dever tenant component enable|disable <root> <id> <component>` 控制租户功能。可用租户组件从 Model/Job 推导,不手写 Profile 分组。
|
||||
|
||||
job.dever 声明持久任务并绑定 App;enqueue 与事务、重试、调度、权限重验使用核心机制,不另写后台死循环。实际 Job 声明从对应版本指南和 CMS publishing/schedule 示例复用,不能把第三方 Worker 当持久 Job。
|
||||
|
||||
部署配置的真实结构可查官方 CMS `config/setting.json`,只添加项目用到的 database、tenant、auth、sites、http、job、runtime、log。最小 CMD 项目只需模板配置。密码、token 与真实数据库连接不提交 Git。
|
||||
@@ -0,0 +1,128 @@
|
||||
# 项目开发
|
||||
|
||||
新建最小项目:
|
||||
|
||||
```sh
|
||||
dever new my_app
|
||||
dever fmt my_app --check
|
||||
dever check my_app
|
||||
dever test my_app
|
||||
dever run my_app -- hello.greeting.greet '{"name":"Dever"}'
|
||||
dever build my_app --output my_app/program
|
||||
./my_app/program hello.greeting.greet '{"name":"Dever"}'
|
||||
```
|
||||
|
||||
创建 Markdown 项目用 `dever new my_app --markdown`。两种模板使用相同代码和行为,Markdown 另加编译器校验的说明。目标目录必须不存在,父目录必须已存在;不接受向现有项目合并或覆盖。build 输出也必须不存在。
|
||||
|
||||
模板只包含 CMD、App、配置、一个测试和开发指引,无需数据库或 HTTP 服务。实际项目在它的目录合同上扩展,替换演示领域,删除不再使用的示例与测试。添加 HTTP 时须完成 [站点与身份配置](application.md),不能只把 cmd 换成 get。
|
||||
|
||||
```text
|
||||
my_app/
|
||||
AGENTS.md
|
||||
README.md
|
||||
config/setting.json
|
||||
module/
|
||||
news/article/
|
||||
app.dever
|
||||
domain.dever
|
||||
model.dever
|
||||
port.dever
|
||||
adapter.dever
|
||||
job.dever
|
||||
api/
|
||||
admin/manage.dever
|
||||
front/browse.dever
|
||||
test/news/article/publish.dever
|
||||
```
|
||||
|
||||
这是可用职责位置,不是要求创建全部文件。component、domain 和文件主题使用有业务意义的 ASCII 小写蛇形命名;类型用 PascalCase,方法和字段用 snake_case。不要增加任意第三层领域目录。组件按业务能力划分,领域按一致的数据和业务边界划分。组件、领域和主题不能命名为 `common/shared/utils/helper/helpers/base/service/services` 等编译器禁止的通用桶。
|
||||
|
||||
| 位置 | 责任和访问规则 |
|
||||
| --- | --- |
|
||||
| App | 跨领域公开能力,校验与业务编排;同领域用 `app.publish`,外部用 `news.article.publish` |
|
||||
| Domain | 同领域内部业务规则;纯计算优先放这里,不承接数据库/外部 I/O |
|
||||
| Model | 存储字段、索引、关系、迁移、Seed、静态 SQL;同领域 App 使用 ORM |
|
||||
| Port | 外部能力的类型、操作与失败合同 |
|
||||
| Adapter | 实现 Port;私有,不反调 App/Domain/Model |
|
||||
| API | HTTP/CMD 入口绑定与自动 REST,无业务函数体 |
|
||||
| Job | 持久任务声明,绑定同领域 App |
|
||||
| Test | 文件同名、零输入零输出的唯一测试入口 |
|
||||
|
||||
## 文件与函数组织
|
||||
|
||||
简单领域保留角色单文件;复杂角色可以拆为 `app/publish.dever`、`app/search.dever` 等内聚主题,调用名不带文件名。非 API topic 目录不递归。App/Domain/Port/Adapter/Job 单文件与同名目录二选一,选择目录时至少有两个内聚主题文件;Model/API 主文件与 topic 目录可按编译器合同共存,不受这个最少文件数限制。只有 `api/` 可按站点和资源继续嵌套,目录会影响 URL。
|
||||
|
||||
一个文件可以包含多个相关类型、函数和分句。按完整业务主题命名,不机械地一个函数一个文件,也不为尚不存在的需求创建空 App、Domain、Port 或 Adapter。
|
||||
|
||||
抽取函数应表达独立业务规则、维护明确的不变量、复用已有逻辑,或隔离难以理解的复杂流程。只使用一次的函数也可以有这些作用;不能只因几行代码能起名字就再加一层。职责内聚的代码不按行数强拆,也不通过把所有逻辑塞进一个长函数来规避碎片化。
|
||||
|
||||
| 情况 | 处理方式 |
|
||||
| --- | --- |
|
||||
| `parse_id` 重新手写数字解析并把失败悄悄变成 0 | 复用已有解析、名义 ID 和明确失败合同,不复制算法 |
|
||||
| `trim_name` 只原样转发一次标准 trim,没有新增合同 | 在使用处调用标准能力 |
|
||||
| `page_slice` 重复 Model 已有的分页规则 | 使用 Model 分页,不在各领域复制一份 |
|
||||
| `publish` 组织发布条件、状态变化和后续任务 | 保留完整 App 能力,把内聚业务规则放同领域 Domain |
|
||||
| 单次使用的规则需要独立表达有效期或状态不变量 | 可以抽取并按业务含义命名 |
|
||||
| 两处相似代码承担不同规则、未来变化原因不同 | 保持各自归属,不为表面相似增加通用调度层 |
|
||||
|
||||
相同规则先复用现有所有者;只有真实共享的逻辑才抽象。跨领域共享能力由负责该业务的 App 提供,不直接调用对方私有实现,不为缩短调用名建立空转发链。普通 CRUD 直接用 Model 和 `rest model`;需要超出 Model 字段合同的输入转换、业务校验、关联操作或输出合同才增加 App 编排,具体见 [应用规则](application.md#modelcrud-与业务编排)。
|
||||
|
||||
## 配置与硬编码
|
||||
|
||||
| 数据或规则 | 归属 |
|
||||
| --- | --- |
|
||||
| 随部署变化的服务地址、端口、数据库连接、凭据 | `config/setting.json`,不增加环境变量配置,不提交真实秘密 |
|
||||
| 当前用户、租户、权限及资源归属 | 可信认证上下文、核心授权与 Model 策略,不接受客户端自报身份 |
|
||||
| 有固定业务含义的状态、范围和规则 | 类型、互斥分句、字段约束或内聚 Domain 定义,复用同一规则 |
|
||||
| 需要用户或运营维护的业务数据 | 项目 Model 与相应业务流程,不把具体记录写进源码分支 |
|
||||
| 测试 ID、样例地址和固定结果 | 测试夹具,不作为生产失败时的兜底 |
|
||||
|
||||
禁止按某个账号、租户、记录的裸 ID、名字或地址开特例,例如用 `user_id == 1` 代替管理员授权。普通查询参数可以标识目标记录,但不能因此成为操作者身份或访问权限。
|
||||
|
||||
避免硬编码不等于搬走所有字面量。局部的 0、1、提示文字和稳定协议常量可以保留;有业务意义、难以理解或反复出现的值由现有类型或领域定义表达。只有确需运行时变化的值才增加配置。官方发行源是工具链固定合同,不能塞进业务 setting.json。
|
||||
|
||||
## 禁止绕过检查
|
||||
|
||||
- 不添加假入口、无意义调用或仅供测试触达的调用,掩盖生产入口不可达的 App/Domain。删除本次废弃代码或接通真实业务调用链。
|
||||
- 不把重复业务逻辑转移到 Adapter、Python、JS 或 Go 来避开 Dever 检查。外部实现的质量同样需要审查。
|
||||
- 不吞掉失败、用空值或假数据冒充成功;有业务依据的恢复须使用明确结果合同,并验证恢复行为。
|
||||
- 不为通过检查擅自改 `dever.api`、删失败测试、弱化断言或关闭权限、类型及沙箱限制。确需改变公开合同,先说明调用方影响,在用户授权范围内同步实现、基线与测试。
|
||||
- 普通应用开发不修改编译器或核心库来容纳违规代码;语言或核心维护须有相应任务授权。只处理当前改动相关问题,不借机重写无关代码。
|
||||
|
||||
## 测试与检查
|
||||
|
||||
`test/hello/greeting/greet.dever`:
|
||||
|
||||
```dever
|
||||
greet() () {
|
||||
assert_eq(hello.greeting.greet("Dever"), "Hello, Dever")
|
||||
}
|
||||
```
|
||||
|
||||
模板中的实际字符串以生成文件为准。测试只执行文件同名函数,不需要 main 或注解。`assert` 接受 Bool,`assert_eq` 要求同类型。测试可访问同领域 App/Domain,跨领域仅 App,不能直接写 Model CRUD。使用 Model 时运行器使用临时 SQLite;不使用 Model 时不需要数据库。它不会读取生产 setting.json 或生产 data。对业务失败使用 `result(call)` 配合 choice 分句验证。
|
||||
|
||||
常用命令:`fmt --check` 查格式,`check` 查语法/类型/目录/分句/配置,`api` 输出 API 合同,`test` 运行应用套件,`run` 开发执行,`build` 生成独立程序。不要发明 `test --filter`、`run api` 或 `dever init`。
|
||||
|
||||
### 验证范围
|
||||
|
||||
| 检查 | 能证明的范围 |
|
||||
| --- | --- |
|
||||
| `dever fmt <root> --check` | 源码格式;不证明类型或业务正确 |
|
||||
| `dever check <root>` | 静态语法、类型、目录、命名、分句、相关配置、已有 API 基线,以及应用入口可达性和冗余硬检查;不执行应用 |
|
||||
| `dever test <root>` | 当前项目全部应用测试的实际断言;没有筛选参数,不证明生产入口完整 |
|
||||
| `dever run/build` | 通过与 check 相同的应用硬检查,再准备本地编译资源并执行或编译;成功不等于部署或性能验收 |
|
||||
| AI 审查 | 业务含义、职责拆分、复用、硬编码与验证范围,不能替代程序检查 |
|
||||
|
||||
`check/run/build` 共用 C016,拒绝生产入口不可达的 App/Domain,以及符合现有判定条件的私有空转发和 Model CRUD 包装;并非任意角色、所有函数或全部 CRUD 包装都能检出。`check` 不准备 Worker 或 runtime pack,不进行原生编译,不启动应用、服务或数据库。`test` 保持独立的测试入口与 Port fake 检查,不执行生产入口可达性检查;不能用测试调用掩盖生产死代码,也不能把静态检查当作运行验收。
|
||||
|
||||
W001–W005 等诊断包含未使用赋值、部分冗余条件、相同私有实现、重复纯调用和空转发建议,警告本身不会使命令失败。审查本次引入的诊断,修正有证据的问题;不能声称编译器能判定全部硬编码或业务价值。skill 中的开发要求不自动变成编译器硬错误。
|
||||
|
||||
选择与改动相符且已获授权的检查。新模板的小套件可以完整运行;已有大项目不默认运行全量 `dever test`,也不默认启动服务、连接真实数据库或压测。需要但尚未运行的检查要说明原因和剩余证据,不能伪报通过。已有 `dever.api` 时保留基线约束;`dever api <root> --output <新文件>` 可以导出待比较合同,不覆盖原文件。
|
||||
|
||||
源码放 module/,测试放 test/,部署配置放 config/,运行数据放 data/。生成程序从二进制同级 config/setting.json 读取配置。应用无需打包编译器;使用外部 Lib 时相关 runtime/依赖由 build 嵌入。只读 check 不证明真实数据库或部署验收。
|
||||
|
||||
## 核心与业务的区别
|
||||
|
||||
统一源码仓库地址为 `ssh://git@git.dever.cc:2222/shemic/dever.git`,迁移与发行状态见 [安装指引](install.md)。`crates/dever-core` 负责语言检查/编译,`crates/dever-runtime` 负责运行时,`crates/dever-cli` 负责命令,`library/` 是随版本提供的标准 Dever 源码。维护中的完整业务示例是 `examples/cms/dever` 与 `examples/cms/md`;`examples/old` 是历史回归,不作新项目模板。
|
||||
|
||||
开发普通应用无需复制或修改这些核心目录。可复用业务组件作为 Dever Package;外部 Python/JS/Go 生态称 Lib。多个项目共享机器安装的 Dever。
|
||||
@@ -0,0 +1,79 @@
|
||||
# 安装与更新
|
||||
|
||||
安装入口为 `https://git.dever.cc/shemic/dever/install`,官方二进制源为同站 `/shemic/dever/dist`。这些地址由发行工具固定,不写入业务项目配置,不通过环境变量选择。Git 源码可访问不代表安装端点或二进制已发布;服务器尚未部署时如实报告,不能把登录 HTML 当作脚本。
|
||||
|
||||
## 安装 dever
|
||||
|
||||
先检查 `dever --help`。机器版提供 new、install、update、target、version、skill;仅源码开发二进制不管理机器安装。不要把已有同名命令直接删掉或覆盖,先识别归属。
|
||||
|
||||
初次安装需要 Linux、Bash、Python 3.9 或更新版本的 `/usr/bin/python3` 和支持 Ed25519 的 `/usr/bin/openssl`;管道下载还需要 curl。非 root 安装通过 `/usr/bin/sudo` 提权,帮助不提权。这些工具用于校验和安装,生成的应用不依赖系统 Python、Node、Go 或 Rust。检查安装脚本并取得机器安装授权后执行:
|
||||
|
||||
还须满足所选发行包的主机 ABI 要求;当前准备的 Linux x86_64 编译器要求 glibc 2.39。ARM64 应用交叉构建可在 x86_64 主机使用,不能据此宣称 ARM64 宿主编译器包已经发布。
|
||||
|
||||
```sh
|
||||
curl -fsSL https://git.dever.cc/shemic/dever/install | bash
|
||||
```
|
||||
|
||||
无需先克隆源码或安装 skill。查看参数用 `bash -s -- --help`;固定版本用 `bash -s -- --version <准确版本>`,替换上面命令尾部的 `bash` 即可。本地已下载脚本可用 `bash install --help` 检查。
|
||||
|
||||
该命令下载当前平台最新已签名基础包。脚本包含独立固定公钥,先校验发行元数据,再验证引导程序及其私有库摘要,由引导程序解压 Zstandard 包;无需系统 zstd。安装 `/opt/dever`、`/usr/local/bin/dever`、机器共享服务和必要沙箱策略,默认启动服务。`--no-start` 可仅安装。没有对应正式资产时明确失败,不修改已安装版本。
|
||||
|
||||
基础包包含 Dever 编译器、本机应用编译资源、四种数据库运行库和配套 skill。Python、Node、Go、第三方原生构建工具与 ARM 应用目标按需安装,保存在机器共享资源目录;同一版本的多个用户和项目共用一份。
|
||||
|
||||
## 将 skill 接入 AI
|
||||
|
||||
安装核心后,将稳定入口装到用户选择的 AI 技能目录:
|
||||
|
||||
```sh
|
||||
dever skill install <新的AI技能目录>/dever-language
|
||||
```
|
||||
|
||||
目录必须尚不存在,不能覆盖已有 skill。入口每次解析与核心配套的完整 skill,重载 AI 工具的技能列表后使用。这是 Dever 语言的 `dever-language`,不是 Go 框架的 `shemic-dever`。不自动修改机器上其他用户的 AI 目录。
|
||||
|
||||
## 按需准备资源
|
||||
|
||||
首次添加或更新 Lib 时,`dever lib add/update <project-root> ...` 自动准备相应生态,只有进入源码构建流程时才准备构建工具。已有 `dever.lock` 的项目在新机器运行 `dever lib install <project-root>`,按锁恢复依赖,保持配置和锁文件不变;没有 Lib 的 Python/JS/Go Adapter 也可通过该命令准备环境。缺少锁时先显式 `dever lib update <project-root>` 生成锁。不要把 install 当作重新选版本的 update。
|
||||
|
||||
在 x86_64 机器准备 ARM64 应用目标:
|
||||
|
||||
```sh
|
||||
dever target add linux-aarch64
|
||||
dever lib install <project-root> --target linux-aarch64
|
||||
dever build <project-root> --target linux-aarch64 --output <新文件>
|
||||
```
|
||||
|
||||
只用 Dever、没有外部依赖的项目省略 lib install。目标 Lib 必须已有匹配目标的锁;首次生成 ARM 锁使用 lib add/update 的同名 target 参数。准备会显式联网,后续 run/build 离线;缺资源时执行提示的准备命令,不改用系统解释器。target add 准备当前活动版本,锁定其它编译器版本的项目先准备并选择对应版本。
|
||||
|
||||
已准备本地发行包时:
|
||||
|
||||
```sh
|
||||
bash install --release /可信发行目录 --trusted-key /独立确认的公钥文件
|
||||
```
|
||||
|
||||
测试或镜像制作增加 `--system-root /已有的自有镜像目录`;不会启动宿主服务。安装器生成的临时 `config/setting.json` 仅供机器 bootstrap 使用,包含本地发行路径、安装根和公钥路径;不是业务配置,不写发行仓库地址或环境变量。
|
||||
|
||||
公钥可公开提交;签名私钥绝不能进 skill、源码仓库或发行包。只有已独立确认的公钥才可作为 `--trusted-key`,不能从未知下载包顺手取一把钥匙作为信任依据。
|
||||
|
||||
已持有完整 skill 时仍可直接运行 `sudo python3 <skill目录>/scripts/install.py`,它与根 Bash 入口复用同一安装实现。
|
||||
|
||||
## 一条命令更新核心与 skill
|
||||
|
||||
```sh
|
||||
sudo dever update
|
||||
dever version
|
||||
dever skill path
|
||||
```
|
||||
|
||||
update 只访问内置官方发行源,先准备核心、同版本完整 skill,以及当前活动版本已安装的扩展,再切换活动版本。未使用的扩展不会一起下载;任一准备失败保留原活动版本。普通 check/test/run/build 不检查更新、不隐式联网。
|
||||
|
||||
从旧 GitHub 发行源迁移时,需要在新源正式包发布后执行一次新的 `install`。旧启动器和守护进程内置旧地址,普通 update 不负责替换这两个稳定程序;只修改仓库 remote 或重新发布旧包不能完成迁移。新 install 成功后再用 `dever update`。
|
||||
|
||||
本仓库直接安装的 skill 在开始开发时先运行 `dever skill path` 并加载该版本的完整 skill,不必每个项目 git pull。也可以用 `dever skill install <新的AI技能目录>/dever-language` 安装稳定的薄入口,之后每次自动解析当前机器版本;已有目录不会被覆盖。不要把新入口嵌套装进已经存在的完整 skill 目录。
|
||||
|
||||
项目可选 `config/setting.json` 的 `dever.version` 锁定准确 `major.minor.patch`,未锁定时使用机器活动版本。`dever install 版本` 准备指定版本;`dever use 版本` 显式切换活动版本。update 不改业务项目文件或数据库。锁定项目用 `dever skill path <project-root>` 读取对应指引,不能仅凭活动版指南采用新语法。
|
||||
|
||||
## 源码维护者
|
||||
|
||||
统一源码仓库为 `ssh://git@git.dever.cc:2222/shemic/dever.git`。`skills/` 是主仓库中的普通目录,与核心、模板和安装器一起提交、校验及发行;无需初始化 submodule 或另行克隆 skill 仓库。普通应用开发者无需克隆核心或编译 Rust。
|
||||
|
||||
根 `install` 从 `skills/scripts/install.py` 与 `skills/assets/release.pub` 生成;修改安装器后运行 `python3 sdk/install-entry.py`,交付前运行 `python3 sdk/install-entry.py --check`。禁止单独修改生成物中的安装算法。首个新源发行包发布前,默认下载会明确失败;使用真实签名本地包可验证安装,但不能代表线上安装或更新已经通过。
|
||||
@@ -0,0 +1,83 @@
|
||||
# 核心语法
|
||||
|
||||
以下片段说明语法。将它们放进正确角色文件并补完整调用链后检查,不能当作免配置 HTTP 项目。
|
||||
|
||||
## 类型和函数
|
||||
|
||||
```dever
|
||||
type Greeting {
|
||||
message: Text
|
||||
}
|
||||
|
||||
greet(name: Text) (response: Greeting) {
|
||||
response = Greeting { message = "Hello, " + text.trim(name) }
|
||||
}
|
||||
```
|
||||
|
||||
函数是 `name(输入) (命名输出) { 线性语句 }`,没有 function/return。调用按位置传参。零输入或零输出也写 `()`。单输出直接得到值;多输出调用返回只能按输出名访问的结果。App 的输入、输出和向外传播错误均为公开合同,不暴露 Domain/Adapter 私有类型。
|
||||
|
||||
函数命名表达业务行为,调用路径不附加主题文件名。相关函数、类型和同名分句可以同处一个内聚文件;拆分与复用的判断见 [文件与函数组织](development.md#文件与函数组织),不按函数长度自动增加 helper。
|
||||
|
||||
常用类型:`Bool`、`Int`(检查溢出)、`Float`、精确 `Decimal`、`Text`、`Bytes`、`Uuid`、`Id`、`DateTime`、`Date`、`Time`、`Duration`、`Secret`、`Json`。可空用 `T?`,集合用 `List<T>`、`Map<K,V>`。Model ID 是每个 Model 独有的名义类型,不等于任意 Int。不得把不同表的 ID 混用。
|
||||
|
||||
record 用字段初始化;choice 用分支构造:
|
||||
|
||||
```dever
|
||||
type State {
|
||||
Draft
|
||||
Published
|
||||
Rejected(reason: Text)
|
||||
}
|
||||
|
||||
label(state: State.Published) (text: Text) {
|
||||
text = "published"
|
||||
}
|
||||
|
||||
label(state: State.Rejected(reason)) (text: Text) {
|
||||
text = reason
|
||||
}
|
||||
|
||||
label(state: other) (text: Text) {
|
||||
text = "draft"
|
||||
}
|
||||
```
|
||||
|
||||
## 分支与边界
|
||||
|
||||
没有 if、else、switch、match、条件表达式或递归。同名、同参数数量的分句必须连续,相同输出合同,互斥且穷尽;没有先匹配谁的顺序优先级。`other` 是同一参数位置所有明确模式的补集。
|
||||
|
||||
```dever
|
||||
display(value: Text) (text: Text) {
|
||||
text = value
|
||||
}
|
||||
|
||||
display(value: null) (text: Text) {
|
||||
text = "missing"
|
||||
}
|
||||
|
||||
grade(score: Int < 60) (text: Text) {
|
||||
text = "fail"
|
||||
}
|
||||
|
||||
grade(score: Int >= 60) (text: Text) {
|
||||
text = "pass"
|
||||
}
|
||||
```
|
||||
|
||||
支持完整类型、choice 分支、null、Bool/Text/数值字面量、Int/Decimal 范围与 other 模式;多输入检查全部输入组合。任一函数都必须为命名输出赋值。不要写 `return` 提前退出,按分句表示结果与失败。
|
||||
|
||||
字面量分句适合明确的状态和规则,不意味着可以按某个用户 ID、租户名字或样例数据写业务特例。运行时配置与可信身份的归属见 [配置与硬编码](development.md#配置与硬编码)。
|
||||
|
||||
集合遍历使用语言的 `map/filter/reduce/each` 等核心操作及静态 handler,不能加入 for/while。handler 的签名和可达调用链由编译器检查,不是运行期闭包或动态插件。具体签名查当前版本 `library/` 与核心语言指南,不杜撰 lambda 语法。
|
||||
|
||||
## 失败和能力
|
||||
|
||||
业务错误通过 choice 的 `error` 分支声明,`fail` 传播,`result(call)` 显式捕获;普通调用直接得到成功值。不能用字符串/任意 JSON 代替类型化失败,不能捕获后悄悄吞掉错误。错误映射到 HTTP 的方式见 application.md。
|
||||
|
||||
纯 Domain 函数可声明 `pure`,编译器检查其调用链;要从 Model REST 字段来源调用的业务转换必须是合规的同领域 pure Domain。外部文件/网络 I/O 经 Port/Adapter,不把系统调用塞入普通 App 或 Domain。
|
||||
|
||||
Dever 推断挂起,无需 async/await。直接调用按顺序完成;`run` 显式启动结构化子任务,`wait/stop` 消费 Task,任务不能逃逸所属作用域。Group/Channel/Stream 具有静态资源约束;不能跨挂起、线程或请求随意保存句柄。`result` 不改变调度,也不绕开 effect 检查。
|
||||
|
||||
`Secret` 不可打印、比较或转为普通 Text。密码使用现有 crypto 能力;不要自制哈希。声明类型、分句和 effect 报错时修正真实边界,不添加无意义中转函数、泛用返回包装或吞错分句来绕过检查。
|
||||
|
||||
更多完整语法以官方核心仓库同版本 `LANGUAGE.md` 为准;新建项目先使用本 skill 的已验证模板。
|
||||
@@ -0,0 +1,46 @@
|
||||
# 标准能力与依赖
|
||||
|
||||
内置 package 不需要 import、下载或把标准库复制到 module/。先查已有能力,避免项目里堆积 parse_id、page_slice、trim 包装函数。
|
||||
|
||||
| 能力 | 入口 |
|
||||
| --- | --- |
|
||||
| 文本 | `text.trim/lower/upper/contains/starts_with/ends_with/split/replace/join` |
|
||||
| 数字 | `int.parse/to_text`、`decimal.parse/round/from_int`、`float.parse`、`math` |
|
||||
| 字节 | `dever.bytes.from_text/to_text/from_ints/length/at/slice/concat` |
|
||||
| 时间 | `dever.time.now/parse_datetime/format_datetime/parse_date/format_date/duration/add/subtract/difference` |
|
||||
| 密码与摘要 | `dever.crypto.password_hash/password_verify/token/sha256/hmac_sha256/constant_time_eq` |
|
||||
| 类型化 JSON | `dever.json`,API/CMD 通常直接复用自动 wire codec |
|
||||
| HTTP/网络/文件 | `dever.http`、`dever.net`、`dever.io`,业务外部 I/O 按 Port 边界使用 |
|
||||
| 请求与身份 | `dever.api`、`dever.auth`、`dever.site`,受入口可达性限制 |
|
||||
|
||||
这是查找索引,不保证省略的参数/返回值。精确函数签名在官方核心仓库同版本 `library/`,复杂标准能力先读取对应文件和 LANGUAGE.md。`parse` 常返回可空值,不能假定失败得到 0。新版本发布前 skill 索引与库签名须一起验证。
|
||||
|
||||
## Dever Package
|
||||
|
||||
Package 是可复用 Dever 组件。通过项目 setting.json 中的 `package.registry` 与 `package.use` 声明;显式 `dever package add|list|update|remove|doctor <root> ...` 管理。`dever.lock` 固定版本、摘要和传递依赖;Package 不能覆盖本地同名组件。不要在业务源码中引入 import 或自建 vendor 查找规则。
|
||||
|
||||
## 外部 Lib 与普通二进制
|
||||
|
||||
第三方生态叫 Lib。项目 `config/setting.json` 的根 lib 数组声明 `pip:name@version`、`npm:name@version` 或 Go 依赖,使用 `dever lib add/list/install/update/remove/doctor` 管理。add/update 自动准备实际需要的运行环境与构建工具;install 按已有锁精确恢复,不改变配置或锁。run/build 只消费锁,不联网,也不读取系统 Python、Node、Go 或 PATH。
|
||||
|
||||
锁记录原始来源、摘要、固定构建输入和产物。新机器缺少已构建产物时,install 使用固定输入重建并核对输出摘要;第三方构建不能重现相同字节时会明确失败,不能用更新锁或偷偷重新解析版本冒充恢复。检查详细错误后,由用户决定是否执行 update 重新生成锁。
|
||||
|
||||
Lib 必须通过领域 Port/Adapter 使用。Port 声明类型与失败合同,Adapter 实现它;App 只调用 Port。声明的类型、返回值、业务失败、超时和 capability 使用统一 Worker 协议,各语言 SDK 不替代编译器类型检查。Python/JS/Go SDK 与可用 runtime 必须匹配 Dever 发行版本。
|
||||
|
||||
Dever 不检查第三方语言源码内部的函数拆分、重复实现和业务硬编码;Port 类型与 Worker 协议验证不能代替这部分审查。外部生态承接确需复用的现成能力,不能用于转移普通业务逻辑以规避 Dever 约束,开发规则仍见 [项目开发](development.md)。
|
||||
|
||||
普通 Linux 二进制不需要 Worker 协议。领域 `port.dever`:
|
||||
|
||||
```dever
|
||||
execute(args: List<Text>, stdin: Bytes?) (output: dever.process.Output) fails dever.process.Error
|
||||
```
|
||||
|
||||
`adapter.dever`:
|
||||
|
||||
```dever
|
||||
external command "bin/tool" {}
|
||||
```
|
||||
|
||||
将相应架构 ELF 放在领域的 bin/tool,App 调用 `port.execute(["--version"], null)`。结果有 code、stdout、stderr,字节显式转文本;参数不是 shell 字符串。非零退出码仍是结果,启动失败/超时/超限是错误。文件、网络、子进程能力显式声明且受配置授权,不能关闭沙箱来掩盖部署问题。
|
||||
|
||||
测试必须使用 Port fake,不执行真实第三方程序。跨到 ARM 时必须提供目标架构的库和二进制,Dever 不转换已有 x86 ELF。
|
||||
@@ -0,0 +1,15 @@
|
||||
# Markdown 源码
|
||||
|
||||
使用 `dever new <new-directory> --markdown` 获得经过验证的模板;不要只把任意 Markdown 中的代码围栏改名当作完整程序。
|
||||
|
||||
文件后缀 `.dever.md`;编译器只编译顶层 `dever` 或 `typescript dever` 围栏,且校验说明与代码合同。普通 `.md` 不是源码,两种源码格式的类型、目录、访问、权限约束一致。
|
||||
|
||||
- 每个文件一个一级标题,随后写用途、包、公开类型、公开方法、使用;空项写“无”。包说明来自路径,不是源码 package 声明。
|
||||
- 每个逻辑声明有自己的二级标题、用途和唯一代码块,一级标题下不直接放源码。
|
||||
- 类型写 `- 类型:` 与字段/分支说明;函数写 `- 函数:`、输入、输出,名称、类型、顺序与代码一致。每个字段说明包含非空中文用途。
|
||||
- 同名同参数数量的所有分句放同一章节、同一围栏;不同签名或类型分开。
|
||||
- API 写 `- 声明:cmd greet`、`post publish`、`rest model` 等,与代码一致,不虚构公开方法。
|
||||
- App 自动公开其类型/函数;Domain、Adapter、API 和测试没有公开方法。调用清单隐藏 app role 和 app topic。
|
||||
- 测试同样需要完整说明,唯一入口仍是文件同名零输入零输出函数。
|
||||
|
||||
维护源码与说明后一起跑 fmt --check、check。完整声明说明协议见官方核心仓库同版本 MARKDOWN-SYNTAX.md。
|
||||
Reference in new issue
Block a user