• Stars
    star
    119
  • Rank 297,930 (Top 6 %)
  • Language
    JavaScript
  • License
    MIT License
  • Created over 9 years ago
  • Updated about 7 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Effortless data model versioning for Javascript and Node.js

Vers Build Status

Effortless data model versioning for Javascript and Node.js

Why do I need model versioning?

  • Support versioned REST APIs without cluttering your API code with an endpoint for every individual version
  • Only code against the latest version of your data -- no messy if-statements throughout your codebase to check for earlier versions or properties in different places
  • Update your backends and your frontends on their own schedules
  • Roll out new schemas and update your code for the new changes independently, without coordinating a precise rollout, and with no downtime
  • For the love of all things holy stop trying to update every record in your document store every time you update your data model. Every time you pull a new record from your database, just call toLatest on it. Done. If you save it, it saves as the new version. If you don't, it stays the old version and saves you the bandwidth/request time. Your code only ever deals with the latest version and you never scan through and update your entire database ever again. Doesn't that feel better?

Quick start

const Vers = require('vers')
const baseUser = {
  version: 1,
  firstName: 'Doug',
  lastName: 'Funnie'
}
const userVers = new Vers()

// Tell Vers how to convert from version 1 to version 2, and back again.
// We could also use "1.0.1" to "2.4.3", 100 to 200, or "cow" to "chicken"
userVers.addConverter(1, 2, obj => {
  // Version 2 has user initials
  obj.version = 2
  obj.initials = obj.firstName[0] + obj.lastName[0]
}, obj => {
  // Version 1 does not
  obj.version = 1
  delete obj.initials
})

// And now to go from version 2 to version 3 and back
userVers.addConverter(2, 3, obj => {
  // Version 3 combines the names into a single name field 
  obj.version = 3
  obj.name = obj.firstName + ' ' + obj.lastName
  delete obj.firstName
  delete obj.lastName
}, obj => {
  // To go back to version 2, we'd need to split them up again
  obj.version = 2
  const names = obj.name.split(' ')
  obj.firstName = names[0]
  obj.lastName = names.pop()
  delete obj.name
})

userVers.toLatest(baseUser).then(user => {
  // user is now:
  // {
  //   version: 3,
  //   initials: 'DF',
  //   name: 'Doug Funnie'
  // }
  return userVers.to(1, user)
}).then(user => {
  // user is back to the original version defined in baseUser
})

Installation

Vers requires an environment that supports the Promise/A+ specification as standardized in ES6. Node.js version 0.12.0 and up is great right out of the box (no --harmony flag necessary), as well as the latest versions of many browsers. To support older browsers, just include a Promise library such as Bluebird.

To install, just type:

npm install vers --save

API

new Vers([options])

Function options.getVersion: A function that accepts an object as its only argument, and returns either the current version identifier of the object as a number or string, or a Promise that resolves to the current version identifier. By default, Vers will use the object's version property if it exists, or 1 if it doesn't.
number|string options.latest: The latest version identifier available for this model. If not specified, Vers will detect the latest version by calling Math.max on each version specified in addConverter(). For string-based versions, this option should be specified.

Constructs a new instance of Vers. Each data model should have one instance to define all of its versions. The options object is optional.

addConverter(fromVer, toVer, forward, [back])

number|string fromVer: The version to convert from
number|string toVer: The version to convert to
Function forward: A function that accepts an object to be converted, and moves it from fromVer to toVer.
Function back: An optional function that accepts an object and moves it from toVer to fromVer.

Adds a converter to this instance that knows how to change an object from one version to another, and optionally, how to go back again. If you're using Vers to power a versioned REST API, then telling it how to go back again is essential. If your versioning scheme uses numbers, Vers will use Math.max to determine what your latest version is so you don't have to specify that in the constructor.

Vers is smart: if you need to upgrade from Version 1 to Version 5, it will upgrade from 1 to 2, then from 2 to 3, and so on up to 5, assuming that you've added converters for each of those. However, if you add a converter that shortcuts that in any way to jump over some of those versions, Vers will always find the shortest path possible to the target -- even if that means upgrading from 1 to 6, then downgrading to 5.

Note that the forward and back functions are called with the object to be converted as their only argument. These functions can:

  • modify the object directly and return nothing
  • return a new object
  • return a Promise that resolves with the modified or new object

