json-storage-formatter 3.0.1 β†’ 3.0.3

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 +189 -118
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -1,26 +1,22 @@
1
- const README = `
2
-
3
1
  # json-storage-formatter 🌟
4
2
 
5
- ![Image John Avatar](https://raw.githubusercontent.com/johnny-quesada-developer/global-hooks-example/main/public/avatar2.jpeg)
6
-
7
- A **lightweight solution** to store complex JavaScript values as JSON β€” **without losing their types**. πŸš€
8
-
9
- ---
10
-
11
- ## πŸ€” The Problem
12
-
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`.
15
-
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.
3
+ <div align="center">
4
+ <img src="https://raw.githubusercontent.com/johnny-quesada-developer/global-hooks-example/main/public/avatar2.jpeg" width="100" alt="John Avatar" />
18
5
 
19
- Let’s see an example.
6
+ <br />
7
+ <b>Type-safe serialization for any JavaScript object.<br />
8
+ Store and restore Maps, Sets, Dates, RegExps, Errors, and more.<br />
9
+ <br />
10
+ <i>One line. No data loss. No headaches.</i> πŸš€</b>
11
+ <br /><br />
12
+ <a href="https://www.npmjs.com/package/json-storage-formatter"><img src="https://img.shields.io/npm/v/json-storage-formatter.svg" /></a>
13
+ <a href="https://www.npmjs.com/package/json-storage-formatter"><img src="https://img.shields.io/npm/dm/json-storage-formatter.svg" /></a>
14
+ <a href="LICENSE"><img src="https://img.shields.io/npm/l/json-storage-formatter.svg" /></a>
15
+ </div>
20
16
 
21
17
  ---
22
18
 
23
- ### πŸ” Example: Losing Real Data
19
+ ## 🎯 The Problem
24
20
 
25
21
  ```ts
26
22
  const userProfile = {
@@ -45,47 +41,127 @@ console.log(JSON.stringify(userProfile, null, 2));
45
41
  }
46
42
  ```
47
43
 
48
- What happened?
44
+ **JSON.stringify** loses all type information for Dates, Maps, Sets, RegExps, and more. Your data is flattened, and restoring it is impossible.
45
+
46
+ ---
47
+
48
+ <div align="center">
49
+ <b>json-storage-formatter lets you serialize <i>any</i> JavaScript value for storage,<br />
50
+ and restore it to its original type β€” <i>automatically</i>.</b>
51
+ </div>
52
+
53
+ ---
54
+
55
+ ## πŸš€ Why Use This Library?
49
56
 
50
- - The **Date** turned into a string.
51
- - The **Map** disappeared.
52
- - The **Set** vanished inside the Map.
57
+ ## 🟒 Quick Start
53
58
 
54
- If we try to restore it:
59
+ ### Instantly Store and Restore Complex Data
55
60
 
56
61
  ```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
62
+ import { formatToStore, formatFromStore } from 'json-storage-formatter';
63
+
64
+ // Imagine you want to save this to localStorage, a URL, or a DB:
65
+ const userProfile = {
66
+ id: 42,
67
+ createdAt: new Date('2024-10-01T10:30:00Z'),
68
+ preferences: new Map([
69
+ ['theme', 'dark'],
70
+ ['languages', new Set(['en', 'es'])],
71
+ ]),
72
+ };
73
+
74
+ // Serialize for storage (preserves all types!)
75
+ const stored = formatToStore(userProfile);
76
+ localStorage.setItem('profile', stored);
77
+
78
+ // ...later, or in another environment:
79
+ const loaded = localStorage.getItem('profile');
80
+ const restored = formatFromStore<typeof userProfile>(loaded);
81
+
82
+ // restored.createdAt is a Date
83
+ // restored.preferences is a Map with a Set inside
60
84
  ```
61
85
 
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.
86
+ // Works for any structure: deeply nested, with Dates, Sets, Maps, RegExps, Errors, undefined, NaN, etc.
66
87
 
67
88
  ---
68
89
 
69
- ## πŸ’‘ What json-storage-formatter Does
90
+ ## 🟣 Complex Types Example
70
91
 
71
- Exposes **two simple functions**:
92
+ ```ts
93
+ const complex = {
94
+ date: new Date('2024-10-01T10:30:00Z'),
95
+ set: new Set(['a', 'b']),
96
+ map: new Map([
97
+ ['x', 1],
98
+ ['y', 2],
99
+ ]),
100
+ regex: /abc/i,
101
+ error: new Error('fail'),
102
+ undef: undefined,
103
+ nan: NaN,
104
+ inf: Infinity,
105
+ };
72
106
 
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**.
107
+ const stored = formatToStore(complex);
108
+ const restored = formatFromStore<typeof complex>(stored);
109
+ // All types are preserved!
110
+ ```
75
111
 
76
- As simple as that.
112
+ ---
77
113
 
78
- # Let’s see it a couple of examples
114
+ ### πŸ”’ Type-Safe Storage
79
115
 
80
- ---
116
+ Store and restore Maps, Sets, Dates, RegExps, Errors, and more β€” not just plain objects.
81
117
 
