@seaverse/data-sdk 0.2.6 → 0.3.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/README.md CHANGED
@@ -32,6 +32,7 @@
32
32
  - ✅ 支持过滤、排序、分页
33
33
  - ✅ 支持标签和 JSONB 字段查询
34
34
  - ✅ **零配置使用** - 自动从 PostMessage 获取配置
35
+ - ✅ **自动配额限制** - 数据库层强制执行配额,防止资源滥用
35
36
 
36
37
  ## 安装
37
38
 
@@ -41,20 +42,63 @@ npm install @seaverse/data-sdk
41
42
 
42
43
  ## 快速开始
43
44
 
44
- ### 使用 DataClient
45
+ ### 方式1: 函数式 API(推荐 ⭐)
46
+
47
+ 最简单的使用方式 - 零配置,直接调用函数:
48
+
49
+ ```typescript
50
+ import { query, create, update, deleteData } from '@seaverse/data-sdk';
51
+
52
+ // 第一次调用自动初始化 SDK(从 PostMessage 获取 appId 和 token)
53
+ // 无需任何配置代码!
54
+
55
+ // 查询数据
56
+ const notes = await query({
57
+ table_name: 'notes',
58
+ filters: { category: 'work' },
59
+ order: { field: 'created_at', direction: 'desc' }
60
+ });
61
+
62
+ // 创建数据
63
+ const newNote = await create({
64
+ table_name: 'notes',
65
+ data_value: { title: 'My Note', content: '...' },
66
+ visibility: 'private'
67
+ });
68
+
69
+ // 更新数据
70
+ await update(newNote.id, {
71
+ data_value: { title: 'Updated Title' }
72
+ });
73
+
74
+ // 删除数据
75
+ await deleteData(newNote.id);
76
+ ```
77
+
78
+ **为什么推荐函数式 API:**
79
+ - ✅ **零配置** - 无需创建客户端实例,直接调用函数
80
+ - ✅ **自动初始化** - 第一次调用自动获取配置(PostMessage)
81
+ - ✅ **代码简洁** - 代码更简洁,更易理解
82
+ - ✅ **单例管理** - SDK 自动管理全局实例,避免重复初始化
83
+
84
+ ---
85
+
86
+ ### 方式2: DataClient 类 API(高级场景)
87
+
88
+ 适用于需要多个实例或自定义配置的场景:
45
89
 
46
90
  ```typescript
47
91
  import { DataClient } from '@seaverse/data-sdk';
48
92
 
49
- // 方式1: 零配置(推荐)- 自动从 PostMessage 获取 appId 和 token
93
+ // 方式2a: 零配置(推荐)- 自动从 PostMessage 获取 appId 和 token
50
94
  const client = await DataClient.create();
51
95
 
52
- // 方式2: 只提供 appId,token 自动获取
96
+ // 方式2b: 只提供 appId,token 自动获取
53
97
  const client = await DataClient.create({
54
98
  appId: 'my-app-123',
55
99
  });
56
100
 
57
- // 方式3: 显式提供所有配置
101
+ // 方式2c: 显式提供所有配置
58
102
  const client = new DataClient({
59
103
  appId: 'my-app-123',
60
104
  token: 'user-jwt-token',
@@ -64,23 +108,7 @@ const client = new DataClient({
64
108
  const notes = await client.query({
65
109
  table_name: 'notes',
66
110
  filters: { category: 'work' },
67
- order: { field: 'created_at', direction: 'desc' },
68
- });
69
-
70
- // 创建数据
71
- const newNote = await client.create({
72
- table_name: 'notes',
73
- data_value: { title: 'My Note', content: '...' },
74
- visibility: 'private',
75
111
  });
76
-
77
- // 更新数据
78
- await client.update('note-id-123', {
79
- data_value: { title: 'Updated' },
80
- });
81
-
82
- // 删除数据
83
- await client.delete('note-id-123');
84
112
  ```
85
113
 
86
114
  **配置选项说明:**
@@ -530,6 +558,86 @@ client.updateToken('new-jwt-token');
530
558
  client.updateAppId('another-app-id');
