UNPKG

json-variables

Version:

Resolves custom-marked, cross-referenced paths in parsed JSON

17 lines (14 loc) 9.86 kB
/** * @name json-variables * @fileoverview Resolves custom-marked, cross-referenced paths in parsed JSON * @version 12.0.23 * @author Roy Revelt, Codsen Ltd * @license MIT * {@link https://codsen.com/os/json-variables/} */ import{matchLeftIncl as k,matchRightIncl as x}from"string-match-left-right";import{remDup as F}from"string-remove-duplicate-heads-tails";import{strFindHeadsTails as I}from"string-find-heads-tails";import{getByKey as _}from"ast-get-values-by-key";import{arrayiffy as B}from"arrayiffy-if-string";import{traverse as L}from"ast-monkey-traverse";import{rApply as O}from"ranges-apply";import h from"object-path";import{Ranges as U}from"ranges-push";import{isMatch as M}from"matcher";import{isPlainObject as w,existy as q,isBool as A,isNull as N,isStr as o,isNum as K}from"codsen-utils";var j="12.0.23";var ce=j,G=Object.prototype.hasOwnProperty,z={heads:"%%_",tails:"_%%",headsNoWrap:"%%-",tailsNoWrap:"-%%",lookForDataContainers:!0,dataContainerIdentifierTails:"_data",wrapHeadsWith:"",wrapTailsWith:"",dontWrapVars:[],preventDoubleWrapping:!0,wrapGlobalFlipSwitch:!0,noSingleMarkers:!1,resolveToBoolIfAnyValuesContainBool:!0,resolveToFalseIfAnyValuesContainBool:!0,throwWhenNonStringInsertedInString:!1,allowUnresolved:!1};function g(r){return o(r)?r.trim():r}function Y(r){if(o(r)&&r.length&&r.indexOf(".")!==-1){for(let e=0,t=r.length;e<t;e++)if(r[e]===".")return r.slice(0,e)}return r}function Q(r){if(o(r)&&r.length&&r.indexOf(".")!==-1){for(let e=0,t=r.length;e<t;e++)if(r[e]===".")return r.slice(e+1)}return r}function J(r){if(o(r)&&r.length&&r.indexOf(".")!==-1){for(let e=r.length;e--;)if(r[e]===".")return r.slice(0,e)}return r}function P(r){if(o(r)&&r.length&&r.indexOf(".")!==-1){for(let e=r.length;e--;)if(r[e]===".")return r.slice(e+1)}return r}function T(r,e){return!o(r)||!r.trim()?!1:!!(r.includes(e.heads)||r.includes(e.tails)||o(e.headsNoWrap)&&e.headsNoWrap.length&&r.includes(e.headsNoWrap)||o(e.tailsNoWrap)&&e.tailsNoWrap.length&&r.includes(e.tailsNoWrap))}function X(r,e,t){let l,s;return o(r)&&r.length&&x(r,0,e,{trimBeforeMatching:!0,cb:(n,a,i)=>(l=i,!0)})&&k(r,r.length-1,t,{trimBeforeMatching:!0,cb:(n,a,i)=>(s=(i||0)+1,!0)})?r.slice(l,s):r}function H(r,e,t=!1,l,s,n){if(e.wrapHeadsWith||(e.wrapHeadsWith=""),e.wrapTailsWith||(e.wrapTailsWith=""),o(r)&&!t&&e.wrapGlobalFlipSwitch&&!e.dontWrapVars.some(a=>M(n,a))&&(!e.preventDoubleWrapping||e.preventDoubleWrapping&&o(r)&&!r.includes(e.wrapHeadsWith)&&!r.includes(e.wrapTailsWith)))return`${e.wrapHeadsWith}${r}${e.wrapTailsWith}`;if(t){if(!o(r))return r;let a=F(r,{heads:e.wrapHeadsWith,tails:e.wrapTailsWith});return o(a)?X(a,e.wrapHeadsWith,e.wrapTailsWith):a}return r}function Z(r,e,t,l){let s;if(t.indexOf(".")!==-1){let n=t,a=!0;if(l.lookForDataContainers&&o(l.dataContainerIdentifierTails)&&l.dataContainerIdentifierTails.length&&!n.endsWith(l.dataContainerIdentifierTails)){let i=h.get(r,n+l.dataContainerIdentifierTails);w(i)&&h.get(i,e)&&(s=h.get(i,e),a=!1)}for(;a&&n.indexOf(".")!==-1;){if(n=J(n),P(n)===e)throw new Error(`json-variables/findValues(): [THROW_ID_20] While trying to resolve: "${e}" at path "${t}", we encountered a closed loop. The parent key "${P(n)}" is called the same as the variable "${e}" we're looking for.`);if(l.lookForDataContainers&&o(l.dataContainerIdentifierTails)&&l.dataContainerIdentifierTails.length&&!n.endsWith(l.dataContainerIdentifierTails)){let i=h.get(r,n+l.dataContainerIdentifierTails);w(i)&&h.get(i,e)&&(s=h.get(i,e),a=!1)}if(s===void 0){let i=h.get(r,n);w(i)&&h.get(i,e)&&(s=h.get(i,e),a=!1)}}}if(s===void 0){let n=h.get(r,e);n!==void 0&&(s=n)}if(s===void 0)if(e.indexOf(".")===-1){let n=_(r,e);if(n.length){for(let a=0,i=n.length;a<i;a++)if(o(n[a].val)||A(n[a].val)||N(n[a].val)){s=n[a].val;break}else if(K(n[a].val)){s=String(n[a].val);break}else if(Array.isArray(n[a].val)){s=n[a].val.join("");break}}}else{let n=_(r,Y(e));if(n.length)for(let a=0,i=n.length;a<i;a++){let m=h.get(n[a].val,Q(e));m&&o(m)&&(s=m)}}return s}function R(r,e,t,l,s=[]){if(s.includes(t)){let c="";if(s.length>1){let y=` \u2192 `;c=s.reduce((D,b,S)=>D+(S===0?"":y)+(b===t?"\u{1F4A5} ":" ")+b,` Here's the path we travelled up until we hit the recursion: `),c+=`${y}\u{1F4A5} ${t}`}throw new Error(`json-variables/resolveString(): [THROW_ID_19] While trying to resolve: "${e}" at path "${t}", we encountered a closed loop, the key is referencing itself."${c}`)}let n={},a=Array.from(s);a.push(t);let i=new U;function m(c,y,D){for(let b=0,S=c.length;b<S;b++){let f=c[b],p=e.slice(f.headsEndAt,f.tailsStartAt);if(p.length===0)i.push(f.headsStartAt,f.tailsEndAt);else if(G.call(n,p)&&o(n[p]))i.push(f.headsStartAt,f.tailsEndAt,n[p]);else{let u=Z(r,p.trim(),t,l);if(u===void 0)if(l.allowUnresolved===!0)u="";else if(o(l.allowUnresolved))u=l.allowUnresolved;else throw new Error(`json-variables/processHeadsAndTails(): [THROW_ID_18] We couldn't find the value to resolve the variable ${e.slice(f.headsEndAt,f.tailsStartAt)}. We're at path: "${t}".`);if(!D&&l.throwWhenNonStringInsertedInString&&!o(u))throw new Error(`json-variables/processHeadsAndTails(): [THROW_ID_23] While resolving the variable ${e.slice(f.headsEndAt,f.tailsStartAt)} at path ${t}, it resolved into a non-string value, ${JSON.stringify(u,null,4)}. This is happening because options setting "throwWhenNonStringInsertedInString" is active (set to "true").`);if(A(u)){if(l.resolveToBoolIfAnyValuesContainBool)return i.wipe(),l.resolveToFalseIfAnyValuesContainBool?!1:u;u=""}else{if(N(u)&&D)return i.wipe(),u;Array.isArray(u)?u=String(u.join("")):N(u)?u="":u=String(u)}let v=t.includes(".")?`${J(t)}.${p}`:p;if(T(u,l)){let V=H(R(r,u,v,l,a),l,y,a,v,p.trim());o(V)&&i.push(f.headsStartAt,f.tailsEndAt,V)}else{n[p]=u;let V=H(u,l,y,a,v,p.trim());o(V)&&i.push(f.headsStartAt,f.tailsEndAt,V)}}}}let d;try{d=I(e,l.heads,l.tails,{source:"",throwWhenSomethingWrongIsDetected:!1})}catch(c){throw new Error(`json-variables/resolveString(): [THROW_ID_17] While trying to resolve string: "${e}" at path ${t}, something wrong with heads and tails was detected! Here's the internal error message: ${c}`)}let W=!1;d.length===1&&O(e,[[d[0].headsStartAt,d[0].tailsEndAt]]).trim()===""&&(W=!0);let $=m(d,!1,W);if(typeof $=="boolean"||$===null)return $;try{d=I(e,l.headsNoWrap,l.tailsNoWrap,{source:"",throwWhenSomethingWrongIsDetected:!1})}catch(c){throw new Error(`json-variables/resolveString(): [THROW_ID_22] While trying to resolve string: "${e}" at path ${t}, something wrong with no-wrap heads and no-wrap tails was detected! Here's the internal error message: ${c}`)}d.length===1&&O(e,[[d[0].headsStartAt,d[0].tailsEndAt]]).trim()===""&&(W=!0);let E=m(d,!0,W);return A(E)||N(E)?E:i?.current()?O(e,i.current()):e}function pe(r,e){if(!arguments.length)throw new Error("json-variables/jVar(): [THROW_ID_01] Alas! Inputs are missing!");if(!w(r))throw new TypeError(`json-variables/jVar(): [THROW_ID_02] Alas! The input must be a plain object! Currently it's: ${Array.isArray(r)?"array":typeof r}`);if(e&&!w(e))throw new TypeError(`json-variables/jVar(): [THROW_ID_03] Alas! An Optional Options Object must be a plain object! Currently it's: ${Array.isArray(e)?"array":typeof e}`);let t={...z,...e};t.dontWrapVars?Array.isArray(t.dontWrapVars)||(t.dontWrapVars=B(t.dontWrapVars)):t.dontWrapVars=[];let l,s;if(t.dontWrapVars.length&&!t.dontWrapVars.every((a,i)=>o(a)?!0:(l=a,s=i,!1)))throw new Error(`json-variables/jVar(): [THROW_ID_05] Alas! All variable names set in resolvedOpts.dontWrapVars should be of a string type. Computer detected a value "${l}" at index ${s}, which is not string but ${Array.isArray(l)?"array":typeof l}!`);if(t.heads==="")throw new Error("json-variables/jVar(): [THROW_ID_06] Alas! resolvedOpts.heads are empty!");if(t.tails==="")throw new Error("json-variables/jVar(): [THROW_ID_07] Alas! resolvedOpts.tails are empty!");if(t.lookForDataContainers&&t.dataContainerIdentifierTails==="")throw new Error("json-variables/jVar(): [THROW_ID_08] Alas! resolvedOpts.dataContainerIdentifierTails is empty!");if(t.heads===t.tails)throw new Error("json-variables/jVar(): [THROW_ID_09] Alas! resolvedOpts.heads and resolvedOpts.tails can't be equal!");if(t.heads===t.headsNoWrap)throw new Error("json-variables/jVar(): [THROW_ID_10] Alas! resolvedOpts.heads and resolvedOpts.headsNoWrap can't be equal!");if(t.tails===t.tailsNoWrap)throw new Error("json-variables/jVar(): [THROW_ID_11] Alas! resolvedOpts.tails and resolvedOpts.tailsNoWrap can't be equal!");if(t.headsNoWrap==="")throw new Error("json-variables/jVar(): [THROW_ID_12] Alas! resolvedOpts.headsNoWrap is an empty string!");if(t.tailsNoWrap==="")throw new Error("json-variables/jVar(): [THROW_ID_13] Alas! resolvedOpts.tailsNoWrap is an empty string!");if(t.headsNoWrap===t.tailsNoWrap)throw new Error("json-variables/jVar(): [THROW_ID_14] Alas! resolvedOpts.headsNoWrap and resolvedOpts.tailsNoWrap can't be equal!");let n;return L(r,(a,i,m)=>{if(q(i)&&T(a,t))throw new Error(`json-variables/jVar(): [THROW_ID_15] Alas! Object keys can't contain variables! Please check the following key: ${a}`);if(i!==void 0?n=i:n=a,n==="")return n;if(t.heads.length&&g(n)===g(t.heads)||t.tails.length&&g(n)===g(t.tails)||t.headsNoWrap.length&&g(n)===g(t.headsNoWrap)||t.tailsNoWrap.length&&g(n)===g(t.tailsNoWrap)){if(!t.noSingleMarkers)return n;throw new Error(`json-variables/jVar(): [THROW_ID_16] Alas! While processing the input, we stumbled upon ${g(n)} which is equal to ${g(n)===g(t.heads)?"heads":""}${g(n)===g(t.tails)?"tails":""}${o(t.headsNoWrap)&&g(n)===g(t.headsNoWrap)?"headsNoWrap":""}${o(t.tailsNoWrap)&&g(n)===g(t.tailsNoWrap)?"tailsNoWrap":""}. If you wouldn't have set resolvedOpts.noSingleMarkers to "true" this error would not happen and computer would have left the current element (${g(n)}) alone`)}return o(n)&&T(n,t)?R(r,n,m.path,t):n})}export{z as defaults,pe as jVar,ce as version};