@anfenn/dync 1.0.33 → 1.1.0
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 +1 -1
- package/dist/index.cjs +45 -14
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +45 -14
- package/dist/index.js.map +1 -1
- package/dist/react/index.d.cts +1 -1
- package/dist/react/index.d.ts +1 -1
- package/dist/{types-Dhx9MuUp.d.ts → types-BIJhsSOf.d.ts} +7 -5
- package/dist/{types-BszcepJK.d.cts → types-DhCTdAep.d.cts} +7 -5
- package/package.json +2 -2
- package/src/core/StateManager.ts +3 -2
- package/src/core/firstLoad.ts +5 -5
- package/src/core/pullOperations.ts +46 -8
- package/src/core/pushOperations.ts +2 -2
- package/src/index.native.ts +1 -1
- package/src/index.shared.ts +6 -5
- package/src/index.ts +1 -1
- package/src/types.ts +7 -4
package/README.md
CHANGED
|
@@ -45,7 +45,7 @@ And see how Dync compares to the alternatives [below](#hasnt-this-already-been-d
|
|
|
45
45
|
```
|
|
46
46
|
|
|
47
47
|
- Sync some or all tables with any backend in 2 ways:
|
|
48
|
-
- Option 1: Map remote api CRUD urls to a local
|
|
48
|
+
- Option 1: Map remote api CRUD urls to a local table:
|
|
49
49
|
|
|
50
50
|
```ts
|
|
51
51
|
const db = new Dync({
|
package/dist/index.cjs
CHANGED
|
@@ -169,7 +169,7 @@ var SYNC_STATE_KEY = "sync_state";
|
|
|
169
169
|
var DEFAULT_STATE = {
|
|
170
170
|
firstLoadDone: false,
|
|
171
171
|
pendingChanges: [],
|
|
172
|
-
|
|
172
|
+
newestServerUpdatedAt: {}
|
|
173
173
|
};
|
|
174
174
|
var StateManager = class {
|
|
175
175
|
persistedState;
|
|
@@ -339,7 +339,8 @@ function clonePersistedState(state) {
|
|
|
339
339
|
before: cloneRecord(change.before),
|
|
340
340
|
after: cloneRecord(change.after)
|
|
341
341
|
})),
|
|
342
|
-
|
|
342
|
+
newestServerUpdatedAt: { ...state.newestServerUpdatedAt },
|
|
343
|
+
lastPulledAt: state.lastPulledAt ? { ...state.lastPulledAt } : void 0,
|
|
343
344
|
conflicts: cloneConflicts(state.conflicts)
|
|
344
345
|
};
|
|
345
346
|
}
|
|
@@ -738,12 +739,25 @@ async function pullAll(ctx) {
|
|
|
738
739
|
const changedTables = [];
|
|
739
740
|
for (const [tableName, api] of Object.entries(ctx.syncApis)) {
|
|
740
741
|
try {
|
|
741
|
-
const
|
|
742
|
-
|
|
742
|
+
const now = Date.now();
|
|
743
|
+
if (beforeListExtraInterval(api, tableName, ctx, now)) {
|
|
744
|
+
continue;
|
|
745
|
+
}
|
|
746
|
+
const newestServerUpdatedAt = ctx.state.getState().newestServerUpdatedAt[tableName];
|
|
747
|
+
const since = newestServerUpdatedAt ? new Date(newestServerUpdatedAt) : /* @__PURE__ */ new Date(0);
|
|
743
748
|
ctx.logger.debug(`[dync] pull:start tableName=${tableName} since=${since.toISOString()}`);
|
|
744
749
|
const serverData = await api.list(since);
|
|
745
750
|
const changed = await processPullData(tableName, serverData, since, ctx);
|
|
746
751
|
if (changed) changedTables.push(tableName);
|
|
752
|
+
if (hasListExtraInterval(api)) {
|
|
753
|
+
await ctx.state.setState((syncState) => ({
|
|
754
|
+
...syncState,
|
|
755
|
+
lastPulledAt: {
|
|
756
|
+
...syncState.lastPulledAt,
|
|
757
|
+
[tableName]: now
|
|
758
|
+
}
|
|
759
|
+
}));
|
|
760
|
+
}
|
|
747
761
|
} catch (err) {
|
|
748
762
|
firstSyncError = firstSyncError ?? err;
|
|
749
763
|
ctx.logger.error(`[dync] pull:error tableName=${tableName}`, err);
|
|
@@ -751,6 +765,22 @@ async function pullAll(ctx) {
|
|
|
751
765
|
}
|
|
752
766
|
return { error: firstSyncError, changedTables };
|
|
753
767
|
}
|
|
768
|
+
function hasListExtraInterval(api) {
|
|
769
|
+
return Number.isFinite(api.listExtraIntervalMs) && api.listExtraIntervalMs > 0;
|
|
770
|
+
}
|
|
771
|
+
function beforeListExtraInterval(api, tableName, ctx, now) {
|
|
772
|
+
if (!hasListExtraInterval(api)) {
|
|
773
|
+
return false;
|
|
774
|
+
}
|
|
775
|
+
const lastPulledAt = ctx.state.getState().lastPulledAt?.[tableName] ?? 0;
|
|
776
|
+
if (now - lastPulledAt < api.listExtraIntervalMs) {
|
|
777
|
+
ctx.logger.debug(
|
|
778
|
+
`[dync] pull:skip-interval tableName=${tableName} lastPulledAt=${new Date(lastPulledAt).toISOString()} nextAllowed=${new Date(lastPulledAt + api.listExtraIntervalMs).toISOString()}`
|
|
779
|
+
);
|
|
780
|
+
return true;
|
|
781
|
+
}
|
|
782
|
+
return false;
|
|
783
|
+
}
|
|
754
784
|
async function handleRemoteItemUpdate(table, tableName, localItem, remote, ctx) {
|
|
755
785
|
const pendingChange = ctx.state.getState().pendingChanges.find((p) => p.tableName === tableName && p.localId === localItem._localId);
|
|
756
786
|
const conflictStrategy = ctx.conflictResolutionStrategy;
|
|
@@ -807,8 +837,8 @@ async function pullAllBatch(ctx) {
|
|
|
807
837
|
try {
|
|
808
838
|
const sinceMap = {};
|
|
809
839
|
for (const tableName of ctx.batchSync.syncTables) {
|
|
810
|
-
const
|
|
811
|
-
sinceMap[tableName] =
|
|
840
|
+
const newestServerUpdatedAt = ctx.state.getState().newestServerUpdatedAt[tableName];
|
|
841
|
+
sinceMap[tableName] = newestServerUpdatedAt ? new Date(newestServerUpdatedAt) : /* @__PURE__ */ new Date(0);
|
|
812
842
|
}
|
|
813
843
|
ctx.logger.debug(`[dync] pull:batch:start tables=${[...ctx.batchSync.syncTables].join(",")}`, sinceMap);
|
|
814
844
|
const serverDataByTable = await ctx.batchSync.pull(sinceMap);
|
|
@@ -870,8 +900,8 @@ async function processPullData(tableName, serverData, since, ctx) {
|
|
|
870
900
|
}
|
|
871
901
|
await ctx.state.setState((syncState) => ({
|
|
872
902
|
...syncState,
|
|
873
|
-
|
|
874
|
-
...syncState.
|
|
903
|
+
newestServerUpdatedAt: {
|
|
904
|
+
...syncState.newestServerUpdatedAt,
|
|
875
905
|
[tableName]: newest.toISOString()
|
|
876
906
|
}
|
|
877
907
|
}));
|
|
@@ -1153,7 +1183,7 @@ async function startFirstLoad(ctx) {
|
|
|
1153
1183
|
ctx.logger.debug("[dync] First load completed");
|
|
1154
1184
|
}
|
|
1155
1185
|
async function processBatchInChunks(ctx, tableName, batch, isEmptyTable, isFirstBatch) {
|
|
1156
|
-
let newest = new Date(ctx.state.getState().
|
|
1186
|
+
let newest = new Date(ctx.state.getState().newestServerUpdatedAt[tableName] || 0);
|
|
1157
1187
|
return ctx.withTransaction("rw", [tableName, DYNC_STATE_TABLE], async (tables) => {
|
|
1158
1188
|
const txTable = tables[tableName];
|
|
1159
1189
|
let tableIsEmpty = isEmptyTable;
|
|
@@ -1188,8 +1218,8 @@ async function processBatchInChunks(ctx, tableName, batch, isEmptyTable, isFirst
|
|
|
1188
1218
|
}
|
|
1189
1219
|
await ctx.state.setState((syncState) => ({
|
|
1190
1220
|
...syncState,
|
|
1191
|
-
|
|
1192
|
-
...syncState.
|
|
1221
|
+
newestServerUpdatedAt: {
|
|
1222
|
+
...syncState.newestServerUpdatedAt,
|
|
1193
1223
|
[tableName]: newest.toISOString()
|
|
1194
1224
|
}
|
|
1195
1225
|
}));
|
|
@@ -1363,7 +1393,7 @@ var DyncBase = class {
|
|
|
1363
1393
|
this.adapter = storageAdapter;
|
|
1364
1394
|
this.name = databaseName;
|
|
1365
1395
|
this.syncOptions = {
|
|
1366
|
-
|
|
1396
|
+
syncIntervalMs: DEFAULT_SYNC_INTERVAL_MILLIS,
|
|
1367
1397
|
logger: DEFAULT_LOGGER,
|
|
1368
1398
|
minLogLevel: DEFAULT_MIN_LOG_LEVEL,
|
|
1369
1399
|
missingRemoteRecordDuringUpdateStrategy: DEFAULT_MISSING_REMOTE_RECORD_STRATEGY,
|
|
@@ -1614,7 +1644,8 @@ var DyncBase = class {
|
|
|
1614
1644
|
}
|
|
1615
1645
|
return pullAll({
|
|
1616
1646
|
...baseContext,
|
|
1617
|
-
syncApis: this.syncApis
|
|
1647
|
+
syncApis: this.syncApis,
|
|
1648
|
+
syncIntervalMs: this.syncOptions.syncIntervalMs
|
|
1618
1649
|
});
|
|
1619
1650
|
}
|
|
1620
1651
|
async pushAll() {
|
|
@@ -1649,7 +1680,7 @@ var DyncBase = class {
|
|
|
1649
1680
|
while (this.syncTimerStarted) {
|
|
1650
1681
|
this.sleepAbortController = new AbortController();
|
|
1651
1682
|
await this.syncOnce();
|
|
1652
|
-
await sleep(this.syncOptions.
|
|
1683
|
+
await sleep(this.syncOptions.syncIntervalMs, this.sleepAbortController.signal);
|
|
1653
1684
|
}
|
|
1654
1685
|
this.syncStatus = "disabled";
|
|
1655
1686
|
this.disableSyncPromiseResolver?.();
|