82
- ## βš™οΈ Example: useDashboardConfig hook
118
+ ```ts
119
+ import { formatToStore, formatFromStore } from 'json-storage-formatter';
120
+
121
+ const original = new Map([
122
+ ['created', new Date('2024-10-01T10:30:00Z')],
123
+ ['tags', new Set(['a', 'b'])],
124
+ ]);
125
+
126
+ const json = formatToStore(original); // string for storage
127
+ const restored = formatFromStore<Map<string, unknown>>(json);
128
+ ```
129
+
130
+ ### ⚑ No Boilerplate
83
131
 
84
- Let’s create a hook that sync localStorage with react state:
132
+ Just call `formatToStore` before saving, and `formatFromStore` when loading. No config, no setup, no custom revivers.
85
133
 
86
134
  ```ts
135
+ localStorage.setItem('profile', formatToStore(profile));
136
+ const profile = formatFromStore(localStorage.getItem('profile'));
137
+ ```
138
+
139
+ ---
140
+
141
+ ## πŸ› οΈ How It Works
142
+
143
+ `formatToStore` adds a tiny type marker to every special value:
144
+
145
+ ```json
146
+ {
147
+ "$t": "map",
148
+ "$v": [["key", { "$t": "date", "$v": "2024-10-01T10:30:00.000Z" }]]
149
+ }
150
+ ```
151
+
152
+ When you call `formatFromStore`, it reads those markers and reconstructs the original types β€” even deeply nested.
153
+
154
+ ---
155
+
156
+ ## ✨ Real-World Examples
157
+
158
+ ### 1️⃣ React: Syncing Complex State to localStorage
159
+
160
+ ```tsx
161
+ import { useState } from 'react';
87
162
  import { formatToStore, formatFromStore } from 'json-storage-formatter';
88
163
 
164
+ type WidgetConfig = { location: string; units: string };
89
165
  type DashboardConfig = {
90
166
  theme: 'light' | 'dark' | 'system';
91
167
  widgets: Map<string, WidgetConfig>;
@@ -93,30 +169,26 @@ type DashboardConfig = {
93
169
  lastCustomizedAt: Date;
94
170
  };
95
171
 
96
- const useDashboardConfig = () => {
172
+ function useDashboardConfig() {
97
173
  const [config, setConfig] = useState<DashboardConfig>(() => {
98
174
  const json = localStorage.getItem('dashboard-config');
99
-
100
- if (json) return formatFromStore<DashboardConfig>(json);
101
-
102
- return getDefaultDashboardConfig();
175
+ return json ? formatFromStore<DashboardConfig>(json) : getDefaultDashboardConfig();
103
176
  });
104
177
 
105
178
  const saveConfig = (newConfig: DashboardConfig) => {
106
179
  localStorage.setItem('dashboard-config', formatToStore(newConfig));
107
-
108
180
  setConfig(newConfig);
109
181
  };
110
182
 
111
183
  return { config, saveConfig };
112
- };
184
+ }
113
185
 
114
- // Even if the config contains Maps, Sets, or Dates, they will be preserved.
186
+ // Usage
115
187
  const example: DashboardConfig = {
116
188
  theme: 'dark',
117
189
  widgets: new Map([
118
190
  ['weather', { location: 'New York', units: 'metric' }],
119
- ['stocks', { symbols: ['AAPL', 'GOOGL'] }],
191
+ ['stocks', { location: 'NASDAQ', units: 'USD' }],
120
192
  ]),
121
193
  hiddenWidgets: new Set(['news']),
122
194
  lastCustomizedAt: new Date(),
@@ -125,12 +197,10 @@ const example: DashboardConfig = {
125
197
 
126
198
  ---
127
199
 
128
- ## 🌐 Example: Sync dashboard queries through URL (Dashboards / Reports)
129
-
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.
200
+ ### 2️⃣ React: Syncing Filters via URL (Shareable Dashboard Queries)
132
201
 
133
202
  ```tsx
203
+ import { useState } from 'react';
134
204
  import { formatToStore, formatFromStore } from 'json-storage-formatter';
135
205
 
