@seaverse/data-sdk 0.2.6 → 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 +275 -51
- package/dist/index.cjs +353 -114
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +228 -3
- package/dist/index.js +344 -115
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
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
|
-
###
|
|
28
|
+
### 方式 1: 函数式 API(推荐 ⭐)
|
|
45
29
|
|
|
46
|
-
|
|
47
|
-
import { DataClient } from '@seaverse/data-sdk';
|
|
30
|
+
最简单的使用方式,零配置,自动初始化:
|
|
48
31
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
// 方式2: 只提供 appId,token 自动获取
|
|
53
|
-
const client = await DataClient.create({
|
|
54
|
-
appId: 'my-app-123',
|
|
55
|
-
});
|
|
32
|
+
```typescript
|
|
33
|
+
import { query, create, update, deleteData } from '@seaverse/data-sdk';
|
|
56
34
|
|
|
57
|
-
//
|
|
58
|
-
|
|
59
|
-
appId: 'my-app-123',
|
|
60
|
-
token: 'user-jwt-token',
|
|
61
|
-
});
|
|
35
|
+
// 首次调用会自动初始化 SDK(从 PostMessage 获取 appId 和 token)
|
|
36
|
+
// 无需任何配置代码!
|
|
62
37
|
|
|
63
|
-
//
|
|
64
|
-
const notes = await
|
|
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
|
|
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
|
|
53
|
+
await update('note-id-123', {
|
|
79
54
|
data_value: { title: 'Updated' },
|
|
80
55
|
});
|
|
81
56
|
|
|
82
57
|
// 删除数据
|
|
83
|
-
await
|
|
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
|
| 参数 | 类型 | 必需 | 说明 |
|
|
@@ -118,9 +129,61 @@ environment?: 'production' | 'staging' | 'development' | 'local'
|
|
|
118
129
|
|
|
119
130
|
## API 文档
|
|
120
131
|
|
|
121
|
-
###
|
|
132
|
+
### 函数式 API(推荐 ⭐)
|
|
133
|
+
|
|
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(高级场景)
|
|
122
185
|
|
|
123
|
-
使用 `DataClient.
|
|
186
|
+
使用 `DataClient.connect()` 创建实例后可用的方法:
|
|
124
187
|
|
|
125
188
|
| 方法 | 说明 | 参数 | 返回值 |
|
|
126
189
|
|------|------|------|--------|
|
|
@@ -398,7 +461,43 @@ const notes = await client.query({ table_name: 'notes' });
|
|
|
398
461
|
|
|
399
462
|
### 无缝接入场景
|
|
400
463
|
|
|
401
|
-
#### 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 类 - 多实例场景):**
|
|
402
501
|
|
|
403
502
|
```typescript
|
|
404
503
|
import { DataClient } from '@seaverse/data-sdk';
|
|
@@ -409,18 +508,15 @@ function App() {
|
|
|
409
508
|
|
|
410
509
|
useEffect(() => {
|
|
411
510
|
// 应用启动时初始化客户端
|
|
412
|
-
|
|
413
|
-
DataClient.create({ debug: true }).then(setClient);
|
|
511
|
+
DataClient.connect({ debug: true }).then(setClient);
|
|
414
512
|
}, []);
|
|
415
513
|
|
|
416
514
|
const loadNotes = async () => {
|
|
417
515
|
if (!client) return [];
|
|
418
|
-
|
|
419
|
-
const notes = await client.query({
|
|
516
|
+
return await client.query({
|
|
420
517
|
table_name: 'notes',
|
|
421
518
|
order: { field: 'created_at', direction: 'desc' },
|
|
422
519
|
});
|
|
423
|
-
return notes;
|
|
424
520
|
};
|
|
425
521
|
|
|
426
522
|
return <div>...</div>;
|
|
@@ -477,13 +573,27 @@ window.addEventListener('message', (event) => {
|
|
|
477
573
|
});
|
|
478
574
|
```
|
|
479
575
|
|
|
480
|
-
**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 类:**
|
|
481
591
|
|
|
482
592
|
```typescript
|
|
483
593
|
import { DataClient } from '@seaverse/data-sdk';
|
|
484
594
|
|
|
485
|
-
//
|
|
486
|
-
const client = await DataClient.
|
|
595
|
+
// 零配置创建客户端
|
|
596
|
+
const client = await DataClient.connect();
|
|
487
597
|
const notes = await client.query({ table_name: 'notes' });
|
|
488
598
|
```
|
|
489
599
|
|
|
@@ -518,6 +628,20 @@ export async function getServerSideProps() {
|
|
|
518
628
|
|
|
519
629
|
### 动态更新 Token
|
|
520
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
|
+
|
|
521
645
|
```typescript
|
|
522
646
|
// JWT 过期后更新 token
|
|
523
647
|
client.updateToken('new-jwt-token');
|
|
@@ -525,6 +649,17 @@ client.updateToken('new-jwt-token');
|
|
|
525
649
|
|
|
526
650
|
### 切换应用
|
|
527
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
|
+
|
|
528
663
|
```typescript
|
|
529
664
|
// 切换到其他应用
|
|
530
665
|
client.updateAppId('another-app-id');
|
|
@@ -532,9 +667,13 @@ client.updateAppId('another-app-id');
|
|
|
532
667
|
|
|
533
668
|
### JSONB 字段查询
|
|
534
669
|
|
|
670
|
+
**函数式 API(推荐):**
|
|
671
|
+
|
|
535
672
|
```typescript
|
|
673
|
+
import { query } from '@seaverse/data-sdk';
|
|
674
|
+
|
|
536
675
|
// 查询 data_value 中的字段
|
|
537
|
-
const results = await
|
|
676
|
+
const results = await query({
|
|
538
677
|
table_name: 'posts',
|
|
539
678
|
filters: {
|
|
540
679
|
data_value: {
|
|
@@ -545,11 +684,26 @@ const results = await client.query({
|
|
|
545
684
|
});
|
|
546
685
|
```
|
|
547
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
|
+
|
|
548
698
|
### 标签查询
|
|
549
699
|
|
|
700
|
+
**函数式 API(推荐):**
|
|
701
|
+
|
|
550
702
|
```typescript
|
|
703
|
+
import { query } from '@seaverse/data-sdk';
|
|
704
|
+
|
|
551
705
|
// 查询包含指定标签的数据
|
|
552
|
-
const results = await
|
|
706
|
+
const results = await query({
|
|
553
707
|
table_name: 'posts',
|
|
554
708
|
filters: {
|
|
555
709
|
tags: ['javascript', 'typescript'], // 包含任一标签
|
|
@@ -559,9 +713,13 @@ const results = await client.query({
|
|
|
559
713
|
|
|
560
714
|
### 时间范围查询
|
|
561
715
|
|
|
716
|
+
**函数式 API(推荐):**
|
|
717
|
+
|
|
562
718
|
```typescript
|
|
719
|
+
import { query } from '@seaverse/data-sdk';
|
|
720
|
+
|
|
563
721
|
// 查询指定时间范围的数据
|
|
564
|
-
const results = await
|
|
722
|
+
const results = await query({
|
|
565
723
|
table_name: 'logs',
|
|
566
724
|
filters: {
|
|
567
725
|
created_after: '2026-01-01T00:00:00Z',
|
|
@@ -572,9 +730,13 @@ const results = await client.query({
|
|
|
572
730
|
|
|
573
731
|
### 分页查询
|
|
574
732
|
|
|
733
|
+
**函数式 API(推荐):**
|
|
734
|
+
|
|
575
735
|
```typescript
|
|
736
|
+
import { queryWithPagination } from '@seaverse/data-sdk';
|
|
737
|
+
|
|
576
738
|
// 查询带总数的分页数据
|
|
577
|
-
const result = await
|
|
739
|
+
const result = await queryWithPagination({
|
|
578
740
|
table_name: 'posts',
|
|
579
741
|
pagination: { limit: 10, offset: 0 },
|
|
580
742
|
});
|
|
@@ -583,6 +745,15 @@ console.log(`总共 ${result.total} 条,当前返回 ${result.data.length} 条
|
|
|
583
745
|
console.log(`是否还有更多: ${result.hasMore}`);
|
|
584
746
|
```
|
|
585
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
|
+
|
|
586
757
|
## 性能说明
|
|
587
758
|
|
|
588
759
|
基于新的 RLS 架构,SDK 具有以下性能特性:
|
|
@@ -592,6 +763,22 @@ console.log(`是否还有更多: ${result.hasMore}`);
|
|
|
592
763
|
- ⚡ **短路求值**:优先检查 visibility 和 owner
|
|
593
764
|
- ⚡ **哈希分区**:256 个分区,支持并行查询
|
|
594
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
|
+
|
|
595
782
|
## 架构说明
|
|
596
783
|
|
|
597
784
|
### JWT Token 架构
|
|
@@ -633,6 +820,43 @@ psql -h <host> -U postgres -d <database> -f init/init-schema.sql
|
|
|
633
820
|
|
|
634
821
|
## 版本历史
|
|
635
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
|
+
|
|
636
860
|
### v0.2.0 (2026-01-15)
|
|
637
861
|
|
|
638
862
|
**🔄 重大变更(Breaking Changes)**
|