diff --git a/README.md b/README.md index 80ed146..75f6410 100644 --- a/README.md +++ b/README.md @@ -13,8 +13,8 @@ This repository contains the documentation for: ## Features - 🌍 **Multi-language Support**: - - Source: English (`content/docs`) - - Target: Chinese (`content/docs-cn`) - *Auto-translated via AI* + - Source: English (`content/docs/*.mdx`) + - Target: Chinese (`content/docs/*.cn.mdx`) - *Auto-translated via AI using dot parser* - 📝 **MDX Content**: Interactive documentation with Type-safe components. - 🛠️ **Automated Workflows**: - AI Translation CLI (`packages/cli`) diff --git a/content/docs/concepts/ai-codex.cn.mdx b/content/docs/concepts/ai-codex.cn.mdx new file mode 100644 index 0000000..dbf7123 --- /dev/null +++ b/content/docs/concepts/ai-codex.cn.mdx @@ -0,0 +1,373 @@ +--- +title: AI 代码宝典 +description: AI 辅助 ObjectStack 开发的最佳实践 +--- + +# AI 代码宝典 + +本指南帮助开发者利用 AI 工具来提高 ObjectStack 开发效率。 + +## 为什么选择 AI 协作 + +ObjectStack 作为协议驱动的平台,涉及很多: +- 架构定义 +- UI 协议配置 +- 重复的 CRUD 代码 +- API 文档生成 + +这些都非常适合 AI 协助,可以显著提高开发效率。 + +## 核心术语 + +与 AI 协作时使用一致的术语至关重要。以下是 ObjectStack 的核心术语: + +### 数据层术语 + +- **Schema**:JSON 格式的数据模型定义,描述表结构 +- **Object**:业务对象,对应于数据库表 +- **Field**:对象字段,对应于数据库列 +- **Reference**:关系字段,用于建立对象之间的关联 +- **Virtual Field**:计算字段,不存储在数据库中 + +### 查询层术语 + +- **ObjectQL**:统一的跨数据库查询语言 +- **Query DSL**:查询域特定语言 +- **Filter**:查询过滤条件 +- **Aggregation**:聚合查询 +- **Driver**:数据库驱动程序,例如 `@objectql/driver-mysql` + +### UI 层术语 + +- **ObjectUI**:JSON 驱动的 UI 协议 +- **Component**:表单、表格、卡片等组件 +- **Action**:交互操作,如 API 请求、页面导航等 +- **Renderer**:将 JSON 协议转换为实际 UI + +### 平台层术语 + +- **ObjectOS**:运行时平台 +- **Plugin**:功能扩展 +- **Hook**:生命周期钩子,如 beforeInsert、afterUpdate +- **RBAC**:基于角色的访问控制 +- **FLS**:字段级安全 + +## AI 辅助架构设计 + +### 提示模板 + +``` +我需要在 ObjectStack 中为[业务场景]创建一个 Schema。 + +业务需求: +- [需求 1] +- [需求 2] +- [需求 3] + +请生成符合 ObjectStack 规范的 JSON Schema,包括: +1. 所有必要的字段定义 +2. 字段类型(text、number、date、reference 等) +3. 字段约束(required、unique 等) +4. 对象之间的关系定义 +``` + +### 示例对话 + +**用户**: +``` +我需要在 ObjectStack 中为电子商务订单管理系统创建一个 Schema。 + +业务需求: +- 管理客户信息(名称、电话、邮箱) +- 管理产品信息(名称、价格、库存) +- 管理订单(订单号、客户、产品列表、总金额、状态) +- 订单状态包括:待支付、已支付、已发货、已完成、已取消 + +请生成符合 ObjectStack 规范的 JSON Schema。 +``` + +**AI 响应**: +```json +{ + "objects": { + "customers": { + "label": "Customer", + "fields": { + "name": { "type": "text", "label": "Name", "required": true }, + "phone": { "type": "text", "label": "Phone" }, + "email": { "type": "email", "label": "Email", "unique": true } + } + }, + "products": { + "label": "Product", + "fields": { + "name": { "type": "text", "label": "Product Name", "required": true }, + "price": { "type": "number", "label": "Price", "required": true }, + "stock": { "type": "number", "label": "Stock", "default": 0 } + } + }, + "orders": { + "label": "Order", + "fields": { + "order_no": { "type": "text", "label": "Order Number", "unique": true }, + "customer": { "type": "reference", "ref": "customers", "label": "Customer" }, + "items": { "type": "grid", "label": "Order Items", "fields": { + "product": { "type": "reference", "ref": "products" }, + "quantity": { "type": "number", "default": 1 }, + "price": { "type": "number" } + }}, + "total": { "type": "number", "label": "Total Amount" }, + "status": { + "type": "select", + "label": "Status", + "options": ["pending", "paid", "shipped", "completed", "cancelled"], + "default": "pending" + } + } + } + } +} +``` + +## AI 辅助 UI 协议生成 + +### 提示模板 + +``` +我需要为[对象名称]创建 ObjectUI 协议。 + +UI 需求: +- [UI 需求 1] +- [UI 需求 2] + +请生成符合 ObjectStack ObjectUI 规范的 JSON 协议。 +``` + +### 示例对话 + +**用户**: +``` +我需要为订单对象创建列表页面和详情表单。 + +UI 需求: +- 列表页面显示订单号、客户名称、总金额、状态 +- 支持按状态过滤 +- 点击订单显示详情 +- 详情表单可以编辑订单状态 +``` + +**AI 响应**: +```json +{ + "pages": { + "order_list": { + "type": "page", + "title": "Order List", + "components": [ + { + "type": "table", + "object": "orders", + "columns": [ + { "field": "order_no", "label": "Order No" }, + { "field": "customer.name", "label": "Customer" }, + { "field": "total", "label": "Total" }, + { "field": "status", "label": "Status" } + ], + "filters": [ + { "field": "status", "type": "select", "label": "Status" } + ], + "actions": [ + { "type": "navigate", "target": "order_detail", "label": "View" } + ] + } + ] + }, + "order_detail": { + "type": "page", + "title": "Order Detail", + "components": [ + { + "type": "form", + "object": "orders", + "fields": [ + { "name": "order_no", "label": "Order No", "readonly": true }, + { "name": "customer", "label": "Customer", "readonly": true }, + { "name": "total", "label": "Total", "readonly": true }, + { "name": "status", "label": "Status", "type": "select" } + ], + "actions": [ + { "type": "submit", "label": "Save" } + ] + } + ] + } + } +} +``` + +## AI 辅助插件开发 + +### 提示模板 + +``` +我需要为 ObjectStack 开发一个服务端插件。 + +功能需求: +- [需求描述] + +请生成符合 ObjectStack 插件规范的代码,包括: +1. 插件入口文件 +2. 必要的生命周期钩子 +3. 错误处理 +``` + +### 示例代码生成 + +**用户**: +``` +我需要开发一个插件,在订单创建后自动发送电子邮件通知。 +``` + +**AI 响应**: +```javascript +// plugins/order-notification.js +module.exports = { + name: 'order-notification', + + hooks: { + afterInsert: async (context, object, record) => { + if (object === 'orders') { + const { customer, total, order_no } = record; + + // Query customer email + const customerData = await context.db.query({ + object: 'customers', + filters: { _id: customer }, + fields: ['email', 'name'] + }); + + if (customerData && customerData[0]?.email) { + await context.email.send({ + to: customerData[0].email, + subject: `Order Confirmation - ${order_no}`, + body: ` + Dear ${customerData[0].name}, + + Your order ${order_no} has been created successfully. + Order amount: $${total} + + Thank you for your purchase! + ` + }); + } + } + } + } +}; +``` + +## AI 辅助文档生成 + +### 自动生成 API 文档 + +使用 TypeDoc 或 JSDoc 从代码注释自动生成文档: + +```typescript +/** + * Query object data + * @param {Object} options - Query options + * @param {string} options.object - Object name + * @param {Object} options.filters - Filter conditions + * @param {Object} options.sort - Sort rules + * @param {number} options.limit - Limit count + * @returns {Promise} Query results + * + * @example + * const users = await db.query({ + * object: 'users', + * filters: { age: { $gt: 18 } }, + * sort: { created_at: 'desc' }, + * limit: 10 + * }); + */ +async function query(options) { + // Implementation code +} +``` + +然后运行: +```bash +npx typedoc --out docs/api src/ +``` + +## 最佳实践 + +### 1. 清晰的背景 + +与 AI 交流时,明确指定: +- 使用 ObjectStack 概念 +- 要遵循的协议规范 +- 目标数据库类型(如有特殊要求) + +### 2. 提供完整信息 + +包括: +- 业务需求的详细描述 +- 数据模型之间的关系 +- UI 交互流 +- 特殊业务规则 + +### 3. 验证生成的代码 + +AI 生成的代码需要: +- 验证 ObjectStack 符合性 +- 功能测试 +- 安全和性能审查 + +### 4. 迭代优化 + +如果结果不理想: +- 提供更具体的需求 +- 给出示例或参考 +- 逐步分解需求 + +## 推荐工具 + +### 代码生成 +- **GitHub Copilot**:代码补全和生成 +- **ChatGPT / Claude**:架构设计和问题解决 +- **Cursor**:AI 辅助编程 IDE + +### 文档生成 +- **TypeDoc**:TypeScript API 文档 +- **JSDoc**:JavaScript API 文档 +- **Swagger/OpenAPI**:REST API 文档 + +### 测试协助 +- **AI 生成的测试用例**:覆盖边界情况 +- **AI 代码审查**:发现潜在问题 + +## 考虑事项 + +### ⚠️ AI 限制 + +- AI 可能生成不符合最新规范的代码 +- 需要手动验证业务逻辑正确性 +- 复杂的架构设计仍需要人类决策 + +### ✅ AI 优势 + +- 快速生成重复代码 +- 提供多个实现选项 +- 协助文档编写 +- 代码重构建议 + +## 总结 + +AI 是 ObjectStack 开发的强大助手,但不是替代品。最佳实践: + +1. **使用 AI 加速**:架构定义、UI 协议、重复代码 +2. **手动审查**:业务逻辑、安全、性能优化 +3. **持续学习**:理解 AI 的能力和局限,适当使用 + +通过正确使用 AI 工具,开发效率可以提高 3-5 倍,使开发者能够更多地专注于核心业务逻辑。 diff --git a/content/docs/concepts/architecture.cn.mdx b/content/docs/concepts/architecture.cn.mdx new file mode 100644 index 0000000..0d2ae70 --- /dev/null +++ b/content/docs/concepts/architecture.cn.mdx @@ -0,0 +1,94 @@ +--- +title: 架构全景 +description: 理解 ObjectStack 三位一体。ObjectQL、ObjectOS 和 ObjectUI 如何协作构建企业内核。 +--- + +# 架构全景 + +ObjectStack 不是一个单体框架。它是一个围绕**分层架构**设计的可组合生态系统。我们称之为 **"ObjectStack 三位一体"**。 + +每一层都是解耦的,并通过标准的 JSON 协议进行通信。这使得你可以替换实现(例如,将 React 渲染器替换为 Flutter 渲染器),而不会破坏堆栈的其余部分。 + + + +## 三位一体 + +### 1. 数据层: ObjectQL +**"通用协议"** + +基础层是 ObjectQL。它负责**数据定义**和**数据访问**。 + +* **角色:** 定义*结构*(Schema)和*意图*(Query AST)。 +* **职责:** 它知道 "Customer" 对象长什么样,但它不知道*谁*在访问它或*如何*显示它。 +* **核心组件:** **编译器**。它接收抽象查询(`find customers where active = true`)并将其转换为针对特定底层数据库(Postgres、SQLite、MySQL)的优化 SQL。 + +### 2. 控制层: ObjectOS +**"业务内核"** + +位于中间的是 ObjectOS。它负责**编排**和**治理**。 + +* **角色:** 管理请求的*生命周期*。 +* **职责:** + * **身份:** "这个用户是谁?"(身份验证)。 + * **安全:** "他们能看到这个字段吗?"(RBAC/ACL)。 + * **同步:** "我们如何合并这些离线更改?"(冲突解决)。 + * **流程:** "保存这条记录后会发生什么?"(工作流/触发器)。 +* **核心概念:** 它充当网关。不允许直接访问数据库;所有操作都必须通过 OS 内核。 + +### 3. 视图层: ObjectUI +**"投影引擎"** + +顶层是 ObjectUI。它负责**交互**和**渲染**。 + +* **角色:** 消费协议来渲染界面。 +* **职责:** 它不包含硬编码的表单。相反,它询问 ObjectQL:*"Customer 的 Schema 是什么?"*,然后根据该元数据动态渲染布局。 +* **核心概念:** **服务端驱动 UI (SDUI)**。后端决定布局、验证规则和可用操作。前端仅仅是一个高性能的渲染器。 + +--- + +## 请求生命周期 + +为了理解这些部分如何协同工作,让我们追踪一个典型的用户交互——例如,销售代表在离线状态下更新交易状态。 + +### 步骤 1: 交互 (ObjectUI) +用户在 UI 中点击 "标记为成功"。 +* **ObjectUI** 根据 JSON Schema(本地加载)验证输入。 +* 它不会立即发送 API 请求。它将更改写入**本地数据库**(例如 SQLite/RxDB)。 +* UI 立即更新(0ms 延迟)。 + +### 步骤 2: 同步 (ObjectOS Sync) +当网络可用时,客户端向服务器推送 "变更包"。 +* **ObjectOS** 接收数据包。 +* 它验证会话身份(`@objectos/auth`)。 +* 它检查**审计日志**以查找冲突(例如,5 分钟前是否有其他人编辑了这笔交易?)。 +* 它运行任何服务端**工作流**逻辑(例如,"如果交易 > $10k,触发经理审批")。 + +### 步骤 3: 编译 (ObjectQL) +一旦 ObjectOS 批准请求,它将数据操作传递给 ObjectQL。 +* **ObjectQL** 接收 AST:`UPDATE Deals SET Status = 'Won' WHERE ID = '123'`。 +* **编译器**将其转换为目标方言:`UPDATE "deals" SET "status" = 'Won'...`。 +* **驱动程序**针对主 PostgreSQL 数据库执行 SQL。 + +--- + +## 部署拓扑 + +由于架构是协议驱动的,它支持各种部署模型,具体取决于你的基础设施需求。 + +### A. 单体架构(默认) +适用于中小型企业应用。 +* **前端:** React 单页应用(SPA)。 +* **后端:** 运行 ObjectOS + ObjectQL Core 的单个 Node.js 实例。 +* **数据库:** 单个 PostgreSQL 实例。 + +### B. 本地优先 / 边缘 +适用于现场服务应用、POS 系统和高性能 SaaS。 +* **前端:** ObjectUI + 嵌入式 ObjectQL(Wasm)+ SQLite。 +* **后端:** ObjectOS 作为同步网关运行(无状态)。 +* **数据库:** 分布式 SQL 或简单的对象存储用于复制日志。 + +### C. 微服务联邦 +适用于大规模企业集成。 +* 多个 ObjectOS 实例(CRM 服务、ERP 服务、HR 服务)。 +* 集中式**网关**将 ObjectQL Schema 聚合成 "超级图"(类似于 GraphQL Federation)。 +* ObjectUI 通过消费联邦 Schema 渲染统一的仪表板。 diff --git a/content/docs/concepts/core-values.cn.mdx b/content/docs/concepts/core-values.cn.mdx new file mode 100644 index 0000000..a33e99e --- /dev/null +++ b/content/docs/concepts/core-values.cn.mdx @@ -0,0 +1,81 @@ +--- +title: 核心价值 +description: "深入探讨 ObjectStack 的三大支柱:协议驱动架构、本地优先数据主权和数据库无关性。" +--- + +# 核心价值 + +ObjectStack 建立在三个不可妥协的架构价值之上。这些不仅仅是"特性";它们是指导我们每个设计决策的约束。 + +## 1. 协议驱动: 意图优于实现 + +ObjectStack 的基本论点是**应用逻辑应该由声明式数据定义,而不是命令式代码。** + +### "代码优先"的问题 +在现代开发中,"意图"(例如,*"这个字段是必填的电子邮件地址"*)通常分散在三层: +1. **数据库:** SQL 约束(`NOT NULL`)。 +2. **后端:** ORM 验证(例如 TypeORM 装饰器)。 +3. **前端:** UI 验证(例如 React Hook Form + Zod)。 + +当业务需求变更时,你必须在三个地方更新代码。这就是**实现耦合**。 + +### 协议驱动解决方案 +ObjectStack 将"意图"集中到单个协议定义(JSON/YAML)中。实现层(React、Node.js、SQL)仅仅作为解释此协议的**运行时引擎**。 + + + +* **UI 是投影:** ObjectUI 不"构建"表单;它将 ObjectQL Schema *投影*成可视化表示。 +* **API 是结果:** 你不需要编写端点;ObjectOS 基于访问控制协议*生成*安全图。 + +> **类比:** 将 ObjectStack 想象成 Web 浏览器。你向它发送 HTML(协议),它就渲染页面。你不需要每次想更改网站文本时都重写浏览器引擎(C++)。 + +## 2. 本地优先: 所有权与零延迟 + +在过去的十年中,"云原生"一直是黄金标准。虽然它解决了部署问题,但引入了一个新问题:**用户租用他们对数据的访问权。** + +如果服务器慢,应用就慢。如果互联网断开,应用就死了。 + +### "七次跳转"问题 +在传统的云应用中,一个简单的按钮点击要经过: +`点击 -> Wi-Fi -> ISP -> 云负载均衡器 -> Web 服务器 -> 数据库 -> 查询执行` ...然后一路返回。 + +### 本地优先解决方案 +ObjectStack 应用被设计为首先读写**本地数据库**(嵌入在客户端环境中)。 +`点击 -> 本地数据库 -> UI 更新`(0ms 延迟)。 + +与云的同步在后台异步进行。 + +1. **即时响应:** UI 立即反应(乐观 UI),使企业应用感觉像原生桌面软件一样流畅。 +2. **离线能力:** 现场工作人员、飞机或不稳定的连接不再是障碍。 +3. **数据主权:** 数据物理上驻留在用户的设备上。云充当同步中心,而不是唯一的守门人。 + +## 3. 数据库无关: "通用编译器" + +供应商锁定是长久性的敌人。业务应用通常比最初构建时使用的数据库技术存活时间更长。 + +ObjectQL 将底层数据库视为**实现细节**。 + +### 编译器方法 +ObjectQL 不是运行时包装器(如 ORM),而是作为**编译器**运行。 +1. **输入:** ObjectQL 抽象语法树(AST)。 +2. **处理:** 将 AST 编译为特定方言的 SQL。 +3. **输出:** 针对目标的高度优化查询。 + +这种架构允许极大的灵活性: +* **开发环境:** 运行在 **SQLite** 上(零配置,单文件)。 +* **生产环境:** 运行在 **PostgreSQL** 上(健壮,可扩展)。 +* **边缘计算:** 运行在 **Cloudflare D1** 上(分布式)。 +* **遗留系统:** 连接到现有的 **Oracle/SQL Server**(集成)。 + +你改变*驱动程序*,而不是*代码*。 + +## 总结 + +| 价值 | 旧方式 | ObjectStack 方式 | +| :--- | :--- | :--- | +| **架构** | 代码驱动(命令式) | 协议驱动(声明式) | +| **逻辑位置** | 分散(DB + API + UI) | 集中化(JSON/YAML Schema) | +| **数据访问** | 云依赖(仅在线) | 本地优先(离线 + 同步) | +| **存储** | 供应商锁定 | 数据库无关 | + +通过遵循这些价值观,我们构建的软件**能够抵御变化**,**尊重用户时间**,并且**在技术上独立自主**。 diff --git a/content/docs/concepts/enterprise-patterns.cn.mdx b/content/docs/concepts/enterprise-patterns.cn.mdx new file mode 100644 index 0000000..54b7ab9 --- /dev/null +++ b/content/docs/concepts/enterprise-patterns.cn.mdx @@ -0,0 +1,179 @@ +--- +title: 企业模式 +description: 使用协议驱动方法处理复杂的 ERP/CRM 业务逻辑(状态机、计算、RBAC)。 +--- + +# 企业模式 + +关于"低代码"或"协议驱动"平台,一个常见的误解是它们只适合简单的 CRUD 应用程序。 + +虽然这对许多可视化构建器是真实的,但 **ObjectStack** 的架构专门用于处理企业资源规划 (ERP) 和客户关系管理 (CRM) 系统的复杂性。我们处理复杂性的方式不是隐藏它,而是在协议中**明确建模**它。 + +以下是我们如何将常见的企业模式映射到 ObjectStack 架构的方法。 + +## 1. 工作流作为状态机 (FSM) + +在企业软件中,一条记录(例如"采购订单")很少只是静态数据。它是一个活的实体,会经历生命周期的不同阶段。 + +**反模式:** +在控制器中编写散乱的 `if/else` 逻辑: +```javascript +// 不要这样做 +if (order.status === 'draft' && user.role === 'manager') { + order.status = 'approved'; +} + +``` + +**ObjectStack 模式:** +我们在 ObjectOS Protocol 中将生命周期定义为**有限状态机 (FSM)**。这使业务流程具有确定性和可视化。 + +```yaml +# workflows/purchase_order.yaml +name: purchase_approval +object: purchase_order +states: + draft: + initial: true + on_exit: ['validate_budget'] + transitions: + submit: pending_approval + pending_approval: + transitions: + approve: approved + reject: rejected + guards: + approve: "user.has_permission('approve_budget')" + approved: + final: true + +``` + +* **确定性:** 订单*不能*从 `draft` 跳转到 `shipped`,除非协议允许。 +* **审计:** 引擎自动记录每个转换(谁移动它?何时?为什么?)。 + +## 2. 高精度计算(虚拟列) + +ERP 本质上是数据库与复杂电子表格的混合体。您需要计算税费、汇总项目行和计算利润——通常跨越数百万行。 + +**反模式:** +将所有数据获取到 Node.js 内存中进行循环和计算。这会杀死性能。 + +**ObjectStack 模式:** +我们使用 **ObjectQL 虚拟列**将逻辑编译到数据库层。 + +```yaml +# objects/invoice.object.yaml +name: invoice +fields: + lines: + type: master_detail + reference_to: invoice_line + + # 一个编译为 SQL 子查询或聚合的摘要字段 + total_amount: + type: summary + reference_to: lines + summary_type: sum + summary_field: amount + + # 一个编译为 SQL 表达式的公式字段 + margin_percent: + type: formula + formula: "(${total_amount} - ${cost}) / ${total_amount}" + precision: 18 + scale: 2 + +``` + +* **性能:** ObjectQL 编译器将 `total_amount` 转换为高度优化的 SQL `SUM()` 或物化视图。 +* **一致性:** 计算在 Schema 中定义一次,确保 API、UI 和报表都显示完全相同的数字。 + +## 3. 细粒度治理(字段级安全) + +在人力资源系统中,每个人都可以看到"员工"记录,但只有人力资源经理才能看到"工资"字段。 + +**反模式:** +在 API 控制器中手动删除字段:`delete user.salary`。这容易出错;开发人员经常忘记一个端点(例如搜索 API)。 + +**ObjectStack 模式:** +安全性被注入到**编译阶段**。 + +```yaml +# permissions/hr_manager.permission.yaml +role: hr_manager +object: employee +allow_read: true +allow_edit: true +field_permissions: + salary: + read: true + edit: true + +# permissions/employee.permission.yaml +role: employee +object: employee +allow_read: true +field_permissions: + salary: + read: false # 编译器从 SELECT 语句中物理移除此列 + +``` + +* **安全性:** 如果没有权限的用户尝试查询 `salary`,ObjectQL 引擎会抛出编译错误或返回 `null`(取决于配置)。它永远不会接触数据库。 + +## 4. 主从界面(复合 UI) + +企业用户需要高密度的界面。他们需要在单个屏幕上编辑订单(头)及其项目(行),而无需页面刷新。 + +**ObjectStack 模式:** +ObjectUI 支持通过 JSON 定义的**复合布局**。 + +```json +{ + "type": "layout.master_detail", + "props": { + "master_object": "order", + "detail_object": "order_line", + "link_field": "order_id" + }, + "children": [ + { + "region": "header", + "type": "form", + "fields": ["customer", "date", "status"] + }, + { + "region": "body", + "type": "grid.editable", // 类似 Excel 的可编辑表格 + "fields": ["product", "quantity", "price", "subtotal"] + } + ] +} + +``` + +* **事务感知:** ObjectUI 引擎知道这两个数据集是链接的。当用户点击"保存"时,它会构造一个**事务变动**来原子性地保存订单和行。 + +## 5. 审计跟踪和合规性 + +对于财务和医疗保健(HIPAA/SOX),"谁改变了什么"是法律要求。 + +**ObjectStack 模式:** +因为所有变动都通过 ObjectQL Protocol 进行,所以通过一个标志就能启用审计。 + +* **协议:** 引擎捕获每个字段的 `before` 和 `after` 状态。 +* **存储:** 变更被写入本地化的 `audit_log` 表(或不可变账本)。 +* **可视化:** ObjectUI 提供内置的"历史"组件,可立即呈现此日志。 + +## 总结 + +ObjectStack 通过**将模式提升到协议**来处理企业复杂性。 + +| 复杂性 | 传统代码 | ObjectStack 协议 | +| --- | --- | --- | +| **流程** | `if/else` 意大利面条式代码 | **有限状态机 (YAML)** | +| **数学** | 内存中的循环 | **虚拟列 (SQL 编译)** | +| **保密** | 手动 API 过滤 | **引擎级 RBAC** | +| **用户体验** | 硬编码的 React 表单 | **主从布局 (JSON)** | +| **历史** | 自定义日志记录逻辑 | **原生审计跟踪** | diff --git a/content/docs/concepts/manifesto.cn.mdx b/content/docs/concepts/manifesto.cn.mdx new file mode 100644 index 0000000..f5df59e --- /dev/null +++ b/content/docs/concepts/manifesto.cn.mdx @@ -0,0 +1,450 @@ +--- +title: ObjectStack 宣言 +description: 管理 ObjectStack 的存在和演进的坚不可摧的核心原则 +--- + +# ObjectStack 宣言 + +ObjectStack 的存在是为了将数据应用程序开发回归到其本质。为了维护健康和开放的生态系统,我们承诺坚守以下不可动摇的核心原则: + +## 原则 I:协议中立性 + +### 原则 + +**ObjectQL 是中立的**:它不能包含任何特定于特定语言(例如 Node.js)、数据库(例如 MySQL)或运行时(例如 Electron)的逻辑。 + +### 标准优先 + +**规范优于引擎**:任何功能必须首先在规范层中定义,然后再在引擎层中实现。我们拒绝"先实现后标准化"的黑盒方法。 + +### 这意味着什么 + +ObjectStack 的协议层(ObjectQL、ObjectUI)完全由规范定义组成,没有具体实现。这确保: + +- ObjectQL 协议可以有多个实现(JavaScript、Python、Java 等) +- ObjectUI 协议可以有多个渲染器(React、Vue、Angular 等) +- 底层数据库可以自由切换(MySQL、PostgreSQL、Oracle 等) + +### 实践指南 + +**设计协议时**: +- 使用标准 JSON Schema 格式 +- 避免引入特定于语言或概念的概念 +- 保持协议简单且可扩展 +- 先在规范层定义,再在引擎层实现 + +**开发实现时**: +- 严格遵循协议规范 +- 通过测试套件验证协议兼容性 +- 实现应该可互换,不影响应用程序 +- 实现特定逻辑不应该泄露到协议层 + +### 示例 + +```json +{ + "type": "query", + "object": "users", + "filters": { + "age": { "$gt": 18 } + }, + "sort": { "created_at": "desc" }, + "limit": 10 +} +``` + +这个 ObjectQL 查询协议可以: +- 由 JavaScript 实现编译为 MySQL 查询 +- 由 Python 实现编译为 PostgreSQL 查询 +- 由 Java 实现编译为 Oracle 查询 + +**协议保持中立;实现可替换。** + +## 原则 II:机制优于策略 + +### 原则 + +**ObjectQL 只提供机制**:它定义 `allowRead` 接口,但从不规定用户数据必须存在的位置。 + +**ObjectOS 提供实现**:用户系统、文件存储和多租户逻辑属于 OS 层。用规范污染协议层是严格禁止的。 + +### 关注点分离 + +我们完全分离"做什么"(机制)和"如何做"(策略/实现)。 + +开发者只需要: +- 定义数据模型(Schema) +- 定义接口结构(UI Protocol) +- 定义业务规则(Validation Rules) + +而无需担心: +- 数据如何存储 +- 接口如何渲染 +- 查询如何优化 +- 权限如何执行 + +### 实践指南 + +**架构定义**(机制): + +```json +{ + "object": "orders", + "fields": { + "order_id": { "type": "text", "primary": true }, + "customer": { "type": "reference", "ref": "customers" }, + "total": { "type": "number" }, + "status": { "type": "select", "options": ["pending", "completed"] } + }, + "permissions": { + "allowRead": "{{ formula }}" + } +} +``` + +协议定义**机制**(`allowRead` 接口),而 ObjectOS 提供**实现**(用户身份验证、数据过滤)。 + +开发者只需定义数据模型和权限接口,系统自动: +- 创建数据库表结构 +- 生成 CRUD API +- 提供数据验证 +- 建立关系映射 +- 执行权限规则 + +**UI 定义**(机制): + +```json +{ + "type": "page", + "components": [ + { + "type": "form", + "fields": [ + { "name": "customer", "label": "Customer", "type": "select" }, + { "name": "total", "label": "Total", "type": "number" } + ] + } + ] +} +``` + +开发者只需定义接口结构,系统自动: +- 渲染表单组件 +- 处理数据绑定 +- 执行表单验证 +- 管理状态更新 + +### 为什么这很重要 + +1. **协议层保持纯净**:ObjectQL 定义 `allowRead` 之类的机制,而不是"必须使用 JWT 认证"之类的策略 +2. **实现灵活性**:ObjectOS 可以使用 JWT、OAuth 或自定义解决方案实现用户系统 +3. **避免供应商锁定**:用户系统逻辑属于 OS 层,不硬编码在协议中 +4. **清晰的边界**:严格执行机制(ObjectQL)与实现(ObjectOS)的分离 + +### ❌ 我们拒绝的 + +**坏示例**:直接将用户身份验证逻辑添加到 ObjectQL 协议 +```json +// ❌ 禁止:这污染了协议层 +{ + "object": "users", + "authentication": { + "provider": "jwt", + "secret": "hardcoded-secret" + } +} +``` + +**好示例**:ObjectQL 定义机制,ObjectOS 提供实现 +```json +// ✅ 正确:协议定义机制 +{ + "object": "users", + "permissions": { + "allowRead": "{{ currentUser.id === record.id }}" + } +} + +// ObjectOS 实现(独立层)处理: +// - 什么是 "currentUser"? +// - 如何执行身份验证? +// - 用户数据存储在哪里? +``` + +## 原则 III:数据主权 + +### 原则 + +**本地优先**:所有架构设计必须优先考虑"离线可用性"。任何依赖云连接才能运行的核心功能都是**禁止的**。 + +**便携性**:用户数据(Schema + Data)必须可以以标准文件格式(.oos / .json)导出,永远不会被锁定在任何特定供应商的云平台中。 + +### 核心哲学 + +**"数据属于用户,不属于平台"** + +ObjectStack 遵循本地优先哲学: +- 数据默认存储在本地 +- 用户可以选择自己的数据库 +- 没有强制云服务绑定 +- 支持完全离线数据操作 +- 保证完整的数据便携性 + +### 实践指南 + +**本地优先架构**: + +1. **独立模式**: + - 使用 .oos 文件存储数据(基于 SQLite) + - 数据完全本地,不需要网络 + - 适合个人应用场景 + - 设计上支持离线工作 + +2. **自托管模式**: + - 部署到企业自己的服务器 + - 使用企业现有的数据库(MySQL、Oracle 等) + - 企业完全控制数据 + - 不依赖外部服务 + +3. **混合模式**: + - 本地优先加可选的云同步 + - 支持端到端加密 + - 用户可以随时导出数据 + - 云是增强功能,不是必需 + +### 数据迁移自由 + +**零摩擦迁移**: + +```bash +# 以标准格式导出数据 +objectstack export --format json --output my-data.json + +# 从 SQLite 迁移到 MySQL +objectstack migrate --from sqlite://app.oos --to mysql://localhost/mydb + +# 从 MySQL 迁移到 PostgreSQL +objectstack migrate --from mysql://... --to postgresql://... + +# 导出为便携 .oos 文件 +objectstack export --format oos --output my-app.oos +``` + +由于协议层抽象,数据可以自由地在不同数据库之间迁移,无需供应商锁定。用户数据(Schema + Data)总是可以以标准格式导出。 + +### 禁止的内容 + +❌ **禁止**:需要云连接的核心功能 +``` +// ❌ 禁止 +"此功能需要网络连接才能工作" +"数据必须存储在我们的云服务器上" +"不支持离线模式" +``` + +✅ **必需**:核心功能必须支持离线 +``` +// ✅ 正确 +"默认离线工作,云同步可选" +"数据存储在本地,您拥有和控制它" +"随时以 .oos 或 .json 格式导出您的数据" +``` + +### 隐私保护 + +- **字段级加密**:敏感字段可在存储中加密 +- **字段级权限**:细粒度数据访问控制 +- **审计日志**:完整的数据访问记录 +- **数据删除**:支持完整的用户数据删除 +- **无遥测锁定**:用户控制共享的数据 + +### 开源承诺 + +- 核心协议层(ObjectQL、ObjectUI)使用 MIT/Apache 2.0 开源许可 +- 确保协议规范永久开放 +- 社区可以自由实现兼容引擎 +- 避免单一供应商控制 +- 数据格式公开文档化和开放 + +## 原则 IV:稳定性承诺 + +### 原则 + +**作为基础设施,我们承诺 ObjectQL 核心语法的稳定性。** 对于破坏性变化,我们将提供至少 2 个主要版本的迁移窗口。 + +### 版本兼容性承诺 + +ObjectStack 不是典型的应用程序——它是基础设施。在 ObjectStack 上构建的应用程序必须相信其基础是稳定的。 + +**我们的承诺**: +1. **核心语法稳定性**:ObjectQL 查询语法、架构定义和协议格式是稳定的 +2. **迁移窗口**:破坏性变化需要至少 2 个主要版本的通知 +3. **弃用路径**:标记为弃用的功能将至少支持 2 个主要版本 +4. **向后兼容性**:新功能是添加性的,不是破坏性的 + +### 这在实践中意味着什么 + +**版本策略**: +- **补丁版本** (1.0.x):仅修复错误,零破坏性变化 +- **次要版本** (1.x.0):新功能,向后兼容 +- **主要版本** (x.0.0):可能包括破坏性变化,但有迁移路径 + +**破坏性变化流程**: +1. **版本 N**:功能标记为已弃用,添加警告 +2. **版本 N+1**:弃用警告继续,提供迁移指南 +3. **版本 N+2**:功能可以移除,但提供迁移工具 + +**示例时间线**: +``` +v1.0.0: 功能 X 正常工作 +v2.0.0: 功能 X 已弃用,添加警告 + "⚠️ 功能 X 已弃用,请改用功能 Y" + X 和 Y 都能工作 +v3.0.0: 功能 X 仍可工作但有警告 + 提供迁移指南和自动迁移工具 +v4.0.0: 功能 X 可以移除 + 迁移工具继续工作 +``` + +### 我们保证的 + +✅ **稳定核心**: +- ObjectQL 查询语法 +- 架构定义格式 +- 协议消息结构 +- 数据类型系统 +- 权限模型接口 + +✅ **迁移支持**: +- 自动迁移工具 +- 全面的迁移指南 +- 版本兼容性测试 +- 迁移期间的社区支持 + +### 可以改变的内容 + +以下内容可以在不需要 2 版本窗口的情况下演进: +- **实现细节**:引擎如何在内部执行查询 +- **性能优化**:查询优化策略 +- **新功能**:不破坏现有代码的添加功能 +- **错误修复**:对未预期行为的更正 +- **文档**:澄清和改进 + +### 为什么这很重要 + +作为基础设施,ObjectStack 为可能存在多年甚至数十年的应用程序提供支持。随意破坏兼容性会: +- ❌ 摧毁对平台的信任 +- ❌ 强制用户昂贵的重写 +- ❌ 在生态系统中造成分裂 +- ❌ 违反数据主权原则 + +我们的稳定性承诺确保: +- ✅ 对 ObjectStack 的长期信心 +- ✅ 可预测的升级路径 +- ✅ 更低的总体拥有成本 +- ✅ 生态系统的一致性 + +### 兼容性测试 + +每个 ObjectStack 发布版本都包括: +- 向后兼容性测试套件 +- 迁移路径验证 +- 版本兼容性矩阵 +- 破坏性变化文档 + +## 不可动摇的基础 + +这四个原则不是技术细节——它们是 **ObjectStack 的核心价值**: + +1. **协议中立性**:确保技术选择的自由 +2. **机制优于策略**:确保清晰的架构和灵活性 +3. **数据主权**:确保用户权利和数据自由 +4. **稳定性承诺**:确保长期的可靠性和信任 + +违反这些原则的功能,即使具有短期好处,**也不能**添加到 ObjectStack 中。 + +## 设计决策示例 + +### ✅ 符合规范的设计 + +**场景**:添加全文搜索功能 + +**决策**: +- 在协议层定义统一的全文搜索语法(原则 I:协议中立性) +- 允许不同的实现使用不同的搜索引擎(Elasticsearch、Meilisearch 等) +- 用户可以选择适合他们的搜索解决方案(原则 III:数据主权) +- 保持搜索语法向后兼容(原则 IV:稳定性承诺) + +**为什么符合规范**: +- 协议层定义机制,不实现 +- 没有供应商锁定 +- 支持离线搜索索引 +- 稳定、记录的语法 + +### ❌ 不符合规范的设计 + +**场景**:添加云存储功能 + +**决策**: +- 必须使用特定的云服务提供商 +- 数据必须上传到平台服务器 +- 不提供本地存储选项 +- 核心功能需要网络连接 + +**为什么违反规范**: +- ❌ 违反协议中立性(原则 I):绑定到特定供应商 +- ❌ 违反数据主权(原则 III):强制云存储,需要网络 +- ❌ 违反本地优先授权:核心功能依赖云连接 + +**符合规范的替代方案**: +- 定义存储抽象协议 +- 本地存储(SQLite、文件系统)作为默认 +- 云存储作为可选插件 +- 所有功能首先支持离线工作 + +## 实践检查清单 + +设计新功能时,问自己: + +**协议中立性**: +- [ ] 此功能在规范层中首先定义了吗? +- [ ] 它是否避免了特定于语言/数据库/运行时的逻辑? +- [ ] 它能有多个实现吗? + +**机制优于策略**: +- [ ] 它是否定义机制(接口)而不是策略(实现)? +- [ ] 实现逻辑是否正确分离到 ObjectOS 层? +- [ ] 它是否避免污染协议层? + +**数据主权**: +- [ ] 它是否支持离线工作(本地优先)? +- [ ] 用户能否以标准格式导出其数据? +- [ ] 它是否避免供应商锁定? +- [ ] 用户是否保持完全控制其数据? + +**稳定性承诺**: +- [ ] 它是否向后兼容? +- [ ] 如果破坏性,是否有 2 版本迁移路径? +- [ ] 变更是否有迁移指南文档? + +## 执行 + +这份宣言通过以下方式执行: + +1. **代码审查**:所有贡献必须符合这些原则 +2. **架构审查**:主要功能针对宣言进行审查 +3. **社区治理**:任何人都可以提出宣言违规 +4. **文档**:所有新功能记录有宣言符合性原因 + +## 总结 + +ObjectStack 宣言不仅仅是技术指南——它是一份**价值声明**。它确保: + +- **技术自由**:开发者可以选择最合适的技术栈 +- **架构纯净**:机制和实现之间的清晰分离 +- **数据自由**:用户完全拥有和控制其数据 +- **演进自由**:系统可以持续演进,不破坏兼容性 + +这些原则从根本上将 ObjectStack 与其他平台区分开来。它们是**不可动摇的**和**不可协商的**。 + +如有疑问,回到这四个原则。它们是 ObjectStack 构建的基础,以及我们对每个在 ObjectStack 上构建的人所做的承诺。 diff --git a/content/docs/concepts/terminology.cn.mdx b/content/docs/concepts/terminology.cn.mdx new file mode 100644 index 0000000..aab904c --- /dev/null +++ b/content/docs/concepts/terminology.cn.mdx @@ -0,0 +1,85 @@ +--- +title: 术语表 +description: ObjectStack 生态系统中使用的关键术语、概念和行话的词汇表。 +--- + +# 术语表 + +为了有效地浏览 ObjectStack 生态系统,理解我们使用的特定词汇很有帮助。虽然许多术语是计算机科学中的标准术语,但在我们的"协议驱动"背景下,有些术语具有特定的含义。 + +## 生态系统 + +### ObjectStack +整个协议套件和参考实现的总称。它包括数据层 (ObjectQL)、UI 层 (ObjectUI) 和操作系统 (ObjectOS)。 + +### ObjectQL(数据协议) +一个与数据库无关的协议,用于定义数据结构和查询它们。与 GraphQL(这是一个 API 规范)不同,ObjectQL 是一个**数据库编译器**,它将抽象意图转换为特定方言的 SQL(例如 PostgreSQL、SQLite)。 + +### ObjectUI(视图协议) +一个基于 JSON 的用户界面规范。它遵循**服务器驱动 UI (SDUI)** 模式,其中后端指定布局、层次和行为,前端 (React/Flutter) 充当渲染器。 + +### ObjectOS(内核) +协调生态系统的运行时环境。它管理身份、插件生命周期、工作流执行和客户端与服务器之间的数据同步。 + +--- + +## 架构概念 + +### 协议驱动 +一种开发范例,其中逻辑定义在静态、声明式数据格式 (JSON/YAML) 中,而不是在命令式代码中。目标是将**意图**(业务逻辑)与**实现**(技术栈)分离。 + +### 本地优先 +一种架构模式,其中应用程序首先读写用户设备(客户端)上嵌入的数据库。网络同步在后台进行。这确保了零延迟交互和离线可用性。 + +### 数据库编译器 +一个系统,它将高级查询 AST(抽象语法树)编译成优化的数据库查询字符串(例如 SQL)。这与 ORM 不同,后者通常作为运行时包装器对象。 + +### 虚拟列 +在 ObjectQL 架构中定义的字段,在数据库表中不物理存在,但在运行时计算。 +* *示例:* 在编译时注入到 `SELECT` 语句中的 SQL 子查询或表达式。 + +--- + +## 数据和架构 + +### 对象(实体) +ObjectStack 中数据建模的基本单元。大致相当于 SQL 中的"表"或 NoSQL 中的"集合"。对象定义包括字段、操作、触发器和权限。 + +### 驱动程序 +一个适配器插件,允许 ObjectQL 与特定的底层存储引擎通信。 +* *示例:* `@objectql/driver-postgres`、`@objectql/driver-sqlite`。 + +### AST(抽象语法树) +查询或架构的中间表示。ObjectQL 在编译器将其转换为 SQL 之前,将 JSON 请求解析为 AST。这允许在执行前进行安全注入和分析。 + +### 清单 +ObjectOS 插件的入口点配置文件(通常为 `package.json` 或 `manifest.json`)。它声明依赖项、创建资源并注册扩展。 + +--- + +## 接口和逻辑 + +### 布局 +在 ObjectUI 中定义的 JSON 结构,描述组件的视觉排列。布局可以嵌套和动态(例如主从、网格、看板)。 + +### 工作流 +定义为**有限状态机 (FSM)** 的业务流程。它包括状态(例如 `draft`、`approved`)、转换和防卫。 + +### 操作 +可由用户(UI 按钮)或系统事件(工作流转换)触发的离散逻辑单元。操作通常在架构中定义并在 TypeScript 中实现。 + +### 组件注册表 +ObjectUI 运行时中的一个映射,将字符串标识符(例如 `"chart.bar"`)链接到真实的 React 组件。这允许 JSON 协议动态实例化 UI 元素。 + +--- + +## 治理 + +### 空间(工作区) +多租户的逻辑隔离单元。单个 ObjectOS 实例可以托管多个空间。数据通过 `space_id` 列进行物理隔离。 + +### FLS(字段级安全) +一个细粒度权限模型,其中访问控制应用于单个字段(列),而不仅仅是整个对象(行)。 + +### TCK(技术兼容性工具包) +一套测试,用于验证驱动程序或渲染器是否符合官方 ObjectStack 协议。如果新驱动程序通过 TCK,则将其认证为兼容。 diff --git a/content/docs/specifications/index.cn.mdx b/content/docs/specifications/index.cn.mdx new file mode 100644 index 0000000..5d9d9db --- /dev/null +++ b/content/docs/specifications/index.cn.mdx @@ -0,0 +1,72 @@ +--- +title: 规范概述 +description: ObjectStack 协议的权威指南。理解"意图优于实现"的哲学。 +--- + +# 规范概述 + +> "我们塑造工具,随后工具塑造我们。" — Marshall McLuhan + +欢迎来到 ObjectStack 的**规范**部分("圣经")。 + +与*指南*(告诉你如何使用 SDK)或*概念*(解释哲学)不同,本节定义了生态系统的**严格契约**。它详细说明了每个 ObjectStack 实现必须遵守的线路格式、Schema 结构和确定性行为。 + +如果你正在构建新的数据库驱动程序、自定义 UI 渲染器或生成软件的 AI Agent,这就是你的参考手册。 + +## 核心哲学: 意图优于实现 + +驱动这些规范的唯一公理是**意图优于实现**。 + +在传统软件工程中,"业务意图"与"技术实现"不可分割地混合在一起。 +* **意图:** "18 岁以上的用户可以看到'葡萄酒'类别。" +* **实现:** Python 的 `if` 语句、SQL 的 `WHERE` 子句或 React 条件渲染。 + +ObjectStack 将这些完全分离。 + + + +### 关注点分离 + +| 层次 | 职责 | 格式 | 示例 | +| :--- | :--- | :--- | :--- | +| **意图(规范)** | 定义系统*是什么*。 | JSON / YAML | `visible_on: "user.age >= 18"` | +| **引擎(运行时)** | 决定*如何*执行它。 | Node.js / Go / Rust | 编译为 SQL 或生成 React Tree。 | + +通过将**意图**固定为标准化的数据协议,我们实现了: +1. **可移植性:** 相同的逻辑可以在 PostgreSQL、SQLite 或 MongoDB 上运行。 +2. **持久性:** 你今天编写的 JSON Schema 在 10 年后仍然有效,即使底层运行时从 Node.js 切换到 Bun 或 Rust。 +3. **AI 原生性:** AI 生成结构化的 JSON 意图比生成充满副作用的命令式代码更安全、更准确。 + +## 协议栈 + +这些规范分为三大支柱,对应于"三位一体"架构: + +### 1. ObjectQL(数据规范) +* **重点:** 数据建模、查询和变更。 +* **核心规范:** Schema 定义、AST 线路协议、事务模型。 +* **目标:** 使数据库层声明化且可互换。 + +### 2. ObjectUI(视图规范) +* **重点:** 界面结构、布局和交互。 +* **核心规范:** Component Schema、视图类型、Action 协议。 +* **目标:** 实现服务端驱动 UI,其中后端决定前端体验。 + +### 3. ObjectOS(运行时规范) +* **重点:** 身份、治理和编排。 +* **核心规范:** 工作流 FSM、权限注入、审计跟踪。 +* **目标:** 为业务逻辑提供标准操作环境。 + +## 一致性与术语 + +在本文档中,关键词 **"MUST"**(必须)、**"MUST NOT"**(禁止)、**"REQUIRED"**(需要)、**"SHALL"**(应当)、**"SHALL NOT"**(不应当)、**"SHOULD"**(应该)、**"SHOULD NOT"**(不应该)、**"RECOMMENDED"**(推荐)、**"MAY"**(可以)和 **"OPTIONAL"**(可选)应按照 [RFC 2119](https://www.ietf.org/rfc/rfc2119.txt) 中的描述进行解释。 + +### 这适用于谁? + +* **✅ 架构师:** 了解系统的能力和约束。 +* **✅ 驱动程序开发者:** 实现新的存储后端(例如 ClickHouse 驱动程序)。 +* **✅ 平台工程师:** 将 ObjectStack 集成到现有的微服务网格中。 +* **❌ 初级开发者:** 如果你只想构建一个应用,请从 **[入门指南](../index)** 开始。 + +--- + +**继续阅读第一个规范:** **[ObjectQL 概述](objectql/index)** diff --git a/content/docs/specifications/objectos/audit-compliance.cn.mdx b/content/docs/specifications/objectos/audit-compliance.cn.mdx new file mode 100644 index 0000000..b1462dc --- /dev/null +++ b/content/docs/specifications/objectos/audit-compliance.cn.mdx @@ -0,0 +1,152 @@ +--- +title: 审计与合规 +description: 问责协议。字段历史跟踪、系统审计跟踪和数据保留策略。 +--- + +# 审计与合规 + +在企业世界中,"谁改变了这个?"是最昂贵的问题。 + +ObjectOS 将**可审计性**视为一流公民。与您必须在控制器中手动写入日志的框架不同,ObjectOS 实现了**内核级审计**。如果变更通过 ObjectOS 引擎,它*将*被记录,无论它来自 UI、API 还是后台作业。 + +## 1. 数据历史跟踪(字段级) + +此机制跟踪业务记录内的值更改。它回答:"*Deal Amount 从 $10k 改变为 $5k 吗,谁做的?*" + +### 配置(声明式) +您无需编写代码来启用此功能。您只需在 Schema 中标记对象或特定字段。 + +```yaml +# objects/deal.object.yml +name: deal +label: Sales Deal +enable_audit: true # 主开关 + +fields: + name: + type: text + + amount: + type: currency + track_history: true # 跟踪此特定字段的更改 + + stage: + type: select + track_history: true + + description: + type: textarea + track_history: false # 不要跟踪大文本块(节省空间) + +``` + +### 历史协议 + +当事务提交时,审计引擎计算**增量**并写入 `object_history` 存储。 + +```json +{ + "event_id": "evt_001", + "timestamp": "2026-01-20T10:00:00Z", + "actor": "user_123", + "ip_address": "192.168.1.1", + "object": "deal", + "record_id": "deal_abc", + "changes": [ + { + "field": "amount", + "old_value": 10000, + "new_value": 5000 + }, + { + "field": "stage", + "old_value": "negotiation", + "new_value": "closed_won" + } + ] +} + +``` + +## 2. 设置审计跟踪(元数据级) + +超越数据,您必须跟踪**系统配置**的更改。这防止了"影子 IT"修改,其中管理员悄悄降低安全设置。 + +ObjectOS 自动记录以下操作: + +* **Schema:** 创建/删除对象或字段。 +* **安全:** 更改权限集或共享规则。 +* **逻辑:** 修改工作流或触发器。 +* **用户:** 密码重置、角色分配。 + +### 示例日志条目 + +> **用户:** Alice(管理员) +> **操作:** 权限简介更新 +> **目标:** Sales Rep 简介 +> **更改:** `lead.export_permission` 从 `false` 改为 `true`。 + +## 3. 登录与访问日志 + +为了符合安全合规性,访问事件被单独跟踪。 + +* **登录成功/失败:** 跟踪时间戳、用户、IP、用户代理和身份验证方法(密码 vs. SSO)。 +* **API 访问:** (可选)可以配置为在高安全环境中记录每个 API 调用(警告:高容量)。 + +## 4. 存储与保留策略 + +审计日志增长迅速。ObjectOS 提供了**保留协议**来有效地管理生命周期成本。 + +### 架构 + +审计数据**永不**与事务性数据存储在同一表中。 + +* **热存储(最后 30 天):** 存储在主 SQL 数据库中以供 UI 即时访问。 +* **冷存储(存档):** 卸载到低成本对象存储 (S3/Parquet) 或专用日志服务 (Elasticsearch/Splunk)。 + +### 策略配置 + +```yaml +# config/audit_retention.yml +policies: + - object: deal + retention_period: 3650 # 10 年(财务规定) + archive_after: 90 # 90 天后移至冷存储 + + - object: task + retention_period: 180 # 6 个月 + purge_after: 180 # 硬删除 + +``` + +## 5. 合规功能(GDPR/HIPAA) + +### "被遗忘权"(GDPR) + +当用户请求删除时,ObjectOS 提供 `System.anonymize` 实用程序。 + +* 它从 `users` 表中清除 PII(个人可识别信息)。 +* **关键:** 它*不*删除审计日志行(用于法律完整性),但它掩盖 `actor` ID 或用"匿名用户"替换名称,确保历史完整性,同时尊重隐私。 + +### 不可变性 + +审计引擎被设计为**仅追加**。 + +* API 不为 `audit_log` 对象暴露 `UPDATE` 或 `DELETE` 端点。 +* 即使系统管理员也无法通过标准 UI/API 删除审计跟踪(需要直接数据库访问,留下自己的痕迹)。 + +## 6. 快照(时间旅行) + +对于高级场景,ObjectOS 支持**完整文档快照**。它不是存储差异,而是存储每次保存时记录的整个 JSON 版本。 + +* **用例:** 法律合同或医疗记录,您需要"查看记录在 2024 年 1 月 1 日时的确切样子"。 +* **配置:** `enable_versioning: true`。 + +## 摘要 + +ObjectOS 审计协议确保您的应用"开箱即用"是企业就绪的。 + +1. **零代码:** 只需添加 `track_history: true`。 +2. **精细:** 跟踪特定字段,而不仅仅是"修改日期"。 +3. **治理:** 跟踪管理员(设置审计跟踪)。 +4. **生命周期:** 自动存档和清除以管理数据库增长。 diff --git a/content/docs/specifications/objectos/automation-rules.cn.mdx b/content/docs/specifications/objectos/automation-rules.cn.mdx new file mode 100644 index 0000000..05e23b5 --- /dev/null +++ b/content/docs/specifications/objectos/automation-rules.cn.mdx @@ -0,0 +1,165 @@ +--- +title: 自动化规则 +description: 服务器端逻辑协议。数据库触发器、计划作业和无代码自动化流。 +--- + +# 自动化规则 + +虽然工作流引导记录经历生命周期,但**自动化规则**处理数据变更的即时逻辑和副作用。 + +ObjectOS 将自动化分为三类: +1. **触发器(代码):** 用于数据完整性的高性能、同步 TypeScript 钩子。 +2. **流(低代码):** 声明性、异步事件链(IFTTT 风格)。 +3. **计划作业:** 基于时间的执行(CRON)。 + +## 1. 数据库触发器(同步逻辑) + +触发器是系统的"反射"。它们在数据库操作发生**之前**或**之后**截获它们。它们在与变更相同的数据库事务中执行。 + +### 触发器定义 + +触发器在对象定义旁的 TypeScript 文件中定义。 + +```typescript +// triggers/order.trigger.ts +import { Trigger } from '@objectos/types'; + +export const validateDiscount: Trigger = { + name: 'validate_order_discount', + object: 'order', + on: ['create', 'update'], + when: 'before', // 在写入数据库前运行 + + handler: async ({ doc, previousDoc, session, broker }) => { + // 1. 逻辑:折扣不能超过 20%,除非获得授权 + if (doc.discount > 0.20 && !session.hasRole('manager')) { + throw new Error("Discounts > 20% require Manager approval."); + } + + // 2. 逻辑:自动计算最终价格 + doc.final_price = doc.list_price * (1 - doc.discount); + } +} + +``` + +### 关键能力 + +* **验证:** 抛出错误将中止整个事务。 +* **计算:** 直接修改 `doc` 会更新正在保存的数据。 +* **快照访问:** 您可以访问 `doc`(新状态)和 `previousDoc`(旧状态)来检测更改(例如,`if (doc.status !== previousDoc.status)`)。 + +## 2. 自动化流(声明性逻辑) + +对于不需要硬编码的逻辑,ObjectOS 支持**自动化流**。这些在 YAML 中定义(或通过可视化生成器构建),并在事务提交**之后****异步**运行。 + +### 流协议 + +```yaml +# automations/notify_high_value_deal.yaml +name: notify_high_value_deal +label: Notify VP on Big Deals +trigger: + type: data.changed + object: deal + condition: "doc.amount > 1000000 && doc.stage == 'closed_won'" + +actions: + - type: notification.send + params: + recipient: "role:vp_sales" + subject: "Big Win: ${doc.name}" + message: "Deal closed for ${formatCurrency(doc.amount)}!" + + - type: record.create + params: + object: "audit_log" + data: + event: "big_deal_alert" + deal_id: "${doc._id}" + +``` + +### 流组件 + +* **触发器:** 什么启动流?(`data.changed`、`user.login`、`webhook.received`)。 +* **条件:** 必须为真的逻辑表达式(表达式语言)。 +* **操作:** 任务的顺序列表(发送电子邮件、调用 API、创建记录)。 + +## 3. 计划作业(CRON) + +企业系统需要在没人注意时做事情。ObjectOS 包括一个分布式**作业调度程序**。 + +### 协议定义 + +```yaml +# jobs/monthly_invoicing.job.yml +name: generate_monthly_invoices +cron: "0 0 1 * *" # 每月 1 日午夜运行 +timeout: 3600 # 最多 1 小时 +retries: 3 + +task: + action: "finance.batch_generate_invoices" + params: + period: "last_month" + +``` + +* **分布式:** 在集群中,OS 确保作业在**仅一个**节点上运行(通过 Redis 锁)。 +* **弹性:** 失败的作业根据策略自动重试。 + +## 4. 服务器端脚本 API + +无论是编写触发器还是自定义操作,您都通过标准**代理 API** 与 ObjectOS 内核交互。这确保您的代码是安全的、版本升级兼容的。 + +### 代理对象 + +`broker` 是您访问操作系统其余部分的网关。 + +```typescript +// 在触发器或服务内部 +async function handler({ broker, session }) { + + // 1. 数据访问(尊重权限) + const user = await broker.call('data.find', { + object: 'user', + id: 'u1' + }, { session }); + + // 2. 跨服务调用 + await broker.call('mail.send', { ... }); + + // 3. 发出自定义事件 + broker.emit('custom.event', { foo: 'bar' }); +} + +``` + +### "Sudo"模式 + +有时您需要绕过权限(例如,系统后台作业)。 + +```typescript +// 创建系统会话(超级管理员) +const sudoSession = session.sudo(); + +await broker.call('data.update', { ... }, { session: sudoSession }); + +``` + +## 5. 比较:触发器 vs. 流 vs. 工作流 + +| 特征 | 数据库触发器 | 自动化流 | 工作流 (BPM) | +| --- | --- | --- | --- | +| **协议** | TypeScript | YAML / JSON | YAML / BPMN | +| **时间** | 同步(阻塞) | 异步(后台) | 长期运行(天/周) | +| **事务性** | 是(可回滚) | 否(已提交) | 否 | +| **用例** | 数据完整性、计算 | 通知、同步 | 批准、生命周期 | +| **复杂性** | 高(代码) | 低(配置) | 中等(状态机) | + +:::tip 最佳实践 +始终为数据完整性选择**触发器**(例如,"价格不能为负")。 +始终为人工流程选择**工作流**(例如,"经理必须批准")。 +为介于两者之间的所有内容使用**流**(例如,"更新时发送电子邮件")。 +::: diff --git a/content/docs/specifications/objectos/index.cn.mdx b/content/docs/specifications/objectos/index.cn.mdx new file mode 100644 index 0000000..55e69f6 --- /dev/null +++ b/content/docs/specifications/objectos/index.cn.mdx @@ -0,0 +1,92 @@ +--- +title: ObjectOS 概述 +description: 业务操作系统介绍。身份、同步和编排的内核。 +--- + +# ObjectOS 协议 + +**ObjectOS** 是 ObjectStack 生态系统的运行时**内核**。 + +虽然 ObjectQL 定义*结构*(数据),ObjectUI 定义*外观*(视图),但 ObjectOS 定义**生命**。它负责编排身份、强制执行安全性、管理数据同步和执行业务逻辑。 + +## 内核隐喻 + +将标准 Web 框架(如 Express 或 NestJS)视为"裸机"环境,您必须手动配置身份验证、数据库连接和 API 路由。 + +ObjectOS 像一个**操作系统**一样为您的业务逻辑服务: +1. **启动:** 它加载核心服务(Auth、HTTP、Sync)。 +2. **挂载:** 它将 ObjectQL Schema 定义加载到内存中。 +3. **运行:** 它在沙盒化的、受治理的环境中执行插件和工作流。 + + +## 核心责任 + +ObjectOS 解决企业后端开发的"硬问题",以便您无需重新发明它们。 + +### 1. 身份与治理(守卫) +仅仅"登录"是不够的。企业应用需要复杂的治理。 +* **身份验证:** 本地支持 OIDC、SAML 和 JWT。 +* **RBAC:** 在 API 网关级别强制执行基于角色的访问控制。 +* **审计:** 自动记录*谁*对*哪条记录*做了*什么*(不可变审计日志)。 + +### 2. 本地优先同步(桥梁) +这是 ObjectOS 的区别特征。它充当离线优先客户端的**复制主机**。 +* **差分同步:** 计算客户端本地数据库和服务器数据库之间的"增量"(变化)。 +* **冲突解决:** 实现诸如最后写入获胜 (LWW) 或向量时钟之类的策略来处理离线用户的并发编辑。 + +### 3. 工作流编排(指挥) +业务逻辑被建模为**状态机**,而不是意大利面条代码。 +* ObjectOS 管理文档的转换(例如,`Draft` -> `Pending` -> `Approved`)。 +* 它在状态变化发生时执行**触发器**和 **Webhook**。 + +### 4. 事件总线(神经系统) +ObjectOS 从根本上是**事件驱动**的。 +* 它为模块间通信提供了一个集中的 `Broker`。 +* *示例:* 当 `CRM` 插件发出 `deal.won` 时,`Finance` 插件监听并自动生成发票。 + +## 插件架构 + +ObjectOS 遵循**微内核架构**。核心很小;其他一切都是**插件**。 + +即使是标准功能(如"用户管理"或"文件上传")也只是插件。这确保了系统是模块化的、精简的。 + +### 插件解剖 + +插件是一个自包含的包,通过**清单**声明其功能。 + +```typescript +// plugins/crm/manifest.ts +export default definePlugin({ + id: "steedos-crm", + version: "1.0.0", + + // 此插件所需的依赖项 + dependsOn: ["@objectos/auth", "@objectos/notifications"], + + // 此插件对操作系统的贡献 + objects: ["./objects/*.object.yml"], + workflows: ["./workflows/*.workflow.yml"], + + // 生命周期钩子 + async onLoad(ctx) { + ctx.logger.info("CRM Plugin Booted"); + } +}); + +``` + +## 为什么选择 ObjectOS? + +| 问题 | ObjectOS 解决方案 | +| --- | --- | +| **意大利面条代码** | 逻辑组织为**插件**和**工作流**。 | +| **安全漏洞** | 安全由**内核**注入(RBAC、FLS),而不是在控制器中编写。 | +| **离线同步** | 内置**同步引擎**处理本地优先数据的复杂性。 | +| **供应商锁定** | 操作系统抽象底层基础设施(DB、文件存储)。 | + +## 后续步骤 + +* **[插件系统](plugin-manifest):** 如何构建扩展。 +* **[工作流引擎](workflow-engine):** 自动化业务流程。 +* **[同步协议](integration-etl):** 理解复制机制。 +* **[安全模型](permission-governance):** 身份验证和 RBAC 深度解析。 diff --git a/content/docs/specifications/objectos/integration-etl.cn.mdx b/content/docs/specifications/objectos/integration-etl.cn.mdx new file mode 100644 index 0000000..ad2df4e --- /dev/null +++ b/content/docs/specifications/objectos/integration-etl.cn.mdx @@ -0,0 +1,180 @@ +--- +title: 集成与 ETL +description: 连接性协议。数据导入/导出、虚拟对象(外部数据源)和 API 映射标准。 +--- + +# 集成与 ETL + +没有企业应用是孤立的。它必须从供应商那里摄入 CSV、将订单同步到 SAP、以及从 LinkedIn 提取潜在客户数据。 + +ObjectOS 提供了统一的**集成协议**来处理这些场景。您不必编写自定义 Python 脚本或维护脆弱的中间件,只需在标准 YAML 中定义**数据映射**和**连接器**。 + +## 1. 导入/导出协议(ETL) + +ObjectOS 包括为批量操作而设计的内置 ETL(提取、转换、加载)引擎。 + + + +### 映射模板 +最终用户讨厌映射列("'First Name' 映射到 `fname` 还是 `first_name`?")。您可以预定义**映射模板**。 + +```yaml +# integration/mappings/lead_import_linkedin.map.yml +name: linkedin_lead_import +target_object: lead +source_format: csv + +field_mapping: + - source: "Profile URL" + target: "linkedin_url" + + - source: "Full Name" + target: ["first_name", "last_name"] + transform: "split_name" # 内置助手 + + - source: "Company" + target: "company_id" + transform: "lookup" # 将字符串解析为外键 ID + params: + object: "account" + field: "name" + auto_create: true # 如果找不到,创建 Account + +``` + +### Upsert 逻辑 + +重复数据是敌人。ETL 协议支持声明式去重。 + +```yaml +mode: upsert +upsert_key: ["email"] # 如果电子邮件存在,则更新;否则插入。 +batch_size: 1000 +error_policy: skip # skip、abort 或 retry + +``` + +## 2. 虚拟对象(外部数据源) + +传统上,如果您想在您的应用中显示来自外部 ERP(例如 SAP 订单)的数据,您必须同步它(复制数据 = 陈旧数据)。 + +ObjectOS 引入了**虚拟对象**。您在 ObjectQL 中定义 Schema,但数据保留在外部系统中。ObjectOS 充当**实时代理**。 + +### 定义 + +```yaml +# objects/sap_order.object.yml +name: sap_order +label: SAP Sales Order +datasource: sap_erp_connector # 指向配置的 OData/REST 源 +virtual: true # 数据不存储在 ObjectOS 数据库中 + +fields: + order_number: + type: text + external_name: "OrderID" # 映射到远程 API 字段 + + amount: + type: currency + external_name: "TotalNet" + +``` + +### 透明查询 + +当前端请求: +`GET /api/objectql/sap_order?filters=[["amount", ">", 1000]]` + +ObjectOS 内核实时将其转换为外部 API 调用: +`GET https://sap-gateway.com/Orders?$filter=TotalNet gt 1000` + +UI 组件(网格)不知道区别。它就是有效。 + +## 3. Webhook 和事件集成 + +用于实时、事件驱动的集成。 + +### 入站 Webhook + +您无需编写 Node.js 路由来处理 Stripe 支付,只需定义**Webhook 接收器**。 + +```yaml +# integration/webhooks/stripe_payment.yml +path: /webhooks/stripe +secret: "${env.STRIPE_SECRET}" + +actions: + - type: script + code: | + if (payload.type === 'payment_intent.succeeded') { + const email = payload.data.object.receipt_email; + // 调用内部 broker 来更新 Subscription + await broker.call('subscription.renew', { email }); + } + +``` + +### 出站 Webhook + +当 ObjectOS 中的事件发生时,将数据推送到其他系统。 + +```yaml +# triggers/slack_notify.trigger.yml +object: incident +on: create +action: webhook.send +params: + url: "[https://hooks.slack.com/](https://hooks.slack.com/)..." + payload: + text: "New Incident: ${doc.title}" + +``` + +## 4. OData 和 GraphQL 标准 + +ObjectOS 不仅仅是 API 的消费者;它是标准 API 的**生产者**。 + +为了确保您的应用与更广泛的生态系统配合工作(Excel、PowerBI、Salesforce),ObjectOS 自动暴露标准端点。 + +### OData v4 支持 + +每个 ObjectQL Schema 都自动映射到 OData 元数据文档。 + +* **URL:** `/api/odata/v4/$metadata` +* **优势:** 您可以打开 Excel,转到"数据 > 获取数据 > 从 OData 源",粘贴您的 ObjectOS URL,获取实时、可刷新的数据电子表格。**无需编码。** + +### GraphQL 支持 + +对于喜欢 GraphQL 而不是 ObjectQL JSON 的前端开发人员。 + +* **URL:** `/graphql` +* **Schema:** 从对象定义即时生成。 + +## 5. 转换引擎 + +数据很少完全匹配。ObjectOS 提供了一种轻量级表达式语言(基于 JSONata)用于**有效负载转换**。 + +**场景:** 外部 API 发送 `{"user": {"first": "John", "last": "Doe"}}`,但您需要 `full_name`。 + +**转换定义:** + +```yaml +transform: + full_name: "${data.user.first} & ' ' & ${data.user.last}" + status_code: "${data.isActive ? 'Active' : 'Inactive'}" + +``` + +## 摘要 + +| 集成类型 | 模式 | 用例 | +| --- | --- | --- | +| **ETL 导入** | 批量 / 计划 | 迁移遗留数据、每月供应商 CSV。 | +| **虚拟对象** | 实时代理 | 查看 SAP 订单而不复制它们。 | +| **Webhook** | 事件驱动 | 实时支付确认、Slack 警报。 | +| **OData/GraphQL** | 标准协议 | BI 工具(PowerBI、Tableau)、第三方客户端。 | + +:::tip 架构决定 +当您需要查看数据但不拥有数据时,使用**虚拟对象**。 +当您需要在该数据上运行复杂查询、报告或触发器时,使用 **ETL/同步**(因为外部 API 通常很慢或在过滤中受到限制)。 +::: diff --git a/content/docs/specifications/objectos/permission-governance.cn.mdx b/content/docs/specifications/objectos/permission-governance.cn.mdx new file mode 100644 index 0000000..b48a1ce --- /dev/null +++ b/content/docs/specifications/objectos/permission-governance.cn.mdx @@ -0,0 +1,180 @@ +--- +title: 权限与治理 +description: 三层安全模型。RBAC、字段级安全和记录级共享规则。 +sidebar_position: 3 +slug: /objectos/permission-governance +--- + +# 权限与治理 + +在 ObjectStack 中,安全性不是在 API 控制器或 UI 逻辑中实现的。它是**由内核注入**的。 + +当开发人员编写查询 `db.find('contract')` 时,他们不需要担心*谁*在运行它。ObjectOS 内核自动截获请求、分析用户会话,并重写查询以确保他们只能看到允许他们看到的内容。 + +我们称之为**三层安全模型**。 + + + +## 第 1 层:对象级安全 (RBAC) +**"我能进入房间吗?"** + +这是基础的基于角色的访问控制。它确定用户是否可以对对象类型执行通用 CRUD 操作。 + +### 简介定义 +权限捆绑到**简介**或**权限集**中。 + +```yaml +# permissions/profiles/sales_rep.profile.yml +name: sales_rep +label: Sales Representative +license: standard + +permissions: + - object: lead + allow_create: true + allow_read: true + allow_edit: true + allow_delete: false # 代表无法删除潜在客户 + allow_view_all: false # 只能看到自己的(参见第 3 层) + allow_modify_all: false + + - object: product + allow_read: true + allow_create: false # 只读 + +``` + +* **`allow_view_all`:** "上帝模式"标志。如果为真,则忽略共享规则(第 3 层)。 +* **`allow_modify_all`:** 无论所有权如何,都可以编辑/删除任何记录。 + +## 第 2 层:字段级安全 (FLS) + +**"我能看到这个文件夹的内容吗?"** + +即使您有权访问 `Employee` 对象,您也可能无权查看 `Salary` 列。 + +### FLS 协议 + +FLS 与对象权限一起定义。它控制可见性(`read`)和可变性(`edit`)。 + +```yaml +# permissions/profiles/sales_rep.profile.yml (续) +field_permissions: + # 对象:lead + lead.revenue: + read: true + edit: true + + # 对象:employee + employee.salary: + read: false # 编译器从 SELECT 中物理移除此列 + edit: false + +``` + +### 编译器行为 + +如果用户尝试查询禁止的字段: + +1. **严格模式:** API 抛出 `403 Forbidden` 错误。 +2. **宽松模式(默认):** 该字段从返回有效负载中静默删除(返回 `undefined`),确保 UI 不会崩溃,但数据仍然安全。 + +## 第 3 层:记录级安全(共享) + +**"我能打开哪些特定文件?"** + +这是最复杂和最强大的层。它回答:"*为什么 Alice 能看到 Deal A 但不能看到 Deal B?*" + +ObjectOS 根据四种机制(按顺序评估)确定记录可见性: + +### 1. 组织范围默认值 (OWD) + +对象的基线策略。 + +* **公共读/写:** 每个人都可以查看和编辑所有内容。 +* **公开只读:** 每个人都可以查看,但只有所有者可以编辑。 +* **私密:** 用户只能看到他们拥有的记录(或被授予访问权限的记录)。 + +### 2. 所有权 + +每条记录都有一个 `owner` 字段(用户 ID)。 + +* **所有者**始终对其记录拥有完全访问权限(读/编辑/删除/转移)。 + +### 3. 角色层次结构 + +ObjectOS 支持分层树(例如,CEO > VP > Manager > Rep)。 + +* **规则:** 经理继承对下属拥有的数据的访问权限。 +* 如果 Rep 拥有 Deal,他们的 Manager 可以自动看到它。 + +### 4. 共享规则(基于条件) + +层次结构的例外。用于横向共享数据或基于逻辑共享数据。 + +```yaml +# permissions/sharing/deal_high_value.sharing.yml +name: share_high_value_deals +object: deal +type: criteria +condition: "amount > 1000000" # 如果交易超过 100 万美元 + +access_level: read_only + +shared_with: + role: "vp_finance" # 与财务副总裁共享,即使他们在不同的分支 + +``` + +## 查询注入机制 + +这是如何有效工作的?ObjectOS **不**在内存中过滤数据(这会很慢)。它使用**谓词注入**。 + +**场景:** +用户"Alice"(角色:Rep,ID:`u1`)查询 `SELECT * FROM lead`。 +`lead` 对象是**私密**的。 + +**步骤 1:内核分析** + +* Alice 在 `lead` 上有 `allow_read: true`。(第 1 层:通过) +* Alice 请求 `salary`,但 `FLS: false`。字段已删除。(第 2 层:已调整) +* Alice 在"西方销售"角色中。 + +**步骤 2:谓词生成** +安全引擎生成 SQL `WHERE` 子句: + +```sql +( + -- 所有权 + t1.owner = 'u1' + OR + -- 层次结构(Alice 的下属) + t1.owner IN ('u2', 'u3') + OR + -- 共享规则(与 Alice 的小组共享) + t1.id IN (SELECT record_id FROM objectos_shares WHERE user_or_group_id = 'group_western') +) + +``` + +**步骤 3:最终执行** +修改后的 AST 被发送到数据库驱动程序。 + +## 共享计算 + +为了性能,复杂的共享规则(如组成员关系和共享条件)通常被预计算为**共享表** (`objectos_shares`)。 + +* **异步计算:** 当用户角色改变或 Deal 金额改变时,后台作业重新计算 `objectos_shares` 条目。 +* **即时读取:** 查询只需加入共享表,保持读取延迟低。 + +## 摘要:安全矩阵 + +| 层 | 控制 | 通过以下配置 | 执行 | +| --- | --- | --- | --- | +| **对象 (RBAC)** | CRUD 操作 | 简介 (YAML) | API 网关 | +| **字段 (FLS)** | 列可见性 | 简介 (YAML) | 查询编译器 (AST) | +| **记录 (共享)** | 行可见性 | OWD / 规则 / 层次结构 | SQL 注入 (WHERE) | + +:::tip 开发人员注意 +编写服务器端代码(触发器/API)时,您通常使用**用户会话**。安全规则会自动应用。如果需要访问所有数据(例如,用于后台计算),请明确使用 `session.sudo()` 或 `sudo: true` 来绕过第 3 层检查。 +::: diff --git a/content/docs/specifications/objectos/plugin-manifest.cn.mdx b/content/docs/specifications/objectos/plugin-manifest.cn.mdx new file mode 100644 index 0000000..15964ca --- /dev/null +++ b/content/docs/specifications/objectos/plugin-manifest.cn.mdx @@ -0,0 +1,199 @@ +--- +title: 插件清单 +description: 打包能力的规范。清单结构、生命周期钩子和依赖项管理。 +--- + +# 插件清单 + +ObjectOS 遵循**微内核架构**。核心引擎是极小的,仅提供基本运行时(Auth、DB 驱动程序、HTTP 服务器)。 + +所有业务功能——CRM、项目管理、人力资源以及甚至系统工具(如"文件存储")——都作为**插件**提供。 + +插件是可部署单元(通常是 NPM 包),其中包含**清单文件**。此清单告诉内核插件对系统的确切贡献。 + +## 1. 清单结构(`plugin.config.yml`) + +每个插件的入口点是其配置文件。这是模块的"身份证"。 + +```yaml +# plugin.config.yml +id: "@steedos/crm" +version: "2.4.0" +name: "Steedos CRM" +description: "Enterprise Customer Relationship Management suite." +author: "Steedos Labs" +license: "MIT" + +# 1. 依赖项管理 +dependencies: + "@objectos/auth": "^1.0.0" + "@steedos/common": "^2.0.0" + +# 2. 贡献点(协议加载) +contributes: + objects: + - "./objects/*.object.yml" + apps: + - "./apps/*.app.yml" + workflows: + - "./workflows/*.workflow.yml" + permissions: + - "./permissions/*.profile.yml" + translations: + - "./i18n/*.json" + +# 3. 服务器端逻辑 +entry: "./src/index.ts" + +``` + +## 2. 贡献点 + +`contributes` 部分允许内核**自动发现**资源。您无需手动编写 `app.register(...)` 代码。 + +### 标准贡献 + +| 类型 | 描述 | 路径惯例 | +| --- | --- | --- | +| **对象** | 数据 Schema 定义。 | `src/objects/*.yml` | +| **应用** | 应用分组(菜单结构)。 | `src/apps/*.yml` | +| **触发器** | 后端逻辑钩子。 | `src/triggers/*.ts` | +| **API** | 自定义 REST/GraphQL 端点。 | `src/api/*.ts` | +| **客户端** | 自定义 UI 组件(React)。 | `src/client/index.tsx` | +| **资源** | 静态文件(图像、CSS)。 | `public/` | + +### 扩展点 + +插件也可以定义*新的*贡献点。 + +* *示例:* "支付插件"可能会暴露 `payment_gateways` 贡献点,允许其他插件注册"Stripe"或"PayPal"适配器。 + +## 3. 插件生命周期 + +ObjectOS 严格管理插件的生命周期以确保稳定性。 + +### 生命周期接口(TypeScript) + +如果您的插件需要在启动期间执行逻辑(例如,连接到 Redis、种子初始数据),您可以导出实现 `PluginLifecycle` 接口的类。 + +```typescript +// src/index.ts +import { Plugin, PluginContext } from '@objectos/types'; + +export default class CRMPlugin implements Plugin { + + /** + * 阶段 1:加载 + * 验证配置。还不连接数据库。 + */ + async onLoad(ctx: PluginContext) { + ctx.logger.info("CRM Plugin Loaded"); + } + + /** + * 阶段 2:初始化(安装) + * 当插件首次安装时运行一次。 + * 很好用于种子默认数据(例如,默认的"Lead Status"值)。 + */ + async onInstall(ctx: PluginContext) { + await ctx.broker.call('data.create', { + object: 'lead_status', + data: { name: 'New', is_default: true } + }); + } + + /** + * 阶段 3:启动 + * 系统已准备好。连接到外部服务。 + */ + async onStart(ctx: PluginContext) { + // 启动后台工作进程 + this.worker = new LeadScoringWorker(); + await this.worker.start(); + } + + /** + * 阶段 4:停止 + * 优雅关闭。 + */ + async onStop(ctx: PluginContext) { + await this.worker.stop(); + } +} + +``` + +## 4. 资源隔离与命名空间 + +为了防止插件冲突(例如,两个插件都定义了 `settings` 对象),ObjectOS 强制执行命名空间约定。 + +* **全局命名空间:** 核心对象(`user`、`space`、`role`)。 +* **插件命名空间:** 自定义对象应该加前缀,如果用于公开分发(例如,`stripe_payment_log`)。 + +但是,对于内部企业项目,通常会省略命名空间以获得更简单的 API。清单验证器在启动时检查 **ID 冲突**,如果两个插件声明相同的对象名称,则抛出 `硬错误`。 + +## 5. 配置与环境 + +插件应符合 12-因素应用标准。它们不应在代码中存储配置。 + +### 配置模式 + +插件可以声明它期望的配置。 + +```yaml +# plugin.config.yml +config_schema: + stripe_key: + type: string + required: true + secret: true + description: "API Key from Stripe Dashboard" + +``` + +### 注入 + +操作系统从环境变量或中央 `steedos-config.yml` 注入这些值。 + +* 环境变量:`STEEDOS_CRM_STRIPE_KEY=sk_test_...` +* 代码中的访问:`ctx.config.stripe_key` + +## 6. 分发(NPM) + +ObjectOS 插件是标准**NPM 包**。 + +### 开发流程 + +1. **创建:** `npm create objectos-plugin my-plugin` +2. **开发:** `npm run dev`(启动本地内核和热重载)。 +3. **构建:** `npm run build`(将 TS 编译为 JS,验证 YAML)。 +4. **发布:** `npm publish`(部署到私有或公开注册表)。 + +### 安装 + +要将插件添加到您的项目: + +```bash +npm install @steedos/crm + +``` + +然后将其添加到您的项目的 `steedos-config.yml`: + +```yaml +plugins: + - "@steedos/crm" + +``` + +## 摘要 + +插件清单将代码变为**产品**。 + +| 特征 | 描述 | +| --- | --- | +| **清单** | 功能的声明性清单(`plugin.yml`)。 | +| **自动加载器** | 无需连接;只需将文件放在文件夹中。 | +| **生命周期** | 为健壮逻辑的结构化钩子(`onInstall`、`onStart`)。 | +| **配置** | 类型安全配置注入。 | +| **标准** | 基于 NPM 生态系统用于版本控制和分发。 | diff --git a/content/docs/specifications/objectos/workflow-engine.cn.mdx b/content/docs/specifications/objectos/workflow-engine.cn.mdx new file mode 100644 index 0000000..1ae8cdb --- /dev/null +++ b/content/docs/specifications/objectos/workflow-engine.cn.mdx @@ -0,0 +1,192 @@ +--- +title: 工作流引擎 +description: 业务流程管理 (BPM) 协议。状态机、审批链和 BPMN 映射。 +--- + +# 工作流引擎 + +**ObjectOS 工作流引擎**是一个确定性状态机,它控制业务对象的生命周期。 + +与即席脚本或分散的布尔标志不同,工作流协议将"道路规则"集中化。它确保 `Purchase Order` 不能在不经过 `Approved` 的情况下从 `Draft` 移动到 `Paid`。 + +## 1. 工作流协议(FSM) + +从核心来说,工作流是在 YAML 中定义的**有限状态机 (FSM)**。 + +### 协议结构 + +```yaml +# workflows/contract_approval.workflow.yml +name: contract_process +object: contract +initial_state: draft +field: status # 存储状态的对象上的字段 + +states: + draft: + allow_edit: true + transitions: + submit: pending_review + + pending_review: + allow_edit: false + transitions: + approve: legal_review + reject: draft + + legal_review: + transitions: + sign: active + reject: draft + + active: + final: true + +``` + +### 关键组件 + +* **状态**:记录可以处于的不同阶段。 +* **转换**:状态之间的有向路径(例如,`submit`)。 +* **防护**:防止转换的规则(例如,"仅经理可以批准")。 +* **副作用**:在进入/退出时触发的操作(例如,"发送电子邮件")。 + +## 2. 审批链(人工任务) + +企业工作流通常需要人工干预。ObjectOS 提供了一个专门的**审批协议**来处理"谁需要签署此文件?"的复杂性。 + +### 指定审批人 + +您可以将 `approval` 块附加到任何状态。 + +```yaml +states: + pending_review: + type: approval + approval: + # 谁可以批准? + participants: + - type: role + id: manager + - type: user + id: "${record.department_head}" # 动态解析 + + # 需要多少个签名? + strategy: any # 'any'(1 人)或 'all'(共识) + + transitions: + approve: active + reject: draft + +``` + +### "收件箱"概念 + +当记录进入 `approval` 状态时: + +1. ObjectOS 为参与者生成**工作项**(任务)。 +2. 这些项出现在用户的 ObjectUI 中的"我的批准"收件箱中。 +3. 在做出决定之前,记录被严格**锁定**(只读)。 + +## 3. 自动化(服务任务) + +并非所有步骤都是人工的。ObjectOS 支持自动执行代码或调用 API 的**服务任务**。 + +```yaml +states: + processing_payment: + type: service + action: "finance.charge_credit_card" + params: + amount: "${record.amount}" + token: "${record.payment_token}" + transitions: + success: paid + failure: payment_failed + +``` + +## 4. BPMN 2.0 映射 + +ObjectOS 被设计为与 **BPMN 2.0(业务流程模型和符号)** 兼容。这允许您使用可视化建模工具(如 Camunda Modeler 或 BPmn.io)来生成 ObjectOS YAML 协议。 + +| ObjectOS 概念 | BPMN 2.0 元素 | 描述 | +| --- | --- | --- | +| **工作流** | `Process` | 定义的容器。 | +| **状态** | `UserTask` / `Task` | 等待操作的停止点。 | +| **初始状态** | `StartEvent` | 入口点。 | +| **最终状态** | `EndEvent` | 完成点。 | +| **转换** | `SequenceFlow` | 连接节点的箭头。 | +| **防护** | `ExclusiveGateway` (XOR) | 菱形决策节点。 | +| **触发器** | `ServiceTask` | 自动逻辑执行。 | + +## 5. 事件集成 + +工作流发出系统其他部分可以监听的事件。 + +* `workflow.state_changed`:每当状态移动时触发。 +* `workflow.step_started`:进入状态时触发。 +* `workflow.completed`:到达最终状态时触发。 + +### 示例:通知监听器 + +```typescript +// plugins/notifications/listeners.ts +broker.on('workflow.state_changed', async (ctx) => { + const { object, record_id, to_state } = ctx.params; + + if (object === 'contract' && to_state === 'active') { + await sendEmail(ctx.user.email, "Contract Signed!"); + } +}); + +``` + +## 6. 交互 API + +前端如何与引擎交互? + +### 1. 检查可用的转换 + +ObjectUI 询问:"*我应该显示哪些按钮?*" + +```json +// 请求 +POST /api/workflow/permissions +{ "object": "contract", "id": "123" } + +// 响应 +{ + "allow_edit": false, + "transitions": [ + { "name": "approve", "label": "Approve Contract", "variant": "success" }, + { "name": "reject", "label": "Send Back", "variant": "danger" } + ] +} + +``` + +### 2. 执行转换 + +用户点击"批准"。 + +```json +// 请求 +POST /api/workflow/transition +{ + "object": "contract", + "id": "123", + "transition": "approve", + "comment": "Looks good to me." +} + +``` + +## 摘要 + +工作流引擎将"流程"变为"协议"。 + +* **确定性:** 消除无效的状态修改。 +* **审计就绪:** 每个转换都以时间戳和用户身份记录。 +* **可视化:** 与 BPMN 图表 1:1 映射,方便业务利益相关者。 +* **集成:** 与 ObjectUI(按钮)和 ObjectQL(锁定)无缝配合。 diff --git a/content/docs/specifications/objectql/advanced-types.cn.mdx b/content/docs/specifications/objectql/advanced-types.cn.mdx new file mode 100644 index 0000000..2f481e8 --- /dev/null +++ b/content/docs/specifications/objectql/advanced-types.cn.mdx @@ -0,0 +1,158 @@ +--- +title: 高级类型 +description: "深入研究企业数据类型:货币、查询、公式和汇总。" +--- + +# 高级企业类型 + +虽然基本类型(如 `text` 和 `boolean`)可以处理标准数据,但企业应用程序需要专用类型来处理金钱、关系和动态计算。 + +ObjectQL 开箱即用地提供这些"智能类型"。它们不仅仅是存储定义;它们携带**逻辑**和**编译规则**,引擎会自动强制执行。 + +## 1. 货币(高精度货币) + +在财务系统中,浮点数学(例如 `0.1 + 0.2`)由于舍入误差而很危险。ObjectQL 的 `currency` 类型确保数学精确性。 + +### 定义 + +```yaml +fields: + amount: + type: currency + label: Invoice Amount + precision: 18 # Total digits + scale: 2 # Decimal places + required: true + +``` + +### 协议行为 + +* **存储:** 编译为 SQL 中的 `DECIMAL(18,2)` 或 MongoDB 中的 `Decimal128`。它永远不会使用 `FLOAT` 或 `DOUBLE`。 +* **运行时:** 在 TypeScript 运行时中,值被视为**字符串**或 **BigInt** 包装器,以防止 JavaScript 的 `number` 类型在 API 序列化期间引入精度丢失。 +* **格式化:** ObjectUI 根据系统配置自动使用正确的区域设置符号呈现此内容(例如 `$1,000.00`)。 + +## 2. 查询(外键关系) + +`lookup` 类型定义多对一关系。与简单的 SQL 外键不同,ObjectQL 查询支持**多态性**和**虚拟扩展**。 + +### 定义 + +```yaml +fields: + owner: + type: lookup + reference_to: users + label: Project Owner + index: true + +``` + +### 高级:多态查询 + +ObjectQL 允许字段指向*多个*对象类型。这对于 CRM 功能(如任务上的"相关")很重要,该功能可以链接到潜在客户、客户或机会。 + +```yaml +fields: + related_to: + type: lookup + reference_to: [lead, account, opportunity] # Polymorphic Array + +``` + +### 工作原理 + +* **编译器:** 当您查询查询字段时,引擎不仅返回 ID。它允许**图扩展**: +```json +// Query Intent +{ "expand": ["owner"] } + +``` + + +编译器将其转换为高度优化的 `LEFT JOIN users ON ...`。 + +## 3. 公式(数据库编译逻辑) + +公式字段是**只读虚拟列**。它们允许您在模式中定义业务逻辑,该逻辑被编译到数据库查询执行计划中。 + +### 为什么不使用 JavaScript? + +如果您在 JavaScript(Node.js)中计算 `Total = Price * Qty`,您无法在数据库中按 `Total` 排序或过滤。通过使用公式字段,计算发生在数据库引擎内部,允许对数百万行进行高性能排序和过滤。 + +### 定义 + +使用 `${field_name}` 语法引用其他字段。 + +```yaml +fields: + price: { type: currency } + quantity: { type: number } + + # The Magic Field + subtotal: + type: formula + data_type: currency + formula: "${price} * ${quantity}" + +``` + +### 编译器输出(PostgreSQL 示例) + +当 ObjectQL 为此对象生成 SQL 时,它将逻辑注入到 `SELECT` 列表中: + +```sql +SELECT + t1.price, + t1.quantity, + (t1.price * t1.quantity) AS subtotal +FROM order_lines t1 + +``` + +## 4. 汇总(汇总聚合) + +汇总字段允许父对象从其子记录计算指标(一对多)。 + +### 挑战 + +在传统开发中,计算"客户的开放订单总价值"需要编写复杂的 SQL 查询或触发器。 + +### ObjectQL 解决方案 + +以声明方式定义聚合。引擎处理子查询或物化视图。 + +### 定义 + +```yaml +# Object: account +fields: + # Metric: How much has this customer spent? + total_lifetime_value: + type: summary + summary_object: order # The child object + summary_type: sum # Operation: count, sum, min, max + summary_field: grand_total # The field on child to aggregate + filters: # Conditional Aggregation + - ["status", "=", "paid"] + +``` + +### 用例 + +* **CRM:** 客户资料上的"开放罚单数"。 +* **项目管理:** 项目中所有任务的"最大到期日期"。 +* **库存:** 库存移动的"数量总和"。 + +## 功能总结 + +| 类型 | 数据位置 | 计算时间 | 主要用途 | +| --- | --- | --- | --- | +| **货币** | 物理列 | 不适用 | 财务交易、价格。 | +| **查询** | 物理列(FK) | 不适用 | 链接记录、多态关系。 | +| **公式** | **虚拟** | 读取时间(查询) | 行级数学、字符串连接。 | +| **汇总** | **虚拟** | 读取时间(查询) | 父级聚合(求和/计数)。 | + +:::tip 性能说明 +虚拟字段(公式和汇总)很强大,但在大型数据集上依赖它们进行复杂排序可能会影响数据库性能。对于超过 1000 万行的数据集,考虑使用 ObjectOS 触发器将这些值物化到物理列中。 +::: diff --git a/content/docs/specifications/objectql/analytics-protocol.cn.mdx b/content/docs/specifications/objectql/analytics-protocol.cn.mdx new file mode 100644 index 0000000..f68e3a9 --- /dev/null +++ b/content/docs/specifications/objectql/analytics-protocol.cn.mdx @@ -0,0 +1,191 @@ +--- +title: 分析协议 +description: 使用 ObjectQL 协议定义聚合、数据透视表和 BI 数据源。 +--- + +# 分析协议 + +在传统架构中,生成报告通常需要将数据导出到数据仓库或编写复杂的、不可移植的 SQL 查询。 + +ObjectQL 弥合了事务性(OLTP)和分析性(OLAP)工作负载之间的差距。它提供**声明式分析协议**,允许您直接从操作数据库请求分组、汇总和重塑的数据,或透明地将这些请求路由到分析副本。 + +## 1. 聚合 AST + +就像您查询记录一样,您也可以查询**聚合**。聚合协议旨在成为 SQL `GROUP BY` 或 MongoDB 聚合管道的与数据库无关的抽象。 + +### 协议结构 + +聚合请求由三个核心组件组成:**维度**(分组)、**度量**(值)和**过滤**(作用域)。 + +```typescript +// @objectql/types +interface AggregateRequest { + object: string; // Target Object (e.g., 'invoice') + filters?: FilterNode; // Scope (e.g., 'year = 2024') + groupBy: string[]; // Dimensions (e.g., ['sales_rep', 'status']) + measures: Record; // Calculations +} + +interface AggregateDef { + field: string; + method: 'sum' | 'avg' | 'min' | 'max' | 'count' | 'count_distinct'; +} + +``` + +### 示例:销售绩效 + +> *"按销售代表显示已关闭交易的总销售额和平均交易规模。"* + +**协议(JSON):** + +```json +{ + "object": "deal", + "filters": [["stage", "=", "closed_won"]], + "groupBy": ["owner"], + "measures": { + "total_revenue": { "field": "amount", "method": "sum" }, + "avg_deal_size": { "field": "amount", "method": "avg" }, + "deal_count": { "field": "_id", "method": "count" } + } +} + +``` + +**编译(SQL):** + +```sql +SELECT + t1.owner, + SUM(t1.amount) as total_revenue, + AVG(t1.amount) as avg_deal_size, + COUNT(t1._id) as deal_count +FROM deals t1 +WHERE t1.stage = 'closed_won' +GROUP BY t1.owner + +``` + +## 2. 日期直方图(时间序列分析) + +企业报告在很大程度上依赖于基于时间的分组(例如,"每月销售额")。ObjectQL 标准化了日期截断,以确保在数据库中的行为一致。 + +### 协议语法 + +在 `groupBy` 数组中使用特殊逻辑函数 `date_trunc(field, interval)`。 + +```json +{ + "object": "log_entry", + "groupBy": ["date_trunc('created_at', 'month')"], + "measures": { + "error_count": { "field": "_id", "method": "count" } + } +} + +``` + +* **Postgres 驱动程序:** 编译为 `DATE_TRUNC('month', created_at)` +* **MySQL 驱动程序:** 编译为 `DATE_FORMAT(created_at, '%Y-%m-01')` +* **Mongo 驱动程序:** 编译为 `$dateToString`(带格式)。 + +## 3. 数据透视协议(交叉制表) + +数据透视表将行转换为列。虽然大多数 ORM 将此留给前端,但 ObjectQL 在协议中定义了**数据透视结构**,以启用服务器端优化(以及与 Excel 类似的 UI 组件的兼容性)。 + +### 协议结构 + +```typescript +interface PivotRequest { + object: string; + rows: string[]; // The Y-Axis (e.g., Region) + columns: string[]; // The X-Axis (e.g., Year) + values: AggregateDef[]; // The Cell Data +} + +``` + +### 示例:按地区与年份的销售额 + +```json +{ + "type": "pivot", + "object": "sales_order", + "rows": ["region"], + "columns": ["fiscal_year"], + "values": [{ "field": "amount", "method": "sum" }] +} + +``` + +### 响应格式 + +引擎返回一个标准化结构,可直接用于呈现网格组件: + +```json +{ + "metadata": { "columns": ["2023", "2024", "2025"] }, + "data": [ + { "region": "North", "2023": 1000, "2024": 1500, "2025": 2000 }, + { "region": "South", "2023": 800, "2024": 900, "2025": 1100 } + ] +} + +``` + +## 4. BI 数据源(无头 BI) + +ObjectQL 启用了**"无头 BI"**架构。您可以在 ObjectQL **分析立方体**中定义指标,而不是在 Tableau 或 PowerBI 中定义指标(它们被锁定)。 + +### 定义立方体(YAML) + +立方体是专门为分析设计的虚拟视图。 + +```yaml +# src/analytics/sales_cube.yml +name: sales_performance +label: Sales Performance Cube +base_object: deal +dimensions: + - name: region + field: owner.region + - name: month + expression: "date_trunc('created_at', 'month')" +measures: + - name: revenue + field: amount + method: sum + - name: win_rate + expression: "count(case when stage='won' then 1 end) / count(*)" + +``` + +### 使用 + +外部 BI 工具可以通过 ObjectQL 分析 API 使用此立方体。 + +* **API:** `POST /api/analytics/cube/sales_performance/query` +* **好处:** 如果您在 YAML 中更改"收入"的定义,每个报告(仪表板、PDF、Excel 导出)都会立即更新。 + +## 5. 性能和物化 + +实时对数百万行运行聚合是资源密集型的。ObjectQL 支持**透明物化**。 + +### `materialized` 标志 + +```yaml +# src/analytics/sales_cube.yml +name: sales_performance +materialized: true +refresh_interval: "1h" + +``` + +* **行为:** ObjectOS 内核自动创建一个**物化视图**(在 Postgres 中)或单独的汇总集合(在 Mongo 中)。 +* **路由:** 当客户端查询此立方体时,ObjectQL 编译器重写查询以命中预计算的视图,而不是原始表。 +* **延迟:** 查询变成即时(O(1)),代价是数据新鲜度(例如,1 小时延迟)。 + +:::tip 架构师说明 +对于超过 100M 行的数据集,ObjectQL 驱动程序可以配置为将分析查询卸载到专用的 OLAP 引擎(如 ClickHouse 或 Snowflake),同时保持协议相同。这允许您在不重写应用程序逻辑的情况下扩展基础结构。 +::: diff --git a/content/docs/specifications/objectql/ast-structure.cn.mdx b/content/docs/specifications/objectql/ast-structure.cn.mdx new file mode 100644 index 0000000..8941d49 --- /dev/null +++ b/content/docs/specifications/objectql/ast-structure.cn.mdx @@ -0,0 +1,157 @@ +--- +title: 核心 AST +description: 理解驱动 ObjectQL 协议的抽象语法树(AST)。 +--- + +# 抽象语法树(AST) + +ObjectQL 不仅仅是一个 URL 查询参数解析器。它是一个**数据库编译器**。 + +当您向 ObjectQL 发送请求(通过 REST、GraphQL 或 SDK)时,引擎做的第一件事是将您的请求解析为一个标准化的**抽象语法树(AST)**。 + +此 AST 充当**中间表示(IR)**。它将*意图*(您想要什么数据)与*执行*(数据库如何检索它)解耦。 + +## 1. 根节点(`QueryAST`) + +ObjectQL 中的每个数据检索操作都解析为一个 `QueryAST` 对象。这是每个驱动程序(Postgres、Mongo、SQLite)必须实现的协议。 + +### TypeScript 定义 + +```typescript +// @objectql/types +export interface QueryAST { + /** The target object (table) to query */ + objectName: string; + + /** Columns to retrieve. Strings for primitives, Objects for joins. */ + fields: Array; + + /** The recursive filtering tree */ + filters?: FilterNode; + + /** Sorting instructions */ + sort?: SortNode[]; + + /** Pagination */ + top?: number; + skip?: number; +} + +``` + +## 2. 字段选择(图) + +ObjectQL 允许"类似图"的字段选择。您可以在单个请求中检索原始字段或遍历关系(Join)。 + +### JSON 结构 + +```json +{ + "fields": [ + "name", + "status", + { + "field": "owner", + "fields": ["name", "email"] + }, + { + "field": "tasks", + "fields": ["subject", "due_date"] + } + ] +} + +``` + +### 编译器行为 + +* **原始字段(`name`)**:编译为 `SELECT "name"`。 +* **查询字段(`owner`)**:编译为 `LEFT JOIN "users" ON ...`(关系型)或 `$lookup`(文档型)。 +* **虚拟字段**:如果选定的字段是 `公式`,编译器会注入 SQL 表达式。 + +## 3. 过滤(逻辑树) + +ObjectQL 中的过滤器不是简单的键值对。它们是能够表达复杂布尔逻辑(`AND`、`OR`、`NOT`)的递归树。 + +### 过滤节点 + +过滤器是一个数组元组:`[field, operator, value]`。 + +| 索引 | 类型 | 描述 | +| --- | --- | --- | +| 0 | `string` | 字段名称(或点分路径 `owner.name`) | +| 1 | `string` | 操作符(`=`、`<>`、`>`、`contains`、`in`) | +| 2 | `any` | 要比较的值 | + +### 复杂逻辑(分组) + +要创建分组,只需嵌套数组。默认连接符是 `AND`。使用 `"or"` 字符串来切换逻辑。 + +**示例意图:** + +> *"查找状态为'活跃' AND (由'Alice'拥有 OR 预算 > 10000)的项目"* + +**AST JSON:** + +```json +[ + ["status", "=", "active"], + "or", + [ + ["owner.name", "=", "Alice"], + ["budget", ">", 10000] + ] +] + +``` + +## 4. 编译管道 + +这个 JSON 如何变成数据库查询?ObjectOS 内核运行一个严格有序的管道。 + +### 步骤 A:清理和扩展 + +内核基于安全上下文注入**隐式过滤器**。 + +* *输入:* `SELECT * FROM projects` +* *上下文:* 用户在'地区 A'。 +* *输出 AST:* `SELECT * FROM projects WHERE region = 'A'`(修改的 AST)。 + +### 步骤 B:驱动程序编译 + +驱动程序接收*最终 AST*并将其转换为方言。 + +**驱动程序输入(AST):** + +```json +{ + "objectName": "project", + "filters": [["owner.name", "=", "Alice"]] +} + +``` + +**驱动程序输出(PostgreSQL):** + +```sql +SELECT t1.* FROM projects t1 +LEFT JOIN users t2 ON t1.owner = t2.id +WHERE t2.name = 'Alice' + +``` + +## 5. 为什么是 AST?(vs. 原始 SQL) + +为什么我们通过这种复杂性而不是直接写 SQL? + +1. **安全性:** 通过 AST 执行 SQL 注入在数学上是不可能的。编译器对每个值节点都使用参数化查询。 +2. **可移植性:** 相同的 AST 在 SQLite(本地)和 Oracle(企业)上运行。 +3. **治理:** 您可以编写"中间件"来检查 AST。 +* *示例:* "阻止任何尝试下载超过 1000 行 PII 数据的查询。"(您无法从原始 SQL 字符串轻松解析此内容,但用 AST 很简单)。 + + + +:::tip 开发者说明 +如果您正在构建自定义 UI 组件,请不要手动构造这些 JSON。使用 `@objectql/sdk`,它提供流利的构建器: +`const q = objectql("project").select(["name"]).where("status", "=", "active");` +::: diff --git a/content/docs/specifications/objectql/index.cn.mdx b/content/docs/specifications/objectql/index.cn.mdx new file mode 100644 index 0000000..35328b1 --- /dev/null +++ b/content/docs/specifications/objectql/index.cn.mdx @@ -0,0 +1,70 @@ +--- +title: ObjectQL 概览 +description: 数据协议简介。了解数据库编译器架构和抽象语法树(AST)。 +--- + +# ObjectQL 数据协议 + +**ObjectQL** 是一个与数据库无关的协议,用于定义、查询和操作企业数据。 + +与 ORM(一个代码库)或 GraphQL(一个 API 规范)不同,ObjectQL 充当**数据库编译器**的角色。它在物理存储引擎上创建了一个标准化的抽象层,使应用程序能够用 JSON/YAML 定义业务意图,并在 PostgreSQL、SQLite、MongoDB 或 Oracle 上高效执行,无需代码更改。 + +## 架构:数据库编译器 + +ObjectQL 的核心创新是将数据库交互视为一个编译过程,而不是字符串连接过程。 + + + +管道由四个阶段组成: + +1. **模式定义(输入):** 开发者使用 **[对象协议](./schema-definition)** (YAML) 定义数据形状。 +2. **请求解析(AST):** 在运行时,查询以 JSON 形式接收并解析为严格的 **[抽象语法树](./ast-structure)**。 +3. **语义分析(中间件):** 内核注入安全谓词(RBAC)、验证类型并应用逻辑钩子。 +4. **编译(输出):** **驱动程序** 将优化后的 AST 转换为目标数据库的原生方言(例如 PL/SQL)。 + +## 核心概念 + +要理解后续的规范,您必须熟悉这三个概念: + +### 1. 单一信息源 +在 ObjectStack 中,数据库模式(`CREATE TABLE`)**不是**信息源。**ObjectQL 模式**才是。 +* ObjectQL 引擎负责执行 DDL 迁移,使物理数据库与 YAML 定义保持同步。 +* 这确保"业务逻辑"(例如,该字段是具有 2 位小数的货币)在各个环境中得到保留。 + +### 2. 通用 AST +ObjectQL 定义了一个基于 JSON 的 **Wire Protocol**。这作为中间表示(IR)。 +* **意图:** `{ "op": "find", "from": "users", "where": ["age", ">", 18] }` +* **实现:** 解耦。发送者不需要知道接收者是使用 Postgres 还是 CSV 文件。 + +### 3. 智能类型 +ObjectQL 支持超越标准 SQL 的 **企业数据类型**。 +* **主-从关系:** 自动处理父子级联。 +* **汇总/汇总:** 声明式聚合(例如,"总订单数")。 +* **公式:** 在读取时计算的虚拟列。 + +## 为什么不只用 SQL? + +SQL 很强大,但它是一种**语言**,而不是**协议**。 + +| 特性 | 原始 SQL | ObjectQL 协议 | +| :--- | :--- | :--- | +| **结构** | 非结构化字符串 | 结构化 JSON AST | +| **安全性** | 易受注入攻击(如果不小心) | 数学上防止注入 | +| **可移植性** | 特定于供应商(PL/SQL vs T-SQL) | 100% 可移植 | +| **治理** | 难以解析/拦截 | 易于注入权限(AST 中间件) | +| **上下文** | 无状态 | 了解用户会话和租户 | + +## 规范路线图 + +本文档部分定义了 ObjectQL 的严格协议: + +* **[模式定义](./schema-definition)**:如何在 YAML 中定义对象、字段和关系。 +* **[高级类型](./advanced-types)**:货币、查询和公式的规范。 +* **[AST 结构](./ast-structure)**:查询的 JSON Wire 格式。 +* **[分析协议](./analytics-protocol)**:定义聚合、数据透视表和 BI 立方体。 +* **[事务模型](./transaction-model)**:原子性和跨对象变更的规则。 +* **[安全注入](./security-injection)**:编译器如何强制执行 RBAC 和 FLS。 + +:::info 实现说明 +虽然 `steedos-server` 是参考实现(Node.js),但 ObjectQL 规范是与语言无关的。符合规范的驱动程序可以用 Go、Rust 或 Java 编写。 +::: diff --git a/content/docs/specifications/objectql/schema-definition.cn.mdx b/content/docs/specifications/objectql/schema-definition.cn.mdx new file mode 100644 index 0000000..c404e79 --- /dev/null +++ b/content/docs/specifications/objectql/schema-definition.cn.mdx @@ -0,0 +1,185 @@ +--- +title: 模式定义 +description: ObjectQL 的核心。如何使用声明式 YAML 协议定义对象、字段和关系。 +--- + +# 模式定义 + +在 ObjectQL 中,您不需要编写 `CREATE TABLE` 语句,也不需要定义 Mongoose Schema 或 TypeORM 类。相反,您使用标准 YAML(或 JSON)协议定义**对象**。 + +此模式是**单一信息源**。它不仅驱动数据库结构,还驱动 API 验证、UI 生成和权限检查。 + +## 1. 对象协议 + +ObjectQL 中的`对象`表示业务实体(例如`项目`、`发票`、`员工`)。它大致映射到关系数据库中的表或文档数据库中的集合。 + +### 基本结构 + +```yaml +# src/objects/project.object.yml +name: project # Unique API identifier (snake_case) +label: Project # Human-readable label +table_name: projects # (Optional) Physical table name override +icon: standard:account # Icon for ObjectUI +description: A high-level container for tasks and resources. +hidden: false # If true, hidden from the API discovery + +``` + +## 2. 字段 + +字段定义对象的列和属性。ObjectQL 开箱即用地支持**企业数据类型**,确保在不同的底层数据库中保持一致性。 + +### 核心数据类型 + +| 类型 | 描述 | 映射到(Postgres) | 映射到(Mongo) | +| --- | --- | --- | --- | +| `text` | 单行字符串 | `VARCHAR` | `String` | +| `textarea` | 多行文本 | `TEXT` | `String` | +| `html` | 富文本 | `TEXT` | `String` | +| `number` | 双精度 | `NUMERIC` | `Number` | +| `currency` | 高精度货币 | `DECIMAL(18, 2)` | `Decimal128` | +| `boolean` | 真/假 | `BOOLEAN` | `Boolean` | +| `date` | 仅日期 | `DATE` | `Date` | +| `datetime` | 日期和时间 | `TIMESTAMP` | `Date` | +| `select` | 枚举/下拉列表 | `VARCHAR` | `String` | + +### 字段配置 + +```yaml +fields: + name: + type: text + label: Project Name + required: true + searchable: true # Creates a database index automatically + index: true + + status: + type: select + options: + - label: Planning + value: planning + - label: In Progress + value: in_progress + - label: Completed + value: completed + default: planning + + budget: + type: currency + scale: 2 + precision: 18 + +``` + +## 3. 关系 + +ObjectQL 通过将关系视为**字段类型**来处理关系。编译器自动生成必要的外键和 JOIN 逻辑。 + +### 查询(多对一) + +最常见的关系。一个任务属于一个项目。 + +```yaml +# src/objects/task.object.yml +fields: + project: + type: lookup + reference_to: project # Points to the 'name' of the target Object + required: true + +``` + +* **数据库效果:** 在 `tasks` 表中创建 `project` 列(FK)。 +* **UI 效果:** 呈现可搜索的下拉列表或模态选择器。 + +### 主-从关系(强所有权) + +类似于查询,但暗示**所有权**。如果删除主记录,则删除详细记录(级联删除)。 + +```yaml +# src/objects/invoice_line.object.yml +fields: + invoice: + type: master_detail + reference_to: invoice + write_requires_master_read: true # Security inheritance + +``` + +### 分层(自引用) + +一个对象链接到自身(例如,组织结构图或文件夹树)。 + +```yaml +fields: + parent_task: + type: lookup + reference_to: task + +``` + +## 4. 虚拟字段(计算) + +这是 ObjectQL 作为**编译器**的闪光点。您可以定义在数据库中不存在但在查询期间动态计算的字段。 + +### 公式字段 + +编译为注入到 `SELECT` 子句中的 SQL 表达式。 + +```yaml +fields: + # Logic: (Total - Cost) / Total + margin_percentage: + type: formula + data_type: number + formula: "({amount} - {cost}) / {amount}" + scale: 2 + +``` + +### 汇总字段(汇总) + +编译为 SQL 子查询或聚合。 + +```yaml +# src/objects/project.object.yml +fields: + # Counts all tasks linked to this project where status = 'closed' + closed_task_count: + type: summary + summary_object: task + summary_type: count + summary_field: _id + filters: [["status", "=", "closed"]] + +``` + +## 5. 编译过程 + +当您启动 ObjectOS 引擎时,它读取这些 YAML 文件并执行**模式差异**: + +1. **解析:** 将 YAML 转换为 AST。 +2. **比较:** 对照当前数据库信息模式检查 AST。 +3. **迁移:** 生成 SQL DDL(`CREATE`、`ALTER`)以同步数据库。 + +### 示例输出 + +对于上面的 YAML,Postgres 驱动程序可能执行: + +```sql +CREATE TABLE projects ( + _id VARCHAR(50) PRIMARY KEY, + name VARCHAR(255) NOT NULL, + status VARCHAR(50) DEFAULT 'planning', + budget DECIMAL(18, 2) +); + +CREATE INDEX idx_projects_name ON projects(name); + +``` + +:::info 与数据库无关 +因为定义在 YAML 中,从 PostgreSQL 切换到 MySQL 只需**零更改**模式文件。您只需更改驱动程序配置。 +::: diff --git a/content/docs/specifications/objectql/transaction-model.cn.mdx b/content/docs/specifications/objectql/transaction-model.cn.mdx new file mode 100644 index 0000000..75e0120 --- /dev/null +++ b/content/docs/specifications/objectql/transaction-model.cn.mdx @@ -0,0 +1,189 @@ +--- +title: 事务模型 +description: 通过跨对象事务、原子操作和乐观锁定确保数据完整性。 +sidebar_position: 5 +slug: /objectql/transaction-model +--- + +# 事务模型和原子性 + +在企业应用程序中,数据完整性是不可商量的。一个经典示例是保存一个**订单**及其**行项目**。您不能创建没有项目的订单,也不能在订单保存失败的情况下扣除库存。 + +ObjectQL 提供**声明式事务协议**来处理这些场景,而无需编写复杂的命令式代码。 + +## 1. 原子变更协议 + +标准 REST API 通常会强制您进行多个请求(`POST /orders`,然后循环 `POST /items`)。如果网络在中途失败,您会有"僵尸数据"。 + +ObjectQL 通过**原子变更数据包**解决这个问题。您可以将多个操作捆绑到一个请求中。如果*任何*操作失败,整个事务都会回滚。 + +### 嵌套变更(父子) +最常见的模式是同时创建主记录及其详细信息。 + +**协议有效负载(JSON):** +```json +{ + "operation": "create", + "object": "order", + "data": { + "customer": "cust_001", + "date": "2024-03-20", + "status": "draft", + // Nested writes are detected automatically + "lines": [ + { + "product": "prod_A", + "quantity": 5, + "price": 100 + }, + { + "product": "prod_B", + "quantity": 2, + "price": 50 + } + ] + } +} + +``` + +* **行为:** ObjectQL 引擎检测 `lines` 关系。它打开数据库事务,插入订单,获取新的 `_id`,将其注入到行中,插入行,然后提交。 + +### 批量变更(混合对象) + +有时您需要在一次操作中更新无关的对象(例如,"批准发票"AND"扣除预算")。 + +**协议有效负载(JSON):** + +```json +{ + "operation": "transaction", + "steps": [ + { + "operation": "update", + "object": "invoice", + "id": "inv_123", + "data": { "status": "approved" } + }, + { + "operation": "update", + "object": "budget", + "id": "bdg_999", + "data": { "amount_remaining": { "$inc": -5000 } } + } + ] +} + +``` + +## 2. 乐观锁定(并发控制) + +在多用户环境中(例如,两个销售代表编辑同一笔交易),"最后写入获胜"是危险的。它会导致数据丢失。 + +ObjectQL 默认通过 `_version` 字段强制执行**乐观锁定**。 + +### 机制 + +1. **读取:** 当您获取记录时,ObjectQL 返回 `_version` 号(例如 `v1`)。 +2. **写入:** 当您更新时,您**必须**发回您读取的 `_version`。 +3. **检查:** 数据库执行:`UPDATE ... WHERE id = '...' AND _version = 1`。 +4. **结果:** +* 如果受影响的行 = 1:成功。`_version` 增加到 2。 +* 如果受影响的行 = 0:**冲突错误**。其他人已将其更新为 `v2`。 + + + +### 协议示例 + +**请求:** + +```json +{ + "operation": "update", + "object": "deal", + "id": "deal_123", + "data": { "amount": 20000 }, + "_version": 5 // I believe I am editing version 5 +} + +``` + +**响应(错误):** + +```json +{ + "error": { + "code": "VERSION_CONFLICT", + "message": "Record has been modified by another user.", + "current_version": 6 + } +} + +``` + +:::tip UI 处理 +ObjectUI 自动处理此问题。如果它收到 `VERSION_CONFLICT`,它会提示用户"刷新并重新应用"。 +::: + +## 3. 服务器端事务钩子 + +有时,逻辑太复杂而无法在客户端处理。您需要在服务器上定义事务边界。 + +您可以在 `*.trigger.ts` 文件中定义**事务钩子**。这些钩子在数据库事务作用域*内*运行。 + +```typescript +// src/triggers/order.trigger.ts +import { Trigger } from '@objectql/types'; + +export const afterOrderApprove: Trigger = { + on: 'update', + object: 'order', + when: (newDoc, oldDoc) => newDoc.status === 'approved' && oldDoc.status !== 'approved', + + // This function receives a 'session' which is bound to the DB transaction + handler: async ({ id, session, broker }) => { + + // 1. Create Shipment (Must succeed) + await broker.call('data.create', { + object: 'shipment', + data: { order_id: id } + }, { session }); + + // 2. Notify Warehouse (Side effect, does not block transaction) + await broker.emit('warehouse.notify', { order_id: id }); + + // If Step 1 throws an error, the Order update is ALSO rolled back. + } +} + +``` + +## 4. 隔离级别 + +ObjectQL 通常默认为关系数据库的**读已提交**隔离级别。 + +* **脏读:** 防止。您永远看不到来自其他事务的未提交数据。 +* **不可重复读:** 允许。 +* **幻读:** 允许。 + +对于需要严格序列化访问的场景(例如,生成顺序发票号码),使用**原子增量**操作符或专用序列对象,而不是锁定整个表。 + +```json +// Atomic Increment Protocol +{ + "operation": "update", + "object": "counter", + "id": "invoice_seq", + "data": { "seq": { "$inc": 1 } } +} + +``` + +## 总结 + +| 特性 | 描述 | 好处 | +| --- | --- | --- | +| **嵌套变更** | 在一个 JSON 中保存父级 + 子级。 | 防止孤立记录。 | +| **事务数据包** | 捆绑混合操作。 | 确保跨模块一致性。 | +| **乐观锁定** | `_version` 检查。 | 防止多用户应用程序中的丢失更新。 | +| **钩子** | 事务中的服务器端逻辑。 | 保证业务规则完整性。 | diff --git a/content/docs/specifications/objectql/wire-protocol.cn.mdx b/content/docs/specifications/objectql/wire-protocol.cn.mdx new file mode 100644 index 0000000..6af2014 --- /dev/null +++ b/content/docs/specifications/objectql/wire-protocol.cn.mdx @@ -0,0 +1,171 @@ +--- +title: Wire 协议 +description: HTTP/WebSocket 传输规范。请求信封、响应格式和错误处理标准。 +--- + +# Wire 协议 + +**Wire 协议**定义了 ObjectQL AST 和变更如何在网络上序列化和传输。 + +虽然大多数开发者使用官方 SDK(`@objectql/sdk`),但理解 Wire 协议对以下方面至关重要: +1. 在其他语言(Rust、Go、Swift)中构建自定义驱动程序或 SDK。 +2. 调试原始 API 流量。 +3. 实现低级代理或网关。 + +ObjectQL 主要使用**JSON over HTTP**,但结构设计为与传输无关(兼容 WebSocket 或 gRPC)。 + +## 1. 端点 + +ObjectQL 遵循**单一入口点**模式(类似于 GraphQL 或 RPC)。您没有针对不同对象的不同 URL。 + +* **URL:** `POST /api/objectql/v1` +* **方法:** `POST`(对读和写都优先使用,以避免复杂过滤器的 URL 长度限制)。 +* **Content-Type:** `application/json` + +### 头部 + +| 头部 | 描述 | +| :--- | :--- | +| `Authorization` | `Bearer `(标准 OIDC/JWT) | +| `X-Space-Id` | (可选)多租户上下文隔离。 | +| `X-ObjectQL-Version` | 协议版本(例如 `1.0`)。 | + +## 2. 请求信封 + +请求体是包装操作的 JSON 对象。 + +### A. 查询请求(读取) + +要获取数据,您发送一个包含 [Query AST](./ast-structure) 的 `query` 操作。 + +```json +// POST /api/objectql/v1 +{ + "op": "query", + "payload": { + "object": "deal", + "fields": ["name", "amount", "stage"], + "filters": [["stage", "=", "negotiation"]], + "sort": [["amount", "desc"]], + "top": 10, + "skip": 0 + } +} + +``` + +### B. 变更请求(写入) + +要修改数据,您发送一个 `mutation` 操作。 + +```json +// POST /api/objectql/v1 +{ + "op": "mutation", + "payload": { + "object": "deal", + "method": "create", // create, update, delete + "data": { + "name": "Big Enterprise Deal", + "amount": 50000, + "owner": "usr_001" + } + // For Update: "id": "deal_123" + } +} + +``` + +## 3. 响应信封 + +ObjectQL 保证一致的响应形状。它**从不**返回原始数组或原始错误字符串。每个响应都包装在一个 `StandardResponse` 信封中。 + +### 成功响应 + +```json +{ + "data": [ ... ], // The Result Array or Object + "error": null, // Null indicates success + "meta": { // Metadata + "count": 150, // Total record count (if requested) + "debug_id": "req_xyz" + } +} + +``` + +### 错误响应 + +如果操作失败(验证、权限或系统错误),HTTP 状态代码将是 `200 OK`(软错误)或 `4xx/5xx`(硬错误),但正文始终包含错误详细信息。 + +```json +{ + "data": null, + "error": { + "code": "VALIDATION_FAILED", + "message": "Field 'amount' cannot be negative.", + "details": [ + { "field": "amount", "issue": "min_value", "expected": 0 } + ] + }, + "meta": { ... } +} + +``` + +## 4. 标准错误代码 + +ObjectQL 定义了一组不可变的错误代码。客户端应该根据 `error.code` 以编程方式切换,而不是 `error.message`。 + +| 代码 | HTTP 状态 | 含义 | +| --- | --- | --- | +| `AUTH_REQUIRED` | 401 | 缺少或无效令牌。 | +| `PERMISSION_DENIED` | 403 | RBAC 检查失败(对象或字段级别)。 | +| `record_NOT_FOUND` | 404 | ID 不存在(用于更新/删除)。 | +| `VALIDATION_FAILED` | 400 | 数据违反模式规则。 | +| `VERSION_CONFLICT` | 409 | 乐观锁定失败(数据过时)。 | +| `INTERNAL_ERROR` | 500 | 数据库连接失败或未处理的异常。 | + +## 5. 流协议(NDJSON) + +对于大型数据集(例如,导出 100 万行),标准 JSON 响应消耗太多内存。ObjectQL 支持 **Newline Delimited JSON (NDJSON)**。 + +* **头部:** `Accept: application/x-ndjson` +* **行为:** 服务器在从数据库游标读取时每行刷新一个 JSON 对象。 + +**响应流:** + +```json +{"type": "meta", "count": 1000000} +{"type": "record", "id": "1", "name": "A"} +{"type": "record", "id": "2", "name": "B"} +... +{"type": "done"} + +``` + +## 6. 多部分协议(文件上传) + +由于 JSON 无法有效处理二进制文件,ObjectQL 使用 `multipart/form-data` 进行文件操作。 + +**请求:** + +* **部分 1(`operations`):** 描述变更的 JSON 字符串。 +```json +{ "op": "mutation", "object": "attachment", "method": "create", "data": { "file": null } } + +``` + + +* **部分 2(`map`):** 将文件输入映射到 JSON 路径。 +```json +{ "0": ["data.file"] } + +``` + + +* **部分 3(`0`):** 实际的二进制文件流。 + +:::info 实现说明 +这与 **GraphQL 多部分请求规范**非常相似。针对该规范定制的标准库通常对 ObjectQL 上传的工作方式相似,只需进行少量调整。 +::: diff --git a/content/docs/specifications/objectui/action-triggers.cn.mdx b/content/docs/specifications/objectui/action-triggers.cn.mdx new file mode 100644 index 0000000..eadb322 --- /dev/null +++ b/content/docs/specifications/objectui/action-triggers.cn.mdx @@ -0,0 +1,207 @@ +--- +title: 动作触发器 +description: 客户端交互协议。通过 JSON 事件处理点击、导航和 API 调用。 +--- + +# 动作触发器 + +在 ObjectUI 中,交互性由**动作**而非函数定义。 + +由于 UI 定义必须严格序列化(JSON),我们不能传递 JavaScript 函数如 `onClick={() => alert('Hello')}`。相反,我们声明**动作对象**,由 ObjectUI 运行时引擎解释和执行。 + +## 1. 动作协议 + +动作是一个 JSON 对象,描述*应该发生什么*。事件如 `onClick` 或 `onSuccess` 接受单个动作或**动作链**(数组)。 + +### 基础结构 + +```typescript +interface ActionDef { + /** 操作标识符 */ + action: string; + + /** 操作的参数 */ + params?: Record; + + /** 在执行前要求用户确认 */ + confirm?: { + title: string; + message: string; + variant?: 'danger' | 'info'; + }; + + /** 执行条件(表达式) */ + when?: string; +} + +``` + +### 示例:删除按钮 + +```json +{ + "type": "button", + "props": { + "label": "Delete Project", + "variant": "destructive", + "onClick": [ + { + "action": "api.mutation", + "confirm": { + "title": "Are you sure?", + "message": "This action cannot be undone.", + "variant": "danger" + }, + "params": { + "object": "project", + "method": "delete", + "id": "${record._id}" + } + }, + { + "action": "toast.success", + "params": { "message": "Project deleted successfully." } + }, + { + "action": "navigate", + "params": { "url": "/projects" } + } + ] + } +} + +``` + +## 2. 标准动作库 + +ObjectUI 运行时带有内置的标准动作库。你无需为这些动作编写代码。 + +### UI 和导航 + +| 动作 | 参数 | 说明 | +| --- | --- | --- | +| `navigate` | `url`、`target` | 转到 URL 或 ObjectUI 路由。 | +| `toast.success` | `message`、`duration` | 显示绿色成功通知。 | +| `toast.error` | `message` | 显示红色错误通知。 | +| `modal.open` | `layout`、`title` | 在对话框中打开 JSON 布局。 | +| `modal.close` | - | 关闭最上层的对话框。 | +| `drawer.open` | `layout`、`width` | 打开幻灯片面板。 | +| `copy` | `text` | 将文本复制到剪贴板。 | + +### 数据和 API + +| 动作 | 参数 | 说明 | +| --- | --- | --- | +| `api.query` | `query`、`bind` | 运行 ObjectQL 查询并将结果绑定到变量。 | +| `api.mutation` | `object`、`method`、`data` | 执行创建/更新/删除。 | +| `form.submit` | `formId` | 触发特定表单的验证和提交。 | +| `form.reset` | `formId` | 将表单字段重置为默认值。 | +| `record.refresh` | - | 从服务器重新获取当前记录。 | + +## 3. 动作上下文和变量 + +动作在**上下文**中运行。你可以使用 `${variable}` 语法访问动态数据。 + +* **`${record}`**: 显示的当前数据记录(行)。 +* **`${user}`**: 当前登录用户会话。 +* **`${scope}`**: 从父组件传递的临时变量。 +* **`${result}`**: 链中*前一个*动作的返回值。 + +### 示例:使用上一个结果 + +```json +[ + // 步骤 1:创建记录 + { + "action": "api.mutation", + "params": { "object": "task", "method": "create", "data": {...} } + }, + // 步骤 2:导航到新 ID + { + "action": "navigate", + "params": { "url": "/tasks/${result.id}" } + } +] + +``` + +## 4. 客户端逻辑 (`action.script`) + +有时标准动作不够。你需要自定义计算或逻辑。 +ObjectUI 提供**沙箱化脚本动作**。 + +> **警告:** 这*不是* `eval()`。这是一个安全、有限的表达式解析器。它无法访问 `window`、`document` 或发出任意网络请求。 + +```json +{ + "action": "script", + "params": { + "code": "if (record.amount > 1000) { return 'high_value'; } return 'standard';" + }, + "output_to": "temp.category" +} + +``` + +## 5. 动作容器 + +通常,动作被分组到通用"工具栏"或"菜单"中。 + +### Toolbar (`layout.toolbar`) + +```json +{ + "type": "layout.toolbar", + "children": [ + { + "type": "button", + "props": { "label": "Edit", "icon": "edit" }, + "events": { "onClick": { "action": "modal.open", "params": { "layout": "edit_form" } } } + }, + { + "type": "button", + "props": { "label": "More", "icon": "more_horizontal" }, + "children": [ + // 下拉菜单项 + { "label": "Duplicate", "action": "api.mutation", ... }, + { "label": "Archive", "action": "api.mutation", ... } + ] + } + ] +} + +``` + +## 6. 扩展动作 + +你可以在前端应用程序代码中注册自定义动作。这允许你在 JSON 协议和特定 React 功能之间架起桥梁。 + +```typescript +// src/app.tsx +import { registerAction } from '@objectui/runtime'; + +registerAction('custom.printLabel', async (context, params) => { + const zpl = generateZPL(context.record); + await sendToBluetoothPrinter(zpl); +}); + +``` + +**JSON 中的使用:** + +```json +{ + "action": "custom.printLabel", + "params": { "format": "4x6" } +} + +``` + +## 总结 + +动作协议将命令式行为转变为声明式配置。 + +1. **链接:** 动作按顺序执行。 +2. **上下文感知:** 它们可以读取当前记录状态。 +3. **安全:** 无原始 JavaScript 注入;仅白名单动作。 +4. **确认:** 针对危险操作的内置 UI 模式。 diff --git a/content/docs/specifications/objectui/component-schema.cn.mdx b/content/docs/specifications/objectui/component-schema.cn.mdx new file mode 100644 index 0000000..8e603e0 --- /dev/null +++ b/content/docs/specifications/objectui/component-schema.cn.mdx @@ -0,0 +1,219 @@ +--- +title: 基础组件 +description: "原子表单元素的 JSON Schema 规范:Input、Select 和 DatePicker。" +--- + +# 基础组件 Schema + +在 ObjectUI 中,每个表单元素都是渲染树中的**叶节点**。这些节点直接映射到 **Shadcn UI** 原语,确保可访问性和现代美观。 + +与传统 React 开发不同,在 React 中你编写 ``,而在 ObjectUI 中你定义**结构**和**数据绑定**,引擎处理状态管理。 + +## 1. 通用约定 + +所有表单组件(输入框、下拉框、复选框)都继承自基础 `FieldComponent` 接口。 + +### 基础属性 + +| 属性 | 类型 | 说明 | +| :--- | :--- | :--- | +| `type` | `string` | 组件标识符(例如,`input.text`)。 | +| `bind` | `string` | **关键。** 数据字段的路径(例如,`order.customer_name`)。引擎使用它进行双向绑定。 | +| `label` | `string` | 输入框上方显示的文本标签。 | +| `description` | `string` | 输入框下方显示的辅助文本(灰显颜色)。 | +| `placeholder` | `string` | 占位符文本。 | +| `disabled` | `boolean` | 静态禁用状态(或使用动态表达式)。 | +| `className` | `string` | **Tailwind** 类用于覆盖样式(例如,`w-1/2 bg-gray-50`)。 | + +--- + +## 2. 文本输入框 (`input.text`) + +任何表单的主要元素。它处理字符串、数字和密码输入。 + +### Schema 定义 + +```json +{ + "type": "input.text", + "bind": "contact.email", + "props": { + "label": "Email Address", + "placeholder": "john@example.com", + "inputType": "email", // text, password, email, url, tel + "autoFocus": true, + "startIcon": "mail" // Lucide 图标名称 + } +} + +``` + +### Shadcn 映射 + +* 呈现一个 `