136
206
  type DashboardQuery = {
@@ -139,86 +209,60 @@ type DashboardQuery = {
139
209
  additionalSettings: Map<string, unknown>;
140
210
  };
141
211
 
142
- const useUrlQuery = () => {
212
+ function useUrlQuery() {
143
213
  const [query, setQuery] = useState<DashboardQuery>(() => {
144
- const params = new URLSearchParams(location.search);
214
+ const params = new URLSearchParams(window.location.search);
145
215
  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();
216
+ return storedQuery ? formatFromStore<DashboardQuery>(atob(storedQuery)) : getDefaultDashboardQuery();
153
217
  });
154
218
 
155
219
  const updateQuery = (newQuery: DashboardQuery) => {
156
220
  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
-
221
+ window.history.replaceState(null, '', `${window.location.pathname}?query=${encoded}`);
161
222
  setQuery(newQuery);
162
223
  };
163
224
 
164
225
  return { query, updateQuery };
165
- };
226
+ }
166
227
  ```
167
228
 
168
- The examples above are in react but the library is framework-agnostic and can be used anywhere in JavaScript or TypeScript projects.
169
-
170
- ## 🧩 Why It’s Useful
171
-
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
229
  ---
180
230
 
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:
231
+ ### 3️⃣ Framework-Agnostic: Node.js/Backend Example
185
232
 
186
- ```json
187
- {
188
- "$t": "map",
189
- "$v": [["key", { "$t": "date", "$v": "2024-10-01T10:30:00.000Z" }]]
190
- }
191
- ```
233
+ ```js
234
+ // Save and load any structure in Redis, PostgreSQL, or files
235
+ const { formatToStore, formatFromStore } = require('json-storage-formatter');
192
236
 
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.
237
+ const session = {
238
+ userId: 123,
239
+ expires: new Date(),
240
+ permissions: new Set(['read', 'write']),
241
+ };
196
242
 
197
- Resulting on:
243
+ // Store in Redis
244
+ redis.set('session:123', formatToStore(session));
198
245
 
199
- ```ts
200
- new Map([['key', new Date('2024-10-01T10:30:00.000Z')]]);
246
+ // Later...
247
+ const raw = await redis.get('session:123');
248
+ const restored = formatFromStore(raw);
249
+ // restored.expires is a Date, restored.permissions is a Set
201
250
  ```
202
251
 
203
252
  ---
204
253
 
205
- ## βš™οΈ API Reference
254
+ ## 🧩 Supported Types
206
255
 
207
- ### 🟣 formatToStore
208
-
209
- Converts any value into a JSON-safe structure with internal type metadata.
210
-
211
- ```ts
212
- const objectWithMetadata = formatToStore(object);
213
- ```
214
-
215
- ### πŸ”΅ formatFromStore<T>
216
-
217
- Restores the serialized object back to its original types.
218
-
219
- ```ts
220
- const result = formatFromStore<Map<string, unknown>>(objectWithMetadata);
221
- ```
256
+ | Type | Supported? | Restored As |
257
+ | ------------ | ---------- | --------------- |
258
+ | Date | βœ… | Date |
259
+ | Set | βœ… | Set |
260
+ | Map | βœ… | Map |
261
+ | RegExp | βœ… | RegExp |
262
+ | Error | βœ… | Error |
263
+ | undefined | βœ… | undefined |
264
+ | NaN/Infinity | βœ… | number |
265
+ | Function | ❌ | (not supported) |
222
266
 
223
267
  ---
224
268
 
@@ -236,13 +280,14 @@ const result = formatFromStore<Map<string, unknown>>(objectWithMetadata);
236
280
 
237
281
  ## βš–οΈ Comparison
238
282
 
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 |
283
+ | Behavior | JSON.stringify | json-storage-formatter |
284
+ | ------------- | --------------- | ------------------------ |
285
+ | **Date** | Becomes string | βœ… Restored as Date |
286
+ | **Set** | Lost completely | βœ… Restored as Set |
287
+ | **Map** | Lost completely | βœ… Restored as Map |
288
+ | **Undefined** | Omitted | βœ… Restored as undefined |
289
+ | **Regexp** | Lost completely | βœ… Restored as RegExp |
290
+ | **Error** | Lost completely | βœ… Restored as Error |
246
291
 
247
292
  ---
248
293
 
@@ -252,9 +297,35 @@ const result = formatFromStore<Map<string, unknown>>(objectWithMetadata);
252
297
  npm install json-storage-formatter
253
298
  ```
254
299
 
300
+ ```bash
301
+ yarn add json-storage-formatter
302
+ ```
303
+
255
304
  ---
256
305
 
257
- ## 🎯 Ready to Try It?
306
+ ## πŸ“ API Reference
307
+
308
+ ### formatToStore(value)
309
+
310
+ Converts any value into a JSON-safe string with type metadata.
311
+
312
+ ### formatFromStore<T>(string)
313
+
314
+ Restores the serialized string back to its original types.
315
+
316
+ ---
317
+
318
+ ## πŸ’‘ Pro Tips
319
+
320
+ - Use with any storage: localStorage, sessionStorage, AsyncStorage, Redis, PostgreSQL JSON columns, URLs, etc.
321
+ - Works with deeply nested structures.
322
+ - Framework-agnostic: use in React, Node.js, or vanilla JS/TS.
323
+
324
+ ---
258
325
 
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. ✨
326
+ <div align="center">
327
+ <b>Serialize, store, and restore <i>any</i> JavaScript data type β€”<br />
328
+ without losing its identity. Lightweight. Fast. Reliable.</b>
329
+ <br /><br />
330
+ <a href="https://www.npmjs.com/package/json-storage-formatter">⭐ Try it on NPM</a>
331
+ </div>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "json-storage-formatter",
3
- "version": "3.0.1",
3
+ "version": "3.0.3",
4
4
  "description": "Package for json stringify objects without losing data types",
5
5
  "main": "./bundle.js",
6
6
  "types": "./index.d.ts",