531
559
  ```
532
560
 
561
+ ### 配额限制
562
+
563
+ Data SDK 在数据库层实现了自动配额限制,防止单个应用占用过多资源。
564
+
565
+ #### 配额说明
566
+
567
+ SDK 支持以下配额限制(在数据库层通过触发器强制执行,无法绕过):
568
+
569
+ | 配额类型 | 默认值 | 说明 |
570
+ |---------|-------|------|
571
+ | 总数据条数 | 100,000 条 | 单个应用的最大数据总量 |
572
+ | 单表数据条数 | 50,000 条 | 单个 table_name 的最大数据量 |
573
+ | 存储空间 | 1 GB | 单个应用的最大存储空间 |
574
+ | 每分钟操作 | 1,000 次 | 防止短时间内大量操作 |
575
+ | 每小时操作 | 10,000 次 | 防止持续高频操作 |
576
+ | 每天操作 | 100,000 次 | 防止每日滥用 |
577
+
578
+ **配额检查机制:**
579
+ - 创建操作(CREATE):检查数据总量、单表数据量、存储空间、操作频率
580
+ - 更新操作(UPDATE):检查存储空间变化、操作频率
581
+ - 删除操作(DELETE):检查操作频率
582
+
583
+ 超限时会自动抛出错误,操作被拒绝并回滚。
584
+
585
+ #### 错误处理
586
+
587
+ ```typescript
588
+ try {
589
+ await client.create({
590
+ table_name: 'notes',
591
+ data_value: { title: 'New Note' },
592
+ });
593
+ } catch (error) {
594
+ // 检查是否是配额超限错误
595
+ if (error.message && error.message.includes('Quota exceeded')) {
596
+ console.error('配额超限:', error.message);
597
+ // 示例错误信息:
598
+ // "Quota exceeded: Total records quota exceeded: 100000/100000 records"
599
+ // "Quota exceeded: Storage quota exceeded: 1024.5 MB/1024 MB"
600
+ // "Quota exceeded: Rate limit exceeded: 1234/1000 operations in last minute"
601
+ } else {
602
+ console.error('操作失败:', error);
603
+ }
604
+ }
605
+ ```
606
+
607
+ #### 平台管理员监控
608
+
609
+ 配额的监控和调整由平台管理员通过数据库查询完成:
610
+
611
+ ```sql
612
+ -- 查看所有应用的使用情况
613
+ SELECT
614
+ u.app_id,
615
+ u.total_records,
616
+ ROUND(u.total_storage_bytes::numeric / 1024 / 1024, 2) as storage_mb,
617
+ q.max_total_records,
618
+ ROUND((u.total_records::numeric / q.max_total_records * 100), 2) as usage_percent
619
+ FROM app_usage_stats u
620
+ LEFT JOIN app_quotas q ON u.app_id = q.app_id
621
+ ORDER BY usage_percent DESC;
622
+
623
+ -- 查找接近配额的应用(预警)
624
+ SELECT app_id, usage_percent
625
+ FROM (
626
+ SELECT
627
+ u.app_id,
628
+ ROUND((u.total_records::numeric / q.max_total_records * 100), 2) as usage_percent
629
+ FROM app_usage_stats u
630
+ INNER JOIN app_quotas q ON u.app_id = q.app_id
631
+ ) t
632
+ WHERE usage_percent > 80;
633
+
634
+ -- 为应用调整配额
635
+ UPDATE app_quotas
636
+ SET max_total_records = 500000,
637
+ max_storage_bytes = 5368709120 -- 5GB
638
+ WHERE app_id = 'your-app-id';
639
+ ```
640
+
533
641
  ### JSONB 字段查询
534
642
 
535
643
  ```typescript
package/dist/index.cjs CHANGED
@@ -160,52 +160,6 @@ function resolveBaseURL(options) {
160
160
  const detectedEnv = detectEnvironment();
161
161
  return ENVIRONMENT_CONFIGS[detectedEnv].baseURL;
162
162
  }
