@stamprally/core 0.18.0 → 0.19.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 +3 -4
- package/dist/index.cjs +53 -32
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +53 -32
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -653,6 +653,9 @@ type ClientEvent = {
|
|
|
653
653
|
} | {
|
|
654
654
|
readonly type: "syncLifecycle";
|
|
655
655
|
readonly event: SyncLifecycleEvent;
|
|
656
|
+
} | {
|
|
657
|
+
readonly type: "storageCapabilityWarning";
|
|
658
|
+
readonly warning: OfflineQueueCapabilityWarning;
|
|
656
659
|
} | {
|
|
657
660
|
readonly type: "error";
|
|
658
661
|
readonly error: ClientError | OfflineOperationError;
|
package/dist/index.d.ts
CHANGED
|
@@ -653,6 +653,9 @@ type ClientEvent = {
|
|
|
653
653
|
} | {
|
|
654
654
|
readonly type: "syncLifecycle";
|
|
655
655
|
readonly event: SyncLifecycleEvent;
|
|
656
|
+
} | {
|
|
657
|
+
readonly type: "storageCapabilityWarning";
|
|
658
|
+
readonly warning: OfflineQueueCapabilityWarning;
|
|
656
659
|
} | {
|
|
657
660
|
readonly type: "error";
|
|
658
661
|
readonly error: ClientError | OfflineOperationError;
|
package/dist/index.js
CHANGED
|
@@ -1579,9 +1579,10 @@ var OfflineQueue = class {
|
|
|
1579
1579
|
);
|
|
1580
1580
|
if (spot2 === void 0) return false;
|
|
1581
1581
|
const failedSpots = new Set(
|
|
1582
|
-
|
|
1583
|
-
(entry) => entry.operation
|
|
1584
|
-
|
|
1582
|
+
[
|
|
1583
|
+
...this.#rejectedHistory.map((entry) => entry.operation),
|
|
1584
|
+
...this.#operations.filter((candidate) => candidate.status === "REJECTED_PERMANENT")
|
|
1585
|
+
].filter((candidate) => candidate.kind === "checkIn").map((candidate) => candidate.kind === "checkIn" ? candidate.request.spotId : void 0).filter((spotId) => spotId !== void 0)
|
|
1585
1586
|
);
|
|
1586
1587
|
if (!spot2.prerequisites?.some((prerequisite) => failedSpots.has(prerequisite))) return false;
|
|
1587
1588
|
const error = {
|
|
@@ -1792,18 +1793,18 @@ function applyInventoryDelta(state, previous, optimistic) {
|
|
|
1792
1793
|
if (before !== void 0 && after !== void 0)
|
|
1793
1794
|
rewardRemaining[key] = Math.max(0, (currentRewards[key] ?? before) + after - before);
|
|
1794
1795
|
}
|
|
1795
|
-
|
|
1796
|
-
...
|
|
1797
|
-
|
|
1798
|
-
...currentInventory.sharedRemaining === void 0 || sharedDelta === void 0 ? {} : { sharedRemaining: Math.max(0, currentInventory.sharedRemaining + sharedDelta) },
|
|
1799
|
-
...Object.keys(rewardRemaining).length === 0 ? {} : { rewardRemaining }
|
|
1800
|
-
}
|
|
1796
|
+
const nextInventory = {
|
|
1797
|
+
...currentInventory.sharedRemaining === void 0 || sharedDelta === void 0 ? optimisticInventory.sharedRemaining === void 0 || sharedDelta === void 0 ? {} : { sharedRemaining: Math.max(0, optimisticInventory.sharedRemaining) } : { sharedRemaining: Math.max(0, currentInventory.sharedRemaining + sharedDelta) },
|
|
1798
|
+
...Object.keys(rewardRemaining).length === 0 ? {} : { rewardRemaining }
|
|
1801
1799
|
};
|
|
1800
|
+
return { ...state, inventory: nextInventory };
|
|
1802
1801
|
}
|
|
1803
|
-
function applyOperation(state, operation, config) {
|
|
1802
|
+
function applyOperation(state, operation, config, rejectedCheckIns) {
|
|
1804
1803
|
if (operation.kind === "checkIn") {
|
|
1805
1804
|
const spot2 = config?.spots.find((candidate) => candidate.id === operation.request.spotId);
|
|
1806
|
-
if (spot2?.prerequisites?.some(
|
|
1805
|
+
if (spot2?.prerequisites?.some(
|
|
1806
|
+
(id2) => rejectedCheckIns.has(id2) || !state.records.some((record2) => record2.stampId === id2)
|
|
1807
|
+
))
|
|
1807
1808
|
return { state, prerequisiteFailed: true };
|
|
1808
1809
|
if (state.records.some((record2) => record2.stampId === operation.request.spotId))
|
|
1809
1810
|
return { state, prerequisiteFailed: false };
|
|
@@ -1850,11 +1851,21 @@ function rebuildUserStateFromLog(baselineOrOptions, operationsArgument, configAr
|
|
|
1850
1851
|
function rebuildUserStateLog(baseline, operations, config) {
|
|
1851
1852
|
let state = cloneState(baseline);
|
|
1852
1853
|
const rejectedOperationIds = [];
|
|
1854
|
+
const rejectedCheckIns = new Set(
|
|
1855
|
+
operations.filter(
|
|
1856
|
+
(operation) => operation.status === "REJECTED_PERMANENT" && operation.kind === "checkIn"
|
|
1857
|
+
).map((operation) => operation.kind === "checkIn" ? operation.request.spotId : void 0).filter((spotId) => spotId !== void 0)
|
|
1858
|
+
);
|
|
1853
1859
|
for (const operation of operations) {
|
|
1860
|
+
if (operation.status === "REJECTED_PERMANENT") {
|
|
1861
|
+
if (operation.kind === "checkIn") rejectedCheckIns.add(operation.request.spotId);
|
|
1862
|
+
continue;
|
|
1863
|
+
}
|
|
1854
1864
|
if (!isReplayable(operation)) continue;
|
|
1855
|
-
const replay = applyOperation(state, operation, config);
|
|
1865
|
+
const replay = applyOperation(state, operation, config, rejectedCheckIns);
|
|
1856
1866
|
if (replay.prerequisiteFailed) {
|
|
1857
1867
|
rejectedOperationIds.push(operationId(operation));
|
|
1868
|
+
if (operation.kind === "checkIn") rejectedCheckIns.add(operation.request.spotId);
|
|
1858
1869
|
continue;
|
|
1859
1870
|
}
|
|
1860
1871
|
state = replay.state;
|
|
@@ -1902,6 +1913,30 @@ function emptyState(config, userId, now) {
|
|
|
1902
1913
|
updatedAt: now
|
|
1903
1914
|
};
|
|
1904
1915
|
}
|
|
1916
|
+
function applyOptimisticRewardClaim(state, rewardId, reward2, now) {
|
|
1917
|
+
if (reward2.claimTicketNumber === void 0 || state.inventory === void 0)
|
|
1918
|
+
return {
|
|
1919
|
+
...state,
|
|
1920
|
+
rewards: state.rewards.map((item) => item.rewardId === rewardId ? reward2 : item),
|
|
1921
|
+
updatedAt: now
|
|
1922
|
+
};
|
|
1923
|
+
const currentInventory = state.inventory;
|
|
1924
|
+
const currentRewardRemaining = currentInventory.rewardRemaining?.[rewardId];
|
|
1925
|
+
return {
|
|
1926
|
+
...state,
|
|
1927
|
+
rewards: state.rewards.map((item) => item.rewardId === rewardId ? reward2 : item),
|
|
1928
|
+
updatedAt: now,
|
|
1929
|
+
inventory: {
|
|
1930
|
+
...currentInventory.sharedRemaining === void 0 ? {} : { sharedRemaining: Math.max(0, currentInventory.sharedRemaining - 1) },
|
|
1931
|
+
...currentInventory.rewardRemaining === void 0 || currentRewardRemaining === void 0 ? {} : {
|
|
1932
|
+
rewardRemaining: {
|
|
1933
|
+
...currentInventory.rewardRemaining,
|
|
1934
|
+
[rewardId]: Math.max(0, currentRewardRemaining - 1)
|
|
1935
|
+
}
|
|
1936
|
+
}
|
|
1937
|
+
}
|
|
1938
|
+
};
|
|
1939
|
+
}
|
|
1905
1940
|
function errorMessage(error, fallback) {
|
|
1906
1941
|
return error !== void 0 && "message" in error && typeof error.message === "string" ? error.message : fallback;
|
|
1907
1942
|
}
|
|
@@ -1929,6 +1964,9 @@ var StampRallyClient = class {
|
|
|
1929
1964
|
this.#offlineQueue = this.#options.offlineQueue;
|
|
1930
1965
|
this.#offlineQueue?.setReplayConfig(config);
|
|
1931
1966
|
this.#offlineQueue?.setSyncResultListener((event) => this.#handleOfflineSyncResult(event));
|
|
1967
|
+
this.#offlineQueue?.setCapabilityWarningListener(
|
|
1968
|
+
(warning) => this.#emitEvent({ type: "storageCapabilityWarning", warning })
|
|
1969
|
+
);
|
|
1932
1970
|
this.#offlineQueue?.setChangeListener(() => {
|
|
1933
1971
|
this.#syncRevision += 1;
|
|
1934
1972
|
if (this.#state !== null) this.#emit(this.#state);
|
|
@@ -2159,23 +2197,13 @@ var StampRallyClient = class {
|
|
|
2159
2197
|
return result.ok ? this.#commitClaim(result) : this.#fail(result.error);
|
|
2160
2198
|
} catch (error) {
|
|
2161
2199
|
if (this.#offlineQueue === void 0) throw error;
|
|
2162
|
-
const next2 =
|
|
2163
|
-
...current,
|
|
2164
|
-
rewards: current.rewards.map(
|
|
2165
|
-
(item) => item.rewardId === rewardId ? local.value : item
|
|
2166
|
-
),
|
|
2167
|
-
updatedAt: now
|
|
2168
|
-
};
|
|
2200
|
+
const next2 = applyOptimisticRewardClaim(current, rewardId, local.value, now);
|
|
2169
2201
|
await this.#offlineQueue.enqueueClaimReward(request, next2);
|
|
2170
2202
|
await this.#storage.save(next2);
|
|
2171
2203
|
return this.#commitClaim({ ok: true, value: { state: next2, reward: local.value } });
|
|
2172
2204
|
}
|
|
2173
2205
|
}
|
|
2174
|
-
const next =
|
|
2175
|
-
...current,
|
|
2176
|
-
rewards: current.rewards.map((item) => item.rewardId === rewardId ? local.value : item),
|
|
2177
|
-
updatedAt: now
|
|
2178
|
-
};
|
|
2206
|
+
const next = applyOptimisticRewardClaim(current, rewardId, local.value, now);
|
|
2179
2207
|
await this.#storage.save(next);
|
|
2180
2208
|
return this.#commitClaim({ ok: true, value: { state: next, reward: local.value } });
|
|
2181
2209
|
});
|
|
@@ -3249,7 +3277,7 @@ function validateRallyConfigRelations(config) {
|
|
|
3249
3277
|
["stockKey", reward2.stockKey],
|
|
3250
3278
|
["secondaryStockKey", reward2.secondaryStockKey]
|
|
3251
3279
|
]) {
|
|
3252
|
-
if (key !== void 0 && key !== "__shared__" && inventory?.[key] === void 0)
|
|
3280
|
+
if (key !== void 0 && (key === "__shared__" && inventory?.sharedStock === void 0 || key !== "__shared__" && inventory?.[key] === void 0))
|
|
3253
3281
|
add(
|
|
3254
3282
|
errors,
|
|
3255
3283
|
`rewards[${index}].${field}`,
|
|
@@ -3257,13 +3285,6 @@ function validateRallyConfigRelations(config) {
|
|
|
3257
3285
|
"missing_inventory_key"
|
|
3258
3286
|
);
|
|
3259
3287
|
}
|
|
3260
|
-
if (reward2.stockKey === "__shared__" && inventory?.sharedStock === void 0)
|
|
3261
|
-
add(
|
|
3262
|
-
errors,
|
|
3263
|
-
`rewards[${index}].stockKey`,
|
|
3264
|
-
"sharedStock is not defined.",
|
|
3265
|
-
"missing_inventory_key"
|
|
3266
|
-
);
|
|
3267
3288
|
});
|
|
3268
3289
|
const visiting = /* @__PURE__ */ new Set();
|
|
3269
3290
|
const visited = /* @__PURE__ */ new Set();
|