supastash 0.2.9 → 0.2.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/dist/desktop/hooks/syncEngine.d.ts.map +1 -1
- package/dist/desktop/hooks/syncEngine.js +7 -2
- package/dist/desktop/index.d.ts +3 -2
- package/dist/desktop/index.d.ts.map +1 -1
- package/dist/desktop/index.js +1 -0
- package/dist/desktop/utils/sync/pullFromRemote/index.d.ts +2 -1
- package/dist/desktop/utils/sync/pullFromRemote/index.d.ts.map +1 -1
- package/dist/desktop/utils/sync/pullFromRemote/index.js +3 -2
- package/dist/desktop/utils/sync/pullFromRemote/pullFromRemoteBatch.d.ts +9 -0
- package/dist/desktop/utils/sync/pullFromRemote/pullFromRemoteBatch.d.ts.map +1 -0
- package/dist/desktop/utils/sync/pullFromRemote/pullFromRemoteBatch.js +202 -0
- package/dist/desktop/utils/sync/pushLocal/uploadChunk.d.ts.map +1 -1
- package/dist/desktop/utils/sync/pushLocal/uploadChunk.js +54 -11
- package/dist/desktop/utils/sync/pushLocal/uploadHelpers.d.ts +1 -1
- package/dist/desktop/utils/sync/pushLocal/uploadHelpers.d.ts.map +1 -1
- package/dist/desktop/utils/sync/pushLocal/uploadHelpers.js +24 -2
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/native/hooks/syncEngine.d.ts.map +1 -1
- package/dist/native/hooks/syncEngine.js +7 -2
- package/dist/native/index.d.ts +1 -0
- package/dist/native/index.d.ts.map +1 -1
- package/dist/native/index.js +1 -0
- package/dist/native/utils/sync/pullFromRemote/index.d.ts +2 -1
- package/dist/native/utils/sync/pullFromRemote/index.d.ts.map +1 -1
- package/dist/native/utils/sync/pullFromRemote/index.js +7 -1
- package/dist/native/utils/sync/pullFromRemote/pullFromRemoteBatch.d.ts +9 -0
- package/dist/native/utils/sync/pullFromRemote/pullFromRemoteBatch.d.ts.map +1 -0
- package/dist/native/utils/sync/pullFromRemote/pullFromRemoteBatch.js +183 -0
- package/dist/native/utils/sync/pushLocal/uploadChunk.d.ts.map +1 -1
- package/dist/native/utils/sync/pushLocal/uploadChunk.js +53 -11
- package/dist/native/utils/sync/pushLocal/uploadHelpers.d.ts +1 -1
- package/dist/native/utils/sync/pushLocal/uploadHelpers.d.ts.map +1 -1
- package/dist/native/utils/sync/pushLocal/uploadHelpers.js +24 -2
- package/dist/shared/core/config/index.d.ts.map +1 -1
- package/dist/shared/core/config/index.js +2 -0
- package/dist/shared/hooks/supastashFilters/index.d.ts +9 -4
- package/dist/shared/hooks/supastashFilters/index.d.ts.map +1 -1
- package/dist/shared/hooks/supastashFilters/index.js +13 -5
- package/dist/shared/store/rpcTableFilters.d.ts +7 -0
- package/dist/shared/store/rpcTableFilters.d.ts.map +1 -0
- package/dist/shared/store/rpcTableFilters.js +5 -0
- package/dist/shared/types/rpcFilter.types.d.ts +23 -0
- package/dist/shared/types/supastashConfig.types.d.ts +38 -10
- package/dist/shared/utils/schema/createSyncStatus.d.ts.map +1 -1
- package/dist/shared/utils/schema/createSyncStatus.js +5 -1
- package/dist/shared/utils/sync/pullFromRemote/postgrestToRpc.d.ts +9 -0
- package/dist/shared/utils/sync/pullFromRemote/postgrestToRpc.d.ts.map +1 -0
- package/dist/shared/utils/sync/pullFromRemote/postgrestToRpc.js +50 -0
- package/dist/shared/utils/sync/pullFromRemote/updateFilter.d.ts +8 -5
- package/dist/shared/utils/sync/pullFromRemote/updateFilter.d.ts.map +1 -1
- package/dist/shared/utils/sync/pullFromRemote/updateFilter.js +11 -5
- package/dist/shared/utils/sync/pullFromRemote/updateRpcFilters.d.ts +12 -0
- package/dist/shared/utils/sync/pullFromRemote/updateRpcFilters.d.ts.map +1 -0
- package/dist/shared/utils/sync/pullFromRemote/updateRpcFilters.js +36 -0
- package/dist/shared/utils/sync/status/remoteSchema.d.ts +12 -0
- package/dist/shared/utils/sync/status/remoteSchema.d.ts.map +1 -1
- package/dist/shared/utils/sync/status/remoteSchema.js +46 -0
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"syncEngine.d.ts","sourceRoot":"","sources":["../../../src/desktop/hooks/syncEngine.ts"],"names":[],"mappings":"AA6BA;;;;;GAKG;AACH,wBAAsB,OAAO,CAAC,KAAK,GAAE,OAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAqCnE;
|
|
1
|
+
{"version":3,"file":"syncEngine.d.ts","sourceRoot":"","sources":["../../../src/desktop/hooks/syncEngine.ts"],"names":[],"mappings":"AA6BA;;;;;GAKG;AACH,wBAAsB,OAAO,CAAC,KAAK,GAAE,OAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAqCnE;AA2DD;;;;;GAKG;AACH,wBAAgB,aAAa;;;EA2D5B;AAMD;;;;GAIG;AACH,wBAAsB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAgC5D;AAED;;GAEG;AACH,wBAAsB,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CAEnD"}
|
|
@@ -7,8 +7,8 @@ import { isOnline } from "../../shared/utils/connection";
|
|
|
7
7
|
import log from "../../shared/utils/logs";
|
|
8
8
|
import { subscribeToAppVisibility } from "../adapters/appstate";
|
|
9
9
|
import { pullFromRemote as doPullFromRemote } from "../utils/sync/pullFromRemote";
|
|
10
|
+
import { pullFromRemoteBatch } from "../utils/sync/pullFromRemote/pullFromRemoteBatch";
|
|
10
11
|
import { updateLocalDb } from "../utils/sync/pullFromRemote/updateLocalDb";
|
|
11
|
-
import { pushLocalData as doPushLocalData } from "../utils/sync/pushLocal";
|
|
12
12
|
import { pushLocalDataToRemote } from "../utils/sync/pushLocal/sendUnsyncedToSupabase";
|
|
13
13
|
// -----------------------------
|
|
14
14
|
// Module-scoped state & tunables
|
|
@@ -85,7 +85,12 @@ async function pushLocalDataSafe() {
|
|
|
85
85
|
return;
|
|
86
86
|
isPushing = true;
|
|
87
87
|
try {
|
|
88
|
-
|
|
88
|
+
if (cfg.useBatchPullSync) {
|
|
89
|
+
await pullFromRemoteBatch();
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
await doPullFromRemote();
|
|
93
|
+
}
|
|
89
94
|
lastPushAt = Date.now();
|
|
90
95
|
}
|
|
91
96
|
catch (e) {
|
package/dist/desktop/index.d.ts
CHANGED
|
@@ -9,6 +9,7 @@ export { refreshScreen } from "../shared/utils/refreshScreenCalls";
|
|
|
9
9
|
export { getSupastashRuntimeMode, reinitializeSupastash, } from "../shared/utils/supastashMode";
|
|
10
10
|
export { getAllTables } from "../shared/utils/sync/getAllTables";
|
|
11
11
|
export { updateFilters } from "../shared/utils/sync/pullFromRemote/updateFilter";
|
|
12
|
+
export { updateRpcFilters } from "../shared/utils/sync/pullFromRemote/updateRpcFilters";
|
|
12
13
|
export { refreshAllTables, refreshTable, refreshTableWithPayload, } from "../shared/utils/sync/refreshTables";
|
|
13
14
|
export { clearSyncCalls, getAllSyncTables, getSyncCall, registerSyncCall, unregisterSyncCall, } from "../shared/utils/sync/registration/syncCalls";
|
|
14
15
|
export { defineLocalSchema } from "./core/schemaManager";
|
|
@@ -21,8 +22,8 @@ export { updateLocalDb, upsertChunkData, upsertData, } from "./utils/sync/pullFr
|
|
|
21
22
|
export { clearAllLocalDeleteLog, clearAllLocalSyncLog, clearLocalDeleteLog, clearLocalSyncLog, clearSyncLog, getLocalDeleteLog, getSyncLog, resetSyncLog, setLocalDeleteLog, setLocalSyncLog, setSyncLog, } from "./utils/sync/status/syncStatus";
|
|
22
23
|
export type { CrudMethods } from "../shared/types/query.types";
|
|
23
24
|
export type { RealtimeOptions, SupastashDataResult, SupastashFilter, } from "../shared/types/realtimeData.types";
|
|
24
|
-
export type { ExpoSQLiteClient, RNSqliteNitroClient, RNStorageSQLiteClient, SupastashConfig, SupastashHookReturn, SupastashSQLiteClientTypes, SupastashSQLiteDatabase, SupastashSQLiteExecutor, TauriSQLiteClient, } from "../shared/types/supastashConfig.types";
|
|
25
25
|
export type { LocalSchemaDefinition } from "../shared/types/schemaManager.types";
|
|
26
|
-
export type {
|
|
26
|
+
export type { ExpoSQLiteClient, RNSqliteNitroClient, RNStorageSQLiteClient, SupastashConfig, SupastashHookReturn, SupastashSQLiteClientTypes, SupastashSQLiteDatabase, SupastashSQLiteExecutor, TauriSQLiteClient, } from "../shared/types/supastashConfig.types";
|
|
27
27
|
export type { SupastashClient, SupastashTransactionClient, } from "../shared/utils/query/builder";
|
|
28
|
+
export type { SyncInfo } from "../shared/types/syncEngine.types";
|
|
28
29
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/desktop/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAC/E,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AACvE,OAAO,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AACpE,OAAO,EACL,aAAa,EACb,gBAAgB,EAChB,YAAY,GACb,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AACpE,OAAO,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAC1D,OAAO,EAAE,aAAa,EAAE,MAAM,oCAAoC,CAAC;AACnE,OAAO,EACL,uBAAuB,EACvB,qBAAqB,GACtB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,YAAY,EAAE,MAAM,mCAAmC,CAAC;AACjE,OAAO,EAAE,aAAa,EAAE,MAAM,kDAAkD,CAAC;AACjF,OAAO,EACL,gBAAgB,EAChB,YAAY,EACZ,uBAAuB,GACxB,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EACL,cAAc,EACd,gBAAgB,EAChB,WAAW,EACX,gBAAgB,EAChB,kBAAkB,GACnB,MAAM,6CAA6C,CAAC;AACrD,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC9D,OAAO,EACL,aAAa,EACb,SAAS,EACT,aAAa,EACb,uBAAuB,EACvB,oBAAoB,EACpB,SAAS,GACV,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,cAAc,EAAE,MAAM,wCAAwC,CAAC;AACxE,OAAO,EACL,aAAa,EACb,eAAe,EACf,UAAU,GACX,MAAM,2CAA2C,CAAC;AACnD,OAAO,EACL,sBAAsB,EACtB,oBAAoB,EACpB,mBAAmB,EACnB,iBAAiB,EACjB,YAAY,EACZ,iBAAiB,EACjB,UAAU,EACV,YAAY,EACZ,iBAAiB,EACjB,eAAe,EACf,UAAU,GACX,MAAM,gCAAgC,CAAC;AAExC,YAAY,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAC/D,YAAY,EACV,eAAe,EACf,mBAAmB,EACnB,eAAe,GAChB,MAAM,oCAAoC,CAAC;AAC5C,YAAY,EACV,gBAAgB,EAChB,mBAAmB,EACnB,qBAAqB,EACrB,eAAe,EACf,mBAAmB,EACnB,0BAA0B,EAC1B,uBAAuB,EACvB,uBAAuB,EACvB,iBAAiB,GAClB,MAAM,uCAAuC,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/desktop/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAC/E,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AACvE,OAAO,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AACpE,OAAO,EACL,aAAa,EACb,gBAAgB,EAChB,YAAY,GACb,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AACpE,OAAO,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAC1D,OAAO,EAAE,aAAa,EAAE,MAAM,oCAAoC,CAAC;AACnE,OAAO,EACL,uBAAuB,EACvB,qBAAqB,GACtB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,YAAY,EAAE,MAAM,mCAAmC,CAAC;AACjE,OAAO,EAAE,aAAa,EAAE,MAAM,kDAAkD,CAAC;AACjF,OAAO,EAAE,gBAAgB,EAAE,MAAM,sDAAsD,CAAC;AACxF,OAAO,EACL,gBAAgB,EAChB,YAAY,EACZ,uBAAuB,GACxB,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EACL,cAAc,EACd,gBAAgB,EAChB,WAAW,EACX,gBAAgB,EAChB,kBAAkB,GACnB,MAAM,6CAA6C,CAAC;AACrD,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC9D,OAAO,EACL,aAAa,EACb,SAAS,EACT,aAAa,EACb,uBAAuB,EACvB,oBAAoB,EACpB,SAAS,GACV,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,cAAc,EAAE,MAAM,wCAAwC,CAAC;AACxE,OAAO,EACL,aAAa,EACb,eAAe,EACf,UAAU,GACX,MAAM,2CAA2C,CAAC;AACnD,OAAO,EACL,sBAAsB,EACtB,oBAAoB,EACpB,mBAAmB,EACnB,iBAAiB,EACjB,YAAY,EACZ,iBAAiB,EACjB,UAAU,EACV,YAAY,EACZ,iBAAiB,EACjB,eAAe,EACf,UAAU,GACX,MAAM,gCAAgC,CAAC;AAExC,YAAY,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAC/D,YAAY,EACV,eAAe,EACf,mBAAmB,EACnB,eAAe,GAChB,MAAM,oCAAoC,CAAC;AAC5C,YAAY,EAAE,qBAAqB,EAAE,MAAM,qCAAqC,CAAC;AACjF,YAAY,EACV,gBAAgB,EAChB,mBAAmB,EACnB,qBAAqB,EACrB,eAAe,EACf,mBAAmB,EACnB,0BAA0B,EAC1B,uBAAuB,EACvB,uBAAuB,EACvB,iBAAiB,GAClB,MAAM,uCAAuC,CAAC;AAC/C,YAAY,EACV,eAAe,EACf,0BAA0B,GAC3B,MAAM,+BAA+B,CAAC;AAEvC,YAAY,EAAE,QAAQ,EAAE,MAAM,kCAAkC,CAAC"}
|
package/dist/desktop/index.js
CHANGED
|
@@ -9,6 +9,7 @@ export { refreshScreen } from "../shared/utils/refreshScreenCalls";
|
|
|
9
9
|
export { getSupastashRuntimeMode, reinitializeSupastash, } from "../shared/utils/supastashMode";
|
|
10
10
|
export { getAllTables } from "../shared/utils/sync/getAllTables";
|
|
11
11
|
export { updateFilters } from "../shared/utils/sync/pullFromRemote/updateFilter";
|
|
12
|
+
export { updateRpcFilters } from "../shared/utils/sync/pullFromRemote/updateRpcFilters";
|
|
12
13
|
export { refreshAllTables, refreshTable, refreshTableWithPayload, } from "../shared/utils/sync/refreshTables";
|
|
13
14
|
export { clearSyncCalls, getAllSyncTables, getSyncCall, registerSyncCall, unregisterSyncCall, } from "../shared/utils/sync/registration/syncCalls";
|
|
14
15
|
export { defineLocalSchema } from "./core/schemaManager";
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Pulls the data from the remote database to the local database
|
|
2
|
+
* Pulls the data from the remote database to the local database (per-table path).
|
|
3
|
+
* For the batch RPC path, see pullFromRemoteBatch — routed via syncEngine.
|
|
3
4
|
*/
|
|
4
5
|
export declare function pullFromRemote(): Promise<void>;
|
|
5
6
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/desktop/utils/sync/pullFromRemote/index.ts"],"names":[],"mappings":"AASA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/desktop/utils/sync/pullFromRemote/index.ts"],"names":[],"mappings":"AASA;;;GAGG;AACH,wBAAsB,cAAc,kBAqEnC"}
|
|
@@ -5,9 +5,10 @@ import log from "../../../../shared/utils/logs";
|
|
|
5
5
|
import { getAllTables } from "../../../../shared/utils/sync/getAllTables";
|
|
6
6
|
import { runLimitedConcurrency } from "../../../../shared/utils/sync/pullFromRemote/runLimitedConcurrency";
|
|
7
7
|
import { SyncInfoUpdater } from "../../../../shared/utils/sync/queryStatus";
|
|
8
|
-
import { updateLocalDb } from "
|
|
8
|
+
import { updateLocalDb } from "./updateLocalDb";
|
|
9
9
|
/**
|
|
10
|
-
* Pulls the data from the remote database to the local database
|
|
10
|
+
* Pulls the data from the remote database to the local database (per-table path).
|
|
11
|
+
* For the batch RPC path, see pullFromRemoteBatch — routed via syncEngine.
|
|
11
12
|
*/
|
|
12
13
|
export async function pullFromRemote() {
|
|
13
14
|
let numberOfTables = 0;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Batch pull: fetches all tables in a single RPC call per round,
|
|
3
|
+
* looping until `remaining_tables` is empty.
|
|
4
|
+
*
|
|
5
|
+
* Requires `useBatchPullSync: true` in config and the
|
|
6
|
+
* `supastash_pull_sync` Postgres function to be deployed.
|
|
7
|
+
*/
|
|
8
|
+
export declare function pullFromRemoteBatch(): Promise<void>;
|
|
9
|
+
//# sourceMappingURL=pullFromRemoteBatch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pullFromRemoteBatch.d.ts","sourceRoot":"","sources":["../../../../../src/desktop/utils/sync/pullFromRemote/pullFromRemoteBatch.ts"],"names":[],"mappings":"AA+CA;;;;;;GAMG;AACH,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC,CA4MzD"}
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
import { getSupastashConfig } from "../../../../shared/core/config";
|
|
2
|
+
import { getSupastashDb } from "../../../../shared/db/dbInitializer";
|
|
3
|
+
import { rpcTableFilters } from "../../../../shared/store/rpcTableFilters";
|
|
4
|
+
import { tableFilters } from "../../../../shared/store/tableFilters";
|
|
5
|
+
import log, { logError, logWarn } from "../../../../shared/utils/logs";
|
|
6
|
+
import { refreshScreen } from "../../../../shared/utils/refreshScreenCalls";
|
|
7
|
+
import { supabaseClientErr } from "../../../../shared/utils/supabaseClientErr";
|
|
8
|
+
import { getAllTables } from "../../../../shared/utils/sync/getAllTables";
|
|
9
|
+
import { getMaxSyncLookBack, logNoUpdates, returnMaxDate, } from "../../../../shared/utils/sync/pullFromRemote/helpers";
|
|
10
|
+
import { postgrestFiltersToRpc } from "../../../../shared/utils/sync/pullFromRemote/postgrestToRpc";
|
|
11
|
+
import { SyncInfoUpdater } from "../../../../shared/utils/sync/queryStatus";
|
|
12
|
+
import { prefetchRemoteTableSchemas } from "../../../../shared/utils/sync/status/remoteSchema";
|
|
13
|
+
import { selectSyncStatus } from "../status/repo";
|
|
14
|
+
import { setSupastashSyncStatus } from "../status/services";
|
|
15
|
+
import { upsertChunkData } from "./updateLocalDb";
|
|
16
|
+
const CHUNK_SIZE = 999;
|
|
17
|
+
function buildCursorFilter(tsCol, lastSyncedAt, lastPk) {
|
|
18
|
+
if (lastPk) {
|
|
19
|
+
return {
|
|
20
|
+
or: [
|
|
21
|
+
{ col: tsCol, op: "gt", val: lastSyncedAt },
|
|
22
|
+
{
|
|
23
|
+
and: [
|
|
24
|
+
{ col: tsCol, op: "eq", val: lastSyncedAt },
|
|
25
|
+
{ col: "id", op: "gt", val: lastPk },
|
|
26
|
+
],
|
|
27
|
+
},
|
|
28
|
+
],
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
return { col: tsCol, op: "gte", val: lastSyncedAt };
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Batch pull: fetches all tables in a single RPC call per round,
|
|
35
|
+
* looping until `remaining_tables` is empty.
|
|
36
|
+
*
|
|
37
|
+
* Requires `useBatchPullSync: true` in config and the
|
|
38
|
+
* `supastash_pull_sync` Postgres function to be deployed.
|
|
39
|
+
*/
|
|
40
|
+
export async function pullFromRemoteBatch() {
|
|
41
|
+
const cfg = getSupastashConfig();
|
|
42
|
+
const supabase = cfg.supabaseClient;
|
|
43
|
+
if (!supabase)
|
|
44
|
+
throw new Error(`No supabase client found: ${supabaseClientErr}`);
|
|
45
|
+
if (cfg.supastashMode === "ghost")
|
|
46
|
+
return;
|
|
47
|
+
const tables = await getAllTables();
|
|
48
|
+
if (!tables) {
|
|
49
|
+
log("[Supastash] Batch pull: no tables found");
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
const excludeTables = cfg.excludeTables?.pull ?? [];
|
|
53
|
+
const tablesToPull = tables.filter((t) => !excludeTables.includes(t));
|
|
54
|
+
if (!tablesToPull.length)
|
|
55
|
+
return;
|
|
56
|
+
const tsCol = cfg.replicationMode === "server-side" ? "arrived_at" : "updated_at";
|
|
57
|
+
const db = await getSupastashDb();
|
|
58
|
+
const completedTables = new Set();
|
|
59
|
+
SyncInfoUpdater.setInProgress({ action: "start", type: "pull" });
|
|
60
|
+
SyncInfoUpdater.setNumberOfTables({
|
|
61
|
+
amount: tablesToPull.length,
|
|
62
|
+
type: "pull",
|
|
63
|
+
});
|
|
64
|
+
// Warm schema cache for all tables in one call if enabled
|
|
65
|
+
if (cfg.useBatchSchemaFetch) {
|
|
66
|
+
await prefetchRemoteTableSchemas(tablesToPull);
|
|
67
|
+
}
|
|
68
|
+
let remainingTables = tablesToPull;
|
|
69
|
+
try {
|
|
70
|
+
while (remainingTables.length > 0) {
|
|
71
|
+
// ── Build per-table filters: base filters + cursor ──────────────────
|
|
72
|
+
const p_filters = {};
|
|
73
|
+
for (const table of remainingTables) {
|
|
74
|
+
const syncStatus = await selectSyncStatus(db, table, tableFilters.get(table) ?? []);
|
|
75
|
+
// Mirror pageThrough: cap the cursor to maxSyncLookbackDays so a
|
|
76
|
+
// first-time sync doesn't try to pull decades of data.
|
|
77
|
+
// fullSyncTables bypass the cap (getMaxSyncLookBack returns undefined).
|
|
78
|
+
const maxLookBack = getMaxSyncLookBack({ table });
|
|
79
|
+
const effectiveSince = maxLookBack &&
|
|
80
|
+
Date.parse(syncStatus.last_synced_at) < Date.parse(maxLookBack)
|
|
81
|
+
? maxLookBack
|
|
82
|
+
: syncStatus.last_synced_at;
|
|
83
|
+
const cursorFilter = buildCursorFilter(tsCol, effectiveSince, syncStatus.last_synced_at_pk);
|
|
84
|
+
// Merge explicit RPC filters + PostgREST filters auto-converted at query time
|
|
85
|
+
const rpcBase = rpcTableFilters.get(table) ?? [];
|
|
86
|
+
const converted = postgrestFiltersToRpc(tableFilters.get(table));
|
|
87
|
+
const baseFilters = [...rpcBase, ...converted];
|
|
88
|
+
p_filters[table] = [...baseFilters, cursorFilter];
|
|
89
|
+
}
|
|
90
|
+
// ── Single RPC call ─────────────────────────────────────────────────
|
|
91
|
+
const { data, error } = await supabase.rpc("supastash_pull_sync", {
|
|
92
|
+
p_tables: remainingTables,
|
|
93
|
+
p_filters,
|
|
94
|
+
p_ts_col: tsCol,
|
|
95
|
+
});
|
|
96
|
+
if (error)
|
|
97
|
+
throw error;
|
|
98
|
+
const result = data;
|
|
99
|
+
const nextRemaining = result.remaining_tables ?? [];
|
|
100
|
+
// ── Process each table ──────────────────────────────────────────────
|
|
101
|
+
for (const [table, rows] of Object.entries(result.tables ?? {})) {
|
|
102
|
+
SyncInfoUpdater.markLogStart({ type: "pull", table });
|
|
103
|
+
try {
|
|
104
|
+
if (!rows?.length) {
|
|
105
|
+
logNoUpdates(table);
|
|
106
|
+
SyncInfoUpdater.markLogSuccess({ type: "pull", table });
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
109
|
+
const toDelete = [];
|
|
110
|
+
const toUpsert = [];
|
|
111
|
+
let prevMaxSyncedAt = null;
|
|
112
|
+
let prevMaxDeletedAt = null;
|
|
113
|
+
for (const row of rows) {
|
|
114
|
+
if (!row?.id) {
|
|
115
|
+
logWarn(`[Supastash] Batch: skipped row without id from "${table}"`);
|
|
116
|
+
continue;
|
|
117
|
+
}
|
|
118
|
+
prevMaxSyncedAt = returnMaxDate({
|
|
119
|
+
row,
|
|
120
|
+
prevMax: prevMaxSyncedAt,
|
|
121
|
+
col: tsCol,
|
|
122
|
+
});
|
|
123
|
+
prevMaxDeletedAt = returnMaxDate({
|
|
124
|
+
row,
|
|
125
|
+
prevMax: prevMaxDeletedAt,
|
|
126
|
+
col: "deleted_at",
|
|
127
|
+
});
|
|
128
|
+
if (row.deleted_at) {
|
|
129
|
+
toDelete.push(row.id);
|
|
130
|
+
}
|
|
131
|
+
else {
|
|
132
|
+
toUpsert.push(row);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
SyncInfoUpdater.setUnsyncedDataCount({
|
|
136
|
+
amount: toUpsert.length,
|
|
137
|
+
type: "pull",
|
|
138
|
+
table,
|
|
139
|
+
});
|
|
140
|
+
SyncInfoUpdater.setUnsyncedDeletedCount({
|
|
141
|
+
amount: toDelete.length,
|
|
142
|
+
type: "pull",
|
|
143
|
+
table,
|
|
144
|
+
});
|
|
145
|
+
// Delete soft-deleted rows
|
|
146
|
+
if (toDelete.length > 0) {
|
|
147
|
+
for (let i = 0; i < toDelete.length; i += CHUNK_SIZE) {
|
|
148
|
+
const slice = toDelete.slice(i, i + CHUNK_SIZE);
|
|
149
|
+
const placeholders = slice.map(() => "?").join(", ");
|
|
150
|
+
await db.runAsync(`DELETE FROM ${table} WHERE id IN (${placeholders})`, slice);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
// Upsert live rows
|
|
154
|
+
if (toUpsert.length > 0) {
|
|
155
|
+
await upsertChunkData({ table, records: toUpsert });
|
|
156
|
+
}
|
|
157
|
+
// Update sync cursor so the next round starts from the right place
|
|
158
|
+
if (prevMaxSyncedAt || prevMaxDeletedAt) {
|
|
159
|
+
await setSupastashSyncStatus(table, tableFilters.get(table) ?? [], {
|
|
160
|
+
lastSyncedAt: prevMaxSyncedAt?.value ?? undefined,
|
|
161
|
+
lastDeletedAt: prevMaxDeletedAt?.value ?? undefined,
|
|
162
|
+
lastSyncedAtPk: prevMaxSyncedAt?.pk ?? null,
|
|
163
|
+
filterNamespace: "global",
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
if (toUpsert.length > 0 || toDelete.length > 0) {
|
|
167
|
+
refreshScreen(table);
|
|
168
|
+
}
|
|
169
|
+
log(`[Supastash] Batch received ${rows.length} rows for "${table}" ` +
|
|
170
|
+
`(u${toUpsert.length}/d${toDelete.length})`);
|
|
171
|
+
SyncInfoUpdater.markLogSuccess({ type: "pull", table });
|
|
172
|
+
}
|
|
173
|
+
catch (e) {
|
|
174
|
+
SyncInfoUpdater.markLogError({
|
|
175
|
+
type: "pull",
|
|
176
|
+
table,
|
|
177
|
+
lastError: e,
|
|
178
|
+
errorCount: 1,
|
|
179
|
+
});
|
|
180
|
+
logError(`[Supastash] Batch pull failed for "${table}"`, e);
|
|
181
|
+
}
|
|
182
|
+
finally {
|
|
183
|
+
// Mark table as fully completed only once it leaves remaining_tables
|
|
184
|
+
if (!nextRemaining.includes(table)) {
|
|
185
|
+
completedTables.add(table);
|
|
186
|
+
SyncInfoUpdater.setTablesCompleted({
|
|
187
|
+
amount: completedTables.size,
|
|
188
|
+
type: "pull",
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
remainingTables = nextRemaining;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
catch (error) {
|
|
197
|
+
logError("[Supastash] Error in batch pull from remote", error);
|
|
198
|
+
}
|
|
199
|
+
finally {
|
|
200
|
+
SyncInfoUpdater.reset({ type: "pull" });
|
|
201
|
+
}
|
|
202
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"uploadChunk.d.ts","sourceRoot":"","sources":["../../../../../src/desktop/utils/sync/pushLocal/uploadChunk.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,sCAAsC,CAAC;
|
|
1
|
+
{"version":3,"file":"uploadChunk.d.ts","sourceRoot":"","sources":["../../../../../src/desktop/utils/sync/pushLocal/uploadChunk.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,sCAAsC,CAAC;AA6OnE;;;;GAIG;AACH,wBAAsB,UAAU,CAC9B,KAAK,EAAE,MAAM,EACb,eAAe,EAAE,WAAW,EAAE,EAC9B,cAAc,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,KAAK,OAAO,CAAC,OAAO,CAAC,iBAetD"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { DEFAULT_CHUNK_SIZE } from "../../../../shared/constants/syncDefaults";
|
|
2
2
|
import { getSupastashConfig } from "../../../../shared/core/config";
|
|
3
|
+
import { isOnline } from "../../../../shared/utils/connection";
|
|
3
4
|
import { normalizeForSupabase } from "../../../../shared/utils/getSafeValues";
|
|
4
5
|
import log from "../../../../shared/utils/logs";
|
|
5
6
|
import { supabaseClientErr } from "../../../../shared/utils/supabaseClientErr";
|
|
@@ -28,6 +29,7 @@ async function uploadChunk(table, chunk, onPushToRemote) {
|
|
|
28
29
|
const hasRPCPath = !!config.pushRPCPath;
|
|
29
30
|
const ids = chunk.map((row) => row.id);
|
|
30
31
|
const toPush = [];
|
|
32
|
+
let remoteExistsMap = new Map();
|
|
31
33
|
// If we have a RPC path, we can push the whole chunk. Server validates freshness.
|
|
32
34
|
if (hasRPCPath) {
|
|
33
35
|
toPush.push(...chunk);
|
|
@@ -35,6 +37,8 @@ async function uploadChunk(table, chunk, onPushToRemote) {
|
|
|
35
37
|
else {
|
|
36
38
|
// Fetch remote data for the current chunk
|
|
37
39
|
const remoteIds = await fetchRemoteHeadsChunked(table, ids, supabase);
|
|
40
|
+
for (const id of ids)
|
|
41
|
+
remoteExistsMap.set(id, remoteIds.has(id));
|
|
38
42
|
// Loop through the initial chunk and check if the id is in the remote data
|
|
39
43
|
const filtered = filterRowsByUpdatedAt(table, chunk, remoteIds);
|
|
40
44
|
toPush.push(...filtered);
|
|
@@ -70,7 +74,7 @@ async function uploadChunk(table, chunk, onPushToRemote) {
|
|
|
70
74
|
let batchOk = false;
|
|
71
75
|
// RPC return values
|
|
72
76
|
let completed = [];
|
|
73
|
-
let existsMap = new Map();
|
|
77
|
+
let existsMap = new Map(remoteExistsMap);
|
|
74
78
|
if (onPushToRemote) {
|
|
75
79
|
const ok = await onPushToRemote(pending);
|
|
76
80
|
if (ok)
|
|
@@ -82,12 +86,43 @@ async function uploadChunk(table, chunk, onPushToRemote) {
|
|
|
82
86
|
pending = [...res.data.skipped];
|
|
83
87
|
existsMap = res.data.existsMap;
|
|
84
88
|
batchOk = res.error == null && pending.length === 0;
|
|
85
|
-
// If there was an RPC error, we need to retry the main function
|
|
86
89
|
if (res.error) {
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
90
|
+
if (!(await isOnline())) {
|
|
91
|
+
attempts++;
|
|
92
|
+
await backoff(attempts);
|
|
93
|
+
pending = [...preflightOK];
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
// Online: RPC failed — run per-row single upserts immediately, no retry.
|
|
97
|
+
// pending was reassigned to res.data.skipped (empty on error), so use preflightOK.
|
|
98
|
+
const rowsToProcess = [...preflightOK];
|
|
99
|
+
try {
|
|
100
|
+
const heads = await fetchRemoteHeadsChunked(table, rowsToProcess.map((r) => r.id), supabase);
|
|
101
|
+
for (const r of rowsToProcess)
|
|
102
|
+
existsMap.set(r.id, heads.has(r.id));
|
|
103
|
+
}
|
|
104
|
+
catch {
|
|
105
|
+
// existsMap stays empty — singleUpsert will fall back to upsert
|
|
106
|
+
}
|
|
107
|
+
const syncedNow = [];
|
|
108
|
+
const keep = [];
|
|
109
|
+
for (const row of rowsToProcess) {
|
|
110
|
+
const rowRes = await singleUpsert(table, row, supabase, existsMap);
|
|
111
|
+
if (!rowRes.error) {
|
|
112
|
+
syncedNow.push(row.id);
|
|
113
|
+
continue;
|
|
114
|
+
}
|
|
115
|
+
errorCount++;
|
|
116
|
+
lastError = rowRes.error;
|
|
117
|
+
const decision = await handleRowFailure(config, table, row, rowRes.error, supabase);
|
|
118
|
+
if (decision !== "KEEP")
|
|
119
|
+
continue;
|
|
120
|
+
keep.push(row);
|
|
121
|
+
}
|
|
122
|
+
if (syncedNow.length)
|
|
123
|
+
await markSynced(table, syncedNow);
|
|
124
|
+
pending = keep;
|
|
125
|
+
break;
|
|
91
126
|
}
|
|
92
127
|
}
|
|
93
128
|
else {
|
|
@@ -115,7 +150,7 @@ async function uploadChunk(table, chunk, onPushToRemote) {
|
|
|
115
150
|
res = await rpcUpsertSingle({ table, row, supabase, existsMap });
|
|
116
151
|
}
|
|
117
152
|
else {
|
|
118
|
-
res = await singleUpsert(table, row, supabase);
|
|
153
|
+
res = await singleUpsert(table, row, supabase, existsMap);
|
|
119
154
|
}
|
|
120
155
|
if (!res.error) {
|
|
121
156
|
syncedNow.push(row.id);
|
|
@@ -133,10 +168,18 @@ async function uploadChunk(table, chunk, onPushToRemote) {
|
|
|
133
168
|
await markSynced(table, syncedNow);
|
|
134
169
|
if (keep.length === 0)
|
|
135
170
|
return;
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
171
|
+
if (!(await isOnline())) {
|
|
172
|
+
attempts++;
|
|
173
|
+
await backoff(attempts);
|
|
174
|
+
pending = keep;
|
|
175
|
+
}
|
|
176
|
+
else {
|
|
177
|
+
// Online: errors are genuine failures, not network issues — don't retry
|
|
178
|
+
for (const r of keep)
|
|
179
|
+
setQueryStatus(r.id, table, "error");
|
|
180
|
+
pending = keep; // update pending so post-loop markLogError reflects only true failures
|
|
181
|
+
break;
|
|
182
|
+
}
|
|
140
183
|
}
|
|
141
184
|
if (pending.length > 0) {
|
|
142
185
|
SyncInfoUpdater.markLogError({
|
|
@@ -2,7 +2,7 @@ import { SupastashConfig } from "../../../../shared/types/supastashConfig.types"
|
|
|
2
2
|
import { RowLike } from "../../../../shared/types/syncEngine.types";
|
|
3
3
|
export declare function classifyFailure(cfg: SupastashConfig<any>, code?: string | number): "HTTP" | "UNKNOWN" | "NON_RETRYABLE" | "FK_BLOCK" | "UNIQUE_VIOLATION" | "RETRYABLE";
|
|
4
4
|
declare function batchUpsert(table: string, rows: RowLike[], supabase: any): Promise<any>;
|
|
5
|
-
declare function singleUpsert(table: string, row: RowLike, supabase: any): Promise<any>;
|
|
5
|
+
declare function singleUpsert(table: string, row: RowLike, supabase: any, existsMap?: Map<string, boolean>): Promise<any>;
|
|
6
6
|
declare function backoff(attempts: number): Promise<void>;
|
|
7
7
|
declare function rpcUpsert({ table, rows, supabase, }: {
|
|
8
8
|
table: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"uploadHelpers.d.ts","sourceRoot":"","sources":["../../../../../src/desktop/utils/sync/pushLocal/uploadHelpers.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,gDAAgD,CAAC;AACjF,OAAO,EAAE,OAAO,EAAE,MAAM,2CAA2C,CAAC;AAOpE,wBAAgB,eAAe,CAC7B,GAAG,EAAE,eAAe,CAAC,GAAG,CAAC,EACzB,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,wFAYvB;AAED,iBAAe,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,QAAQ,EAAE,GAAG,gBAEvE;AAED,iBAAe,YAAY,
|
|
1
|
+
{"version":3,"file":"uploadHelpers.d.ts","sourceRoot":"","sources":["../../../../../src/desktop/utils/sync/pushLocal/uploadHelpers.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,gDAAgD,CAAC;AACjF,OAAO,EAAE,OAAO,EAAE,MAAM,2CAA2C,CAAC;AAOpE,wBAAgB,eAAe,CAC7B,GAAG,EAAE,eAAe,CAAC,GAAG,CAAC,EACzB,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,wFAYvB;AAED,iBAAe,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,QAAQ,EAAE,GAAG,gBAEvE;AAED,iBAAe,YAAY,CACzB,KAAK,EAAE,MAAM,EACb,GAAG,EAAE,OAAO,EACZ,QAAQ,EAAE,GAAG,EACb,SAAS,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,gBAwBjC;AAED,iBAAe,OAAO,CAAC,QAAQ,EAAE,MAAM,iBAOtC;AAmBD,iBAAe,SAAS,CAAC,EACvB,KAAK,EACL,IAAI,EACJ,QAAQ,GACT,EAAE;IACD,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,OAAO,EAAE,CAAC;IAChB,QAAQ,EAAE,GAAG,CAAC;CACf;;;;;;;GA+CA;AAED,iBAAe,eAAe,CAAC,EAC7B,KAAK,EACL,GAAG,EACH,QAAQ,EACR,SAAS,GACV,EAAE;IACD,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,OAAO,CAAC;IACb,QAAQ,EAAE,GAAG,CAAC;IACd,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACjC;;;;;;GAaA;AAMD,iBAAe,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,iBAIrD;AAWD,iBAAS,qBAAqB,CAC5B,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,OAAO,EAAE,EAChB,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,aAiCjC;AAMD,iBAAe,gBAAgB,CAC7B,GAAG,EAAE,eAAe,CAAC,GAAG,CAAC,EACzB,KAAK,EAAE,MAAM,EACb,GAAG,EAAE,OAAO,EACZ,GAAG,EAAE,GAAG,EACR,QAAQ,EAAE,GAAG,GACZ,OAAO,CAAC,MAAM,GAAG,MAAM,GAAG,UAAU,CAAC,CA4DvC;AAgBD,OAAO,EACL,OAAO,EACP,WAAW,EACX,qBAAqB,EACrB,gBAAgB,EAChB,UAAU,EACV,SAAS,EACT,eAAe,EACf,YAAY,GACb,CAAC;AAEF;;;GAGG;AACH,wBAAsB,kBAAkB,CACtC,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,GAAG,iBAkBd;AASD,wBAAsB,uBAAuB,CAC3C,KAAK,EAAE,MAAM,EACb,GAAG,EAAE,MAAM,EAAE,EACb,QAAQ,EAAE,GAAG,gCAcd"}
|
|
@@ -26,8 +26,30 @@ export function classifyFailure(cfg, code) {
|
|
|
26
26
|
async function batchUpsert(table, rows, supabase) {
|
|
27
27
|
return await supabase.from(table).upsert(rows);
|
|
28
28
|
}
|
|
29
|
-
async function singleUpsert(table, row, supabase) {
|
|
30
|
-
|
|
29
|
+
async function singleUpsert(table, row, supabase, existsMap) {
|
|
30
|
+
const exists = existsMap?.get(row.id);
|
|
31
|
+
if (exists === true) {
|
|
32
|
+
const { data, error } = await supabase
|
|
33
|
+
.from(table)
|
|
34
|
+
.update(row)
|
|
35
|
+
.eq("id", row.id)
|
|
36
|
+
.select("id")
|
|
37
|
+
.maybeSingle();
|
|
38
|
+
if (!error)
|
|
39
|
+
return { data, error: null };
|
|
40
|
+
// RLS may block update — fall through to upsert
|
|
41
|
+
}
|
|
42
|
+
else if (exists === false) {
|
|
43
|
+
const { data, error } = await supabase
|
|
44
|
+
.from(table)
|
|
45
|
+
.insert(row)
|
|
46
|
+
.select("id")
|
|
47
|
+
.maybeSingle();
|
|
48
|
+
if (!error)
|
|
49
|
+
return { data, error: null };
|
|
50
|
+
// RLS may block insert — fall through to upsert
|
|
51
|
+
}
|
|
52
|
+
return supabase.from(table).upsert(row).select("id").maybeSingle();
|
|
31
53
|
}
|
|
32
54
|
async function backoff(attempts) {
|
|
33
55
|
const config = getSupastashConfig();
|
package/dist/index.d.ts
CHANGED
|
@@ -7,6 +7,7 @@ export { refreshScreen } from "./shared/utils/refreshScreenCalls";
|
|
|
7
7
|
export { getSupastashRuntimeMode, reinitializeSupastash, } from "./shared/utils/supastashMode";
|
|
8
8
|
export { getAllTables } from "./shared/utils/sync/getAllTables";
|
|
9
9
|
export { updateFilters } from "./shared/utils/sync/pullFromRemote/updateFilter";
|
|
10
|
+
export { updateRpcFilters } from "./shared/utils/sync/pullFromRemote/updateRpcFilters";
|
|
10
11
|
export { refreshAllTables, refreshTable, refreshTableWithPayload, } from "./shared/utils/sync/refreshTables";
|
|
11
12
|
export { clearSyncCalls, getAllSyncTables, getSyncCall, registerSyncCall, unregisterSyncCall, } from "./shared/utils/sync/registration/syncCalls";
|
|
12
13
|
export { supastash } from "./shared/utils/query/builder";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC9E,OAAO,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AACtE,OAAO,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAC;AACnE,OAAO,EACL,aAAa,EACb,gBAAgB,EAChB,YAAY,GACb,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AACnE,OAAO,EAAE,aAAa,EAAE,MAAM,mCAAmC,CAAC;AAClE,OAAO,EACL,uBAAuB,EACvB,qBAAqB,GACtB,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAC;AAChE,OAAO,EAAE,aAAa,EAAE,MAAM,iDAAiD,CAAC;AAChF,OAAO,EACL,gBAAgB,EAChB,YAAY,EACZ,uBAAuB,GACxB,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EACL,cAAc,EACd,gBAAgB,EAChB,WAAW,EACX,gBAAgB,EAChB,kBAAkB,GACnB,MAAM,4CAA4C,CAAC;AAEpD,OAAO,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAC;AAEzD,YAAY,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAC9D,YAAY,EACV,eAAe,EACf,mBAAmB,EACnB,eAAe,GAChB,MAAM,mCAAmC,CAAC;AAC3C,YAAY,EAAE,qBAAqB,EAAE,MAAM,oCAAoC,CAAC;AAChF,YAAY,EACV,gBAAgB,EAChB,mBAAmB,EACnB,qBAAqB,EACrB,eAAe,EACf,mBAAmB,EACnB,0BAA0B,EAC1B,uBAAuB,EACvB,uBAAuB,EACvB,iBAAiB,GAClB,MAAM,sCAAsC,CAAC;AAC9C,YAAY,EAAE,QAAQ,EAAE,MAAM,iCAAiC,CAAC;AAChE,YAAY,EACV,eAAe,EACf,0BAA0B,GAC3B,MAAM,8BAA8B,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC9E,OAAO,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AACtE,OAAO,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAC;AACnE,OAAO,EACL,aAAa,EACb,gBAAgB,EAChB,YAAY,GACb,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AACnE,OAAO,EAAE,aAAa,EAAE,MAAM,mCAAmC,CAAC;AAClE,OAAO,EACL,uBAAuB,EACvB,qBAAqB,GACtB,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAC;AAChE,OAAO,EAAE,aAAa,EAAE,MAAM,iDAAiD,CAAC;AAChF,OAAO,EAAE,gBAAgB,EAAE,MAAM,qDAAqD,CAAC;AACvF,OAAO,EACL,gBAAgB,EAChB,YAAY,EACZ,uBAAuB,GACxB,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EACL,cAAc,EACd,gBAAgB,EAChB,WAAW,EACX,gBAAgB,EAChB,kBAAkB,GACnB,MAAM,4CAA4C,CAAC;AAEpD,OAAO,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAC;AAEzD,YAAY,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAC9D,YAAY,EACV,eAAe,EACf,mBAAmB,EACnB,eAAe,GAChB,MAAM,mCAAmC,CAAC;AAC3C,YAAY,EAAE,qBAAqB,EAAE,MAAM,oCAAoC,CAAC;AAChF,YAAY,EACV,gBAAgB,EAChB,mBAAmB,EACnB,qBAAqB,EACrB,eAAe,EACf,mBAAmB,EACnB,0BAA0B,EAC1B,uBAAuB,EACvB,uBAAuB,EACvB,iBAAiB,GAClB,MAAM,sCAAsC,CAAC;AAC9C,YAAY,EAAE,QAAQ,EAAE,MAAM,iCAAiC,CAAC;AAChE,YAAY,EACV,eAAe,EACf,0BAA0B,GAC3B,MAAM,8BAA8B,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -7,6 +7,7 @@ export { refreshScreen } from "./shared/utils/refreshScreenCalls";
|
|
|
7
7
|
export { getSupastashRuntimeMode, reinitializeSupastash, } from "./shared/utils/supastashMode";
|
|
8
8
|
export { getAllTables } from "./shared/utils/sync/getAllTables";
|
|
9
9
|
export { updateFilters } from "./shared/utils/sync/pullFromRemote/updateFilter";
|
|
10
|
+
export { updateRpcFilters } from "./shared/utils/sync/pullFromRemote/updateRpcFilters";
|
|
10
11
|
export { refreshAllTables, refreshTable, refreshTableWithPayload, } from "./shared/utils/sync/refreshTables";
|
|
11
12
|
export { clearSyncCalls, getAllSyncTables, getSyncCall, registerSyncCall, unregisterSyncCall, } from "./shared/utils/sync/registration/syncCalls";
|
|
12
13
|
export { supastash } from "./shared/utils/query/builder";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"syncEngine.d.ts","sourceRoot":"","sources":["../../../src/native/hooks/syncEngine.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"syncEngine.d.ts","sourceRoot":"","sources":["../../../src/native/hooks/syncEngine.ts"],"names":[],"mappings":"AA8BA;;;;;GAKG;AACH,wBAAsB,OAAO,CAAC,KAAK,GAAE,OAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAqCnE;AAyDD;;;;;GAKG;AACH,wBAAgB,aAAa;;;EA+D5B;AAMD;;;;GAIG;AACH,wBAAsB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAgC5D;AAED;;GAEG;AACH,wBAAsB,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CAEnD"}
|
|
@@ -7,6 +7,7 @@ import { tableFilters } from "../../shared/store/tableFilters";
|
|
|
7
7
|
import { isOnline } from "../../shared/utils/connection";
|
|
8
8
|
import log from "../../shared/utils/logs";
|
|
9
9
|
import { pullFromRemote as doPullFromRemote } from "../utils/sync/pullFromRemote";
|
|
10
|
+
import { pullFromRemoteBatch } from "../utils/sync/pullFromRemote/pullFromRemoteBatch";
|
|
10
11
|
import { updateLocalDb } from "../utils/sync/pullFromRemote/updateLocalDb";
|
|
11
12
|
import { pushLocalData as doPushLocalData } from "../utils/sync/pushLocal";
|
|
12
13
|
import { pushLocalDataToRemote } from "../utils/sync/pushLocal/sendUnsyncedToSupabase";
|
|
@@ -103,7 +104,6 @@ async function pullFromRemoteSafe() {
|
|
|
103
104
|
return;
|
|
104
105
|
if (!(await isOnline()))
|
|
105
106
|
return;
|
|
106
|
-
// If in ghost mode, don't pull
|
|
107
107
|
const cfg = getSupastashConfig();
|
|
108
108
|
if (cfg.supastashMode === "ghost")
|
|
109
109
|
return;
|
|
@@ -111,7 +111,12 @@ async function pullFromRemoteSafe() {
|
|
|
111
111
|
return;
|
|
112
112
|
isPulling = true;
|
|
113
113
|
try {
|
|
114
|
-
|
|
114
|
+
if (cfg.useBatchPullSync) {
|
|
115
|
+
await pullFromRemoteBatch();
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
await doPullFromRemote();
|
|
119
|
+
}
|
|
115
120
|
lastPullAt = Date.now();
|
|
116
121
|
}
|
|
117
122
|
catch (e) {
|
package/dist/native/index.d.ts
CHANGED
|
@@ -9,6 +9,7 @@ export { refreshScreen } from "../shared/utils/refreshScreenCalls";
|
|
|
9
9
|
export { getSupastashRuntimeMode, reinitializeSupastash, } from "../shared/utils/supastashMode";
|
|
10
10
|
export { getAllTables } from "../shared/utils/sync/getAllTables";
|
|
11
11
|
export { updateFilters } from "../shared/utils/sync/pullFromRemote/updateFilter";
|
|
12
|
+
export { updateRpcFilters } from "../shared/utils/sync/pullFromRemote/updateRpcFilters";
|
|
12
13
|
export { refreshAllTables, refreshTable, refreshTableWithPayload, } from "../shared/utils/sync/refreshTables";
|
|
13
14
|
export { clearSyncCalls, getAllSyncTables, getSyncCall, registerSyncCall, unregisterSyncCall, } from "../shared/utils/sync/registration/syncCalls";
|
|
14
15
|
export { defineLocalSchema } from "./core/schemaManager";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/native/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAC/E,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AACvE,OAAO,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AACpE,OAAO,EACL,aAAa,EACb,gBAAgB,EAChB,YAAY,GACb,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AACpE,OAAO,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAC1D,OAAO,EAAE,aAAa,EAAE,MAAM,oCAAoC,CAAC;AACnE,OAAO,EACL,uBAAuB,EACvB,qBAAqB,GACtB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,YAAY,EAAE,MAAM,mCAAmC,CAAC;AACjE,OAAO,EAAE,aAAa,EAAE,MAAM,kDAAkD,CAAC;AACjF,OAAO,EACL,gBAAgB,EAChB,YAAY,EACZ,uBAAuB,GACxB,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EACL,cAAc,EACd,gBAAgB,EAChB,WAAW,EACX,gBAAgB,EAChB,kBAAkB,GACnB,MAAM,6CAA6C,CAAC;AACrD,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC9D,OAAO,EACL,aAAa,EACb,SAAS,EACT,aAAa,EACb,uBAAuB,EACvB,oBAAoB,EACpB,SAAS,GACV,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,cAAc,EAAE,MAAM,wCAAwC,CAAC;AACxE,OAAO,EACL,aAAa,EACb,eAAe,EACf,UAAU,GACX,MAAM,2CAA2C,CAAC;AACnD,OAAO,EACL,sBAAsB,EACtB,oBAAoB,EACpB,mBAAmB,EACnB,iBAAiB,EACjB,YAAY,EACZ,iBAAiB,EACjB,UAAU,EACV,YAAY,EACZ,iBAAiB,EACjB,eAAe,EACf,UAAU,GACX,MAAM,gCAAgC,CAAC;AAExC,YAAY,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAC/D,YAAY,EACV,eAAe,EACf,mBAAmB,EACnB,eAAe,GAChB,MAAM,oCAAoC,CAAC;AAC5C,YAAY,EAAE,qBAAqB,EAAE,MAAM,qCAAqC,CAAC;AACjF,YAAY,EACV,gBAAgB,EAChB,mBAAmB,EACnB,qBAAqB,EACrB,eAAe,EACf,mBAAmB,EACnB,0BAA0B,EAC1B,uBAAuB,EACvB,uBAAuB,EACvB,iBAAiB,GAClB,MAAM,uCAAuC,CAAC;AAC/C,YAAY,EACV,eAAe,EACf,0BAA0B,GAC3B,MAAM,+BAA+B,CAAC;AAEvC,YAAY,EAAE,QAAQ,EAAE,MAAM,kCAAkC,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/native/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAC/E,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AACvE,OAAO,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AACpE,OAAO,EACL,aAAa,EACb,gBAAgB,EAChB,YAAY,GACb,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AACpE,OAAO,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAC1D,OAAO,EAAE,aAAa,EAAE,MAAM,oCAAoC,CAAC;AACnE,OAAO,EACL,uBAAuB,EACvB,qBAAqB,GACtB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,YAAY,EAAE,MAAM,mCAAmC,CAAC;AACjE,OAAO,EAAE,aAAa,EAAE,MAAM,kDAAkD,CAAC;AACjF,OAAO,EAAE,gBAAgB,EAAE,MAAM,sDAAsD,CAAC;AACxF,OAAO,EACL,gBAAgB,EAChB,YAAY,EACZ,uBAAuB,GACxB,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EACL,cAAc,EACd,gBAAgB,EAChB,WAAW,EACX,gBAAgB,EAChB,kBAAkB,GACnB,MAAM,6CAA6C,CAAC;AACrD,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC9D,OAAO,EACL,aAAa,EACb,SAAS,EACT,aAAa,EACb,uBAAuB,EACvB,oBAAoB,EACpB,SAAS,GACV,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,cAAc,EAAE,MAAM,wCAAwC,CAAC;AACxE,OAAO,EACL,aAAa,EACb,eAAe,EACf,UAAU,GACX,MAAM,2CAA2C,CAAC;AACnD,OAAO,EACL,sBAAsB,EACtB,oBAAoB,EACpB,mBAAmB,EACnB,iBAAiB,EACjB,YAAY,EACZ,iBAAiB,EACjB,UAAU,EACV,YAAY,EACZ,iBAAiB,EACjB,eAAe,EACf,UAAU,GACX,MAAM,gCAAgC,CAAC;AAExC,YAAY,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAC/D,YAAY,EACV,eAAe,EACf,mBAAmB,EACnB,eAAe,GAChB,MAAM,oCAAoC,CAAC;AAC5C,YAAY,EAAE,qBAAqB,EAAE,MAAM,qCAAqC,CAAC;AACjF,YAAY,EACV,gBAAgB,EAChB,mBAAmB,EACnB,qBAAqB,EACrB,eAAe,EACf,mBAAmB,EACnB,0BAA0B,EAC1B,uBAAuB,EACvB,uBAAuB,EACvB,iBAAiB,GAClB,MAAM,uCAAuC,CAAC;AAC/C,YAAY,EACV,eAAe,EACf,0BAA0B,GAC3B,MAAM,+BAA+B,CAAC;AAEvC,YAAY,EAAE,QAAQ,EAAE,MAAM,kCAAkC,CAAC"}
|
package/dist/native/index.js
CHANGED
|
@@ -9,6 +9,7 @@ export { refreshScreen } from "../shared/utils/refreshScreenCalls";
|
|
|
9
9
|
export { getSupastashRuntimeMode, reinitializeSupastash, } from "../shared/utils/supastashMode";
|
|
10
10
|
export { getAllTables } from "../shared/utils/sync/getAllTables";
|
|
11
11
|
export { updateFilters } from "../shared/utils/sync/pullFromRemote/updateFilter";
|
|
12
|
+
export { updateRpcFilters } from "../shared/utils/sync/pullFromRemote/updateRpcFilters";
|
|
12
13
|
export { refreshAllTables, refreshTable, refreshTableWithPayload, } from "../shared/utils/sync/refreshTables";
|
|
13
14
|
export { clearSyncCalls, getAllSyncTables, getSyncCall, registerSyncCall, unregisterSyncCall, } from "../shared/utils/sync/registration/syncCalls";
|
|
14
15
|
export { defineLocalSchema } from "./core/schemaManager";
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Pulls the data from the remote database to the local database
|
|
2
|
+
* Pulls the data from the remote database to the local database (per-table path).
|
|
3
|
+
* For the batch RPC path, see pullFromRemoteBatch — routed via syncEngine.
|
|
3
4
|
*/
|
|
4
5
|
export declare function pullFromRemote(): Promise<void>;
|
|
5
6
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/native/utils/sync/pullFromRemote/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/native/utils/sync/pullFromRemote/index.ts"],"names":[],"mappings":"AAUA;;;GAGG;AACH,wBAAsB,cAAc,kBA0EnC"}
|
|
@@ -5,9 +5,11 @@ import log from "../../../../shared/utils/logs";
|
|
|
5
5
|
import { getAllTables } from "../../../../shared/utils/sync/getAllTables";
|
|
6
6
|
import { runLimitedConcurrency } from "../../../../shared/utils/sync/pullFromRemote/runLimitedConcurrency";
|
|
7
7
|
import { SyncInfoUpdater } from "../../../../shared/utils/sync/queryStatus";
|
|
8
|
+
import { prefetchRemoteTableSchemas } from "../../../../shared/utils/sync/status/remoteSchema";
|
|
8
9
|
import { updateLocalDb } from "./updateLocalDb";
|
|
9
10
|
/**
|
|
10
|
-
* Pulls the data from the remote database to the local database
|
|
11
|
+
* Pulls the data from the remote database to the local database (per-table path).
|
|
12
|
+
* For the batch RPC path, see pullFromRemoteBatch — routed via syncEngine.
|
|
11
13
|
*/
|
|
12
14
|
export async function pullFromRemote() {
|
|
13
15
|
let numberOfTables = 0;
|
|
@@ -21,6 +23,10 @@ export async function pullFromRemote() {
|
|
|
21
23
|
const excludeTables = getSupastashConfig()?.excludeTables?.pull || [];
|
|
22
24
|
const tablesToPull = tables.filter((table) => !excludeTables?.includes(table));
|
|
23
25
|
numberOfTables = tablesToPull.length;
|
|
26
|
+
// Warm schema cache for all tables in one call if enabled
|
|
27
|
+
if (getSupastashConfig().useBatchSchemaFetch) {
|
|
28
|
+
await prefetchRemoteTableSchemas(tablesToPull);
|
|
29
|
+
}
|
|
24
30
|
SyncInfoUpdater.setInProgress({
|
|
25
31
|
action: "start",
|
|
26
32
|
type: "pull",
|