@aiao/rxdb-adapter-supabase 0.0.8 → 0.0.10

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 N, 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,192 @@ 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
  }
204
+ case "null":
240
205
  case "isNull":
241
- return r.is(t, null);
206
+ return i.is(t, null);
207
+ case "notNull":
242
208
  case "isNotNull":
243
- return r.not(t, "is", null);
209
+ return i.not(t, "is", null);
244
210
  default:
245
211
  throw new Error(`Unsupported operator: ${e}`);
246
212
  }
247
213
  }
248
- function P(r, t) {
249
- if (r == null) return r;
214
+ function T(i) {
215
+ const t = /* @__PURE__ */ new Map();
216
+ for (const e of i) {
217
+ const s = e.constructor;
218
+ t.has(s) || t.set(s, /* @__PURE__ */ new Set()), t.get(s).add(e);
219
+ }
220
+ return t;
221
+ }
222
+ function v(i, t) {
223
+ const e = [];
224
+ for (const [s, n] of i) {
225
+ const a = b(s), r = Array.from(n);
226
+ e.push({
227
+ table: a.name,
228
+ schema: a.namespace,
229
+ data: t ? r.map((o) => ({ ...o, createdBy: t, updatedBy: t })) : r
230
+ });
231
+ }
232
+ return e;
233
+ }
234
+ function Z(i) {
235
+ const t = [];
236
+ for (const [e, s] of i) {
237
+ const n = b(e);
238
+ t.push({
239
+ table: n.name,
240
+ schema: n.namespace,
241
+ ids: Array.from(s).map((a) => a.id)
242
+ });
243
+ }
244
+ return t;
245
+ }
246
+ function j(i, t) {
247
+ if (i == null) return i;
250
248
  switch (t.type) {
251
249
  case E.date:
252
- return r instanceof Date ? r : new Date(r);
250
+ return i instanceof Date ? i : new Date(i);
253
251
  case E.keyValue:
254
- if (typeof r == "object" && t.properties) {
252
+ if (typeof i == "object" && t.properties) {
255
253
  const e = {};
256
254
  for (const s of t.properties)
257
- r[s.name] !== void 0 && (e[s.name] = P(r[s.name], s));
255
+ i[s.name] !== void 0 && (e[s.name] = j(i[s.name], s));
258
256
  return e;
259
257
  }
260
- return r;
258
+ return i;
261
259
  case E.boolean:
262
- return !!r;
260
+ return !!i;
263
261
  case E.json:
264
262
  case E.stringArray:
265
263
  case E.numberArray:
266
264
  default:
267
- return r;
265
+ return i;
268
266
  }
269
267
  }
270
- function X(r, t, e) {
271
- const s = new r();
268
+ function G(i, t, e) {
269
+ const s = new i();
272
270
  for (const n of Object.keys(e)) {
273
271
  const a = t.propertyMap.get(n);
274
- s[n] = a ? P(e[n], a) : e[n];
272
+ s[n] = a ? j(e[n], a) : e[n];
275
273
  }
276
274
  return s;
277
275
  }
278
- class F extends W {
276
+ class P extends K {
279
277
  constructor(t, e) {
280
278
  super(t.rxdb, e), this.adapter = t, this.metadata = b(e);
281
279
  }
@@ -287,22 +285,22 @@ class F extends W {
287
285
  const e = this.extract_relation_fields(t.where);
288
286
  let s = "*";
289
287
  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(", ")}`;
288
+ const o = Array.from(e);
289
+ s = `*, ${o.filter(
290
+ (d) => !o.some((u) => u !== d && u.startsWith(d + "."))
291
+ ).map((d) => this.build_relation_select(d)).join(", ")}`;
294
292
  }
295
293
  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" });
294
+ if (n = $(n, t.where, this.metadata, this.adapter.rxdb.schemaManager), t.orderBy?.length)
295
+ for (const o of t.orderBy)
296
+ n = n.order(o.field, { ascending: o.sort === "asc" });
299
297
  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);
298
+ const o = t.offset, c = t.limit !== void 0 ? o + t.limit - 1 : Number.MAX_SAFE_INTEGER;
299
+ n = n.range(o, c);
302
300
  } 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));
301
+ const { data: a, error: r } = await n;
302
+ if (r) throw new m(`Failed to find entities: ${r.message}`);
303
+ return (a || []).map((o) => G(this.EntityType, this.metadata, o));
306
304
  }
307
305
  /**
308
306
  * 查询实体数量
@@ -311,14 +309,14 @@ class F extends W {
311
309
  if (t.groupBy) throw new Error("groupBy not supported yet");
312
310
  const e = this.extract_relation_fields(t.where);
313
311
  let s = "*";
314
- e.size > 0 && (s = `*, ${Array.from(e).map((c) => this.build_relation_select(c)).join(", ")}`);
312
+ e.size > 0 && (s = `*, ${Array.from(e).map((o) => this.build_relation_select(o)).join(", ")}`);
315
313
  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)
314
+ n = $(n, t.where, this.metadata, this.adapter.rxdb.schemaManager);
315
+ const { count: a, error: r } = await n;
316
+ if (r) {
317
+ if (!r.message)
320
318
  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}`);
319
+ throw new m(`Failed to count entities: ${r.message}`);
322
320
  }
323
321
  return a ?? 0;
324
322
  }
@@ -329,7 +327,7 @@ class F extends W {
329
327
  const e = { ...t }, s = this.rxdb.context.userId;
330
328
  s && (e.createdBy = s);
331
329
  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}`);
330
+ if (a) throw new m(`Failed to create entity: ${a.message}`);
333
331
  return n;
334
332
  }
335
333
  /**
@@ -337,7 +335,7 @@ class F extends W {
337
335
  */
338
336
  async update(t, e) {
339
337
  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}`);
338
+ if (n) throw new m(`Failed to update entity: ${n.message}`);
341
339
  return s;
342
340
  }
