@tier0/sdk-v2 0.0.0-stage → 0.2.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.
- 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 +67 -0
- package/dist/cjs/cloud-transport.js +272 -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 +70 -0
- package/dist/cjs/data/bootstrap.js +291 -0
- package/dist/cjs/data/bootstrap.js.map +1 -0
- package/dist/cjs/data/call.d.ts +33 -0
- package/dist/cjs/data/call.js +216 -0
- package/dist/cjs/data/call.js.map +1 -0
- package/dist/cjs/data/client.d.ts +134 -0
- package/dist/cjs/data/client.js +185 -0
- package/dist/cjs/data/client.js.map +1 -0
- package/dist/cjs/data/collection.d.ts +335 -0
- package/dist/cjs/data/collection.js +601 -0
- package/dist/cjs/data/collection.js.map +1 -0
- package/dist/cjs/data/context.d.ts +12 -0
- package/dist/cjs/data/context.js +50 -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 +77 -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 +78 -0
- package/dist/cjs/data/error.js +182 -0
- package/dist/cjs/data/error.js.map +1 -0
- package/dist/cjs/data/index.d.ts +24 -0
- package/dist/cjs/data/index.js +49 -0
- package/dist/cjs/data/index.js.map +1 -0
- package/dist/cjs/data/schema.d.ts +88 -0
- package/dist/cjs/data/schema.js +657 -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/data/subscribe.d.ts +108 -0
- package/dist/cjs/data/subscribe.js +270 -0
- package/dist/cjs/data/subscribe.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 +132 -0
- package/dist/cjs/uns-v2/client.js +352 -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 +18178 -0
- package/dist/cjs/uns-v2/generated.js +144 -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/uns-v2/sse.d.ts +20 -0
- package/dist/cjs/uns-v2/sse.js +65 -0
- package/dist/cjs/uns-v2/sse.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 +67 -0
- package/dist/esm/cloud-transport.js +267 -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 +70 -0
- package/dist/esm/data/bootstrap.js +286 -0
- package/dist/esm/data/bootstrap.js.map +1 -0
- package/dist/esm/data/call.d.ts +33 -0
- package/dist/esm/data/call.js +211 -0
- package/dist/esm/data/call.js.map +1 -0
- package/dist/esm/data/client.d.ts +134 -0
- package/dist/esm/data/client.js +181 -0
- package/dist/esm/data/client.js.map +1 -0
- package/dist/esm/data/collection.d.ts +335 -0
- package/dist/esm/data/collection.js +594 -0
- package/dist/esm/data/collection.js.map +1 -0
- package/dist/esm/data/context.d.ts +12 -0
- package/dist/esm/data/context.js +44 -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 +77 -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 +78 -0
- package/dist/esm/data/error.js +176 -0
- package/dist/esm/data/error.js.map +1 -0
- package/dist/esm/data/index.d.ts +24 -0
- package/dist/esm/data/index.js +20 -0
- package/dist/esm/data/index.js.map +1 -0
- package/dist/esm/data/schema.d.ts +88 -0
- package/dist/esm/data/schema.js +646 -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/data/subscribe.d.ts +108 -0
- package/dist/esm/data/subscribe.js +265 -0
- package/dist/esm/data/subscribe.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 +132 -0
- package/dist/esm/uns-v2/client.js +343 -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 +18178 -0
- package/dist/esm/uns-v2/generated.js +141 -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/uns-v2/sse.d.ts +20 -0
- package/dist/esm/uns-v2/sse.js +60 -0
- package/dist/esm/uns-v2/sse.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 +243 -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/tier0-sdk-v2-agent/SKILL.md +73 -0
- package/skills/tier0-sdk-v2/tier0-sdk-v2-agent/references/results.md +45 -0
- package/skills/tier0-sdk-v2/tier0-sdk-v2-controls/SKILL.md +63 -0
- package/skills/tier0-sdk-v2/tier0-sdk-v2-data/SKILL.md +58 -0
- package/skills/tier0-sdk-v2/tier0-sdk-v2-data/references/consistency.md +70 -0
- package/skills/tier0-sdk-v2/tier0-sdk-v2-data/references/errors.md +82 -0
- package/skills/tier0-sdk-v2/tier0-sdk-v2-data/references/modeling.md +113 -0
- package/skills/tier0-sdk-v2/tier0-sdk-v2-data/references/read-write.md +168 -0
- package/skills/tier0-sdk-v2/tier0-sdk-v2-data/references/schema-evolution.md +36 -0
- package/skills/tier0-sdk-v2/tier0-sdk-v2-files/SKILL.md +85 -0
- package/skills/tier0-sdk-v2/tier0-sdk-v2-files/references/delete.md +22 -0
- package/skills/tier0-sdk-v2/tier0-sdk-v2-files/references/download.md +49 -0
- package/skills/tier0-sdk-v2/tier0-sdk-v2-files/references/multipart.md +42 -0
- package/skills/tier0-sdk-v2/tier0-sdk-v2-files/references/upload.md +27 -0
- package/skills/tier0-sdk-v2/tier0-sdk-v2-files/references/url.md +22 -0
- package/skills/tier0-sdk-v2/tier0-sdk-v2-members/SKILL.md +56 -0
- package/skills/tier0-sdk-v2/tier0-sdk-v2-members/references/app-members.md +41 -0
- package/skills/tier0-sdk-v2/tier0-sdk-v2-members/references/platform-members.md +56 -0
- package/skills/tier0-sdk-v2/tier0-sdk-v2-mq/SKILL.md +78 -0
- package/skills/tier0-sdk-v2/tier0-sdk-v2-mq/references/quickstart.md +69 -0
- package/skills/tier0-sdk-v2/tier0-sdk-v2-notifications/SKILL.md +42 -0
- package/skills/tier0-sdk-v2/tier0-sdk-v2-notifications/references/get.md +34 -0
- package/skills/tier0-sdk-v2/tier0-sdk-v2-notifications/references/send.md +72 -0
- package/skills/tier0-sdk-v2/tier0-sdk-v2-source/SKILL.md +38 -0
- package/skills/tier0-sdk-v2/tier0-sdk-v2-source/references/changes.md +40 -0
- package/skills/tier0-sdk-v2/tier0-sdk-v2-source/references/create.md +63 -0
- package/skills/tier0-sdk-v2/tier0-sdk-v2-source/references/delete.md +47 -0
- package/skills/tier0-sdk-v2/tier0-sdk-v2-source/references/protocols.md +36 -0
- package/skills/tier0-sdk-v2/tier0-sdk-v2-source/references/read.md +34 -0
- package/skills/tier0-sdk-v2/tier0-sdk-v2-source/references/state.md +37 -0
- package/skills/tier0-sdk-v2/tier0-sdk-v2-source/references/update.md +62 -0
- package/skills/tier0-sdk-v2/tier0-sdk-v2-stream/SKILL.md +43 -0
- package/skills/tier0-sdk-v2/tier0-sdk-v2-stream/references/create.md +56 -0
- package/skills/tier0-sdk-v2/tier0-sdk-v2-stream/references/delete.md +35 -0
- package/skills/tier0-sdk-v2/tier0-sdk-v2-stream/references/deploy.md +64 -0
- package/skills/tier0-sdk-v2/tier0-sdk-v2-stream/references/lifecycle.md +26 -0
- package/skills/tier0-sdk-v2/tier0-sdk-v2-stream/references/read.md +35 -0
- package/skills/tier0-sdk-v2/tier0-sdk-v2-stream/references/update.md +36 -0
- package/skills/tier0-sdk-v2/tier0-sdk-v2-system/SKILL.md +64 -0
- package/skills/tier0-sdk-v2/tier0-sdk-v2-system/references/info.md +23 -0
- package/skills/tier0-sdk-v2/tier0-sdk-v2-system/references/whoami.md +21 -0
- package/skills/tier0-sdk-v2/tier0-sdk-v2-uns/SKILL.md +55 -0
- package/skills/tier0-sdk-v2/tier0-sdk-v2-uns/references/create.md +56 -0
- package/skills/tier0-sdk-v2/tier0-sdk-v2-uns/references/data-workflows.md +69 -0
- package/skills/tier0-sdk-v2/tier0-sdk-v2-uns/references/delete.md +53 -0
- package/skills/tier0-sdk-v2/tier0-sdk-v2-uns/references/namespace.md +38 -0
- package/skills/tier0-sdk-v2/tier0-sdk-v2-uns/references/read.md +34 -0
- package/skills/tier0-sdk-v2/tier0-sdk-v2-uns/references/restore.md +39 -0
- package/skills/tier0-sdk-v2/tier0-sdk-v2-uns/references/update.md +62 -0
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# UNS 分页、采样与写入恢复
|
|
2
|
+
|
|
3
|
+
## 完整游标遍历
|
|
4
|
+
|
|
5
|
+
```ts
|
|
6
|
+
import { createClient } from '@tier0/sdk-v2';
|
|
7
|
+
|
|
8
|
+
export async function* scanRecords(collectionId: string, signal?: AbortSignal) {
|
|
9
|
+
const client = createClient();
|
|
10
|
+
let cursor: string | undefined;
|
|
11
|
+
const seen = new Set<string>();
|
|
12
|
+
while (true) {
|
|
13
|
+
const { data } = await client.uns.recordFind({ collectionId, limit: 200, cursor }, { signal });
|
|
14
|
+
yield data.items;
|
|
15
|
+
if (!data.pageInfo.hasMore) return;
|
|
16
|
+
const next = data.pageInfo.nextCursor;
|
|
17
|
+
if (!next || seen.has(next)) throw new Error('服务端未返回可继续的游标');
|
|
18
|
+
seen.add(next);
|
|
19
|
+
cursor = next;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
消费方逐批处理以避免无限堆积内存;需要截止时用 AbortSignal。分页保证按返回游标继续,不保证跨请求保留相同行版本;导出审计要求一致快照时必须另行确认后端能力。
|
|
25
|
+
|
|
26
|
+
## 历史采样
|
|
27
|
+
|
|
28
|
+
```ts
|
|
29
|
+
import { createClient } from '@tier0/sdk-v2';
|
|
30
|
+
|
|
31
|
+
export async function readHistory(collectionId: string, recordId: string, from: number, to: number) {
|
|
32
|
+
if (!Number.isSafeInteger(from) || !Number.isSafeInteger(to) || from < 0 || to <= from) {
|
|
33
|
+
throw new Error('时间应为有效的 Unix 毫秒范围');
|
|
34
|
+
}
|
|
35
|
+
return createClient().uns.sampleFind({
|
|
36
|
+
collectionId, recordIds: [recordId], from, to, limit: 200,
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
返回可能分页;page 模式与 limit/cursor 互斥。Record 是业务实体,Sample 是该实体的时间序列,不用覆盖 Record 伪装保存历史。sampleDeleteRange 删除明确的时间范围,与删除 Record 的操作不可混淆。
|
|
42
|
+
|
|
43
|
+
## 写入、事务与恢复
|
|
44
|
+
|
|
45
|
+
```ts
|
|
46
|
+
import { createClient, UnsV2Error, UnsV2OutcomeUnknownError, type UnsV2JSONValue } from '@tier0/sdk-v2';
|
|
47
|
+
|
|
48
|
+
export async function insertRecord(collectionId: string, id: string, data: Record<string, UnsV2JSONValue>, intentKey: string) {
|
|
49
|
+
try {
|
|
50
|
+
return await createClient().uns.recordInsertOne({
|
|
51
|
+
collectionId, id, data, dryRun: false, idempotencyKey: intentKey,
|
|
52
|
+
});
|
|
53
|
+
} catch (error) {
|
|
54
|
+
if (error instanceof UnsV2OutcomeUnknownError) {
|
|
55
|
+
return { state: 'unknown' as const, requestId: error.requestId, replaySafe: error.retry.safe };
|
|
56
|
+
}
|
|
57
|
+
if (error instanceof UnsV2Error) {
|
|
58
|
+
return { state: 'rejected' as const, code: error.code, execution: error.execution, retry: error.retry };
|
|
59
|
+
}
|
|
60
|
+
throw error;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
该函数执行真实写入,仅用于已授权的新增意图。错误的 `execution` 说明执行到哪一步:`notStarted` / `rolledBack` 没有任何改动,`committed` 已生效,`unknown`(只出现在写入)可能已生效,此时抛出的是 `UnsV2OutcomeUnknownError`。`retry.safe` 表示可以用同一请求(同一幂等键)重发,`retry.afterMs` 是建议等待时间。`client.uns` 从不自动重试;unknown 时按指定 id 读取并核对业务内容,不能只凭记录存在就判定本次成功。
|
|
66
|
+
|
|
67
|
+
recordTransactionExecute 用 opId/dependsOn 表达依赖;不要拆成若干普通请求后声称具备事务性。allowPartial 适用于支持它的普通数组写入,事务不接受。部分成功检查每项结果,修正后的失败项是新的业务请求,不能原样重放整个批次。
|
|
68
|
+
|
|
69
|
+
recordLock 返回的 token 是租约凭据,更新/续租/解锁按原记录匹配;超时或租约失效不能继续假定持锁。只读响应中的 lock 状态不包含可用于写入的令牌。
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# 删除记录与元数据
|
|
2
|
+
|
|
3
|
+
记录删除仍使用专属数据接口:
|
|
4
|
+
|
|
5
|
+
```ts
|
|
6
|
+
import { createClient, type Tier0Client } from '@tier0/sdk-v2';
|
|
7
|
+
|
|
8
|
+
export async function deleteDevice(
|
|
9
|
+
collectionId: string, id: string, intentKey: string, client: Tier0Client = createClient(),
|
|
10
|
+
) {
|
|
11
|
+
const current = (await client.uns.recordFind({ collectionId, filter: { _id: id }, limit: 1 })).data.items[0];
|
|
12
|
+
if (!current) throw new Error('记录不存在或不可见,未执行删除');
|
|
13
|
+
const receipt = await client.uns.recordDeleteOne({
|
|
14
|
+
collectionId, filter: { _id: id }, expectedRevision: current.revision,
|
|
15
|
+
dryRun: false, idempotencyKey: intentKey,
|
|
16
|
+
});
|
|
17
|
+
if (receipt.data.status !== 'committed' || String(receipt.data.deletedCount) !== '1') {
|
|
18
|
+
return { state: 'unconfirmed' as const, receipt };
|
|
19
|
+
}
|
|
20
|
+
const after = await client.uns.recordFind({ collectionId, filter: { _id: id }, limit: 1 });
|
|
21
|
+
if (after.data.items.length) throw new Error('删除有回执,但记录仍可见或已被恢复');
|
|
22
|
+
return { state: 'committed' as const, receipt };
|
|
23
|
+
}
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
元数据使用 metadataDeleteOne/Many,或 metadataFindOneAndDelete 返回删除前对象。它们执行软删除,增加 revision,不隐式级联目录后代、引用对象或集合数据。引用约束与版本冲突必须处理,不能自行扩展删除范围。
|
|
27
|
+
|
|
28
|
+
```ts
|
|
29
|
+
import { createClient, type Tier0Client } from '@tier0/sdk-v2';
|
|
30
|
+
|
|
31
|
+
export async function deleteCollection(
|
|
32
|
+
id: string, intentKey: string, client: Tier0Client = createClient(),
|
|
33
|
+
) {
|
|
34
|
+
const current = (await client.uns.metadataFindOne({ kind: 'collection', filter: { _id: id } })).data.value;
|
|
35
|
+
if (!current) throw new Error('集合不存在或不可见,未执行删除');
|
|
36
|
+
const receipt = await client.uns.metadataDeleteOne({
|
|
37
|
+
kind: 'collection', filter: { _id: id }, expectedRevision: current.revision,
|
|
38
|
+
dryRun: false, idempotencyKey: intentKey,
|
|
39
|
+
});
|
|
40
|
+
if (receipt.data.status !== 'committed' || String(receipt.data.deletedCount) !== '1') {
|
|
41
|
+
return { state: 'unconfirmed' as const, receipt };
|
|
42
|
+
}
|
|
43
|
+
const deleted = await client.uns.metadataFindOne({ kind: 'collection', filter: { _id: id }, state: 'deleted' });
|
|
44
|
+
if (!deleted.data.value) throw new Error('删除有回执,但删除状态读回未确认');
|
|
45
|
+
return { state: 'deleted' as const, receipt, deleted: deleted.data.value };
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
metadataDeleteMany 使用明确 filter 和 maxDocs。默认原子;超过上限整体拒绝,不会静默只删第一批。批量删除前可 dryRun。state 默认 active,删除对象通过 state=deleted 查询;all 同时包含两种状态。
|
|
50
|
+
|
|
51
|
+
业务记录使用 recordDeleteOne/Many,传 collectionId 和明确 filter,编辑型流程同时传 expectedRevision。不要把元数据软删除解释成逐条删除该集合的 Record。Sample 的删除是独立的显式时间范围操作,具体影响遵循当前数据 API 契约。
|
|
52
|
+
|
|
53
|
+
恢复见[恢复](restore.md)。未知写入结果保留原意图键,先按对象身份核对,不自动换键重试。
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# 目录、Topic 与元数据事务
|
|
2
|
+
|
|
3
|
+
目录、Topic、Collection 使用同一套 metadata* 方法,通过 kind 指定类型。Source/Stream 的启停、连接和发布仍使用各自专用生命周期接口;不允许把系统任务、凭据或发布历史当作普通元数据修改。
|
|
4
|
+
|
|
5
|
+
| 场景 | 方法 |
|
|
6
|
+
| --- | --- |
|
|
7
|
+
| 单条/批量新增 | metadataInsertOne / metadataInsertMany |
|
|
8
|
+
| 单条/批量条件更新 | metadataUpdateOne / metadataUpdateMany |
|
|
9
|
+
| 更新并读取原子结果 | metadataFindOneAndUpdate / metadataFindOneAndReplace |
|
|
10
|
+
| 同 kind 混合写入 | metadataBulkWrite |
|
|
11
|
+
| 跨 kind、有依赖的组合操作 | metadataTransact |
|
|
12
|
+
| 软删除并返回原对象 | metadataFindOneAndDelete |
|
|
13
|
+
| 按明确 ID 批量恢复 | metadataRestore |
|
|
14
|
+
|
|
15
|
+
普通写操作只指定一个 kind。insertMany/updateMany/deleteMany/restore 固定原子执行;bulkWrite 默认 atomic=true,原子批次不接受 ordered=false。bulkWrite 显式 atomic=false 时 ordered=true 遇错停止,false 继续,并检查 results/errors。非原子执行有任一项已提交后失败时,`execution` 为 committed、`retry.safe` 为 false,错误的 data 是累计结果:序号小于 `nextIndex` 且不在 errors 里的操作已提交;有 `unknownUntil` 时 `[nextIndex, unknownUntil)` 结局未知,用同一个幂等键重试(不带键时只有按 id 的操作能先读回再续做,所以非原子批次始终带幂等键);没有 `unknownUntil` 时从 `nextIndex` 续做。第一块就结局未知时 `execution` 为 unknown。批次最多 200 项。不要给所有对象套一个相同 expectedRevision:需要逐项版本检查时在 bulkWrite 中分别提供。
|
|
16
|
+
|
|
17
|
+
```ts
|
|
18
|
+
import { createClient, type Tier0Client } from '@tier0/sdk-v2';
|
|
19
|
+
|
|
20
|
+
export async function createDirectoryAndTopic(
|
|
21
|
+
directoryId: string, topicId: string, collectionId: string, intentKey: string,
|
|
22
|
+
client: Tier0Client = createClient(),
|
|
23
|
+
) {
|
|
24
|
+
return client.uns.metadataTransact({
|
|
25
|
+
idempotencyKey: intentKey,
|
|
26
|
+
operations: [
|
|
27
|
+
{ opId: 'directory', action: 'insertOne', kind: 'directory', id: directoryId,
|
|
28
|
+
data: { name: '设备目录', parentId: null } },
|
|
29
|
+
{ opId: 'topic', action: 'insertOne', kind: 'topic', id: topicId, dependsOn: ['directory'],
|
|
30
|
+
data: { name: '设备视图', parentId: { ref: 'directory' }, viewMode: 'records', collectionId } },
|
|
31
|
+
],
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
transact 始终原子,结果通过 opId 对应输入;dryRun=true 校验,不预留 ID 或名称。正式执行仍重新检查。创建结果引用仅用于契约支持的关系字段,不能把任意字符串或脚本当引用。
|
|
37
|
+
|
|
38
|
+
名称、父目录、Schema、引用与权限由服务端校验。移动不改变对象 ID;删除目录不隐式清空后代;删除 Topic 不删除所引用的 Collection。引用查询仍使用 references 专用方法。
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# 查询集合与记录
|
|
2
|
+
|
|
3
|
+
| 方法 | 必要输入 | 返回 data |
|
|
4
|
+
| --- | --- | --- |
|
|
5
|
+
| metadataFind | kinds;可选 filter、sort、projection、page、state | items、pageInfo |
|
|
6
|
+
| metadataFindOne | kind、filter;可选 state | value,未找到为 null |
|
|
7
|
+
| metadataCount / metadataDistinct | kind/kinds 与查询条件;distinct 还指定 field | count / values、pageInfo |
|
|
8
|
+
| collectionDescribe | collectionId | 集合结构和数据能力 |
|
|
9
|
+
| recordFind | collectionId;可选 filter、sort、limit、cursor | items、pageInfo |
|
|
10
|
+
|
|
11
|
+
元数据查询配置字段写 name、parentId;系统字段写 _id、_meta.kind、_meta.revision。返回资源的配置在 value.data 或 items[].data 中。state 为 active/deleted/all,默认 active。对象身份始终是 kind + id。
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
import { createClient, type Tier0Client } from '@tier0/sdk-v2';
|
|
15
|
+
|
|
16
|
+
export async function readDevices(collectionId: string, client: Tier0Client = createClient()) {
|
|
17
|
+
const collection = await client.uns.metadataFindOne({ kind: 'collection', filter: { _id: collectionId } });
|
|
18
|
+
if (!collection.data.value) throw new Error('集合不存在或不可见');
|
|
19
|
+
const records = await client.uns.recordFind({
|
|
20
|
+
collectionId, filter: { enabled: true }, sort: [['name', 1]], limit: 20,
|
|
21
|
+
});
|
|
22
|
+
return { definition: collection.data.value.data, items: records.data.items, pageInfo: records.data.pageInfo };
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export async function listCollections(page = 1, client: Tier0Client = createClient()) {
|
|
26
|
+
return client.uns.metadataFind({
|
|
27
|
+
kinds: ['collection'], state: 'active', sort: [['_id', 1]], page: { mode: 'offset', page, size: 20 },
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
按 pageInfo.hasMore/nextPage 继续元数据分页;不要把第一页当全量。recordFind 的游标循环见[数据工作流](data-workflows.md)。sort 是数组元组。
|
|
33
|
+
|
|
34
|
+
以上 metadataFind/FindOne 示例用于 Workspace 集成(会话、personal / agent Key)。App 凭证不能调用 metadataFind/FindOne:用 dataAppContext 精确选择授权 alias,集合的 revision、indexStatus、ttl 也在其中。数据授权不等于元数据管理授权。网络/权限错误必须传播,不能用空数组掩盖错误。
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# 恢复元数据与记录
|
|
2
|
+
|
|
3
|
+
metadataRestore 接收 kind、items[{id,expectedRevision?}],支持一个或多个明确 ID。revision 应从 state=deleted 的当前对象读取。恢复重新校验名称、父目录、Schema 与引用;不会恢复其他对象,冲突时原子批次回滚。
|
|
4
|
+
|
|
5
|
+
```ts
|
|
6
|
+
import { createClient, type Tier0Client } from '@tier0/sdk-v2';
|
|
7
|
+
|
|
8
|
+
export async function restoreCollection(
|
|
9
|
+
id: string, intentKey: string, client: Tier0Client = createClient(),
|
|
10
|
+
) {
|
|
11
|
+
const deleted = (await client.uns.metadataFindOne({ kind: 'collection', filter: { _id: id }, state: 'deleted' })).data.value;
|
|
12
|
+
if (!deleted) throw new Error('未找到待恢复集合');
|
|
13
|
+
const receipt = await client.uns.metadataRestore({
|
|
14
|
+
kind: 'collection', items: [{ id, expectedRevision: deleted.revision }], idempotencyKey: intentKey,
|
|
15
|
+
});
|
|
16
|
+
if (receipt.data.status !== 'committed' || String(receipt.data.restoredCount) !== '1') {
|
|
17
|
+
return { state: 'unconfirmed' as const, receipt };
|
|
18
|
+
}
|
|
19
|
+
const current = (await client.uns.metadataFindOne({ kind: 'collection', filter: { _id: id } })).data.value;
|
|
20
|
+
if (!current) throw new Error('恢复有回执,读回未确认');
|
|
21
|
+
return { state: 'committed' as const, receipt, current };
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export async function restoreDevice(
|
|
25
|
+
collectionId: string, id: string, intentKey: string, client: Tier0Client = createClient(),
|
|
26
|
+
) {
|
|
27
|
+
const receipt = await client.uns.recordRestore({
|
|
28
|
+
collectionId, ids: [id], dryRun: false, idempotencyKey: intentKey,
|
|
29
|
+
});
|
|
30
|
+
if (receipt.data.status !== 'committed' || !receipt.data.restoredIds.includes(id)) {
|
|
31
|
+
return { state: 'unconfirmed' as const, receipt };
|
|
32
|
+
}
|
|
33
|
+
const found = await client.uns.recordFind({ collectionId, filter: { _id: id }, limit: 1 });
|
|
34
|
+
if (!found.data.items[0]) throw new Error('恢复有回执,读回未确认');
|
|
35
|
+
return { state: 'committed' as const, receipt, current: found.data.items[0] };
|
|
36
|
+
}
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Record 恢复使用 recordRestore 的 ids(最多 100 条),重新校验当前 Schema 和有效唯一索引,冲突整批回滚。新增同 ID 或 upsert 不会隐式恢复对象。幂等键每个新意图独立。
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# 修改记录、元数据和 Schema
|
|
2
|
+
|
|
3
|
+
元数据单条使用 metadataUpdateOne 或 metadataFindOneAndUpdate;后者原子返回 value,returnDocument 可选 before/after。批量相同更新使用 metadataUpdateMany;不同更新使用 metadataBulkWrite。完整替换使用 metadataReplaceOne/metadataFindOneAndReplace,replacement 是完整可写配置。
|
|
4
|
+
|
|
5
|
+
update 首版支持 $set/$unset/$setOnInsert。字段使用裸配置路径;_id/_meta 为只读。写前读取 revision,编辑页面携带 expectedRevision,冲突后重新比较。单条 upsert 需明确 _id 等值条件,新增内容满足完整创建约束;同 ID 的软删除对象必须显式恢复。
|
|
6
|
+
|
|
7
|
+
```ts
|
|
8
|
+
import { createClient, type Tier0Client } from '@tier0/sdk-v2';
|
|
9
|
+
|
|
10
|
+
export async function renameCollection(
|
|
11
|
+
id: string, name: string, intentKey: string, client: Tier0Client = createClient(),
|
|
12
|
+
) {
|
|
13
|
+
const current = (await client.uns.metadataFindOne({ kind: 'collection', filter: { _id: id } })).data.value;
|
|
14
|
+
if (!current) throw new Error('集合不存在或不可见');
|
|
15
|
+
return client.uns.metadataFindOneAndUpdate({
|
|
16
|
+
kind: 'collection', filter: { _id: id }, expectedRevision: current.revision,
|
|
17
|
+
update: { $set: { name } }, returnDocument: 'after', upsert: false, idempotencyKey: intentKey,
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
修改 Schema 时先构造完整 recordSchema,再用 $set 更新该字段。它不迁移已有记录,必须兼容保留数据与引用。没有修改的 sampleSchema/indexes 保持原值。先 dryRun,再用独立正式意图键提交。
|
|
23
|
+
|
|
24
|
+
```ts
|
|
25
|
+
import { createClient, type Tier0Client, type Schema } from '@tier0/sdk-v2';
|
|
26
|
+
|
|
27
|
+
export async function replaceRecordSchema(
|
|
28
|
+
id: string, recordSchema: Schema, intentKey: string, client: Tier0Client = createClient(),
|
|
29
|
+
) {
|
|
30
|
+
const current = (await client.uns.metadataFindOne({ kind: 'collection', filter: { _id: id } })).data.value;
|
|
31
|
+
if (!current) throw new Error('集合不存在或不可见');
|
|
32
|
+
const request = { kind: 'collection' as const, filter: { _id: id },
|
|
33
|
+
expectedRevision: current.revision, update: { $set: { recordSchema } } };
|
|
34
|
+
const preview = await client.uns.metadataUpdateOne({ ...request, dryRun: true });
|
|
35
|
+
if (preview.data.status !== 'validated') throw new Error('Schema 预检未通过');
|
|
36
|
+
return client.uns.metadataUpdateOne({ ...request, dryRun: false, idempotencyKey: intentKey });
|
|
37
|
+
}
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
业务记录仍使用 recordUpdateOne:传 collectionId/filter/update,按需携带 expectedRevision。metadataUpdateOne 不能更新 Record 的业务内容。matchedCount 和 modifiedCount 不等价;值未变化时 modifiedCount 可为 0。
|
|
41
|
+
|
|
42
|
+
```ts
|
|
43
|
+
import { createClient, type Tier0Client } from '@tier0/sdk-v2';
|
|
44
|
+
|
|
45
|
+
export async function renameDevice(
|
|
46
|
+
collectionId: string, id: string, name: string, intentKey: string,
|
|
47
|
+
client: Tier0Client = createClient(),
|
|
48
|
+
) {
|
|
49
|
+
const current = (await client.uns.recordFind({ collectionId, filter: { _id: id }, limit: 1 })).data.items[0];
|
|
50
|
+
if (!current) throw new Error('记录不存在或不可见');
|
|
51
|
+
const receipt = await client.uns.recordUpdateOne({
|
|
52
|
+
collectionId, filter: { _id: id }, expectedRevision: current.revision,
|
|
53
|
+
update: { $set: { name } }, upsert: false, dryRun: false, idempotencyKey: intentKey,
|
|
54
|
+
});
|
|
55
|
+
if (receipt.data.status !== 'committed' || String(receipt.data.matchedCount) !== '1') {
|
|
56
|
+
return { state: 'unconfirmed' as const, receipt };
|
|
57
|
+
}
|
|
58
|
+
const after = await client.uns.recordFind({ collectionId, filter: { _id: id }, limit: 1 });
|
|
59
|
+
if (after.data.items[0]?.data.name !== name) throw new Error('读回名称与目标不一致');
|
|
60
|
+
return { state: 'committed' as const, receipt, current: after.data.items[0] };
|
|
61
|
+
}
|
|
62
|
+
```
|