nexabase-console 2.1.6 → 2.1.7

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.
@@ -59,7 +59,6 @@ class NexaApp {
59
59
  if (typeof document !== 'undefined' && typeof document.addEventListener === 'function') {
60
60
  document.addEventListener('visibilitychange', () => {
61
61
  if (document.visibilityState === 'visible') {
62
- // Re-ensure SSE and WS when coming back from background
63
62
  if (this._firestoreListening) {
64
63
  if (this.wsClient && typeof this.wsClient.ensureConnected === 'function') {
65
64
  this.wsClient.ensureConnected();
@@ -67,10 +66,7 @@ class NexaApp {
67
66
  if (this.sseClient && typeof this.sseClient.ensureConnected === 'function') {
68
67
  this.sseClient.ensureConnected();
69
68
  }
70
- // Notify server that we need latest changes by simulating subscribe again for each path?
71
- // wsClient handles this on resync event.
72
69
  }
73
- // Optionally sync offline queue
74
70
  this._syncOfflineQueue().catch(console.error);
75
71
  }
76
72
  });
@@ -80,10 +76,10 @@ class NexaApp {
80
76
  this.syncEngine.listenCrossTab((path, action, data) => {
81
77
  const cleanPath = path.replace(/^\/+|\/+$/g, '');
82
78
  if (action === 'delete') {
83
- this.localStore.delete(cleanPath);
79
+ this._deleteCache(cleanPath);
84
80
  }
85
- else if (data) {
86
- this.localStore.set(cleanPath, data);
81
+ else if (data !== undefined && data !== null) {
82
+ this._setCache(cleanPath, data);
87
83
  }
88
84
  this._notifySnapshotCallbacks(cleanPath, action === 'delete' ? 'document_deleted' : 'document_written', data);
89
85
  const parts = cleanPath.split('/');
@@ -7,6 +7,7 @@ export declare class SyncEngine {
7
7
  private broadcastChannel;
8
8
  constructor(projectId: string, mutationQueue: MutationQueue, sseClient: SSEClient);
9
9
  private initCrossTabSync;
10
+ private _serializeForBroadcast;
10
11
  broadcastLocalMutation(path: string, action: string, data?: any): void;
11
12
  listenCrossTab(onMutation: (path: string, action: string, data?: any) => void): () => void;
12
13
  syncOfflineMutations(): Promise<void>;
@@ -19,10 +19,48 @@ class SyncEngine {
19
19
  }
20
20
  }
21
21
  }
22
+ _serializeForBroadcast(data, seen = new WeakSet()) {
23
+ if (data === null || data === undefined)
24
+ return data;
25
+ if (typeof data === 'boolean' || typeof data === 'number' || typeof data === 'string')
26
+ return data;
27
+ if (data instanceof Date) {
28
+ return { __nexa_type__: 'timestamp', seconds: Math.floor(data.getTime() / 1000), nanoseconds: (data.getTime() % 1000) * 1000000 };
29
+ }
30
+ // Check if it's a Timestamp object (even without prototype due to potential prior cloning)
31
+ if (typeof data === 'object' && 'seconds' in data && 'nanoseconds' in data && typeof data.seconds === 'number' && typeof data.nanoseconds === 'number') {
32
+ return { __nexa_type__: 'timestamp', seconds: data.seconds, nanoseconds: data.nanoseconds };
33
+ }
34
+ // Check for GeoPoint
35
+ if (typeof data === 'object' && 'latitude' in data && 'longitude' in data && typeof data.latitude === 'number' && typeof data.longitude === 'number') {
36
+ return { __nexa_type__: 'geopoint', latitude: data.latitude, longitude: data.longitude };
37
+ }
38
+ if (Array.isArray(data)) {
39
+ if (seen.has(data))
40
+ return null;
41
+ seen.add(data);
42
+ const res = data.map(item => this._serializeForBroadcast(item, seen));
43
+ seen.delete(data);
44
+ return res;
45
+ }
46
+ if (typeof data === 'object') {
47
+ if (seen.has(data))
48
+ return null;
49
+ seen.add(data);
50
+ const res = {};
51
+ for (const key of Object.keys(data)) {
52
+ res[key] = this._serializeForBroadcast(data[key], seen);
53
+ }
54
+ seen.delete(data);
55
+ return res;
56
+ }
57
+ return data;
58
+ }
22
59
  broadcastLocalMutation(path, action, data) {
23
60
  if (this.broadcastChannel) {
24
61
  try {
25
- this.broadcastChannel.postMessage({ type: 'LOCAL_MUTATION', path, action, data });
62
+ const serialized = this._serializeForBroadcast(data);
63
+ this.broadcastChannel.postMessage({ type: 'LOCAL_MUTATION', path, action, data: serialized });
26
64
  }
27
65
  catch (e) { }
28
66
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nexabase-console",
3
- "version": "2.1.6",
3
+ "version": "2.1.7",
4
4
  "description": "SDK Client resmi untuk NexaBase: Platform Sinkronisasi NoSQL, Realtime, File Storage, & Autentikasi Offline-First.",
5
5
  "main": "dist/index.cjs",
6
6
  "module": "dist/index.js",