effector-storage 4.2.1 → 5.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (108) hide show
  1. package/README.md +87 -46
  2. package/async-storage/index.cjs +2 -0
  3. package/async-storage/index.cjs.d.ts +21 -0
  4. package/async-storage/index.cjs.map +1 -0
  5. package/async-storage/index.d.ts +21 -0
  6. package/async-storage/index.js +2 -0
  7. package/async-storage/index.js.flow +19 -0
  8. package/async-storage/index.js.map +1 -0
  9. package/{fp → async-storage}/package.json +0 -0
  10. package/index.cjs +1 -1
  11. package/index.cjs.d.ts +37 -17
  12. package/index.cjs.map +1 -1
  13. package/index.d.ts +37 -17
  14. package/index.js +1 -1
  15. package/index.js.flow +31 -17
  16. package/index.js.map +1 -1
  17. package/local/index.cjs +1 -1
  18. package/local/index.cjs.d.ts +76 -21
  19. package/local/index.cjs.map +1 -1
  20. package/local/index.d.ts +76 -21
  21. package/local/index.js +1 -1
  22. package/local/index.js.flow +84 -21
  23. package/local/index.js.map +1 -1
  24. package/memory/index.cjs +1 -1
  25. package/memory/index.cjs.d.ts +68 -18
  26. package/memory/index.cjs.map +1 -1
  27. package/memory/index.d.ts +68 -18
  28. package/memory/index.js +1 -1
  29. package/memory/index.js.flow +81 -18
  30. package/memory/index.js.map +1 -1
  31. package/nil/index.cjs +1 -1
  32. package/nil/index.cjs.d.ts +1 -1
  33. package/nil/index.cjs.map +1 -1
  34. package/nil/index.d.ts +1 -1
  35. package/nil/index.js +1 -1
  36. package/nil/index.js.flow +2 -2
  37. package/nil/index.js.map +1 -1
  38. package/package.json +21 -27
  39. package/query/index.cjs +1 -1
  40. package/query/index.cjs.d.ts +77 -25
  41. package/query/index.cjs.map +1 -1
  42. package/query/index.d.ts +77 -25
  43. package/query/index.js +1 -1
  44. package/query/index.js.flow +87 -27
  45. package/query/index.js.map +1 -1
  46. package/rn/async/index.cjs +2 -0
  47. package/rn/async/index.cjs.d.ts +89 -0
  48. package/rn/async/index.cjs.map +1 -0
  49. package/rn/async/index.d.ts +89 -0
  50. package/rn/async/index.js +2 -0
  51. package/rn/async/index.js.flow +98 -0
  52. package/rn/async/index.js.map +1 -0
  53. package/{local/fp → rn/async}/package.json +0 -0
  54. package/rn/encrypted/index.cjs +2 -0
  55. package/rn/encrypted/index.cjs.d.ts +89 -0
  56. package/rn/encrypted/index.cjs.map +1 -0
  57. package/rn/encrypted/index.d.ts +89 -0
  58. package/rn/encrypted/index.js +2 -0
  59. package/rn/encrypted/index.js.flow +98 -0
  60. package/rn/encrypted/index.js.map +1 -0
  61. package/{memory/fp → rn/encrypted}/package.json +0 -0
  62. package/session/index.cjs +1 -1
  63. package/session/index.cjs.d.ts +76 -21
  64. package/session/index.cjs.map +1 -1
  65. package/session/index.d.ts +76 -21
  66. package/session/index.js +1 -1
  67. package/session/index.js.flow +84 -21
  68. package/session/index.js.map +1 -1
  69. package/storage/index.cjs.map +1 -1
  70. package/storage/index.js.flow +1 -1
  71. package/storage/index.js.map +1 -1
  72. package/fp/index.cjs +0 -2
  73. package/fp/index.cjs.d.ts +0 -19
  74. package/fp/index.cjs.map +0 -1
  75. package/fp/index.d.ts +0 -19
  76. package/fp/index.js +0 -2
  77. package/fp/index.js.flow +0 -21
  78. package/fp/index.js.map +0 -1
  79. package/local/fp/index.cjs +0 -2
  80. package/local/fp/index.cjs.d.ts +0 -39
  81. package/local/fp/index.cjs.map +0 -1
  82. package/local/fp/index.d.ts +0 -39
  83. package/local/fp/index.js +0 -2
  84. package/local/fp/index.js.flow +0 -50
  85. package/local/fp/index.js.map +0 -1
  86. package/memory/fp/index.cjs +0 -2
  87. package/memory/fp/index.cjs.d.ts +0 -36
  88. package/memory/fp/index.cjs.map +0 -1
  89. package/memory/fp/index.d.ts +0 -36
  90. package/memory/fp/index.js +0 -2
  91. package/memory/fp/index.js.flow +0 -47
  92. package/memory/fp/index.js.map +0 -1
  93. package/query/fp/index.cjs +0 -2
  94. package/query/fp/index.cjs.d.ts +0 -45
  95. package/query/fp/index.cjs.map +0 -1
  96. package/query/fp/index.d.ts +0 -45
  97. package/query/fp/index.js +0 -2
  98. package/query/fp/index.js.flow +0 -60
  99. package/query/fp/index.js.map +0 -1
  100. package/query/fp/package.json +0 -7
  101. package/session/fp/index.cjs +0 -2
  102. package/session/fp/index.cjs.d.ts +0 -39
  103. package/session/fp/index.cjs.map +0 -1
  104. package/session/fp/index.d.ts +0 -39
  105. package/session/fp/index.js +0 -2
  106. package/session/fp/index.js.flow +0 -50
  107. package/session/fp/index.js.map +0 -1
  108. package/session/fp/package.json +0 -7
