@tier0/sdk-v2 0.2.2 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (110) hide show
  1. package/README.md +28 -13
  2. package/dist/cjs/capabilities.js +2 -2
  3. package/dist/cjs/capabilities.js.map +1 -1
  4. package/dist/cjs/client.d.ts +284 -374
  5. package/dist/cjs/cloud-transport.js +6 -1
  6. package/dist/cjs/cloud-transport.js.map +1 -1
  7. package/dist/cjs/controls.d.ts +19 -7
  8. package/dist/cjs/controls.js +37 -34
  9. package/dist/cjs/controls.js.map +1 -1
  10. package/dist/cjs/data/bootstrap.js +3 -2
  11. package/dist/cjs/data/bootstrap.js.map +1 -1
  12. package/dist/cjs/data/collection.d.ts +22 -0
  13. package/dist/cjs/data/collection.js +10 -9
  14. package/dist/cjs/data/collection.js.map +1 -1
  15. package/dist/cjs/files.d.ts +9 -9
  16. package/dist/cjs/mq/broker.d.ts +1 -1
  17. package/dist/cjs/mq/broker.js +1 -1
  18. package/dist/cjs/mq/broker.js.map +1 -1
  19. package/dist/cjs/mq/types.d.ts +1 -1
  20. package/dist/cjs/mq/types.js.map +1 -1
  21. package/dist/cjs/openapi/api.generated.d.ts +417 -541
  22. package/dist/cjs/openapi/api.generated.js +292 -377
  23. package/dist/cjs/openapi/api.generated.js.map +1 -1
  24. package/dist/cjs/openapi/client.js +1 -1
  25. package/dist/cjs/openapi/client.js.map +1 -1
  26. package/dist/cjs/openapi/codecs.generated.d.ts +394 -652
  27. package/dist/cjs/openapi/codecs.generated.js +2 -2
  28. package/dist/cjs/openapi/codecs.generated.js.map +1 -1
  29. package/dist/cjs/openapi/types.generated.d.ts +697 -906
  30. package/dist/cjs/openapi/types.generated.js.map +1 -1
  31. package/dist/cjs/source.d.ts +0 -7
  32. package/dist/cjs/source.js +1 -3
  33. package/dist/cjs/source.js.map +1 -1
  34. package/dist/cjs/stream.d.ts +0 -5
  35. package/dist/cjs/stream.js +3 -4
  36. package/dist/cjs/stream.js.map +1 -1
  37. package/dist/cjs/uns-v2/codec.js +1 -1
  38. package/dist/cjs/uns-v2/codec.js.map +1 -1
  39. package/dist/cjs/uns-v2/generated.d.ts +4713 -13494
  40. package/dist/cjs/uns-v2/generated.js +12 -33
  41. package/dist/cjs/uns-v2/generated.js.map +1 -1
  42. package/dist/esm/capabilities.js +2 -2
  43. package/dist/esm/capabilities.js.map +1 -1
  44. package/dist/esm/client.d.ts +284 -374
  45. package/dist/esm/cloud-transport.js +6 -1
  46. package/dist/esm/cloud-transport.js.map +1 -1
  47. package/dist/esm/controls.d.ts +19 -7
  48. package/dist/esm/controls.js +38 -35
  49. package/dist/esm/controls.js.map +1 -1
  50. package/dist/esm/data/bootstrap.js +4 -3
  51. package/dist/esm/data/bootstrap.js.map +1 -1
  52. package/dist/esm/data/collection.d.ts +22 -0
  53. package/dist/esm/data/collection.js +10 -10
  54. package/dist/esm/data/collection.js.map +1 -1
  55. package/dist/esm/files.d.ts +9 -9
  56. package/dist/esm/mq/broker.d.ts +1 -1
  57. package/dist/esm/mq/broker.js +1 -1
  58. package/dist/esm/mq/broker.js.map +1 -1
  59. package/dist/esm/mq/types.d.ts +1 -1
  60. package/dist/esm/mq/types.js.map +1 -1
  61. package/dist/esm/openapi/api.generated.d.ts +417 -541
  62. package/dist/esm/openapi/api.generated.js +292 -377
  63. package/dist/esm/openapi/api.generated.js.map +1 -1
  64. package/dist/esm/openapi/client.js +1 -1
  65. package/dist/esm/openapi/client.js.map +1 -1
  66. package/dist/esm/openapi/codecs.generated.d.ts +394 -652
  67. package/dist/esm/openapi/codecs.generated.js +1 -1
  68. package/dist/esm/openapi/codecs.generated.js.map +1 -1
  69. package/dist/esm/openapi/types.generated.d.ts +697 -906
  70. package/dist/esm/openapi/types.generated.js.map +1 -1
  71. package/dist/esm/source.d.ts +0 -7
  72. package/dist/esm/source.js +1 -3
  73. package/dist/esm/source.js.map +1 -1
  74. package/dist/esm/stream.d.ts +0 -5
  75. package/dist/esm/stream.js +3 -4
  76. package/dist/esm/stream.js.map +1 -1
  77. package/dist/esm/uns-v2/codec.js +2 -2
  78. package/dist/esm/uns-v2/codec.js.map +1 -1
  79. package/dist/esm/uns-v2/generated.d.ts +4713 -13494
  80. package/dist/esm/uns-v2/generated.js +12 -33
  81. package/dist/esm/uns-v2/generated.js.map +1 -1
  82. package/package.json +1 -1
  83. package/skills/tier0-sdk-v2/SKILL.md +5 -3
  84. package/skills/tier0-sdk-v2/tier0-sdk-v2-agent/SKILL.md +4 -4
  85. package/skills/tier0-sdk-v2/tier0-sdk-v2-controls/SKILL.md +3 -3
  86. package/skills/tier0-sdk-v2/tier0-sdk-v2-data/references/read-write.md +12 -0
  87. package/skills/tier0-sdk-v2/tier0-sdk-v2-files/references/delete.md +1 -1
  88. package/skills/tier0-sdk-v2/tier0-sdk-v2-files/references/url.md +1 -1
  89. package/skills/tier0-sdk-v2/tier0-sdk-v2-members/references/app-members.md +1 -1
  90. package/skills/tier0-sdk-v2/tier0-sdk-v2-members/references/platform-members.md +1 -1
  91. package/skills/tier0-sdk-v2/tier0-sdk-v2-notifications/references/get.md +1 -1
  92. package/skills/tier0-sdk-v2/tier0-sdk-v2-notifications/references/send.md +1 -1
  93. package/skills/tier0-sdk-v2/tier0-sdk-v2-source/SKILL.md +2 -2
  94. package/skills/tier0-sdk-v2/tier0-sdk-v2-source/references/changes.md +4 -4
  95. package/skills/tier0-sdk-v2/tier0-sdk-v2-source/references/read.md +2 -2
  96. package/skills/tier0-sdk-v2/tier0-sdk-v2-stream/SKILL.md +3 -3
  97. package/skills/tier0-sdk-v2/tier0-sdk-v2-stream/references/create.md +1 -1
  98. package/skills/tier0-sdk-v2/tier0-sdk-v2-stream/references/deploy.md +11 -2
  99. package/skills/tier0-sdk-v2/tier0-sdk-v2-stream/references/lifecycle.md +1 -1
  100. package/skills/tier0-sdk-v2/tier0-sdk-v2-stream/references/read.md +25 -5
  101. package/skills/tier0-sdk-v2/tier0-sdk-v2-stream/references/update.md +1 -1
  102. package/skills/tier0-sdk-v2/tier0-sdk-v2-system/references/info.md +1 -1
  103. package/skills/tier0-sdk-v2/tier0-sdk-v2-system/references/whoami.md +1 -1
  104. package/skills/tier0-sdk-v2/tier0-sdk-v2-uns/SKILL.md +3 -3
  105. package/skills/tier0-sdk-v2/tier0-sdk-v2-uns/references/create.md +9 -5
  106. package/skills/tier0-sdk-v2/tier0-sdk-v2-uns/references/delete.md +5 -5
  107. package/skills/tier0-sdk-v2/tier0-sdk-v2-uns/references/namespace.md +4 -4
  108. package/skills/tier0-sdk-v2/tier0-sdk-v2-uns/references/read.md +8 -7
  109. package/skills/tier0-sdk-v2/tier0-sdk-v2-uns/references/restore.md +2 -2
  110. package/skills/tier0-sdk-v2/tier0-sdk-v2-uns/references/update.md +4 -4
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tier0/sdk-v2",
3
- "version": "0.2.2",
3
+ "version": "0.3.0",
4
4
  "description": "Tier0 Cloud new-architecture SDK for TypeScript and JavaScript",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -5,7 +5,7 @@ description: 使用 @tier0/sdk-v2 开发或迁移 Tier0 云端 TypeScript/JavaSc
