@dxtmisha/wiki 0.39.7 → 0.56.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{defineProperty-DblGXmzD.js → defineProperty-149Ahniv.js} +4 -4
- package/dist/library.js +1 -1
- package/dist/media/descriptions/wikiDescriptionsArea.d.ts +7 -0
- package/dist/media/descriptions/wikiDescriptionsClientOnly.d.ts +7 -0
- package/dist/media/descriptions/wikiDescriptionsContainer.d.ts +7 -0
- package/dist/media/descriptions/wikiDescriptionsHeader.d.ts +7 -0
- package/dist/media/descriptions/wikiDescriptionsPageArea.d.ts +7 -0
- package/dist/media/mdx/Area/wikiMdxArea.d.ts +7 -0
- package/dist/media/mdx/ClientOnly/wikiMdxClientOnly.d.ts +7 -0
- package/dist/media/mdx/Container/wikiMdxContainer.d.ts +7 -0
- package/dist/media/mdx/Header/wikiMdxHeader.d.ts +7 -0
- package/dist/media/mdx/PageArea/wikiMdxPageArea.d.ts +7 -0
- package/dist/media.d.ts +1 -1
- package/dist/media.js +127 -68
- package/dist/storybook.js +2707 -1841
- package/dist/{wikiDescriptions-Cv4WzSNL.js → wikiDescriptions-7XaHU3Yk.js} +182 -0
- package/package.json +1 -1
- package/src/media/functional/functional/composables/useApiAsyncRef/useApiAsyncRef.en.mdx +43 -0
- package/src/media/functional/functional/composables/useApiAsyncRef/useApiAsyncRef.ru.mdx +43 -0
- package/src/media/functional/functional/composables/useApiAsyncRef/useApiAsyncRef.vi.mdx +41 -0
- package/src/media/functional/functional/composables/useApiRef/useApiRef.en.mdx +20 -4
- package/src/media/functional/functional/composables/useApiRef/useApiRef.ru.mdx +21 -3
- package/src/media/functional/functional/composables/useApiRef/useApiRef.vi.mdx +20 -2
- package/src/media/functional/functional/functions/computedAsync/computedAsync.en.mdx +8 -0
- package/src/media/functional/functional/functions/computedAsync/computedAsync.ru.mdx +8 -0
- package/src/media/functional/functional/functions/computedAsync/computedAsync.vi.mdx +8 -0
- package/src/media/functional/functional/functions/computedEternity/computedEternity.en.mdx +8 -0
- package/src/media/functional/functional/functions/computedEternity/computedEternity.ru.mdx +8 -0
- package/src/media/functional/functional/functions/computedEternity/computedEternity.vi.mdx +8 -0
- package/src/media/functional/functional-basic/api/api.en.mdx +45 -0
- package/src/media/functional/functional-basic/api/api.ru.mdx +45 -0
- package/src/media/functional/functional-basic/api/api.vi.mdx +45 -0
- package/src/media/functional/functional-basic/classes/Api/Api.en.mdx +57 -54
- package/src/media/functional/functional-basic/classes/Api/Api.ru.mdx +57 -54
- package/src/media/functional/functional-basic/classes/Api/Api.vi.mdx +57 -54
- package/src/media/functional/functional-basic/classes/ApiCache/ApiCache.en.mdx +111 -0
- package/src/media/functional/functional-basic/classes/ApiCache/ApiCache.ru.mdx +111 -0
- package/src/media/functional/functional-basic/classes/ApiCache/ApiCache.vi.mdx +111 -0
- package/src/media/functional/functional-basic/classes/ApiDataReturn/ApiDataReturn.en.mdx +32 -0
- package/src/media/functional/functional-basic/classes/ApiDataReturn/ApiDataReturn.ru.mdx +32 -0
- package/src/media/functional/functional-basic/classes/ApiDataReturn/ApiDataReturn.vi.mdx +32 -0
- package/src/media/functional/functional-basic/classes/ApiDefault/ApiDefault.en.mdx +24 -28
- package/src/media/functional/functional-basic/classes/ApiDefault/ApiDefault.ru.mdx +24 -28
- package/src/media/functional/functional-basic/classes/ApiDefault/ApiDefault.vi.mdx +24 -28
- package/src/media/functional/functional-basic/classes/ApiHeaders/ApiHeaders.en.mdx +28 -14
- package/src/media/functional/functional-basic/classes/ApiHeaders/ApiHeaders.ru.mdx +33 -19
- package/src/media/functional/functional-basic/classes/ApiHeaders/ApiHeaders.vi.mdx +33 -19
- package/src/media/functional/functional-basic/classes/ApiHydration/ApiHydration.en.mdx +56 -0
- package/src/media/functional/functional-basic/classes/ApiHydration/ApiHydration.ru.mdx +56 -0
- package/src/media/functional/functional-basic/classes/ApiHydration/ApiHydration.vi.mdx +55 -0
- package/src/media/functional/functional-basic/classes/ApiInstance/ApiInstance.en.mdx +106 -51
- package/src/media/functional/functional-basic/classes/ApiInstance/ApiInstance.ru.mdx +107 -52
- package/src/media/functional/functional-basic/classes/ApiInstance/ApiInstance.vi.mdx +103 -49
- package/src/media/functional/functional-basic/classes/ApiPreparation/ApiPreparation.en.mdx +44 -26
- package/src/media/functional/functional-basic/classes/ApiPreparation/ApiPreparation.ru.mdx +45 -27
- package/src/media/functional/functional-basic/classes/ApiPreparation/ApiPreparation.vi.mdx +44 -26
- package/src/media/functional/functional-basic/classes/ApiResponse/ApiResponse.en.mdx +59 -21
- package/src/media/functional/functional-basic/classes/ApiResponse/ApiResponse.ru.mdx +63 -25
- package/src/media/functional/functional-basic/classes/ApiResponse/ApiResponse.vi.mdx +64 -26
- package/src/media/functional/functional-basic/classes/ApiStatus/ApiStatus.en.mdx +29 -32
- package/src/media/functional/functional-basic/classes/ApiStatus/ApiStatus.ru.mdx +33 -36
- package/src/media/functional/functional-basic/classes/ApiStatus/ApiStatus.vi.mdx +33 -36
- package/src/media/functional/functional-basic/classes/BroadcastMessage/BroadcastMessage.en.mdx +34 -53
- package/src/media/functional/functional-basic/classes/BroadcastMessage/BroadcastMessage.ru.mdx +33 -52
- package/src/media/functional/functional-basic/classes/BroadcastMessage/BroadcastMessage.vi.mdx +39 -58
- package/src/media/functional/functional-basic/classes/Cache/Cache.en.mdx +7 -4
- package/src/media/functional/functional-basic/classes/Cache/Cache.ru.mdx +7 -4
- package/src/media/functional/functional-basic/classes/Cache/Cache.vi.mdx +28 -25
- package/src/media/functional/functional-basic/classes/CacheItem/CacheItem.en.mdx +45 -53
- package/src/media/functional/functional-basic/classes/CacheItem/CacheItem.ru.mdx +46 -54
- package/src/media/functional/functional-basic/classes/CacheItem/CacheItem.vi.mdx +47 -55
- package/src/media/functional/functional-basic/classes/CacheStatic/CacheStatic.en.mdx +13 -1
- package/src/media/functional/functional-basic/classes/CacheStatic/CacheStatic.ru.mdx +13 -1
- package/src/media/functional/functional-basic/classes/CacheStatic/CacheStatic.vi.mdx +13 -0
- package/src/media/functional/functional-basic/classes/Cookie/Cookie.en.mdx +88 -44
- package/src/media/functional/functional-basic/classes/Cookie/Cookie.ru.mdx +88 -44
- package/src/media/functional/functional-basic/classes/Cookie/Cookie.vi.mdx +85 -41
- package/src/media/functional/functional-basic/classes/CookieBlock/CookieBlock.en.mdx +43 -22
- package/src/media/functional/functional-basic/classes/CookieBlock/CookieBlock.ru.mdx +46 -25
- package/src/media/functional/functional-basic/classes/CookieBlock/CookieBlock.vi.mdx +43 -22
- package/src/media/functional/functional-basic/classes/CookieBlockInstance/CookieBlockInstance.en.mdx +84 -0
- package/src/media/functional/functional-basic/classes/CookieBlockInstance/CookieBlockInstance.ru.mdx +84 -0
- package/src/media/functional/functional-basic/classes/CookieBlockInstance/CookieBlockInstance.vi.mdx +100 -0
- package/src/media/functional/functional-basic/classes/CookieStorage/CookieStorage.en.mdx +178 -0
- package/src/media/functional/functional-basic/classes/CookieStorage/CookieStorage.ru.mdx +178 -0
- package/src/media/functional/functional-basic/classes/CookieStorage/CookieStorage.vi.mdx +178 -0
- package/src/media/functional/functional-basic/classes/DataStorage/DataStorage.en.mdx +32 -25
- package/src/media/functional/functional-basic/classes/DataStorage/DataStorage.ru.mdx +32 -25
- package/src/media/functional/functional-basic/classes/DataStorage/DataStorage.vi.mdx +32 -27
- package/src/media/functional/functional-basic/classes/Datetime/Datetime.en.mdx +36 -4
- package/src/media/functional/functional-basic/classes/Datetime/Datetime.ru.mdx +36 -4
- package/src/media/functional/functional-basic/classes/Datetime/Datetime.vi.mdx +36 -4
- package/src/media/functional/functional-basic/classes/ErrorCenter/ErrorCenter.en.mdx +101 -70
- package/src/media/functional/functional-basic/classes/ErrorCenter/ErrorCenter.ru.mdx +100 -69
- package/src/media/functional/functional-basic/classes/ErrorCenter/ErrorCenter.vi.mdx +101 -70
- package/src/media/functional/functional-basic/classes/ErrorCenterHandler/ErrorCenterHandler.en.mdx +46 -42
- package/src/media/functional/functional-basic/classes/ErrorCenterHandler/ErrorCenterHandler.ru.mdx +46 -42
- package/src/media/functional/functional-basic/classes/ErrorCenterHandler/ErrorCenterHandler.vi.mdx +46 -42
- package/src/media/functional/functional-basic/classes/ErrorCenterInstance/ErrorCenterInstance.en.mdx +44 -96
- package/src/media/functional/functional-basic/classes/ErrorCenterInstance/ErrorCenterInstance.ru.mdx +44 -96
- package/src/media/functional/functional-basic/classes/ErrorCenterInstance/ErrorCenterInstance.vi.mdx +44 -96
- package/src/media/functional/functional-basic/classes/EventItem/EventItem.en.mdx +49 -28
- package/src/media/functional/functional-basic/classes/EventItem/EventItem.ru.mdx +21 -0
- package/src/media/functional/functional-basic/classes/EventItem/EventItem.vi.mdx +63 -42
- package/src/media/functional/functional-basic/classes/Formatters/Formatters.en.mdx +97 -109
- package/src/media/functional/functional-basic/classes/Formatters/Formatters.ru.mdx +86 -98
- package/src/media/functional/functional-basic/classes/Formatters/Formatters.vi.mdx +99 -111
- package/src/media/functional/functional-basic/classes/Geo/Geo.en.mdx +3 -3
- package/src/media/functional/functional-basic/classes/Geo/Geo.ru.mdx +5 -5
- package/src/media/functional/functional-basic/classes/Geo/Geo.vi.mdx +5 -5
- package/src/media/functional/functional-basic/classes/GeoFlag/GeoFlag.en.mdx +83 -40
- package/src/media/functional/functional-basic/classes/GeoFlag/GeoFlag.ru.mdx +83 -40
- package/src/media/functional/functional-basic/classes/GeoFlag/GeoFlag.vi.mdx +87 -44
- package/src/media/functional/functional-basic/classes/GeoInstance/GeoInstance.en.mdx +81 -0
- package/src/media/functional/functional-basic/classes/GeoInstance/GeoInstance.ru.mdx +81 -0
- package/src/media/functional/functional-basic/classes/GeoInstance/GeoInstance.vi.mdx +81 -0
- package/src/media/functional/functional-basic/classes/GeoPhone/GeoPhone.en.mdx +56 -105
- package/src/media/functional/functional-basic/classes/GeoPhone/GeoPhone.ru.mdx +53 -102
- package/src/media/functional/functional-basic/classes/GeoPhone/GeoPhone.vi.mdx +55 -105
- package/src/media/functional/functional-basic/classes/Hash/Hash.en.mdx +18 -7
- package/src/media/functional/functional-basic/classes/Hash/Hash.ru.mdx +18 -7
- package/src/media/functional/functional-basic/classes/Hash/Hash.vi.mdx +18 -7
- package/src/media/functional/functional-basic/classes/HashInstance/HashInstance.en.mdx +54 -0
- package/src/media/functional/functional-basic/classes/HashInstance/HashInstance.ru.mdx +54 -0
- package/src/media/functional/functional-basic/classes/HashInstance/HashInstance.vi.mdx +54 -0
- package/src/media/functional/functional-basic/classes/Meta/Meta.en.mdx +16 -0
- package/src/media/functional/functional-basic/classes/Meta/Meta.ru.mdx +16 -0
- package/src/media/functional/functional-basic/classes/Meta/Meta.vi.mdx +17 -1
- package/src/media/functional/functional-basic/classes/MetaManager/MetaManager.en.mdx +9 -0
- package/src/media/functional/functional-basic/classes/MetaManager/MetaManager.ru.mdx +9 -0
- package/src/media/functional/functional-basic/classes/MetaManager/MetaManager.vi.mdx +9 -0
- package/src/media/functional/functional-basic/classes/MetaStatic/MetaStatic.en.mdx +79 -0
- package/src/media/functional/functional-basic/classes/MetaStatic/MetaStatic.ru.mdx +79 -0
- package/src/media/functional/functional-basic/classes/MetaStatic/MetaStatic.vi.mdx +79 -0
- package/src/media/functional/functional-basic/classes/ResumableTimer/ResumableTimer.en.mdx +50 -0
- package/src/media/functional/functional-basic/classes/ResumableTimer/ResumableTimer.ru.mdx +50 -0
- package/src/media/functional/functional-basic/classes/ResumableTimer/ResumableTimer.vi.mdx +50 -0
- package/src/media/functional/functional-basic/classes/ServerStorage/ServerStorage.en.mdx +131 -0
- package/src/media/functional/functional-basic/classes/ServerStorage/ServerStorage.ru.mdx +131 -0
- package/src/media/functional/functional-basic/classes/ServerStorage/ServerStorage.vi.mdx +131 -0
- package/src/media/functional/functional-basic/classes/StorageCallback/StorageCallback.en.mdx +97 -0
- package/src/media/functional/functional-basic/classes/StorageCallback/StorageCallback.ru.mdx +97 -0
- package/src/media/functional/functional-basic/classes/StorageCallback/StorageCallback.vi.mdx +97 -0
- package/src/media/functional/functional-basic/functions/addTagHighlightMatch/addTagHighlightMatch.en.mdx +13 -5
- package/src/media/functional/functional-basic/functions/addTagHighlightMatch/addTagHighlightMatch.ru.mdx +13 -5
- package/src/media/functional/functional-basic/functions/addTagHighlightMatch/addTagHighlightMatch.vi.mdx +13 -5
- package/src/media/functional/functional-basic/functions/anyToString/anyToString.en.mdx +37 -19
- package/src/media/functional/functional-basic/functions/anyToString/anyToString.ru.mdx +37 -19
- package/src/media/functional/functional-basic/functions/anyToString/anyToString.vi.mdx +35 -17
- package/src/media/functional/functional-basic/functions/applyTemplate/applyTemplate.en.mdx +31 -19
- package/src/media/functional/functional-basic/functions/applyTemplate/applyTemplate.ru.mdx +31 -19
- package/src/media/functional/functional-basic/functions/applyTemplate/applyTemplate.vi.mdx +32 -20
- package/src/media/functional/functional-basic/functions/blobToBase64/blobToBase64.en.mdx +29 -15
- package/src/media/functional/functional-basic/functions/blobToBase64/blobToBase64.ru.mdx +28 -14
- package/src/media/functional/functional-basic/functions/blobToBase64/blobToBase64.vi.mdx +28 -14
- package/src/media/functional/functional-basic/functions/capitalize/capitalize.en.mdx +7 -3
- package/src/media/functional/functional-basic/functions/capitalize/capitalize.ru.mdx +7 -3
- package/src/media/functional/functional-basic/functions/capitalize/capitalize.vi.mdx +7 -3
- package/src/media/functional/functional-basic/functions/copyObject/copyObject.en.mdx +17 -13
- package/src/media/functional/functional-basic/functions/copyObject/copyObject.ru.mdx +17 -13
- package/src/media/functional/functional-basic/functions/copyObject/copyObject.vi.mdx +17 -13
- package/src/media/functional/functional-basic/functions/createElement/createElement.en.mdx +2 -0
- package/src/media/functional/functional-basic/functions/createElement/createElement.ru.mdx +2 -0
- package/src/media/functional/functional-basic/functions/createElement/createElement.vi.mdx +2 -0
- package/src/media/functional/functional-basic/functions/encodeAttribute/encodeAttribute.en.mdx +1 -3
- package/src/media/functional/functional-basic/functions/encodeAttribute/encodeAttribute.ru.mdx +1 -3
- package/src/media/functional/functional-basic/functions/encodeAttribute/encodeAttribute.vi.mdx +1 -3
- package/src/media/functional/functional-basic/functions/executeFunction/executeFunction.en.mdx +13 -10
- package/src/media/functional/functional-basic/functions/executeFunction/executeFunction.ru.mdx +14 -11
- package/src/media/functional/functional-basic/functions/executeFunction/executeFunction.vi.mdx +12 -9
- package/src/media/functional/functional-basic/functions/executePromise/executePromise.en.mdx +14 -13
- package/src/media/functional/functional-basic/functions/executePromise/executePromise.ru.mdx +15 -14
- package/src/media/functional/functional-basic/functions/executePromise/executePromise.vi.mdx +14 -13
- package/src/media/functional/functional-basic/functions/forEach/forEach.en.mdx +1 -1
- package/src/media/functional/functional-basic/functions/forEach/forEach.ru.mdx +1 -1
- package/src/media/functional/functional-basic/functions/forEach/forEach.vi.mdx +1 -1
- package/src/media/functional/functional-basic/functions/frame/frame.en.mdx +7 -4
- package/src/media/functional/functional-basic/functions/frame/frame.ru.mdx +6 -3
- package/src/media/functional/functional-basic/functions/frame/frame.vi.mdx +7 -4
- package/src/media/functional/functional-basic/functions/getArrayHighlightMatch/getArrayHighlightMatch.en.mdx +34 -0
- package/src/media/functional/functional-basic/functions/getArrayHighlightMatch/getArrayHighlightMatch.ru.mdx +34 -0
- package/src/media/functional/functional-basic/functions/getArrayHighlightMatch/getArrayHighlightMatch.vi.mdx +35 -0
- package/src/media/functional/functional-basic/functions/getCurrentDate/getCurrentDate.en.mdx +2 -0
- package/src/media/functional/functional-basic/functions/getCurrentDate/getCurrentDate.ru.mdx +2 -0
- package/src/media/functional/functional-basic/functions/getCurrentDate/getCurrentDate.vi.mdx +2 -0
- package/src/media/functional/functional-basic/functions/getCurrentTime/getCurrentTime.en.mdx +21 -0
- package/src/media/functional/functional-basic/functions/getCurrentTime/getCurrentTime.ru.mdx +21 -0
- package/src/media/functional/functional-basic/functions/getCurrentTime/getCurrentTime.vi.mdx +21 -0
- package/src/media/functional/functional-basic/functions/getElementId/getElementId.en.mdx +17 -3
- package/src/media/functional/functional-basic/functions/getElementId/getElementId.ru.mdx +17 -3
- package/src/media/functional/functional-basic/functions/getElementId/getElementId.vi.mdx +18 -4
- package/src/media/functional/functional-basic/functions/getElementSafeScript/getElementSafeScript.en.mdx +31 -0
- package/src/media/functional/functional-basic/functions/getElementSafeScript/getElementSafeScript.ru.mdx +31 -0
- package/src/media/functional/functional-basic/functions/getElementSafeScript/getElementSafeScript.vi.mdx +31 -0
- package/src/media/functional/functional-basic/functions/getOnlyText/getOnlyText.en.mdx +25 -0
- package/src/media/functional/functional-basic/functions/getOnlyText/getOnlyText.ru.mdx +25 -0
- package/src/media/functional/functional-basic/functions/getOnlyText/getOnlyText.vi.mdx +25 -0
- package/src/media/functional/functional-basic/functions/getSearchExp/getSearchExp.en.mdx +11 -4
- package/src/media/functional/functional-basic/functions/getSearchExp/getSearchExp.ru.mdx +14 -7
- package/src/media/functional/functional-basic/functions/getSearchExp/getSearchExp.vi.mdx +13 -6
- package/src/media/functional/functional-basic/functions/getSeparatingSearchExp/getSeparatingSearchExp.en.mdx +3 -2
- package/src/media/functional/functional-basic/functions/getSeparatingSearchExp/getSeparatingSearchExp.ru.mdx +3 -2
- package/src/media/functional/functional-basic/functions/getSeparatingSearchExp/getSeparatingSearchExp.vi.mdx +3 -2
- package/src/media/functional/functional-basic/functions/toNumber/toNumber.en.mdx +25 -9
- package/src/media/functional/functional-basic/functions/toNumber/toNumber.ru.mdx +25 -9
- package/src/media/functional/functional-basic/functions/toNumber/toNumber.vi.mdx +25 -9
- package/src/media/functional/functional-basic/functions/toString/toString.en.mdx +28 -0
- package/src/media/functional/functional-basic/functions/toString/toString.ru.mdx +28 -0
- package/src/media/functional/functional-basic/functions/toString/toString.vi.mdx +28 -0
- package/src/media/functional/functional-basic/icons/icons.en.mdx +3 -0
- package/src/media/functional/functional-basic/icons/icons.ru.mdx +3 -0
- package/src/media/functional/functional-basic/icons/icons.vi.mdx +3 -0
- package/src/media/functional/nitro-basic/functions/getInject.en.mdx +27 -0
- package/src/media/functional/nitro-basic/functions/getInject.ru.mdx +27 -0
- package/src/media/functional/nitro-basic/functions/getInject.vi.mdx +20 -0
- package/src/media/functional/ui/about/about.en.mdx +45 -0
- package/src/media/functional/ui/about/about.ru.mdx +45 -0
- package/src/media/functional/ui/about/about.vi.mdx +45 -0
- package/src/media/functional/ui/component/component.en.mdx +104 -0
- package/src/media/functional/ui/component/component.ru.mdx +106 -0
- package/src/media/functional/ui/component/component.vi.mdx +104 -0
- package/src/media/functional/ui/setup/setup.en.mdx +72 -0
- package/src/media/functional/ui/setup/setup.ru.mdx +72 -0
- package/src/media/functional/ui/setup/setup.vi.mdx +72 -0
- package/src/media/functional/ui/wiki-data.en.mdx +114 -0
- package/src/media/functional/ui/wiki-data.ru.mdx +114 -0
- package/src/media/functional/ui/wiki-data.vi.mdx +114 -0
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import {Meta} from '@storybook/addon-docs/blocks'
|
|
2
|
+
|
|
3
|
+
<Meta title='@dxtmisha/en/functional-basic/Classes/ServerStorage - Data Isolation in SSR'/>
|
|
4
|
+
|
|
5
|
+
# ServerStorage Class
|
|
6
|
+
|
|
7
|
+
`ServerStorage` is a mechanism for managing **isolated global state** in applications with SSR (Server-Side Rendering) support.
|
|
8
|
+
|
|
9
|
+
The class allows you to work with data as easily as with static variables, but ensures that user data on the server does not intermingle between parallel requests.
|
|
10
|
+
|
|
11
|
+
## Key Features
|
|
12
|
+
|
|
13
|
+
- **Request Isolation** — data on the server is bound to the context of the current human or machine request.
|
|
14
|
+
- **Hydration** — ability to automatically transfer state from the server to the client via JSON.
|
|
15
|
+
- **Security** — automatic XSS escaping during data transfer.
|
|
16
|
+
|
|
17
|
+
```typescript
|
|
18
|
+
import { ServerStorage } from '@dxtmisha/functional-basic'
|
|
19
|
+
|
|
20
|
+
// Save data with a hydration flag (will be available on the client)
|
|
21
|
+
ServerStorage.set('theme', () => 'dark', true)
|
|
22
|
+
|
|
23
|
+
// Retrieve data
|
|
24
|
+
const theme = ServerStorage.get('theme') // 'dark'
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Data Access Methods
|
|
28
|
+
|
|
29
|
+
### `get`
|
|
30
|
+
|
|
31
|
+
Retrieves a value by key. If it doesn't exist, creates it using the default value factory.
|
|
32
|
+
|
|
33
|
+
**Parameters:**
|
|
34
|
+
- `key: string` — unique storage key.
|
|
35
|
+
- `defaultValue?: () => T` — function that returns the default value if not found.
|
|
36
|
+
- `hydration: boolean` — if `true`, the value will be included in the JSON for the client (default: `false`).
|
|
37
|
+
|
|
38
|
+
**Returns:** `T`
|
|
39
|
+
|
|
40
|
+
### `set`
|
|
41
|
+
|
|
42
|
+
Saves a value to the storage.
|
|
43
|
+
|
|
44
|
+
**Parameters:**
|
|
45
|
+
- `key: string` — unique storage key.
|
|
46
|
+
- `value: () => T` — function that returns the value to save.
|
|
47
|
+
- `hydration: boolean` — if `true`, the value will be included in the JSON for the client (default: `false`).
|
|
48
|
+
|
|
49
|
+
**Returns:** `T`
|
|
50
|
+
|
|
51
|
+
## Utility & Lifecycle Methods
|
|
52
|
+
|
|
53
|
+
- `init(listener: () => Record<string, any>): typeof ServerStorage` — Initializes the storage with a context listener. On the server, this listener should return an object unique to each request.
|
|
54
|
+
- `has(key: string): boolean` — Checks for the existence of a key in the current context.
|
|
55
|
+
- `remove(key: string): void` — Removes a value by key from the storage.
|
|
56
|
+
- `setErrorStatus(hide: boolean): void` — Sets whether to hide context missing errors in the console/error center.
|
|
57
|
+
- `reset(): void` — Resets the storage, clearing all stored data and the listener. Useful for performing cleanup.
|
|
58
|
+
- `toString(): string` — Generates an HTML `<script type="application/json">` tag containing all data marked for hydration.
|
|
59
|
+
|
|
60
|
+
## Isolation in SSR
|
|
61
|
+
|
|
62
|
+
In standard client-side applications, global state belongs to a single user. However, in an SSR environment, one Node.js process handles many concurrent requests simultaneously. To prevent user data from "leaking" between these requests (State Pollution), `ServerStorage` must be correctly isolated.
|
|
63
|
+
|
|
64
|
+
To achieve this, you must initialize `ServerStorage` with the `init` method. This method accepts a listener function that returns a data object unique to the current request context.
|
|
65
|
+
|
|
66
|
+
> Important: Correct isolation is critical for security. If not configured, data from one user could be served to another.
|
|
67
|
+
|
|
68
|
+
### Node.js (AsyncLocalStorage)
|
|
69
|
+
|
|
70
|
+
The recommended way for Node.js is to use `AsyncLocalStorage` to store context throughout an asynchronous request.
|
|
71
|
+
|
|
72
|
+
```typescript
|
|
73
|
+
import { AsyncLocalStorage } from 'node:async_hooks'
|
|
74
|
+
import { ServerStorage } from '@dxtmisha/functional-basic'
|
|
75
|
+
|
|
76
|
+
const als = new AsyncLocalStorage<Record<string, any>>()
|
|
77
|
+
|
|
78
|
+
// Initialization
|
|
79
|
+
ServerStorage.init(() => als.getStore() || {})
|
|
80
|
+
|
|
81
|
+
// Usage in server
|
|
82
|
+
http.createServer((req, res) => {
|
|
83
|
+
als.run({}, () => {
|
|
84
|
+
// All calls to ServerStorage inside this block will be isolated
|
|
85
|
+
ServerStorage.set('requestId', () => req.id)
|
|
86
|
+
})
|
|
87
|
+
})
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### Nuxt / Nitro
|
|
91
|
+
|
|
92
|
+
In Nuxt/Nitro, isolation is managed via the `h3` event context using `useEvent()` within a server plugin.
|
|
93
|
+
|
|
94
|
+
```typescript
|
|
95
|
+
// server/plugins/server-storage.ts
|
|
96
|
+
import { ServerStorage } from '@dxtmisha/functional-basic'
|
|
97
|
+
|
|
98
|
+
export default defineNitroPlugin(() => {
|
|
99
|
+
ServerStorage.init(() => {
|
|
100
|
+
try {
|
|
101
|
+
return useEvent().context
|
|
102
|
+
} catch {
|
|
103
|
+
return {}
|
|
104
|
+
}
|
|
105
|
+
})
|
|
106
|
+
})
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## Hydration (Transferring Data to Client)
|
|
110
|
+
|
|
111
|
+
Hydration is the process of transferring the application state set on the server to the client. This allows the browser to pick up where the server left off, ensuring consistency and preventing redundant data fetching or "flickering" during page load.
|
|
112
|
+
|
|
113
|
+
### 1. Identify Data for Hydration
|
|
114
|
+
|
|
115
|
+
When using `set()` or `get()`, pass `true` as the third parameter (`hydration`). Only values marked this way will be transferred to the client.
|
|
116
|
+
|
|
117
|
+
```typescript
|
|
118
|
+
// Set on server
|
|
119
|
+
ServerStorage.set('userSettings', () => ({ fontSize: 16 }), true)
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### 2. Injecting State into HTML
|
|
123
|
+
|
|
124
|
+
On the server, you must call `ServerStorage.toString()` and insert its result into your page template (usually at the very end of the `<body>` tag, before your application scripts).
|
|
125
|
+
|
|
126
|
+
This method generates a special script tag:
|
|
127
|
+
```html
|
|
128
|
+
<script id="__ui:server:storage:id__" type="application/json">
|
|
129
|
+
{"userSettings":{"fontSize":16}}
|
|
130
|
+
</script>
|
|
131
|
+
```
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import {Meta} from '@storybook/addon-docs/blocks'
|
|
2
|
+
|
|
3
|
+
<Meta title='@dxtmisha/ru/functional-basic/Classes/ServerStorage - Изоляция данных в SSR'/>
|
|
4
|
+
|
|
5
|
+
# Класс ServerStorage
|
|
6
|
+
|
|
7
|
+
`ServerStorage` — это механизм для управления **изолированным глобальным состоянием** в приложениях с поддержкой SSR (Server-Side Rendering).
|
|
8
|
+
|
|
9
|
+
Класс позволяет работать с данными так же просто, как со статическими переменными, но гарантирует, что на сервере данные разных пользователей не будут смешиваться.
|
|
10
|
+
|
|
11
|
+
## Основные возможности
|
|
12
|
+
|
|
13
|
+
- **Изоляция запросов** — на сервере данные привязываются к контексту текущего HTTP-запроса.
|
|
14
|
+
- **Гидратация** — возможность автоматически передавать состояние с сервера на клиент через JSON.
|
|
15
|
+
- **Безопасность** — автоматическое экранирование XSS при передаче данных.
|
|
16
|
+
|
|
17
|
+
```typescript
|
|
18
|
+
import { ServerStorage } from '@dxtmisha/functional-basic'
|
|
19
|
+
|
|
20
|
+
// Сохранение данных с флагом гидратации (будут доступны на клиенте)
|
|
21
|
+
ServerStorage.set('theme', () => 'dark', true)
|
|
22
|
+
|
|
23
|
+
// Получение данных
|
|
24
|
+
const theme = ServerStorage.get('theme') // 'dark'
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Методы доступа к данным
|
|
28
|
+
|
|
29
|
+
### `get`
|
|
30
|
+
|
|
31
|
+
Извлекает значение по ключу. Если оно не существует, создает его с помощью фабрики значений по умолчанию.
|
|
32
|
+
|
|
33
|
+
**Параметры:**
|
|
34
|
+
- `key: string` — уникальный ключ хранилища.
|
|
35
|
+
- `defaultValue?: () => T` — функция, возвращающая значение по умолчанию, если оно не найдено.
|
|
36
|
+
- `hydration: boolean` — если `true`, значение будет включено в JSON для передачи на клиент (по умолчанию: `false`).
|
|
37
|
+
|
|
38
|
+
**Возвращает:** `T`
|
|
39
|
+
|
|
40
|
+
### `set`
|
|
41
|
+
|
|
42
|
+
Записывает значение в хранилище.
|
|
43
|
+
|
|
44
|
+
**Параметры:**
|
|
45
|
+
- `key: string` — уникальный ключ хранилища.
|
|
46
|
+
- `value: () => T` — функция, возвращающая значение для сохранения.
|
|
47
|
+
- `hydration: boolean` — если `true`, значение будет включено в JSON для передачи на клиент (по умолчанию: `false`).
|
|
48
|
+
|
|
49
|
+
**Возвращает:** `T`
|
|
50
|
+
|
|
51
|
+
## Вспомогательные методы и жизненный цикл
|
|
52
|
+
|
|
53
|
+
- `init(listener: () => Record<string, any>): typeof ServerStorage` — Инициализирует хранилище слушателем контекста. На сервере этот слушатель должен возвращать объект, уникальный для каждого запроса.
|
|
54
|
+
- `has(key: string): boolean` — Проверяет наличие ключа в текущем контексте.
|
|
55
|
+
- `remove(key: string): void` — Удаляет значение по ключу из хранилища.
|
|
56
|
+
- `setErrorStatus(hide: boolean): void` — Устанавливает, нужно ли скрывать ошибки отсутствия контекста в консоли/центре ошибок.
|
|
57
|
+
- `reset(): void` — Сбрасывает хранилище, очищая все сохраненные данные и слушателя. Полезно для выполнения очистки.
|
|
58
|
+
- `toString(): string` — Генерирует HTML-тег `<script type="application/json">` со всеми данными, помеченными для гидратации.
|
|
59
|
+
|
|
60
|
+
## Изоляция в SSR
|
|
61
|
+
|
|
62
|
+
В обычных клиентских приложениях глобальное состояние принадлежит одному пользователю. Однако в среде SSR один процесс Node.js обрабатывает множество одновременных запросов. Чтобы данные пользователей не смешивались между собой (Загрязнение состояния), `ServerStorage` должен быть правильно изолирован.
|
|
63
|
+
|
|
64
|
+
Для этого необходимо инициализировать `ServerStorage` с помощью метода `init`. Он принимает функцию-слушатель, которая возвращает объект данных, уникальный для контекста текущего запроса.
|
|
65
|
+
|
|
66
|
+
> Важно: Правильная изоляция критична для безопасности. Без нее данные одного пользователя могут быть по ошибке переданы другому.
|
|
67
|
+
|
|
68
|
+
### Node.js (AsyncLocalStorage)
|
|
69
|
+
|
|
70
|
+
Рекомендуемый способ для Node.js — использование `AsyncLocalStorage` для сохранения контекста на протяжении асинхронного запроса.
|
|
71
|
+
|
|
72
|
+
```typescript
|
|
73
|
+
import { AsyncLocalStorage } from 'node:async_hooks'
|
|
74
|
+
import { ServerStorage } from '@dxtmisha/functional-basic'
|
|
75
|
+
|
|
76
|
+
const als = new AsyncLocalStorage<Record<string, any>>()
|
|
77
|
+
|
|
78
|
+
// Инициализация
|
|
79
|
+
ServerStorage.init(() => als.getStore() || {})
|
|
80
|
+
|
|
81
|
+
// Использование на сервере
|
|
82
|
+
http.createServer((req, res) => {
|
|
83
|
+
als.run({}, () => {
|
|
84
|
+
// Внутри этого блока все вызовы ServerStorage будут изолированы
|
|
85
|
+
ServerStorage.set('requestId', () => req.id)
|
|
86
|
+
})
|
|
87
|
+
})
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### Nuxt / Nitro
|
|
91
|
+
|
|
92
|
+
В Nuxt/Nitro изоляция управляется через контекст события `h3` с помощью `useEvent()` внутри серверного плагина.
|
|
93
|
+
|
|
94
|
+
```typescript
|
|
95
|
+
// server/plugins/server-storage.ts
|
|
96
|
+
import { ServerStorage } from '@dxtmisha/functional-basic'
|
|
97
|
+
|
|
98
|
+
export default defineNitroPlugin(() => {
|
|
99
|
+
ServerStorage.init(() => {
|
|
100
|
+
try {
|
|
101
|
+
return useEvent().context
|
|
102
|
+
} catch {
|
|
103
|
+
return {}
|
|
104
|
+
}
|
|
105
|
+
})
|
|
106
|
+
})
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## Гидратация (Передача данных клиенту)
|
|
110
|
+
|
|
111
|
+
Гидратация — это процесс передачи состояния приложения, установленного на сервере, клиенту. Это позволяет браузеру «подхватить» данные там, где закончил сервер, обеспечивая согласованность и предотвращая повторные запросы данных или «мерцание» страницы при загрузке.
|
|
112
|
+
|
|
113
|
+
### 1. Пометка данных для гидратации
|
|
114
|
+
|
|
115
|
+
При использовании `set()` или `get()` передайте `true` третьим параметром (`hydration`). Только значения, помеченные таким образом, будут переданы на клиент.
|
|
116
|
+
|
|
117
|
+
```typescript
|
|
118
|
+
// Установка на сервере
|
|
119
|
+
ServerStorage.set('userSettings', () => ({ fontSize: 16 }), true)
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### 2. Вставка состояния в HTML
|
|
123
|
+
|
|
124
|
+
На сервере необходимо вызвать `ServerStorage.toString()` и вставить результат в шаблон страницы (обычно в самый конец тега `<body>`, перед скриптами приложения).
|
|
125
|
+
|
|
126
|
+
Этот метод генерирует специальный тег script:
|
|
127
|
+
```html
|
|
128
|
+
<script id="__ui:server:storage:id__" type="application/json">
|
|
129
|
+
{"userSettings":{"fontSize":16}}
|
|
130
|
+
</script>
|
|
131
|
+
```
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import {Meta} from '@storybook/addon-docs/blocks'
|
|
2
|
+
|
|
3
|
+
<Meta title='@dxtmisha/vi/functional-basic/Classes/ServerStorage - Cách ly dữ liệu trong SSR'/>
|
|
4
|
+
|
|
5
|
+
# Lớp ServerStorage
|
|
6
|
+
|
|
7
|
+
`ServerStorage` là một cơ chế để quản lý **trạng thái toàn cục được cách ly** trong các ứng dụng hỗ trợ SSR (Server-Side Rendering).
|
|
8
|
+
|
|
9
|
+
Lớp này cho phép bạn làm việc với dữ liệu dễ dàng như với các biến tĩnh (static), nhưng đảm bảo rằng dữ liệu người dùng trên máy chủ không bị trộn lẫn giữa các yêu cầu song song.
|
|
10
|
+
|
|
11
|
+
## Các tính năng chính
|
|
12
|
+
|
|
13
|
+
- **Cách ly yêu cầu** — dữ liệu trên máy chủ được liên kết với ngữ cảnh của yêu cầu hiện tại.
|
|
14
|
+
- **Hydration** — khả năng tự động chuyển trạng thái từ máy chủ sang máy khách thông qua JSON.
|
|
15
|
+
- **Bảo mật** — tự động thoát (escape) XSS trong quá trình truyền dữ liệu.
|
|
16
|
+
|
|
17
|
+
```typescript
|
|
18
|
+
import { ServerStorage } from '@dxtmisha/functional-basic'
|
|
19
|
+
|
|
20
|
+
// Lưu dữ liệu với cờ hydration (sẽ có sẵn trên máy khách)
|
|
21
|
+
ServerStorage.set('theme', () => 'dark', true)
|
|
22
|
+
|
|
23
|
+
// Truy xuất dữ liệu
|
|
24
|
+
const theme = ServerStorage.get('theme') // 'dark'
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Các phương thức truy cập dữ liệu
|
|
28
|
+
|
|
29
|
+
### `get`
|
|
30
|
+
|
|
31
|
+
Truy xuất giá trị theo khóa. Nếu không tìm thấy, nó sẽ tạo giá trị mới bằng cách sử dụng factory giá trị mặc định.
|
|
32
|
+
|
|
33
|
+
**Tham số:**
|
|
34
|
+
- `key: string` — khóa lưu trữ duy nhất.
|
|
35
|
+
- `defaultValue?: () => T` — hàm trả về giá trị mặc định nếu không tìm thấy.
|
|
36
|
+
- `hydration: boolean` — nếu là `true`, giá trị sẽ được bao gồm trong JSON cho máy khách (mặc định: `false`).
|
|
37
|
+
|
|
38
|
+
**Trả về:** `T`
|
|
39
|
+
|
|
40
|
+
### `set`
|
|
41
|
+
|
|
42
|
+
Lưu một giá trị vào kho lưu trữ.
|
|
43
|
+
|
|
44
|
+
**Tham số:**
|
|
45
|
+
- `key: string` — khóa lưu trữ duy nhất.
|
|
46
|
+
- `value: () => T` — hàm trả về giá trị để lưu.
|
|
47
|
+
- `hydration: boolean` — nếu là `true`, giá trị sẽ được bao gồm trong JSON cho máy khách (mặc định: `false`).
|
|
48
|
+
|
|
49
|
+
**Trả về:** `T`
|
|
50
|
+
|
|
51
|
+
## Các phương thức tiện ích và vòng đời
|
|
52
|
+
|
|
53
|
+
- `init(listener: () => Record<string, any>): typeof ServerStorage` — Khởi tạo kho lưu trữ với bộ lắng nghe ngữ cảnh. Trên máy chủ, bộ lắng nghe này sẽ trả về một đối tượng duy nhất cho mỗi yêu cầu.
|
|
54
|
+
- `has(key: string): boolean` — Kiếm tra sự tồn tại của một khóa trong ngữ cảnh hiện tại.
|
|
55
|
+
- `remove(key: string): void` — Xóa một giá trị theo khóa khỏi kho lưu trữ.
|
|
56
|
+
- `setErrorStatus(hide: boolean): void` — Thiết lập việc ẩn lỗi thiếu ngữ cảnh trong bảng điều khiển hoặc trung tâm lỗi.
|
|
57
|
+
- `reset(): void` — Đặt lại kho lưu trữ, xóa tất cả dữ liệu đã lưu và bộ lắng nghe. Hữu ích cho việc dọn dẹp.
|
|
58
|
+
- `toString(): string` — Tạo một thẻ HTML `<script type="application/json">` chứa tất cả dữ liệu được đánh dấu để hydration.
|
|
59
|
+
|
|
60
|
+
## Cách ly trong SSR
|
|
61
|
+
|
|
62
|
+
Trong các ứng dụng phía máy khách thông thường, trạng thái toàn cục thuộc về một người dùng duy nhất. Tuy nhiên, trong môi trường SSR, một quy trình Node.js xử lý nhiều yêu cầu đồng thời. Để ngăn chặn dữ liệu của người dùng này "rò rỉ" sang yêu cầu của người dùng khác (Ô nhiễm trạng thái), `ServerStorage` phải được cách ly chính xác.
|
|
63
|
+
|
|
64
|
+
Để đạt được điều này, bạn phải khởi tạo `ServerStorage` bằng phương thức `init`. Phương thức này chấp nhận một hàm lắng nghe trả về một đối tượng dữ liệu duy nhất cho ngữ cảnh yêu cầu hiện tại.
|
|
65
|
+
|
|
66
|
+
> Quan trọng: Việc cách ly chính xác là cực kỳ quan trọng đối với bảo mật. Nếu không được cấu hình, dữ liệu từ người dùng này có thể được cung cấp cho người dùng khác.
|
|
67
|
+
|
|
68
|
+
### Node.js (AsyncLocalStorage)
|
|
69
|
+
|
|
70
|
+
Cách được khuyến nghị cho Node.js là sử dụng `AsyncLocalStorage` để lưu trữ ngữ cảnh trong suốt một yêu cầu không đồng bộ.
|
|
71
|
+
|
|
72
|
+
```typescript
|
|
73
|
+
import { AsyncLocalStorage } from 'node:async_hooks'
|
|
74
|
+
import { ServerStorage } from '@dxtmisha/functional-basic'
|
|
75
|
+
|
|
76
|
+
const als = new AsyncLocalStorage<Record<string, any>>()
|
|
77
|
+
|
|
78
|
+
// Khởi tạo
|
|
79
|
+
ServerStorage.init(() => als.getStore() || {})
|
|
80
|
+
|
|
81
|
+
// Sử dụng trong máy chủ
|
|
82
|
+
http.createServer((req, res) => {
|
|
83
|
+
als.run({}, () => {
|
|
84
|
+
// Tất cả các lệnh gọi đến ServerStorage bên trong khối này sẽ được cách ly
|
|
85
|
+
ServerStorage.set('requestId', () => req.id)
|
|
86
|
+
})
|
|
87
|
+
})
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### Nuxt / Nitro
|
|
91
|
+
|
|
92
|
+
Trong Nuxt/Nitro, việc cách ly được quản lý thông qua ngữ cảnh sự kiện `h3` bằng cách sử dụng `useEvent()` bên trong một plugin máy chủ.
|
|
93
|
+
|
|
94
|
+
```typescript
|
|
95
|
+
// server/plugins/server-storage.ts
|
|
96
|
+
import { ServerStorage } from '@dxtmisha/functional-basic'
|
|
97
|
+
|
|
98
|
+
export default defineNitroPlugin(() => {
|
|
99
|
+
ServerStorage.init(() => {
|
|
100
|
+
try {
|
|
101
|
+
return useEvent().context
|
|
102
|
+
} catch {
|
|
103
|
+
return {}
|
|
104
|
+
}
|
|
105
|
+
})
|
|
106
|
+
})
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## Hydration (Chuyển dữ liệu sang máy khách)
|
|
110
|
+
|
|
111
|
+
Hydration là quá trình chuyển trạng thái ứng dụng được thiết lập trên máy chủ sang máy khách. Điều này cho phép trình duyệt tiếp tục công việc từ nơi máy chủ dừng lại, đảm bảo tính nhất quán và ngăn chặn việc tìm kiếm dữ liệu thừa hoặc hiện tượng "nhấp nháy" (flickering) trong quá trình tải trang.
|
|
112
|
+
|
|
113
|
+
### 1. Xác định dữ liệu để Hydration
|
|
114
|
+
|
|
115
|
+
Khi sử dụng `set()` hoặc `get()`, hãy truyền `true` làm tham số thứ ba (`hydration`). Chỉ những giá trị được đánh dấu theo cách này mới được chuyển sang máy khách.
|
|
116
|
+
|
|
117
|
+
```typescript
|
|
118
|
+
// Thiết lập trên máy chủ
|
|
119
|
+
ServerStorage.set('userSettings', () => ({ fontSize: 16 }), true)
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### 2. Chèn trạng thái vào HTML
|
|
123
|
+
|
|
124
|
+
Trên máy chủ, bạn phải gọi `ServerStorage.toString()` và chèn kết quả của nó vào mẫu trang của bạn (thường ở cuối thẻ `<body>`, trước các tập lệnh ứng dụng của bạn).
|
|
125
|
+
|
|
126
|
+
Phương thức này tạo ra một thẻ script đặc biệt:
|
|
127
|
+
```html
|
|
128
|
+
<script id="__ui:server:storage:id__" type="application/json">
|
|
129
|
+
{"userSettings":{"fontSize":16}}
|
|
130
|
+
</script>
|
|
131
|
+
```
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import {Meta} from '@storybook/addon-docs/blocks'
|
|
2
|
+
|
|
3
|
+
<Meta title='@dxtmisha/en/functional-basic/Classes/StorageCallback - Storage Callbacks'/>
|
|
4
|
+
|
|
5
|
+
# StorageCallback Class
|
|
6
|
+
|
|
7
|
+
A utility class for managing groups of callback functions associated with specific storage keys. It ensures that multiple components or functions can react to storage changes or triggers in a coordinated, asynchronous manner.
|
|
8
|
+
|
|
9
|
+
## Key Features
|
|
10
|
+
|
|
11
|
+
- **Named Instances** — facilitates a singleton-like pattern where instances are retrieved by name and group, ensuring different parts of the application share the same callback list for the same resource.
|
|
12
|
+
- **Group Separation** — allows segregating callback lists by group (e.g., 'main', 'global', 'local'), preventing name collisions between different modules.
|
|
13
|
+
- **Asynchronous Execution** — supports `Promise`-based callbacks and executes them sequentially during the `run` process.
|
|
14
|
+
- **Loading State Tracking** — provides a built-in `loading` flag that is automatically managed during the callback execution phase.
|
|
15
|
+
|
|
16
|
+
## Initialization
|
|
17
|
+
|
|
18
|
+
To initialize the object, call the `StorageCallback(name, group)` constructor or use the static method `getInstance(name, group)`.
|
|
19
|
+
|
|
20
|
+
### Generic Constraints
|
|
21
|
+
|
|
22
|
+
To ensure strict typing, the class supports the following generics:
|
|
23
|
+
- `T = any` — The type of data passed to callbacks.
|
|
24
|
+
- `Callback = (value: T) => void | Promise<void>` — The structure of the callback function.
|
|
25
|
+
|
|
26
|
+
**Parameters:**
|
|
27
|
+
- `name: string` — a unique identifier for the storage entry.
|
|
28
|
+
- `group: string = 'main'` — optional category to prevent name collisions.
|
|
29
|
+
|
|
30
|
+
```typescript
|
|
31
|
+
import { StorageCallback } from '@dxtmisha/functional-basic'
|
|
32
|
+
|
|
33
|
+
// 1. Simple initialization (group defaults to 'main')
|
|
34
|
+
const storage = new StorageCallback('user-data')
|
|
35
|
+
|
|
36
|
+
// 2. Using the singleton-like getInstance method
|
|
37
|
+
const sharedStorage = StorageCallback.getInstance('settings', 'global')
|
|
38
|
+
|
|
39
|
+
// 3. Using generics for strict typing
|
|
40
|
+
const numberStorage = new StorageCallback<number>('counter')
|
|
41
|
+
numberStorage.addCallback((val) => console.log(val + 1))
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Methods
|
|
45
|
+
|
|
46
|
+
### Information
|
|
47
|
+
|
|
48
|
+
- `getName(): string` — returns the storage instance name.
|
|
49
|
+
- `isLoading(): boolean` — returns the current loading state.
|
|
50
|
+
- `getLoading(): boolean` — returns the current loading state (alias for `isLoading`).
|
|
51
|
+
|
|
52
|
+
### Management
|
|
53
|
+
|
|
54
|
+
- `addCallback(callback: Callback, isOnce?: boolean): this` — adds a new callback to the execution list. If `isOnce: true`, the callback will be removed after the first execution.
|
|
55
|
+
- `removeCallback(callback: Callback): this` — removes a specific callback from the list.
|
|
56
|
+
|
|
57
|
+
### Control
|
|
58
|
+
|
|
59
|
+
- `preparation(): this` — prepares the state before execution (sets `loading` to `true`). Should be called manually when starting an asynchronous process.
|
|
60
|
+
- `run(value: T): Promise<this>` — executes all callbacks sequentially with the provided value. Sets `loading` back to `false` at the start of execution.
|
|
61
|
+
|
|
62
|
+
## Usage Examples
|
|
63
|
+
|
|
64
|
+
### Manual Loading Management
|
|
65
|
+
|
|
66
|
+
When data is fetched asynchronously from an external source (e.g., Figma storage), you can manage the `loading` state manually to coordinate multiple requests.
|
|
67
|
+
|
|
68
|
+
```typescript
|
|
69
|
+
const storage = new StorageCallback('figma-data')
|
|
70
|
+
|
|
71
|
+
// 1. Check if it is not already loading
|
|
72
|
+
if (!storage.isLoading()) {
|
|
73
|
+
// 2. Set loading state to true
|
|
74
|
+
storage.preparation()
|
|
75
|
+
|
|
76
|
+
// 3. Request the data
|
|
77
|
+
fetchFromFigma((data) => {
|
|
78
|
+
// 4. Run callbacks (run will reset loading to false)
|
|
79
|
+
storage.run(data)
|
|
80
|
+
})
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### One-time Callback
|
|
85
|
+
|
|
86
|
+
If you only need a function to trigger once (e.g., for initial data hydration), use the `isOnce` flag.
|
|
87
|
+
|
|
88
|
+
```typescript
|
|
89
|
+
const storage = new StorageCallback('initial-data')
|
|
90
|
+
|
|
91
|
+
storage.addCallback((data) => {
|
|
92
|
+
console.log('Executed once:', data)
|
|
93
|
+
}, true)
|
|
94
|
+
|
|
95
|
+
await storage.run('update 1') // 'Executed once: update 1'
|
|
96
|
+
await storage.run('update 2') // (no output, callback removed)
|
|
97
|
+
```
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import {Meta} from '@storybook/addon-docs/blocks'
|
|
2
|
+
|
|
3
|
+
<Meta title='@dxtmisha/ru/functional-basic/Classes/StorageCallback - Обратные вызовы хранилища'/>
|
|
4
|
+
|
|
5
|
+
# Класс StorageCallback
|
|
6
|
+
|
|
7
|
+
Вспомогательный класс для управления группами функций обратного вызова, связанных с конкретными ключами хранилища. Он позволяет нескольким компонентам или функциям реагировать на изменения или триггеры хранилища согласованно и асинхронно.
|
|
8
|
+
|
|
9
|
+
## Основные особенности
|
|
10
|
+
|
|
11
|
+
- **Именованные экземпляры** — реализует паттерн, похожий на синглтон, где экземпляры извлекаются по имени и группе, гарантируя, что разные части приложения используют один и тот же список обратных вызовов для одного и того же ресурса.
|
|
12
|
+
- **Разделение по группам** — позволяет разделять списки обратных вызовов по группам (например, 'main', 'global', 'local'), предотвращая конфликты имен между различными модулями.
|
|
13
|
+
- **Асинхронное выполнение** — поддерживает асинхронные обратные вызовы и выполняет их последовательно в процессе вызова `run`.
|
|
14
|
+
- **Отслеживание состояния загрузки** — предоставляет встроенный флаг `loading`, который автоматически переключается во время фазы выполнения обратных вызовов.
|
|
15
|
+
|
|
16
|
+
## Инициализация
|
|
17
|
+
|
|
18
|
+
Для инициализации объекта вызовите конструктор `StorageCallback(name, group)` или используйте статический метод `getInstance(name, group)`.
|
|
19
|
+
|
|
20
|
+
### Ограничения типов (Generics)
|
|
21
|
+
|
|
22
|
+
Для обеспечения строгой типизации класс поддерживает следующие параметры:
|
|
23
|
+
- `T = any` — тип данных, передаваемых в обратные вызовы.
|
|
24
|
+
- `Callback = (value: T) => void | Promise<void>` — структура функции обратного вызова.
|
|
25
|
+
|
|
26
|
+
**Параметры:**
|
|
27
|
+
- `name: string` — уникальный идентификатор для записи в хранилище.
|
|
28
|
+
- `group: string = 'main'` — необязательная категория для предотвращения конфликтов имен.
|
|
29
|
+
|
|
30
|
+
```typescript
|
|
31
|
+
import { StorageCallback } from '@dxtmisha/functional-basic'
|
|
32
|
+
|
|
33
|
+
// 1. Простая инициализация (группа по умолчанию 'main')
|
|
34
|
+
const storage = new StorageCallback('user-data')
|
|
35
|
+
|
|
36
|
+
// 2. Использование статического метода getInstance
|
|
37
|
+
const sharedStorage = StorageCallback.getInstance('settings', 'global')
|
|
38
|
+
|
|
39
|
+
// 3. Использование generic-типов для строгой типизации
|
|
40
|
+
const numberStorage = new StorageCallback<number>('counter')
|
|
41
|
+
numberStorage.addCallback((val) => console.log(val + 1))
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Методы
|
|
45
|
+
|
|
46
|
+
### Информация
|
|
47
|
+
|
|
48
|
+
- `getName(): string` — возвращает имя экземпляра хранилища.
|
|
49
|
+
- `isLoading(): boolean` — возвращает текущее состояние загрузки.
|
|
50
|
+
- `getLoading(): boolean` — возвращает текущее состояние загрузки (аналог `isLoading`).
|
|
51
|
+
|
|
52
|
+
### Управление
|
|
53
|
+
|
|
54
|
+
- `addCallback(callback: Callback, isOnce?: boolean): this` — добавляет новый обратный вызов в список выполнения. При `isOnce: true` callback будет удален после первого выполнения.
|
|
55
|
+
- `removeCallback(callback: Callback): this` — удаляет конкретный обратный вызов из списка.
|
|
56
|
+
|
|
57
|
+
### Управление процессом (Control)
|
|
58
|
+
|
|
59
|
+
- `preparation(): this` — подготавливает состояние перед выполнением (устанавливает `loading` в `true`). Используется вручную при запуске асинхронных операций.
|
|
60
|
+
- `run(value: T): Promise<this>` — последовательно выполняет все обратные вызовы с переданным значением. В начале выполнения устанавливает `loading` в `false`.
|
|
61
|
+
|
|
62
|
+
## Примеры использования
|
|
63
|
+
|
|
64
|
+
### Ручное управление состоянием загрузки
|
|
65
|
+
|
|
66
|
+
Если данные загружаются асинхронно из внешнего источника (например, Figma storage), вы можете управлять состоянием `loading` вручную.
|
|
67
|
+
|
|
68
|
+
```typescript
|
|
69
|
+
const storage = new StorageCallback('figma-data')
|
|
70
|
+
|
|
71
|
+
// 1. Проверяем, не идет ли уже загрузка
|
|
72
|
+
if (!storage.isLoading()) {
|
|
73
|
+
// 2. Устанавливаем состояние загрузки
|
|
74
|
+
storage.preparation()
|
|
75
|
+
|
|
76
|
+
// 3. Запрашиваем данные
|
|
77
|
+
fetchFromFigma((data) => {
|
|
78
|
+
// 4. Выполняем колбэки (run сбросит loading в false)
|
|
79
|
+
storage.run(data)
|
|
80
|
+
})
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### Одноразовый обратный вызов
|
|
85
|
+
|
|
86
|
+
Если вам нужно, чтобы функция сработала только один раз (например, для начальной загрузки данных), используйте флаг `isOnce`.
|
|
87
|
+
|
|
88
|
+
```typescript
|
|
89
|
+
const storage = new StorageCallback('initial-data')
|
|
90
|
+
|
|
91
|
+
storage.addCallback((data) => {
|
|
92
|
+
console.log('Выполнено один раз:', data)
|
|
93
|
+
}, true)
|
|
94
|
+
|
|
95
|
+
await storage.run('update 1') // 'Выполнено один раз: update 1'
|
|
96
|
+
await storage.run('update 2') // (ничего не выводится, callback удален)
|
|
97
|
+
```
|