supastash 0.1.9 → 0.1.11
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/README.md +20 -16
- package/dist/hooks/supastashData/fetchCalls.d.ts.map +1 -1
- package/dist/hooks/supastashData/fetchCalls.js +2 -1
- package/dist/hooks/supastashData/realtimeSubscription.d.ts.map +1 -1
- package/dist/hooks/supastashData/realtimeSubscription.js +2 -1
- package/dist/hooks/supastashLogic.d.ts.map +1 -1
- package/dist/hooks/supastashLogic.js +4 -3
- package/dist/utils/fetchData/deleteData.d.ts.map +1 -1
- package/dist/utils/fetchData/deleteData.js +2 -1
- package/dist/utils/fetchData/fetchLocalData.d.ts.map +1 -1
- package/dist/utils/fetchData/fetchLocalData.js +4 -4
- package/dist/utils/fetchData/initialFetch.d.ts.map +1 -1
- package/dist/utils/fetchData/initialFetch.js +2 -1
- package/dist/utils/fetchData/realTimeCall.d.ts.map +1 -1
- package/dist/utils/fetchData/realTimeCall.js +2 -1
- package/dist/utils/fetchData/realTimeManager.js +2 -2
- package/dist/utils/fetchData/receiveData.js +2 -2
- package/dist/utils/logs.d.ts +7 -0
- package/dist/utils/logs.d.ts.map +1 -1
- package/dist/utils/logs.js +19 -0
- package/dist/utils/query/builder/mainQuery.d.ts.map +1 -1
- package/dist/utils/query/builder/mainQuery.js +2 -1
- package/dist/utils/query/helpers/mainQueryHelpers.js +4 -4
- package/dist/utils/query/localDbQuery/delete.d.ts.map +1 -1
- package/dist/utils/query/localDbQuery/delete.js +3 -2
- package/dist/utils/query/localDbQuery/insert.d.ts.map +1 -1
- package/dist/utils/query/localDbQuery/insert.js +2 -1
- package/dist/utils/query/localDbQuery/select.d.ts.map +1 -1
- package/dist/utils/query/localDbQuery/select.js +2 -1
- package/dist/utils/query/localDbQuery/update.d.ts.map +1 -1
- package/dist/utils/query/localDbQuery/update.js +3 -2
- package/dist/utils/query/localDbQuery/upsert.d.ts.map +1 -1
- package/dist/utils/query/localDbQuery/upsert.js +3 -2
- package/dist/utils/schema/createSyncStatus.d.ts.map +1 -1
- package/dist/utils/schema/createSyncStatus.js +5 -0
- package/dist/utils/sync/pullFromRemote/getLastCreatedInfo.d.ts +13 -0
- package/dist/utils/sync/pullFromRemote/getLastCreatedInfo.d.ts.map +1 -0
- package/dist/utils/sync/pullFromRemote/getLastCreatedInfo.js +34 -0
- package/dist/utils/sync/pullFromRemote/getLastDeletedInfo.d.ts.map +1 -1
- package/dist/utils/sync/pullFromRemote/getLastDeletedInfo.js +6 -1
- package/dist/utils/sync/pullFromRemote/getLastPulledInfo.d.ts.map +1 -1
- package/dist/utils/sync/pullFromRemote/getLastPulledInfo.js +6 -1
- package/dist/utils/sync/pullFromRemote/pullData.d.ts.map +1 -1
- package/dist/utils/sync/pullFromRemote/pullData.js +46 -15
- package/dist/utils/sync/pullFromRemote/updateLocalDb.d.ts.map +1 -1
- package/dist/utils/sync/pullFromRemote/updateLocalDb.js +16 -17
- package/dist/utils/sync/pushLocal/sendUnsyncedToSupabase.d.ts.map +1 -1
- package/dist/utils/sync/pushLocal/sendUnsyncedToSupabase.js +2 -1
- package/dist/utils/sync/pushLocal/uploadChunk.js +2 -2
- package/dist/utils/syncStatus.d.ts.map +1 -1
- package/dist/utils/syncStatus.js +2 -0
- package/dist/utils/syncUpdate.d.ts.map +1 -1
- package/dist/utils/syncUpdate.js +2 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
# Supastash
|
|
2
2
|
|
|
3
|
+
[](https://www.npmjs.com/package/supastash)
|
|
4
|
+
|
|
3
5
|
**Offline-First Sync Engine for Supabase + React Native**
|
|
4
6
|
|
|
5
|
-
> Sync
|
|
7
|
+
> Sync between SQLite and Supabase in real-time — even when your app is offline. Built for React Native, no boilerplate required.
|
|
6
8
|
|
|
7
|
-
Supastash gives your app **instant offline access**, **two-way
|
|
9
|
+
Supastash gives your app **instant offline access**, **two-way sync**, and **real-time updates** — with local database as the source of truth.
|
|
8
10
|
|
|
9
11
|
---
|
|
10
12
|
|
|
@@ -56,6 +58,8 @@ npm install react-native-sqlite-storage
|
|
|
56
58
|
|
|
57
59
|
## ⚙️ Quick Setup
|
|
58
60
|
|
|
61
|
+
Initialize once, use anywhere
|
|
62
|
+
|
|
59
63
|
```ts
|
|
60
64
|
// lib/supastash.ts
|
|
61
65
|
import { configureSupastash, defineLocalSchema } from "supastash";
|
|
@@ -85,7 +89,11 @@ configureSupastash({
|
|
|
85
89
|
debugMode: true,
|
|
86
90
|
syncEngine: {
|
|
87
91
|
push: true,
|
|
88
|
-
pull: false, // enable if using RLS
|
|
92
|
+
pull: false, // enable if using RLS and want to pull filtered data
|
|
93
|
+
},
|
|
94
|
+
excludeTables: {
|
|
95
|
+
push: ["daily_reminders"],
|
|
96
|
+
pull: ["daily_reminders"],
|
|
89
97
|
},
|
|
90
98
|
});
|
|
91
99
|
```
|
|
@@ -95,8 +103,13 @@ Then in your root layout:
|
|
|
95
103
|
```ts
|
|
96
104
|
// App.tsx or _layout.tsx
|
|
97
105
|
import "@/lib/supastash";
|
|
106
|
+
import { useSupatash } from "supastash";
|
|
98
107
|
|
|
99
108
|
export default function App() {
|
|
109
|
+
const { dbReady } = useSupatash();
|
|
110
|
+
|
|
111
|
+
if (!dbReady) return null;
|
|
112
|
+
|
|
100
113
|
return <Stack />;
|
|
101
114
|
}
|
|
102
115
|
```
|
|
@@ -106,7 +119,7 @@ export default function App() {
|
|
|
106
119
|
## 🚨 Important Notes
|
|
107
120
|
|
|
108
121
|
- Timestamp fields (`created_at`, `updated_at`, `deleted_at`) **must be `timestamptz`** in Supabase
|
|
109
|
-
- Every synced table must have a valid `id`
|
|
122
|
+
- Every synced table must have a valid `id` column
|
|
110
123
|
- Create this SQL function in Supabase to allow schema reflection:
|
|
111
124
|
|
|
112
125
|
```sql
|
|
@@ -142,15 +155,6 @@ const { data: userOrders } = useSupatashData("orders", {
|
|
|
142
155
|
});
|
|
143
156
|
```
|
|
144
157
|
|
|
145
|
-
Ensure sync engine is ready:
|
|
146
|
-
|
|
147
|
-
```tsx
|
|
148
|
-
import { useSupatash } from "supastash";
|
|
149
|
-
|
|
150
|
-
const { dbReady } = useSupatash();
|
|
151
|
-
if (!dbReady) return null;
|
|
152
|
-
```
|
|
153
|
-
|
|
154
158
|
---
|
|
155
159
|
|
|
156
160
|
## 🔧 API Overview
|
|
@@ -172,10 +176,10 @@ if (!dbReady) return null;
|
|
|
172
176
|
## 🧩 Sync Modes (via query builder)
|
|
173
177
|
|
|
174
178
|
```ts
|
|
175
|
-
supastash
|
|
179
|
+
await supastash
|
|
176
180
|
.from("orders")
|
|
177
|
-
.
|
|
178
|
-
.syncMode("
|
|
181
|
+
.update({ status: "Dropped-off" })
|
|
182
|
+
.syncMode("localFirst") // or localOnly, remoteOnly, remoteFirst
|
|
179
183
|
.run();
|
|
180
184
|
```
|
|
181
185
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fetchCalls.d.ts","sourceRoot":"","sources":["../../../src/hooks/supastashData/fetchCalls.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;
|
|
1
|
+
{"version":3,"file":"fetchCalls.d.ts","sourceRoot":"","sources":["../../../src/hooks/supastashData/fetchCalls.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AAKjE,wBAAgB,UAAU,CAAC,CAAC,EAC1B,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,eAAe,CAAC,CAAC,CAAC,EAC3B,WAAW,EAAE,KAAK,CAAC,SAAS,CAAC,OAAO,CAAC;;;;;EAsEtC"}
|
|
@@ -3,6 +3,7 @@ import { syncCalls } from "../../store/syncCalls";
|
|
|
3
3
|
import { tableFilters } from "../../store/tableFilters";
|
|
4
4
|
import { fetchLocalData } from "../../utils/fetchData/fetchLocalData";
|
|
5
5
|
import { initialFetch } from "../../utils/fetchData/initialFetch";
|
|
6
|
+
import { logError } from "../../utils/logs";
|
|
6
7
|
export function fetchCalls(table, options, initialized) {
|
|
7
8
|
const { shouldFetch = true, limit, filter, onPushToRemote, onInsertAndUpdate, useFilterWhileSyncing = true, extraMapKeys, daylength, } = options;
|
|
8
9
|
const cancelled = useRef(false);
|
|
@@ -49,7 +50,7 @@ export function fetchCalls(table, options, initialized) {
|
|
|
49
50
|
await fetch();
|
|
50
51
|
}
|
|
51
52
|
catch (error) {
|
|
52
|
-
|
|
53
|
+
logError(`[Supastash] Error on initial fetch for ${table}`, error);
|
|
53
54
|
}
|
|
54
55
|
};
|
|
55
56
|
return {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"realtimeSubscription.d.ts","sourceRoot":"","sources":["../../../src/hooks/supastashData/realtimeSubscription.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACtD,OAAO,EACL,eAAe,EACf,cAAc,EACf,MAAM,gCAAgC,CAAC;
|
|
1
|
+
{"version":3,"file":"realtimeSubscription.d.ts","sourceRoot":"","sources":["../../../src/hooks/supastashData/realtimeSubscription.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACtD,OAAO,EACL,eAAe,EACf,cAAc,EACf,MAAM,gCAAgC,CAAC;AAQxC,iBAAS,uBAAuB,CAC9B,KAAK,EAAE,MAAM,EACb,YAAY,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,KAAK,IAAI,EAC5D,OAAO,EAAE,eAAe,EACxB,WAAW,EAAE,OAAO,EACpB,QAAQ,EAAE,OAAO,kBAyGlB;AAED,eAAe,uBAAuB,CAAC"}
|
|
@@ -4,6 +4,7 @@ import { useCallback, useEffect, useRef } from "react";
|
|
|
4
4
|
import { getSupastashConfig } from "../../core/config";
|
|
5
5
|
import { buildFilterString } from "../../utils/fetchData/buildFilter";
|
|
6
6
|
import { RealtimeManager } from "../../utils/fetchData/realTimeManager";
|
|
7
|
+
import { logError } from "../../utils/logs";
|
|
7
8
|
import { supabaseClientErr } from "../../utils/supabaseClientErr";
|
|
8
9
|
const generateHookId = () => `hook_${Date.now()}_${Math.random().toString(36)}`;
|
|
9
10
|
function useRealtimeSubscription(table, queueHandler, options, initialized, realtime) {
|
|
@@ -58,7 +59,7 @@ function useRealtimeSubscription(table, queueHandler, options, initialized, real
|
|
|
58
59
|
}, [table, hookId, options.filter]);
|
|
59
60
|
useEffect(() => {
|
|
60
61
|
if (!supabase) {
|
|
61
|
-
|
|
62
|
+
logError("[Supastash] No supabase client found", supabaseClientErr);
|
|
62
63
|
return;
|
|
63
64
|
}
|
|
64
65
|
const filterString = options.filter
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"supastashLogic.d.ts","sourceRoot":"","sources":["../../src/hooks/supastashLogic.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;
|
|
1
|
+
{"version":3,"file":"supastashLogic.d.ts","sourceRoot":"","sources":["../../src/hooks/supastashLogic.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AAQrE;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,YAAY,IAAI,mBAAmB,CA6DlD"}
|
|
@@ -2,6 +2,7 @@ import { useEffect, useRef, useState } from "react";
|
|
|
2
2
|
import { getSupastashConfig } from "../core/config";
|
|
3
3
|
import { supastashDbErrorMsg } from "../db/dbErrorMsg";
|
|
4
4
|
import { useSyncEngine } from "../hooks/syncEngine";
|
|
5
|
+
import { logError } from "../utils/logs";
|
|
5
6
|
import { createDeletedStatusTable, createSyncStatusTable, } from "../utils/schema/createSyncStatus";
|
|
6
7
|
import { supabaseClientErr } from "../utils/supabaseClientErr";
|
|
7
8
|
/**
|
|
@@ -25,7 +26,7 @@ export function useSupastash() {
|
|
|
25
26
|
const initialized = useRef(false);
|
|
26
27
|
const config = getSupastashConfig();
|
|
27
28
|
if (!config.sqliteClient || !config.sqliteClientType) {
|
|
28
|
-
|
|
29
|
+
logError(`
|
|
29
30
|
[Supastash] ${supastashDbErrorMsg}`);
|
|
30
31
|
return {
|
|
31
32
|
dbReady: false,
|
|
@@ -34,7 +35,7 @@ export function useSupastash() {
|
|
|
34
35
|
};
|
|
35
36
|
}
|
|
36
37
|
if (!config.supabaseClient) {
|
|
37
|
-
|
|
38
|
+
logError(`[Supastash] Add a supabase client to config ${supabaseClientErr}`);
|
|
38
39
|
return {
|
|
39
40
|
dbReady: false,
|
|
40
41
|
startSync: () => { },
|
|
@@ -57,7 +58,7 @@ export function useSupastash() {
|
|
|
57
58
|
setDbReady(true);
|
|
58
59
|
}
|
|
59
60
|
catch (error) {
|
|
60
|
-
|
|
61
|
+
logError(`[Supastash] Error initializing: ${error}`);
|
|
61
62
|
}
|
|
62
63
|
}
|
|
63
64
|
init();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"deleteData.d.ts","sourceRoot":"","sources":["../../../src/utils/fetchData/deleteData.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"deleteData.d.ts","sourceRoot":"","sources":["../../../src/utils/fetchData/deleteData.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAOtD,wBAAsB,UAAU,CAC9B,OAAO,EAAE,WAAW,EACpB,KAAK,EAAE,MAAM,EACb,WAAW,GAAE,OAAc,iBAqB5B"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { permanentlyDeleteData } from "../../utils/query/localDbQuery/delete";
|
|
2
2
|
import { checkIfTableExist } from "../../utils/tableValidator";
|
|
3
|
+
import { logError } from "../logs";
|
|
3
4
|
import { refreshScreen } from "../refreshScreenCalls";
|
|
4
5
|
import { createTable } from "./createTable";
|
|
5
6
|
export async function deleteData(payload, table, shouldFetch = true) {
|
|
@@ -19,6 +20,6 @@ export async function deleteData(payload, table, shouldFetch = true) {
|
|
|
19
20
|
refreshScreen(table);
|
|
20
21
|
}
|
|
21
22
|
catch (error) {
|
|
22
|
-
|
|
23
|
+
logError("[Supastash] Error receiving data:", error);
|
|
23
24
|
}
|
|
24
25
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fetchLocalData.d.ts","sourceRoot":"","sources":["../../../src/utils/fetchData/fetchLocalData.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AA0DtD;;;;;;GAMG;AACH,wBAAsB,cAAc,CAAC,CAAC,EACpC,KAAK,EAAE,MAAM,EACb,WAAW,GAAE,OAAc,EAC3B,KAAK,GAAE,MAAY,EACnB,YAAY,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,EAAE,EAC1B,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC;IACT,IAAI,EAAE,WAAW,EAAE,CAAC;IACpB,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IAClC,SAAS,EAAE;SACR,CAAC,IAAI,MAAM,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,WAAW,CAAC,CAAC;KAC9C,CAAC;CACH,GAAG,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"fetchLocalData.d.ts","sourceRoot":"","sources":["../../../src/utils/fetchData/fetchLocalData.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AA0DtD;;;;;;GAMG;AACH,wBAAsB,cAAc,CAAC,CAAC,EACpC,KAAK,EAAE,MAAM,EACb,WAAW,GAAE,OAAc,EAC3B,KAAK,GAAE,MAAY,EACnB,YAAY,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,EAAE,EAC1B,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC;IACT,IAAI,EAAE,WAAW,EAAE,CAAC;IACpB,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IAClC,SAAS,EAAE;SACR,CAAC,IAAI,MAAM,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,WAAW,CAAC,CAAC;KAC9C,CAAC;CACH,GAAG,IAAI,CAAC,CA6ER"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { getSupastashDb } from "../../db/dbInitializer";
|
|
2
2
|
import { localCache } from "../../store/localCache";
|
|
3
|
-
import log from "../logs";
|
|
3
|
+
import log, { logError, logWarn } from "../logs";
|
|
4
4
|
import { notifySubscribers } from "./snapShot";
|
|
5
5
|
const fetchingPromises = new Map();
|
|
6
6
|
const versionMap = new Map();
|
|
@@ -27,7 +27,7 @@ function getNewVersion(table) {
|
|
|
27
27
|
clearTimeout(debounceMap.get(table));
|
|
28
28
|
const timeout = setTimeout(() => {
|
|
29
29
|
if (queue.length > 10) {
|
|
30
|
-
|
|
30
|
+
logWarn(`[Supastash] Table "${table}" is noisy: ${queue.length} events in ${timeoutMs}ms`);
|
|
31
31
|
}
|
|
32
32
|
versionMap.delete(table);
|
|
33
33
|
notifySubscribers(table);
|
|
@@ -75,7 +75,7 @@ export async function fetchLocalData(table, shouldFetch = true, limit = 200, ext
|
|
|
75
75
|
if (extraMapKeys?.length) {
|
|
76
76
|
for (const key of extraMapKeys) {
|
|
77
77
|
if (item[key] == null) {
|
|
78
|
-
|
|
78
|
+
logWarn(`[Supastash] Item ${item.id} has no ${String(key)} field`);
|
|
79
79
|
continue;
|
|
80
80
|
}
|
|
81
81
|
const groupVal = item[key];
|
|
@@ -96,7 +96,7 @@ export async function fetchLocalData(table, shouldFetch = true, limit = 200, ext
|
|
|
96
96
|
return { data, dataMap, groupedBy };
|
|
97
97
|
}
|
|
98
98
|
catch (error) {
|
|
99
|
-
|
|
99
|
+
logError(`[Supastash] Error fetching local data for ${table}:`, error);
|
|
100
100
|
return null;
|
|
101
101
|
}
|
|
102
102
|
})();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"initialFetch.d.ts","sourceRoot":"","sources":["../../../src/utils/fetchData/initialFetch.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;
|
|
1
|
+
{"version":3,"file":"initialFetch.d.ts","sourceRoot":"","sources":["../../../src/utils/fetchData/initialFetch.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAQhE,wBAAsB,YAAY,CAChC,KAAK,EAAE,MAAM,EACb,MAAM,CAAC,EAAE,cAAc,EACvB,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,KAAK,OAAO,CAAC,IAAI,CAAC,EAC/C,cAAc,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,KAAK,OAAO,CAAC,OAAO,CAAC,iBAatD"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { logError } from "../logs";
|
|
1
2
|
import { updateLocalDb } from "../sync/pullFromRemote/updateLocalDb";
|
|
2
3
|
import { pushLocalDataToRemote } from "../sync/pushLocal/sendUnsyncedToSupabase";
|
|
3
4
|
import { createTable } from "./createTable";
|
|
@@ -12,7 +13,7 @@ export async function initialFetch(table, filter, onReceiveData, onPushToRemote)
|
|
|
12
13
|
await pushLocalDataToRemote(table, onPushToRemote);
|
|
13
14
|
}
|
|
14
15
|
catch (error) {
|
|
15
|
-
|
|
16
|
+
logError(`[Supastash] Error on initial fetch for ${table}`, error);
|
|
16
17
|
}
|
|
17
18
|
finally {
|
|
18
19
|
isInSync.delete(table);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"realTimeCall.d.ts","sourceRoot":"","sources":["../../../src/utils/fetchData/realTimeCall.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;
|
|
1
|
+
{"version":3,"file":"realTimeCall.d.ts","sourceRoot":"","sources":["../../../src/utils/fetchData/realTimeCall.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AAOjE,QAAA,MAAM,eAAe,GACnB,OAAO,MAAM,EACb,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,KAAK,IAAI,EAC5D,SAAS,eAAe,EACxB,aAAa,OAAO,EACpB,UAAU,OAAO,SA0ClB,CAAC;AAEF,eAAe,eAAe,CAAC"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { useEffect, useMemo } from "react";
|
|
2
2
|
import { getSupastashConfig } from "../../core/config";
|
|
3
|
+
import { logError } from "../logs";
|
|
3
4
|
import { supabaseClientErr } from "../supabaseClientErr";
|
|
4
5
|
import { buildFilterString } from "./buildFilter";
|
|
5
6
|
const hasRegistered = new Map();
|
|
@@ -15,7 +16,7 @@ const useRealtimeData = (table, queueHandler, options, initialized, realtime) =>
|
|
|
15
16
|
return;
|
|
16
17
|
const supabase = getSupastashConfig().supabaseClient;
|
|
17
18
|
if (!supabase) {
|
|
18
|
-
|
|
19
|
+
logError("[Supastash] No supabase client found", supabaseClientErr);
|
|
19
20
|
return;
|
|
20
21
|
}
|
|
21
22
|
hasRegistered.set(subKey, true);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// DEPRECATED: Use useRealtimeData instead
|
|
2
2
|
import { getSupastashConfig } from "../../core/config";
|
|
3
|
-
import log from "../logs";
|
|
3
|
+
import log, { logError } from "../logs";
|
|
4
4
|
import { supabaseClientErr } from "../supabaseClientErr";
|
|
5
5
|
class SupastashRealtimeManager {
|
|
6
6
|
constructor() {
|
|
@@ -29,7 +29,7 @@ class SupastashRealtimeManager {
|
|
|
29
29
|
async createConnection() {
|
|
30
30
|
const supabase = getSupastashConfig().supabaseClient;
|
|
31
31
|
if (!supabase) {
|
|
32
|
-
|
|
32
|
+
logError("[Supastash] No supabase client found", supabaseClientErr);
|
|
33
33
|
return null;
|
|
34
34
|
}
|
|
35
35
|
if (this.connection) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { getSupastashDb } from "../../db/dbInitializer";
|
|
2
2
|
import { upsertData } from "../../utils/sync/pullFromRemote/updateLocalDb";
|
|
3
3
|
import { checkIfTableExist } from "../../utils/tableValidator";
|
|
4
|
-
import log from "../logs";
|
|
4
|
+
import log, { logError } from "../logs";
|
|
5
5
|
import { refreshScreen } from "../refreshScreenCalls";
|
|
6
6
|
import { createTable } from "./createTable";
|
|
7
7
|
const DEFAULT_DATE = "1970-01-01T00:00:00Z";
|
|
@@ -34,6 +34,6 @@ export async function receiveData(payload, table, shouldFetch = true, upsertCall
|
|
|
34
34
|
refreshScreen(table);
|
|
35
35
|
}
|
|
36
36
|
catch (error) {
|
|
37
|
-
|
|
37
|
+
logError("[Supastash] Error receiving data:", error);
|
|
38
38
|
}
|
|
39
39
|
}
|
package/dist/utils/logs.d.ts
CHANGED
|
@@ -4,4 +4,11 @@
|
|
|
4
4
|
*/
|
|
5
5
|
declare const log: (...args: any[]) => void;
|
|
6
6
|
export default log;
|
|
7
|
+
/**
|
|
8
|
+
* Logs an error to the console if debug mode is enabled
|
|
9
|
+
* @param args - The arguments to log
|
|
10
|
+
*/
|
|
11
|
+
declare const logError: (...args: any[]) => void;
|
|
12
|
+
declare const logWarn: (...args: any[]) => void;
|
|
13
|
+
export { log, logError, logWarn };
|
|
7
14
|
//# sourceMappingURL=logs.d.ts.map
|
package/dist/utils/logs.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logs.d.ts","sourceRoot":"","sources":["../../src/utils/logs.ts"],"names":[],"mappings":"AAIA;;;GAGG;AACH,QAAA,MAAM,GAAG,GAAI,GAAG,MAAM,GAAG,EAAE,SAM1B,CAAC;AAEF,eAAe,GAAG,CAAC"}
|
|
1
|
+
{"version":3,"file":"logs.d.ts","sourceRoot":"","sources":["../../src/utils/logs.ts"],"names":[],"mappings":"AAIA;;;GAGG;AACH,QAAA,MAAM,GAAG,GAAI,GAAG,MAAM,GAAG,EAAE,SAM1B,CAAC;AAEF,eAAe,GAAG,CAAC;AAEnB;;;GAGG;AACH,QAAA,MAAM,QAAQ,GAAI,GAAG,MAAM,GAAG,EAAE,SAK/B,CAAC;AAEF,QAAA,MAAM,OAAO,GAAI,GAAG,MAAM,GAAG,EAAE,SAK9B,CAAC;AAEF,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC"}
|
package/dist/utils/logs.js
CHANGED
|
@@ -13,3 +13,22 @@ const log = (...args) => {
|
|
|
13
13
|
}
|
|
14
14
|
};
|
|
15
15
|
export default log;
|
|
16
|
+
/**
|
|
17
|
+
* Logs an error to the console if debug mode is enabled
|
|
18
|
+
* @param args - The arguments to log
|
|
19
|
+
*/
|
|
20
|
+
const logError = (...args) => {
|
|
21
|
+
if (!DEBUG_MODE)
|
|
22
|
+
return;
|
|
23
|
+
if (typeof console !== "undefined" && console.error) {
|
|
24
|
+
Function.prototype.apply.call(console.error, console, args);
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
const logWarn = (...args) => {
|
|
28
|
+
if (!DEBUG_MODE)
|
|
29
|
+
return;
|
|
30
|
+
if (typeof console !== "undefined" && console.warn) {
|
|
31
|
+
Function.prototype.apply.call(console.warn, console, args);
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
export { log, logError, logWarn };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mainQuery.d.ts","sourceRoot":"","sources":["../../../../src/utils/query/builder/mainQuery.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,WAAW,EAGX,cAAc,EACd,oBAAoB,EACrB,MAAM,4BAA4B,CAAC;
|
|
1
|
+
{"version":3,"file":"mainQuery.d.ts","sourceRoot":"","sources":["../../../../src/utils/query/builder/mainQuery.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,WAAW,EAGX,cAAc,EACd,oBAAoB,EACrB,MAAM,4BAA4B,CAAC;AAWpC;;;;GAIG;AACH,wBAAsB,OAAO,CAC3B,CAAC,SAAS,WAAW,EACrB,CAAC,SAAS,OAAO,EACjB,CAAC,SAAS,OAAO,EACjB,CAAC,EACD,CAAC,EAED,KAAK,EAAE,cAAc,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,GAAG;IAAE,gBAAgB,EAAE,CAAC,CAAA;CAAE,GACvD,OAAO,CAAC,oBAAoB,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CA2E3C"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { logError } from "../../logs";
|
|
1
2
|
import { refreshScreen } from "../../refreshScreenCalls";
|
|
2
3
|
import { assignInsertIds, getCommonError, runSyncStrategy, validatePayloadForSingleInsert, } from "../helpers/mainQueryHelpers";
|
|
3
4
|
import { validateQuery } from "../helpers/queryValidator";
|
|
@@ -41,7 +42,7 @@ export async function queryDb(state) {
|
|
|
41
42
|
});
|
|
42
43
|
}
|
|
43
44
|
catch (error) {
|
|
44
|
-
|
|
45
|
+
logError(`[Supastash] ${error instanceof Error ? error.message : String(error)}`);
|
|
45
46
|
if (state.viewRemoteResult) {
|
|
46
47
|
return Promise.resolve({
|
|
47
48
|
remote: null,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { isOnline } from "../../../utils/connection";
|
|
2
|
-
import log from "../../../utils/logs";
|
|
2
|
+
import log, { logError } from "../../../utils/logs";
|
|
3
3
|
import { generateUUIDv4 } from "../../genUUID";
|
|
4
4
|
import { queryLocalDb } from "../localDbQuery";
|
|
5
5
|
import { querySupabase } from "../remoteQuery/supabaseQuery";
|
|
@@ -68,7 +68,7 @@ async function runBatchedRemoteQuery() {
|
|
|
68
68
|
const state = stateCache.shift();
|
|
69
69
|
if (calledOfflineRetries.get(state.id) &&
|
|
70
70
|
calledOfflineRetries.get(state.id) >= MAX_OFFLINE_RETRIES) {
|
|
71
|
-
|
|
71
|
+
logError(`[Supastash] Failed to send remote batch query:\n` +
|
|
72
72
|
` Table: ${state.table}\n` +
|
|
73
73
|
` Method: ${state.method}\n` +
|
|
74
74
|
` Retries: ${MAX_OFFLINE_RETRIES}\n` +
|
|
@@ -108,7 +108,7 @@ async function runBatchedRemoteQuery() {
|
|
|
108
108
|
continue;
|
|
109
109
|
}
|
|
110
110
|
else {
|
|
111
|
-
|
|
111
|
+
logError(`[Supastash] Remote sync failed on ${state.table} with ${state.method} after ${retryCount + 1} tries: ${error.message}`);
|
|
112
112
|
}
|
|
113
113
|
}
|
|
114
114
|
}
|
|
@@ -124,7 +124,7 @@ function addToCache(state) {
|
|
|
124
124
|
clearTimeout(batchTimer);
|
|
125
125
|
batchTimer = setTimeout(() => {
|
|
126
126
|
runBatchedRemoteQuery();
|
|
127
|
-
},
|
|
127
|
+
}, 200);
|
|
128
128
|
}
|
|
129
129
|
export async function runSyncStrategy(state) {
|
|
130
130
|
const { type } = state;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"delete.d.ts","sourceRoot":"","sources":["../../../../src/utils/query/localDbQuery/delete.ts"],"names":[],"mappings":"AACA,OAAO,EACL,WAAW,EACX,oBAAoB,EACpB,QAAQ,EACT,MAAM,4BAA4B,CAAC;
|
|
1
|
+
{"version":3,"file":"delete.d.ts","sourceRoot":"","sources":["../../../../src/utils/query/localDbQuery/delete.ts"],"names":[],"mappings":"AACA,OAAO,EACL,WAAW,EACX,oBAAoB,EACpB,QAAQ,EACT,MAAM,4BAA4B,CAAC;AAKpC;;;;;GAKG;AACH,wBAAsB,UAAU,CAAC,CAAC,GAAG,GAAG,EACtC,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,WAAW,EAAE,GAAG,IAAI,EAC7B,QAAQ,CAAC,EAAE,QAAQ,GAClB,OAAO,CAAC,oBAAoB,CAAC,CAAC,CAAC,CAAC,CA+BlC;AAED;;;;;GAKG;AACH,wBAAsB,qBAAqB,CAAC,CAAC,GAAG,GAAG,EACjD,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,WAAW,EAAE,GAAG,IAAI,GAC5B,OAAO,CAAC,oBAAoB,CAAC,CAAC,CAAC,CAAC,CAkBlC"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { getSupastashDb } from "../../../db/dbInitializer";
|
|
2
|
+
import { logError } from "../../logs";
|
|
2
3
|
import { assertTableExists } from "../../tableValidator";
|
|
3
4
|
import { buildWhereClause } from "../helpers/remoteDb/queryFilterBuilder";
|
|
4
5
|
/**
|
|
@@ -21,7 +22,7 @@ export async function deleteData(table, filters, syncMode) {
|
|
|
21
22
|
return { error: null, data: itemsToBeDeleted };
|
|
22
23
|
}
|
|
23
24
|
catch (error) {
|
|
24
|
-
|
|
25
|
+
logError(`[Supastash] ${error}`);
|
|
25
26
|
return {
|
|
26
27
|
error: {
|
|
27
28
|
message: error instanceof Error ? error.message : String(error),
|
|
@@ -44,7 +45,7 @@ export async function permanentlyDeleteData(table, filters) {
|
|
|
44
45
|
return { error: null };
|
|
45
46
|
}
|
|
46
47
|
catch (error) {
|
|
47
|
-
|
|
48
|
+
logError(`[Supastash] ${error}`);
|
|
48
49
|
return {
|
|
49
50
|
error: {
|
|
50
51
|
message: error instanceof Error ? error.message : String(error),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"insert.d.ts","sourceRoot":"","sources":["../../../../src/utils/query/localDbQuery/insert.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,iBAAiB,EACjB,aAAa,EACb,QAAQ,EACT,MAAM,4BAA4B,CAAC;
|
|
1
|
+
{"version":3,"file":"insert.d.ts","sourceRoot":"","sources":["../../../../src/utils/query/localDbQuery/insert.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,iBAAiB,EACjB,aAAa,EACb,QAAQ,EACT,MAAM,4BAA4B,CAAC;AAMpC;;;;;;GAMG;AACH,wBAAsB,UAAU,CAAC,CAAC,SAAS,OAAO,EAAE,CAAC,EAAE,CAAC,EACtD,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,CAAC,EAAE,GAAG,IAAI,EACnB,QAAQ,CAAC,EAAE,QAAQ,EACnB,QAAQ,CAAC,EAAE,CAAC,GACX,OAAO,CAAC,CAAC,SAAS,IAAI,GAAG,aAAa,CAAC,CAAC,CAAC,GAAG,iBAAiB,CAAC,CAAC,CAAC,CAAC,CA6EnE"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { getSupastashDb } from "../../../db/dbInitializer";
|
|
2
|
+
import { logError } from "../../logs";
|
|
2
3
|
import { getSafeValue } from "../../serializer";
|
|
3
4
|
import { parseStringifiedFields } from "../../sync/pushLocal/parseFields";
|
|
4
5
|
import { assertTableExists } from "../../tableValidator";
|
|
@@ -54,7 +55,7 @@ export async function insertData(table, payload, syncMode, isSingle) {
|
|
|
54
55
|
};
|
|
55
56
|
}
|
|
56
57
|
catch (error) {
|
|
57
|
-
|
|
58
|
+
logError(`[Supastash] ${error}`);
|
|
58
59
|
return {
|
|
59
60
|
error: {
|
|
60
61
|
message: error instanceof Error ? error.message : String(error),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"select.d.ts","sourceRoot":"","sources":["../../../../src/utils/query/localDbQuery/select.ts"],"names":[],"mappings":"AACA,OAAO,EACL,WAAW,EACX,iBAAiB,EACjB,aAAa,EACd,MAAM,4BAA4B,CAAC;
|
|
1
|
+
{"version":3,"file":"select.d.ts","sourceRoot":"","sources":["../../../../src/utils/query/localDbQuery/select.ts"],"names":[],"mappings":"AACA,OAAO,EACL,WAAW,EACX,iBAAiB,EACjB,aAAa,EACd,MAAM,4BAA4B,CAAC;AAMpC;;;;;;;;;GASG;AACH,wBAAsB,UAAU,CAAC,CAAC,SAAS,OAAO,EAAE,CAAC,EAAE,CAAC,EACtD,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,WAAW,EAAE,GAAG,IAAI,EAC7B,KAAK,EAAE,MAAM,GAAG,IAAI,EACpB,QAAQ,EAAE,CAAC,GACV,OAAO,CAAC,CAAC,SAAS,IAAI,GAAG,aAAa,CAAC,CAAC,CAAC,GAAG,iBAAiB,CAAC,CAAC,CAAC,CAAC,CAoCnE"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { getSupastashDb } from "../../../db/dbInitializer";
|
|
2
|
+
import { logError } from "../../logs";
|
|
2
3
|
import { parseStringifiedFields } from "../../sync/pushLocal/parseFields";
|
|
3
4
|
import { assertTableExists } from "../../tableValidator";
|
|
4
5
|
import { buildWhereClause } from "../helpers/remoteDb/queryFilterBuilder";
|
|
@@ -33,7 +34,7 @@ export async function selectData(table, select, filters, limit, isSingle) {
|
|
|
33
34
|
return { data, error: null };
|
|
34
35
|
}
|
|
35
36
|
catch (error) {
|
|
36
|
-
|
|
37
|
+
logError(`[Supastash] ${error}`);
|
|
37
38
|
return {
|
|
38
39
|
error: {
|
|
39
40
|
message: error instanceof Error ? error.message : String(error),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"update.d.ts","sourceRoot":"","sources":["../../../../src/utils/query/localDbQuery/update.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,WAAW,EAEX,iBAAiB,EACjB,aAAa,EACb,QAAQ,EACT,MAAM,4BAA4B,CAAC;
|
|
1
|
+
{"version":3,"file":"update.d.ts","sourceRoot":"","sources":["../../../../src/utils/query/localDbQuery/update.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,WAAW,EAEX,iBAAiB,EACjB,aAAa,EACb,QAAQ,EACT,MAAM,4BAA4B,CAAC;AASpC;;;;;;;GAOG;AACH,wBAAsB,UAAU,CAAC,CAAC,SAAS,OAAO,EAAE,CAAC,EAAE,CAAC,EACtD,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,CAAC,GAAG,IAAI,EACjB,OAAO,EAAE,WAAW,EAAE,GAAG,IAAI,EAC7B,QAAQ,CAAC,EAAE,QAAQ,EACnB,QAAQ,CAAC,EAAE,CAAC,EACZ,iBAAiB,CAAC,EAAE,OAAO,GAC1B,OAAO,CAAC,CAAC,SAAS,IAAI,GAAG,aAAa,CAAC,CAAC,CAAC,GAAG,iBAAiB,CAAC,CAAC,CAAC,CAAC,CA+EnE"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { getSupastashConfig } from "../../../core/config";
|
|
2
2
|
import { getSupastashDb } from "../../../db/dbInitializer";
|
|
3
3
|
import { parseStringifiedFields } from "../../../utils/sync/pushLocal/parseFields";
|
|
4
|
+
import { logError, logWarn } from "../../logs";
|
|
4
5
|
import { getSafeValue } from "../../serializer";
|
|
5
6
|
import { assertTableExists } from "../../tableValidator";
|
|
6
7
|
import { buildWhereClause } from "../helpers/remoteDb/queryFilterBuilder";
|
|
@@ -31,7 +32,7 @@ export async function updateData(table, payload, filters, syncMode, isSingle, pr
|
|
|
31
32
|
if (!preserveTimestamp || payload.updated_at === undefined) {
|
|
32
33
|
if (!warned.has(table) && !getSupastashConfig().debugMode && __DEV__) {
|
|
33
34
|
warned.add(table);
|
|
34
|
-
|
|
35
|
+
logWarn(`[Supastash] updated_at not provided for update call on ${table} – defaulting to ${timeStamp}`);
|
|
35
36
|
}
|
|
36
37
|
const userUpdatedAt = payload.updated_at;
|
|
37
38
|
newPayload.updated_at =
|
|
@@ -66,7 +67,7 @@ export async function updateData(table, payload, filters, syncMode, isSingle, pr
|
|
|
66
67
|
};
|
|
67
68
|
}
|
|
68
69
|
catch (error) {
|
|
69
|
-
|
|
70
|
+
logError(`[Supastash] ${error}`);
|
|
70
71
|
return {
|
|
71
72
|
error: {
|
|
72
73
|
message: error instanceof Error ? error.message : String(error),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"upsert.d.ts","sourceRoot":"","sources":["../../../../src/utils/query/localDbQuery/upsert.ts"],"names":[],"mappings":"AAEA,OAAO,EAEL,iBAAiB,EACjB,aAAa,EACb,QAAQ,EACT,MAAM,4BAA4B,CAAC;
|
|
1
|
+
{"version":3,"file":"upsert.d.ts","sourceRoot":"","sources":["../../../../src/utils/query/localDbQuery/upsert.ts"],"names":[],"mappings":"AAEA,OAAO,EAEL,iBAAiB,EACjB,aAAa,EACb,QAAQ,EACT,MAAM,4BAA4B,CAAC;AASpC;;;;;GAKG;AACH,wBAAsB,UAAU,CAAC,CAAC,SAAS,OAAO,EAAE,CAAC,EAAE,CAAC,EACtD,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,CAAC,GAAG,CAAC,EAAE,GAAG,IAAI,EACvB,QAAQ,CAAC,EAAE,QAAQ,EACnB,QAAQ,CAAC,EAAE,CAAC,EACZ,cAAc,GAAE,MAAM,EAAW,EACjC,iBAAiB,CAAC,EAAE,OAAO,GAC1B,OAAO,CAAC,CAAC,SAAS,IAAI,GAAG,aAAa,CAAC,CAAC,CAAC,GAAG,iBAAiB,CAAC,CAAC,CAAC,CAAC,CA4HnE"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { getSupastashConfig } from "../../../core/config";
|
|
2
2
|
import { getSupastashDb } from "../../../db/dbInitializer";
|
|
3
3
|
import { generateUUIDv4 } from "../../../utils/genUUID";
|
|
4
|
+
import { logError, logWarn } from "../../logs";
|
|
4
5
|
import { getSafeValue } from "../../serializer";
|
|
5
6
|
import { parseStringifiedFields } from "../../sync/pushLocal/parseFields";
|
|
6
7
|
import { assertTableExists } from "../../tableValidator";
|
|
@@ -48,7 +49,7 @@ export async function upsertData(table, payload, syncMode, isSingle, onConflictK
|
|
|
48
49
|
!getSupastashConfig().debugMode &&
|
|
49
50
|
__DEV__) {
|
|
50
51
|
warned.add(table);
|
|
51
|
-
|
|
52
|
+
logWarn(`[Supastash] updated_at not provided for upsert call on ${table} – defaulting to ${timeStamp}`);
|
|
52
53
|
}
|
|
53
54
|
const userUpdatedAt = item.updated_at;
|
|
54
55
|
newPayload.updated_at =
|
|
@@ -90,7 +91,7 @@ export async function upsertData(table, payload, syncMode, isSingle, onConflictK
|
|
|
90
91
|
};
|
|
91
92
|
}
|
|
92
93
|
catch (error) {
|
|
93
|
-
|
|
94
|
+
logError(`[Supastash] ${error}`);
|
|
94
95
|
return {
|
|
95
96
|
error: {
|
|
96
97
|
message: error instanceof Error ? error.message : String(error),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createSyncStatus.d.ts","sourceRoot":"","sources":["../../../src/utils/schema/createSyncStatus.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,wBAAsB,qBAAqB,
|
|
1
|
+
{"version":3,"file":"createSyncStatus.d.ts","sourceRoot":"","sources":["../../../src/utils/schema/createSyncStatus.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,wBAAsB,qBAAqB,kBAe1C;AAED;;GAEG;AACH,wBAAsB,wBAAwB,kBAS7C"}
|
|
@@ -7,8 +7,13 @@ export async function createSyncStatusTable() {
|
|
|
7
7
|
const sql = `CREATE TABLE IF NOT EXISTS supastash_sync_status (
|
|
8
8
|
table_name TEXT NOT NULL,
|
|
9
9
|
last_synced_at TEXT NOT NULL
|
|
10
|
+
);`;
|
|
11
|
+
const sql2 = `CREATE TABLE IF NOT EXISTS supastash_last_created (
|
|
12
|
+
table_name TEXT NOT NULL,
|
|
13
|
+
last_created_at TEXT NOT NULL
|
|
10
14
|
);`;
|
|
11
15
|
await db.execAsync(sql);
|
|
16
|
+
await db.execAsync(sql2);
|
|
12
17
|
}
|
|
13
18
|
/**
|
|
14
19
|
* Creates the supastash_deleted_status table if it doesn't exist
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Gets the last synced timestamp for a given table
|
|
3
|
+
* @param table - The table to get the last created timestamp for
|
|
4
|
+
* @returns The last synced timestamp
|
|
5
|
+
*/
|
|
6
|
+
export declare function getLastCreatedInfo(table: string): Promise<string>;
|
|
7
|
+
/**
|
|
8
|
+
* Updates the last synced timestamp for a given table
|
|
9
|
+
* @param table - The table to update the last created timestamp for
|
|
10
|
+
* @param lastCreatedAt - The last created timestamp
|
|
11
|
+
*/
|
|
12
|
+
export declare function updateLastCreatedInfo(table: string, lastCreatedAt: string): Promise<void>;
|
|
13
|
+
//# sourceMappingURL=getLastCreatedInfo.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getLastCreatedInfo.d.ts","sourceRoot":"","sources":["../../../../src/utils/sync/pullFromRemote/getLastCreatedInfo.ts"],"names":[],"mappings":"AAMA;;;;GAIG;AACH,wBAAsB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CA6BvE;AAED;;;;GAIG;AACH,wBAAsB,qBAAqB,CACzC,KAAK,EAAE,MAAM,EACb,aAAa,EAAE,MAAM,iBAQtB"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { getSupastashDb } from "../../../db/dbInitializer";
|
|
2
|
+
import { logWarn } from "../../logs";
|
|
3
|
+
const DEFAULT_LAST_CREATED_AT = "2000-01-01T00:00:00Z";
|
|
4
|
+
const LAST_CREATED_TABLE = "supastash_last_created";
|
|
5
|
+
/**
|
|
6
|
+
* Gets the last synced timestamp for a given table
|
|
7
|
+
* @param table - The table to get the last created timestamp for
|
|
8
|
+
* @returns The last synced timestamp
|
|
9
|
+
*/
|
|
10
|
+
export async function getLastCreatedInfo(table) {
|
|
11
|
+
const db = await getSupastashDb();
|
|
12
|
+
// Add table name to supastash_last_created if it doesn't exist
|
|
13
|
+
await db.runAsync(`INSERT OR IGNORE INTO supastash_last_created (table_name, last_created_at) VALUES (?, ?)`, [table, DEFAULT_LAST_CREATED_AT]);
|
|
14
|
+
// Get the latest sync timestamp for this table
|
|
15
|
+
const result = await db.getFirstAsync(`SELECT last_created_at FROM ${LAST_CREATED_TABLE} WHERE table_name = ?`, [table]);
|
|
16
|
+
const original = result?.last_created_at || DEFAULT_LAST_CREATED_AT;
|
|
17
|
+
const timestamp = Date.parse(original);
|
|
18
|
+
if (isNaN(timestamp)) {
|
|
19
|
+
logWarn(`[Supastash] Invalid date string found on created_at column for ${table}: ${original}`);
|
|
20
|
+
return original;
|
|
21
|
+
}
|
|
22
|
+
const lastSyncedAt = new Date(timestamp + 1);
|
|
23
|
+
const lastSyncedAtISOString = lastSyncedAt.toISOString();
|
|
24
|
+
return lastSyncedAtISOString;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Updates the last synced timestamp for a given table
|
|
28
|
+
* @param table - The table to update the last created timestamp for
|
|
29
|
+
* @param lastCreatedAt - The last created timestamp
|
|
30
|
+
*/
|
|
31
|
+
export async function updateLastCreatedInfo(table, lastCreatedAt) {
|
|
32
|
+
const db = await getSupastashDb();
|
|
33
|
+
await db.runAsync(`UPDATE ${LAST_CREATED_TABLE} SET last_created_at = ? WHERE table_name = ?`, [lastCreatedAt, table]);
|
|
34
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getLastDeletedInfo.d.ts","sourceRoot":"","sources":["../../../../src/utils/sync/pullFromRemote/getLastDeletedInfo.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"getLastDeletedInfo.d.ts","sourceRoot":"","sources":["../../../../src/utils/sync/pullFromRemote/getLastDeletedInfo.ts"],"names":[],"mappings":"AAMA;;;;GAIG;AACH,wBAAsB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CA6BvE;AAED;;;;GAIG;AACH,wBAAsB,qBAAqB,CACzC,KAAK,EAAE,MAAM,EACb,aAAa,EAAE,MAAM,iBAQtB"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { getSupastashDb } from "../../../db/dbInitializer";
|
|
2
|
-
|
|
2
|
+
import { logWarn } from "../../logs";
|
|
3
|
+
const DEFAULT_LAST_DELETED_AT = "2000-01-01T00:00:00Z";
|
|
3
4
|
const DELETED_STATUS_TABLE = "supastash_deleted_status";
|
|
4
5
|
/**
|
|
5
6
|
* Gets the last deleted timestamp for a given table
|
|
@@ -14,6 +15,10 @@ export async function getLastDeletedInfo(table) {
|
|
|
14
15
|
const result = await db.getFirstAsync(`SELECT last_deleted_at FROM ${DELETED_STATUS_TABLE} WHERE table_name = ?`, [table]);
|
|
15
16
|
const original = result?.last_deleted_at || DEFAULT_LAST_DELETED_AT;
|
|
16
17
|
const timestamp = Date.parse(original);
|
|
18
|
+
if (isNaN(timestamp)) {
|
|
19
|
+
logWarn(`[Supastash] Invalid date string found on deleted_at column for ${table}: ${original}`);
|
|
20
|
+
return original;
|
|
21
|
+
}
|
|
17
22
|
const lastDeletedAt = new Date(timestamp + 1);
|
|
18
23
|
const lastDeletedAtISOString = lastDeletedAt.toISOString();
|
|
19
24
|
return lastDeletedAtISOString;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getLastPulledInfo.d.ts","sourceRoot":"","sources":["../../../../src/utils/sync/pullFromRemote/getLastPulledInfo.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"getLastPulledInfo.d.ts","sourceRoot":"","sources":["../../../../src/utils/sync/pullFromRemote/getLastPulledInfo.ts"],"names":[],"mappings":"AAMA;;;;GAIG;AACH,wBAAsB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CA6BtE;AAED;;;;GAIG;AACH,wBAAsB,oBAAoB,CACxC,KAAK,EAAE,MAAM,EACb,YAAY,EAAE,MAAM,iBAQrB"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { getSupastashDb } from "../../../db/dbInitializer";
|
|
2
|
-
|
|
2
|
+
import { logWarn } from "../../logs";
|
|
3
|
+
const DEFAULT_LAST_PULLED_AT = "2000-01-01T00:00:00Z";
|
|
3
4
|
const SYNC_STATUS_TABLE = "supastash_sync_status";
|
|
4
5
|
/**
|
|
5
6
|
* Gets the last synced timestamp for a given table
|
|
@@ -14,6 +15,10 @@ export async function getLastPulledInfo(table) {
|
|
|
14
15
|
const result = await db.getFirstAsync(`SELECT last_synced_at FROM ${SYNC_STATUS_TABLE} WHERE table_name = ?`, [table]);
|
|
15
16
|
const original = result?.last_synced_at || DEFAULT_LAST_PULLED_AT;
|
|
16
17
|
const timestamp = Date.parse(original);
|
|
18
|
+
if (isNaN(timestamp)) {
|
|
19
|
+
logWarn(`[Supastash] Invalid date string found on updated_at column for ${table}: ${original}`);
|
|
20
|
+
return original;
|
|
21
|
+
}
|
|
17
22
|
const lastSyncedAt = new Date(timestamp + 1);
|
|
18
23
|
const lastSyncedAtISOString = lastSyncedAt.toISOString();
|
|
19
24
|
return lastSyncedAtISOString;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pullData.d.ts","sourceRoot":"","sources":["../../../../src/utils/sync/pullFromRemote/pullData.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAC;
|
|
1
|
+
{"version":3,"file":"pullData.d.ts","sourceRoot":"","sources":["../../../../src/utils/sync/pullFromRemote/pullData.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAC;AA2BnE;;;;GAIG;AACH,wBAAsB,QAAQ,CAC5B,KAAK,EAAE,MAAM,EACb,MAAM,CAAC,EAAE,cAAc,GACtB,OAAO,CAAC,WAAW,EAAE,GAAG,IAAI,CAAC,CAmF/B"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { getSupastashConfig } from "../../../core/config";
|
|
2
2
|
import log from "../../logs";
|
|
3
3
|
import { supabaseClientErr } from "../../supabaseClientErr";
|
|
4
|
+
import { getLastCreatedInfo, updateLastCreatedInfo, } from "./getLastCreatedInfo";
|
|
4
5
|
import { getLastPulledInfo, updateLastPulledInfo } from "./getLastPulledInfo";
|
|
5
6
|
const validOperators = new Set([
|
|
6
7
|
"eq",
|
|
@@ -14,8 +15,10 @@ const validOperators = new Set([
|
|
|
14
15
|
"is",
|
|
15
16
|
"in",
|
|
16
17
|
]);
|
|
17
|
-
|
|
18
|
-
let
|
|
18
|
+
const DEFAULT_MAX_PULL_ATTEMPTS = 150;
|
|
19
|
+
let timesPulled = new Map();
|
|
20
|
+
let lastPulled = new Map();
|
|
21
|
+
const RANDOM_OLD_DATE = "2000-01-01T00:00:00Z";
|
|
19
22
|
/**
|
|
20
23
|
* Pulls data from the remote database for a given table
|
|
21
24
|
* @param table - The table to pull data from
|
|
@@ -23,13 +26,14 @@ let lastPulled = 0;
|
|
|
23
26
|
*/
|
|
24
27
|
export async function pullData(table, filter) {
|
|
25
28
|
const lastSyncedAt = await getLastPulledInfo(table);
|
|
29
|
+
const lastCreatedAt = await getLastCreatedInfo(table);
|
|
26
30
|
const supabase = getSupastashConfig().supabaseClient;
|
|
27
31
|
if (!supabase)
|
|
28
32
|
throw new Error(`No supabase client found: ${supabaseClientErr}`);
|
|
29
33
|
let filteredQuery = supabase
|
|
30
34
|
.from(table)
|
|
31
35
|
.select("*")
|
|
32
|
-
.
|
|
36
|
+
.or(`created_at.gte.${lastCreatedAt},updated_at.gte.${lastSyncedAt}`)
|
|
33
37
|
.is("deleted_at", null)
|
|
34
38
|
.order("updated_at", { ascending: false, nullsFirst: false });
|
|
35
39
|
if (filter &&
|
|
@@ -39,33 +43,60 @@ export async function pullData(table, filter) {
|
|
|
39
43
|
!filter.value)) {
|
|
40
44
|
throw new Error(`Invalid filter: ${JSON.stringify(filter)} for table ${table}`);
|
|
41
45
|
}
|
|
46
|
+
const isValidValue = filter &&
|
|
47
|
+
(filter.operator === "is" ||
|
|
48
|
+
filter.operator === "in" ||
|
|
49
|
+
typeof filter.value !== "undefined");
|
|
42
50
|
if (filter?.operator &&
|
|
43
51
|
validOperators.has(filter.operator) &&
|
|
44
52
|
filter.column &&
|
|
45
|
-
|
|
53
|
+
isValidValue) {
|
|
46
54
|
filteredQuery = filteredQuery[filter.operator](filter.column, filter.value);
|
|
47
55
|
}
|
|
48
|
-
// Fetch records
|
|
56
|
+
// Fetch records where created_at >= lastCreatedAt OR updated_at >= lastSyncedAt
|
|
49
57
|
const { data, error } = await filteredQuery;
|
|
50
58
|
if (error) {
|
|
51
59
|
log(`[Supastash] Error fetching from ${table}:`, error.message);
|
|
52
60
|
return null;
|
|
53
61
|
}
|
|
54
62
|
if (!data || data.length === 0) {
|
|
55
|
-
timesPulled
|
|
56
|
-
if (timesPulled >=
|
|
57
|
-
const timeSinceLastPull = Date.now() - lastPulled;
|
|
58
|
-
lastPulled
|
|
59
|
-
log(`[Supastash] No updates for ${table} at ${lastSyncedAt} (times pulled: ${timesPulled}) in the last ${timeSinceLastPull}ms`);
|
|
60
|
-
timesPulled
|
|
63
|
+
timesPulled.set(table, (timesPulled.get(table) || 0) + 1);
|
|
64
|
+
if ((timesPulled.get(table) || 0) >= DEFAULT_MAX_PULL_ATTEMPTS) {
|
|
65
|
+
const timeSinceLastPull = Date.now() - (lastPulled.get(table) || 0);
|
|
66
|
+
lastPulled.set(table, Date.now());
|
|
67
|
+
log(`[Supastash] No updates for ${table} at ${lastSyncedAt} (times pulled: ${timesPulled.get(table)}) in the last ${timeSinceLastPull}ms`);
|
|
68
|
+
timesPulled.set(table, 0);
|
|
61
69
|
}
|
|
62
70
|
return null;
|
|
63
71
|
}
|
|
64
72
|
log(`Received ${data.length} updates for ${table}`);
|
|
65
|
-
// Update the
|
|
66
|
-
const
|
|
67
|
-
if (
|
|
68
|
-
await updateLastPulledInfo(table,
|
|
73
|
+
// Update the sync status tables with the latest timestamps
|
|
74
|
+
const { createdMaxDate, updatedMaxDate } = getMaxDate(data);
|
|
75
|
+
if (updatedMaxDate) {
|
|
76
|
+
await updateLastPulledInfo(table, updatedMaxDate);
|
|
77
|
+
}
|
|
78
|
+
if (createdMaxDate) {
|
|
79
|
+
await updateLastCreatedInfo(table, createdMaxDate);
|
|
69
80
|
}
|
|
70
81
|
return data;
|
|
71
82
|
}
|
|
83
|
+
function getMaxDate(data) {
|
|
84
|
+
let createdMaxDate = RANDOM_OLD_DATE;
|
|
85
|
+
let updatedMaxDate = RANDOM_OLD_DATE;
|
|
86
|
+
const createdColumn = "created_at";
|
|
87
|
+
const updatedColumn = "updated_at";
|
|
88
|
+
for (const item of data) {
|
|
89
|
+
const createdValue = item[createdColumn];
|
|
90
|
+
const updatedValue = item[updatedColumn];
|
|
91
|
+
if (typeof createdValue === "string" && !isNaN(Date.parse(createdValue))) {
|
|
92
|
+
createdMaxDate = new Date(Math.max(new Date(createdMaxDate).getTime(), new Date(createdValue).getTime())).toISOString();
|
|
93
|
+
}
|
|
94
|
+
if (typeof updatedValue === "string" && !isNaN(Date.parse(updatedValue))) {
|
|
95
|
+
updatedMaxDate = new Date(Math.max(new Date(updatedMaxDate).getTime(), new Date(updatedValue).getTime())).toISOString();
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return {
|
|
99
|
+
createdMaxDate: createdMaxDate === RANDOM_OLD_DATE ? null : createdMaxDate,
|
|
100
|
+
updatedMaxDate: updatedMaxDate === RANDOM_OLD_DATE ? null : updatedMaxDate,
|
|
101
|
+
};
|
|
102
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"updateLocalDb.d.ts","sourceRoot":"","sources":["../../../../src/utils/sync/pullFromRemote/updateLocalDb.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAC;AAanE;;;GAGG;AACH,wBAAsB,aAAa,CACjC,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE,cAAc,EACxB,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,KAAK,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"updateLocalDb.d.ts","sourceRoot":"","sources":["../../../../src/utils/sync/pullFromRemote/updateLocalDb.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAC;AAanE;;;GAGG;AACH,wBAAsB,aAAa,CACjC,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE,cAAc,EACxB,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,KAAK,OAAO,CAAC,IAAI,CAAC,iBA+ChD;AAID;;;;;GAKG;AACH,wBAAsB,UAAU,CAC9B,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,GAAG,EACX,SAAS,CAAC,EAAE,OAAO,iBAiEpB"}
|
|
@@ -2,7 +2,7 @@ import { getSupastashConfig } from "../../../core/config";
|
|
|
2
2
|
import { getSupastashDb } from "../../../db/dbInitializer";
|
|
3
3
|
import { isOnline } from "../../connection";
|
|
4
4
|
import { getTableSchema } from "../../getTableSchema";
|
|
5
|
-
import log from "../../logs";
|
|
5
|
+
import log, { logError, logWarn } from "../../logs";
|
|
6
6
|
import { refreshScreen } from "../../refreshScreenCalls";
|
|
7
7
|
import { updateLocalSyncedAt } from "../../syncUpdate";
|
|
8
8
|
import { pullData } from "./pullData";
|
|
@@ -24,18 +24,18 @@ export async function updateLocalDb(table, filters, onReceiveData) {
|
|
|
24
24
|
const db = await getSupastashDb();
|
|
25
25
|
const deletedData = await pullDeletedData(table, filters);
|
|
26
26
|
const data = await pullData(table, filters);
|
|
27
|
-
const
|
|
28
|
-
const changes = !!deletedData || !!dataToUpdate;
|
|
27
|
+
const refreshNeeded = !!deletedData?.records.length || !!data?.length;
|
|
29
28
|
// Delete records that are no longer in the remote data
|
|
30
|
-
if (deletedData) {
|
|
29
|
+
if (deletedData && deletedData.records.length > 0) {
|
|
31
30
|
for (const record of deletedData.records) {
|
|
32
31
|
await db.runAsync(`DELETE FROM ${table} WHERE id = ?`, [record.id]);
|
|
33
32
|
}
|
|
34
|
-
refreshScreen(table);
|
|
35
33
|
}
|
|
36
34
|
// Update local database with remote changes
|
|
37
|
-
if (
|
|
38
|
-
for (const record of
|
|
35
|
+
if (data && data.length > 0) {
|
|
36
|
+
for (const record of data) {
|
|
37
|
+
if (deletedData?.deletedDataMap.has(record.id))
|
|
38
|
+
continue;
|
|
39
39
|
const { doesExist, newer } = await checkIfRecordExistsAndIsNewer(table, record);
|
|
40
40
|
if (newer) {
|
|
41
41
|
if (onReceiveData) {
|
|
@@ -47,11 +47,13 @@ export async function updateLocalDb(table, filters, onReceiveData) {
|
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
49
|
}
|
|
50
|
-
if (
|
|
50
|
+
if (refreshNeeded)
|
|
51
51
|
refreshScreen(table);
|
|
52
52
|
}
|
|
53
53
|
catch (error) {
|
|
54
|
-
|
|
54
|
+
if (__DEV__) {
|
|
55
|
+
logError(`[Supastash] Error updating local db for ${table}`, error);
|
|
56
|
+
}
|
|
55
57
|
}
|
|
56
58
|
finally {
|
|
57
59
|
isInSync.delete(table);
|
|
@@ -83,20 +85,17 @@ export async function upsertData(table, record, doesExist) {
|
|
|
83
85
|
const unknownKeys = Object.keys(record).filter((key) => !columns.includes(key));
|
|
84
86
|
if (unknownKeys.length > 0 && !warned.get(table)) {
|
|
85
87
|
warned.set(table, true);
|
|
86
|
-
|
|
88
|
+
logWarn(`⚠️ [Supastash] ${table} record contains keys not in local schema: ${unknownKeys.join(", ")}. Data will still be stored`);
|
|
87
89
|
}
|
|
88
90
|
}
|
|
89
91
|
// Prep for upsert
|
|
90
92
|
const keys = columns;
|
|
91
93
|
const placeholders = keys.map(() => "?").join(", ");
|
|
92
|
-
const
|
|
93
|
-
|
|
94
|
-
.map((key) => `${key} = ?`);
|
|
94
|
+
const updateColumns = keys.filter((key) => key !== "id");
|
|
95
|
+
const updateParts = updateColumns.map((key) => `${key} = ?`);
|
|
95
96
|
const updatePlaceholders = updateParts.join(", ");
|
|
96
97
|
const values = keys.map((key) => recordToSave[key]);
|
|
97
|
-
const updateValues =
|
|
98
|
-
.filter((key) => key !== "id")
|
|
99
|
-
.map((key) => recordToSave[key]);
|
|
98
|
+
const updateValues = updateColumns.map((key) => recordToSave[key]);
|
|
100
99
|
if (itemExists) {
|
|
101
100
|
// Update existing record
|
|
102
101
|
await db.runAsync(`UPDATE ${table} SET ${updatePlaceholders} WHERE id = ?`, [...updateValues, record.id]);
|
|
@@ -108,7 +107,7 @@ export async function upsertData(table, record, doesExist) {
|
|
|
108
107
|
await updateLocalSyncedAt(table, record.id);
|
|
109
108
|
}
|
|
110
109
|
catch (error) {
|
|
111
|
-
|
|
110
|
+
logError(`[Supastash] Error upserting data for ${table}`, error);
|
|
112
111
|
}
|
|
113
112
|
}
|
|
114
113
|
async function checkIfRecordExistsAndIsNewer(table, item) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sendUnsyncedToSupabase.d.ts","sourceRoot":"","sources":["../../../../src/utils/sync/pushLocal/sendUnsyncedToSupabase.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"sendUnsyncedToSupabase.d.ts","sourceRoot":"","sources":["../../../../src/utils/sync/pushLocal/sendUnsyncedToSupabase.ts"],"names":[],"mappings":"AASA;;;GAGG;AACH,wBAAsB,qBAAqB,CACzC,KAAK,EAAE,MAAM,EACb,cAAc,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,KAAK,OAAO,CAAC,OAAO,CAAC,EACrD,MAAM,CAAC,EAAE,MAAM,EAAE,iBAsClB"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { isOnline } from "../../connection";
|
|
2
|
+
import { logError } from "../../logs";
|
|
2
3
|
import { refreshScreen } from "../../refreshScreenCalls";
|
|
3
4
|
import { deleteData } from "./deleteChunks";
|
|
4
5
|
import { getAllDeletedData, getAllUnsyncedData } from "./getAllUnsyncedData";
|
|
@@ -35,7 +36,7 @@ export async function pushLocalDataToRemote(table, onPushToRemote, noSync) {
|
|
|
35
36
|
}
|
|
36
37
|
}
|
|
37
38
|
catch (error) {
|
|
38
|
-
|
|
39
|
+
logError(`[Supastash] Error pushing local data to remote for ${table}`, error);
|
|
39
40
|
}
|
|
40
41
|
finally {
|
|
41
42
|
isInSync.delete(table);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { getSupastashConfig } from "../../../core/config";
|
|
2
|
-
import log from "../../logs";
|
|
2
|
+
import log, { logError } from "../../logs";
|
|
3
3
|
import { supabaseClientErr } from "../../supabaseClientErr";
|
|
4
4
|
import { updateLocalSyncedAt } from "../../syncUpdate";
|
|
5
5
|
import { parseStringifiedFields } from "./parseFields";
|
|
@@ -77,7 +77,7 @@ async function uploadChunk(table, chunk, onPushToRemote) {
|
|
|
77
77
|
if (onPushToRemote) {
|
|
78
78
|
const result = await onPushToRemote(toUpsert);
|
|
79
79
|
if (typeof result !== "boolean") {
|
|
80
|
-
|
|
80
|
+
logError(`[Supastash] Invalid return type from "onPushToRemote" callback on table ${table}.\n
|
|
81
81
|
Expected boolean but received ${typeof result}.\n
|
|
82
82
|
Skipping this chunk.
|
|
83
83
|
Check the "onPushToRemote" callback in the "useSupastashData" hook for table ${table}.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"syncStatus.d.ts","sourceRoot":"","sources":["../../src/utils/syncStatus.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"syncStatus.d.ts","sourceRoot":"","sources":["../../src/utils/syncStatus.ts"],"names":[],"mappings":"AAUA;;;;;GAKG;AACH,wBAAsB,iBAAiB,CAAC,SAAS,EAAE,MAAM,iBAKxD;AAED;;;;GAIG;AACH,wBAAsB,oBAAoB,kBAKzC;AAED;;;;;;;GAOG;AACH,wBAAsB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC;IAChE,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;CACtB,GAAG,IAAI,CAAC,CAUR;AAED;;;;;;GAMG;AACH,wBAAsB,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,iBAM5E;AAED;;;;;GAKG;AACH,wBAAsB,mBAAmB,CAAC,SAAS,EAAE,MAAM,iBAM1D;AAED;;;;GAIG;AACH,wBAAsB,sBAAsB,kBAI3C;AAED;;;;;;;GAOG;AACH,wBAAsB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC;IAClE,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;CACvB,GAAG,IAAI,CAAC,CAUR;AAED;;;;;;GAMG;AACH,wBAAsB,iBAAiB,CACrC,SAAS,EAAE,MAAM,EACjB,aAAa,EAAE,MAAM,iBAOtB"}
|
package/dist/utils/syncStatus.js
CHANGED
|
@@ -2,6 +2,7 @@ import { getSupastashDb } from "../db/dbInitializer";
|
|
|
2
2
|
import { createDeletedStatusTable, createSyncStatusTable, } from "./schema/createSyncStatus";
|
|
3
3
|
const SYNC_STATUS_TABLE = "supastash_sync_status";
|
|
4
4
|
const DELETED_STATUS_TABLE = "supastash_deleted_status";
|
|
5
|
+
const LAST_CREATED_TABLE = "supastash_last_created";
|
|
5
6
|
/**
|
|
6
7
|
* Clears the sync log for a given table
|
|
7
8
|
* @param tableName - The name of the table to clear the sync status for
|
|
@@ -22,6 +23,7 @@ export async function clearLocalSyncLog(tableName) {
|
|
|
22
23
|
export async function clearAllLocalSyncLog() {
|
|
23
24
|
const db = await getSupastashDb();
|
|
24
25
|
await db.runAsync(`DROP TABLE IF EXISTS ${SYNC_STATUS_TABLE}`);
|
|
26
|
+
await db.runAsync(`DROP TABLE IF EXISTS ${LAST_CREATED_TABLE}`);
|
|
25
27
|
await createSyncStatusTable();
|
|
26
28
|
}
|
|
27
29
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"syncUpdate.d.ts","sourceRoot":"","sources":["../../src/utils/syncUpdate.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"syncUpdate.d.ts","sourceRoot":"","sources":["../../src/utils/syncUpdate.ts"],"names":[],"mappings":"AAGA;;;;GAIG;AACH,wBAAsB,mBAAmB,CAAC,SAAS,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,iBAYtE"}
|
package/dist/utils/syncUpdate.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { getSupastashDb } from "../db/dbInitializer";
|
|
2
|
+
import { logError } from "./logs";
|
|
2
3
|
/**
|
|
3
4
|
* Updates synced_at from null to a timeStamp
|
|
4
5
|
* @param tableName - The name of the table to update
|
|
@@ -14,6 +15,6 @@ export async function updateLocalSyncedAt(tableName, id) {
|
|
|
14
15
|
]);
|
|
15
16
|
}
|
|
16
17
|
catch (error) {
|
|
17
|
-
|
|
18
|
+
logError(error);
|
|
18
19
|
}
|
|
19
20
|
}
|