@tier0/sdk-v2 0.9.9 → 0.9.10
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/CHANGELOG.md +6 -0
- package/README.md +6 -4
- package/dist/cjs/connection-diagnostics.d.ts +2 -0
- package/dist/cjs/connection-diagnostics.js +20 -0
- package/dist/cjs/connection-diagnostics.js.map +1 -0
- package/dist/cjs/data/error.d.ts +1 -1
- package/dist/cjs/data/error.js +2 -2
- package/dist/cjs/data/error.js.map +1 -1
- package/dist/cjs/openapi/client.js +3 -2
- package/dist/cjs/openapi/client.js.map +1 -1
- package/dist/cjs/uns-v2/client.js +3 -2
- package/dist/cjs/uns-v2/client.js.map +1 -1
- package/dist/esm/connection-diagnostics.d.ts +2 -0
- package/dist/esm/connection-diagnostics.js +17 -0
- package/dist/esm/connection-diagnostics.js.map +1 -0
- package/dist/esm/data/error.d.ts +1 -1
- package/dist/esm/data/error.js +2 -2
- package/dist/esm/data/error.js.map +1 -1
- package/dist/esm/openapi/client.js +3 -2
- package/dist/esm/openapi/client.js.map +1 -1
- package/dist/esm/uns-v2/client.js +3 -2
- package/dist/esm/uns-v2/client.js.map +1 -1
- package/package.json +1 -1
- package/skills/tier0-sdk-v2/SKILL.md +2 -0
- package/skills/tier0-sdk-v2/references/local-connection.md +61 -0
- package/skills/tier0-sdk-v2/tier0-sdk-v2-data/references/consistency.md +2 -2
- package/skills/tier0-sdk-v2/tier0-sdk-v2-data/references/errors.md +4 -2
- package/skills/tier0-sdk-v2/tier0-sdk-v2-data/references/modeling.md +3 -1
- package/skills/tier0-sdk-v2/tier0-sdk-v2-data/references/schema-evolution.md +2 -0
- package/skills/tier0-sdk-v2/tier0-sdk-v2-uns/SKILL.md +1 -1
- package/skills/tier0-sdk-v2/tier0-sdk-v2-uns/references/delete.md +25 -19
- package/skills/tier0-sdk-v2/tier0-sdk-v2-uns/references/namespace.md +3 -3
- package/skills/tier0-sdk-v2/tier0-sdk-v2-uns/references/read.md +7 -1
- package/skills/tier0-sdk-v2/tier0-sdk-v2-uns/references/restore.md +12 -13
|
@@ -1,56 +1,62 @@
|
|
|
1
1
|
# 删除记录与元数据
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
记录删除使用专属数据接口,`expectedRevision` 取自已有记录或最近写回执;没有版本时再读取:
|
|
4
4
|
|
|
5
5
|
```ts
|
|
6
|
-
import { createClient, type Tier0Client } from '@tier0/sdk-v2';
|
|
6
|
+
import { createClient, type Tier0Client, type UnsV2Integer } from '@tier0/sdk-v2';
|
|
7
7
|
|
|
8
8
|
export async function deleteDevice(
|
|
9
|
-
collectionId: string, id: string,
|
|
9
|
+
collectionId: string, id: string, expectedRevision: UnsV2Integer,
|
|
10
|
+
intentKey: string, client: Tier0Client = createClient(),
|
|
10
11
|
) {
|
|
11
|
-
const current = (await client.uns.recordFind({ collectionId, filter: { _id: id }, limit: 1 })).data.items[0];
|
|
12
|
-
if (!current) throw new Error('记录不存在或不可见,未执行删除');
|
|
13
12
|
const receipt = await client.uns.recordDeleteOne({
|
|
14
|
-
collectionId, filter: { _id: id }, expectedRevision
|
|
13
|
+
collectionId, filter: { _id: id }, expectedRevision,
|
|
15
14
|
dryRun: false, idempotencyKey: intentKey,
|
|
16
15
|
});
|
|
17
16
|
if (receipt.data.status !== 'committed' || String(receipt.data.deletedCount) !== '1') {
|
|
18
17
|
return { state: 'unconfirmed' as const, receipt };
|
|
19
18
|
}
|
|
20
|
-
const after = await client.uns.recordFind({ collectionId, filter: { _id: id }, limit: 1 });
|
|
21
|
-
if (after.data.items.length) throw new Error('删除有回执,但记录仍可见或已被恢复');
|
|
22
19
|
return { state: 'committed' as const, receipt };
|
|
23
20
|
}
|
|
24
21
|
```
|
|
25
22
|
|
|
26
|
-
元数据使用 metadataDeleteOne/Many
|
|
23
|
+
元数据使用 metadataDeleteOne/Many;需要删除前对象时传 returnDocument:before。已知 revision 可直接提交,不要求重新读取或先 dryRun。
|
|
27
24
|
|
|
28
25
|
```ts
|
|
29
|
-
import { createClient, type Tier0Client } from '@tier0/sdk-v2';
|
|
26
|
+
import { createClient, type Tier0Client, type UnsV2Integer } from '@tier0/sdk-v2';
|
|
30
27
|
|
|
31
28
|
export async function deleteCollection(
|
|
32
|
-
id: string,
|
|
29
|
+
id: string, expectedRevision: UnsV2Integer,
|
|
30
|
+
intentKey: string, client: Tier0Client = createClient(),
|
|
33
31
|
) {
|
|
34
|
-
const current = (await client.uns.metadataFind({ kind: 'collection', filter: { _id: id }, limit: 1 })).data.items[0];
|
|
35
|
-
if (!current) throw new Error('集合不存在或不可见,未执行删除');
|
|
36
32
|
const receipt = await client.uns.metadataDeleteOne({
|
|
37
|
-
kind: 'collection', filter: { _id: id }, expectedRevision
|
|
33
|
+
kind: 'collection', filter: { _id: id }, expectedRevision,
|
|
38
34
|
dryRun: false, idempotencyKey: intentKey,
|
|
39
35
|
});
|
|
40
36
|
if (receipt.data.status !== 'committed' || String(receipt.data.deletedCount) !== '1') {
|
|
41
37
|
return { state: 'unconfirmed' as const, receipt };
|
|
42
38
|
}
|
|
43
|
-
|
|
44
|
-
if (!deleted.data.items[0]) throw new Error('删除有回执,但删除状态读回未确认');
|
|
45
|
-
return { state: 'deleted' as const, receipt, deleted: deleted.data.items[0] };
|
|
39
|
+
return { state: 'deleted' as const, receipt };
|
|
46
40
|
}
|
|
47
41
|
```
|
|
48
42
|
|
|
49
|
-
metadataDeleteMany 使用明确 filter 和 maxDocs
|
|
43
|
+
metadataDeleteMany 使用明确 filter 和 maxDocs。默认原子;超过上限整体拒绝。目录删除的 maxDocs 与 deletedCount 只计显式匹配项,不计隐式级联后代;服务端会去重父子项,无需逐个删除后代。需要预览时可 dryRun。state 默认 active,回收对象通过 state=deleted 查询;all 包含两种状态。
|
|
44
|
+
|
|
45
|
+
## 回收规则
|
|
46
|
+
|
|
47
|
+
软删除增加 revision,保留 Record、Sample 与查询索引;历史按既有授权只读,数据写入和后台 TTL 清理停止。外部引用不阻止回收,引用方配置保留;删除 Topic 不删除其引用的 Collection。
|
|
48
|
+
|
|
49
|
+
| 操作 | 范围与授权 |
|
|
50
|
+
| --- | --- |
|
|
51
|
+
| 元数据软删除 | 目录在同一事务内回收有效子树;此前独立回收的对象不加入本次批次。既有授权保留。 |
|
|
52
|
+
| App 集合 archive | 归档指定自有集合,撤销调用 App 对它的 grant;其他未撤销授权仍可读取历史。 |
|
|
53
|
+
| App 移入回收站 | 停用该 App,联动回收其自有集合和明确专属目录;借用集合、共享目录保留,其他活跃授权主体仍可读取历史。 |
|
|
54
|
+
|
|
55
|
+
恢复范围和授权区别见[恢复](restore.md)。保留的物理索引仍占配额,归档不释放索引空间。
|
|
50
56
|
|
|
51
57
|
业务记录使用 recordDeleteOne/Many,传 collectionId 和明确 filter,编辑型流程同时传 expectedRevision。不要把元数据软删除解释成逐条删除该集合的 Record。Sample 的删除是独立的显式时间范围操作,具体影响遵循当前数据 API 契约。
|
|
52
58
|
|
|
53
|
-
|
|
59
|
+
成功回执已确认本次操作,不再固定读回验证。结果未知时保留原意图键,按对象身份核对;需要展示最新状态时再刷新。版本冲突应重新读取并由调用方处理,不自动覆盖。
|
|
54
60
|
|
|
55
61
|
## 永久删除回收站集合
|
|
56
62
|
|
|
@@ -6,8 +6,8 @@
|
|
|
6
6
|
|
|
7
7
|
| 凭证 | Namespace / metadata 查询 | 发现并读取集合 |
|
|
8
8
|
| --- | --- | --- |
|
|
9
|
-
| 未绑定 App 的 Agent / Personal Key | 有当前工作空间权限及 Key scope 时可用;Agent Key 还会复核真实负责人的状态和权限 |
|
|
10
|
-
| App Key | 当前不开放;`appCollectionsList` 也不能调用 | `dataAppContext({})`
|
|
9
|
+
| 未绑定 App 的 Agent / Personal Key | 有当前工作空间权限及 Key scope 时可用;Agent Key 还会复核真实负责人的状态和权限 | 已知集合 ID 时直接调用 `recordFind`;需要发现集合时按工作空间权限查询元数据 |
|
|
10
|
+
| App Key | 当前不开放;`appCollectionsList` 也不能调用 | 已知集合 ID 时直接调用 `recordFind`;需要发现集合及结构时使用 `dataAppContext({})` |
|
|
11
11
|
| 平台系统 Service Key | 按实际系统凭证授权,不按“Agent 正在调用”推定权限 | 带 Builder 目标时,指定 App 操作可使用目标 App 视角;不代表所有查询都变成 App 视角 |
|
|
12
12
|
|
|
13
13
|
目录位置不产生数据授权。App 自有集合的正常创建流程提供相应授权,但读取仍受凭证权限、App 状态及数据策略约束;不能仅凭 `ownerAppId` 推定任何接口都可调用。SDK 和 MCP 使用相同凭证时仍受服务端授权约束。
|
|
@@ -60,4 +60,4 @@ export async function createDirectoryAndTopic(
|
|
|
60
60
|
|
|
61
61
|
transact 始终原子,结果通过 opId 对应输入;dryRun=true 校验,不预留 ID 或名称。正式执行仍重新检查。创建结果引用仅用于契约支持的关系字段,不能把任意字符串或脚本当引用。
|
|
62
62
|
|
|
63
|
-
名称、父目录、Schema、引用与权限由服务端校验。移动不改变对象 ID
|
|
63
|
+
名称、父目录、Schema、引用与权限由服务端校验。移动不改变对象 ID;删除目录原子回收有效子树,删除 Topic 不删除所引用的 Collection。外部引用不阻止回收;范围、授权和恢复规则见[删除](delete.md#回收规则)与[恢复](restore.md)。引用查询仍使用 references 专用方法。
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
## App Key:从授权上下文读取
|
|
4
4
|
|
|
5
|
-
App Key
|
|
5
|
+
App Key 已知集合 ID 时直接调用 `recordFind`;需要发现集合时使用 `dataAppContext`,不调用 `namespace`、`metadataFind` 或 `appCollectionsList`。上下文包含可访问集合的名称、目录路径、Schema 和有效权限;按已配置 alias 精确定位,不能随意选择列表第一项。
|
|
6
6
|
|
|
7
7
|
```ts
|
|
8
8
|
import { createClient, type Tier0Client } from '@tier0/sdk-v2';
|
|
@@ -55,3 +55,9 @@ export async function listCollections(page = 1, client: Tier0Client = createClie
|
|
|
55
55
|
按 pageInfo.hasMore/nextPage 继续元数据分页;不要把第一页当全量。recordFind 的游标循环见[数据工作流](data-workflows.md)。sort 是数组元组。
|
|
56
56
|
|
|
57
57
|
以上 metadataFind 示例用于 Workspace 集成(会话、personal / agent Key)。App 凭证不能调用 metadataFind:用 dataAppContext 精确选择授权 alias,集合的 revision、indexStatus、ttl 也在其中。数据授权不等于元数据管理授权。网络/权限错误必须传播,不能用空数组掩盖错误。
|
|
58
|
+
|
|
59
|
+
## 回收集合的历史读取
|
|
60
|
+
|
|
61
|
+
按原 collectionId 读取 Record、Sample、count 或 aggregate;既有授权、员工行规则和字段权限仍生效。活跃 Topic 可继续读取其引用的回收集合。活跃 App 的 dataAppContext 保留仍可读的回收集合,但不授予新增能力;回收中的 App 自身不能运行。
|
|
62
|
+
|
|
63
|
+
已知 ID 直接读取,不必先恢复集合或查询元数据。数据层也可用 `data.collection({ collectionId })`,不会 ensure、写种子或补授权。只有 Workspace 集成确需回收对象定义时,才用 metadataFind 的 state=deleted 或 all;App Key 仍不调用该接口。[回收规则](delete.md#回收规则)说明写入和恢复边界。
|
|
@@ -1,24 +1,25 @@
|
|
|
1
1
|
# 恢复元数据与记录
|
|
2
2
|
|
|
3
|
-
metadataRestore 接收 kind、items[{id,expectedRevision?}]
|
|
3
|
+
metadataRestore 接收 kind、items[{id,expectedRevision?}]。编辑流程复用回收列表中的 revision,没有版本时再用 state=deleted 读取。恢复由服务端校验名称、父目录、Schema 与引用,冲突时原子批次回滚。
|
|
4
|
+
|
|
5
|
+
恢复目录会一并恢复同次回收的子树,此前独立回收的对象保持原状态。随目录回收的子项应通过原目录恢复;单独恢复返回 CONDITION_FAILED / DIRECTORY_IN_TRASH。无需枚举子项逐个恢复;若请求同时列出父子项,服务端仍检查每项 expectedRevision。
|
|
6
|
+
|
|
7
|
+
随 App 回收的对象通过恢复原 App 处理,此前独立回收的对象保持原状态;OWNER_APP_TRASHED 不应触发重建或写入重试。通用元数据恢复不补回撤销的 grant;App 集合 restore 则恢复该 alias 最近归档的集合并重新授权。此前独立删除的记录不会随集合恢复。当前 archive / restore 不逐条重写记录;2000 条上限仅适用于旧 recordsArchivedAt 墓碑恢复。
|
|
4
8
|
|
|
5
9
|
```ts
|
|
6
|
-
import { createClient, type Tier0Client } from '@tier0/sdk-v2';
|
|
10
|
+
import { createClient, type Tier0Client, type UnsV2Integer } from '@tier0/sdk-v2';
|
|
7
11
|
|
|
8
12
|
export async function restoreCollection(
|
|
9
|
-
id: string,
|
|
13
|
+
id: string, expectedRevision: UnsV2Integer,
|
|
14
|
+
intentKey: string, client: Tier0Client = createClient(),
|
|
10
15
|
) {
|
|
11
|
-
const deleted = (await client.uns.metadataFind({ kind: 'collection', filter: { _id: id }, state: 'deleted', limit: 1 })).data.items[0];
|
|
12
|
-
if (!deleted) throw new Error('未找到待恢复集合');
|
|
13
16
|
const receipt = await client.uns.metadataRestore({
|
|
14
|
-
kind: 'collection', items: [{ id, expectedRevision
|
|
17
|
+
kind: 'collection', items: [{ id, expectedRevision }], idempotencyKey: intentKey,
|
|
15
18
|
});
|
|
16
19
|
if (receipt.data.status !== 'committed' || String(receipt.data.restoredCount) !== '1') {
|
|
17
20
|
return { state: 'unconfirmed' as const, receipt };
|
|
18
21
|
}
|
|
19
|
-
|
|
20
|
-
if (!current) throw new Error('恢复有回执,读回未确认');
|
|
21
|
-
return { state: 'committed' as const, receipt, current };
|
|
22
|
+
return { state: 'committed' as const, receipt };
|
|
22
23
|
}
|
|
23
24
|
|
|
24
25
|
export async function restoreDevice(
|
|
@@ -30,10 +31,8 @@ export async function restoreDevice(
|
|
|
30
31
|
if (receipt.data.status !== 'committed' || !receipt.data.restoredIds.includes(id)) {
|
|
31
32
|
return { state: 'unconfirmed' as const, receipt };
|
|
32
33
|
}
|
|
33
|
-
|
|
34
|
-
if (!found.data.items[0]) throw new Error('恢复有回执,读回未确认');
|
|
35
|
-
return { state: 'committed' as const, receipt, current: found.data.items[0] };
|
|
34
|
+
return { state: 'committed' as const, receipt };
|
|
36
35
|
}
|
|
37
36
|
```
|
|
38
37
|
|
|
39
|
-
Record 恢复使用 recordRestore 的 ids(最多 100 条),重新校验当前 Schema 和有效唯一索引,冲突整批回滚。新增同 ID 或 upsert
|
|
38
|
+
Record 恢复使用 recordRestore 的 ids(最多 100 条),重新校验当前 Schema 和有效唯一索引,冲突整批回滚。新增同 ID 或 upsert 不会隐式恢复对象。幂等键每个新意图独立;结果未知时核对原对象,正常成功无需额外读回。需要最新快照时,元数据恢复可使用回执 items,记录恢复可按需查询。
|