163
- /**
164
- * 解析用户配置,返回最终的 baseURL(异步版本)
165
- *
166
- * 优先级:
167
- * 1. 显式传入的 baseURL(最高优先级)
168
- * 2. 环境变量 DATA_SDK_BASE_URL
169
- * 3. environment 参数指定的环境
170
- * 4. iframe 环境 - 从父页面获取环境标识
171
- * - 父页面返回 'develop' → development 环境
172
- * - 父页面返回 'production' → production 环境
173
- * - 父页面返回其他值 → 自动检测环境
174
- * 5. 非 iframe 环境 - 自动检测环境
175
- *
176
- * @param options 用户配置选项
177
- * @returns 最终使用的 baseURL
178
- */
179
- async function resolveBaseURLAsync(options) {
180
- // 优先级 1: 显式传入的 baseURL
181
- if (options.baseURL) {
182
- return options.baseURL;
183
- }
184
- // 优先级 2: 环境变量 DATA_SDK_BASE_URL
185
- if (typeof process !== 'undefined' && process.env?.DATA_SDK_BASE_URL) {
186
- return process.env.DATA_SDK_BASE_URL;
187
- }
188
- // 优先级 3: environment 参数
189
- if (options.environment) {
190
- return ENVIRONMENT_CONFIGS[options.environment].baseURL;
191
- }
192
- // 优先级 4: iframe 环境 - 从父页面获取环境标识
193
- if (isInIframe()) {
194
- const parentEnv = await getEnvFromParent(3000);
195
- if (parentEnv === 'develop') {
196
- console.log('[DataSDK] iframe 环境:父页面返回开发环境,使用 development baseURL');
197
- return ENVIRONMENT_CONFIGS.development.baseURL;
198
- }
199
- else if (parentEnv === 'production') {
200
- console.log('[DataSDK] iframe 环境:父页面返回生产环境,使用 production baseURL');
201
- return ENVIRONMENT_CONFIGS.production.baseURL;
202
- }
203
- // 如果获取到其他值或没有获取到,继续自动检测
204
- }
205
- // 优先级 5: 自动检测环境
206
- const detectedEnv = detectEnvironment();
207
- return ENVIRONMENT_CONFIGS[detectedEnv].baseURL;
208
- }
209
163
  /**
210
164
  * 默认超时时间(毫秒)
211
165
  */
@@ -338,59 +292,6 @@ async function getAppIdFromParent(timeout = 5000) {
338
292
  }
339
293
  });
340
294
  }
341
- /**
342
- * 通过 PostMessage 从父页面获取环境标识
343
- *
344
- * 此函数允许接收来自任何源的 PostMessage 消息,便于跨域 iframe 集成。
345
- * 使用 seaverse 协议与父页面通信:
346
- * - 发送: { type: 'seaverse:get_env' }
347
- * - 接收: { type: 'seaverse:env', payload: { env: string } }
348
- * - 错误: { type: 'seaverse:error', error: string }
349
- *
350
- * @param timeout 超时时间(毫秒),默认 5000ms
351
- * @returns 环境标识字符串 (如 "develop", "production") 或 null
352
- */
353
- async function getEnvFromParent(timeout = 5000) {
354
- if (!isInIframe()) {
355
- return null;
356
- }
357
- return new Promise((resolve) => {
358
- const messageHandler = (event) => {
359
- // 验证消息格式
360
- if (event.data && event.data.type === 'seaverse:env') {
361
- cleanup();
362
- // 从 payload.env 中获取环境标识
363
- const env = event.data.payload?.env;
364
- resolve(env || null);
365
- }
366
- else if (event.data && event.data.type === 'seaverse:error') {
367
- // 处理错误响应
368
- cleanup();
369
- console.warn('[DataSDK] Error getting env from parent:', event.data.error);
370
- resolve(null);
371
- }
372
- };
373
- const timeoutId = setTimeout(() => {
374
- cleanup();
375
- resolve(null);
376
- }, timeout);
377
- const cleanup = () => {
378
- clearTimeout(timeoutId);
379
- globalThis.window.removeEventListener('message', messageHandler);
380
- };
381
- // 监听父页面的响应(不限制来源)
382
- globalThis.window.addEventListener('message', messageHandler);
383
- // 向父页面发送请求(允许任何源接收)
384
- try {
385
- globalThis.window.parent.postMessage({ type: 'seaverse:get_env' }, '*' // 允许任何源,支持跨域场景
386
- );
387
- }
388
- catch (e) {
389
- cleanup();
390
- resolve(null);
391
- }
392
- });
393
- }
394
295
  /**
395
296
  * 动态获取 API Token
396
297
  * 优先级:
@@ -476,40 +377,42 @@ async function getAppId(providedAppId) {
476
377
  */
