ObjectOS
构建数据

数据模型

对象、字段、关系、校验、索引 —— 描述给 AI,或者用 TypeScript 写。

数据模型

数据模型是你应用的唯一事实来源。一旦对象存在,ObjectOS 就免费给你 REST API、Console 视图、RBAC 检查点、审计日志条目和 AI 工具暴露。

**多数客户从不手写 Schema。**他们在 AI Builder 里描述他们想要的,平台就会创建对象、字段、索引与翻译。本页描述底层结构 —— 让你理解 AI 生成的内容,并在需要时直接编辑。

编写路径

路径形态
AI Builder(主推)"创建一个 support_ticket 对象,含 subject、description、priority、status、assignee。"
Console 点选构建Console → Objects → New Object → 表单
TypeScript(*.object.ts)下面展示的 TS —— 通常在某个 fork 的模板

三种方式产生同一份 Schema。Schema 是规范的;其他一切都从它派生。

对象的解剖

// src/objects/task.ts
import { ObjectSchema, Field } from '@objectstack/spec/data';

export const Task = ObjectSchema.create({
  name: 'todo_task',
  label: 'Task',
  pluralLabel: 'Tasks',
  icon: 'check-square',
  description: 'A single unit of work.',

  fields: {
    subject:     Field.text({ label: 'Subject', required: true, maxLength: 200 }),
    description: Field.markdown({ label: 'Description' }),
    status:      Field.select({
      label: 'Status',
      options: [
        { label: 'To Do',       value: 'todo', default: true },
        { label: 'In Progress', value: 'in_progress' },
        { label: 'Done',        value: 'done' },
      ],
    }),
    due:         Field.date({ label: 'Due' }),
    assignee:    Field.lookup('sys_user', { label: 'Assignee' }),
  },

  enable: {
    trackHistory: true,    // 在审计日志里记录字段变更
    apiEnabled: true,      // 暴露 REST 端点(默认 true)
    feeds: true,           // chatter / 评论 / @提及
  },
});

在你的 stack 中注册它:

// objectstack.config.ts
import { defineStack } from '@objectstack/spec';
import * as objects from './src/objects';

export default defineStack({
  manifest: { id: 'my.app', namespace: 'myapp', version: '0.1.0', type: 'app', name: 'My App' },
  objects: Object.values(objects),
});

需要的就这些。os dev 重编译之后,/api/v1/data/todo_task、Console 的 Task 视图和 Console 的权限行就都出现了。

字段类型

ObjectStack 自带约 25 种字段类型。最常用的:

标量

类型存什么Helper
text短字符串Field.text({ maxLength, required })
textarea长字符串Field.textarea(...)
markdownMarkdown 富文本Field.markdown(...)
number整数Field.number({ min, max })
decimal精确小数(金额等)Field.decimal({ precision, scale })
booleanTrue/falseField.boolean({ defaultValue })
date日历日期Field.date(...)
datetime时间戳Field.datetime(...)
email经校验的邮箱Field.email(...)
url经校验的 URLField.url(...)
phone经校验的电话Field.phone(...)
json任意 JSONField.json(...)

选项

类型用于
select单选(枚举)
multiselect多选

关系

类型基数Helper
lookup一对多(外键)Field.lookup({ reference: 'sys_user' })
masterDetail一对多并级联删除Field.masterDetail({ reference: 'order' })

文件与媒体

类型存什么
file通过存储服务保存的一个文件
image带预览的图片文件

计算 / 派生

类型行为
formula读时按 CEL 表达式计算
summary关联记录的聚合(sum/count/avg)
autonumber序列号(INV-{000001})
createdlastModified系统维护的时间戳
createdBylastModifiedBy系统维护的用户引用

required / unique / 默认值

每个标量字段通用的修饰符:

Field.text({
  label: 'Code',
  required: true,
  unique: true,          // 数据库层强制唯一约束
  defaultValue: '',
  helpText: 'Internal short code',
})

校验

内联:

Field.number({ label: 'Quantity', min: 1, max: 9999 })
Field.text({ label: 'SKU', pattern: '^[A-Z]{3}-[0-9]{4}$' })

