npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

isopod

v0.5.1

Published

Universal (isomorphic) Javascript object serialization / deserialization

Downloads

64

Readme

Coverage Status

About

Have you ever wanted to clone an object (including all its methods and prototyped goodness) from one Javascript runtime to another?

This library will, you know, do that.

Getting started

When using it in node.js, you could:

npm install isopod

...and from your node source code do:

const isopod = require('isopod');

When using from the browser, download it, then in your html include a <script> pointing to the correct file. The script will make isopod a global variable.

For example you might run:

npm install isopod

...and then you might put this in your html (assuming the node_modules directory is statically served to the client):

<script src="/isopod/dist/isopod.min.js"></script>

...and now isopod would be a global variable available to any subsequent client scripts.

What does it include?

isopod has but two methods: serialize and deserialize.

Why would I use it?

Normally when you send some Javascript data from one program (e.g. your server) to another (e.g. your client) it loses "richness". Functions, regular expressions, circular objects, objects with non-standard prototypes—all of these things would not normally transfer over.

One way to think about why this happens is that any data that gets sent somewhere else by your Javascript program will (basically) need to get converted into a string, and is generally converted back into data (parsed) on the receiving end. Commonly the sender will JSON.stringify the data and the receiver will JSON.parse the incoming string.

This means that Javascript objects get converted into JSON strings, which are only natively equipped to represent plain objects, plain arrays, strings, numbers, booleans, and null.

isopod.serialize converts anything more complex than that into a plain object so that it can be stringified. Importantly this plain, "dehydrated", object still contains all the information necessary to reconstruct the details of the original. As such, when parsed on the other end, we should get a clone of the dehydrated object. isopod.deserialize can "rehydrate" this into a clone of the original.

Any change that occurs to the cloned object will not affect the original and vice-versa. Those objects exist in different runtimes and cannot directly affect each other. If you want automated synchronization, isopod is not that, though you could build something like that "on top" of it.

With isopod you can remotely clone:

  • Plain objects, arrays, strings, numbers, booleans, and null (these are no different than what you can do without isopod)
  • undefined, ±Infinity, and NaN
  • Functions (but not closures, nor bound functions)
  • Regular expressions
  • Errors
  • Dates
  • Symbols
  • Sets
  • Maps
  • Anything with a non-standard prototype
  • Anything with circular or duplicate references to the same object or symbol
  • Array buffers / typed arrays / data views

Note that cloning will exclude non-enumerable properties (except for the .constructor property—this in order to clone prototypes effectively). Here's a not-necessarily complete list of what you might not yet be able to clone:

  • Promises¹
  • Generators
  • Proxies

¹ The plan is never to support cloning promises—it involves cloning too much hairy state for a non-obvious use case. If you're looking to resolve any values on an object, you could do so and then pass the result to isopod.serialize. Check out bluebird's Promise.props or even promise-resolve-deep for help resolving inside an object.

How would I use it?

Install and include isopod into both environments: client and server, one iframe and another iframe, tessel and electron app—whatever two Javascript runtimes you want to clone data between.

Then for any data you'd like to "richly clone", just before sending it across call isopod.serialize on it. Just after parsing the data on the other end call isopod.deserialize on it.

For example, you might have an express route handler on your node server that looks like:

...
// an example of some data that is sufficiently complex
function Thing (names) {
  this.self = this;
  this.names = new Set(names);
}
Thing.prototype.jump = function () {
  this.state = 'jumping';
};
const thing = new Thing(['robert', 'bob', 'rob']);
...
app.get('/thing', function (req, res, next) {
  const serialized = isopod.serialize(thing);
  res.json(serialized);
});
...

And an AJAX request on your client that looks like:

...
fetch('/thing')
.then(function (response) {
  return response.json();
})
.then(function (jsonObj) {
  const deserialized = isopod.deserialize(jsonObj);
  // should now be able to do the following
  deserialized.names.has('bob'); // => true
  deserialized.jump();
  console.log(deserialized.state); // 'jumping'
  console.log(deserialized.self === deserialized); // true
});
...

For something more concrete, you can find runnable examples in the examples folder.

Similar libraries

Contributing

Pull requests / issues / comments / hate mail welcome!

If you'd like to run the tests, download this repo, open a terminal, navigate to it, then run:

npm install

...and once that's done:

npm test