sdawood / json-tots

JSON Template of Templates
MIT License
9 stars 4 forks source link

Filtering via an outer object #6

Open repl-mike-roest opened 5 years ago

repl-mike-roest commented 5 years ago

I'm trying to use your library to do some object transformations and I'm trying to figure out a way to implement the following

{
  "plan": {
    "swimlane": "test1",
    "test": {
      "blarg": "sre"
    }
  },
  "config": {
    "accountid": "12345678",
    "component": {
      "component-1": {}
    },
    "swimlanes": {
      "test1": {
        "awsregion": "us-west-1",
        "service": {
          "component-1": {
            "application-name": "app1",
            "environment-name": "env1"
          }
        }
      },
      "test2": {
        "awsregion": "eu-west-1",
        "service": {
          "component-1": {
            "application-name": "app2",
            "environment-name": "env2"
          }
        }
      }
    }
  }
}

Given this data document I'm trying to apply this template (logically)

{
  "version": "<VERSION>",
  "metadata": {
    "component": "component-1",
    "task": [{
      "name": "deploy",
      "aws-ecs": {
        "region": "{{$.config.swimlanes[plan.swimlane].awsregion}|",
        "accountid": "{{$.config.accountid}}"
      },
      "docker": {
        "image": "<DEPLOYIMAGE>",
        "environment": {
          "APPLICATION_NAME": "{{$.config.swimlanes[plan.swimlane].service.component-1.application-name}}",
          "ENVIRONMENT_NAME": "{{$.config.swimlanes[plan.swimlane].service.component-1.environment-name}}",
          "VERSION": "<VERSION>"
        }
      }
    }]
  }
} 

But I can't seem to figure out a way to filter the config.swimlanes object by a parent level key. Is this possible? i found a hacky way to access a top level element referenced by the parent key with a custom function like so.

const lookup = (path,key,subpath) => {
  console.log(subpath);
  const res = jp.query(data.config, `$.${path}.${key}.${subpath}`);
  if(Array.isArray(res) && res.length === 1) {
    return res[0];
  }
  return res;
}

and then referencing it in the template

{{$.plan.swimlane} | lookup:swimlanes:__:awsregion}}

but it doesn't seem to work with a sub key

{{$.plan.swimlane} | lookup:swimlanes:__:service.component-1.application-name}}

It just renders the raw string in the second case Thanks

repl-mike-roest commented 5 years ago

Well I've gotten something to work but it's pretty gross.

I had to munge my json keys to remove - and replace with _ it's not nice but at least it allows me to dive into a deeper object with my update lookup function:

const lookup = (...args) => {
  const res = jp.query(data, `$.${args.join('.')}`);
  if(Array.isArray(res) && res.length === 1) {
    return res[0];
  }
  return res;
}

And I added a additional helper method to munge values if I need to use them as lookups into other keys:

const keyify = (val) => {
  return val.replace(/-/g,'_');
}

this allows me to do something like this in my template

{{$.plan.swimlane} | lookup:config:swimlanes:__:service:component_1:application_name}

and I can chain multiple lookups together if I need to do multiple dives to get to a key. But it still seems really messy and would appreciate any suggestions if there is a nicer way to do this.