@aiao/rxdb-adapter-supabase 0.0.8 → 0.0.9
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.
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { EntityType, IRepository, IRxDBAdapter, RemoteChange, RxDB, RxDBMutationsMap, SwitchVersionActions, RxDBAdapterRemoteBase } from '../packages/rxdb/src/index.ts';
|
|
1
|
+
import { EntityType, IRepository, IRxDBAdapter, QueryCacheEntityMetadata, RemoteChange, RuleGroup, RxDB, RxDBMutationsMap, SwitchVersionActions, RxDBAdapterRemoteBase } from '../packages/rxdb/src/index.ts';
|
|
2
2
|
import { SupabaseClient } from '@supabase/supabase-js';
|
|
3
|
+
import { Observable } from 'rxjs';
|
|
3
4
|
import { SupabaseAdapterOptions } from './supabase.interface.js';
|
|
4
5
|
export declare const ADAPTER_NAME = "supabase";
|
|
5
6
|
/**
|
|
@@ -49,12 +50,16 @@ export declare class RxDBAdapterSupabase extends RxDBAdapterRemoteBase implement
|
|
|
49
50
|
* @param sinceId - 拉取此 ID 之后的变更(不包含该 ID)
|
|
50
51
|
* @param limit - 最大拉取数量
|
|
51
52
|
* @param repositoryFilter - 可选的实体过滤列表(用于 repository-level sync)
|
|
53
|
+
* @param filter - 可选的行级过滤条件(用于 SyncType.Filter)
|
|
52
54
|
* @returns RxDBChange 记录数组,按 id ASC 排序
|
|
53
55
|
*
|
|
54
56
|
* @remarks
|
|
55
57
|
* 使用 id 而非 createdAt 作为游标,避免同毫秒内多条记录导致的重复问题
|
|
58
|
+
*
|
|
59
|
+
* 当提供 filter 参数时,会通过 JOIN 实体表并应用过滤条件,
|
|
60
|
+
* 只返回满足条件的实体对应的变更记录。
|
|
56
61
|
*/
|
|
57
|
-
pullChanges(sinceId: number, limit?: number, repositoryFilter?: string[]): Promise<RemoteChange[]>;
|
|
62
|
+
pullChanges(sinceId: number, limit?: number, repositoryFilter?: string[], filter?: RuleGroup<any>): Promise<RemoteChange[]>;
|
|
58
63
|
/**
|
|
59
64
|
* 获取远程变更数量(轻量级,不下载数据)(T042, US2)
|
|
60
65
|
*
|
|
@@ -95,6 +100,30 @@ export declare class RxDBAdapterSupabase extends RxDBAdapterRemoteBase implement
|
|
|
95
100
|
* @param actions - 压缩后的变更操作集合
|
|
96
101
|
*/
|
|
97
102
|
mergeChanges(actions: SwitchVersionActions): Promise<any>;
|
|
103
|
+
/**
|
|
104
|
+
* 获取实体元数据,用于新鲜度比较(QueryCache 专用)
|
|
105
|
+
*
|
|
106
|
+
* 只返回 `{ id, updatedAt }` 元数据,网络传输量比完整数据减少 90%+。
|
|
107
|
+
*
|
|
108
|
+
* @param entityName - 实体名称
|
|
109
|
+
* @param query - 查询条件
|
|
110
|
+
* @returns Observable<QueryCacheEntityMetadata[]>
|
|
111
|
+
*
|
|
112
|
+
* @example
|
|
113
|
+
* ```typescript
|
|
114
|
+
* adapter.fetchMetadata('Product', { combinator: 'and', rules: [{ field: 'status', operator: 'eq', value: 'active' }] })
|
|
115
|
+
* .subscribe(metadata => console.log(metadata));
|
|
116
|
+
* ```
|
|
117
|
+
*/
|
|
118
|
+
fetchMetadata(entityName: string, queryFilter: RuleGroup<unknown>): Observable<QueryCacheEntityMetadata[]>;
|
|
119
|
+
/**
|
|
120
|
+
* 按 ID 列表批量获取完整数据(QueryCache 专用)
|
|
121
|
+
*
|
|
122
|
+
* @param entityName - 实体名称
|
|
123
|
+
* @param ids - 需要获取的实体 ID 列表
|
|
124
|
+
* @returns Observable<T[]>
|
|
125
|
+
*/
|
|
126
|
+
findByIds<T>(entityName: string, ids: string[]): Observable<T[]>;
|
|
98
127
|
/** 获取带 schema 的客户端 */
|
|
99
128
|
private getSchemaClient;
|
|
100
129
|
/** 执行 upsert(非事务) */
|
|
@@ -1 +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;
|
|
1
|
+
{"version":3,"file":"RxDBAdapterSupabase.d.ts","sourceRoot":"","sources":["../src/RxDBAdapterSupabase.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +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;
|
|
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;AAKjF,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"}
|
package/dist/index.js
CHANGED
|
@@ -1,85 +1,54 @@
|
|
|
1
|
-
import { EntityRemoteRemovedEvent as
|
|
2
|
-
import { createClient as
|
|
1
|
+
import { EntityRemoteRemovedEvent as O, EntityRemoteUpdatedEvent as W, EntityRemoteCreatedEvent as U, isRuleGroup as A, getEntityMetadata as b, PropertyType as E, RepositoryBase as K, RxDBAdapterRemoteBase as z } from "@aiao/rxdb";
|
|
2
|
+
import { createClient as L } from "@supabase/supabase-js";
|
|
3
|
+
import { defer as D, from as k, map as T, of as Q } from "rxjs";
|
|
3
4
|
class S extends Error {
|
|
4
5
|
constructor(t, e) {
|
|
5
6
|
super(t), this.code = e, this.name = "SupabaseSyncError";
|
|
6
7
|
}
|
|
7
8
|
}
|
|
8
|
-
class
|
|
9
|
+
class at extends S {
|
|
9
10
|
constructor(t) {
|
|
10
11
|
super(t, "CONFIG_ERROR"), this.name = "SupabaseConfigError";
|
|
11
12
|
}
|
|
12
13
|
}
|
|
13
|
-
class
|
|
14
|
+
class rt extends S {
|
|
14
15
|
constructor(t) {
|
|
15
16
|
super(t, "NETWORK_ERROR"), this.name = "SupabaseNetworkError";
|
|
16
17
|
}
|
|
17
18
|
}
|
|
18
|
-
class
|
|
19
|
+
class m extends S {
|
|
19
20
|
constructor(t) {
|
|
20
21
|
super(t, "DATA_ERROR"), this.name = "SupabaseDataError";
|
|
21
22
|
}
|
|
22
23
|
}
|
|
23
|
-
const
|
|
24
|
-
INSERT:
|
|
25
|
-
UPDATE:
|
|
26
|
-
DELETE:
|
|
24
|
+
const V = {
|
|
25
|
+
INSERT: U,
|
|
26
|
+
UPDATE: W,
|
|
27
|
+
DELETE: O
|
|
27
28
|
};
|
|
28
|
-
function
|
|
29
|
+
function J(i, t) {
|
|
29
30
|
if (t.table !== "RxDBChange" || t.eventType !== "INSERT") return;
|
|
30
31
|
const e = t.new;
|
|
31
32
|
if (!e) return;
|
|
32
|
-
const { namespace: s, entity: n, entityId: a, type:
|
|
33
|
-
if (
|
|
34
|
-
const
|
|
35
|
-
if (!
|
|
36
|
-
const
|
|
37
|
-
|
|
38
|
-
new
|
|
33
|
+
const { namespace: s, entity: n, entityId: a, type: r, patch: o, clientId: c } = e, d = i.rxdb.context.clientId;
|
|
34
|
+
if (c && d && c === d || !a || !r) return;
|
|
35
|
+
const u = V[r];
|
|
36
|
+
if (!u) return;
|
|
37
|
+
const l = { id: a, ...o };
|
|
38
|
+
i.rxdb.dispatchEvent(
|
|
39
|
+
new u([
|
|
39
40
|
{
|
|
40
|
-
type:
|
|
41
|
+
type: r,
|
|
41
42
|
namespace: s || "public",
|
|
42
43
|
entity: n,
|
|
43
44
|
id: a,
|
|
44
|
-
data:
|
|
45
|
+
data: l,
|
|
45
46
|
recordAt: e.createdAt ? new Date(e.createdAt) : /* @__PURE__ */ new Date()
|
|
46
47
|
}
|
|
47
48
|
])
|
|
48
49
|
);
|
|
49
50
|
}
|
|
50
|
-
|
|
51
|
-
const t = /* @__PURE__ */ new Map();
|
|
52
|
-
for (const e of r) {
|
|
53
|
-
const s = e.constructor;
|
|
54
|
-
t.has(s) || t.set(s, /* @__PURE__ */ new Set()), t.get(s).add(e);
|
|
55
|
-
}
|
|
56
|
-
return t;
|
|
57
|
-
}
|
|
58
|
-
function k(r, t) {
|
|
59
|
-
const e = [];
|
|
60
|
-
for (const [s, n] of r) {
|
|
61
|
-
const a = b(s), i = Array.from(n);
|
|
62
|
-
e.push({
|
|
63
|
-
table: a.name,
|
|
64
|
-
schema: a.namespace,
|
|
65
|
-
data: t ? i.map((c) => ({ ...c, createdBy: t, updatedBy: t })) : i
|
|
66
|
-
});
|
|
67
|
-
}
|
|
68
|
-
return e;
|
|
69
|
-
}
|
|
70
|
-
function Q(r) {
|
|
71
|
-
const t = [];
|
|
72
|
-
for (const [e, s] of r) {
|
|
73
|
-
const n = b(e);
|
|
74
|
-
t.push({
|
|
75
|
-
table: n.name,
|
|
76
|
-
schema: n.namespace,
|
|
77
|
-
ids: Array.from(s).map((a) => a.id)
|
|
78
|
-
});
|
|
79
|
-
}
|
|
80
|
-
return t;
|
|
81
|
-
}
|
|
82
|
-
const V = {
|
|
51
|
+
const X = {
|
|
83
52
|
"=": "eq",
|
|
84
53
|
"!=": "neq",
|
|
85
54
|
"<": "lt",
|
|
@@ -92,22 +61,22 @@ const V = {
|
|
|
92
61
|
startsWith: "ilike",
|
|
93
62
|
endsWith: "ilike"
|
|
94
63
|
};
|
|
95
|
-
function C(
|
|
96
|
-
return
|
|
64
|
+
function C(i) {
|
|
65
|
+
return i instanceof Date ? i.toISOString() : Array.isArray(i) ? i.map(C) : i;
|
|
97
66
|
}
|
|
98
|
-
function
|
|
99
|
-
return !t || !
|
|
67
|
+
function B(i, t, e) {
|
|
68
|
+
return !t || !i.mappedEntity ? e : t.getEntityMetadata(i.mappedEntity, i.mappedNamespace ?? "") ?? e;
|
|
100
69
|
}
|
|
101
|
-
function
|
|
70
|
+
function H(i, t) {
|
|
102
71
|
const e = C(t);
|
|
103
|
-
switch (
|
|
72
|
+
switch (i) {
|
|
104
73
|
case "=":
|
|
105
74
|
case "!=":
|
|
106
75
|
case "<":
|
|
107
76
|
case "<=":
|
|
108
77
|
case ">":
|
|
109
78
|
case ">=":
|
|
110
|
-
return `${
|
|
79
|
+
return `${X[i]}.${e}`;
|
|
111
80
|
case "in":
|
|
112
81
|
if (!Array.isArray(e)) throw new Error("IN operator requires array");
|
|
113
82
|
return `in.(${e.join(",")})`;
|
|
@@ -119,163 +88,190 @@ function N(r, t) {
|
|
|
119
88
|
case "endsWith":
|
|
120
89
|
return `ilike.*${e}`;
|
|
121
90
|
default:
|
|
122
|
-
throw new Error(`Unsupported operator: ${
|
|
91
|
+
throw new Error(`Unsupported operator: ${i}`);
|
|
123
92
|
}
|
|
124
93
|
}
|
|
125
|
-
function
|
|
126
|
-
const [s, ...n] =
|
|
127
|
-
return n.length === 0 ? { field:
|
|
94
|
+
function F(i, t, e) {
|
|
95
|
+
const [s, ...n] = i.split(".");
|
|
96
|
+
return n.length === 0 ? { field: i, operator: t, value: e } : {
|
|
128
97
|
field: s,
|
|
129
98
|
operator: "exists",
|
|
130
|
-
where: { combinator: "and", rules: [
|
|
99
|
+
where: { combinator: "and", rules: [F(n.join("."), t, e)] }
|
|
131
100
|
};
|
|
132
101
|
}
|
|
133
|
-
function
|
|
134
|
-
if (!t?.rules?.length) return
|
|
102
|
+
function $(i, t, e, s) {
|
|
103
|
+
if (!t?.rules?.length) return i;
|
|
135
104
|
if (t.rules.length === 1) {
|
|
136
105
|
const a = t.rules[0];
|
|
137
|
-
return
|
|
106
|
+
return A(a) ? $(i, a, e, s) : I(i, a, e, s);
|
|
138
107
|
}
|
|
139
108
|
if (t.combinator === "and")
|
|
140
109
|
return t.rules.reduce(
|
|
141
|
-
(a,
|
|
142
|
-
|
|
110
|
+
(a, r) => A(r) ? $(a, r, e, s) : I(a, r, e, s),
|
|
111
|
+
i
|
|
143
112
|
);
|
|
144
113
|
const n = t.rules.map((a) => {
|
|
145
|
-
if (
|
|
146
|
-
const { field:
|
|
147
|
-
return `${
|
|
114
|
+
if (A(a)) throw new Error("Nested OR conditions not supported");
|
|
115
|
+
const { field: r, operator: o, value: c } = a;
|
|
116
|
+
return `${r}.${H(o, c)}`;
|
|
148
117
|
});
|
|
149
|
-
return
|
|
118
|
+
return i.or(n.join(","));
|
|
150
119
|
}
|
|
151
|
-
function
|
|
152
|
-
const { field: n, operator: a, value:
|
|
153
|
-
return typeof n == "string" && n.includes(".") ?
|
|
120
|
+
function I(i, t, e, s) {
|
|
121
|
+
const { field: n, operator: a, value: r } = t;
|
|
122
|
+
return typeof n == "string" && n.includes(".") ? I(i, F(n, a, r), e, s) : a === "exists" || a === "notExists" ? Y(i, t, e, s) : M(i, n, a, r);
|
|
154
123
|
}
|
|
155
|
-
function
|
|
156
|
-
const { field: n, operator: a } = t,
|
|
157
|
-
if (!
|
|
158
|
-
throw new Error(`Relation '${
|
|
159
|
-
const
|
|
160
|
-
if (!
|
|
161
|
-
return a === "exists" ?
|
|
162
|
-
const
|
|
163
|
-
if (!
|
|
164
|
-
return
|
|
124
|
+
function Y(i, t, e, s) {
|
|
125
|
+
const { field: n, operator: a } = t, r = t.where, o = String(n), c = e?.relationMap?.get(o);
|
|
126
|
+
if (!c)
|
|
127
|
+
throw new Error(`Relation '${o}' not found in '${e?.name || "unknown"}'`);
|
|
128
|
+
const d = c.mappedEntity;
|
|
129
|
+
if (!r?.rules?.length)
|
|
130
|
+
return a === "exists" ? i.not(d, "is", null) : i.is(d, null);
|
|
131
|
+
const u = e ? B(c, s, e) : void 0;
|
|
132
|
+
if (!u) throw new Error(`Cannot resolve metadata for '${o}'`);
|
|
133
|
+
return R(i, d, r, u, s, d);
|
|
165
134
|
}
|
|
166
|
-
function
|
|
167
|
-
if (!e?.rules?.length) return
|
|
168
|
-
let
|
|
169
|
-
for (const
|
|
170
|
-
if (
|
|
171
|
-
|
|
135
|
+
function R(i, t, e, s, n, a = "") {
|
|
136
|
+
if (!e?.rules?.length) return i;
|
|
137
|
+
let r = i;
|
|
138
|
+
for (const o of e.rules) {
|
|
139
|
+
if (A(o)) {
|
|
140
|
+
r = R(r, t, o, s, n, a);
|
|
172
141
|
continue;
|
|
173
142
|
}
|
|
174
|
-
const { field:
|
|
175
|
-
if (
|
|
176
|
-
const
|
|
177
|
-
if (!
|
|
178
|
-
const
|
|
179
|
-
if (
|
|
180
|
-
const
|
|
181
|
-
|
|
143
|
+
const { field: c, operator: d, value: u } = o;
|
|
144
|
+
if (d === "exists" || d === "notExists") {
|
|
145
|
+
const p = s?.relationMap?.get(String(c));
|
|
146
|
+
if (!p) throw new Error(`Relation '${c}' not found in ${t}`);
|
|
147
|
+
const f = p.mappedEntity, h = o.where, y = B(p, n, s);
|
|
148
|
+
if (h?.rules?.length) {
|
|
149
|
+
const g = a ? `${a}.${f}` : f;
|
|
150
|
+
r = R(r, f, h, y, n, g);
|
|
182
151
|
} else
|
|
183
|
-
|
|
152
|
+
r = d === "exists" ? r.not(f, "is", null) : r.is(f, null);
|
|
184
153
|
continue;
|
|
185
154
|
}
|
|
186
|
-
const
|
|
187
|
-
|
|
155
|
+
const l = a ? `${a}.${c}` : `${t}.${c}`;
|
|
156
|
+
r = M(r, l, d, u);
|
|
188
157
|
}
|
|
189
|
-
return
|
|
158
|
+
return r;
|
|
190
159
|
}
|
|
191
|
-
function
|
|
160
|
+
function M(i, t, e, s) {
|
|
192
161
|
const n = C(s);
|
|
193
|
-
if (t.includes(".")) {
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
if (e === "between") {
|
|
197
|
-
const [i, c] = n;
|
|
198
|
-
return r.url.searchParams.append(t, `gte.${i}`), r.url.searchParams.append(t, `lte.${c}`), r;
|
|
199
|
-
}
|
|
200
|
-
return r.url.searchParams.append(t, N(e, n)), r;
|
|
162
|
+
if (t.includes(".") && e === "between") {
|
|
163
|
+
const [r, o] = n;
|
|
164
|
+
return i.gte(t, r).lte(t, o);
|
|
201
165
|
}
|
|
202
166
|
switch (e) {
|
|
203
167
|
case "=":
|
|
204
|
-
return n === null ?
|
|
168
|
+
return n === null ? i.is(t, null) : i.eq(t, n);
|
|
205
169
|
case "!=":
|
|
206
|
-
return n === null ?
|
|
170
|
+
return n === null ? i.not(t, "is", null) : i.neq(t, n);
|
|
207
171
|
case "<":
|
|
208
|
-
return
|
|
172
|
+
return i.lt(t, n);
|
|
209
173
|
case ">":
|
|
210
|
-
return
|
|
174
|
+
return i.gt(t, n);
|
|
211
175
|
case "<=":
|
|
212
|
-
return
|
|
176
|
+
return i.lte(t, n);
|
|
213
177
|
case ">=":
|
|
214
|
-
return
|
|
178
|
+
return i.gte(t, n);
|
|
215
179
|
case "in":
|
|
216
|
-
return
|
|
180
|
+
return i.in(t, n);
|
|
217
181
|
case "notIn":
|
|
218
|
-
return
|
|
182
|
+
return i.not(t, "in", `(${n.join(",")})`);
|
|
219
183
|
case "contains":
|
|
220
184
|
case "includes":
|
|
221
|
-
return
|
|
185
|
+
return i.ilike(t, `%${n}%`);
|
|
222
186
|
case "notContains":
|
|
223
|
-
return
|
|
187
|
+
return i.not(t, "ilike", `%${n}%`);
|
|
224
188
|
case "startsWith":
|
|
225
|
-
return
|
|
189
|
+
return i.ilike(t, `${n}%`);
|
|
226
190
|
case "notStartsWith":
|
|
227
|
-
return
|
|
191
|
+
return i.not(t, "ilike", `${n}%`);
|
|
228
192
|
case "endsWith":
|
|
229
|
-
return
|
|
193
|
+
return i.ilike(t, `%${n}`);
|
|
230
194
|
case "notEndsWith":
|
|
231
|
-
return
|
|
195
|
+
return i.not(t, "ilike", `%${n}`);
|
|
232
196
|
case "between": {
|
|
233
|
-
const [
|
|
234
|
-
return
|
|
197
|
+
const [r, o] = n;
|
|
198
|
+
return i.gte(t, r).lte(t, o);
|
|
235
199
|
}
|
|
236
200
|
case "notBetween": {
|
|
237
|
-
const [
|
|
238
|
-
return
|
|
201
|
+
const [r, o] = n;
|
|
202
|
+
return i.or(`${t}.lt.${r},${t}.gt.${o}`);
|
|
239
203
|
}
|
|
240
204
|
case "isNull":
|
|
241
|
-
return
|
|
205
|
+
return i.is(t, null);
|
|
242
206
|
case "isNotNull":
|
|
243
|
-
return
|
|
207
|
+
return i.not(t, "is", null);
|
|
244
208
|
default:
|
|
245
209
|
throw new Error(`Unsupported operator: ${e}`);
|
|
246
210
|
}
|
|
247
211
|
}
|
|
248
|
-
function
|
|
249
|
-
|
|
212
|
+
function N(i) {
|
|
213
|
+
const t = /* @__PURE__ */ new Map();
|
|
214
|
+
for (const e of i) {
|
|
215
|
+
const s = e.constructor;
|
|
216
|
+
t.has(s) || t.set(s, /* @__PURE__ */ new Set()), t.get(s).add(e);
|
|
217
|
+
}
|
|
218
|
+
return t;
|
|
219
|
+
}
|
|
220
|
+
function v(i, t) {
|
|
221
|
+
const e = [];
|
|
222
|
+
for (const [s, n] of i) {
|
|
223
|
+
const a = b(s), r = Array.from(n);
|
|
224
|
+
e.push({
|
|
225
|
+
table: a.name,
|
|
226
|
+
schema: a.namespace,
|
|
227
|
+
data: t ? r.map((o) => ({ ...o, createdBy: t, updatedBy: t })) : r
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
return e;
|
|
231
|
+
}
|
|
232
|
+
function Z(i) {
|
|
233
|
+
const t = [];
|
|
234
|
+
for (const [e, s] of i) {
|
|
235
|
+
const n = b(e);
|
|
236
|
+
t.push({
|
|
237
|
+
table: n.name,
|
|
238
|
+
schema: n.namespace,
|
|
239
|
+
ids: Array.from(s).map((a) => a.id)
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
return t;
|
|
243
|
+
}
|
|
244
|
+
function j(i, t) {
|
|
245
|
+
if (i == null) return i;
|
|
250
246
|
switch (t.type) {
|
|
251
247
|
case E.date:
|
|
252
|
-
return
|
|
248
|
+
return i instanceof Date ? i : new Date(i);
|
|
253
249
|
case E.keyValue:
|
|
254
|
-
if (typeof
|
|
250
|
+
if (typeof i == "object" && t.properties) {
|
|
255
251
|
const e = {};
|
|
256
252
|
for (const s of t.properties)
|
|
257
|
-
|
|
253
|
+
i[s.name] !== void 0 && (e[s.name] = j(i[s.name], s));
|
|
258
254
|
return e;
|
|
259
255
|
}
|
|
260
|
-
return
|
|
256
|
+
return i;
|
|
261
257
|
case E.boolean:
|
|
262
|
-
return !!
|
|
258
|
+
return !!i;
|
|
263
259
|
case E.json:
|
|
264
260
|
case E.stringArray:
|
|
265
261
|
case E.numberArray:
|
|
266
262
|
default:
|
|
267
|
-
return
|
|
263
|
+
return i;
|
|
268
264
|
}
|
|
269
265
|
}
|
|
270
|
-
function
|
|
271
|
-
const s = new
|
|
266
|
+
function G(i, t, e) {
|
|
267
|
+
const s = new i();
|
|
272
268
|
for (const n of Object.keys(e)) {
|
|
273
269
|
const a = t.propertyMap.get(n);
|
|
274
|
-
s[n] = a ?
|
|
270
|
+
s[n] = a ? j(e[n], a) : e[n];
|
|
275
271
|
}
|
|
276
272
|
return s;
|
|
277
273
|
}
|
|
278
|
-
class
|
|
274
|
+
class P extends K {
|
|
279
275
|
constructor(t, e) {
|
|
280
276
|
super(t.rxdb, e), this.adapter = t, this.metadata = b(e);
|
|
281
277
|
}
|
|
@@ -287,22 +283,22 @@ class F extends W {
|
|
|
287
283
|
const e = this.extract_relation_fields(t.where);
|
|
288
284
|
let s = "*";
|
|
289
285
|
if (e.size > 0) {
|
|
290
|
-
const
|
|
291
|
-
s = `*, ${
|
|
292
|
-
(
|
|
293
|
-
).map((
|
|
286
|
+
const o = Array.from(e);
|
|
287
|
+
s = `*, ${o.filter(
|
|
288
|
+
(d) => !o.some((u) => u !== d && u.startsWith(d + "."))
|
|
289
|
+
).map((d) => this.build_relation_select(d)).join(", ")}`;
|
|
294
290
|
}
|
|
295
291
|
let n = this.get_client().select(s);
|
|
296
|
-
if (n =
|
|
297
|
-
for (const
|
|
298
|
-
n = n.order(
|
|
292
|
+
if (n = $(n, t.where, this.metadata, this.adapter.rxdb.schemaManager), t.orderBy?.length)
|
|
293
|
+
for (const o of t.orderBy)
|
|
294
|
+
n = n.order(o.field, { ascending: o.sort === "asc" });
|
|
299
295
|
if (t.offset !== void 0) {
|
|
300
|
-
const
|
|
301
|
-
n = n.range(
|
|
296
|
+
const o = t.offset, c = t.limit !== void 0 ? o + t.limit - 1 : Number.MAX_SAFE_INTEGER;
|
|
297
|
+
n = n.range(o, c);
|
|
302
298
|
} else t.limit !== void 0 && (n = n.limit(t.limit));
|
|
303
|
-
const { data: a, error:
|
|
304
|
-
if (
|
|
305
|
-
return (a || []).map((
|
|
299
|
+
const { data: a, error: r } = await n;
|
|
300
|
+
if (r) throw new m(`Failed to find entities: ${r.message}`);
|
|
301
|
+
return (a || []).map((o) => G(this.EntityType, this.metadata, o));
|
|
306
302
|
}
|
|
307
303
|
/**
|
|
308
304
|
* 查询实体数量
|
|
@@ -311,14 +307,14 @@ class F extends W {
|
|
|
311
307
|
if (t.groupBy) throw new Error("groupBy not supported yet");
|
|
312
308
|
const e = this.extract_relation_fields(t.where);
|
|
313
309
|
let s = "*";
|
|
314
|
-
e.size > 0 && (s = `*, ${Array.from(e).map((
|
|
310
|
+
e.size > 0 && (s = `*, ${Array.from(e).map((o) => this.build_relation_select(o)).join(", ")}`);
|
|
315
311
|
let n = this.get_client().select(s, { count: "exact", head: !0 });
|
|
316
|
-
n =
|
|
317
|
-
const { count: a, error:
|
|
318
|
-
if (
|
|
319
|
-
if (!
|
|
312
|
+
n = $(n, t.where, this.metadata, this.adapter.rxdb.schemaManager);
|
|
313
|
+
const { count: a, error: r } = await n;
|
|
314
|
+
if (r) {
|
|
315
|
+
if (!r.message)
|
|
320
316
|
return console.warn("Supabase count returned empty error, returning 0. Options:", JSON.stringify(t)), 0;
|
|
321
|
-
throw new
|
|
317
|
+
throw new m(`Failed to count entities: ${r.message}`);
|
|
322
318
|
}
|
|
323
319
|
return a ?? 0;
|
|
324
320
|
}
|
|
@@ -329,7 +325,7 @@ class F extends W {
|
|
|
329
325
|
const e = { ...t }, s = this.rxdb.context.userId;
|
|
330
326
|
s && (e.createdBy = s);
|
|
331
327
|
const { data: n, error: a } = await this.get_client().insert(e).select().single();
|
|
332
|
-
if (a) throw new
|
|
328
|
+
if (a) throw new m(`Failed to create entity: ${a.message}`);
|
|
333
329
|
return n;
|
|
334
330
|
}
|
|
335
331
|
/**
|
|
@@ -337,7 +333,7 @@ class F extends W {
|
|
|
337
333
|
*/
|
|
338
334
|
async update(t, e) {
|
|
339
335
|
const { data: s, error: n } = await this.get_client().update(e).eq("id", t.id).select().single();
|
|
340
|
-
if (n) throw new
|
|
336
|
+
if (n) throw new m(`Failed to update entity: ${n.message}`);
|
|
341
337
|
return s;
|
|
342
338
|
}
|
|
343
339
|
/**
|
|
@@ -347,7 +343,7 @@ class F extends W {
|
|
|
347
343
|
*/
|
|
348
344
|
async remove(t) {
|
|
349
345
|
const { error: e } = await this.get_client().delete().eq("id", t.id);
|
|
350
|
-
if (e) throw new
|
|
346
|
+
if (e) throw new m(`Failed to remove entity: ${e.message}`);
|
|
351
347
|
return t;
|
|
352
348
|
}
|
|
353
349
|
// ============================================
|
|
@@ -357,18 +353,18 @@ class F extends W {
|
|
|
357
353
|
extract_relation_fields(t) {
|
|
358
354
|
const e = /* @__PURE__ */ new Set(), s = (n, a = "") => {
|
|
359
355
|
if (n?.rules) {
|
|
360
|
-
for (const
|
|
361
|
-
if (
|
|
362
|
-
s(
|
|
363
|
-
else if (typeof
|
|
364
|
-
const
|
|
365
|
-
for (let
|
|
366
|
-
const
|
|
367
|
-
e.add(a ? `${a}.${
|
|
356
|
+
for (const r of n.rules)
|
|
357
|
+
if (r.rules)
|
|
358
|
+
s(r, a);
|
|
359
|
+
else if (typeof r.field == "string" && r.field.includes(".")) {
|
|
360
|
+
const o = r.field.split(".");
|
|
361
|
+
for (let c = 1; c < o.length; c++) {
|
|
362
|
+
const d = o.slice(0, c).join(".");
|
|
363
|
+
e.add(a ? `${a}.${d}` : d);
|
|
368
364
|
}
|
|
369
|
-
} else if (
|
|
370
|
-
const
|
|
371
|
-
this.metadata.relationMap?.has(
|
|
365
|
+
} else if (r.operator === "exists" || r.operator === "notExists") {
|
|
366
|
+
const o = String(r.field), c = a ? `${a}.${o}` : o;
|
|
367
|
+
this.metadata.relationMap?.has(o) && e.add(c), r.where && s(r.where, c);
|
|
372
368
|
}
|
|
373
369
|
}
|
|
374
370
|
};
|
|
@@ -383,16 +379,16 @@ class F extends W {
|
|
|
383
379
|
if (e.length === 1) return this.build_single_relation_select(e[0]);
|
|
384
380
|
const s = [];
|
|
385
381
|
let n = this.metadata;
|
|
386
|
-
for (const
|
|
387
|
-
const
|
|
388
|
-
if (!
|
|
389
|
-
s.push({ tableName:
|
|
390
|
-
const
|
|
391
|
-
|
|
382
|
+
for (const r of e) {
|
|
383
|
+
const o = n.relationMap?.get(r);
|
|
384
|
+
if (!o) return `${r}(id)`;
|
|
385
|
+
s.push({ tableName: o.mappedEntity, kind: o.kind, sourceEntity: n.name });
|
|
386
|
+
const c = this.adapter.rxdb.schemaManager.getEntityMetadata(o.mappedEntity, o.mappedNamespace ?? "");
|
|
387
|
+
c && (n = c);
|
|
392
388
|
}
|
|
393
389
|
let a = this.build_relation_segment(s[s.length - 1], !0);
|
|
394
|
-
for (let
|
|
395
|
-
a = this.build_relation_segment(s[
|
|
390
|
+
for (let r = s.length - 2; r >= 0; r--)
|
|
391
|
+
a = this.build_relation_segment(s[r], !0).replace("(*)", `(*, ${a})`);
|
|
396
392
|
return a;
|
|
397
393
|
}
|
|
398
394
|
/**
|
|
@@ -431,7 +427,7 @@ class F extends W {
|
|
|
431
427
|
return this.adapter.client.schema(this.metadata.namespace).from(this.metadata.name);
|
|
432
428
|
}
|
|
433
429
|
}
|
|
434
|
-
class
|
|
430
|
+
class q extends P {
|
|
435
431
|
constructor(t, e) {
|
|
436
432
|
super(t, e);
|
|
437
433
|
}
|
|
@@ -450,9 +446,9 @@ class H extends F {
|
|
|
450
446
|
if (a) {
|
|
451
447
|
if (a.message.includes("function") || a.message.includes("Could not find"))
|
|
452
448
|
return this.findDescendantsFallback(t);
|
|
453
|
-
throw new
|
|
449
|
+
throw new m(`Failed to find descendants: ${a.message}`);
|
|
454
450
|
}
|
|
455
|
-
return (n || []).map((
|
|
451
|
+
return (n || []).map((r) => this.transformRowToEntity(r));
|
|
456
452
|
}
|
|
457
453
|
/**
|
|
458
454
|
* 查询子孙节点数量
|
|
@@ -482,9 +478,9 @@ class H extends F {
|
|
|
482
478
|
if (a) {
|
|
483
479
|
if (a.message.includes("function") || a.message.includes("Could not find"))
|
|
484
480
|
return this.findAncestorsFallback(t);
|
|
485
|
-
throw new
|
|
481
|
+
throw new m(`Failed to find ancestors: ${a.message}`);
|
|
486
482
|
}
|
|
487
|
-
return (n || []).map((
|
|
483
|
+
return (n || []).map((r) => this.transformRowToEntity(r));
|
|
488
484
|
}
|
|
489
485
|
/**
|
|
490
486
|
* 查询祖先节点数量
|
|
@@ -504,28 +500,28 @@ class H extends F {
|
|
|
504
500
|
* 优化方案:一次查询获取所有节点,在内存中构建树结构。
|
|
505
501
|
*/
|
|
506
502
|
async findDescendantsFallback(t) {
|
|
507
|
-
const { entityId: e, level: s = 100 } = t, n = this.metadata.name, a = this.metadata.features?.tree?.hasChildren,
|
|
508
|
-
let
|
|
509
|
-
e ?
|
|
510
|
-
const { data:
|
|
511
|
-
if (
|
|
512
|
-
throw new
|
|
513
|
-
const
|
|
514
|
-
for (const
|
|
515
|
-
if (
|
|
516
|
-
|
|
517
|
-
const
|
|
503
|
+
const { entityId: e, level: s = 100 } = t, n = this.metadata.name, a = this.metadata.features?.tree?.hasChildren, r = [], o = /* @__PURE__ */ new Set();
|
|
504
|
+
let c = this.adapter.client.schema("public").from(n).select("*");
|
|
505
|
+
e ? c = c.eq("id", e) : c = c.is("parentId", null);
|
|
506
|
+
const { data: d, error: u } = await c;
|
|
507
|
+
if (u)
|
|
508
|
+
throw new m(`Failed to find start nodes: ${u.message}`);
|
|
509
|
+
const l = async (p, f) => {
|
|
510
|
+
for (const h of p) {
|
|
511
|
+
if (o.has(h.id) || f > s) continue;
|
|
512
|
+
o.add(h.id);
|
|
513
|
+
const y = this.transformRowToEntity(h);
|
|
518
514
|
if (a) {
|
|
519
|
-
const { count:
|
|
520
|
-
|
|
515
|
+
const { count: g } = await this.adapter.client.schema("public").from(n).select("*", { count: "exact", head: !0 }).eq("parentId", h.id);
|
|
516
|
+
y.hasChildren = (g || 0) > 0;
|
|
521
517
|
}
|
|
522
|
-
if (
|
|
523
|
-
const { data:
|
|
524
|
-
|
|
518
|
+
if (r.push(y), f < s) {
|
|
519
|
+
const { data: g } = await this.adapter.client.schema("public").from(n).select("*").eq("parentId", h.id);
|
|
520
|
+
g && g.length > 0 && await l(g, f + 1);
|
|
525
521
|
}
|
|
526
522
|
}
|
|
527
523
|
};
|
|
528
|
-
return await d
|
|
524
|
+
return await l(d || [], 0), r;
|
|
529
525
|
}
|
|
530
526
|
/**
|
|
531
527
|
* 备用的祖先节点查询(不使用存储函数)
|
|
@@ -537,20 +533,20 @@ class H extends F {
|
|
|
537
533
|
const { entityId: e, level: s = 100 } = t;
|
|
538
534
|
if (!e)
|
|
539
535
|
return [];
|
|
540
|
-
const n = this.metadata.name, a = this.metadata.features?.tree?.hasChildren,
|
|
541
|
-
let
|
|
542
|
-
for (;
|
|
543
|
-
const { data:
|
|
544
|
-
if (
|
|
536
|
+
const n = this.metadata.name, a = this.metadata.features?.tree?.hasChildren, r = [];
|
|
537
|
+
let o = e, c = 0;
|
|
538
|
+
for (; o && c <= s; ) {
|
|
539
|
+
const { data: d, error: u } = await this.adapter.client.schema("public").from(n).select("*").eq("id", o);
|
|
540
|
+
if (u || !d || d.length === 0)
|
|
545
541
|
break;
|
|
546
|
-
const
|
|
542
|
+
const l = d[0], p = this.transformRowToEntity(l);
|
|
547
543
|
if (a) {
|
|
548
|
-
const { count:
|
|
549
|
-
|
|
544
|
+
const { count: f } = await this.adapter.client.schema("public").from(n).select("*", { count: "exact", head: !0 }).eq("parentId", l.id);
|
|
545
|
+
p.hasChildren = (f || 0) > 0;
|
|
550
546
|
}
|
|
551
|
-
|
|
547
|
+
r.push(p), o = l.parentId, c++;
|
|
552
548
|
}
|
|
553
|
-
return
|
|
549
|
+
return r;
|
|
554
550
|
}
|
|
555
551
|
/**
|
|
556
552
|
* 将数据库行转换为实体
|
|
@@ -562,14 +558,14 @@ class H extends F {
|
|
|
562
558
|
}), e;
|
|
563
559
|
}
|
|
564
560
|
}
|
|
565
|
-
const
|
|
566
|
-
class
|
|
561
|
+
const tt = "supabase";
|
|
562
|
+
class it extends z {
|
|
567
563
|
constructor(t, e) {
|
|
568
|
-
super(t), this.options = e, this.#t = e.client ??
|
|
564
|
+
super(t), this.options = e, this.#t = e.client ?? L(e.supabaseUrl, e.supabaseKey);
|
|
569
565
|
}
|
|
570
566
|
#t;
|
|
571
567
|
#e = null;
|
|
572
|
-
name =
|
|
568
|
+
name = tt;
|
|
573
569
|
get client() {
|
|
574
570
|
return this.#t;
|
|
575
571
|
}
|
|
@@ -580,7 +576,7 @@ class et extends U {
|
|
|
580
576
|
return this.#e || (this.#e = this.#t.channel("rxdb-changes").on(
|
|
581
577
|
"postgres_changes",
|
|
582
578
|
{ event: "INSERT", schema: "public", table: "RxDBChange" },
|
|
583
|
-
(t) =>
|
|
579
|
+
(t) => J(this, t)
|
|
584
580
|
).subscribe((t, e) => {
|
|
585
581
|
e && console.error("Supabase Realtime subscription failed:", e);
|
|
586
582
|
})), this;
|
|
@@ -598,13 +594,13 @@ class et extends U {
|
|
|
598
594
|
* 批量保存实体(upsert 语义,非事务)
|
|
599
595
|
*/
|
|
600
596
|
async saveMany(t) {
|
|
601
|
-
return t.length === 0 ? [] : this.executeUpsert(
|
|
597
|
+
return t.length === 0 ? [] : this.executeUpsert(N(t));
|
|
602
598
|
}
|
|
603
599
|
/**
|
|
604
600
|
* 批量删除实体(非事务)
|
|
605
601
|
*/
|
|
606
602
|
async removeMany(t) {
|
|
607
|
-
return t.length === 0 ? [] : this.executeDelete(
|
|
603
|
+
return t.length === 0 ? [] : this.executeDelete(N(t));
|
|
608
604
|
}
|
|
609
605
|
/**
|
|
610
606
|
* 批量修改实体(事务)
|
|
@@ -613,16 +609,16 @@ class et extends U {
|
|
|
613
609
|
* 在单个数据库事务中执行所有操作,确保原子性。
|
|
614
610
|
*/
|
|
615
611
|
async mutations(t) {
|
|
616
|
-
const e = this.rxdb.context.userId, s = [...
|
|
612
|
+
const e = this.rxdb.context.userId, s = [...v(t.create, e), ...v(t.update, e)], n = Z(t.remove), { data: a, error: r } = await this.#t.rpc("rxdb_mutations", {
|
|
617
613
|
p_upserts: s,
|
|
618
614
|
p_deletes: n
|
|
619
615
|
});
|
|
620
|
-
if (
|
|
621
|
-
throw new
|
|
622
|
-
const
|
|
623
|
-
for (const [,
|
|
624
|
-
|
|
625
|
-
return
|
|
616
|
+
if (r)
|
|
617
|
+
throw new m(`Transaction failed: ${r.message}`);
|
|
618
|
+
const o = a?.upserted ?? [];
|
|
619
|
+
for (const [, c] of t.remove)
|
|
620
|
+
o.push(...c);
|
|
621
|
+
return o;
|
|
626
622
|
}
|
|
627
623
|
// ============================================
|
|
628
624
|
// Repository
|
|
@@ -630,7 +626,7 @@ class et extends U {
|
|
|
630
626
|
getRepository(t) {
|
|
631
627
|
if (this.repository_cache.has(t))
|
|
632
628
|
return this.repository_cache.get(t);
|
|
633
|
-
const s = b(t).features?.tree ? new
|
|
629
|
+
const s = b(t).features?.tree ? new q(this, t) : new P(this, t);
|
|
634
630
|
return this.repository_cache.set(t, s), s;
|
|
635
631
|
}
|
|
636
632
|
// ============================================
|
|
@@ -640,7 +636,7 @@ class et extends U {
|
|
|
640
636
|
const e = b(t), n = await this.getSchemaClient(e.namespace).from(e.name).select("*", { count: "exact", head: !0 });
|
|
641
637
|
if (n.status === 200) return !0;
|
|
642
638
|
if (n.status === 204) return !1;
|
|
643
|
-
throw new
|
|
639
|
+
throw new m(
|
|
644
640
|
`Failed to check table existence: ${n.error?.message || `status ${n.status}`}`
|
|
645
641
|
);
|
|
646
642
|
}
|
|
@@ -653,24 +649,34 @@ class et extends U {
|
|
|
653
649
|
* @param sinceId - 拉取此 ID 之后的变更(不包含该 ID)
|
|
654
650
|
* @param limit - 最大拉取数量
|
|
655
651
|
* @param repositoryFilter - 可选的实体过滤列表(用于 repository-level sync)
|
|
652
|
+
* @param filter - 可选的行级过滤条件(用于 SyncType.Filter)
|
|
656
653
|
* @returns RxDBChange 记录数组,按 id ASC 排序
|
|
657
654
|
*
|
|
658
655
|
* @remarks
|
|
659
656
|
* 使用 id 而非 createdAt 作为游标,避免同毫秒内多条记录导致的重复问题
|
|
657
|
+
*
|
|
658
|
+
* 当提供 filter 参数时,会通过 JOIN 实体表并应用过滤条件,
|
|
659
|
+
* 只返回满足条件的实体对应的变更记录。
|
|
660
660
|
*/
|
|
661
|
-
async pullChanges(t, e = 1e3, s) {
|
|
662
|
-
const
|
|
663
|
-
let
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
661
|
+
async pullChanges(t, e = 1e3, s, n) {
|
|
662
|
+
const a = [];
|
|
663
|
+
let r;
|
|
664
|
+
if (n && s?.length === 1) {
|
|
665
|
+
const l = s[0];
|
|
666
|
+
if (r = await this.#n(l, n), r.length === 0)
|
|
667
|
+
return [];
|
|
668
|
+
}
|
|
669
|
+
let o = this.#t.from("RxDBChange").select("*").gt("id", t).order("id", { ascending: !0 }).limit(e);
|
|
670
|
+
s && s.length > 0 && (o = o.in("entity", s)), r && (o = o.in("entityId", r));
|
|
671
|
+
const { data: c, error: d } = await o;
|
|
672
|
+
if (d)
|
|
673
|
+
throw new m(`Failed to pull changes: ${d.message}`);
|
|
674
|
+
const u = (c ?? []).map((l) => ({
|
|
669
675
|
...l,
|
|
670
676
|
createdAt: new Date(l.createdAt),
|
|
671
677
|
updatedAt: l.updatedAt ? new Date(l.updatedAt) : null
|
|
672
678
|
}));
|
|
673
|
-
return
|
|
679
|
+
return a.push(...u), a;
|
|
674
680
|
}
|
|
675
681
|
/**
|
|
676
682
|
* 获取远程变更数量(轻量级,不下载数据)(T042, US2)
|
|
@@ -694,19 +700,19 @@ class et extends U {
|
|
|
694
700
|
e && e.length > 0 && (s = s.in("entity", e));
|
|
695
701
|
const { count: n, error: a } = await s;
|
|
696
702
|
if (a)
|
|
697
|
-
throw new
|
|
698
|
-
let
|
|
703
|
+
throw new m(`Failed to get change count: ${a.message}`);
|
|
704
|
+
let r = t;
|
|
699
705
|
if (n && n > 0) {
|
|
700
|
-
let
|
|
701
|
-
e && e.length > 0 && (
|
|
702
|
-
const { data:
|
|
703
|
-
if (
|
|
704
|
-
throw new
|
|
705
|
-
|
|
706
|
+
let o = this.#t.from("RxDBChange").select("id").gt("id", t).order("id", { ascending: !1 }).limit(1);
|
|
707
|
+
e && e.length > 0 && (o = o.in("entity", e));
|
|
708
|
+
const { data: c, error: d } = await o;
|
|
709
|
+
if (d)
|
|
710
|
+
throw new m(`Failed to get latest changeId: ${d.message}`);
|
|
711
|
+
c && c.length > 0 && (r = c[0].id);
|
|
706
712
|
}
|
|
707
713
|
return {
|
|
708
714
|
count: n ?? 0,
|
|
709
|
-
latestChangeId:
|
|
715
|
+
latestChangeId: r
|
|
710
716
|
};
|
|
711
717
|
}
|
|
712
718
|
/**
|
|
@@ -724,17 +730,17 @@ class et extends U {
|
|
|
724
730
|
deletes: /* @__PURE__ */ new Map()
|
|
725
731
|
};
|
|
726
732
|
for (const s of t) {
|
|
727
|
-
const { entityKey: n, finalType: a, finalPatch:
|
|
733
|
+
const { entityKey: n, finalType: a, finalPatch: r, inversePatch: o } = s;
|
|
728
734
|
if (a)
|
|
729
735
|
switch (a) {
|
|
730
736
|
case "INSERT":
|
|
731
|
-
e.inserts.set(n, { patch:
|
|
737
|
+
e.inserts.set(n, { patch: r, inversePatch: o });
|
|
732
738
|
break;
|
|
733
739
|
case "UPDATE":
|
|
734
|
-
e.updates.set(n, { patch:
|
|
740
|
+
e.updates.set(n, { patch: r, inversePatch: o });
|
|
735
741
|
break;
|
|
736
742
|
case "DELETE":
|
|
737
|
-
e.deletes.set(n, { patch: null, inversePatch:
|
|
743
|
+
e.deletes.set(n, { patch: null, inversePatch: o });
|
|
738
744
|
break;
|
|
739
745
|
}
|
|
740
746
|
}
|
|
@@ -751,70 +757,119 @@ class et extends U {
|
|
|
751
757
|
* @param actions - 压缩后的变更操作集合
|
|
752
758
|
*/
|
|
753
759
|
async mergeChanges(t) {
|
|
754
|
-
const e = (/* @__PURE__ */ new Date()).toISOString(), s = this.rxdb.context.userId, n = [], a = /* @__PURE__ */ new Map(),
|
|
755
|
-
for (const [
|
|
756
|
-
const [
|
|
760
|
+
const e = (/* @__PURE__ */ new Date()).toISOString(), s = this.rxdb.context.userId, n = [], a = /* @__PURE__ */ new Map(), r = /* @__PURE__ */ new Map();
|
|
761
|
+
for (const [l, { inversePatch: p }] of t.deletes) {
|
|
762
|
+
const [f, h, y] = l.split(":"), g = f ? `${f}.${h}` : h;
|
|
757
763
|
n.push({
|
|
758
|
-
namespace:
|
|
759
|
-
entity:
|
|
760
|
-
entityId:
|
|
764
|
+
namespace: f || "public",
|
|
765
|
+
entity: h,
|
|
766
|
+
entityId: y,
|
|
761
767
|
type: "DELETE",
|
|
762
768
|
patch: null,
|
|
763
|
-
inversePatch:
|
|
769
|
+
inversePatch: p,
|
|
764
770
|
clientId: this.rxdb.context.clientId,
|
|
765
771
|
createdAt: e,
|
|
766
772
|
updatedAt: e
|
|
767
773
|
});
|
|
768
|
-
const
|
|
769
|
-
|
|
774
|
+
const w = r.get(g) ?? [];
|
|
775
|
+
w.push(y), r.set(g, w);
|
|
770
776
|
}
|
|
771
|
-
for (const [
|
|
772
|
-
const [
|
|
777
|
+
for (const [l, { patch: p, inversePatch: f }] of t.updates) {
|
|
778
|
+
const [h, y, g] = l.split(":"), w = h ? `${h}.${y}` : y;
|
|
773
779
|
n.push({
|
|
774
|
-
namespace:
|
|
775
|
-
entity:
|
|
776
|
-
entityId:
|
|
780
|
+
namespace: h || "public",
|
|
781
|
+
entity: y,
|
|
782
|
+
entityId: g,
|
|
777
783
|
type: "UPDATE",
|
|
778
|
-
patch:
|
|
779
|
-
inversePatch:
|
|
784
|
+
patch: p,
|
|
785
|
+
inversePatch: f,
|
|
780
786
|
clientId: this.rxdb.context.clientId,
|
|
781
787
|
createdAt: e,
|
|
782
788
|
updatedAt: e
|
|
783
789
|
});
|
|
784
|
-
const
|
|
785
|
-
s && (_.updatedBy = s),
|
|
790
|
+
const x = a.get(w) ?? [], _ = { id: g, ...p };
|
|
791
|
+
s && (_.updatedBy = s), x.push(_), a.set(w, x);
|
|
786
792
|
}
|
|
787
|
-
for (const [
|
|
788
|
-
const [
|
|
793
|
+
for (const [l, { patch: p, inversePatch: f }] of t.inserts) {
|
|
794
|
+
const [h, y, g] = l.split(":"), w = h ? `${h}.${y}` : y;
|
|
789
795
|
n.push({
|
|
790
|
-
namespace:
|
|
791
|
-
entity:
|
|
792
|
-
entityId:
|
|
796
|
+
namespace: h || "public",
|
|
797
|
+
entity: y,
|
|
798
|
+
entityId: g,
|
|
793
799
|
type: "INSERT",
|
|
794
|
-
patch:
|
|
795
|
-
inversePatch:
|
|
800
|
+
patch: p,
|
|
801
|
+
inversePatch: f,
|
|
796
802
|
clientId: this.rxdb.context.clientId,
|
|
797
803
|
createdAt: e,
|
|
798
804
|
updatedAt: e
|
|
799
805
|
});
|
|
800
|
-
const
|
|
801
|
-
s && (_.createdBy = s, _.updatedBy = s),
|
|
806
|
+
const x = a.get(w) ?? [], _ = { id: g, ...p };
|
|
807
|
+
s && (_.createdBy = s, _.updatedBy = s), x.push(_), a.set(w, x);
|
|
802
808
|
}
|
|
803
|
-
const
|
|
804
|
-
const [
|
|
805
|
-
return { table:
|
|
806
|
-
}),
|
|
807
|
-
const [
|
|
808
|
-
return { table:
|
|
809
|
-
}), { data:
|
|
810
|
-
p_upserts:
|
|
811
|
-
p_deletes:
|
|
809
|
+
const o = Array.from(a.entries()).map(([l, p]) => {
|
|
810
|
+
const [f, h] = l.includes(".") ? l.split(".") : ["public", l];
|
|
811
|
+
return { table: h, schema: f, data: p };
|
|
812
|
+
}), c = Array.from(r.entries()).map(([l, p]) => {
|
|
813
|
+
const [f, h] = l.includes(".") ? l.split(".") : ["public", l];
|
|
814
|
+
return { table: h, schema: f, ids: p };
|
|
815
|
+
}), { data: d, error: u } = await this.#t.rpc("rxdb_mutations", {
|
|
816
|
+
p_upserts: o,
|
|
817
|
+
p_deletes: c,
|
|
812
818
|
p_changes: n,
|
|
813
819
|
p_skip_sync: !0
|
|
814
820
|
});
|
|
815
|
-
if (
|
|
816
|
-
throw new
|
|
817
|
-
return
|
|
821
|
+
if (u)
|
|
822
|
+
throw new m(`Failed to merge changes: ${u.message}`);
|
|
823
|
+
return d?.max_change_id ?? void 0;
|
|
824
|
+
}
|
|
825
|
+
// ============================================
|
|
826
|
+
// QueryCache 方法
|
|
827
|
+
// ============================================
|
|
828
|
+
/**
|
|
829
|
+
* 获取实体元数据,用于新鲜度比较(QueryCache 专用)
|
|
830
|
+
*
|
|
831
|
+
* 只返回 `{ id, updatedAt }` 元数据,网络传输量比完整数据减少 90%+。
|
|
832
|
+
*
|
|
833
|
+
* @param entityName - 实体名称
|
|
834
|
+
* @param query - 查询条件
|
|
835
|
+
* @returns Observable<QueryCacheEntityMetadata[]>
|
|
836
|
+
*
|
|
837
|
+
* @example
|
|
838
|
+
* ```typescript
|
|
839
|
+
* adapter.fetchMetadata('Product', { combinator: 'and', rules: [{ field: 'status', operator: 'eq', value: 'active' }] })
|
|
840
|
+
* .subscribe(metadata => console.log(metadata));
|
|
841
|
+
* ```
|
|
842
|
+
*/
|
|
843
|
+
fetchMetadata(t, e) {
|
|
844
|
+
return D(() => {
|
|
845
|
+
let s = this.#t.from(t).select("id, updatedAt");
|
|
846
|
+
return s = $(s, e), k(s).pipe(
|
|
847
|
+
T(({ data: n, error: a }) => {
|
|
848
|
+
if (a)
|
|
849
|
+
throw new m(`Failed to fetch metadata: ${a.message}`);
|
|
850
|
+
return (n ?? []).map((r) => ({
|
|
851
|
+
id: r.id,
|
|
852
|
+
updatedAt: r.updatedAt
|
|
853
|
+
}));
|
|
854
|
+
})
|
|
855
|
+
);
|
|
856
|
+
});
|
|
857
|
+
}
|
|
858
|
+
/**
|
|
859
|
+
* 按 ID 列表批量获取完整数据(QueryCache 专用)
|
|
860
|
+
*
|
|
861
|
+
* @param entityName - 实体名称
|
|
862
|
+
* @param ids - 需要获取的实体 ID 列表
|
|
863
|
+
* @returns Observable<T[]>
|
|
864
|
+
*/
|
|
865
|
+
findByIds(t, e) {
|
|
866
|
+
return D(() => e.length === 0 ? Q([]) : k(this.#t.from(t).select("*").in("id", e)).pipe(
|
|
867
|
+
T(({ data: s, error: n }) => {
|
|
868
|
+
if (n)
|
|
869
|
+
throw new m(`Failed to find by ids: ${n.message}`);
|
|
870
|
+
return s ?? [];
|
|
871
|
+
})
|
|
872
|
+
));
|
|
818
873
|
}
|
|
819
874
|
// ============================================
|
|
820
875
|
// 私有方法
|
|
@@ -827,10 +882,10 @@ class et extends U {
|
|
|
827
882
|
async executeUpsert(t) {
|
|
828
883
|
const e = [], s = this.rxdb.context.userId;
|
|
829
884
|
for (const [n, a] of t) {
|
|
830
|
-
const
|
|
831
|
-
if (
|
|
832
|
-
throw new
|
|
833
|
-
e.push(...
|
|
885
|
+
const r = b(n), o = this.getSchemaClient(r.namespace), c = Array.from(a), d = s ? c.map((p) => ({ ...p, createdBy: s, updatedBy: s })) : c, { data: u, error: l } = await o.from(r.name).upsert(d).select();
|
|
886
|
+
if (l)
|
|
887
|
+
throw new m(`Failed to upsert: ${l.message}`);
|
|
888
|
+
e.push(...u);
|
|
834
889
|
}
|
|
835
890
|
return e;
|
|
836
891
|
}
|
|
@@ -838,21 +893,36 @@ class et extends U {
|
|
|
838
893
|
async executeDelete(t) {
|
|
839
894
|
const e = [];
|
|
840
895
|
for (const [s, n] of t) {
|
|
841
|
-
const a = b(s),
|
|
842
|
-
if (
|
|
843
|
-
throw new
|
|
844
|
-
e.push(...
|
|
896
|
+
const a = b(s), r = this.getSchemaClient(a.namespace), o = Array.from(n), c = o.map((u) => u.id), { error: d } = await r.from(a.name).delete().in("id", c);
|
|
897
|
+
if (d)
|
|
898
|
+
throw new m(`Failed to delete: ${d.message}`);
|
|
899
|
+
e.push(...o);
|
|
845
900
|
}
|
|
846
901
|
return e;
|
|
847
902
|
}
|
|
903
|
+
/**
|
|
904
|
+
* 获取满足 filter 条件的实体 ID 列表
|
|
905
|
+
*
|
|
906
|
+
* @param entityName - 实体表名
|
|
907
|
+
* @param filter - 过滤条件
|
|
908
|
+
* @returns 满足条件的 entityId 列表
|
|
909
|
+
*/
|
|
910
|
+
async #n(t, e) {
|
|
911
|
+
let s = this.#t.from(t).select("id");
|
|
912
|
+
s = $(s, e);
|
|
913
|
+
const { data: n, error: a } = await s;
|
|
914
|
+
if (a)
|
|
915
|
+
throw new m(`Failed to query filtered entities: ${a.message}`);
|
|
916
|
+
return (n ?? []).map((r) => r.id);
|
|
917
|
+
}
|
|
848
918
|
}
|
|
849
919
|
export {
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
920
|
+
tt as ADAPTER_NAME,
|
|
921
|
+
it as RxDBAdapterSupabase,
|
|
922
|
+
at as SupabaseConfigError,
|
|
923
|
+
m as SupabaseDataError,
|
|
924
|
+
rt as SupabaseNetworkError,
|
|
925
|
+
P as SupabaseRepository,
|
|
856
926
|
S as SupabaseSyncError,
|
|
857
|
-
|
|
927
|
+
q as SupabaseTreeRepository
|
|
858
928
|
};
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { SchemaManager, EntityMetadata, RuleGroup } from '../packages/rxdb/src/index.ts';
|
|
2
|
+
import { PostgrestFilterBuilder } from '@supabase/postgrest-js';
|
|
2
3
|
/**
|
|
3
|
-
* Supabase Query Builder
|
|
4
|
+
* Supabase Query Builder
|
|
4
5
|
*/
|
|
5
|
-
type SupabaseQueryBuilder = any
|
|
6
|
+
type SupabaseQueryBuilder = PostgrestFilterBuilder<any, any, any, any, any, any, any>;
|
|
6
7
|
/**
|
|
7
8
|
* 应用 RuleGroup 到 Supabase Query Builder
|
|
8
9
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rule_group_builder.d.ts","sourceRoot":"","sources":["../src/rule_group_builder.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAEL,aAAa,EACb,KAAK,cAAc,EAGnB,KAAK,SAAS,EACf,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"rule_group_builder.d.ts","sourceRoot":"","sources":["../src/rule_group_builder.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAEL,aAAa,EACb,KAAK,cAAc,EAGnB,KAAK,SAAS,EACf,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AAMrE;;GAEG;AACH,KAAK,oBAAoB,GAAG,sBAAsB,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;AA4FtF;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAChC,KAAK,EAAE,oBAAoB,EAC3B,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC,EACvB,QAAQ,CAAC,EAAE,cAAc,EACzB,aAAa,CAAC,EAAE,aAAa,GAC5B,oBAAoB,CA6BtB"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aiao/rxdb-adapter-supabase",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.9",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.js",
|
|
@@ -18,6 +18,9 @@
|
|
|
18
18
|
"dist",
|
|
19
19
|
"!**/*.tsbuildinfo"
|
|
20
20
|
],
|
|
21
|
+
"publishConfig": {
|
|
22
|
+
"access": "public"
|
|
23
|
+
},
|
|
21
24
|
"nx": {
|
|
22
25
|
"name": "rxdb-adapter-supabase",
|
|
23
26
|
"tags": [
|
|
@@ -25,12 +28,14 @@
|
|
|
25
28
|
]
|
|
26
29
|
},
|
|
27
30
|
"peerDependencies": {
|
|
28
|
-
"@supabase/supabase-js": "^2.
|
|
29
|
-
"@
|
|
31
|
+
"@supabase/supabase-js": "^2.88.0",
|
|
32
|
+
"@supabase/postgrest-js": "^2.89.0",
|
|
33
|
+
"rxjs": "^7.8.2",
|
|
34
|
+
"@aiao/rxdb": "0.0.9"
|
|
30
35
|
},
|
|
31
36
|
"devDependencies": {
|
|
32
37
|
"dotenv": "^17.2.3",
|
|
33
|
-
"@aiao/rxdb-test": "0.0.
|
|
34
|
-
"@aiao/rxdb-adapter-sqlite": "0.0.
|
|
38
|
+
"@aiao/rxdb-test": "0.0.9",
|
|
39
|
+
"@aiao/rxdb-adapter-sqlite": "0.0.9"
|
|
35
40
|
}
|
|
36
41
|
}
|