@seaverse/data-sdk 0.2.5 → 0.3.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 CHANGED
@@ -5,22 +5,6 @@
5
5
 
6
6
  高性能数据服务 SDK,基于 PostgreSQL/AlloyDB + PostgREST + RLS 架构。
7
7
 
8
- ## 🚀 核心概念
9
-
10
- ### App ID 是什么?
11
-
12
- **App ID** 是您在 SeaVerse 平台上创建的应用的唯一标识符。它用于:
13
- - ✅ 多租户数据隔离(每个应用的数据互不干扰)
14
- - ✅ 权限控制(RLS 策略基于 app_id)
15
- - ✅ 资源配额管理
16
-
17
- **如何获取 App ID?**
18
- 1. 登录 [SeaVerse 控制台](https://console.seaverse.ai)
19
- 2. 进入"应用管理"
20
- 3. 复制您的 App ID
21
-
22
- > ⚠️ **重要**:所有 SDK 操作都需要提供有效的 `appId`,否则无法访问数据。
23
-
24
8
  ## 特性
25
9
 
26
10
  - ✅ TypeScript 类型支持
@@ -41,48 +25,75 @@ npm install @seaverse/data-sdk
41
25
 
42
26
  ## 快速开始
43
27
 
44
- ### 使用 DataClient
28
+ ### 方式 1: 函数式 API(推荐 ⭐)
45
29
 
46
- ```typescript
47
- import { DataClient } from '@seaverse/data-sdk';
30
+ 最简单的使用方式,零配置,自动初始化:
48
31
 
49
- // 方式1: 零配置(推荐)- 自动从 PostMessage 获取 appId 和 token
50
- const client = await DataClient.create();
32
+ ```typescript
33
+ import { query, create, update, deleteData } from '@seaverse/data-sdk';
51
34
 
52
- // 方式2: 只提供 appIdtoken 自动获取
53
- const client = await DataClient.create({
54
- appId: 'my-app-123',
55
- });
35
+ // 首次调用会自动初始化 SDK(从 PostMessage 获取 appIdtoken
36
+ // 无需任何配置代码!
56
37
 
57
- // 方式3: 显式提供所有配置
58
- const client = new DataClient({
59
- appId: 'my-app-123',
60
- token: 'user-jwt-token',
61
- });
62
-
63
- // 使用 client 实例
64
- const notes = await client.query({
38
+ // 查询数据
39
+ const notes = await query({
65
40
  table_name: 'notes',
66
41
  filters: { category: 'work' },
67
42
  order: { field: 'created_at', direction: 'desc' },
68
43
  });
69
44
 
70
45
  // 创建数据
71
- const newNote = await client.create({
46
+ const newNote = await create({
72
47
  table_name: 'notes',
73
48
  data_value: { title: 'My Note', content: '...' },
74
49
  visibility: 'private',
75
50
  });
76
51
 
77
52
  // 更新数据
78
- await client.update('note-id-123', {
53
+ await update('note-id-123', {
79
54
  data_value: { title: 'Updated' },
80
55
  });
81
56
 
82
57
  // 删除数据
83
- await client.delete('note-id-123');
58
+ await deleteData('note-id-123');
59
+ ```
60
+
61
+ **✨ 为什么推荐函数式 API?**
62
+
63
+ - ✅ **零配置** - 无需创建客户端实例,直接调用函数
64
+ - ✅ **自动初始化** - 首次调用自动获取配置(通过 PostMessage)
65
+ - ✅ **简洁易用** - 代码更简洁,AI 更容易理解
66
+ - ✅ **单例管理** - SDK 自动管理全局实例,避免重复初始化
67
+
68
+ ### 方式 2: DataClient 类 API(高级场景)
69
+
70
+ 适合需要多实例或自定义配置的场景:
71
+
72
+ ```typescript
73
+ import { DataClient } from '@seaverse/data-sdk';
74
+
75
+ // 零配置(推荐)
76
+ const client = await DataClient.connect();
77
+
78
+ // 或者指定配置
79
+ const client = await DataClient.connect({
80
+ appId: 'my-app-123',
81
+ token: 'user-jwt-token',
82
+ });
83
+
84
+ // 使用 client 实例
85
+ const notes = await client.query({
86
+ table_name: 'notes',
87
+ filters: { category: 'work' },
88
+ });
84
89
  ```
85
90
 
91
+ **🎯 何时使用 DataClient 类?**
92
+
93
+ - 需要管理多个应用的实例
94
+ - 需要动态切换 token 或 appId
95
+ - 需要自定义配置(如 baseURL、timeout)
96
+
86
97
  **配置选项说明:**
87
98
 
88
99
  | 参数 | 类型 | 必需 | 说明 |
@@ -101,28 +112,78 @@ await client.delete('note-id-123');
101
112
  > ```
102
113
  > 如果启用 `debug: true`,还会打印完整的 token 和详细的配置信息(⚠️ 注意:生产环境建议关闭 debug 模式)。
103
114
 
104
- ### 配置自动获取规则
115
+ ### 配置自动获取
105
116
 
106
- **Token 自动获取:**
107
- SDK 会按照以下优先级自动获取 token:
108
- 1. 显式传入的 `token` 参数(最高优先级)
109
- 2. PostMessage 从父窗口获取(使用 `seaverse:get_token` 协议)
117
+ SDK 支持零配置使用,会自动从以下来源获取配置:
110
118
 
111
- **AppId 自动获取:**
112
- SDK 会按照以下优先级自动获取 appId:
113
- 1. 显式传入的 `appId` 参数(最高优先级)
114
- 2. PostMessage 从父窗口获取(使用 `seaverse:get_appId` 协议)
119
+ - **Token & AppId**: 通过 PostMessage 从父窗口获取,或显式传入
120
+ - **BaseURL**: 自动检测运行环境,或通过 `environment` 参数指定
121
+ - **环境变量**: Node.js 环境支持 `DATA_SDK_BASE_URL` 覆盖默认配置
122
+
123
+ **支持的环境类型:**
124
+ ```typescript
125
+ environment?: 'production' | 'staging' | 'development' | 'local'
126
+ ```
115
127
 
116
- > 💡 **最佳实践**:
117
- > - data-sdk 通过 PostMessage 协议与父页面通信获取配置
118
- > - 父页面需要监听并响应 `seaverse:get_token` 和 `seaverse:get_appId` 消息
119
- > - 适用于 iframe 嵌入场景,实现安全的跨域配置传递
128
+ > 💡 **iframe 集成提示**:在 iframe 中使用时,SDK 会通过 PostMessage 与父页面通信获取配置(token、appId、环境标识),无需手动传递。
120
129
 
121
130
  ## API 文档
122
131
 
123
- ### DataClient 方法
132
+ ### 函数式 API(推荐 ⭐)
124
133
 
125
- 使用 `DataClient.create()` 或 `new DataClient(options)` 创建实例后可用的方法:
134
+ 零配置,直接导入使用:
135
+
136
+ ```typescript
137
+ import {
138
+ query, // 查询数据
139
+ get, // 获取单条数据
140
+ create, // 创建数据
141
+ update, // 更新数据
142
+ deleteData, // 删除单条数据
143
+ batchDelete, // 批量删除
144
+ queryWithPagination,// 分页查询
145
+ isAdmin, // 检查管理员权限
146
+ reinit, // 重新初始化(切换用户/应用)
147
+ getClientStatus, // 获取客户端状态
148
+ } from '@seaverse/data-sdk';
149
+ ```
150
+
151
+ | 函数 | 说明 | 参数 | 返回值 |
152
+ |------|------|------|--------|
153
+ | `query(options)` | 查询数据列表 | `QueryOptions` | `Promise<DataRecord[]>` |
154
+ | `get(id)` | 获取单条数据 | `id: string` | `Promise<DataRecord \| null>` |
155
+ | `create(options)` | 创建数据 | `CreateDataOptions` | `Promise<DataRecord>` |
156
+ | `update(id, options)` | 更新数据 | `id: string`, `UpdateDataOptions` | `Promise<DataRecord>` |
157
+ | `deleteData(id)` | 删除数据 | `id: string` | `Promise<void>` |
158
+ | `batchDelete(ids)` | 批量删除 | `ids: string[]` | `Promise<void>` |
159
+ | `queryWithPagination(options)` | 查询带分页信息 | `QueryOptions` | `Promise<PaginatedResponse<DataRecord>>` |
160
+ | `isAdmin()` | 检查管理员权限 | - | `Promise<boolean>` |
161
+ | `reinit(options?)` | 重新初始化 | `DataClientOptions?` | `Promise<void>` |
162
+ | `getClientStatus()` | 获取客户端状态 | - | `ClientStatus` |
163
+
164
+ **使用示例:**
165
+
166
+ ```typescript
167
+ // 查询数据
168
+ const notes = await query({ table_name: 'notes' });
169
+
170
+ // 创建数据
171
+ const note = await create({
172
+ table_name: 'notes',
173
+ data_value: { title: 'Hello' },
174
+ });
175
+
176
+ // 重新初始化(用户登录后切换 token)
177
+ await reinit({ token: newToken });
178
+
179
+ // 检查初始化状态
180
+ const status = getClientStatus();
181
+ console.log('已初始化:', status.initialized);
182
+ ```
183
+
184
+ ### DataClient 类 API(高级场景)
185
+
186
+ 使用 `DataClient.connect()` 创建实例后可用的方法:
126
187
 
127
188
  | 方法 | 说明 | 参数 | 返回值 |
128
189
  |------|------|------|--------|
@@ -400,7 +461,43 @@ const notes = await client.query({ table_name: 'notes' });
400
461
 
401
462
  ### 无缝接入场景
402
463
 
403
- #### React 应用中使用
464
+ #### React 应用中使用(推荐:函数式 API)
465
+
466
+ ```typescript
467
+ import { query, create, update } from '@seaverse/data-sdk';
468
+ import { useEffect, useState } from 'react';
469
+
470
+ function NotesApp() {
471
+ const [notes, setNotes] = useState([]);
472
+
473
+ useEffect(() => {
474
+ // 直接调用函数,首次调用会自动初始化 SDK
475
+ loadNotes();
476
+ }, []);
477
+
478
+ const loadNotes = async () => {
479
+ // 无需初始化,直接使用
480
+ const data = await query({
481
+ table_name: 'notes',
482
+ order: { field: 'created_at', direction: 'desc' },
483
+ });
484
+ setNotes(data);
485
+ };
486
+
487
+ const addNote = async (title: string) => {
488
+ const newNote = await create({
489
+ table_name: 'notes',
490
+ data_value: { title },
491
+ visibility: 'private',
492
+ });
493
+ setNotes([newNote, ...notes]);
494
+ };
495
+
496
+ return <div>...</div>;
497
+ }
498
+ ```
499
+
500
+ **React 应用中使用(DataClient 类 - 多实例场景):**
404
501
 
405
502
  ```typescript
406
503
  import { DataClient } from '@seaverse/data-sdk';
@@ -411,18 +508,15 @@ function App() {
411
508
 
412
509
  useEffect(() => {
413
510
  // 应用启动时初始化客户端
414
- // SDK 会自动通过 PostMessage 从父页面获取配置
415
- DataClient.create({ debug: true }).then(setClient);
511
+ DataClient.connect({ debug: true }).then(setClient);
416
512
  }, []);
417
513
 
418
514
  const loadNotes = async () => {
419
515
  if (!client) return [];
420
-
421
- const notes = await client.query({
516
+ return await client.query({
422
517
  table_name: 'notes',
423
518
  order: { field: 'created_at', direction: 'desc' },
424
519
  });
425
- return notes;
426
520
  };
427
521
 
428
522
  return <div>...</div>;
@@ -479,13 +573,27 @@ window.addEventListener('message', (event) => {
479
573
  });
480
574
  ```
481
575
 
482
- **iframe 页面(自动获取):**
576
+ **iframe 页面(自动获取) - 推荐:函数式 API:**
577
+
578
+ ```typescript
579
+ import { query, create } from '@seaverse/data-sdk';
580
+
581
+ // 直接使用,SDK 会自动通过 PostMessage 从父页面获取 appId 和 token
582
+ const notes = await query({ table_name: 'notes' });
583
+
584
+ const newNote = await create({
585
+ table_name: 'notes',
586
+ data_value: { title: 'Hello' },
587
+ });
588
+ ```
589
+
590
+ **iframe 页面 - DataClient 类:**
483
591
 
484
592
  ```typescript
485
593
  import { DataClient } from '@seaverse/data-sdk';
486
594
 
487
- // 零配置创建客户端,SDK 会自动通过 PostMessage 从父页面获取 appId 和 token
488
- const client = await DataClient.create();
595
+ // 零配置创建客户端
596
+ const client = await DataClient.connect();
489
597
  const notes = await client.query({ table_name: 'notes' });
490
598
  ```
491
599
 
@@ -520,6 +628,20 @@ export async function getServerSideProps() {
520
628
 
521
629
  ### 动态更新 Token
522
630
 
631
+ **函数式 API(推荐):**
632
+
633
+ ```typescript
634
+ import { reinit } from '@seaverse/data-sdk';
635
+
636
+ // 用户登录后,使用新 token
637
+ await reinit({ token: newToken });
638
+
639
+ // 完全重置(重新从 PostMessage 获取)
640
+ await reinit();
641
+ ```
642
+
643
+ **DataClient 类:**
644
+
523
645
  ```typescript
524
646
  // JWT 过期后更新 token
525
647
  client.updateToken('new-jwt-token');
@@ -527,6 +649,17 @@ client.updateToken('new-jwt-token');
527
649
 
528
650
  ### 切换应用
529
651
 
652
+ **函数式 API(推荐):**
653
+
654
+ ```typescript
655
+ import { reinit } from '@seaverse/data-sdk';
656
+
657
+ // 切换到其他应用
658
+ await reinit({ appId: 'another-app', token: anotherToken });
659
+ ```
660
+
661
+ **DataClient 类:**
662
+
530
663
  ```typescript
531
664
  // 切换到其他应用
532
665
  client.updateAppId('another-app-id');
@@ -534,9 +667,13 @@ client.updateAppId('another-app-id');
534
667
 
535
668
  ### JSONB 字段查询
536
669
 
670
+ **函数式 API(推荐):**
671
+
537
672
  ```typescript
673
+ import { query } from '@seaverse/data-sdk';
674
+
538
675
  // 查询 data_value 中的字段
539
- const results = await client.query({
676
+ const results = await query({
540
677
  table_name: 'posts',
541
678
  filters: {
542
679
  data_value: {
@@ -547,11 +684,26 @@ const results = await client.query({
547
684
  });
548
685
  ```
549
686
 
687
+ **DataClient 类:**
688
+
689
+ ```typescript
690
+ const results = await client.query({
691
+ table_name: 'posts',
692
+ filters: {
693
+ data_value: { title: 'Hello World', author: 'Alice' },
694
+ },
695
+ });
696
+ ```
697
+
550
698
  ### 标签查询
551
699
 
700
+ **函数式 API(推荐):**
701
+
552
702
  ```typescript
703
+ import { query } from '@seaverse/data-sdk';
704
+
553
705
  // 查询包含指定标签的数据
554
- const results = await client.query({
706
+ const results = await query({
555
707
  table_name: 'posts',
556
708
  filters: {
557
709
  tags: ['javascript', 'typescript'], // 包含任一标签
@@ -561,9 +713,13 @@ const results = await client.query({
561
713
 
562
714
  ### 时间范围查询
563
715
 
716
+ **函数式 API(推荐):**
717
+
564
718
  ```typescript
719
+ import { query } from '@seaverse/data-sdk';
720
+
565
721
  // 查询指定时间范围的数据
566
- const results = await client.query({
722
+ const results = await query({
567
723
  table_name: 'logs',
568
724
  filters: {
569
725
  created_after: '2026-01-01T00:00:00Z',
@@ -574,9 +730,13 @@ const results = await client.query({
574
730
 
575
731
  ### 分页查询
576
732
 
733
+ **函数式 API(推荐):**
734
+
577
735
  ```typescript
736
+ import { queryWithPagination } from '@seaverse/data-sdk';
737
+
578
738
  // 查询带总数的分页数据
579
- const result = await client.queryWithPagination({
739
+ const result = await queryWithPagination({
580
740
  table_name: 'posts',
581
741
  pagination: { limit: 10, offset: 0 },
582
742
  });
@@ -585,6 +745,15 @@ console.log(`总共 ${result.total} 条,当前返回 ${result.data.length} 条
585
745
  console.log(`是否还有更多: ${result.hasMore}`);
586
746
  ```
587
747
 
748
+ **DataClient 类:**
749
+
750
+ ```typescript
751
+ const result = await client.queryWithPagination({
752
+ table_name: 'posts',
753
+ pagination: { limit: 10, offset: 0 },
754
+ });
755
+ ```
756
+
588
757
  ## 性能说明
589
758
 
590
759
  基于新的 RLS 架构,SDK 具有以下性能特性:
@@ -594,6 +763,22 @@ console.log(`是否还有更多: ${result.hasMore}`);
594
763
  - ⚡ **短路求值**:优先检查 visibility 和 owner
595
764
  - ⚡ **哈希分区**:256 个分区,支持并行查询
596
765
 
766
+ ## 核心概念
767
+
768
+ ### App ID 是什么?
769
+
770
+ **App ID** 是您在 SeaVerse 平台上创建的应用的唯一标识符。它用于:
771
+ - ✅ 多租户数据隔离(每个应用的数据互不干扰)
772
+ - ✅ 权限控制(RLS 策略基于 app_id)
773
+ - ✅ 资源配额管理
774
+
775
+ **如何获取 App ID?**
776
+ 1. 登录 [SeaVerse 控制台](https://console.seaverse.ai)
777
+ 2. 进入"应用管理"
778
+ 3. 复制您的 App ID
779
+
780
+ > ⚠️ **重要**:所有 SDK 操作都需要提供有效的 `appId`,否则无法访问数据。
781
+
597
782
  ## 架构说明
598
783
 
599
784
  ### JWT Token 架构
@@ -635,6 +820,43 @@ psql -h <host> -U postgres -d <database> -f init/init-schema.sql
635
820
 
636
821
  ## 版本历史
637
822
 
823
+ ### v0.3.0 (2026-01-19)
824
+
825
+ **🎉 重大功能更新**
826
+
827
+ - ✅ **新增函数式 API**(推荐使用 ⭐):提供 `query()`, `create()`, `update()`, `deleteData()` 等零配置便捷函数
828
+ - ✅ **零配置优先**:首次调用函数时自动初始化 SDK(通过 PostMessage 获取配置)
829
+ - ✅ **全局单例管理**:自动懒加载初始化,防止并发初始化问题
830
+ - ✅ **新增 `DataClient.connect()`**:语义更清晰的连接方法(推荐使用,`create()` 保留作为别名)
831
+ - ✅ **新增 `reinit()` 函数**:支持重新初始化(用于切换用户 token 或应用 appId)
832
+ - ✅ **新增 `getClientStatus()` 函数**:查询客户端初始化状态
833
+
834
+ **使用方式对比:**
835
+
836
+ ```typescript
837
+ // ⭐ 方式 1: 函数式 API(推荐 - 最简单)
838
+ import { query, create } from '@seaverse/data-sdk';
839
+ const notes = await query({ table_name: 'notes' });
840
+
841
+ // 方式 2: DataClient 类(高级场景 - 多实例)
842
+ import { DataClient } from '@seaverse/data-sdk';
843
+ const client = await DataClient.connect();
844
+ const notes = await client.query({ table_name: 'notes' });
845
+ ```
846
+
847
+ **架构改进:**
848
+
849
+ - 新增 `src/singleton.ts` - 全局单例管理
850
+ - 新增 `src/api.ts` - 函数式 API 封装
851
+ - 优化 `src/client.ts` - 添加 `connect()` 方法
852
+ - 更新 `src/index.ts` - 统一导出函数式 API 和类 API
853
+
854
+ **向后兼容:**
855
+
856
+ - ✅ `DataClient.create()` 方法保留(现为 `connect()` 的别名)
857
+ - ✅ 所有原有的类方法继续支持
858
+ - ✅ 无需修改现有代码,完全向后兼容
859
+
638
860
  ### v0.2.0 (2026-01-15)
639
861
 
640
862
  **🔄 重大变更(Breaking Changes)**