@tier0/sdk-v2 0.0.0-stage → 0.1.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.
- package/LICENSE +21 -0
- package/NOTICE.md +7 -0
- package/README.md +201 -2
- package/dist/cjs/app-identity-contract.generated.d.ts +22 -0
- package/dist/cjs/app-identity-contract.generated.js +51 -0
- package/dist/cjs/app-identity-contract.generated.js.map +1 -0
- package/dist/cjs/capabilities.d.ts +54 -0
- package/dist/cjs/capabilities.js +134 -0
- package/dist/cjs/capabilities.js.map +1 -0
- package/dist/cjs/client.d.ts +604 -0
- package/dist/cjs/client.js +35 -0
- package/dist/cjs/client.js.map +1 -0
- package/dist/cjs/cloud-server.d.ts +31 -0
- package/dist/cjs/cloud-server.js +114 -0
- package/dist/cjs/cloud-server.js.map +1 -0
- package/dist/cjs/cloud-transport.d.ts +46 -0
- package/dist/cjs/cloud-transport.js +192 -0
- package/dist/cjs/cloud-transport.js.map +1 -0
- package/dist/cjs/controls.d.ts +93 -0
- package/dist/cjs/controls.js +169 -0
- package/dist/cjs/controls.js.map +1 -0
- package/dist/cjs/data/bootstrap.d.ts +66 -0
- package/dist/cjs/data/bootstrap.js +282 -0
- package/dist/cjs/data/bootstrap.js.map +1 -0
- package/dist/cjs/data/call.d.ts +16 -0
- package/dist/cjs/data/call.js +51 -0
- package/dist/cjs/data/call.js.map +1 -0
- package/dist/cjs/data/client.d.ts +92 -0
- package/dist/cjs/data/client.js +102 -0
- package/dist/cjs/data/client.js.map +1 -0
- package/dist/cjs/data/collection.d.ts +238 -0
- package/dist/cjs/data/collection.js +441 -0
- package/dist/cjs/data/collection.js.map +1 -0
- package/dist/cjs/data/context.d.ts +10 -0
- package/dist/cjs/data/context.js +39 -0
- package/dist/cjs/data/context.js.map +1 -0
- package/dist/cjs/data/declarations.d.ts +11 -0
- package/dist/cjs/data/declarations.js +18 -0
- package/dist/cjs/data/declarations.js.map +1 -0
- package/dist/cjs/data/define.d.ts +69 -0
- package/dist/cjs/data/define.js +31 -0
- package/dist/cjs/data/define.js.map +1 -0
- package/dist/cjs/data/error.d.ts +60 -0
- package/dist/cjs/data/error.js +184 -0
- package/dist/cjs/data/error.js.map +1 -0
- package/dist/cjs/data/index.d.ts +21 -0
- package/dist/cjs/data/index.js +43 -0
- package/dist/cjs/data/index.js.map +1 -0
- package/dist/cjs/data/schema.d.ts +82 -0
- package/dist/cjs/data/schema.js +607 -0
- package/dist/cjs/data/schema.js.map +1 -0
- package/dist/cjs/data/sort.d.ts +8 -0
- package/dist/cjs/data/sort.js +21 -0
- package/dist/cjs/data/sort.js.map +1 -0
- package/dist/cjs/files.d.ts +67 -0
- package/dist/cjs/files.js +119 -0
- package/dist/cjs/files.js.map +1 -0
- package/dist/cjs/framework-scope.d.ts +1 -0
- package/dist/cjs/framework-scope.js +14 -0
- package/dist/cjs/framework-scope.js.map +1 -0
- package/dist/cjs/index.d.ts +14 -0
- package/dist/cjs/index.js +33 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/mq/broker.d.ts +65 -0
- package/dist/cjs/mq/broker.js +115 -0
- package/dist/cjs/mq/broker.js.map +1 -0
- package/dist/cjs/mq/client.d.ts +37 -0
- package/dist/cjs/mq/client.js +321 -0
- package/dist/cjs/mq/client.js.map +1 -0
- package/dist/cjs/mq/index.d.ts +5 -0
- package/dist/cjs/mq/index.js +11 -0
- package/dist/cjs/mq/index.js.map +1 -0
- package/dist/cjs/mq/types.d.ts +48 -0
- package/dist/cjs/mq/types.js +3 -0
- package/dist/cjs/mq/types.js.map +1 -0
- package/dist/cjs/openapi/api.generated.d.ts +820 -0
- package/dist/cjs/openapi/api.generated.js +607 -0
- package/dist/cjs/openapi/api.generated.js.map +1 -0
- package/dist/cjs/openapi/client.d.ts +56 -0
- package/dist/cjs/openapi/client.js +219 -0
- package/dist/cjs/openapi/client.js.map +1 -0
- package/dist/cjs/openapi/codecs.generated.d.ts +2234 -0
- package/dist/cjs/openapi/codecs.generated.js +6 -0
- package/dist/cjs/openapi/codecs.generated.js.map +1 -0
- package/dist/cjs/openapi/index.d.ts +5 -0
- package/dist/cjs/openapi/index.js +12 -0
- package/dist/cjs/openapi/index.js.map +1 -0
- package/dist/cjs/openapi/types.generated.d.ts +3227 -0
- package/dist/cjs/openapi/types.generated.js +3 -0
- package/dist/cjs/openapi/types.generated.js.map +1 -0
- package/dist/cjs/package.json +1 -0
- package/dist/cjs/react.d.ts +9 -0
- package/dist/cjs/react.js +16 -0
- package/dist/cjs/react.js.map +1 -0
- package/dist/cjs/runtime-context.d.ts +9 -0
- package/dist/cjs/runtime-context.js +25 -0
- package/dist/cjs/runtime-context.js.map +1 -0
- package/dist/cjs/runtime-env.d.ts +1 -0
- package/dist/cjs/runtime-env.js +18 -0
- package/dist/cjs/runtime-env.js.map +1 -0
- package/dist/cjs/source.d.ts +39 -0
- package/dist/cjs/source.js +29 -0
- package/dist/cjs/source.js.map +1 -0
- package/dist/cjs/stream.d.ts +40 -0
- package/dist/cjs/stream.js +33 -0
- package/dist/cjs/stream.js.map +1 -0
- package/dist/cjs/uns-v2/client.d.ts +54 -0
- package/dist/cjs/uns-v2/client.js +177 -0
- package/dist/cjs/uns-v2/client.js.map +1 -0
- package/dist/cjs/uns-v2/codec.d.ts +11 -0
- package/dist/cjs/uns-v2/codec.js +290 -0
- package/dist/cjs/uns-v2/codec.js.map +1 -0
- package/dist/cjs/uns-v2/data-client.d.ts +10 -0
- package/dist/cjs/uns-v2/data-client.js +18 -0
- package/dist/cjs/uns-v2/data-client.js.map +1 -0
- package/dist/cjs/uns-v2/generated.d.ts +15551 -0
- package/dist/cjs/uns-v2/generated.js +139 -0
- package/dist/cjs/uns-v2/generated.js.map +1 -0
- package/dist/cjs/uns-v2/index.d.ts +5 -0
- package/dist/cjs/uns-v2/index.js +24 -0
- package/dist/cjs/uns-v2/index.js.map +1 -0
- package/dist/cjs/vue.d.ts +9 -0
- package/dist/cjs/vue.js +39 -0
- package/dist/cjs/vue.js.map +1 -0
- package/dist/esm/app-identity-contract.generated.d.ts +22 -0
- package/dist/esm/app-identity-contract.generated.js +48 -0
- package/dist/esm/app-identity-contract.generated.js.map +1 -0
- package/dist/esm/capabilities.d.ts +54 -0
- package/dist/esm/capabilities.js +129 -0
- package/dist/esm/capabilities.js.map +1 -0
- package/dist/esm/client.d.ts +604 -0
- package/dist/esm/client.js +32 -0
- package/dist/esm/client.js.map +1 -0
- package/dist/esm/cloud-server.d.ts +31 -0
- package/dist/esm/cloud-server.js +109 -0
- package/dist/esm/cloud-server.js.map +1 -0
- package/dist/esm/cloud-transport.d.ts +46 -0
- package/dist/esm/cloud-transport.js +187 -0
- package/dist/esm/cloud-transport.js.map +1 -0
- package/dist/esm/controls.d.ts +93 -0
- package/dist/esm/controls.js +163 -0
- package/dist/esm/controls.js.map +1 -0
- package/dist/esm/data/bootstrap.d.ts +66 -0
- package/dist/esm/data/bootstrap.js +277 -0
- package/dist/esm/data/bootstrap.js.map +1 -0
- package/dist/esm/data/call.d.ts +16 -0
- package/dist/esm/data/call.js +47 -0
- package/dist/esm/data/call.js.map +1 -0
- package/dist/esm/data/client.d.ts +92 -0
- package/dist/esm/data/client.js +99 -0
- package/dist/esm/data/client.js.map +1 -0
- package/dist/esm/data/collection.d.ts +238 -0
- package/dist/esm/data/collection.js +434 -0
- package/dist/esm/data/collection.js.map +1 -0
- package/dist/esm/data/context.d.ts +10 -0
- package/dist/esm/data/context.js +34 -0
- package/dist/esm/data/context.js.map +1 -0
- package/dist/esm/data/declarations.d.ts +11 -0
- package/dist/esm/data/declarations.js +10 -0
- package/dist/esm/data/declarations.js.map +1 -0
- package/dist/esm/data/define.d.ts +69 -0
- package/dist/esm/data/define.js +27 -0
- package/dist/esm/data/define.js.map +1 -0
- package/dist/esm/data/error.d.ts +60 -0
- package/dist/esm/data/error.js +178 -0
- package/dist/esm/data/error.js.map +1 -0
- package/dist/esm/data/index.d.ts +21 -0
- package/dist/esm/data/index.js +18 -0
- package/dist/esm/data/index.js.map +1 -0
- package/dist/esm/data/schema.d.ts +82 -0
- package/dist/esm/data/schema.js +596 -0
- package/dist/esm/data/schema.js.map +1 -0
- package/dist/esm/data/sort.d.ts +8 -0
- package/dist/esm/data/sort.js +18 -0
- package/dist/esm/data/sort.js.map +1 -0
- package/dist/esm/files.d.ts +67 -0
- package/dist/esm/files.js +113 -0
- package/dist/esm/files.js.map +1 -0
- package/dist/esm/framework-scope.d.ts +1 -0
- package/dist/esm/framework-scope.js +11 -0
- package/dist/esm/framework-scope.js.map +1 -0
- package/dist/esm/index.d.ts +14 -0
- package/dist/esm/index.js +10 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/mq/broker.d.ts +65 -0
- package/dist/esm/mq/broker.js +109 -0
- package/dist/esm/mq/broker.js.map +1 -0
- package/dist/esm/mq/client.d.ts +37 -0
- package/dist/esm/mq/client.js +314 -0
- package/dist/esm/mq/client.js.map +1 -0
- package/dist/esm/mq/index.d.ts +5 -0
- package/dist/esm/mq/index.js +3 -0
- package/dist/esm/mq/index.js.map +1 -0
- package/dist/esm/mq/types.d.ts +48 -0
- package/dist/esm/mq/types.js +2 -0
- package/dist/esm/mq/types.js.map +1 -0
- package/dist/esm/openapi/api.generated.d.ts +820 -0
- package/dist/esm/openapi/api.generated.js +603 -0
- package/dist/esm/openapi/api.generated.js.map +1 -0
- package/dist/esm/openapi/client.d.ts +56 -0
- package/dist/esm/openapi/client.js +210 -0
- package/dist/esm/openapi/client.js.map +1 -0
- package/dist/esm/openapi/codecs.generated.d.ts +2234 -0
- package/dist/esm/openapi/codecs.generated.js +3 -0
- package/dist/esm/openapi/codecs.generated.js.map +1 -0
- package/dist/esm/openapi/index.d.ts +5 -0
- package/dist/esm/openapi/index.js +3 -0
- package/dist/esm/openapi/index.js.map +1 -0
- package/dist/esm/openapi/types.generated.d.ts +3227 -0
- package/dist/esm/openapi/types.generated.js +2 -0
- package/dist/esm/openapi/types.generated.js.map +1 -0
- package/dist/esm/package.json +1 -0
- package/dist/esm/react.d.ts +9 -0
- package/dist/esm/react.js +12 -0
- package/dist/esm/react.js.map +1 -0
- package/dist/esm/runtime-context.d.ts +9 -0
- package/dist/esm/runtime-context.js +22 -0
- package/dist/esm/runtime-context.js.map +1 -0
- package/dist/esm/runtime-env.d.ts +1 -0
- package/dist/esm/runtime-env.js +15 -0
- package/dist/esm/runtime-env.js.map +1 -0
- package/dist/esm/source.d.ts +39 -0
- package/dist/esm/source.js +25 -0
- package/dist/esm/source.js.map +1 -0
- package/dist/esm/stream.d.ts +40 -0
- package/dist/esm/stream.js +29 -0
- package/dist/esm/stream.js.map +1 -0
- package/dist/esm/uns-v2/client.d.ts +54 -0
- package/dist/esm/uns-v2/client.js +170 -0
- package/dist/esm/uns-v2/client.js.map +1 -0
- package/dist/esm/uns-v2/codec.d.ts +11 -0
- package/dist/esm/uns-v2/codec.js +284 -0
- package/dist/esm/uns-v2/codec.js.map +1 -0
- package/dist/esm/uns-v2/data-client.d.ts +10 -0
- package/dist/esm/uns-v2/data-client.js +14 -0
- package/dist/esm/uns-v2/data-client.js.map +1 -0
- package/dist/esm/uns-v2/generated.d.ts +15551 -0
- package/dist/esm/uns-v2/generated.js +136 -0
- package/dist/esm/uns-v2/generated.js.map +1 -0
- package/dist/esm/uns-v2/index.d.ts +5 -0
- package/dist/esm/uns-v2/index.js +5 -0
- package/dist/esm/uns-v2/index.js.map +1 -0
- package/dist/esm/vue.d.ts +9 -0
- package/dist/esm/vue.js +36 -0
- package/dist/esm/vue.js.map +1 -0
- package/docs/acceptance-2026-10-22.md +88 -0
- package/package.json +242 -4
- package/skills/tier0-sdk-v2/SKILL.md +66 -0
- package/skills/tier0-sdk-v2/references/integration.md +72 -0
- package/skills/tier0-sdk-v2-agent/SKILL.md +73 -0
- package/skills/tier0-sdk-v2-agent/references/results.md +45 -0
- package/skills/tier0-sdk-v2-controls/SKILL.md +63 -0
- package/skills/tier0-sdk-v2-data/SKILL.md +57 -0
- package/skills/tier0-sdk-v2-data/references/consistency.md +70 -0
- package/skills/tier0-sdk-v2-data/references/errors.md +69 -0
- package/skills/tier0-sdk-v2-data/references/modeling.md +77 -0
- package/skills/tier0-sdk-v2-data/references/read-write.md +72 -0
- package/skills/tier0-sdk-v2-data/references/schema-evolution.md +36 -0
- package/skills/tier0-sdk-v2-files/SKILL.md +85 -0
- package/skills/tier0-sdk-v2-files/references/delete.md +22 -0
- package/skills/tier0-sdk-v2-files/references/download.md +49 -0
- package/skills/tier0-sdk-v2-files/references/multipart.md +42 -0
- package/skills/tier0-sdk-v2-files/references/upload.md +27 -0
- package/skills/tier0-sdk-v2-files/references/url.md +22 -0
- package/skills/tier0-sdk-v2-members/SKILL.md +56 -0
- package/skills/tier0-sdk-v2-members/references/app-members.md +41 -0
- package/skills/tier0-sdk-v2-members/references/platform-members.md +56 -0
- package/skills/tier0-sdk-v2-mq/SKILL.md +78 -0
- package/skills/tier0-sdk-v2-mq/references/quickstart.md +69 -0
- package/skills/tier0-sdk-v2-notifications/SKILL.md +42 -0
- package/skills/tier0-sdk-v2-notifications/references/get.md +34 -0
- package/skills/tier0-sdk-v2-notifications/references/send.md +72 -0
- package/skills/tier0-sdk-v2-source/SKILL.md +38 -0
- package/skills/tier0-sdk-v2-source/references/changes.md +40 -0
- package/skills/tier0-sdk-v2-source/references/create.md +63 -0
- package/skills/tier0-sdk-v2-source/references/delete.md +47 -0
- package/skills/tier0-sdk-v2-source/references/protocols.md +36 -0
- package/skills/tier0-sdk-v2-source/references/read.md +34 -0
- package/skills/tier0-sdk-v2-source/references/state.md +37 -0
- package/skills/tier0-sdk-v2-source/references/update.md +61 -0
- package/skills/tier0-sdk-v2-stream/SKILL.md +43 -0
- package/skills/tier0-sdk-v2-stream/references/create.md +55 -0
- package/skills/tier0-sdk-v2-stream/references/delete.md +35 -0
- package/skills/tier0-sdk-v2-stream/references/deploy.md +63 -0
- package/skills/tier0-sdk-v2-stream/references/lifecycle.md +25 -0
- package/skills/tier0-sdk-v2-stream/references/read.md +35 -0
- package/skills/tier0-sdk-v2-stream/references/update.md +35 -0
- package/skills/tier0-sdk-v2-system/SKILL.md +64 -0
- package/skills/tier0-sdk-v2-system/references/info.md +23 -0
- package/skills/tier0-sdk-v2-system/references/whoami.md +21 -0
- package/skills/tier0-sdk-v2-uns/SKILL.md +53 -0
- package/skills/tier0-sdk-v2-uns/references/create.md +85 -0
- package/skills/tier0-sdk-v2-uns/references/data-workflows.md +73 -0
- package/skills/tier0-sdk-v2-uns/references/delete.md +69 -0
- package/skills/tier0-sdk-v2-uns/references/namespace.md +75 -0
- package/skills/tier0-sdk-v2-uns/references/read.md +32 -0
- package/skills/tier0-sdk-v2-uns/references/restore.md +41 -0
- package/skills/tier0-sdk-v2-uns/references/update.md +86 -0
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# Source 影响分析
|
|
2
|
+
|
|
3
|
+
方法:`source.impact`;POST `/openapi/v2/uns/sources/impact`。
|
|
4
|
+
|
|
5
|
+
| 字段 | 类型 | 必填 | 说明 |
|
|
6
|
+
| --- | --- | --- | --- |
|
|
7
|
+
| id / expectedRevision | string / integer | 是 | 当前 ID 和读取到的修订 |
|
|
8
|
+
| action | update/enable/disable/delete | 是 | 精确变更类型 |
|
|
9
|
+
| document | CloudSourceDocument | 更新时 | 完整拟提交文档 |
|
|
10
|
+
| offset / size | integer | 否 | 首次 0;size 1–200 |
|
|
11
|
+
| impactRevision | string | 翻页时 | 沿用首次返回的确认值 |
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
import { createClient, type Tier0Client, type UnsV2Request } from '@tier0/sdk-v2';
|
|
15
|
+
|
|
16
|
+
export async function collectSourceImpact(
|
|
17
|
+
intent: Pick<UnsV2Request<'sourceImpact'>, 'id' | 'expectedRevision' | 'action' | 'document'>,
|
|
18
|
+
client: Tier0Client = createClient(),
|
|
19
|
+
) {
|
|
20
|
+
const first = await client.source.impact({ ...intent, offset: 0, size: 200 });
|
|
21
|
+
const references = [...first.data.references];
|
|
22
|
+
let offset = first.data.nextOffset;
|
|
23
|
+
const seen = new Set<string>();
|
|
24
|
+
while (String(offset) !== '0') {
|
|
25
|
+
if (seen.has(String(offset))) throw new Error('影响分页未前进');
|
|
26
|
+
seen.add(String(offset));
|
|
27
|
+
const next = await client.source.impact({
|
|
28
|
+
...intent, offset, size: 200, impactRevision: first.data.impactRevision,
|
|
29
|
+
});
|
|
30
|
+
if (next.data.impactRevision !== first.data.impactRevision) throw new Error('影响确认值发生变化');
|
|
31
|
+
references.push(...next.data.references);
|
|
32
|
+
offset = next.data.nextOffset;
|
|
33
|
+
}
|
|
34
|
+
return { ...first.data, references, nextOffset: offset };
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
data:impactRevision、sourceID/sourceRevision、action、counts(draft/activeRelease/historicalRelease)、restrictedCount、references、nextOffset、expiresAt。nextOffset=0 结束;complete=1 表示计算完成,不表示首页有全部引用。
|
|
39
|
+
|
|
40
|
+
确认值绑定身份、修订、精确意图,不能合成或自动刷新。评估 counts 和 restrictedCount;有受限引用时不能说“无影响”。Source 更新不会自动替换 Stream 冻结修订。已有明确操作授权时不重复索要确认;影响分析本身不授予额外操作权限。
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# 创建 Source
|
|
2
|
+
|
|
3
|
+
方法:`source.documents.create`;POST `/openapi/v2/uns/sources/documents/create`。需要 Source manage 权限。
|
|
4
|
+
|
|
5
|
+
| 字段 | 类型 | 必填 | 说明 |
|
|
6
|
+
| --- | --- | --- | --- |
|
|
7
|
+
| dryRun | boolean | 是 | true 校验;false 保存 |
|
|
8
|
+
| document.name | string | 是 | 1–128 字符 |
|
|
9
|
+
| document.protocol | string | 是 | 原生协议,如 http、mqtt、modbus |
|
|
10
|
+
| document.config | object | 是 | configVersion=2、endpoint、options;见[协议配置](protocols.md) |
|
|
11
|
+
| document.description | string | 否 | 最多 512 字符 |
|
|
12
|
+
| credentials | object | 否 | 仅创建时提供新 HTTP 凭据,与已有 auth/TLS 引用互斥 |
|
|
13
|
+
| idempotencyKey | string | 否 | 建议提供,最多 128 字符,同一业务意图保持不变 |
|
|
14
|
+
|
|
15
|
+
## 完整示例:HTTP 数据源
|
|
16
|
+
|
|
17
|
+
传入实际端点、名称和意图键。此函数创建配置,不启用源。client 从服务端环境读取 API Host/Key,也可显式注入。
|
|
18
|
+
|
|
19
|
+
```ts
|
|
20
|
+
import { createClient, type Tier0Client, type CloudSourceDocument } from '@tier0/sdk-v2';
|
|
21
|
+
|
|
22
|
+
export async function createHttpSource(
|
|
23
|
+
endpoint: string, name: string, intentKey: string, client: Tier0Client = createClient(),
|
|
24
|
+
) {
|
|
25
|
+
const document: CloudSourceDocument = {
|
|
26
|
+
name, protocol: 'http', description: '订单系统 HTTP 接入',
|
|
27
|
+
config: { configVersion: 2, endpoint, options: {} },
|
|
28
|
+
};
|
|
29
|
+
const preview = await client.source.documents.create({ dryRun: true, document });
|
|
30
|
+
if (!('validated' in preview.data) || !preview.data.validated) throw new Error('Source 预检未通过');
|
|
31
|
+
const saved = await client.source.documents.create({
|
|
32
|
+
dryRun: false, document, idempotencyKey: intentKey,
|
|
33
|
+
});
|
|
34
|
+
if (!('id' in saved.data)) throw new Error('未返回已保存的 Source');
|
|
35
|
+
const current = await client.source.documents.get({ id: saved.data.id });
|
|
36
|
+
return { receipt: saved, current: current.data };
|
|
37
|
+
}
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
提交返回 data:id、revision、document、desiredState、runtimeState、health、createdAt、updatedAt;预检返回 `{ validated: true, sideEffects: false }`,没有 ID。ID 原样保留十进制字符串。
|
|
41
|
+
|
|
42
|
+
## HTTP Bearer 凭据
|
|
43
|
+
|
|
44
|
+
token 从服务端密钥提供者取得,不写入脚本、文档、日志或仓库。
|
|
45
|
+
|
|
46
|
+
```ts
|
|
47
|
+
import { createClient, type Tier0Client } from '@tier0/sdk-v2';
|
|
48
|
+
|
|
49
|
+
export async function createAuthenticatedHttpSource(
|
|
50
|
+
endpoint: string, name: string, token: string, intentKey: string,
|
|
51
|
+
client: Tier0Client = createClient(),
|
|
52
|
+
) {
|
|
53
|
+
const saved = await client.source.documents.create({
|
|
54
|
+
dryRun: false, idempotencyKey: intentKey,
|
|
55
|
+
document: { name, protocol: 'http', config: { configVersion: 2, endpoint, options: {} } },
|
|
56
|
+
credentials: { method: 'GET', kind: 'bearer', material: { token } },
|
|
57
|
+
});
|
|
58
|
+
if (!('id' in saved.data)) throw new Error('未返回 Source ID');
|
|
59
|
+
return client.source.documents.get({ id: saved.data.id });
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
配置保存不代表连接健康;见[查询](read.md)。仅在任务包含启用时执行[启停](state.md)。结果未知时保留原请求、requestId、意图键,先核对列表/历史,不自动重复创建。
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# 删除 Source
|
|
2
|
+
|
|
3
|
+
方法:`source.delete`;POST `/openapi/v2/uns/sources/delete`。
|
|
4
|
+
|
|
5
|
+
| 字段 | 类型 | 必填 | 说明 |
|
|
6
|
+
| --- | --- | --- | --- |
|
|
7
|
+
| dryRun | boolean | 是 | true 预检;false 提交 |
|
|
8
|
+
| items | array | 是 | 1–200 项 |
|
|
9
|
+
| items[].id | string | 是 | 正十进制 int64 字符串 |
|
|
10
|
+
| items[].expectedRevision | integer | 是 | get 返回的修订 |
|
|
11
|
+
| items[].confirmedImpactRevision | string | 是 | action=delete 的影响回执 |
|
|
12
|
+
| mode | auto/sync | 否 | 不支持 async |
|
|
13
|
+
| allowPartial | false | 否 | 不支持部分提交 |
|
|
14
|
+
| idempotencyKey | string | 否 | 最多 128 字符 |
|
|
15
|
+
|
|
16
|
+
先 get → impact(action=delete) → [遍历并评估影响](changes.md)。存在 Stream 依赖时遵守服务端保护,不自动删除依赖流。
|
|
17
|
+
|
|
18
|
+
```ts
|
|
19
|
+
import { createClient, type Tier0Client, type UnsV2Request } from '@tier0/sdk-v2';
|
|
20
|
+
|
|
21
|
+
export async function deleteSource(
|
|
22
|
+
id: string, expectedRevision: UnsV2Request<'sourceImpact'>['expectedRevision'],
|
|
23
|
+
confirmedImpactRevision: string, intentKey: string, client: Tier0Client = createClient(),
|
|
24
|
+
) {
|
|
25
|
+
const receipt = await client.source.delete({
|
|
26
|
+
dryRun: false, mode: 'sync', allowPartial: false, idempotencyKey: intentKey,
|
|
27
|
+
items: [{ id, expectedRevision, confirmedImpactRevision }],
|
|
28
|
+
});
|
|
29
|
+
if (receipt.data.status !== 'committed' || receipt.data.results?.some(item => item.error)) {
|
|
30
|
+
return { state: 'unconfirmed' as const, receipt };
|
|
31
|
+
}
|
|
32
|
+
let page = 1;
|
|
33
|
+
while (true) {
|
|
34
|
+
const { data } = await client.source.documents.list({
|
|
35
|
+
archived: true, page, size: 200, includeDocument: false,
|
|
36
|
+
});
|
|
37
|
+
const archived = data.list.find(item => item.id === id);
|
|
38
|
+
if (archived) return { state: 'archived' as const, receipt, archived };
|
|
39
|
+
if (!data.hasMore) break;
|
|
40
|
+
if (typeof data.nextPage !== 'number' || data.nextPage <= page) throw new Error('无有效下一页');
|
|
41
|
+
page = data.nextPage;
|
|
42
|
+
}
|
|
43
|
+
return { state: 'committed-readback-unconfirmed' as const, receipt };
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
返回 Outcome,HTTP 200/validated/accepted 不等于完成。归档列表找到 ID 是额外核验;读回不可见时保留提交回执,报告核验未完成。不能把任意 get 异常当成成功。
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# 协议与连接配置
|
|
2
|
+
|
|
3
|
+
先调用 `source.protocols.list({})`。协议枚举存在不等于目标环境驱动或凭据解析器已就绪。原生 `protocol: 'http'` 与通用投影 `adapter: 'http-api'` 不可混用。
|
|
4
|
+
|
|
5
|
+
| 配置字段 | 类型 | 必填 | 说明 |
|
|
6
|
+
| --- | --- | --- | --- |
|
|
7
|
+
| configVersion | 2 | 是 | 新架构配置快照 |
|
|
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 校验。
|
|
15
|
+
|
|
16
|
+
```ts
|
|
17
|
+
import { createClient, type CloudSourceDocument } from '@tier0/sdk-v2';
|
|
18
|
+
|
|
19
|
+
export async function inspectProtocolExamples() {
|
|
20
|
+
const capabilities = await createClient().source.protocols.list({});
|
|
21
|
+
const examples: CloudSourceDocument[] = [
|
|
22
|
+
{ name: 'orders-http', protocol: 'http',
|
|
23
|
+
config: { configVersion: 2, endpoint: 'https://orders.example.com', options: {} } },
|
|
24
|
+
{ name: 'line-plc', protocol: 'modbus',
|
|
25
|
+
config: { configVersion: 2, endpoint: 'tcp://plc.example.com:502', options: { unitId: 1 } } },
|
|
26
|
+
{ name: 'line-mqtt', protocol: 'mqtt',
|
|
27
|
+
config: { configVersion: 2, endpoint: 'mqtt://broker.example.com:1883',
|
|
28
|
+
options: { clientId: 'tier0-line-reader', subscriptions: { 'factory/line1/status': 1 } } } },
|
|
29
|
+
];
|
|
30
|
+
return { capabilities: capabilities.data, examples };
|
|
31
|
+
}
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
HTTP 公开 headers 只允许 Accept/Content-Type,不能塞 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。
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# 查询 Source
|
|
2
|
+
|
|
3
|
+
| 方法 | POST 路径 | 输入 | data |
|
|
4
|
+
| --- | --- | --- | --- |
|
|
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、状态 |
|
|
7
|
+
| source.runtime.get | /openapi/v2/uns/sources/runtime/get | id(必填) | 运行状态 |
|
|
8
|
+
| source.observations.get | /openapi/v2/uns/sources/observations/get | items:id、expectedRevision | 指定源和修订的观测 |
|
|
9
|
+
|
|
10
|
+
page 从 1 开始,size 1–200。列表默认安全摘要;完整文档需要管理权限,编辑时显式 get。
|
|
11
|
+
|
|
12
|
+
```ts
|
|
13
|
+
import { createClient, type Tier0Client } from '@tier0/sdk-v2';
|
|
14
|
+
|
|
15
|
+
export async function* listSources(client: Tier0Client = createClient()) {
|
|
16
|
+
let page = 1;
|
|
17
|
+
while (true) {
|
|
18
|
+
const { data } = await client.source.documents.list({ page, size: 100, includeDocument: false });
|
|
19
|
+
yield data.list;
|
|
20
|
+
if (!data.hasMore) return;
|
|
21
|
+
if (typeof data.nextPage !== 'number' || data.nextPage <= page) throw new Error('无有效下一页');
|
|
22
|
+
page = data.nextPage;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
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 };
|
|
31
|
+
}
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
ID 不得转 Number;跨页不是稳定快照。权限错误、网络故障与不存在应分别处理,不能把任何 get 失败当成删除成功。probe 可能触达外部系统,不属于单纯读取。
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# 启用、停用 Source
|
|
2
|
+
|
|
3
|
+
方法:`source.state.update`;POST `/openapi/v2/uns/sources/state/update`。
|
|
4
|
+
|
|
5
|
+
| 字段 | 类型 | 必填 | 说明 |
|
|
6
|
+
| --- | --- | --- | --- |
|
|
7
|
+
| dryRun | boolean | 是 | 提交 false |
|
|
8
|
+
| items[].id / expectedRevision | string / integer | 是 | 当前对象和修订 |
|
|
9
|
+
| items[].desiredState | enabled/disabled | 是 | 目标状态 |
|
|
10
|
+
| items[].confirmedImpactRevision | string | 是 | enable/disable 对应的影响回执 |
|
|
11
|
+
| mode / allowPartial | string / boolean | 否 | 单项示例 sync / false |
|
|
12
|
+
| idempotencyKey | string | 否 | 本次状态变更的独立意图键 |
|
|
13
|
+
|
|
14
|
+
先 get,以相同修订执行 impact(action=enable 或 disable),按[影响分析](changes.md)遍历并评估。将原修订和回执传给下例。
|
|
15
|
+
|
|
16
|
+
```ts
|
|
17
|
+
import { createClient, type Tier0Client, type UnsV2Request } from '@tier0/sdk-v2';
|
|
18
|
+
|
|
19
|
+
export async function setSourceState(
|
|
20
|
+
id: string, expectedRevision: UnsV2Request<'sourceImpact'>['expectedRevision'],
|
|
21
|
+
desiredState: 'enabled' | 'disabled', confirmedImpactRevision: string,
|
|
22
|
+
intentKey: string, client: Tier0Client = createClient(),
|
|
23
|
+
) {
|
|
24
|
+
const receipt = await client.source.state.update({
|
|
25
|
+
dryRun: false, mode: 'sync', allowPartial: false, idempotencyKey: intentKey,
|
|
26
|
+
items: [{ id, expectedRevision, desiredState, confirmedImpactRevision }],
|
|
27
|
+
});
|
|
28
|
+
if (receipt.data.status !== 'committed' || receipt.data.results?.some(item => item.error)) {
|
|
29
|
+
return { state: 'unconfirmed' as const, receipt };
|
|
30
|
+
}
|
|
31
|
+
const current = await client.source.documents.get({ id });
|
|
32
|
+
if (current.data.desiredState !== desiredState) throw new Error('读回状态与目标不一致');
|
|
33
|
+
return { state: 'committed' as const, receipt, current: current.data };
|
|
34
|
+
}
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
响应为 Outcome;accepted/jobId 仅表示受理,继续查询作业。enabled 是期望状态;健康与连通性另用 observations/runtime 检查。
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# 修改 Source
|
|
2
|
+
|
|
3
|
+
方法:`source.documents.update`;POST `/openapi/v2/uns/sources/documents/update`。
|
|
4
|
+
|
|
5
|
+
| 字段 | 类型 | 必填 | 说明 |
|
|
6
|
+
| --- | --- | --- | --- |
|
|
7
|
+
| id | string | 是 | get 返回的 ID |
|
|
8
|
+
| document | CloudSourceDocument | 是 | 完整新文档,保留未改字段和认证引用 |
|
|
9
|
+
| expectedRevision | integer | 是 | 读取时的 revision,原样传回 |
|
|
10
|
+
| confirmedImpactRevision | string | 是 | 相同文档和修订的 impact 回执 |
|
|
11
|
+
| dryRun | boolean | 是 | true 预检;false 提交 |
|
|
12
|
+
| idempotencyKey | string | 否 | 最多 128 字符 |
|
|
13
|
+
|
|
14
|
+
## 示例:修改名称并保留连接
|
|
15
|
+
|
|
16
|
+
prepare 读取文档、形成新文档并收集全部影响分页。在已有授权范围内评估 counts、restrictedCount 和引用后调用 commit,不自动串联未经授权的操作。影响字段说明见[影响分析](changes.md)。
|
|
17
|
+
|
|
18
|
+
```ts
|
|
19
|
+
import { createClient, type Tier0Client, type CloudSourceDocument, type UnsV2Request } from '@tier0/sdk-v2';
|
|
20
|
+
|
|
21
|
+
export async function prepareSourceRename(id: string, name: string, client: Tier0Client = createClient()) {
|
|
22
|
+
const { data: current } = await client.source.documents.get({ id });
|
|
23
|
+
const document: CloudSourceDocument = { ...current.document, name };
|
|
24
|
+
const intent: UnsV2Request<'sourceImpact'> = {
|
|
25
|
+
id, expectedRevision: current.revision, action: 'update', document,
|
|
26
|
+
};
|
|
27
|
+
const impact = await client.source.impact({ ...intent, offset: 0, size: 200 });
|
|
28
|
+
const references = [...impact.data.references];
|
|
29
|
+
let offset = impact.data.nextOffset;
|
|
30
|
+
const seen = new Set<string>();
|
|
31
|
+
while (String(offset) !== '0') {
|
|
32
|
+
if (seen.has(String(offset))) throw new Error('影响分页未前进');
|
|
33
|
+
seen.add(String(offset));
|
|
34
|
+
const next = await client.source.impact({
|
|
35
|
+
...intent, offset, size: 200, impactRevision: impact.data.impactRevision,
|
|
36
|
+
});
|
|
37
|
+
if (next.data.impactRevision !== impact.data.impactRevision) throw new Error('影响确认值发生变化');
|
|
38
|
+
references.push(...next.data.references);
|
|
39
|
+
offset = next.data.nextOffset;
|
|
40
|
+
}
|
|
41
|
+
return { intent, impact: { ...impact.data, references, nextOffset: offset } };
|
|
42
|
+
}
|
|
43
|
+
export async function commitSourceRename(
|
|
44
|
+
plan: { intent: UnsV2Request<'sourceImpact'>; impact: { impactRevision: string } },
|
|
45
|
+
intentKey: string, client: Tier0Client = createClient(),
|
|
46
|
+
) {
|
|
47
|
+
const { id, expectedRevision, document, action } = plan.intent;
|
|
48
|
+
if (action !== 'update' || !document) throw new Error('需要完整更新意图');
|
|
49
|
+
const request = { id, expectedRevision, document,
|
|
50
|
+
confirmedImpactRevision: plan.impact.impactRevision };
|
|
51
|
+
const preview = await client.source.documents.update({ ...request, dryRun: true });
|
|
52
|
+
if (!('validated' in preview.data) || !preview.data.validated) throw new Error('预检未通过');
|
|
53
|
+
const saved = await client.source.documents.update({
|
|
54
|
+
...request, dryRun: false, idempotencyKey: intentKey,
|
|
55
|
+
});
|
|
56
|
+
if (!('id' in saved.data)) throw new Error('未收到更新提交结果');
|
|
57
|
+
return { receipt: saved, current: (await client.source.documents.get({ id })).data };
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
提交返回完整 Source view。核对读回名称、配置和提交修订;若读回又被别人修改,报告并发变化。影响评估后的 plan 保持不变。遇到 VERSION_CONFLICT、确认过期/不匹配,重新读取并评估,不静默刷新 token 重放。
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: tier0-sdk-v2-stream
|
|
3
|
+
description: 使用 @tier0/sdk-v2 的 client.stream 创建、查询、修改和删除 Stream,绑定 Source,校验脚本,发布、停用、回滚及检查运行结果。
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Stream 处理与运行
|
|
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。
|
|
9
|
+
|
|
10
|
+
## 按任务加载参考
|
|
11
|
+
|
|
12
|
+
| 用户任务 | 参考 | 方法 |
|
|
13
|
+
| --- | --- | --- |
|
|
14
|
+
| 新建并绑定 HTTP Source | [创建](references/create.md) | programs.validate/create |
|
|
15
|
+
| 列表、完整文档、运行记录 | [查询](references/read.md) | programs.list/get、documents.get、observations.get、runs.list |
|
|
16
|
+
| 修改草稿、脚本和绑定 | [修改](references/update.md) | documents.validate/update |
|
|
17
|
+
| 发布、停用、版本回滚 | [部署](references/deploy.md) | programs.deploy/rollback、documents.disable |
|
|
18
|
+
| 删除并核验归档 | [删除](references/delete.md) | programs.delete |
|
|
19
|
+
| 隔离样例测试、流程衔接 | [生命周期](references/lifecycle.md) | sampleTest |
|
|
20
|
+
|
|
21
|
+
## 两种文档形态
|
|
22
|
+
|
|
23
|
+
| 形态 | 完整输入 | 适用入口 |
|
|
24
|
+
| --- | --- | --- |
|
|
25
|
+
| Runtime program | name、sdkVersion、script 字符串、sourceBindings、timeoutMs | programs.create/update/validate |
|
|
26
|
+
| 云端原生文档 | name、model、script 对象、sources、entries | documents.create/get/update/validate |
|
|
27
|
+
|
|
28
|
+
程序必须是完整 `module.exports = api => { ... }`,执行器 API 是 api.sources/api.uns/api.stream,与 npm 包的 client.source 不同。Runtime sourceBindings 为 sourceId/configRevision/acquisition;原生 sources 还使用 alias/resources。连接凭据不进脚本或 acquisition。
|
|
29
|
+
|
|
30
|
+
## 核心约束
|
|
31
|
+
|
|
32
|
+
1. programs.get 返回脱敏摘要,不含可回写脚本;编辑必须 documents.get。保留未修改的 sources/entries/script 字段。
|
|
33
|
+
2. create/update 保存草稿,不自动发布;documents 没有 deploy,云端 program 发布使用 programs.deploy。不能将已保存报告为已运行。
|
|
34
|
+
3. 所有更新/部署/删除携带当前 expectedRevision。原生停用另需 expectedActiveRelease,避免停掉他人刚发布的版本。
|
|
35
|
+
4. versionId 从 versions.list 取得,不把 release 序号当 ID。expectedSourceRevision 仅用于恰好一个依赖源,不代表多个源的修订。
|
|
36
|
+
5. resources=[] 是空冻结资源集,不是通配符。先查询 runtime.capabilities,并让服务端 validate 检查能力;当前云端程序 timeoutMs 上限 30000。
|
|
37
|
+
6. 仅执行用户要求的生命周期步骤;修改脚本不自动授予发布、停用或删除权限。
|
|
38
|
+
|
|
39
|
+
## 成功与异常
|
|
40
|
+
|
|
41
|
+
响应保留 code/msg/requestId/data。校验要检查 valid,样例要检查 completed/failed,删除要检查 deleted,发布要检查 activeVersion 和观测。样例 writePreview 不代表线上数据写入。
|
|
42
|
+
|
|
43
|
+
UnsV2OutcomeUnknownError、发布超时或取消后先读取版本/观测对账,保留原请求意图键,不自动重复发布。版本冲突先比较当前草稿,不能忽略 expectedRevision。不同写入意图使用不同键;本地 SDK 测试不能代替目标环境联调。
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# 创建 Stream
|
|
2
|
+
|
|
3
|
+
方法:`stream.programs.create`;POST `/openapi/v2/uns/streams/program/create`。
|
|
4
|
+
|
|
5
|
+
| 字段 | 类型 | 必填 | 说明 |
|
|
6
|
+
| --- | --- | --- | --- |
|
|
7
|
+
| dryRun | boolean | 是 | true 预检,false 保存草稿 |
|
|
8
|
+
| document.name | string | 是 | 1–63 字符 |
|
|
9
|
+
| document.sdkVersion | tier0-stream/v2 | 是 | 运行时脚本版本 |
|
|
10
|
+
| document.script | string | 是 | 完整 module.exports 程序 |
|
|
11
|
+
| document.timeoutMs | integer | 否 | 当前云端上限 30000 ms |
|
|
12
|
+
| document.sourceBindings | array | 否 | sourceId、configRevision、acquisition |
|
|
13
|
+
| idempotencyKey | string | 否 | 最多 128 字符,本次创建的固定意图键 |
|
|
14
|
+
|
|
15
|
+
## HTTP Source 绑定示例
|
|
16
|
+
|
|
17
|
+
先按[Source 查询](../../tier0-sdk-v2-source/references/read.md)选定真实 HTTP Source。脚本的 api.sources 属于平台执行器,与应用中的 client.source 不同。sourceId 保持字符串,configRevision 从完整源读取。
|
|
18
|
+
|
|
19
|
+
```ts
|
|
20
|
+
import { createClient, type Tier0Client, type RuntimeStreamDefinition } from '@tier0/sdk-v2';
|
|
21
|
+
|
|
22
|
+
export async function createHttpStream(
|
|
23
|
+
sourceId: string, name: string, intentKey: string, client: Tier0Client = createClient(),
|
|
24
|
+
) {
|
|
25
|
+
if (!/^[1-9][0-9]*$/.test(sourceId)) throw new Error('Source ID 必须是正十进制字符串');
|
|
26
|
+
const source = await client.source.documents.get({ id: sourceId });
|
|
27
|
+
if (source.data.document.protocol !== 'http') throw new Error('此示例需要 HTTP Source');
|
|
28
|
+
const document: RuntimeStreamDefinition = {
|
|
29
|
+
name, sdkVersion: 'tier0-stream/v2', timeoutMs: 5000,
|
|
30
|
+
sourceBindings: [{ sourceId, configRevision: source.data.revision, acquisition: {} }],
|
|
31
|
+
script: [
|
|
32
|
+
'module.exports = api => {',
|
|
33
|
+
' const upstream = api.sources.use({ id: ' + JSON.stringify(sourceId) + ', resources: [] });',
|
|
34
|
+
' api.stream.onTimer({ id: "tick", intervalMs: 60000 }, async () => {',
|
|
35
|
+
' const response = await upstream.request({ method: "GET", path: "orders" });',
|
|
36
|
+
' return response.data;',
|
|
37
|
+
' });',
|
|
38
|
+
'};',
|
|
39
|
+
].join('\n'),
|
|
40
|
+
};
|
|
41
|
+
const validation = await client.stream.programs.validate({ document });
|
|
42
|
+
if (validation.data.valid !== true) throw new Error('Stream 校验未通过');
|
|
43
|
+
const saved = await client.stream.programs.create({
|
|
44
|
+
dryRun: false, document, idempotencyKey: intentKey,
|
|
45
|
+
});
|
|
46
|
+
if (typeof saved.data.id !== 'string') throw new Error('创建回执缺少 ID');
|
|
47
|
+
return { receipt: saved, current: (await client.stream.documents.get({ id: saved.data.id })).data };
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
将 path="orders"、60 秒周期改为业务实际值。示例保存草稿,不部署,也不将返回值自动写入 UNS;需要写入集合时按执行器能力定义 api.uns 操作。resources=[] 是空冻结资源集,不是通配授权。源地址和凭据留在 Source,不能拷进 acquisition 或脚本。
|
|
52
|
+
|
|
53
|
+
创建 data 是开放对象,成功返回 id、revision、activeVersion、executionState、脱敏 document;以实际字段判断,预检不生成 ID。当前后端创建/校验需要注册 Worker 可用。TEMPORARILY_UNAVAILABLE 不代表脚本一定错误;不要自动改用旧 Flow。
|
|
54
|
+
|
|
55
|
+
原生编辑器形态 `documents.create({dryRun, document})` 的 document 为 name/model/script对象/sources/entries,script 为 `{sdkVersion,code,timeoutMs}`,sources 用 alias/sourceId/configRevision/resources/acquisition。不要把上面的 script 字符串直接塞入原生文档。
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# 删除 Stream
|
|
2
|
+
|
|
3
|
+
方法:`stream.programs.delete`;POST `/openapi/v2/uns/streams/program/delete`。
|
|
4
|
+
|
|
5
|
+
| 字段 | 类型 | 必填 | 说明 |
|
|
6
|
+
| --- | --- | --- | --- |
|
|
7
|
+
| id | string | 是 | 十进制字符串 |
|
|
8
|
+
| expectedRevision | integer | 建议提供 | 当前 get 返回修订 |
|
|
9
|
+
| dryRun | boolean | 是 | true 预检;false 提交 |
|
|
10
|
+
| idempotencyKey | string | 否 | 最多 128 字符 |
|
|
11
|
+
|
|
12
|
+
先读取明确目标并评估活跃发布/调用依赖。停止运行与删除是两个操作,删除请求不自动授予对 Source/UNS 数据的清理权限。
|
|
13
|
+
|
|
14
|
+
```ts
|
|
15
|
+
import { createClient, type Tier0Client } from '@tier0/sdk-v2';
|
|
16
|
+
|
|
17
|
+
export async function deleteStream(id: string, intentKey: string, client: Tier0Client = createClient()) {
|
|
18
|
+
const { data: current } = await client.stream.documents.get({ id });
|
|
19
|
+
const receipt = await client.stream.programs.delete({
|
|
20
|
+
id, expectedRevision: current.revision, dryRun: false, idempotencyKey: intentKey,
|
|
21
|
+
});
|
|
22
|
+
if (!('deleted' in receipt.data) || receipt.data.deleted !== true) throw new Error('未确认删除');
|
|
23
|
+
let page = 1;
|
|
24
|
+
while (true) {
|
|
25
|
+
const { data } = await client.stream.programs.list({ archived: true, page, size: 200 });
|
|
26
|
+
const archived = data.list.find(item => item.id === id);
|
|
27
|
+
if (archived) return { receipt, archived };
|
|
28
|
+
if (!data.hasMore) return { receipt, archived: undefined };
|
|
29
|
+
if (typeof data.nextPage !== 'number' || data.nextPage <= page) throw new Error('无有效下一页');
|
|
30
|
+
page = data.nextPage;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
成功 data 为 `{id,revision,deleted:true}`;预检为 `{validated:true,sideEffects:false}`。归档列表额外核验,未查到时报告“删除有回执,读回未确认”。不要捕获所有 get 异常并返回删除成功。并发冲突重新评估,不用无版本保护的请求覆盖。
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# 发布、停用与回滚 Stream
|
|
2
|
+
|
|
3
|
+
| 方法 | POST 路径 | 必要参数 |
|
|
4
|
+
| --- | --- | --- |
|
|
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
|
+
| programs.rollback | /openapi/v2/uns/streams/program/rollback | id、versionId、dryRun;建议 expectedRevision |
|
|
8
|
+
| documents.disable | /openapi/v2/uns/streams/documents/disable | id、expectedRevision、expectedActiveRelease、dryRun |
|
|
9
|
+
|
|
10
|
+
全部写操作使用各自的 idempotencyKey。expectedSourceRevision 只适用于恰好一个 Source 依赖,且同时保护草稿冻结修订与当前 Source head;多源不能塞入单个修订值。原生文档没有 documents.deploy,当前云端 program 模型发布走 programs.deploy。
|
|
11
|
+
|
|
12
|
+
```ts
|
|
13
|
+
import { createClient, type Tier0Client } from '@tier0/sdk-v2';
|
|
14
|
+
|
|
15
|
+
export async function deployStream(id: string, intentKey: string, client: Tier0Client = createClient()) {
|
|
16
|
+
const { data: current } = await client.stream.documents.get({ id });
|
|
17
|
+
const sources = current.document.sources ?? [];
|
|
18
|
+
const request = {
|
|
19
|
+
id, expectedRevision: current.revision,
|
|
20
|
+
...(sources.length === 1 ? { expectedSourceRevision: sources[0]!.configRevision } : {}),
|
|
21
|
+
};
|
|
22
|
+
const receipt = await client.stream.programs.deploy({
|
|
23
|
+
...request, dryRun: false, idempotencyKey: intentKey,
|
|
24
|
+
});
|
|
25
|
+
if (typeof receipt.data.activeVersion !== 'string' || receipt.data.activeVersion === '0') {
|
|
26
|
+
throw new Error('未确认发布版本');
|
|
27
|
+
}
|
|
28
|
+
return { receipt, current: (await client.stream.documents.get({ id })).data,
|
|
29
|
+
observation: (await client.stream.observations.get({ id })).data };
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export async function disableStream(id: string, intentKey: string, client: Tier0Client = createClient()) {
|
|
33
|
+
const { data: current } = await client.stream.documents.get({ id });
|
|
34
|
+
if (String(current.activeRelease) === '0') throw new Error('没有活跃发布可停用');
|
|
35
|
+
const receipt = await client.stream.documents.disable({
|
|
36
|
+
id, expectedRevision: current.revision, expectedActiveRelease: current.activeRelease,
|
|
37
|
+
dryRun: false, idempotencyKey: intentKey,
|
|
38
|
+
});
|
|
39
|
+
const after = await client.stream.documents.get({ id });
|
|
40
|
+
if (String(after.data.activeRelease) !== '0') throw new Error('停用读回未确认');
|
|
41
|
+
return { receipt, current: after.data };
|
|
42
|
+
}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
发布成功不表示外部连接健康或每次执行成功;检查 observation 与执行记录。停用保留草稿。仅修改草稿的任务不额外发布/停用。
|
|
46
|
+
|
|
47
|
+
## 回滚到明确版本
|
|
48
|
+
|
|
49
|
+
```ts
|
|
50
|
+
import { createClient, type Tier0Client } from '@tier0/sdk-v2';
|
|
51
|
+
|
|
52
|
+
export async function rollbackStream(
|
|
53
|
+
id: string, versionId: string, intentKey: string, client: Tier0Client = createClient(),
|
|
54
|
+
) {
|
|
55
|
+
// versionId 必须先从 programs.versions.list({id,page,size}) 查询并选定。
|
|
56
|
+
const { data: current } = await client.stream.documents.get({ id });
|
|
57
|
+
return client.stream.programs.rollback({
|
|
58
|
+
id, versionId, expectedRevision: current.revision, dryRun: false, idempotencyKey: intentKey,
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
检查回执 activeVersion,并重新 get/observation。超时或 UnsV2OutcomeUnknownError 时先核对版本和观测,保留原请求意图键,不重复 deploy/rollback。预览用 dryRun=true,但不保证稍后的实际发布一定成功。
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Stream 样例测试与流程衔接
|
|
2
|
+
|
|
3
|
+
完整流程按任务选取:[创建](create.md) → [查询](read.md) → [修改](update.md) → [发布/停用/回滚](deploy.md) → [删除](delete.md)。不要为了完成一次查询自动执行整套流程。
|
|
4
|
+
|
|
5
|
+
## 原生文档样例测试
|
|
6
|
+
|
|
7
|
+
方法:stream.sampleTest;输入 document、entryId、input。document 来自 documents.get 的完整草稿,entryId 必须在该文档注册的 entries 内。
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
import { createClient, type Tier0Client, type UnsV2JSONValue } from '@tier0/sdk-v2';
|
|
11
|
+
|
|
12
|
+
export async function testStreamSample(
|
|
13
|
+
id: string, entryId: string, input: UnsV2JSONValue, client: Tier0Client = createClient(),
|
|
14
|
+
) {
|
|
15
|
+
const { data: current } = await client.stream.documents.get({ id });
|
|
16
|
+
if (!current.document.entries?.some(entry => entry.id === entryId)) throw new Error('入口不在草稿中');
|
|
17
|
+
const response = await client.stream.sampleTest({ document: current.document, entryId, input });
|
|
18
|
+
return { status: response.data.status, errorCode: response.data.errorCode,
|
|
19
|
+
writes: response.data.writePreview, logs: response.data.logs, mode: response.data.mode };
|
|
20
|
+
}
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
HTTP 成功也要检查 completed/failed 和 errorCode。模式为 isolated-sample,writePreview 不是线上写入;样例成功不能证明线上依赖健康。日志可能有业务数据,不直接公开。
|
|
24
|
+
|
|
25
|
+
所有 Source/Stream 接口返回完整 code/msg/requestId/data。预检、草稿保存、发布回执和真实运行应分别记录;不要以 SDK 本地测试通过宣称完成真实环境联调。
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# 查询 Stream
|
|
2
|
+
|
|
3
|
+
| 方法 | POST 路径 | 输入 | 结果 |
|
|
4
|
+
| --- | --- | --- | --- |
|
|
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 |
|
|
8
|
+
| observations.get | /openapi/v2/uns/streams/observation/get | id | 运行观测 |
|
|
9
|
+
| runs.list | /openapi/v2/uns/streams/runs/list | id、size、cursor | 执行记录 |
|
|
10
|
+
| programs.versions.list | /openapi/v2/uns/streams/program/versions/list | id、page、size | list、total,含 versionId |
|
|
11
|
+
|
|
12
|
+
page 从 1 开始,size 最大 200。完整文档需要 Stream manage 权限;programs.get 的 scriptConfigured 不是脚本内容,不能据此重建草稿。
|
|
13
|
+
|
|
14
|
+
```ts
|
|
15
|
+
import { createClient, type Tier0Client } from '@tier0/sdk-v2';
|
|
16
|
+
|
|
17
|
+
export async function readStream(id: string, client: Tier0Client = createClient()) {
|
|
18
|
+
const draft = await client.stream.documents.get({ id });
|
|
19
|
+
const summary = await client.stream.programs.get({ id });
|
|
20
|
+
const observation = await client.stream.observations.get({ id });
|
|
21
|
+
return { draft: draft.data, summary: summary.data, observation: observation.data };
|
|
22
|
+
}
|
|
23
|
+
export async function* listStreams(client: Tier0Client = createClient()) {
|
|
24
|
+
let page = 1;
|
|
25
|
+
while (true) {
|
|
26
|
+
const { data } = await client.stream.programs.list({ page, size: 100, archived: false });
|
|
27
|
+
yield data.list;
|
|
28
|
+
if (!data.hasMore) return;
|
|
29
|
+
if (typeof data.nextPage !== 'number' || data.nextPage <= page) throw new Error('无有效下一页');
|
|
30
|
+
page = data.nextPage;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
保存、发布、某次执行成功是三个事实。显示实际 revision/activeVersion/release,不用旧 runs 证明新版本生效。版本列表不保证与普通列表相同分页结构;按其 list/total/page/size 读取,versionId 不是 release 序号。
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# 修改 Stream 草稿
|
|
2
|
+
|
|
3
|
+
方法:`stream.documents.update`;POST `/openapi/v2/uns/streams/documents/update`。
|
|
4
|
+
|
|
5
|
+
| 字段 | 类型 | 必填 | 说明 |
|
|
6
|
+
| --- | --- | --- | --- |
|
|
7
|
+
| id | string | 是 | 十进制字符串 |
|
|
8
|
+
| document | CloudStreamDocument | 是 | name、model、script、sources、entries 完整文档 |
|
|
9
|
+
| expectedRevision | integer | 建议始终提供 | get 返回修订,防止覆盖他人修改 |
|
|
10
|
+
| dryRun | boolean | 是 | true 预检;false 保存 |
|
|
11
|
+
| idempotencyKey | string | 否 | 本次更新独立意图键 |
|
|
12
|
+
|
|
13
|
+
## 示例:更新描述,保持脚本和绑定
|
|
14
|
+
|
|
15
|
+
```ts
|
|
16
|
+
import { createClient, type Tier0Client, type CloudStreamDocument } from '@tier0/sdk-v2';
|
|
17
|
+
|
|
18
|
+
export async function updateStreamDescription(
|
|
19
|
+
id: string, description: string, intentKey: string, client: Tier0Client = createClient(),
|
|
20
|
+
) {
|
|
21
|
+
const { data: current } = await client.stream.documents.get({ id });
|
|
22
|
+
const document: CloudStreamDocument = { ...current.document, description };
|
|
23
|
+
const checked = await client.stream.documents.validate({ document });
|
|
24
|
+
if (!checked.data.valid) throw new Error('Stream 文档校验失败,请检查 issues');
|
|
25
|
+
const saved = await client.stream.documents.update({
|
|
26
|
+
id, expectedRevision: current.revision, document, dryRun: false, idempotencyKey: intentKey,
|
|
27
|
+
});
|
|
28
|
+
if (!('id' in saved.data)) throw new Error('未返回已保存文档');
|
|
29
|
+
return { receipt: saved, current: (await client.stream.documents.get({ id })).data };
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
需要改脚本时构造 `{ ...current.document, script: { ...current.document.script, code: newCode } }`,保留 sdkVersion/timeoutMs;变更入口或绑定时同步修改 entries/sources 并重新 validate。不要对脱敏 programs.get.document 做展开更新。
|
|
34
|
+
|
|
35
|
+
响应是完整 CloudStreamDocumentView 或预检结果;保存草稿不会自动部署,activeDocument 可能仍是旧发布版本。VERSION_CONFLICT 后重新读取、比较并决策;不无条件覆盖。下一步发布见[部署](deploy.md)。
|