@lovrabet/sdk 1.0.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/README.md +213 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +1 -0
- package/dist/src/auth/auth-manager.d.ts +16 -0
- package/dist/src/auth/cookie-auth.d.ts +14 -0
- package/dist/src/auth/openapi-auth.d.ts +7 -0
- package/dist/src/auth/user-auth.d.ts +8 -0
- package/dist/src/client/client.d.ts +58 -0
- package/dist/src/client/index.d.ts +21 -0
- package/dist/src/config/constants.d.ts +75 -0
- package/dist/src/config/endpoints.d.ts +16 -0
- package/dist/src/config/model-registry.d.ts +42 -0
- package/dist/src/http/cookie.d.ts +2 -0
- package/dist/src/http/get.d.ts +1 -0
- package/dist/src/http/http-client.d.ts +26 -0
- package/dist/src/http/post.d.ts +1 -0
- package/dist/src/http/process-response.d.ts +4 -0
- package/dist/src/http/traceparent.d.ts +5 -0
- package/dist/src/models/base-model.d.ts +18 -0
- package/dist/src/models/model-manager.d.ts +15 -0
- package/dist/src/types/index.d.ts +321 -0
- package/dist/src/utils/errors.d.ts +15 -0
- package/package.json +30 -0
package/README.md
ADDED
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
# Lovrabet Node SDK
|
|
2
|
+
|
|
3
|
+
一个现代化的 Lovrabet 数据平台 SDK,支持 TypeScript,提供优雅的 API 设计。
|
|
4
|
+
|
|
5
|
+
## 特性
|
|
6
|
+
|
|
7
|
+
- 🚀 **现代化 API** - 基于 `createClient()` 的简洁设计
|
|
8
|
+
- 🔒 **多种鉴权** - 支持用户 token、OpenAPI 等多种认证方式
|
|
9
|
+
- 🌍 **环境切换** - 支持生产环境和日常环境
|
|
10
|
+
- 📦 **TypeScript** - 完整的类型支持
|
|
11
|
+
- 🔧 **配置文件** - 支持配置文件管理
|
|
12
|
+
- 🔄 **向后兼容** - 保持对旧版 API 的兼容
|
|
13
|
+
- ⚡ **动态实体** - 通过 Proxy 实现动态实体访问
|
|
14
|
+
|
|
15
|
+
## 快速开始
|
|
16
|
+
|
|
17
|
+
### 安装
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
npm install @lovrabet/sdk
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
### 基础用法
|
|
24
|
+
|
|
25
|
+
```typescript
|
|
26
|
+
import { createClient } from "@lovrabet/sdk";
|
|
27
|
+
|
|
28
|
+
// 创建客户端
|
|
29
|
+
const client = createClient({
|
|
30
|
+
appCode: "your-app-code",
|
|
31
|
+
env: "online",
|
|
32
|
+
|
|
33
|
+
entities: {
|
|
34
|
+
Requirements: {
|
|
35
|
+
tableName: "requirements",
|
|
36
|
+
datasetId: "your-dataset-id",
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
// 使用实体
|
|
42
|
+
const requirements = await client.entities.Requirements.list();
|
|
43
|
+
const newReq = await client.entities.Requirements.create({
|
|
44
|
+
title: "New Requirement",
|
|
45
|
+
});
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### 配置文件支持
|
|
49
|
+
|
|
50
|
+
创建 `lovrabet.config.js`:
|
|
51
|
+
|
|
52
|
+
```javascript
|
|
53
|
+
module.exports = {
|
|
54
|
+
appCode: "your-app-code",
|
|
55
|
+
env: "online",
|
|
56
|
+
entities: {
|
|
57
|
+
Requirements: {
|
|
58
|
+
tableName: "requirements",
|
|
59
|
+
datasetId: "your-dataset-id",
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
};
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
使用配置文件:
|
|
66
|
+
|
|
67
|
+
```typescript
|
|
68
|
+
const client = createClient({
|
|
69
|
+
configFile: "./lovrabet.config.js",
|
|
70
|
+
});
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## API 文档
|
|
74
|
+
|
|
75
|
+
### 创建客户端
|
|
76
|
+
|
|
77
|
+
```typescript
|
|
78
|
+
import { createClient, ClientConfig } from '@lovrabet/sdk';
|
|
79
|
+
|
|
80
|
+
const config: ClientConfig = {
|
|
81
|
+
// 必需
|
|
82
|
+
appCode: string;
|
|
83
|
+
|
|
84
|
+
// 可选
|
|
85
|
+
serverUrl?: string; // 自定义服务器地址
|
|
86
|
+
env?: 'online' | 'daily'; // 环境,默认 'online'
|
|
87
|
+
|
|
88
|
+
// 鉴权方式(选择其一或组合使用)
|
|
89
|
+
token?: string; // 用户 token
|
|
90
|
+
accessKey?: string; // OpenAPI access key
|
|
91
|
+
secretKey?: string; // OpenAPI secret key
|
|
92
|
+
requiresAuth?: boolean; // 是否必须鉴权
|
|
93
|
+
|
|
94
|
+
// 实体配置
|
|
95
|
+
entities?: Record<string, {
|
|
96
|
+
tableName: string;
|
|
97
|
+
datasetId: string;
|
|
98
|
+
}>;
|
|
99
|
+
|
|
100
|
+
// 其他选项
|
|
101
|
+
options?: {
|
|
102
|
+
timeout?: number; // 请求超时时间
|
|
103
|
+
retryCount?: number; // 重试次数
|
|
104
|
+
onError?: (error: any) => void; // 错误回调
|
|
105
|
+
onRedirectToLogin?: () => void; // 登录重定向回调
|
|
106
|
+
};
|
|
107
|
+
};
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### 实体操作
|
|
111
|
+
|
|
112
|
+
每个实体支持标准的 CRUD 操作:
|
|
113
|
+
|
|
114
|
+
```typescript
|
|
115
|
+
// 查询列表
|
|
116
|
+
await client.entities.EntityName.list({
|
|
117
|
+
currentPage?: number;
|
|
118
|
+
pageSize?: number;
|
|
119
|
+
[key: string]: any;
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
// 获取单条
|
|
123
|
+
await client.entities.EntityName.get(id: string | number);
|
|
124
|
+
|
|
125
|
+
// 创建
|
|
126
|
+
await client.entities.EntityName.create(data: Record<string, any>);
|
|
127
|
+
|
|
128
|
+
// 更新
|
|
129
|
+
await client.entities.EntityName.update(id: string | number, data: Record<string, any>);
|
|
130
|
+
|
|
131
|
+
// 删除
|
|
132
|
+
await client.entities.EntityName.delete(id: string | number);
|
|
133
|
+
|
|
134
|
+
// 批量创建
|
|
135
|
+
await client.entities.EntityName.bulkCreate(data: Record<string, any>[]);
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### 客户端方法
|
|
139
|
+
|
|
140
|
+
```typescript
|
|
141
|
+
// 设置新 token
|
|
142
|
+
client.setToken(token: string);
|
|
143
|
+
|
|
144
|
+
// 获取配置
|
|
145
|
+
client.getConfig(): ClientConfig;
|
|
146
|
+
|
|
147
|
+
// 测试连接
|
|
148
|
+
await client.testConnection(): Promise<boolean>;
|
|
149
|
+
|
|
150
|
+
// 设置环境
|
|
151
|
+
client.setEnvironment(env: 'online' | 'daily');
|
|
152
|
+
|
|
153
|
+
// 获取当前环境
|
|
154
|
+
client.getEnvironment(): 'online' | 'daily';
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
## 向后兼容
|
|
158
|
+
|
|
159
|
+
旧版代码无需修改:
|
|
160
|
+
|
|
161
|
+
```typescript
|
|
162
|
+
import { LovrabetTableApi, initEnv } from "@lovrabet/sdk";
|
|
163
|
+
|
|
164
|
+
initEnv("online");
|
|
165
|
+
|
|
166
|
+
const api = new LovrabetTableApi({
|
|
167
|
+
appCode: "your-app-code",
|
|
168
|
+
tableName: "requirements",
|
|
169
|
+
datasetId: "your-dataset-id",
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
const data = await api.getList();
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
## 错误处理
|
|
176
|
+
|
|
177
|
+
```typescript
|
|
178
|
+
import { createClient, LovrabetError } from "@lovrabet/sdk";
|
|
179
|
+
|
|
180
|
+
try {
|
|
181
|
+
const data = await client.entities.Requirements.list();
|
|
182
|
+
} catch (error) {
|
|
183
|
+
if (error instanceof LovrabetError) {
|
|
184
|
+
console.log("Status:", error.status);
|
|
185
|
+
console.log("Code:", error.code);
|
|
186
|
+
console.log("Data:", error.data);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
## 文档
|
|
192
|
+
|
|
193
|
+
- [使用指南](./docs/usage-guide.md) - 详细的使用文档和最佳实践
|
|
194
|
+
- [架构设计](./docs/new-sdk-design.md) - SDK 的架构设计说明
|
|
195
|
+
- [迁移指南](./docs/usage-guide.md#迁移指南) - 从旧版本迁移的指南
|
|
196
|
+
|
|
197
|
+
## 开发
|
|
198
|
+
|
|
199
|
+
```bash
|
|
200
|
+
# 构建
|
|
201
|
+
bun run build
|
|
202
|
+
|
|
203
|
+
# 发布
|
|
204
|
+
bun run release
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
## 许可证
|
|
208
|
+
|
|
209
|
+
MIT
|
|
210
|
+
|
|
211
|
+
## 支持
|
|
212
|
+
|
|
213
|
+
如有问题或建议,请提交 Issue。
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { createClient } from "./src/client/index";
|
|
2
|
+
export { registerModels, getRegisteredModels, getRegisteredConfigNames, unregisterModels, clearAllRegistrations, } from "./src/config/model-registry";
|
|
3
|
+
export { getApiEndpoint, getAvailableEnvironments, } from "./src/config/endpoints";
|
|
4
|
+
export { CONFIG_NAMES, ENVIRONMENTS, DEFAULTS, HTTP_STATUS, ERROR_MESSAGES, API_PATHS, } from "./src/config/constants";
|
|
5
|
+
export { LovrabetError } from "./src/utils/errors";
|
|
6
|
+
export type { ClientConfig, LovrabetClient, ModelConfig, ModelsConfig, } from "./src/types/index";
|
|
7
|
+
export type { ListParams, ListResponse, Environment, BaseModelMethods, } from "./src/types/index";
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const a0_0x2a4f3a=a0_0x4033;(function(_0x3b6070,_0x2785da){const _0x3239b1=a0_0x4033,_0x3e1124=_0x3b6070();while(!![]){try{const _0x403962=parseInt(_0x3239b1(0x162))/0x1*(parseInt(_0x3239b1(0x12e))/0x2)+-parseInt(_0x3239b1(0x114))/0x3*(-parseInt(_0x3239b1(0x11a))/0x4)+-parseInt(_0x3239b1(0x153))/0x5*(parseInt(_0x3239b1(0xfc))/0x6)+parseInt(_0x3239b1(0x103))/0x7+parseInt(_0x3239b1(0x104))/0x8*(parseInt(_0x3239b1(0xdc))/0x9)+-parseInt(_0x3239b1(0x12d))/0xa*(parseInt(_0x3239b1(0x10a))/0xb)+-parseInt(_0x3239b1(0xfb))/0xc*(parseInt(_0x3239b1(0x129))/0xd);if(_0x403962===_0x2785da)break;else _0x3e1124['push'](_0x3e1124['shift']());}catch(_0x56dbb8){_0x3e1124['push'](_0x3e1124['shift']());}}}(a0_0x128b,0x75a28));class UserAuth{[a0_0x2a4f3a(0xdd)];constructor(_0x5080ba){const _0x2b2c3e=a0_0x2a4f3a;this[_0x2b2c3e(0xdd)]=_0x5080ba;}async['getAuthHeaders'](){const _0x1c99e5=a0_0x2a4f3a;return{'Authorization':_0x1c99e5(0xdf)+this[_0x1c99e5(0xdd)][_0x1c99e5(0xff)]};}[a0_0x2a4f3a(0x15a)](){const _0x3057d8=a0_0x2a4f3a;return this[_0x3057d8(0xdd)]['token'];}[a0_0x2a4f3a(0x14e)](_0x5b2d90){const _0x2832d3=a0_0x2a4f3a;this[_0x2832d3(0xdd)][_0x2832d3(0xff)]=_0x5b2d90;}}class OpenApiAuth{['config'];constructor(_0x583ed5){const _0x111e2b=a0_0x2a4f3a;this[_0x111e2b(0xdd)]=_0x583ed5;}async[a0_0x2a4f3a(0xea)](){const _0x3e2971=a0_0x2a4f3a,_0x47961f=Date[_0x3e2971(0x150)]()[_0x3e2971(0xe1)](),_0x196f0f=Math[_0x3e2971(0xf0)]()['toString'](0x24)[_0x3e2971(0xd6)](0x2),_0x4acbb8=await this['generateSignature'](_0x47961f,_0x196f0f);return{'X-Access-Key':this[_0x3e2971(0xdd)][_0x3e2971(0x142)],'X-Timestamp':_0x47961f,'X-Nonce':_0x196f0f,'X-Signature':_0x4acbb8};}async[a0_0x2a4f3a(0x136)](_0x291803,_0x3db088){const _0x3b817d=a0_0x2a4f3a,_0x169d40=''+this[_0x3b817d(0xdd)][_0x3b817d(0x142)]+_0x291803+_0x3db088;if(typeof crypto!==_0x3b817d(0x154)&&crypto[_0x3b817d(0x12b)]){const _0x28807a=new TextEncoder(),_0x8272ca=_0x28807a[_0x3b817d(0x15e)](this[_0x3b817d(0xdd)]['secretKey']),_0x4b63d2=_0x28807a[_0x3b817d(0x15e)](_0x169d40),_0x4d6f3d=await crypto[_0x3b817d(0x12b)][_0x3b817d(0x13e)](_0x3b817d(0xeb),_0x8272ca,{'name':_0x3b817d(0x160),'hash':'SHA-256'},![],[_0x3b817d(0x165)]),_0x3ff238=await crypto['subtle'][_0x3b817d(0x165)](_0x3b817d(0x160),_0x4d6f3d,_0x4b63d2),_0x4344a1=Array[_0x3b817d(0x174)](new Uint8Array(_0x3ff238));return _0x4344a1[_0x3b817d(0x161)](_0x2ffe74=>_0x2ffe74[_0x3b817d(0xe1)](0x10)[_0x3b817d(0x10b)](0x2,'0'))[_0x3b817d(0xee)]('');}if(typeof globalThis!=='undefined'&&globalThis[_0x3b817d(0x13b)]){const _0x58e7c8=globalThis[_0x3b817d(0x13b)];return _0x58e7c8[_0x3b817d(0x174)](_0x169d40+this[_0x3b817d(0xdd)][_0x3b817d(0x116)])[_0x3b817d(0xe1)](_0x3b817d(0xd8));}return btoa(_0x169d40+this[_0x3b817d(0xdd)][_0x3b817d(0x116)]);}}class CookieAuth{constructor(){}async[a0_0x2a4f3a(0xea)](){return{};}[a0_0x2a4f3a(0xe9)](){const _0x50c497=a0_0x2a4f3a;return typeof window!==_0x50c497(0x154)&&typeof document!==_0x50c497(0x154);}}class AuthManager{[a0_0x2a4f3a(0xdd)];[a0_0x2a4f3a(0xd9)];[a0_0x2a4f3a(0x11c)];['cookieAuth'];constructor(_0x3e5780){const _0x2ad820=a0_0x2a4f3a;this[_0x2ad820(0xdd)]=_0x3e5780,this[_0x2ad820(0x122)]();}[a0_0x2a4f3a(0x122)](){const _0x5a7941=a0_0x2a4f3a;this[_0x5a7941(0xdd)][_0x5a7941(0xff)]&&(this[_0x5a7941(0xd9)]=new UserAuth({'token':this[_0x5a7941(0xdd)][_0x5a7941(0xff)]})),this[_0x5a7941(0xdd)]['accessKey']&&this[_0x5a7941(0xdd)][_0x5a7941(0x116)]&&(this[_0x5a7941(0x11c)]=new OpenApiAuth({'accessKey':this[_0x5a7941(0xdd)][_0x5a7941(0x142)],'secretKey':this['config'][_0x5a7941(0x116)]})),!this['config'][_0x5a7941(0xff)]&&!this[_0x5a7941(0xdd)][_0x5a7941(0x142)]&&!this[_0x5a7941(0xdd)]['secretKey']&&(this[_0x5a7941(0x166)]=new CookieAuth());}async[a0_0x2a4f3a(0xea)](){const _0x3a9242=a0_0x2a4f3a,_0x526c82={};if(this[_0x3a9242(0xd9)]){const _0x50cac8=await this['userAuth']['getAuthHeaders']();Object['assign'](_0x526c82,_0x50cac8);}else{if(this[_0x3a9242(0x11c)]){const _0x15e029=await this[_0x3a9242(0x11c)][_0x3a9242(0xea)]();Object[_0x3a9242(0x139)](_0x526c82,_0x15e029);}else{if(this['cookieAuth']){const _0x397fee=await this['cookieAuth'][_0x3a9242(0xea)]();Object[_0x3a9242(0x139)](_0x526c82,_0x397fee);}}}return _0x526c82;}async['validateAuth'](){const _0x4f3ae9=a0_0x2a4f3a;try{if(this[_0x4f3ae9(0x166)]?.[_0x4f3ae9(0xe9)]())return!![];const _0x5e4db5=await this[_0x4f3ae9(0xea)]();return Object['keys'](_0x5e4db5)[_0x4f3ae9(0xed)]>0x0;}catch{return![];}}[a0_0x2a4f3a(0x145)](){const _0x168c0d=a0_0x2a4f3a;return!!this[_0x168c0d(0x166)];}[a0_0x2a4f3a(0x14e)](_0x2215cb){const _0x1e007a=a0_0x2a4f3a;this[_0x1e007a(0xdd)][_0x1e007a(0xff)]=_0x2215cb,this[_0x1e007a(0xd9)]=new UserAuth({'token':_0x2215cb}),this[_0x1e007a(0x166)]=undefined;}}class LovrabetError extends Error{['status'];[a0_0x2a4f3a(0xf2)];[a0_0x2a4f3a(0x14f)];['originalError'];constructor(_0x40e9c7,_0x59a568,_0x20f515,_0x283b72,_0x5a0873){const _0x3c06ac=a0_0x2a4f3a;super(_0x40e9c7),this[_0x3c06ac(0x13a)]=_0x3c06ac(0xef),this[_0x3c06ac(0x14d)]=_0x59a568,this[_0x3c06ac(0xf2)]=_0x20f515,this['data']=_0x283b72,this[_0x3c06ac(0x128)]=_0x5a0873;}['toJSON'](){const _0x5cc2ef=a0_0x2a4f3a;return{'name':this[_0x5cc2ef(0x13a)],'message':this[_0x5cc2ef(0xda)],'status':this[_0x5cc2ef(0x14d)],'code':this[_0x5cc2ef(0xf2)],'data':this[_0x5cc2ef(0x14f)]};}}function createErrorHandler(_0x50615f){return _0x447b91=>{const _0x1fc592=a0_0x4033,_0x717847=_0x447b91 instanceof LovrabetError?_0x447b91:new LovrabetError(_0x447b91['message']||_0x1fc592(0x15d),_0x447b91[_0x1fc592(0x14d)],_0x447b91[_0x1fc592(0xf2)],_0x447b91[_0x1fc592(0x14f)],_0x447b91);return typeof globalThis!==_0x1fc592(0x154)&&globalThis[_0x1fc592(0xf3)]?.[_0x1fc592(0x126)]?.['NODE_ENV']!==_0x1fc592(0x132)&&console[_0x1fc592(0x13d)](_0x1fc592(0x133),_0x717847),_0x50615f?.(_0x717847),Promise[_0x1fc592(0x144)](_0x717847);};}var CONFIG_NAMES={'DEFAULT':a0_0x2a4f3a(0x16a),'PROD':a0_0x2a4f3a(0x11e),'DEV':a0_0x2a4f3a(0x127),'TEST':a0_0x2a4f3a(0x157)},ENVIRONMENTS={'ONLINE':a0_0x2a4f3a(0x149),'DAILY':a0_0x2a4f3a(0x14b)},HTTP_STATUS={'OK':0xc8,'UNAUTHORIZED':0x191,'FORBIDDEN':0x193,'NOT_FOUND':0x194,'INTERNAL_ERROR':0x1f4},DEFAULTS={'ENV':ENVIRONMENTS[a0_0x2a4f3a(0x110)],'TIMEOUT':0x7530,'RETRY_COUNT':0x3,'PAGE_SIZE':0x14,'CURRENT_PAGE':0x1},ERROR_MESSAGES={'APP_CODE_REQUIRED':a0_0x2a4f3a(0x138),'CONFIG_NOT_FOUND':_0x4f363e=>a0_0x2a4f3a(0x11d)+_0x4f363e+a0_0x2a4f3a(0x13c),'INVALID_ENV':a0_0x2a4f3a(0x124),'NETWORK_ERROR':a0_0x2a4f3a(0x130),'UNAUTHORIZED':a0_0x2a4f3a(0x10d),'FORBIDDEN':a0_0x2a4f3a(0x125),'NOT_FOUND':a0_0x2a4f3a(0x16b),'SERVER_ERROR':'Internal\x20server\x20error'},API_PATHS={'BASE':'/api/{appCode}/{datasetId}','LIST':'','DETAIL':a0_0x2a4f3a(0xfd)},API_ENDPOINTS={[ENVIRONMENTS['ONLINE']]:a0_0x2a4f3a(0x111),[ENVIRONMENTS[a0_0x2a4f3a(0x131)]]:'https://daily-runtime.lovrabet.com'};function getApiEndpoint(_0x110162){return API_ENDPOINTS[_0x110162];}function getAvailableEnvironments(){return Object['keys'](API_ENDPOINTS);}var cacheCookie='';function getCookie(){return cacheCookie;}var processResponse=async _0x400e95=>{const _0x45456b=a0_0x2a4f3a,_0x4e7ba9=await _0x400e95[_0x45456b(0x119)]();if(!_0x4e7ba9['success']){const _0x580dcd=new Error(_0x4e7ba9[_0x45456b(0x163)]);_0x580dcd['response']=_0x4e7ba9;throw _0x580dcd;}return _0x4e7ba9[_0x45456b(0x14f)];};function getTraceparent(){const _0x393b05=a0_0x2a4f3a;try{return document[_0x393b05(0x172)](_0x393b05(0x10f))?.['getAttribute']('content')||undefined;}catch(_0x3e3ac0){return;}}function generateTraceparent(){const _0x52ee32=a0_0x2a4f3a,_0x503da3=getTraceparent(),_0x522b55=_0x503da3?_0x503da3[_0x52ee32(0x12a)]('-')[0x1]:Array[_0x52ee32(0x174)](crypto[_0x52ee32(0x12f)](new Uint8Array(0x10)))['map'](_0x4ee31e=>_0x4ee31e['toString'](0x10)[_0x52ee32(0x10b)](0x2,'0'))[_0x52ee32(0xee)](''),_0x5f0b7=Array['from'](crypto[_0x52ee32(0x12f)](new Uint8Array(0x8)))[_0x52ee32(0x161)](_0x354f74=>_0x354f74[_0x52ee32(0xe1)](0x10)[_0x52ee32(0x10b)](0x2,'0'))['join'](''),_0x33bd98='01';return _0x52ee32(0x123)+_0x522b55+'-'+_0x5f0b7+'-'+_0x33bd98;}var get=async(_0xaf11ff,_0x306f22,_0x19ef69={})=>{const _0x25da50=a0_0x2a4f3a,_0x14f0f7=new URL(_0xaf11ff);if(_0x306f22)for(const _0x559b03 of Object['keys'](_0x306f22)){_0x14f0f7[_0x25da50(0x135)][_0x25da50(0x121)](_0x559b03,String(_0x306f22[_0x559b03]));}const _0x1ef2fe={'Content-Type':_0x25da50(0x105),..._0x19ef69['headers'],'traceparent':generateTraceparent()};getCookie()&&(_0x1ef2fe['Cookie']=getCookie());const _0x590c0f=await fetch(_0x14f0f7[_0x25da50(0xe1)](),{..._0x19ef69,'headers':_0x1ef2fe,'credentials':_0x25da50(0xfa)});if(_0x590c0f[_0x25da50(0x15b)]){window[_0x25da50(0x169)][_0x25da50(0x12c)]=_0x590c0f[_0x25da50(0x146)];return;}return await processResponse(_0x590c0f);},post=async(_0x3060e7,_0x91ce93,_0x117f19={})=>{const _0xa4d02=a0_0x2a4f3a,_0x1d9d36={'Content-Type':'application/json',..._0x117f19[_0xa4d02(0x170)],'traceparent':generateTraceparent()};getCookie()&&(_0x1d9d36[_0xa4d02(0xfe)]=getCookie());const _0x9c50d6=await fetch(_0x3060e7,{..._0x117f19,'method':'POST','headers':_0x1d9d36,'body':_0x91ce93&&JSON[_0xa4d02(0x168)](_0x91ce93),'credentials':_0xa4d02(0xfa)});if(_0x9c50d6['redirected']){window[_0xa4d02(0x169)][_0xa4d02(0x12c)]=_0x9c50d6[_0xa4d02(0x146)];return;}return await processResponse(_0x9c50d6);};class HttpClient{['config'];[a0_0x2a4f3a(0x137)];['errorHandler'];constructor(_0x49e906,_0x4f6263){const _0xb1e618=a0_0x2a4f3a;this[_0xb1e618(0xdd)]=_0x49e906,this[_0xb1e618(0x137)]=_0x4f6263,this[_0xb1e618(0x151)]=createErrorHandler(_0x49e906[_0xb1e618(0x100)]?.[_0xb1e618(0x16f)]);}[a0_0x2a4f3a(0x152)](){const _0x347ef2=a0_0x2a4f3a;if(this['config'][_0x347ef2(0x107)])return this['config']['serverUrl'];const _0x333af6=this[_0x347ef2(0xdd)][_0x347ef2(0x126)]||_0x347ef2(0x149);return getApiEndpoint(_0x333af6);}[a0_0x2a4f3a(0xd5)](_0x5012e1){const _0x128241=a0_0x2a4f3a;return _0x5012e1[_0x128241(0x173)](_0x128241(0x16c))?_0x5012e1:''+this[_0x128241(0x152)]()+_0x5012e1;}async[a0_0x2a4f3a(0x108)](_0x4f737f){const _0x13d4a2=a0_0x2a4f3a,_0x2b7998=await this[_0x13d4a2(0x137)][_0x13d4a2(0xea)](),_0x4f58c7={..._0x4f737f,'headers':{..._0x2b7998,..._0x4f737f?.[_0x13d4a2(0x170)]}};return this[_0x13d4a2(0x137)][_0x13d4a2(0x145)]()&&(_0x4f58c7[_0x13d4a2(0xdb)]=_0x13d4a2(0xfa)),_0x4f58c7;}async[a0_0x2a4f3a(0x155)](_0x552d4c){const _0x465d18=a0_0x2a4f3a;try{return await _0x552d4c();}catch(_0x3dfc8c){return this[_0x465d18(0x151)](_0x3dfc8c);}}async[a0_0x2a4f3a(0x140)](_0x1842ce,_0x2af564,_0x14c06b,_0x2dbf5c){const _0x15dc67=a0_0x2a4f3a,_0x24c3f5=this['getFullUrl'](_0x2af564),_0x3af383=await this['prepareRequestInit']({..._0x2dbf5c,'method':_0x1842ce,'headers':{'Content-Type':_0x15dc67(0x105),..._0x2dbf5c?.[_0x15dc67(0x170)]}}),_0x3def8d=new AbortController(),_0x44eab0=setTimeout(()=>{const _0x208e30=_0x15dc67;_0x3def8d[_0x208e30(0x143)]();},this[_0x15dc67(0xdd)]['options']?.[_0x15dc67(0x158)]||0x7530);try{const _0x3ea46e=await fetch(_0x24c3f5,{..._0x3af383,'body':_0x14c06b?JSON['stringify'](_0x14c06b):undefined,'signal':_0x3def8d[_0x15dc67(0x115)]});clearTimeout(_0x44eab0);if(!_0x3ea46e['ok']){const _0x3403cb=await _0x3ea46e[_0x15dc67(0x119)]()['catch'](()=>({}));throw new LovrabetError(_0x3403cb[_0x15dc67(0xda)]||'HTTP\x20'+_0x3ea46e['status']+':\x20'+_0x3ea46e[_0x15dc67(0x148)],_0x3ea46e[_0x15dc67(0x14d)],_0x3403cb[_0x15dc67(0xf2)],_0x3403cb);}return await _0x3ea46e[_0x15dc67(0x119)]();}catch(_0x4d3d66){clearTimeout(_0x44eab0);if(_0x4d3d66[_0x15dc67(0x13a)]===_0x15dc67(0xf7))throw new LovrabetError('Request\x20timeout',0x198,_0x15dc67(0xf4));throw _0x4d3d66;}}async[a0_0x2a4f3a(0xe8)](_0x45536d,_0x4521f2,_0x42d854){const _0x1a6bca=a0_0x2a4f3a;return this[_0x1a6bca(0x155)](async()=>{const _0x1b7111=_0x1a6bca,_0x51b6cd=this[_0x1b7111(0xd5)](_0x45536d),_0x1dd10a=await this[_0x1b7111(0x108)](_0x42d854);return await get(_0x51b6cd,_0x4521f2,_0x1dd10a);});}async[a0_0x2a4f3a(0x101)](_0x12d271,_0x1e52f2,_0x136501){const _0x14335d=a0_0x2a4f3a;return this[_0x14335d(0x155)](async()=>{const _0x1dc944=_0x14335d,_0x8ec90f=this[_0x1dc944(0xd5)](_0x12d271),_0x5ee506=await this['prepareRequestInit'](_0x136501);return await post(_0x8ec90f,_0x1e52f2,_0x5ee506);});}async[a0_0x2a4f3a(0xf1)](_0x5a62df,_0x34386e,_0xdafcf9){const _0x5defd1=a0_0x2a4f3a;return this[_0x5defd1(0x155)](async()=>{const _0x3a962c=_0x5defd1;return this['makeRequest'](_0x3a962c(0xde),_0x5a62df,_0x34386e,_0xdafcf9);});}async[a0_0x2a4f3a(0x175)](_0x139312,_0x10fecf){return this['executeWithErrorHandling'](async()=>{const _0x55c24e=a0_0x4033;return this[_0x55c24e(0x140)](_0x55c24e(0x159),_0x139312,undefined,_0x10fecf);});}async[a0_0x2a4f3a(0xe0)](_0xf49b42,_0x24b1d6,_0x4802af,_0xa91e30){const _0x3c20df=a0_0x2a4f3a;switch(_0xf49b42){case _0x3c20df(0xe2):return this[_0x3c20df(0xe8)](_0x24b1d6,_0x4802af,_0xa91e30);case _0x3c20df(0x167):return this[_0x3c20df(0x101)](_0x24b1d6,_0x4802af,_0xa91e30);case _0x3c20df(0xde):return this['put'](_0x24b1d6,_0x4802af,_0xa91e30);case'DELETE':return this['delete'](_0x24b1d6,_0xa91e30);default:throw new LovrabetError(_0x3c20df(0xe3)+_0xf49b42,0x190,'INVALID_METHOD');}}}class BaseModel{[a0_0x2a4f3a(0x10e)];[a0_0x2a4f3a(0x109)];[a0_0x2a4f3a(0xdd)];[a0_0x2a4f3a(0x10c)];constructor(_0x342460,_0x4da876,_0x4b5614){const _0xb39a00=a0_0x2a4f3a;this[_0xb39a00(0x10e)]=_0x342460,this[_0xb39a00(0x109)]=_0x4da876,this[_0xb39a00(0x10c)]=_0x4b5614[_0xb39a00(0x10c)],this[_0xb39a00(0xdd)]=this[_0xb39a00(0xe7)](_0x342460,_0x4b5614);}[a0_0x2a4f3a(0xe7)](_0x287759,_0x215ae4){const _0x216dc0=a0_0x2a4f3a;if(_0x215ae4[_0x216dc0(0x106)]?.[_0x287759])return _0x215ae4[_0x216dc0(0x106)][_0x287759];throw new Error(_0x216dc0(0xe5)+_0x287759+_0x216dc0(0xe4));}[a0_0x2a4f3a(0x171)](){const _0x11955c=a0_0x2a4f3a;return _0x11955c(0x11f)+this[_0x11955c(0x10c)]+'/'+this[_0x11955c(0xdd)]['datasetId'];}async['getList'](_0x4b15e2){const _0x128bfa=a0_0x2a4f3a,_0x309f5d=this['getApiPath']()+_0x128bfa(0x14c),_0x5a16d9={'currentPage':0x1,'pageSize':0x14,..._0x4b15e2};return this[_0x128bfa(0x109)]['post'](_0x309f5d,_0x5a16d9);}async[a0_0x2a4f3a(0x112)](_0x4b4a60){const _0x413843=a0_0x2a4f3a,_0xc163fd=this['getApiPath']()+'/getOne';return this[_0x413843(0x109)]['post'](_0xc163fd,{'id':_0x4b4a60});}async['create'](_0x356cfe){const _0x12e34e=a0_0x2a4f3a,_0x4d7441=this['getApiPath']()+'/create';return this['httpClient'][_0x12e34e(0x101)](_0x4d7441,_0x356cfe);}async[a0_0x2a4f3a(0xec)](_0x1bc66f,_0x3f0a24){const _0xb23c7f=a0_0x2a4f3a,_0x1cd55a=this[_0xb23c7f(0x171)]()+'/update';return this[_0xb23c7f(0x109)][_0xb23c7f(0x101)](_0x1cd55a,{'id':_0x1bc66f,..._0x3f0a24});}async[a0_0x2a4f3a(0x175)](_0x1c0a1e){const _0x3576ad=a0_0x2a4f3a,_0xa091a0=this[_0x3576ad(0x171)]()+_0x3576ad(0xf8);await this[_0x3576ad(0x109)][_0x3576ad(0x101)](_0xa091a0,{'id':_0x1c0a1e});}[a0_0x2a4f3a(0x156)](){const _0x1a8bc7=a0_0x2a4f3a;return{...this[_0x1a8bc7(0xdd)]};}[a0_0x2a4f3a(0x141)](){const _0x447796=a0_0x2a4f3a;return this[_0x447796(0x10e)];}}class ModelManager{['httpClient'];[a0_0x2a4f3a(0xdd)];[a0_0x2a4f3a(0xf9)]=new Map();constructor(_0x2100d8,_0x2b24d0){const _0xb33fbc=a0_0x2a4f3a;return this['httpClient']=_0x2100d8,this[_0xb33fbc(0xdd)]=_0x2b24d0,new Proxy(this,{'get'(_0x282f30,_0x12f3c1){const _0x7a94eb=_0xb33fbc;if(typeof _0x12f3c1===_0x7a94eb(0x102)||_0x12f3c1 in _0x282f30)return Reflect[_0x7a94eb(0xe8)](_0x282f30,_0x12f3c1);if(_0x12f3c1==='then'||_0x12f3c1[_0x7a94eb(0x173)]('_')||_0x12f3c1===_0x7a94eb(0x117))return;return _0x282f30[_0x7a94eb(0x134)](_0x12f3c1);}});}[a0_0x2a4f3a(0x134)](_0xb3561b){const _0x5426d7=a0_0x2a4f3a;if(!this[_0x5426d7(0xf9)][_0x5426d7(0x120)](_0xb3561b)){const _0xac6fb8=new BaseModel(_0xb3561b,this['httpClient'],this[_0x5426d7(0xdd)]);this['modelCache']['set'](_0xb3561b,_0xac6fb8);}return this[_0x5426d7(0xf9)][_0x5426d7(0xe8)](_0xb3561b);}[a0_0x2a4f3a(0x164)](){const _0x506c4c=a0_0x2a4f3a;return Array[_0x506c4c(0x174)](this['modelCache'][_0x506c4c(0x118)]());}[a0_0x2a4f3a(0x16e)](){const _0x4104bf=a0_0x2a4f3a;this[_0x4104bf(0xf9)][_0x4104bf(0x14a)]();}['addModel'](_0x31a629,_0x2f5d92){const _0x3a4589=a0_0x2a4f3a;!this[_0x3a4589(0xdd)][_0x3a4589(0x106)]&&(this[_0x3a4589(0xdd)][_0x3a4589(0x106)]={}),this[_0x3a4589(0xdd)][_0x3a4589(0x106)][_0x31a629]=_0x2f5d92,this[_0x3a4589(0xf9)][_0x3a4589(0x120)](_0x31a629)&&this[_0x3a4589(0xf9)]['delete'](_0x31a629);}}class LovrabetClient{[a0_0x2a4f3a(0xdd)];[a0_0x2a4f3a(0x137)];[a0_0x2a4f3a(0x109)];[a0_0x2a4f3a(0x106)];constructor(_0xc272ce){const _0x8860de=a0_0x2a4f3a;this[_0x8860de(0x11b)](_0xc272ce),this[_0x8860de(0xdd)]={..._0xc272ce},this[_0x8860de(0x137)]=new AuthManager(this[_0x8860de(0xdd)]),this[_0x8860de(0x109)]=new HttpClient(this[_0x8860de(0xdd)],this['authManager']),this[_0x8860de(0x106)]=new ModelManager(this[_0x8860de(0x109)],this['config']);}[a0_0x2a4f3a(0x11b)](_0x4685ac){const _0xadcc2f=a0_0x2a4f3a;if(_0x4685ac['requiresAuth']){const _0x11df58=!!_0x4685ac[_0xadcc2f(0xff)],_0x31abc5=!!(_0x4685ac[_0xadcc2f(0x142)]&&_0x4685ac[_0xadcc2f(0x116)]);if(!_0x11df58&&!_0x31abc5)throw new Error(_0xadcc2f(0x16d));}}[a0_0x2a4f3a(0x14e)](_0x16bd20){const _0x53f58a=a0_0x2a4f3a;this[_0x53f58a(0xdd)][_0x53f58a(0xff)]=_0x16bd20,this['authManager'][_0x53f58a(0x14e)](_0x16bd20);}[a0_0x2a4f3a(0x156)](){const _0x2f4e75=a0_0x2a4f3a;return{...this[_0x2f4e75(0xdd)]};}[a0_0x2a4f3a(0x152)](){const _0x517ada=a0_0x2a4f3a;if(this[_0x517ada(0xdd)][_0x517ada(0x107)])return this[_0x517ada(0xdd)][_0x517ada(0x107)];const _0x1158e5=this[_0x517ada(0xdd)][_0x517ada(0x126)]||_0x517ada(0x149);return getApiEndpoint(_0x1158e5);}[a0_0x2a4f3a(0xe6)](_0x2ce0ec){const _0x520771=a0_0x2a4f3a;this['config'][_0x520771(0x126)]=_0x2ce0ec;}[a0_0x2a4f3a(0x15c)](){const _0x1ce01a=a0_0x2a4f3a;return this[_0x1ce01a(0xdd)]['env']||'online';}}var modelConfigRegistry=new Map();function registerModels(_0x57ad5e,_0x2fd0e3=CONFIG_NAMES[a0_0x2a4f3a(0x13f)]){const _0x1e2d8d=a0_0x2a4f3a;modelConfigRegistry[_0x1e2d8d(0xf6)](_0x2fd0e3,_0x57ad5e);}function getRegisteredModels(_0x131f5f){const _0x191bf1=a0_0x2a4f3a;return modelConfigRegistry[_0x191bf1(0xe8)](_0x131f5f);}function a0_0x128b(){const _0x39663d=['data','now','errorHandler','getBaseUrl','44905bSgqjm','undefined','executeWithErrorHandling','getConfig','test','timeout','DELETE','getToken','redirected','getEnvironment','Unknown\x20error','encode','string','HMAC','map','183663vYnxqe','errorMsg','getCachedModels','sign','cookieAuth','POST','stringify','location','default','Resource\x20not\x20found','http','Authentication\x20is\x20required\x20but\x20no\x20auth\x20method\x20provided.\x20Please\x20provide\x20either\x20\x22token\x22\x20or\x20\x22accessKey\x20+\x20secretKey\x22','clearCache','onError','headers','getApiPath','querySelector','startsWith','from','delete','getFullUrl','substring','CONFIG_NOT_FOUND','base64','userAuth','message','credentials','576MWZbLm','config','PUT','Bearer\x20','request','toString','GET','Unsupported\x20method:\x20','\x22\x20not\x20configured.\x20Please\x20provide\x20datasetId\x20in\x20config.models\x20or\x20use\x20registerModels()\x20to\x20configure\x20it.','Model\x20\x22','setEnvironment','resolveModelConfig','get','isValid','getAuthHeaders','raw','update','length','join','LovrabetError','random','put','code','process','TIMEOUT','apiConfigName','set','AbortError','/delete','modelCache','include','12RpNnzR','90WOlxsO','/{id}','Cookie','token','options','post','symbol','613123GSTznT','54584OunrtY','application/json','models','serverUrl','prepareRequestInit','httpClient','310497SxrqvF','padStart','appCode','Unauthorized\x20access','modelName','meta[name=\x22traceparent\x22]','ONLINE','https://runtime.lovrabet.com','getOne','ENV','69ZiLSIj','signal','secretKey','constructor','keys','json','154388yGqbAa','validateConfig','openApiAuth','Model\x20config\x20with\x20name\x20\x22','prod','/api/','has','append','initAuthMethods','00-','Invalid\x20environment.\x20Must\x20be\x20\x22online\x22\x20or\x20\x22daily\x22.','Access\x20forbidden','env','dev','originalError','5389384nHsoxh','split','subtle','href','200CImYec','2jTKQju','getRandomValues','Network\x20request\x20failed','DAILY','production','[Lovrabet\x20SDK\x20Error]','getModel','searchParams','generateSignature','authManager','appCode\x20is\x20required.\x20Please\x20provide\x20it\x20in\x20the\x20config\x20or\x20register\x20models\x20first.','assign','name','Buffer','\x22\x20not\x20found.\x20Please\x20register\x20it\x20first\x20using\x20registerModels().','error','importKey','DEFAULT','makeRequest','getModelName','accessKey','abort','reject','isCookieAuth','url','object','statusText','online','clear','daily','/getList','status','setToken'];a0_0x128b=function(){return _0x39663d;};return a0_0x128b();}function a0_0x4033(_0x126f5a,_0x315814){const _0x128ba8=a0_0x128b();return a0_0x4033=function(_0x4033d5,_0x2295e8){_0x4033d5=_0x4033d5-0xd5;let _0x5ac58b=_0x128ba8[_0x4033d5];return _0x5ac58b;},a0_0x4033(_0x126f5a,_0x315814);}function getRegisteredConfigNames(){const _0x565ccd=a0_0x2a4f3a;return Array[_0x565ccd(0x174)](modelConfigRegistry[_0x565ccd(0x118)]());}function unregisterModels(_0x1f6651){const _0x3198fb=a0_0x2a4f3a;return modelConfigRegistry[_0x3198fb(0x175)](_0x1f6651);}function clearAllRegistrations(){const _0x2c71e4=a0_0x2a4f3a;modelConfigRegistry[_0x2c71e4(0x14a)]();}function createClient(_0x27c13c=CONFIG_NAMES[a0_0x2a4f3a(0x13f)]){const _0x4c2f3=a0_0x2a4f3a;let _0x34b6a4;if(typeof _0x27c13c===_0x4c2f3(0x15f)){const _0x203b96=getRegisteredModels(_0x27c13c);if(!_0x203b96)throw new Error(ERROR_MESSAGES[_0x4c2f3(0xd7)](_0x27c13c));_0x34b6a4={'appCode':_0x203b96['appCode'],'env':DEFAULTS[_0x4c2f3(0x113)],'models':_0x203b96[_0x4c2f3(0x106)]};}else{if(typeof _0x27c13c===_0x4c2f3(0x147)&&_0x4c2f3(0x10c)in _0x27c13c&&_0x4c2f3(0x106)in _0x27c13c&&!('env'in _0x27c13c))_0x34b6a4={'appCode':_0x27c13c['appCode'],'env':DEFAULTS[_0x4c2f3(0x113)],'models':_0x27c13c[_0x4c2f3(0x106)]};else{if(typeof _0x27c13c==='object'&&_0x4c2f3(0xf5)in _0x27c13c){const {apiConfigName:_0x20b453,..._0x374343}=_0x27c13c,_0x5a53b1=getRegisteredModels(_0x20b453);if(!_0x5a53b1)throw new Error(ERROR_MESSAGES[_0x4c2f3(0xd7)](_0x20b453));_0x34b6a4={'appCode':_0x5a53b1['appCode'],'env':DEFAULTS['ENV'],'models':_0x5a53b1[_0x4c2f3(0x106)],..._0x374343};}else{const _0x2ae246={'env':DEFAULTS['ENV'],'models':{}};_0x34b6a4={..._0x2ae246,..._0x27c13c};}}}if(!_0x34b6a4[_0x4c2f3(0x10c)])throw new Error(ERROR_MESSAGES['APP_CODE_REQUIRED']);return new LovrabetClient(_0x34b6a4);}export{unregisterModels,registerModels,getRegisteredModels,getRegisteredConfigNames,getAvailableEnvironments,getApiEndpoint,createClient,clearAllRegistrations,LovrabetError,HTTP_STATUS,ERROR_MESSAGES,ENVIRONMENTS,DEFAULTS,CONFIG_NAMES,API_PATHS};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { ClientConfig, AuthHeaders, AuthManager as IAuthManager } from "../types";
|
|
2
|
+
export declare class AuthManager implements IAuthManager {
|
|
3
|
+
private config;
|
|
4
|
+
private userAuth?;
|
|
5
|
+
private openApiAuth?;
|
|
6
|
+
private cookieAuth?;
|
|
7
|
+
constructor(config: ClientConfig);
|
|
8
|
+
private initAuthMethods;
|
|
9
|
+
getAuthHeaders(): Promise<AuthHeaders>;
|
|
10
|
+
validateAuth(): Promise<boolean>;
|
|
11
|
+
/**
|
|
12
|
+
* Check if we're using cookie-based authentication
|
|
13
|
+
*/
|
|
14
|
+
isCookieAuth(): boolean;
|
|
15
|
+
setToken(token: string): void;
|
|
16
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { AuthHeaders } from "../types";
|
|
2
|
+
/**
|
|
3
|
+
* Cookie-based authentication for users logged into Lovrabet.com
|
|
4
|
+
* Uses browser cookies with credentials: 'include'
|
|
5
|
+
*/
|
|
6
|
+
export declare class CookieAuth {
|
|
7
|
+
constructor();
|
|
8
|
+
getAuthHeaders(): Promise<AuthHeaders>;
|
|
9
|
+
/**
|
|
10
|
+
* Cookie auth is always considered valid in browser environment
|
|
11
|
+
* The server will validate the actual cookie
|
|
12
|
+
*/
|
|
13
|
+
isValid(): boolean;
|
|
14
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import type { ClientConfig, LovrabetClient as ILovrabetClient, ModelManager, Environment } from "../types";
|
|
2
|
+
/**
|
|
3
|
+
* Lovrabet SDK 核心客户端类
|
|
4
|
+
*
|
|
5
|
+
* 设计原则:
|
|
6
|
+
* 1. 实例化设计 - 避免全局状态,支持多项目并存
|
|
7
|
+
* 2. 依赖注入 - 通过构造函数注入依赖,便于测试和扩展
|
|
8
|
+
* 3. 配置不可变 - 创建后配置基本不可变,提高安全性
|
|
9
|
+
* 4. 职责分离 - 认证、HTTP、模型管理各司其职
|
|
10
|
+
*/
|
|
11
|
+
export declare class LovrabetClient implements ILovrabetClient {
|
|
12
|
+
private config;
|
|
13
|
+
private authManager;
|
|
14
|
+
private httpClient;
|
|
15
|
+
/**
|
|
16
|
+
* 模型管理器公开访问 - 这是用户主要的交互接口
|
|
17
|
+
* 为什么是公开的:用户需要通过 client.models.xxx 访问各种模型
|
|
18
|
+
*/
|
|
19
|
+
models: ModelManager;
|
|
20
|
+
constructor(config: ClientConfig);
|
|
21
|
+
private validateConfig;
|
|
22
|
+
/**
|
|
23
|
+
* 运行时动态设置 token
|
|
24
|
+
* 为什么需要这个方法:
|
|
25
|
+
* 1. 用户登录后可能需要更新 token
|
|
26
|
+
* 2. token 可能会过期需要刷新
|
|
27
|
+
* 3. 支持动态认证切换(比如用户切换账号)
|
|
28
|
+
*/
|
|
29
|
+
setToken(token: string): void;
|
|
30
|
+
/**
|
|
31
|
+
* 获取当前配置的副本
|
|
32
|
+
* 为什么返回副本而不是原始对象:
|
|
33
|
+
* 1. 防止外部代码意外修改内部配置
|
|
34
|
+
* 2. 遵循不可变性原则,保证配置稳定性
|
|
35
|
+
*/
|
|
36
|
+
getConfig(): ClientConfig;
|
|
37
|
+
/**
|
|
38
|
+
* 获取当前环境的 API 基础地址
|
|
39
|
+
* 为什么需要这个方法:
|
|
40
|
+
* 1. 用户可能需要知道当前使用的 API 地址用于调试
|
|
41
|
+
* 2. 某些场景可能需要直接使用基础地址构造 URL
|
|
42
|
+
* 3. 支持自定义服务器地址的覆盖逻辑
|
|
43
|
+
*/
|
|
44
|
+
getBaseUrl(): string;
|
|
45
|
+
/**
|
|
46
|
+
* 动态切换环境
|
|
47
|
+
* 为什么允许运行时切换环境:
|
|
48
|
+
* 1. 开发调试时可能需要在不同环境间切换
|
|
49
|
+
* 2. 某些应用场景需要动态环境选择
|
|
50
|
+
* 注意:这不会影响已缓存的模型实例
|
|
51
|
+
*/
|
|
52
|
+
setEnvironment(env: Environment): void;
|
|
53
|
+
/**
|
|
54
|
+
* 获取当前环境
|
|
55
|
+
* 为什么提供这个方法:用户可能需要根据当前环境执行不同的逻辑
|
|
56
|
+
*/
|
|
57
|
+
getEnvironment(): Environment;
|
|
58
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { ClientConfig, ModelsConfig } from "../types";
|
|
2
|
+
import { LovrabetClient } from "./client";
|
|
3
|
+
/**
|
|
4
|
+
* 创建 Lovrabet 客户端实例 - SDK 的主要入口函数
|
|
5
|
+
*
|
|
6
|
+
* 设计理念:
|
|
7
|
+
* 1. 多重载设计 - 支持 4 种不同的调用方式,满足各种使用场景
|
|
8
|
+
* 2. 智能类型推断 - 根据参数类型自动选择不同的处理逻辑
|
|
9
|
+
* 3. 配置优先级 - 明确的配置合并和覆盖规则
|
|
10
|
+
* 4. 错误优先 - 在客户端创建阶段就发现配置问题
|
|
11
|
+
*
|
|
12
|
+
* @param config - 客户端配置,支持以下类型:
|
|
13
|
+
* - string: 注册的配置名称(如 'default', 'prod')
|
|
14
|
+
* - ModelsConfig: 纯模型配置对象
|
|
15
|
+
* - ClientConfig: 完整的客户端配置对象
|
|
16
|
+
* - ClientConfig & {apiConfigName}: 引用注册配置 + 额外选项
|
|
17
|
+
* @returns Lovrabet client instance
|
|
18
|
+
*/
|
|
19
|
+
export declare function createClient(config?: Partial<ClientConfig> | ModelsConfig | string): LovrabetClient;
|
|
20
|
+
export { LovrabetClient };
|
|
21
|
+
export type { ClientConfig } from "../types";
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SDK 配置常量定义
|
|
3
|
+
* 统一管理 SDK 中使用的各种常量值
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* 默认配置名称常量
|
|
7
|
+
*/
|
|
8
|
+
export declare const CONFIG_NAMES: {
|
|
9
|
+
/** 默认配置名称 */
|
|
10
|
+
readonly DEFAULT: "default";
|
|
11
|
+
/** 生产环境配置 */
|
|
12
|
+
readonly PROD: "prod";
|
|
13
|
+
/** 开发环境配置 */
|
|
14
|
+
readonly DEV: "dev";
|
|
15
|
+
/** 测试环境配置 */
|
|
16
|
+
readonly TEST: "test";
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* 环境常量
|
|
20
|
+
*/
|
|
21
|
+
export declare const ENVIRONMENTS: {
|
|
22
|
+
/** 线上环境 */
|
|
23
|
+
readonly ONLINE: "online";
|
|
24
|
+
/** 日常环境 */
|
|
25
|
+
readonly DAILY: "daily";
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* HTTP 状态码常量
|
|
29
|
+
*/
|
|
30
|
+
export declare const HTTP_STATUS: {
|
|
31
|
+
readonly OK: 200;
|
|
32
|
+
readonly UNAUTHORIZED: 401;
|
|
33
|
+
readonly FORBIDDEN: 403;
|
|
34
|
+
readonly NOT_FOUND: 404;
|
|
35
|
+
readonly INTERNAL_ERROR: 500;
|
|
36
|
+
};
|
|
37
|
+
/**
|
|
38
|
+
* 默认配置值
|
|
39
|
+
*/
|
|
40
|
+
export declare const DEFAULTS: {
|
|
41
|
+
/** 默认环境 */
|
|
42
|
+
readonly ENV: "online";
|
|
43
|
+
/** 默认超时时间(毫秒) */
|
|
44
|
+
readonly TIMEOUT: 30000;
|
|
45
|
+
/** 默认重试次数 */
|
|
46
|
+
readonly RETRY_COUNT: 3;
|
|
47
|
+
/** 默认页大小 */
|
|
48
|
+
readonly PAGE_SIZE: 20;
|
|
49
|
+
/** 默认当前页 */
|
|
50
|
+
readonly CURRENT_PAGE: 1;
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* 错误消息常量
|
|
54
|
+
*/
|
|
55
|
+
export declare const ERROR_MESSAGES: {
|
|
56
|
+
readonly APP_CODE_REQUIRED: "appCode is required. Please provide it in the config or register models first.";
|
|
57
|
+
readonly CONFIG_NOT_FOUND: (name: string) => string;
|
|
58
|
+
readonly INVALID_ENV: "Invalid environment. Must be \"online\" or \"daily\".";
|
|
59
|
+
readonly NETWORK_ERROR: "Network request failed";
|
|
60
|
+
readonly UNAUTHORIZED: "Unauthorized access";
|
|
61
|
+
readonly FORBIDDEN: "Access forbidden";
|
|
62
|
+
readonly NOT_FOUND: "Resource not found";
|
|
63
|
+
readonly SERVER_ERROR: "Internal server error";
|
|
64
|
+
};
|
|
65
|
+
/**
|
|
66
|
+
* API 路径模板
|
|
67
|
+
*/
|
|
68
|
+
export declare const API_PATHS: {
|
|
69
|
+
/** 基础 API 路径模板 */
|
|
70
|
+
readonly BASE: "/api/{appCode}/{datasetId}";
|
|
71
|
+
/** 列表查询路径 */
|
|
72
|
+
readonly LIST: "";
|
|
73
|
+
/** 单条记录路径 */
|
|
74
|
+
readonly DETAIL: "/{id}";
|
|
75
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export declare const API_ENDPOINTS: {
|
|
2
|
+
readonly online: "https://runtime.lovrabet.com";
|
|
3
|
+
readonly daily: "https://daily-runtime.lovrabet.com";
|
|
4
|
+
};
|
|
5
|
+
export type Environment = keyof typeof API_ENDPOINTS;
|
|
6
|
+
/**
|
|
7
|
+
* 获取指定环境的 API 端点
|
|
8
|
+
* @param env - 环境名称
|
|
9
|
+
* @returns API 端点 URL
|
|
10
|
+
*/
|
|
11
|
+
export declare function getApiEndpoint(env: Environment): string;
|
|
12
|
+
/**
|
|
13
|
+
* 获取所有可用的环境
|
|
14
|
+
* @returns 环境列表
|
|
15
|
+
*/
|
|
16
|
+
export declare function getAvailableEnvironments(): Environment[];
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 模型配置注册器 - 全局配置管理中心
|
|
3
|
+
*
|
|
4
|
+
* 设计目的:
|
|
5
|
+
* 1. 配置复用 - 避免在多处重复定义相同的模型配置
|
|
6
|
+
* 2. 多项目支持 - 在同一应用中管理多个项目的配置
|
|
7
|
+
* 3. 简化 API - 让 createClient() 可以无参数调用
|
|
8
|
+
* 4. 类型安全 - 通过命名常量避免字符串拼写错误
|
|
9
|
+
*/
|
|
10
|
+
import type { ModelsConfig } from "../types";
|
|
11
|
+
/**
|
|
12
|
+
* 注册模型配置
|
|
13
|
+
*
|
|
14
|
+
* 为什么需要这个函数:
|
|
15
|
+
* 1. CLI 自动生成 - CLI 工具会调用此函数自动注册配置
|
|
16
|
+
* 2. 手动配置场景 - 用户可以手动注册多个环境或项目的配置
|
|
17
|
+
* 3. 配置集中管理 - 统一的地方管理所有模型配置
|
|
18
|
+
*
|
|
19
|
+
* @param config 模型配置对象
|
|
20
|
+
* @param name 配置名称,默认为 'default'
|
|
21
|
+
*/
|
|
22
|
+
export declare function registerModels(config: ModelsConfig, name?: string): void;
|
|
23
|
+
/**
|
|
24
|
+
* 获取已注册的模型配置
|
|
25
|
+
* @param name 配置名称
|
|
26
|
+
* @returns 模型配置对象
|
|
27
|
+
*/
|
|
28
|
+
export declare function getRegisteredModels(name: string): ModelsConfig | undefined;
|
|
29
|
+
/**
|
|
30
|
+
* 获取所有已注册的配置名称
|
|
31
|
+
* @returns 配置名称数组
|
|
32
|
+
*/
|
|
33
|
+
export declare function getRegisteredConfigNames(): string[];
|
|
34
|
+
/**
|
|
35
|
+
* 清除指定配置
|
|
36
|
+
* @param name 配置名称
|
|
37
|
+
*/
|
|
38
|
+
export declare function unregisterModels(name: string): boolean;
|
|
39
|
+
/**
|
|
40
|
+
* 清除所有配置
|
|
41
|
+
*/
|
|
42
|
+
export declare function clearAllRegistrations(): void;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const get: <ResponseData>(url: string, params?: Record<string, any>, init?: RequestInit) => Promise<ResponseData>;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { ClientConfig, AuthManager } from "../types";
|
|
2
|
+
export declare class HttpClient {
|
|
3
|
+
private config;
|
|
4
|
+
private authManager;
|
|
5
|
+
private errorHandler;
|
|
6
|
+
constructor(config: ClientConfig, authManager: AuthManager);
|
|
7
|
+
private getBaseUrl;
|
|
8
|
+
private getFullUrl;
|
|
9
|
+
/**
|
|
10
|
+
* 准备请求的通用逻辑:认证头、Cookie配置等
|
|
11
|
+
*/
|
|
12
|
+
private prepareRequestInit;
|
|
13
|
+
/**
|
|
14
|
+
* 通用的错误处理包装器
|
|
15
|
+
*/
|
|
16
|
+
private executeWithErrorHandling;
|
|
17
|
+
/**
|
|
18
|
+
* 通用的fetch请求方法(用于PUT/DELETE等没有专门优化函数的方法)
|
|
19
|
+
*/
|
|
20
|
+
private makeRequest;
|
|
21
|
+
get<T = any>(url: string, params?: Record<string, any>, options?: RequestInit): Promise<T>;
|
|
22
|
+
post<T = any>(url: string, data?: any, options?: RequestInit): Promise<T>;
|
|
23
|
+
put<T = any>(url: string, data?: any, options?: RequestInit): Promise<T>;
|
|
24
|
+
delete<T = any>(url: string, options?: RequestInit): Promise<T>;
|
|
25
|
+
request<T = any>(method: "GET" | "POST" | "PUT" | "DELETE", url: string, data?: any, options?: RequestInit): Promise<T>;
|
|
26
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const post: <ResponseData>(url: string, body?: Record<string, any>, init?: RequestInit) => Promise<ResponseData>;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { BaseModelMethods, ListParams, ListResponse, ClientConfig, ModelConfig } from "../types";
|
|
2
|
+
import type { HttpClient } from "../http/http-client";
|
|
3
|
+
export declare class BaseModel implements BaseModelMethods {
|
|
4
|
+
private modelName;
|
|
5
|
+
private httpClient;
|
|
6
|
+
private config;
|
|
7
|
+
private appCode;
|
|
8
|
+
constructor(modelName: string, httpClient: HttpClient, globalConfig: ClientConfig);
|
|
9
|
+
private resolveModelConfig;
|
|
10
|
+
private getApiPath;
|
|
11
|
+
getList<T = any>(params?: ListParams): Promise<ListResponse<T>>;
|
|
12
|
+
getOne<T = any>(id: string | number): Promise<T>;
|
|
13
|
+
create<T = any>(data: Record<string, any>): Promise<T>;
|
|
14
|
+
update<T = any>(id: string | number, data: Record<string, any>): Promise<T>;
|
|
15
|
+
delete(id: string | number): Promise<void>;
|
|
16
|
+
getConfig(): ModelConfig;
|
|
17
|
+
getModelName(): string;
|
|
18
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { ModelManager as IModelManager, ClientConfig } from "../types";
|
|
2
|
+
import type { HttpClient } from "../http/http-client";
|
|
3
|
+
export declare class ModelManager implements IModelManager {
|
|
4
|
+
private httpClient;
|
|
5
|
+
private config;
|
|
6
|
+
private modelCache;
|
|
7
|
+
constructor(httpClient: HttpClient, config: ClientConfig);
|
|
8
|
+
private getModel;
|
|
9
|
+
getCachedModels(): string[];
|
|
10
|
+
clearCache(): void;
|
|
11
|
+
addModel(modelName: string, config: {
|
|
12
|
+
tableName: string;
|
|
13
|
+
datasetId: string;
|
|
14
|
+
}): void;
|
|
15
|
+
}
|
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lovrabet SDK 核心类型定义
|
|
3
|
+
*
|
|
4
|
+
* 本文件包含 SDK 的所有核心类型定义,包括:
|
|
5
|
+
* - 环境配置类型
|
|
6
|
+
* - 请求和响应类型
|
|
7
|
+
* - 模型配置类型
|
|
8
|
+
* - 客户端配置类型
|
|
9
|
+
* - 认证相关类型
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* 环境类型定义
|
|
13
|
+
* @description 支持的运行环境,用于区分不同的 API 端点
|
|
14
|
+
*/
|
|
15
|
+
export type Environment = "online" | "daily";
|
|
16
|
+
/**
|
|
17
|
+
* 列表查询参数接口
|
|
18
|
+
* @description 用于分页查询的通用参数接口
|
|
19
|
+
*/
|
|
20
|
+
export interface ListParams {
|
|
21
|
+
/** 当前页码,从 1 开始 */
|
|
22
|
+
currentPage?: number;
|
|
23
|
+
/** 每页数量 */
|
|
24
|
+
pageSize?: number;
|
|
25
|
+
/** 其他查询参数,支持任意字段 */
|
|
26
|
+
[key: string]: any;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* 列表响应数据接口
|
|
30
|
+
* @template T 数据项的类型
|
|
31
|
+
* @description 分页查询的标准响应格式
|
|
32
|
+
*/
|
|
33
|
+
export interface ListResponse<T> {
|
|
34
|
+
/** 数据列表 */
|
|
35
|
+
tableData: T[];
|
|
36
|
+
/** 总数量 */
|
|
37
|
+
total: number;
|
|
38
|
+
/** 当前页码 */
|
|
39
|
+
currentPage: number;
|
|
40
|
+
/** 每页数量 */
|
|
41
|
+
pageSize: number;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* 单个模型配置接口
|
|
45
|
+
* @description 定义数据模型的基本配置信息
|
|
46
|
+
*/
|
|
47
|
+
export interface ModelConfig {
|
|
48
|
+
/** 数据表名称 */
|
|
49
|
+
tableName: string;
|
|
50
|
+
/** 数据集 ID */
|
|
51
|
+
datasetId: string;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* 模型配置集合接口
|
|
55
|
+
* @description 包含应用代码和所有模型配置的集合
|
|
56
|
+
* @example
|
|
57
|
+
* ```typescript
|
|
58
|
+
* const config: ModelsConfig = {
|
|
59
|
+
* appCode: 'my-app',
|
|
60
|
+
* models: {
|
|
61
|
+
* Users: { tableName: 'users', datasetId: 'user-dataset-id' },
|
|
62
|
+
* Posts: { tableName: 'posts', datasetId: 'post-dataset-id' }
|
|
63
|
+
* }
|
|
64
|
+
* };
|
|
65
|
+
* ```
|
|
66
|
+
*/
|
|
67
|
+
export interface ModelsConfig {
|
|
68
|
+
/** 应用代码,用于标识不同的应用 */
|
|
69
|
+
appCode: string;
|
|
70
|
+
/** 模型配置映射,键为模型名称,值为模型配置 */
|
|
71
|
+
models: Record<string, ModelConfig>;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* 客户端配置接口
|
|
75
|
+
* @description Lovrabet 客户端的完整配置选项
|
|
76
|
+
* @example
|
|
77
|
+
* ```typescript
|
|
78
|
+
* // 基本配置
|
|
79
|
+
* const config: ClientConfig = {
|
|
80
|
+
* appCode: 'my-app',
|
|
81
|
+
* env: 'online',
|
|
82
|
+
* token: 'your-token'
|
|
83
|
+
* };
|
|
84
|
+
*
|
|
85
|
+
* // 引用预注册配置
|
|
86
|
+
* const config: ClientConfig = {
|
|
87
|
+
* apiConfigName: 'prod',
|
|
88
|
+
* token: 'override-token'
|
|
89
|
+
* };
|
|
90
|
+
* ```
|
|
91
|
+
*/
|
|
92
|
+
export interface ClientConfig {
|
|
93
|
+
/** 应用代码,用于标识不同的应用 */
|
|
94
|
+
appCode?: string;
|
|
95
|
+
/** 自定义服务器 URL,可选 */
|
|
96
|
+
serverUrl?: string;
|
|
97
|
+
/** 运行环境,默认为 'online' */
|
|
98
|
+
env?: Environment;
|
|
99
|
+
/** 用户 Token,用于 Bearer 认证 */
|
|
100
|
+
token?: string;
|
|
101
|
+
/** API 访问密钥,用于签名认证 */
|
|
102
|
+
accessKey?: string;
|
|
103
|
+
/** API 密钥,用于签名认证 */
|
|
104
|
+
secretKey?: string;
|
|
105
|
+
/** 是否需要认证,默认为 true */
|
|
106
|
+
requiresAuth?: boolean;
|
|
107
|
+
/** 模型配置映射,直接传入的模型配置 */
|
|
108
|
+
models?: Record<string, ModelConfig>;
|
|
109
|
+
/**
|
|
110
|
+
* 引用已注册的 API 配置名称
|
|
111
|
+
* @description 当指定此字段时,会从配置注册表中获取对应的模型配置
|
|
112
|
+
* @example 'default', 'prod', 'dev'
|
|
113
|
+
*/
|
|
114
|
+
apiConfigName?: string;
|
|
115
|
+
/** 额外配置选项 */
|
|
116
|
+
options?: {
|
|
117
|
+
/** 请求超时时间(毫秒) */
|
|
118
|
+
timeout?: number;
|
|
119
|
+
/** 重试次数 */
|
|
120
|
+
retryCount?: number;
|
|
121
|
+
/** 错误处理回调函数 */
|
|
122
|
+
onError?: (error: any) => void;
|
|
123
|
+
/** 需要重新登录时的回调函数 */
|
|
124
|
+
onRedirectToLogin?: () => void;
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* 基础模型方法接口
|
|
129
|
+
* @description 定义所有模型实例的标准 CRUD 操作方法
|
|
130
|
+
* @template T 数据类型,默认为 any
|
|
131
|
+
* @example
|
|
132
|
+
* ```typescript
|
|
133
|
+
* // 使用示例
|
|
134
|
+
* const users: BaseModelMethods = client.models.Users;
|
|
135
|
+
* const userList = await users.getList({ currentPage: 1, pageSize: 10 });
|
|
136
|
+
* const user = await users.getOne('123');
|
|
137
|
+
* const newUser = await users.create({ name: 'John', email: 'john@example.com' });
|
|
138
|
+
* ```
|
|
139
|
+
*/
|
|
140
|
+
export interface BaseModelMethods {
|
|
141
|
+
/**
|
|
142
|
+
* 获取数据列表
|
|
143
|
+
* @template T 返回数据的类型
|
|
144
|
+
* @param params 查询参数,包含分页等信息
|
|
145
|
+
* @returns 返回分页数据
|
|
146
|
+
*/
|
|
147
|
+
getList<T = any>(params?: ListParams): Promise<ListResponse<T>>;
|
|
148
|
+
/**
|
|
149
|
+
* 获取单条数据
|
|
150
|
+
* @template T 返回数据的类型
|
|
151
|
+
* @param id 数据 ID,支持字符串或数字类型
|
|
152
|
+
* @returns 返回单条数据
|
|
153
|
+
*/
|
|
154
|
+
getOne<T = any>(id: string | number): Promise<T>;
|
|
155
|
+
/**
|
|
156
|
+
* 创建新数据
|
|
157
|
+
* @template T 返回数据的类型
|
|
158
|
+
* @param data 要创建的数据对象
|
|
159
|
+
* @returns 返回创建后的数据
|
|
160
|
+
*/
|
|
161
|
+
create<T = any>(data: Record<string, any>): Promise<T>;
|
|
162
|
+
/**
|
|
163
|
+
* 更新数据
|
|
164
|
+
* @template T 返回数据的类型
|
|
165
|
+
* @param id 要更新的数据 ID
|
|
166
|
+
* @param data 要更新的数据对象
|
|
167
|
+
* @returns 返回更新后的数据
|
|
168
|
+
*/
|
|
169
|
+
update<T = any>(id: string | number, data: Record<string, any>): Promise<T>;
|
|
170
|
+
/**
|
|
171
|
+
* 删除数据
|
|
172
|
+
* @param id 要删除的数据 ID
|
|
173
|
+
* @returns Promise<void>
|
|
174
|
+
*/
|
|
175
|
+
delete(id: string | number): Promise<void>;
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* 模型管理器接口
|
|
179
|
+
* @description 通过 Proxy 实现的动态模型访问管理器
|
|
180
|
+
* @example
|
|
181
|
+
* ```typescript
|
|
182
|
+
* // 动态访问模型
|
|
183
|
+
* client.models.Users.getList(); // 自动创建 Users 模型实例
|
|
184
|
+
* client.models.Posts.getOne(1); // 自动创建 Posts 模型实例
|
|
185
|
+
*
|
|
186
|
+
* // 管理方法
|
|
187
|
+
* client.models.getCachedModels(); // 获取已缓存的模型列表
|
|
188
|
+
* client.models.clearCache(); // 清除所有模型缓存
|
|
189
|
+
* ```
|
|
190
|
+
*/
|
|
191
|
+
export interface ModelManager {
|
|
192
|
+
/** 动态模型访问,支持任意模型名称 */
|
|
193
|
+
[modelName: string]: BaseModelMethods | any;
|
|
194
|
+
/**
|
|
195
|
+
* 获取已缓存的模型列表
|
|
196
|
+
* @returns 返回已创建并缓存的模型名称数组
|
|
197
|
+
*/
|
|
198
|
+
getCachedModels(): string[];
|
|
199
|
+
/**
|
|
200
|
+
* 清除所有模型缓存
|
|
201
|
+
* @description 清除后下次访问模型时会重新创建实例
|
|
202
|
+
*/
|
|
203
|
+
clearCache(): void;
|
|
204
|
+
/**
|
|
205
|
+
* 动态添加模型配置
|
|
206
|
+
* @param modelName 模型名称
|
|
207
|
+
* @param config 模型配置信息
|
|
208
|
+
*/
|
|
209
|
+
addModel(modelName: string, config: {
|
|
210
|
+
tableName: string;
|
|
211
|
+
datasetId: string;
|
|
212
|
+
}): void;
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* 认证请求头接口
|
|
216
|
+
* @description 包含认证信息的 HTTP 请求头
|
|
217
|
+
* @example
|
|
218
|
+
* ```typescript
|
|
219
|
+
* // Bearer Token 认证
|
|
220
|
+
* { "Authorization": "Bearer your-token" }
|
|
221
|
+
*
|
|
222
|
+
* // API 密钥认证
|
|
223
|
+
* { "X-Access-Key": "your-key", "X-Signature": "calculated-signature" }
|
|
224
|
+
* ```
|
|
225
|
+
*/
|
|
226
|
+
export interface AuthHeaders {
|
|
227
|
+
/** 请求头键值对 */
|
|
228
|
+
[key: string]: string;
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* 用户 Token 认证配置
|
|
232
|
+
* @description 用于 Bearer Token 认证方式
|
|
233
|
+
*/
|
|
234
|
+
export interface UserAuthConfig {
|
|
235
|
+
/** 用户认证 Token */
|
|
236
|
+
token: string;
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* OpenAPI 密钥认证配置
|
|
240
|
+
* @description 用于签名认证方式
|
|
241
|
+
*/
|
|
242
|
+
export interface OpenApiAuthConfig {
|
|
243
|
+
/** API 访问密钥 */
|
|
244
|
+
accessKey: string;
|
|
245
|
+
/** API 密钥,用于计算签名 */
|
|
246
|
+
secretKey: string;
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* 认证管理器接口
|
|
250
|
+
* @description 统一管理不同的认证方式,按优先级自动选择认证策略
|
|
251
|
+
* 认证优先级:Token > OpenAPI密钥 > Cookie
|
|
252
|
+
* @example
|
|
253
|
+
* ```typescript
|
|
254
|
+
* // 设置 Token 认证
|
|
255
|
+
* authManager.setToken('your-token');
|
|
256
|
+
*
|
|
257
|
+
* // 获取认证头
|
|
258
|
+
* const headers = await authManager.getAuthHeaders();
|
|
259
|
+
* // 返回: { "Authorization": "Bearer your-token" }
|
|
260
|
+
* ```
|
|
261
|
+
*/
|
|
262
|
+
export interface AuthManager {
|
|
263
|
+
/**
|
|
264
|
+
* 获取认证请求头
|
|
265
|
+
* @description 根据当前配置的认证方式生成对应的请求头
|
|
266
|
+
* @returns 包含认证信息的请求头对象
|
|
267
|
+
*/
|
|
268
|
+
getAuthHeaders(): Promise<AuthHeaders>;
|
|
269
|
+
/**
|
|
270
|
+
* 验证当前认证是否有效
|
|
271
|
+
* @returns 认证是否有效
|
|
272
|
+
*/
|
|
273
|
+
validateAuth(): Promise<boolean>;
|
|
274
|
+
/**
|
|
275
|
+
* 设置用户 Token
|
|
276
|
+
* @param token 用户认证 Token
|
|
277
|
+
*/
|
|
278
|
+
setToken(token: string): void;
|
|
279
|
+
/**
|
|
280
|
+
* 检查是否使用 Cookie 认证
|
|
281
|
+
* @description 当没有 Token 和 API 密钥时,会降级到 Cookie 认证
|
|
282
|
+
* @returns 是否使用 Cookie 认证
|
|
283
|
+
*/
|
|
284
|
+
isCookieAuth(): boolean;
|
|
285
|
+
}
|
|
286
|
+
/**
|
|
287
|
+
* Lovrabet 客户端接口
|
|
288
|
+
* @description SDK 的主要客户端接口,提供模型访问和配置管理功能
|
|
289
|
+
* @example
|
|
290
|
+
* ```typescript
|
|
291
|
+
* // 创建客户端
|
|
292
|
+
* const client = createClient();
|
|
293
|
+
*
|
|
294
|
+
* // 使用模型
|
|
295
|
+
* const users = await client.models.Users.getList();
|
|
296
|
+
*
|
|
297
|
+
* // 设置认证
|
|
298
|
+
* client.setToken('new-token');
|
|
299
|
+
*
|
|
300
|
+
* // 获取配置
|
|
301
|
+
* const config = client.getConfig();
|
|
302
|
+
* ```
|
|
303
|
+
*/
|
|
304
|
+
export interface LovrabetClient {
|
|
305
|
+
/**
|
|
306
|
+
* 模型管理器
|
|
307
|
+
* @description 通过此属性可以访问所有已配置的数据模型
|
|
308
|
+
*/
|
|
309
|
+
models: ModelManager;
|
|
310
|
+
/**
|
|
311
|
+
* 设置用户认证 Token
|
|
312
|
+
* @param token 用户认证 Token
|
|
313
|
+
* @description 设置后所有 API 请求将使用此 Token 进行认证
|
|
314
|
+
*/
|
|
315
|
+
setToken(token: string): void;
|
|
316
|
+
/**
|
|
317
|
+
* 获取客户端配置
|
|
318
|
+
* @returns 当前客户端的完整配置信息
|
|
319
|
+
*/
|
|
320
|
+
getConfig(): ClientConfig;
|
|
321
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export declare class LovrabetError extends Error {
|
|
2
|
+
readonly status?: number;
|
|
3
|
+
readonly code?: string;
|
|
4
|
+
readonly data?: any;
|
|
5
|
+
readonly originalError?: Error;
|
|
6
|
+
constructor(message: string, status?: number, code?: string, data?: any, originalError?: Error);
|
|
7
|
+
toJSON(): {
|
|
8
|
+
name: string;
|
|
9
|
+
message: string;
|
|
10
|
+
status: number;
|
|
11
|
+
code: string;
|
|
12
|
+
data: any;
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
export declare function createErrorHandler(onError?: (error: any) => void): (error: any) => Promise<never>;
|
package/package.json
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@lovrabet/sdk",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"main": "dist/index.js",
|
|
5
|
+
"module": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"import": "./dist/index.js",
|
|
10
|
+
"require": "./dist/index.js",
|
|
11
|
+
"types": "./dist/index.d.ts"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"type": "module",
|
|
15
|
+
"scripts": {
|
|
16
|
+
"build": "rm -rf dist && bun build index.ts --outdir=dist --target=browser --format=esm && javascript-obfuscator dist --output dist && npm run types",
|
|
17
|
+
"types": "npx tsc --emitDeclarationOnly --declaration --outDir dist index.ts",
|
|
18
|
+
"release": "bun run build && bun pm version patch && git push && git push origin --tag && bun publish"
|
|
19
|
+
},
|
|
20
|
+
"files": [
|
|
21
|
+
"dist"
|
|
22
|
+
],
|
|
23
|
+
"devDependencies": {
|
|
24
|
+
"@types/bun": "latest",
|
|
25
|
+
"javascript-obfuscator": "^4.1.1"
|
|
26
|
+
},
|
|
27
|
+
"peerDependencies": {
|
|
28
|
+
"typescript": "^5"
|
|
29
|
+
}
|
|
30
|
+
}
|