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

quick-model

v0.3.0

Published

data modeling with serialization

Downloads

7

Readme

quick-model

It provides serialization and deserialization using a defined data model. That's it.

What is it for?

Mapping data from A to B.

E.g. your database query returns snake_cased keys and embedded relationships but you want to send it to the client with camelCase keys and sideloaded relationships. quick-model can do that.

Another usecase is a client sends data to your server in a client-friendly format and you need to 'deserialize' it into yet another format and insert it into some 3rd party database like a SalesForce table with a wacky__c schema.

Quick install:

npm install quick-model

Quick model setup:

const {
  Model,
  Transforms
} = require('quick-model');

const {
  attr,
  one
} = Model;

const {
  stringTransform
} = Transforms;

const personModel = new Model({
  name: attr(stringTransform)
});

const bookModel = new Model({
  title: attr(stringTransform),

  author: one(personModel)
});

Quick serializer setup:

Imagine your database query returns an object (continuing the example above) :

const book = await db.books.findByTitle('foundation');
console.log(book);
// {
//   book_title: 'Foundation',
//   book_author: {
//     full_name: 'Isaac Asimov'
//   }
// }

Notice the differences between db result and defined model.
database -> model
book_title -> title
book_author -> author
full_name -> name

This is where quick-model shines. Let us make a quick serializer!

const { Serializer } = require('quick-model');

const personSerializer = new Serializer({
  model: personModel,

  keyForNonSerializedAttribute(attribute) {
    const { name } = attribute;

    // attribute.name is the key you defined when creating an attr() in your model.
    if (name === 'name') {
      return 'full_name';
    }

    // default behavior
    return name;
  }
});

const bookSerializer = new Serializer({
  model: bookModel,

  serializers: {
    author: personSerializer
  },

  keyForNonSerializedAttribute(attribute) {
    const { name } = attribute;

    return `book_${name}`;
  },

  keyForNonSerializedRelationship(relationship) {
    const { name } = relationship;

    if (name === 'author') {
      return 'book_author';
    }

    return name;
  }
});

Now you can call bookSerializer.serialize(dataFromDatabase).
It will properly extract the fields from the raw data and , by default, return an object that resembles how the model was defined:

bookSerializer.serialize({
  book_title: 'Foundation',
  book_author: {
    full_name: 'Isaac Asimov'
  }
});
// returns:
{
  title: 'Foundation',
  author: {
    name: 'Isaac Asimov'
  }
}

This is a simple example. But you can model some really unfriendly data and serialize it into something friendly :)

Full docs coming as soon...

Some ideas I'd personally like to explore (or see explored) in future:

  • Building a JSON API Serializer
  • Building an XML Serializer

TODO FOR 1.0:

  • [x] implement primaryKey in model and write tests!

  • [x] create a map-compact util & test

  • [x] tests working for both directories: lib, utils

  • [x] test for deserializeAttribute, keyForDeserializedRelationship

  • [x] test for serialize

  • [x] test for deserialize

  • [ ] Cache for camelize and underscore

  • [ ] tests for camelize and underscore

  • move utils into files that represent the data type they operate on/with

    • [x] array
    • [x] string
    • [ ] function
    • [ ] object
  • [ ] deepAssign when overwriting transform's deserializer, serializer, and validator objects. I.e. don't overwrite entire object, just merge the defined properties

deepAssign({ serializer: { foo: bar } }, { serializer: { baz: 'boo' } })
// returns:
{ serializer: {
    foo: 'bar',
    baz: 'boo'
  }
}
  • [ ] in each directory, combine tests for that directory and place in tests/ directory relative to where each test currently is

  • [x] split deserialize, serialize, and normalize functionality into separate mixins

  • [x] re-organize serializer tests into the appropriate mixins/tests/*-test.js file

  • [x] { include: [], exclude: [] } options support during serialize, deserialize, and normalize

  • [x] serializer.serialize/deserialize should accept a hash of 3rd party serializers in the event of embedded relationships. So that serializing an embedded relationship can use the correct serializer.

  • [x] serializer.normalize

  • [ ] accept hash of filter functions that can be applied to attributes or relationships.e.g. { filters: { password(x) { return x.replace('.+', '*') } } }