interpolate-json
Advanced tools
Comparing version 2.0.0-alpha.1 to 2.0.0-alpha.2
## 2.0.0 | ||
Changes | ||
- declaration syntax. | ||
#### Changes | ||
- declaration syntax. | ||
```javascript | ||
@@ -12,2 +12,5 @@ // declare the variable at the beginning | ||
- `subKeyPointer` is restricted to dot(`.`), hash(`#`), underscore(`_`) & colon(`:`) (or it's multiple, like: `::` etc) | ||
- `funcSpecifier` is fixed to equal(`=`) | ||
- `escapeSpecifier` is fixed to star(`*`) | ||
- improved coding standards | ||
@@ -31,3 +34,4 @@ ## 1.0.0 | ||
type: 'saving people', | ||
post: 'Doctor' } | ||
post: 'Doctor', | ||
}, | ||
}; | ||
@@ -34,0 +38,0 @@ someString = interpolation.expand(someString, values); |
@@ -1,1 +0,1 @@ | ||
"use strict";const extend=require("extend"),type=require("type-detect"),{BadRequest}=require("./exceptions"),{subtract}=require("./setoperations"),{RegexEscaped}=require("./regexp-extensions"),spaces="[\\s]*",paramExpressionSet="[\\w]+",allowedFuncExpressions="{}()+-_*/%:|?,.$!&#'",funcExpressionSet=`[\\s\\w${RegexEscaped("{}()+-_*/%:|?,.$!&#'")}]+`,allowedOperators=["==","===","!=","!==","<","<=",">",">="],getOperatorSet=allowedOperators.map(e=>RegexEscaped(e)).join("|"),acceptedValueTypes=new Set(["number","string","boolean"]),isArgument=(e,t)=>e&&type(e)===(t||type(e)),isFunction=e=>"function"===type(e),envPrefix="INTERPOLATE_OPTION_",debugEnv=`${envPrefix}DEBUG`,isDebug=()=>process.env[debugEnv],log=e=>{isDebug()&&console.log(`[dotconfig][debug]: ${e}`)},trace=e=>{isDebug()&&console.trace(`[dotconfig][error]: ${e}`)},traceNThrow=(e,t)=>{throw trace(e),"Exception"===type(t)?new t(e):new Error(e)},InterpolateOption=function(e="${",t="}",r=".",n="=",i="*"){let s={};return s.updateOption=(e,t=!1)=>{const r=isArgument(e,"Object");for(let i in s)if(n=s[i],"function"!==type(n)){let n,o=`${envPrefix}${i.toUpperCase()}`;r&&(n=t?o:i),s[i]=r&&e.hasOwnProperty(n)?e[n]:process.env[o]||s[i]}var n;return s},s.clone=()=>({...s}),s.cloneFrom=e=>("InterpolateOption"===type(e)&&(s.prefix=e.prefix,s.suffix=e.suffix,s.subKeyPointer=e.subKeyPointer,s.funcSpecifier=e.funcSpecifier,s.escapeSpecifier=e.escapeSpecifier),s),s[Symbol.toStringTag]="InterpolateOption",s.prefix=e,s.suffix=e&&!t?"":t,s.subKeyPointer=r,s.funcSpecifier=n,s.escapeSpecifier=i,s},Interpolation=function(e=InterpolateOption()){let t,r,n,i,s={},o=null;const _updateRegex=()=>{r=_getParamRegex(),n=_getFuncRegex(o),i=_getEscapeRegex()},_updateOption=(e,t=!1)=>{o.updateOption(e,t),_updateRegex()},_getParamRegex=e=>new RegExp(RegexEscaped(o.prefix)+(isArgument(e,"string")?RegexEscaped(e):"")+"([\\s]*[\\w]+"+`(?:(${RegexEscaped(o.subKeyPointer)})`+"[\\w]+)*[\\s]*)"+RegexEscaped(o.suffix),"g"),_getFuncRegex=(e,t=!1)=>new RegExp(RegexEscaped(e.prefix)+(t?"((":"")+RegexEscaped(e.funcSpecifier)+(t?")?":"")+`([\\s]*${funcExpressionSet}`+`(?:(${getOperatorSet})${funcExpressionSet})*[\\s]*)`+(t?"(":"")+RegexEscaped(e.funcSpecifier)+(t?")?)":"")+RegexEscaped(e.suffix),"g"),_getEscapeRegex=()=>{let e=o.clone();return e.prefix='"'+e.prefix.trim()+e.escapeSpecifier.trim(),e.suffix=e.suffix.trim()+'"',_getFuncRegex(e,!0)},_missingKeyKeepAlive=e=>`${o.prefix}${e}${o.suffix}`,_getMatchSet=e=>new Set(e.reduce((e,t)=>(e.push(t.replace(r,(e,t)=>t.trim())),e),[])),_getInterpolated=(e,t,n=!1)=>(log(`Found match: ${e.match(r)}`),e.replace(r,(e,r)=>(r=r.trim(),t.hasOwnProperty(r)?t[r].toString():n?e:""))),_getInterpolatedFunc=(e,t,i=!1)=>(log(`Found func match: ${e.match(n)}`),e.replace(n,(e,n)=>{let i={};return n=n.trim().replace(r,(e,r)=>(i[r]=t.hasOwnProperty(r)?t[r].toString():"",`$val['${r}']`)),new Function("$val",`return ${n}`)(i)})),_flattenAndResolve=(e,t,i,s=!1)=>{let p=i||{};return t.forEach(t=>{if(p.hasOwnProperty(t))return;let i=!1,a=((e,t,r=!1)=>{const n=t.split(o.subKeyPointer).reduce((e,t)=>e[t]||{},e);return acceptedValueTypes.has(type(n))?n:r?_missingKeyKeepAlive(t):""})(e,t,s);_missingKeyKeepAlive(t)!==a&&r.test(a)&&(p=_flattenAndResolve(e,subtract(_getMatchSet(a.match(r)),new Set(Object.keys(p))),p,s),i=!0),n.test(a)&&(a=_getInterpolatedFunc(a,p)),i&&r.test(a)&&(a=_getInterpolated(a,p,s)),p[t]=a}),p},_containsOption=e=>Object.keys(e).some(e=>e.startsWith(envPrefix));return s.expand=(e,n=null,s=null)=>{let p=!1,a=!1;const c=type(e);isArgument(s,"Object")||isArgument(s,"InterpolateOption")?(s.prefix&&!s.suffix&&(s.suffix=""),_updateOption(s),a=!0):isArgument(n,"Object")&&_containsOption(n)?(_updateOption(n,!0),a=!0):isArgument(e,"Object")&&_containsOption(e)&&(_updateOption(e,!0),a=!0);var u={};switch(c){case"Object":let t=JSON.stringify(e);i.test(t)&&(e=JSON.parse(t.replace(i,(e,t)=>e.replace(`${o.prefix.trim()}${o.escapeSpecifier.trim()}`,`${o.prefix.trim()}`))),t=(e=>e.replace(i,(e,t)=>`${o.prefix}${t.trim()}${o.suffix}`))(t)),u=extend(u,e,n||{}),e=t;break;case"string":log(`Input: "${e}"`),r.test(e)&&null===n&&traceNThrow('Please provide "values"',BadRequest),u=extend(u,n);break;default:return trace(`Interpolation for ${c} has not yet been implemented`),e}log(`before interpolation:\n${e}`);let l="";if(r.test(e)){const t=e.match(r);n=_flattenAndResolve(u,_getMatchSet(t)),log(`all values: ${JSON.stringify(n,null,2)}`),p=!0}switch(p?(l=_getInterpolatedFunc(e,n),l=_getInterpolated(l,n)):l=e,log(`after interpolation:\n${l}`),a&&(o.cloneFrom(t),_updateRegex()),c){case"Object":return JSON.parse(l);case"string":default:return l}},s.debug=(e=!0)=>(process.env[debugEnv]=e,s),"InterpolateOption"!==type(e)&&traceNThrow('Please provide "values"',BadRequest),s[Symbol.toStringTag]="Interpolation",o=e,o.updateOption(),null!==o&&(t=o.clone()),_updateRegex(),s};module.exports={InterpolateOption,Interpolation,interpolation:Interpolation()}; | ||
"use strict";const extend=require("extend"),type=require("type-detect"),{BadRequest}=require("./exceptions"),{subtract}=require("./setoperations"),{RegexEscaped}=require("./regexp-extensions"),spaces="[\\s]*",paramExpressionSet="[\\w]+",allowedFuncExpressions="{}()+-_*/%:|?,.$!&#'",funcExpressionSet=`[\\s\\w${RegexEscaped("{}()+-_*/%:|?,.$!&#'")}]+`,allowedOperators=["==","===","!=","!==","<","<=",">",">="],getOperatorSet=allowedOperators.map(e=>RegexEscaped(e)).join("|"),acceptedValueTypes=new Set(["number","string","boolean"]),isArgument=(e,t)=>e&&type(e)===(t||type(e)),isFunction=e=>"function"===type(e),envPrefix="INTERPOLATE_OPTION_",debugEnv=`${envPrefix}DEBUG`,isDebug=()=>"true"===process.env[debugEnv].toString().toLowerCase(),log=e=>{isDebug()&&console.log(`[dotconfig][debug]: ${e}`)},trace=e=>{isDebug()&&console.trace(`[dotconfig][error]: ${e}`)},traceNThrow=(e,t)=>{throw trace(e),"Exception"===type(t)?new t(e):new Error(e)},InterpolateOption=function(e="${",t="}",r="."){let n={};const _defineFixedProperties=e=>{Object.defineProperty(e,"funcSpecifier",{value:"=",writable:!1,enumerable:!1}),Object.defineProperty(e,"escapeSpecifier",{value:"*",writable:!1,enumerable:!1})};return n.updateOption=(e,t=!1)=>{const r=isArgument(e,"Object");for(let o in n)if(i=n[o],"function"!==type(i)){let i,s=`${envPrefix}${o.toUpperCase()}`;r&&(i=t?s:o),n[o]=r&&e.hasOwnProperty(i)?e[i]:process.env[s]||n[o]}var i;return n},n.clone=()=>{var e={...n};return _defineFixedProperties(e),e},n.cloneFrom=e=>("InterpolateOption"===type(e)&&(n.prefix=e.prefix,n.suffix=e.suffix,n.subKeyPointer=e.subKeyPointer),n),n[Symbol.toStringTag]="InterpolateOption",n.prefix=e,n.suffix=e&&!t?"":t,n.subKeyPointer=r,_defineFixedProperties(n),n},Interpolation=function(e=InterpolateOption()){let t,r,n,i,o={},s=null;const _updateRegex=()=>{r=_getParamRegex(),n=_getFuncRegex(s),i=_getEscapeRegex()},_updateOption=(e,t=!1)=>{s.updateOption(e,t),_updateRegex()},_getParamRegex=e=>new RegExp(RegexEscaped(s.prefix)+(isArgument(e,"string")?RegexEscaped(e):"")+"([\\s]*[\\w]+"+`(?:(${RegexEscaped(s.subKeyPointer)})`+"[\\w]+)*[\\s]*)"+RegexEscaped(s.suffix),"g"),_getFuncRegex=(e,t=!1)=>new RegExp(RegexEscaped(e.prefix)+(t?"((":"")+RegexEscaped(e.funcSpecifier)+(t?")?":"")+`([\\s]*${funcExpressionSet}`+`(?:(${getOperatorSet})${funcExpressionSet})*[\\s]*)`+(t?"(":"")+RegexEscaped(e.funcSpecifier)+(t?")?)":"")+RegexEscaped(e.suffix),"g"),_getEscapeRegex=()=>{let e=s.clone();return e.prefix='"'+e.prefix.trim()+e.escapeSpecifier.trim(),e.suffix=e.suffix.trim()+'"',_getFuncRegex(e,!0)},_missingKeyKeepAlive=e=>`${s.prefix}${e}${s.suffix}`,_getMatchSet=e=>new Set(e.reduce((e,t)=>(e.push(t.replace(r,(e,t)=>t.trim())),e),[])),_getInterpolated=(e,t,n=!1)=>(log(`Found match: ${e.match(r)}`),e.replace(r,(e,r)=>(r=r.trim(),t.hasOwnProperty(r)?t[r].toString():n?e:""))),_getInterpolatedFunc=(e,t,i=!1)=>(log(`Found func match: ${e.match(n)}`),e.replace(n,(e,n)=>{let i={};return n=n.trim().replace(r,(e,r)=>(i[r]=t.hasOwnProperty(r)?t[r].toString():"",`$val['${r}']`)),new Function("$val",`return ${n}`)(i)})),_flattenAndResolve=(e,t,i,o=!1)=>{let p=i||{};return t.forEach(t=>{if(p.hasOwnProperty(t))return;let i=!1,a=((e,t,r=!1)=>{const n=t.split(s.subKeyPointer).reduce((e,t)=>e[t]||{},e);return acceptedValueTypes.has(type(n))?n:r?_missingKeyKeepAlive(t):""})(e,t,o);_missingKeyKeepAlive(t)!==a&&r.test(a)&&(p=_flattenAndResolve(e,subtract(_getMatchSet(a.match(r)),new Set(Object.keys(p))),p,o),i=!0),n.test(a)&&(a=_getInterpolatedFunc(a,p)),i&&r.test(a)&&(a=_getInterpolated(a,p,o)),p[t]=a}),p},_containsOption=e=>Object.keys(e).some(e=>e.startsWith(envPrefix));return o.expand=(e,n=null,o=null)=>{let p=!1,a=!1;const c=type(e);isArgument(o,"Object")||isArgument(o,"InterpolateOption")?(o.prefix&&!o.suffix&&(o.suffix=""),_updateOption(o),a=!0):isArgument(n,"Object")&&_containsOption(n)?(_updateOption(n,!0),a=!0):isArgument(e,"Object")&&_containsOption(e)&&(_updateOption(e,!0),a=!0);var u={};switch(c){case"Object":let t=JSON.stringify(e);i.test(t)&&(e=JSON.parse(t.replace(i,(e,t)=>e.replace(`${s.prefix.trim()}${s.escapeSpecifier.trim()}`,`${s.prefix.trim()}`))),t=(e=>e.replace(i,(e,t)=>`${s.prefix}${t.trim()}${s.suffix}`))(t)),u=extend(u,e,n||{}),e=t;break;case"string":log(`Input: "${e}"`),r.test(e)&&null===n&&traceNThrow('Please provide "values"',BadRequest),u=extend(u,n);break;default:return trace(`Interpolation for ${c} has not yet been implemented`),e}log(`before interpolation:\n${e}`);let l="";if(r.test(e)){const t=e.match(r);n=_flattenAndResolve(u,_getMatchSet(t)),log(`all values: ${JSON.stringify(n,null,2)}`),p=!0}switch(p?(l=_getInterpolatedFunc(e,n),l=_getInterpolated(l,n)):l=e,log(`after interpolation:\n${l}`),a&&(s.cloneFrom(t),_updateRegex()),c){case"Object":return JSON.parse(l);case"string":default:return l}},o.debug=(e=!0)=>(process.env[debugEnv]=e.toString(),o),"InterpolateOption"!==type(e)&&traceNThrow('Please provide "values"',BadRequest),o[Symbol.toStringTag]="Interpolation",s=e,s.updateOption(),null!==s&&(t=s.clone()),_updateRegex(),o};module.exports={InterpolateOption,Interpolation,interpolation:Interpolation()}; |
{ | ||
"name": "interpolate-json", | ||
"version": "2.0.0-alpha.1", | ||
"version": "2.0.0-alpha.2", | ||
"description": "Interpolate a Javascript Object or String with json - Advanced", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
124
README.md
@@ -1,2 +0,2 @@ | ||
# interpolate-json [![NPM version](https://img.shields.io/npm/v/interpolate-json.svg?style=plastic)](https://www.npmjs.com/package/interpolate-json) | ||
# interpolate-json [![NPM version](https://img.shields.io/npm/v/interpolate-json.svg?style=plastic)](https://www.npmjs.com/package/interpolate-json) | ||
@@ -33,3 +33,5 @@ [![Travis (.org)](https://img.shields.io/travis/Terran-Source/interpolate-json?logo=travis&style=plastic)](https://travis-ci.org/Terran-Source/interpolate-json) [![node](https://img.shields.io/node/v/interpolate-json?logo=nodejs&style=plastic)](https://www.npmjs.com/package/interpolate-json) [![GitHub](https://img.shields.io/github/license/Terran-Source/interpolate-json?logo=github&style=plastic)](LICENSE) | ||
// declare the varible at the beginning | ||
const { expand } = require('interpolate-json'); | ||
const interpolation = require('interpolate-json').interpolation; | ||
// or | ||
const { interpolation } = require('interpolate-json'); | ||
``` | ||
@@ -46,5 +48,6 @@ | ||
type: 'saving people', | ||
post: 'Doctor' } | ||
post: 'Doctor', | ||
}, | ||
}; | ||
someString = expand(someString, values); | ||
someString = interpolation.expand(someString, values); | ||
console.log(someString); | ||
@@ -56,3 +59,3 @@ // output: I want to be a Hero in saving people by being a Doctor | ||
let someString = "Hi, my name is '${USER_NAME}'. I'm ${USER_AGE}"; | ||
console.log(expand(someString, process.env)); | ||
console.log(interpolation.expand(someString, process.env)); | ||
// execute using: USER_NAME='John' USER_AGE=19 node test-string.js | ||
@@ -73,3 +76,3 @@ // output: Hi, my name is 'John'. I'm 19 | ||
}; | ||
console.log(expand(myJson)); // Look for values inside itself | ||
console.log(interpolation.expand(myJson)); // Look for values inside itself | ||
// output: | ||
@@ -94,3 +97,3 @@ { | ||
console.log(expand(myJson)); | ||
console.log(interpolation.expand(myJson)); | ||
// execute using: PORT=8080 USER_NAME='John' USER_PASSWORD='P@ss#ord' node test-json.js | ||
@@ -110,7 +113,5 @@ // output: | ||
## Definition | ||
Syntax: `expand(obj, values = null, options = {});` | ||
Syntax: `interpolation.expand(obj, values = null, options = {});` | ||
@@ -159,3 +160,3 @@ The `expand` function takes 3 parameters | ||
The [`options`](#options) setup. Each section can be individually set through Environment Variables INTERPOLATE_OPTION_[*CONFIGNAME*] (or you can also set it inside [`values`](#values) or `json` type [`obj`](#obj). See an extreme [Example](tests/config.func.custom.option.json)) | ||
The [`options`](#options) setup. Each section can be individually set through Environment Variables INTERPOLATE*OPTION*[*CONFIGNAME*] (or you can also set it inside [`values`](#values) or `json` type [`obj`](#obj). See an extreme [Example](tests/config.func.custom.option.json)) | ||
@@ -168,3 +169,3 @@ ###### debug | ||
Set it true to turn on logging to help debug why certain things are not working as expected. Can be turned on [globally](<#debug-1>). | ||
Set it true to turn on logging to help debug why certain things are not working as expected. Can be turned on [globally](#debug-1). | ||
@@ -193,20 +194,20 @@ ###### prefix | ||
The json object tree sub-node pointer for interpolation parameter. | ||
The json object tree sub-node pointer for interpolation parameter. | ||
```javascript | ||
let json = { | ||
a: "A", | ||
b: "B", | ||
c: { | ||
d: "D", | ||
e: "E", | ||
f: { | ||
g: "G" | ||
} | ||
} | ||
} | ||
a: 'A', | ||
b: 'B', | ||
c: { | ||
d: 'D', | ||
e: 'E', | ||
f: { | ||
g: 'G', | ||
}, | ||
}, | ||
}; | ||
// If subKeyPointer = '.' | ||
{ | ||
reference: "${c.d}" | ||
reference: '${c.d}'; | ||
} | ||
@@ -216,48 +217,38 @@ | ||
{ | ||
reference: "${c#f#g}" | ||
reference: '${c#f#g}'; | ||
} | ||
``` | ||
###### funcSpecifier\* | ||
###### funcSpecifier* | ||
- type: `string` | ||
- default: `=` | ||
- Environment Variable override: `INTERPOLATE_OPTION_FUNCSPECIFIER` | ||
- ***fixed value***: `=` | ||
The notation after [`prefix`](#prefix) & before [`suffix`](#suffix) to describe a function expression boundary. (e.g. `${= Func(${param1}, ${param2}) =}`). Must not be same as any of [`prefix`](#prefix), [`suffix`](#suffix), [`subKeyPointer`](#subKeyPointer) or [`escapeSpecifier`](#escapeSpecifier). | ||
The notation after [`prefix`](#prefix) & before [`suffix`](#suffix) to describe a function expression boundary. (e.g. `${= Func(${param1}, ${param2}) =}`). | ||
> It should not be touched unless really needed. Should be a single character (preferably a special character, e.g. #, =, *, <, >, ~ etc) | ||
###### escapeSpecifier\* | ||
###### escapeSpecifier* | ||
- type: `string` | ||
- default: `*` | ||
- Environment Variable override: `INTERPOLATE_OPTION_ESCAPESPECIFIER` | ||
- ***fixed value***: `*` | ||
The notation after [`prefix`](#prefix) to escape string expression for certain data-types (like number, boolean etc.). Must not be same as any of [`prefix`](#prefix), [`suffix`](#suffix), [`subKeyPointer`](#subKeyPointer) or [`funcSpecifier`](#funcSpecifier). | ||
The notation after [`prefix`](#prefix) to escape string expression for certain data-types (like number, boolean etc.). | ||
> This option is only applicable to `json` type [`obj`](#obj) | ||
> It should not also be touched either unless really needed. Should be a single character (preferably a special character, e.g. #, =, *, <, >, ~ etc). | ||
```javascript | ||
let json = { | ||
myKey: "${*keyValue}", | ||
isKey: "${*boolValue}" | ||
} | ||
myKey: '${*keyValue}', | ||
isKey: '${*boolValue}', | ||
}; | ||
// values = {keyValue: 123.45, boolValue: false} | ||
interpolatedJson = { | ||
myKey: 123.45, // instead of myKey: "123.45" | ||
isKey: false // instead of isKey: "false" | ||
} | ||
interpolatedJson = { | ||
myKey: 123.45, // instead of myKey: "123.45" | ||
isKey: false, // instead of isKey: "false" | ||
}; | ||
``` | ||
### Functions | ||
```javascript | ||
// When declared as a varible at the beginning | ||
// When declared as a variable at the beginning | ||
const interpolation = require('interpolate-json'); | ||
@@ -272,8 +263,8 @@ ``` | ||
// Syntax I | ||
const interpolation = require('interpolate-json'); | ||
const interpolation = require('interpolate-json').interpolation; | ||
interpolation.expand(obj, value); | ||
// Syntax II | ||
const { expand } = require('interpolate-json'); | ||
expand(obj, value); | ||
const { interpolation } = require('interpolate-json'); | ||
interpolation.expand(obj, value); | ||
``` | ||
@@ -283,30 +274,13 @@ | ||
Globally turn on [`debug`](#debug) flag. | ||
Globally turn on [`debug`](#debug) flag. If set to `true`, it'll write console output of detailed operations. | ||
Can also be turned on via setting Environment Variable `INTERPOLATE_OPTION_DEBUG` to `true` | ||
```javascript | ||
// to globally turn it on | ||
const interpolation = require('interpolate-json').debug(); | ||
const interpolation = require('interpolate-json').interpolation; | ||
interpolation.debug(); | ||
// to globally turn off | ||
// to globally turn off debugging output | ||
interpolation.debug(false); | ||
``` | ||
#### reset() | ||
Resets the [options](#options). | ||
```javascript | ||
const interpolation = require('interpolate-json'); | ||
// do some custom job | ||
let result = interpolation.expand(someObj, process.env, { | ||
debug: true, // globally turn it on | ||
prefix: '{{', // not affecting next call | ||
suffix: '}}' | ||
}); | ||
let result2 = interpolation.expand(someOtherObj); // `dubug` is still set as true, `prefix` & `siffix` will be '${' & '}' respectively | ||
// now if you want to reset debug & all other options | ||
interpolation.reset(); | ||
``` |
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
18348
275