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

factoryb

v0.3.3

Published

A simple JSON based fixture solution

Downloads

20

Readme

Build Status Stories in Ready

NPM

About FactoryB

FactoryB is a fixture solution for Node.js using simple JSON object storing and mutating. FactoryB is inspired by frustrations with other Node.js fixture solutions that, themselves, were inspired by Factory_Girl (from ThoughtBot).

FactoryB is a dictionary that does two simple things:

  1. It stores JSON objects under string keys and
  2. Allows you to apply changes to those objects when you retrieve them.

The following examples are provided in CoffeeScript.

Simple Usage

The simplest way you can use FactoryB is requiring it,

FactoryB = require 'FactoryB'

instantiating an instance without arguments,

bee = new FactoryB

using its set() method with one JSON argument,

jsonArgument =
  fire: 'hot'
  ice: 'cold'

bee.set jsonArgument

and then retrieving that JSON object with get().

console.log bee.get()

# OUTPUT> {fire: 'hot', ice: 'cold'}

Storing More Than One JSON Object

FactoryB stores JSON dictionary entries under the key 'default' when it is not given a key. So the following:

bee = new FactoryB
bee.set jsonArgument

is the same as:

bee = new FactoryB
bee.set 'default', jsonArgument

Likewise, FactoryB's get() uses the 'default' key when not given a key. So, the following:

bee.get

is the same as:

bee.get 'default'

If we want to store more JSON we can store it under other keys,

jsonArgument2 =
  fire: 'cold'
  ice: 'hot'

bee.set 'oppositeWorld', jsonArgument2

and then retrieve it using those keys:

console.log bee.get('oppositeWorld')

# OUTPUT> {fire: 'cold', ice: 'hot'}

'default' can still be accessed just like before:

console.log bee.get()
console.log bee.get('default')

# OUTPUT> {fire: 'hot', ice: 'cold'}
# OUTPUT> {fire: 'hot', ice: 'cold'}

Setting JSON with the Constructor

FactoryB's constructor will also accept a JSON object, using its keys and subobject values to populate the dictionary:

bee = new FactoryB
  default: jsonArgument
  oppositeWorld: jsonArgument2

Retrieval is the same:

console.log bee.get()
console.log bee.get('default')
console.log bee.get('oppositeWorld')

# OUTPUT> {fire: 'hot', ice: 'cold'}
# OUTPUT> {fire: 'hot', ice: 'cold'}
# OUTPUT> {fire: 'cold', ice: 'hot'}

Changing JSON Through the get() Method

FactoryB's get() method will accept a JSON object with values to change for the keys provided. The returned JSON will reflect the change.

console.log bee.get('oppositeWorld', fire: 'DARK')

# OUTPUT> {fire: 'DARK', ice: 'hot'}

FactoryB protects your objects from being passed by reference. The JSON you give FactoryB is cloned before set() saves and when get() retrieves; so, changes do not affect either FactoryB's state or any of the arguments you pass it.

console.log jsonArgument2
console.log bee.get('oppositeWorld')

# OUTPUT> {fire: 'cold', ice: 'hot'}
# OUTPUT> {fire: 'cold', ice: 'hot'}

When given JSON without a key, get() retrieves what is under the 'default' key and changes it accordingly:

console.log bee.get()
console.log bee.get(ice: 'MELTED')

# OUTPUT> {fire: 'hot', ice: 'cold'}
# OUTPUT> {fire: 'hot', ice: 'MELTED'}

Creating Dynamic Values Using Functions

When JSON objects are retrieved using the get method any functions in the object are run and replaced with their return values.

ones = 1
twos = 2

numberWang =
  ones: -> ones += ones
  twos: -> twos + twos
numberBee = new FactoryB default: numberWang
console.log numberBee.get()
# OUTPUT> {ones: 2, twos:4}
console.log numberBee.get()
# OUTPUT> {ones: 4, twos:4}

Variables scoped outside these functions can be changed to change the results of the functions.

ones = 1
twos = 5
console.log numberBee.get()
# OUTPUT> {ones: 2, twos:10}

Functions are also passed the previous value in the chain of mutators allowing programmatic changes.

dogs =
  description: "dog list"
  dogs: [
    "Snoopy"
  ]

addScooby =
  dogs: (prev)->
    prev.push "Scooby"
    return prev

pound = new FactoryB default: dogs
console.log pound.get()
console.log pound.get addScooby

# OUTPUT> {description: "dog list", dogs: ["Snoopy", "Scooby"]}

If one wants to replace a sub-object with a whole different object by wrapping the new object in a function:

dogsFoods =
  description: 'dog foods'
  dogs: dog: 'dog food'

specific =
  dogs:->
    Scooby: 'Scooby Snacks'
    Snoopy: 'Peanuts'

store = new FactoryB default: dogsFoods

console.log store.get()
console.log store.get 'default', specific

Chaining Saved JSON as Changes to Retrieved JSON

FactoryB's get() method will accept multiple JSON objects applying them in the order given.

time =
  fire: 'out'
  ice: 'melted'

reignite =
  fire: 'HOT'

console.log bee.get('default', time, reignite)

# OUTPUT> {fire: 'HOT', ice: 'melted'}

When it doesn't get a key first, it still assumes changes are to default.

console.log bee.get(time, reignite)

# OUTPUT> {fire: 'HOT', ice: 'melted'}

When given keys, the get() method will use JSON objects it has saved at those keys.

bee.set 'time', time
bee.set 'reignite', reignite

console.log bee.get('default', 'time', 'reignite')

# OUTPUT> {fire: 'HOT', ice: 'melted'}

get() will also mix and match accordingly.

console.log bee.get('default', time, 'reignite')

# OUTPUT> {fire: 'HOT', ice: 'melted'}

Managing Multiple Factories With The Constructor

The FactoryB constructor will track any factories that are instantiated with a name string, which can then be retrieved using get() on the contructor.

honeyBee = new FactoryB 'honeyBee', default: collects: 'honey'
fireBee = new FactoryB 'fireBee', default: collects: 'fire'

console.log FactoryB.get('honeyBee').get()
console.log FactoryB.get('fireBee').get()

# OUTPUT> {collects: 'honey'}
# OUTPUT> {collects: 'fire'}

The FactoryB constructor also has a set() method, if you decide you want the constructor to track it after instantiation.

iceBee = new FactoryB default: collects: 'ice'
FactoryB.set 'iceBee', iceBee

console.log FactoryB.get('iceBee').get()

# OUTPUT> {collects: 'ice'}

With require's caching, stored factories can be retrieved anywhere you can use require to get the FactoryB constructor.

console.log require('FactoryB').get('honeyBee').get()

Recent Fixes

  • 04/28/2014: Addressed problem in mutating arrays
  • 04/03/2014: Addressed problem in mutating Dates

Future Features

  • Better array handling
  • Knowing its model
  • Knowing how its model should be instantiated
  • Knowing how its model should be saved
  • Object relationship handling