varstor 0.6.62 → 0.6.64
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 +60 -11
- package/dist/varstor-webextension.js +121 -59
- package/dist/varstor-webextension.min.js +1 -1
- package/dist/varstor.js +111 -55
- package/dist/varstor.min.js +1 -1
- package/package.json +1 -1
- package/src/actions.ts +19 -0
- package/src/helpers.ts +8 -0
- package/src/index.ts +57 -16
- package/src/listeners.ts +19 -7
- package/src/storage.ts +7 -0
- package/src/types.d.ts +16 -4
- package/src/webextension-storage.ts +7 -0
- package/src/webextension.ts +3 -3
- package/src/validation.ts +0 -31
package/dist/varstor.js
CHANGED
|
@@ -12,6 +12,38 @@ return /******/ (() => { // webpackBootstrap
|
|
|
12
12
|
/******/ "use strict";
|
|
13
13
|
/******/ var __webpack_modules__ = ({
|
|
14
14
|
|
|
15
|
+
/***/ "./src/actions.ts"
|
|
16
|
+
/*!************************!*\
|
|
17
|
+
!*** ./src/actions.ts ***!
|
|
18
|
+
\************************/
|
|
19
|
+
(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
|
20
|
+
|
|
21
|
+
__webpack_require__.r(__webpack_exports__);
|
|
22
|
+
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
23
|
+
/* harmony export */ addStateActions: () => (/* binding */ addStateActions)
|
|
24
|
+
/* harmony export */ });
|
|
25
|
+
/* harmony import */ var ___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! . */ "./src/index.ts");
|
|
26
|
+
|
|
27
|
+
function addStateActions(namespace, actions) {
|
|
28
|
+
const stateAcessor = {
|
|
29
|
+
get: ___WEBPACK_IMPORTED_MODULE_0__.getState.bind(null, namespace),
|
|
30
|
+
set: ___WEBPACK_IMPORTED_MODULE_0__.setState.bind(null, namespace),
|
|
31
|
+
reset: ___WEBPACK_IMPORTED_MODULE_0__.resetState.bind(null, namespace),
|
|
32
|
+
};
|
|
33
|
+
for (let [actionName, actionFn] of Object.entries(actions)) {
|
|
34
|
+
___WEBPACK_IMPORTED_MODULE_0__.STATE[namespace(actionName)] = {
|
|
35
|
+
key: actionName,
|
|
36
|
+
namespace,
|
|
37
|
+
value: actionFn.bind(null, stateAcessor),
|
|
38
|
+
isAction: true,
|
|
39
|
+
listeners: [],
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
/***/ },
|
|
46
|
+
|
|
15
47
|
/***/ "./src/constants.ts"
|
|
16
48
|
/*!**************************!*\
|
|
17
49
|
!*** ./src/constants.ts ***!
|
|
@@ -39,11 +71,13 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
39
71
|
/* harmony export */ forEach: () => (/* binding */ forEach),
|
|
40
72
|
/* harmony export */ getParamNames: () => (/* binding */ getParamNames),
|
|
41
73
|
/* harmony export */ isArray: () => (/* binding */ isArray),
|
|
74
|
+
/* harmony export */ isAsyncFunction: () => (/* binding */ isAsyncFunction),
|
|
42
75
|
/* harmony export */ isFunction: () => (/* binding */ isFunction),
|
|
43
76
|
/* harmony export */ isObject: () => (/* binding */ isObject),
|
|
44
77
|
/* harmony export */ isString: () => (/* binding */ isString),
|
|
45
78
|
/* harmony export */ map: () => (/* binding */ map),
|
|
46
|
-
/* harmony export */ recreateStructure: () => (/* binding */ recreateStructure)
|
|
79
|
+
/* harmony export */ recreateStructure: () => (/* binding */ recreateStructure),
|
|
80
|
+
/* harmony export */ uid: () => (/* binding */ uid)
|
|
47
81
|
/* harmony export */ });
|
|
48
82
|
const STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/gm;
|
|
49
83
|
const ARGUMENT_NAMES = /([^\s,]+)/g;
|
|
@@ -56,6 +90,9 @@ function isString(obj) {
|
|
|
56
90
|
function isFunction(obj) {
|
|
57
91
|
return getObjectType(obj) === "[object Function]";
|
|
58
92
|
}
|
|
93
|
+
function isAsyncFunction(obj) {
|
|
94
|
+
return getObjectType(obj) === "[object AsyncFunction]";
|
|
95
|
+
}
|
|
59
96
|
function isObject(obj) {
|
|
60
97
|
return getObjectType(obj) === "[object Object]";
|
|
61
98
|
}
|
|
@@ -101,6 +138,9 @@ function recreateStructure(value) {
|
|
|
101
138
|
}
|
|
102
139
|
return newValue;
|
|
103
140
|
}
|
|
141
|
+
function uid() {
|
|
142
|
+
return Date.now().toString(36) + Math.random().toString(36).substr(2);
|
|
143
|
+
}
|
|
104
144
|
|
|
105
145
|
|
|
106
146
|
/***/ },
|
|
@@ -116,12 +156,17 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
116
156
|
/* harmony export */ STATE: () => (/* binding */ STATE),
|
|
117
157
|
/* harmony export */ createStore: () => (/* binding */ createStore),
|
|
118
158
|
/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__),
|
|
119
|
-
/* harmony export */
|
|
159
|
+
/* harmony export */ getState: () => (/* binding */ getState),
|
|
160
|
+
/* harmony export */ getValues: () => (/* binding */ getValues),
|
|
161
|
+
/* harmony export */ joinStateChanges: () => (/* binding */ joinStateChanges),
|
|
162
|
+
/* harmony export */ resetState: () => (/* binding */ resetState),
|
|
163
|
+
/* harmony export */ setState: () => (/* binding */ setState),
|
|
164
|
+
/* harmony export */ setupValue: () => (/* binding */ setupValue)
|
|
120
165
|
/* harmony export */ });
|
|
121
166
|
/* harmony import */ var _storage__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./storage */ "./src/storage.ts");
|
|
122
167
|
/* harmony import */ var _helpers__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./helpers */ "./src/helpers.ts");
|
|
123
|
-
/* harmony import */ var
|
|
124
|
-
/* harmony import */ var
|
|
168
|
+
/* harmony import */ var _actions__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./actions */ "./src/actions.ts");
|
|
169
|
+
/* harmony import */ var _constants__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./constants */ "./src/constants.ts");
|
|
125
170
|
/* harmony import */ var _listeners__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./listeners */ "./src/listeners.ts");
|
|
126
171
|
|
|
127
172
|
|
|
@@ -129,6 +174,7 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
129
174
|
|
|
130
175
|
|
|
131
176
|
const STATE = {};
|
|
177
|
+
const WAITING_CHANGES = {};
|
|
132
178
|
const STORAGE = {};
|
|
133
179
|
setStorageUtils(_storage__WEBPACK_IMPORTED_MODULE_0__["default"]);
|
|
134
180
|
async function addState(namespace, initialState, isPersistent) {
|
|
@@ -143,7 +189,6 @@ async function addState(namespace, initialState, isPersistent) {
|
|
|
143
189
|
}
|
|
144
190
|
for (const key in initialState) {
|
|
145
191
|
const fullKey = namespace(key);
|
|
146
|
-
_validation__WEBPACK_IMPORTED_MODULE_3__.isValid.Defining(fullKey);
|
|
147
192
|
STATE[fullKey] = setupValue(key, namespace, values[fullKey], defaultValues[key], storageType);
|
|
148
193
|
}
|
|
149
194
|
return createStore(namespace());
|
|
@@ -194,6 +239,26 @@ function getArguments(dependencies, namespace) {
|
|
|
194
239
|
const values = getValues(namespace);
|
|
195
240
|
return dependencies.map((name) => values[name]);
|
|
196
241
|
}
|
|
242
|
+
async function joinStateChanges(changesPiece) {
|
|
243
|
+
for (const [updateId, { storageTypes, readyStorageTypes, changes },] of Object.entries(WAITING_CHANGES)) {
|
|
244
|
+
if (changesPiece[updateId]) {
|
|
245
|
+
const storageType = changesPiece[updateId].newValue;
|
|
246
|
+
readyStorageTypes[storageType] = true;
|
|
247
|
+
delete changesPiece[updateId];
|
|
248
|
+
Object.assign(changes, changesPiece);
|
|
249
|
+
if (STORAGE.IS_AVAILABE(storageType)) {
|
|
250
|
+
STORAGE.REMOVE_KEY(storageType, updateId);
|
|
251
|
+
}
|
|
252
|
+
for (const key in storageTypes) {
|
|
253
|
+
if (!readyStorageTypes[key]) {
|
|
254
|
+
return;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
delete WAITING_CHANGES[updateId];
|
|
258
|
+
await onStateChange(changes);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
}
|
|
197
262
|
async function onStateChange(changes) {
|
|
198
263
|
const realChanges = {};
|
|
199
264
|
for (const key in changes) {
|
|
@@ -241,19 +306,27 @@ function getState(namespace, arg) {
|
|
|
241
306
|
}
|
|
242
307
|
async function setState(namespace, changes) {
|
|
243
308
|
const storageChanges = {};
|
|
309
|
+
const updateId = (0,_helpers__WEBPACK_IMPORTED_MODULE_1__.uid)();
|
|
310
|
+
const storageTypes = {};
|
|
244
311
|
(0,_helpers__WEBPACK_IMPORTED_MODULE_1__.forEach)(changes, (k, v) => {
|
|
245
312
|
const fullKey = namespace(k);
|
|
246
|
-
const { storageType, computeFn } = STATE[fullKey];
|
|
247
|
-
if (computeFn) {
|
|
313
|
+
const { storageType, computeFn, isAction } = STATE[fullKey];
|
|
314
|
+
if (computeFn || isAction) {
|
|
248
315
|
return;
|
|
249
316
|
}
|
|
250
317
|
if (!storageChanges[storageType]) {
|
|
251
318
|
storageChanges[storageType] = {};
|
|
252
319
|
}
|
|
320
|
+
storageTypes[storageType] = true;
|
|
253
321
|
storageChanges[storageType][fullKey] = v;
|
|
254
322
|
});
|
|
323
|
+
WAITING_CHANGES[updateId] = {
|
|
324
|
+
storageTypes,
|
|
325
|
+
readyStorageTypes: {},
|
|
326
|
+
changes: {},
|
|
327
|
+
};
|
|
255
328
|
for (let [storageType, changes] of Object.entries(storageChanges)) {
|
|
256
|
-
await setValues(storageType, changes);
|
|
329
|
+
await setValues(storageType, { ...changes, [updateId]: storageType });
|
|
257
330
|
}
|
|
258
331
|
return createStore(namespace());
|
|
259
332
|
}
|
|
@@ -264,7 +337,7 @@ async function setValues(storageType, changes) {
|
|
|
264
337
|
return;
|
|
265
338
|
}
|
|
266
339
|
}
|
|
267
|
-
|
|
340
|
+
joinStateChanges((0,_helpers__WEBPACK_IMPORTED_MODULE_1__.map)(changes, (k, newValue) => [k, { newValue }]));
|
|
268
341
|
}
|
|
269
342
|
async function resetState(namespace, keys) {
|
|
270
343
|
const namespaceState = getNamespaceState(namespace);
|
|
@@ -288,7 +361,7 @@ function setStorageUtils(storageUtils) {
|
|
|
288
361
|
Object.assign(STORAGE, storageUtils);
|
|
289
362
|
}
|
|
290
363
|
function addNamespace(namespace, str) {
|
|
291
|
-
return `${namespace}${((0,_helpers__WEBPACK_IMPORTED_MODULE_1__.isString)(str) &&
|
|
364
|
+
return `${namespace}${((0,_helpers__WEBPACK_IMPORTED_MODULE_1__.isString)(str) && _constants__WEBPACK_IMPORTED_MODULE_3__.NAMESPACE_DELIMITER) || ""}${str || ""}`;
|
|
292
365
|
}
|
|
293
366
|
function createStore(_namespace) {
|
|
294
367
|
const namespace = ((key) => addNamespace(_namespace, key));
|
|
@@ -300,8 +373,10 @@ function createStore(_namespace) {
|
|
|
300
373
|
reset: (keys) => resetState(namespace, keys),
|
|
301
374
|
onChange: (keys, cb) => (0,_listeners__WEBPACK_IMPORTED_MODULE_4__.addStateListener)(namespace, keys, cb),
|
|
302
375
|
removeListener: (keys, cb) => (0,_listeners__WEBPACK_IMPORTED_MODULE_4__.removeStateListener)(namespace, keys, cb),
|
|
376
|
+
actions: (actions) => (0,_actions__WEBPACK_IMPORTED_MODULE_2__.addStateActions)(namespace, actions),
|
|
303
377
|
setStorageUtils,
|
|
304
|
-
|
|
378
|
+
joinStateChanges,
|
|
379
|
+
namespace,
|
|
305
380
|
});
|
|
306
381
|
}
|
|
307
382
|
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (createStore(""));
|
|
@@ -336,20 +411,33 @@ async function runStateChangeListeners(realChanges) {
|
|
|
336
411
|
for (let [changeKey, change] of Object.entries(realChanges)) {
|
|
337
412
|
const { listeners, key } = ___WEBPACK_IMPORTED_MODULE_0__.STATE[changeKey];
|
|
338
413
|
for (const cb of listeners) {
|
|
339
|
-
|
|
414
|
+
const fn = cb.bind(null, [key], stateValues, change);
|
|
415
|
+
if ((0,_helpers__WEBPACK_IMPORTED_MODULE_2__.isAsyncFunction)(cb)) {
|
|
416
|
+
await fn();
|
|
417
|
+
}
|
|
418
|
+
else {
|
|
419
|
+
fn();
|
|
420
|
+
}
|
|
340
421
|
}
|
|
341
422
|
}
|
|
342
|
-
const
|
|
423
|
+
const namespaceLength = `${namespace()}${_constants__WEBPACK_IMPORTED_MODULE_1__.NAMESPACE_DELIMITER}`.length;
|
|
424
|
+
const readableKeys = (0,_helpers__WEBPACK_IMPORTED_MODULE_2__.map)(realChanges, (k) => k.slice(namespaceLength));
|
|
343
425
|
for (const cb of LISTENERS[namespace()]) {
|
|
344
|
-
|
|
345
|
-
k.slice(
|
|
426
|
+
const fn = cb.bind(null, readableKeys, stateValues, (0,_helpers__WEBPACK_IMPORTED_MODULE_2__.map)(realChanges, (k, v) => [
|
|
427
|
+
k.slice(namespaceLength),
|
|
346
428
|
v,
|
|
347
429
|
]));
|
|
430
|
+
if ((0,_helpers__WEBPACK_IMPORTED_MODULE_2__.isAsyncFunction)(cb)) {
|
|
431
|
+
await fn();
|
|
432
|
+
}
|
|
433
|
+
else {
|
|
434
|
+
fn();
|
|
435
|
+
}
|
|
348
436
|
}
|
|
349
437
|
}
|
|
350
438
|
}
|
|
351
439
|
function addStateListener(namespace, observables, cb) {
|
|
352
|
-
if ((0,_helpers__WEBPACK_IMPORTED_MODULE_2__.isFunction)(observables)) {
|
|
440
|
+
if ((0,_helpers__WEBPACK_IMPORTED_MODULE_2__.isFunction)(observables) || (0,_helpers__WEBPACK_IMPORTED_MODULE_2__.isAsyncFunction)(observables)) {
|
|
353
441
|
LISTENERS[namespace()].push(observables);
|
|
354
442
|
return (0,___WEBPACK_IMPORTED_MODULE_0__.createStore)(namespace());
|
|
355
443
|
}
|
|
@@ -357,7 +445,7 @@ function addStateListener(namespace, observables, cb) {
|
|
|
357
445
|
return (0,___WEBPACK_IMPORTED_MODULE_0__.createStore)(namespace());
|
|
358
446
|
}
|
|
359
447
|
function removeStateListener(namespace, observables, removeCb) {
|
|
360
|
-
if ((0,_helpers__WEBPACK_IMPORTED_MODULE_2__.isFunction)(observables)) {
|
|
448
|
+
if ((0,_helpers__WEBPACK_IMPORTED_MODULE_2__.isFunction)(observables) || (0,_helpers__WEBPACK_IMPORTED_MODULE_2__.isAsyncFunction)(observables)) {
|
|
361
449
|
const removeIdx = LISTENERS[namespace()].findIndex((cb) => cb === observables);
|
|
362
450
|
LISTENERS[namespace()].splice(removeIdx, 1);
|
|
363
451
|
return (0,___WEBPACK_IMPORTED_MODULE_0__.createStore)(namespace());
|
|
@@ -405,52 +493,20 @@ async function setStorageValue(storageType, changes) {
|
|
|
405
493
|
}
|
|
406
494
|
return false;
|
|
407
495
|
}
|
|
496
|
+
function removeStorageKey(type, key) {
|
|
497
|
+
if (type) {
|
|
498
|
+
localStorage.removeItem(key);
|
|
499
|
+
}
|
|
500
|
+
}
|
|
408
501
|
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ({
|
|
409
502
|
GET_TYPE: getStorageType,
|
|
410
503
|
IS_AVAILABE: isStorageAvailable,
|
|
411
504
|
UPDATE_STATE: updateFromLocalStorage,
|
|
412
505
|
SET_VALUES: setStorageValue,
|
|
506
|
+
REMOVE_KEY: removeStorageKey,
|
|
413
507
|
});
|
|
414
508
|
|
|
415
509
|
|
|
416
|
-
/***/ },
|
|
417
|
-
|
|
418
|
-
/***/ "./src/validation.ts"
|
|
419
|
-
/*!***************************!*\
|
|
420
|
-
!*** ./src/validation.ts ***!
|
|
421
|
-
\***************************/
|
|
422
|
-
(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
|
423
|
-
|
|
424
|
-
__webpack_require__.r(__webpack_exports__);
|
|
425
|
-
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
426
|
-
/* harmony export */ isValid: () => (/* binding */ isValid)
|
|
427
|
-
/* harmony export */ });
|
|
428
|
-
/* harmony import */ var ___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! . */ "./src/index.ts");
|
|
429
|
-
/* harmony import */ var _constants__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./constants */ "./src/constants.ts");
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
function splitFullKey(fullKey) {
|
|
433
|
-
const segments = fullKey.split(_constants__WEBPACK_IMPORTED_MODULE_1__.NAMESPACE_DELIMITER);
|
|
434
|
-
return [segments.slice(-1)[0], segments.join(_constants__WEBPACK_IMPORTED_MODULE_1__.NAMESPACE_DELIMITER)];
|
|
435
|
-
}
|
|
436
|
-
const isValid = {
|
|
437
|
-
Setting: (fullKey) => {
|
|
438
|
-
if (!___WEBPACK_IMPORTED_MODULE_0__.STATE[fullKey]) {
|
|
439
|
-
const [key, namespace] = splitFullKey(fullKey);
|
|
440
|
-
throw new Error(`Setting "${key}" key in "${namespace}" namespace. DOES NOT EXIST`);
|
|
441
|
-
}
|
|
442
|
-
return true;
|
|
443
|
-
},
|
|
444
|
-
Defining: (fullKey) => {
|
|
445
|
-
if (___WEBPACK_IMPORTED_MODULE_0__.STATE[fullKey]) {
|
|
446
|
-
const [key, namespace] = splitFullKey(fullKey);
|
|
447
|
-
throw new Error(`Redefining "${key}" key in "${namespace}" namespace. ALREADY DEFINED`);
|
|
448
|
-
}
|
|
449
|
-
return true;
|
|
450
|
-
},
|
|
451
|
-
};
|
|
452
|
-
|
|
453
|
-
|
|
454
510
|
/***/ }
|
|
455
511
|
|
|
456
512
|
/******/ });
|
package/dist/varstor.min.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
/*! For license information please see varstor.min.js.LICENSE.txt */
|
|
2
|
-
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.Varstor=t():e.Varstor=t()}(this,()=>(()=>{"use strict";var e={"./src/constants.ts"(e,t,n){n.r(t),n.d(t,{NAMESPACE_DELIMITER:()=>r});const r="::"},"./src/helpers.ts"(e,t,n){n.r(t),n.d(t,{filter:()=>
|
|
2
|
+
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.Varstor=t():e.Varstor=t()}(this,()=>(()=>{"use strict";var e={"./src/actions.ts"(e,t,n){n.r(t),n.d(t,{addStateActions:()=>s});var r=n("./src/index.ts");function s(e,t){const n={get:r.getState.bind(null,e),set:r.setState.bind(null,e),reset:r.resetState.bind(null,e)};for(let[s,o]of Object.entries(t))r.STATE[e(s)]={key:s,namespace:e,value:o.bind(null,n),isAction:!0,listeners:[]}}},"./src/constants.ts"(e,t,n){n.r(t),n.d(t,{NAMESPACE_DELIMITER:()=>r});const r="::"},"./src/helpers.ts"(e,t,n){n.r(t),n.d(t,{filter:()=>S,forEach:()=>p,getParamNames:()=>f,isArray:()=>o,isAsyncFunction:()=>a,isFunction:()=>i,isObject:()=>u,isString:()=>c,map:()=>d,recreateStructure:()=>y,uid:()=>E});const r=/((\/\/.*$)|(\/\*[\s\S]*?\*\/))/gm,s=/([^\s,]+)/g;function o(e){return"[object Array]"===l(e)}function c(e){return"[object String]"===l(e)}function i(e){return"[object Function]"===l(e)}function a(e){return"[object AsyncFunction]"===l(e)}function u(e){return"[object Object]"===l(e)}function l(e){return Object.prototype.toString.call(e)}function f(e){const t=e.toString().replace(r,"").split("=>")[0],n=t.slice(t.indexOf("(")+1,t.indexOf(")")).match(s);return null===n?[]:n}function d(e,t){const n=Object.entries(e).map(([e,n])=>t(e,n));return 2===n[0]?.length?Object.fromEntries(n):n}function p(e,t){Object.entries(e||{}).forEach(([e,n])=>t(e,n))}function S(e,t){return Object.fromEntries(Object.entries(e||{}).filter(([e,n])=>!0===t(e,n)))}function y(e){let t=e;if(o(e))return t=[],e.forEach(e=>t.push(y(e))),t;if(u(e)){t={};for(let n in e)t[n]=y(e[n]);return t}return t}function E(){return Date.now().toString(36)+Math.random().toString(36).substr(2)}},"./src/index.ts"(e,t,n){n.r(t),n.d(t,{STATE:()=>a,createStore:()=>v,default:()=>I,getState:()=>m,getValues:()=>S,joinStateChanges:()=>E,resetState:()=>j,setState:()=>A,setupValue:()=>d});var r=n("./src/storage.ts"),s=n("./src/helpers.ts"),o=n("./src/actions.ts"),c=n("./src/constants.ts"),i=n("./src/listeners.ts");const a={},u={},l={};async function f(e,t,n){const r=l.GET_TYPE(n),o=Object.assign({},t),c=(0,s.map)(t,(t,n)=>[e(t),n]);l.IS_AVAILABE(r)&&await l.UPDATE_STATE(c,r),i.LISTENERS[e()]||(i.LISTENERS[e()]=[]);for(const n in t){const t=e(n);a[t]=d(n,e,c[t],o[n],r)}return v(e())}function d(e,t,n,r,o){const c=t(e),i=(0,s.isFunction)(n),u=i?(0,s.getParamNames)(n):[];return u.forEach(e=>{const n=t(e);a[n]||(a[n]={dependants:[],dependencies:[],namespace:t,storageType:o}),a[n].dependants?.push(c)}),{key:e,fullKey:c,value:i?n.apply(null,y(u,t)):n,computeFn:i&&n,dependencies:u,dependants:[],listeners:[],defaultValue:r,storageType:o,namespace:t}}function p(e){return(0,s.filter)(a,(t,{key:n})=>t===e(n))}function S(e){return(0,s.map)(p(e),(e,{key:t,value:n})=>[t,n])}function y(e,t){const n=S(t);return e.map(e=>n[e])}async function E(e){for(const[t,{storageTypes:n,readyStorageTypes:r,changes:s}]of Object.entries(u))if(e[t]){const o=e[t].newValue;r[o]=!0,delete e[t],Object.assign(s,e),l.IS_AVAILABE(o)&&l.REMOVE_KEY(o,t);for(const e in n)if(!r[e])return;delete u[t],await g(s)}}async function g(e){const t={};for(const n in e){const r=a[n].value,s=e[n].newValue;r!==s?(t[n]={newValue:s,prevValue:r},a[n].value=s):t[n]={isSame:!0},b(n,e,t)}await(0,i.runStateChangeListeners)((0,s.filter)(t,(e,t)=>!t.isSame))}function b(e,t,n){a[e].dependants?.forEach(e=>{const{dependencies:r,namespace:s}=a[e];if(!function(e,t,n,r){return e.every(e=>{const s=t(e);return n.includes(s)&&r.includes(s)||!n.includes(s)})}(r,s,Object.keys(t),Object.keys(n))||n[e])return;const o=a[e].value,c=a[e].computeFn?.apply(null,y(r,s));o!==c&&(n[e]={newValue:c,prevValue:o},a[e].value=c,b(e,t,n))})}function m(e,t){return(0,s.isString)(t)?v(t):(0,s.recreateStructure)(S(e))}async function A(e,t){const n={},r=(0,s.uid)(),o={};(0,s.forEach)(t,(t,r)=>{const s=e(t),{storageType:c,computeFn:i,isAction:u}=a[s];i||u||(n[c]||(n[c]={}),o[c]=!0,n[c][s]=r)}),u[r]={storageTypes:o,readyStorageTypes:{},changes:{}};for(let[e,t]of Object.entries(n))await T(e,{...t,[r]:e});return v(e())}async function T(e,t){if(l.IS_AVAILABE(e)){if(await l.SET_VALUES(e,t))return}E((0,s.map)(t,(e,t)=>[e,{newValue:t}]))}async function j(e,t){const n=p(e);return await A(e,(0,s.map)(t?(0,s.filter)(n,(e,{key:n})=>t.includes(n)):n,(e,{key:t,defaultValue:n})=>[t,n])),v(e())}function O(e){return!arguments[1]||(0,s.isString)(arguments[1])?m.apply(null,arguments):(0,s.isArray)(arguments[1])?i.addStateListener.apply(null,arguments):(0,s.isObject)(arguments[1])?A.apply(null,arguments):void 0}function h(e){Object.assign(l,e)}function v(e){const t=t=>function(e,t){return`${e}${(0,s.isString)(t)&&c.NAMESPACE_DELIMITER||""}${t||""}`}(e,t);return Object.assign(O.bind(null,t),{add:e=>f(t,e,!1),addPersistent:e=>f(t,e,!0),get:e=>m(t,e),set:async e=>await A(t,e),reset:e=>j(t,e),onChange:(e,n)=>(0,i.addStateListener)(t,e,n),removeListener:(e,n)=>(0,i.removeStateListener)(t,e,n),actions:e=>(0,o.addStateActions)(t,e),setStorageUtils:h,joinStateChanges:E,namespace:t})}h(r.default);const I=v("")},"./src/listeners.ts"(e,t,n){n.r(t),n.d(t,{LISTENERS:()=>c,addStateListener:()=>a,removeStateListener:()=>u,runStateChangeListeners:()=>i});var r=n("./src/index.ts"),s=n("./src/constants.ts"),o=n("./src/helpers.ts");const c={};async function i(e){if(Object.keys(e).length){const{namespace:t}=r.STATE[Object.keys(e)[0]],n=(0,r.getValues)(t);for(let[t,s]of Object.entries(e)){const{listeners:e,key:c}=r.STATE[t];for(const t of e){const e=t.bind(null,[c],n,s);(0,o.isAsyncFunction)(t)?await e():e()}}const i=`${t()}${s.NAMESPACE_DELIMITER}`.length,a=(0,o.map)(e,e=>e.slice(i));for(const r of c[t()]){const t=r.bind(null,a,n,(0,o.map)(e,(e,t)=>[e.slice(i),t]));(0,o.isAsyncFunction)(r)?await t():t()}}}function a(e,t,n){return(0,o.isFunction)(t)||(0,o.isAsyncFunction)(t)?(c[e()].push(t),(0,r.createStore)(e())):(t.forEach(t=>r.STATE[e(t)].listeners?.push(n)),(0,r.createStore)(e()))}function u(e,t,n){if((0,o.isFunction)(t)||(0,o.isAsyncFunction)(t)){const n=c[e()].findIndex(e=>e===t);return c[e()].splice(n,1),(0,r.createStore)(e())}return t.forEach(t=>{const s=r.STATE[e(t)].listeners,o=s?.findIndex(e=>e===n);s?.splice(o,1)}),(0,r.createStore)(e())}},"./src/storage.ts"(e,t,n){n.r(t),n.d(t,{default:()=>r});const r={GET_TYPE:function(e){return e?"localStorage":""},IS_AVAILABE:function(e){return!!e},UPDATE_STATE:async function(e){const t={};for(const n in e){const e=localStorage.getItem(n);null!==e&&(t[n]=e)}return Object.assign(e,t)},SET_VALUES:async function(e,t){for(let[e,n]of Object.entries(t))localStorage.setItem(e,n);return!1},REMOVE_KEY:function(e,t){e&&localStorage.removeItem(t)}}}};const t={};function n(r){const s=t[r];if(void 0!==s)return s.exports;const o=t[r]={exports:{}};if(!(r in e)){delete t[r];const e=new Error("Cannot find module '"+r+"'");throw e.code="MODULE_NOT_FOUND",e}return e[r](o,o.exports,n),o.exports}n.d=(e,t)=>{if(Array.isArray(t))for(var r=0;r<t.length;){var s=t[r++],o=t[r++];n.o(e,s)?0===o&&r++:0===o?Object.defineProperty(e,s,{enumerable:!0,value:t[r++]}):Object.defineProperty(e,s,{enumerable:!0,get:o})}else for(var s in t)n.o(t,s)&&!n.o(e,s)&&Object.defineProperty(e,s,{enumerable:!0,get:t[s]})},n.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),n.r=e=>{Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})};let r=n("./src/index.ts");return r=r.default,r})());
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "varstor",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.64",
|
|
4
4
|
"description": "State manager for web applications and webextensions, employing reactivity, wrapping, and uniting the usage of different storages' values and common variables into a simple universal interface",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Igor Morozov <ismorozs@gmail.com>",
|
package/src/actions.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { STATE, getState, setState, resetState } from ".";
|
|
2
|
+
|
|
3
|
+
export function addStateActions(namespace: INamespace, actions: IStateActions) {
|
|
4
|
+
const stateAcessor = {
|
|
5
|
+
get: getState.bind(null, namespace),
|
|
6
|
+
set: setState.bind(null, namespace),
|
|
7
|
+
reset: resetState.bind(null, namespace),
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
for (let [actionName, actionFn] of Object.entries(actions)) {
|
|
11
|
+
STATE[namespace(actionName)] = {
|
|
12
|
+
key: actionName,
|
|
13
|
+
namespace,
|
|
14
|
+
value: actionFn.bind(null, stateAcessor),
|
|
15
|
+
isAction: true,
|
|
16
|
+
listeners: [],
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
}
|
package/src/helpers.ts
CHANGED
|
@@ -13,6 +13,10 @@ export function isFunction(obj: unknown) {
|
|
|
13
13
|
return getObjectType(obj) === "[object Function]";
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
+
export function isAsyncFunction (obj: unknown) {
|
|
17
|
+
return getObjectType(obj) === "[object AsyncFunction]";
|
|
18
|
+
}
|
|
19
|
+
|
|
16
20
|
export function isObject(obj: unknown) {
|
|
17
21
|
return getObjectType(obj) === "[object Object]";
|
|
18
22
|
}
|
|
@@ -86,3 +90,7 @@ export function recreateStructure(value: unknown) {
|
|
|
86
90
|
|
|
87
91
|
return newValue;
|
|
88
92
|
}
|
|
93
|
+
|
|
94
|
+
export function uid() {
|
|
95
|
+
return Date.now().toString(36) + Math.random().toString(36).substr(2);
|
|
96
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -10,11 +10,13 @@ import {
|
|
|
10
10
|
filter,
|
|
11
11
|
recreateStructure,
|
|
12
12
|
forEach,
|
|
13
|
+
uid,
|
|
13
14
|
} from "./helpers";
|
|
14
15
|
|
|
16
|
+
import { addStateActions } from "./actions";
|
|
17
|
+
|
|
15
18
|
import { NAMESPACE_DELIMITER } from "./constants";
|
|
16
19
|
|
|
17
|
-
import { isValid } from "./validation";
|
|
18
20
|
import {
|
|
19
21
|
runStateChangeListeners,
|
|
20
22
|
addStateListener,
|
|
@@ -23,6 +25,7 @@ import {
|
|
|
23
25
|
} from "./listeners";
|
|
24
26
|
|
|
25
27
|
export const STATE = {} as IState;
|
|
28
|
+
const WAITING_CHANGES = {} as IStateUpdatePieces;
|
|
26
29
|
const STORAGE = {} as IStorageFunctions;
|
|
27
30
|
|
|
28
31
|
setStorageUtils(storageUtils);
|
|
@@ -49,7 +52,6 @@ async function addState(
|
|
|
49
52
|
|
|
50
53
|
for (const key in initialState) {
|
|
51
54
|
const fullKey = namespace(key);
|
|
52
|
-
isValid.Defining(fullKey);
|
|
53
55
|
STATE[fullKey] = setupValue(
|
|
54
56
|
key,
|
|
55
57
|
namespace,
|
|
@@ -62,7 +64,7 @@ async function addState(
|
|
|
62
64
|
return createStore(namespace());
|
|
63
65
|
}
|
|
64
66
|
|
|
65
|
-
function setupValue(
|
|
67
|
+
export function setupValue(
|
|
66
68
|
key: string,
|
|
67
69
|
namespace: INamespace,
|
|
68
70
|
value: unknown,
|
|
@@ -123,6 +125,33 @@ function getArguments(dependencies: string[], namespace: INamespace) {
|
|
|
123
125
|
return dependencies.map((name) => values[name as keyof typeof values]);
|
|
124
126
|
}
|
|
125
127
|
|
|
128
|
+
export async function joinStateChanges(changesPiece: IStateChanges) {
|
|
129
|
+
for (const [
|
|
130
|
+
updateId,
|
|
131
|
+
{ storageTypes, readyStorageTypes, changes },
|
|
132
|
+
] of Object.entries(WAITING_CHANGES)) {
|
|
133
|
+
if (changesPiece[updateId]) {
|
|
134
|
+
const storageType = changesPiece[updateId].newValue;
|
|
135
|
+
readyStorageTypes[storageType] = true;
|
|
136
|
+
delete changesPiece[updateId];
|
|
137
|
+
Object.assign(changes, changesPiece);
|
|
138
|
+
if (STORAGE.IS_AVAILABE(storageType)) {
|
|
139
|
+
STORAGE.REMOVE_KEY(storageType, updateId);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
for (const key in storageTypes) {
|
|
143
|
+
if (!readyStorageTypes[key]) {
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
delete WAITING_CHANGES[updateId];
|
|
149
|
+
|
|
150
|
+
await onStateChange(changes);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
126
155
|
async function onStateChange(changes: IStateChanges) {
|
|
127
156
|
const realChanges = {} as IStateChanges;
|
|
128
157
|
|
|
@@ -153,7 +182,7 @@ function updateDependencies(
|
|
|
153
182
|
|
|
154
183
|
if (
|
|
155
184
|
!isEveryDependencyReady(
|
|
156
|
-
dependencies
|
|
185
|
+
dependencies!,
|
|
157
186
|
namespace,
|
|
158
187
|
Object.keys(changes),
|
|
159
188
|
Object.keys(realChanges),
|
|
@@ -166,7 +195,7 @@ function updateDependencies(
|
|
|
166
195
|
const prevValue = STATE[name].value;
|
|
167
196
|
const newValue = (STATE[name].computeFn as IComputeFunction)?.apply(
|
|
168
197
|
null,
|
|
169
|
-
getArguments(dependencies
|
|
198
|
+
getArguments(dependencies!, namespace),
|
|
170
199
|
);
|
|
171
200
|
|
|
172
201
|
if (prevValue !== newValue) {
|
|
@@ -192,7 +221,7 @@ function isEveryDependencyReady(
|
|
|
192
221
|
});
|
|
193
222
|
}
|
|
194
223
|
|
|
195
|
-
function getState(namespace: INamespace, arg: string) {
|
|
224
|
+
export function getState(namespace: INamespace, arg: string) {
|
|
196
225
|
if (isString(arg)) {
|
|
197
226
|
return createStore(arg);
|
|
198
227
|
}
|
|
@@ -200,29 +229,39 @@ function getState(namespace: INamespace, arg: string) {
|
|
|
200
229
|
return recreateStructure(getValues(namespace));
|
|
201
230
|
}
|
|
202
231
|
|
|
203
|
-
async function setState(
|
|
232
|
+
export async function setState(
|
|
204
233
|
namespace: INamespace,
|
|
205
234
|
changes: Record<string, unknown>,
|
|
206
235
|
): Promise<unknown> {
|
|
207
236
|
const storageChanges: Record<string, any> = {};
|
|
237
|
+
const updateId = uid();
|
|
238
|
+
const storageTypes = {} as Record<string, boolean>;
|
|
208
239
|
|
|
209
240
|
forEach(changes, (k, v) => {
|
|
210
241
|
const fullKey = namespace(k);
|
|
211
|
-
const { storageType, computeFn } = STATE[fullKey];
|
|
242
|
+
const { storageType, computeFn, isAction } = STATE[fullKey];
|
|
212
243
|
|
|
213
|
-
if (computeFn) {
|
|
244
|
+
if (computeFn || isAction) {
|
|
214
245
|
return;
|
|
215
246
|
}
|
|
216
247
|
|
|
217
|
-
if (!storageChanges[storageType]) {
|
|
218
|
-
storageChanges[storageType] = {};
|
|
248
|
+
if (!storageChanges[storageType!]) {
|
|
249
|
+
storageChanges[storageType!] = {};
|
|
219
250
|
}
|
|
220
251
|
|
|
221
|
-
|
|
252
|
+
storageTypes[storageType!] = true;
|
|
253
|
+
|
|
254
|
+
storageChanges[storageType!][fullKey] = v;
|
|
222
255
|
});
|
|
223
256
|
|
|
257
|
+
WAITING_CHANGES[updateId] = {
|
|
258
|
+
storageTypes,
|
|
259
|
+
readyStorageTypes: {},
|
|
260
|
+
changes: {},
|
|
261
|
+
};
|
|
262
|
+
|
|
224
263
|
for (let [storageType, changes] of Object.entries(storageChanges)) {
|
|
225
|
-
await setValues(storageType, changes);
|
|
264
|
+
await setValues(storageType, { ...changes, [updateId]: storageType });
|
|
226
265
|
}
|
|
227
266
|
|
|
228
267
|
return createStore(namespace());
|
|
@@ -239,12 +278,12 @@ async function setValues(
|
|
|
239
278
|
}
|
|
240
279
|
}
|
|
241
280
|
|
|
242
|
-
|
|
281
|
+
joinStateChanges(
|
|
243
282
|
map(changes, (k, newValue) => [k, { newValue }]) as Record<string, any>,
|
|
244
283
|
);
|
|
245
284
|
}
|
|
246
285
|
|
|
247
|
-
async function resetState(namespace: INamespace, keys?: string[]) {
|
|
286
|
+
export async function resetState(namespace: INamespace, keys?: string[]) {
|
|
248
287
|
const namespaceState = getNamespaceState(namespace);
|
|
249
288
|
|
|
250
289
|
await setState(
|
|
@@ -303,8 +342,10 @@ export function createStore(_namespace: string) {
|
|
|
303
342
|
addStateListener(namespace, keys, cb),
|
|
304
343
|
removeListener: (keys: string[], cb: () => {}) =>
|
|
305
344
|
removeStateListener(namespace, keys, cb),
|
|
345
|
+
actions: (actions: IStateActions) => addStateActions(namespace, actions),
|
|
306
346
|
setStorageUtils,
|
|
307
|
-
|
|
347
|
+
joinStateChanges,
|
|
348
|
+
namespace,
|
|
308
349
|
});
|
|
309
350
|
}
|
|
310
351
|
|
package/src/listeners.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { STATE, getValues, createStore } from ".";
|
|
2
2
|
import { NAMESPACE_DELIMITER } from "./constants";
|
|
3
|
-
import { map, isFunction } from "./helpers";
|
|
3
|
+
import { map, isFunction, isAsyncFunction } from "./helpers";
|
|
4
4
|
|
|
5
5
|
export const LISTENERS = {} as IStateListeners;
|
|
6
6
|
|
|
@@ -13,23 +13,35 @@ export async function runStateChangeListeners(realChanges: IStateChanges) {
|
|
|
13
13
|
for (let [changeKey, change] of Object.entries(realChanges)) {
|
|
14
14
|
const { listeners, key } = STATE[changeKey];
|
|
15
15
|
for (const cb of listeners!) {
|
|
16
|
-
|
|
16
|
+
const fn = cb.bind(null, [key], stateValues, change);
|
|
17
|
+
if (isAsyncFunction(cb)) {
|
|
18
|
+
await fn();
|
|
19
|
+
} else {
|
|
20
|
+
fn();
|
|
21
|
+
}
|
|
17
22
|
}
|
|
18
23
|
}
|
|
19
24
|
|
|
25
|
+
const namespaceLength = `${namespace()}${NAMESPACE_DELIMITER}`.length;
|
|
20
26
|
const readableKeys = map(realChanges, (k) =>
|
|
21
|
-
k.slice(
|
|
27
|
+
k.slice(namespaceLength),
|
|
22
28
|
) as string[];
|
|
23
29
|
|
|
24
30
|
for (const cb of LISTENERS[namespace()]) {
|
|
25
|
-
|
|
31
|
+
const fn = cb.bind(
|
|
32
|
+
null,
|
|
26
33
|
readableKeys,
|
|
27
34
|
stateValues,
|
|
28
35
|
map(realChanges, (k, v) => [
|
|
29
|
-
k.slice(
|
|
36
|
+
k.slice(namespaceLength),
|
|
30
37
|
v,
|
|
31
38
|
]) as IStateChanges,
|
|
32
39
|
);
|
|
40
|
+
if (isAsyncFunction(cb)) {
|
|
41
|
+
await fn();
|
|
42
|
+
} else {
|
|
43
|
+
fn();
|
|
44
|
+
}
|
|
33
45
|
}
|
|
34
46
|
}
|
|
35
47
|
}
|
|
@@ -39,7 +51,7 @@ export function addStateListener(
|
|
|
39
51
|
observables: string[] | IStateListener,
|
|
40
52
|
cb: () => {},
|
|
41
53
|
) {
|
|
42
|
-
if (isFunction(observables)) {
|
|
54
|
+
if (isFunction(observables) || isAsyncFunction(observables)) {
|
|
43
55
|
LISTENERS[namespace()].push(observables as IStateListener);
|
|
44
56
|
return createStore(namespace());
|
|
45
57
|
}
|
|
@@ -56,7 +68,7 @@ export function removeStateListener(
|
|
|
56
68
|
observables: string[] | IStateListener,
|
|
57
69
|
removeCb: () => {},
|
|
58
70
|
) {
|
|
59
|
-
if (isFunction(observables)) {
|
|
71
|
+
if (isFunction(observables) || isAsyncFunction(observables)) {
|
|
60
72
|
const removeIdx = LISTENERS[namespace()].findIndex(
|
|
61
73
|
(cb) => cb === observables,
|
|
62
74
|
);
|
package/src/storage.ts
CHANGED
|
@@ -29,9 +29,16 @@ async function setStorageValue(
|
|
|
29
29
|
return false;
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
+
function removeStorageKey (type: string, key: string) {
|
|
33
|
+
if (type) {
|
|
34
|
+
localStorage.removeItem(key);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
32
38
|
export default {
|
|
33
39
|
GET_TYPE: getStorageType,
|
|
34
40
|
IS_AVAILABE: isStorageAvailable,
|
|
35
41
|
UPDATE_STATE: updateFromLocalStorage,
|
|
36
42
|
SET_VALUES: setStorageValue,
|
|
43
|
+
REMOVE_KEY: removeStorageKey,
|
|
37
44
|
};
|