Token导航 LogoToken导航TokenDH.com
研究检索敏感数据github未标认证来源可访问许可证需确认审计异常

apaas-object-skillAPAAS 对象技能

Agent Skill

apaas-object-skill 用于查找、检索和筛选相关信息,适合在 Codex、Claude、Cursor、Gemini CLI 中需要根据关键词、任务场景或来源线索快速定位候选结果时使用。可结合来源仓库、安装命令和原始 README 继续核验具体用法。安装前建议确认权限范围、维护状态,以及是否会触发联网、命令执行或文件读写。

总安装

353

周安装

15

GitHub Stars

2

下载量

124
CodexClaudeCursorGemini CLI

安装说明

本站只整理中文说明和来源信息,不托管安装包,也不代用户安装。

GitHub

来源数

2

许可证

unknown

最后核验

2026-05-01

来源状态

来源可访问

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:apaas-object-skill(APAAS 对象技能)
来源仓库:https://github.com/ennann/apaas-object-skill
仓库路径:skills/apaas-object-skill
安装命令:
npx skills add https://github.com/ennann/apaas-object-skill --skill apaas-object-skill
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。该命令会通过 npx skills 从第三方来源获取 Skill;本站只展示命令,不托管安装包,也不自动执行。

skills.shnpx skills
npx skills add https://github.com/ennann/apaas-object-skill --skill apaas-object-skill

简介

管理 aPaaS 平台数据对象(表)的创建、字段定义与批量操作。

  • 通过 Node SDK client.schema.* 接口实现两步式建表与字段添加。
  • 支持字段类型映射、SQL 转换与多对象分阶段创建策略。
  • 需使用完整 settings 模板,避免静默失败与系统字段冲突。
  • apaas-object-skill 属于研究检索类 Skill,可作为该场景下的辅助能力补充。

SKILL.md

aPaaS 数据对象管理

管理 aPaaS 平台数据对象(表)的创建、更新、删除。通过 Node SDK 的 client.schema.* 接口操作。

快速导航

必读陷阱 | 前置条件 | 核心 API | 创建对象(两步走) | 字段类型映射 | 字段 settings 模板 | SQL 转换 | 多对象分阶段创建 | 错误处理 | 完整示例

必读陷阱清单

先看完这 5 条再动手,每条都是真实踩坑总结。
  1. schema.create 静默忽略 fields — 传了字段定义也返回成功,但字段不会被创建。必须两步走:先 create 空壳,再 update 添加字段。
  2. text/multilingualmultiline = 整批静默失败 — API 返回 code: "0" + data: null,看似成功但所有字段都没创建。始终用完整 settings 模板。
  3. metadata type ≠ schema typenumber 要写 floatoption 要写 enumfile 要写 attachment。用错直接报类型不识别。
  4. 系统字段 _id/_createdBy 等不能手动创建 — 新建对象自动生成 5 个系统字段,重复定义会冲突报错。
  5. 批量上限 10 个对象schema.create/update/delete 每次最多 10 个,超过需分批。

前置条件

使用此 skill 前,必须确保以下环境已就绪:

  1. 安装 Node.js(>= 16)
  2. 安装 SDKnpm install apaas-oapi-client@^0.1.37schema 模块从 0.1.37 开始提供,低版本会报 Cannot read properties of undefined
  3. 获取凭据(在 aPaaS 平台的应用管理中获取):

