diff --git a/dist/index.esm.js b/dist/index.esm.js index fc7ea64d..45961c6c 100644 --- a/dist/index.esm.js +++ b/dist/index.esm.js @@ -1,4 +1,4 @@ -import React, { useEffect, createContext, useContext, useRef, useMemo, useState, useCallback } from 'react'; +import React, { createContext, useContext, useRef, useEffect, useMemo, useState, useCallback } from 'react'; /*! ***************************************************************************** Copyright (c) Microsoft Corporation. @@ -195,17 +195,6 @@ var Ortho = /** @class */ (function () { }; return Ortho; }()); -/** - * Orthogonal state listener - */ -function useOrtho(ortho, key, callback) { - useEffect(function () { - if (!key) - return; - ortho.subscribe(key, callback); - return function () { return ortho.unsubscribe(key, callback); }; - }, [ortho, key, callback]); -} function jseq(a, b) { return a === b; @@ -247,22 +236,22 @@ var Scroll = /** @class */ (function () { * @param force Should ignore cooldown * @returns The new state */ - Scroll.prototype.first = function (skey, scroller, fetcher, aborter, tparams, force) { + Scroll.prototype.first = function (skey, scroller, fetcher, aborter, params, force) { var _a; if (aborter === void 0) { aborter = new AbortController(); } - if (tparams === void 0) { tparams = {}; } + if (params === void 0) { params = {}; } if (force === void 0) { force = false; } return __awaiter(this, void 0, void 0, function () { - var _b, dcooldown, _c, dexpiration, _d, dtimeout, current, pages, first, timeout, signal, _e, data, _f, cooldown, _g, expiration, _h, error_1, cooldown, expiration; - return __generator(this, function (_j) { - switch (_j.label) { + var _b, equals, _c, dcooldown, _d, dexpiration, _e, dtimeout, current, pages, first, timeout, signal, _f, data, _g, cooldown, _h, expiration, _j, error_1, cooldown, expiration; + return __generator(this, function (_k) { + switch (_k.label) { case 0: if (skey === undefined) return [2 /*return*/]; - _b = tparams.cooldown, dcooldown = _b === void 0 ? this.core.cooldown : _b, _c = tparams.expiration, dexpiration = _c === void 0 ? this.core.expiration : _c, _d = tparams.timeout, dtimeout = _d === void 0 ? this.core.timeout : _d; - return [4 /*yield*/, this.core.get(skey)]; + _b = params.equals, equals = _b === void 0 ? this.core.equals : _b, _c = params.cooldown, dcooldown = _c === void 0 ? this.core.cooldown : _c, _d = params.expiration, dexpiration = _d === void 0 ? this.core.expiration : _d, _e = params.timeout, dtimeout = _e === void 0 ? this.core.timeout : _e; + return [4 /*yield*/, this.core.get(skey, params)]; case 1: - current = _j.sent(); + current = _k.sent(); if (current === null || current === void 0 ? void 0 : current.aborter) return [2 /*return*/, current]; if (this.core.shouldCooldown(current, force)) @@ -274,32 +263,32 @@ var Scroll = /** @class */ (function () { timeout = setTimeout(function () { aborter.abort("Timed out"); }, dtimeout); - _j.label = 2; + _k.label = 2; case 2: - _j.trys.push([2, 9, 11, 12]); + _k.trys.push([2, 9, 11, 12]); signal = aborter.signal; - return [4 /*yield*/, this.core.apply(skey, current, { aborter: aborter })]; + return [4 /*yield*/, this.core.apply(skey, current, { aborter: aborter }, params)]; case 3: - current = _j.sent(); + current = _k.sent(); return [4 /*yield*/, fetcher(first, { signal: signal })]; case 4: - _e = _j.sent(), data = _e.data, _f = _e.cooldown, cooldown = _f === void 0 ? getTimeFromDelay(dcooldown) : _f, _g = _e.expiration, expiration = _g === void 0 ? getTimeFromDelay(dexpiration) : _g; - if (!this.core.equals(data, pages[0])) return [3 /*break*/, 6]; - return [4 /*yield*/, this.core.apply(skey, current, { cooldown: cooldown, expiration: expiration })]; + _f = _k.sent(), data = _f.data, _g = _f.cooldown, cooldown = _g === void 0 ? getTimeFromDelay(dcooldown) : _g, _h = _f.expiration, expiration = _h === void 0 ? getTimeFromDelay(dexpiration) : _h; + if (!equals(data, pages[0])) return [3 /*break*/, 6]; + return [4 /*yield*/, this.core.apply(skey, current, { cooldown: cooldown, expiration: expiration }, params)]; case 5: - _h = _j.sent(); + _j = _k.sent(); return [3 /*break*/, 8]; - case 6: return [4 /*yield*/, this.core.apply(skey, current, { data: [data], cooldown: cooldown, expiration: expiration })]; + case 6: return [4 /*yield*/, this.core.apply(skey, current, { data: [data], cooldown: cooldown, expiration: expiration }, params)]; case 7: - _h = _j.sent(); - _j.label = 8; - case 8: return [2 /*return*/, _h]; + _j = _k.sent(); + _k.label = 8; + case 8: return [2 /*return*/, _j]; case 9: - error_1 = _j.sent(); + error_1 = _k.sent(); cooldown = getTimeFromDelay(dcooldown); expiration = getTimeFromDelay(dexpiration); - return [4 /*yield*/, this.core.apply(skey, current, { error: error_1, cooldown: cooldown, expiration: expiration })]; - case 10: return [2 /*return*/, _j.sent()]; + return [4 /*yield*/, this.core.apply(skey, current, { error: error_1, cooldown: cooldown, expiration: expiration }, params)]; + case 10: return [2 /*return*/, _k.sent()]; case 11: clearTimeout(timeout); return [7 /*endfinally*/]; @@ -318,10 +307,10 @@ var Scroll = /** @class */ (function () { * @param force Should ignore cooldown * @returns The new state */ - Scroll.prototype.scroll = function (skey, scroller, fetcher, aborter, tparams, force) { + Scroll.prototype.scroll = function (skey, scroller, fetcher, aborter, params, force) { var _a; if (aborter === void 0) { aborter = new AbortController(); } - if (tparams === void 0) { tparams = {}; } + if (params === void 0) { params = {}; } if (force === void 0) { force = false; } return __awaiter(this, void 0, void 0, function () { var _b, dcooldown, _c, dexpiration, _d, dtimeout, current, pages, last, timeout, signal, _e, data, _f, cooldown, _g, expiration, error_2, cooldown, expiration; @@ -330,8 +319,8 @@ var Scroll = /** @class */ (function () { case 0: if (skey === undefined) return [2 /*return*/]; - _b = tparams.cooldown, dcooldown = _b === void 0 ? this.core.cooldown : _b, _c = tparams.expiration, dexpiration = _c === void 0 ? this.core.expiration : _c, _d = tparams.timeout, dtimeout = _d === void 0 ? this.core.timeout : _d; - return [4 /*yield*/, this.core.get(skey)]; + _b = params.cooldown, dcooldown = _b === void 0 ? this.core.cooldown : _b, _c = params.expiration, dexpiration = _c === void 0 ? this.core.expiration : _c, _d = params.timeout, dtimeout = _d === void 0 ? this.core.timeout : _d; + return [4 /*yield*/, this.core.get(skey, params)]; case 1: current = _h.sent(); if (current === null || current === void 0 ? void 0 : current.aborter) @@ -349,20 +338,20 @@ var Scroll = /** @class */ (function () { case 2: _h.trys.push([2, 6, 8, 9]); signal = aborter.signal; - return [4 /*yield*/, this.core.apply(skey, current, { aborter: aborter })]; + return [4 /*yield*/, this.core.apply(skey, current, { aborter: aborter }, params)]; case 3: current = _h.sent(); return [4 /*yield*/, fetcher(last, { signal: signal })]; case 4: _e = _h.sent(), data = _e.data, _f = _e.cooldown, cooldown = _f === void 0 ? getTimeFromDelay(dcooldown) : _f, _g = _e.expiration, expiration = _g === void 0 ? getTimeFromDelay(dexpiration) : _g; expiration = Math.min(expiration, current.expiration); - return [4 /*yield*/, this.core.apply(skey, current, { data: __spreadArray(__spreadArray([], __read(pages), false), [data], false), cooldown: cooldown, expiration: expiration })]; + return [4 /*yield*/, this.core.apply(skey, current, { data: __spreadArray(__spreadArray([], __read(pages), false), [data], false), cooldown: cooldown, expiration: expiration }, params)]; case 5: return [2 /*return*/, _h.sent()]; case 6: error_2 = _h.sent(); cooldown = getTimeFromDelay(dcooldown); expiration = getTimeFromDelay(dexpiration); - return [4 /*yield*/, this.core.apply(skey, current, { error: error_2, cooldown: cooldown, expiration: expiration })]; + return [4 /*yield*/, this.core.apply(skey, current, { error: error_2, cooldown: cooldown, expiration: expiration }, params)]; case 7: return [2 /*return*/, _h.sent()]; case 8: clearTimeout(timeout); @@ -389,9 +378,9 @@ var Single = /** @class */ (function () { * @param force Should ignore cooldown * @returns The new state */ - Single.prototype.fetch = function (key, skey, fetcher, aborter, tparams, force) { + Single.prototype.fetch = function (key, skey, fetcher, aborter, params, force) { if (aborter === void 0) { aborter = new AbortController(); } - if (tparams === void 0) { tparams = {}; } + if (params === void 0) { params = {}; } if (force === void 0) { force = false; } return __awaiter(this, void 0, void 0, function () { var _a, dcooldown, _b, dexpiration, _c, dtimeout, current, timeout, signal, _d, data, _e, cooldown, _f, expiration, error_1, cooldown, expiration; @@ -402,8 +391,8 @@ var Single = /** @class */ (function () { return [2 /*return*/]; if (skey === undefined) return [2 /*return*/]; - _a = tparams.cooldown, dcooldown = _a === void 0 ? this.core.cooldown : _a, _b = tparams.expiration, dexpiration = _b === void 0 ? this.core.expiration : _b, _c = tparams.timeout, dtimeout = _c === void 0 ? this.core.timeout : _c; - return [4 /*yield*/, this.core.get(skey)]; + _a = params.cooldown, dcooldown = _a === void 0 ? this.core.cooldown : _a, _b = params.expiration, dexpiration = _b === void 0 ? this.core.expiration : _b, _c = params.timeout, dtimeout = _c === void 0 ? this.core.timeout : _c; + return [4 /*yield*/, this.core.get(skey, params)]; case 1: current = _g.sent(); if (current === null || current === void 0 ? void 0 : current.aborter) @@ -417,19 +406,19 @@ var Single = /** @class */ (function () { case 2: _g.trys.push([2, 6, 8, 9]); signal = aborter.signal; - return [4 /*yield*/, this.core.apply(skey, current, { aborter: aborter })]; + return [4 /*yield*/, this.core.apply(skey, current, { aborter: aborter }, params)]; case 3: current = _g.sent(); return [4 /*yield*/, fetcher(key, { signal: signal })]; case 4: _d = _g.sent(), data = _d.data, _e = _d.cooldown, cooldown = _e === void 0 ? getTimeFromDelay(dcooldown) : _e, _f = _d.expiration, expiration = _f === void 0 ? getTimeFromDelay(dexpiration) : _f; - return [4 /*yield*/, this.core.apply(skey, current, { data: data, cooldown: cooldown, expiration: expiration })]; + return [4 /*yield*/, this.core.apply(skey, current, { data: data, cooldown: cooldown, expiration: expiration }, params)]; case 5: return [2 /*return*/, _g.sent()]; case 6: error_1 = _g.sent(); cooldown = getTimeFromDelay(dcooldown); expiration = getTimeFromDelay(dexpiration); - return [4 /*yield*/, this.core.apply(skey, current, { error: error_1, cooldown: cooldown, expiration: expiration })]; + return [4 /*yield*/, this.core.apply(skey, current, { error: error_1, cooldown: cooldown, expiration: expiration }, params)]; case 7: return [2 /*return*/, _g.sent()]; case 8: clearTimeout(timeout); @@ -450,9 +439,9 @@ var Single = /** @class */ (function () { * @returns The new state * @throws Error */ - Single.prototype.update = function (key, skey, poster, updater, aborter, tparams) { + Single.prototype.update = function (key, skey, poster, updater, aborter, params) { if (aborter === void 0) { aborter = new AbortController(); } - if (tparams === void 0) { tparams = {}; } + if (params === void 0) { params = {}; } return __awaiter(this, void 0, void 0, function () { var _a, dcooldown, _b, dexpiration, _c, dtimeout, current, updated, timeout, signal, _d, data, _e, cooldown, _f, expiration, error_2; return __generator(this, function (_g) { @@ -462,8 +451,8 @@ var Single = /** @class */ (function () { return [2 /*return*/]; if (skey === undefined) return [2 /*return*/]; - _a = tparams.cooldown, dcooldown = _a === void 0 ? this.core.cooldown : _a, _b = tparams.expiration, dexpiration = _b === void 0 ? this.core.expiration : _b, _c = tparams.timeout, dtimeout = _c === void 0 ? this.core.timeout : _c; - return [4 /*yield*/, this.core.get(skey)]; + _a = params.cooldown, dcooldown = _a === void 0 ? this.core.cooldown : _a, _b = params.expiration, dexpiration = _b === void 0 ? this.core.expiration : _b, _c = params.timeout, dtimeout = _c === void 0 ? this.core.timeout : _c; + return [4 /*yield*/, this.core.get(skey, params)]; case 1: current = _g.sent(); updated = updater(current === null || current === void 0 ? void 0 : current.data); @@ -474,17 +463,17 @@ var Single = /** @class */ (function () { case 2: _g.trys.push([2, 6, 7, 8]); signal = aborter.signal; - return [4 /*yield*/, this.core.mutate(skey, { data: updated, time: current === null || current === void 0 ? void 0 : current.time })]; + return [4 /*yield*/, this.core.mutate(skey, { data: updated, time: current === null || current === void 0 ? void 0 : current.time }, params)]; case 3: _g.sent(); return [4 /*yield*/, poster(key, { data: updated, signal: signal })]; case 4: _d = _g.sent(), data = _d.data, _e = _d.cooldown, cooldown = _e === void 0 ? getTimeFromDelay(dcooldown) : _e, _f = _d.expiration, expiration = _f === void 0 ? getTimeFromDelay(dexpiration) : _f; - return [4 /*yield*/, this.core.mutate(skey, { data: data, cooldown: cooldown, expiration: expiration })]; + return [4 /*yield*/, this.core.mutate(skey, { data: data, cooldown: cooldown, expiration: expiration }, params)]; case 5: return [2 /*return*/, _g.sent()]; case 6: error_2 = _g.sent(); - this.core.mutate(skey, current); + this.core.mutate(skey, current, params); throw error_2; case 7: clearTimeout(timeout); @@ -510,7 +499,7 @@ var Core = /** @class */ (function (_super) { _this.single = new Single(_this); _this.scroll = new Scroll(_this); _this.cache = new Map(); - _this.mounted = true; + _this._mounted = true; _this.counts = new Map(); _this.timeouts = new Map(); Object.assign(_this, params); @@ -521,71 +510,71 @@ var Core = /** @class */ (function (_super) { (_e = _this.timeout) !== null && _e !== void 0 ? _e : (_this.timeout = DEFAULT_TIMEOUT); return _this; } - Object.defineProperty(Core.prototype, "async", { - get: function () { - if (!this.storage) - return false; - return isAsyncStorage(this.storage); - }, - enumerable: false, - configurable: true - }); - Core.prototype.hasSync = function (key) { + Core.prototype.hasSync = function (key, params) { + if (params === void 0) { params = {}; } if (!key) return; if (this.cache.has(key)) return true; - if (!this.storage) + var _a = params.storage, storage = _a === void 0 ? this.storage : _a; + if (!storage) return false; - if (isAsyncStorage(this.storage)) + if (isAsyncStorage(storage)) return false; - return this.storage.has(key); + return storage.has(key); }; - Core.prototype.has = function (key) { + Core.prototype.has = function (key, params) { + if (params === void 0) { params = {}; } return __awaiter(this, void 0, void 0, function () { - return __generator(this, function (_a) { - switch (_a.label) { + var _a, storage; + return __generator(this, function (_b) { + switch (_b.label) { case 0: if (!key) return [2 /*return*/, false]; if (this.cache.has(key)) return [2 /*return*/, true]; - if (!this.storage) + _a = params.storage, storage = _a === void 0 ? this.storage : _a; + if (!storage) return [2 /*return*/, false]; - return [4 /*yield*/, this.storage.has(key)]; - case 1: return [2 /*return*/, _a.sent()]; + return [4 /*yield*/, storage.has(key)]; + case 1: return [2 /*return*/, _b.sent()]; } }); }); }; - Core.prototype.getSync = function (key) { + Core.prototype.getSync = function (key, params) { + if (params === void 0) { params = {}; } if (!key) return; if (this.cache.has(key)) return this.cache.get(key); - if (!this.storage) + var _a = params.storage, storage = _a === void 0 ? this.storage : _a; + if (!storage) return; - if (isAsyncStorage(this.storage)) + if (isAsyncStorage(storage)) return; - var state = this.storage.get(key); + var state = storage.get(key); this.cache.set(key, state); return state; }; - Core.prototype.get = function (key) { + Core.prototype.get = function (key, params) { + if (params === void 0) { params = {}; } return __awaiter(this, void 0, void 0, function () { - var state; - return __generator(this, function (_a) { - switch (_a.label) { + var _a, storage, state; + return __generator(this, function (_b) { + switch (_b.label) { case 0: if (!key) return [2 /*return*/]; if (this.cache.has(key)) return [2 /*return*/, this.cache.get(key)]; - if (!this.storage) + _a = params.storage, storage = _a === void 0 ? this.storage : _a; + if (!storage) return [2 /*return*/]; - return [4 /*yield*/, this.storage.get(key)]; + return [4 /*yield*/, storage.get(key)]; case 1: - state = _a.sent(); + state = _b.sent(); this.cache.set(key, state); return [2 /*return*/, state]; } @@ -599,20 +588,23 @@ var Core = /** @class */ (function (_super) { * @param state New state * @returns */ - Core.prototype.set = function (key, state) { + Core.prototype.set = function (key, state, params) { + if (params === void 0) { params = {}; } return __awaiter(this, void 0, void 0, function () { - return __generator(this, function (_a) { - switch (_a.label) { + var _a, storage; + return __generator(this, function (_b) { + switch (_b.label) { case 0: if (!key) return [2 /*return*/]; this.cache.set(key, state); this.publish(key, state); - if (!this.storage) + _a = params.storage, storage = _a === void 0 ? this.storage : _a; + if (!storage) return [2 /*return*/]; - return [4 /*yield*/, this.storage.set(key, state)]; + return [4 /*yield*/, storage.set(key, state)]; case 1: - _a.sent(); + _b.sent(); return [2 /*return*/]; } }); @@ -623,46 +615,51 @@ var Core = /** @class */ (function (_super) { * @param key * @returns */ - Core.prototype.delete = function (key) { + Core.prototype.delete = function (key, params) { + if (params === void 0) { params = {}; } return __awaiter(this, void 0, void 0, function () { - return __generator(this, function (_a) { - switch (_a.label) { + var _a, storage; + return __generator(this, function (_b) { + switch (_b.label) { case 0: if (!key) return [2 /*return*/]; this.cache.delete(key); this.publish(key, undefined); - if (!this.storage) + _a = params.storage, storage = _a === void 0 ? this.storage : _a; + if (!storage) return [2 /*return*/]; - return [4 /*yield*/, this.storage.delete(key)]; + return [4 /*yield*/, storage.delete(key)]; case 1: - _a.sent(); + _b.sent(); return [2 /*return*/]; } }); }); }; - Core.prototype.apply = function (key, current, state) { + Core.prototype.apply = function (key, current, state, params) { + if (params === void 0) { params = {}; } return __awaiter(this, void 0, void 0, function () { - var next; - return __generator(this, function (_a) { - switch (_a.label) { + var _a, equals, next; + return __generator(this, function (_b) { + switch (_b.label) { case 0: if (!key) return [2 /*return*/]; if (!!state) return [3 /*break*/, 2]; - return [4 /*yield*/, this.delete(key)]; + return [4 /*yield*/, this.delete(key, params)]; case 1: - _a.sent(); + _b.sent(); return [2 /*return*/]; case 2: if (state.time === undefined) state.time = Date.now(); if ((current === null || current === void 0 ? void 0 : current.time) !== undefined && state.time < current.time) return [2 /*return*/, current]; - if (this.equals(state.data, current === null || current === void 0 ? void 0 : current.data)) + _a = params.equals, equals = _a === void 0 ? this.equals : _a; + if (equals(state.data, current === null || current === void 0 ? void 0 : current.data)) state.data = current === null || current === void 0 ? void 0 : current.data; - if (this.equals(state.error, current === null || current === void 0 ? void 0 : current.error)) + if (equals(state.error, current === null || current === void 0 ? void 0 : current.error)) state.error = current === null || current === void 0 ? void 0 : current.error; next = __assign(__assign({}, current), state); if (state.data !== undefined) @@ -673,17 +670,18 @@ var Core = /** @class */ (function (_super) { delete next.expiration; if (state.cooldown === -1) delete next.cooldown; - if (this.equals(current, next)) + if (equals(current, next)) return [2 /*return*/, current]; - return [4 /*yield*/, this.set(key, next)]; + return [4 /*yield*/, this.set(key, next, params)]; case 3: - _a.sent(); + _b.sent(); return [2 /*return*/, next]; } }); }); }; - Core.prototype.mutate = function (key, state) { + Core.prototype.mutate = function (key, state, params) { + if (params === void 0) { params = {}; } return __awaiter(this, void 0, void 0, function () { var current; return __generator(this, function (_a) { @@ -691,10 +689,10 @@ var Core = /** @class */ (function (_super) { case 0: if (!key) return [2 /*return*/]; - return [4 /*yield*/, this.get(key)]; + return [4 /*yield*/, this.get(key, params)]; case 1: current = _a.sent(); - return [4 /*yield*/, this.apply(key, current, state)]; + return [4 /*yield*/, this.apply(key, current, state, params)]; case 2: return [2 /*return*/, _a.sent()]; } }); @@ -712,7 +710,7 @@ var Core = /** @class */ (function (_super) { return true; return false; }; - Core.prototype.subscribe = function (key, listener) { + Core.prototype.subscribe = function (key, listener, params) { var _a; if (!key) return; @@ -725,7 +723,7 @@ var Core = /** @class */ (function (_super) { clearTimeout(timeout); this.timeouts.delete(key); }; - Core.prototype.unsubscribe = function (key, listener) { + Core.prototype.unsubscribe = function (key, listener, params) { return __awaiter(this, void 0, void 0, function () { var count, current, erase, delay, timeout; var _this = this; @@ -753,7 +751,7 @@ var Core = /** @class */ (function (_super) { return __generator(this, function (_a) { switch (_a.label) { case 0: - if (!this.mounted) + if (!this._mounted) return [2 /*return*/]; count = this.counts.get(key); if (count !== undefined) @@ -780,6 +778,13 @@ var Core = /** @class */ (function (_super) { }); }); }; + Object.defineProperty(Core.prototype, "mounted", { + get: function () { + return this._mounted; + }, + enumerable: false, + configurable: true + }); Core.prototype.unmount = function () { var e_1, _a; try { @@ -795,7 +800,7 @@ var Core = /** @class */ (function (_super) { } finally { if (e_1) throw e_1.error; } } - this.mounted = false; + this._mounted = false; }; return Core; }(Ortho)); @@ -830,9 +835,9 @@ function isAbortError(e) { * @param tparams Time parameters (constant) * @returns Scrolling handle */ -function useScroll(scroller, fetcher, tparams) { +function useScroll(scroller, fetcher, params) { var _this = this; - if (tparams === void 0) { tparams = {}; } + if (params === void 0) { params = {}; } var core = useCore(); var key = useMemo(function () { return scroller(); @@ -840,20 +845,26 @@ function useScroll(scroller, fetcher, tparams) { var skey = useMemo(function () { if (key === undefined) return; - return "scroll:" + core.serializer.stringify(key); + var _a = params.serializer, serializer = _a === void 0 ? core.serializer : _a; + return "scroll:".concat(serializer.stringify(key)); }, [core, key]); - var _a = __read(useState(!core.async), 2), ready = _a[0], setReady = _a[1]; - var _b = __read(useState(function () { return core.getSync(skey); }), 2), state = _b[0], setState = _b[1]; + var _a = __read(useState(function () { return core.hasSync(skey, params); }), 2), ready = _a[0], setReady = _a[1]; + var _b = __read(useState(function () { return core.getSync(skey, params); }), 2), state = _b[0], setState = _b[1]; useEffect(function () { - core.get(skey) + core.get(skey, params) .then(setState) .finally(function () { return setReady(true); }); }, [core, skey]); - useOrtho(core, skey, setState); + useEffect(function () { + if (!skey) + return; + core.subscribe(skey, setState, params); + return function () { return void core.unsubscribe(skey, setState, params); }; + }, [core, skey]); var mutate = useCallback(function (res) { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) { switch (_a.label) { - case 0: return [4 /*yield*/, core.mutate(skey, res)]; + case 0: return [4 /*yield*/, core.mutate(skey, res, params)]; case 1: return [2 /*return*/, _a.sent()]; } }); @@ -861,7 +872,7 @@ function useScroll(scroller, fetcher, tparams) { var fetch = useCallback(function (aborter) { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) { switch (_a.label) { - case 0: return [4 /*yield*/, core.scroll.first(skey, scroller, fetcher, aborter, tparams)]; + case 0: return [4 /*yield*/, core.scroll.first(skey, scroller, fetcher, aborter, params)]; case 1: return [2 /*return*/, _a.sent()]; } }); @@ -869,7 +880,7 @@ function useScroll(scroller, fetcher, tparams) { var refetch = useCallback(function (aborter) { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) { switch (_a.label) { - case 0: return [4 /*yield*/, core.scroll.first(skey, scroller, fetcher, aborter, tparams, true)]; + case 0: return [4 /*yield*/, core.scroll.first(skey, scroller, fetcher, aborter, params, true)]; case 1: return [2 /*return*/, _a.sent()]; } }); @@ -877,7 +888,7 @@ function useScroll(scroller, fetcher, tparams) { var scroll = useCallback(function (aborter) { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) { switch (_a.label) { - case 0: return [4 /*yield*/, core.scroll.scroll(skey, scroller, fetcher, aborter, tparams, true)]; + case 0: return [4 /*yield*/, core.scroll.scroll(skey, scroller, fetcher, aborter, params, true)]; case 1: return [2 /*return*/, _a.sent()]; } }); @@ -885,7 +896,7 @@ function useScroll(scroller, fetcher, tparams) { var clear = useCallback(function () { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) { switch (_a.label) { - case 0: return [4 /*yield*/, core.delete(skey)]; + case 0: return [4 /*yield*/, core.delete(skey, params)]; case 1: _a.sent(); return [2 /*return*/]; @@ -903,27 +914,33 @@ function useScroll(scroller, fetcher, tparams) { * @param tparams Time parameters (constant) * @returns Single handle */ -function useSingle(key, poster, tparams) { +function useSingle(key, poster, params) { var _this = this; - if (tparams === void 0) { tparams = {}; } + if (params === void 0) { params = {}; } var core = useCore(); var skey = useMemo(function () { if (key === undefined) return; - return core.serializer.stringify(key); + var _a = params.serializer, serializer = _a === void 0 ? core.serializer : _a; + return serializer.stringify(key); }, [core, key]); - var _a = __read(useState(function () { return core.hasSync(skey); }), 2), ready = _a[0], setReady = _a[1]; - var _b = __read(useState(function () { return core.getSync(skey); }), 2), state = _b[0], setState = _b[1]; + var _a = __read(useState(function () { return core.hasSync(skey, params); }), 2), ready = _a[0], setReady = _a[1]; + var _b = __read(useState(function () { return core.getSync(skey, params); }), 2), state = _b[0], setState = _b[1]; useEffect(function () { - core.get(skey) + core.get(skey, params) .then(setState) .finally(function () { return setReady(true); }); }, [core, skey]); - useOrtho(core, skey, setState); + useEffect(function () { + if (!skey) + return; + core.subscribe(skey, setState, params); + return function () { return void core.unsubscribe(skey, setState, params); }; + }, [core, skey]); var mutate = useCallback(function (res) { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) { switch (_a.label) { - case 0: return [4 /*yield*/, core.mutate(skey, res)]; + case 0: return [4 /*yield*/, core.mutate(skey, res, params)]; case 1: return [2 /*return*/, _a.sent()]; } }); @@ -931,7 +948,7 @@ function useSingle(key, poster, tparams) { var fetch = useCallback(function (aborter) { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) { switch (_a.label) { - case 0: return [4 /*yield*/, core.single.fetch(key, skey, poster, aborter, tparams)]; + case 0: return [4 /*yield*/, core.single.fetch(key, skey, poster, aborter, params)]; case 1: return [2 /*return*/, _a.sent()]; } }); @@ -939,7 +956,7 @@ function useSingle(key, poster, tparams) { var refetch = useCallback(function (aborter) { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) { switch (_a.label) { - case 0: return [4 /*yield*/, core.single.fetch(key, skey, poster, aborter, tparams, true)]; + case 0: return [4 /*yield*/, core.single.fetch(key, skey, poster, aborter, params, true)]; case 1: return [2 /*return*/, _a.sent()]; } }); @@ -947,7 +964,7 @@ function useSingle(key, poster, tparams) { var update = useCallback(function (updater, aborter) { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) { switch (_a.label) { - case 0: return [4 /*yield*/, core.single.update(key, skey, poster, updater, aborter, tparams)]; + case 0: return [4 /*yield*/, core.single.update(key, skey, poster, updater, aborter, params)]; case 1: return [2 /*return*/, _a.sent()]; } }); @@ -955,7 +972,7 @@ function useSingle(key, poster, tparams) { var clear = useCallback(function () { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) { switch (_a.label) { - case 0: return [4 /*yield*/, core.delete(skey)]; + case 0: return [4 /*yield*/, core.delete(skey, params)]; case 1: _a.sent(); return [2 /*return*/]; diff --git a/dist/index.js b/dist/index.js index 28f2b671..85ec63aa 100644 --- a/dist/index.js +++ b/dist/index.js @@ -201,17 +201,6 @@ var Ortho = /** @class */ (function () { }; return Ortho; }()); -/** - * Orthogonal state listener - */ -function useOrtho(ortho, key, callback) { - React.useEffect(function () { - if (!key) - return; - ortho.subscribe(key, callback); - return function () { return ortho.unsubscribe(key, callback); }; - }, [ortho, key, callback]); -} function jseq(a, b) { return a === b; @@ -253,22 +242,22 @@ var Scroll = /** @class */ (function () { * @param force Should ignore cooldown * @returns The new state */ - Scroll.prototype.first = function (skey, scroller, fetcher, aborter, tparams, force) { + Scroll.prototype.first = function (skey, scroller, fetcher, aborter, params, force) { var _a; if (aborter === void 0) { aborter = new AbortController(); } - if (tparams === void 0) { tparams = {}; } + if (params === void 0) { params = {}; } if (force === void 0) { force = false; } return __awaiter(this, void 0, void 0, function () { - var _b, dcooldown, _c, dexpiration, _d, dtimeout, current, pages, first, timeout, signal, _e, data, _f, cooldown, _g, expiration, _h, error_1, cooldown, expiration; - return __generator(this, function (_j) { - switch (_j.label) { + var _b, equals, _c, dcooldown, _d, dexpiration, _e, dtimeout, current, pages, first, timeout, signal, _f, data, _g, cooldown, _h, expiration, _j, error_1, cooldown, expiration; + return __generator(this, function (_k) { + switch (_k.label) { case 0: if (skey === undefined) return [2 /*return*/]; - _b = tparams.cooldown, dcooldown = _b === void 0 ? this.core.cooldown : _b, _c = tparams.expiration, dexpiration = _c === void 0 ? this.core.expiration : _c, _d = tparams.timeout, dtimeout = _d === void 0 ? this.core.timeout : _d; - return [4 /*yield*/, this.core.get(skey)]; + _b = params.equals, equals = _b === void 0 ? this.core.equals : _b, _c = params.cooldown, dcooldown = _c === void 0 ? this.core.cooldown : _c, _d = params.expiration, dexpiration = _d === void 0 ? this.core.expiration : _d, _e = params.timeout, dtimeout = _e === void 0 ? this.core.timeout : _e; + return [4 /*yield*/, this.core.get(skey, params)]; case 1: - current = _j.sent(); + current = _k.sent(); if (current === null || current === void 0 ? void 0 : current.aborter) return [2 /*return*/, current]; if (this.core.shouldCooldown(current, force)) @@ -280,32 +269,32 @@ var Scroll = /** @class */ (function () { timeout = setTimeout(function () { aborter.abort("Timed out"); }, dtimeout); - _j.label = 2; + _k.label = 2; case 2: - _j.trys.push([2, 9, 11, 12]); + _k.trys.push([2, 9, 11, 12]); signal = aborter.signal; - return [4 /*yield*/, this.core.apply(skey, current, { aborter: aborter })]; + return [4 /*yield*/, this.core.apply(skey, current, { aborter: aborter }, params)]; case 3: - current = _j.sent(); + current = _k.sent(); return [4 /*yield*/, fetcher(first, { signal: signal })]; case 4: - _e = _j.sent(), data = _e.data, _f = _e.cooldown, cooldown = _f === void 0 ? getTimeFromDelay(dcooldown) : _f, _g = _e.expiration, expiration = _g === void 0 ? getTimeFromDelay(dexpiration) : _g; - if (!this.core.equals(data, pages[0])) return [3 /*break*/, 6]; - return [4 /*yield*/, this.core.apply(skey, current, { cooldown: cooldown, expiration: expiration })]; + _f = _k.sent(), data = _f.data, _g = _f.cooldown, cooldown = _g === void 0 ? getTimeFromDelay(dcooldown) : _g, _h = _f.expiration, expiration = _h === void 0 ? getTimeFromDelay(dexpiration) : _h; + if (!equals(data, pages[0])) return [3 /*break*/, 6]; + return [4 /*yield*/, this.core.apply(skey, current, { cooldown: cooldown, expiration: expiration }, params)]; case 5: - _h = _j.sent(); + _j = _k.sent(); return [3 /*break*/, 8]; - case 6: return [4 /*yield*/, this.core.apply(skey, current, { data: [data], cooldown: cooldown, expiration: expiration })]; + case 6: return [4 /*yield*/, this.core.apply(skey, current, { data: [data], cooldown: cooldown, expiration: expiration }, params)]; case 7: - _h = _j.sent(); - _j.label = 8; - case 8: return [2 /*return*/, _h]; + _j = _k.sent(); + _k.label = 8; + case 8: return [2 /*return*/, _j]; case 9: - error_1 = _j.sent(); + error_1 = _k.sent(); cooldown = getTimeFromDelay(dcooldown); expiration = getTimeFromDelay(dexpiration); - return [4 /*yield*/, this.core.apply(skey, current, { error: error_1, cooldown: cooldown, expiration: expiration })]; - case 10: return [2 /*return*/, _j.sent()]; + return [4 /*yield*/, this.core.apply(skey, current, { error: error_1, cooldown: cooldown, expiration: expiration }, params)]; + case 10: return [2 /*return*/, _k.sent()]; case 11: clearTimeout(timeout); return [7 /*endfinally*/]; @@ -324,10 +313,10 @@ var Scroll = /** @class */ (function () { * @param force Should ignore cooldown * @returns The new state */ - Scroll.prototype.scroll = function (skey, scroller, fetcher, aborter, tparams, force) { + Scroll.prototype.scroll = function (skey, scroller, fetcher, aborter, params, force) { var _a; if (aborter === void 0) { aborter = new AbortController(); } - if (tparams === void 0) { tparams = {}; } + if (params === void 0) { params = {}; } if (force === void 0) { force = false; } return __awaiter(this, void 0, void 0, function () { var _b, dcooldown, _c, dexpiration, _d, dtimeout, current, pages, last, timeout, signal, _e, data, _f, cooldown, _g, expiration, error_2, cooldown, expiration; @@ -336,8 +325,8 @@ var Scroll = /** @class */ (function () { case 0: if (skey === undefined) return [2 /*return*/]; - _b = tparams.cooldown, dcooldown = _b === void 0 ? this.core.cooldown : _b, _c = tparams.expiration, dexpiration = _c === void 0 ? this.core.expiration : _c, _d = tparams.timeout, dtimeout = _d === void 0 ? this.core.timeout : _d; - return [4 /*yield*/, this.core.get(skey)]; + _b = params.cooldown, dcooldown = _b === void 0 ? this.core.cooldown : _b, _c = params.expiration, dexpiration = _c === void 0 ? this.core.expiration : _c, _d = params.timeout, dtimeout = _d === void 0 ? this.core.timeout : _d; + return [4 /*yield*/, this.core.get(skey, params)]; case 1: current = _h.sent(); if (current === null || current === void 0 ? void 0 : current.aborter) @@ -355,20 +344,20 @@ var Scroll = /** @class */ (function () { case 2: _h.trys.push([2, 6, 8, 9]); signal = aborter.signal; - return [4 /*yield*/, this.core.apply(skey, current, { aborter: aborter })]; + return [4 /*yield*/, this.core.apply(skey, current, { aborter: aborter }, params)]; case 3: current = _h.sent(); return [4 /*yield*/, fetcher(last, { signal: signal })]; case 4: _e = _h.sent(), data = _e.data, _f = _e.cooldown, cooldown = _f === void 0 ? getTimeFromDelay(dcooldown) : _f, _g = _e.expiration, expiration = _g === void 0 ? getTimeFromDelay(dexpiration) : _g; expiration = Math.min(expiration, current.expiration); - return [4 /*yield*/, this.core.apply(skey, current, { data: __spreadArray(__spreadArray([], __read(pages), false), [data], false), cooldown: cooldown, expiration: expiration })]; + return [4 /*yield*/, this.core.apply(skey, current, { data: __spreadArray(__spreadArray([], __read(pages), false), [data], false), cooldown: cooldown, expiration: expiration }, params)]; case 5: return [2 /*return*/, _h.sent()]; case 6: error_2 = _h.sent(); cooldown = getTimeFromDelay(dcooldown); expiration = getTimeFromDelay(dexpiration); - return [4 /*yield*/, this.core.apply(skey, current, { error: error_2, cooldown: cooldown, expiration: expiration })]; + return [4 /*yield*/, this.core.apply(skey, current, { error: error_2, cooldown: cooldown, expiration: expiration }, params)]; case 7: return [2 /*return*/, _h.sent()]; case 8: clearTimeout(timeout); @@ -395,9 +384,9 @@ var Single = /** @class */ (function () { * @param force Should ignore cooldown * @returns The new state */ - Single.prototype.fetch = function (key, skey, fetcher, aborter, tparams, force) { + Single.prototype.fetch = function (key, skey, fetcher, aborter, params, force) { if (aborter === void 0) { aborter = new AbortController(); } - if (tparams === void 0) { tparams = {}; } + if (params === void 0) { params = {}; } if (force === void 0) { force = false; } return __awaiter(this, void 0, void 0, function () { var _a, dcooldown, _b, dexpiration, _c, dtimeout, current, timeout, signal, _d, data, _e, cooldown, _f, expiration, error_1, cooldown, expiration; @@ -408,8 +397,8 @@ var Single = /** @class */ (function () { return [2 /*return*/]; if (skey === undefined) return [2 /*return*/]; - _a = tparams.cooldown, dcooldown = _a === void 0 ? this.core.cooldown : _a, _b = tparams.expiration, dexpiration = _b === void 0 ? this.core.expiration : _b, _c = tparams.timeout, dtimeout = _c === void 0 ? this.core.timeout : _c; - return [4 /*yield*/, this.core.get(skey)]; + _a = params.cooldown, dcooldown = _a === void 0 ? this.core.cooldown : _a, _b = params.expiration, dexpiration = _b === void 0 ? this.core.expiration : _b, _c = params.timeout, dtimeout = _c === void 0 ? this.core.timeout : _c; + return [4 /*yield*/, this.core.get(skey, params)]; case 1: current = _g.sent(); if (current === null || current === void 0 ? void 0 : current.aborter) @@ -423,19 +412,19 @@ var Single = /** @class */ (function () { case 2: _g.trys.push([2, 6, 8, 9]); signal = aborter.signal; - return [4 /*yield*/, this.core.apply(skey, current, { aborter: aborter })]; + return [4 /*yield*/, this.core.apply(skey, current, { aborter: aborter }, params)]; case 3: current = _g.sent(); return [4 /*yield*/, fetcher(key, { signal: signal })]; case 4: _d = _g.sent(), data = _d.data, _e = _d.cooldown, cooldown = _e === void 0 ? getTimeFromDelay(dcooldown) : _e, _f = _d.expiration, expiration = _f === void 0 ? getTimeFromDelay(dexpiration) : _f; - return [4 /*yield*/, this.core.apply(skey, current, { data: data, cooldown: cooldown, expiration: expiration })]; + return [4 /*yield*/, this.core.apply(skey, current, { data: data, cooldown: cooldown, expiration: expiration }, params)]; case 5: return [2 /*return*/, _g.sent()]; case 6: error_1 = _g.sent(); cooldown = getTimeFromDelay(dcooldown); expiration = getTimeFromDelay(dexpiration); - return [4 /*yield*/, this.core.apply(skey, current, { error: error_1, cooldown: cooldown, expiration: expiration })]; + return [4 /*yield*/, this.core.apply(skey, current, { error: error_1, cooldown: cooldown, expiration: expiration }, params)]; case 7: return [2 /*return*/, _g.sent()]; case 8: clearTimeout(timeout); @@ -456,9 +445,9 @@ var Single = /** @class */ (function () { * @returns The new state * @throws Error */ - Single.prototype.update = function (key, skey, poster, updater, aborter, tparams) { + Single.prototype.update = function (key, skey, poster, updater, aborter, params) { if (aborter === void 0) { aborter = new AbortController(); } - if (tparams === void 0) { tparams = {}; } + if (params === void 0) { params = {}; } return __awaiter(this, void 0, void 0, function () { var _a, dcooldown, _b, dexpiration, _c, dtimeout, current, updated, timeout, signal, _d, data, _e, cooldown, _f, expiration, error_2; return __generator(this, function (_g) { @@ -468,8 +457,8 @@ var Single = /** @class */ (function () { return [2 /*return*/]; if (skey === undefined) return [2 /*return*/]; - _a = tparams.cooldown, dcooldown = _a === void 0 ? this.core.cooldown : _a, _b = tparams.expiration, dexpiration = _b === void 0 ? this.core.expiration : _b, _c = tparams.timeout, dtimeout = _c === void 0 ? this.core.timeout : _c; - return [4 /*yield*/, this.core.get(skey)]; + _a = params.cooldown, dcooldown = _a === void 0 ? this.core.cooldown : _a, _b = params.expiration, dexpiration = _b === void 0 ? this.core.expiration : _b, _c = params.timeout, dtimeout = _c === void 0 ? this.core.timeout : _c; + return [4 /*yield*/, this.core.get(skey, params)]; case 1: current = _g.sent(); updated = updater(current === null || current === void 0 ? void 0 : current.data); @@ -480,17 +469,17 @@ var Single = /** @class */ (function () { case 2: _g.trys.push([2, 6, 7, 8]); signal = aborter.signal; - return [4 /*yield*/, this.core.mutate(skey, { data: updated, time: current === null || current === void 0 ? void 0 : current.time })]; + return [4 /*yield*/, this.core.mutate(skey, { data: updated, time: current === null || current === void 0 ? void 0 : current.time }, params)]; case 3: _g.sent(); return [4 /*yield*/, poster(key, { data: updated, signal: signal })]; case 4: _d = _g.sent(), data = _d.data, _e = _d.cooldown, cooldown = _e === void 0 ? getTimeFromDelay(dcooldown) : _e, _f = _d.expiration, expiration = _f === void 0 ? getTimeFromDelay(dexpiration) : _f; - return [4 /*yield*/, this.core.mutate(skey, { data: data, cooldown: cooldown, expiration: expiration })]; + return [4 /*yield*/, this.core.mutate(skey, { data: data, cooldown: cooldown, expiration: expiration }, params)]; case 5: return [2 /*return*/, _g.sent()]; case 6: error_2 = _g.sent(); - this.core.mutate(skey, current); + this.core.mutate(skey, current, params); throw error_2; case 7: clearTimeout(timeout); @@ -516,7 +505,7 @@ var Core = /** @class */ (function (_super) { _this.single = new Single(_this); _this.scroll = new Scroll(_this); _this.cache = new Map(); - _this.mounted = true; + _this._mounted = true; _this.counts = new Map(); _this.timeouts = new Map(); Object.assign(_this, params); @@ -527,71 +516,71 @@ var Core = /** @class */ (function (_super) { (_e = _this.timeout) !== null && _e !== void 0 ? _e : (_this.timeout = DEFAULT_TIMEOUT); return _this; } - Object.defineProperty(Core.prototype, "async", { - get: function () { - if (!this.storage) - return false; - return isAsyncStorage(this.storage); - }, - enumerable: false, - configurable: true - }); - Core.prototype.hasSync = function (key) { + Core.prototype.hasSync = function (key, params) { + if (params === void 0) { params = {}; } if (!key) return; if (this.cache.has(key)) return true; - if (!this.storage) + var _a = params.storage, storage = _a === void 0 ? this.storage : _a; + if (!storage) return false; - if (isAsyncStorage(this.storage)) + if (isAsyncStorage(storage)) return false; - return this.storage.has(key); + return storage.has(key); }; - Core.prototype.has = function (key) { + Core.prototype.has = function (key, params) { + if (params === void 0) { params = {}; } return __awaiter(this, void 0, void 0, function () { - return __generator(this, function (_a) { - switch (_a.label) { + var _a, storage; + return __generator(this, function (_b) { + switch (_b.label) { case 0: if (!key) return [2 /*return*/, false]; if (this.cache.has(key)) return [2 /*return*/, true]; - if (!this.storage) + _a = params.storage, storage = _a === void 0 ? this.storage : _a; + if (!storage) return [2 /*return*/, false]; - return [4 /*yield*/, this.storage.has(key)]; - case 1: return [2 /*return*/, _a.sent()]; + return [4 /*yield*/, storage.has(key)]; + case 1: return [2 /*return*/, _b.sent()]; } }); }); }; - Core.prototype.getSync = function (key) { + Core.prototype.getSync = function (key, params) { + if (params === void 0) { params = {}; } if (!key) return; if (this.cache.has(key)) return this.cache.get(key); - if (!this.storage) + var _a = params.storage, storage = _a === void 0 ? this.storage : _a; + if (!storage) return; - if (isAsyncStorage(this.storage)) + if (isAsyncStorage(storage)) return; - var state = this.storage.get(key); + var state = storage.get(key); this.cache.set(key, state); return state; }; - Core.prototype.get = function (key) { + Core.prototype.get = function (key, params) { + if (params === void 0) { params = {}; } return __awaiter(this, void 0, void 0, function () { - var state; - return __generator(this, function (_a) { - switch (_a.label) { + var _a, storage, state; + return __generator(this, function (_b) { + switch (_b.label) { case 0: if (!key) return [2 /*return*/]; if (this.cache.has(key)) return [2 /*return*/, this.cache.get(key)]; - if (!this.storage) + _a = params.storage, storage = _a === void 0 ? this.storage : _a; + if (!storage) return [2 /*return*/]; - return [4 /*yield*/, this.storage.get(key)]; + return [4 /*yield*/, storage.get(key)]; case 1: - state = _a.sent(); + state = _b.sent(); this.cache.set(key, state); return [2 /*return*/, state]; } @@ -605,20 +594,23 @@ var Core = /** @class */ (function (_super) { * @param state New state * @returns */ - Core.prototype.set = function (key, state) { + Core.prototype.set = function (key, state, params) { + if (params === void 0) { params = {}; } return __awaiter(this, void 0, void 0, function () { - return __generator(this, function (_a) { - switch (_a.label) { + var _a, storage; + return __generator(this, function (_b) { + switch (_b.label) { case 0: if (!key) return [2 /*return*/]; this.cache.set(key, state); this.publish(key, state); - if (!this.storage) + _a = params.storage, storage = _a === void 0 ? this.storage : _a; + if (!storage) return [2 /*return*/]; - return [4 /*yield*/, this.storage.set(key, state)]; + return [4 /*yield*/, storage.set(key, state)]; case 1: - _a.sent(); + _b.sent(); return [2 /*return*/]; } }); @@ -629,46 +621,51 @@ var Core = /** @class */ (function (_super) { * @param key * @returns */ - Core.prototype.delete = function (key) { + Core.prototype.delete = function (key, params) { + if (params === void 0) { params = {}; } return __awaiter(this, void 0, void 0, function () { - return __generator(this, function (_a) { - switch (_a.label) { + var _a, storage; + return __generator(this, function (_b) { + switch (_b.label) { case 0: if (!key) return [2 /*return*/]; this.cache.delete(key); this.publish(key, undefined); - if (!this.storage) + _a = params.storage, storage = _a === void 0 ? this.storage : _a; + if (!storage) return [2 /*return*/]; - return [4 /*yield*/, this.storage.delete(key)]; + return [4 /*yield*/, storage.delete(key)]; case 1: - _a.sent(); + _b.sent(); return [2 /*return*/]; } }); }); }; - Core.prototype.apply = function (key, current, state) { + Core.prototype.apply = function (key, current, state, params) { + if (params === void 0) { params = {}; } return __awaiter(this, void 0, void 0, function () { - var next; - return __generator(this, function (_a) { - switch (_a.label) { + var _a, equals, next; + return __generator(this, function (_b) { + switch (_b.label) { case 0: if (!key) return [2 /*return*/]; if (!!state) return [3 /*break*/, 2]; - return [4 /*yield*/, this.delete(key)]; + return [4 /*yield*/, this.delete(key, params)]; case 1: - _a.sent(); + _b.sent(); return [2 /*return*/]; case 2: if (state.time === undefined) state.time = Date.now(); if ((current === null || current === void 0 ? void 0 : current.time) !== undefined && state.time < current.time) return [2 /*return*/, current]; - if (this.equals(state.data, current === null || current === void 0 ? void 0 : current.data)) + _a = params.equals, equals = _a === void 0 ? this.equals : _a; + if (equals(state.data, current === null || current === void 0 ? void 0 : current.data)) state.data = current === null || current === void 0 ? void 0 : current.data; - if (this.equals(state.error, current === null || current === void 0 ? void 0 : current.error)) + if (equals(state.error, current === null || current === void 0 ? void 0 : current.error)) state.error = current === null || current === void 0 ? void 0 : current.error; next = __assign(__assign({}, current), state); if (state.data !== undefined) @@ -679,17 +676,18 @@ var Core = /** @class */ (function (_super) { delete next.expiration; if (state.cooldown === -1) delete next.cooldown; - if (this.equals(current, next)) + if (equals(current, next)) return [2 /*return*/, current]; - return [4 /*yield*/, this.set(key, next)]; + return [4 /*yield*/, this.set(key, next, params)]; case 3: - _a.sent(); + _b.sent(); return [2 /*return*/, next]; } }); }); }; - Core.prototype.mutate = function (key, state) { + Core.prototype.mutate = function (key, state, params) { + if (params === void 0) { params = {}; } return __awaiter(this, void 0, void 0, function () { var current; return __generator(this, function (_a) { @@ -697,10 +695,10 @@ var Core = /** @class */ (function (_super) { case 0: if (!key) return [2 /*return*/]; - return [4 /*yield*/, this.get(key)]; + return [4 /*yield*/, this.get(key, params)]; case 1: current = _a.sent(); - return [4 /*yield*/, this.apply(key, current, state)]; + return [4 /*yield*/, this.apply(key, current, state, params)]; case 2: return [2 /*return*/, _a.sent()]; } }); @@ -718,7 +716,7 @@ var Core = /** @class */ (function (_super) { return true; return false; }; - Core.prototype.subscribe = function (key, listener) { + Core.prototype.subscribe = function (key, listener, params) { var _a; if (!key) return; @@ -731,7 +729,7 @@ var Core = /** @class */ (function (_super) { clearTimeout(timeout); this.timeouts.delete(key); }; - Core.prototype.unsubscribe = function (key, listener) { + Core.prototype.unsubscribe = function (key, listener, params) { return __awaiter(this, void 0, void 0, function () { var count, current, erase, delay, timeout; var _this = this; @@ -759,7 +757,7 @@ var Core = /** @class */ (function (_super) { return __generator(this, function (_a) { switch (_a.label) { case 0: - if (!this.mounted) + if (!this._mounted) return [2 /*return*/]; count = this.counts.get(key); if (count !== undefined) @@ -786,6 +784,13 @@ var Core = /** @class */ (function (_super) { }); }); }; + Object.defineProperty(Core.prototype, "mounted", { + get: function () { + return this._mounted; + }, + enumerable: false, + configurable: true + }); Core.prototype.unmount = function () { var e_1, _a; try { @@ -801,7 +806,7 @@ var Core = /** @class */ (function (_super) { } finally { if (e_1) throw e_1.error; } } - this.mounted = false; + this._mounted = false; }; return Core; }(Ortho)); @@ -836,9 +841,9 @@ function isAbortError(e) { * @param tparams Time parameters (constant) * @returns Scrolling handle */ -function useScroll(scroller, fetcher, tparams) { +function useScroll(scroller, fetcher, params) { var _this = this; - if (tparams === void 0) { tparams = {}; } + if (params === void 0) { params = {}; } var core = useCore(); var key = React.useMemo(function () { return scroller(); @@ -846,20 +851,26 @@ function useScroll(scroller, fetcher, tparams) { var skey = React.useMemo(function () { if (key === undefined) return; - return "scroll:" + core.serializer.stringify(key); + var _a = params.serializer, serializer = _a === void 0 ? core.serializer : _a; + return "scroll:".concat(serializer.stringify(key)); }, [core, key]); - var _a = __read(React.useState(!core.async), 2), ready = _a[0], setReady = _a[1]; - var _b = __read(React.useState(function () { return core.getSync(skey); }), 2), state = _b[0], setState = _b[1]; + var _a = __read(React.useState(function () { return core.hasSync(skey, params); }), 2), ready = _a[0], setReady = _a[1]; + var _b = __read(React.useState(function () { return core.getSync(skey, params); }), 2), state = _b[0], setState = _b[1]; React.useEffect(function () { - core.get(skey) + core.get(skey, params) .then(setState) .finally(function () { return setReady(true); }); }, [core, skey]); - useOrtho(core, skey, setState); + React.useEffect(function () { + if (!skey) + return; + core.subscribe(skey, setState, params); + return function () { return void core.unsubscribe(skey, setState, params); }; + }, [core, skey]); var mutate = React.useCallback(function (res) { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) { switch (_a.label) { - case 0: return [4 /*yield*/, core.mutate(skey, res)]; + case 0: return [4 /*yield*/, core.mutate(skey, res, params)]; case 1: return [2 /*return*/, _a.sent()]; } }); @@ -867,7 +878,7 @@ function useScroll(scroller, fetcher, tparams) { var fetch = React.useCallback(function (aborter) { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) { switch (_a.label) { - case 0: return [4 /*yield*/, core.scroll.first(skey, scroller, fetcher, aborter, tparams)]; + case 0: return [4 /*yield*/, core.scroll.first(skey, scroller, fetcher, aborter, params)]; case 1: return [2 /*return*/, _a.sent()]; } }); @@ -875,7 +886,7 @@ function useScroll(scroller, fetcher, tparams) { var refetch = React.useCallback(function (aborter) { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) { switch (_a.label) { - case 0: return [4 /*yield*/, core.scroll.first(skey, scroller, fetcher, aborter, tparams, true)]; + case 0: return [4 /*yield*/, core.scroll.first(skey, scroller, fetcher, aborter, params, true)]; case 1: return [2 /*return*/, _a.sent()]; } }); @@ -883,7 +894,7 @@ function useScroll(scroller, fetcher, tparams) { var scroll = React.useCallback(function (aborter) { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) { switch (_a.label) { - case 0: return [4 /*yield*/, core.scroll.scroll(skey, scroller, fetcher, aborter, tparams, true)]; + case 0: return [4 /*yield*/, core.scroll.scroll(skey, scroller, fetcher, aborter, params, true)]; case 1: return [2 /*return*/, _a.sent()]; } }); @@ -891,7 +902,7 @@ function useScroll(scroller, fetcher, tparams) { var clear = React.useCallback(function () { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) { switch (_a.label) { - case 0: return [4 /*yield*/, core.delete(skey)]; + case 0: return [4 /*yield*/, core.delete(skey, params)]; case 1: _a.sent(); return [2 /*return*/]; @@ -909,27 +920,33 @@ function useScroll(scroller, fetcher, tparams) { * @param tparams Time parameters (constant) * @returns Single handle */ -function useSingle(key, poster, tparams) { +function useSingle(key, poster, params) { var _this = this; - if (tparams === void 0) { tparams = {}; } + if (params === void 0) { params = {}; } var core = useCore(); var skey = React.useMemo(function () { if (key === undefined) return; - return core.serializer.stringify(key); + var _a = params.serializer, serializer = _a === void 0 ? core.serializer : _a; + return serializer.stringify(key); }, [core, key]); - var _a = __read(React.useState(function () { return core.hasSync(skey); }), 2), ready = _a[0], setReady = _a[1]; - var _b = __read(React.useState(function () { return core.getSync(skey); }), 2), state = _b[0], setState = _b[1]; + var _a = __read(React.useState(function () { return core.hasSync(skey, params); }), 2), ready = _a[0], setReady = _a[1]; + var _b = __read(React.useState(function () { return core.getSync(skey, params); }), 2), state = _b[0], setState = _b[1]; React.useEffect(function () { - core.get(skey) + core.get(skey, params) .then(setState) .finally(function () { return setReady(true); }); }, [core, skey]); - useOrtho(core, skey, setState); + React.useEffect(function () { + if (!skey) + return; + core.subscribe(skey, setState, params); + return function () { return void core.unsubscribe(skey, setState, params); }; + }, [core, skey]); var mutate = React.useCallback(function (res) { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) { switch (_a.label) { - case 0: return [4 /*yield*/, core.mutate(skey, res)]; + case 0: return [4 /*yield*/, core.mutate(skey, res, params)]; case 1: return [2 /*return*/, _a.sent()]; } }); @@ -937,7 +954,7 @@ function useSingle(key, poster, tparams) { var fetch = React.useCallback(function (aborter) { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) { switch (_a.label) { - case 0: return [4 /*yield*/, core.single.fetch(key, skey, poster, aborter, tparams)]; + case 0: return [4 /*yield*/, core.single.fetch(key, skey, poster, aborter, params)]; case 1: return [2 /*return*/, _a.sent()]; } }); @@ -945,7 +962,7 @@ function useSingle(key, poster, tparams) { var refetch = React.useCallback(function (aborter) { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) { switch (_a.label) { - case 0: return [4 /*yield*/, core.single.fetch(key, skey, poster, aborter, tparams, true)]; + case 0: return [4 /*yield*/, core.single.fetch(key, skey, poster, aborter, params, true)]; case 1: return [2 /*return*/, _a.sent()]; } }); @@ -953,7 +970,7 @@ function useSingle(key, poster, tparams) { var update = React.useCallback(function (updater, aborter) { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) { switch (_a.label) { - case 0: return [4 /*yield*/, core.single.update(key, skey, poster, updater, aborter, tparams)]; + case 0: return [4 /*yield*/, core.single.update(key, skey, poster, updater, aborter, params)]; case 1: return [2 /*return*/, _a.sent()]; } }); @@ -961,7 +978,7 @@ function useSingle(key, poster, tparams) { var clear = React.useCallback(function () { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) { switch (_a.label) { - case 0: return [4 /*yield*/, core.delete(skey)]; + case 0: return [4 /*yield*/, core.delete(skey, params)]; case 1: _a.sent(); return [2 /*return*/]; diff --git a/dist/libs/ortho.d.ts b/dist/libs/ortho.d.ts index 7d2ce656..431ada9d 100644 --- a/dist/libs/ortho.d.ts +++ b/dist/libs/ortho.d.ts @@ -16,7 +16,3 @@ export declare class Ortho { subscribe(key: K, listener: (x: S) => void): void; unsubscribe(key: K, listener: (x: S) => void): void; } -/** - * Orthogonal state listener - */ -export declare function useOrtho(ortho: Ortho, key: K | undefined, callback: (s: S) => void): void; diff --git a/dist/mods/core.d.ts b/dist/mods/core.d.ts index 16cd05fc..d0585f1f 100644 --- a/dist/mods/core.d.ts +++ b/dist/mods/core.d.ts @@ -21,6 +21,11 @@ export declare type PosterMore = { }; export declare type Scroller = (previous?: D) => K | undefined; export declare type Updater = (previous?: D) => D; +export interface Params extends TimeParams { + storage?: Storage>; + serializer?: Serializer; + equals?: Equals; +} export interface CoreParams extends TimeParams { storage?: Storage; serializer?: Serializer; @@ -36,13 +41,12 @@ export declare class Core extends Ortho { readonly cooldown: number; readonly expiration: number; readonly timeout: number; - protected mounted: boolean; + _mounted: boolean; constructor(params?: CoreParams); - get async(): boolean; - hasSync(key: string | undefined): boolean; - has(key: string | undefined): Promise; - getSync(key: string | undefined): State | undefined; - get(key: string | undefined): Promise | undefined>; + hasSync(key: string | undefined, params?: Params): boolean; + has(key: string | undefined, params?: Params): Promise; + getSync(key: string | undefined, params?: Params): State | undefined; + get(key: string | undefined, params?: Params): Promise | undefined>; /** * Force set a key to a state and publish it * No check, no merge @@ -50,22 +54,23 @@ export declare class Core extends Ortho { * @param state New state * @returns */ - set(key: string | undefined, state: State): Promise; + set(key: string | undefined, state: State, params?: Params): Promise; /** * Delete key and publish undefined * @param key * @returns */ - delete(key: string | undefined): Promise; - apply(key: string | undefined, current?: State, state?: State): Promise | undefined>; - mutate(key: string | undefined, state?: State): Promise | undefined>; + delete(key: string | undefined, params?: Params): Promise; + apply(key: string | undefined, current?: State, state?: State, params?: Params): Promise | undefined>; + mutate(key: string | undefined, state?: State, params?: Params): Promise | undefined>; /** * True if we should cooldown this resource */ shouldCooldown(current?: State, force?: boolean): boolean; counts: Map; timeouts: Map; - subscribe(key: string | undefined, listener: (x: State) => void): void; - unsubscribe(key: string | undefined, listener: (x: State) => void): Promise; + subscribe(key: string | undefined, listener: (x: State) => void, params?: Params): void; + unsubscribe(key: string | undefined, listener: (x: State) => void, params?: Params): Promise; + get mounted(): boolean; unmount(): void; } diff --git a/dist/mods/handles/scroll.d.ts b/dist/mods/handles/scroll.d.ts index 6adaee00..426b9d87 100644 --- a/dist/mods/handles/scroll.d.ts +++ b/dist/mods/handles/scroll.d.ts @@ -1,6 +1,5 @@ -import { Fetcher, Scroller } from "../core.js"; +import { Fetcher, Params, Scroller } from "../core.js"; import { State } from "../storages/storage.js"; -import { TimeParams } from "../time.js"; import { Handle } from "./handle.js"; /** * Handle for a scrolling resource @@ -18,4 +17,4 @@ export interface ScrollHandle extends Handle(scroller: Scroller, fetcher: Fetcher, tparams?: TimeParams): ScrollHandle; +export declare function useScroll(scroller: Scroller, fetcher: Fetcher, params?: Params): ScrollHandle; diff --git a/dist/mods/handles/single.d.ts b/dist/mods/handles/single.d.ts index e74bc688..e01529e5 100644 --- a/dist/mods/handles/single.d.ts +++ b/dist/mods/handles/single.d.ts @@ -1,6 +1,5 @@ -import { Poster, Updater } from "../core.js"; +import { Params, Poster, Updater } from "../core.js"; import { State } from "../storages/storage.js"; -import { TimeParams } from "../time.js"; import { Handle } from "./handle.js"; /** * Handle for a single resource @@ -20,4 +19,4 @@ export interface SingleHandle extends Handle * @param tparams Time parameters (constant) * @returns Single handle */ -export declare function useSingle(key: K | undefined, poster: Poster, tparams?: TimeParams): SingleHandle; +export declare function useSingle(key: K | undefined, poster: Poster, params?: Params): SingleHandle; diff --git a/dist/mods/scroll.d.ts b/dist/mods/scroll.d.ts index b84eb65e..8972f45d 100644 --- a/dist/mods/scroll.d.ts +++ b/dist/mods/scroll.d.ts @@ -1,5 +1,5 @@ import { Core, Fetcher, Scroller } from "./core.js"; -import { TimeParams } from "./time.js"; +import { Params } from "./index.js"; export declare class Scroll { readonly core: Core; constructor(core: Core); @@ -13,7 +13,7 @@ export declare class Scroll { * @param force Should ignore cooldown * @returns The new state */ - first(skey: string | undefined, scroller: Scroller, fetcher: Fetcher, aborter?: AbortController, tparams?: TimeParams, force?: boolean): Promise>; + first(skey: string | undefined, scroller: Scroller, fetcher: Fetcher, aborter?: AbortController, params?: Params, force?: boolean): Promise>; /** * Scroll to the next page * @param skey Storage key @@ -24,5 +24,5 @@ export declare class Scroll { * @param force Should ignore cooldown * @returns The new state */ - scroll(skey: string | undefined, scroller: Scroller, fetcher: Fetcher, aborter?: AbortController, tparams?: TimeParams, force?: boolean): Promise>; + scroll(skey: string | undefined, scroller: Scroller, fetcher: Fetcher, aborter?: AbortController, params?: Params, force?: boolean): Promise>; } diff --git a/dist/mods/single.d.ts b/dist/mods/single.d.ts index 63804126..ff7cbc42 100644 --- a/dist/mods/single.d.ts +++ b/dist/mods/single.d.ts @@ -1,6 +1,6 @@ import { Core, Fetcher, Poster, Updater } from "./core.js"; +import { Params } from "./index.js"; import { State } from "./storages/storage.js"; -import { TimeParams } from "./time.js"; export declare class Single { readonly core: Core; constructor(core: Core); @@ -14,7 +14,7 @@ export declare class Single { * @param force Should ignore cooldown * @returns The new state */ - fetch(key: K | undefined, skey: string | undefined, fetcher: Fetcher, aborter?: AbortController, tparams?: TimeParams, force?: boolean): Promise | undefined>; + fetch(key: K | undefined, skey: string | undefined, fetcher: Fetcher, aborter?: AbortController, params?: Params, force?: boolean): Promise | undefined>; /** * Optimistic update * @param key Key (:K) (passed to poster) @@ -26,5 +26,5 @@ export declare class Single { * @returns The new state * @throws Error */ - update(key: K | undefined, skey: string | undefined, poster: Poster, updater: Updater, aborter?: AbortController, tparams?: TimeParams): Promise>; + update(key: K | undefined, skey: string | undefined, poster: Poster, updater: Updater, aborter?: AbortController, params?: Params): Promise>; } diff --git a/src/libs/ortho.ts b/src/libs/ortho.ts index cf5f5cf8..560e4484 100644 --- a/src/libs/ortho.ts +++ b/src/libs/ortho.ts @@ -1,4 +1,3 @@ -import { useEffect } from "react" /** * Map of arrays data structure @@ -50,18 +49,3 @@ export class Ortho { this.listeners.erase(key, listener) } } - -/** - * Orthogonal state listener - */ -export function useOrtho( - ortho: Ortho, - key: K | undefined, - callback: (s: S) => void -) { - useEffect(() => { - if (!key) return - ortho.subscribe(key, callback) - return () => ortho.unsubscribe(key, callback) - }, [ortho, key, callback]) -} \ No newline at end of file diff --git a/src/mods/core.ts b/src/mods/core.ts index 019d02a0..b21bd778 100644 --- a/src/mods/core.ts +++ b/src/mods/core.ts @@ -30,6 +30,12 @@ export type Scroller = export type Updater = (previous?: D) => D +export interface Params extends TimeParams { + storage?: Storage> + serializer?: Serializer, + equals?: Equals +} + export interface CoreParams extends TimeParams { storage?: Storage, serializer?: Serializer, @@ -50,7 +56,7 @@ export class Core extends Ortho { readonly expiration: number readonly timeout: number - protected mounted = true + _mounted = true constructor(params?: CoreParams) { super() @@ -64,63 +70,72 @@ export class Core extends Ortho { this.timeout ??= DEFAULT_TIMEOUT } - get async() { - if (!this.storage) return false - return isAsyncStorage(this.storage) - } - - hasSync( - key: string | undefined + hasSync( + key: string | undefined, + params: Params = {} ): boolean { if (!key) return if (this.cache.has(key)) return true - if (!this.storage) - return false - if (isAsyncStorage(this.storage)) - return false - return this.storage.has(key) + + const { + storage = this.storage + } = params + if (!storage) return false + if (isAsyncStorage(storage)) return false + return storage.has(key) } - async has( - key: string | undefined + async has( + key: string | undefined, + params: Params = {} ) { if (!key) return false if (this.cache.has(key)) return true - if (!this.storage) - return false - return await this.storage.has(key) + + const { + storage = this.storage + } = params + if (!storage) return false + return await storage.has(key) } getSync( - key: string | undefined + key: string | undefined, + params: Params = {} ): State | undefined { if (!key) return if (this.cache.has(key)) return this.cache.get(key) - if (!this.storage) - return - if (isAsyncStorage(this.storage)) - return - const state = this.storage.get(key) + + const { + storage = this.storage + } = params + if (!storage) return + if (isAsyncStorage(storage)) return + const state = storage.get(key) this.cache.set(key, state) return state } async get( - key: string | undefined + key: string | undefined, + params: Params = {} ): Promise | undefined> { if (!key) return if (this.cache.has(key)) return this.cache.get(key) - if (!this.storage) - return - const state = await this.storage.get(key) + + const { + storage = this.storage + } = params + if (!storage) return + const state = await storage.get(key) this.cache.set(key, state) return state } @@ -134,16 +149,19 @@ export class Core extends Ortho { */ async set( key: string | undefined, - state: State + state: State, + params: Params = {} ) { if (!key) return this.cache.set(key, state) this.publish(key, state) - if (!this.storage) - return - await this.storage.set(key, state) + const { + storage = this.storage + } = params + if (!storage) return + await storage.set(key, state) } /** @@ -151,28 +169,32 @@ export class Core extends Ortho { * @param key * @returns */ - async delete( - key: string | undefined + async delete( + key: string | undefined, + params: Params = {} ) { if (!key) return this.cache.delete(key) this.publish(key, undefined) - if (!this.storage) - return - await this.storage.delete(key) + const { + storage = this.storage + } = params + if (!storage) return + await storage.delete(key) } async apply( key: string | undefined, current?: State, - state?: State + state?: State, + params: Params = {} ): Promise | undefined> { if (!key) return if (!state) { - await this.delete(key) + await this.delete(key, params) return } @@ -181,9 +203,11 @@ export class Core extends Ortho { if (current?.time !== undefined && state.time < current.time) return current - if (this.equals(state.data, current?.data)) + const { equals = this.equals } = params + + if (equals(state.data, current?.data)) state.data = current?.data - if (this.equals(state.error, current?.error)) + if (equals(state.error, current?.error)) state.error = current?.error const next = { ...current, ...state } @@ -197,20 +221,21 @@ export class Core extends Ortho { if (state.cooldown === -1) delete next.cooldown - if (this.equals(current, next)) + if (equals(current, next)) return current - await this.set(key, next) + await this.set(key, next, params) return next } async mutate( key: string | undefined, - state?: State + state?: State, + params: Params = {} ): Promise | undefined> { if (!key) return - const current = await this.get(key) - return await this.apply(key, current, state) + const current = await this.get(key, params) + return await this.apply(key, current, state, params) } /** @@ -229,9 +254,10 @@ export class Core extends Ortho { counts = new Map() timeouts = new Map() - subscribe( + subscribe( key: string | undefined, - listener: (x: State) => void + listener: (x: State) => void, + params: Params = {} ) { if (!key) return @@ -247,9 +273,10 @@ export class Core extends Ortho { this.timeouts.delete(key) } - async unsubscribe( + async unsubscribe( key: string | undefined, - listener: (x: State) => void + listener: (x: State) => void, + params: Params = {} ) { if (!key) return @@ -269,7 +296,7 @@ export class Core extends Ortho { if (current?.expiration === -1) return const erase = async () => { - if (!this.mounted) return + if (!this._mounted) return const count = this.counts.get(key) if (count !== undefined) return @@ -288,9 +315,13 @@ export class Core extends Ortho { this.timeouts.set(key, timeout) } + get mounted() { + return this._mounted + } + unmount() { for (const timeout of this.timeouts.values()) clearTimeout(timeout) - this.mounted = false + this._mounted = false } } \ No newline at end of file diff --git a/src/mods/handles/scroll.ts b/src/mods/handles/scroll.ts index b7127a4d..a1b22e28 100644 --- a/src/mods/handles/scroll.ts +++ b/src/mods/handles/scroll.ts @@ -1,9 +1,7 @@ import { useCallback, useEffect, useMemo, useState } from "react" import { useCore } from "../../comps/index.js" -import { useOrtho } from "../../libs/ortho.js" -import { Fetcher, Scroller } from "../core.js" +import { Fetcher, Params, Scroller } from "../core.js" import { State } from "../storages/storage.js" -import { TimeParams } from "../time.js" import { Handle } from "./handle.js" /** @@ -26,7 +24,7 @@ export interface ScrollHandle extends Handle( scroller: Scroller, fetcher: Fetcher, - tparams: TimeParams = {}, + params: Params = {}, ): ScrollHandle { const core = useCore() @@ -36,38 +34,45 @@ export function useScroll( const skey = useMemo(() => { if (key === undefined) return - return "scroll:" + core.serializer.stringify(key) + + const { serializer = core.serializer } = params + return `scroll:${serializer.stringify(key)}` }, [core, key]) - const [ready, setReady] = useState(!core.async) - const [state, setState] = useState(() => core.getSync(skey)) + const [ready, setReady] = useState(() => core.hasSync(skey, params)) + const [state, setState] = useState(() => core.getSync(skey, params)) useEffect(() => { - core.get(skey) + core.get(skey, params) .then(setState) .finally(() => setReady(true)) }, [core, skey]) - useOrtho(core, skey, setState) + useEffect(() => { + if (!skey) return + + core.subscribe(skey, setState, params) + return () => void core.unsubscribe(skey, setState, params) + }, [core, skey]) const mutate = useCallback(async (res: State) => { - return await core.mutate(skey, res) + return await core.mutate(skey, res, params) }, [core, skey]) const fetch = useCallback(async (aborter?: AbortController) => { - return await core.scroll.first(skey, scroller, fetcher, aborter, tparams) + return await core.scroll.first(skey, scroller, fetcher, aborter, params) }, [core, skey, scroller, fetcher]) const refetch = useCallback(async (aborter?: AbortController) => { - return await core.scroll.first(skey, scroller, fetcher, aborter, tparams, true) + return await core.scroll.first(skey, scroller, fetcher, aborter, params, true) }, [core, skey, scroller, fetcher]) const scroll = useCallback(async (aborter?: AbortController) => { - return await core.scroll.scroll(skey, scroller, fetcher, aborter, tparams, true) + return await core.scroll.scroll(skey, scroller, fetcher, aborter, params, true) }, [core, skey, scroller, fetcher]) const clear = useCallback(async () => { - await core.delete(skey) + await core.delete(skey, params) }, [core, skey]) const loading = Boolean(state?.aborter) diff --git a/src/mods/handles/single.ts b/src/mods/handles/single.ts index 7490ce3e..f168c2a0 100644 --- a/src/mods/handles/single.ts +++ b/src/mods/handles/single.ts @@ -1,9 +1,7 @@ import { useCallback, useEffect, useMemo, useState } from "react" import { useCore } from "../../comps/core.js" -import { useOrtho } from "../../libs/ortho.js" -import { Poster, Updater } from "../core.js" +import { Params, Poster, Updater } from "../core.js" import { State } from "../storages/storage.js" -import { TimeParams } from "../time.js" import { Handle } from "./handle.js" /** @@ -28,44 +26,51 @@ export interface SingleHandle extends Handle export function useSingle( key: K | undefined, poster: Poster, - tparams: TimeParams = {} + params: Params = {}, ): SingleHandle { const core = useCore() const skey = useMemo(() => { if (key === undefined) return - return core.serializer.stringify(key) + + const { serializer = core.serializer } = params + return serializer.stringify(key) }, [core, key]) - const [ready, setReady] = useState(() => core.hasSync(skey)) - const [state, setState] = useState(() => core.getSync(skey)) + const [ready, setReady] = useState(() => core.hasSync(skey, params)) + const [state, setState] = useState(() => core.getSync(skey, params)) useEffect(() => { - core.get(skey) + core.get(skey, params) .then(setState) .finally(() => setReady(true)) }, [core, skey]) - useOrtho(core, skey, setState) + useEffect(() => { + if (!skey) return + + core.subscribe(skey, setState, params) + return () => void core.unsubscribe(skey, setState, params) + }, [core, skey]) const mutate = useCallback(async (res: State) => { - return await core.mutate(skey, res) + return await core.mutate(skey, res, params) }, [core, skey]) const fetch = useCallback(async (aborter?: AbortController) => { - return await core.single.fetch(key, skey, poster, aborter, tparams) + return await core.single.fetch(key, skey, poster, aborter, params) }, [core, skey, poster]) const refetch = useCallback(async (aborter?: AbortController) => { - return await core.single.fetch(key, skey, poster, aborter, tparams, true) + return await core.single.fetch(key, skey, poster, aborter, params, true) }, [core, skey, poster]) const update = useCallback(async (updater: Updater, aborter?: AbortController) => { - return await core.single.update(key, skey, poster, updater, aborter, tparams) + return await core.single.update(key, skey, poster, updater, aborter, params) }, [core, skey, poster]) const clear = useCallback(async () => { - await core.delete(skey) + await core.delete(skey, params) }, [core, skey]) const loading = Boolean(state?.aborter) diff --git a/src/mods/scroll.ts b/src/mods/scroll.ts index d53969fc..b053a6e4 100644 --- a/src/mods/scroll.ts +++ b/src/mods/scroll.ts @@ -1,6 +1,7 @@ import { lastOf } from "../libs/arrays.js"; import { Core, Fetcher, Scroller } from "./core.js"; -import { getTimeFromDelay, TimeParams } from "./time.js"; +import { Params } from "./index.js"; +import { getTimeFromDelay } from "./time.js"; export class Scroll { constructor(readonly core: Core) { } @@ -20,18 +21,19 @@ export class Scroll { scroller: Scroller, fetcher: Fetcher, aborter = new AbortController(), - tparams: TimeParams = {}, + params: Params = {}, force = false ) { if (skey === undefined) return const { + equals = this.core.equals, cooldown: dcooldown = this.core.cooldown, expiration: dexpiration = this.core.expiration, timeout: dtimeout = this.core.timeout, - } = tparams + } = params - let current = await this.core.get(skey) + let current = await this.core.get(skey, params) if (current?.aborter) return current if (this.core.shouldCooldown(current, force)) @@ -48,7 +50,7 @@ export class Scroll { try { const { signal } = aborter - current = await this.core.apply(skey, current, { aborter }) + current = await this.core.apply(skey, current, { aborter }, params) const { data, @@ -56,14 +58,14 @@ export class Scroll { expiration = getTimeFromDelay(dexpiration) } = await fetcher(first, { signal }) - return this.core.equals(data, pages[0]) - ? await this.core.apply(skey, current, { cooldown, expiration }) - : await this.core.apply(skey, current, { data: [data], cooldown, expiration }) + return equals(data, pages[0]) + ? await this.core.apply(skey, current, { cooldown, expiration }, params) + : await this.core.apply(skey, current, { data: [data], cooldown, expiration }, params) } catch (error: any) { const cooldown = getTimeFromDelay(dcooldown) const expiration = getTimeFromDelay(dexpiration) - return await this.core.apply(skey, current, { error, cooldown, expiration }) + return await this.core.apply(skey, current, { error, cooldown, expiration }, params) } finally { clearTimeout(timeout) } @@ -84,7 +86,7 @@ export class Scroll { scroller: Scroller, fetcher: Fetcher, aborter = new AbortController(), - tparams: TimeParams = {}, + params: Params = {}, force = false ) { if (skey === undefined) return @@ -93,9 +95,9 @@ export class Scroll { cooldown: dcooldown = this.core.cooldown, expiration: dexpiration = this.core.expiration, timeout: dtimeout = this.core.timeout, - } = tparams + } = params - let current = await this.core.get(skey) + let current = await this.core.get(skey, params) if (current?.aborter) return current if (this.core.shouldCooldown(current, force)) @@ -112,7 +114,7 @@ export class Scroll { try { const { signal } = aborter - current = await this.core.apply(skey, current, { aborter }) + current = await this.core.apply(skey, current, { aborter }, params) let { data, @@ -122,12 +124,12 @@ export class Scroll { expiration = Math.min(expiration, current.expiration) - return await this.core.apply(skey, current, { data: [...pages, data], cooldown, expiration }) + return await this.core.apply(skey, current, { data: [...pages, data], cooldown, expiration }, params) } catch (error: any) { const cooldown = getTimeFromDelay(dcooldown) const expiration = getTimeFromDelay(dexpiration) - return await this.core.apply(skey, current, { error, cooldown, expiration }) + return await this.core.apply(skey, current, { error, cooldown, expiration }, params) } finally { clearTimeout(timeout) } diff --git a/src/mods/single.ts b/src/mods/single.ts index 5d388d13..4e53b78c 100644 --- a/src/mods/single.ts +++ b/src/mods/single.ts @@ -1,6 +1,7 @@ import { Core, Fetcher, Poster, Updater } from "./core.js"; +import { Params } from "./index.js"; import { State } from "./storages/storage.js"; -import { getTimeFromDelay, TimeParams } from "./time.js"; +import { getTimeFromDelay } from "./time.js"; export class Single { constructor(readonly core: Core) { } @@ -20,7 +21,7 @@ export class Single { skey: string | undefined, fetcher: Fetcher, aborter = new AbortController(), - tparams: TimeParams = {}, + params: Params = {}, force = false ): Promise | undefined> { if (key === undefined) return @@ -30,9 +31,9 @@ export class Single { cooldown: dcooldown = this.core.cooldown, expiration: dexpiration = this.core.expiration, timeout: dtimeout = this.core.timeout, - } = tparams + } = params - let current = await this.core.get(skey) + let current = await this.core.get(skey, params) if (current?.aborter) return current if (this.core.shouldCooldown(current, force)) @@ -45,7 +46,7 @@ export class Single { try { const { signal } = aborter - current = await this.core.apply(skey, current, { aborter }) + current = await this.core.apply(skey, current, { aborter }, params) const { data, @@ -53,12 +54,12 @@ export class Single { expiration = getTimeFromDelay(dexpiration) } = await fetcher(key, { signal }) - return await this.core.apply(skey, current, { data, cooldown, expiration }) + return await this.core.apply(skey, current, { data, cooldown, expiration }, params) } catch (error: any) { const cooldown = getTimeFromDelay(dcooldown) const expiration = getTimeFromDelay(dexpiration) - return await this.core.apply(skey, current, { error, cooldown, expiration }) + return await this.core.apply(skey, current, { error, cooldown, expiration }, params) } finally { clearTimeout(timeout) } @@ -81,7 +82,7 @@ export class Single { poster: Poster, updater: Updater, aborter = new AbortController(), - tparams: TimeParams = {}, + params: Params = {}, ) { if (key === undefined) return if (skey === undefined) return @@ -90,9 +91,9 @@ export class Single { cooldown: dcooldown = this.core.cooldown, expiration: dexpiration = this.core.expiration, timeout: dtimeout = this.core.timeout, - } = tparams + } = params - const current = await this.core.get(skey) + const current = await this.core.get(skey, params) const updated = updater(current?.data) const timeout = setTimeout(() => { @@ -102,7 +103,7 @@ export class Single { try { const { signal } = aborter - await this.core.mutate(skey, { data: updated, time: current?.time }) + await this.core.mutate(skey, { data: updated, time: current?.time }, params) const { data, @@ -110,9 +111,9 @@ export class Single { expiration = getTimeFromDelay(dexpiration) } = await poster(key, { data: updated, signal }) - return await this.core.mutate(skey, { data, cooldown, expiration }) + return await this.core.mutate(skey, { data, cooldown, expiration }, params) } catch (error: any) { - this.core.mutate(skey, current) + this.core.mutate(skey, current, params) throw error } finally { clearTimeout(timeout) diff --git a/test/next/pages/optimistic/index.tsx b/test/next/pages/optimistic/index.tsx index f3918da9..eede0a82 100644 --- a/test/next/pages/optimistic/index.tsx +++ b/test/next/pages/optimistic/index.tsx @@ -25,7 +25,7 @@ export default function Page() { const hello = useHelloData() // this is for you, gaearon - const { data, error, loading, ready, update, refetch, aborter } = hello + const { data, error, loading, update, refetch, aborter } = hello const onRefreshClick = useCallback(() => { refetch() diff --git a/test/next/pages/storage/index.tsx b/test/next/pages/storage/index.tsx index 99a13299..7700bf61 100644 --- a/test/next/pages/storage/index.tsx +++ b/test/next/pages/storage/index.tsx @@ -22,15 +22,6 @@ class GZIP { } } -export default function Wrapper() { - const storage = XSWR.useAsyncLocalStorage(GZIP) - - return - - -} - async function fetchAsJson(url: string, more: XSWR.PosterMore) { const { signal } = more @@ -45,14 +36,18 @@ async function fetchAsJson(url: string, more: XSWR.PosterMore) { } function useHelloData() { - const handle = XSWR.useSingle("/api/hello", fetchAsJson) + const storage = XSWR.useAsyncLocalStorage(GZIP) + + const handle = XSWR.useSingle( + "/api/hello", + fetchAsJson, + { storage }) XSWR.useDebug(handle, "hello") - XSWR.useFetch(handle) return handle } -export function Page() { +export default function Page() { const { data, fetch, clear } = useHelloData() return <>