intro
Directives
Directives are small functions for accessing and manipulating data, composable in pipelines to achieve more complex transformations. Their primary use case is for mapping arguments and results in resolver configurations.
They have a minimal set of options and can access the values in the currentQuery
context.
type Directive = [
function: string,
{
[key: string]: string;
}
];
set
This simple directive returns the provided value
as a string. It's great for directly setting a literal value, or for
starting off a directive pipeline with a value available in the currentQuery
syntax.
Options
-
value
requiredThe string that should be set.
get
In its simplest form, get
will get the value at path
and pass it into the directive pipeline. Most directives
pipelines start with get
and the mapping
shorthand is itself a get
operation. If the value at path
evaluates to
undefined the value of $previousDirective
, if any, will be sent on. If a defaultValue
is set, this will be passed on
instead.
get
can also take an array of string paths. In this case it will return multiple values. This can be useful for
further directives, like format
or zipAndMerge
.
Finally, get
supports tokens, which are evaluated against the context, in the path. This allows for extended logic,
like using a $loop.key
to maintain a reference to the same array item in a loop. A path with a token looks like
this: $finalResolver[{$loop.key}].params[{$args.someParamName}]
. See the examples below for more.
Under the hood, get
uses jsonpath-plus so you have a fair amount
of power getting values into your directive.
Options
-
path
(string | string[], required) This is property path to get from the context. -
defaultValue
(any, optional) A value to use if the path returnsundefined
-
passThroughOnUndefined
(boolean, optional) Ifpath
returnsundefined
, and nodefaultValue
is set, return the previous value. Defaults totrue
. -
flatten
(boolean, optional) When your path returns a multidimensional array, flatten it to a single dimension. For example, if the path$args.colors[*]
returned[['Red'], ['Blue']]
settingflatten
would instead return['Red', 'Blue']
to the directive pipeline. -
wrap
(boolean, optional) Whether to wrap your results in an array. Default isfalse
, so only actual array results will return an array, otherwise you'll get the primitive value as-is. For example, if the path$args.page
contained the number5
, settingwrap
would instead return[5]
to the directive pipeline.
Example
In the example below, input.title
would be set to the value of either the takeshapeUpdate
or takeshapeCreate
step,
if one is undefined
and the other has a value. If both have a value, input.title
will be the value of
takeshapeCreate
since that step is run later in the pipeline.
If we disabled passThroughOnUndefined
and the takeshapeCreate
step returned undefined
our result would be
undefined
, not the value of takeshapeUpdate
.
{
"args": {
"ops": [
{
"path": "input.title",
"mapping": [
["get", {"path": "$resolvers.takeshapeUpdate.result.name"}],
["get", {"path": "$resolvers.takeshapeCreate.result.name"}]
]
},
{
"path": "input.vendor",
"mapping": "get", {"path": "$resolvers.takeshapeCreate.result.vendor", "defaultValue": "Kirkland"}
}
]
}
}
And in this example, we're getting multiple values and passing them to the format
directive. Each of the values
returns a string.
{
"results": {
"ops": [
{
"path": "name",
"mapping": [
["get", {"path": ["$resolvers.takeshapeUpdate.result.name", "$args.nameSuffix"]}],
["format", {"template": "%s, %s"}]
]
}
]
}
}
In the following example, we'll use path tokens to maintain the same index in a source array while populating a results array.
{
"results": {
"ops": [
{
"path": "items",
"mapping": [
["get", {"path": "$finalResolver.length"}],
["array", {}]
]
},
{
"path": "items[*].newParams",
"mapping": "get", {"path": "$finalResolver[{$loop.key}].params"}
}
]
}
}
trim
Removes matching leading and trailing characters from a string.
Options
**chars
** Defines the leading and trailing characters to remove from a string. For example, if you want to remove quotes from a string. Defaults to remove whitespace characters.
toUpper
Converts the string, as a whole, to upper case.
prepend
Prepends the text provided in options to the string.
Options
**text
** required The text you'd like to prepend to the string
expressionEval
Use the expression-eval module and our own custom context.
Options
expression
****required
Context
- The same
currentQuery
context from above, plus - A number of callable functions
- ~180 functions exported from
lodash/fp
format
exported fromutil
mapDeep
a custom function for deep mappings, for example, all[foo.name](http://foo.name)
object paths at any depth in an array of objectsnewObject
provides a new object, given the limitations of the expression evaluation approachgetImageUrl
from@takeshape/routing
- ~180 functions exported from
zipAndMerge
zipWith from lodash, using merge also from lodash to deeply merge objects at the same indexes in multiple arrays.
This will operate on whatever was output from the directive at the previous step, but is a noop if that value is not an array.
replace
Replaces patterns or a regexp in a string provided by the $previousDirective
.
replace from lodash.
Options
replacement
(string, required)pattern
(string, required if no regexp)regexp
(string, required if no pattern)regexpFlag
(string, optional)
filter
Filters any string
, array
or object
passed in from the $previousDirective
.
filter from lodash.
Options
-
predicate
(string | Object | Array, required if no expression)- A
lodash.filter
iteratee predicates.
- A
-
expression
(string, required if no predicate)-
An
expressionEval
expression as described above. You have access to the full query context, and get the additional context variables$value
,$index
and$collection
for comparison. For example,$value.species !== 'Human'
would compare thespecies
property in an object to the literal stringHuman
. -
If you happen to be using a
string
as your input, the iteratee context variables will be$char
,$index
and$string
.
-
format
A printf
-like format utility, using
util.formatWithOptions from the
Node.js standard library.
If the $previousDirective
provides an array, that array will be spread onto the params of util.formatWithOptions
. If
a non-array value is found it will be supplied as the single param for formatting.
Options
-
template
(string, required)- A string with replacement specifiers. Common specifiers are
%s
for a string, and%d
for a number. A full list can be found here.
- A string with replacement specifiers. Common specifiers are
-
options
(Object, optional)- Options for
util.inspect
. Full list here.
- Options for
array
A utility for initializing an array. The array
directive takes a single option, initial
which will be the value
passed to the
Array constructor. If no
initial
option is set, the results of the $previousDirective
are used instead.
If the number passed is a number, then an array of that length will be initialized. Any other value will be set as the sole element of the new array.
If both initial
and $previousDirective
are undefined, an empty array will be returned.
Options
-
initial
(any, optional)- An optional value to set as the initial value in the Array constructor.
Examples
One of the most useful applications of this directive is to initialize ops values of a length equivalent to some other
iterable value in your context. In this example, if your $finalResolver
was an array of 10 items, your results item
path will be initialized with an empty array of length 10.
{
"results": {
"ops": [
{
"path": "items",
"mapping": [
["get", {"path": "$finalResolver.length"}],
["array", {}]
]
},
{
"path": "items[*].newParams",
"mapping": "get", {"path": "$finalResolver[{$loop.key}].params"}
}
]
}
}
md5
Compute the md5 hash of $previousDirective
or value
.
Options
value
(string, optional)
Examples
In this example we create an composite id. First we get several properties of the source object, we then concatenate them and finally we hash the result to create a shorter id.
{
"id": {
"@tag": "id",
"@resolver": {
"name": "util:noop",
"results": {
"ops": [
{
"path": "$",
"mapping": [
["get", {"path": ["$source.company", "$source.jobtitle", "$source:city"]}],
["format", {"template": "%s:%s:%s"}],
["md5", {}]
]
}
]
}
}
}
}
sha1
Compute the sha1 hash of $previousDirective
or value
.
Options
value
(string, optional)
sha256
Compute the sha256 hash of $previousDirective
or value
.
Options
value
(string, optional)
encodeBase64
Encode $previousDirective
or value
from utf8 into base64
Options
value
(string, optional)
decodeBase64
Decode $previousDirective
or value
from base64 into utf8
Options
value
(string, optional)