json-storage-formatter 3.0.0 β†’ 3.0.1

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