@absolutejs/sync 1.17.0 → 1.18.1
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/adapters/tanstack-db/index.js +9 -2
- package/dist/adapters/tanstack-db/index.js.map +3 -3
- package/dist/angular/index.js +9 -2
- package/dist/angular/index.js.map +3 -3
- package/dist/client/index.js +29 -4
- package/dist/client/index.js.map +5 -5
- package/dist/engine/cluster.d.ts +17 -3
- package/dist/engine/connection.d.ts +18 -3
- package/dist/engine/index.js +121 -26
- package/dist/engine/index.js.map +5 -5
- package/dist/engine/syncEngine.d.ts +58 -8
- package/dist/index.js +121 -26
- package/dist/index.js.map +4 -4
- package/dist/react/index.js +9 -2
- package/dist/react/index.js.map +3 -3
- package/dist/svelte/index.js +9 -2
- package/dist/svelte/index.js.map +3 -3
- package/dist/testing.js +104 -18
- package/dist/testing.js.map +3 -3
- package/dist/vue/index.js +9 -2
- package/dist/vue/index.js.map +3 -3
- package/package.json +1 -1
package/dist/engine/index.js
CHANGED
|
@@ -1565,11 +1565,11 @@ var createSyncEngine = (options = {}) => {
|
|
|
1565
1565
|
};
|
|
1566
1566
|
const streamSubscribers = new Set;
|
|
1567
1567
|
const runInTransaction = options.transaction;
|
|
1568
|
-
const instanceId = globalThis.crypto?.randomUUID?.() ?? `i${Math.random()}`;
|
|
1568
|
+
const instanceId = options.instanceId ?? globalThis.crypto?.randomUUID?.() ?? `i${Math.random()}`;
|
|
1569
1569
|
let clusterBus;
|
|
1570
|
-
const broadcast = (changes) => {
|
|
1570
|
+
const broadcast = (changes, originVersion) => {
|
|
1571
1571
|
if (clusterBus !== undefined && changes.length > 0) {
|
|
1572
|
-
clusterBus.publish({ changes, origin: instanceId });
|
|
1572
|
+
clusterBus.publish({ changes, origin: instanceId, originVersion });
|
|
1573
1573
|
}
|
|
1574
1574
|
};
|
|
1575
1575
|
const subsFor = (collection) => {
|
|
@@ -1946,11 +1946,44 @@ var createSyncEngine = (options = {}) => {
|
|
|
1946
1946
|
subscriber(entry);
|
|
1947
1947
|
}
|
|
1948
1948
|
};
|
|
1949
|
+
const encodeCursor = (versions) => JSON.stringify(versions);
|
|
1950
|
+
const decodeCursor = (cursor) => {
|
|
1951
|
+
try {
|
|
1952
|
+
const parsed = JSON.parse(cursor);
|
|
1953
|
+
if (typeof parsed !== "object" || parsed === null)
|
|
1954
|
+
return null;
|
|
1955
|
+
const out = {};
|
|
1956
|
+
for (const [k, v] of Object.entries(parsed)) {
|
|
1957
|
+
if (typeof v === "number")
|
|
1958
|
+
out[k] = v;
|
|
1959
|
+
}
|
|
1960
|
+
return out;
|
|
1961
|
+
} catch {
|
|
1962
|
+
return null;
|
|
1963
|
+
}
|
|
1964
|
+
};
|
|
1965
|
+
const currentCursor = () => {
|
|
1966
|
+
const versions = { [instanceId]: version };
|
|
1967
|
+
for (let i = changeLog.length - 1;i >= 0; i--) {
|
|
1968
|
+
const entry = changeLog[i];
|
|
1969
|
+
if (versions[entry.origin] === undefined) {
|
|
1970
|
+
versions[entry.origin] = entry.originVersion;
|
|
1971
|
+
}
|
|
1972
|
+
}
|
|
1973
|
+
return encodeCursor(versions);
|
|
1974
|
+
};
|
|
1949
1975
|
const applyChange = async (table, change, shouldBroadcast = true) => {
|
|
1950
1976
|
version += 1;
|
|
1951
1977
|
const changeVersion = version;
|
|
1952
1978
|
const at = Date.now();
|
|
1953
|
-
logChange(changeVersion, {
|
|
1979
|
+
logChange(changeVersion, {
|
|
1980
|
+
version: changeVersion,
|
|
1981
|
+
table,
|
|
1982
|
+
change,
|
|
1983
|
+
at,
|
|
1984
|
+
origin: instanceId,
|
|
1985
|
+
originVersion: changeVersion
|
|
1986
|
+
});
|
|
1954
1987
|
emitActivity({
|
|
1955
1988
|
type: "change",
|
|
1956
1989
|
at,
|
|
@@ -1969,14 +2002,15 @@ var createSyncEngine = (options = {}) => {
|
|
|
1969
2002
|
{ table, key: changedKeyFor(table, change), row: change.row }
|
|
1970
2003
|
]));
|
|
1971
2004
|
emissions.push(...searchPairs([{ table, change }]));
|
|
2005
|
+
const cursorForBatch = currentCursor();
|
|
1972
2006
|
for (const [subscription, diff] of emissions) {
|
|
1973
|
-
subscription.onDiff(diff, changeVersion);
|
|
2007
|
+
subscription.onDiff(diff, changeVersion, cursorForBatch);
|
|
1974
2008
|
}
|
|
1975
2009
|
if (shouldBroadcast) {
|
|
1976
|
-
broadcast([{ table, change }]);
|
|
2010
|
+
broadcast([{ table, change }], changeVersion);
|
|
1977
2011
|
}
|
|
1978
2012
|
};
|
|
1979
|
-
const applyChangeBatch = async (changes, shouldBroadcast = true) => {
|
|
2013
|
+
const applyChangeBatch = async (changes, shouldBroadcast = true, peerOrigin) => {
|
|
1980
2014
|
if (changes.length === 0) {
|
|
1981
2015
|
return;
|
|
1982
2016
|
}
|
|
@@ -1985,8 +2019,17 @@ var createSyncEngine = (options = {}) => {
|
|
|
1985
2019
|
const perSubscription = new Map;
|
|
1986
2020
|
const reactiveChanges = [];
|
|
1987
2021
|
const batchAt = Date.now();
|
|
2022
|
+
const batchOrigin = peerOrigin?.origin ?? instanceId;
|
|
2023
|
+
const batchOriginVersion = peerOrigin?.originVersion ?? batchVersion;
|
|
1988
2024
|
for (const { table, change } of changes) {
|
|
1989
|
-
logChange(batchVersion, {
|
|
2025
|
+
logChange(batchVersion, {
|
|
2026
|
+
version: batchVersion,
|
|
2027
|
+
table,
|
|
2028
|
+
change,
|
|
2029
|
+
at: batchAt,
|
|
2030
|
+
origin: batchOrigin,
|
|
2031
|
+
originVersion: batchOriginVersion
|
|
2032
|
+
});
|
|
1990
2033
|
emitActivity({
|
|
1991
2034
|
type: "change",
|
|
1992
2035
|
at: batchAt,
|
|
@@ -2018,29 +2061,63 @@ var createSyncEngine = (options = {}) => {
|
|
|
2018
2061
|
}
|
|
2019
2062
|
emissions.push(...await reactivePairs(reactiveChanges));
|
|
2020
2063
|
emissions.push(...searchPairs(changes));
|
|
2064
|
+
const cursorForBatch = currentCursor();
|
|
2021
2065
|
for (const [subscription, diff] of emissions) {
|
|
2022
|
-
subscription.onDiff(diff, batchVersion);
|
|
2066
|
+
subscription.onDiff(diff, batchVersion, cursorForBatch);
|
|
2023
2067
|
}
|
|
2024
2068
|
if (shouldBroadcast) {
|
|
2025
|
-
broadcast(changes);
|
|
2069
|
+
broadcast(changes, batchVersion);
|
|
2026
2070
|
}
|
|
2027
2071
|
};
|
|
2072
|
+
const normalizeSince = (since) => {
|
|
2073
|
+
if (typeof since === "number") {
|
|
2074
|
+
return { [instanceId]: since };
|
|
2075
|
+
}
|
|
2076
|
+
return decodeCursor(since);
|
|
2077
|
+
};
|
|
2028
2078
|
const canResume = (since, incremental) => {
|
|
2029
2079
|
if (!incremental) {
|
|
2030
2080
|
return false;
|
|
2031
2081
|
}
|
|
2032
|
-
|
|
2033
|
-
|
|
2082
|
+
const sinceVec = normalizeSince(since);
|
|
2083
|
+
if (sinceVec === null) {
|
|
2084
|
+
return false;
|
|
2085
|
+
}
|
|
2086
|
+
const oldestPerOrigin = new Map;
|
|
2087
|
+
for (const entry of changeLog) {
|
|
2088
|
+
const current = oldestPerOrigin.get(entry.origin);
|
|
2089
|
+
if (current === undefined || entry.originVersion < current) {
|
|
2090
|
+
oldestPerOrigin.set(entry.origin, entry.originVersion);
|
|
2091
|
+
}
|
|
2092
|
+
}
|
|
2093
|
+
for (const [origin, lastSeen] of Object.entries(sinceVec)) {
|
|
2094
|
+
if (origin === instanceId) {
|
|
2095
|
+
if (lastSeen >= version)
|
|
2096
|
+
continue;
|
|
2097
|
+
const oldestLocal = oldestPerOrigin.get(instanceId);
|
|
2098
|
+
if (oldestLocal === undefined || oldestLocal > lastSeen + 1)
|
|
2099
|
+
return false;
|
|
2100
|
+
} else {
|
|
2101
|
+
const oldestPeer = oldestPerOrigin.get(origin);
|
|
2102
|
+
if (oldestPeer === undefined) {
|
|
2103
|
+
if (lastSeen > 0)
|
|
2104
|
+
return false;
|
|
2105
|
+
} else if (oldestPeer > lastSeen + 1) {
|
|
2106
|
+
return false;
|
|
2107
|
+
}
|
|
2108
|
+
}
|
|
2034
2109
|
}
|
|
2035
|
-
|
|
2036
|
-
return oldest !== undefined && oldest.version <= since + 1;
|
|
2110
|
+
return true;
|
|
2037
2111
|
};
|
|
2038
2112
|
const buildCatchup = (since, tables, key, match) => {
|
|
2113
|
+
const sinceVec = normalizeSince(since) ?? {};
|
|
2039
2114
|
const latest = new Map;
|
|
2040
2115
|
for (const entry of changeLog) {
|
|
2041
|
-
if (
|
|
2116
|
+
if (!tables.includes(entry.table))
|
|
2117
|
+
continue;
|
|
2118
|
+
const lastSeen = sinceVec[entry.origin];
|
|
2119
|
+
if (lastSeen !== undefined && entry.originVersion <= lastSeen)
|
|
2042
2120
|
continue;
|
|
2043
|
-
}
|
|
2044
2121
|
const row = entry.change.row;
|
|
2045
2122
|
const present = entry.change.op !== "delete" && match(row) ? "upsert" : "remove";
|
|
2046
2123
|
latest.set(key(row), { op: present, row });
|
|
@@ -2085,6 +2162,7 @@ var createSyncEngine = (options = {}) => {
|
|
|
2085
2162
|
set.add(subscription);
|
|
2086
2163
|
return {
|
|
2087
2164
|
initial: op.rows(),
|
|
2165
|
+
cursor: currentCursor(),
|
|
2088
2166
|
version: atVersion,
|
|
2089
2167
|
unsubscribe: () => {
|
|
2090
2168
|
set.delete(subscription);
|
|
@@ -2111,6 +2189,7 @@ var createSyncEngine = (options = {}) => {
|
|
|
2111
2189
|
set.add(subscription);
|
|
2112
2190
|
return {
|
|
2113
2191
|
initial,
|
|
2192
|
+
cursor: currentCursor(),
|
|
2114
2193
|
version: atVersion,
|
|
2115
2194
|
unsubscribe: () => {
|
|
2116
2195
|
set.delete(subscription);
|
|
@@ -2172,6 +2251,7 @@ var createSyncEngine = (options = {}) => {
|
|
|
2172
2251
|
reactiveSubs.add(subscription);
|
|
2173
2252
|
return {
|
|
2174
2253
|
initial: first.rows,
|
|
2254
|
+
cursor: currentCursor(),
|
|
2175
2255
|
version: atVersion,
|
|
2176
2256
|
unsubscribe: () => {
|
|
2177
2257
|
set.delete(subscription);
|
|
@@ -2216,6 +2296,7 @@ var createSyncEngine = (options = {}) => {
|
|
|
2216
2296
|
searchSubs.add(subscription);
|
|
2217
2297
|
return {
|
|
2218
2298
|
initial,
|
|
2299
|
+
cursor: currentCursor(),
|
|
2219
2300
|
version: atVersion,
|
|
2220
2301
|
unsubscribe: () => {
|
|
2221
2302
|
set.delete(subscription);
|
|
@@ -2317,12 +2398,14 @@ var createSyncEngine = (options = {}) => {
|
|
|
2317
2398
|
return wrapReturn({
|
|
2318
2399
|
initial: [],
|
|
2319
2400
|
catchup: buildCatchup(since, tables, key, boundMatch),
|
|
2401
|
+
cursor: currentCursor(),
|
|
2320
2402
|
version: atVersion,
|
|
2321
2403
|
unsubscribe
|
|
2322
2404
|
});
|
|
2323
2405
|
}
|
|
2324
2406
|
return wrapReturn({
|
|
2325
2407
|
initial: view.rows(),
|
|
2408
|
+
cursor: currentCursor(),
|
|
2326
2409
|
version: atVersion,
|
|
2327
2410
|
unsubscribe
|
|
2328
2411
|
});
|
|
@@ -2361,7 +2444,10 @@ var createSyncEngine = (options = {}) => {
|
|
|
2361
2444
|
if (message.origin === instanceId) {
|
|
2362
2445
|
return;
|
|
2363
2446
|
}
|
|
2364
|
-
applyChangeBatch(message.changes, false
|
|
2447
|
+
applyChangeBatch(message.changes, false, {
|
|
2448
|
+
origin: message.origin,
|
|
2449
|
+
originVersion: message.originVersion ?? 0
|
|
2450
|
+
});
|
|
2365
2451
|
});
|
|
2366
2452
|
clusterBus = bus;
|
|
2367
2453
|
return async () => {
|
|
@@ -3032,12 +3118,13 @@ var parseFrame = (raw, serializer) => {
|
|
|
3032
3118
|
}
|
|
3033
3119
|
const frame = value;
|
|
3034
3120
|
if (frame.type === "subscribe") {
|
|
3121
|
+
const since = typeof frame.since === "number" || typeof frame.since === "string" ? frame.since : undefined;
|
|
3035
3122
|
return typeof frame.id === "string" && typeof frame.collection === "string" ? {
|
|
3036
3123
|
type: "subscribe",
|
|
3037
3124
|
id: frame.id,
|
|
3038
3125
|
collection: frame.collection,
|
|
3039
3126
|
params: frame.params,
|
|
3040
|
-
since
|
|
3127
|
+
since
|
|
3041
3128
|
} : undefined;
|
|
3042
3129
|
}
|
|
3043
3130
|
if (frame.type === "unsubscribe") {
|
|
@@ -3089,6 +3176,7 @@ var createSyncConnection = ({
|
|
|
3089
3176
|
};
|
|
3090
3177
|
let pending = [];
|
|
3091
3178
|
let pendingVersion;
|
|
3179
|
+
let pendingCursor;
|
|
3092
3180
|
let flushScheduled = false;
|
|
3093
3181
|
const flush = () => {
|
|
3094
3182
|
if (pending.length === 0) {
|
|
@@ -3096,8 +3184,10 @@ var createSyncConnection = ({
|
|
|
3096
3184
|
}
|
|
3097
3185
|
const diffs = pending;
|
|
3098
3186
|
const version = pendingVersion;
|
|
3187
|
+
const cursor = pendingCursor;
|
|
3099
3188
|
pending = [];
|
|
3100
3189
|
pendingVersion = undefined;
|
|
3190
|
+
pendingCursor = undefined;
|
|
3101
3191
|
if (diffs.length === 1) {
|
|
3102
3192
|
const only = diffs[0];
|
|
3103
3193
|
send({
|
|
@@ -3106,10 +3196,11 @@ var createSyncConnection = ({
|
|
|
3106
3196
|
added: only.added,
|
|
3107
3197
|
removed: only.removed,
|
|
3108
3198
|
changed: only.changed,
|
|
3109
|
-
version
|
|
3199
|
+
version,
|
|
3200
|
+
cursor
|
|
3110
3201
|
});
|
|
3111
3202
|
} else {
|
|
3112
|
-
send({ type: "frame", diffs, version });
|
|
3203
|
+
send({ type: "frame", diffs, version, cursor });
|
|
3113
3204
|
}
|
|
3114
3205
|
};
|
|
3115
3206
|
const scheduleFlush = () => {
|
|
@@ -3122,12 +3213,14 @@ var createSyncConnection = ({
|
|
|
3122
3213
|
flush();
|
|
3123
3214
|
});
|
|
3124
3215
|
};
|
|
3125
|
-
const bufferDiff = (diff, diffVersion) => {
|
|
3216
|
+
const bufferDiff = (diff, diffVersion, cursor) => {
|
|
3126
3217
|
if (pending.length > 0 && pendingVersion !== diffVersion) {
|
|
3127
3218
|
flush();
|
|
3128
3219
|
}
|
|
3129
3220
|
pending.push(diff);
|
|
3130
3221
|
pendingVersion = diffVersion;
|
|
3222
|
+
if (cursor !== undefined)
|
|
3223
|
+
pendingCursor = cursor;
|
|
3131
3224
|
scheduleFlush();
|
|
3132
3225
|
};
|
|
3133
3226
|
const handle = async (raw) => {
|
|
@@ -3203,13 +3296,13 @@ var createSyncConnection = ({
|
|
|
3203
3296
|
params: frame.params,
|
|
3204
3297
|
ctx,
|
|
3205
3298
|
since: frame.since,
|
|
3206
|
-
onDiff: (diff, diffVersion) => {
|
|
3299
|
+
onDiff: (diff, diffVersion, cursor) => {
|
|
3207
3300
|
bufferDiff({
|
|
3208
3301
|
id: frame.id,
|
|
3209
3302
|
added: diff.added,
|
|
3210
3303
|
removed: diff.removed,
|
|
3211
3304
|
changed: diff.changed
|
|
3212
|
-
}, diffVersion);
|
|
3305
|
+
}, diffVersion, cursor);
|
|
3213
3306
|
}
|
|
3214
3307
|
});
|
|
3215
3308
|
subscriptions.set(frame.id, subscription);
|
|
@@ -3220,14 +3313,16 @@ var createSyncConnection = ({
|
|
|
3220
3313
|
added: subscription.catchup.added,
|
|
3221
3314
|
removed: subscription.catchup.removed,
|
|
3222
3315
|
changed: subscription.catchup.changed,
|
|
3223
|
-
version: subscription.version
|
|
3316
|
+
version: subscription.version,
|
|
3317
|
+
cursor: subscription.cursor
|
|
3224
3318
|
});
|
|
3225
3319
|
} else {
|
|
3226
3320
|
send({
|
|
3227
3321
|
type: "snapshot",
|
|
3228
3322
|
id: frame.id,
|
|
3229
3323
|
rows: subscription.initial,
|
|
3230
|
-
version: subscription.version
|
|
3324
|
+
version: subscription.version,
|
|
3325
|
+
cursor: subscription.cursor
|
|
3231
3326
|
});
|
|
3232
3327
|
}
|
|
3233
3328
|
} catch (error) {
|
|
@@ -3304,5 +3399,5 @@ export {
|
|
|
3304
3399
|
CdcConsumerSlowError
|
|
3305
3400
|
};
|
|
3306
3401
|
|
|
3307
|
-
//# debugId=
|
|
3402
|
+
//# debugId=2B4AA96446522F9164756E2164756E21
|
|
3308
3403
|
//# sourceMappingURL=index.js.map
|