package/README.md CHANGED
@@ -17,12 +17,17 @@ Small module for [Effector](https://github.com/effector/effector) ☄️ to sync
17
17
  - [with `localStorage`](#with-localstorage)
18
18
  - [with `sessionStorage`](#with-sessionstorage)
19
19
  - [with query string](#with-query-string)
20
+ - [with React Native AsyncStorage](#with-react-native-asyncstorage)
21
+ - [with React Native EncryptedStorage](#with-react-native-encryptedstorage)
20
22
  - [Usage with domains](#usage-with-domains)
21
23
  - [Functional helpers](#functional-helpers)
22
24
  - [Formulae](#formulae)
23
25
  - [Units](#units)
24
26
  - [Options](#options)
25
27
  - [Returns](#returns)
28
+ - [`createPersist` factory](#createpersist-factory)
29
+ - [Options](#options-1)
30
+ - [Returns](#returns-1)
26
31
  - [Advanced usage](#advanced-usage)
27
32
  - [Storage adapters](#storage-adapters)
28
33
  - [Synchronous storage adapter example](#synchronous-storage-adapter-example)
@@ -40,13 +45,16 @@ Small module for [Effector](https://github.com/effector/effector) ☄️ to sync
40
45
 
41
46
  ## Install
42
47
 
48
+ Depending on your package manager
49
+
43
50
  ```bash
44
- $ yarn add effector-storage
45
- ```
51
+ # using `pnpm`
52
+ $ pnpm add effector-storage
46
53
 
47
- Or using `npm`
54
+ # using `yarn`
55
+ $ yarn add effector-storage
48
56
 
49
- ```bash
57
+ # using `npm` ↓
50
58
  $ npm install --save effector-storage
51
59
  ```
52
60
 
@@ -98,44 +106,53 @@ If two (or more) stores are persisted in query string with the same key — they
98
106
  ⚠️ **Note**<br>
99
107
  Use this only with plain string stores (`Store<string | null>`) to avoid strange unexpected behavior.
100
108
 
101
- ## Usage with domains
109
+ ### with React Native AsyncStorage
102
110
 
103
- You can use `persist` inside Domain's `onCreateStore` hook:
111
+ Docs: [effector-storage/rn/async](https://github.com/yumauri/effector-storage/tree/master/src/rn/async/README.md)
104
112
 
105
113
  ```javascript
106
- import { createDomain } from 'effector'
107
- import { persist } from 'effector-storage/local'
114
+ import { persist } from 'effector-storage/rn/async'
108
115
 
109
- const app = createDomain('app')
116
+ // persist store `$counter` with key 'counter'
117
+ persist({ store: $counter, key: 'counter' })
110
118
 
111
- // this hook will persist every store, created in domain,
112
- // in `localStorage`, using stores' names as keys
113
- app.onCreateStore((store) => persist({ store }))
119
+ // if your storage has a name, you can omit `key` field
120
+ persist({ store: $counter })
121
+ ```
114
122
 
115
- const $store = app.createStore(0, { name: 'store' })
123
+ ⚠️ Note, that [AsyncStorage] is asynchronous, hence the name.
124
+
125
+ ### with React Native EncryptedStorage
126
+
127
+ Docs: [effector-storage/rn/encrypted](https://github.com/yumauri/effector-storage/tree/master/src/rn/encrypted/README.md)
128
+
129
+ ```javascript
130
+ import { persist } from 'effector-storage/rn/encrypted'
131
+
132
+ // persist store `$counter` with key 'counter'
133
+ persist({ store: $counter, key: 'counter' })
134
+
135
+ // if your storage has a name, you can omit `key` field
136
+ persist({ store: $counter })
116
137
  ```
117
138
 
118
- ## Functional helpers
139
+ ⚠️ Note, that [EncryptedStorage] is asynchronous (it is based on [AsyncStorage] actually).
119
140
 
120
- There are special `persist` forms to use with functional programming style. You can use them, if you like, with Domain hook or `.thru()` store method:
141
+ ## Usage with domains
142
+
143
+ You can use `persist` inside Domain's `onCreateStore` hook:
121
144
 
122
145
  ```javascript
123
146
  import { createDomain } from 'effector'
124
- import { persist } from 'effector-storage/local/fp'
147
+ import { persist } from 'effector-storage/local'
125
148
 
126
149
  const app = createDomain('app')
127
150
 
128
151
  // this hook will persist every store, created in domain,
129
152
  // in `localStorage`, using stores' names as keys
130
- app.onCreateStore(persist())
153
+ app.onCreateStore((store) => persist({ store }))
131
154
 
132
155
  const $store = app.createStore(0, { name: 'store' })
133
-
134
- // or persist single store in `localStorage` via .thru
135
- const $counter = createStore(0)
136
- .on(increment, (state) => state + 1)
137
- .on(decrement, (state) => state - 1)
138
- .thru(persist({ key: 'counter' }))
139
156
  ```
140
157
 
141
158
  ## Formulae
@@ -147,12 +164,6 @@ import { persist } from 'effector-storage/<adapter>'
147
164
  - `persist({ store, ...options }): Subscription`
148
165
  - `persist({ source, target, ...options }): Subscription`
149
166
 
150
- ```javascript
151
- import { persist } from 'effector-storage/<adapter>/fp'
152
- ```
153
-
154
- - `persist({ ...options }?): (store: Store) => Store`
155
-
156
167
  ### Units
157
168
 
158
169
  In order to synchronize _something_, you need to specify effector units. Depending on a requirements, you may want to use `store` parameter, or `source` and `target` parameters:
@@ -164,21 +175,26 @@ In order to synchronize _something_, you need to specify effector units. Dependi
164
175
  ### Options
165
176
 
166
177
  - `key`? ([_string_]): Key for local/session storage, to store value in. If omitted — `store` name is used. **Note!** If `key` is not specified, `store` _must_ have a `name`! You can use `'effector/babel-plugin'` to have those names automatically.
167
- - `pickup`? ([_Event_] | [_Effect_] | [_Store_]): Unit, which you can specify to force update `store` value from storage.
178
+ - `keyPrefix`? ([_string_]): Prefix, used in adapter, to be concatenated to `key`. By default = `''`.
179
+ - `clock`? ([_Event_] | [_Effect_] | [_Store_]): Unit, if passed – then value from `store`/`source` will be stored in the storage only upon its trigger.
180
+ - `pickup`? ([_Event_] | [_Effect_] | [_Store_]): Unit, which you can specify to update `store` value from storage. **Note!** When you add `pickup`, `persist` _will not_ get initial value from storage automatically!
168
181
  - `done`? ([_Event_] | [_Effect_] | [_Store_]): Unit, which will be triggered on each successful read or write from/to storage.<br>
169
182
  Payload structure:
170
183
  - `key` ([_string_]): Same `key` as above.
184
+ - `keyPrefix` ([_string_]): Prefix, used in adapter, to be concatenated to `key`. By default = `''`.
171
185
  - `operation` (_`'set'`_ | _`'get'`_): Did error occurs during setting value to storage or getting value from storage.
172
186
  - `value` (_State_): Value set to `store` or got from `store`.
173
187
  - `fail`? ([_Event_] | [_Effect_] | [_Store_]): Unit, which will be triggered in case of any error (serialization/deserialization error, storage is full and so on). **Note!** If `fail` unit is not specified, any errors will be printed using `console.error(Error)`.<br>
174
188
  Payload structure:
175
189
  - `key` ([_string_]): Same `key` as above.
190
+ - `keyPrefix` ([_string_]): Prefix, used in adapter, to be concatenated to `key`. By default = `''`.
176
191
  - `operation` (_`'set'`_ | _`'get'`_): Did error occurs during setting value to storage or getting value from storage.
177
192
  - `error` ([_Error_]): Error instance
178
193
  - `value`? (_any_): In case of _'set'_ operation — value from `store`. In case of _'get'_ operation could contain raw value from storage or could be empty.
179
194
  - `finally`? ([_Event_] | [_Effect_] | [_Store_]): Unit, which will be triggered either in case of success or error.<br>
180
195
  Payload structure:
181
196
  - `key` ([_string_]): Same `key` as above.
197
+ - `keyPrefix` ([_string_]): Prefix, used in adapter, to be concatenated to `key`. By default = `''`.
182
198
  - `operation` (_`'set'`_ | _`'get'`_): Operation stage.
183
199
  - `status` (_`'done'`_ | _`'fail'`_): Operation status.
184
200
  - `error`? ([_Error_]): Error instance, in case of error.
@@ -188,9 +204,36 @@ In order to synchronize _something_, you need to specify effector units. Dependi
188
204
 
189
205
  - ([_Subscription_]): You can use this subscription to remove store association with storage, if you don't need them to be synced anymore. It is a function.
190
206
 
191
- - `(store) => Store` ([_Function_]): Function, which accepts store to synchronize with storage, and returns:
192
- - ([_Store_]): Same given store.<br>
193
- _You cannot unsubscribe store from storage when using functional form of `persist`._
207
+ ## `createPersist` factory
208
+
209
+ In rare cases you might want to use `createPersist` factory. It allows you to specify some adapter options, like `keyPrefix`.
210
+
211
+ ```javascript
212
+ import { createPersist } from 'effector-storage/local'
213
+
214
+ const persist = createPersist({
215
+ keyPrefix: 'app/',
216
+ })
217
+
218
+ // ---8<---
219
+
220
+ persist({
221
+ store: $store1,
222
+ key: 'store1', // localStorage key will be `app/store1`
223
+ })
224
+ persist({
225
+ store: $store2,
226
+ key: 'store2', // localStorage key will be `app/store2`
227
+ })
228
+ ```
229
+
230
+ ### Options
231
+
232
+ - `keyPrefix`? ([_string_]): Key prefix for adapter. It will be concatenated with any `key`, given to returned `persist` function.
233
+
234
+ ### Returns
235
+
236
+ - Custom `persist` function, with predefined adapter options.
194
237
 
195
238
  ## Advanced usage
196
239
 
@@ -208,12 +251,6 @@ Core function `persist` accepts all **common** options, as `persist` functions f
208
251
 
209
252
  - `adapter` (_StorageAdapter_): Storage adapter to use.
210
253
 
211
- There is also _fp_ form too:
212
-
213
- ```javascript
214
- import { persist } from 'effector-storage/fp'
215
- ```
216
-
217
254
  ## Storage adapters
218
255
 
219
256
  Adapter is a function, which is called by the core `persist` function, and has following interface:
@@ -312,13 +349,13 @@ persist({ store, adapter }) // <- use adapter
312
349
 
313
350
  If your storage can be updated from _external source_, and doesn't have any events to react to, but you are able to know about it somehow.
314
351
 
315
- You can use optional `pickup` parameter to specify unit to trigger force update:
352
+ You can use optional `pickup` parameter to specify unit to trigger update (keep in mind, that when you add `pickup`, `persist` _will not_ get initial value from storage automatically):
316
353
 
317
354
  ```javascript
318
355
  import { createEvent, createStore, forward } from 'effector'
319
356
  import { persist } from 'effector-storage/session'
320
357
 
321
- // event, which will be used to trigger force update
358
+ // event, which will be used to trigger update
322
359
  const pickup = createEvent()
323
360
 
324
361
  const store = createStore('', { name: 'store' })
@@ -327,7 +364,7 @@ persist({ store, pickup }) // <- set `pickup` parameter
327
364
  // --8<--
328
365
 
329
366
  // when you are sure, that storage was updated,
330
- // and you need to force update `store` from storage with new value
367
+ // and you need to update `store` from storage with new value
331
368
  pickup()
332
369
  ```
333
370
 
@@ -406,7 +443,7 @@ adapter = storage(options)
406
443
  #### Options
407
444
 
408
445
  - `storage` (_Storage_): Storage to communicate with.
409
- - `sync`? ([_boolean_], **deprecated**): Add [`'storage'`] event listener or no. Default = `false`.
446
+ - `sync`? ([_boolean_]): Add [`'storage'`] event listener or no. Default = `false`.
410
447
  - `serialize`? (_(value: any) => string_): Custom serialize function. Default = `JSON.stringify`
411
448
  - `deserialize`? (_(value: string) => any_): Custom deserialize function. Default = `JSON.parse`
412
449
 
@@ -445,27 +482,31 @@ persist({
445
482
  ```
446
483
 
447
484
  ⚠️ **BIG WARNING!**<br>
448
- Use this approach with caution, beware of infinite circular updates. To avoid them, persist _only plain values_ in storage. So, mapped store in `source` will not trigger update, if object in original store has changed.
485
+ Use this approach with caution, beware of infinite circular updates. To avoid them, persist _only plain values_ in storage. So, mapped store in `source` will not trigger update, if object in original store has changed. Also, you can take a look at [`updateFilter` option](https://effector.dev/docs/api/effector/createStore).
449
486
 
450
487
  ## TODO
451
488
 
452
489
  - [x] [localStorage] support (docs: [effector-storage/local](https://github.com/yumauri/effector-storage/tree/master/src/local/README.md))
453
490
  - [x] [sessionStorage] support (docs: [effector-storage/session](https://github.com/yumauri/effector-storage/tree/master/src/session/README.md))
454
491
  - [x] [query string](https://developer.mozilla.org/en-US/docs/Web/API/Location/search) support (docs: [effector-storage/query](https://github.com/yumauri/effector-storage/tree/master/src/query/README.md))
492
+ - [x] [AsyncStorage] support (docs: [effector-storage/rn/async](https://github.com/yumauri/effector-storage/tree/master/src/rn/async/README.md))
493
+ - [x] [EncryptedStorage] support (docs: [effector-storage/rn/encrypted](https://github.com/yumauri/effector-storage/tree/master/src/rn/encrypted/README.md))
455
494
  - [ ] [IndexedDB] support
456
- - [ ] [AsyncStorage] support
457
495
  - [ ] [Cookies] support
458
496
  - [ ] you name it support
459
497
 
460
498
  ## Sponsored
461
499
 
462
- [<img src="https://setplex.com/img/logo.png" alt="Setplex" width="236">](https://setplex.com)
500
+ [<img src="https://setplex.com/img/logo.png" alt="Setplex OTT Platform" width="236">](https://setplex.com/en/)
501
+
502
+ [Setplex OTT Platform](https://setplex.com/en/)
463
503
 
464
504
  [localstorage]: https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage
465
505
  [sessionstorage]: https://developer.mozilla.org/en-US/docs/Web/API/Window/sessionStorage
466
506
  [`'storage'`]: https://developer.mozilla.org/en-US/docs/Web/API/StorageEvent
467
507
  [indexeddb]: https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API
468
508
  [asyncstorage]: https://react-native-async-storage.github.io/async-storage/
509
+ [encryptedstorage]: https://github.com/emeraldsanto/react-native-encrypted-storage
469
510
  [cookies]: https://developer.mozilla.org/en-US/docs/Web/API/Document/cookie
470
511
  [_subscription_]: https://effector.dev/docs/glossary#subscription
471
512
  [_effect_]: https://effector.dev/docs/api/effector/effect
@@ -0,0 +1,2 @@
1
+ "use strict";exports.asyncStorage=function({storage:e,serialize:t=JSON.stringify,deserialize:a=JSON.parse}){var r=r=>({async get(){var t=await e.getItem(r);return null===t?void 0:a(t)},async set(a){await e.setItem(r,t(a))}});return r.keyArea=e,r};
2
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1,21 @@
1
+ import { StorageAdapter } from '..'
2
+
3
+ interface AsyncStorage {
4
+ getItem: (key: string) => Promise<string | null>
5
+ setItem: (key: string, value: string) => Promise<void>
6
+ }
7
+ interface AsyncStorageConfig {
8
+ storage: AsyncStorage
9
+ serialize?: (value: any) => string
10
+ deserialize?: (value: string) => any
11
+ }
12
+ /**
13
+ * Generic `AsyncStorage` adapter factory
14
+ */
15
+ declare function asyncStorage({
16
+ storage,
17
+ serialize,
18
+ deserialize,
19
+ }: AsyncStorageConfig): StorageAdapter
20
+
21
+ export { AsyncStorage, AsyncStorageConfig, asyncStorage }
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","sources":["../../src/async-storage/index.ts"],"sourcesContent":["import type { StorageAdapter } from '..'\n\nexport interface AsyncStorage {\n getItem: (key: string) => Promise<string | null>\n setItem: (key: string, value: string) => Promise<void>\n}\n\nexport interface AsyncStorageConfig {\n storage: AsyncStorage\n serialize?: (value: any) => string\n deserialize?: (value: string) => any\n}\n\n/**\n * Generic `AsyncStorage` adapter factory\n */\nexport function asyncStorage({\n storage,\n serialize = JSON.stringify,\n deserialize = JSON.parse,\n}: AsyncStorageConfig): StorageAdapter {\n const adapter: StorageAdapter = <State>(key: string) => ({\n async get() {\n const item = await storage.getItem(key)\n return item === null ? undefined : deserialize(item)\n },\n\n async set(value: State) {\n await storage.setItem(key, serialize(value))\n },\n })\n\n adapter.keyArea = storage\n return adapter\n}\n"],"names":["storage","serialize","JSON","stringify","deserialize","parse","adapter","key","item","getItem","undefined","value","setItem","keyArea"],"mappings":"kCAgBO,UAAsBA,QAC3BA,EAD2BC,UAE3BA,EAAYC,KAAKC,UAFUC,YAG3BA,EAAcF,KAAKG,YAEbC,EAAkCC,qBAE9BC,QAAaR,EAAQS,QAAQF,UACnB,OAATC,OAAgBE,EAAYN,EAAYI,cAGvCG,SACFX,EAAQY,QAAQL,EAAKN,EAAUU,cAIzCL,EAAQO,QAAUb,EACXM"}
@@ -0,0 +1,21 @@
1
+ import { StorageAdapter } from '..'
2
+
3
+ interface AsyncStorage {
4
+ getItem: (key: string) => Promise<string | null>
5
+ setItem: (key: string, value: string) => Promise<void>
6
+ }
7
+ interface AsyncStorageConfig {
8
+ storage: AsyncStorage
9
+ serialize?: (value: any) => string
10
+ deserialize?: (value: string) => any
11
+ }
12
+ /**
13
+ * Generic `AsyncStorage` adapter factory
14
+ */
15
+ declare function asyncStorage({
16
+ storage,
17
+ serialize,
18
+ deserialize,
19
+ }: AsyncStorageConfig): StorageAdapter
20
+
21
+ export { AsyncStorage, AsyncStorageConfig, asyncStorage }
@@ -0,0 +1,2 @@
1
+ function e({storage:e,serialize:t=JSON.stringify,deserialize:a=JSON.parse}){var r=r=>({async get(){var t=await e.getItem(r);return null===t?void 0:a(t)},async set(a){await e.setItem(r,t(a))}});return r.keyArea=e,r}export{e as asyncStorage};
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Flowtype definitions for index
3
+ * Generated by Flowgen from a Typescript Definition
4
+ * Flowgen v1.16.2
5
+ * @flow
6
+ */
7
+
8
+ import { StorageAdapter } from '..'
9
+ declare interface AsyncStorage {
10
+ getItem: (key: string) => Promise<string | null>;
11
+ setItem: (key: string, value: string) => Promise<void>;
12
+ }
13
+ declare interface AsyncStorageConfig {
14
+ storage: AsyncStorage;
15
+ serialize?: (value: any) => string;
16
+ deserialize?: (value: string) => any;
17
+ }
18
+ declare function asyncStorage(x: AsyncStorageConfig): StorageAdapter
19
+ declare export { AsyncStorage, AsyncStorageConfig, asyncStorage }
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":["../../src/async-storage/index.ts"],"sourcesContent":["import type { StorageAdapter } from '..'\n\nexport interface AsyncStorage {\n getItem: (key: string) => Promise<string | null>\n setItem: (key: string, value: string) => Promise<void>\n}\n\nexport interface AsyncStorageConfig {\n storage: AsyncStorage\n serialize?: (value: any) => string\n deserialize?: (value: string) => any\n}\n\n/**\n * Generic `AsyncStorage` adapter factory\n */\nexport function asyncStorage({\n storage,\n serialize = JSON.stringify,\n deserialize = JSON.parse,\n}: AsyncStorageConfig): StorageAdapter {\n const adapter: StorageAdapter = <State>(key: string) => ({\n async get() {\n const item = await storage.getItem(key)\n return item === null ? undefined : deserialize(item)\n },\n\n async set(value: State) {\n await storage.setItem(key, serialize(value))\n },\n })\n\n adapter.keyArea = storage\n return adapter\n}\n"],"names":["asyncStorage","storage","serialize","JSON","stringify","deserialize","parse","adapter","key","item","getItem","undefined","value","setItem","keyArea"],"mappings":"AAgBO,SAASA,GAAaC,QAC3BA,EAD2BC,UAE3BA,EAAYC,KAAKC,UAFUC,YAG3BA,EAAcF,KAAKG,YAEbC,EAAkCC,qBAE9BC,QAAaR,EAAQS,QAAQF,UACnB,OAATC,OAAgBE,EAAYN,EAAYI,cAGvCG,SACFX,EAAQY,QAAQL,EAAKN,EAAUU,cAIzCL,EAAQO,QAAUb,EACXM"}
File without changes
package/index.cjs CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";var r=require("effector"),e=new Map,o=r.createEvent();o.watch((r=>console.error(r.error))),exports.persist=function({adapter:t,store:a,source:i=a,target:f=a,done:n,fail:s=o,finally:d,pickup:u,key:p}){if(!t)throw Error("Adapter is not defined");if(!i)throw Error("Store or source is not defined");if(!f)throw Error("Target is not defined");if(!p&&i.shortName===i.id)throw Error("Key or name is not defined");if(i===f&&!r.is.store(i))throw Error("Source must be different from target");var l=p||i.shortName,c=function(o,t){var a=e.get(o);void 0===a&&(a=new Map,e.set(o,a));var i=a.get(t);return void 0!==i||(i=r.createStore(null),a.set(t,i)),i}(t.keyArea||t,l),v=r.createNode(),m=()=>r.clearNode(v),w=r=>({status:e,params:o,result:t,error:a})=>"done"===e?{status:e,key:l,operation:r,value:t}:{status:e,key:l,operation:r,value:o,error:a};return r.withRegion(v,(()=>{var e=r.createEffect(),o=r.createEffect(),a=r.createEvent(),p=a.filterMap((({status:r,key:e,operation:o,value:t})=>"done"===r?{key:e,operation:o,value:t}:void 0)),v=a.filterMap((({status:r,key:e,operation:o,error:t,value:a})=>"fail"===r?{key:e,operation:o,error:t,value:a}:void 0)),m=t(l,e);e.use(m.get),o.use(m.set),r.guard({source:r.sample(c,i,((r,e)=>[e,r])),filter:([r,e])=>r!==e,target:o.prepend((([r])=>r))}),r.forward({from:[e.doneData,o],to:c}),r.forward({from:[e.doneData,c],to:f}),r.forward({from:[e.finally.map(w("get")),o.finally.map(w("set"))],to:a}),r.forward({from:v,to:s}),n&&r.forward({from:p,to:n}),d&&r.forward({from:a,to:d}),u&&r.forward({from:u,to:e.prepend((()=>{}))}),e()})),m.unsubscribe=m};
1
+ "use strict";var e=require("effector"),r=new Map,t=e.createEvent();function o(o){return a=>function({adapter:o,clock:a,store:i,source:f=i,target:s=i,done:n,fail:d=t,finally:u,pickup:p,key:c,keyPrefix:l=""}){if(!o)throw Error("Adapter is not defined");if(!f)throw Error("Store or source is not defined");if(!s)throw Error("Target is not defined");if(!c&&f.shortName===f.id)throw Error("Key or name is not defined");if(f===s&&!e.is.store(f))throw Error("Source must be different from target");var y=c||f.shortName,v=function(t,o){var a=r.get(t);void 0===a&&(a=new Map,r.set(t,a));var i=a.get(o);return void 0!==i||(i=e.createStore(null),a.set(o,i)),i}(o.keyArea||o,l+y),k=e.createNode(),m=()=>e.clearNode(k),w=e=>({status:r,params:t,result:o,error:a})=>"done"===r?{status:r,key:y,keyPrefix:l,operation:e,value:"get"===e?o:t}:{status:r,key:y,keyPrefix:l,operation:e,value:t,error:a};return e.withRegion(k,(()=>{var r=e.createEffect(),t=e.createEffect(),i=e.createEvent(),c=i.filterMap((({status:e,key:r,keyPrefix:t,operation:o,value:a})=>"done"===e?{key:r,keyPrefix:t,operation:o,value:a}:void 0)),k=i.filterMap((({status:e,key:r,keyPrefix:t,operation:o,error:a,value:i})=>"fail"===e?{key:r,keyPrefix:t,operation:o,error:a,value:i}:void 0)),m=o(l+y,r);r.use(m.get),t.use(m.set),e.guard({source:e.sample(v,e.sample(f,a),((e,r)=>[r,e])),filter:([e,r])=>e!==r,target:t.prepend((([e])=>e))}),e.forward({from:[r.doneData,t],to:v}),e.forward({from:[r.doneData,v],to:s}),e.forward({from:[r.finally.map(w("get")),t.finally.map(w("set"))],to:i}),e.forward({from:k,to:d}),n&&e.forward({from:c,to:n}),u&&e.forward({from:i,to:u}),p?e.forward({from:p,to:r.prepend((()=>{}))}):r()})),m.unsubscribe=m}({...o,...a})}t.watch((e=>console.error(e.error)));var a=o();exports.createPersist=o,exports.persist=a;
2
2
  //# sourceMappingURL=index.cjs.map
package/index.cjs.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Store, Unit, Event, Effect, Subscription } from 'effector'
1
+ import { Subscription, Unit, Store, Event, Effect } from 'effector'
2
2
 
3
3
  interface StorageAdapter {
4
4
  <State>(key: string, update: (raw?: any) => any): {
@@ -9,11 +9,13 @@ interface StorageAdapter {
9
9
  }
10
10
  declare type Done<State> = {
11
11
  key: string
12
+ keyPrefix: string
12
13
  operation: 'set' | 'get'
13
14
  value: State
14
15
  }
15
16
  declare type Fail<Err> = {
16
17
  key: string
18
+ keyPrefix: string
17
19
  operation: 'set' | 'get'
18
20
  error: Err
19
21
  value?: any
@@ -25,41 +27,59 @@ declare type Finally<State, Err> =
25
27
  | (Fail<Err> & {
26
28
  status: 'fail'
27
29
  })
28
- interface ConfigStore<State, Err = Error> {
30
+ interface ConfigPersist {
31
+ keyPrefix?: string
32
+ }
33
+ interface ConfigAdapter {
29
34
  adapter: StorageAdapter
30
- store: Store<State>
35
+ }
36
+ interface ConfigCommon<State, Err = Error> {
37
+ clock?: Unit<any>
31
38
  done?: Unit<Done<State>>
32
39
  fail?: Unit<Fail<Err>>
33
40
  finally?: Unit<Finally<State, Err>>
34
41
  pickup?: Unit<any>
35
42
  key?: string
43
+ keyPrefix?: string
36
44
  }
37
- interface ConfigSourceTarget<State, Err = Error> {
38
- adapter: StorageAdapter
45
+ interface ConfigJustStore<State> {
46
+ store: Store<State>
47
+ }
48
+ interface ConfigJustSourceTarget<State> {
39
49
  source: Store<State> | Event<State> | Effect<State, any, any>
40
50
  target: Store<State> | Event<State> | Effect<State, any, any>
41
- done?: Unit<Done<State>>
42
- fail?: Unit<Fail<Err>>
43
- finally?: Unit<Finally<State, Err>>
44
- pickup?: Unit<any>
45
- key?: string
46
51
  }
52
+ interface ConfigStore<State, Err = Error>
53
+ extends ConfigAdapter,
54
+ ConfigCommon<State, Err>,
55
+ ConfigJustStore<State> {}
56
+ interface ConfigSourceTarget<State, Err = Error>
57
+ extends ConfigAdapter,
58
+ ConfigCommon<State, Err>,
59
+ ConfigJustSourceTarget<State> {}
60
+ interface Persist {
61
+ <State, Err = Error>(config: ConfigSourceTarget<State, Err>): Subscription
62
+ <State, Err = Error>(config: ConfigStore<State, Err>): Subscription
63
+ }
64
+
65
+ /**
66
+ * Creates custom `persist`
67
+ */
68
+ declare function createPersist(defaults?: ConfigPersist): Persist
47
69
  /**
48
- * Main root `persist` function
70
+ * Default `persist`
49
71
  */
50
- declare function persist<State, Err = Error>(
51
- config: ConfigStore<State, Err>
52
- ): Subscription
53
- declare function persist<State, Err = Error>(
54
- config: ConfigSourceTarget<State, Err>
55
- ): Subscription
72
+ declare const persist: Persist
56
73
 
57
74
  export {
75
+ ConfigPersist,
58
76
  ConfigSourceTarget,
59
77
  ConfigStore,
60
78
  Done,
61
79
  Fail,
62
80
  Finally,
81
+ Persist,
63
82
  StorageAdapter,
83
+ createPersist,
64
84
  persist,
65
85
  }
package/index.cjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sources":["../src/index.ts"],"sourcesContent":["import type { Event, Effect, Store, Unit, Subscription } from 'effector'\nimport {\n clearNode,\n createEffect,\n createEvent,\n createNode,\n createStore,\n forward,\n guard,\n is,\n sample,\n withRegion,\n} from 'effector'\n\nexport interface StorageAdapter {\n <State>(key: string, update: (raw?: any) => any): {\n set(value: State): void\n get(value?: any): State | Promise<State>\n }\n keyArea?: any\n}\n\nexport type Done<State> = {\n key: string\n operation: 'set' | 'get'\n value: State\n}\n\nexport type Fail<Err> = {\n key: string\n operation: 'set' | 'get'\n error: Err\n value?: any\n}\n\nexport type Finally<State, Err> =\n | (Done<State> & { status: 'done' })\n | (Fail<Err> & { status: 'fail' })\n\nexport interface ConfigStore<State, Err = Error> {\n adapter: StorageAdapter\n store: Store<State>\n done?: Unit<Done<State>>\n fail?: Unit<Fail<Err>>\n finally?: Unit<Finally<State, Err>>\n pickup?: Unit<any>\n key?: string\n}\n\nexport interface ConfigSourceTarget<State, Err = Error> {\n adapter: StorageAdapter\n source: Store<State> | Event<State> | Effect<State, any, any>\n target: Store<State> | Event<State> | Effect<State, any, any>\n done?: Unit<Done<State>>\n fail?: Unit<Fail<Err>>\n finally?: Unit<Finally<State, Err>>\n pickup?: Unit<any>\n key?: string\n}\n\n/**\n * Keys areas / namespaces cache\n */\nconst areas = new Map<any, Map<string, Store<any>>>()\n\n/**\n * Get store, responsible for the key in key area / namespace\n */\nfunction getAreaStorage<State>(keyArea: any, key: string): Store<State> {\n let area = areas.get(keyArea)\n if (area === undefined) {\n area = new Map()\n areas.set(keyArea, area)\n }\n\n let store = area.get(key)\n if (store !== undefined) {\n return store\n }\n\n store = createStore(null)\n area.set(key, store)\n\n return store\n}\n\n/**\n * Default sink for unhandled errors\n */\nconst sink = createEvent<Fail<any>>()\nsink.watch((payload) => console.error(payload.error))\n\n/**\n * Main root `persist` function\n */\nexport function persist<State, Err = Error>(\n config: ConfigStore<State, Err>\n): Subscription\nexport function persist<State, Err = Error>(\n config: ConfigSourceTarget<State, Err>\n): Subscription\nexport function persist<State, Err = Error>({\n adapter,\n store,\n source = store,\n target = store,\n done,\n fail = sink,\n finally: anyway,\n pickup,\n key: keyName,\n}: Partial<\n ConfigStore<State, Err> & ConfigSourceTarget<State, Err>\n>): Subscription {\n if (!adapter) {\n throw Error('Adapter is not defined')\n }\n if (!source) {\n throw Error('Store or source is not defined')\n }\n if (!target) {\n throw Error('Target is not defined')\n }\n if (!keyName && source.shortName === (source as any).id) {\n throw Error('Key or name is not defined')\n }\n if (source === target && !is.store(source)) {\n throw Error('Source must be different from target')\n }\n\n const key = keyName || source.shortName\n const storage = getAreaStorage<State>(adapter.keyArea || adapter, key)\n const region = createNode()\n const desist = () => clearNode(region)\n\n const op =\n (operation: 'get' | 'set') =>\n ({ status, params, result, error }: any): any =>\n status === 'done'\n ? { status, key, operation, value: result }\n : { status, key, operation, value: params, error }\n\n // create all auxiliary units and nodes within the region,\n // to be able to remove them all at once on unsubscription\n withRegion(region, () => {\n const getFx = createEffect<void, State, Err>()\n const setFx = createEffect<State, void, Err>()\n\n const localAnyway = createEvent<Finally<State, Err>>()\n const localDone = localAnyway.filterMap<Done<State>>(\n ({ status, key, operation, value }) =>\n status === 'done' ? { key, operation, value } : undefined\n )\n const localFail = localAnyway.filterMap<Fail<Err>>(\n ({ status, key, operation, error, value }: any) =>\n status === 'fail' ? { key, operation, error, value } : undefined\n )\n\n const value = adapter<State>(key, getFx)\n getFx.use(value.get)\n setFx.use(value.set)\n\n guard({\n source: sample<State, State, [State, State]>(\n storage,\n source,\n (current: any, proposed) => [proposed, current]\n ),\n filter: ([proposed, current]) => proposed !== current,\n target: setFx.prepend<[State, State]>(([proposed]) => proposed),\n })\n forward({ from: [getFx.doneData, setFx], to: storage })\n forward({ from: [getFx.doneData, storage], to: target })\n forward({\n from: [getFx.finally.map(op('get')), setFx.finally.map(op('set'))],\n to: localAnyway,\n })\n\n forward({ from: localFail, to: fail })\n done && forward({ from: localDone, to: done })\n anyway && forward({ from: localAnyway, to: anyway })\n\n pickup && forward({ from: pickup, to: getFx.prepend(() => undefined) })\n\n // kick getter to pick up initial value from storage\n getFx()\n })\n\n return (desist.unsubscribe = desist)\n}\n"],"names":["areas","Map","sink","createEvent","watch","payload","console","error","adapter","store","source","target","done","fail","finally","anyway","pickup","key","keyName","Error","shortName","id","is","storage","keyArea","area","get","undefined","set","createStore","getAreaStorage","region","createNode","desist","clearNode","op","operation","status","params","result","value","withRegion","getFx","createEffect","setFx","localAnyway","localDone","filterMap","localFail","use","guard","sample","current","proposed","filter","prepend","forward","from","doneData","to","map","unsubscribe"],"mappings":"uCA+DMA,EAAQ,IAAIC,IA0BZC,EAAOC,gBACbD,EAAKE,OAAOC,GAAYC,QAAQC,MAAMF,EAAQE,yBAWvC,UAAqCC,QAC1CA,EAD0CC,MAE1CA,EAF0CC,OAG1CA,EAASD,EAHiCE,OAI1CA,EAASF,EAJiCG,KAK1CA,EAL0CC,KAM1CA,EAAOX,EACPY,QAASC,EAPiCC,OAQ1CA,EACAC,IAAKC,QAIAV,QACGW,MAAM,8BAETT,QACGS,MAAM,sCAETR,QACGQ,MAAM,6BAETD,GAAWR,EAAOU,YAAeV,EAAeW,SAC7CF,MAAM,iCAEVT,IAAWC,IAAWW,KAAGb,MAAMC,SAC3BS,MAAM,4CAGRF,EAAMC,GAAWR,EAAOU,UACxBG,EA/DR,SAA+BC,EAAcP,OACvCQ,EAAOzB,EAAM0B,IAAIF,QACRG,IAATF,IACFA,EAAO,IAAIxB,IACXD,EAAM4B,IAAIJ,EAASC,QAGjBhB,EAAQgB,EAAKC,IAAIT,eACPU,IAAVlB,IAIJA,EAAQoB,cAAY,MACpBJ,EAAKG,IAAIX,EAAKR,IAJLA,EAsDOqB,CAAsBtB,EAAQgB,SAAWhB,EAASS,GAC5Dc,EAASC,eACTC,EAAS,IAAMC,YAAUH,GAEzBI,EACHC,GACD,EAAGC,OAAAA,EAAQC,OAAAA,EAAQC,OAAAA,EAAQhC,MAAAA,KACd,SAAX8B,EACI,CAAEA,OAAAA,EAAQpB,IAAAA,EAAKmB,UAAAA,EAAWI,MAAOD,GACjC,CAAEF,OAAAA,EAAQpB,IAAAA,EAAKmB,UAAAA,EAAWI,MAAOF,EAAQ/B,MAAAA,UAIjDkC,aAAWV,GAAQ,SACXW,EAAQC,iBACRC,EAAQD,iBAERE,EAAc1C,gBACd2C,EAAYD,EAAYE,WAC5B,EAAGV,OAAAA,EAAQpB,IAAAA,EAAKmB,UAAAA,EAAWI,MAAAA,KACd,SAAXH,EAAoB,CAAEpB,IAAAA,EAAKmB,UAAAA,EAAWI,MAAAA,QAAUb,IAE9CqB,EAAYH,EAAYE,WAC5B,EAAGV,OAAAA,EAAQpB,IAAAA,EAAKmB,UAAAA,EAAW7B,MAAAA,EAAOiC,MAAAA,KACrB,SAAXH,EAAoB,CAAEpB,IAAAA,EAAKmB,UAAAA,EAAW7B,MAAAA,EAAOiC,MAAAA,QAAUb,IAGrDa,EAAQhC,EAAeS,EAAKyB,GAClCA,EAAMO,IAAIT,EAAMd,KAChBkB,EAAMK,IAAIT,EAAMZ,KAEhBsB,QAAM,CACJxC,OAAQyC,SACN5B,EACAb,GACA,CAAC0C,EAAcC,IAAa,CAACA,EAAUD,KAEzCE,OAAQ,EAAED,EAAUD,KAAaC,IAAaD,EAC9CzC,OAAQiC,EAAMW,SAAwB,EAAEF,KAAcA,MAExDG,UAAQ,CAAEC,KAAM,CAACf,EAAMgB,SAAUd,GAAQe,GAAIpC,IAC7CiC,UAAQ,CAAEC,KAAM,CAACf,EAAMgB,SAAUnC,GAAUoC,GAAIhD,IAC/C6C,UAAQ,CACNC,KAAM,CAACf,EAAM5B,QAAQ8C,IAAIzB,EAAG,QAASS,EAAM9B,QAAQ8C,IAAIzB,EAAG,SAC1DwB,GAAId,IAGNW,UAAQ,CAAEC,KAAMT,EAAWW,GAAI9C,IAC/BD,GAAQ4C,UAAQ,CAAEC,KAAMX,EAAWa,GAAI/C,IACvCG,GAAUyC,UAAQ,CAAEC,KAAMZ,EAAac,GAAI5C,IAE3CC,GAAUwC,UAAQ,CAAEC,KAAMzC,EAAQ2C,GAAIjB,EAAMa,SAAQ,WAGpDb,OAGMT,EAAO4B,YAAc5B"}
1
+ {"version":3,"file":"index.cjs","sources":["../src/area.ts","../src/persist.ts","../src/index.ts"],"sourcesContent":["import type { Store } from 'effector'\nimport { createStore } from 'effector'\n\n/**\n * Keys areas / namespaces cache\n */\nconst areas = new Map<any, Map<string, Store<any>>>()\n\n/**\n * Get store, responsible for the key in key area / namespace\n */\nexport function getAreaStorage<State>(keyArea: any, key: string): Store<State> {\n let area = areas.get(keyArea)\n if (area === undefined) {\n area = new Map()\n areas.set(keyArea, area)\n }\n\n let store = area.get(key)\n if (store !== undefined) {\n return store\n }\n\n store = createStore(null)\n area.set(key, store)\n\n return store\n}\n","import type { Subscription } from 'effector'\nimport type {\n ConfigPersist,\n ConfigSourceTarget,\n ConfigStore,\n Done,\n Fail,\n Finally,\n} from './types'\nimport {\n clearNode,\n createEffect,\n createEvent,\n createNode,\n forward,\n guard,\n is,\n sample,\n withRegion,\n} from 'effector'\nimport { getAreaStorage } from './area'\n\n/**\n * Default sink for unhandled errors\n */\nconst sink = createEvent<Fail<any>>()\nsink.watch((payload) => console.error(payload.error))\n\n/**\n * Main `persist` function\n */\nexport function persist<State, Err = Error>({\n adapter,\n clock,\n store,\n source = store,\n target = store,\n done,\n fail = sink,\n finally: anyway,\n pickup,\n key: keyName,\n keyPrefix = '',\n}: Partial<\n ConfigPersist & ConfigStore<State, Err> & ConfigSourceTarget<State, Err>\n>): Subscription {\n if (!adapter) {\n throw Error('Adapter is not defined')\n }\n if (!source) {\n throw Error('Store or source is not defined')\n }\n if (!target) {\n throw Error('Target is not defined')\n }\n if (!keyName && source.shortName === (source as any).id) {\n throw Error('Key or name is not defined')\n }\n if (source === target && !is.store(source)) {\n throw Error('Source must be different from target')\n }\n\n const key = keyName || source.shortName\n const storage = getAreaStorage<State>(\n adapter.keyArea || adapter,\n keyPrefix + key\n )\n const region = createNode()\n const desist = () => clearNode(region)\n\n const op =\n (operation: 'get' | 'set') =>\n ({ status, params, result, error }: any): any =>\n status === 'done'\n ? {\n status,\n key,\n keyPrefix,\n operation,\n value: operation === 'get' ? result : params,\n }\n : {\n status,\n key,\n keyPrefix,\n operation,\n value: params,\n error,\n }\n\n // create all auxiliary units and nodes within the region,\n // to be able to remove them all at once on unsubscription\n withRegion(region, () => {\n const getFx = createEffect<void, State, Err>()\n const setFx = createEffect<State, void, Err>()\n\n const localAnyway = createEvent<Finally<State, Err>>()\n const localDone = localAnyway.filterMap<Done<State>>(\n ({ status, key, keyPrefix, operation, value }) =>\n status === 'done' ? { key, keyPrefix, operation, value } : undefined\n )\n const localFail = localAnyway.filterMap<Fail<Err>>(\n ({ status, key, keyPrefix, operation, error, value }: any) =>\n status === 'fail'\n ? { key, keyPrefix, operation, error, value }\n : undefined\n )\n\n const value = adapter<State>(keyPrefix + key, getFx)\n getFx.use(value.get)\n setFx.use(value.set)\n\n guard({\n source: sample<State, State, [State, State]>(\n storage,\n (sample as any)(source, clock),\n (current: any, proposed) => [proposed, current]\n ),\n filter: ([proposed, current]) => proposed !== current,\n target: setFx.prepend<[State, State]>(([proposed]) => proposed),\n })\n forward({ from: [getFx.doneData, setFx], to: storage })\n forward({ from: [getFx.doneData, storage], to: target })\n forward({\n from: [getFx.finally.map(op('get')), setFx.finally.map(op('set'))],\n to: localAnyway,\n })\n\n forward({ from: localFail, to: fail })\n if (done) forward({ from: localDone, to: done })\n if (anyway) forward({ from: localAnyway, to: anyway })\n\n if (pickup) {\n // pick up value from storage ONLY on `pickup` update\n forward({ from: pickup, to: getFx.prepend(() => undefined) })\n } else {\n // kick getter to pick up initial value from storage\n getFx()\n }\n })\n\n return (desist.unsubscribe = desist)\n}\n","import type { ConfigPersist, Persist } from './types'\nimport { persist as base } from './persist'\n\nexport type {\n ConfigPersist,\n ConfigSourceTarget,\n ConfigStore,\n Done,\n Fail,\n Finally,\n Persist,\n StorageAdapter,\n} from './types'\n\n/**\n * Creates custom `persist`\n */\nexport function createPersist(defaults?: ConfigPersist): Persist {\n return (config) => base({ ...defaults, ...config })\n}\n\n/**\n * Default `persist`\n */\nexport const persist = createPersist()\n"],"names":["areas","Map","sink","createEvent","createPersist","defaults","config","adapter","clock","store","source","target","done","fail","finally","anyway","pickup","key","keyName","keyPrefix","Error","shortName","id","is","storage","keyArea","area","get","undefined","set","createStore","getAreaStorage","region","createNode","desist","clearNode","op","operation","status","params","result","error","value","withRegion","getFx","createEffect","setFx","localAnyway","localDone","filterMap","localFail","use","guard","sample","current","proposed","filter","prepend","forward","from","doneData","to","map","unsubscribe","base","watch","payload","console","persist"],"mappings":"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"}
package/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Store, Unit, Event, Effect, Subscription } from 'effector'
1
+ import { Subscription, Unit, Store, Event, Effect } from 'effector'
2
2
 
3
3
  interface StorageAdapter {
4
4
  <State>(key: string, update: (raw?: any) => any): {
@@ -9,11 +9,13 @@ interface StorageAdapter {
9
9
  }
10
10
  declare type Done<State> = {
11
11
  key: string
12
+ keyPrefix: string
12
13
  operation: 'set' | 'get'
13
14
  value: State
14
15
  }
15
16
  declare type Fail<Err> = {
16
17
  key: string
18
+ keyPrefix: string
17
19
  operation: 'set' | 'get'
18
20
  error: Err
19
21
  value?: any
@@ -25,41 +27,59 @@ declare type Finally<State, Err> =
25
27
  | (Fail<Err> & {
26
28
  status: 'fail'
27
29
  })
28
- interface ConfigStore<State, Err = Error> {
30
+ interface ConfigPersist {
31
+ keyPrefix?: string
32
+ }
33
+ interface ConfigAdapter {
29
34
  adapter: StorageAdapter
30
- store: Store<State>
35
+ }
36
+ interface ConfigCommon<State, Err = Error> {
37
+ clock?: Unit<any>
31
38
  done?: Unit<Done<State>>
32
39
  fail?: Unit<Fail<Err>>
33
40
  finally?: Unit<Finally<State, Err>>
34
41
  pickup?: Unit<any>
35
42
  key?: string
43
+ keyPrefix?: string
36
44
  }
37
- interface ConfigSourceTarget<State, Err = Error> {
38
- adapter: StorageAdapter
45
+ interface ConfigJustStore<State> {
46
+ store: Store<State>
47
+ }
48
+ interface ConfigJustSourceTarget<State> {
39
49
  source: Store<State> | Event<State> | Effect<State, any, any>
40
50
  target: Store<State> | Event<State> | Effect<State, any, any>
41
- done?: Unit<Done<State>>
42
- fail?: Unit<Fail<Err>>
43
- finally?: Unit<Finally<State, Err>>
44
- pickup?: Unit<any>
45
- key?: string
46
51
  }
52
+ interface ConfigStore<State, Err = Error>
53
+ extends ConfigAdapter,
54
+ ConfigCommon<State, Err>,
55
+ ConfigJustStore<State> {}
56
+ interface ConfigSourceTarget<State, Err = Error>
57
+ extends ConfigAdapter,
58
+ ConfigCommon<State, Err>,
59
+ ConfigJustSourceTarget<State> {}
60
+ interface Persist {
61
+ <State, Err = Error>(config: ConfigSourceTarget<State, Err>): Subscription
62
+ <State, Err = Error>(config: ConfigStore<State, Err>): Subscription
63
+ }
64
+
65
+ /**
66
+ * Creates custom `persist`
67
+ */
68
+ declare function createPersist(defaults?: ConfigPersist): Persist
47
69
  /**
48
- * Main root `persist` function
70
+ * Default `persist`
49
71
  */
50
- declare function persist<State, Err = Error>(
51
- config: ConfigStore<State, Err>
52
- ): Subscription
53
- declare function persist<State, Err = Error>(
54
- config: ConfigSourceTarget<State, Err>
55
- ): Subscription
72
+ declare const persist: Persist
56
73
 
57
74
  export {
75
+ ConfigPersist,
58
76
  ConfigSourceTarget,
59
77
  ConfigStore,
60
78
  Done,
61
79
  Fail,
62
80
  Finally,
81
+ Persist,
63
82
  StorageAdapter,
83
+ createPersist,
64
84
  persist,
65
85
  }
package/index.js CHANGED
@@ -1,2 +1,2 @@
1
- import{createEvent as r,is as e,createNode as o,withRegion as t,createEffect as a,guard as i,sample as n,forward as s,createStore as f,clearNode as u}from"effector";var d=new Map,p=r();function l({adapter:l,store:m,source:v=m,target:y=m,done:c,fail:k=p,finally:g,pickup:h,key:w}){if(!l)throw Error("Adapter is not defined");if(!v)throw Error("Store or source is not defined");if(!y)throw Error("Target is not defined");if(!w&&v.shortName===v.id)throw Error("Key or name is not defined");if(v===y&&!e.store(v))throw Error("Source must be different from target");var E=w||v.shortName,M=function(r,e){var o=d.get(r);void 0===o&&(o=new Map,d.set(r,o));var t=o.get(e);return void 0!==t||(t=f(null),o.set(e,t)),t}(l.keyArea||l,E),b=o(),A=()=>u(b),D=r=>({status:e,params:o,result:t,error:a})=>"done"===e?{status:e,key:E,operation:r,value:t}:{status:e,key:E,operation:r,value:o,error:a};return t(b,(()=>{var e=a(),o=a(),t=r(),f=t.filterMap((({status:r,key:e,operation:o,value:t})=>"done"===r?{key:e,operation:o,value:t}:void 0)),u=t.filterMap((({status:r,key:e,operation:o,error:t,value:a})=>"fail"===r?{key:e,operation:o,error:t,value:a}:void 0)),d=l(E,e);e.use(d.get),o.use(d.set),i({source:n(M,v,((r,e)=>[e,r])),filter:([r,e])=>r!==e,target:o.prepend((([r])=>r))}),s({from:[e.doneData,o],to:M}),s({from:[e.doneData,M],to:y}),s({from:[e.finally.map(D("get")),o.finally.map(D("set"))],to:t}),s({from:u,to:k}),c&&s({from:f,to:c}),g&&s({from:t,to:g}),h&&s({from:h,to:e.prepend((()=>{}))}),e()})),A.unsubscribe=A}p.watch((r=>console.error(r.error)));export{l as persist};
1
+ import{createStore as e,createEvent as r,is as o,createNode as t,clearNode as a,withRegion as i,createEffect as f,guard as n,sample as s,forward as u}from"effector";var d=new Map,p=r();function l(l){return y=>function({adapter:l,clock:y,store:k,source:m=k,target:v=k,done:c,fail:g=p,finally:h,pickup:w,key:x,keyPrefix:P=""}){if(!l)throw Error("Adapter is not defined");if(!m)throw Error("Store or source is not defined");if(!v)throw Error("Target is not defined");if(!x&&m.shortName===m.id)throw Error("Key or name is not defined");if(m===v&&!o.store(m))throw Error("Source must be different from target");var E=x||m.shortName,M=function(r,o){var t=d.get(r);void 0===t&&(t=new Map,d.set(r,t));var a=t.get(o);return void 0!==a||(a=e(null),t.set(o,a)),a}(l.keyArea||l,P+E),b=t(),A=()=>a(b),D=e=>({status:r,params:o,result:t,error:a})=>"done"===r?{status:r,key:E,keyPrefix:P,operation:e,value:"get"===e?t:o}:{status:r,key:E,keyPrefix:P,operation:e,value:o,error:a};return i(b,(()=>{var e=f(),o=f(),t=r(),a=t.filterMap((({status:e,key:r,keyPrefix:o,operation:t,value:a})=>"done"===e?{key:r,keyPrefix:o,operation:t,value:a}:void 0)),i=t.filterMap((({status:e,key:r,keyPrefix:o,operation:t,error:a,value:i})=>"fail"===e?{key:r,keyPrefix:o,operation:t,error:a,value:i}:void 0)),d=l(P+E,e);e.use(d.get),o.use(d.set),n({source:s(M,s(m,y),((e,r)=>[r,e])),filter:([e,r])=>e!==r,target:o.prepend((([e])=>e))}),u({from:[e.doneData,o],to:M}),u({from:[e.doneData,M],to:v}),u({from:[e.finally.map(D("get")),o.finally.map(D("set"))],to:t}),u({from:i,to:g}),c&&u({from:a,to:c}),h&&u({from:t,to:h}),w?u({from:w,to:e.prepend((()=>{}))}):e()})),A.unsubscribe=A}({...l,...y})}p.watch((e=>console.error(e.error)));var y=l();export{l as createPersist,y as persist};
2
2
  //# sourceMappingURL=index.js.map