fx/DOCS.md
2019-04-04 00:14:28 +07:00

6.8 KiB

Documentation

Getting started

fx can work in two modes: cli and interactive. To start interactive mode pipe into fx any JSON:

$ curl ... | fx

Or you can pass file argument as first parameter:

$ fx my.json

If any argument was passed, fx will apply it and prints to stdout.

Usage

Anonymous function

Use an anonymous function as reducer which gets JSON and processes it:

$ echo '{"foo": [{"bar": "value"}]}' | fx 'x => x.foo[0].bar'
value

Binding

If you don't pass anonymous function param => ..., code will be automatically transformed into anonymous function. And you can get access to JSON by this keyword:

$ echo '{"foo": [{"bar": "value"}]}' | fx 'this.foo[0].bar'
value

Dot

It is possible to omit this keyword:

$ echo '{"foo": [{"bar": "value"}]}' | fx .foo[0].bar
value

If single dot is passed, JSON will be processed without modification:

$ echo '{"foo": "bar"}' | fx .
{
  "foo": "bar"
}

Chaining

You can pass any number of anonymous functions for reducing JSON:

$ echo '{"foo": [{"bar": "value"}]}' | fx 'x => x.foo' 'this[0]' 'this.bar'
value

Generator

If passed code contains yield keyword, generator expression will be used:

$ curl ... | fx 'for (let user of this) if (user.login.startsWith("a")) yield user'

Access to JSON through this keyword:

$ echo '["a", "b"]' | fx 'yield* this'
[
  "a",
  "b"
]
$ echo '["a", "b"]' | fx 'yield* this; yield "c";'
[
  "a",
  "b",
  "c"
]

Updating

You can update existing JSON using spread operator:

$ echo '{"count": 0}' | fx '{...this, count: 1}'
{
  "count": 1
}

Using packages

Use any npm package by installing it globally:

$ npm install -g lodash
$ cat package.json | fx 'require("lodash").keys(this.dependencies)'

Using .fxrc

Create .fxrc file in $HOME directory, and require any packages or define global functions.

For example, access all lodash methods without _ prefix. Put in your .fxrc file:

Object.assign(global, require('lodash/fp'))

And now you will be able to call all lodash methods. For example, see who's been committing to react recently:

curl 'https://api.github.com/repos/facebook/react/commits?per_page=100' \
| fx 'groupBy("commit.author.name")' 'mapValues(size)' toPairs 'sortBy(1)' reverse 'take(10)' fromPairs

To be able require global modules make sure you have correct NODE_PATH env variable.

export NODE_PATH=`npm root -g`

Edit in place

Add next code to your .fxrc file:

const fs = require('fs')

global.save = json => {
  fs.writeFileSync(process.argv[2], JSON.stringify(json, null, 2))
  return json
}

Usage:

fx data.json '{...this, count: this.count+1}' save .count

Formatting

If you need something different then JSON (for example arguments for xargs) do not return anything from reducer. undefined value is printed into stderr by default.

echo '[]' | fx 'void 0'
undefined
echo '[1,2,3]' | fx 'this.forEach(x => console.log(x))' 2>/dev/null | xargs echo
1 2 3

Other examples

Convert object to array:

$ cat package.json | fx 'Object.keys(this.dependencies)'

Or by two functions:

$ cat package.json | fx .dependencies Object.keys

By the way, fx has shortcut for Object.keys. Previous example can be rewritten as:

$ cat package.json | fx .dependencies ?

Streaming mode

fx supports line-delimited JSON and concatenated JSON streaming.

$ kubectl logs ... | fx .message

Sometimes it is necessary to omit some messages in JSON stream, or select only specified log messages. For this purpose, fx has special helper select, pass function into it to select only some JSON messages.

$ kubectl logs ... | fx 'select(x => x.message.length > 40)' .message

Interactive mode

Click on fields to expand or collapse JSON tree, use mouse wheel to scroll view.

Next commands available in interactive mode:

Key Command
q or Esc or Ctrl+c Exit
e/E Expand/Collapse all
g/G Goto top/bottom
up/down or k/j Move cursor up/down
left/right or h/l Expand/Collapse
. Edit filter
/ Search
n Goto next found pattern

These commands are available when editing the filter:

Key Command
Enter Apply filter
Ctrl+u Clear filter
Ctrl+w Delete last part
up/down Select autocomplete

Searching

Press / and type regexp pattern to search in current JSON. Search work with currently applied filter.

Examples of pattern and corresponding regexp:

Pattern RegExp
/apple /apple/ig
/apple/ /apple/
/apple/u /apple/u
/\w+ /\w+/ig

Selecting text

You may found what you can't just select text in fx. This is due the fact that all mouse events redirected to stdin. To be able select again you need instruct your terminal not to do it. This can be done by holding special keys while selecting:

Key Terminal
Option+Mouse iTerm2, Hyper
Fn+Mouse Terminal.app
Shift+Mouse Linux

Memory Usage

You may find what sometimes, on a really big JSON files, fx prints an error with message like this:

FATAL ERROR: JavaScript heap out of memory 

There is a limit for the memory usage in V8 of around 2GB. You can increase the limit by putting next lines to you .profile:

export NODE_OPTIONS='--max-old-space-size=8192'