@appthen/sdk-node 0.0.0 → 0.0.2
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/dist/index.d.ts +9 -2
- package/dist/index.js +11 -0
- package/dist-cjs/index.d.ts +9 -2
- package/dist-cjs/index.js +11 -0
- package/package.json +4 -3
- package/skills/appthen-platform-sdk/SKILL.md +118 -0
package/dist/index.d.ts
CHANGED
|
@@ -51,8 +51,8 @@ export declare class TenantAppAuthProvider implements AuthProvider {
|
|
|
51
51
|
}
|
|
52
52
|
export declare function createChatHubNodeClient(options: CreateChatHubNodeClientOptions): ChatHubClient;
|
|
53
53
|
export declare function createChatHubNodeRuntime(options: CreateChatHubNodeRuntimeOptions): ChatHubAppRuntime;
|
|
54
|
-
import { PlatformApi, type PlatformProvisionTenantInput, type PlatformProvisionTenantResult, type PlatformResolveTenantResult, type PlatformSyncSubjectInput, type PlatformSyncSubjectResult } from '@appthen/sdk-core';
|
|
55
|
-
export { PlatformApi, type PlatformProvisionTenantInput, type PlatformProvisionTenantResult, type PlatformResolveTenantResult, type PlatformSyncSubjectInput, type PlatformSyncSubjectResult, } from '@appthen/sdk-core';
|
|
54
|
+
import { PlatformApi, type PlatformNotifyInput, type PlatformNotifyRequest, type PlatformNotifyResult, type PlatformProvisionTenantInput, type PlatformProvisionTenantResult, type PlatformResolveTenantResult, type PlatformSyncSubjectInput, type PlatformSyncSubjectResult } from '@appthen/sdk-core';
|
|
55
|
+
export { PlatformApi, type PlatformLazySubject, type PlatformNotifyInput, type PlatformNotifyRequest, type PlatformNotifyResult, type PlatformNotifySelector, type PlatformProvisionTenantInput, type PlatformProvisionTenantResult, type PlatformResolveTenantResult, type PlatformSyncSubjectInput, type PlatformSyncSubjectResult, } from '@appthen/sdk-core';
|
|
56
56
|
export interface CreateAppThenSdkOptions {
|
|
57
57
|
baseUrl: string;
|
|
58
58
|
accessKey: string;
|
|
@@ -70,11 +70,18 @@ export declare class PlatformTenantClient {
|
|
|
70
70
|
constructor(platform: PlatformApi, tenantId: string);
|
|
71
71
|
/** 幂等代同步成员:重复推送只产生一个 Subject,可安全重试。 */
|
|
72
72
|
syncSubject(input: PlatformSyncSubjectInput): Promise<PlatformSyncSubjectResult>;
|
|
73
|
+
/**
|
|
74
|
+
* 按标签/条件圈人并直接触达(声明式):sender 按声明 lazily create-or-get;
|
|
75
|
+
* 收件人 selector(标签圈人)或 receive(单点声明,如微信客服消息迁移)二选一。
|
|
76
|
+
*/
|
|
77
|
+
notify(request: PlatformNotifyRequest, notify: PlatformNotifyInput): Promise<PlatformNotifyResult>;
|
|
73
78
|
}
|
|
74
79
|
export declare class AppThenPlatformSdk {
|
|
75
80
|
private readonly http;
|
|
76
81
|
readonly platform: PlatformApi;
|
|
77
82
|
constructor(platform: PlatformApi, http: NodeFetchHttpAdapter);
|
|
83
|
+
/** 获取某个被授权租户的操作客户端(per-tenant,调用自动携带 targetTenantId)。 */
|
|
84
|
+
platformTenant(tenantId: string): PlatformTenantClient;
|
|
78
85
|
/** 代开通租户(目标租户尚不存在,故在 sdk 根上而非 tenant client)。 */
|
|
79
86
|
provisionTenant(input: PlatformProvisionTenantInput): Promise<PlatformProvisionTenantResult>;
|
|
80
87
|
/** 对账:externalCorrelationId → tenantId + grants。未命中抛 CORRELATION_MISMATCH。 */
|
package/dist/index.js
CHANGED
|
@@ -178,12 +178,23 @@ export class PlatformTenantClient {
|
|
|
178
178
|
async syncSubject(input) {
|
|
179
179
|
return this.platform.syncSubject(this.tenantId, input);
|
|
180
180
|
}
|
|
181
|
+
/**
|
|
182
|
+
* 按标签/条件圈人并直接触达(声明式):sender 按声明 lazily create-or-get;
|
|
183
|
+
* 收件人 selector(标签圈人)或 receive(单点声明,如微信客服消息迁移)二选一。
|
|
184
|
+
*/
|
|
185
|
+
async notify(request, notify) {
|
|
186
|
+
return this.platform.notify(this.tenantId, request, notify);
|
|
187
|
+
}
|
|
181
188
|
}
|
|
182
189
|
export class AppThenPlatformSdk {
|
|
183
190
|
constructor(platform, http) {
|
|
184
191
|
this.http = http;
|
|
185
192
|
this.platform = platform;
|
|
186
193
|
}
|
|
194
|
+
/** 获取某个被授权租户的操作客户端(per-tenant,调用自动携带 targetTenantId)。 */
|
|
195
|
+
platformTenant(tenantId) {
|
|
196
|
+
return new PlatformTenantClient(this.platform, tenantId);
|
|
197
|
+
}
|
|
187
198
|
/** 代开通租户(目标租户尚不存在,故在 sdk 根上而非 tenant client)。 */
|
|
188
199
|
async provisionTenant(input) {
|
|
189
200
|
return this.platform.provisionTenant(input);
|
package/dist-cjs/index.d.ts
CHANGED
|
@@ -51,8 +51,8 @@ export declare class TenantAppAuthProvider implements AuthProvider {
|
|
|
51
51
|
}
|
|
52
52
|
export declare function createChatHubNodeClient(options: CreateChatHubNodeClientOptions): ChatHubClient;
|
|
53
53
|
export declare function createChatHubNodeRuntime(options: CreateChatHubNodeRuntimeOptions): ChatHubAppRuntime;
|
|
54
|
-
import { PlatformApi, type PlatformProvisionTenantInput, type PlatformProvisionTenantResult, type PlatformResolveTenantResult, type PlatformSyncSubjectInput, type PlatformSyncSubjectResult } from '@appthen/sdk-core';
|
|
55
|
-
export { PlatformApi, type PlatformProvisionTenantInput, type PlatformProvisionTenantResult, type PlatformResolveTenantResult, type PlatformSyncSubjectInput, type PlatformSyncSubjectResult, } from '@appthen/sdk-core';
|
|
54
|
+
import { PlatformApi, type PlatformNotifyInput, type PlatformNotifyRequest, type PlatformNotifyResult, type PlatformProvisionTenantInput, type PlatformProvisionTenantResult, type PlatformResolveTenantResult, type PlatformSyncSubjectInput, type PlatformSyncSubjectResult } from '@appthen/sdk-core';
|
|
55
|
+
export { PlatformApi, type PlatformLazySubject, type PlatformNotifyInput, type PlatformNotifyRequest, type PlatformNotifyResult, type PlatformNotifySelector, type PlatformProvisionTenantInput, type PlatformProvisionTenantResult, type PlatformResolveTenantResult, type PlatformSyncSubjectInput, type PlatformSyncSubjectResult, } from '@appthen/sdk-core';
|
|
56
56
|
export interface CreateAppThenSdkOptions {
|
|
57
57
|
baseUrl: string;
|
|
58
58
|
accessKey: string;
|
|
@@ -70,11 +70,18 @@ export declare class PlatformTenantClient {
|
|
|
70
70
|
constructor(platform: PlatformApi, tenantId: string);
|
|
71
71
|
/** 幂等代同步成员:重复推送只产生一个 Subject,可安全重试。 */
|
|
72
72
|
syncSubject(input: PlatformSyncSubjectInput): Promise<PlatformSyncSubjectResult>;
|
|
73
|
+
/**
|
|
74
|
+
* 按标签/条件圈人并直接触达(声明式):sender 按声明 lazily create-or-get;
|
|
75
|
+
* 收件人 selector(标签圈人)或 receive(单点声明,如微信客服消息迁移)二选一。
|
|
76
|
+
*/
|
|
77
|
+
notify(request: PlatformNotifyRequest, notify: PlatformNotifyInput): Promise<PlatformNotifyResult>;
|
|
73
78
|
}
|
|
74
79
|
export declare class AppThenPlatformSdk {
|
|
75
80
|
private readonly http;
|
|
76
81
|
readonly platform: PlatformApi;
|
|
77
82
|
constructor(platform: PlatformApi, http: NodeFetchHttpAdapter);
|
|
83
|
+
/** 获取某个被授权租户的操作客户端(per-tenant,调用自动携带 targetTenantId)。 */
|
|
84
|
+
platformTenant(tenantId: string): PlatformTenantClient;
|
|
78
85
|
/** 代开通租户(目标租户尚不存在,故在 sdk 根上而非 tenant client)。 */
|
|
79
86
|
provisionTenant(input: PlatformProvisionTenantInput): Promise<PlatformProvisionTenantResult>;
|
|
80
87
|
/** 对账:externalCorrelationId → tenantId + grants。未命中抛 CORRELATION_MISMATCH。 */
|
package/dist-cjs/index.js
CHANGED
|
@@ -203,6 +203,13 @@ class PlatformTenantClient {
|
|
|
203
203
|
async syncSubject(input) {
|
|
204
204
|
return this.platform.syncSubject(this.tenantId, input);
|
|
205
205
|
}
|
|
206
|
+
/**
|
|
207
|
+
* 按标签/条件圈人并直接触达(声明式):sender 按声明 lazily create-or-get;
|
|
208
|
+
* 收件人 selector(标签圈人)或 receive(单点声明,如微信客服消息迁移)二选一。
|
|
209
|
+
*/
|
|
210
|
+
async notify(request, notify) {
|
|
211
|
+
return this.platform.notify(this.tenantId, request, notify);
|
|
212
|
+
}
|
|
206
213
|
}
|
|
207
214
|
exports.PlatformTenantClient = PlatformTenantClient;
|
|
208
215
|
class AppThenPlatformSdk {
|
|
@@ -210,6 +217,10 @@ class AppThenPlatformSdk {
|
|
|
210
217
|
this.http = http;
|
|
211
218
|
this.platform = platform;
|
|
212
219
|
}
|
|
220
|
+
/** 获取某个被授权租户的操作客户端(per-tenant,调用自动携带 targetTenantId)。 */
|
|
221
|
+
platformTenant(tenantId) {
|
|
222
|
+
return new PlatformTenantClient(this.platform, tenantId);
|
|
223
|
+
}
|
|
213
224
|
/** 代开通租户(目标租户尚不存在,故在 sdk 根上而非 tenant client)。 */
|
|
214
225
|
async provisionTenant(input) {
|
|
215
226
|
return this.platform.provisionTenant(input);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@appthen/sdk-node",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.2",
|
|
4
4
|
"description": "AppThen Conversation Hub SDK - Node.js server adapter",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -16,10 +16,11 @@
|
|
|
16
16
|
"files": [
|
|
17
17
|
"dist",
|
|
18
18
|
"README.md",
|
|
19
|
-
"dist-cjs"
|
|
19
|
+
"dist-cjs",
|
|
20
|
+
"skills"
|
|
20
21
|
],
|
|
21
22
|
"dependencies": {
|
|
22
|
-
"@appthen/sdk-core": "0.0.
|
|
23
|
+
"@appthen/sdk-core": "0.0.2"
|
|
23
24
|
},
|
|
24
25
|
"sideEffects": false,
|
|
25
26
|
"license": "UNLICENSED",
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: appthen-platform-sdk
|
|
3
|
+
description: 对接 AppThen 开放平台「服务商(代运营)」能力时使用。当任务涉及:用 @appthen/sdk-node 接入 AppThen、代开通租户、幂等同步成员(含 tags 一次推全)、按标签/条件圈人触达(notify 发消息/通知)、externalCorrelationId 对账、启停授权、认领激活(claimToken)时读取本技能。触发词:appthen sdk、sdk-node、代运营、服务商接入、platform token、代同步、notify、触达、按标签推送、claimToken。
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# AppThen Platform SDK(@appthen/sdk-node)使用指南
|
|
7
|
+
|
|
8
|
+
## 模型(先读,避免用错)
|
|
9
|
+
|
|
10
|
+
- 心智模型与**微信第三方平台同构**:你的 SaaS 后端 = 服务商(第三方平台),AppThen 的每个租户 = 公众号。**所有能力都是"给单一租户"的,你只是代替被授权租户调用。**
|
|
11
|
+
- 凭证:`accessKey` / `accessSecret` **永远只存在于你的后端**。platform token(2h)由 SDK 自动换取与刷新——**不要自己管 token**。
|
|
12
|
+
- 授权是双向的:代开通 → 实验室管理员凭 `claimToken` 认领激活(≈扫码授权)→ grant `active` 后才能代操作。
|
|
13
|
+
- **零预建(声明式贯穿)**:主体类(classId)、通知会话类型(typeId)、sender / receiver 都不用预建——随调用声明 lazily 自动创建(幂等键 = externalIdentity)。
|
|
14
|
+
- 本包是 monorepo `packages/appthen-sdk`(`@appthen/sdk-core/node/web/react` 四包);本技能随包分发,agent 可整体 symlink 到自己的 skills 目录。
|
|
15
|
+
|
|
16
|
+
## 安装
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
# AppThen 仓库内:workspace 直接可用(packages/appthen-sdk)
|
|
20
|
+
# 外部 SaaS(发布后):
|
|
21
|
+
pnpm add @appthen/sdk-node
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## 快速开始
|
|
25
|
+
|
|
26
|
+
```ts
|
|
27
|
+
import { createAppThenSdk } from '@appthen/sdk-node';
|
|
28
|
+
|
|
29
|
+
const sdk = createAppThenSdk({
|
|
30
|
+
baseUrl: 'https://<appthen-host>',
|
|
31
|
+
accessKey: process.env.APPTHEN_ACCESS_KEY!, // AppThen 控制台「接入凭证」创建(带 platformId)
|
|
32
|
+
accessSecret: process.env.APPTHEN_ACCESS_SECRET!, // 仅创建时一次明文展示,入库你的密钥管理
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
// 1) 代开通租户——幂等:同 externalCorrelationId 重复调用返回已有租户(created:false)
|
|
36
|
+
const provisioned = await sdk.provisionTenant({
|
|
37
|
+
name: 'XX 检测实验室',
|
|
38
|
+
externalCorrelationId: 'lims_org_10086', // 对账锚:LIMS 机构 ID ↔ AppThen tenantId,必填
|
|
39
|
+
});
|
|
40
|
+
// 首次返回 claimToken(7d)→ 交给实验室管理员完成认领激活(见下)
|
|
41
|
+
|
|
42
|
+
// 2) 按租户组织调用(per-tenant client,自动携带 targetTenantId)
|
|
43
|
+
const lab = sdk.platformTenant(provisioned.tenantId);
|
|
44
|
+
await lab.syncSubject({
|
|
45
|
+
classId: 'class_lims_member', // 不存在会自动创建(external 类)
|
|
46
|
+
displayName: '张三',
|
|
47
|
+
tags: ['lims:type:app', 'lims:dept:88'], // 事件时一次推全(整体覆盖)
|
|
48
|
+
updateOnMatch: true, // 命中已存在时覆盖更新(未传字段保留)
|
|
49
|
+
externalIdentity: { source: 'lims', externalKey: 'user_001' }, // 幂等键,可安全重试
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
// 3) 对账(防串租户)
|
|
53
|
+
const resolved = await sdk.resolveTenant('lims_org_10086');
|
|
54
|
+
// → { tenantId, tenantStatus, grants: [{ grantId, scopes, status }] }
|
|
55
|
+
|
|
56
|
+
// 4) 启停授权
|
|
57
|
+
await sdk.toggleGrant(grantId, 'revoked'); // 或 'active'
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## 认领激活(走用户 JWT,非 platform token)
|
|
61
|
+
|
|
62
|
+
认领是**租户管理员的动作**(信任锚),必须用该管理员的用户 JWT:
|
|
63
|
+
|
|
64
|
+
```ts
|
|
65
|
+
await sdk.claimTenant(tenantId, claimToken, userJwt);
|
|
66
|
+
// 租户 pending → active,grant pending → active
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## 触达(notify):声明式,无 subjectId 概念
|
|
70
|
+
|
|
71
|
+
发送者/收件人都是声明式的(`{source, externalKey, displayName, avatarUrl?}`),服务端 lazily create-or-get(幂等键 = externalIdentity,同一 id 只建一次)——调用方只需本地维护 id/昵称/头像。
|
|
72
|
+
|
|
73
|
+
```ts
|
|
74
|
+
// 路径 ① 标签圈人(运营触达,多标签取交集)
|
|
75
|
+
const result = await lab.notify(
|
|
76
|
+
{ selector: { tags: ['lims:role:admin', 'lims:type:app'] } },
|
|
77
|
+
{
|
|
78
|
+
classId: 'class_lims_member', // 本次触达涉及的外部主体类
|
|
79
|
+
sender: { source: 'lims', externalKey: 'kf_001', displayName: '客服小王' },
|
|
80
|
+
typeId: 'type_lims_notify', // 通知会话类型(不存在则自动创建)
|
|
81
|
+
kind: 'text',
|
|
82
|
+
content: { text: '明日 22:00 系统维护' },
|
|
83
|
+
},
|
|
84
|
+
);
|
|
85
|
+
|
|
86
|
+
// 路径 ② 单点声明收件人(如微信公众号客服消息迁移:客服=sender、微信用户=receive 全部 lazily 建主体)
|
|
87
|
+
await lab.notify(
|
|
88
|
+
{ receive: { source: 'wechat', externalKey: 'wx_123', displayName: '微信用户' } },
|
|
89
|
+
{ classId: 'class_lims_member', sender: { source: 'lims', externalKey: 'kf_001', displayName: '客服小王' }, typeId: 'type_lims_notify', kind: 'text', content: { text: 'hi' } },
|
|
90
|
+
);
|
|
91
|
+
// → { matched, delivered, failed }
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
前置:grant 需含 `platform:message:send`。语音播报走 `kind` 扩展(渲染层解释)。
|
|
95
|
+
|
|
96
|
+
## 幂等与错误处理纪律
|
|
97
|
+
|
|
98
|
+
| 场景 | 行为 | 你该做的 |
|
|
99
|
+
|---|---|---|
|
|
100
|
+
| 重复 syncSubject 同一 externalKey | 返回已有主体(`created:false`) | **安全重试**,无需自行去重 |
|
|
101
|
+
| `GRANT_NOT_FOUND` (403) | 该租户未授权给你 | 检查代开通 / 认领流程是否完成 |
|
|
102
|
+
| `GRANT_INACTIVE` (403) | grant 为 pending / revoked | pending = 等认领;revoked = 被停用或解除 |
|
|
103
|
+
| `PLATFORM_SCOPE_DENIED` (403) | token 缺对应 scope | 换 token 时 `requestedScopes` 补上 |
|
|
104
|
+
| `CORRELATION_MISMATCH` (403) | externalCorrelationId 对不上 | **停止操作**,人工核对租户映射 |
|
|
105
|
+
| `TENANT_PENDING_CLAIM` / 已认领 (409) | 租户待认领 / 已认领过 | 引导管理员走认领流程 |
|
|
106
|
+
|
|
107
|
+
## 职责边界(不要做)
|
|
108
|
+
|
|
109
|
+
- ❌ 前端 / 浏览器**永远不要**持有 accessSecret——前端用 `@appthen/sdk-web`(后端签发的短期 token)。
|
|
110
|
+
- ❌ 不要绕过 SDK 手工管 token(2h 过期 + 60s 刷新提前量 + 并发刷新去重已内置)。
|
|
111
|
+
- ❌ 认领是租户管理员动作,不要在你的后端"代管理员认领"。
|
|
112
|
+
- ❌ 不要每类资源各写一套准入逻辑——获得方式统一走 `distribution` 维度(见契约文档补丁)。
|
|
113
|
+
|
|
114
|
+
## 权威文档
|
|
115
|
+
|
|
116
|
+
- API 契约(字段级签名 / 错误码 / 状态机 / 冻结 gate):`docs/service-provider-platform-api.md`
|
|
117
|
+
- 授权事件通知 SaaS(§6.1)与租户侧解除授权(§4.7):⏳ 待实现
|
|
118
|
+
- 代安装工作台(§4.3):⏳ 依赖工作台分发制(mkt-10)落地
|