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 🙏

© 2025 – Pkg Stats / Ryan Hefner

refract-cli

v0.5.0

Published

A command-line utility to reshape objects. Destructuring assignment on steroids.

Downloads

5

Readme

Refract

Build Status

Refract is a command-line utility to reshape objects to a template.

// object
{
    "id": "5768", 
    "customer": "Stijn Debrouwere", 
    "subtotal": 200, 
    "handling": 10 
}
// template
{
    "id": "parseInt id", 
    "uid": "dasherize customer", 
    "tax": "subtotal * 0.21", 
    "total": "subtotal + handling + tax"
}
// result
{
    "id": 5768, 
    "uid": "stijn-debrouwere", 
    "tax": 42, 
    "total": 252
}

Think of it as destructuring assignment on steroids.

Installation

Install refract using the NPM package manager which comes bundled with node.js.

npm install refract-cli -g

This will make the refract command globally available on your system. You can also use the refract-cli module in node.js, as detailed below.

Usage

Refract takes data and modifies it according to a template.

Templates are JSON or YAML objects containing keys and expressions. Each expression will be evaluated and the resulting object will be returned.

There are many ways to specify a template:

| option | description | example | ------------------- | -------------------------------------- | ------- | --template | a path to a YAML or JSON template file | --template template.yml | --string | a string with interpolations | --string 'hello #{name}' | --template-string | a template string | --template-string 'head: uppercase title' | --apply | a list of mapping functions | --apply title:uppercase

While --template is recommended for most purposes, --apply works really well for quick refractions, as do --string and --template-string. They save you the bother of needing to have a refraction template on disk.

--template

refract order.json --template template.json

--string

With --string you pass a simple string. Output can become dynamic by including placeholders for interpolation.

refract bio.json --string 'Hello #{name}! You are #{age - 20} years over twenty.'

--template-string

With --template-string, you pass the actual template as a string of YAML of JSON instead of a path to a template file.

refract order.json --template-string 'total: subtotal + tax'
{
    "total": ..., 
}

--apply

Use --apply to apply a helper function to a field. The helper function will receive the current value of the field as its only argument.

refract order.json --apply total:parseInt,title:titleize

Mapping fields with --apply is considerably less flexible than using templates, but when all you need to do is clean up or modify a couple of fields in a straightforward way, it does the trick.

Use --update to keep fields that were not transformed in the output.

Expressions

Refract will evaluate every value in the template object as CoffeeScript code, or if that fails, as a string with string interpolation. Every expression is then replaced with its result.

Variables:

book.author

Math:

handling + subtotal * 1.21

String interpolation:

Dr. #{name.first} #{name.last}

Plain strings:

Hello world.

Explicit strings:

'Hello world.'

Arrays:

[1, 2, 3]

Methods:

participants.join ', '

Functions:

titleize permalink

Because, in this limited environment, almost all valid JavaScript is also valid CoffeeScript, you can get away with just writing expressions in JavaScript if you'd prefer:

{
    // CoffeeScript
    "slug": "(slugify title).toUpperCase()", 
    // JavaScript
    "slug": "slugify(title).toUpperCase();"
}

Helpers

Available context includes the object itself as well as numerous helper functions loaned from underscore and underscore.string. Please take a look at their documentation to find out which helper functions are available to you.

Because the keys of your data object can sometimes override helpers (for example, you might have a where key that clashes with underscore's where function), underscore functions are also available under the _ namespace, underscore.string functions under the _.str namespace.

// template that calls titleize with and without namespacing
{
    "slug": "dr-livingstone-i-presume", 
    "title": "titleize slug", 
    "alternative-title": "_.str.titleize slug"
}
// resulting in two identical titles
{
    "title": "Dr Livingstone I Presume", 
    "alternative-title": "Dr Livingstone I Presume"
}

Additional features

Merging the refraction with the original object

By default, only the evaluated fields from the template object will be included in the output. Specify --update if you would like to merge this output with the original object. If the template should only be used to fill in missing values, instead use --missing.

Editing JSON in-place

Refract prints to stdout. If you'd like to modify the original JSON file instead, use --in-place. For obvious reasons, this only works if a file was specified on the command line rather than piped in over stdin.

Iterating over multiple objects

Refract can also iterate over an array of objects. Use the --each option.

Normalizing keys

Renaming the fields of an object is easy:

// object
{
    "firstName": "Belle"
}
// template
{
    "first-name": "firstName"
}

However, if you'd like all fields of an object to adhere to the same standard, this field-per-field approach gets cumbersome really fast. The --normalized option provides a handy shortcut. You can normalize key names using any underscore.string function, e.g. --normalized underscored. The most useful ones are probably:

  • titleize
  • camelize
  • underscored
  • dasherize
  • humanize
  • slugify

Normalization happens before refraction, so refraction expressions should refer to variables by their new normalized names, not their original ones.

Custom helper functions

You can add your own helper functions. This should be a regular .js or .coffee file that can be require'd in node.

For example, your helpers.js might look like:

exports.toCelcius = function (fahrenheit) {
    return (fahrenheit - 32) * 5 / 9;
}

And then you can use that helper with

refract data.json \
    --apply temperature:toCelcius \
    --helpers helpers.js

Usage from node.js

var refract = require('refract-cli');

var obj = {
    count: '137'
}
var template = {
    count: 'parseInt count'
}

// refract with only JavaScript builtin functions
// like `parseInt` and `Math.max` as helpers
var newObj = refract(template, obj);

// include underscore and underscore.string
// as helpers
var _ = require('underscore');
var context = _.extend({}, obj, refract.defaultHelpers)
var newObj = refract(template, context);

// keep original fields too, not just refracted ones
_.extend(newObj, obj);

Future

  • It would be kind of cool if refract supported CSV input, converting header names into variables, and then back into (new) headers and columns on output. Maybe someday.
  • It might be useful to support not just JavaScript functions as helpers, but also shell commands. (It wouldn't be terribly efficient, because you'd have to have a bunch of child processes running to manage this, but that's another matter.)