Convert Things to Falcor JSON Graph
This makes it easy to bring Falcor into established projects, by transforming existing JSON REST responses into conformant JSON Graph objects.
Note: Experimental! Might change before 1.0.
Install
npm install json-graphify
Example
; // this will be used to convert user// objects into JSON Graph fragmentsconst convertUser = ; // example of a user object returned// from a REST APIconst user = id: '1' username: 'superman' avatar: '2' alter_ego: id: '3' username: 'lexluthor' ; // convert it to JSON Graphconst jsong = convertUser; console;// output graph usersById: 1: id: '1' username: 'superman' avatar: $type: 'ref' value: 'mediaById' '2' alter_ego: $type: 'ref' value: 'usersById' '3' 3: id: '3' username: 'lexluthor'
API Documentation
Main factory function
This module exports a factory function which creates an object transformer based a set of declarative rules you provide. The resultant converter is stateless, and can be kept in memory and endlessly re-used to transform JSON objects into conformant JSON graph fragments. You can create a separate converter for each different type returned from your API.
; // Create an object that we can use to convert user// objects returned from the "/api/users/{id}" endpoint// into JSON graph output.const convertUser = ;
Move objects
An array of these are passed as an option to the factory method (see above).
A move object has the form { from, to }
.
from
is a path from the root of the input object, which matches zero or more sub-roots in the object tree.
to
is a path from the root of the output graph, pointing to those subtrees' new home.
// `$index` matches any positive integer, thus // if the incoming object has an `avatars` array, // this path will match every item in it. from: 'avatars' '$index' // `$id` will be replaced by the avatar object's // `id` attribute, creating an `mediaById` hash // in the output graph. to: 'mediaById' '$id'
Munge objects
An array of these are passed as an option to the factory method (see above).
A munge object has the form { select, edit }
.
select
is a path from the root of the input object, which matches zero or more sub-roots in the object tree.
edit
is a function which operates on the found value.
Whatever edit
returns becomes the new value.
If it returns undefined
, the value is deleted.
// if the input object has an `avatar` property // this selector will match it. select: 'avatar' // the value of `inputObject.avatar` is passed to // this function, which converts it to a JSON // graph reference. $type: 'ref' value: 'mediaById' id
convert.toPathValues(...objects)
This converts an input object into an iterator of { path, value }
objects.
Note: this was recently changed from returning an array to returning an iterable.
If an array is needed simply do [ ...convert.toPathValues() ]
.
Returning an iterator instead of an array allows lazy evaluation.
Accepts one or more objects which are converted and added to the result.
const user1 = await ;const user2 = await ;const paths = ...convertUser ;
convert.toGraph(...objects)
This converts an input object into a JSON graph that can be used to populate a Falcor model. Accepts one or more objects which are converted and added to the result.
const user1 = await ;const user2 = await ;const graph = convertUser;
graphify.extractor(pathHandlers)
This is an alternative approach, with the goal of being as performant and lightweight as possible. This is more suitable when the objects being converted don't need lots of munging. Subsequently, there's not much heavy object manipulation, and graph-building is more a manual process.
The idea is to create an extractor, which is a factory used to create a pool. The extractor is kept in memory as a singleton and re-used. One pool is created for each Falcor route handler. Insert into the pool to build a graph, then extract to fulfill request paths.
To create an extractor, pass it an array of { path, handler }
objects like so:
const extractor = graphify;
path
is a pattern where $key
matches any property and $index
matches any positive integer.
handler
is a function that receives the value and returns a result.
For example, in the above, the avatar
property on the resource is an ID string; we want to convert it to a JSON graph ref.
This conversion is done lazily at extraction time.
Next, create a pool and add JSON objects to it like so:
const pool = extractorstart;for const user of users // build up the graph manually pool;
Next, extract the values you want like so:
const value = pool;
In a falcor router it might look like this:
// allPaths() iterates the pathSet// passed to the falcor route handlerconst pathVals = ;const pool = extractorstart;const user = await api;pool;for const path of const value = pool; pathVals;return pathVals;
If the path
used to extract matches one of the path patterns provided above, then the returned value is run through the associated handler
function.