@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;AAI3F,OAAO,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AAIjE,eAAO,MAAM,YAAY,aAAa,CAAC;AAEvC;;;;;;;;;;;;;;GAcG;AACH,qBAAa,mBAAoB,SAAQ,qBAAsB,YAAW,YAAY;;IAWlF,QAAQ,CAAC,OAAO,EAAE,sBAAsB;IAR1C,QAAQ,CAAC,IAAI,cAAgB;IAE7B,IAAI,MAAM,IAAI,cAAc,CAE3B;gBAGC,IAAI,EAAE,IAAI,EACD,OAAO,EAAE,sBAAsB;IAUpC,OAAO,IAAI,OAAO,CAAC,YAAY,CAAC;IAiBhC,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAO3B,OAAO,IAAI,OAAO,CAAC,MAAM,CAAC;IAQhC;;OAEG;IACG,QAAQ,CAAC,CAAC,SAAS,UAAU,EAAE,QAAQ,EAAE,YAAY,CAAC,CAAC,CAAC,EAAE,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC;IAK7F;;OAEG;IACG,UAAU,CAAC,CAAC,SAAS,UAAU,EAAE,QAAQ,EAAE,YAAY,CAAC,CAAC,CAAC,EAAE,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC;IAK/F;;;;;OAKG;IACG,SAAS,CAAC,CAAC,SAAS,UAAU,EAAE,OAAO,EAAE,gBAAgB,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC;IA+B/F,aAAa,CAAC,CAAC,SAAS,UAAU,EAAE,EAAE,SAAS,WAAW,CAAC,CAAC,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,GAAG,EAAE;IAmB5F,cAAc,CAAC,UAAU,EAAE,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC;IAiB9D;;;;;;;;;;OAUG;IACG,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,GAAE,MAAa,EAAE,gBAAgB,CAAC,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;IAmC9G;;;;;;;;;;;;;;;;OAgBG;IACG,cAAc,CAClB,OAAO,EAAE,MAAM,EACf,gBAAgB,CAAC,EAAE,MAAM,EAAE,GAC1B,OAAO,CAAC;QACT,KAAK,EAAE,MAAM,CAAC;QACd,cAAc,EAAE,MAAM,CAAC;KACxB,CAAC;IAmDF;;;;;;OAMG;IACG,WAAW,CAAC,OAAO,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IA8BhD;;;;;;;;;OASG;IACG,YAAY,CAAC,OAAO,EAAE,oBAAoB;IAyHhD,sBAAsB;IACtB,OAAO,CAAC,eAAe;IAIvB,qBAAqB;YACP,aAAa;IA0B3B,qBAAqB;YACP,aAAa;CAqB5B"}
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,wBAAwB,EACxB,YAAY,EACZ,SAAS,EACT,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;AAC3F,OAAO,EAAoB,UAAU,EAAM,MAAM,MAAM,CAAC;AAKxD,OAAO,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AAIjE,eAAO,MAAM,YAAY,aAAa,CAAC;AAEvC;;;;;;;;;;;;;;GAcG;AACH,qBAAa,mBAAoB,SAAQ,qBAAsB,YAAW,YAAY;;IAWlF,QAAQ,CAAC,OAAO,EAAE,sBAAsB;IAR1C,QAAQ,CAAC,IAAI,cAAgB;IAE7B,IAAI,MAAM,IAAI,cAAc,CAE3B;gBAGC,IAAI,EAAE,IAAI,EACD,OAAO,EAAE,sBAAsB;IAUpC,OAAO,IAAI,OAAO,CAAC,YAAY,CAAC;IAiBhC,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAO3B,OAAO,IAAI,OAAO,CAAC,MAAM,CAAC;IAQhC;;OAEG;IACG,QAAQ,CAAC,CAAC,SAAS,UAAU,EAAE,QAAQ,EAAE,YAAY,CAAC,CAAC,CAAC,EAAE,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC;IAK7F;;OAEG;IACG,UAAU,CAAC,CAAC,SAAS,UAAU,EAAE,QAAQ,EAAE,YAAY,CAAC,CAAC,CAAC,EAAE,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC;IAK/F;;;;;OAKG;IACG,SAAS,CAAC,CAAC,SAAS,UAAU,EAAE,OAAO,EAAE,gBAAgB,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC;IA+B/F,aAAa,CAAC,CAAC,SAAS,UAAU,EAAE,EAAE,SAAS,WAAW,CAAC,CAAC,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,GAAG,EAAE;IAmB5F,cAAc,CAAC,UAAU,EAAE,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC;IAiB9D;;;;;;;;;;;;;;OAcG;IACG,WAAW,CACf,OAAO,EAAE,MAAM,EACf,KAAK,GAAE,MAAa,EACpB,gBAAgB,CAAC,EAAE,MAAM,EAAE,EAC3B,MAAM,CAAC,EAAE,SAAS,CAAC,GAAG,CAAC,GACtB,OAAO,CAAC,YAAY,EAAE,CAAC;IAoD1B;;;;;;;;;;;;;;;;OAgBG;IACG,cAAc,CAClB,OAAO,EAAE,MAAM,EACf,gBAAgB,CAAC,EAAE,MAAM,EAAE,GAC1B,OAAO,CAAC;QACT,KAAK,EAAE,MAAM,CAAC;QACd,cAAc,EAAE,MAAM,CAAC;KACxB,CAAC;IAmDF;;;;;;OAMG;IACG,WAAW,CAAC,OAAO,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IA8BhD;;;;;;;;;OASG;IACG,YAAY,CAAC,OAAO,EAAE,oBAAoB;IAyHhD;;;;;;;;;;;;;;OAcG;IACH,aAAa,CAAC,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,SAAS,CAAC,OAAO,CAAC,GAAG,UAAU,CAAC,wBAAwB,EAAE,CAAC;IAmB1G;;;;;;OAMG;IACH,SAAS,CAAC,CAAC,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,UAAU,CAAC,CAAC,EAAE,CAAC;IAoBhE,sBAAsB;IACtB,OAAO,CAAC,eAAe;IAIvB,qBAAqB;YACP,aAAa;IA0B3B,qBAAqB;YACP,aAAa;CA4C5B"}
@@ -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;AAGjF,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAGpE;;;GAGG;AACH,qBAAa,kBAAkB,CAAC,CAAC,SAAS,UAAU,CAAE,SAAQ,cAAc,CAAC,CAAC,CAAE,YAAW,WAAW,CAAC,CAAC,CAAC;IAIrG,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAE,mBAAmB;IAHjD,SAAS,CAAC,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAC;gBAGvB,OAAO,EAAE,mBAAmB,EAC/C,UAAU,EAAE,CAAC;IAMf;;OAEG;IACG,IAAI,CAAC,OAAO,EAAE,gBAAgB,CAAC,CAAC,EAAE,aAAa,CAAC,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC;IAsCnF;;OAEG;IACG,KAAK,CAAC,OAAO,EAAE,gBAAgB,CAAC,CAAC,EAAE,cAAc,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC;IA2B1E;;OAEG;IACG,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAW/D;;OAEG;IACG,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAMhG;;;;OAIG;IACG,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAU/D,6CAA6C;IAC7C,OAAO,CAAC,uBAAuB;IAgC/B;;;OAGG;IACH,OAAO,CAAC,qBAAqB;IA2B7B;;;OAGG;IACH,OAAO,CAAC,4BAA4B;IAuBpC,qBAAqB;IACrB,OAAO,CAAC,sBAAsB;IAY9B,yBAAyB;IACzB,OAAO,CAAC,mBAAmB;IAI3B,0BAA0B;IAC1B,OAAO,CAAC,UAAU;CAGnB"}
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 M, EntityRemoteUpdatedEvent as j, EntityRemoteCreatedEvent as O, getEntityMetadata as b, isRuleGroup as x, PropertyType as E, RepositoryBase as W, RxDBAdapterRemoteBase as U } from "@aiao/rxdb";
2
- import { createClient as K } from "@supabase/supabase-js";
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 q extends S {
9
+ class at extends S {
9
10
  constructor(t) {
10
11
  super(t, "CONFIG_ERROR"), this.name = "SupabaseConfigError";
11
12
  }
12
13
  }
13
- class tt extends S {
14
+ class rt extends S {
14
15
  constructor(t) {
15
16
  super(t, "NETWORK_ERROR"), this.name = "SupabaseNetworkError";
16
17
  }
17
18
  }
18
- class g extends S {
19
+ class m extends S {
19
20
  constructor(t) {
20
21
  super(t, "DATA_ERROR"), this.name = "SupabaseDataError";
21
22
  }
22
23
  }
23
- const z = {
24
- INSERT: O,
25
- UPDATE: j,
26
- DELETE: M
24
+ const V = {
25
+ INSERT: U,
26
+ UPDATE: W,
27
+ DELETE: O
27
28
  };
28
- function L(r, t) {
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: i, patch: c, clientId: o } = e, l = r.rxdb.context.clientId;
33
- if (o && l && o === l || !a || !i) return;
34
- const p = z[i];
35
- if (!p) return;
36
- const d = { id: a, ...c };
37
- r.rxdb.dispatchEvent(
38
- new p([
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: i,
41
+ type: r,
41
42
  namespace: s || "public",
42
43
  entity: n,
43
44
  id: a,
44
- data: d,
45
+ data: l,
45
46
  recordAt: e.createdAt ? new Date(e.createdAt) : /* @__PURE__ */ new Date()
46
47
  }
47
48
  ])
48
49
  );
49
50
  }
50
- function D(r) {
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(r) {
96
- return r instanceof Date ? r.toISOString() : Array.isArray(r) ? r.map(C) : r;
64
+ function C(i) {
65
+ return i instanceof Date ? i.toISOString() : Array.isArray(i) ? i.map(C) : i;
97
66
  }
98
- function T(r, t, e) {
99
- return !t || !r.mappedEntity ? e : t.getEntityMetadata(r.mappedEntity, r.mappedNamespace ?? "") ?? e;
67
+ function B(i, t, e) {
68
+ return !t || !i.mappedEntity ? e : t.getEntityMetadata(i.mappedEntity, i.mappedNamespace ?? "") ?? e;
100
69
  }
101
- function N(r, t) {
70
+ function H(i, t) {
102
71
  const e = C(t);
103
- switch (r) {
72
+ switch (i) {
104
73
  case "=":
105
74
  case "!=":
106
75
  case "<":
107
76
  case "<=":
108
77
  case ">":
109
78
  case ">=":
110
- return `${V[r]}.${e}`;
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: ${r}`);
91
+ throw new Error(`Unsupported operator: ${i}`);
123
92
  }
124
93
  }
125
- function v(r, t, e) {
126
- const [s, ...n] = r.split(".");
127
- return n.length === 0 ? { field: r, operator: t, value: e } : {
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: [v(n.join("."), t, e)] }
99
+ where: { combinator: "and", rules: [F(n.join("."), t, e)] }
131
100
  };
132
101
  }
133
- function A(r, t, e, s) {
134
- if (!t?.rules?.length) return r;
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 x(a) ? A(r, a, e, s) : R(r, a, e, s);
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, i) => x(i) ? A(a, i, e, s) : R(a, i, e, s),
142
- r
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 (x(a)) throw new Error("Nested OR conditions not supported");
146
- const { field: i, operator: c, value: o } = a;
147
- return `${i}.${N(c, o)}`;
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 r.or(n.join(","));
118
+ return i.or(n.join(","));
150
119
  }
151
- function R(r, t, e, s) {
152
- const { field: n, operator: a, value: i } = t;
153
- return typeof n == "string" && n.includes(".") ? R(r, v(n, a, i), e, s) : a === "exists" || a === "notExists" ? J(r, t, e, s) : B(r, n, a, i);
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 J(r, t, e, s) {
156
- const { field: n, operator: a } = t, i = t.where, c = String(n), o = e?.relationMap?.get(c);
157
- if (!o)
158
- throw new Error(`Relation '${c}' not found in '${e?.name || "unknown"}'`);
159
- const l = o.mappedEntity;
160
- if (!i?.rules?.length)
161
- return a === "exists" ? r.not(l, "is", null) : r.is(l, null);
162
- const p = e ? T(o, s, e) : void 0;
163
- if (!p) throw new Error(`Cannot resolve metadata for '${c}'`);
164
- return I(r, l, i, p, s, l);
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 I(r, t, e, s, n, a = "") {
167
- if (!e?.rules?.length) return r;
168
- let i = r;
169
- for (const c of e.rules) {
170
- if (x(c)) {
171
- i = I(i, t, c, s, n, a);
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: o, operator: l, value: p } = c;
175
- if (l === "exists" || l === "notExists") {
176
- const f = s?.relationMap?.get(String(o));
177
- if (!f) throw new Error(`Relation '${o}' not found in ${t}`);
178
- const h = f.mappedEntity, u = c.where, w = T(f, n, s);
179
- if (u?.rules?.length) {
180
- const m = a ? `${a}.${h}` : h;
181
- i = I(i, h, u, w, n, m);
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
- i = l === "exists" ? i.not(h, "is", null) : i.is(h, null);
152
+ r = d === "exists" ? r.not(f, "is", null) : r.is(f, null);
184
153
  continue;
185
154
  }
186
- const d = a ? `${a}.${o}` : `${t}.${o}`;
187
- i = B(i, d, l, p);
155
+ const l = a ? `${a}.${c}` : `${t}.${c}`;
156
+ r = M(r, l, d, u);
188
157
  }
189
- return i;
158
+ return r;
190
159
  }
191
- function B(r, t, e, s) {
160
+ function M(i, t, e, s) {
192
161
  const n = C(s);
193
- if (t.includes(".")) {
194
- if (!r.url?.searchParams)
195
- throw new Error("Cannot apply nested filter: query.url.searchParams unavailable");
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 ? r.is(t, null) : r.eq(t, n);
168
+ return n === null ? i.is(t, null) : i.eq(t, n);
205
169
  case "!=":
206
- return n === null ? r.not(t, "is", null) : r.neq(t, n);
170
+ return n === null ? i.not(t, "is", null) : i.neq(t, n);
207
171
  case "<":
208
- return r.lt(t, n);
172
+ return i.lt(t, n);
209
173
  case ">":
210
- return r.gt(t, n);
174
+ return i.gt(t, n);
211
175
  case "<=":
212
- return r.lte(t, n);
176
+ return i.lte(t, n);
213
177
  case ">=":
214
- return r.gte(t, n);
178
+ return i.gte(t, n);
215
179
  case "in":
216
- return r.in(t, n);
180
+ return i.in(t, n);
217
181
  case "notIn":
218
- return r.not(t, "in", `(${n.join(",")})`);
182
+ return i.not(t, "in", `(${n.join(",")})`);
219
183
  case "contains":
220
184
  case "includes":
221
- return r.ilike(t, `%${n}%`);
185
+ return i.ilike(t, `%${n}%`);
222
186
  case "notContains":
223
- return r.not(t, "ilike", `%${n}%`);
187
+ return i.not(t, "ilike", `%${n}%`);
224
188
  case "startsWith":
225
- return r.ilike(t, `${n}%`);
189
+ return i.ilike(t, `${n}%`);
226
190
  case "notStartsWith":
227
- return r.not(t, "ilike", `${n}%`);
191
+ return i.not(t, "ilike", `${n}%`);
228
192
  case "endsWith":
229
- return r.ilike(t, `%${n}`);
193
+ return i.ilike(t, `%${n}`);
230
194
  case "notEndsWith":
231
- return r.not(t, "ilike", `%${n}`);
195
+ return i.not(t, "ilike", `%${n}`);
232
196
  case "between": {
233
- const [i, c] = n;
234
- return r.gte(t, i).lte(t, c);
197
+ const [r, o] = n;
198
+ return i.gte(t, r).lte(t, o);
235
199
  }
236
200
  case "notBetween": {
237
- const [i, c] = n;
238
- return r.or(`${t}.lt.${i},${t}.gt.${c}`);
201
+ const [r, o] = n;
202
+ return i.or(`${t}.lt.${r},${t}.gt.${o}`);
239
203
  }
240
204
  case "isNull":
241
- return r.is(t, null);
205
+ return i.is(t, null);
242
206
  case "isNotNull":
243
- return r.not(t, "is", null);
207
+ return i.not(t, "is", null);
244
208
  default:
245
209
  throw new Error(`Unsupported operator: ${e}`);
246
210
  }
247
211
  }
248
- function P(r, t) {
249
- if (r == null) return r;
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 r instanceof Date ? r : new Date(r);
248
+ return i instanceof Date ? i : new Date(i);
253
249
  case E.keyValue:
254
- if (typeof r == "object" && t.properties) {
250
+ if (typeof i == "object" && t.properties) {
255
251
  const e = {};
256
252
  for (const s of t.properties)
257
- r[s.name] !== void 0 && (e[s.name] = P(r[s.name], s));
253
+ i[s.name] !== void 0 && (e[s.name] = j(i[s.name], s));
258
254
  return e;
259
255
  }
260
- return r;
256
+ return i;
261
257
  case E.boolean:
262
- return !!r;
258
+ return !!i;
263
259
  case E.json:
264
260
  case E.stringArray:
265
261
  case E.numberArray:
266
262
  default:
267
- return r;
263
+ return i;
268
264
  }
269
265
  }
270
- function X(r, t, e) {
271
- const s = new r();
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 ? P(e[n], a) : e[n];
270
+ s[n] = a ? j(e[n], a) : e[n];
275
271
  }
276
272
  return s;
277
273
  }
278
- class F extends W {
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 c = Array.from(e);
291
- s = `*, ${c.filter(
292
- (l) => !c.some((p) => p !== l && p.startsWith(l + "."))
293
- ).map((l) => this.build_relation_select(l)).join(", ")}`;
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 = A(n, t.where, this.metadata, this.adapter.rxdb.schemaManager), t.orderBy?.length)
297
- for (const c of t.orderBy)
298
- n = n.order(c.field, { ascending: c.sort === "asc" });
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 c = t.offset, o = t.limit !== void 0 ? c + t.limit - 1 : Number.MAX_SAFE_INTEGER;
301
- n = n.range(c, o);
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: i } = await n;
304
- if (i) throw new g(`Failed to find entities: ${i.message}`);
305
- return (a || []).map((c) => X(this.EntityType, this.metadata, c));
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((c) => this.build_relation_select(c)).join(", ")}`);
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 = A(n, t.where, this.metadata, this.adapter.rxdb.schemaManager);
317
- const { count: a, error: i } = await n;
318
- if (i) {
319
- if (!i.message)
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 g(`Failed to count entities: ${i.message}`);
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 g(`Failed to create entity: ${a.message}`);
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 g(`Failed to update entity: ${n.message}`);
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 g(`Failed to remove entity: ${e.message}`);
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 i of n.rules)
361
- if (i.rules)
362
- s(i, a);
363
- else if (typeof i.field == "string" && i.field.includes(".")) {
364
- const c = i.field.split(".");
365
- for (let o = 1; o < c.length; o++) {
366
- const l = c.slice(0, o).join(".");
367
- e.add(a ? `${a}.${l}` : l);
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 (i.operator === "exists" || i.operator === "notExists") {
370
- const c = String(i.field), o = a ? `${a}.${c}` : c;
371
- this.metadata.relationMap?.has(c) && e.add(o), i.where && s(i.where, o);
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 i of e) {
387
- const c = n.relationMap?.get(i);
388
- if (!c) return `${i}(id)`;
389
- s.push({ tableName: c.mappedEntity, kind: c.kind, sourceEntity: n.name });
390
- const o = this.adapter.rxdb.schemaManager.getEntityMetadata(c.mappedEntity, c.mappedNamespace ?? "");
391
- o && (n = o);
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 i = s.length - 2; i >= 0; i--)
395
- a = this.build_relation_segment(s[i], !0).replace("(*)", `(*, ${a})`);
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 H extends F {
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 g(`Failed to find descendants: ${a.message}`);
449
+ throw new m(`Failed to find descendants: ${a.message}`);
454
450
  }
455
- return (n || []).map((i) => this.transformRowToEntity(i));
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 g(`Failed to find ancestors: ${a.message}`);
481
+ throw new m(`Failed to find ancestors: ${a.message}`);
486
482
  }
487
- return (n || []).map((i) => this.transformRowToEntity(i));
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, i = [], c = /* @__PURE__ */ new Set();
508
- let o = this.adapter.client.schema("public").from(n).select("*");
509
- e ? o = o.eq("id", e) : o = o.is("parentId", null);
510
- const { data: l, error: p } = await o;
511
- if (p)
512
- throw new g(`Failed to find start nodes: ${p.message}`);
513
- const d = async (f, h) => {
514
- for (const u of f) {
515
- if (c.has(u.id) || h > s) continue;
516
- c.add(u.id);
517
- const w = this.transformRowToEntity(u);
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: m } = await this.adapter.client.schema("public").from(n).select("*", { count: "exact", head: !0 }).eq("parentId", u.id);
520
- w.hasChildren = (m || 0) > 0;
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 (i.push(w), h < s) {
523
- const { data: m } = await this.adapter.client.schema("public").from(n).select("*").eq("parentId", u.id);
524
- m && m.length > 0 && await d(m, h + 1);
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(l || [], 0), i;
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, i = [];
541
- let c = e, o = 0;
542
- for (; c && o <= s; ) {
543
- const { data: l, error: p } = await this.adapter.client.schema("public").from(n).select("*").eq("id", c);
544
- if (p || !l || l.length === 0)
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 d = l[0], f = this.transformRowToEntity(d);
542
+ const l = d[0], p = this.transformRowToEntity(l);
547
543
  if (a) {
548
- const { count: h } = await this.adapter.client.schema("public").from(n).select("*", { count: "exact", head: !0 }).eq("parentId", d.id);
549
- f.hasChildren = (h || 0) > 0;
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
- i.push(f), c = d.parentId, o++;
547
+ r.push(p), o = l.parentId, c++;
552
548
  }
553
- return i;
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 Y = "supabase";
566
- class et extends U {
561
+ const tt = "supabase";
562
+ class it extends z {
567
563
  constructor(t, e) {
568
- super(t), this.options = e, this.#t = e.client ?? K(e.supabaseUrl, e.supabaseKey);
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 = Y;
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) => L(this, 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(D(t));
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(D(t));
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 = [...k(t.create, e), ...k(t.update, e)], n = Q(t.remove), { data: a, error: i } = await this.#t.rpc("rxdb_mutations", {
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 (i)
621
- throw new g(`Transaction failed: ${i.message}`);
622
- const c = a?.upserted ?? [];
623
- for (const [, o] of t.remove)
624
- c.push(...o);
625
- return c;
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 H(this, t) : new F(this, t);
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 g(
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 n = [];
663
- let a = this.#t.from("RxDBChange").select("*").gt("id", t).order("id", { ascending: !0 }).limit(e);
664
- s && s.length > 0 && (a = a.in("entity", s));
665
- const { data: i, error: c } = await a;
666
- if (c)
667
- throw new g(`Failed to pull changes: ${c.message}`);
668
- const o = (i ?? []).map((l) => ({
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 n.push(...o), n;
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 g(`Failed to get change count: ${a.message}`);
698
- let i = t;
703
+ throw new m(`Failed to get change count: ${a.message}`);
704
+ let r = t;
699
705
  if (n && n > 0) {
700
- let c = this.#t.from("RxDBChange").select("id").gt("id", t).order("id", { ascending: !1 }).limit(1);
701
- e && e.length > 0 && (c = c.in("entity", e));
702
- const { data: o, error: l } = await c;
703
- if (l)
704
- throw new g(`Failed to get latest changeId: ${l.message}`);
705
- o && o.length > 0 && (i = o[0].id);
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: i
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: i, inversePatch: c } = s;
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: i, inversePatch: c });
737
+ e.inserts.set(n, { patch: r, inversePatch: o });
732
738
  break;
733
739
  case "UPDATE":
734
- e.updates.set(n, { patch: i, inversePatch: c });
740
+ e.updates.set(n, { patch: r, inversePatch: o });
735
741
  break;
736
742
  case "DELETE":
737
- e.deletes.set(n, { patch: null, inversePatch: c });
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(), i = /* @__PURE__ */ new Map();
755
- for (const [d, { inversePatch: f }] of t.deletes) {
756
- const [h, u, w] = d.split(":"), m = h ? `${h}.${u}` : u;
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: h || "public",
759
- entity: u,
760
- entityId: w,
764
+ namespace: f || "public",
765
+ entity: h,
766
+ entityId: y,
761
767
  type: "DELETE",
762
768
  patch: null,
763
- inversePatch: f,
769
+ inversePatch: p,
764
770
  clientId: this.rxdb.context.clientId,
765
771
  createdAt: e,
766
772
  updatedAt: e
767
773
  });
768
- const y = i.get(m) ?? [];
769
- y.push(w), i.set(m, y);
774
+ const w = r.get(g) ?? [];
775
+ w.push(y), r.set(g, w);
770
776
  }
771
- for (const [d, { patch: f, inversePatch: h }] of t.updates) {
772
- const [u, w, m] = d.split(":"), y = u ? `${u}.${w}` : w;
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: u || "public",
775
- entity: w,
776
- entityId: m,
780
+ namespace: h || "public",
781
+ entity: y,
782
+ entityId: g,
777
783
  type: "UPDATE",
778
- patch: f,
779
- inversePatch: h,
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 $ = a.get(y) ?? [], _ = { id: m, ...f };
785
- s && (_.updatedBy = s), $.push(_), a.set(y, $);
790
+ const x = a.get(w) ?? [], _ = { id: g, ...p };
791
+ s && (_.updatedBy = s), x.push(_), a.set(w, x);
786
792
  }
787
- for (const [d, { patch: f, inversePatch: h }] of t.inserts) {
788
- const [u, w, m] = d.split(":"), y = u ? `${u}.${w}` : w;
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: u || "public",
791
- entity: w,
792
- entityId: m,
796
+ namespace: h || "public",
797
+ entity: y,
798
+ entityId: g,
793
799
  type: "INSERT",
794
- patch: f,
795
- inversePatch: h,
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 $ = a.get(y) ?? [], _ = { id: m, ...f };
801
- s && (_.createdBy = s, _.updatedBy = s), $.push(_), a.set(y, $);
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 c = Array.from(a.entries()).map(([d, f]) => {
804
- const [h, u] = d.includes(".") ? d.split(".") : ["public", d];
805
- return { table: u, schema: h, data: f };
806
- }), o = Array.from(i.entries()).map(([d, f]) => {
807
- const [h, u] = d.includes(".") ? d.split(".") : ["public", d];
808
- return { table: u, schema: h, ids: f };
809
- }), { data: l, error: p } = await this.#t.rpc("rxdb_mutations", {
810
- p_upserts: c,
811
- p_deletes: o,
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 (p)
816
- throw new g(`Failed to merge changes: ${p.message}`);
817
- return l?.max_change_id ?? void 0;
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 i = b(n), c = this.getSchemaClient(i.namespace), o = Array.from(a), l = s ? o.map((f) => ({ ...f, createdBy: s, updatedBy: s })) : o, { data: p, error: d } = await c.from(i.name).upsert(l).select();
831
- if (d)
832
- throw new g(`Failed to upsert: ${d.message}`);
833
- e.push(...p);
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), i = this.getSchemaClient(a.namespace), c = Array.from(n), o = c.map((p) => p.id), { error: l } = await i.from(a.name).delete().in("id", o);
842
- if (l)
843
- throw new g(`Failed to delete: ${l.message}`);
844
- e.push(...c);
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
- Y as ADAPTER_NAME,
851
- et as RxDBAdapterSupabase,
852
- q as SupabaseConfigError,
853
- g as SupabaseDataError,
854
- tt as SupabaseNetworkError,
855
- F as SupabaseRepository,
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
- H as SupabaseTreeRepository
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(SDK 未导出精确类型)
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;AAMpB;;GAEG;AACH,KAAK,oBAAoB,GAAG,GAAG,CAAC;AA4FhC;;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"}
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.8",
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.86.0",
29
- "@aiao/rxdb": "0.0.8"
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.8",
34
- "@aiao/rxdb-adapter-sqlite": "0.0.8"
38
+ "@aiao/rxdb-test": "0.0.9",
39
+ "@aiao/rxdb-adapter-sqlite": "0.0.9"
35
40
  }
36
41
  }