@aiao/rxdb-devtools 0.0.8

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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Aiao Team
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1 @@
1
+ # rxdb-devtools
@@ -0,0 +1,24 @@
1
+ import { SerializedEvent } from './types.js';
2
+ /**
3
+ * 事件缓冲区类
4
+ * FIFO 策略:当缓冲区满时,移除最旧的事件
5
+ */
6
+ export declare class EventBuffer {
7
+ #private;
8
+ /** 当前缓冲区大小 */
9
+ get length(): number;
10
+ /** 最大缓冲区大小 */
11
+ get maxSize(): number;
12
+ /** 缓冲区是否为空 */
13
+ get isEmpty(): boolean;
14
+ /** 缓冲区是否已满 */
15
+ get isFull(): boolean;
16
+ constructor(maxSize?: number);
17
+ /** 添加事件到缓冲区 */
18
+ push(event: SerializedEvent): void;
19
+ /** 清空并返回所有缓冲的事件 */
20
+ flush(): SerializedEvent[];
21
+ /** 清空缓冲区 */
22
+ clear(): void;
23
+ }
24
+ //# sourceMappingURL=buffer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"buffer.d.ts","sourceRoot":"","sources":["../src/buffer.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAKlD;;;GAGG;AACH,qBAAa,WAAW;;IAItB,cAAc;IACd,IAAI,MAAM,IAAI,MAAM,CAEnB;IAED,cAAc;IACd,IAAI,OAAO,IAAI,MAAM,CAEpB;IAED,cAAc;IACd,IAAI,OAAO,IAAI,OAAO,CAErB;IAED,cAAc;IACd,IAAI,MAAM,IAAI,OAAO,CAEpB;gBAEW,OAAO,SAAmB;IAItC,eAAe;IACf,IAAI,CAAC,KAAK,EAAE,eAAe,GAAG,IAAI;IAOlC,mBAAmB;IACnB,KAAK,IAAI,eAAe,EAAE;IAM1B,YAAY;IACZ,KAAK,IAAI,IAAI;CAGd"}
@@ -0,0 +1,74 @@
1
+ /**
2
+ * DevTools 连接器
3
+ * 负责与 Chrome DevTools Extension 建立通信
4
+ */
5
+ /** RxDB 事件类型 */
6
+ interface RxDBEventData {
7
+ type: string;
8
+ [key: string]: unknown;
9
+ }
10
+ /** 实体元数据接口 */
11
+ interface EntityMeta {
12
+ name: string;
13
+ namespace?: string;
14
+ version?: number;
15
+ }
16
+ /** 实体类型 */
17
+ type EntityType = new (...args: unknown[]) => unknown;
18
+ /** 获取实体元数据的函数类型 */
19
+ type GetEntityMetadataFn = (entity: EntityType) => EntityMeta | undefined;
20
+ /** RxDB 实例接口(避免直接依赖 @aiao/rxdb) */
21
+ interface RxDBInstance {
22
+ addEventListener(type: string, listener: (event: RxDBEventData) => void): void;
23
+ removeEventListener(type: string, listener: (event: RxDBEventData) => void): void;
24
+ version?: string;
25
+ config?: {
26
+ dbName?: string;
27
+ entities?: EntityType[];
28
+ };
29
+ entityManager?: {
30
+ getRepository(entity: EntityType): {
31
+ findAll(options: {
32
+ where: {
33
+ combinator: string;
34
+ rules: unknown[];
35
+ };
36
+ orderBy: {
37
+ field: string;
38
+ sort: string;
39
+ }[];
40
+ limit?: number;
41
+ }): {
42
+ subscribe(callback: (data: unknown[]) => void): {
43
+ unsubscribe(): void;
44
+ };
45
+ };
46
+ };
47
+ };
48
+ }
49
+ /** DevTools 配置选项 */
50
+ export interface DevToolsOptions {
51
+ maxBufferSize?: number;
52
+ enabled?: boolean;
53
+ }
54
+ /**
55
+ * DevTools 连接器类
56
+ */
57
+ export declare class DevToolsConnector {
58
+ #private;
59
+ /** 连接状态 */
60
+ get connected(): boolean;
61
+ /** 是否启用 */
62
+ get enabled(): boolean;
63
+ constructor(options?: DevToolsOptions);
64
+ /** 初始化连接 */
65
+ init(rxdb: RxDBInstance | any, getEntityMetadata?: GetEntityMetadataFn): void;
66
+ /** 断开连接 */
67
+ disconnect(): void;
68
+ }
69
+ /** 获取或创建全局连接器 */
70
+ export declare function getDevToolsConnector(options?: DevToolsOptions): DevToolsConnector;
71
+ /** 重置全局连接器(用于测试) */
72
+ export declare function resetDevToolsConnector(): void;
73
+ export {};
74
+ //# sourceMappingURL=connector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connector.d.ts","sourceRoot":"","sources":["../src/connector.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAaH,gBAAgB;AAChB,UAAU,aAAa;IACrB,IAAI,EAAE,MAAM,CAAC;IAEb,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,cAAc;AACd,UAAU,UAAU;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,WAAW;AACX,KAAK,UAAU,GAAG,KAAK,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC;AAEtD,mBAAmB;AACnB,KAAK,mBAAmB,GAAG,CAAC,MAAM,EAAE,UAAU,KAAK,UAAU,GAAG,SAAS,CAAC;AAE1E,mCAAmC;AACnC,UAAU,YAAY;IACpB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,GAAG,IAAI,CAAC;IAC/E,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,GAAG,IAAI,CAAC;IAClF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE;QACP,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,QAAQ,CAAC,EAAE,UAAU,EAAE,CAAC;KACzB,CAAC;IACF,aAAa,CAAC,EAAE;QACd,aAAa,CAAC,MAAM,EAAE,UAAU,GAAG;YACjC,OAAO,CAAC,OAAO,EAAE;gBACf,KAAK,EAAE;oBAAE,UAAU,EAAE,MAAM,CAAC;oBAAC,KAAK,EAAE,OAAO,EAAE,CAAA;iBAAE,CAAC;gBAChD,OAAO,EAAE;oBAAE,KAAK,EAAE,MAAM,CAAC;oBAAC,IAAI,EAAE,MAAM,CAAA;iBAAE,EAAE,CAAC;gBAC3C,KAAK,CAAC,EAAE,MAAM,CAAC;aAChB,GAAG;gBAAE,SAAS,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,GAAG;oBAAE,WAAW,IAAI,IAAI,CAAA;iBAAE,CAAA;aAAE,CAAC;SACjF,CAAC;KACH,CAAC;CACH;AAED,oBAAoB;AACpB,MAAM,WAAW,eAAe;IAC9B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAiCD;;GAEG;AACH,qBAAa,iBAAiB;;IAU5B,WAAW;IACX,IAAI,SAAS,IAAI,OAAO,CAEvB;IAED,WAAW;IACX,IAAI,OAAO,IAAI,OAAO,CAErB;gBAEW,OAAO,GAAE,eAAoB;IAMzC,YAAY;IACZ,IAAI,CAAC,IAAI,EAAE,YAAY,GAAG,GAAG,EAAE,iBAAiB,CAAC,EAAE,mBAAmB,GAAG,IAAI;IAW7E,WAAW;IACX,UAAU,IAAI,IAAI;CA+VnB;AAKD,iBAAiB;AACjB,wBAAgB,oBAAoB,CAAC,OAAO,CAAC,EAAE,eAAe,GAAG,iBAAiB,CAKjF;AAED,oBAAoB;AACpB,wBAAgB,sBAAsB,IAAI,IAAI,CAK7C"}
@@ -0,0 +1,7 @@
1
+ export { DevToolsConnector, getDevToolsConnector, resetDevToolsConnector } from './connector.js';
2
+ export type { DevToolsOptions } from './connector.js';
3
+ export { RXDB_DEVTOOLS_MESSAGE, createMessage, isDevToolsMessage, type AnyDevToolsMessage, type ClearMessage, type DevToolsMessage, type DisconnectMessage, type EventMessage, type HandshakeAckMessage, type HandshakeMessage, type MessageDirection, type MessageType, type PingMessage, type PongMessage, type SerializedEvent } from './types.js';
4
+ export { EventBuffer } from './buffer.js';
5
+ export { SequenceGenerator } from './sequence.js';
6
+ export { deserialize, serialize } from './serializer.js';
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AACjG,YAAY,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAGtD,OAAO,EACL,qBAAqB,EACrB,aAAa,EACb,iBAAiB,EACjB,KAAK,kBAAkB,EACvB,KAAK,YAAY,EACjB,KAAK,eAAe,EACpB,KAAK,iBAAiB,EACtB,KAAK,YAAY,EACjB,KAAK,mBAAmB,EACxB,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EACrB,KAAK,WAAW,EAChB,KAAK,WAAW,EAChB,KAAK,WAAW,EAChB,KAAK,eAAe,EACrB,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,429 @@
1
+ class E {
2
+ #e = [];
3
+ #s;
4
+ /** 当前缓冲区大小 */
5
+ get length() {
6
+ return this.#e.length;
7
+ }
8
+ /** 最大缓冲区大小 */
9
+ get maxSize() {
10
+ return this.#s;
11
+ }
12
+ /** 缓冲区是否为空 */
13
+ get isEmpty() {
14
+ return this.#e.length === 0;
15
+ }
16
+ /** 缓冲区是否已满 */
17
+ get isFull() {
18
+ return this.#e.length >= this.#s;
19
+ }
20
+ constructor(e = 100) {
21
+ this.#s = e;
22
+ }
23
+ /** 添加事件到缓冲区 */
24
+ push(e) {
25
+ this.#e.length >= this.#s && this.#e.shift(), this.#e.push(e);
26
+ }
27
+ /** 清空并返回所有缓冲的事件 */
28
+ flush() {
29
+ const e = [...this.#e];
30
+ return this.#e = [], e;
31
+ }
32
+ /** 清空缓冲区 */
33
+ clear() {
34
+ this.#e = [];
35
+ }
36
+ }
37
+ class T {
38
+ #e = 0;
39
+ /** 获取当前序列号(不递增) */
40
+ get current() {
41
+ return this.#e;
42
+ }
43
+ /** 获取下一个序列号 */
44
+ next() {
45
+ return ++this.#e;
46
+ }
47
+ /** 重置序列号 */
48
+ reset() {
49
+ this.#e = 0;
50
+ }
51
+ }
52
+ let p = 0;
53
+ function y() {
54
+ return `evt_${Date.now()}_${++p}`;
55
+ }
56
+ function f(n, e = /* @__PURE__ */ new WeakSet()) {
57
+ if (n == null) return n;
58
+ const t = typeof n;
59
+ if (t === "string" || t === "number" || t === "boolean")
60
+ return n;
61
+ if (!(t === "function" || t === "symbol")) {
62
+ if (n instanceof Date)
63
+ return n.toISOString();
64
+ if (Array.isArray(n))
65
+ return n.map((s) => f(s, e)).filter((s) => s !== void 0);
66
+ if (t === "object") {
67
+ if (e.has(n))
68
+ return "[Circular]";
69
+ e.add(n);
70
+ const s = {};
71
+ for (const r of Object.keys(n)) {
72
+ if (typeof r == "symbol") continue;
73
+ const o = n[r], c = f(o, e);
74
+ c !== void 0 && (s[r] = c);
75
+ }
76
+ return s;
77
+ }
78
+ }
79
+ }
80
+ function v(n, e) {
81
+ const t = n, { type: s, ...r } = t;
82
+ return {
83
+ id: y(),
84
+ eventType: s,
85
+ timestamp: Date.now(),
86
+ sequence: e,
87
+ data: f(r)
88
+ };
89
+ }
90
+ function _(n) {
91
+ return {
92
+ id: n.id,
93
+ eventType: n.eventType,
94
+ timestamp: n.timestamp,
95
+ sequence: n.sequence,
96
+ data: n.data
97
+ };
98
+ }
99
+ const d = "@aiao/rxdb-devtools";
100
+ function N(n) {
101
+ return typeof n != "object" || n === null ? !1 : n.source === d;
102
+ }
103
+ function i(n, e, t, s) {
104
+ return {
105
+ source: d,
106
+ direction: e,
107
+ type: n,
108
+ payload: t,
109
+ timestamp: Date.now(),
110
+ sequence: s
111
+ };
112
+ }
113
+ const g = {
114
+ maxBufferSize: 100,
115
+ enabled: !0
116
+ }, m = [
117
+ // 'ENTITY_LOCAL_NEW',
118
+ "ENTITY_LOCAL_CREATE",
119
+ "ENTITY_LOCAL_UPDATE",
120
+ "ENTITY_LOCAL_REMOVE",
121
+ "ENTITY_REMOTE_CREATE",
122
+ "ENTITY_REMOTE_UPDATE",
123
+ "ENTITY_REMOTE_REMOVE",
124
+ // 'TRANSACTION_BEGIN',
125
+ // 'TRANSACTION_COMMIT',
126
+ // 'TRANSACTION_ROLLBACK',
127
+ "SWITCH_BRANCH_BEGIN",
128
+ "SWITCH_BRANCH_COMMIT",
129
+ "SWITCH_BRANCH_ROLLBACK",
130
+ "SYNC_BEGIN",
131
+ "SYNC_COMPLETE",
132
+ "SYNC_ERROR",
133
+ "CONFLICT_DETECTED",
134
+ "CONFLICT_PENDING",
135
+ "REPOSITORY_SYNC_BEGIN",
136
+ "REPOSITORY_SYNC_COMPLETE",
137
+ "REPOSITORY_SYNC_ERROR"
138
+ ];
139
+ class C {
140
+ #e;
141
+ #s = !1;
142
+ #c;
143
+ #t;
144
+ #r = /* @__PURE__ */ new Set();
145
+ #l = /* @__PURE__ */ new Map();
146
+ #o = null;
147
+ #a = null;
148
+ #h = /* @__PURE__ */ new Map();
149
+ /** 连接状态 */
150
+ get connected() {
151
+ return this.#s;
152
+ }
153
+ /** 是否启用 */
154
+ get enabled() {
155
+ return this.#e.enabled;
156
+ }
157
+ constructor(e = {}) {
158
+ this.#e = { ...g, ...e }, this.#c = new E(this.#e.maxBufferSize), this.#t = new T();
159
+ }
160
+ /** 初始化连接 */
161
+ init(e, t) {
162
+ !this.#e.enabled || typeof window > "u" || this.#r.has(e) || (this.#d(), this.#u(), this.#r.add(e), t && (this.#a = t), this.#m(e));
163
+ }
164
+ /** 断开连接 */
165
+ disconnect() {
166
+ if (!(typeof window > "u")) {
167
+ this.#n(i("DISCONNECT", "page-to-devtools", null, this.#t.next())), this.#o && (window.removeEventListener("message", this.#o), this.#o = null);
168
+ for (const e of this.#r)
169
+ this.#C(e);
170
+ this.#r.clear(), this.#s = !1, this.#c.clear(), this.#t.reset();
171
+ }
172
+ }
173
+ /** 设置消息监听器 */
174
+ #d() {
175
+ this.#o = (e) => {
176
+ if (e.source !== window || !N(e.data)) return;
177
+ const t = e.data;
178
+ t.direction === "devtools-to-page" && this.#E(t);
179
+ }, window.addEventListener("message", this.#o);
180
+ }
181
+ /** 处理来自 DevTools 的消息 */
182
+ #E(e) {
183
+ switch (e.type) {
184
+ case "HANDSHAKE_ACK":
185
+ this.#T();
186
+ break;
187
+ case "PING":
188
+ this.#u();
189
+ break;
190
+ case "CLEAR":
191
+ break;
192
+ case "DISCONNECT":
193
+ this.#s = !1;
194
+ break;
195
+ case "INSPECT_DB":
196
+ this.#p();
197
+ break;
198
+ case "QUERY_ENTITY":
199
+ this.#y(e.payload);
200
+ break;
201
+ case "GET_BRANCHES":
202
+ this.#i();
203
+ break;
204
+ case "SWITCH_BRANCH":
205
+ this.#v(e.payload);
206
+ break;
207
+ case "CREATE_BRANCH":
208
+ this.#N(e.payload);
209
+ break;
210
+ }
211
+ }
212
+ /** 发送握手消息 */
213
+ #u() {
214
+ this.#n(i("HANDSHAKE", "page-to-devtools", null, this.#t.next()));
215
+ }
216
+ /** 握手确认处理 */
217
+ #T() {
218
+ this.#s = !0, this.#g();
219
+ }
220
+ /** 处理数据库检查请求 */
221
+ #p() {
222
+ const e = Array.from(this.#r)[0];
223
+ if (!e || !this.#a) {
224
+ this.#n(i("DB_INFO", "page-to-devtools", null, this.#t.next()));
225
+ return;
226
+ }
227
+ const t = [];
228
+ if (e.config?.entities)
229
+ for (const r of e.config.entities) {
230
+ const o = this.#a(r);
231
+ o?.name && t.push({
232
+ name: o.name,
233
+ namespace: o.namespace || "public",
234
+ entityType: r
235
+ });
236
+ }
237
+ const s = {
238
+ version: e.version || "unknown",
239
+ dbName: e.config?.dbName || "unknown",
240
+ entities: t.map((r) => ({ name: r.name, namespace: r.namespace }))
241
+ };
242
+ this.#h = new Map(t.map((r) => [r.name, r.entityType])), this.#n(i("DB_INFO", "page-to-devtools", s, this.#t.next()));
243
+ }
244
+ /** 处理实体查询请求 */
245
+ #y(e) {
246
+ const t = Array.from(this.#r)[0];
247
+ if (!t?.entityManager) {
248
+ this.#n(
249
+ i(
250
+ "ENTITY_DATA",
251
+ "page-to-devtools",
252
+ { entityName: e.entityName, error: "RxDB 未初始化", data: [] },
253
+ this.#t.next()
254
+ )
255
+ );
256
+ return;
257
+ }
258
+ const s = this.#h.get(e.entityName);
259
+ if (!s) {
260
+ this.#n(
261
+ i(
262
+ "ENTITY_DATA",
263
+ "page-to-devtools",
264
+ { entityName: e.entityName, error: `实体 ${e.entityName} 不存在`, data: [] },
265
+ this.#t.next()
266
+ )
267
+ );
268
+ return;
269
+ }
270
+ try {
271
+ const c = t.entityManager.getRepository(s).findAll({
272
+ where: { combinator: "and", rules: [] },
273
+ orderBy: [{ field: "id", sort: "desc" }],
274
+ limit: e.limit || 1e3
275
+ }).subscribe((l) => {
276
+ c.unsubscribe();
277
+ const u = l.map((a) => {
278
+ try {
279
+ return a && typeof a == "object" && "toJSON" in a ? JSON.parse(JSON.stringify(a.toJSON())) : JSON.parse(JSON.stringify(a));
280
+ } catch {
281
+ return { id: a?.id, _error: "Cannot serialize" };
282
+ }
283
+ });
284
+ this.#n(
285
+ i(
286
+ "ENTITY_DATA",
287
+ "page-to-devtools",
288
+ { entityName: e.entityName, error: null, data: u },
289
+ this.#t.next()
290
+ )
291
+ );
292
+ });
293
+ } catch (r) {
294
+ console.error("[RxDB DevTools Connector] Query error:", r), this.#n(
295
+ i(
296
+ "ENTITY_DATA",
297
+ "page-to-devtools",
298
+ { entityName: e.entityName, error: r.message, data: [] },
299
+ this.#t.next()
300
+ )
301
+ );
302
+ }
303
+ }
304
+ /** 处理获取分支列表请求 */
305
+ #i() {
306
+ const e = Array.from(this.#r)[0];
307
+ if (!e?.entityManager) {
308
+ this.#n(i("BRANCHES", "page-to-devtools", [], this.#t.next()));
309
+ return;
310
+ }
311
+ let t = this.#h.get("RxDBBranch");
312
+ if (!t && e.config?.entities && this.#a) {
313
+ for (const s of e.config.entities)
314
+ if (this.#a(s)?.name === "RxDBBranch") {
315
+ t = s, this.#h.set("RxDBBranch", s);
316
+ break;
317
+ }
318
+ }
319
+ if (!t) {
320
+ this.#n(i("BRANCHES", "page-to-devtools", [], this.#t.next()));
321
+ return;
322
+ }
323
+ try {
324
+ const o = e.entityManager.getRepository(t).findAll({
325
+ where: { combinator: "and", rules: [] },
326
+ orderBy: [{ field: "id", sort: "desc" }]
327
+ }).subscribe((c) => {
328
+ o.unsubscribe();
329
+ const l = c.map((u) => {
330
+ const a = u;
331
+ return { id: a.id || "", activated: a.activated || !1 };
332
+ });
333
+ this.#n(i("BRANCHES", "page-to-devtools", l, this.#t.next()));
334
+ });
335
+ } catch (s) {
336
+ console.error("[RxDB DevTools Connector] Get branches error:", s), this.#n(i("BRANCHES", "page-to-devtools", [], this.#t.next()));
337
+ }
338
+ }
339
+ /** 处理切换分支请求 */
340
+ #v(e) {
341
+ const t = Array.from(this.#r)[0];
342
+ if (!t?.versionManager) {
343
+ console.error("[RxDB DevTools Connector] versionManager not available"), this.#i();
344
+ return;
345
+ }
346
+ t.versionManager.switchBranch(e).then(() => {
347
+ this.#i();
348
+ }).catch((s) => {
349
+ console.error("[RxDB DevTools Connector] Switch branch error:", s), this.#i();
350
+ });
351
+ }
352
+ /** 处理创建分支请求 */
353
+ #N(e) {
354
+ const t = Array.from(this.#r)[0];
355
+ if (!t?.versionManager) {
356
+ console.error("[RxDB DevTools Connector] versionManager not available"), this.#i();
357
+ return;
358
+ }
359
+ t.versionManager.createBranch(e).then(() => {
360
+ this.#i();
361
+ }).catch((s) => {
362
+ console.error("[RxDB DevTools Connector] Create branch error:", s), this.#i();
363
+ });
364
+ }
365
+ /** 刷新缓冲区 */
366
+ #g() {
367
+ const e = this.#c.flush();
368
+ for (const t of e)
369
+ this.#f(t);
370
+ }
371
+ /** 订阅 RxDB 事件 */
372
+ #m(e) {
373
+ const t = /* @__PURE__ */ new Map();
374
+ for (const s of m) {
375
+ const r = (o) => {
376
+ this.#_(o);
377
+ };
378
+ e.addEventListener(s, r), t.set(s, r);
379
+ }
380
+ this.#l.set(e, t);
381
+ }
382
+ /** 取消订阅 RxDB 事件 */
383
+ #C(e) {
384
+ const t = this.#l.get(e);
385
+ if (t) {
386
+ for (const [s, r] of t)
387
+ e.removeEventListener(s, r);
388
+ this.#l.delete(e);
389
+ }
390
+ }
391
+ /** 处理 RxDB 事件 */
392
+ #_(e) {
393
+ const t = v(e, this.#t.next());
394
+ this.#s ? this.#f(t) : this.#c.push(t), e.type === "SWITCH_BRANCH_COMMIT" && this.#i();
395
+ }
396
+ /** 发送事件到 DevTools */
397
+ #f(e) {
398
+ const t = i("EVENT", "page-to-devtools", e, e.sequence);
399
+ this.#n(t);
400
+ }
401
+ /** 发送消息到 window */
402
+ #n(e) {
403
+ if (!(typeof window > "u"))
404
+ try {
405
+ window.postMessage(e, "*");
406
+ } catch (t) {
407
+ console.warn(`[${d}] Failed to post message:`, t);
408
+ }
409
+ }
410
+ }
411
+ let h = null;
412
+ function b(n) {
413
+ return h || (h = new C(n)), h;
414
+ }
415
+ function A() {
416
+ h && (h.disconnect(), h = null);
417
+ }
418
+ export {
419
+ C as DevToolsConnector,
420
+ E as EventBuffer,
421
+ d as RXDB_DEVTOOLS_MESSAGE,
422
+ T as SequenceGenerator,
423
+ i as createMessage,
424
+ _ as deserialize,
425
+ b as getDevToolsConnector,
426
+ N as isDevToolsMessage,
427
+ A as resetDevToolsConnector,
428
+ v as serialize
429
+ };
@@ -0,0 +1,17 @@
1
+ /**
2
+ * 序列号生成器
3
+ * 生成单调递增的序列号,用于事件排序
4
+ */
5
+ /**
6
+ * 序列号生成器类
7
+ */
8
+ export declare class SequenceGenerator {
9
+ #private;
10
+ /** 获取当前序列号(不递增) */
11
+ get current(): number;
12
+ /** 获取下一个序列号 */
13
+ next(): number;
14
+ /** 重置序列号 */
15
+ reset(): void;
16
+ }
17
+ //# sourceMappingURL=sequence.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sequence.d.ts","sourceRoot":"","sources":["../src/sequence.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;GAEG;AACH,qBAAa,iBAAiB;;IAG5B,mBAAmB;IACnB,IAAI,OAAO,IAAI,MAAM,CAEpB;IAED,eAAe;IACf,IAAI,IAAI,MAAM;IAId,YAAY;IACZ,KAAK,IAAI,IAAI;CAGd"}
@@ -0,0 +1,14 @@
1
+ import { SerializedEvent } from './types.js';
2
+ /**
3
+ * 序列化 RxDB 事件
4
+ */
5
+ export declare function serialize(event: {
6
+ type: string;
7
+ }, sequence: number): SerializedEvent;
8
+ /**
9
+ * 反序列化事件(主要用于类型转换)
10
+ */
11
+ export declare function deserialize(data: SerializedEvent): SerializedEvent;
12
+ /** 重置事件 ID 计数器(用于测试) */
13
+ export declare function resetEventIdCounter(): void;
14
+ //# sourceMappingURL=serializer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serializer.d.ts","sourceRoot":"","sources":["../src/serializer.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AA8DlD;;GAEG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,EAAE,QAAQ,EAAE,MAAM,GAAG,eAAe,CAWpF;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,eAAe,GAAG,eAAe,CAQlE;AAED,wBAAwB;AACxB,wBAAgB,mBAAmB,IAAI,IAAI,CAE1C"}
@@ -0,0 +1,65 @@
1
+ /**
2
+ * RxDB DevTools 消息协议类型定义
3
+ */
4
+ /** 消息来源标识符 */
5
+ export declare const RXDB_DEVTOOLS_MESSAGE: "@aiao/rxdb-devtools";
6
+ /** 消息方向 */
7
+ export type MessageDirection = 'page-to-devtools' | 'devtools-to-page';
8
+ /** 消息类型 */
9
+ export type MessageType = 'HANDSHAKE' | 'HANDSHAKE_ACK' | 'EVENT' | 'DISCONNECT' | 'CLEAR' | 'PING' | 'PONG' | 'INSPECT_DB' | 'DB_INFO' | 'QUERY_ENTITY' | 'ENTITY_DATA' | 'GET_BRANCHES' | 'BRANCHES' | 'SWITCH_BRANCH' | 'CREATE_BRANCH';
10
+ /** 基础消息结构 */
11
+ export interface DevToolsMessage<T = unknown> {
12
+ source: typeof RXDB_DEVTOOLS_MESSAGE;
13
+ direction: MessageDirection;
14
+ type: MessageType;
15
+ payload: T;
16
+ timestamp: number;
17
+ sequence: number;
18
+ }
19
+ /** 握手消息 */
20
+ export interface HandshakeMessage extends DevToolsMessage<null> {
21
+ type: 'HANDSHAKE';
22
+ direction: 'page-to-devtools';
23
+ }
24
+ /** 握手确认消息 */
25
+ export interface HandshakeAckMessage extends DevToolsMessage<null> {
26
+ type: 'HANDSHAKE_ACK';
27
+ direction: 'devtools-to-page';
28
+ }
29
+ /** 序列化后的事件 */
30
+ export interface SerializedEvent {
31
+ id: string;
32
+ eventType: string;
33
+ timestamp: number;
34
+ sequence: number;
35
+ data: Record<string, unknown>;
36
+ }
37
+ /** 事件消息 */
38
+ export interface EventMessage extends DevToolsMessage<SerializedEvent> {
39
+ type: 'EVENT';
40
+ direction: 'page-to-devtools';
41
+ }
42
+ /** 断开连接消息 */
43
+ export interface DisconnectMessage extends DevToolsMessage<null> {
44
+ type: 'DISCONNECT';
45
+ }
46
+ /** 清除事件消息 */
47
+ export interface ClearMessage extends DevToolsMessage<null> {
48
+ type: 'CLEAR';
49
+ direction: 'devtools-to-page';
50
+ }
51
+ /** Ping 消息 */
52
+ export interface PingMessage extends DevToolsMessage<null> {
53
+ type: 'PING';
54
+ }
55
+ /** Pong 消息 */
56
+ export interface PongMessage extends DevToolsMessage<null> {
57
+ type: 'PONG';
58
+ }
59
+ /** 所有消息类型联合 */
60
+ export type AnyDevToolsMessage = HandshakeMessage | HandshakeAckMessage | EventMessage | DisconnectMessage | ClearMessage | PingMessage | PongMessage | DevToolsMessage<unknown>;
61
+ /** 类型守卫:检查是否为 DevTools 消息 */
62
+ export declare function isDevToolsMessage(data: unknown): data is AnyDevToolsMessage;
63
+ /** 创建消息的工厂函数 */
64
+ export declare function createMessage<T>(type: MessageType, direction: MessageDirection, payload: T, sequence: number): DevToolsMessage<T>;
65
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc;AACd,eAAO,MAAM,qBAAqB,EAAG,qBAA8B,CAAC;AAEpE,WAAW;AACX,MAAM,MAAM,gBAAgB,GAAG,kBAAkB,GAAG,kBAAkB,CAAC;AAEvE,WAAW;AACX,MAAM,MAAM,WAAW,GACnB,WAAW,GACX,eAAe,GACf,OAAO,GACP,YAAY,GACZ,OAAO,GACP,MAAM,GACN,MAAM,GACN,YAAY,GACZ,SAAS,GACT,cAAc,GACd,aAAa,GACb,cAAc,GACd,UAAU,GACV,eAAe,GACf,eAAe,CAAC;AAEpB,aAAa;AACb,MAAM,WAAW,eAAe,CAAC,CAAC,GAAG,OAAO;IAC1C,MAAM,EAAE,OAAO,qBAAqB,CAAC;IACrC,SAAS,EAAE,gBAAgB,CAAC;IAC5B,IAAI,EAAE,WAAW,CAAC;IAClB,OAAO,EAAE,CAAC,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,WAAW;AACX,MAAM,WAAW,gBAAiB,SAAQ,eAAe,CAAC,IAAI,CAAC;IAC7D,IAAI,EAAE,WAAW,CAAC;IAClB,SAAS,EAAE,kBAAkB,CAAC;CAC/B;AAED,aAAa;AACb,MAAM,WAAW,mBAAoB,SAAQ,eAAe,CAAC,IAAI,CAAC;IAChE,IAAI,EAAE,eAAe,CAAC;IACtB,SAAS,EAAE,kBAAkB,CAAC;CAC/B;AAED,cAAc;AACd,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC/B;AAED,WAAW;AACX,MAAM,WAAW,YAAa,SAAQ,eAAe,CAAC,eAAe,CAAC;IACpE,IAAI,EAAE,OAAO,CAAC;IACd,SAAS,EAAE,kBAAkB,CAAC;CAC/B;AAED,aAAa;AACb,MAAM,WAAW,iBAAkB,SAAQ,eAAe,CAAC,IAAI,CAAC;IAC9D,IAAI,EAAE,YAAY,CAAC;CACpB;AAED,aAAa;AACb,MAAM,WAAW,YAAa,SAAQ,eAAe,CAAC,IAAI,CAAC;IACzD,IAAI,EAAE,OAAO,CAAC;IACd,SAAS,EAAE,kBAAkB,CAAC;CAC/B;AAED,cAAc;AACd,MAAM,WAAW,WAAY,SAAQ,eAAe,CAAC,IAAI,CAAC;IACxD,IAAI,EAAE,MAAM,CAAC;CACd;AAED,cAAc;AACd,MAAM,WAAW,WAAY,SAAQ,eAAe,CAAC,IAAI,CAAC;IACxD,IAAI,EAAE,MAAM,CAAC;CACd;AAED,eAAe;AACf,MAAM,MAAM,kBAAkB,GAC1B,gBAAgB,GAChB,mBAAmB,GACnB,YAAY,GACZ,iBAAiB,GACjB,YAAY,GACZ,WAAW,GACX,WAAW,GACX,eAAe,CAAC,OAAO,CAAC,CAAC;AAE7B,6BAA6B;AAC7B,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,IAAI,kBAAkB,CAI3E;AAED,gBAAgB;AAChB,wBAAgB,aAAa,CAAC,CAAC,EAC7B,IAAI,EAAE,WAAW,EACjB,SAAS,EAAE,gBAAgB,EAC3B,OAAO,EAAE,CAAC,EACV,QAAQ,EAAE,MAAM,GACf,eAAe,CAAC,CAAC,CAAC,CASpB"}
package/package.json ADDED
@@ -0,0 +1,31 @@
1
+ {
2
+ "name": "@aiao/rxdb-devtools",
3
+ "version": "0.0.8",
4
+ "type": "module",
5
+ "main": "./dist/index.js",
6
+ "module": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ "./package.json": "./package.json",
10
+ ".": {
11
+ "@aiao/source": "./src/index.ts",
12
+ "types": "./dist/index.d.ts",
13
+ "import": "./dist/index.js",
14
+ "default": "./dist/index.js"
15
+ }
16
+ },
17
+ "files": [
18
+ "dist",
19
+ "!**/*.tsbuildinfo"
20
+ ],
21
+ "publishConfig": {
22
+ "access": "public"
23
+ },
24
+ "nx": {
25
+ "name": "rxdb-devtools",
26
+ "tags": [
27
+ "js-lib"
28
+ ]
29
+ },
30
+ "dependencies": {}
31
+ }