@aiao/rxdb-adapter-supabase 0.0.9 → 0.0.11
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.
|
@@ -41,17 +41,14 @@ export declare class SupabaseTreeRepository<T extends EntityType> extends Supaba
|
|
|
41
41
|
countAncestors(options: FindTreeOptions<T>): Promise<number>;
|
|
42
42
|
/**
|
|
43
43
|
* 备用的子孙节点查询(不使用存储函数)
|
|
44
|
-
* 仅支持简单的层级查询
|
|
45
44
|
*
|
|
46
|
-
*
|
|
47
|
-
* 优化方案:一次查询获取所有节点,在内存中构建树结构。
|
|
45
|
+
* 一次查询获取所有节点,在内存中构建树结构,避免 N+1 问题。
|
|
48
46
|
*/
|
|
49
47
|
private findDescendantsFallback;
|
|
50
48
|
/**
|
|
51
49
|
* 备用的祖先节点查询(不使用存储函数)
|
|
52
50
|
*
|
|
53
|
-
*
|
|
54
|
-
* 优化方案:一次查询获取所有节点,在内存中向上遍历。
|
|
51
|
+
* 一次查询获取所有节点,在内存中向上遍历,避免 N+1 问题。
|
|
55
52
|
*/
|
|
56
53
|
private findAncestorsFallback;
|
|
57
54
|
/**
|
|
@@ -1 +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
|
|
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;;;;OAIG;YACW,uBAAuB;IAgErC;;;;OAIG;YACW,qBAAqB;IAsDnC;;OAEG;IACH,OAAO,CAAC,oBAAoB;CAW7B"}
|
package/dist/index.js
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
|
-
import { EntityRemoteRemovedEvent as O, EntityRemoteUpdatedEvent as W, EntityRemoteCreatedEvent as U, isRuleGroup as A, getEntityMetadata as
|
|
1
|
+
import { EntityRemoteRemovedEvent as O, EntityRemoteUpdatedEvent as W, EntityRemoteCreatedEvent as U, isRuleGroup as A, getEntityMetadata as _, PropertyType as $, RepositoryBase as K, RxDBAdapterRemoteBase as z } from "@aiao/rxdb";
|
|
2
2
|
import { createClient as L } from "@supabase/supabase-js";
|
|
3
|
-
import { defer as D, from as
|
|
3
|
+
import { defer as D, from as N, map as k, of as Q } from "rxjs";
|
|
4
4
|
class S extends Error {
|
|
5
5
|
constructor(t, e) {
|
|
6
6
|
super(t), this.code = e, this.name = "SupabaseSyncError";
|
|
7
7
|
}
|
|
8
8
|
}
|
|
9
|
-
class
|
|
9
|
+
class rt extends S {
|
|
10
10
|
constructor(t) {
|
|
11
11
|
super(t, "CONFIG_ERROR"), this.name = "SupabaseConfigError";
|
|
12
12
|
}
|
|
13
13
|
}
|
|
14
|
-
class
|
|
14
|
+
class at extends S {
|
|
15
15
|
constructor(t) {
|
|
16
16
|
super(t, "NETWORK_ERROR"), this.name = "SupabaseNetworkError";
|
|
17
17
|
}
|
|
18
18
|
}
|
|
19
|
-
class
|
|
19
|
+
class g extends S {
|
|
20
20
|
constructor(t) {
|
|
21
21
|
super(t, "DATA_ERROR"), this.name = "SupabaseDataError";
|
|
22
22
|
}
|
|
@@ -30,19 +30,19 @@ function J(i, t) {
|
|
|
30
30
|
if (t.table !== "RxDBChange" || t.eventType !== "INSERT") return;
|
|
31
31
|
const e = t.new;
|
|
32
32
|
if (!e) return;
|
|
33
|
-
const { namespace:
|
|
33
|
+
const { namespace: n, entity: s, entityId: a, type: r, patch: o, clientId: c } = e, d = i.rxdb.context.clientId;
|
|
34
34
|
if (c && d && c === d || !a || !r) return;
|
|
35
|
-
const
|
|
36
|
-
if (!
|
|
37
|
-
const
|
|
35
|
+
const f = V[r];
|
|
36
|
+
if (!f) return;
|
|
37
|
+
const u = { id: a, ...o };
|
|
38
38
|
i.rxdb.dispatchEvent(
|
|
39
|
-
new
|
|
39
|
+
new f([
|
|
40
40
|
{
|
|
41
41
|
type: r,
|
|
42
|
-
namespace:
|
|
43
|
-
entity:
|
|
42
|
+
namespace: n || "public",
|
|
43
|
+
entity: s,
|
|
44
44
|
id: a,
|
|
45
|
-
data:
|
|
45
|
+
data: u,
|
|
46
46
|
recordAt: e.createdAt ? new Date(e.createdAt) : /* @__PURE__ */ new Date()
|
|
47
47
|
}
|
|
48
48
|
])
|
|
@@ -64,7 +64,7 @@ const X = {
|
|
|
64
64
|
function C(i) {
|
|
65
65
|
return i instanceof Date ? i.toISOString() : Array.isArray(i) ? i.map(C) : i;
|
|
66
66
|
}
|
|
67
|
-
function
|
|
67
|
+
function M(i, t, e) {
|
|
68
68
|
return !t || !i.mappedEntity ? e : t.getEntityMetadata(i.mappedEntity, i.mappedNamespace ?? "") ?? e;
|
|
69
69
|
}
|
|
70
70
|
function H(i, t) {
|
|
@@ -91,136 +91,138 @@ function H(i, t) {
|
|
|
91
91
|
throw new Error(`Unsupported operator: ${i}`);
|
|
92
92
|
}
|
|
93
93
|
}
|
|
94
|
-
function
|
|
95
|
-
const [
|
|
96
|
-
return
|
|
97
|
-
field:
|
|
94
|
+
function B(i, t, e) {
|
|
95
|
+
const [n, ...s] = i.split(".");
|
|
96
|
+
return s.length === 0 ? { field: i, operator: t, value: e } : {
|
|
97
|
+
field: n,
|
|
98
98
|
operator: "exists",
|
|
99
|
-
where: { combinator: "and", rules: [
|
|
99
|
+
where: { combinator: "and", rules: [B(s.join("."), t, e)] }
|
|
100
100
|
};
|
|
101
101
|
}
|
|
102
|
-
function
|
|
102
|
+
function x(i, t, e, n) {
|
|
103
103
|
if (!t?.rules?.length) return i;
|
|
104
104
|
if (t.rules.length === 1) {
|
|
105
105
|
const a = t.rules[0];
|
|
106
|
-
return A(a) ?
|
|
106
|
+
return A(a) ? x(i, a, e, n) : I(i, a, e, n);
|
|
107
107
|
}
|
|
108
108
|
if (t.combinator === "and")
|
|
109
109
|
return t.rules.reduce(
|
|
110
|
-
(a, r) => A(r) ?
|
|
110
|
+
(a, r) => A(r) ? x(a, r, e, n) : I(a, r, e, n),
|
|
111
111
|
i
|
|
112
112
|
);
|
|
113
|
-
const
|
|
113
|
+
const s = t.rules.map((a) => {
|
|
114
114
|
if (A(a)) throw new Error("Nested OR conditions not supported");
|
|
115
115
|
const { field: r, operator: o, value: c } = a;
|
|
116
116
|
return `${r}.${H(o, c)}`;
|
|
117
117
|
});
|
|
118
|
-
return i.or(
|
|
118
|
+
return i.or(s.join(","));
|
|
119
119
|
}
|
|
120
|
-
function I(i, t, e,
|
|
121
|
-
const { field:
|
|
122
|
-
return typeof
|
|
120
|
+
function I(i, t, e, n) {
|
|
121
|
+
const { field: s, operator: a, value: r } = t;
|
|
122
|
+
return typeof s == "string" && s.includes(".") ? I(i, B(s, a, r), e, n) : a === "exists" || a === "notExists" ? Y(i, t, e, n) : F(i, s, a, r);
|
|
123
123
|
}
|
|
124
|
-
function Y(i, t, e,
|
|
125
|
-
const { field:
|
|
124
|
+
function Y(i, t, e, n) {
|
|
125
|
+
const { field: s, operator: a } = t, r = t.where, o = String(s), c = e?.relationMap?.get(o);
|
|
126
126
|
if (!c)
|
|
127
127
|
throw new Error(`Relation '${o}' not found in '${e?.name || "unknown"}'`);
|
|
128
128
|
const d = c.mappedEntity;
|
|
129
129
|
if (!r?.rules?.length)
|
|
130
130
|
return a === "exists" ? i.not(d, "is", null) : i.is(d, null);
|
|
131
|
-
const
|
|
132
|
-
if (!
|
|
133
|
-
return R(i, d, r,
|
|
131
|
+
const f = e ? M(c, n, e) : void 0;
|
|
132
|
+
if (!f) throw new Error(`Cannot resolve metadata for '${o}'`);
|
|
133
|
+
return R(i, d, r, f, n, d);
|
|
134
134
|
}
|
|
135
|
-
function R(i, t, e,
|
|
135
|
+
function R(i, t, e, n, s, a = "") {
|
|
136
136
|
if (!e?.rules?.length) return i;
|
|
137
137
|
let r = i;
|
|
138
138
|
for (const o of e.rules) {
|
|
139
139
|
if (A(o)) {
|
|
140
|
-
r = R(r, t, o,
|
|
140
|
+
r = R(r, t, o, n, s, a);
|
|
141
141
|
continue;
|
|
142
142
|
}
|
|
143
|
-
const { field: c, operator: d, value:
|
|
143
|
+
const { field: c, operator: d, value: f } = o;
|
|
144
144
|
if (d === "exists" || d === "notExists") {
|
|
145
|
-
const p =
|
|
145
|
+
const p = n?.relationMap?.get(String(c));
|
|
146
146
|
if (!p) throw new Error(`Relation '${c}' not found in ${t}`);
|
|
147
|
-
const
|
|
148
|
-
if (
|
|
149
|
-
const
|
|
150
|
-
r = R(r,
|
|
147
|
+
const h = p.mappedEntity, l = o.where, m = M(p, s, n);
|
|
148
|
+
if (l?.rules?.length) {
|
|
149
|
+
const w = a ? `${a}.${h}` : h;
|
|
150
|
+
r = R(r, h, l, m, s, w);
|
|
151
151
|
} else
|
|
152
|
-
r = d === "exists" ? r.not(
|
|
152
|
+
r = d === "exists" ? r.not(h, "is", null) : r.is(h, null);
|
|
153
153
|
continue;
|
|
154
154
|
}
|
|
155
|
-
const
|
|
156
|
-
r =
|
|
155
|
+
const u = a ? `${a}.${c}` : `${t}.${c}`;
|
|
156
|
+
r = F(r, u, d, f);
|
|
157
157
|
}
|
|
158
158
|
return r;
|
|
159
159
|
}
|
|
160
|
-
function
|
|
161
|
-
const
|
|
160
|
+
function F(i, t, e, n) {
|
|
161
|
+
const s = C(n);
|
|
162
162
|
if (t.includes(".") && e === "between") {
|
|
163
|
-
const [r, o] =
|
|
163
|
+
const [r, o] = s;
|
|
164
164
|
return i.gte(t, r).lte(t, o);
|
|
165
165
|
}
|
|
166
166
|
switch (e) {
|
|
167
167
|
case "=":
|
|
168
|
-
return
|
|
168
|
+
return s === null ? i.is(t, null) : i.eq(t, s);
|
|
169
169
|
case "!=":
|
|
170
|
-
return
|
|
170
|
+
return s === null ? i.not(t, "is", null) : i.neq(t, s);
|
|
171
171
|
case "<":
|
|
172
|
-
return i.lt(t,
|
|
172
|
+
return i.lt(t, s);
|
|
173
173
|
case ">":
|
|
174
|
-
return i.gt(t,
|
|
174
|
+
return i.gt(t, s);
|
|
175
175
|
case "<=":
|
|
176
|
-
return i.lte(t,
|
|
176
|
+
return i.lte(t, s);
|
|
177
177
|
case ">=":
|
|
178
|
-
return i.gte(t,
|
|
178
|
+
return i.gte(t, s);
|
|
179
179
|
case "in":
|
|
180
|
-
return i.in(t,
|
|
180
|
+
return i.in(t, s);
|
|
181
181
|
case "notIn":
|
|
182
|
-
return i.not(t, "in", `(${
|
|
182
|
+
return i.not(t, "in", `(${s.join(",")})`);
|
|
183
183
|
case "contains":
|
|
184
184
|
case "includes":
|
|
185
|
-
return i.ilike(t, `%${
|
|
185
|
+
return i.ilike(t, `%${s}%`);
|
|
186
186
|
case "notContains":
|
|
187
|
-
return i.not(t, "ilike", `%${
|
|
187
|
+
return i.not(t, "ilike", `%${s}%`);
|
|
188
188
|
case "startsWith":
|
|
189
|
-
return i.ilike(t, `${
|
|
189
|
+
return i.ilike(t, `${s}%`);
|
|
190
190
|
case "notStartsWith":
|
|
191
|
-
return i.not(t, "ilike", `${
|
|
191
|
+
return i.not(t, "ilike", `${s}%`);
|
|
192
192
|
case "endsWith":
|
|
193
|
-
return i.ilike(t, `%${
|
|
193
|
+
return i.ilike(t, `%${s}`);
|
|
194
194
|
case "notEndsWith":
|
|
195
|
-
return i.not(t, "ilike", `%${
|
|
195
|
+
return i.not(t, "ilike", `%${s}`);
|
|
196
196
|
case "between": {
|
|
197
|
-
const [r, o] =
|
|
197
|
+
const [r, o] = s;
|
|
198
198
|
return i.gte(t, r).lte(t, o);
|
|
199
199
|
}
|
|
200
200
|
case "notBetween": {
|
|
201
|
-
const [r, o] =
|
|
201
|
+
const [r, o] = s;
|
|
202
202
|
return i.or(`${t}.lt.${r},${t}.gt.${o}`);
|
|
203
203
|
}
|
|
204
|
+
case "null":
|
|
204
205
|
case "isNull":
|
|
205
206
|
return i.is(t, null);
|
|
207
|
+
case "notNull":
|
|
206
208
|
case "isNotNull":
|
|
207
209
|
return i.not(t, "is", null);
|
|
208
210
|
default:
|
|
209
211
|
throw new Error(`Unsupported operator: ${e}`);
|
|
210
212
|
}
|
|
211
213
|
}
|
|
212
|
-
function
|
|
214
|
+
function T(i) {
|
|
213
215
|
const t = /* @__PURE__ */ new Map();
|
|
214
216
|
for (const e of i) {
|
|
215
|
-
const
|
|
216
|
-
t.has(
|
|
217
|
+
const n = e.constructor;
|
|
218
|
+
t.has(n) || t.set(n, /* @__PURE__ */ new Set()), t.get(n).add(e);
|
|
217
219
|
}
|
|
218
220
|
return t;
|
|
219
221
|
}
|
|
220
222
|
function v(i, t) {
|
|
221
223
|
const e = [];
|
|
222
|
-
for (const [
|
|
223
|
-
const a =
|
|
224
|
+
for (const [n, s] of i) {
|
|
225
|
+
const a = _(n), r = Array.from(s);
|
|
224
226
|
e.push({
|
|
225
227
|
table: a.name,
|
|
226
228
|
schema: a.namespace,
|
|
@@ -231,12 +233,12 @@ function v(i, t) {
|
|
|
231
233
|
}
|
|
232
234
|
function Z(i) {
|
|
233
235
|
const t = [];
|
|
234
|
-
for (const [e,
|
|
235
|
-
const
|
|
236
|
+
for (const [e, n] of i) {
|
|
237
|
+
const s = _(e);
|
|
236
238
|
t.push({
|
|
237
|
-
table:
|
|
238
|
-
schema:
|
|
239
|
-
ids: Array.from(
|
|
239
|
+
table: s.name,
|
|
240
|
+
schema: s.namespace,
|
|
241
|
+
ids: Array.from(n).map((a) => a.id)
|
|
240
242
|
});
|
|
241
243
|
}
|
|
242
244
|
return t;
|
|
@@ -244,36 +246,36 @@ function Z(i) {
|
|
|
244
246
|
function j(i, t) {
|
|
245
247
|
if (i == null) return i;
|
|
246
248
|
switch (t.type) {
|
|
247
|
-
case
|
|
249
|
+
case $.date:
|
|
248
250
|
return i instanceof Date ? i : new Date(i);
|
|
249
|
-
case
|
|
251
|
+
case $.keyValue:
|
|
250
252
|
if (typeof i == "object" && t.properties) {
|
|
251
253
|
const e = {};
|
|
252
|
-
for (const
|
|
253
|
-
i[
|
|
254
|
+
for (const n of t.properties)
|
|
255
|
+
i[n.name] !== void 0 && (e[n.name] = j(i[n.name], n));
|
|
254
256
|
return e;
|
|
255
257
|
}
|
|
256
258
|
return i;
|
|
257
|
-
case
|
|
259
|
+
case $.boolean:
|
|
258
260
|
return !!i;
|
|
259
|
-
case
|
|
260
|
-
case
|
|
261
|
-
case
|
|
261
|
+
case $.json:
|
|
262
|
+
case $.stringArray:
|
|
263
|
+
case $.numberArray:
|
|
262
264
|
default:
|
|
263
265
|
return i;
|
|
264
266
|
}
|
|
265
267
|
}
|
|
266
268
|
function G(i, t, e) {
|
|
267
|
-
const
|
|
268
|
-
for (const
|
|
269
|
-
const a = t.propertyMap.get(
|
|
270
|
-
s
|
|
269
|
+
const n = new i();
|
|
270
|
+
for (const s of Object.keys(e)) {
|
|
271
|
+
const a = t.propertyMap.get(s);
|
|
272
|
+
n[s] = a ? j(e[s], a) : e[s];
|
|
271
273
|
}
|
|
272
|
-
return
|
|
274
|
+
return n;
|
|
273
275
|
}
|
|
274
276
|
class P extends K {
|
|
275
277
|
constructor(t, e) {
|
|
276
|
-
super(t.rxdb, e), this.adapter = t, this.metadata =
|
|
278
|
+
super(t.rxdb, e), this.adapter = t, this.metadata = _(e);
|
|
277
279
|
}
|
|
278
280
|
metadata;
|
|
279
281
|
/**
|
|
@@ -281,23 +283,23 @@ class P extends K {
|
|
|
281
283
|
*/
|
|
282
284
|
async find(t) {
|
|
283
285
|
const e = this.extract_relation_fields(t.where);
|
|
284
|
-
let
|
|
286
|
+
let n = "*";
|
|
285
287
|
if (e.size > 0) {
|
|
286
288
|
const o = Array.from(e);
|
|
287
|
-
|
|
288
|
-
(d) => !o.some((
|
|
289
|
+
n = `*, ${o.filter(
|
|
290
|
+
(d) => !o.some((f) => f !== d && f.startsWith(d + "."))
|
|
289
291
|
).map((d) => this.build_relation_select(d)).join(", ")}`;
|
|
290
292
|
}
|
|
291
|
-
let
|
|
292
|
-
if (
|
|
293
|
+
let s = this.get_client().select(n);
|
|
294
|
+
if (s = x(s, t.where, this.metadata, this.adapter.rxdb.schemaManager), t.orderBy?.length)
|
|
293
295
|
for (const o of t.orderBy)
|
|
294
|
-
|
|
296
|
+
s = s.order(o.field, { ascending: o.sort === "asc" });
|
|
295
297
|
if (t.offset !== void 0) {
|
|
296
298
|
const o = t.offset, c = t.limit !== void 0 ? o + t.limit - 1 : Number.MAX_SAFE_INTEGER;
|
|
297
|
-
|
|
298
|
-
} else t.limit !== void 0 && (
|
|
299
|
-
const { data: a, error: r } = await
|
|
300
|
-
if (r) throw new
|
|
299
|
+
s = s.range(o, c);
|
|
300
|
+
} else t.limit !== void 0 && (s = s.limit(t.limit));
|
|
301
|
+
const { data: a, error: r } = await s;
|
|
302
|
+
if (r) throw new g(`Failed to find entities: ${r.message}`);
|
|
301
303
|
return (a || []).map((o) => G(this.EntityType, this.metadata, o));
|
|
302
304
|
}
|
|
303
305
|
/**
|
|
@@ -306,15 +308,15 @@ class P extends K {
|
|
|
306
308
|
async count(t) {
|
|
307
309
|
if (t.groupBy) throw new Error("groupBy not supported yet");
|
|
308
310
|
const e = this.extract_relation_fields(t.where);
|
|
309
|
-
let
|
|
310
|
-
e.size > 0 && (
|
|
311
|
-
let
|
|
312
|
-
|
|
313
|
-
const { count: a, error: r } = await
|
|
311
|
+
let n = "*";
|
|
312
|
+
e.size > 0 && (n = `*, ${Array.from(e).map((o) => this.build_relation_select(o)).join(", ")}`);
|
|
313
|
+
let s = this.get_client().select(n, { count: "exact", head: !0 });
|
|
314
|
+
s = x(s, t.where, this.metadata, this.adapter.rxdb.schemaManager);
|
|
315
|
+
const { count: a, error: r } = await s;
|
|
314
316
|
if (r) {
|
|
315
317
|
if (!r.message)
|
|
316
318
|
return console.warn("Supabase count returned empty error, returning 0. Options:", JSON.stringify(t)), 0;
|
|
317
|
-
throw new
|
|
319
|
+
throw new g(`Failed to count entities: ${r.message}`);
|
|
318
320
|
}
|
|
319
321
|
return a ?? 0;
|
|
320
322
|
}
|
|
@@ -322,19 +324,19 @@ class P extends K {
|
|
|
322
324
|
* 创建实体
|
|
323
325
|
*/
|
|
324
326
|
async create(t) {
|
|
325
|
-
const e = { ...t },
|
|
326
|
-
|
|
327
|
-
const { data:
|
|
328
|
-
if (a) throw new
|
|
329
|
-
return
|
|
327
|
+
const e = { ...t }, n = this.rxdb.context.userId;
|
|
328
|
+
n && (e.createdBy = n);
|
|
329
|
+
const { data: s, error: a } = await this.get_client().insert(e).select().single();
|
|
330
|
+
if (a) throw new g(`Failed to create entity: ${a.message}`);
|
|
331
|
+
return s;
|
|
330
332
|
}
|
|
331
333
|
/**
|
|
332
334
|
* 更新实体
|
|
333
335
|
*/
|
|
334
336
|
async update(t, e) {
|
|
335
|
-
const { data:
|
|
336
|
-
if (
|
|
337
|
-
return
|
|
337
|
+
const { data: n, error: s } = await this.get_client().update(e).eq("id", t.id).select().single();
|
|
338
|
+
if (s) throw new g(`Failed to update entity: ${s.message}`);
|
|
339
|
+
return n;
|
|
338
340
|
}
|
|
339
341
|
/**
|
|
340
342
|
* 删除实体
|
|
@@ -343,7 +345,7 @@ class P extends K {
|
|
|
343
345
|
*/
|
|
344
346
|
async remove(t) {
|
|
345
347
|
const { error: e } = await this.get_client().delete().eq("id", t.id);
|
|
346
|
-
if (e) throw new
|
|
348
|
+
if (e) throw new g(`Failed to remove entity: ${e.message}`);
|
|
347
349
|
return t;
|
|
348
350
|
}
|
|
349
351
|
// ============================================
|
|
@@ -351,11 +353,11 @@ class P extends K {
|
|
|
351
353
|
// ============================================
|
|
352
354
|
/** 提取查询中的关系字段路径(用于 EXISTS 查询的 INNER JOIN) */
|
|
353
355
|
extract_relation_fields(t) {
|
|
354
|
-
const e = /* @__PURE__ */ new Set(),
|
|
355
|
-
if (
|
|
356
|
-
for (const r of
|
|
356
|
+
const e = /* @__PURE__ */ new Set(), n = (s, a = "") => {
|
|
357
|
+
if (s?.rules) {
|
|
358
|
+
for (const r of s.rules)
|
|
357
359
|
if (r.rules)
|
|
358
|
-
|
|
360
|
+
n(r, a);
|
|
359
361
|
else if (typeof r.field == "string" && r.field.includes(".")) {
|
|
360
362
|
const o = r.field.split(".");
|
|
361
363
|
for (let c = 1; c < o.length; c++) {
|
|
@@ -364,11 +366,11 @@ class P extends K {
|
|
|
364
366
|
}
|
|
365
367
|
} else if (r.operator === "exists" || r.operator === "notExists") {
|
|
366
368
|
const o = String(r.field), c = a ? `${a}.${o}` : o;
|
|
367
|
-
this.metadata.relationMap?.has(o) && e.add(c), r.where &&
|
|
369
|
+
this.metadata.relationMap?.has(o) && e.add(c), r.where && n(r.where, c);
|
|
368
370
|
}
|
|
369
371
|
}
|
|
370
372
|
};
|
|
371
|
-
return
|
|
373
|
+
return n(t), e;
|
|
372
374
|
}
|
|
373
375
|
/**
|
|
374
376
|
* 构建关系字段的 SELECT 语法
|
|
@@ -377,18 +379,18 @@ class P extends K {
|
|
|
377
379
|
build_relation_select(t) {
|
|
378
380
|
const e = t.split(".");
|
|
379
381
|
if (e.length === 1) return this.build_single_relation_select(e[0]);
|
|
380
|
-
const
|
|
381
|
-
let
|
|
382
|
+
const n = [];
|
|
383
|
+
let s = this.metadata;
|
|
382
384
|
for (const r of e) {
|
|
383
|
-
const o =
|
|
385
|
+
const o = s.relationMap?.get(r);
|
|
384
386
|
if (!o) return `${r}(id)`;
|
|
385
|
-
|
|
387
|
+
n.push({ tableName: o.mappedEntity, kind: o.kind, sourceEntity: s.name });
|
|
386
388
|
const c = this.adapter.rxdb.schemaManager.getEntityMetadata(o.mappedEntity, o.mappedNamespace ?? "");
|
|
387
|
-
c && (
|
|
389
|
+
c && (s = c);
|
|
388
390
|
}
|
|
389
|
-
let a = this.build_relation_segment(
|
|
390
|
-
for (let r =
|
|
391
|
-
a = this.build_relation_segment(
|
|
391
|
+
let a = this.build_relation_segment(n[n.length - 1], !0);
|
|
392
|
+
for (let r = n.length - 2; r >= 0; r--)
|
|
393
|
+
a = this.build_relation_segment(n[r], !0).replace("(*)", `(*, ${a})`);
|
|
392
394
|
return a;
|
|
393
395
|
}
|
|
394
396
|
/**
|
|
@@ -398,25 +400,25 @@ class P extends K {
|
|
|
398
400
|
build_single_relation_select(t) {
|
|
399
401
|
const e = this.metadata.relationMap?.get(t);
|
|
400
402
|
if (!e) return `${t}(id)`;
|
|
401
|
-
const
|
|
403
|
+
const n = e.mappedEntity, s = this.metadata.name;
|
|
402
404
|
if (e.kind === "m:1" || e.kind === "1:1") {
|
|
403
|
-
const a = `${
|
|
404
|
-
return `${
|
|
405
|
+
const a = `${s}_${t}Id_fkey`;
|
|
406
|
+
return `${n}!${a}(*)`;
|
|
405
407
|
}
|
|
406
408
|
if (e.kind === "m:n") {
|
|
407
|
-
const a = this.get_join_table_name(
|
|
408
|
-
return `${
|
|
409
|
+
const a = this.get_join_table_name(s, n);
|
|
410
|
+
return `${n}!${a}(*)`;
|
|
409
411
|
}
|
|
410
|
-
return `${
|
|
412
|
+
return `${n}(*)`;
|
|
411
413
|
}
|
|
412
414
|
/** 构建关系 SELECT 片段 */
|
|
413
415
|
build_relation_segment(t, e) {
|
|
414
|
-
const
|
|
416
|
+
const n = e ? "!inner" : "";
|
|
415
417
|
if (t.kind === "m:n") {
|
|
416
|
-
const
|
|
417
|
-
return `${t.tableName}!${
|
|
418
|
+
const s = this.get_join_table_name(t.sourceEntity, t.tableName);
|
|
419
|
+
return `${t.tableName}!${s}${n}(*)`;
|
|
418
420
|
}
|
|
419
|
-
return `${t.tableName}${
|
|
421
|
+
return `${t.tableName}${n}(*)`;
|
|
420
422
|
}
|
|
421
423
|
/** 获取 m:n 中间表名(按字母顺序) */
|
|
422
424
|
get_join_table_name(t, e) {
|
|
@@ -439,16 +441,16 @@ class q extends P {
|
|
|
439
441
|
* - 不指定 entityId 时:返回所有根节点及其子孙
|
|
440
442
|
*/
|
|
441
443
|
async findDescendants(t) {
|
|
442
|
-
const { entityId: e, level:
|
|
444
|
+
const { entityId: e, level: n = 100 } = t, { data: s, error: a } = await this.adapter.client.rpc(
|
|
443
445
|
e ? "get_descendants" : "get_root_descendants",
|
|
444
|
-
e ? { root_id: e, max_level:
|
|
446
|
+
e ? { root_id: e, max_level: n } : { max_level: n }
|
|
445
447
|
);
|
|
446
448
|
if (a) {
|
|
447
449
|
if (a.message.includes("function") || a.message.includes("Could not find"))
|
|
448
450
|
return this.findDescendantsFallback(t);
|
|
449
|
-
throw new
|
|
451
|
+
throw new g(`Failed to find descendants: ${a.message}`);
|
|
450
452
|
}
|
|
451
|
-
return (
|
|
453
|
+
return (s || []).map((r) => this.transformRowToEntity(r));
|
|
452
454
|
}
|
|
453
455
|
/**
|
|
454
456
|
* 查询子孙节点数量
|
|
@@ -458,8 +460,8 @@ class q extends P {
|
|
|
458
460
|
* - 不指定 entityId 时:统计所有根节点及其后代的总数
|
|
459
461
|
*/
|
|
460
462
|
async countDescendants(t) {
|
|
461
|
-
const { entityId: e } = t,
|
|
462
|
-
return e ?
|
|
463
|
+
const { entityId: e } = t, n = await this.findDescendants(t);
|
|
464
|
+
return e ? n.length - 1 : n.length;
|
|
463
465
|
}
|
|
464
466
|
/**
|
|
465
467
|
* 查询祖先节点
|
|
@@ -468,19 +470,19 @@ class q extends P {
|
|
|
468
470
|
* 指定 entityId 时:包含当前节点 + 祖先节点
|
|
469
471
|
*/
|
|
470
472
|
async findAncestors(t) {
|
|
471
|
-
const { entityId: e, level:
|
|
473
|
+
const { entityId: e, level: n = 100 } = t;
|
|
472
474
|
if (!e)
|
|
473
475
|
return [];
|
|
474
|
-
const { data:
|
|
476
|
+
const { data: s, error: a } = await this.adapter.client.rpc("get_ancestors", {
|
|
475
477
|
node_id: e,
|
|
476
|
-
max_level:
|
|
478
|
+
max_level: n
|
|
477
479
|
});
|
|
478
480
|
if (a) {
|
|
479
481
|
if (a.message.includes("function") || a.message.includes("Could not find"))
|
|
480
482
|
return this.findAncestorsFallback(t);
|
|
481
|
-
throw new
|
|
483
|
+
throw new g(`Failed to find ancestors: ${a.message}`);
|
|
482
484
|
}
|
|
483
|
-
return (
|
|
485
|
+
return (s || []).map((r) => this.transformRowToEntity(r));
|
|
484
486
|
}
|
|
485
487
|
/**
|
|
486
488
|
* 查询祖先节点数量
|
|
@@ -494,67 +496,85 @@ class q extends P {
|
|
|
494
496
|
}
|
|
495
497
|
/**
|
|
496
498
|
* 备用的子孙节点查询(不使用存储函数)
|
|
497
|
-
* 仅支持简单的层级查询
|
|
498
499
|
*
|
|
499
|
-
*
|
|
500
|
-
* 优化方案:一次查询获取所有节点,在内存中构建树结构。
|
|
500
|
+
* 一次查询获取所有节点,在内存中构建树结构,避免 N+1 问题。
|
|
501
501
|
*/
|
|
502
502
|
async findDescendantsFallback(t) {
|
|
503
|
-
const { entityId: e, level:
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
503
|
+
const { entityId: e, level: n = 100 } = t, s = this.metadata.name, a = this.metadata.features?.tree?.hasChildren, { data: r, error: o } = await this.adapter.client.schema("public").from(s).select("*");
|
|
504
|
+
if (o)
|
|
505
|
+
throw new g(`Failed to find descendants: ${o.message}`);
|
|
506
|
+
if (!r || r.length === 0) return [];
|
|
507
|
+
const c = /* @__PURE__ */ new Map(), d = /* @__PURE__ */ new Map();
|
|
508
|
+
for (const l of r) {
|
|
509
|
+
d.set(l.id, l);
|
|
510
|
+
const m = l.parentId ?? null;
|
|
511
|
+
c.has(m) || c.set(m, []), c.get(m).push(l);
|
|
512
|
+
}
|
|
513
|
+
const f = [], u = /* @__PURE__ */ new Set();
|
|
514
|
+
let p;
|
|
515
|
+
if (e) {
|
|
516
|
+
const l = d.get(e);
|
|
517
|
+
p = l ? [l] : [];
|
|
518
|
+
} else
|
|
519
|
+
p = c.get(null) ?? [];
|
|
520
|
+
const h = p.map((l) => ({ node: l, depth: 0 }));
|
|
521
|
+
for (; h.length > 0; ) {
|
|
522
|
+
const { node: l, depth: m } = h.shift();
|
|
523
|
+
if (u.has(l.id) || m > n) continue;
|
|
524
|
+
u.add(l.id);
|
|
525
|
+
const w = this.transformRowToEntity(l);
|
|
526
|
+
if (a) {
|
|
527
|
+
const y = c.get(l.id);
|
|
528
|
+
w.hasChildren = !!y && y.length > 0;
|
|
522
529
|
}
|
|
523
|
-
|
|
524
|
-
|
|
530
|
+
if (f.push(w), m < n) {
|
|
531
|
+
const y = c.get(l.id) ?? [];
|
|
532
|
+
for (const b of y)
|
|
533
|
+
h.push({ node: b, depth: m + 1 });
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
return f;
|
|
525
537
|
}
|
|
526
538
|
/**
|
|
527
539
|
* 备用的祖先节点查询(不使用存储函数)
|
|
528
540
|
*
|
|
529
|
-
*
|
|
530
|
-
* 优化方案:一次查询获取所有节点,在内存中向上遍历。
|
|
541
|
+
* 一次查询获取所有节点,在内存中向上遍历,避免 N+1 问题。
|
|
531
542
|
*/
|
|
532
543
|
async findAncestorsFallback(t) {
|
|
533
|
-
const { entityId: e, level:
|
|
544
|
+
const { entityId: e, level: n = 100 } = t;
|
|
534
545
|
if (!e)
|
|
535
546
|
return [];
|
|
536
|
-
const
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
547
|
+
const s = this.metadata.name, a = this.metadata.features?.tree?.hasChildren, { data: r, error: o } = await this.adapter.client.schema("public").from(s).select("*");
|
|
548
|
+
if (o)
|
|
549
|
+
throw new g(`Failed to find ancestors: ${o.message}`);
|
|
550
|
+
if (!r || r.length === 0) return [];
|
|
551
|
+
const c = /* @__PURE__ */ new Map(), d = /* @__PURE__ */ new Map();
|
|
552
|
+
for (const h of r) {
|
|
553
|
+
c.set(h.id, h);
|
|
554
|
+
const l = h.parentId ?? null;
|
|
555
|
+
d.has(l) || d.set(l, []), d.get(l).push(h);
|
|
556
|
+
}
|
|
557
|
+
const f = [];
|
|
558
|
+
let u = e, p = 0;
|
|
559
|
+
for (; u && p <= n; ) {
|
|
560
|
+
const h = c.get(u);
|
|
561
|
+
if (!h) break;
|
|
562
|
+
const l = this.transformRowToEntity(h);
|
|
543
563
|
if (a) {
|
|
544
|
-
const
|
|
545
|
-
|
|
564
|
+
const m = d.get(h.id);
|
|
565
|
+
l.hasChildren = !!m && m.length > 0;
|
|
546
566
|
}
|
|
547
|
-
|
|
567
|
+
f.push(l), u = h.parentId ?? null, p++;
|
|
548
568
|
}
|
|
549
|
-
return
|
|
569
|
+
return f;
|
|
550
570
|
}
|
|
551
571
|
/**
|
|
552
572
|
* 将数据库行转换为实体
|
|
553
573
|
*/
|
|
554
574
|
transformRowToEntity(t) {
|
|
555
575
|
const e = new this.EntityType();
|
|
556
|
-
return Object.keys(t).forEach((
|
|
557
|
-
|
|
576
|
+
return Object.keys(t).forEach((n) => {
|
|
577
|
+
n !== "level" && (e[n] = t[n]);
|
|
558
578
|
}), e;
|
|
559
579
|
}
|
|
560
580
|
}
|
|
@@ -594,13 +614,13 @@ class it extends z {
|
|
|
594
614
|
* 批量保存实体(upsert 语义,非事务)
|
|
595
615
|
*/
|
|
596
616
|
async saveMany(t) {
|
|
597
|
-
return t.length === 0 ? [] : this.executeUpsert(
|
|
617
|
+
return t.length === 0 ? [] : this.executeUpsert(T(t));
|
|
598
618
|
}
|
|
599
619
|
/**
|
|
600
620
|
* 批量删除实体(非事务)
|
|
601
621
|
*/
|
|
602
622
|
async removeMany(t) {
|
|
603
|
-
return t.length === 0 ? [] : this.executeDelete(
|
|
623
|
+
return t.length === 0 ? [] : this.executeDelete(T(t));
|
|
604
624
|
}
|
|
605
625
|
/**
|
|
606
626
|
* 批量修改实体(事务)
|
|
@@ -609,12 +629,12 @@ class it extends z {
|
|
|
609
629
|
* 在单个数据库事务中执行所有操作,确保原子性。
|
|
610
630
|
*/
|
|
611
631
|
async mutations(t) {
|
|
612
|
-
const e = this.rxdb.context.userId,
|
|
613
|
-
p_upserts:
|
|
614
|
-
p_deletes:
|
|
632
|
+
const e = this.rxdb.context.userId, n = [...v(t.create, e), ...v(t.update, e)], s = Z(t.remove), { data: a, error: r } = await this.#t.rpc("rxdb_mutations", {
|
|
633
|
+
p_upserts: n,
|
|
634
|
+
p_deletes: s
|
|
615
635
|
});
|
|
616
636
|
if (r)
|
|
617
|
-
throw new
|
|
637
|
+
throw new g(`Transaction failed: ${r.message}`);
|
|
618
638
|
const o = a?.upserted ?? [];
|
|
619
639
|
for (const [, c] of t.remove)
|
|
620
640
|
o.push(...c);
|
|
@@ -626,18 +646,18 @@ class it extends z {
|
|
|
626
646
|
getRepository(t) {
|
|
627
647
|
if (this.repository_cache.has(t))
|
|
628
648
|
return this.repository_cache.get(t);
|
|
629
|
-
const
|
|
630
|
-
return this.repository_cache.set(t,
|
|
649
|
+
const n = _(t).features?.tree ? new q(this, t) : new P(this, t);
|
|
650
|
+
return this.repository_cache.set(t, n), n;
|
|
631
651
|
}
|
|
632
652
|
// ============================================
|
|
633
653
|
// 工具方法
|
|
634
654
|
// ============================================
|
|
635
655
|
async isTableExisted(t) {
|
|
636
|
-
const e =
|
|
637
|
-
if (
|
|
638
|
-
if (
|
|
639
|
-
throw new
|
|
640
|
-
`Failed to check table existence: ${
|
|
656
|
+
const e = _(t), s = await this.getSchemaClient(e.namespace).from(e.name).select("*", { count: "exact", head: !0 });
|
|
657
|
+
if (s.status === 200) return !0;
|
|
658
|
+
if (s.status === 204) return !1;
|
|
659
|
+
throw new g(
|
|
660
|
+
`Failed to check table existence: ${s.error?.message || `status ${s.status}`}`
|
|
641
661
|
);
|
|
642
662
|
}
|
|
643
663
|
// ============================================
|
|
@@ -658,25 +678,25 @@ class it extends z {
|
|
|
658
678
|
* 当提供 filter 参数时,会通过 JOIN 实体表并应用过滤条件,
|
|
659
679
|
* 只返回满足条件的实体对应的变更记录。
|
|
660
680
|
*/
|
|
661
|
-
async pullChanges(t, e = 1e3,
|
|
681
|
+
async pullChanges(t, e = 1e3, n, s) {
|
|
662
682
|
const a = [];
|
|
663
683
|
let r;
|
|
664
|
-
if (
|
|
665
|
-
const
|
|
666
|
-
if (r = await this.#n(
|
|
684
|
+
if (s && n?.length === 1) {
|
|
685
|
+
const u = n[0];
|
|
686
|
+
if (r = await this.#n(u, s), r.length === 0)
|
|
667
687
|
return [];
|
|
668
688
|
}
|
|
669
689
|
let o = this.#t.from("RxDBChange").select("*").gt("id", t).order("id", { ascending: !0 }).limit(e);
|
|
670
|
-
|
|
690
|
+
n && n.length > 0 && (o = o.in("entity", n)), r && (o = o.in("entityId", r));
|
|
671
691
|
const { data: c, error: d } = await o;
|
|
672
692
|
if (d)
|
|
673
|
-
throw new
|
|
674
|
-
const
|
|
675
|
-
...
|
|
676
|
-
createdAt: new Date(
|
|
677
|
-
updatedAt:
|
|
693
|
+
throw new g(`Failed to pull changes: ${d.message}`);
|
|
694
|
+
const f = (c ?? []).map((u) => ({
|
|
695
|
+
...u,
|
|
696
|
+
createdAt: new Date(u.createdAt),
|
|
697
|
+
updatedAt: u.updatedAt ? new Date(u.updatedAt) : null
|
|
678
698
|
}));
|
|
679
|
-
return a.push(...
|
|
699
|
+
return a.push(...f), a;
|
|
680
700
|
}
|
|
681
701
|
/**
|
|
682
702
|
* 获取远程变更数量(轻量级,不下载数据)(T042, US2)
|
|
@@ -696,22 +716,22 @@ class it extends z {
|
|
|
696
716
|
* ```
|
|
697
717
|
*/
|
|
698
718
|
async getChangeCount(t, e) {
|
|
699
|
-
let
|
|
700
|
-
e && e.length > 0 && (
|
|
701
|
-
const { count:
|
|
719
|
+
let n = this.#t.from("RxDBChange").select("*", { count: "exact", head: !0 }).gt("id", t);
|
|
720
|
+
e && e.length > 0 && (n = n.in("entity", e));
|
|
721
|
+
const { count: s, error: a } = await n;
|
|
702
722
|
if (a)
|
|
703
|
-
throw new
|
|
723
|
+
throw new g(`Failed to get change count: ${a.message}`);
|
|
704
724
|
let r = t;
|
|
705
|
-
if (
|
|
725
|
+
if (s && s > 0) {
|
|
706
726
|
let o = this.#t.from("RxDBChange").select("id").gt("id", t).order("id", { ascending: !1 }).limit(1);
|
|
707
727
|
e && e.length > 0 && (o = o.in("entity", e));
|
|
708
728
|
const { data: c, error: d } = await o;
|
|
709
729
|
if (d)
|
|
710
|
-
throw new
|
|
730
|
+
throw new g(`Failed to get latest changeId: ${d.message}`);
|
|
711
731
|
c && c.length > 0 && (r = c[0].id);
|
|
712
732
|
}
|
|
713
733
|
return {
|
|
714
|
-
count:
|
|
734
|
+
count: s ?? 0,
|
|
715
735
|
latestChangeId: r
|
|
716
736
|
};
|
|
717
737
|
}
|
|
@@ -729,18 +749,18 @@ class it extends z {
|
|
|
729
749
|
updates: /* @__PURE__ */ new Map(),
|
|
730
750
|
deletes: /* @__PURE__ */ new Map()
|
|
731
751
|
};
|
|
732
|
-
for (const
|
|
733
|
-
const { entityKey:
|
|
752
|
+
for (const n of t) {
|
|
753
|
+
const { entityKey: s, finalType: a, finalPatch: r, inversePatch: o } = n;
|
|
734
754
|
if (a)
|
|
735
755
|
switch (a) {
|
|
736
756
|
case "INSERT":
|
|
737
|
-
e.inserts.set(
|
|
757
|
+
e.inserts.set(s, { patch: r, inversePatch: o });
|
|
738
758
|
break;
|
|
739
759
|
case "UPDATE":
|
|
740
|
-
e.updates.set(
|
|
760
|
+
e.updates.set(s, { patch: r, inversePatch: o });
|
|
741
761
|
break;
|
|
742
762
|
case "DELETE":
|
|
743
|
-
e.deletes.set(
|
|
763
|
+
e.deletes.set(s, { patch: null, inversePatch: o });
|
|
744
764
|
break;
|
|
745
765
|
}
|
|
746
766
|
}
|
|
@@ -757,13 +777,13 @@ class it extends z {
|
|
|
757
777
|
* @param actions - 压缩后的变更操作集合
|
|
758
778
|
*/
|
|
759
779
|
async mergeChanges(t) {
|
|
760
|
-
const e = (/* @__PURE__ */ new Date()).toISOString(),
|
|
761
|
-
for (const [
|
|
762
|
-
const [
|
|
763
|
-
|
|
764
|
-
namespace:
|
|
765
|
-
entity:
|
|
766
|
-
entityId:
|
|
780
|
+
const e = (/* @__PURE__ */ new Date()).toISOString(), n = this.rxdb.context.userId, s = [], a = /* @__PURE__ */ new Map(), r = /* @__PURE__ */ new Map();
|
|
781
|
+
for (const [u, { inversePatch: p }] of t.deletes) {
|
|
782
|
+
const [h, l, m] = u.split(":"), w = h ? `${h}.${l}` : l;
|
|
783
|
+
s.push({
|
|
784
|
+
namespace: h || "public",
|
|
785
|
+
entity: l,
|
|
786
|
+
entityId: m,
|
|
767
787
|
type: "DELETE",
|
|
768
788
|
patch: null,
|
|
769
789
|
inversePatch: p,
|
|
@@ -771,55 +791,55 @@ class it extends z {
|
|
|
771
791
|
createdAt: e,
|
|
772
792
|
updatedAt: e
|
|
773
793
|
});
|
|
774
|
-
const
|
|
775
|
-
|
|
794
|
+
const y = r.get(w) ?? [];
|
|
795
|
+
y.push(m), r.set(w, y);
|
|
776
796
|
}
|
|
777
|
-
for (const [
|
|
778
|
-
const [
|
|
779
|
-
|
|
780
|
-
namespace:
|
|
781
|
-
entity:
|
|
782
|
-
entityId:
|
|
797
|
+
for (const [u, { patch: p, inversePatch: h }] of t.updates) {
|
|
798
|
+
const [l, m, w] = u.split(":"), y = l ? `${l}.${m}` : m;
|
|
799
|
+
s.push({
|
|
800
|
+
namespace: l || "public",
|
|
801
|
+
entity: m,
|
|
802
|
+
entityId: w,
|
|
783
803
|
type: "UPDATE",
|
|
784
804
|
patch: p,
|
|
785
|
-
inversePatch:
|
|
805
|
+
inversePatch: h,
|
|
786
806
|
clientId: this.rxdb.context.clientId,
|
|
787
807
|
createdAt: e,
|
|
788
808
|
updatedAt: e
|
|
789
809
|
});
|
|
790
|
-
const
|
|
791
|
-
|
|
810
|
+
const b = a.get(y) ?? [], E = { id: w, ...p };
|
|
811
|
+
n && (E.updatedBy = n), b.push(E), a.set(y, b);
|
|
792
812
|
}
|
|
793
|
-
for (const [
|
|
794
|
-
const [
|
|
795
|
-
|
|
796
|
-
namespace:
|
|
797
|
-
entity:
|
|
798
|
-
entityId:
|
|
813
|
+
for (const [u, { patch: p, inversePatch: h }] of t.inserts) {
|
|
814
|
+
const [l, m, w] = u.split(":"), y = l ? `${l}.${m}` : m;
|
|
815
|
+
s.push({
|
|
816
|
+
namespace: l || "public",
|
|
817
|
+
entity: m,
|
|
818
|
+
entityId: w,
|
|
799
819
|
type: "INSERT",
|
|
800
820
|
patch: p,
|
|
801
|
-
inversePatch:
|
|
821
|
+
inversePatch: h,
|
|
802
822
|
clientId: this.rxdb.context.clientId,
|
|
803
823
|
createdAt: e,
|
|
804
824
|
updatedAt: e
|
|
805
825
|
});
|
|
806
|
-
const
|
|
807
|
-
|
|
826
|
+
const b = a.get(y) ?? [], E = { id: w, ...p };
|
|
827
|
+
n && (E.createdBy = n, E.updatedBy = n), b.push(E), a.set(y, b);
|
|
808
828
|
}
|
|
809
|
-
const o = Array.from(a.entries()).map(([
|
|
810
|
-
const [
|
|
811
|
-
return { table:
|
|
812
|
-
}), c = Array.from(r.entries()).map(([
|
|
813
|
-
const [
|
|
814
|
-
return { table:
|
|
815
|
-
}), { data: d, error:
|
|
829
|
+
const o = Array.from(a.entries()).map(([u, p]) => {
|
|
830
|
+
const [h, l] = u.includes(".") ? u.split(".") : ["public", u];
|
|
831
|
+
return { table: l, schema: h, data: p };
|
|
832
|
+
}), c = Array.from(r.entries()).map(([u, p]) => {
|
|
833
|
+
const [h, l] = u.includes(".") ? u.split(".") : ["public", u];
|
|
834
|
+
return { table: l, schema: h, ids: p };
|
|
835
|
+
}), { data: d, error: f } = await this.#t.rpc("rxdb_mutations", {
|
|
816
836
|
p_upserts: o,
|
|
817
837
|
p_deletes: c,
|
|
818
|
-
p_changes:
|
|
838
|
+
p_changes: s,
|
|
819
839
|
p_skip_sync: !0
|
|
820
840
|
});
|
|
821
|
-
if (
|
|
822
|
-
throw new
|
|
841
|
+
if (f)
|
|
842
|
+
throw new g(`Failed to merge changes: ${f.message}`);
|
|
823
843
|
return d?.max_change_id ?? void 0;
|
|
824
844
|
}
|
|
825
845
|
// ============================================
|
|
@@ -842,12 +862,12 @@ class it extends z {
|
|
|
842
862
|
*/
|
|
843
863
|
fetchMetadata(t, e) {
|
|
844
864
|
return D(() => {
|
|
845
|
-
let
|
|
846
|
-
return
|
|
847
|
-
|
|
865
|
+
let n = this.#t.from(t).select("id, updatedAt");
|
|
866
|
+
return n = x(n, e), N(n).pipe(
|
|
867
|
+
k(({ data: s, error: a }) => {
|
|
848
868
|
if (a)
|
|
849
|
-
throw new
|
|
850
|
-
return (
|
|
869
|
+
throw new g(`Failed to fetch metadata: ${a.message}`);
|
|
870
|
+
return (s ?? []).map((r) => ({
|
|
851
871
|
id: r.id,
|
|
852
872
|
updatedAt: r.updatedAt
|
|
853
873
|
}));
|
|
@@ -863,11 +883,11 @@ class it extends z {
|
|
|
863
883
|
* @returns Observable<T[]>
|
|
864
884
|
*/
|
|
865
885
|
findByIds(t, e) {
|
|
866
|
-
return D(() => e.length === 0 ? Q([]) :
|
|
867
|
-
|
|
868
|
-
if (
|
|
869
|
-
throw new
|
|
870
|
-
return
|
|
886
|
+
return D(() => e.length === 0 ? Q([]) : N(this.#t.from(t).select("*").in("id", e)).pipe(
|
|
887
|
+
k(({ data: n, error: s }) => {
|
|
888
|
+
if (s)
|
|
889
|
+
throw new g(`Failed to find by ids: ${s.message}`);
|
|
890
|
+
return n ?? [];
|
|
871
891
|
})
|
|
872
892
|
));
|
|
873
893
|
}
|
|
@@ -880,22 +900,22 @@ class it extends z {
|
|
|
880
900
|
}
|
|
881
901
|
/** 执行 upsert(非事务) */
|
|
882
902
|
async executeUpsert(t) {
|
|
883
|
-
const e = [],
|
|
884
|
-
for (const [
|
|
885
|
-
const r =
|
|
886
|
-
if (
|
|
887
|
-
throw new
|
|
888
|
-
e.push(...
|
|
903
|
+
const e = [], n = this.rxdb.context.userId;
|
|
904
|
+
for (const [s, a] of t) {
|
|
905
|
+
const r = _(s), o = this.getSchemaClient(r.namespace), c = Array.from(a), d = n ? c.map((p) => ({ ...p, createdBy: n, updatedBy: n })) : c, { data: f, error: u } = await o.from(r.name).upsert(d).select();
|
|
906
|
+
if (u)
|
|
907
|
+
throw new g(`Failed to upsert: ${u.message}`);
|
|
908
|
+
e.push(...f);
|
|
889
909
|
}
|
|
890
910
|
return e;
|
|
891
911
|
}
|
|
892
912
|
/** 执行 delete(非事务) */
|
|
893
913
|
async executeDelete(t) {
|
|
894
914
|
const e = [];
|
|
895
|
-
for (const [
|
|
896
|
-
const a =
|
|
915
|
+
for (const [n, s] of t) {
|
|
916
|
+
const a = _(n), r = this.getSchemaClient(a.namespace), o = Array.from(s), c = o.map((f) => f.id), { error: d } = await r.from(a.name).delete().in("id", c);
|
|
897
917
|
if (d)
|
|
898
|
-
throw new
|
|
918
|
+
throw new g(`Failed to delete: ${d.message}`);
|
|
899
919
|
e.push(...o);
|
|
900
920
|
}
|
|
901
921
|
return e;
|
|
@@ -908,20 +928,20 @@ class it extends z {
|
|
|
908
928
|
* @returns 满足条件的 entityId 列表
|
|
909
929
|
*/
|
|
910
930
|
async #n(t, e) {
|
|
911
|
-
let
|
|
912
|
-
|
|
913
|
-
const { data:
|
|
931
|
+
let n = this.#t.from(t).select("id");
|
|
932
|
+
n = x(n, e);
|
|
933
|
+
const { data: s, error: a } = await n;
|
|
914
934
|
if (a)
|
|
915
|
-
throw new
|
|
916
|
-
return (
|
|
935
|
+
throw new g(`Failed to query filtered entities: ${a.message}`);
|
|
936
|
+
return (s ?? []).map((r) => r.id);
|
|
917
937
|
}
|
|
918
938
|
}
|
|
919
939
|
export {
|
|
920
940
|
tt as ADAPTER_NAME,
|
|
921
941
|
it as RxDBAdapterSupabase,
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
942
|
+
rt as SupabaseConfigError,
|
|
943
|
+
g as SupabaseDataError,
|
|
944
|
+
at as SupabaseNetworkError,
|
|
925
945
|
P as SupabaseRepository,
|
|
926
946
|
S as SupabaseSyncError,
|
|
927
947
|
q as SupabaseTreeRepository
|
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.11",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.js",
|
|
@@ -28,14 +28,14 @@
|
|
|
28
28
|
]
|
|
29
29
|
},
|
|
30
30
|
"peerDependencies": {
|
|
31
|
-
"@supabase/supabase-js": "^2.88.0",
|
|
32
31
|
"@supabase/postgrest-js": "^2.89.0",
|
|
32
|
+
"@supabase/supabase-js": "^2.88.0",
|
|
33
33
|
"rxjs": "^7.8.2",
|
|
34
|
-
"@aiao/rxdb": "0.0.
|
|
34
|
+
"@aiao/rxdb": "0.0.11"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
|
-
"dotenv": "^17.2.
|
|
38
|
-
"@aiao/rxdb-
|
|
39
|
-
"@aiao/rxdb-
|
|
37
|
+
"dotenv": "^17.2.4",
|
|
38
|
+
"@aiao/rxdb-adapter-sqlite": "0.0.11",
|
|
39
|
+
"@aiao/rxdb-test": "0.0.11"
|
|
40
40
|
}
|
|
41
41
|
}
|