@tier0/sdk-v2 0.9.10 → 0.10.1

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 (238) hide show
  1. package/CHANGELOG.md +102 -0
  2. package/LICENSE +21 -21
  3. package/README.md +162 -24
  4. package/dist/cjs/client.d.ts +83 -3
  5. package/dist/cjs/client.js +4 -6
  6. package/dist/cjs/client.js.map +1 -1
  7. package/dist/cjs/cloud-server.d.ts +33 -26
  8. package/dist/cjs/cloud-server.js +102 -100
  9. package/dist/cjs/cloud-server.js.map +1 -1
  10. package/dist/cjs/cloud-transport.d.ts +15 -20
  11. package/dist/cjs/cloud-transport.js +87 -68
  12. package/dist/cjs/cloud-transport.js.map +1 -1
  13. package/dist/cjs/data/bootstrap.js +3 -4
  14. package/dist/cjs/data/bootstrap.js.map +1 -1
  15. package/dist/cjs/data/call.d.ts +1 -3
  16. package/dist/cjs/data/call.js +8 -12
  17. package/dist/cjs/data/call.js.map +1 -1
  18. package/dist/cjs/data/client.d.ts +8 -7
  19. package/dist/cjs/data/client.js +24 -11
  20. package/dist/cjs/data/client.js.map +1 -1
  21. package/dist/cjs/data/collection.d.ts +3 -5
  22. package/dist/cjs/data/collection.js +3 -4
  23. package/dist/cjs/data/collection.js.map +1 -1
  24. package/dist/cjs/data/context.d.ts +5 -11
  25. package/dist/cjs/data/context.js +21 -36
  26. package/dist/cjs/data/context.js.map +1 -1
  27. package/dist/cjs/data/error.js +1 -1
  28. package/dist/cjs/data/error.js.map +1 -1
  29. package/dist/cjs/data/index.d.ts +5 -3
  30. package/dist/cjs/data/index.js +5 -5
  31. package/dist/cjs/data/index.js.map +1 -1
  32. package/dist/cjs/data/relay.d.ts +51 -0
  33. package/dist/cjs/data/relay.js +371 -0
  34. package/dist/cjs/data/relay.js.map +1 -0
  35. package/dist/cjs/data/subscribe.d.ts +22 -38
  36. package/dist/cjs/data/subscribe.js +22 -28
  37. package/dist/cjs/data/subscribe.js.map +1 -1
  38. package/dist/cjs/event-stream.d.ts +28 -0
  39. package/dist/cjs/event-stream.js +222 -0
  40. package/dist/cjs/event-stream.js.map +1 -0
  41. package/dist/cjs/mq/client.d.ts +32 -1
  42. package/dist/cjs/mq/client.js +404 -69
  43. package/dist/cjs/mq/client.js.map +1 -1
  44. package/dist/cjs/mq/index.d.ts +1 -0
  45. package/dist/cjs/mq/index.js +3 -1
  46. package/dist/cjs/mq/index.js.map +1 -1
  47. package/dist/cjs/mq/topic.d.ts +29 -0
  48. package/dist/cjs/mq/topic.js +48 -0
  49. package/dist/cjs/mq/topic.js.map +1 -0
  50. package/dist/cjs/mq/types.d.ts +21 -1
  51. package/dist/cjs/mq/types.js.map +1 -1
  52. package/dist/cjs/openapi/api.generated.d.ts +21 -0
  53. package/dist/cjs/openapi/api.generated.js +11 -0
  54. package/dist/cjs/openapi/api.generated.js.map +1 -1
  55. package/dist/cjs/openapi/client.d.ts +46 -0
  56. package/dist/cjs/openapi/client.js +158 -10
  57. package/dist/cjs/openapi/client.js.map +1 -1
  58. package/dist/cjs/openapi/codecs.generated.d.ts +75 -0
  59. package/dist/cjs/openapi/codecs.generated.js +1 -1
  60. package/dist/cjs/openapi/codecs.generated.js.map +1 -1
  61. package/dist/cjs/openapi/types.generated.d.ts +206 -1
  62. package/dist/cjs/openapi/types.generated.js.map +1 -1
  63. package/dist/cjs/page-runtime.d.ts +48 -0
  64. package/dist/cjs/page-runtime.js +74 -0
  65. package/dist/cjs/page-runtime.js.map +1 -0
  66. package/dist/cjs/platform-proxy.d.ts +17 -0
  67. package/dist/cjs/platform-proxy.js +52 -0
  68. package/dist/cjs/platform-proxy.js.map +1 -0
  69. package/dist/cjs/runtime-context.d.ts +2 -1
  70. package/dist/cjs/runtime-context.js +6 -2
  71. package/dist/cjs/runtime-context.js.map +1 -1
  72. package/dist/cjs/runtime-env.js.map +1 -1
  73. package/dist/cjs/source.d.ts +19 -1
  74. package/dist/cjs/source.js +9 -3
  75. package/dist/cjs/source.js.map +1 -1
  76. package/dist/cjs/stream.js +3 -2
  77. package/dist/cjs/stream.js.map +1 -1
  78. package/dist/cjs/streams/contract.generated.d.ts +7 -1
  79. package/dist/cjs/streams/contract.generated.js.map +1 -1
  80. package/dist/cjs/streams/messages.js +1 -10
  81. package/dist/cjs/streams/messages.js.map +1 -1
  82. package/dist/cjs/streams/requests.d.ts +3 -0
  83. package/dist/cjs/streams/requests.js +5 -2
  84. package/dist/cjs/streams/requests.js.map +1 -1
  85. package/dist/cjs/streams/transport.d.ts +1 -13
  86. package/dist/cjs/streams/transport.js +2 -18
  87. package/dist/cjs/streams/transport.js.map +1 -1
  88. package/dist/cjs/uns-v2/client.d.ts +1 -6
  89. package/dist/cjs/uns-v2/client.js +30 -6
  90. package/dist/cjs/uns-v2/client.js.map +1 -1
  91. package/dist/cjs/uns-v2/data-client.d.ts +5 -2
  92. package/dist/cjs/uns-v2/data-client.js +7 -4
  93. package/dist/cjs/uns-v2/data-client.js.map +1 -1
  94. package/dist/cjs/uns-v2/generated.d.ts +6783 -4655
  95. package/dist/cjs/uns-v2/generated.js +221 -65
  96. package/dist/cjs/uns-v2/generated.js.map +1 -1
  97. package/dist/cjs/uns-v2/sse.d.ts +7 -1
  98. package/dist/cjs/uns-v2/sse.js +12 -2
  99. package/dist/cjs/uns-v2/sse.js.map +1 -1
  100. package/dist/esm/client.d.ts +83 -3
  101. package/dist/esm/client.js +5 -7
  102. package/dist/esm/client.js.map +1 -1
  103. package/dist/esm/cloud-server.d.ts +33 -26
  104. package/dist/esm/cloud-server.js +99 -97
  105. package/dist/esm/cloud-server.js.map +1 -1
  106. package/dist/esm/cloud-transport.d.ts +15 -20
  107. package/dist/esm/cloud-transport.js +86 -67
  108. package/dist/esm/cloud-transport.js.map +1 -1
  109. package/dist/esm/data/bootstrap.js +3 -4
  110. package/dist/esm/data/bootstrap.js.map +1 -1
  111. package/dist/esm/data/call.d.ts +1 -3
  112. package/dist/esm/data/call.js +9 -13
  113. package/dist/esm/data/call.js.map +1 -1
  114. package/dist/esm/data/client.d.ts +8 -7
  115. package/dist/esm/data/client.js +22 -9
  116. package/dist/esm/data/client.js.map +1 -1
  117. package/dist/esm/data/collection.d.ts +3 -5
  118. package/dist/esm/data/collection.js +3 -4
  119. package/dist/esm/data/collection.js.map +1 -1
  120. package/dist/esm/data/context.d.ts +5 -11
  121. package/dist/esm/data/context.js +19 -33
  122. package/dist/esm/data/context.js.map +1 -1
  123. package/dist/esm/data/error.js +1 -1
  124. package/dist/esm/data/error.js.map +1 -1
  125. package/dist/esm/data/index.d.ts +5 -3
  126. package/dist/esm/data/index.js +3 -2
  127. package/dist/esm/data/index.js.map +1 -1
  128. package/dist/esm/data/relay.d.ts +51 -0
  129. package/dist/esm/data/relay.js +368 -0
  130. package/dist/esm/data/relay.js.map +1 -0
  131. package/dist/esm/data/subscribe.d.ts +22 -38
  132. package/dist/esm/data/subscribe.js +22 -27
  133. package/dist/esm/data/subscribe.js.map +1 -1
  134. package/dist/esm/event-stream.d.ts +28 -0
  135. package/dist/esm/event-stream.js +217 -0
  136. package/dist/esm/event-stream.js.map +1 -0
  137. package/dist/esm/mq/client.d.ts +32 -1
  138. package/dist/esm/mq/client.js +404 -69
  139. package/dist/esm/mq/client.js.map +1 -1
  140. package/dist/esm/mq/index.d.ts +1 -0
  141. package/dist/esm/mq/index.js +1 -0
  142. package/dist/esm/mq/index.js.map +1 -1
  143. package/dist/esm/mq/topic.d.ts +29 -0
  144. package/dist/esm/mq/topic.js +44 -0
  145. package/dist/esm/mq/topic.js.map +1 -0
  146. package/dist/esm/mq/types.d.ts +21 -1
  147. package/dist/esm/mq/types.js.map +1 -1
  148. package/dist/esm/openapi/api.generated.d.ts +21 -0
  149. package/dist/esm/openapi/api.generated.js +11 -0
  150. package/dist/esm/openapi/api.generated.js.map +1 -1
  151. package/dist/esm/openapi/client.d.ts +46 -0
  152. package/dist/esm/openapi/client.js +157 -10
  153. package/dist/esm/openapi/client.js.map +1 -1
  154. package/dist/esm/openapi/codecs.generated.d.ts +75 -0
  155. package/dist/esm/openapi/codecs.generated.js +1 -1
  156. package/dist/esm/openapi/codecs.generated.js.map +1 -1
  157. package/dist/esm/openapi/types.generated.d.ts +206 -1
  158. package/dist/esm/openapi/types.generated.js.map +1 -1
  159. package/dist/esm/page-runtime.d.ts +48 -0
  160. package/dist/esm/page-runtime.js +65 -0
  161. package/dist/esm/page-runtime.js.map +1 -0
  162. package/dist/esm/platform-proxy.d.ts +17 -0
  163. package/dist/esm/platform-proxy.js +47 -0
  164. package/dist/esm/platform-proxy.js.map +1 -0
  165. package/dist/esm/runtime-context.d.ts +2 -1
  166. package/dist/esm/runtime-context.js +6 -2
  167. package/dist/esm/runtime-context.js.map +1 -1
  168. package/dist/esm/runtime-env.js.map +1 -1
  169. package/dist/esm/source.d.ts +19 -1
  170. package/dist/esm/source.js +10 -4
  171. package/dist/esm/source.js.map +1 -1
  172. package/dist/esm/stream.js +4 -3
  173. package/dist/esm/stream.js.map +1 -1
  174. package/dist/esm/streams/contract.generated.d.ts +7 -1
  175. package/dist/esm/streams/contract.generated.js.map +1 -1
  176. package/dist/esm/streams/messages.js +1 -10
  177. package/dist/esm/streams/messages.js.map +1 -1
  178. package/dist/esm/streams/requests.d.ts +3 -0
  179. package/dist/esm/streams/requests.js +5 -2
  180. package/dist/esm/streams/requests.js.map +1 -1
  181. package/dist/esm/streams/transport.d.ts +1 -13
  182. package/dist/esm/streams/transport.js +1 -17
  183. package/dist/esm/streams/transport.js.map +1 -1
  184. package/dist/esm/uns-v2/client.d.ts +1 -6
  185. package/dist/esm/uns-v2/client.js +30 -6
  186. package/dist/esm/uns-v2/client.js.map +1 -1
  187. package/dist/esm/uns-v2/data-client.d.ts +5 -2
  188. package/dist/esm/uns-v2/data-client.js +8 -5
  189. package/dist/esm/uns-v2/data-client.js.map +1 -1
  190. package/dist/esm/uns-v2/generated.d.ts +6783 -4655
  191. package/dist/esm/uns-v2/generated.js +221 -65
  192. package/dist/esm/uns-v2/generated.js.map +1 -1
  193. package/dist/esm/uns-v2/sse.d.ts +7 -1
  194. package/dist/esm/uns-v2/sse.js +12 -2
  195. package/dist/esm/uns-v2/sse.js.map +1 -1
  196. package/package.json +25 -12
  197. package/skills/tier0-sdk-v2/SKILL.md +11 -5
  198. package/skills/tier0-sdk-v2/references/integration.md +14 -24
  199. package/skills/tier0-sdk-v2/tier0-sdk-v2-data/SKILL.md +11 -5
  200. package/skills/tier0-sdk-v2/tier0-sdk-v2-data/references/consistency.md +6 -10
  201. package/skills/tier0-sdk-v2/tier0-sdk-v2-data/references/errors.md +20 -3
  202. package/skills/tier0-sdk-v2/tier0-sdk-v2-data/references/read-write.md +46 -13
  203. package/skills/tier0-sdk-v2/tier0-sdk-v2-members/SKILL.md +2 -2
  204. package/skills/tier0-sdk-v2/tier0-sdk-v2-members/references/app-members.md +5 -1
  205. package/skills/tier0-sdk-v2/tier0-sdk-v2-mq/SKILL.md +25 -0
  206. package/skills/tier0-sdk-v2/tier0-sdk-v2-mq/references/quickstart.md +1 -1
  207. package/skills/tier0-sdk-v2/tier0-sdk-v2-notifications/SKILL.md +3 -3
  208. package/skills/tier0-sdk-v2/tier0-sdk-v2-notifications/references/send.md +6 -6
  209. package/skills/tier0-sdk-v2/tier0-sdk-v2-source/SKILL.md +4 -4
  210. package/skills/tier0-sdk-v2/tier0-sdk-v2-source/references/changes.md +2 -2
  211. package/skills/tier0-sdk-v2/tier0-sdk-v2-source/references/create.md +26 -36
  212. package/skills/tier0-sdk-v2/tier0-sdk-v2-source/references/delete.md +9 -23
  213. package/skills/tier0-sdk-v2/tier0-sdk-v2-source/references/protocols.md +12 -29
  214. package/skills/tier0-sdk-v2/tier0-sdk-v2-source/references/read.md +4 -5
  215. package/skills/tier0-sdk-v2/tier0-sdk-v2-source/references/update.md +5 -5
  216. package/skills/tier0-sdk-v2/tier0-sdk-v2-stream/SKILL.md +3 -3
  217. package/skills/tier0-sdk-v2/tier0-sdk-v2-stream/references/create.md +23 -9
  218. package/skills/tier0-sdk-v2/tier0-sdk-v2-stream/references/deploy.md +14 -12
  219. package/skills/tier0-sdk-v2/tier0-sdk-v2-stream/references/http-server.md +4 -4
  220. package/skills/tier0-sdk-v2/tier0-sdk-v2-stream/references/read.md +4 -3
  221. package/skills/tier0-sdk-v2/tier0-sdk-v2-streams/SKILL.md +14 -12
  222. package/skills/tier0-sdk-v2/tier0-sdk-v2-uns/SKILL.md +3 -1
  223. package/skills/tier0-sdk-v2/tier0-sdk-v2-uns/references/create.md +2 -2
  224. package/skills/tier0-sdk-v2/tier0-sdk-v2-uns/references/delete.md +22 -1
  225. package/skills/tier0-sdk-v2/tier0-sdk-v2-uns/references/read.md +5 -6
  226. package/skills/tier0-sdk-v2/tier0-sdk-v2-uns/references/update.md +11 -0
  227. package/dist/cjs/app-identity-contract.generated.d.ts +0 -22
  228. package/dist/cjs/app-identity-contract.generated.js +0 -51
  229. package/dist/cjs/app-identity-contract.generated.js.map +0 -1
  230. package/dist/cjs/runtime.d.ts +0 -13
  231. package/dist/cjs/runtime.js +0 -51
  232. package/dist/cjs/runtime.js.map +0 -1
  233. package/dist/esm/app-identity-contract.generated.d.ts +0 -22
  234. package/dist/esm/app-identity-contract.generated.js +0 -48
  235. package/dist/esm/app-identity-contract.generated.js.map +0 -1
  236. package/dist/esm/runtime.d.ts +0 -13
  237. package/dist/esm/runtime.js +0 -46
  238. package/dist/esm/runtime.js.map +0 -1