5
5
 
6
6
  # Tier0 SDK v2 应用集成
7
7
 
8
- 面向应用代码编写;运行时为 Node.js 20.19+。独立包 `@tier0/sdk-v2` 的当前源码版本为 0.2.0(UNS v2 契约 5.0.0),是否可从 npm 安装须检查实际发布状态;未发布时安装仓库构建的 tarball。不要改回旧包或旧 Flow API。
8
+ 面向应用代码编写;运行时为 Node.js 20.19+。独立包 `@tier0/sdk-v2` 的版本以 package.json 为准(UNS v2 契约 5.0.0),是否可从 npm 安装须检查实际发布状态;未发布时安装仓库构建的 tarball。新参数还需要目标环境部署对应后端,不能只凭 SDK 方法存在判断可用。不要改回旧包或旧 Flow API。
9
9
 
10
10
  ## 选择业务入口
11
11
 
@@ -46,7 +46,7 @@ export async function inspectConnection() {
46
46
  | 入口 | 成功值 | 失败类型 |
47
47
  | --- | --- | --- |
48
48
  | Source、Stream、UNS | 完整 `{ code, msg, requestId, data }` | `UnsV2Error` / `UnsV2OutcomeUnknownError` |
49
- | 普通 v1,如 system、members、agent、mqttAuth | 解包后的 `data` | `ApiError` / `TransportError` |
49
+ | 平台 v2,如 system、members、agent、mqttAuth | 解包后的 `data` | `ApiError` / `TransportError` |
50
50
  | notifications | 直接对象,如 `messageId`、`status` | `ApiError` |
51
51
  | controls、capabilities | 专属响应对象 | `ControlError` / `CapabilityError` |
52
52
 
@@ -56,7 +56,7 @@ export async function inspectConnection() {
56
56
 
57
57
  ## 从首版入口迁移
58
58
 
59
- - `client.uns.sourceList(body)` → `client.source.list(body)`。
59
+ - `client.uns.sourceList(body)` → `client.source.documents.list(body)`。
60
60
  - `client.uns.sourceDocumentGet(body)` → `client.source.documents.get(body)`。
61
61
  - `client.uns.streamProgramDeploy(body)` → `client.stream.programs.deploy(body)`。
62
62
  - `client.uns.streamDocumentValidate(body)` → `client.stream.documents.validate(body)`。
@@ -64,3 +64,5 @@ export async function inspectConnection() {
64
64
  - 低层 `createUnsV2Client` 保留完整生成契约,供契约工具使用;业务主入口不再把 Source/Stream/Control 混入 `client.uns`。
65
65
 
66
66
  React/Vue 示例与验签见 [集成参考](references/integration.md)。完成接入时验证目标入口、真实身份、响应解包和错误分支;SDK 本地测试通过不代表环境联调完成。
67
+
68
+ 公开 HTTP 入口统一为 `/openapi/v2`。旧的重复操作已退役,不生成兼容调用或回退。Source 配置用 documents.*,Stream 草稿用 documents.*、发布用 programs.deploy;App 数据层仍提供 insertMany/findOneAnd*/distinct 等便捷方法。历史旧写结果未知时先核对业务状态,不能转换路由后盲目重放。
@@ -5,7 +5,7 @@ description: 使用 @tier0/sdk-v2 的 client.agent 查询和管理 Agent 作业
5
5
 
6
6
  # Agent 作业与结果
7
7
 
8
- Agent 是平台应用能力,区别于 Stream 数据处理程序。使用服务端 client.agent;本领域普通 v1 响应已解包,直接读取 list/job/run/result 等字段。
8
+ Agent 是平台应用能力,区别于 Stream 数据处理程序。使用服务端 client.agent;本领域平台 v2 响应已解包,直接读取 list/job/run/result 等字段。
9
9
 
10
10
  ## 入口选择
11
11
 
@@ -18,10 +18,8 @@ Agent 是平台应用能力,区别于 Stream 数据处理程序。使用服务
18
18
  | cards | list/get/update/delete,操作画布卡片 |
19
19
  | canvases | list,查找画布 |
20
20
  | library | list/get/create/update/delete,复用卡片定义 |
21
- | nodes | searchSemantic/indexSync,语义搜索与索引同步 |
22
- | relations | list/teach,读取和写入数据关系 |
23
21
 
24
- dispatch、trigger、indexSync、teach 都有副作用,不能在普通查询流程中悄悄执行。
22
+ dispatch、trigger 都有副作用,不能在普通查询流程中悄悄执行。
25
23
 
26
24
  ## 查询作业与运行
27
25
 
@@ -71,3 +69,5 @@ result.create 的 operationId 由调用方持有;保存超时后可用 `result
71
69
  cards.update 要带读取时的完整 expectedCardSpec;library.update 要带完整 expectedItem 快照。409 表示内容已变化,应重新读取并合并用户意图,不能自动覆盖。具体示例见 [结果与卡片编辑](references/results.md)。
72
70
 
73
71
  结果附件/图片使用 [文件 Skill](../tier0-sdk-v2-files/SKILL.md) 的持久化 filePath,不保存签名 URL 作为长期资源。失败保留 ApiError.status/code/errorCode;写入 outcomeUnknown 时先查询对应资源,不自动重发。
72
+
73
+ 旧 Namespace 节点的语义索引和 path 关系接口未纳入 v2,不再提供 nodes/relations 方法。
@@ -5,7 +5,7 @@ description: 使用 @tier0/sdk-v2 发现、描述和调用 Tier0 Control 业务
5
5
 
6
6
  # Control 契约调用
7
7
 
8
- Control 是已发布的业务调用入口;它可由 Stream 提供,但调用方不选择内部 streamId、entryId 或部署版本。使用服务端 client.controls,不重建旧 Flow 调用。
8
+ Control 是已发布的业务调用入口;它可由 Stream 提供,但调用方不选择内部 streamId、entryId 或部署版本。使用服务端 client.controls,实际调用 `/openapi/v2/uns/controls/discover|describe|invoke`,不重建旧 Flow 调用。
9
9
 
10
10
  ## 发现和读取契约
11
11
 
@@ -52,12 +52,12 @@ export async function invokePreparedControl(code: string, input: ControlJSON, in
52
52
  }
53
53
  ```
54
54
 
55
- 幂等键非空、不能有首尾空白,最多 128 UTF-8 字节。输入只能是普通 JSON,不传 Date、函数、循环对象、bigint、NaN/Infinity。业务 input 内名为 timeoutMs/streamId 的字段仍只是业务输入;不能借它覆盖服务端绑定、版本或执行超时。
55
+ 幂等键非空、不能有首尾空白,最多 128 UTF-8 字节。输入使用 JSON;需要保留精确数字时可用 UnsV2RawNumber,不传 Date、函数、循环对象、bigint、NaN/Infinity。业务 input 内名为 timeoutMs/streamId 的字段仍只是业务输入;不能借它覆盖服务端绑定、版本或执行超时。
56
56
 
57
57
  ## 返回与失败
58
58
 
59
59
  成功值为直接对象:code(Control 标识)、contractVersion、result、runID、status、replayed。这里的 code 不是 HTTP 业务状态码;replayed 只有服务端明确报告重放时才为 true。
60
60
 
61
- `ControlError` 含 status/errorCode/runID 等信息,SDK 不自动重试。`ControlResultUnknownError` 表示执行可能已经发生,包括调用响应无法证明最终结果的情况;按业务或平台运行记录对账。本 SDK 未提供通用 `controls.getRun`,不要虚构方法。若业务明确允许重放,保留原 key 和原输入,不能换新 key 重做。
61
+ `ControlError` 含 status/errorCode/runID 与 requestId/execution/retry 等信息,SDK 不自动重试。`ControlResultUnknownError` 表示执行可能已经发生,包括调用响应无法证明最终结果的情况;按业务或平台运行记录对账。本 SDK 未提供通用 `controls.getRun`,不要虚构方法。若业务明确允许重放,保留原 key 和原输入,不能换新 key 重做。
62
62
 
63
63
  `client.capabilities.discover()` 的 control.invoke.v1 就绪只是入口条件,不等于有权调用每一个 Control。执行源发布和内部绑定管理请使用 [Stream Skill](../tier0-sdk-v2-stream/SKILL.md)。
@@ -41,6 +41,16 @@ export async function releasedBadge() {
41
41
  export async function addNote(id: string, notes: string, revision: number) {
42
42
  return orders.updateOne({ _id: id }, { $set: { notes } }, { expectedRevision: revision });
43
43
  }
44
+
45
+ export async function createWorkOrder(
46
+ code: string, line: { id: string; name: string }, targetQty: number, intentKey: string,
47
+ ) {
48
+ const { value } = await orders.insertOne({ code, status: 'DRAFT', line, targetQty }, {
49
+ returnDocument: 'after', projection: { code: 1, 'line.name': 1 }, idempotencyKey: intentKey,
50
+ });
51
+ // 投影后的业务字段可能缺失,元信息仍必有;revision 可交给下一次更新。
52
+ return { id: value._id, revision: value._meta.revision, code: value.code, lineName: value.line?.name };
53
+ }
44
54
  ```
45
55
 
46
56
  ## 一个页面一次请求:`data.queryBatch`
@@ -99,6 +109,8 @@ export async function ordersScreen(page: number, selectedId: string) {
99
109
 
100
110
  带 `projection` 时,返回类型将业务字段递归标为可选,包括嵌套对象和数组元素的字段;读取前需判断是否存在。`_id` 和 `_meta` 仍然必有。不带 `projection` 的 `after` 保持完整文档类型。
101
111
 
112
+ 上面的 createWorkOrder 在一次记录写入中取得投影和修订;首次使用集合时仍会先 ensure 声明,不代表首次调用总共只有一次 HTTP。用于跨调用恢复时保存 intentKey,并重发同一创建意图;不要把原来的默认返回改为 after 来补取数据。读取权限在首次提交和历史重放时都检查,具体边界见 [UNS 创建快照](../../tier0-sdk-v2-uns/references/create.md)。
113
+
102
114
  ## 批量与原子性
103
115
 
104
116
  | 调用 | 上限 | 原子 |
@@ -1,6 +1,6 @@
1
1
  # 删除文件
2
2
 
3
- 方法:`files.delete({filePath}, {signal}?)`;POST /openapi/v1/assets/files/delete。
3
+ 方法:`files.delete({filePath}, {signal}?)`;POST /openapi/v2/assets/files/delete。
4
4
 
5
5
  | 字段 | 类型 | 必填 | 说明 |
6
6
  | --- | --- | --- | --- |
@@ -1,6 +1,6 @@
1
1
  # 获取文件访问地址
2
2
 
3
- 方法:`files.url({filePath,expiredSec?,responseContentDisposition?}, {signal}?)`;GET /openapi/v1/assets/files/url。
3
+ 方法:`files.url({filePath,expiredSec?,responseContentDisposition?}, {signal}?)`;GET /openapi/v2/assets/files/url。
4
4
 
5
5
  | 字段 | 类型 | 必填 | 说明 |
6
6
  | --- | --- | --- | --- |
@@ -1,6 +1,6 @@
1
1
  # App 可用成员
2
2
 
3
- 方法:`members.listApp(body)`;POST /openapi/v1/apps/access-members/list。返回能使用该 App 线上版本的有效成员。`appId` 必填且由调用方显式传入,SDK 不隐式读取 `APP_ID`;查询当前 App 时传 `getCurrentAppId()`。接口只接受 API Key,登录会话不能调用;绑定 App 的凭证只能查自己的 appId,查其他 App 返回 403。
3
+ 方法:`members.listApp(body)`;POST /openapi/v2/apps/access-members/list。返回能使用该 App 线上版本的有效成员。`appId` 必填且由调用方显式传入,SDK 不隐式读取 `APP_ID`;查询当前 App 时传 `getCurrentAppId()`。接口只接受 API Key,登录会话不能调用;绑定 App 的凭证只能查自己的 appId,查其他 App 返回 403。
4
4
 
5
5
  | 字段 | 类型 | 说明 |
6
6
  | --- | --- | --- |
@@ -1,6 +1,6 @@
1
1
  # Workspace 成员查询与选择
2
2
 
3
- 方法:`members.listWorkspace(body)`;POST /openapi/v1/platform/getMembers。查询当前 Key 所属 Workspace;云端需要 uns:read。通知读写权限不自动包含成员查询。
3
+ 方法:`members.listWorkspace(body)`;POST /openapi/v2/platform/getMembers。查询当前 Key 所属 Workspace;云端需要 uns:read。通知读写权限不自动包含成员查询。
4
4
 
5
5
  | 字段 | 类型 | 说明 |
6
6
  | --- | --- | --- |
@@ -1,6 +1,6 @@
1
1
  # 查询通知投递状态
2
2
 
3
- 方法:`notifications.get({messageId})`;POST /openapi/v1/notifications/get。需要 notifications:read,与 send 权限独立;仅查询当前发送 Key 可见的消息。
3
+ 方法:`notifications.get({messageId})`;POST /openapi/v2/notifications/get。需要 notifications:read,与 send 权限独立;仅查询当前发送 Key 可见的消息。
4
4
 
5
5
  | 参数/结果 | 类型 | 说明 |
6
6
  | --- | --- | --- |
@@ -1,6 +1,6 @@
1
1
  # 发送通知
2
2
 
3
- 方法:`notifications.send(body)`;POST /openapi/v1/notifications/send。需要 notifications:send;收件人为当前 Workspace 内可用的成员,按[成员查询](../../tier0-sdk-v2-members/references/platform-members.md)解析。
3
+ 方法:`notifications.send(body)`;POST /openapi/v2/notifications/send。需要 notifications:send;收件人为当前 Workspace 内可用的成员,按[成员查询](../../tier0-sdk-v2-members/references/platform-members.md)解析。
4
4
 
5
5
  | 字段 | 类型 | 必填 | 说明 |
6
6
  | --- | --- | --- | --- |
@@ -23,7 +23,7 @@ Source 维护连接配置、认证引用与源状态。脚本处理用 [Stream](
23
23
 
24
24
  ## 核心约束
25
25
 
26
- 1. 原生文档 `{name,protocol,config}` 使用 documents.*;通用投影使用 source.list/get/create/update。http 原生协议与 http-api adapter 不可互换。
26
+ 1. Source 配置统一使用 documents.*,原生文档为 `{name,protocol,config}`。http 原生协议与 http-api adapter 不可互换。
27
27
  2. 已有 ID 和 revision 时优先用 documents.update 的 patch,避免额外 get;完整替换 document 前读取完整文档,安全列表摘要不能无损回写。原生 ID 是十进制字符串,revision 原样传递,不转 Number。
28
28
  3. 现有 Source 修改、启停、删除都要 expectedRevision。没有任何 Stream 引用时可直接提交;有草稿、活动、历史或不可见引用时仍需 confirmedImpactRevision。先形成精确意图,再读取全部影响分页;回执不可合成、跨意图复用或静默刷新。提供的回执始终严格校验,不自动获取并同意影响。
29
29
  4. 配置中保留认证/TLS 引用,不写明文秘密;HTTP 新凭据走创建专用 credentials。
@@ -33,6 +33,6 @@ Source 维护连接配置、认证引用与源状态。脚本处理用 [Stream](
33
33
 
34
34
  所有调用返回完整 code/msg/requestId/data。documents.create/update 的预检返回 validated/sideEffects,提交返回完整 Source view,可直接使用其中的文档和 revision,无需额外 get;批量状态/删除返回 Outcome。只有 committed 且无项错误才可报告提交成功;accepted/jobId 继续查询作业。预检按需使用,不是每次提交的必经步骤。
35
35
 
36
- 需要查看历史用 source.history({id,beforeRevision,size}),按 nextBeforeRevision 继续;探测用 source.probe,其外部系统访问应属于当前任务。source.connection.update 属于现有源变更,同样遵守影响确认契约,不能作为绕过文档校验的入口。
36
+ 需要查看历史用 source.history({id,beforeRevision,size}),按 nextBeforeRevision 继续;探测用 source.probe,其外部系统访问应属于当前任务。连接配置修改使用 documents.update,遵守同一影响确认契约。
37
37
 
38
38
  UnsV2Error 表示已知拒绝;UnsV2OutcomeUnknownError 表示可能已写入。保存 requestId、原请求和意图键,先查详情/历史/作业对账。取消等待不撤销服务端操作;SDK 不自动重试。权限不足不能解释为资源不存在。
@@ -4,9 +4,9 @@
4
4
 
5
5
  | 字段 | 类型 | 必填 | 说明 |
6
6
  | --- | --- | --- | --- |
7
- | id / expectedRevision | string / integer | 是 | 当前 ID 和读取到的修订 |
7
+ | id / expectedRevision | string / integer | 是 | 当前 ID 和最近写回执或读取取得的修订 |
8
8
  | action | update/enable/disable/delete | 是 | 精确变更类型 |
9
- | document | CloudSourceDocument | 更新时 | 完整拟提交文档 |
9
+ | patch / document | CloudSourceDocumentPatch / CloudSourceDocument | 更新时二选一 | 与随后提交完全相同的补丁或完整文档;其他 action 不传 |
10
10
  | offset / size | integer | 否 | 首次 0;size 1–200 |
11
11
  | impactRevision | string | 翻页时 | 沿用首次返回的确认值 |
12
12
 
@@ -14,7 +14,7 @@
14
14
  import { createClient, type Tier0Client, type UnsV2Request } from '@tier0/sdk-v2';
15
15
 
16
16
  export async function collectSourceImpact(
17
- intent: Pick<UnsV2Request<'sourceImpact'>, 'id' | 'expectedRevision' | 'action' | 'document'>,
17
+ intent: Pick<UnsV2Request<'sourceImpact'>, 'id' | 'expectedRevision' | 'action' | 'patch' | 'document'>,
18
18
  client: Tier0Client = createClient(),
19
19
  ) {
20
20
  const first = await client.source.impact({ ...intent, offset: 0, size: 200 });
@@ -37,4 +37,4 @@ export async function collectSourceImpact(
37
37
 
38
38
  data:impactRevision、sourceID/sourceRevision、action、counts(draft/activeRelease/historicalRelease)、restrictedCount、references、nextOffset、expiresAt。nextOffset=0 结束;complete=1 表示计算完成,不表示首页有全部引用。
39
39
 
40
- 确认值绑定身份、修订、精确意图,不能合成或自动刷新。评估 counts 和 restrictedCount;有受限引用时不能说“无影响”。Source 更新不会自动替换 Stream 冻结修订。已有明确操作授权时不重复索要确认;影响分析本身不授予额外操作权限。
40
+ 确认值绑定身份、修订、精确意图,不能合成或自动刷新。分析时用 patch,提交时就沿用该 patch;不要另行补齐为 document 或更改字段。评估 counts 和 restrictedCount;有受限引用时不能说“无影响”。Source 更新不会自动替换 Stream 冻结修订。已有明确操作授权时不重复索要确认;影响分析本身不授予额外操作权限。没有任何引用时可直接变更,见 [修改](update.md),不必先执行本流程。
@@ -3,11 +3,11 @@
3
3
  | 方法 | POST 路径 | 输入 | data |
4
4
  | --- | --- | --- | --- |
5
5
  | source.documents.list | /openapi/v2/uns/sources/documents/list | page、size、search、protocol、desiredState、health、archived、includeDocument | list、total、page、hasMore、nextPage |
6
- | source.documents.get | /openapi/v2/uns/sources/documents/get | id(必填) | id、revision、完整 document、状态 |
6
+ | source.documents.get | /openapi/v2/uns/sources/documents/get | id(必填)、view:'summary' 或 'full' | id、revision、状态;full 才包含完整 document |
7
7
  | source.runtime.get | /openapi/v2/uns/sources/runtime/get | id(必填) | 运行状态 |
8
8
  | source.observations.get | /openapi/v2/uns/sources/observations/get | items:id、expectedRevision | 指定源和修订的观测 |
9
9
 
10
- page 从 1 开始,size 1–200。列表默认安全摘要;完整文档需要管理权限,编辑时显式 get。
10
+ page 从 1 开始,size 1–200。列表默认安全摘要。get 省略 view 保持旧的 full 行为;summary 需要 uns.source.view 或 uns.source.manage,full 需要 uns.source.manage;API Key 读取完整文档还必须是 full_access(includeDocument:true 同样适用)。未知 revision 时可读取 summary;要完整替换 document 或查看配置时读取 full。已持有写回执中的 ID/revision 时,可直接提交 patch,无需为了编辑再 get;服务端仍会检查版本冲突。摘要不能用于重建完整配置。
11
11
 
12
12
  ```ts
13
13
  import { createClient, type Tier0Client } from '@tier0/sdk-v2';
@@ -12,7 +12,7 @@ description: 使用 @tier0/sdk-v2 的 client.stream 创建、查询、修改和
12
12
  | 用户任务 | 参考 | 方法 |
13
13
  | --- | --- | --- |
14
14
  | 新建并绑定 HTTP Source | [创建](references/create.md) | documents.create({program}) |
15
- | 列表、完整文档、运行记录 | [查询](references/read.md) | programs.list/get、documents.get、observations.get、runs.list |
15
+ | 列表、完整文档、运行记录 | [查询](references/read.md) | programs.list、documents.get、observations.get、runs.list |
16
16
  | 修改草稿、脚本和绑定 | [修改](references/update.md) | documents.validate/update |
17
17
  | 发布、停用、版本回滚 | [部署](references/deploy.md) | programs.deploy/rollback、documents.disable |
18
18
  | 删除并核验归档 | [删除](references/delete.md) | programs.delete |
@@ -22,14 +22,14 @@ description: 使用 @tier0/sdk-v2 的 client.stream 创建、查询、修改和
22
22
 
23
23
  | 形态 | 完整输入 | 适用入口 |
24
24
  | --- | --- | --- |
25
- | Runtime program | name、sdkVersion、script 字符串、sourceBindings、timeoutMs | documents.create/update/validate({program});兼容 programs.create/update/validate({document}) |
25
+ | Runtime program | name、sdkVersion、script 字符串、sourceBindings、timeoutMs | documents.create/update/validate({program}) |
26
26
  | 云端原生文档 | name、model、script 对象、sources、entries | documents.create/get/update/validate |
27
27
 
28
28
  程序必须是完整 `module.exports = api => { ... }`,执行器 API 是 api.sources/api.uns/api.stream,与 npm 包的 client.source 不同。Runtime sourceBindings 为 sourceId/configRevision/acquisition;原生 sources 还使用 alias/resources。连接凭据不进脚本或 acquisition。
29
29
 
30
30
  ## 核心约束
31
31
 
32
- 1. programs.get 返回脱敏摘要,不含可回写脚本;完整编辑使用 documents.get 或上次 documents.create/update 返回的完整文档。保留未修改的 sources/entries/script 字段。
32
+ 1. documents.get({id,view:"summary"}) 返回安全摘要,不含可回写脚本;完整编辑使用 documents.get 或上次 documents.create/update 返回的完整文档。保留未修改的 sources/entries/script 字段。
33
33
  2. create/update 保存草稿,不自动发布;documents 没有 deploy,云端 program 发布使用 programs.deploy。不能将已保存报告为已运行。
34
34
  3. 所有更新/部署/删除携带当前 expectedRevision。原生停用另需 expectedActiveRelease,避免停掉他人刚发布的版本。
35
35
  4. versionId 从 versions.list 取得,不把 release 序号当 ID。expectedSourceRevision 仅用于恰好一个依赖源,不代表多个源的修订。
@@ -51,6 +51,6 @@ export async function createHttpStream(
51
51
 
52
52
  创建 data 为 CloudStreamDocumentView 或预检结果,实际保存返回 id、revision 和完整 document;预检不生成 ID。需要展示预检时单独调用 documents.validate({program});普通保存无需先校验再保存。当前后端创建/校验需要注册 Worker 可用。TEMPORARILY_UNAVAILABLE 不代表脚本一定错误;不要自动改用旧 Flow。
53
53
 
54
- 兼容入口 programs.create({document}) 仍返回含 id、revision、activeVersion、executionState 的程序摘要回执,可直接使用 revision。恢复旧请求必须保留原路由、原载荷和原幂等键,不能改投 documents.create。
54
+ programs.create 已退役,创建统一使用 documents.create。历史创建结局未知时先按已知 ID 或业务标识核对状态,不能将旧请求或幂等键改投 documents.create 重做。
55
55
 
56
56
  原生编辑器形态 `documents.create({dryRun, document})` 的 document 为 name/model/script对象/sources/entries,script 为 `{sdkVersion,code,timeoutMs}`,sources 用 alias/sourceId/configRevision/resources/acquisition。不要把上面的 script 字符串直接塞入原生文档。
@@ -3,12 +3,21 @@
3
3
  | 方法 | POST 路径 | 必要参数 |
4
4
  | --- | --- | --- |
5
5
  | programs.deploy | /openapi/v2/uns/streams/program/deploy | id、dryRun;建议 expectedRevision |
6
- | programs.disable | /openapi/v2/uns/streams/program/disable | id、dryRun;建议 expectedRevision |
7
6
  | programs.rollback | /openapi/v2/uns/streams/program/rollback | id、versionId、dryRun;建议 expectedRevision |
8
7
  | documents.disable | /openapi/v2/uns/streams/documents/disable | id、expectedRevision、expectedActiveRelease、dryRun |
9
8
 
10
9
  全部写操作使用各自的 idempotencyKey。expectedSourceRevision 只适用于恰好一个 Source 依赖,且同时保护草稿冻结修订与当前 Source head;多源不能塞入单个修订值。原生文档没有 documents.deploy,当前云端 program 模型发布走 programs.deploy。
11
10
 
11
+ 发布、停用和回滚需要 uns.stream.manage;相关 Source 访问还受各自授权约束。保存回执中的 revision、发布回执中的 activeVersion 与 activeRelease 分别用于不同目的:
12
+
13
+ | 字段 | 含义与用途 |
14
+ | --- | --- |
15
+ | revision | 草稿修订;传给下次写入的 expectedRevision,冲突时显式处理 |
16
+ | activeVersion | 不可变发布版本 ID;回滚的 versionId 使用这个 ID,不使用发布序号 |
17
+ | activeRelease | 本次事务记录的正整数发布序号;与 runs.list 中的 release 对照;无活跃发布或旧回执未记录时省略 |
18
+
19
+ programs 回执的 activeVersion:'0' 表示无活跃版本;新增 activeRelease 不用 0 表示未发布。原生 documents 回执的既有 activeRelease 约定不变。
20
+
12
21
  ```ts
13
22
  import { createClient, type Tier0Client, type CloudStreamDocumentView } from '@tier0/sdk-v2';
14
23
 
@@ -44,7 +53,7 @@ export async function disableStream(id: string, intentKey: string, client: Tier0
44
53
  }
45
54
  ```
46
55
 
47
- 将创建或更新回执的 current 传给 deployStream,只发一次发布请求。只有手上没有草稿快照时才先 documents.get。programs 回执的 activeRelease 是这次写入事务的正整数发布序号;无活跃发布或历史回执未记录编号时省略。使用 runs.list 并筛选 String(run.release) === String(release) 才能观察这次发布,观察窗口汇总不能证明该版本运行。发布成功不表示外部连接健康或执行成功。停用保留草稿。仅修改草稿的任务不额外发布/停用。
56
+ 将创建或更新回执的 current 传给 deployStream,只发一次发布请求。只有手上没有草稿快照时才先 documents.get。使用 [按发布号查询运行记录](read.md#观察本次发布) 才能观察这次发布,观察窗口汇总不能证明该版本运行。发布成功不表示外部连接健康或执行成功。停用保留草稿。仅修改草稿的任务不额外发布/停用。
48
57
 
49
58
  ## 回滚到明确版本
50
59
 
@@ -1,6 +1,6 @@
1
1
  # Stream 样例测试与流程衔接
2
2
 
3
- 完整流程按任务选取:[创建](create.md) → [查询](read.md) → [修改](update.md) → [发布/停用/回滚](deploy.md) → [删除](delete.md)。不要为了完成一次查询自动执行整套流程。
3
+ 创建并发布时,将 [创建](create.md) 或 [修改](update.md) 回执中的草稿直接交给 [发布](deploy.md),再用发布回执的 activeRelease [观察运行](read.md#观察本次发布),无需在发布前后各 get 一次。只有缺少当前草稿、处理版本冲突或需要最新状态时才 [查询](read.md)。停用、回滚和 [删除](delete.md) 按任务选择,不自动执行整套生命周期。
4
4
 
5
5
  ## 原生文档样例测试
6
6
 
@@ -3,22 +3,20 @@
3
3
  | 方法 | POST 路径 | 输入 | 结果 |
4
4
  | --- | --- | --- | --- |
5
5
  | programs.list | /openapi/v2/uns/streams/program/list | page、size、search、sourceId、model、status、archived | list、total、hasMore、nextPage |
6
- | programs.get | /openapi/v2/uns/streams/program/get | id | 运行摘要,document 已脱敏 |
7
- | documents.get | /openapi/v2/uns/streams/documents/get | id | 完整草稿、revision、status、activeRelease、可选 activeDocument |
6
+ | documents.get | /openapi/v2/uns/streams/documents/get | id;可选 view:summary/full | summary 返回摘要;full 返回完整草稿、revision、status、activeRelease、可选 activeDocument |
8
7
  | observations.get | /openapi/v2/uns/streams/observation/get | id | 运行观测 |
9
8
  | runs.list | /openapi/v2/uns/streams/runs/list | id、size、cursor | 执行记录 |
10
9
  | programs.versions.list | /openapi/v2/uns/streams/program/versions/list | id、page、size | list、total,含 versionId |
11
10
 
12
- page 从 1 开始,size 最大 200。完整文档需要 Stream manage 权限;programs.get 的 scriptConfigured 不是脚本内容,不能据此重建草稿。
11
+ page 从 1 开始,size 最大 200。summary 只需 uns.stream.view 或 uns.stream.manage;full 或省略 view 需要 uns.stream.manage,API Key 还必须是 full_access。摘要不含脚本,不能据此重建草稿。已有创建或更新回执时可复用其文档与 revision,不必再读取。
13
12
 
14
13
  ```ts
15
14
  import { createClient, type Tier0Client } from '@tier0/sdk-v2';
16
15
 
17
16
  export async function readStream(id: string, client: Tier0Client = createClient()) {
18
17
  const draft = await client.stream.documents.get({ id });
19
- const summary = await client.stream.programs.get({ id });
20
18
  const observation = await client.stream.observations.get({ id });
21
- return { draft: draft.data, summary: summary.data, observation: observation.data };
19
+ return { draft: draft.data, observation: observation.data };
22
20
  }
23
21
  export async function* listStreams(client: Tier0Client = createClient()) {
24
22
  let page = 1;
@@ -33,3 +31,25 @@ export async function* listStreams(client: Tier0Client = createClient()) {
33
31
  ```
34
32
 
35
33
  保存、发布、某次执行成功是三个事实。显示实际 revision/activeVersion/release,不用旧 runs 证明新版本生效。版本列表不保证与普通列表相同分页结构;按其 list/total/page/size 读取,versionId 不是 release 序号。
34
+
35
+ ## 观察本次发布
36
+
37
+ 把 deploy 回执的 activeRelease 原样传入,不需要先读取当前 head。runs.list 需要 uns.stream.view 或 uns.stream.manage;它没有服务端 release 过滤参数,按返回的 nextCursor 继续翻页并在客户端匹配发布号:
38
+
39
+ ```ts
40
+ import { createClient, type Tier0Client, type UnsV2Integer } from '@tier0/sdk-v2';
41
+
42
+ export async function readPublishedRuns(
43
+ id: string, release: UnsV2Integer, cursor?: string,
44
+ client: Tier0Client = createClient(),
45
+ ) {
46
+ if (typeof release === 'number' && !Number.isSafeInteger(release)) {
47
+ throw new Error('发布号必须保留回执中的精确整数,不能传已失真的 number');
48
+ }
49
+ if (BigInt(String(release)) <= 0n) throw new Error('需要发布回执中的正整数发布号');
50
+ const { data } = await client.stream.runs.list({ id, size: 100, ...(cursor ? { cursor } : {}) });
51
+ return { ...data, items: data.items.filter(run => run.release === String(release)) };
52
+ }
53
+ ```
54
+
55
+ 此函数只读一页。items 为空但 nextCursor 非空时,下一页仍可能有匹配记录;达到调用方的观察时限就报告“尚未观察到”。匹配记录也要检查 status、entryId 和时间,不能把存在记录当成执行成功。历史幂等回执若缺少 activeRelease,应保留为未确认,不能用当前 head 的发布号代替。
@@ -29,6 +29,6 @@ export async function updateStreamDescription(
29
29
  }
30
30
  ```
31
31
 
32
- 代码应用可直接用 documents.update({id, expectedRevision, program, dryRun:false, idempotencyKey}),由服务端编译入口和绑定。编辑完整文档时保留 sdkVersion/timeoutMs,并同步 entries/sources;写入本身执行校验,只有需要提前展示问题时才单独 validate。不要对脱敏 programs.get.document 做展开更新。
32
+ 代码应用可直接用 documents.update({id, expectedRevision, program, dryRun:false, idempotencyKey}),由服务端编译入口和绑定。编辑完整文档时保留 sdkVersion/timeoutMs,并同步 entries/sources;写入本身执行校验,只有需要提前展示问题时才单独 validate。不要对documents.get 的 summary 做展开更新。
33
33
 
34
34
  响应是完整 CloudStreamDocumentView 或预检结果;把 saved.data 直接传给下一步[发布示例](deploy.md),无需为了 revision 再读取。已有当前完整文档时可省去示例最初的 get。保存草稿不会自动部署,activeDocument 可能仍是旧发布版本。VERSION_CONFLICT 后重新读取、比较并决策;不无条件覆盖。
@@ -1,6 +1,6 @@
1
1
  # 服务信息与 MQTT 地址
2
2
 
3
- 方法:`system.info()`;POST /openapi/v1/info,无业务参数。
3
+ 方法:`system.info()`;POST /openapi/v2/info,无业务参数。
4
4
 
5
5
  ```ts
6
6
  import { createClient, type Tier0Client } from '@tier0/sdk-v2';
@@ -1,6 +1,6 @@
1
1
  # API Key 身份诊断
2
2
 
3
- 方法:`system.whoami()`;POST /openapi/v1/auth/whoami,无业务参数。不是调用其他 API 的强制前置步骤。
3
+ 方法:`system.whoami()`;POST /openapi/v2/auth/whoami,无业务参数。不是调用其他 API 的强制前置步骤。
4
4
 
5
5
  ```ts
6
6
  import { createClient, type Tier0Client } from '@tier0/sdk-v2';
@@ -13,7 +13,7 @@ UNS 管数据命名空间、集合、Record 和 Sample;外部连接与脚本
13
13
  | --- | --- | --- |
14
14
  | 创建集合、定义 Schema、新增记录 | [创建](references/create.md) | metadataInsertOne/Many、recordInsertOne |
15
15
  | 查询集合、筛选/排序记录 | [查询](references/read.md) | dataAppContext、metadataFind/FindOne(非 App 凭证)、collectionDescribe、recordFind |
16
- | 改记录、集合名称、扩展 Schema | [修改](references/update.md) | recordUpdateOne、metadataUpdateOne/Many、metadataFindOneAndUpdate |
16
+ | 改记录、集合名称、扩展 Schema | [修改](references/update.md) | recordUpdateOne、metadataUpdateOne/Many |
17
17
  | 删记录、软删除集合 | [删除](references/delete.md) | recordDeleteOne、metadataDeleteOne/Many |
18
18
  | 恢复集合或记录 | [恢复](references/restore.md) | metadataRestore、recordRestore |
19
19
  | 分页、历史采样、事务、写入结果 | [数据工作流](references/data-workflows.md) | sampleFind、recordTransactionExecute |
@@ -42,7 +42,7 @@ export async function findAppCollection(alias: string) {
42
42
  ## 核心约束
43
43
 
44
44
  1. 记录行是 id/data/revision;filter 与 update 的业务路径用 name、customer.name,不加 data.;系统路径用 _id、_meta.revision。
45
- 2. 改/删前读取 expectedRevision;不同操作使用独立意图键,长度上限以当前操作契约为准。
45
+ 2. 改/删使用最近写回执或读取取得的 revision 作为 expectedRevision;创建时可用 returnDocument:'after' 取得快照。历史重放不是当前最新版本,冲突时显式处理;不同操作使用独立意图键,长度上限以当前操作契约为准。
46
46
  3. metadataUpdateOne 的 $set.recordSchema 替换完整 Schema,不迁移已有记录;未更新的 sampleSchema/indexes 保留。先预检兼容性。
47
47
  4. 集合无硬删除入口,用 metadataDeleteOne/Many 软删除;Record 删除会物理删除关联 Sample,恢复 Record 不会恢复这些 Sample。
48
48
  5. recordFind 使用 pageInfo.hasMore/nextCursor,limit 1–200;sort 为 [['field',1]]。单页不是全量,跨页不是稳定快照。
@@ -50,6 +50,6 @@ export async function findAppCollection(alias: string) {
50
50
 
51
51
  ## 结果与异常
52
52
 
53
- 响应为 code/msg/requestId/data。元数据 find 返回 items/pageInfo;findOne 与 findOneAnd* 返回 value;普通写入返回对应计数和 ID。metadataTransact 的 results 按 opId 对应。检查 committed、每项错误和实际计数;dryRun 只校验。metadataBulkWrite 默认原子,显式非原子时必须逐项检查 results/errors;跨 kind 的依赖写入使用 metadataTransact。recordBulkWrite 不保证跨集合事务。
53
+ 响应为 code/msg/requestId/data。元数据 find 返回 items/pageInfo;单条 updateOne/replaceOne/deleteOne 请求 returnDocument 时附带 value;普通写入默认返回对应计数和 ID。metadataTransact 的 results 按 opId 对应。检查 committed、每项错误和实际计数;dryRun 只校验。metadataBulkWrite 默认原子,显式非原子时必须逐项检查 results/errors;跨 kind 的依赖写入使用 metadataTransact。recordBulkWrite 不保证跨集合事务。
54
54
 
55
55
  大整数与 JSON 精确数字可能为 bigint/UnsV2RawNumber;保留读取到的 revision 类型,不用 Number 或普通 JSON.stringify 做无损往返。错误带 execution(notStarted / rolledBack / committed / unknown)与 retry(safe、afterMs)。UnsV2OutcomeUnknownError(execution 为 unknown)先读回核对内容;retry.safe 时可以用同一请求、同一幂等键原样重发。取消请求不撤销写入;client.uns 不自动重试。
@@ -1,6 +1,6 @@
1
1
  # 创建集合与记录
2
2
 
3
- 元数据使用 metadataInsertOne(POST /openapi/v2/uns/metadata)或 metadataInsertMany;kind 指定 directory/topic/collection。单条提供 data、可选 id;批量提供同一 kind 的 documents[{id?,data}]。idempotencyKey 标识一个写入意图;dryRun=true 仅校验。schemaVersion 由服务端赋默认值。
3
+ 元数据使用 metadataInsertOne(POST /openapi/v2/uns/metadata)或 metadataBulkWrite 的 insertOne 项;kind 指定 directory/topic/collection。单条提供 data、可选 id;批量提供同一 kind 的 operations[{insertOne:{id?,data}}]。idempotencyKey 标识一个写入意图;dryRun=true 仅校验。schemaVersion 由服务端赋默认值。
4
4
 
5
5
  集合 data 必须包含 name、recordSchema,可选 description、parentId、sampleSchema、indexes、semantics。parentId=null 表示根目录。索引创建后仍需确认状态为 ready。
6
6
 
@@ -28,13 +28,17 @@ export async function createDeviceCollection(
28
28
  if (preview.data.status !== 'validated') throw new Error('集合预检未通过');
29
29
  const receipt = await client.uns.metadataInsertOne({ ...request, dryRun: false, idempotencyKey: intentKey });
30
30
  if (receipt.data.status !== 'committed') return { state: 'unconfirmed' as const, receipt };
31
- const current = await client.uns.metadataFindOne({ kind: 'collection', filter: { _id: collectionId } });
32
- if (!current.data.value) throw new Error('集合创建有回执,读回未确认');
33
- return { state: 'committed' as const, receipt, current: current.data.value };
31
+ const current = await client.uns.metadataFind({ kind: 'collection', filter: { _id: collectionId }, limit: 1 });
32
+ if (!current.data.items[0]) throw new Error('集合创建有回执,读回未确认');
33
+ return { state: 'committed' as const, receipt, current: current.data.items[0] };
34
34
  }
35
35
  ```
36
36
 
37
- 单条新增默认返回 insertedId/status/replayed。需要创建后的数据、revision 和时间戳时,传 returnDocument:'after',同一次写入返回 value,无需再查询;可配合 projection,调用者必须同时具有读取权限。幂等重放返回原始创建快照,后续读取最新状态仍用 recordGet/recordFind。dryRun 的 value 是未提交预览。
37
+ 单条 Record 新增默认返回 insertedId/status/replayed。需要创建后的数据、revision 和时间戳时,传 returnDocument:'after',同一次写入返回 value,无需再查询;可配合 projection,调用者必须同时具有读取权限。幂等重放返回原始创建快照,后续读取最新状态仍用 recordGet/recordFind。dryRun 的 value 是未提交预览。
38
+
39
+ returnDocument 只允许 none(默认)或 after,不支持 before;projection 只能和 after 一起传。新增仍是 insert,已存在的 ID 不会变成更新。after 的 value 包括服务端补入的字段,但只返回当前授权可见的数据:普通数据权限需 uns.write 和 uns.read,App 还要满足集合的 record:write / record:read 及当前员工、行和字段策略。服务端在提交前校验读取权限,重放时也重新校验;旧回执不能绕过已撤销的授权。
40
+
41
+ 省略 returnDocument 与显式 none 保持相同幂等语义。不能用同一个意图键把原来的 none 改成 after 补取快照,否则返回 IDEMPOTENCY_CONFLICT;已创建的记录应改用读取接口。after 重放可对原始快照应用 projection,但不会变成最新记录。创建快照中的 revision 可用于下一次修改;若已有并发修改,版本冲突仍需显式处理。
38
42
 
39
43
  批量新增返回 insertedCount/insertedIds 及适用的逐项错误。insertedIds 的键是原始输入从 0 开始的索引。省略自定义 ID 时从成功回执取得实际 ID,不能把名称当成 ID。
40
44
 
@@ -23,7 +23,7 @@ export async function deleteDevice(
23
23
  }
24
24
  ```
25
25
 
26
- 元数据使用 metadataDeleteOne/Many,或 metadataFindOneAndDelete 返回删除前对象。它们执行软删除,增加 revision,不隐式级联目录后代、引用对象或集合数据。引用约束与版本冲突必须处理,不能自行扩展删除范围。
26
+ 元数据使用 metadataDeleteOne/Many,或 metadataDeleteOne + returnDocument:before 返回删除前对象。它们执行软删除,增加 revision,不隐式级联目录后代、引用对象或集合数据。引用约束与版本冲突必须处理,不能自行扩展删除范围。
27
27
 
28
28
  ```ts
29
29
  import { createClient, type Tier0Client } from '@tier0/sdk-v2';
@@ -31,7 +31,7 @@ import { createClient, type Tier0Client } from '@tier0/sdk-v2';
31
31
  export async function deleteCollection(
32
32
  id: string, intentKey: string, client: Tier0Client = createClient(),
33
33
  ) {
34
- const current = (await client.uns.metadataFindOne({ kind: 'collection', filter: { _id: id } })).data.value;
34
+ const current = (await client.uns.metadataFind({ kind: 'collection', filter: { _id: id }, limit: 1 })).data.items[0];
35
35
  if (!current) throw new Error('集合不存在或不可见,未执行删除');
36
36
  const receipt = await client.uns.metadataDeleteOne({
37
37
  kind: 'collection', filter: { _id: id }, expectedRevision: current.revision,
@@ -40,9 +40,9 @@ export async function deleteCollection(
40
40
  if (receipt.data.status !== 'committed' || String(receipt.data.deletedCount) !== '1') {
41
41
  return { state: 'unconfirmed' as const, receipt };
42
42
  }
43
- const deleted = await client.uns.metadataFindOne({ kind: 'collection', filter: { _id: id }, state: 'deleted' });
44
- if (!deleted.data.value) throw new Error('删除有回执,但删除状态读回未确认');
45
- return { state: 'deleted' as const, receipt, deleted: deleted.data.value };
43
+ const deleted = await client.uns.metadataFind({ kind: 'collection', filter: { _id: id }, state: 'deleted', limit: 1 });
44
+ if (!deleted.data.items[0]) throw new Error('删除有回执,但删除状态读回未确认');
45
+ return { state: 'deleted' as const, receipt, deleted: deleted.data.items[0] };
46
46
  }
47
47
  ```
48
48
 
@@ -4,15 +4,15 @@
4
4
 
5
5
  | 场景 | 方法 |
6
6
  | --- | --- |
7
- | 单条/批量新增 | metadataInsertOne / metadataInsertMany |
7
+ | 单条/批量新增 | metadataInsertOne / metadataBulkWrite 的 insertOne 项 |
8
8
  | 单条/批量条件更新 | metadataUpdateOne / metadataUpdateMany |
9
- | 更新并读取原子结果 | metadataFindOneAndUpdate / metadataFindOneAndReplace |
9
+ | 更新并读取原子结果 | metadataUpdateOne / metadataReplaceOne + returnDocument:before/after |
10
10
  | 同 kind 混合写入 | metadataBulkWrite |
11
11
  | 跨 kind、有依赖的组合操作 | metadataTransact |
12
- | 软删除并返回原对象 | metadataFindOneAndDelete |
12
+ | 软删除并返回原对象 | metadataDeleteOne + returnDocument:before |
13
13
  | 按明确 ID 批量恢复 | metadataRestore |
14
14
 
15
- 普通写操作只指定一个 kind。insertMany/updateMany/deleteMany/restore 固定原子执行;bulkWrite 默认 atomic=true,原子批次不接受 ordered=false。bulkWrite 显式 atomic=false 时 ordered=true 遇错停止,false 继续,并检查 results/errors。非原子执行有任一项已提交后失败时,`execution` 为 committed、`retry.safe` 为 false,错误的 data 是累计结果:序号小于 `nextIndex` 且不在 errors 里的操作已提交;有 `unknownUntil` 时 `[nextIndex, unknownUntil)` 结局未知,用同一个幂等键重试(不带键时只有按 id 的操作能先读回再续做,所以非原子批次始终带幂等键);没有 `unknownUntil` 时从 `nextIndex` 续做。第一块就结局未知时 `execution` 为 unknown。批次最多 200 项。不要给所有对象套一个相同 expectedRevision:需要逐项版本检查时在 bulkWrite 中分别提供。
15
+ 普通写操作只指定一个 kind。updateMany/deleteMany/restore 固定原子执行;bulkWrite 默认 atomic=true,原子批次不接受 ordered=false。bulkWrite 显式 atomic=false 时 ordered=true 遇错停止,false 继续,并检查 results/errors。非原子执行有任一项已提交后失败时,`execution` 为 committed、`retry.safe` 为 false,错误的 data 是累计结果:序号小于 `nextIndex` 且不在 errors 里的操作已提交;有 `unknownUntil` 时 `[nextIndex, unknownUntil)` 结局未知,用同一个幂等键重试(不带键时只有按 id 的操作能先读回再续做,所以非原子批次始终带幂等键);没有 `unknownUntil` 时从 `nextIndex` 续做。第一块就结局未知时 `execution` 为 unknown。批次最多 200 项。不要给所有对象套一个相同 expectedRevision:需要逐项版本检查时在 bulkWrite 中分别提供。
16
16
 
17
17
  ```ts
18
18
  import { createClient, type Tier0Client } from '@tier0/sdk-v2';
@@ -3,23 +3,24 @@
3
3
  | 方法 | 必要输入 | 返回 data |
4
4
  | --- | --- | --- |
5
5
  | metadataFind | kinds;可选 filter、sort、projection、page、state | items、pageInfo |
6
- | metadataFindOne | kind、filter;可选 state | value,未找到为 null |
7
- | metadataCount / metadataDistinct | kind/kinds 与查询条件;distinct 还指定 field | count / values、pageInfo |
6
+ | metadataFind + limit:1 | kind、filter;可选 state | 取 items[0],空结果视为未匹配 |
7
+ | metadataCount / metadataAggregate | kind/kinds 与查询条件;去重 pipeline 为 [{ $distinct: field }] | count / items、pageInfo;去重每项为 {value} |
8
8
  | collectionDescribe | collectionId | 集合结构和数据能力 |
9
9
  | recordFind | collectionId;可选 filter、sort、limit、cursor | items、pageInfo |
10
10
 
11
- 元数据查询配置字段写 name、parentId;系统字段写 _id、_meta.kind、_meta.revision。返回资源的配置在 value.data 或 items[].data 中。state 为 active/deleted/all,默认 active。对象身份始终是 kind + id。
11
+ 元数据查询配置字段写 name、parentId;系统字段写 _id、_meta.kind、_meta.revision。返回资源的配置在 items[].data 中。state 为 active/deleted/all,默认 active。对象身份始终是 kind + id。
12
12
 
13
13
  ```ts
14
14
  import { createClient, type Tier0Client } from '@tier0/sdk-v2';
15
15
 
16
16
  export async function readDevices(collectionId: string, client: Tier0Client = createClient()) {
17
- const collection = await client.uns.metadataFindOne({ kind: 'collection', filter: { _id: collectionId } });
18
- if (!collection.data.value) throw new Error('集合不存在或不可见');
17
+ const collection = await client.uns.metadataFind({ kind: 'collection', filter: { _id: collectionId }, limit: 1 });
18
+ const definition = collection.data.items[0];
19
+ if (!definition) throw new Error('集合不存在或不可见');
19
20
  const records = await client.uns.recordFind({
20
21
  collectionId, filter: { enabled: true }, sort: [['name', 1]], limit: 20,
21
22
  });
22
- return { definition: collection.data.value.data, items: records.data.items, pageInfo: records.data.pageInfo };
23
+ return { definition: definition.data, items: records.data.items, pageInfo: records.data.pageInfo };
23
24
  }
24
25
 
25
26
  export async function listCollections(page = 1, client: Tier0Client = createClient()) {
@@ -31,4 +32,4 @@ export async function listCollections(page = 1, client: Tier0Client = createClie
31
32
 
32
33
  按 pageInfo.hasMore/nextPage 继续元数据分页;不要把第一页当全量。recordFind 的游标循环见[数据工作流](data-workflows.md)。sort 是数组元组。
33
34
 
34
- 以上 metadataFind/FindOne 示例用于 Workspace 集成(会话、personal / agent Key)。App 凭证不能调用 metadataFind/FindOne:用 dataAppContext 精确选择授权 alias,集合的 revision、indexStatus、ttl 也在其中。数据授权不等于元数据管理授权。网络/权限错误必须传播,不能用空数组掩盖错误。
35
+ 以上 metadataFind 示例用于 Workspace 集成(会话、personal / agent Key)。App 凭证不能调用 metadataFind:用 dataAppContext 精确选择授权 alias,集合的 revision、indexStatus、ttl 也在其中。数据授权不等于元数据管理授权。网络/权限错误必须传播,不能用空数组掩盖错误。
@@ -8,7 +8,7 @@ import { createClient, type Tier0Client } from '@tier0/sdk-v2';
8
8
  export async function restoreCollection(
9
9
  id: string, intentKey: string, client: Tier0Client = createClient(),
10
10
  ) {
11
- const deleted = (await client.uns.metadataFindOne({ kind: 'collection', filter: { _id: id }, state: 'deleted' })).data.value;
11
+ const deleted = (await client.uns.metadataFind({ kind: 'collection', filter: { _id: id }, state: 'deleted', limit: 1 })).data.items[0];
12
12
  if (!deleted) throw new Error('未找到待恢复集合');
13
13
  const receipt = await client.uns.metadataRestore({
14
14
  kind: 'collection', items: [{ id, expectedRevision: deleted.revision }], idempotencyKey: intentKey,
@@ -16,7 +16,7 @@ export async function restoreCollection(
16
16
  if (receipt.data.status !== 'committed' || String(receipt.data.restoredCount) !== '1') {
17
17
  return { state: 'unconfirmed' as const, receipt };
18
18
  }
19
- const current = (await client.uns.metadataFindOne({ kind: 'collection', filter: { _id: id } })).data.value;
19
+ const current = (await client.uns.metadataFind({ kind: 'collection', filter: { _id: id }, limit: 1 })).data.items[0];
20
20
  if (!current) throw new Error('恢复有回执,读回未确认');
21
21
  return { state: 'committed' as const, receipt, current };
22
22
  }