- Client ID(格式:c_ 开头,如 c_a4dd955086ec45a882b9) - Client Secret(格式:32 位十六进制,如 a62fc785b97a4847810a4f319ccbdb5e) - Namespace(必须以 __c 结尾,如 package_5dc5b7__c

初始化 Client

SDK 导出结构为 {apaas: {Client}}不是直接导出 Client

// ESM
import { apaas } from 'apaas-oapi-client';

// CommonJS
const { apaas } = require('apaas-oapi-client');

构造参数为顶层平铺,不要嵌套在 auth 或其他对象下:

// ✅ 正确
const client = new apaas.Client({
    clientId: 'c_a4dd955086ec45a882b9',
    clientSecret: 'a62fc785b97a4847810a4f319ccbdb5e',
    namespace: 'package_5dc5b7__c'
});
await client.init();

// ❌ 错误:不能解构 Client 直接用
const { Client } = require('apaas-oapi-client');  // Client is undefined

// ❌ 错误:不能嵌套在 auth 下
new apaas.Client({ auth: { clientId: '...' } });  // 鉴权失败

系统预置规则

系统预置对象(只读)

平台预置两张数据表,不可修改、不可删除

对象说明
_user用户表
_department部门表

系统字段识别规则

API name 以 _ 下划线开头的对象或字段,均为系统预置,只读不可修改/删除。

默认字段

任何新建的空白对象,系统自动生成以下 5 个字段,无需手动创建:

字段类型说明
_idbigint记录唯一标识
_createdBylookup创建人
_createdAtdatetime创建时间
_updatedBylookup最后修改人
_updatedAtdatetime最后修改时间

注意

  • 不要在 schema.create 的 fields 中定义这些字段,会冲突报错
  • 不要尝试用 schema.update 修改或删除这些字段
  • _user_department 可以作为 lookup 的 referenced_object_api_name 目标(如关联用户/部门)

核心 API

接口用途
client.schema.create({objects})批量创建数据对象
client.schema.update({objects})批量更新对象(添加/修改/删除字段)
client.schema.delete({api_names})批量删除数据对象
批量上限schema.create / update / delete 每次调用最多 10 个对象,超过时需分批调用: ``typescript // 通用分批执行:将 items 按 batchSize 拆分,逐批调用 fn async function batchExecute<T>(items: T[], batchSize: number, fn: (batch: T[]) => Promise<any>) { for (let i = 0; i < items.length; i += batchSize) { const batch = items.slice(i, i + batchSize); const result = await fn(batch); // 检查 result(见"响应验证"章节) } } // 示例:创建 25 个空壳对象 const allObjects = [/* ... 25 个对象定义 ... */]; await batchExecute(allObjects, 10, (batch) => client.schema.create({ objects: batch })); ``

| client.object.listWithIterator() | 列出所有数据对象 | | client.object.metadata.fields({object_name}) | 获取对象所有字段元数据 | | client.object.metadata.export2markdown() | 导出对象元数据为 Markdown |

创建对象(两步走,必须遵守)

schema.create 会静默忽略 fields 参数 — 即使传了字段定义,返回 code: 0,但实际只创建空壳对象,字段不会被创建。

必须采用两步走:先 create 空壳,再 update 添加字段。

// 步骤 1:创建空壳对象(不传 fields,或传了也会被忽略)
await client.schema.create({
    objects: [{
        api_name: 'product',
        label: { zh_cn: '产品', en_us: 'Product' },
        settings: { display_name: '_id', allow_search_fields: ['_id'], search_layout: [] }
    }]
});

// 步骤 2:用 update + operator:'add' 添加字段
await client.schema.update({
    objects: [{
        api_name: 'product',
        fields: [
            { operator: 'add', api_name: 'name',
              label: { zh_cn: '产品名称', en_us: 'Name' },
              type: { name: 'text', settings: { required: true, unique: false, case_sensitive: false, multiline: false, max_length: 200 } },
              encrypt_type: 'none' }
        ]
    }]
});
字段就位后可再次调用 schema.updatedisplay_name_id 更新为实际字段(如 name),注意 不能用 _name。多对象场景见「三阶段创建法」。

更新对象

三种操作通过 operator 字段区分:

await client.schema.update({
    objects: [{
        api_name: 'product',
        fields: [
            // 添加字段
            { operator: 'add', api_name: 'desc', label: { zh_cn: '描述', en_us: 'Desc' },
              type: { name: 'text', settings: { required: false, unique: false, case_sensitive: false, multiline: true, max_length: 1000 } }, encrypt_type: 'none' },
            // 修改字段(必须带完整 type,只改 label 会报错)
            { operator: 'replace', api_name: 'code',
              label: { zh_cn: '编号', en_us: 'Code' },
              type: { name: 'text', settings: { required: true, unique: true, case_sensitive: false, multiline: false, max_length: 100 } } },
            // 删除字段(只需 api_name)
            { operator: 'remove', api_name: 'desc' }
        ]
    }]
});

删除对象

await client.schema.delete({ api_names: ['product', 'order'] });

字段类型映射(关键陷阱)

metadata 返回的类型名和 schema 接口接受的类型名不一致,以下类型必须转换(用错会报类型不识别):

Metadata TypeSchema Type
numberfloat
optionenum
fileattachment
autoIdauto_number
mobileNumberphone
avatarOrLogoavatar
referenceFieldreference_field

其余类型同名直接使用:textbigintdatedatetimebooleanlookuprichTextemailregiondecimalmultilingual

完整映射见 references/field-schema-rules.tsSCHEMA_TYPE_BY_METADATA_TYPE

各字段类型 settings 模板(必须遵守)

致命陷阱:某些 settings 字段看似可选实则必填。缺失时 API 返回 code: "0" + data: null,看似成功但字段不会被创建。更危险的是,同一批次中一个字段缺少必填 settings,会导致整批所有字段都静默失败。 下表中用 ⚠️ 标记的 settings 为必填项,不传会导致静默失败。始终使用下方完整模板,不要省略任何字段。
Schema Type完整 settings 模板
text{required: false, unique: false, case_sensitive: false, ⚠️ multiline: false, max_length: 255}
float{required: false, unique: false, display_as_percentage: false, decimal_places_number: 2}
bigint{required: false, unique: false}
date / datetime{required: false}
enum{required: false, multiple: false, option_type: "custom", options: [{label, api_name, color, active}]}
boolean{default_value: true, description_if_true: {zh_cn, en_us}, description_if_false: {zh_cn, en_us}}
lookup{required: false, multiple: false, referenced_object_api_name: "target"}
reference_field{current_lookup_field_api_name: "...", target_reference_field_api_name: "..."}
attachment{required: false, any_type: true, max_uploaded_num: 10, mime_types: []}
auto_number{ ⚠️ generation_method: "random", digits: 1, prefix: "", suffix: "", start_at: "1"}
richText{required: false, max_length: 1000}
phone{required: false, unique: false}
avatar{display_style: "square"}
email{required: false, unique: false}
region{required: false, multiple: false, has_level_strict: true, strict_level: 4}
decimal{required: false, unique: false, display_as_percentage: false, decimal_places: 2}
multilingual{required: false, unique: false, case_sensitive: false, ⚠️ multiline: false, max_length: 1000}

已确认的必填 settings(缺失 = 静默失败):

  • text / multilingualmultiline 必须显式传 truefalse
  • auto_numbergeneration_method 必须传(如 "random"

enum 选项颜色blue, cyan, green, yellow, orange, red, magenta, purple, blueMagenta, grey

从关系型数据库设计转换为 aPaaS 对象

用户提供的数据模型文档可能基于 MySQL、PostgreSQL、SQLite 等关系型数据库设计。以下规则指导如何将其转换为 aPaaS 平台的对象和字段。

转换完成后,必须先生成转换确认表呈现给用户确认,再执行创建操作。

SQL 列类型 → aPaaS 字段类型

SQL 类型aPaaS Schema Typesettings 要点转换说明
VARCHAR(n) / CHAR(n)textmultiline: false, max_length: nn > 255 时建议确认是否需要多行
TEXT / LONGTEXT / MEDIUMTEXTtextmultiline: true, max_length: 100000大文本映射为多行文本
INT / INTEGER / BIGINT / SERIALbigintrequired: false, unique: falseaPaaS 无 int/bigint 区分,统一用 bigint
FLOAT / DOUBLE / REALfloatdecimal_places_number: 2按需调整小数位
DECIMAL(p,s) / NUMERIC(p,s)decimaldecimal_places: ss 映射为 decimal_places
DATEdaterequired: false直接映射
DATETIME / TIMESTAMPdatetimerequired: false统一映射为 datetime
BOOLEAN / TINYINT(1) / BITbooleandefault_value: true/false注意转换 DEFAULT 值
ENUM('a','b','c')enum每个枚举值转为 options 数组项见下方枚举转换规则
JSON(存富文本)richTextmax_length: 1000仅当 JSON 用于富文本时
BLOB / BINARY / VARBINARYattachmentany_type: true二进制文件类的列

特殊语义识别(根据列名或注释推断更精确的类型):

列名模式推断 aPaaS 类型判断依据
email / *_email / mailemail列名含 email/mail
phone / mobile / tel / *_phonephone列名含 phone/mobile/tel
avatar / logo / profile_imageavatar列名含 avatar/logo
auto_number / serial_no / *_code(自增编号类)auto_number列名暗示自增编号且有 AUTO_INCREMENT 或 SERIAL
region / province / city / addressregion列名含地区信息
注意:语义识别是启发式的,转换后必须让用户确认。当无法确定时,默认映射为 text

SQL 约束 → aPaaS 字段 settings

SQL 约束aPaaS settings说明
NOT NULLrequired: true非空约束
UNIQUEunique: true唯一约束
DEFAULT valuedefault_value: value(boolean)仅 boolean 类型支持默认值
PRIMARY KEY (id)不转换aPaaS 自动生成 _id,忽略用户的主键列
AUTO_INCREMENT通常忽略_id 自动处理;如果是业务编号列,用 auto_number
CHECK不直接支持需要在应用层实现或告知用户 aPaaS 不支持
INDEX不转换aPaaS 自动管理索引

外键与关联关系 → lookup / reference_field

这是转换中最关键的部分。关系型数据库用外键表达关联,aPaaS 用 lookup 和 reference_field。

关系型设计aPaaS 转换示例
外键列order.customer_id REFERENCES customer(id)在 order 上创建 lookup 字段,referenced_object_api_name: 'customer'customer_id INT FK → lookup
一对多(一个 customer 有多个 order)多的一方(order)加 lookupmultiple: false)指向一的一方标准 lookup
多对多(中间表 student_course(student_id, course_id)消除中间表,在任一方加 lookupmultiple: true)指向另一方中间表不创建为 aPaaS 对象
自关联employee.manager_id REFERENCES employee(id)同一对象上创建 lookup 指向自身referenced_object_api_name 指向自己
外键 + 需要显示关联对象的字段(如订单列表要显示客户名称)先建 lookup,再建 reference_field 引用目标对象的字段lookup + reference_field 组合

中间表识别规则

  • 表只有两个外键列(+ 可能的 id 和时间戳)
  • 表名是两个实体名的组合(如 student_courseuser_roletag_article
  • 没有独立的业务字段

遇到中间表时:

  1. 不要创建为 aPaaS 对象
  2. 在关系的某一方创建 lookupmultiple: true)指向另一方
  3. 选择哪一方加 lookup 时,优先选择业务上"主动关联"的一方(如学生选课 → 在 student 上加 lookup 指向 course)
  4. 如果中间表有额外业务字段(如 scoreenrolled_at),则必须保留为独立对象,两端各用一个 lookup

SQL ENUM → aPaaS enum 转换规则

-- SQL 定义
status ENUM('draft', 'published', 'archived') NOT NULL DEFAULT 'draft'

转换为:

{
    operator: 'add',
    api_name: 'status',
    label: { zh_cn: '状态', en_us: 'Status' },
    type: {
        name: 'enum',
        settings: {
            required: true,    // 来自 NOT NULL
            multiple: false,
            option_source: 'custom',
            options: [
                { label: { zh_cn: '草稿', en_us: 'Draft' }, api_name: 'draft', color: 'grey', active: true },
                { label: { zh_cn: '已发布', en_us: 'Published' }, api_name: 'published', color: 'green', active: true },
                { label: { zh_cn: '已归档', en_us: 'Archived' }, api_name: 'archived', color: 'blue', active: true }
            ]
        }
    },
    encrypt_type: 'none'
}

注意

  • SQL 的 ENUM 值直接作为 api_name(需合法:小写字母、数字、下划线)
  • label 的中文需要根据语义翻译,无法机械转换,转换时用英文作为占位、中文标注"待确认"
  • 颜色按顺序从 enum 选项颜色(见 settings 模板章节)中轮询分配

转换工作流(必须遵守)

拿到用户的数据库设计文档(SQL DDL、ER 图描述、表格等)后,按以下流程执行:

第一步:解析与识别

  1. 提取所有表(→ aPaaS 对象)和列(→ aPaaS 字段)
  2. 识别主键列 → 忽略(aPaaS 用 _id
  3. 识别外键列 → 标记为 lookup 候选
  4. 识别中间表 → 标记为"消除"或"保留"
  5. 识别 ENUM 列 → 提取枚举值列表
  6. 对每个列按「SQL 列类型映射表」和「语义识别规则」确定 aPaaS 类型

第二步:生成转换确认表

以 Markdown 表格形式呈现给用户,必须等待用户确认后才能执行创建

## 转换结果确认

### 对象列表
| SQL 表名 | aPaaS 对象 api_name | 标签(zh_cn) | 处理方式 |
|---|---|---|---|
| customer | customer | 客户 | 创建 |
| order | order | 订单 | 创建 |
| order_item | order_item | 订单明细 | 创建 |
| customer_tag | — | — | ⚠️ 识别为中间表,不创建(在 customer 上加 tags lookup) |

### 字段转换明细
| 对象 | SQL 列 | SQL 类型 | → aPaaS 类型 | api_name | 说明 |
|---|---|---|---|---|---|
| customer | id | INT PK | — | — | 忽略(用系统 _id) |
| customer | name | VARCHAR(100) NOT NULL | text | name | required: true, max_length: 100 |
| customer | email | VARCHAR(200) | email | email | 语义识别为 email 类型 |
| customer | status | ENUM('active','inactive') | enum | status | 2 个选项 |
| order | customer_id | INT FK→customer | lookup | customer | 关联客户 |
| order | total | DECIMAL(10,2) | decimal | total | decimal_places: 2 |

### 需要确认的项
- [ ] customer.email: 推断为 `email` 类型,是否正确?还是保持 `text`?
- [ ] customer_tag 识别为中间表,是否正确?如果该表有额外业务字段请告知
- [ ] enum 选项的中文标签是否准确?

请确认或修改后,我将按照三阶段创建法执行。

第三步:用户确认后执行

用户确认后,按「多对象依赖分析与分阶段创建」章节的流程执行(1a 空壳 → 1b 基础字段 → 2 lookup → 3 reference_field)。

不可转换的 SQL 特性

以下 SQL 特性在 aPaaS 中无直接对应,需告知用户:

SQL 特性aPaaS 处理方式
存储过程 / 触发器不支持,需用应用逻辑实现
视图(VIEW)不支持,忽略
复合主键不支持,aPaaS 用 _id 单列主键
复合唯一约束(多列联合)不支持单字段级 unique 无法表达联合唯一
CHECK 约束不直接支持,需在应用层校验
分区表不支持,忽略
自定义函数 / 计算列不支持

遇到这些特性时,在转换确认表中标注"⚠️ 不支持"并给出替代建议(如果有的话)。

多对象依赖分析与分阶段创建(核心策略)

当一个应用有多张数据表且互相关联时,不能一次性创建带 lookup 的完整对象

问题:循环依赖

订单(order) --lookup--> 客户(customer)
客户(customer) --lookup--> 订单(order)   // 互相引用,谁先创建?

lookup 字段要求目标对象已存在,互相引用时直接创建必然失败。

解决:三阶段创建法

阶段 1a — 创建空壳对象:所有对象只建壳子,不传 fields(传了也会被忽略)。display_name 暂时指向 _id

// 阶段 1a:创建所有空壳
await client.schema.create({
    objects: [
        { api_name: 'customer', label: { zh_cn: '客户', en_us: 'Customer' },
          settings: { display_name: '_id' } },
        { api_name: 'order', label: { zh_cn: '订单', en_us: 'Order' },
          settings: { display_name: '_id' } }
    ]
});

阶段 1b — 添加基础字段:用 schema.update + operator: 'add' 给每个对象补上基础字段(text, bigint, decimal, enum 等不依赖其他对象的字段)。

// 阶段 1b:补基础字段
await client.schema.update({
    objects: [
        { api_name: 'customer', fields: [
            { operator: 'add', api_name: 'name', label: { zh_cn: '客户名', en_us: 'Name' },
              type: { name: 'text', settings: { required: true, unique: false, case_sensitive: false, multiline: false, max_length: 200 } }, encrypt_type: 'none' }
        ]},
        { api_name: 'order', fields: [
            { operator: 'add', api_name: 'order_no', label: { zh_cn: '订单号', en_us: 'Order No' },
              type: { name: 'text', settings: { required: true, unique: true, case_sensitive: false, multiline: false, max_length: 50 } }, encrypt_type: 'none' }
        ]}
    ]
});

阶段 2 — 补充 lookup 字段:所有对象已存在,用 schema.update + operator: 'add' 给每个对象补上 lookup 字段。

// 阶段 2:所有对象已存在,补 lookup
await client.schema.update({
    objects: [
        {
            api_name: 'order',
            fields: [
                { operator: 'add', api_name: 'customer', label: { zh_cn: '客户', en_us: 'Customer' },
                  type: { name: 'lookup', settings: { required: false, multiple: false, referenced_object_api_name: 'customer' } },
                  encrypt_type: 'none' }
            ]
        },
        {
            api_name: 'customer',
            fields: [
                { operator: 'add', api_name: 'latest_order', label: { zh_cn: '最近订单', en_us: 'Latest Order' },
                  type: { name: 'lookup', settings: { required: false, multiple: false, referenced_object_api_name: 'order' } },
                  encrypt_type: 'none' }
            ]
        }
    ]
});

阶段 3 — 补充 reference_field:lookup 就位后,添加引用字段。

// 阶段 3:lookup 就位后,补 reference_field
await client.schema.update({
    objects: [{
        api_name: 'order',
        fields: [
            { operator: 'add', api_name: 'customer_name', label: { zh_cn: '客户名称', en_us: 'Customer Name' },
              type: { name: 'reference_field', settings: {
                  current_lookup_field_api_name: 'customer',
                  target_reference_field_api_name: 'name'
              } }, encrypt_type: 'none' }
        ]
    }]
});

依赖分析流程

拿到需求后,按此流程分析:

  1. 列出所有对象和字段,标记哪些字段是 lookup / lookup_multi / reference_field
  2. 画出依赖关系:lookup 的 referenced_object_api_name 指向谁
  3. 分类到各阶段

- 阶段 1a:schema.create 创建所有空壳对象(不传 fields) - 阶段 1b:schema.update 添加基础字段(text, bigint, float, date, datetime, enum, boolean, attachment, auto_number, richText, phone, avatar, email, region, decimal, multilingual) - 阶段 2:schema.update 添加 lookup / lookup_multi - 阶段 3:schema.update 添加 reference_field

  1. 始终用此流程,即使没有循环依赖也不要尝试在 create 中传 fields

删除顺序(逆向)

删除时必须反向操作:

  1. 先删 reference_field(依赖 lookup)
  2. 再删 lookup / lookup_multi(依赖目标对象)
  3. 最后删对象本身

删除所有对象(完整工作流)

清理环境或重建数据模型时,需要删除应用内所有自定义对象。流程如下:

// 步骤 1:获取所有自定义对象(_ 开头为系统预置,不可删除)
const allObjects = await client.object.listWithIterator();
const customObjects = allObjects.items.filter(o => !o.apiName.startsWith('_'));
if (customObjects.length === 0) return;

// 步骤 2:收集依赖字段
const fieldsByType: Record<string, { object: string; field: string }[]> = { referenceField: [], lookup: [] };
for (const obj of customObjects) {
    const result = await client.object.metadata.fields({ object_name: obj.apiName });
    for (const field of result.data?.fields || []) {
        if (field.apiName.startsWith('_')) continue;
        const typeName = field.type?.name || field.type;
        if (typeName === 'referenceField' || typeName === 'lookup') {
            fieldsByType[typeName].push({ object: obj.apiName, field: field.apiName });
        }
    }
}

// 步骤 3:按依赖顺序删字段(reference_field → lookup)
for (const typeName of ['referenceField', 'lookup']) {
    const items = fieldsByType[typeName];
    if (items.length === 0) continue;
    const grouped: Record<string, { operator: 'remove'; api_name: string }[]> = {};
    for (const { object, field } of items) {
        (grouped[object] ??= []).push({ operator: 'remove', api_name: field });
    }
    await client.schema.update({
        objects: Object.entries(grouped).map(([api_name, fields]) => ({ api_name, fields }))
    });
}

// 步骤 4:删除所有对象
await client.schema.delete({ api_names: customObjects.map(o => o.apiName) });
删除后建议用 verifyObjects()client.object.listWithIterator() 确认清理干净。

约束速记

  • reference_field 只能引用 multiple: false 的 lookup
  • lookup_multimultiple: true不能作为 reference_field 的引导字段
  • 同一批 schema.update 中,add 的执行顺序不保证,不要在同一批里 add lookup 又 add 依赖它的 reference_field

失败恢复与幂等重跑

多阶段创建过程中,任意阶段都可能失败。以下是各阶段失败后的状态和恢复策略:

各阶段失败后的状态

失败点已完成的状态恢复策略
阶段 1a 失败部分空壳对象可能已创建重跑 1a,已存在的对象会报 k_ec_000015(含 "exist"),安全忽略
阶段 1b 失败空壳对象存在,部分字段可能已添加重跑 1b,已存在的字段会报错,可通过先查询 metadata 跳过已有字段
阶段 2 失败基础字段已就位,部分 lookup 可能已添加同上,查询后跳过已有 lookup
阶段 3 失败lookup 已就位,部分 reference_field 可能已添加同上,查询后跳过已有 reference_field

幂等重跑模式

// 查询已有字段,跳过已存在的
async function addFieldsIdempotent(objectName: string, fieldsToAdd: any[]) {
    const existing = await client.object.metadata.fields({ object_name: objectName });
    const existingNames = new Set(
        (existing.data?.fields || []).map((f: any) => f.apiName)
    );
    const newFields = fieldsToAdd.filter(f => !existingNames.has(f.api_name));
    if (newFields.length === 0) {
        console.log(`  [SKIP] ${objectName}: 所有字段已存在`);
        return;
    }
    const result = await client.schema.update({
        objects: [{ api_name: objectName, fields: newFields }]
    });
    checkResponse(result, `addFields(${objectName})`);
}

部分成功的处理

schema.update 可能在一批 10 个对象中只有部分成功。通过 data.items[].status.code 逐项检查,只重跑失败的对象:

const result = await client.schema.update({ objects: batch });
const failed = (result.data?.items || [])
    .filter((item: any) => item.status?.code !== '0')
    .map((item: any) => item.api_name);
if (failed.length > 0) {
    console.warn(`部分失败: ${failed.join(', ')},可针对这些对象重跑`);
}

常见错误与对策

错误原因修复
update 返回 code: "0" + data: null⚠️ 静默失败:字段 settings 缺少必填项(如 text 缺 multiline,auto_number 缺 generation_method),或同一批次中某个字段有此问题导致整批失败始终使用 settings 模板中的完整字段。检查方法:成功时返回 data.items,返回 data: null 即为失败
invalid generation_method valueauto_number 字段未传 generation_method必须传 generation_method: "random"
k_ec_000015 field type is requiredreplace 时只传了 label 没传 typereplace 必须带完整 type(name + settings)
k_ec_000015 + 含 "exist"对象已存在,重复创建先查询是否存在,或安全忽略此错误
create 返回成功但字段为空schema.create 静默忽略 fields必须用两步走:先 create 空壳,再 update 添加字段
创建字段类型不识别用了 metadata type(如 number用 schema type(float
display_name 报错使用了 _name,或指向不存在的字段创建空壳时先用 _id,字段就位后再更新
lookup 创建失败目标对象不存在先创建目标对象
reference_field 创建失败引导 lookup 不存在或是 multi先创建 multiple: false 的 lookup
reference_field field not foundlookup 刚创建,系统索引延迟;或目标字段类型不支持引用(如 avatar批量迁移时对 reference_field 失败做容错(打印错误但不中断),必要时加延迟重试

响应验证

每次 API 调用后必须检查三层状态

  1. result.code!== '0' — 请求级错误(参数格式问题)
  2. result.code === '0' && result.data === null — ⚠️ 静默失败(最危险:看起来成功,但字段未创建。原因:settings 缺必填项)
  3. result.data.items[].status.code!== '0' — 单个对象级错误
上述三层检查已封装在 scripts/run.tscheckResponse(result, context) 函数中,直接调用即可。

创建后验证

创建/更新对象后,调用 scripts/run.tsverifyObjects(['product',...]) 验证:自动检查对象是否存在、列出自定义字段及类型、导出 Markdown 供人工审查。

执行脚本与目录结构

npm install && cp scripts/.env.example scripts/.env  # 填入凭据后执行:
npx ts-node scripts/run.ts

scripts/run.ts 自动加载凭据、初始化 client,内置工具函数:checkResponse()(三层响应验证)、batchExecute()(自动分批)、verifyObjects()(字段级验证)。

apaas-object-skill/
  SKILL.md                          # 主文档(Claude 读取此文件)
  references/
    FIELD_SCHEMA_RULES.md           # 字段类型映射与规则(人读版)
    field-schema-rules.ts           # 字段类型映射与规则(机器可读版,含 SQL 转换规则)
  scripts/
    run.ts                          # 执行脚本(凭据加载、client 初始化、工具函数)
    .env.example                    # 凭据配置模板

端到端完整示例

以下示例演示从 SQL DDL 到 aPaaS 对象的完整流程:

-- 输入:用户提供的 SQL 设计
CREATE TABLE customer (
  id INT PRIMARY KEY AUTO_INCREMENT,
  name VARCHAR(100) NOT NULL,
  email VARCHAR(200),
  status ENUM('active', 'inactive') DEFAULT 'active'
);

CREATE TABLE `order` (
  id INT PRIMARY KEY AUTO_INCREMENT,
  order_no VARCHAR(50) NOT NULL UNIQUE,
  customer_id INT REFERENCES customer(id),
  total DECIMAL(10,2),
  created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
// ===== 阶段 1a:创建空壳对象 =====
await client.schema.create({
    objects: [
        { api_name: 'customer', label: { zh_cn: '客户', en_us: 'Customer' },
          settings: { display_name: '_id', allow_search_fields: ['_id'], search_layout: [] } },
        { api_name: 'order', label: { zh_cn: '订单', en_us: 'Order' },
          settings: { display_name: '_id', allow_search_fields: ['_id'], search_layout: [] } }
    ]
});

// ===== 阶段 1b:添加基础字段 =====
await client.schema.update({
    objects: [
        { api_name: 'customer', fields: [
            { operator: 'add', api_name: 'name',
              label: { zh_cn: '客户名称', en_us: 'Name' },
              type: { name: 'text', settings: { required: true, unique: false, case_sensitive: false, multiline: false, max_length: 100 } },
              encrypt_type: 'none' },
            { operator: 'add', api_name: 'email',
              label: { zh_cn: '邮箱', en_us: 'Email' },
              type: { name: 'email', settings: { required: false, unique: false } },
              encrypt_type: 'none' },
            { operator: 'add', api_name: 'status',
              label: { zh_cn: '状态', en_us: 'Status' },
              type: { name: 'enum', settings: {
                  required: false, multiple: false, option_type: 'custom',
                  options: [
                      { label: { zh_cn: '活跃', en_us: 'Active' }, api_name: 'active', color: 'green', active: true },
                      { label: { zh_cn: '停用', en_us: 'Inactive' }, api_name: 'inactive', color: 'grey', active: true }
                  ]
              } },
              encrypt_type: 'none' }
        ]},
        { api_name: 'order', fields: [
            { operator: 'add', api_name: 'order_no',
              label: { zh_cn: '订单号', en_us: 'Order No' },
              type: { name: 'text', settings: { required: true, unique: true, case_sensitive: false, multiline: false, max_length: 50 } },
              encrypt_type: 'none' },
            { operator: 'add', api_name: 'total',
              label: { zh_cn: '合计', en_us: 'Total' },
              type: { name: 'decimal', settings: { required: false, unique: false, display_as_percentage: false, decimal_places: 2 } },
              encrypt_type: 'none' }
            // created_at → 忽略,系统自动生成 _createdAt
        ]}
    ]
});

// ===== 阶段 2:添加 lookup =====
await client.schema.update({
    objects: [
        { api_name: 'order', fields: [
            { operator: 'add', api_name: 'customer',
              label: { zh_cn: '客户', en_us: 'Customer' },
              type: { name: 'lookup', settings: { required: false, multiple: false, referenced_object_api_name: 'customer' } },
              encrypt_type: 'none' }
        ]}
    ]
});

// ===== 阶段 3 (可选):添加 reference_field =====
await client.schema.update({
    objects: [
        { api_name: 'order', fields: [
            { operator: 'add', api_name: 'customer_name',
              label: { zh_cn: '客户名称', en_us: 'Customer Name' },
              type: { name: 'reference_field', settings: {
                  current_lookup_field_api_name: 'customer',
                  target_reference_field_api_name: 'name'
              } },
              encrypt_type: 'none' }
        ]}
    ]
});

// ===== 更新 display_name =====
await client.schema.update({
    objects: [
        { api_name: 'customer', settings: { display_name: 'name' } },
        { api_name: 'order', settings: { display_name: 'order_no' } }
    ]
});

// ===== 验证 =====
await verifyObjects(['customer', 'order']);

转换要点

  • id INT PRIMARY KEY → 忽略,aPaaS 用 _id
  • created_at DATETIME → 忽略,aPaaS 用 _createdAt
  • customer_id INT FK → lookup 字段
  • VARCHAR(200) 列名含 email → 语义识别为 email 类型

适合场景

01

用户想查找某类 Agent Skill 时

02

需要根据任务场景推荐可安装能力包时

03

需要对比不同来源的安装命令和来源信息时

能力概览

能力 1

按任务关键词查找相关 Skills

能力 2

展示可复制的安装命令

能力 3

保留来源站点、仓库和原始说明,方便继续核验

能力 4

展示第三方安全扫描或审计结果

安装后应在对应宿主中按原始 README 的触发条件使用;具体调用方式请以来源页面和 README 为准。

平台分布

Codex

36.95%
按下载量换算46

Claude

30.09%
按下载量换算37

Cursor

19.78%
按下载量换算25

Gemini CLI

9.47%
按下载量换算12

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

未通过

权限和风险

敏感数据

该 Skill 可能接触密钥、Token、环境变量或敏感配置,应进入高风险复核队列,默认不自动发布。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。来源安全扫描存在 warning/failed 结果,不能写成本站确认安全。当前只有一个来源,正式发布前建议补源仓库或其他目录站核验。

来源信息

继续浏览同类 Skills