varstor 0.6.64 → 0.6.66

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/src/index.ts CHANGED
@@ -1,3 +1,18 @@
1
+ import {
2
+ type IVarstor,
3
+ type IState,
4
+ type IStateUpdatePieces,
5
+ type IStatePendingChanges,
6
+ type IStorageFunctions,
7
+ type INamespace,
8
+ type IStateDefault,
9
+ type IComputeFunction,
10
+ type IValue,
11
+ type IStateChanges,
12
+ type IStateActions,
13
+ type IStateListener,
14
+ } from "./types.d";
15
+
1
16
  import storageUtils from "./storage";
2
17
 
3
18
  import {
@@ -11,6 +26,7 @@ import {
11
26
  recreateStructure,
12
27
  forEach,
13
28
  uid,
29
+ isAsyncFunction,
14
30
  } from "./helpers";
15
31
 
16
32
  import { addStateActions } from "./actions";
@@ -25,7 +41,8 @@ import {
25
41
  } from "./listeners";
26
42
 
27
43
  export const STATE = {} as IState;
28
- const WAITING_CHANGES = {} as IStateUpdatePieces;
44
+ const STATE_CHANGED_PIECES = {} as IStateUpdatePieces;
45
+ const STATE_PENDING_CHANGES = {} as IStatePendingChanges;
29
46
  const STORAGE = {} as IStorageFunctions;
30
47
 
31
48
  setStorageUtils(storageUtils);
@@ -46,10 +63,6 @@ async function addState(
46
63
  await STORAGE.UPDATE_STATE(values, storageType as string);
47
64
  }
48
65
 
49
- if (!LISTENERS[namespace()]) {
50
- LISTENERS[namespace()] = [];
51
- }
52
-
53
66
  for (const key in initialState) {
54
67
  const fullKey = namespace(key);
55
68
  STATE[fullKey] = setupValue(
@@ -129,7 +142,7 @@ export async function joinStateChanges(changesPiece: IStateChanges) {
129
142
  for (const [
130
143
  updateId,
131
144
  { storageTypes, readyStorageTypes, changes },
132
- ] of Object.entries(WAITING_CHANGES)) {
145
+ ] of Object.entries(STATE_CHANGED_PIECES)) {
133
146
  if (changesPiece[updateId]) {
134
147
  const storageType = changesPiece[updateId].newValue;
135
148
  readyStorageTypes[storageType] = true;
@@ -145,7 +158,7 @@ export async function joinStateChanges(changesPiece: IStateChanges) {
145
158
  }
146
159
  }
147
160
 
148
- delete WAITING_CHANGES[updateId];
161
+ delete STATE_CHANGED_PIECES[updateId];
149
162
 
150
163
  await onStateChange(changes);
151
164
  }
@@ -226,13 +239,13 @@ export function getState(namespace: INamespace, arg: string) {
226
239
  return createStore(arg);
227
240
  }
228
241
 
229
- return recreateStructure(getValues(namespace));
242
+ return recreateStructure(getValues(namespace)) as Record<string, any>;
230
243
  }
231
244
 
232
245
  export async function setState(
233
246
  namespace: INamespace,
234
247
  changes: Record<string, unknown>,
235
- ): Promise<unknown> {
248
+ ): Promise<IVarstor> {
236
249
  const storageChanges: Record<string, any> = {};
237
250
  const updateId = uid();
238
251
  const storageTypes = {} as Record<string, boolean>;
@@ -254,7 +267,7 @@ export async function setState(
254
267
  storageChanges[storageType!][fullKey] = v;
255
268
  });
256
269
 
257
- WAITING_CHANGES[updateId] = {
270
+ STATE_CHANGED_PIECES[updateId] = {
258
271
  storageTypes,
259
272
  readyStorageTypes: {},
260
273
  changes: {},
@@ -284,27 +297,51 @@ async function setValues(
284
297
  }
285
298
 
286
299
  export async function resetState(namespace: INamespace, keys?: string[]) {
300
+ return setState(namespace, getDefaultValues(namespace, keys));
301
+ }
302
+
303
+ function getDefaultValues(namespace: INamespace, keys?: string[]) {
287
304
  const namespaceState = getNamespaceState(namespace);
288
305
 
289
- await setState(
290
- namespace,
291
- map(
292
- keys
293
- ? filter(namespaceState, (k, { key }) => keys.includes(key!))
294
- : namespaceState,
295
- (k, { key, defaultValue }) => [key, defaultValue],
296
- ) as Record<string, any>,
297
- );
306
+ return map(
307
+ keys
308
+ ? filter(namespaceState, (k, { key }) => keys.includes(key!))
309
+ : namespaceState,
310
+ (k, { key, defaultValue }) => [key, defaultValue],
311
+ ) as Record<string, any>;
312
+ }
298
313
 
299
- return createStore(namespace());
314
+ export function createPendingChanges(namespace: INamespace) {
315
+ const flush = () => {
316
+ const changes = STATE_PENDING_CHANGES[namespace()];
317
+ STATE_PENDING_CHANGES[namespace()] = {};
318
+ return changes;
319
+ };
320
+
321
+ return {
322
+ add: (changes: Record<string, any>) =>
323
+ Object.assign(STATE_PENDING_CHANGES[namespace()], changes),
324
+ reset: (keys: string[]) =>
325
+ Object.assign(
326
+ STATE_PENDING_CHANGES[namespace()],
327
+ getDefaultValues(namespace, keys),
328
+ ),
329
+ get: () => STATE_PENDING_CHANGES[namespace()],
330
+ flush,
331
+ commit: () => setState(namespace, flush()),
332
+ };
300
333
  }
301
334
 
302
- function main(namespace: INamespace): any {
335
+ function main(namespace?: INamespace): any {
303
336
  if (!arguments[1] || isString(arguments[1])) {
304
337
  return getState.apply(null, arguments as unknown as [INamespace, string]);
305
338
  }
306
339
 
307
- if (isArray(arguments[1])) {
340
+ if (
341
+ isArray(arguments[1]) ||
342
+ isFunction(arguments[1]) ||
343
+ isAsyncFunction(arguments[1])
344
+ ) {
308
345
  return addStateListener.apply(
309
346
  null,
310
347
  arguments as unknown as [INamespace, string[], () => {}],
@@ -327,21 +364,29 @@ function addNamespace(namespace: string, str: string) {
327
364
  return `${namespace}${(isString(str) && NAMESPACE_DELIMITER) || ""}${str || ""}`;
328
365
  }
329
366
 
330
- export function createStore(_namespace: string) {
367
+ export function createStore(_namespace: string): IVarstor {
331
368
  const namespace = ((key: string) =>
332
369
  addNamespace(_namespace, key)) as INamespace;
333
370
 
371
+ if (!STATE_PENDING_CHANGES[namespace()]) {
372
+ STATE_PENDING_CHANGES[namespace()] = {};
373
+ }
374
+
375
+ if (!LISTENERS[namespace()]) {
376
+ LISTENERS[namespace()] = [];
377
+ }
378
+
334
379
  return Object.assign(main.bind(null, namespace), {
335
380
  add: (state: IStateDefault) => addState(namespace, state, false),
336
381
  addPersistent: (state: IStateDefault) => addState(namespace, state, true),
337
- get: (newNamespace: string) => getState(namespace, newNamespace),
338
- set: async (changes: Record<string, unknown>) =>
339
- await setState(namespace, changes),
382
+ get: (newNamespace?: string) => getState(namespace, newNamespace!),
383
+ set: (changes: Record<string, unknown>) => setState(namespace, changes),
340
384
  reset: (keys: string[]) => resetState(namespace, keys),
341
- onChange: (keys: string[], cb: () => {}) =>
342
- addStateListener(namespace, keys, cb),
343
- removeListener: (keys: string[], cb: () => {}) =>
344
- removeStateListener(namespace, keys, cb),
385
+ changes: createPendingChanges(namespace),
386
+ onChange: (keys: string[] | IStateListener, cb?: IStateListener) =>
387
+ addStateListener(namespace, keys, cb!),
388
+ removeListener: (keys: string[] | IStateListener, cb?: IStateListener) =>
389
+ removeStateListener(namespace, keys, cb!),
345
390
  actions: (actions: IStateActions) => addStateActions(namespace, actions),
346
391
  setStorageUtils,
347
392
  joinStateChanges,
package/src/listeners.ts CHANGED
@@ -1,4 +1,12 @@
1
- import { STATE, getValues, createStore } from ".";
1
+ import {
2
+ type INamespace,
3
+ type IStateListeners,
4
+ type IStateChanges,
5
+ type IStateListener,
6
+ type IValue,
7
+ } from "./types";
8
+
9
+ import { STATE, createStore } from ".";
2
10
  import { NAMESPACE_DELIMITER } from "./constants";
3
11
  import { map, isFunction, isAsyncFunction } from "./helpers";
4
12
 
@@ -6,14 +14,13 @@ export const LISTENERS = {} as IStateListeners;
6
14
 
7
15
  export async function runStateChangeListeners(realChanges: IStateChanges) {
8
16
  if (Object.keys(realChanges).length) {
9
- const { namespace } =
10
- STATE[Object.keys(realChanges)[0] as keyof typeof STATE];
11
- const stateValues = getValues(namespace);
12
-
13
- for (let [changeKey, change] of Object.entries(realChanges)) {
17
+ const { namespace } = STATE[
18
+ Object.keys(realChanges)[0] as keyof typeof STATE
19
+ ] as IValue;
20
+ for (const [changeKey] of Object.entries(realChanges)) {
14
21
  const { listeners, key } = STATE[changeKey];
15
22
  for (const cb of listeners!) {
16
- const fn = cb.bind(null, [key], stateValues, change);
23
+ const fn = cb.bind(null, [key!], createStore(namespace()));
17
24
  if (isAsyncFunction(cb)) {
18
25
  await fn();
19
26
  } else {
@@ -28,15 +35,7 @@ export async function runStateChangeListeners(realChanges: IStateChanges) {
28
35
  ) as string[];
29
36
 
30
37
  for (const cb of LISTENERS[namespace()]) {
31
- const fn = cb.bind(
32
- null,
33
- readableKeys,
34
- stateValues,
35
- map(realChanges, (k, v) => [
36
- k.slice(namespaceLength),
37
- v,
38
- ]) as IStateChanges,
39
- );
38
+ const fn = cb.bind(null, readableKeys, createStore(namespace()));
40
39
  if (isAsyncFunction(cb)) {
41
40
  await fn();
42
41
  } else {
@@ -49,7 +48,7 @@ export async function runStateChangeListeners(realChanges: IStateChanges) {
49
48
  export function addStateListener(
50
49
  namespace: INamespace,
51
50
  observables: string[] | IStateListener,
52
- cb: () => {},
51
+ cb: IStateListener,
53
52
  ) {
54
53
  if (isFunction(observables) || isAsyncFunction(observables)) {
55
54
  LISTENERS[namespace()].push(observables as IStateListener);
@@ -66,7 +65,7 @@ export function addStateListener(
66
65
  export function removeStateListener(
67
66
  namespace: INamespace,
68
67
  observables: string[] | IStateListener,
69
- removeCb: () => {},
68
+ removeCb: IStateListener,
70
69
  ) {
71
70
  if (isFunction(observables) || isAsyncFunction(observables)) {
72
71
  const removeIdx = LISTENERS[namespace()].findIndex(
@@ -78,8 +77,8 @@ export function removeStateListener(
78
77
 
79
78
  (observables as string[]).forEach((key) => {
80
79
  const listeners = STATE[namespace(key)].listeners;
81
- const removeIdx = listeners?.findIndex((cb) => cb === removeCb) as number;
82
- listeners?.splice(removeIdx, 1);
80
+ const removeIdx = listeners?.findIndex((cb) => cb === removeCb);
81
+ listeners?.splice(removeIdx!, 1);
83
82
  });
84
83
 
85
84
  return createStore(namespace());
package/src/storage.ts CHANGED
@@ -1,3 +1,5 @@
1
+ import { type IStateDefault } from "./types";
2
+
1
3
  async function updateFromLocalStorage(state: IStateDefault) {
2
4
  const stored = {} as IStateDefault;
3
5
  for (const key in state) {
@@ -29,7 +31,7 @@ async function setStorageValue(
29
31
  return false;
30
32
  }
31
33
 
32
- function removeStorageKey (type: string, key: string) {
34
+ function removeStorageKey(type: string, key: string) {
33
35
  if (type) {
34
36
  localStorage.removeItem(key);
35
37
  }
package/src/types.d.ts CHANGED
@@ -11,7 +11,7 @@ type IValue = {
11
11
  dependencies?: string[];
12
12
  dependants?: string[];
13
13
  storageType?: string;
14
- listeners?: any[];
14
+ listeners?: IStateListener[];
15
15
  defaultValue?: any;
16
16
  namespace: INamespace;
17
17
  };
@@ -32,11 +32,7 @@ type IStorageFunctions = {
32
32
  REMOVE_KEY: (type: string, key: string) => void;
33
33
  };
34
34
 
35
- type IStateListener = (
36
- changes: string[],
37
- values: Record<string, any>,
38
- data: IStateChanges,
39
- ) => any;
35
+ type IStateListener = (changes: string[], store: IStore) => void;
40
36
 
41
37
  type IStateListeners = Record<string, IStateListener[]>;
42
38
 
@@ -44,8 +40,39 @@ type IStateAction = (mutator: IStateMutator, args: any[]) => void;
44
40
 
45
41
  type IStateActions = Record<string, IStateAction>;
46
42
 
47
- type IStateUpdatePieces = Record<string, {
48
- storageTypes: Record<string, boolean>;
49
- readyStorageTypes: Record<string, boolean>;
50
- changes: IStateChanges;
51
- }>;
43
+ type IStateUpdatePieces = Record<
44
+ string,
45
+ {
46
+ storageTypes: Record<string, boolean>;
47
+ readyStorageTypes: Record<string, boolean>;
48
+ changes: IStateChanges;
49
+ }
50
+ >;
51
+
52
+ type IStatePendingChanges = Record<string, Record<string, any>>;
53
+
54
+ type IStatePendingChangesFunctions = {
55
+ add: (changes: Record<string, any>) => Record<string, any>;
56
+ reset: (keys: string[]) => Record<string, any>;
57
+ get: () => Record<string, any>;
58
+ flush: () => Record<string, any>;
59
+ commit: () => Promise<unknown>;
60
+ };
61
+
62
+ export type IVarstor = ((namespace?: INamespace) => any) & {
63
+ add: (state: IStateDefault) => Promise<IVarstor>;
64
+ addPersistent: (state: IStateDefault) => Promise<IVarstor>;
65
+ get: (newNamespace?: string) => IVarstor | Record<string, any>;
66
+ set: (changes: Record<string, unknown>) => Promise<IVarstor>;
67
+ reset: (keys: string[]) => Promise<IVarstor>;
68
+ changes: IStatePendingChangesFunctions;
69
+ onChange: (keys: string[] | IStateListener, cb?: IStateListener) => IVarstor;
70
+ removeListener: (
71
+ keys: string[] | IStateListener,
72
+ cb?: IStateListener,
73
+ ) => IVarstor;
74
+ actions: (actions: IStateActions) => IVarstor;
75
+ setStorageUtils: (storageUtils: IStorageFunctions) => void;
76
+ joinStateChanges: (changesPiece: IStateChanges) => Promise<unknown>;
77
+ namespace: INamespace;
78
+ };
@@ -1,5 +1,7 @@
1
1
  const browser = require("webextension-polyfill/dist/browser-polyfill.min");
2
2
 
3
+ import { type IStateDefault } from "./types";
4
+
3
5
  export default {
4
6
  GET_TYPE: getStorageType,
5
7
  IS_AVAILABE: isStorageAvailable,
package/webpack.config.js CHANGED
@@ -25,13 +25,17 @@ module.exports = (env) => {
25
25
  {
26
26
  test: /\.(ts|tsx)$/i,
27
27
  loader: "ts-loader",
28
- exclude: ["/node_modules/"],
28
+ exclude: /node_modules|\.d\.ts$/,
29
+ },
30
+ {
31
+ test: /\.d\.ts$/,
32
+ loader: "ignore-loader",
29
33
  },
30
34
  ],
31
35
  },
32
36
 
33
37
  resolve: {
34
- extensions: [".ts", ".js"],
38
+ extensions: [".ts", ".js", ".d.ts"],
35
39
  },
36
40
 
37
41
  devtool: false,