@@ -9,7 +9,7 @@
9
9
  | title | string | 是 | 1–50 字符 |
10
10
  | content | string | 是 | 1–800 字符 |
11
11
  | idempotencyKey | string | 是 | 最多 128 字符;同一次业务事件固定 |
12
- | mode | test/live | 否 | 根据实际发布环境显式选择;省略服务端默认 live |
12
+ | mode | test/live | 否 | 已废弃,不传;平台按来源判定 |
13
13
  | channels | array | 否 | SDK 省略补 web+mobile;[] 仅站内信 |
14
14
  | sender | object | 否 | app/other;system 仅平台内部服务 Key |
15
15
  | link | string | 否 | https:// 或单斜杠开头,最多 500 字符 |
@@ -22,19 +22,19 @@
22
22
  import { createClient, getCurrentAppId, type Tier0Client } from '@tier0/sdk-v2';
23
23
 
24
24
  export async function sendCompletedOrder(
25
- recipientUserId: string, orderId: string, intentKey: string, mode: 'test' | 'live',
25
+ recipientUserId: string, orderId: string, intentKey: string,
26
26
  client: Tier0Client = createClient(),
27
27
  ) {
28
28
  return client.notifications.send({
29
29
  recipientUserId, type: 'inbox', title: '工单已完成',
30
30
  content: '工单 ' + orderId + ' 已完成,请查看处理结果。',
31
- idempotencyKey: intentKey, mode, channels: ['web', 'mobile'],
31
+ idempotencyKey: intentKey, channels: ['web', 'mobile'],
32
32
  sender: { type: 'app', id: getCurrentAppId() },
33
33
  });
34
34
  }
