flightcontrolhq / superjson

Safely serialize JavaScript expressions to a superset of JSON, which includes Dates, BigInts, and more.
https://www.flightcontrol.dev?ref=superjson
MIT License
4.01k stars 87 forks source link

Transfer ownership to Blitz.js #5

Closed matthewmueller closed 4 years ago

matthewmueller commented 4 years ago

@flybayer is interested in taking over this project for use in Blitz.js. He aims to maintain backwards compatibility with the existing API, but bring new features like Maps & Sets.

The thinking currently is to add the following API:

const [string, metadata] = superjson.stringifyWithMetadata({})

// optional 2nd argument for metadata
const data = superjson.parse(string, metadata) 

@flybayer, do you mind sharing a bit more about how metadata is used? Currently with superjson all the metadata is encoded into the data itself. Have you run into a situation where that doesn't work?

flybayer commented 4 years ago

Thanks @matthewmueller!

For context, here's the discussion in the Blitz repo: https://github.com/blitz-js/legacy-framework/issues/695

The extra metadata is required to revive Map (serialized as object) and Set (serialized as array). Additionally it's needed for Dates and timestamps. When parsing, it's impossible to know if a timestamp should be converted to a Date or left as string without knowing how it started.

For example, in a Blitz app the types in the frontend are often derived from the types in the database. So if a timestamp is stored as string, the type must be a string when deserialized in the frontend. And likewise if the timestamp is stored as a date in the database.

With this new API, we will send both the serialized json and the metadata to the frontend where it can be correctly deserialized.

Regarding the API

I just realized there's a slight difference here between what superjson currently does and what we need. Currently superjson converts objects to a string and back. But we don't need that, what we need is serializing Javascript to a plain object and then converting plain objects back to Javascript.

So actually we need to add this:

// json, meta are plain objects without Date/Map/Set
const {json, meta} = superjson.serialize(input)

// output is Javascript with Date/Map/Set
const output = superjson.deserialize(json, meta)
matthewmueller commented 4 years ago

Not knowing if the result of "2020-06-30T13:17:17.187Z" should be a string or a Date makes a lot of sense. Differentiating these data types wasn't a requirement for us at the time.

I think picking alternative methods is the right way forward. I like serialize/deserialize or encode/decode. The old methods can be de-emphasized and perhaps removed in a later major release.

I've added you to the NPM package and Github. If you'd like to transfer this repository to the blitz-js repo, let me know.

flybayer commented 4 years ago

@matthewmueller awesome, thanks! And yes, it'd be great to transfer it to the blitz-js Github org.

matthewmueller commented 4 years ago

Looks like I don't have permission to do this. I've given you admin rights so you can move it yourself.