+1
-1
| export { uneval } from './src/uneval.js'; | ||
| export { parse, unflatten } from './src/parse.js'; | ||
| export { stringify } from './src/stringify.js'; | ||
| export { stringify, stringifyAsync } from './src/stringify.js'; | ||
| export { DevalueError } from './src/utils.js'; |
+1
-1
| { | ||
| "name": "devalue", | ||
| "description": "Gets the job done when JSON.stringify can't", | ||
| "version": "5.7.1", | ||
| "version": "5.8.0", | ||
| "repository": "sveltejs/devalue", | ||
@@ -6,0 +6,0 @@ "sideEffects": false, |
+20
-0
@@ -16,2 +16,3 @@ # devalue | ||
| - custom types via replacers, reducers and revivers | ||
| - promises (via `stringifyAsync`) | ||
@@ -30,2 +31,3 @@ Try it out [here](https://svelte.dev/repl/138d70def7a748ce9eda736ef1c71239?version=3.49.0). | ||
| - Stringifying functions | ||
| - Stability of serialization mechanisms between versions (i.e. if you `devalue.stringify` with one version and `devalue.parse` with another, things may break) | ||
@@ -72,2 +74,20 @@ ## Usage | ||
| ### `stringifyAsync` | ||
| `stringifyAsync` is an async version of `stringify` that can handle promises: | ||
| ```js | ||
| import * as devalue from 'devalue'; | ||
| let obj = { | ||
| quick: 'data', | ||
| slow: fetch('/api/slow').then((r) => r.json()) | ||
| }; | ||
| let stringified = await devalue.stringifyAsync(obj); | ||
| devalue.parse(stringified); // { quick: 'data', slow: { ... } } | ||
| ``` | ||
| Promises are awaited and their resolved values are serialized. The output format is identical to `stringify`, so `parse` and `unflatten` work unchanged. | ||
| ### `unflatten` | ||
@@ -74,0 +94,0 @@ |
+70
-4
@@ -28,2 +28,50 @@ import { | ||
| export function stringify(value, reducers) { | ||
| const stringified = run(false, value, reducers); | ||
| return typeof stringified === 'string' ? stringified : `[${stringified.join(',')}]`; | ||
| } | ||
| /** | ||
| * Turn a value into a JSON string that can be parsed with `devalue.parse` | ||
| * @param {any} value | ||
| * @param {Record<string, (value: any) => any>} [reducers] | ||
| */ | ||
| export async function stringifyAsync(value, reducers) { | ||
| const stringified = run(true, value, reducers); | ||
| if (typeof stringified === 'string') { | ||
| return stringified; | ||
| } | ||
| let out = '['; | ||
| for (let i = 0; i < stringified.length; i += 1) { | ||
| let value = stringified[i]; | ||
| if (typeof value !== 'string') { | ||
| await value; | ||
| value = stringified[i]; | ||
| if (i === 0 && value < 0) { | ||
| return `${value}`; | ||
| } | ||
| } | ||
| out += value; | ||
| if (i < stringified.length - 1) { | ||
| out += ','; | ||
| } | ||
| } | ||
| out += ']'; | ||
| return out; | ||
| } | ||
| /** | ||
| * @param {boolean} async | ||
| * @param {any} value | ||
| * @param {Record<string, (value: any) => any>} [reducers] | ||
| */ | ||
| function run(async, value, reducers) { | ||
| /** @type {any[]} */ | ||
@@ -48,4 +96,7 @@ const stringified = []; | ||
| /** @param {any} thing */ | ||
| function flatten(thing) { | ||
| /** | ||
| * @param {any} thing | ||
| * @param {number} [index] | ||
| */ | ||
| function flatten(thing, index) { | ||
| if (thing === undefined) return UNDEFINED; | ||
@@ -59,3 +110,3 @@ if (Number.isNaN(thing)) return NAN; | ||
| const index = p++; | ||
| index ??= p++; | ||
| indexes.set(thing, index); | ||
@@ -77,2 +128,3 @@ | ||
| /** @type {string | Promise<any>} */ | ||
| let str = ''; | ||
@@ -82,2 +134,16 @@ | ||
| str = stringify_primitive(thing); | ||
| } else if (typeof thing.then === 'function') { | ||
| if (!async) { | ||
| throw new DevalueError( | ||
| `Cannot stringify a Promise or thenable — use stringifyAsync instead`, | ||
| keys, | ||
| thing, | ||
| value | ||
| ); | ||
| } | ||
| str = Promise.resolve(thing).then((value) => { | ||
| const i = flatten(value, index); | ||
| if (i < 0) stringified[index] = i; | ||
| }); | ||
| } else { | ||
@@ -326,3 +392,3 @@ const type = get_type(thing); | ||
| return `[${stringified.join(',')}]`; | ||
| return stringified; | ||
| } | ||
@@ -329,0 +395,0 @@ |
+10
-5
@@ -7,7 +7,2 @@ declare module 'devalue' { | ||
| export function uneval(value: any, replacer?: (value: any, uneval: (value: any) => string) => string | void): string; | ||
| /** | ||
| * Turn a value into a JSON string that can be parsed with `devalue.parse` | ||
| * | ||
| */ | ||
| export function stringify(value: any, reducers?: Record<string, (value: any) => any>): string; | ||
| export class DevalueError extends Error { | ||
@@ -33,2 +28,12 @@ /** | ||
| export function unflatten(parsed: number | any[], revivers?: Record<string, (value: any) => any>): any; | ||
| /** | ||
| * Turn a value into a JSON string that can be parsed with `devalue.parse` | ||
| * | ||
| */ | ||
| export function stringify(value: any, reducers?: Record<string, (value: any) => any>): string; | ||
| /** | ||
| * Turn a value into a JSON string that can be parsed with `devalue.parse` | ||
| * | ||
| */ | ||
| export function stringifyAsync(value: any, reducers?: Record<string, (value: any) => any>): Promise<string>; | ||
@@ -35,0 +40,0 @@ export {}; |
@@ -6,12 +6,13 @@ { | ||
| "uneval", | ||
| "stringify", | ||
| "DevalueError", | ||
| "parse", | ||
| "unflatten" | ||
| "unflatten", | ||
| "stringify", | ||
| "stringifyAsync" | ||
| ], | ||
| "sources": [ | ||
| "../src/uneval.js", | ||
| "../src/stringify.js", | ||
| "../src/utils.js", | ||
| "../src/parse.js" | ||
| "../src/parse.js", | ||
| "../src/stringify.js" | ||
| ], | ||
@@ -24,4 +25,4 @@ "sourcesContent": [ | ||
| ], | ||
| "mappings": ";;;;;iBAsBgBA,MAAMA;;;;;iBCINC,SAASA;cCbZC,YAAYA;;;;;;;;;;;;;;iBCGTC,KAAKA;;;;;iBASLC,SAASA", | ||
| "mappings": ";;;;;iBAsBgBA,MAAMA;cCTTC,YAAYA;;;;;;;;;;;;;;iBCGTC,KAAKA;;;;;iBASLC,SAASA;;;;;iBCCTC,SAASA;;;;;iBAUHC,cAAcA", | ||
| "ignoreList": [] | ||
| } |
51128
4.79%1350
4.57%249
8.73%