477
378
  class DataClient {
478
379
  /**
479
- * 创建 DataClient 实例(异步工厂方法)
380
+ * 连接到 Data SDK 服务(推荐 - 零配置优先)
480
381
  *
481
- * 支持自动从 localStorage/环境变量/PostMessage 获取 appId、tokenbaseURL
382
+ * 支持自动从 PostMessage 获取 appId 和 token,自动检测环境
482
383
  *
483
- * @param options - 配置选项(appId 和 token 可选)
384
+ * @param options - 连接选项(所有参数都是可选的)
484
385
  * @returns DataClient 实例
485
386
  *
486
387
  * @example
487
388
  * ```typescript
488
- * // 自动获取 appId token,并通过 PostMessage 获取环境配置
489
- * const client = await DataClient.create();
389
+ * // 🎯 零配置(推荐 - 最简单)
390
+ * const client = await DataClient.connect();
490
391
  *
491
- * // 提供 appId,自动获取 token
492
- * const client = await DataClient.create({ appId: 'my-app-123' });
392
+ * // 部分配置
393
+ * const client = await DataClient.connect({
394
+ * appId: 'my-app-123' // 只提供 appId,其他自动获取
395
+ * });
493
396
  *
494
- * // 显式提供所有配置
495
- * const client = await DataClient.create({
397
+ * // 完整配置
398
+ * const client = await DataClient.connect({
496
399
  * appId: 'my-app-123',
497
400
  * token: 'user-jwt-token',
498
401
  * environment: 'production'
499
402
  * });
500
403
  * ```
501
404
  */
502
- static async create(options = {}) {
405
+ static async connect(options = {}) {
503
406
  const appId = options.appId || (await getAppId());
504
407
  const token = options.token || (await getApiToken());
505
408
  if (!appId) {
506
- throw new ValidationError('appId is required. Please ensure it is available in localStorage.app_id, provide appId explicitly, or configure parent page to provide it via PostMessage.');
409
+ throw new ValidationError('appId is required. Please provide it explicitly or configure parent page to send it via PostMessage.');
507
410
  }
508
411
  if (!token) {
509
- throw new ValidationError('token is required. Please ensure it is available in localStorage.auth_token, provide token explicitly, or configure parent page to provide it via PostMessage.');
412
+ throw new ValidationError('token is required. Please provide it explicitly or configure parent page to send it via PostMessage.');
510
413
  }
511
- // 使用异步版本解析 baseURL,支持环境变量和 PostMessage
512
- const baseURL = await resolveBaseURLAsync({
414
+ // 解析 baseURL
415
+ const baseURL = resolveBaseURL({
513
416
  baseURL: options.baseURL,
514
417
  environment: options.environment,
515
418
  });
@@ -517,9 +420,36 @@ class DataClient {
517
420
  ...options,
518
421
  appId,
519
422
  token,
520
- baseURL, // 传递已解析的 baseURL
423
+ baseURL,
521
424
  });
522
425
  }
426
+ /**
427
+ * 创建 DataClient 实例(异步工厂方法)
428
+ *
429
+ * @deprecated 推荐使用 connect() 方法
430
+ * @param options - 配置选项(appId 和 token 可选)
431
+ * @returns DataClient 实例
432
+ *
433
+ * @example
434
+ * ```typescript
435
+ * // 自动获取 appId 和 token,并通过 PostMessage 获取环境配置
436
+ * const client = await DataClient.create();
437
+ *
438
+ * // 提供 appId,自动获取 token
439
+ * const client = await DataClient.create({ appId: 'my-app-123' });
440
+ *
441
+ * // 显式提供所有配置
442
+ * const client = await DataClient.create({
443
+ * appId: 'my-app-123',
444
+ * token: 'user-jwt-token',
445
+ * environment: 'production'
446
+ * });
447
+ * ```
448
+ */
449
+ static async create(options = {}) {
450
+ // 直接调用 connect 方法
451
+ return DataClient.connect(options);
452
+ }
523
453
  constructor(options) {
524
454
  const { timeout = DEFAULT_TIMEOUT, headers = {}, appId, token, debug = false, } = options;
525
455
  if (!appId) {
@@ -1106,6 +1036,305 @@ class DataClient {
1106
1036
  }
1107
1037
  }
1108
1038
 
1039
+ /**
1040
+ * 全局单例管理
1041
+ *
1042
+ * 为函数式 API 提供自动初始化和实例复用能力
1043
+ */
1044
+ /**
1045
+ * 全局单例客户端实例
1046
+ */
1047
+ let globalClient = null;
1048
+ /**
1049
+ * 初始化 Promise(防止并发初始化)
1050
+ */
1051
+ let initPromise = null;
1052
+ /**
1053
+ * 初始化状态标志
1054
+ */
1055
+ let isInitializing = false;
1056
+ /**
1057
+ * 获取全局客户端实例(自动初始化)
1058
+ *
1059
+ * 工作流程:
1060
+ * 1. 如果已初始化 → 直接返回实例
1061
+ * 2. 如果正在初始化 → 等待初始化完成
1062
+ * 3. 如果未初始化 → 触发初始化
1063
+ *
1064
+ * @returns DataClient 实例
1065
+ * @throws 如果初始化失败(缺少 appId 或 token)
1066
+ */
1067
+ async function getGlobalClient() {
1068
+ // 快速路径:已经初始化完成
1069
+ if (globalClient) {
1070
+ return globalClient;
1071
+ }
1072
+ // 中速路径:正在初始化,等待完成
1073
+ if (initPromise) {
1074
+ return initPromise;
1075
+ }
1076
+ // 慢速路径:首次调用,需要初始化
1077
+ if (!isInitializing) {
1078
+ isInitializing = true;
1079
+ initPromise = (async () => {
1080
+ try {
1081
+ if (process.env.NODE_ENV !== 'production') {
1082
+ console.log('[DataSDK] 🚀 自动初始化...');
1083
+ }
1084
+ // 调用 DataClient.connect() 进行零配置初始化
1085
+ const client = await DataClient.connect();
1086
+ // 缓存实例
1087
+ globalClient = client;
1088
+ if (process.env.NODE_ENV !== 'production') {
1089
+ console.log('[DataSDK] ✅ 自动初始化成功');
1090
+ }
1091
+ return client;
1092
+ }
1093
+ catch (error) {
1094
+ if (process.env.NODE_ENV !== 'production') {
1095
+ console.error('[DataSDK] ❌ 自动初始化失败:', error);
1096
+ }
1097
+ // 重置状态,允许下次重试
1098
+ isInitializing = false;
1099
+ initPromise = null;
1100
+ throw error;
1101
+ }
1102
+ })();
1103
+ }
1104
+ return initPromise;
1105
+ }
1106
+ /**
1107
+ * 重新初始化全局客户端
1108
+ *
1109
+ * 用于以下场景:
1110
+ * - 用户登录后切换 token
1111
+ * - 切换到其他应用
1112
+ * - 需要更新配置
1113
+ *
1114
+ * @param options 连接选项(可选)
1115
+ *
1116
+ * @example
1117
+ * ```typescript
1118
+ * import { reinit } from '@seaverse/data-sdk';
1119
+ *
1120
+ * // 用户登录后,使用新 token
1121
+ * await reinit({ token: newToken });
1122
+ *
1123
+ * // 切换到其他应用
1124
+ * await reinit({ appId: 'another-app', token: anotherToken });
1125
+ *
1126
+ * // 完全重置(重新从 PostMessage 获取)
1127
+ * await reinit();
1128
+ * ```
1129
+ */
1130
+ async function reinit(options = {}) {
1131
+ if (process.env.NODE_ENV !== 'production') {
1132
+ console.log('[DataSDK] 🔄 重新初始化...');
1133
+ }
1134
+ // 清除旧实例和状态
1135
+ globalClient = null;
1136
+ initPromise = null;
1137
+ isInitializing = false;
1138
+ // 创建新实例
1139
+ const client = await DataClient.connect(options);
1140
+ globalClient = client;
1141
+ if (process.env.NODE_ENV !== 'production') {
1142
+ console.log('[DataSDK] ✅ 重新初始化成功');
1143
+ }
1144
+ }
1145
+ /**
1146
+ * 获取当前客户端状态
1147
+ *
1148
+ * @returns 客户端状态信息
1149
+ *
1150
+ * @example
1151
+ * ```typescript
1152
+ * import { getClientStatus } from '@seaverse/data-sdk';
1153
+ *
1154
+ * const status = getClientStatus();
1155
+ * console.log('是否已初始化:', status.initialized);
1156
+ * console.log('是否正在初始化:', status.initializing);
1157
+ * ```
1158
+ */
1159
+ function getClientStatus() {
1160
+ return {
1161
+ initialized: globalClient !== null,
1162
+ initializing: isInitializing,
1163
+ hasInstance: globalClient !== null
1164
+ };
1165
+ }
1166
+
1167
+ /**
1168
+ * 函数式 API
1169
+ *
1170
+ * 提供零配置的便捷函数,自动管理全局客户端实例
1171
+ */
1172
+ /**
1173
+ * 查询数据
1174
+ *
1175
+ * 首次调用会自动初始化 SDK(从 PostMessage 获取配置)
1176
+ *
1177
+ * @param options 查询选项
1178
+ * @returns 数据记录数组
1179
+ *
1180
+ * @example
1181
+ * ```typescript
1182
+ * import { query } from '@seaverse/data-sdk';
1183
+ *
1184
+ * const notes = await query({ table_name: 'notes' });
1185
+ *
1186
+ * const filtered = await query({
1187
+ * table_name: 'notes',
1188
+ * filters: { category: 'work' },
1189
+ * order: { field: 'created_at', direction: 'desc' }
1190
+ * });
1191
+ * ```
1192
+ */
1193
+ async function query(options) {
1194
+ const client = await getGlobalClient();
1195
+ return client.query(options);
1196
+ }
1197
+ /**
1198
+ * 获取单条数据
1199
+ *
1200
+ * @param id 数据 ID
1201
+ * @returns 数据记录,如果不存在返回 null
1202
+ *
1203
+ * @example
1204
+ * ```typescript
1205
+ * import { get } from '@seaverse/data-sdk';
1206
+ *
1207
+ * const note = await get('note-id-123');
1208
+ * if (note) {
1209
+ * console.log('标题:', note.data_value.title);
1210
+ * }
1211
+ * ```
1212
+ */
1213
+ async function get(id) {
1214
+ const client = await getGlobalClient();
1215
+ return client.get(id);
1216
+ }
1217
+ /**
1218
+ * 创建数据
1219
+ *
1220
+ * @param options 创建选项
1221
+ * @returns 创建的数据记录
1222
+ *
1223
+ * @example
1224
+ * ```typescript
1225
+ * import { create } from '@seaverse/data-sdk';
1226
+ *
1227
+ * const note = await create({
1228
+ * table_name: 'notes',
1229
+ * data_value: {
1230
+ * title: 'Hello',
1231
+ * content: 'World'
1232
+ * },
1233
+ * visibility: 'private',
1234
+ * tags: ['important']
1235
+ * });
1236
+ * ```
1237
+ */
1238
+ async function create(options) {
1239
+ const client = await getGlobalClient();
1240
+ return client.create(options);
1241
+ }
1242
+ /**
1243
+ * 更新数据
1244
+ *
1245
+ * @param id 数据 ID
1246
+ * @param options 更新选项
1247
+ * @returns 更新后的数据记录
1248
+ *
1249
+ * @example
1250
+ * ```typescript
1251
+ * import { update } from '@seaverse/data-sdk';
1252
+ *
1253
+ * await update('note-id-123', {
1254
+ * data_value: { title: 'Updated Title' }
1255
+ * });
1256
+ * ```
1257
+ */
1258
+ async function update(id, options) {
1259
+ const client = await getGlobalClient();
1260
+ return client.update(id, options);
1261
+ }
1262
+ /**
1263
+ * 删除数据
1264
+ *
1265
+ * @param id 数据 ID
1266
+ *
1267
+ * @example
1268
+ * ```typescript
1269
+ * import { deleteData } from '@seaverse/data-sdk';
1270
+ *
1271
+ * await deleteData('note-id-123');
1272
+ * ```
1273
+ */
1274
+ async function deleteData(id) {
1275
+ const client = await getGlobalClient();
1276
+ return client.delete(id);
1277
+ }
1278
+ /**
1279
+ * 批量删除数据
1280
+ *
1281
+ * @param ids 数据 ID 数组
1282
+ *
1283
+ * @example
1284
+ * ```typescript
1285
+ * import { batchDelete } from '@seaverse/data-sdk';
1286
+ *
1287
+ * await batchDelete(['id1', 'id2', 'id3']);
1288
+ * ```
1289
+ */
1290
+ async function batchDelete(ids) {
1291
+ const client = await getGlobalClient();
1292
+ return client.batchDelete(ids);
1293
+ }
1294
+ /**
1295
+ * 分页查询
1296
+ *
1297
+ * @param options 查询选项(包含分页参数)
1298
+ * @returns 分页响应(包含数据、总数等)
1299
+ *
1300
+ * @example
1301
+ * ```typescript
1302
+ * import { queryWithPagination } from '@seaverse/data-sdk';
1303
+ *
1304
+ * const result = await queryWithPagination({
1305
+ * table_name: 'notes',
1306
+ * pagination: { limit: 20, offset: 0 }
1307
+ * });
1308
+ *
1309
+ * console.log('数据:', result.data);
1310
+ * console.log('总数:', result.total);
1311
+ * console.log('是否有更多:', result.hasMore);
1312
+ * ```
1313
+ */
1314
+ async function queryWithPagination(options) {
1315
+ const client = await getGlobalClient();
1316
+ return client.queryWithPagination(options);
1317
+ }
1318
+ /**
1319
+ * 检查当前用户是否为管理员
1320
+ *
1321
+ * @returns 是否为管理员
1322
+ *
1323
+ * @example
1324
+ * ```typescript
1325
+ * import { isAdmin } from '@seaverse/data-sdk';
1326
+ *
1327
+ * const admin = await isAdmin();
1328
+ * if (admin) {
1329
+ * console.log('当前用户是管理员');
1330
+ * }
1331
+ * ```
1332
+ */
1333
+ async function isAdmin() {
1334
+ const client = await getGlobalClient();
1335
+ return client.isAdmin();
1336
+ }
1337
+
1109
1338
  exports.DataClient = DataClient;
1110
1339
  exports.DataSDKError = DataSDKError;
1111
1340
  exports.NotFoundError = NotFoundError;
@@ -1113,4 +1342,14 @@ exports.PermissionError = PermissionError;
1113
1342
  exports.RateLimitError = RateLimitError;
1114
1343
  exports.SDKError = SDKError;
1115
1344
  exports.ValidationError = ValidationError;
1345
+ exports.batchDelete = batchDelete;
1346
+ exports.create = create;
1347
+ exports.deleteData = deleteData;
1348
+ exports.get = get;
1349
+ exports.getClientStatus = getClientStatus;
1350
+ exports.isAdmin = isAdmin;
1351
+ exports.query = query;
1352
+ exports.queryWithPagination = queryWithPagination;
1353
+ exports.reinit = reinit;
1354
+ exports.update = update;
1116
1355
  //# sourceMappingURL=index.cjs.map