supastash 0.1.22 → 0.1.24

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.
@@ -5,7 +5,7 @@ export declare function assignInsertIds<R>(payload: R | R[] | null): R | R[] | n
5
5
  export declare function getCommonError<U extends boolean, T extends CrudMethods, R, Z>(table: string, method: CrudMethods, localResult: MethodReturnTypeMap<U, Z>[T] | null, remoteResult: SupabaseQueryReturn<U, Z> | null): (Error & {
6
6
  supabaseError?: PostgrestError;
7
7
  }) | null;
8
- export declare function addToCache(state: SupastashQuery<CrudMethods, boolean, any>): void;
8
+ export declare function queueRemoteCall<T extends CrudMethods, U extends boolean, R>(state: SupastashQuery<T, U, R>): Promise<boolean>;
9
9
  export declare function runSyncStrategy<T extends CrudMethods, U extends boolean, R, Z>(state: SupastashQuery<T, U, R>): Promise<{
10
10
  localResult: MethodReturnTypeMap<U, Z>[T] | null;
11
11
  remoteResult: SupabaseQueryReturn<U, Z> | null;
@@ -1 +1 @@
1
- {"version":3,"file":"mainQueryHelpers.d.ts","sourceRoot":"","sources":["../../../../src/utils/query/helpers/mainQueryHelpers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EACL,WAAW,EACX,mBAAmB,EACnB,mBAAmB,EACnB,cAAc,EACf,MAAM,4BAA4B,CAAC;AAOpC,wBAAgB,8BAA8B,CAC5C,MAAM,EAAE,WAAW,EACnB,QAAQ,EAAE,OAAO,EACjB,OAAO,EAAE,OAAO,EAChB,KAAK,EAAE,MAAM,GACZ,IAAI,CAUN;AAED,wBAAgB,eAAe,CAAC,CAAC,EAC/B,OAAO,EAAE,CAAC,GAAG,CAAC,EAAE,GAAG,IAAI,GACtB,CAAC,GAAG,CAAC,EAAE,GAAG,IAAI,GAAG,SAAS,CAc5B;AAED,wBAAgB,cAAc,CAAC,CAAC,SAAS,OAAO,EAAE,CAAC,SAAS,WAAW,EAAE,CAAC,EAAE,CAAC,EAC3E,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,WAAW,EACnB,WAAW,EAAE,mBAAmB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,EAChD,YAAY,EAAE,mBAAmB,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,IAAI,GAC7C,CAAC,KAAK,GAAG;IAAE,aAAa,CAAC,EAAE,cAAc,CAAA;CAAE,CAAC,GAAG,IAAI,CAwBrD;AAkBD,wBAAgB,UAAU,CAAC,KAAK,EAAE,cAAc,CAAC,WAAW,EAAE,OAAO,EAAE,GAAG,CAAC,QAO1E;AA2DD,wBAAsB,eAAe,CACnC,CAAC,SAAS,WAAW,EACrB,CAAC,SAAS,OAAO,EACjB,CAAC,EACD,CAAC,EAED,KAAK,EAAE,cAAc,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,GAC7B,OAAO,CAAC;IACT,WAAW,EAAE,mBAAmB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;IACjD,YAAY,EAAE,mBAAmB,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC;CAChD,CAAC,CA2CD"}
1
+ {"version":3,"file":"mainQueryHelpers.d.ts","sourceRoot":"","sources":["../../../../src/utils/query/helpers/mainQueryHelpers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAEL,WAAW,EACX,mBAAmB,EACnB,mBAAmB,EACnB,cAAc,EACf,MAAM,4BAA4B,CAAC;AAOpC,wBAAgB,8BAA8B,CAC5C,MAAM,EAAE,WAAW,EACnB,QAAQ,EAAE,OAAO,EACjB,OAAO,EAAE,OAAO,EAChB,KAAK,EAAE,MAAM,GACZ,IAAI,CAUN;AAED,wBAAgB,eAAe,CAAC,CAAC,EAC/B,OAAO,EAAE,CAAC,GAAG,CAAC,EAAE,GAAG,IAAI,GACtB,CAAC,GAAG,CAAC,EAAE,GAAG,IAAI,GAAG,SAAS,CAc5B;AAED,wBAAgB,cAAc,CAAC,CAAC,SAAS,OAAO,EAAE,CAAC,SAAS,WAAW,EAAE,CAAC,EAAE,CAAC,EAC3E,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,WAAW,EACnB,WAAW,EAAE,mBAAmB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,EAChD,YAAY,EAAE,mBAAmB,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,IAAI,GAC7C,CAAC,KAAK,GAAG;IAAE,aAAa,CAAC,EAAE,cAAc,CAAA;CAAE,CAAC,GAAG,IAAI,CAwBrD;AAyBD,wBAAgB,eAAe,CAAC,CAAC,SAAS,WAAW,EAAE,CAAC,SAAS,OAAO,EAAE,CAAC,EACzE,KAAK,EAAE,cAAc,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,GAC7B,OAAO,CAAC,OAAO,CAAC,CAYlB;AA+ED,wBAAsB,eAAe,CACnC,CAAC,SAAS,WAAW,EACrB,CAAC,SAAS,OAAO,EACjB,CAAC,EACD,CAAC,EAED,KAAK,EAAE,cAAc,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,GAC7B,OAAO,CAAC;IACT,WAAW,EAAE,mBAAmB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;IACjD,YAAY,EAAE,mBAAmB,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC;CAChD,CAAC,CA2CD"}
@@ -1,5 +1,5 @@
1
1
  import { isOnline } from "../../../utils/connection";
2
- import { log, logError, logWarn } from "../../../utils/logs";
2
+ import { log, logWarn } from "../../../utils/logs";
3
3
  import { generateUUIDv4 } from "../../genUUID";
4
4
  import { queryLocalDb } from "../localDbQuery";
5
5
  import { querySupabase } from "../remoteQuery/supabaseQuery";
@@ -46,42 +46,60 @@ export function getCommonError(table, method, localResult, remoteResult) {
46
46
  }
47
47
  return null;
48
48
  }
49
- const stateCache = new Map();
49
+ let batchQueue = [];
50
+ let isProcessing = false;
51
+ let batchTimer = null;
52
+ const BATCH_DELAY = 10;
50
53
  const retryCount = new Map();
51
54
  const calledOfflineRetries = new Map();
52
- const opQueue = [];
53
- let isProcessing = false;
54
- const MAX_RETRIES = 2;
55
- const MAX_OFFLINE_RETRIES = 10;
56
- const getOpKey = (state) => `${state.method}:${state.table}:${state.id}`;
55
+ const successfulCalls = new Set();
56
+ const MAX_RETRIES = 3;
57
+ const MAX_OFFLINE_RETRIES = 5;
57
58
  function delay(ms) {
58
- return new Promise((res) => setTimeout(res, ms));
59
+ return new Promise((resolve) => setTimeout(resolve, ms));
60
+ }
61
+ function generateOpKey(state) {
62
+ return `${state.table}_${state.method}_${state.id}_${JSON.stringify(state.payload)}`;
63
+ }
64
+ export function queueRemoteCall(state) {
65
+ return new Promise((resolve, reject) => {
66
+ const opKey = generateOpKey(state);
67
+ if (successfulCalls.has(opKey)) {
68
+ resolve(true);
69
+ return;
70
+ }
71
+ batchQueue.push({ state, opKey, resolve, reject });
72
+ scheduleBatch();
73
+ });
59
74
  }
60
- export function addToCache(state) {
61
- const opKey = getOpKey(state);
62
- if (stateCache.has(opKey))
75
+ function scheduleBatch() {
76
+ if (batchTimer)
63
77
  return;
64
- stateCache.set(opKey, state);
65
- opQueue.push(opKey);
66
- processQueue();
78
+ batchTimer = setTimeout(() => {
79
+ processBatch();
80
+ batchTimer = null;
81
+ }, BATCH_DELAY);
67
82
  }
68
- async function processQueue() {
69
- if (isProcessing)
83
+ async function processBatch() {
84
+ if (isProcessing || batchQueue.length === 0)
70
85
  return;
71
86
  isProcessing = true;
72
- while (opQueue.length > 0) {
73
- const opKey = opQueue.shift();
74
- const state = stateCache.get(opKey);
75
- if (!state)
87
+ const batch = [...batchQueue];
88
+ batchQueue = [];
89
+ for (const call of batch) {
90
+ const { state, opKey, resolve, reject } = call;
91
+ if (successfulCalls.has(opKey)) {
92
+ resolve(true);
76
93
  continue;
77
- retryCount.set(opKey, retryCount.get(opKey) ?? 0);
94
+ }
78
95
  try {
79
96
  while ((retryCount.get(opKey) ?? 0) <= MAX_RETRIES) {
80
97
  const isConnected = await isOnline();
81
98
  if (!isConnected) {
82
99
  const offlineRetries = (calledOfflineRetries.get(opKey) || 0) + 1;
83
100
  if (offlineRetries > MAX_OFFLINE_RETRIES) {
84
- logError(`[Supastash] Gave up on ${opKey} after ${MAX_OFFLINE_RETRIES} offline retries`);
101
+ logWarn(`[Supastash] Gave up on ${opKey} after ${MAX_OFFLINE_RETRIES} offline retries`);
102
+ reject(new Error(`Offline retry limit exceeded for ${opKey}`));
85
103
  break;
86
104
  }
87
105
  calledOfflineRetries.set(opKey, offlineRetries);
@@ -91,21 +109,26 @@ async function processQueue() {
91
109
  calledOfflineRetries.delete(opKey);
92
110
  const { error } = await querySupabase({ ...state }, true);
93
111
  if (!error) {
112
+ successfulCalls.add(opKey);
113
+ retryCount.delete(opKey);
94
114
  log(`[Supastash] Synced item on ${state.table} with ${state.method} to supabase`);
115
+ resolve(true);
95
116
  break;
96
117
  }
97
- const currentRetry = (retryCount.get(opKey) ?? 0) + 1;
98
- logError(`[Supastash] Remote sync failed: ${opKey} (${currentRetry}/${MAX_RETRIES}) ${error.message}`);
99
- retryCount.set(opKey, currentRetry);
100
- await delay(100 * currentRetry);
118
+ else {
119
+ const currentRetries = retryCount.get(opKey) ?? 0;
120
+ retryCount.set(opKey, currentRetries + 1);
121
+ if (currentRetries >= MAX_RETRIES) {
122
+ logWarn(`[Supastash] Gave up on ${opKey} after ${MAX_RETRIES} retries`);
123
+ reject(new Error(`Max retries exceeded for ${opKey}`));
124
+ break;
125
+ }
126
+ await delay(1000 * (currentRetries + 1));
127
+ }
101
128
  }
102
129
  }
103
130
  catch (error) {
104
- logWarn(`[Supastash] Error running remote query: ${opKey} → ${error}`);
105
- }
106
- finally {
107
- retryCount.delete(opKey);
108
- stateCache.delete(opKey);
131
+ reject(error);
109
132
  }
110
133
  }
111
134
  isProcessing = false;
@@ -138,7 +161,7 @@ export async function runSyncStrategy(state) {
138
161
  remoteResult = await querySupabase(state);
139
162
  }
140
163
  else {
141
- addToCache(state);
164
+ queueRemoteCall(state);
142
165
  }
143
166
  break;
144
167
  case "remoteFirst":
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "supastash",
3
- "version": "0.1.22",
3
+ "version": "0.1.24",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "type": "module",