对象级规则(跨字段):

ObjectSchema.create({
  name: 'order',
  fields: { /* ... */ },
  validations: [
    {
      name: 'discount_lt_total',
      message: 'Discount cannot exceed total',
      condition: 'discount < total',
    },
  ],
});

校验对每次写入都执行 —— REST、Console、ObjectQL —— 没有"后门"。

索引与性能

ObjectSchema.create({
  name: 'order',
  fields: { /* ... */ },
  indexes: [
    { fields: ['status', 'created_at'] },
    { fields: ['account', 'created_at'], unique: false },
  ],
});

驱动在 Schema 同步时创建真实的数据库索引。

字段分组

针对长表单,在 Console 里把字段分组:

ObjectSchema.create({
  name: 'task',
  fieldGroups: [
    { key: 'core',     label: 'Task',     icon: 'check-square' },
    { key: 'planning', label: 'Planning', icon: 'calendar' },
    { key: 'meta',     label: 'Metadata', icon: 'info', defaultExpanded: false },
  ],
  fields: {
    subject: Field.text({ label: 'Subject', group: 'core' }),
    due:     Field.date({ label: 'Due',     group: 'planning' }),
  },
});

能力开关与所有权

ObjectSchema.create({
  name: 'task',
  ownership: 'own',          // 'own' | 'shared' | 'system'
  sharingModel: 'private',   // OWD——自定义对象默认私有(v13)
  enable: {
    apiEnabled: true,         // 生成 REST 端点
    trackHistory: true,       // History 选项卡 + 字段级差异(默认 true)
    feeds: true,              // sys_comment / @提及(默认 true)
    activities: true,         // CRUD 镜像到 sys_activity 时间线(默认 true)
    files: true,              // 附件面板(需显式开启,默认 false)
    softDelete: true,         // 软删除而非硬删除
  },
});

自 ObjectStack 14 起,enable.* 开关是强制执行的,而不再只是声明: feeds: false 会以 403 FEEDS_DISABLED 拒绝评论创建;files 必须显式开启 后才能创建 sys_attachment 行(否则返回 403 FILES_DISABLED); activities / trackHistory 控制时间线和 History 选项卡。无论开关如何, 合规用途的 sys_audit_log 行始终会写入。

数据生命周期(保留策略)

大数据量对象可以声明 lifecycle 块,让平台约束其增长(ObjectStack 14.4,ADR-0057):

ObjectSchema.create({
  name: 'my_event',
  lifecycle: {
    class: 'event',            // 'record' | 'audit' | 'telemetry' | 'transient' | 'event'
    retention: '14d',          // 回收器删除超出窗口的行
    storage: { rotation: 'weekly' }, // 按时间分片表,O(1) 过期
  },
});

内置的 LifecycleService(可用 OS_LIFECYCLE_DISABLED=1 关闭)负责回收过期行、 轮换分片表,并归档 audit 类对象。sys_activity(14 天)、sys_audit_log (热存 90 天后归档)等平台对象自带生命周期声明,可通过 lifecycle.retention_overrides 设置按环境调整。

系统对象(每个项目免费自带)

这些你不必声明 —— 它们一直都在:

对象是什么
sys_user用户账户
sys_org组织 / 租户
sys_member组织成员关系
sys_positionsys_permission_setRBAC 原语
sys_audit_log审计轨迹(加载审计能力时)
sys_filesys_attachment文件元数据(加载存储能力时)
sys_commentsys_activityFeed / chatter(加载 feed 能力时)
sys_sessionsys_api_key认证产物
sys_webhooksys_webhook_deliveryWebhook 订阅(启用时)

lookup 字段中按名称引用它们 —— 如 Field.lookup({ reference: 'sys_user' })

多态平台特性

当你启用 feeds: truetrackHistory: true,你的对象就自动加入:

  • sys_comment(thread_id = <object>:<id>)
  • sys_attachment(parent_object = <object>,parent_id = <id>)
  • sys_activity(时间线)
  • sys_audit_log(字段级 diff)

你不必为每个对象单独接线 —— 它们在平台上是多态的。

下一步

On this page