@aiao/rxdb-adapter-supabase 0.0.7
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/LICENSE +21 -0
- package/README.md +91 -0
- package/dist/RxDBAdapterSupabase.d.ts +105 -0
- package/dist/RxDBAdapterSupabase.d.ts.map +1 -0
- package/dist/RxDBAdapterSupabase.utils.d.ts +18 -0
- package/dist/RxDBAdapterSupabase.utils.d.ts.map +1 -0
- package/dist/SupabaseRepository.d.ts +52 -0
- package/dist/SupabaseRepository.d.ts.map +1 -0
- package/dist/SupabaseTreeRepository.d.ts +62 -0
- package/dist/SupabaseTreeRepository.d.ts.map +1 -0
- package/dist/errors.d.ts +29 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/handle_supabase_change.d.ts +10 -0
- package/dist/handle_supabase_change.d.ts.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +858 -0
- package/dist/rule_group_builder.d.ts +11 -0
- package/dist/rule_group_builder.d.ts.map +1 -0
- package/dist/supabase.interface.d.ts +18 -0
- package/dist/supabase.interface.d.ts.map +1 -0
- package/dist/transform.d.ts +6 -0
- package/dist/transform.d.ts.map +1 -0
- package/package.json +36 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Aiao Team
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# rxdb-adapter-supabase
|
|
2
|
+
|
|
3
|
+
Supabase database adapter for AIAO RxDB framework.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- ✅ Full CRUD operations (Create, Read, Update, Delete)
|
|
8
|
+
- ✅ Complex query conditions (`=`, `!=`, `>`, `<`, `>=`, `<=`, `in`, `between`, `startsWith`, etc.)
|
|
9
|
+
- ✅ Relationship queries (ONE_TO_ONE, ONE_TO_MANY, MANY_TO_ONE, MANY_TO_MANY)
|
|
10
|
+
- ✅ EXISTS / NOT EXISTS operators for checking related records
|
|
11
|
+
- ✅ COUNT queries with EXISTS support
|
|
12
|
+
- ✅ Ordering and pagination
|
|
13
|
+
- ✅ Real-time subscriptions via Supabase Realtime
|
|
14
|
+
|
|
15
|
+
## Query Operators
|
|
16
|
+
|
|
17
|
+
### Comparison Operators
|
|
18
|
+
|
|
19
|
+
- `=`, `!=` - Equal / Not equal
|
|
20
|
+
- `>`, `>=`, `<`, `<=` - Greater / Less than
|
|
21
|
+
- `in`, `notIn` - Value in / not in array
|
|
22
|
+
- `between` - Value between range
|
|
23
|
+
- `startsWith`, `endsWith`, `contains` - String pattern matching
|
|
24
|
+
|
|
25
|
+
### Relationship Operators
|
|
26
|
+
|
|
27
|
+
- `exists` - Check if related record exists
|
|
28
|
+
- `notExists` - Check if related record does not exist
|
|
29
|
+
|
|
30
|
+
## EXISTS Operator Examples
|
|
31
|
+
|
|
32
|
+
```typescript
|
|
33
|
+
// Find users who have orders
|
|
34
|
+
// 注意:使用实体定义中的关系名 'orders',而不是表名 'Order'
|
|
35
|
+
const usersWithOrders = await userRepo.find({
|
|
36
|
+
where: {
|
|
37
|
+
combinator: 'and',
|
|
38
|
+
rules: [{ field: 'orders', operator: 'exists' }]
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
// Find users who don't have id cards
|
|
43
|
+
// 使用关系名 'idCard',而不是表名 'IdCard'
|
|
44
|
+
const usersWithoutIdCard = await userRepo.find({
|
|
45
|
+
where: {
|
|
46
|
+
combinator: 'and',
|
|
47
|
+
rules: [{ field: 'idCard', operator: 'notExists' }]
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
// Count users with orders
|
|
52
|
+
const count = await userRepo.count({
|
|
53
|
+
where: {
|
|
54
|
+
combinator: 'and',
|
|
55
|
+
rules: [{ field: 'orders', operator: 'exists' }]
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
**重要**:`field` 参数必须使用实体定义中的**关系名**(如 `'idCard'`, `'orders'`),而不是 Supabase 表名(如 `'IdCard'`, `'Order'`)。
|
|
61
|
+
|
|
62
|
+
## Known Limitations
|
|
63
|
+
|
|
64
|
+
### Bidirectional ONE_TO_ONE Relationships
|
|
65
|
+
|
|
66
|
+
When a ONE_TO_ONE relationship has foreign keys on both sides (e.g., `User.idCardId` → `IdCard` and `IdCard.ownerId` → `User`), Supabase cannot automatically determine which foreign key to use for EXISTS queries.
|
|
67
|
+
|
|
68
|
+
**Workaround**: Redesign schema to have foreign key on only one side, or use the reverse relationship query.
|
|
69
|
+
|
|
70
|
+
```typescript
|
|
71
|
+
// ❌ May fail with bidirectional ONE_TO_ONE
|
|
72
|
+
await userRepo.find({
|
|
73
|
+
where: { rules: [{ field: 'idCard', operator: 'exists' }] }
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
// ✅ Use ONE_TO_MANY instead (works correctly)
|
|
77
|
+
await userRepo.find({
|
|
78
|
+
where: { rules: [{ field: 'orders', operator: 'exists' }] }
|
|
79
|
+
});
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Testing
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
nx test rxdb-adapter-supabase
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Test coverage: 60/62 tests passing (96.8%)
|
|
89
|
+
|
|
90
|
+
- ✅ 5/6 EXISTS operator tests
|
|
91
|
+
- ⏭️ 1 skipped (bidirectional ONE_TO_ONE limitation)
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { EntityType, IRepository, IRxDBAdapter, RemoteChange, RxDB, RxDBMutationsMap, SwitchVersionActions, RxDBAdapterRemoteBase } from '../packages/rxdb/src/index.ts';
|
|
2
|
+
import { SupabaseClient } from '@supabase/supabase-js';
|
|
3
|
+
import { SupabaseAdapterOptions } from './supabase.interface.js';
|
|
4
|
+
export declare const ADAPTER_NAME = "supabase";
|
|
5
|
+
/**
|
|
6
|
+
* Supabase 适配器
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```typescript
|
|
10
|
+
* const rxdb = new RxDB({
|
|
11
|
+
* adapters: {
|
|
12
|
+
* supabase: rxdb => new RxDBAdapterSupabase(rxdb, {
|
|
13
|
+
* supabaseUrl: 'https://xxx.supabase.co',
|
|
14
|
+
* supabaseKey: 'your-anon-key'
|
|
15
|
+
* })
|
|
16
|
+
* }
|
|
17
|
+
* });
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
export declare class RxDBAdapterSupabase extends RxDBAdapterRemoteBase implements IRxDBAdapter {
|
|
21
|
+
#private;
|
|
22
|
+
readonly options: SupabaseAdapterOptions;
|
|
23
|
+
readonly name = "supabase";
|
|
24
|
+
get client(): SupabaseClient;
|
|
25
|
+
constructor(rxdb: RxDB, options: SupabaseAdapterOptions);
|
|
26
|
+
connect(): Promise<IRxDBAdapter>;
|
|
27
|
+
disconnect(): Promise<void>;
|
|
28
|
+
version(): Promise<string>;
|
|
29
|
+
/**
|
|
30
|
+
* 批量保存实体(upsert 语义,非事务)
|
|
31
|
+
*/
|
|
32
|
+
saveMany<T extends EntityType>(entities: InstanceType<T>[]): Promise<InstanceType<T>[]>;
|
|
33
|
+
/**
|
|
34
|
+
* 批量删除实体(非事务)
|
|
35
|
+
*/
|
|
36
|
+
removeMany<T extends EntityType>(entities: InstanceType<T>[]): Promise<InstanceType<T>[]>;
|
|
37
|
+
/**
|
|
38
|
+
* 批量修改实体(事务)
|
|
39
|
+
*
|
|
40
|
+
* 通过 PostgreSQL RPC 调用 `rxdb_mutations` 存储过程,
|
|
41
|
+
* 在单个数据库事务中执行所有操作,确保原子性。
|
|
42
|
+
*/
|
|
43
|
+
mutations<T extends EntityType>(options: RxDBMutationsMap<T>): Promise<InstanceType<T>[]>;
|
|
44
|
+
getRepository<T extends EntityType, RT extends IRepository<T> = IRepository<T>>(EntityType: T): RT;
|
|
45
|
+
isTableExisted(EntityType: EntityType): Promise<boolean>;
|
|
46
|
+
/**
|
|
47
|
+
* 从远程拉取变更记录
|
|
48
|
+
*
|
|
49
|
+
* @param sinceId - 拉取此 ID 之后的变更(不包含该 ID)
|
|
50
|
+
* @param limit - 最大拉取数量
|
|
51
|
+
* @param repositoryFilter - 可选的实体过滤列表(用于 repository-level sync)
|
|
52
|
+
* @returns RxDBChange 记录数组,按 id ASC 排序
|
|
53
|
+
*
|
|
54
|
+
* @remarks
|
|
55
|
+
* 使用 id 而非 createdAt 作为游标,避免同毫秒内多条记录导致的重复问题
|
|
56
|
+
*/
|
|
57
|
+
pullChanges(sinceId: number, limit?: number, repositoryFilter?: string[]): Promise<RemoteChange[]>;
|
|
58
|
+
/**
|
|
59
|
+
* 获取远程变更数量(轻量级,不下载数据)(T042, US2)
|
|
60
|
+
*
|
|
61
|
+
* 此方法只查询远程有多少新变更,不返回实际数据。
|
|
62
|
+
* 用于实现 checkRepositoryUpdates() 功能,节省带宽。
|
|
63
|
+
*
|
|
64
|
+
* @param sinceId - 起始 changeId(不包含该 ID)
|
|
65
|
+
* @param repositoryFilter - 可选的实体过滤列表
|
|
66
|
+
* @returns 变更数量和最新 changeId
|
|
67
|
+
*
|
|
68
|
+
* @example
|
|
69
|
+
* ```typescript
|
|
70
|
+
* // 查询 Todo 实体的新变更数量
|
|
71
|
+
* const { count, latestChangeId } = await adapter.getChangeCount(100, ['Todo']);
|
|
72
|
+
* console.log(`有 ${count} 条新变更,最新 ID: ${latestChangeId}`);
|
|
73
|
+
* ```
|
|
74
|
+
*/
|
|
75
|
+
getChangeCount(sinceId: number, repositoryFilter?: string[]): Promise<{
|
|
76
|
+
count: number;
|
|
77
|
+
latestChangeId: number;
|
|
78
|
+
}>;
|
|
79
|
+
/**
|
|
80
|
+
* 推送变更记录到远程(双写:RxDBChange 表 + 实体表)
|
|
81
|
+
*
|
|
82
|
+
* @deprecated 请使用 mergeChanges 代替,该方法不支持事务且效率较低
|
|
83
|
+
* @param changes - 待推送的变更(已压缩)
|
|
84
|
+
* @throws 当任何变更推送失败时抛出错误
|
|
85
|
+
*/
|
|
86
|
+
pushChanges(changes: any[]): Promise<void>;
|
|
87
|
+
/**
|
|
88
|
+
* 应用压缩后的变更到远程(事务)
|
|
89
|
+
*
|
|
90
|
+
* 通过 rxdb_mutations RPC 在单个事务中:
|
|
91
|
+
* 1. 写入 RxDBChange 表(用于其他客户端 pull)
|
|
92
|
+
* 2. 应用 actions 到实体表(INSERT/UPDATE/DELETE)
|
|
93
|
+
* 3. 自动跳过同步触发器(p_skip_sync=true)
|
|
94
|
+
*
|
|
95
|
+
* @param actions - 压缩后的变更操作集合
|
|
96
|
+
*/
|
|
97
|
+
mergeChanges(actions: SwitchVersionActions): Promise<any>;
|
|
98
|
+
/** 获取带 schema 的客户端 */
|
|
99
|
+
private getSchemaClient;
|
|
100
|
+
/** 执行 upsert(非事务) */
|
|
101
|
+
private executeUpsert;
|
|
102
|
+
/** 执行 delete(非事务) */
|
|
103
|
+
private executeDelete;
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=RxDBAdapterSupabase.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RxDBAdapterSupabase.d.ts","sourceRoot":"","sources":["../src/RxDBAdapterSupabase.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EACV,UAAU,EACV,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,IAAI,EACJ,gBAAgB,EAChB,oBAAoB,EACrB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAqB,qBAAqB,EAAE,MAAM,YAAY,CAAC;AACtE,OAAO,EAAiC,KAAK,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAI3F,OAAO,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AAIjE,eAAO,MAAM,YAAY,aAAa,CAAC;AAEvC;;;;;;;;;;;;;;GAcG;AACH,qBAAa,mBAAoB,SAAQ,qBAAsB,YAAW,YAAY;;IAWlF,QAAQ,CAAC,OAAO,EAAE,sBAAsB;IAR1C,QAAQ,CAAC,IAAI,cAAgB;IAE7B,IAAI,MAAM,IAAI,cAAc,CAE3B;gBAGC,IAAI,EAAE,IAAI,EACD,OAAO,EAAE,sBAAsB;IAUpC,OAAO,IAAI,OAAO,CAAC,YAAY,CAAC;IAiBhC,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAO3B,OAAO,IAAI,OAAO,CAAC,MAAM,CAAC;IAQhC;;OAEG;IACG,QAAQ,CAAC,CAAC,SAAS,UAAU,EAAE,QAAQ,EAAE,YAAY,CAAC,CAAC,CAAC,EAAE,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC;IAK7F;;OAEG;IACG,UAAU,CAAC,CAAC,SAAS,UAAU,EAAE,QAAQ,EAAE,YAAY,CAAC,CAAC,CAAC,EAAE,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC;IAK/F;;;;;OAKG;IACG,SAAS,CAAC,CAAC,SAAS,UAAU,EAAE,OAAO,EAAE,gBAAgB,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC;IA+B/F,aAAa,CAAC,CAAC,SAAS,UAAU,EAAE,EAAE,SAAS,WAAW,CAAC,CAAC,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,GAAG,EAAE;IAmB5F,cAAc,CAAC,UAAU,EAAE,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC;IAiB9D;;;;;;;;;;OAUG;IACG,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,GAAE,MAAa,EAAE,gBAAgB,CAAC,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;IAmC9G;;;;;;;;;;;;;;;;OAgBG;IACG,cAAc,CAClB,OAAO,EAAE,MAAM,EACf,gBAAgB,CAAC,EAAE,MAAM,EAAE,GAC1B,OAAO,CAAC;QACT,KAAK,EAAE,MAAM,CAAC;QACd,cAAc,EAAE,MAAM,CAAC;KACxB,CAAC;IAmDF;;;;;;OAMG;IACG,WAAW,CAAC,OAAO,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IA8BhD;;;;;;;;;OASG;IACG,YAAY,CAAC,OAAO,EAAE,oBAAoB;IAyHhD,sBAAsB;IACtB,OAAO,CAAC,eAAe;IAIvB,qBAAqB;YACP,aAAa;IA0B3B,qBAAqB;YACP,aAAa;CAqB5B"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { EntityType } from '../packages/rxdb/src/index.ts';
|
|
2
|
+
/**
|
|
3
|
+
* 按实体类型分组
|
|
4
|
+
*/
|
|
5
|
+
export declare function group_by_type<T extends EntityType>(entities: InstanceType<T>[]): Map<EntityType, Set<InstanceType<T>>>;
|
|
6
|
+
/** 构建 upsert RPC 参数 */
|
|
7
|
+
export declare function build_upsert_params<T extends EntityType>(entityMap: Map<T, Set<InstanceType<T>>>, userId?: string): Array<{
|
|
8
|
+
table: string;
|
|
9
|
+
schema: string;
|
|
10
|
+
data: any[];
|
|
11
|
+
}>;
|
|
12
|
+
/** 构建 delete RPC 参数 */
|
|
13
|
+
export declare function build_delete_params<T extends EntityType>(entityMap: Map<T, Set<InstanceType<T>>>): Array<{
|
|
14
|
+
table: string;
|
|
15
|
+
schema: string;
|
|
16
|
+
ids: string[];
|
|
17
|
+
}>;
|
|
18
|
+
//# sourceMappingURL=RxDBAdapterSupabase.utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RxDBAdapterSupabase.utils.d.ts","sourceRoot":"","sources":["../src/RxDBAdapterSupabase.utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAqB,MAAM,YAAY,CAAC;AAE3D;;GAEG;AACH,wBAAgB,aAAa,CAAC,CAAC,SAAS,UAAU,EAChD,QAAQ,EAAE,YAAY,CAAC,CAAC,CAAC,EAAE,GAC1B,GAAG,CAAC,UAAU,EAAE,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,CAUvC;AAED,uBAAuB;AACvB,wBAAgB,mBAAmB,CAAC,CAAC,SAAS,UAAU,EACtD,SAAS,EAAE,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,EACvC,MAAM,CAAC,EAAE,MAAM,GACd,KAAK,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,GAAG,EAAE,CAAA;CAAE,CAAC,CAcvD;AAED,uBAAuB;AACvB,wBAAgB,mBAAmB,CAAC,CAAC,SAAS,UAAU,EACtD,SAAS,EAAE,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,GACtC,KAAK,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,CAazD"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { EntityMetadata, EntityType, IRepository, EntityStaticType, RepositoryBase } from '../packages/rxdb/src/index.ts';
|
|
2
|
+
import { RxDBAdapterSupabase } from './RxDBAdapterSupabase.js';
|
|
3
|
+
/**
|
|
4
|
+
* Supabase Repository
|
|
5
|
+
* 提供对 Supabase 表的 CRUD 操作
|
|
6
|
+
*/
|
|
7
|
+
export declare class SupabaseRepository<T extends EntityType> extends RepositoryBase<T> implements IRepository<T> {
|
|
8
|
+
protected readonly adapter: RxDBAdapterSupabase;
|
|
9
|
+
protected readonly metadata: EntityMetadata;
|
|
10
|
+
constructor(adapter: RxDBAdapterSupabase, EntityType: T);
|
|
11
|
+
/**
|
|
12
|
+
* 查询多个实体
|
|
13
|
+
*/
|
|
14
|
+
find(options: EntityStaticType<T, 'findOptions'>): Promise<InstanceType<T>[]>;
|
|
15
|
+
/**
|
|
16
|
+
* 查询实体数量
|
|
17
|
+
*/
|
|
18
|
+
count(options: EntityStaticType<T, 'countOptions'>): Promise<number>;
|
|
19
|
+
/**
|
|
20
|
+
* 创建实体
|
|
21
|
+
*/
|
|
22
|
+
create(entity: InstanceType<T>): Promise<InstanceType<T>>;
|
|
23
|
+
/**
|
|
24
|
+
* 更新实体
|
|
25
|
+
*/
|
|
26
|
+
update(entity: InstanceType<T>, patch: Partial<InstanceType<T>>): Promise<InstanceType<T>>;
|
|
27
|
+
/**
|
|
28
|
+
* 删除实体
|
|
29
|
+
* @param entity
|
|
30
|
+
* @returns
|
|
31
|
+
*/
|
|
32
|
+
remove(entity: InstanceType<T>): Promise<InstanceType<T>>;
|
|
33
|
+
/** 提取查询中的关系字段路径(用于 EXISTS 查询的 INNER JOIN) */
|
|
34
|
+
private extract_relation_fields;
|
|
35
|
+
/**
|
|
36
|
+
* 构建关系字段的 SELECT 语法
|
|
37
|
+
* 支持嵌套路径:'orders.items' → Order!inner(*, OrderItem!inner(*))
|
|
38
|
+
*/
|
|
39
|
+
private build_relation_select;
|
|
40
|
+
/**
|
|
41
|
+
* 构建单层关系 SELECT
|
|
42
|
+
* 根据关系类型生成正确的消歧语法
|
|
43
|
+
*/
|
|
44
|
+
private build_single_relation_select;
|
|
45
|
+
/** 构建关系 SELECT 片段 */
|
|
46
|
+
private build_relation_segment;
|
|
47
|
+
/** 获取 m:n 中间表名(按字母顺序) */
|
|
48
|
+
private get_join_table_name;
|
|
49
|
+
/** 获取带 schema 的 client */
|
|
50
|
+
private get_client;
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=SupabaseRepository.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SupabaseRepository.d.ts","sourceRoot":"","sources":["../src/SupabaseRepository.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC1E,OAAO,EAAE,gBAAgB,EAAqB,cAAc,EAAE,MAAM,YAAY,CAAC;AAGjF,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAGpE;;;GAGG;AACH,qBAAa,kBAAkB,CAAC,CAAC,SAAS,UAAU,CAAE,SAAQ,cAAc,CAAC,CAAC,CAAE,YAAW,WAAW,CAAC,CAAC,CAAC;IAIrG,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAE,mBAAmB;IAHjD,SAAS,CAAC,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAC;gBAGvB,OAAO,EAAE,mBAAmB,EAC/C,UAAU,EAAE,CAAC;IAMf;;OAEG;IACG,IAAI,CAAC,OAAO,EAAE,gBAAgB,CAAC,CAAC,EAAE,aAAa,CAAC,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC;IAsCnF;;OAEG;IACG,KAAK,CAAC,OAAO,EAAE,gBAAgB,CAAC,CAAC,EAAE,cAAc,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC;IA2B1E;;OAEG;IACG,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAW/D;;OAEG;IACG,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAMhG;;;;OAIG;IACG,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAU/D,6CAA6C;IAC7C,OAAO,CAAC,uBAAuB;IAgC/B;;;OAGG;IACH,OAAO,CAAC,qBAAqB;IA2B7B;;;OAGG;IACH,OAAO,CAAC,4BAA4B;IAuBpC,qBAAqB;IACrB,OAAO,CAAC,sBAAsB;IAY9B,yBAAyB;IACzB,OAAO,CAAC,mBAAmB;IAI3B,0BAA0B;IAC1B,OAAO,CAAC,UAAU;CAGnB"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { EntityType, FindTreeOptions, ITreeRepository } from '../packages/rxdb/src/index.ts';
|
|
2
|
+
import { RxDBAdapterSupabase } from './RxDBAdapterSupabase.js';
|
|
3
|
+
import { SupabaseRepository } from './SupabaseRepository.js';
|
|
4
|
+
/**
|
|
5
|
+
* Supabase Tree Repository
|
|
6
|
+
* 提供树形结构的查询操作
|
|
7
|
+
*
|
|
8
|
+
* 使用 PostgreSQL 的递归 CTE (Common Table Expression) 实现树遍历
|
|
9
|
+
*/
|
|
10
|
+
export declare class SupabaseTreeRepository<T extends EntityType> extends SupabaseRepository<T> implements ITreeRepository<T> {
|
|
11
|
+
constructor(adapter: RxDBAdapterSupabase, EntityType: T);
|
|
12
|
+
/**
|
|
13
|
+
* 查询子孙节点
|
|
14
|
+
*
|
|
15
|
+
* @remarks
|
|
16
|
+
* - 指定 entityId 时:包含当前节点 + 子孙节点
|
|
17
|
+
* - 不指定 entityId 时:返回所有根节点及其子孙
|
|
18
|
+
*/
|
|
19
|
+
findDescendants(options: FindTreeOptions<T>): Promise<InstanceType<T>[]>;
|
|
20
|
+
/**
|
|
21
|
+
* 查询子孙节点数量
|
|
22
|
+
*
|
|
23
|
+
* @remarks
|
|
24
|
+
* - 指定 entityId 时:**不包含当前节点**,只统计后代数量
|
|
25
|
+
* - 不指定 entityId 时:统计所有根节点及其后代的总数
|
|
26
|
+
*/
|
|
27
|
+
countDescendants(options: FindTreeOptions<T>): Promise<number>;
|
|
28
|
+
/**
|
|
29
|
+
* 查询祖先节点
|
|
30
|
+
*
|
|
31
|
+
* @remarks
|
|
32
|
+
* 指定 entityId 时:包含当前节点 + 祖先节点
|
|
33
|
+
*/
|
|
34
|
+
findAncestors(options: FindTreeOptions<T>): Promise<InstanceType<T>[]>;
|
|
35
|
+
/**
|
|
36
|
+
* 查询祖先节点数量
|
|
37
|
+
*
|
|
38
|
+
* @remarks
|
|
39
|
+
* 指定 entityId 时:**不包含当前节点**,只统计祖先数量
|
|
40
|
+
*/
|
|
41
|
+
countAncestors(options: FindTreeOptions<T>): Promise<number>;
|
|
42
|
+
/**
|
|
43
|
+
* 备用的子孙节点查询(不使用存储函数)
|
|
44
|
+
* 仅支持简单的层级查询
|
|
45
|
+
*
|
|
46
|
+
* TODO: 当前实现存在 N+1 查询问题,对于深或宽的树性能较差。
|
|
47
|
+
* 优化方案:一次查询获取所有节点,在内存中构建树结构。
|
|
48
|
+
*/
|
|
49
|
+
private findDescendantsFallback;
|
|
50
|
+
/**
|
|
51
|
+
* 备用的祖先节点查询(不使用存储函数)
|
|
52
|
+
*
|
|
53
|
+
* TODO: 当前实现存在 N+1 查询问题,每个祖先都需要一次查询。
|
|
54
|
+
* 优化方案:一次查询获取所有节点,在内存中向上遍历。
|
|
55
|
+
*/
|
|
56
|
+
private findAncestorsFallback;
|
|
57
|
+
/**
|
|
58
|
+
* 将数据库行转换为实体
|
|
59
|
+
*/
|
|
60
|
+
private transformRowToEntity;
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=SupabaseTreeRepository.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SupabaseTreeRepository.d.ts","sourceRoot":"","sources":["../src/SupabaseTreeRepository.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAE/E,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AACpE,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAE7D;;;;;GAKG;AACH,qBAAa,sBAAsB,CAAC,CAAC,SAAS,UAAU,CAAE,SAAQ,kBAAkB,CAAC,CAAC,CAAE,YAAW,eAAe,CAAC,CAAC,CAAC;gBACvG,OAAO,EAAE,mBAAmB,EAAE,UAAU,EAAE,CAAC;IAIvD;;;;;;OAMG;IACG,eAAe,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC;IAoB9E;;;;;;OAMG;IACG,gBAAgB,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC;IAcpE;;;;;OAKG;IACG,aAAa,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC;IAyB5E;;;;;OAKG;IACG,cAAc,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC;IAOlE;;;;;;OAMG;YACW,uBAAuB;IA8DrC;;;;;OAKG;YACW,qBAAqB;IA6CnC;;OAEG;IACH,OAAO,CAAC,oBAAoB;CAW7B"}
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Supabase Adapter 错误类型定义
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Supabase 同步错误基类
|
|
6
|
+
*/
|
|
7
|
+
export declare class SupabaseSyncError extends Error {
|
|
8
|
+
readonly code?: string | undefined;
|
|
9
|
+
constructor(message: string, code?: string | undefined);
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* 配置错误
|
|
13
|
+
*/
|
|
14
|
+
export declare class SupabaseConfigError extends SupabaseSyncError {
|
|
15
|
+
constructor(message: string);
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* 网络错误
|
|
19
|
+
*/
|
|
20
|
+
export declare class SupabaseNetworkError extends SupabaseSyncError {
|
|
21
|
+
constructor(message: string);
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* 数据错误
|
|
25
|
+
*/
|
|
26
|
+
export declare class SupabaseDataError extends SupabaseSyncError {
|
|
27
|
+
constructor(message: string);
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;GAEG;AACH,qBAAa,iBAAkB,SAAQ,KAAK;aAGxB,IAAI,CAAC,EAAE,MAAM;gBAD7B,OAAO,EAAE,MAAM,EACC,IAAI,CAAC,EAAE,MAAM,YAAA;CAKhC;AAED;;GAEG;AACH,qBAAa,mBAAoB,SAAQ,iBAAiB;gBAC5C,OAAO,EAAE,MAAM;CAI5B;AAED;;GAEG;AACH,qBAAa,oBAAqB,SAAQ,iBAAiB;gBAC7C,OAAO,EAAE,MAAM;CAI5B;AAED;;GAEG;AACH,qBAAa,iBAAkB,SAAQ,iBAAiB;gBAC1C,OAAO,EAAE,MAAM;CAI5B"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { RealtimePostgresChangesPayload } from '@supabase/supabase-js';
|
|
2
|
+
import { RxDBAdapterSupabase } from './RxDBAdapterSupabase.js';
|
|
3
|
+
type SupabasePayload = RealtimePostgresChangesPayload<Record<string, unknown>>;
|
|
4
|
+
/**
|
|
5
|
+
* 处理 RxDBChange 表的 INSERT 事件
|
|
6
|
+
* 将变更记录转换为对应的 Remote 事件
|
|
7
|
+
*/
|
|
8
|
+
export declare function handleSupabaseChange(adapter: RxDBAdapterSupabase, payload: SupabasePayload): void;
|
|
9
|
+
export {};
|
|
10
|
+
//# sourceMappingURL=handle_supabase_change.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handle_supabase_change.d.ts","sourceRoot":"","sources":["../src/handle_supabase_change.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EAAE,8BAA8B,EAAE,MAAM,uBAAuB,CAAC;AAC5E,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAEpE,KAAK,eAAe,GAAG,8BAA8B,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AAQ/E;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,mBAAmB,EAAE,OAAO,EAAE,eAAe,GAAG,IAAI,CAkCjG"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,0BAA0B,CAAC;AACzC,cAAc,yBAAyB,CAAC;AACxC,cAAc,yBAAyB,CAAC;AACxC,cAAc,6BAA6B,CAAC"}
|