@aiao/rxdb-adapter-supabase 0.0.10 → 0.0.12
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,114 +91,114 @@ 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
204
|
case "null":
|
|
@@ -214,15 +214,15 @@ function M(i, t, e, s) {
|
|
|
214
214
|
function T(i) {
|
|
215
215
|
const t = /* @__PURE__ */ new Map();
|
|
216
216
|
for (const e of i) {
|
|
217
|
-
const
|
|
218
|
-
t.has(
|
|
217
|
+
const n = e.constructor;
|
|
218
|
+
t.has(n) || t.set(n, /* @__PURE__ */ new Set()), t.get(n).add(e);
|
|
219
219
|
}
|
|
220
220
|
return t;
|
|
221
221
|
}
|
|
222
222
|
function v(i, t) {
|
|
223
223
|
const e = [];
|
|
224
|
-
for (const [
|
|
225
|
-
const a =
|
|
224
|
+
for (const [n, s] of i) {
|
|
225
|
+
const a = _(n), r = Array.from(s);
|
|
226
226
|
e.push({
|
|
227
227
|
table: a.name,
|
|
228
228
|
schema: a.namespace,
|
|
@@ -233,12 +233,12 @@ function v(i, t) {
|
|
|
233
233
|
}
|
|
234
234
|
function Z(i) {
|
|
235
235
|
const t = [];
|
|
236
|
-
for (const [e,
|
|
237
|
-
const
|
|
236
|
+
for (const [e, n] of i) {
|
|
237
|
+
const s = _(e);
|
|
238
238
|
t.push({
|
|
239
|
-
table:
|
|
240
|
-
schema:
|
|
241
|
-
ids: Array.from(
|
|
239
|
+
table: s.name,
|
|
240
|
+
schema: s.namespace,
|
|
241
|
+
ids: Array.from(n).map((a) => a.id)
|
|
242
242
|
});
|
|
243
243
|
}
|
|
244
244
|
return t;
|
|
@@ -246,36 +246,36 @@ function Z(i) {
|
|
|
246
246
|
function j(i, t) {
|
|
247
247
|
if (i == null) return i;
|
|
248
248
|
switch (t.type) {
|
|
249
|
-
case
|
|
249
|
+
case $.date:
|
|
250
250
|
return i instanceof Date ? i : new Date(i);
|
|
251
|
-
case
|
|
251
|
+
case $.keyValue:
|
|
252
252
|
if (typeof i == "object" && t.properties) {
|
|
253
253
|
const e = {};
|
|
254
|
-
for (const
|
|
255
|
-
i[
|
|
254
|
+
for (const n of t.properties)
|
|
255
|
+
i[n.name] !== void 0 && (e[n.name] = j(i[n.name], n));
|
|
256
256
|
return e;
|
|
257
257
|
}
|
|
258
258
|
return i;
|
|
259
|
-
case
|
|
259
|
+
case $.boolean:
|
|
260
260
|
return !!i;
|
|
261
|
-
case
|
|
262
|
-
case
|
|
263
|
-
case
|
|
261
|
+
case $.json:
|
|
262
|
+
case $.stringArray:
|
|
263
|
+
case $.numberArray:
|
|
264
264
|
default:
|
|
265
265
|
return i;
|
|
266
266
|
}
|
|
267
267
|
}
|
|
268
268
|
function G(i, t, e) {
|
|
269
|
-
const
|
|
270
|
-
for (const
|
|
271
|
-
const a = t.propertyMap.get(
|
|
272
|
-
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];
|
|
273
273
|
}
|
|
274
|
-
return
|
|
274
|
+
return n;
|
|
275
275
|
}
|
|
276
276
|
class P extends K {
|
|
277
277
|
constructor(t, e) {
|
|
278
|
-
super(t.rxdb, e), this.adapter = t, this.metadata =
|
|
278
|
+
super(t.rxdb, e), this.adapter = t, this.metadata = _(e);
|
|
279
279
|
}
|
|
280
280
|
metadata;
|
|
281
281
|
/**
|
|
@@ -283,23 +283,23 @@ class P extends K {
|
|
|
283
283
|
*/
|
|
284
284
|
async find(t) {
|
|
285
285
|
const e = this.extract_relation_fields(t.where);
|
|
286
|
-
let
|
|
286
|
+
let n = "*";
|
|
287
287
|
if (e.size > 0) {
|
|
288
288
|
const o = Array.from(e);
|
|
289
|
-
|
|
290
|
-
(d) => !o.some((
|
|
289
|
+
n = `*, ${o.filter(
|
|
290
|
+
(d) => !o.some((f) => f !== d && f.startsWith(d + "."))
|
|
291
291
|
).map((d) => this.build_relation_select(d)).join(", ")}`;
|
|
292
292
|
}
|
|
293
|
-
let
|
|
294
|
-
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)
|
|
295
295
|
for (const o of t.orderBy)
|
|
296
|
-
|
|
296
|
+
s = s.order(o.field, { ascending: o.sort === "asc" });
|
|
297
297
|
if (t.offset !== void 0) {
|
|
298
298
|
const o = t.offset, c = t.limit !== void 0 ? o + t.limit - 1 : Number.MAX_SAFE_INTEGER;
|
|
299
|
-
|
|
300
|
-
} else t.limit !== void 0 && (
|
|
301
|
-
const { data: a, error: r } = await
|
|
302
|
-
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}`);
|
|
303
303
|
return (a || []).map((o) => G(this.EntityType, this.metadata, o));
|
|
304
304
|
}
|
|
305
305
|
/**
|
|
@@ -308,15 +308,15 @@ class P extends K {
|
|
|
308
308
|
async count(t) {
|
|
309
309
|
if (t.groupBy) throw new Error("groupBy not supported yet");
|
|
310
310
|
const e = this.extract_relation_fields(t.where);
|
|
311
|
-
let
|
|
312
|
-
e.size > 0 && (
|
|
313
|
-
let
|
|
314
|
-
|
|
315
|
-
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;
|
|
316
316
|
if (r) {
|
|
317
317
|
if (!r.message)
|
|
318
318
|
return console.warn("Supabase count returned empty error, returning 0. Options:", JSON.stringify(t)), 0;
|
|
319
|
-
throw new
|
|
319
|
+
throw new g(`Failed to count entities: ${r.message}`);
|
|
320
320
|
}
|
|
321
321
|
return a ?? 0;
|
|
322
322
|
}
|
|
@@ -324,19 +324,19 @@ class P extends K {
|
|
|
324
324
|
* 创建实体
|
|
325
325
|
*/
|
|
326
326
|
async create(t) {
|
|
327
|
-
const e = { ...t },
|
|
328
|
-
|
|
329
|
-
const { data:
|
|
330
|
-
if (a) throw new
|
|
331
|
-
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;
|
|
332
332
|
}
|
|
333
333
|
/**
|
|
334
334
|
* 更新实体
|
|
335
335
|
*/
|
|
336
336
|
async update(t, e) {
|
|
337
|
-
const { data:
|
|
338
|
-
if (
|
|
339
|
-
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;
|
|
340
340
|
}
|
|
341
341
|
/**
|
|
342
342
|
* 删除实体
|
|
@@ -345,7 +345,7 @@ class P extends K {
|
|
|
345
345
|
*/
|
|
346
346
|
async remove(t) {
|
|
347
347
|
const { error: e } = await this.get_client().delete().eq("id", t.id);
|
|
348
|
-
if (e) throw new
|
|
348
|
+
if (e) throw new g(`Failed to remove entity: ${e.message}`);
|
|
349
349
|
return t;
|
|
350
350
|
}
|
|
351
351
|
// ============================================
|
|
@@ -353,11 +353,11 @@ class P extends K {
|
|
|
353
353
|
// ============================================
|
|
354
354
|
/** 提取查询中的关系字段路径(用于 EXISTS 查询的 INNER JOIN) */
|
|
355
355
|
extract_relation_fields(t) {
|
|
356
|
-
const e = /* @__PURE__ */ new Set(),
|
|
357
|
-
if (
|
|
358
|
-
for (const r of
|
|
356
|
+
const e = /* @__PURE__ */ new Set(), n = (s, a = "") => {
|
|
357
|
+
if (s?.rules) {
|
|
358
|
+
for (const r of s.rules)
|
|
359
359
|
if (r.rules)
|
|
360
|
-
|
|
360
|
+
n(r, a);
|
|
361
361
|
else if (typeof r.field == "string" && r.field.includes(".")) {
|
|
362
362
|
const o = r.field.split(".");
|
|
363
363
|
for (let c = 1; c < o.length; c++) {
|
|
@@ -366,11 +366,11 @@ class P extends K {
|
|
|
366
366
|
}
|
|
367
367
|
} else if (r.operator === "exists" || r.operator === "notExists") {
|
|
368
368
|
const o = String(r.field), c = a ? `${a}.${o}` : o;
|
|
369
|
-
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);
|
|
370
370
|
}
|
|
371
371
|
}
|
|
372
372
|
};
|
|
373
|
-
return
|
|
373
|
+
return n(t), e;
|
|
374
374
|
}
|
|
375
375
|
/**
|
|
376
376
|
* 构建关系字段的 SELECT 语法
|
|
@@ -379,18 +379,18 @@ class P extends K {
|
|
|
379
379
|
build_relation_select(t) {
|
|
380
380
|
const e = t.split(".");
|
|
381
381
|
if (e.length === 1) return this.build_single_relation_select(e[0]);
|
|
382
|
-
const
|
|
383
|
-
let
|
|
382
|
+
const n = [];
|
|
383
|
+
let s = this.metadata;
|
|
384
384
|
for (const r of e) {
|
|
385
|
-
const o =
|
|
385
|
+
const o = s.relationMap?.get(r);
|
|
386
386
|
if (!o) return `${r}(id)`;
|
|
387
|
-
|
|
387
|
+
n.push({ tableName: o.mappedEntity, kind: o.kind, sourceEntity: s.name });
|
|
388
388
|
const c = this.adapter.rxdb.schemaManager.getEntityMetadata(o.mappedEntity, o.mappedNamespace ?? "");
|
|
389
|
-
c && (
|
|
389
|
+
c && (s = c);
|
|
390
390
|
}
|
|
391
|
-
let a = this.build_relation_segment(
|
|
392
|
-
for (let r =
|
|
393
|
-
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})`);
|
|
394
394
|
return a;
|
|
395
395
|
}
|
|
396
396
|
/**
|
|
@@ -400,25 +400,25 @@ class P extends K {
|
|
|
400
400
|
build_single_relation_select(t) {
|
|
401
401
|
const e = this.metadata.relationMap?.get(t);
|
|
402
402
|
if (!e) return `${t}(id)`;
|
|
403
|
-
const
|
|
403
|
+
const n = e.mappedEntity, s = this.metadata.name;
|
|
404
404
|
if (e.kind === "m:1" || e.kind === "1:1") {
|
|
405
|
-
const a = `${
|
|
406
|
-
return `${
|
|
405
|
+
const a = `${s}_${t}Id_fkey`;
|
|
406
|
+
return `${n}!${a}(*)`;
|
|
407
407
|
}
|
|
408
408
|
if (e.kind === "m:n") {
|
|
409
|
-
const a = this.get_join_table_name(
|
|
410
|
-
return `${
|
|
409
|
+
const a = this.get_join_table_name(s, n);
|
|
410
|
+
return `${n}!${a}(*)`;
|
|
411
411
|
}
|
|
412
|
-
return `${
|
|
412
|
+
return `${n}(*)`;
|
|
413
413
|
}
|
|
414
414
|
/** 构建关系 SELECT 片段 */
|
|
415
415
|
build_relation_segment(t, e) {
|
|
416
|
-
const
|
|
416
|
+
const n = e ? "!inner" : "";
|
|
417
417
|
if (t.kind === "m:n") {
|
|
418
|
-
const
|
|
419
|
-
return `${t.tableName}!${
|
|
418
|
+
const s = this.get_join_table_name(t.sourceEntity, t.tableName);
|
|
419
|
+
return `${t.tableName}!${s}${n}(*)`;
|
|
420
420
|
}
|
|
421
|
-
return `${t.tableName}${
|
|
421
|
+
return `${t.tableName}${n}(*)`;
|
|
422
422
|
}
|
|
423
423
|
/** 获取 m:n 中间表名(按字母顺序) */
|
|
424
424
|
get_join_table_name(t, e) {
|
|
@@ -441,16 +441,16 @@ class q extends P {
|
|
|
441
441
|
* - 不指定 entityId 时:返回所有根节点及其子孙
|
|
442
442
|
*/
|
|
443
443
|
async findDescendants(t) {
|
|
444
|
-
const { entityId: e, level:
|
|
444
|
+
const { entityId: e, level: n = 100 } = t, { data: s, error: a } = await this.adapter.client.rpc(
|
|
445
445
|
e ? "get_descendants" : "get_root_descendants",
|
|
446
|
-
e ? { root_id: e, max_level:
|
|
446
|
+
e ? { root_id: e, max_level: n } : { max_level: n }
|
|
447
447
|
);
|
|
448
448
|
if (a) {
|
|
449
449
|
if (a.message.includes("function") || a.message.includes("Could not find"))
|
|
450
450
|
return this.findDescendantsFallback(t);
|
|
451
|
-
throw new
|
|
451
|
+
throw new g(`Failed to find descendants: ${a.message}`);
|
|
452
452
|
}
|
|
453
|
-
return (
|
|
453
|
+
return (s || []).map((r) => this.transformRowToEntity(r));
|
|
454
454
|
}
|
|
455
455
|
/**
|
|
456
456
|
* 查询子孙节点数量
|
|
@@ -460,8 +460,8 @@ class q extends P {
|
|
|
460
460
|
* - 不指定 entityId 时:统计所有根节点及其后代的总数
|
|
461
461
|
*/
|
|
462
462
|
async countDescendants(t) {
|
|
463
|
-
const { entityId: e } = t,
|
|
464
|
-
return e ?
|
|
463
|
+
const { entityId: e } = t, n = await this.findDescendants(t);
|
|
464
|
+
return e ? n.length - 1 : n.length;
|
|
465
465
|
}
|
|
466
466
|
/**
|
|
467
467
|
* 查询祖先节点
|
|
@@ -470,19 +470,19 @@ class q extends P {
|
|
|
470
470
|
* 指定 entityId 时:包含当前节点 + 祖先节点
|
|
471
471
|
*/
|
|
472
472
|
async findAncestors(t) {
|
|
473
|
-
const { entityId: e, level:
|
|
473
|
+
const { entityId: e, level: n = 100 } = t;
|
|
474
474
|
if (!e)
|
|
475
475
|
return [];
|
|
476
|
-
const { data:
|
|
476
|
+
const { data: s, error: a } = await this.adapter.client.rpc("get_ancestors", {
|
|
477
477
|
node_id: e,
|
|
478
|
-
max_level:
|
|
478
|
+
max_level: n
|
|
479
479
|
});
|
|
480
480
|
if (a) {
|
|
481
481
|
if (a.message.includes("function") || a.message.includes("Could not find"))
|
|
482
482
|
return this.findAncestorsFallback(t);
|
|
483
|
-
throw new
|
|
483
|
+
throw new g(`Failed to find ancestors: ${a.message}`);
|
|
484
484
|
}
|
|
485
|
-
return (
|
|
485
|
+
return (s || []).map((r) => this.transformRowToEntity(r));
|
|
486
486
|
}
|
|
487
487
|
/**
|
|
488
488
|
* 查询祖先节点数量
|
|
@@ -496,67 +496,85 @@ class q extends P {
|
|
|
496
496
|
}
|
|
497
497
|
/**
|
|
498
498
|
* 备用的子孙节点查询(不使用存储函数)
|
|
499
|
-
* 仅支持简单的层级查询
|
|
500
499
|
*
|
|
501
|
-
*
|
|
502
|
-
* 优化方案:一次查询获取所有节点,在内存中构建树结构。
|
|
500
|
+
* 一次查询获取所有节点,在内存中构建树结构,避免 N+1 问题。
|
|
503
501
|
*/
|
|
504
502
|
async findDescendantsFallback(t) {
|
|
505
|
-
const { entityId: e, level:
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
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;
|
|
524
529
|
}
|
|
525
|
-
|
|
526
|
-
|
|
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;
|
|
527
537
|
}
|
|
528
538
|
/**
|
|
529
539
|
* 备用的祖先节点查询(不使用存储函数)
|
|
530
540
|
*
|
|
531
|
-
*
|
|
532
|
-
* 优化方案:一次查询获取所有节点,在内存中向上遍历。
|
|
541
|
+
* 一次查询获取所有节点,在内存中向上遍历,避免 N+1 问题。
|
|
533
542
|
*/
|
|
534
543
|
async findAncestorsFallback(t) {
|
|
535
|
-
const { entityId: e, level:
|
|
544
|
+
const { entityId: e, level: n = 100 } = t;
|
|
536
545
|
if (!e)
|
|
537
546
|
return [];
|
|
538
|
-
const
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
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);
|
|
545
563
|
if (a) {
|
|
546
|
-
const
|
|
547
|
-
|
|
564
|
+
const m = d.get(h.id);
|
|
565
|
+
l.hasChildren = !!m && m.length > 0;
|
|
548
566
|
}
|
|
549
|
-
|
|
567
|
+
f.push(l), u = h.parentId ?? null, p++;
|
|
550
568
|
}
|
|
551
|
-
return
|
|
569
|
+
return f;
|
|
552
570
|
}
|
|
553
571
|
/**
|
|
554
572
|
* 将数据库行转换为实体
|
|
555
573
|
*/
|
|
556
574
|
transformRowToEntity(t) {
|
|
557
575
|
const e = new this.EntityType();
|
|
558
|
-
return Object.keys(t).forEach((
|
|
559
|
-
|
|
576
|
+
return Object.keys(t).forEach((n) => {
|
|
577
|
+
n !== "level" && (e[n] = t[n]);
|
|
560
578
|
}), e;
|
|
561
579
|
}
|
|
562
580
|
}
|
|
@@ -611,12 +629,12 @@ class it extends z {
|
|
|
611
629
|
* 在单个数据库事务中执行所有操作,确保原子性。
|
|
612
630
|
*/
|
|
613
631
|
async mutations(t) {
|
|
614
|
-
const e = this.rxdb.context.userId,
|
|
615
|
-
p_upserts:
|
|
616
|
-
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
|
|
617
635
|
});
|
|
618
636
|
if (r)
|
|
619
|
-
throw new
|
|
637
|
+
throw new g(`Transaction failed: ${r.message}`);
|
|
620
638
|
const o = a?.upserted ?? [];
|
|
621
639
|
for (const [, c] of t.remove)
|
|
622
640
|
o.push(...c);
|
|
@@ -628,18 +646,18 @@ class it extends z {
|
|
|
628
646
|
getRepository(t) {
|
|
629
647
|
if (this.repository_cache.has(t))
|
|
630
648
|
return this.repository_cache.get(t);
|
|
631
|
-
const
|
|
632
|
-
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;
|
|
633
651
|
}
|
|
634
652
|
// ============================================
|
|
635
653
|
// 工具方法
|
|
636
654
|
// ============================================
|
|
637
655
|
async isTableExisted(t) {
|
|
638
|
-
const e =
|
|
639
|
-
if (
|
|
640
|
-
if (
|
|
641
|
-
throw new
|
|
642
|
-
`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}`}`
|
|
643
661
|
);
|
|
644
662
|
}
|
|
645
663
|
// ============================================
|
|
@@ -660,25 +678,25 @@ class it extends z {
|
|
|
660
678
|
* 当提供 filter 参数时,会通过 JOIN 实体表并应用过滤条件,
|
|
661
679
|
* 只返回满足条件的实体对应的变更记录。
|
|
662
680
|
*/
|
|
663
|
-
async pullChanges(t, e = 1e3,
|
|
681
|
+
async pullChanges(t, e = 1e3, n, s) {
|
|
664
682
|
const a = [];
|
|
665
683
|
let r;
|
|
666
|
-
if (
|
|
667
|
-
const
|
|
668
|
-
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)
|
|
669
687
|
return [];
|
|
670
688
|
}
|
|
671
689
|
let o = this.#t.from("RxDBChange").select("*").gt("id", t).order("id", { ascending: !0 }).limit(e);
|
|
672
|
-
|
|
690
|
+
n && n.length > 0 && (o = o.in("entity", n)), r && (o = o.in("entityId", r));
|
|
673
691
|
const { data: c, error: d } = await o;
|
|
674
692
|
if (d)
|
|
675
|
-
throw new
|
|
676
|
-
const
|
|
677
|
-
...
|
|
678
|
-
createdAt: new Date(
|
|
679
|
-
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
|
|
680
698
|
}));
|
|
681
|
-
return a.push(...
|
|
699
|
+
return a.push(...f), a;
|
|
682
700
|
}
|
|
683
701
|
/**
|
|
684
702
|
* 获取远程变更数量(轻量级,不下载数据)(T042, US2)
|
|
@@ -698,22 +716,22 @@ class it extends z {
|
|
|
698
716
|
* ```
|
|
699
717
|
*/
|
|
700
718
|
async getChangeCount(t, e) {
|
|
701
|
-
let
|
|
702
|
-
e && e.length > 0 && (
|
|
703
|
-
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;
|
|
704
722
|
if (a)
|
|
705
|
-
throw new
|
|
723
|
+
throw new g(`Failed to get change count: ${a.message}`);
|
|
706
724
|
let r = t;
|
|
707
|
-
if (
|
|
725
|
+
if (s && s > 0) {
|
|
708
726
|
let o = this.#t.from("RxDBChange").select("id").gt("id", t).order("id", { ascending: !1 }).limit(1);
|
|
709
727
|
e && e.length > 0 && (o = o.in("entity", e));
|
|
710
728
|
const { data: c, error: d } = await o;
|
|
711
729
|
if (d)
|
|
712
|
-
throw new
|
|
730
|
+
throw new g(`Failed to get latest changeId: ${d.message}`);
|
|
713
731
|
c && c.length > 0 && (r = c[0].id);
|
|
714
732
|
}
|
|
715
733
|
return {
|
|
716
|
-
count:
|
|
734
|
+
count: s ?? 0,
|
|
717
735
|
latestChangeId: r
|
|
718
736
|
};
|
|
719
737
|
}
|
|
@@ -731,18 +749,18 @@ class it extends z {
|
|
|
731
749
|
updates: /* @__PURE__ */ new Map(),
|
|
732
750
|
deletes: /* @__PURE__ */ new Map()
|
|
733
751
|
};
|
|
734
|
-
for (const
|
|
735
|
-
const { entityKey:
|
|
752
|
+
for (const n of t) {
|
|
753
|
+
const { entityKey: s, finalType: a, finalPatch: r, inversePatch: o } = n;
|
|
736
754
|
if (a)
|
|
737
755
|
switch (a) {
|
|
738
756
|
case "INSERT":
|
|
739
|
-
e.inserts.set(
|
|
757
|
+
e.inserts.set(s, { patch: r, inversePatch: o });
|
|
740
758
|
break;
|
|
741
759
|
case "UPDATE":
|
|
742
|
-
e.updates.set(
|
|
760
|
+
e.updates.set(s, { patch: r, inversePatch: o });
|
|
743
761
|
break;
|
|
744
762
|
case "DELETE":
|
|
745
|
-
e.deletes.set(
|
|
763
|
+
e.deletes.set(s, { patch: null, inversePatch: o });
|
|
746
764
|
break;
|
|
747
765
|
}
|
|
748
766
|
}
|
|
@@ -759,13 +777,13 @@ class it extends z {
|
|
|
759
777
|
* @param actions - 压缩后的变更操作集合
|
|
760
778
|
*/
|
|
761
779
|
async mergeChanges(t) {
|
|
762
|
-
const e = (/* @__PURE__ */ new Date()).toISOString(),
|
|
763
|
-
for (const [
|
|
764
|
-
const [
|
|
765
|
-
|
|
766
|
-
namespace:
|
|
767
|
-
entity:
|
|
768
|
-
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,
|
|
769
787
|
type: "DELETE",
|
|
770
788
|
patch: null,
|
|
771
789
|
inversePatch: p,
|
|
@@ -773,55 +791,55 @@ class it extends z {
|
|
|
773
791
|
createdAt: e,
|
|
774
792
|
updatedAt: e
|
|
775
793
|
});
|
|
776
|
-
const
|
|
777
|
-
|
|
794
|
+
const y = r.get(w) ?? [];
|
|
795
|
+
y.push(m), r.set(w, y);
|
|
778
796
|
}
|
|
779
|
-
for (const [
|
|
780
|
-
const [
|
|
781
|
-
|
|
782
|
-
namespace:
|
|
783
|
-
entity:
|
|
784
|
-
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,
|
|
785
803
|
type: "UPDATE",
|
|
786
804
|
patch: p,
|
|
787
|
-
inversePatch:
|
|
805
|
+
inversePatch: h,
|
|
788
806
|
clientId: this.rxdb.context.clientId,
|
|
789
807
|
createdAt: e,
|
|
790
808
|
updatedAt: e
|
|
791
809
|
});
|
|
792
|
-
const
|
|
793
|
-
|
|
810
|
+
const b = a.get(y) ?? [], E = { id: w, ...p };
|
|
811
|
+
n && (E.updatedBy = n), b.push(E), a.set(y, b);
|
|
794
812
|
}
|
|
795
|
-
for (const [
|
|
796
|
-
const [
|
|
797
|
-
|
|
798
|
-
namespace:
|
|
799
|
-
entity:
|
|
800
|
-
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,
|
|
801
819
|
type: "INSERT",
|
|
802
820
|
patch: p,
|
|
803
|
-
inversePatch:
|
|
821
|
+
inversePatch: h,
|
|
804
822
|
clientId: this.rxdb.context.clientId,
|
|
805
823
|
createdAt: e,
|
|
806
824
|
updatedAt: e
|
|
807
825
|
});
|
|
808
|
-
const
|
|
809
|
-
|
|
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);
|
|
810
828
|
}
|
|
811
|
-
const o = Array.from(a.entries()).map(([
|
|
812
|
-
const [
|
|
813
|
-
return { table:
|
|
814
|
-
}), c = Array.from(r.entries()).map(([
|
|
815
|
-
const [
|
|
816
|
-
return { table:
|
|
817
|
-
}), { 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", {
|
|
818
836
|
p_upserts: o,
|
|
819
837
|
p_deletes: c,
|
|
820
|
-
p_changes:
|
|
838
|
+
p_changes: s,
|
|
821
839
|
p_skip_sync: !0
|
|
822
840
|
});
|
|
823
|
-
if (
|
|
824
|
-
throw new
|
|
841
|
+
if (f)
|
|
842
|
+
throw new g(`Failed to merge changes: ${f.message}`);
|
|
825
843
|
return d?.max_change_id ?? void 0;
|
|
826
844
|
}
|
|
827
845
|
// ============================================
|
|
@@ -844,12 +862,12 @@ class it extends z {
|
|
|
844
862
|
*/
|
|
845
863
|
fetchMetadata(t, e) {
|
|
846
864
|
return D(() => {
|
|
847
|
-
let
|
|
848
|
-
return
|
|
849
|
-
|
|
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 }) => {
|
|
850
868
|
if (a)
|
|
851
|
-
throw new
|
|
852
|
-
return (
|
|
869
|
+
throw new g(`Failed to fetch metadata: ${a.message}`);
|
|
870
|
+
return (s ?? []).map((r) => ({
|
|
853
871
|
id: r.id,
|
|
854
872
|
updatedAt: r.updatedAt
|
|
855
873
|
}));
|
|
@@ -865,11 +883,11 @@ class it extends z {
|
|
|
865
883
|
* @returns Observable<T[]>
|
|
866
884
|
*/
|
|
867
885
|
findByIds(t, e) {
|
|
868
|
-
return D(() => e.length === 0 ? Q([]) :
|
|
869
|
-
|
|
870
|
-
if (
|
|
871
|
-
throw new
|
|
872
|
-
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 ?? [];
|
|
873
891
|
})
|
|
874
892
|
));
|
|
875
893
|
}
|
|
@@ -882,22 +900,22 @@ class it extends z {
|
|
|
882
900
|
}
|
|
883
901
|
/** 执行 upsert(非事务) */
|
|
884
902
|
async executeUpsert(t) {
|
|
885
|
-
const e = [],
|
|
886
|
-
for (const [
|
|
887
|
-
const r =
|
|
888
|
-
if (
|
|
889
|
-
throw new
|
|
890
|
-
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);
|
|
891
909
|
}
|
|
892
910
|
return e;
|
|
893
911
|
}
|
|
894
912
|
/** 执行 delete(非事务) */
|
|
895
913
|
async executeDelete(t) {
|
|
896
914
|
const e = [];
|
|
897
|
-
for (const [
|
|
898
|
-
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);
|
|
899
917
|
if (d)
|
|
900
|
-
throw new
|
|
918
|
+
throw new g(`Failed to delete: ${d.message}`);
|
|
901
919
|
e.push(...o);
|
|
902
920
|
}
|
|
903
921
|
return e;
|
|
@@ -910,20 +928,20 @@ class it extends z {
|
|
|
910
928
|
* @returns 满足条件的 entityId 列表
|
|
911
929
|
*/
|
|
912
930
|
async #n(t, e) {
|
|
913
|
-
let
|
|
914
|
-
|
|
915
|
-
const { data:
|
|
931
|
+
let n = this.#t.from(t).select("id");
|
|
932
|
+
n = x(n, e);
|
|
933
|
+
const { data: s, error: a } = await n;
|
|
916
934
|
if (a)
|
|
917
|
-
throw new
|
|
918
|
-
return (
|
|
935
|
+
throw new g(`Failed to query filtered entities: ${a.message}`);
|
|
936
|
+
return (s ?? []).map((r) => r.id);
|
|
919
937
|
}
|
|
920
938
|
}
|
|
921
939
|
export {
|
|
922
940
|
tt as ADAPTER_NAME,
|
|
923
941
|
it as RxDBAdapterSupabase,
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
942
|
+
rt as SupabaseConfigError,
|
|
943
|
+
g as SupabaseDataError,
|
|
944
|
+
at as SupabaseNetworkError,
|
|
927
945
|
P as SupabaseRepository,
|
|
928
946
|
S as SupabaseSyncError,
|
|
929
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.12",
|
|
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.12"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
|
-
"dotenv": "^17.
|
|
38
|
-
"@aiao/rxdb-
|
|
39
|
-
"@aiao/rxdb-
|
|
37
|
+
"dotenv": "^17.3.1",
|
|
38
|
+
"@aiao/rxdb-test": "0.0.12",
|
|
39
|
+
"@aiao/rxdb-adapter-sqlite": "0.0.12"
|
|
40
40
|
}
|
|
41
41
|
}
|