343
341
  /**
@@ -347,7 +345,7 @@ class F extends W {
347
345
  */
348
346
  async remove(t) {
349
347
  const { error: e } = await this.get_client().delete().eq("id", t.id);
350
- if (e) throw new g(`Failed to remove entity: ${e.message}`);
348
+ if (e) throw new m(`Failed to remove entity: ${e.message}`);
351
349
  return t;
352
350
  }
353
351
  // ============================================
@@ -357,18 +355,18 @@ class F extends W {
357
355
  extract_relation_fields(t) {
358
356
  const e = /* @__PURE__ */ new Set(), s = (n, a = "") => {
359
357
  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);
358
+ for (const r of n.rules)
359
+ if (r.rules)
360
+ s(r, a);
361
+ else if (typeof r.field == "string" && r.field.includes(".")) {
362
+ const o = r.field.split(".");
363
+ for (let c = 1; c < o.length; c++) {
364
+ const d = o.slice(0, c).join(".");
365
+ e.add(a ? `${a}.${d}` : d);
368
366
  }
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);
367
+ } else if (r.operator === "exists" || r.operator === "notExists") {
368
+ const o = String(r.field), c = a ? `${a}.${o}` : o;
369
+ this.metadata.relationMap?.has(o) && e.add(c), r.where && s(r.where, c);
372
370
  }
373
371
  }
374
372
  };
@@ -383,16 +381,16 @@ class F extends W {
383
381
  if (e.length === 1) return this.build_single_relation_select(e[0]);
384
382
  const s = [];
385
383
  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);
384
+ for (const r of e) {
385
+ const o = n.relationMap?.get(r);
386
+ if (!o) return `${r}(id)`;
387
+ s.push({ tableName: o.mappedEntity, kind: o.kind, sourceEntity: n.name });
388
+ const c = this.adapter.rxdb.schemaManager.getEntityMetadata(o.mappedEntity, o.mappedNamespace ?? "");
389
+ c && (n = c);
392
390
  }