35
35
  ```
36
36
 
37
- sender.id 来自真实 APP_ID UUID。需带链接时传已验证可访问的业务 https 地址,或确认目标前端支持的相对路由。
37
+ sender.id 来自 getCurrentAppId()(平台设置的 TIER0_APP_ID)。需带链接时传已验证可访问的业务 https 地址,或确认目标前端支持的相对路由。
38
38
 
39
39
  other 发送者应给人读名称,如 `{type:'other',name:'库存同步服务'}`。app 不重复硬编码名称。sender/meta/link 都是展示导航提示,不是授权证明。meta 值为字符串,序列化最多 500 字节;sender.name 最多100字符。source 是废弃别名,不用于新代码。
40
40
 
@@ -48,7 +48,7 @@ other 发送者应给人读名称,如 `{type:'other',name:'库存同步服务'
48
48
  | [] | 只建站内信 |
49
49
  | 重复项 | SDK 去重 |
50
50
 
51
- 没有 desktop 渠道。不要将 SDK 默认值与裸后端省略渠道的静默语义混淆。test 也会创建测试消息,不是 dryRun;仅因 NODE_ENV=production 不能证明 App 已发布。
51
+ 没有 desktop 渠道。不要将 SDK 默认值与裸后端省略渠道的静默语义混淆。mode 由平台判定:预览和沙箱发出的是 test,只进该 App 的预览铃铛;线上 App 发出的是 live。test 也是真实消息,不是 dryRun。
52
52
 
53
53
  同键同内容用于重放原意图;同键改内容产生冲突。新事件/不同收件人使用不同键。SDK 不自动重试,结果未知先对账;已有 messageId 用 get,没有按意图键查询的 SDK 方法。
54
54
 
@@ -69,4 +69,4 @@ other 发送者应给人读名称,如 `{type:'other',name:'库存同步服务'
69
69
  | 422 CONTENT_LIMIT_EXCEEDED | 缩短内容 |
70
70
  | 429 NOTIFICATION_RATE_LIMITED | 有界退避;保留原键,不自动广播重发 |
71
71
 
72
- link 拒绝 //host、反斜杠、Unicode 空白/控制/不可见格式字符。省略 link 不保证无按钮,实际导航还取决于发送者与目标前端。
72
+ link 拒绝 //host、反斜杠、Unicode 空白/控制/不可见格式字符。省略 link 时点开消息不跳转;是否另有打开发送 App 的按钮取决于发送者与目标前端。
@@ -5,7 +5,7 @@ description: 使用 @tier0/sdk-v2 的 client.source 查询、创建、修改和
5
5
 
6
6
  # Source 数据接入
7
7
 
8
- Source 维护连接配置、认证引用与源状态。脚本处理用 [Stream](../tier0-sdk-v2-stream/SKILL.md),数据存储用 [UNS](../tier0-sdk-v2-uns/SKILL.md)。服务端使用 `createClient({apiHost,apiKey})`,或注入 TIER0_API_HOST / TIER0_API_KEY 后 `createClient()`;密钥不进入浏览器。
8
+ Source 维护连接配置、认证引用与源状态。脚本处理用 [Stream](../tier0-sdk-v2-stream/SKILL.md),数据存储用 [UNS](../tier0-sdk-v2-uns/SKILL.md)。服务端使用 `createClient({apiHost,apiKey})`,或注入 TIER0_API_HOST / TIER0_API_KEY 后 `createClient()`;密钥不进入浏览器。Tier0 App 的 Key 无权调 Source 管理接口,Backend 拒绝(403)。
9
9
 
10
10
  ## 按任务加载参考
11
11
 
@@ -16,16 +16,16 @@ Source 维护连接配置、认证引用与源状态。脚本处理用 [Stream](
16
16
  | 列表、详情、运行状态 | [查询](references/read.md) | documents.list/get、observations.get、runtime.get |
17
17
  | 修改名称、端点或配置 | [修改](references/update.md) | documents.update |
18
18
  | 查看修改/删除影响 | [影响分析](references/changes.md) | impact |
19
- | 删除并核验 | [删除](references/delete.md) | delete |
19
+ | 禁用后删除并核验 | [删除](references/delete.md) | documents.state.update、documents.delete |
20
20
 
21
21
  先加载对应操作文档,使用其中的参数表、完整请求及返回判断。只执行用户任务所需步骤;示例函数调用才会执行写入,导入不执行。新建→查询→修改→删除可组成生命周期,但查询任务不触发其他操作。
22
22
 
23
23
  ## 核心约束
24
24
 
25
- 1. Source 配置统一使用 documents.*,原生文档为 `{name,protocol,config}`,HTTP API 显式指定 `config.role`。HTTP 统一为 `protocol: http-api` + `config.role: client/server`;Client 主动请求,Server 接收入站请求,不能互换。HTTPServer 统一接收入站请求,固定前缀后的路由和响应时机属于 Stream。
25
+ 1. Source 配置使用 documents.*,原生文档为 SourceDefinition,连接字段 endpoint/role/http/sql/mqtt/modbus 等位于顶层,与 Enterprise 一致。HTTP API 使用 http-api;OAuth 为 oauth2;SQL 为 edge-sql;Modbus TCP 为 modbus-tcp。Server 托管入口的路由和响应时机由 Stream 定义。
26
26
  2. 已有 ID 和 revision 时优先用 documents.update 的 patch,避免额外 get;完整替换 document 前读取完整文档,安全列表摘要不能无损回写。原生 ID 是十进制字符串,revision 原样传递,不转 Number。
27
27
  3. 现有 Source 修改、删除都要 expectedRevision。仅修改名称、描述可直接提交;修改连接配置或删除时,没有任何 Stream 引用可直接提交,有草稿、活动、历史或不可见引用则需 confirmedImpactRevision。先形成精确意图,再读取全部影响分页;回执不可合成、跨意图复用或静默刷新。提供的回执始终严格校验,不自动获取并同意影响。
28
- 4. 配置中保留认证/TLS 引用,不写明文秘密;HTTP Client 与 SQL 新凭据走创建专用 credentials(SQL 使用 usernamePassword,省略 method),普通创建省略 credentials.method(服务端默认 REQUEST 基址绑定),真实 method/path/query 由 Stream 定义。Basic/Bearer 显式凭据方法限制精确 URL 和方法,OAuth 旧 GET 保留既有兼容语义,不自动扩大旧授权;Server 不携带 Client auth/TLS 配置。
28
+ 4. 配置中保留 credentialRef,不写秘密。创建专用 credentials 与 documents.credentials.update 使用原生 kind 和 username/secret/values;OAuth 非秘密配置在 http.oauth。删除使用 documents.delete;不再调用 source.delete 或 credentials.create。远端 Edge 凭据在本地预配,云端只使用批准的 target 绑定。
29
29
  5. Source 创建后即可供 Stream 使用,不提供启停开关。删除 Source 后停止后续使用;runtimeState 和 health 是运行观测,不是用户开关。保存配置不代表 Stream 已切换至新 configRevision。
30
30
 
31
31
  ## 返回值与异常
@@ -6,7 +6,7 @@
6
6
  | --- | --- | --- | --- |
7
7
  | id / expectedRevision | string / integer | 是 | 当前 ID 和最近写回执或读取取得的修订 |
8
8
  | action | update/delete | 是 | 精确变更类型 |
9
- | patch / document | CloudSourceDocumentPatch / CloudSourceDocument | 更新时二选一 | 与随后提交完全相同的补丁或完整文档;其他 action 不传 |
9
+ | patch / document | SourceDefinitionPatch / SourceDefinition | 更新时二选一 | 与随后提交完全相同的补丁或完整文档;其他 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' | 'patch' | 'document'>,
17
+ intent: UnsV2Request<'sourceImpact'>,
18
18
  client: Tier0Client = createClient(),
19
19
  ) {
20
20
  const first = await client.source.impact({ ...intent, offset: 0, size: 200 });
@@ -6,26 +6,27 @@
6
6
  | --- | --- | --- | --- |
7
7
  | dryRun | boolean | 否 | 默认 false 提交;true 仅预检 |
8
8
  | document.name | string | 是 | 1–63 个 Unicode 字符 |
9
- | document.protocol | string | 是 | 原生协议,如 http-api、mqtt、modbus |
10
- | document.config.role | client / server | HTTP API 显式指定 | client 主动请求;server 接收入站请求 |
11
- | document.config | object | 是 | endpoint、options;见[协议配置](protocols.md) |
9
+ | document.protocol | string | 是 | 原生协议,如 http-api、oauth2、mqtt、modbus-tcp、edge-sql |
10
+ | document.role | client / server | HTTP API 显式指定 | client 主动请求;server 接收入站请求 |
11
+ | document.endpoint | string | 是 | 无凭据的协议地址 |
12
+ | document.http/sql/mqtt/modbus | object | 按协议 | 见[协议配置](protocols.md) |
12
13
  | document.description | string | 否 | 最多 512 字符 |
13
- | credentials | object | 否 | HTTP Client 或 SQL 的只写新凭据;与已有 auth 引用互斥 |
14
+ | credentials | object | 否 | HTTP Client 或 SQL 的只写新凭据;与已有 credentialRef 引用互斥 |
14
15
  | idempotencyKey | string | 否 | 建议提供,最多 128 字符,同一业务意图保持不变 |
15
16
 
16
17
  ## 完整示例:HTTP Client 数据源
17
18
 
18
- 传入实际端点、名称和意图键。此函数创建 `http-api` + `config.role: client` 配置,创建后即可供 Stream 使用。client 从服务端环境读取 API Host/Key,也可显式注入。
19
+ 传入实际端点、名称和意图键。此函数创建 `http-api` + `role: client` 配置,创建后即可供 Stream 使用。client 从服务端环境读取 API Host/Key,也可显式注入。
19
20
 
20
21
  ```ts
21
- import { createClient, type Tier0Client, type CloudSourceDocument } from '@tier0/sdk-v2';
22
+ import { createClient, type Tier0Client, type SourceDefinition } from '@tier0/sdk-v2';
22
23
 
23
24
  export async function createHttpSource(
24
25
  endpoint: string, name: string, intentKey: string, client: Tier0Client = createClient(),
25
26
  ) {
26
- const document: CloudSourceDocument = {
27
+ const document: SourceDefinition = {
27
28
  name, protocol: 'http-api', description: '订单系统 HTTP 接入',
28
- config: { role: 'client', endpoint, options: {} },
29
+ role: 'client', endpoint, http: { anonymous: true },
29
30
  };
30
31
  const saved = await client.source.documents.create({
31
32
  dryRun: false, document, idempotencyKey: intentKey,
@@ -37,13 +38,13 @@ export async function createHttpSource(
37
38
 
38
39
  一次提交即可返回完整 data:id、revision、document、runtimeState、health、createdAt、updatedAt,无需另行 get。需要单独预检时可先传 `dryRun: true`,返回 `{ validated: true, sideEffects: false }`,没有 ID。预检不保留提交条件;实际保存仍会校验。ID 原样保留十进制字符串。
39
40
 
40
- HTTP Server 同样使用 `protocol: http-api`,角色为 `config.role: server`;其配置以 `source.protocols.list({})` 返回的正式合同为准,不能复用下方 Client 的主动请求示例。入站业务统一绑定 HTTPServer Source,路由和响应时机在 Stream 定义;202 状态不能据此报告 Stream 执行完成。
41
+ HTTP Server 同样使用 `protocol: http-api`,角色为 `role: server`;其配置以 `source.protocols.list({})` 返回的正式合同为准,不能复用下方 Client 的主动请求示例。入站业务统一绑定 HTTPServer Source,路由和响应时机在 Stream 定义;202 状态不能据此报告 Stream 执行完成。
41
42
 
42
43
  ## HTTP Client Bearer 凭据
43
44
 
44
45
  Source 保存 API 基址和认证;实际请求的 method/path/query 由 Stream 设置。例如 endpoint 使用 `https://inventory.example.com/api/v1`,再由 [Stream 示例](../../tier0-sdk-v2-stream/references/create.md)请求 `GET inventory`。token 从服务端密钥提供者取得,不写入脚本、文档、日志或仓库。
45
46
 
46
- 普通创建省略 `credentials.method`,服务端按 `REQUEST` 绑定 Source 基址。REQUEST 是凭据适用范围标记,不是发送给上游的 HTTP 方法;实际 GET 请求仍由执行宿主逐次授权。
47
+ 凭据使用 `{kind:"bearer",secret:token}`;不再使用 material 或 method。认证类型在 document.http.authentication 声明,实际 HTTP method/path/query 仍在 Stream 中设置。
47
48
 
48
49
  ```ts
49
50
  import { createClient, type Tier0Client } from '@tier0/sdk-v2';
@@ -54,8 +55,8 @@ export async function createAuthenticatedHttpSource(
54
55
  ) {
55
56
  const saved = await client.source.documents.create({
56
57
  dryRun: false, idempotencyKey: intentKey,
57
- document: { name, protocol: 'http-api', config: { role: 'client', endpoint, options: {} } },
58
- credentials: { kind: 'bearer', material: { token } },
58
+ document: { name, protocol: 'http-api', role: 'client', endpoint, http: { authentication: 'bearer' } },
59
+ credentials: { kind: 'bearer', secret: token },
59
60
  });
60
61
  if (!('id' in saved.data)) throw new Error('未返回 Source ID');
61
62
  return { receipt: saved, current: saved.data };
@@ -66,17 +67,17 @@ export async function createAuthenticatedHttpSource(
66
67
 
67
68
  ## HTTP Server:管理配置
68
69
 
69
- 正式协议目录规定 Server 的 `config.endpoint` 为 `http://managed`、`options` 为 `{}`,不携带 Client 的 `auth` / `tls` 或创建专用 `credentials`。该函数只保存 Source,不创建 Stream,也不发起入站请求。
70
+ 正式协议目录规定 Server 的 `endpoint` 为 `http://managed`,不携带 Client 认证 或创建专用 `credentials`。该函数只保存 Source,不创建 Stream,也不发起入站请求。
70
71
 
71
72
  ```ts
72
- import { createClient, type Tier0Client, type CloudSourceDocument } from '@tier0/sdk-v2';
73
+ import { createClient, type Tier0Client, type SourceDefinition } from '@tier0/sdk-v2';
73
74
 
74
75
  export async function createHttpServerSource(
75
76
  name: string, intentKey: string, client: Tier0Client = createClient(),
76
77
  ) {
77
- const document: CloudSourceDocument = {
78
+ const document: SourceDefinition = {
78
79
  name, protocol: 'http-api',
79
- config: { role: 'server', endpoint: 'http://managed', options: {} },
80
+ role: 'server', endpoint: 'http://managed',
80
81
  };
81
82
  const saved = await client.source.documents.create({
82
83
  dryRun: false, document, idempotencyKey: intentKey,
@@ -88,33 +89,20 @@ export async function createHttpServerSource(
88
89
 
89
90
  Server 的固定前缀 `/ingest/v1/{workspaceId}/{sourceId}` 和 Bearer 要求由协议目录的 `x-tier0-http-in` 描述。Source 不接受业务路径配置;在 [Stream HTTPServer 示例](../../tier0-sdk-v2-stream/references/http-server.md)中注册 `onRequest` 的 method/path。响应时机属于 Stream。
90
91
 
91
- ## 四类 inline 认证与 REQUEST 绑定
92
+ ## 原生只写凭据
92
93
 
93
- HTTP Client 单条创建可通过 `credentials` 提供以下只写材料;与已有 auth 引用互斥,HTTP/SQL 当前不支持 TLS 凭据引用,并要求本次创建的 `idempotencyKey`。材料从调用方已授权的密钥提供者注入,不在示例中读取文件或环境中的秘密,不记录或返回材料。
94
-
95
- | kind | material | method |
96
- | --- | --- | --- |
97
- | basic | username、password | 省略时 REQUEST;显式方法绑定精确 URL 和该方法 |
98
- | bearer | token | 省略时 REQUEST;显式方法绑定精确 URL 和该方法 |
99
- | apiKey | headerName、value | 省略或 REQUEST |
100
- | oauth2ClientCredentials | tokenUrl、clientId、clientSecret;可选 scope、clientAuthentication | 普通创建省略;旧 GET 保留既有兼容语义 |
101
-
102
- Basic/Bearer 显式 `credentials.method: 'GET'` 表示凭据只用于所绑定精确 URL 的 GET,不表示该基址下所有 GET 都可使用:绑定 `/api/v1` 不授权 `/api/v1/inventory?limit=5000`。仅在任务明确需要该限制时传入;已有绑定保持原限制,不自动迁移或在拒绝后回退 REQUEST。
103
-
104
- OAuth 的 `clientAuthentication` 支持 `client_secret_post`(默认)和 `client_secret_basic`;method 接受省略、REQUEST 或旧 GET,旧 GET 保留现有兼容语义,不能把 Basic/Bearer 的精确 URL 规则跨认证类型套用。普通创建仍省略 method。vendor SESSION 合同独立保留,不是此 inline 创建的 method,也不新增独立公开凭据 API。
94
+ Cloud 与 Enterprise 使用相同 SourceDefinition / SourceCredentials。HTTP Basic 为 `{kind:'basic',username,secret}`,Bearer 为 `{kind:'bearer',secret}`,OAuth 为 `{kind:'oauth2',secret}`;OAuth 的 tokenUrl/clientId/grantType/clientAuthentication 留在 document.http.oauth,Source protocol 使用 oauth2。custom 使用 values 字符串映射,键名按目标协议目录声明,不凭空推测。创建凭据需要 idempotencyKey 与凭据管理权限,不能把秘密写入 endpoint、脚本或日志。
105
95
 
106
96
  ```ts
107
- import { createClient, type Tier0Client, type CloudSourceCreateCredentials } from '@tier0/sdk-v2';
97
+ import { createClient, type Tier0Client, type SourceCredentials, type SourceDefinition } from '@tier0/sdk-v2';
108
98
 
109
99
  export async function createHttpSourceWithCredentials(
110
- endpoint: string, name: string, credentials: CloudSourceCreateCredentials, intentKey: string,
100
+ document: SourceDefinition, credentials: SourceCredentials, intentKey: string,
111
101
  client: Tier0Client = createClient(),
112
102
  ) {
113
103
  const saved = await client.source.documents.create({
114
104
  dryRun: false, idempotencyKey: intentKey,
115
- document: { name, protocol: 'http-api',
116
- config: { role: 'client', endpoint, options: {} } },
117
- credentials,
105
+ document, credentials,
118
106
  });
119
107
  if (!('id' in saved.data)) throw new Error('未返回已保存的 Source');
120
108
  return { receipt: saved, current: saved.data };
@@ -123,6 +111,8 @@ export async function createHttpSourceWithCredentials(
123
111
 
124
112
  ## SQL 用户名和密码
125
113
 
126
- SQL 单条创建可直接传入 `credentials: { kind: "usernamePassword", material: { username, password } }`,不再预先调用独立凭据接口。`document.protocol` 为 `sql`,`config.endpoint` 只包含数据库地址(不包含用户名或密码),`credentials.method` 必须省略。仍需 `idempotencyKey`。秘密由 Vault 保存,Source 文档仅含引用;预检不写入凭据。
114
+ SQL 使用 protocol=edge-sql、顶层 endpoint 和 sql(固定命名查询)。凭据为 `{kind:'basic',username,secret}`,不传 method/material。查询和 TLS 选项以目标协议目录为准,不允许脚本传任意 SQL。
115
+
116
+ 已有 Source 换证使用 `source.documents.credentials.update({id,expectedRevision,credentials,dryRun:false,idempotencyKey})`,路由 `/openapi/v2/uns/sources/documents/credentials/update`,不再调用独立 credentials.create。远端 Edge 秘密须在目标 Edge 本地预配;云绑定只使用已批准的 target,不经云转发 Edge 秘密。
127
117
 
128
- `dryRun` 省略时直接提交;需要预检才设为 true。后续绑定 Source 并部署 Stream,并通过运行记录和 Collection 读回确认采集成功。
118
+ dryRun 省略时直接提交。创建或换证成功不等于采集成功;仍须检查 Stream 运行与 Collection 数据。
@@ -1,19 +1,10 @@
1
1
  # 删除 Source
2
2
 
3
- 方法:`source.delete`;POST `/openapi/v2/uns/sources/delete`。
3
+ 方法:`source.documents.delete`;POST `/openapi/v2/uns/sources/documents/delete`。
4
4
 
5
- | 字段 | 类型 | 必填 | 说明 |
6
- | --- | --- | --- | --- |
7
- | dryRun | boolean | 是 | true 预检;false 提交 |
8
- | items | array | 是 | 1–200 项 |
9
- | items[].id | string | 是 | 正十进制 int64 字符串 |
10
- | items[].expectedRevision | integer | 是 | 已知的当前修订 |
11
- | items[].confirmedImpactRevision | string | 有引用时 | action=delete 的影响回执 |
12
- | mode | auto/sync | 否 | 不支持 async |
13
- | allowPartial | false | 否 | 不支持部分提交 |
14
- | idempotencyKey | string | 否 | 最多 128 字符 |
5
+ 传入单个 id、当前 expectedRevision、可选 dryRun(默认 false)与本次意图的 idempotencyKey。Source 本身必须先变为 disabled,仅停 Stream 不够。创建默认 enabled:先按[影响分析](changes.md)评估 action=disable,再调用 documents.state.update({id,expectedRevision,desiredState:'disabled',dryRun:false,...});取得新 revision 后重新评估 action=delete。每一步只使用对应意图的 confirmedImpactRevision,不能复用 disable 的确认值删除。无依赖时可省确认值,不自动同意依赖影响。此接口不接受旧批量 items。
15
6
 
16
- Source 可直接删除,无需先停用;删除后停止后续采集和入站接入。没有任何 Stream 引用时,直接用已有 ID 和 revision 提交;有引用时先 impact(action=delete) 并[遍历和评估影响](changes.md),再显式传入回执。服务端在同一事务中检查依赖和修订,不自动删除或停用依赖流。
7
+ 下方函数要求调用方已完成 Source 禁用,并提供最新 revision 与删除影响确认。
17
8
 
18
9
  ```ts
19
10
  import { createClient, type Tier0Client, type UnsV2Request } from '@tier0/sdk-v2';
@@ -22,18 +13,13 @@ export async function deleteSource(
22
13
  id: string, expectedRevision: UnsV2Request<'sourceImpact'>['expectedRevision'],
23
14
  intentKey: string, client: Tier0Client = createClient(), confirmedImpactRevision?: string,
24
15
  ) {
25
- const receipt = await client.source.delete({
26
- dryRun: false, mode: 'sync', allowPartial: false, idempotencyKey: intentKey,
27
- items: [{ id, expectedRevision,
28
- ...(confirmedImpactRevision === undefined ? {} : { confirmedImpactRevision }) }],
16
+ const receipt = await client.source.documents.delete({
17
+ id, expectedRevision, dryRun: false, idempotencyKey: intentKey,
18
+ ...(confirmedImpactRevision === undefined ? {} : { confirmedImpactRevision }),
29
19
  });
30
- if (receipt.data.status !== 'committed' || receipt.data.results?.some(item => item.error)) {
31
- return { state: 'unconfirmed' as const, receipt };
32
- }
33
- const archived = receipt.data.results?.find(item => item.id === id && item.status === 'deleted');
34
- if (!archived) return { state: 'unconfirmed' as const, receipt };
35
- return { state: 'archived' as const, receipt, archived };
20
+ if (receipt.data.id !== id) return { state: 'unconfirmed' as const, receipt };
21
+ return { state: 'archived' as const, receipt, archived: receipt.data };
36
22
  }
37
23
  ```
38
24
 
39
- 返回 Outcome,HTTP 200/validated/accepted 不等于完成。已提交回执中对应 ID 的 deleted 结果足以确认归档,无需遍历归档列表;不能把任意 get 异常当成成功。传输结果未知时保留原请求、requestId 和意图键,不自动重试。补充确认回执是新请求,应使用新幂等键。
25
+ 提交返回 {id};预检不删除。结果未知时先对账,保留原请求、requestId 和意图键,不自动重试;不能把任意 get 错误当成删除成功。
@@ -1,42 +1,25 @@
1
1
  # 协议与连接配置
2
2
 
3
- 先调用 `source.protocols.list({})`。协议枚举存在不等于目标环境驱动或凭据解析器已就绪。HTTP Source 统一使用 `protocol: 'http-api'`,通过文档的 `config.role: 'client' | 'server'` 区分主动请求和入站服务,与 Enterprise 的一协议两角色模型一致。角色和协议能力以目标环境目录为准。
4
-
5
- | 配置字段 | 类型 | 必填 | 说明 |
6
- | --- | --- | --- | --- |
7
- | role | client / server | HTTP 示例显式指定 | 省略时为 client;Server 使用托管地址和空 options |
8
- | endpoint | string | 是 | 地址,不内嵌凭据 |
9
- | options | object | 是 | 协议专用选项 |
10
- | auth.kind | string | 有认证时 | basic/bearer/apiKey/usernamePassword/oauth2ClientCredentials |
11
- | auth.credentialRef | string | 有认证时 | 已存在且可用的凭据引用 |
12
- | tls.caRef / clientIdentityRef | string | 否 | 已存在的 CA/客户端身份引用 |
13
-
14
- 以下只构造文档,不执行创建;实际地址、主题、设备 unitId 由任务上下文提供。需要预览配置问题时使用 documents.create 的 dryRun;正式创建本身执行校验。
3
+ 先调用 source.protocols.list({}) 核对目标能力。Cloud / Enterprise 统一使用 SourceDefinition:顶层 role、endpoint、runtimeLocation,以及协议专属 http/sql/mqtt/modbus 等。没有旧 config/options/auth/material 层。HTTP 使用 http-api,OAuth 使用 oauth2,SQL 使用 edge-sql,Modbus TCP 使用 modbus-tcp。角色默认 client;server 使用目标支持的托管 endpoint。
15
4
 
16
5
  ```ts
17
- import { createClient, type CloudSourceDocument } from '@tier0/sdk-v2';
6
+ import { createClient, type SourceDefinition } from '@tier0/sdk-v2';
18
7
 
19
8
  export async function inspectProtocolExamples() {
20
9
  const capabilities = await createClient().source.protocols.list({});
21
- const examples: CloudSourceDocument[] = [
22
- { name: 'orders-http', protocol: 'http-api',
23
- config: { role: 'client', endpoint: 'https://orders.example.com', options: {} } },
24
- { name: 'line-plc', protocol: 'modbus',
25
- config: { endpoint: 'tcp://plc.example.com:502', options: { unitId: 1 } } },
26
- { name: 'line-mqtt', protocol: 'mqtt',
27
- config: { endpoint: 'mqtt://broker.example.com:1883',
28
- options: { clientId: 'tier0-line-reader', subscriptions: { 'factory/line1/status': 1 } } } },
10
+ const examples: SourceDefinition[] = [
11
+ { name: 'orders-http', protocol: 'http-api', role: 'client',
12
+ endpoint: 'https://orders.example.com', http: { anonymous: true } },
13
+ { name: 'line-plc', protocol: 'modbus-tcp', role: 'client',
14
+ endpoint: 'tcp://plc.example.com:502', modbus: { unitId: 1 } },
15
+ { name: 'line-mqtt', protocol: 'mqtt', role: 'client',
16
+ endpoint: 'mqtt://broker.example.com:1883',
17
+ mqtt: { clientId: 'tier0-line-reader', subscriptions: { 'factory/line1/status': 1 } } },
29
18
  ];
30
19
  return { capabilities: capabilities.data, examples };
31
20
  }
32
21
  ```
33
22
 
34
- HTTP Client 的 options 支持 headers 和 parameters;headers 可包含目录允许的非秘密自定义头,Accept/Content-Type 保留 MIME 校验,认证及传输头保留给服务端,不能塞 Authorization/Cookie。Modbus 寄存器范围和轮询频率在 Stream acquisition 中定义;MQTT QoS 为 0/1/2。认证创建见[创建](create.md),修改时保留原 auth/tls 引用。
35
-
36
- SQL options 包含 tlsMode(verify-full/disable)和 queries(资源名→固定 SQL);脚本不能替换任意 SQL。OPC UA、SAP、Teamcenter 等按能力和服务端校验配置,不从 HTTP 模板生造字段。不要为通过校验自动移除认证或关闭 TLS。
37
-
38
- HTTP Client 示例不能用于 Server。HTTPServer 通过 `source.documents.*` 配置监听源,固定前缀为 `/ingest/v1/{workspaceId}/{sourceId}`;Stream 注册相对业务路由和处理函数,见 [HTTPServer Stream](../../tier0-sdk-v2-stream/references/http-server.md)。响应时机在 Stream 层处理。
39
-
40
- Cloud 的角色位于 `config.role`;Enterprise 投影的顶层 `role` 不能直接抄入 Cloud 管理文档。Server 配置见[创建](create.md),以 `http://managed` 和空 options 保存,不从 Client 模板推导。
23
+ http.headers 仅放非秘密业务头,不能塞 Authorization/Cookie;http.parameters 保存命名厂商配置。sql.query 或 sql.queries 选择固定声明查询,不在脚本执行任意 SQL。TLS 公共 CA 使用协议 caCertificate;秘密密钥经 credentials.values 本地预配,已有引用使用 credentialRef。extensions.tls 引用只有目标明确支持时可用,不自动关闭 TLS。
41
24
 
42
- HTTP Client 的单条 inline 认证支持 basic / bearer / apiKey / oauth2ClientCredentials。普通创建省略 credentials.method,由服务端按 REQUEST 绑定 Source 基址;实际 method/path/query 在 Stream 设置。Basic/Bearer 显式凭据方法同时限制精确 URL,不覆盖基址下的子路径;存量绑定保持限制,不自动扩大权限。APIKey 材料为 headerName/value,OAuth 可提供 clientAuthentication,旧 OAuth GET 保留既有兼容语义。见[创建](create.md)。
25
+ 以上仅构造配置,不创建 Source。HTTP Server 使用 http://managed,业务路由在 Stream 注册,见[HTTPServer](../../tier0-sdk-v2-stream/references/http-server.md)。配置与凭据创建见[创建](create.md)。
@@ -23,12 +23,11 @@ export async function* listSources(client: Tier0Client = createClient()) {
23
23
  }
24
24
  }
25
25
  export async function readSource(id: string, client: Tier0Client = createClient()) {
26
- const current = await client.source.documents.get({ id });
27
- const observation = await client.source.observations.get({
28
- items: [{ id, expectedRevision: current.data.revision }],
29
- });
30
- return { current: current.data, observation: observation.data };
26
+ const current = await client.source.documents.get({ id, view: 'summary' });
27
+ return { current: current.data };
31
28
  }
32
29
  ```
33
30
 
31
+ 查询摘要只需一次请求。需要完整配置时显式使用 `documents.get({ id, view: 'full' })`;需要运行观测时使用已有摘要或写回执的 `id/revision` 调用 `observations.get({ items: [{ id, expectedRevision: revision }] })`,无需再次读取详情。
32
+
34
33
  ID 不得转 Number;跨页不是稳定快照。权限错误、网络故障与不存在应分别处理,不能把任何 get 失败当成删除成功。probe 可能触达外部系统,不属于单纯读取。
@@ -5,7 +5,7 @@
5
5
  | 字段 | 类型 | 必填 | 说明 |
6
6
  | --- | --- | --- | --- |
7
7
  | id | string | 是 | 已知的 Source ID |
8
- | patch / document | object / CloudSourceDocument | 二选一 | patch 保留未提供的字段;document 完整替换 |
8
+ | patch / document | object / SourceDefinition | 二选一 | patch 保留未提供的字段;document 完整替换 |
9
9
  | expectedRevision | integer | 是 | 已读取或上次提交返回的 revision,原样传回 |
10
10
  | confirmedImpactRevision | string | 有引用的连接变更时 | 相同修改意图和修订的 impact 回执;仅改名称、描述无需提供 |
11
11
  | dryRun | boolean | 否 | 默认 false 提交;true 仅预检 |
@@ -13,7 +13,7 @@
13
13
 
14
14
  ## 示例:一次请求修改名称
15
15
 
16
- 已有 ID 和 revision 时直接提交 patch。仅改名称、描述无需 impact;连接配置变更在没有任何草稿、活动或历史 Stream 引用时也无需 impact。服务端在同一事务和依赖锁下检查并修改。patch 中未提供的字段保留原值,config 如果提供则整体替换;完整 document 更新需先取得完整文档并保留未改配置和认证引用。
16
+ 已有 ID 和 revision 时直接提交 patch。仅改名称、描述无需 impact;连接配置变更在没有任何草稿、活动或历史 Stream 引用时也无需 impact。服务端在同一事务和依赖锁下检查并修改。patch 中未提供的字段保留原值,协议子对象如果提供则整体替换;完整 document 更新需先取得完整文档并保留未改配置和认证引用。
17
17
 
18
18
  ```ts
19
19
  import { createClient, type Tier0Client, type UnsV2Request } from '@tier0/sdk-v2';
@@ -37,14 +37,14 @@ export async function renameSource(
37
37
  prepare 收集全部影响分页。在已有授权范围内评估 counts、restrictedCount 和引用后,再调用 commit。不可见引用也要求确认。影响字段说明见[影响分析](changes.md)。
38
38
 
39
39
  ```ts
40
- import { createClient, type Tier0Client, type UnsV2Request, type CloudSourceDocument } from '@tier0/sdk-v2';
40
+ import { createClient, type Tier0Client, type UnsV2Request, type SourceDefinitionPatch } from '@tier0/sdk-v2';
41
41
 
42
42
  export async function prepareSourceConfigUpdate(
43
43
  id: string, expectedRevision: UnsV2Request<'sourceImpact'>['expectedRevision'],
44
- config: CloudSourceDocument['config'], client: Tier0Client = createClient(),
44
+ patch: SourceDefinitionPatch, client: Tier0Client = createClient(),
45
45
  ) {
46
46
  const intent: UnsV2Request<'sourceImpact'> = {
47
- id, expectedRevision, action: 'update', patch: { config },
47
+ id, expectedRevision, action: 'update', patch,
48
48
  };
49
49
  const impact = await client.source.impact({ ...intent, offset: 0, size: 200 });
50
50
  const references = [...impact.data.references];
@@ -5,7 +5,7 @@ description: 使用 @tier0/sdk-v2 的 client.stream 创建、查询、修改和
5
5
 
6
6
  # Stream 处理与运行
7
7
 
8
- 应用代码使用 client.stream;外部连接用 [Source](../tier0-sdk-v2-source/SKILL.md),集合和记录用 [UNS](../tier0-sdk-v2-uns/SKILL.md)。服务端 `createClient()` 读取 TIER0_API_HOST / TIER0_API_KEY,也可显式传 apiHost/apiKey。
8
+ 应用代码使用 client.stream;外部连接用 [Source](../tier0-sdk-v2-source/SKILL.md),集合和记录用 [UNS](../tier0-sdk-v2-uns/SKILL.md)。服务端 `createClient()` 读 TIER0_API_HOST / TIER0_API_KEY(平台里由平台注入 App 的 Key),也可显式传 apiHost/apiKey。Tier0 App 的 Key 无权调 Stream 管理接口(Backend 回 403)。
9
9
 
10
10
  ## 按任务加载参考
11
11
 
@@ -23,7 +23,7 @@ description: 使用 @tier0/sdk-v2 的 client.stream 创建、查询、修改和
23
23
 
24
24
  | 形态 | 完整输入 | 适用入口 |
25
25
  | --- | --- | --- |
26
- | Runtime program | name、script 字符串、sourceBindings、timeoutMs | documents.create/update/validate({program}) |
26
+ | Runtime program | name、script {code,timeoutMs}、sourceBindings | documents.create/update/validate({program}) |
27
27
  | 云端原生文档 | name、model、script 对象、sources、entries | documents.create/get/update/validate |
28
28
 
29
29
  程序必须是完整 `module.exports = api => { ... }`,执行器 API 是 api.sources/api.uns/api.stream,与 npm 包的 client.source 不同。Runtime sourceBindings 为 sourceId/configRevision/acquisition;原生 sources 还使用 alias/resources。连接凭据不进脚本或 acquisition,秘密材料由 Source 执行宿主管理,不通过脚本读取、记录或返回。定时入口使用 api.stream.every,不传播旧注册别名;App 请求与消息交互由本包 @tier0/sdk-v2 的 client.streams.requests/messages 提供,不作为 Goja 注册参数。
@@ -32,7 +32,7 @@ description: 使用 @tier0/sdk-v2 的 client.stream 创建、查询、修改和
32
32
 
33
33
  1. documents.get({id,view:"summary"}) 返回安全摘要,不含可回写脚本;完整编辑使用 documents.get 或上次 documents.create/update 返回的完整文档。保留未修改的 sources/entries/script 字段。
34
34
  2. create/update 保存草稿,不自动发布;documents 没有 deploy,云端 program 发布使用 programs.deploy。不能将已保存报告为已运行。
35
- 3. 所有更新/部署/删除携带当前 expectedRevision。原生停用另需 expectedActiveRelease,避免停掉他人刚发布的版本。
35
+ 3. 所有更新/部署/删除携带当前 expectedRevision。发布/停用/回滚使用权威 activeVersion 字符串作为 expectedActiveVersion,避免停掉他人刚发布的版本。
36
36
  4. versionId 使用已知发布回执的 activeVersion,或从 versions.list 选定,不把 release 序号当 ID。expectedSourceRevision 仅用于恰好一个依赖源,不代表多个源的修订。
37
37
  5. resources=[] 是空冻结资源集,不是通配符。写入本身由服务端校验,需要预览时单独 validate;当前云端程序 timeoutMs 上限 30000。
38
38
  6. HTTPServer 响应时机在 Stream:普通返回等处理/提交完成;HTTP onRequest 内 await ctx.reply 可先回复一次再继续,仍受超时/并发/权限约束,断线不取消但 shutdown 可取消,不保证崩溃重放。
@@ -6,14 +6,14 @@
6
6
  | --- | --- | --- | --- |
7
7
  | dryRun | boolean | 否 | 默认 false 提交;true 仅预检 |
8
8
  | program.name | string | 是 | 1–63 字符 |
9
- | program.script | string | 是 | 完整 module.exports 程序 |
10
- | program.timeoutMs | integer | 否 | 当前云端上限 30000 ms |
9
+ | program.script | object | 是 | code 为完整 module.exports 程序,timeoutMs 为超时 |
10
+ | program.script.timeoutMs | integer | 是 | 当前云端上限 30000 ms |
11
11
  | program.sourceBindings | array | 否 | sourceId、configRevision、acquisition |
12
12
  | idempotencyKey | string | 否 | 最多 128 字符,本次创建的固定意图键 |
13
13
 
14
14
  ## HTTP Client Source 绑定示例
15
15
 
16
- 先按[Source 查询](../../tier0-sdk-v2-source/references/read.md)选定真实 HTTP Client Source。脚本的 api.sources 属于平台执行器,与应用中的 client.source 不同。sourceId 保持字符串,configRevision 使用 Source 创建、更新回执或完整查询得到的修订。已有回执时直接传入 source;没有快照时再调用 source.documents.get({id,view:"full"}) 并检查 data.document。省略 `config.role` 时按正式协议目录默认为 client;Server 走入站语义,不能创建为主动请求程序。
16
+ 先按[Source 查询](../../tier0-sdk-v2-source/references/read.md)选定真实 HTTP Client Source。脚本的 api.sources 属于平台执行器,与应用中的 client.source 不同。sourceId 保持字符串,configRevision 使用 Source 创建、更新回执或完整查询得到的修订。已有回执时直接传入 source;没有快照时再调用 source.documents.get({id,view:"full"}) 并检查 data.document。省略 `role` 时按正式协议目录默认为 client;Server 走入站语义,不能创建为主动请求程序。
17
17
 
18
18
  Source 负责基址和认证,Stream 负责请求的 method/path/query。以下示例与 [Source Bearer 创建](../../tier0-sdk-v2-source/references/create.md#http-client-bearer-凭据)配合:Source endpoint 为 `https://inventory.example.com/api/v1`,凭据使用默认基址绑定;实际请求是 `GET https://inventory.example.com/api/v1/inventory?limit=5000`。已有 Source 的凭据若只绑定精确 URL `/api/v1` 的 GET,不能用于此子路径;不要通过改写请求为 REQUEST 或自动扩大凭据授权来绕过拒绝。
19
19
 
@@ -26,14 +26,14 @@ export async function createHttpStream(
26
26
  if (!collectionId.trim()) throw new Error('需要实际 Collection ID');
27
27
  const sourceId = source.id;
28
28
  if (!/^[1-9][0-9]*$/.test(sourceId)) throw new Error('Source ID 必须是正十进制字符串');
29
- if (source.document.protocol !== 'http-api' || 'sourceType' in source.document.config ||
30
- (source.document.config.role ?? 'client') !== 'client') {
29
+ if (source.document.protocol !== 'http-api' || 'sourceType' in source.document ||
30
+ (source.document.role ?? 'client') !== 'client') {
31
31
  throw new Error('此主动请求示例需要 HTTP API Client Source');
32
32
  }
33
33
  const document: RuntimeStreamDefinition = {
34
- name, timeoutMs: 5000,
34
+ name,
35
35
  sourceBindings: [{ sourceId, configRevision: source.revision, acquisition: {} }],
36
- script: [
36
+ script: { timeoutMs: 5000, code: [
37
37
  'module.exports = api => {',
38
38
  ' const upstream = api.sources.use({ id: ' + JSON.stringify(sourceId) + ', resources: [] });',
39
39
  ' const output = api.uns.use({ collectionId: ' + JSON.stringify(collectionId) + ', access: "write" });',
@@ -49,7 +49,7 @@ export async function createHttpStream(
49
49
  ' return { acceptedRows: records.length };',
50
50
  ' });',
51
51
  '};',
52
- ].join('\n'),
52
+ ].join('\n') },
53
53
  };
54
54
  const saved = await client.stream.documents.create({
55
55
  dryRun: false, program: document, idempotencyKey: intentKey,
@@ -73,4 +73,18 @@ validate 检查配置、程序和可确定的绑定问题,不执行任意业
73
73
 
74
74
  创建结局未知时先按已知 ID 或业务标识核对状态;允许重试时保留原请求与幂等键。
75
75
 
76
- 原生编辑器形态 `documents.create({dryRun, document})` 的 document 为 name/model/script对象/sources/entries,script 为 `{code,timeoutMs}`,sources 用 alias/sourceId/configRevision/resources/acquisition。不要把上面的 script 字符串直接塞入原生文档。
76
+ 原生编辑器形态 `documents.create({dryRun, document})` 的 document 为 name/model/script对象/sources/entries,script 为 `{code,timeoutMs}`,sources 用 alias/sourceId/configRevision/resources/acquisition。两种入口均使用 script 对象;不接受 script 字符串。
77
+
78
+ 远端 Edge 绑定使用 `target: {fleetNodeId, sourceId, configRevision}` 替代同一绑定上的 sourceId/configRevision。fleetNodeId 是发现返回的复合节点字符串,sourceId 是该节点上的原生十进制 ID。服务端验证并创建引用,调用方不拼装 edge:// 引用,也不创建另一种 Source 文档。
79
+
80
+ ```ts
81
+ import type { RuntimeStreamDefinition, StreamSourceTarget } from '@tier0/sdk-v2';
82
+
83
+ export function bindApprovedEdgeSource(
84
+ program: RuntimeStreamDefinition, target: StreamSourceTarget,
85
+ ): RuntimeStreamDefinition {
86
+ return { ...program, sourceBindings: [{ target, acquisition: {} }] };
87
+ }
88
+ ```
89
+
90
+ 该函数只构造绑定;脚本仍须使用声明资源并通过目标目录授权。厂商凭据在 Edge 本地预配,target 不携带秘密。配置成功不证明端到端采集完成。
@@ -4,18 +4,18 @@
4
4
  | --- | --- | --- |
5
5
  | programs.deploy | /openapi/v2/uns/streams/program/deploy | id;dryRun 默认 false,建议 expectedRevision 和发布状态守卫 |
6
6
  | programs.rollback | /openapi/v2/uns/streams/program/rollback | id、versionId、dryRun;建议 expectedRevision 和发布状态守卫 |
7
- | documents.disable | /openapi/v2/uns/streams/documents/disable | id、expectedRevision、expectedActiveRelease、dryRun |
7
+ | documents.disable | /openapi/v2/uns/streams/documents/disable | id、expectedRevision、expectedActiveVersion、dryRun |
8
8
 
9
9
  全部写操作使用各自的 idempotencyKey。expectedSourceRevision 只适用于恰好一个 Source 依赖,且同时保护草稿冻结修订与当前 Source head;多源不能塞入单个修订值。原生文档没有 documents.deploy,当前云端 program 模型发布走 programs.deploy。
10
10
 
11
- 发布和回滚有可选并发守卫:有生效发布时传入正整数 `expectedActiveRelease`;没有生效发布时传入 `expectedReleaseState: 'inactive'`,两者不能同时使用。服务端在事务内比较当前状态,变化时返回版本冲突;重新读取并决策后才能使用新的业务意图。守卫比较当前值,不记录中间发生的全部切换。
11
+ 发布、停用和回滚使用 `expectedActiveVersion` 并发守卫:传服务端回执的十进制字符串 activeVersion,'0' 表示无生效发布。它是不可推算的发布 ID,不是 activeRelease 序号;不再传 expectedReleaseState。服务端在事务内比较当前状态,变化时返回版本冲突;重新读取并决策后才能使用新的业务意图。守卫比较当前值,不记录中间发生的全部切换。
12
12
 
13
13
  发布、停用和回滚需要 uns.stream.manage;相关 Source 访问还受各自授权约束。保存回执中的 revision、发布回执中的 activeVersion 与 activeRelease 分别用于不同目的:
14
14
 
15
15
  | 字段 | 含义与用途 |
16
16
  | --- | --- |
17
17
  | revision | 草稿修订;传给下次写入的 expectedRevision,冲突时显式处理 |
18
- | activeVersion | 不可变发布版本 ID;回滚的 versionId 使用这个 ID,不使用发布序号 |
18
+ | activeVersion | 十进制字符串形式的不可变发布 ID;用于 expectedActiveVersion 与回滚 versionId,不由 activeRelease 序号推算 |
19
19
  | activeRelease | 本次事务记录的正整数发布序号;与 runs.list 中的 release 对照;无活跃发布或回执未记录时省略 |
20
20
 
21
21
  programs 回执的 activeVersion:'0' 表示无活跃版本;programs 的 activeRelease 此时省略;documents 的 activeRelease 此时为 0。
@@ -24,11 +24,12 @@ programs 回执的 activeVersion:'0' 表示无活跃版本;programs 的 active
24
24
  import { createClient, type Tier0Client, type CloudStreamDocumentView, type CloudStreamStopView } from '@tier0/sdk-v2';
25
25
 
26
26
  export async function deployStream(current: CloudStreamDocumentView, intentKey: string, client: Tier0Client = createClient()) {
27
+ if (typeof current.activeVersion !== 'string' || !/^(0|[1-9][0-9]*)$/.test(current.activeVersion)) throw new Error('缺少权威 activeVersion;读取当前文档后再决定');
27
28
  const sources = current.document.sources ?? [];
28
29
  const request = {
29
30
  id: current.id, expectedRevision: current.revision,
30
- ...(String(current.activeRelease) === '0' ? { expectedReleaseState: 'inactive' as const } : { expectedActiveRelease: current.activeRelease }),
31
- ...(sources.length === 1 ? { expectedSourceRevision: sources[0]!.configRevision } : {}),
31
+ expectedActiveVersion: current.activeVersion,
32
+ ...(sources.length === 1 && !sources[0]!.target ? { expectedSourceRevision: sources[0]!.configRevision } : {}),
32
33
  };
33
34
  const receipt = await client.stream.programs.deploy({
34
35
  ...request, dryRun: false, idempotencyKey: intentKey,
@@ -44,22 +45,22 @@ export async function deployStream(current: CloudStreamDocumentView, intentKey:
44
45
  }
45
46
 
46
47
  export async function disableStream(
47
- current: Pick<CloudStreamStopView, 'id' | 'revision' | 'activeRelease'>,
48
+ current: Pick<CloudStreamStopView, 'id' | 'revision' | 'activeVersion'>,
48
49
  intentKey: string, client: Tier0Client = createClient(),
49
50
  ) {
50
- if (BigInt(String(current.activeRelease)) <= 0n) throw new Error('没有活跃发布可停用');
51
+ if (typeof current.activeVersion !== 'string' || !/^[1-9][0-9]*$/.test(current.activeVersion)) throw new Error('没有已确认的活跃版本可停用');
51
52
  const receipt = await client.stream.documents.disable({
52
- id: current.id, expectedRevision: current.revision, expectedActiveRelease: current.activeRelease,
53
+ id: current.id, expectedRevision: current.revision, expectedActiveVersion: current.activeVersion,
53
54
  dryRun: false, idempotencyKey: intentKey,
54
55
  });
55
- if (!('id' in receipt.data) || String(receipt.data.activeRelease) !== '0') {
56
+ if (!('id' in receipt.data) || receipt.data.activeVersion !== '0') {
56
57
  throw new Error('未返回停用回执');
57
58
  }
58
59
  return { receipt, current: receipt.data };
59
60
  }
60
61
  ```
61
62
 
62
- 将创建或更新回执的 current 传给 deployStream,只发一次发布请求。只有手上没有草稿快照时才先 documents.get。使用 [按发布号查询运行记录](read.md#观察本次发布) 才能观察这次发布,观察窗口汇总不能证明该版本运行。发布成功不表示外部连接健康或执行成功。停用使用已确认的 id/revision/activeRelease(可来自发布回执),返回的 current 可直接用于删除;不需要前后各 get。停用保留草稿。仅修改草稿的任务不额外发布/停用。
63
+ 将创建或更新回执的 current 传给 deployStream,只发一次发布请求。只有手上没有草稿快照时才先 documents.get。使用 [按发布号查询运行记录](read.md#观察本次发布) 才能观察这次发布,观察窗口汇总不能证明该版本运行。发布成功不表示外部连接健康或执行成功。停用使用已确认的 id/revision/activeVersion(可来自发布回执),返回的 current 可直接用于删除;不需要前后各 get。停用保留草稿。仅修改草稿的任务不额外发布/停用。
63
64
 
64
65
  ## 回滚到明确版本
65
66
 
@@ -67,12 +68,13 @@ export async function disableStream(
67
68
  import { createClient, type Tier0Client, type CloudStreamStopView } from '@tier0/sdk-v2';
68
69
 
69
70
  export async function rollbackStream(
70
- current: Pick<CloudStreamStopView, 'id' | 'revision' | 'activeRelease'>, versionId: string, intentKey: string, client: Tier0Client = createClient(),
71
+ current: Pick<CloudStreamStopView, 'id' | 'revision' | 'activeVersion'>, versionId: string, intentKey: string, client: Tier0Client = createClient(),
71
72
  ) {
72
73
  // versionId 使用已知发布回执的 activeVersion,或从 programs.versions.list 选定。
74
+ if (typeof current.activeVersion !== 'string' || !/^(0|[1-9][0-9]*)$/.test(current.activeVersion)) throw new Error('缺少权威 activeVersion;读取当前文档后再决定');
73
75
  return client.stream.programs.rollback({
74
76
  id: current.id, versionId, expectedRevision: current.revision,
75
- ...(String(current.activeRelease) === '0' ? { expectedReleaseState: 'inactive' as const } : { expectedActiveRelease: current.activeRelease }),
77
+ expectedActiveVersion: current.activeVersion,
76
78
  dryRun: false, idempotencyKey: intentKey,
77
79
  });
78
80
  }