Any method is fine! But keep in mind: modifying the object directly will also modify the source object. Vers doesn't clone your objects.

fromTo(fromVer, toVer, obj)

Returns a Promise that resolves to an Object
number|string fromVer: The starting version
number|string toVer: The target version
Object obj: The object to be converted

Converts an object from one version to another, using the provided fromVer as the current version instead of trying to detect it. The result is passed on in the form of a Promise that resolves with the object in its target version.

fromToLatest(fromVer, obj)

Returns a Promise that resolves to an Object
number|string fromVer: The starting version
Object obj: The object to be converted

Converts an object from its current version to the latest version available, using the provided fromVer as the current version instead of trying to detect it. The result is passed on in the form of a Promise that resolves with the object in its target version.

to(toVer, obj)

Returns a Promise that resolves to an Object
number|string toVer: The target version
Object obj: The object to be converted

Converts an object from its auto-detected current version to the toVer version. The result is passed on in the form of a Promise that resolves with the object in its target version.

toLatest(obj)

Returns a Promise that resolves to an Object
Object obj: The object to be converted

Converts an object from its auto-detected current version to the latest version available. The result is passed on in the form of a Promise that resolves with the object in its target version.

License

Vers is licensed under the MIT license. Please see LICENSE.txt for full details.

Credits

Vers was originally created at TechnologyAdvice in Nashville, TN.

More Repositories

1

Jexl

Javascript Expression Language: Powerful context-based expression parser and evaluator
JavaScript
520
star
2

Cryptex

Secure secret storage and cryptographic key retrieval for Node.js
JavaScript
141
star
3

Bristol

Insanely configurable logging for Node.js
JavaScript
112
star
4

Squiss

High-volume Amazon SQS Poller for Node.js
JavaScript
97
star
5

node-phonetic

Generates unique, pronounceable names, random and seedable
JavaScript
81
star
6

Hydrogen

Hydrogen is a PHP 5.3+ performance and portability library
PHP
40
star
7

node-attempt

Automatically retry functions that fail, in crazily customizable ways.
JavaScript
37
star
8

node-vitalsigns

Powerful and customizable application health monitoring
JavaScript
27
star
9

fs_eventbridge

A TCP server to stream file-change events to a remote destination, written in Rust.
Rust
23
star
10

DevBox

🐳 A minimal bootstrapper to turn a brand new Mac into a docker-based dev environment
Shell
21
star
11

FlushWritable

A Node.js Writable stream that flushes before emitting finish
JavaScript
15
star
12

Embassy

🎏 Simple JSON Web Tokens (JWT) with embedded scopes for services
TypeScript
12
star
13

Semlocks

Mind-blowingly simple local resource management for Node.js
JavaScript
11
star
14

Hydrogen-MVC-Starter

A project template for using Hydrogen as an MVC framework
PHP
11
star
15

Toady

Wickedly extensible IRC bot written in Node.js. Load and reload mods without reconnecting.
JavaScript
8
star
16

MindEye

A proof-of-concept drawing recognition app.
JavaScript
4
star
17

DeepSea-Storm

A color scheme for IDEA-based *Storm IDEs.
4
star
18

fake-mocha

Run arbitrary commands instead of mocha to integrate with popular IDEs
JavaScript
4
star
19

fsbridge

A command-line client to stream file changes to an FS-EventBridge server
JavaScript
3
star
20

frost-zsh-prompt

Distinct, informative, and fast ZSH prompt
Shell
2
star
21

dotfiles

Mostly original configs, totally original installer. Compatible with macOS and various Linuxes.
Shell
2
star
22

node-argsnip

Snips arguments off of callback functions.
JavaScript
1
star
23

alpine-node-dind-compat

An alpine-node docker image, including automatic compatibility with linked docker-in-docker containers.
1
star
24

toady-github

Toady module: Provides details on Github repositories
JavaScript
1
star
25

RPi-LED-Matrix

A Raspberry Pi animator for 3x3 LED grids, with button input
Python
1
star
26

Imp

IMP: IRC Modularized Preprocessor. A Java-based single-channel IRC helper bot.
Java
1
star
27

fs-eventbridge-js

Node.js client for the FS-EventBridge server
JavaScript
1
star
28

toady-acrophobia

Toady module: A game to turn acronyms into funny phrases
JavaScript
1
star