Skip to content

Commit

Permalink
Merge pull request #67 from trayio/CPS-179/f/smart-substitution
Browse files Browse the repository at this point in the history
CPS-179: smart substitution
  • Loading branch information
johnbastian-trayio authored Jan 21, 2020
2 parents d005b52 + f3a4143 commit 5daacce
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 1 deletion.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ threadneedle.getLists({
* [addMethod](#addmethod)
* [global](#global)
* [SOAP Mode](#soap-mode)
* [Smart Substitution](smartSubstitution.md)


## addMethod
Expand Down
2 changes: 1 addition & 1 deletion lib/addMethod/identifySimpleMustache.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
mustache and is the only thing present in the string.
E.g:
`url: '{{url}}'` is simple.
`url: test.com/{{endpint}}` is not simple, since `{{endpint}}` is not on
`url: test.com/{{endpoint}}` is not simple, since `{{endpoint}}` is not on
its own. This also means any extra whitespace prefixing or suffixing
the mustache is not simple.
*/
Expand Down
14 changes: 14 additions & 0 deletions smartSubstitution.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/*
Top level alias for exposing substitute.js
This enables a lib to simply do `require('@trayio/threadneedle/smartSubstitution')`
*/
const _ = require('lodash');

const substitute = require('./lib/addMethod/substitute.js');

module.exports = (target, params = {}) => {
if (!_.isPlainObject(params)) {
throw new Error('`params` must be an object');
}
return substitute(target, params);
};
70 changes: 70 additions & 0 deletions smartSubstitution.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# Smart Substitution
Smart substitution is Threadneedle's logic for resolving mustaching and functions where applicable in configurations, such `options`, `query`, and `data` in REST method configuration.

Smart substitution can be utilised outside of Threadneedle via the following:
`const smartSubstitution = require('@trayio/threadneedle/smartSubstitution');`

## Overview
Unlike simple templating, smart substitution aims to preserve data types when possible, and as such checks when simple mustaching has been specified. In the event smart substitution is not possible, Threadneedle falls back to [mustache.js](https://github.com/janl/mustache.js/).

Furthermore, smart substitution will resolve functions by providing `params`
/input as the first and only argument, and then setting the function result as the value.

Finally, smart substitution will attempt to traverse objects and arrays. resolving templates which are nested.

## smartSubstitution(target, params)
The function accepts two arguments:
- **target** (any)- the target template to perform smart substitution on.
- **params** (object) - the data source for performing the smart substitution.

The function will return the resolved target.


## Simple mustaching
Simple mustaching are string values that contain only a single mustache template.
Example:
- The following is a simple mustache, as the string value contains simply a template:
```js
{
url: '{{url}}'
}
```
In this case, Threadneedle will attempt smart substitution.

- The following is not a simple mustache:
```js
{
url: 'example.com/{{endpoint}}'
}
```
In this case, Threadneedle will fallback to mustache.js.

## Function substitution
If a function is specified as the value, smart substitution will pass in the `params` and set the response as the value for the property.
Example:
```js
{
url: (params) => {
return params.url;
}
}
```

**NOTE**: smart substitution does not work with async functions/promises.

### Pathing
Smart substitution accepts pathing as part of the template configuration in a mustache. [Lodash](https://lodash.com/docs/)'s `_.get` is utilised to resolve paths.
Example:
```js
{
data: {
address: {
street: '{{billing_address.street}}'
}
}
}
```
This will resolve the `billing_address.street` and fetch the nested value from `params`.

## # Hash properties
Top level properties of the `params`/input that begin with `#` are known as hash properties. This is intended to provide a way of supplying data as part of `params` which is not user input and is meant to be hidden. Threadneedle will identify these properties and attempt smart substitution.

0 comments on commit 5daacce

Please sign in to comment.