json-storage-formatter 3.0.0 β†’ 3.0.2

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 (2) hide show
  1. package/README.md +201 -87
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -1,131 +1,245 @@
1
- # json-storage-formatter
1
+ # json-storage-formatter 🌟
2
2
 
3
- Package for json stringify objects without losing data types. The transformation of the data includes extra metadata into the resulted string which later on is used to restored all the data structures to the their origninal forms.
3
+ ![Image John Avatar](https://raw.githubusercontent.com/johnny-quesada-developer/global-hooks-example/main/public/avatar2.jpeg)
4
4
 
5
- The library suppors Sets, Maps, Objects, Arrays, and Primitive data like Dates
5
+ A **lightweight solution** to format complex JavaScript objects for string-based storage systems **without losing their types**. πŸš€
6
6
 
7
- # API
7
+ ## πŸ€” The Problem?
8
8
 
9
- The main methods of the library are **formatToStore** and **formatFromStore**
10
-
11
- ## formatToStore
9
+ ```ts
10
+ const userProfile = {
11
+ id: 42,
12
+ createdAt: new Date('2024-10-01T10:30:00Z'),
13
+ preferences: new Map([
14
+ ['theme', 'dark'],
15
+ ['languages', new Set(['en', 'es'])],
16
+ ]),
17
+ };
18
+
19
+ console.log(JSON.stringify(userProfile, null, 2));
20
+ ```
12
21
 
13
- Format an object to be stored as JSON
22
+ **Console Output:**
14
23
 
15
- ```TS
16
- const objectWithMetadata = formatToStore(object);
17
-
18
- // The result can be JSON.stringify
19
- console.log(objectWithMetadata);
20
- /*
24
+ ```json
21
25
  {
22
- $t: 'map',
23
- $v: [
24
- [
25
- 'key1',
26
- {
27
- $t: 'date',
28
- $v: '2021-05-08T13:30:00.000Z',
29
- },
30
- ],
31
- [
32
- 'key2',
33
- {
34
- $t: 'set',
35
- $v: [
36
- {
37
- $t: 'map',
38
- $v: [
39
- [
40
- 'key1',
41
- {
42
- $t: 'date',
43
- $v: '2021-05-08T13:30:00.000Z',
44
- },
45
- ],
46
- ],
47
- },
48
- ],
49
- },
50
- ],
51
- ],
26
+ "id": 42,
27
+ "createdAt": "2024-10-01T10:30:00.000Z",
28
+ "preferences": {}
52
29
  }
53
- */
30
+ ```
54
31
 
55
- // you can also stringify directly the result by specifying it on the configuration parameter
56
- const objectString = formatToStore(object, { stringify: true });
32
+ When working with tools like **localStorage**, **sessionStorage**, **AsyncStorage**, or even databases like **Redis** or **PostgreSQL (JSON columns)**, we often need to store application state or configuration objects as strings using `JSON.stringify`.
57
33
 
58
- console.log(objectString); // {"$t":"map","$v":[["key1",{"$t":"date","$v":"2021-05-08T13:30:00.000Z"}],["key2",{"$t":"set","$v":[{"$t":"map","$v":[["key1",{"$t":"date","$v":"2021-05-08T13:30:00.000Z"}]]}]}]]}
34
+ _But there’s a catch!:_
59
35
 
60
- ```
36
+ `JSON.stringify` has no idea what to do with values like `Date`, `Map`, or `Set`...
37
+ It just flattens them into empty objects or strings, making you lose the original data types or the entire structure.
61
38
 
62
- ## formatFromStore<T>
39
+ ---
63
40
 
64
- Format a value with possible metadata to his original form, it also supports Map, Set, Arrays
41
+ ## πŸ’‘ What json-storage-formatter Does
65
42
 
66
- ```TS
67
- const object = formatFromStore<Map<string, unknown>>(objectWithMetadata);
43
+ Exposes **two simple functions**:
68
44
 
69
- // Original types of the object with metadata
70
- console.log(object);
45
+ 1. `formatToStore(value)` β†’ safely prepares your data for storage, returning a JSON string representation.
46
+ 2. `formatFromStore(value)` β†’ restores it to the **exact original shape and types**.
71
47
 
72
- /*
73
- // the result will be the same than executing the following code
74
- const formatFromStoreResultExample = new Map([
75
- ['key1', new Date('2021-05-08T13:30:00.000Z')],
76
- [
77
- 'key2',
78
- new Set([new Map([['key1', new Date('2021-05-08T13:30:00.000Z')]])]),
79
- ],
80
- ]);
81
- */
82
- ```
48
+ As simple as that.
49
+
50
+ # Let’s see a couple of examples
51
+
52
+ ---
83
53
 
84
- ## clone
54
+ ## βš™οΈ Example: useDashboardConfig Hook
85
55
 
86
- Deep clone an object, it also suppors Map, Set, Arrays.
87
- The formatters clones the objects to avoid modify the parameter reference
56
+ Let’s create a hook that syncs `localStorage` with React state:
88
57
 
89
58
  ```ts
90
- const clone: <T>(obj: T) => T;
59
+ import { formatToStore, formatFromStore } from 'json-storage-formatter';
60
+
61
+ type DashboardConfig = {
62
+ theme: 'light' | 'dark' | 'system';
63
+ widgets: Map<string, WidgetConfig>;
64
+ hiddenWidgets: Set<string>;
65
+ lastCustomizedAt: Date;
66
+ };
67
+
68
+ const useDashboardConfig = () => {
69
+ const [config, setConfig] = useState<DashboardConfig>(() => {
70
+ const json = localStorage.getItem('dashboard-config');
71
+
72
+ if (json) return formatFromStore<DashboardConfig>(json);
73
+
74
+ return getDefaultDashboardConfig();
75
+ });
76
+
77
+ const saveConfig = (newConfig: DashboardConfig) => {
78
+ localStorage.setItem('dashboard-config', formatToStore(newConfig));
79
+ setConfig(newConfig);
80
+ };
81
+
82
+ return { config, saveConfig };
83
+ };
84
+
85
+ // Even if the config contains Maps, Sets, or Dates, they will be preserved.
86
+ const example: DashboardConfig = {
87
+ theme: 'dark',
88
+ widgets: new Map([
89
+ ['weather', { location: 'New York', units: 'metric' }],
90
+ ['stocks', { symbols: ['AAPL', 'GOOGL'] }],
91
+ ]),
92
+ hiddenWidgets: new Set(['news']),
93
+ lastCustomizedAt: new Date(),
94
+ };
91
95
  ```
92
96
 
93
- ## isNil
97
+ ---
94
98
 
95
- Check if a value is null or undefined
99
+ ## 🌐 Example: Sync Dashboard Queries Through URL (Dashboards / Reports)
96
100
 
97
- ```ts
98
- const isNil: (value: unknown) => boolean;
101
+ This pattern is common in dashboards, where filters are shared via URL.
102
+ You can safely serialize complex filters (with Dates, Sets, Maps, etc.) and encode them for sharing.
103
+
104
+ ```tsx
105
+ import { formatToStore, formatFromStore } from 'json-storage-formatter';
106
+
107
+ type DashboardQuery = {
108
+ dateRange: { from: Date; to: Date };
109
+ selectedCategories: Set<string>;
110
+ additionalSettings: Map<string, unknown>;
111
+ };
112
+
113
+ const useUrlQuery = () => {
114
+ const [query, setQuery] = useState<DashboardQuery>(() => {
115
+ const params = new URLSearchParams(location.search);
116
+ const storedQuery = params.get('query');
117
+
118
+ if (storedQuery) {
119
+ // decode from base64 and restore types
120
+ return formatFromStore<DashboardQuery>(atob(storedQuery));
121
+ }
122
+
123
+ return getDefaultDashboardQuery();
124
+ });
125
+
126
+ const updateQuery = (newQuery: DashboardQuery) => {
127
+ const encoded = btoa(formatToStore(newQuery));
128
+
129
+ // encode the JSON as base64 to make it URL-safe
130
+ // avoids breaking query strings with +, /, or = characters
131
+ window.history.replaceState(null, '', `\${location.pathname}?query=\${encoded}`);
132
+
133
+ setQuery(newQuery);
134
+ };
135
+
136
+ return { query, updateQuery };
137
+ };
99
138
  ```
100
139
 
101
- ## isNumber
140
+ The examples above use React, but the library itself is **framework-agnostic**
141
+ and can be used anywhere in JavaScript or TypeScript projects.
102
142
 
103
- Check if a value is a number
143
+ ---
104
144
 
105
- ```ts
106
- const isNumber: (value: unknown) => boolean;
145
+ ## 🧩 Why It’s Useful
146
+
147
+ This becomes incredibly powerful when your app needs to **sync complex state**
148
+ to a string-based storage layer β€” like when syncing to **localStorage**, **Redis**, or a **shared dashboard URL**.
149
+
150
+ Instead of being limited by what JSON can handle,
151
+ you can now serialize **any structure** β€” Maps, Sets, nested objects, or Dates β€”
152
+ and restore it back without losing context or meaning.
153
+
154
+ ---
155
+
156
+ ## 🧠 How It Works
157
+
158
+ Under the hood, `formatToStore` adds small metadata markers to every special value.
159
+ Each piece of data gets a structure like this:
160
+
161
+ ```json
162
+ {
163
+ "$t": "map",
164
+ "$v": [["key", { "$t": "date", "$v": "2024-10-01T10:30:00.000Z" }]]
165
+ }
107
166
  ```
108
167
 
109
- ## isBoolean
168
+ The `$t` field stores the **type**, and `$v` holds the actual value.
169
+ When using `formatFromStore`, it reads that metadata and recreates your data structure
170
+ exactly as it was before β€” even if it’s deeply nested.
110
171
 
111
- Check if a value is a boolean
172
+ Resulting in:
112
173
 
113
174
  ```ts
114
- const isBoolean: (value: unknown) => boolean;
175
+ new Map([['key', new Date('2024-10-01T10:30:00.000Z')]]);
115
176
  ```
116
177
 
117
- ## isString
178
+ ---
179
+
180
+ ## βš™οΈ API Reference
181
+
182
+ ### 🟣 formatToStore
118
183
 
119
- Check if a value is a string
184
+ Converts any value into a JSON-safe structure with internal type metadata.
120
185
 
121
186
  ```ts
122
- const isString: (value: unknown) => boolean;
187
+ const objectWithMetadata = formatToStore(object);
123
188
  ```
124
189
 
125
- ## isDate
190
+ ### πŸ”΅ formatFromStore<T>
126
191
 
127
- Check if a value is a Date
192
+ Restores the serialized object back to its original types.
128
193
 
129
194
  ```ts
130
- const isDate: (value: unknown) => boolean;
195
+ const result = formatFromStore<Map<string, unknown>>(objectWithMetadata);
196
+ ```
197
+
198
+ Both functions work directly with strings,
199
+ so you can safely use them with localStorage, AsyncStorage, or URLs.
200
+
201
+ ---
202
+
203
+ ## 🧰 Utility Functions
204
+
205
+ | Function | Description | Example |
206
+ | ------------- | ---------------------------------------- | ----------------------------- |
207
+ | **isNil** | Checks if value is `null` or `undefined` | `isNil(null); // true` |
208
+ | **isNumber** | Checks if value is a number | `isNumber(42); // true` |
209
+ | **isBoolean** | Checks if value is a boolean | `isBoolean(false); // true` |
210
+ | **isString** | Checks if value is a string | `isString('hi'); // true` |
211
+ | **isDate** | Checks if value is a Date | `isDate(new Date()); // true` |
212
+
213
+ ---
214
+
215
+ ## βš–οΈ Comparison
216
+
217
+ | Behavior | JSON.stringify | json-storage-formatter |
218
+ | ------------- | --------------- | ------------------------ |
219
+ | **Date** | Becomes string | βœ… Restored as Date |
220
+ | **Set** | Lost completely | βœ… Restored as Set |
221
+ | **Map** | Lost completely | βœ… Restored as Map |
222
+ | **Undefined** | Omitted | βœ… Restored as undefined |
223
+ | **Regexp** | Lost completely | βœ… Restored as RegExp |
224
+ | **Error** | Lost completely | βœ… Restored as Error |
225
+
226
+ ---
227
+
228
+ ## πŸ“¦ Installation
229
+
230
+ ```bash
231
+ npm install json-storage-formatter
131
232
  ```
233
+
234
+ or
235
+
236
+ ```bash
237
+ yarn add json-storage-formatter
238
+ ```
239
+
240
+ ---
241
+
242
+ ## 🎯 Ready to Try It?
243
+
244
+ πŸ“˜ **NPM:** [json-storage-formatter](https://www.npmjs.com/package/json-storage-formatter)
245
+ Serialize, store, and restore **any JavaScript data type** without losing its identity β€” lightweight, fast. ✨
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "json-storage-formatter",
3
- "version": "3.0.0",
3
+ "version": "3.0.2",
4
4
  "description": "Package for json stringify objects without losing data types",
5
5
  "main": "./bundle.js",
6
6
  "types": "./index.d.ts",