393
391
  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})`);
392
+ for (let r = s.length - 2; r >= 0; r--)
393
+ a = this.build_relation_segment(s[r], !0).replace("(*)", `(*, ${a})`);
396
394
  return a;
397
395
  }
398
396
  /**
@@ -431,7 +429,7 @@ class F extends W {
431
429
  return this.adapter.client.schema(this.metadata.namespace).from(this.metadata.name);
432
430
  }
433
431
  }
434
- class H extends F {
432
+ class q extends P {
435
433
  constructor(t, e) {
436
434
  super(t, e);
437
435
  }
@@ -450,9 +448,9 @@ class H extends F {
450
448
  if (a) {
451
449
  if (a.message.includes("function") || a.message.includes("Could not find"))
452
450
  return this.findDescendantsFallback(t);
453
- throw new g(`Failed to find descendants: ${a.message}`);
451
+ throw new m(`Failed to find descendants: ${a.message}`);
454
452
  }
455
- return (n || []).map((i) => this.transformRowToEntity(i));
453
+ return (n || []).map((r) => this.transformRowToEntity(r));
456
454
  }
457
455
  /**
458
456
  * 查询子孙节点数量
@@ -482,9 +480,9 @@ class H extends F {
482
480
  if (a) {
483
481
  if (a.message.includes("function") || a.message.includes("Could not find"))
484
482
  return this.findAncestorsFallback(t);
485
- throw new g(`Failed to find ancestors: ${a.message}`);
483
+ throw new m(`Failed to find ancestors: ${a.message}`);
486
484
  }
487
- return (n || []).map((i) => this.transformRowToEntity(i));
485
+ return (n || []).map((r) => this.transformRowToEntity(r));
488
486
  }
489
487
  /**
490
488
  * 查询祖先节点数量
@@ -504,28 +502,28 @@ class H extends F {
504
502
  * 优化方案:一次查询获取所有节点,在内存中构建树结构。
505
503
  */
506
504
  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);
505
+ const { entityId: e, level: s = 100 } = t, n = this.metadata.name, a = this.metadata.features?.tree?.hasChildren, r = [], o = /* @__PURE__ */ new Set();
506
+ let c = this.adapter.client.schema("public").from(n).select("*");
507
+ e ? c = c.eq("id", e) : c = c.is("parentId", null);
508
+ const { data: d, error: u } = await c;
509
+ if (u)
510
+ throw new m(`Failed to find start nodes: ${u.message}`);
511
+ const l = async (p, f) => {
512
+ for (const h of p) {
513
+ if (o.has(h.id) || f > s) continue;
514
+ o.add(h.id);
515
+ const y = this.transformRowToEntity(h);
518
516
  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;
517
+ const { count: g } = await this.adapter.client.schema("public").from(n).select("*", { count: "exact", head: !0 }).eq("parentId", h.id);
518
+ y.hasChildren = (g || 0) > 0;
521
519
  }
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);
520
+ if (r.push(y), f < s) {
521
+ const { data: g } = await this.adapter.client.schema("public").from(n).select("*").eq("parentId", h.id);
522
+ g && g.length > 0 && await l(g, f + 1);
525
523
  }
526
524
  }
527
525
  };
528
- return await d(l || [], 0), i;
526
+ return await l(d || [], 0), r;
529
527
  }
530
528
  /**
531
529
  * 备用的祖先节点查询(不使用存储函数)
@@ -537,20 +535,20 @@ class H extends F {
537
535
  const { entityId: e, level: s = 100 } = t;
538
536
  if (!e)
539
537
  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)
538
+ const n = this.metadata.name, a = this.metadata.features?.tree?.hasChildren, r = [];
539
+ let o = e, c = 0;
540
+ for (; o && c <= s; ) {
541
+ const { data: d, error: u } = await this.adapter.client.schema("public").from(n).select("*").eq("id", o);
542
+ if (u || !d || d.length === 0)
545
543
  break;
546
- const d = l[0], f = this.transformRowToEntity(d);
544
+ const l = d[0], p = this.transformRowToEntity(l);
547
545
  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;
546
+ const { count: f } = await this.adapter.client.schema("public").from(n).select("*", { count: "exact", head: !0 }).eq("parentId", l.id);
547
+ p.hasChildren = (f || 0) > 0;
550
548
  }
551
- i.push(f), c = d.parentId, o++;
549
+ r.push(p), o = l.parentId, c++;
552
550
  }
553
- return i;
551
+ return r;
554
552
  }
555
553
  /**
556
554
  * 将数据库行转换为实体
@@ -562,14 +560,14 @@ class H extends F {
562
560
  }), e;
563
561
  }
564
562
  }
565
- const Y = "supabase";
566
- class et extends U {
563
+ const tt = "supabase";
564
+ class it extends z {
567
565
  constructor(t, e) {
568
- super(t), this.options = e, this.#t = e.client ?? K(e.supabaseUrl, e.supabaseKey);
566
+ super(t), this.options = e, this.#t = e.client ?? L(e.supabaseUrl, e.supabaseKey);
569
567
  }
570
568
  #t;
571
569
  #e = null;
572
- name = Y;
570
+ name = tt;
573
571
  get client() {
574
572
  return this.#t;
575
573
  }
@@ -580,7 +578,7 @@ class et extends U {
580
578
  return this.#e || (this.#e = this.#t.channel("rxdb-changes").on(
581
579
  "postgres_changes",
582
580
  { event: "INSERT", schema: "public", table: "RxDBChange" },
583
- (t) => L(this, t)
581
+ (t) => J(this, t)
584
582
  ).subscribe((t, e) => {
585
583
  e && console.error("Supabase Realtime subscription failed:", e);
586
584
  })), this;
@@ -598,13 +596,13 @@ class et extends U {
598
596
  * 批量保存实体(upsert 语义,非事务)
599
597
  */
600
598
  async saveMany(t) {
601
- return t.length === 0 ? [] : this.executeUpsert(D(t));
599
+ return t.length === 0 ? [] : this.executeUpsert(T(t));
602
600
  }
603
601
  /**
604
602
  * 批量删除实体(非事务)
605
603
  */
606
604
  async removeMany(t) {
607
- return t.length === 0 ? [] : this.executeDelete(D(t));
605
+ return t.length === 0 ? [] : this.executeDelete(T(t));
608
606
  }
609
607
  /**
610
608
  * 批量修改实体(事务)
@@ -613,16 +611,16 @@ class et extends U {
613
611
  * 在单个数据库事务中执行所有操作,确保原子性。
614
612
  */
615
613
  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", {
614
+ 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
615
  p_upserts: s,
618
616
  p_deletes: n
619
617
  });
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;
618
+ if (r)
619
+ throw new m(`Transaction failed: ${r.message}`);
620
+ const o = a?.upserted ?? [];
621
+ for (const [, c] of t.remove)
622
+ o.push(...c);
623
+ return o;
626
624
  }
627
625
  // ============================================
628
626
  // Repository
@@ -630,7 +628,7 @@ class et extends U {
630
628
  getRepository(t) {
631
629
  if (this.repository_cache.has(t))
632
630
  return this.repository_cache.get(t);
633
- const s = b(t).features?.tree ? new H(this, t) : new F(this, t);
631
+ const s = b(t).features?.tree ? new q(this, t) : new P(this, t);
634
632
  return this.repository_cache.set(t, s), s;
635
633
  }
636
634
  // ============================================
@@ -640,7 +638,7 @@ class et extends U {
640
638
  const e = b(t), n = await this.getSchemaClient(e.namespace).from(e.name).select("*", { count: "exact", head: !0 });
641
639
  if (n.status === 200) return !0;
642
640
  if (n.status === 204) return !1;
643
- throw new g(
641
+ throw new m(
644
642
  `Failed to check table existence: ${n.error?.message || `status ${n.status}`}`
645
643
  );
646
644
  }
@@ -653,24 +651,34 @@ class et extends U {
653
651
  * @param sinceId - 拉取此 ID 之后的变更(不包含该 ID)
654
652
  * @param limit - 最大拉取数量
655
653
  * @param repositoryFilter - 可选的实体过滤列表(用于 repository-level sync)
654
+ * @param filter - 可选的行级过滤条件(用于 SyncType.Filter)
656
655
  * @returns RxDBChange 记录数组,按 id ASC 排序
657
656
  *
658
657
  * @remarks
659
658
  * 使用 id 而非 createdAt 作为游标,避免同毫秒内多条记录导致的重复问题
659
+ *
660
+ * 当提供 filter 参数时,会通过 JOIN 实体表并应用过滤条件,
661
+ * 只返回满足条件的实体对应的变更记录。
660
662
  */
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) => ({
663
+ async pullChanges(t, e = 1e3, s, n) {
664
+ const a = [];
665
+ let r;
666
+ if (n && s?.length === 1) {
667
+ const l = s[0];
668
+ if (r = await this.#n(l, n), r.length === 0)
669
+ return [];
670
+ }
671
+ let o = this.#t.from("RxDBChange").select("*").gt("id", t).order("id", { ascending: !0 }).limit(e);
672
+ s && s.length > 0 && (o = o.in("entity", s)), r && (o = o.in("entityId", r));
673
+ const { data: c, error: d } = await o;
674
+ if (d)
675
+ throw new m(`Failed to pull changes: ${d.message}`);
676
+ const u = (c ?? []).map((l) => ({
669
677
  ...l,
670
678
  createdAt: new Date(l.createdAt),
671
679
  updatedAt: l.updatedAt ? new Date(l.updatedAt) : null
672
680
  }));
673
- return n.push(...o), n;
681
+ return a.push(...u), a;
674
682
  }
675
683
  /**
676
684
  * 获取远程变更数量(轻量级,不下载数据)(T042, US2)
@@ -694,19 +702,19 @@ class et extends U {
694
702
  e && e.length > 0 && (s = s.in("entity", e));
695
703
  const { count: n, error: a } = await s;
696
704
  if (a)
697
- throw new g(`Failed to get change count: ${a.message}`);
698
- let i = t;
705
+ throw new m(`Failed to get change count: ${a.message}`);
706
+ let r = t;
699
707
  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);
708
+ let o = this.#t.from("RxDBChange").select("id").gt("id", t).order("id", { ascending: !1 }).limit(1);
709
+ e && e.length > 0 && (o = o.in("entity", e));
710
+ const { data: c, error: d } = await o;
711
+ if (d)
712
+ throw new m(`Failed to get latest changeId: ${d.message}`);
713
+ c && c.length > 0 && (r = c[0].id);
706
714
  }
707
715
  return {
708
716
  count: n ?? 0,
709
- latestChangeId: i
717
+ latestChangeId: r
710
718
  };
711
719
  }
712
720
  /**
@@ -724,17 +732,17 @@ class et extends U {
724
732
  deletes: /* @__PURE__ */ new Map()
725
733
  };
726
734
  for (const s of t) {
727
- const { entityKey: n, finalType: a, finalPatch: i, inversePatch: c } = s;
735
+ const { entityKey: n, finalType: a, finalPatch: r, inversePatch: o } = s;
728
736
  if (a)
729
737
  switch (a) {
730
738
  case "INSERT":
731
- e.inserts.set(n, { patch: i, inversePatch: c });
739
+ e.inserts.set(n, { patch: r, inversePatch: o });
732
740
  break;
733
741
  case "UPDATE":
734
- e.updates.set(n, { patch: i, inversePatch: c });
742
+ e.updates.set(n, { patch: r, inversePatch: o });
735
743
  break;
736
744
  case "DELETE":
737
- e.deletes.set(n, { patch: null, inversePatch: c });
745
+ e.deletes.set(n, { patch: null, inversePatch: o });
738
746
  break;
739
747
  }
740
748
  }
@@ -751,70 +759,119 @@ class et extends U {
751
759
  * @param actions - 压缩后的变更操作集合
752
760
  */
753
761
  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;
762
+ const e = (/* @__PURE__ */ new Date()).toISOString(), s = this.rxdb.context.userId, n = [], a = /* @__PURE__ */ new Map(), r = /* @__PURE__ */ new Map();
763
+ for (const [l, { inversePatch: p }] of t.deletes) {
764
+ const [f, h, y] = l.split(":"), g = f ? `${f}.${h}` : h;
757
765
  n.push({
758
- namespace: h || "public",
759
- entity: u,
760
- entityId: w,
766
+ namespace: f || "public",
767
+ entity: h,
768
+ entityId: y,
761
769
  type: "DELETE",
762
770
  patch: null,
763
- inversePatch: f,
771
+ inversePatch: p,
764
772
  clientId: this.rxdb.context.clientId,
765
773
  createdAt: e,
766
774
  updatedAt: e
767
775
  });
768
- const y = i.get(m) ?? [];
769
- y.push(w), i.set(m, y);
776
+ const w = r.get(g) ?? [];
777
+ w.push(y), r.set(g, w);
770
778
  }
771
- for (const [d, { patch: f, inversePatch: h }] of t.updates) {
772
- const [u, w, m] = d.split(":"), y = u ? `${u}.${w}` : w;
779
+ for (const [l, { patch: p, inversePatch: f }] of t.updates) {
780
+ const [h, y, g] = l.split(":"), w = h ? `${h}.${y}` : y;
773
781
  n.push({
774
- namespace: u || "public",
775
- entity: w,
776
- entityId: m,
782
+ namespace: h || "public",
783
+ entity: y,
784
+ entityId: g,
777
785
  type: "UPDATE",
778
- patch: f,
779
- inversePatch: h,
786
+ patch: p,
787
+ inversePatch: f,
780
788
  clientId: this.rxdb.context.clientId,
781
789
  createdAt: e,
782
790
  updatedAt: e
783
791
  });
784
- const $ = a.get(y) ?? [], _ = { id: m, ...f };
785
- s && (_.updatedBy = s), $.push(_), a.set(y, $);
792
+ const x = a.get(w) ?? [], _ = { id: g, ...p };
793
+ s && (_.updatedBy = s), x.push(_), a.set(w, x);
786
794
  }
787
- for (const [d, { patch: f, inversePatch: h }] of t.inserts) {
788
- const [u, w, m] = d.split(":"), y = u ? `${u}.${w}` : w;
795
+ for (const [l, { patch: p, inversePatch: f }] of t.inserts) {
796
+ const [h, y, g] = l.split(":"), w = h ? `${h}.${y}` : y;
789
797
  n.push({
790
- namespace: u || "public",
791
- entity: w,
792
- entityId: m,
798
+ namespace: h || "public",
799
+ entity: y,
800
+ entityId: g,
793
801
  type: "INSERT",
794
- patch: f,
795
- inversePatch: h,
802
+ patch: p,
803
+ inversePatch: f,
796
804
  clientId: this.rxdb.context.clientId,
797
805
  createdAt: e,
798
806
  updatedAt: e
799
807
  });
800
- const $ = a.get(y) ?? [], _ = { id: m, ...f };
801
- s && (_.createdBy = s, _.updatedBy = s), $.push(_), a.set(y, $);
808
+ const x = a.get(w) ?? [], _ = { id: g, ...p };
809
+ s && (_.createdBy = s, _.updatedBy = s), x.push(_), a.set(w, x);
802
810
  }
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,
811
+ const o = Array.from(a.entries()).map(([l, p]) => {
812
+ const [f, h] = l.includes(".") ? l.split(".") : ["public", l];
813
+ return { table: h, schema: f, data: p };
814
+ }), c = Array.from(r.entries()).map(([l, p]) => {
815
+ const [f, h] = l.includes(".") ? l.split(".") : ["public", l];
816
+ return { table: h, schema: f, ids: p };
817
+ }), { data: d, error: u } = await this.#t.rpc("rxdb_mutations", {
818
+ p_upserts: o,
819
+ p_deletes: c,
812
820
  p_changes: n,
813
821
  p_skip_sync: !0
814
822
  });
815
- if (p)
816
- throw new g(`Failed to merge changes: ${p.message}`);
817
- return l?.max_change_id ?? void 0;
823
+ if (u)
824
+ throw new m(`Failed to merge changes: ${u.message}`);
825
+ return d?.max_change_id ?? void 0;
826
+ }
827
+ // ============================================
828
+ // QueryCache 方法
829
+ // ============================================
830
+ /**
831
+ * 获取实体元数据,用于新鲜度比较(QueryCache 专用)
832
+ *
833
+ * 只返回 `{ id, updatedAt }` 元数据,网络传输量比完整数据减少 90%+。
834
+ *
835
+ * @param entityName - 实体名称
836
+ * @param query - 查询条件
837
+ * @returns Observable<QueryCacheEntityMetadata[]>
838
+ *
839
+ * @example
840
+ * ```typescript
841
+ * adapter.fetchMetadata('Product', { combinator: 'and', rules: [{ field: 'status', operator: 'eq', value: 'active' }] })
842
+ * .subscribe(metadata => console.log(metadata));
843
+ * ```
844
+ */
845
+ fetchMetadata(t, e) {
846
+ return D(() => {
847
+ let s = this.#t.from(t).select("id, updatedAt");
848
+ return s = $(s, e), k(s).pipe(
849
+ N(({ data: n, error: a }) => {
850
+ if (a)
851
+ throw new m(`Failed to fetch metadata: ${a.message}`);
852
+ return (n ?? []).map((r) => ({
853
+ id: r.id,
854
+ updatedAt: r.updatedAt
855
+ }));
856
+ })
857
+ );
858
+ });
859
+ }
860
+ /**
861
+ * 按 ID 列表批量获取完整数据(QueryCache 专用)
862
+ *
863
+ * @param entityName - 实体名称
864
+ * @param ids - 需要获取的实体 ID 列表
865
+ * @returns Observable<T[]>
866
+ */
867
+ findByIds(t, e) {
868
+ return D(() => e.length === 0 ? Q([]) : k(this.#t.from(t).select("*").in("id", e)).pipe(
869
+ N(({ data: s, error: n }) => {
870
+ if (n)
871
+ throw new m(`Failed to find by ids: ${n.message}`);
872
+ return s ?? [];
873
+ })
874
+ ));
818
875
  }
819
876
  // ============================================
820
877
  // 私有方法
@@ -827,10 +884,10 @@ class et extends U {
827
884
  async executeUpsert(t) {
828
885
  const e = [], s = this.rxdb.context.userId;
829
886
  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);
887
+ 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();
888
+ if (l)
889
+ throw new m(`Failed to upsert: ${l.message}`);
890
+ e.push(...u);
834
891
  }
835
892
  return e;
836
893
  }
@@ -838,21 +895,36 @@ class et extends U {
838
895
  async executeDelete(t) {
839
896
  const e = [];
840
897
  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);
898
+ 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);
899
+ if (d)
900
+ throw new m(`Failed to delete: ${d.message}`);
901
+ e.push(...o);
845
902
  }
846
903
  return e;
847
904
  }
905
+ /**
906
+ * 获取满足 filter 条件的实体 ID 列表
907
+ *
908
+ * @param entityName - 实体表名
909
+ * @param filter - 过滤条件
910
+ * @returns 满足条件的 entityId 列表
911
+ */
912
+ async #n(t, e) {
913
+ let s = this.#t.from(t).select("id");
914
+ s = $(s, e);
915
+ const { data: n, error: a } = await s;
916
+ if (a)
917
+ throw new m(`Failed to query filtered entities: ${a.message}`);
918
+ return (n ?? []).map((r) => r.id);
919
+ }
848
920
  }
849
921
  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,
922
+ tt as ADAPTER_NAME,
923
+ it as RxDBAdapterSupabase,
924
+ at as SupabaseConfigError,
925
+ m as SupabaseDataError,
926
+ rt as SupabaseNetworkError,
927
+ P as SupabaseRepository,
856
928
  S as SupabaseSyncError,
857
- H as SupabaseTreeRepository
929
+ q as SupabaseTreeRepository
858
930
  };
@@ -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.10",
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.10"
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-adapter-sqlite": "0.0.10",
39
+ "@aiao/rxdb-test": "0.0.10"
35
40
  }
36
41
  }