From 69bf6d86799d8a1bd469ba8493936a440ddc4f0a Mon Sep 17 00:00:00 2001 From: Trey Shugart Date: Sat, 22 Jun 2019 16:02:18 +1000 Subject: [PATCH] Add ability to specify asynd functions in json data that resolve using the key, previous value and object. Remove file.data overriding file.type. They now compose together. --- src/handler.js | 44 ++++++++++++++++++++++++++++++++++++++------ src/sync.js | 2 ++ 2 files changed, 40 insertions(+), 6 deletions(-) diff --git a/src/handler.js b/src/handler.js index dbc7fca..88d54cf 100644 --- a/src/handler.js +++ b/src/handler.js @@ -1,11 +1,39 @@ const fs = require("fs-extra"); const isFunction = require("lodash/isFunction"); -const merge = require("lodash/merge"); +const mergeWith = require("lodash/mergeWith"); const path = require("path"); const prettier = require("prettier"); const stripIndent = require("strip-indent"); const uniq = require("lodash/uniq"); +// Recursively maps over values and allows async functions to be used to +// return new values. If a previousObj is provided, it uses it to retrieve +// a value that corresponds to the same place in oldObj so you can use it +// to return the new value. +async function mapValues(oldObj, previousObj) { + previousObj = previousObj || {}; + const newObj = Array.isArray(oldObj) ? [] : {}; + for (const key in oldObj) { + newObj[key] = isFunction(oldObj[key]) + ? await oldObj[key](key, previousObj[key], previousObj) + : oldObj[key]; + if (typeof newObj[key] === "object") { + newObj[key] = await mapValues(newObj[key], previousObj[key]); + } + } + return newObj; +} + +// Allows for custom merging. +function merge(...src) { + return mergeWith({}, ...src, (objval, srcval, key, obj) => { + // Remove item if explicitly set to undefined. + if (typeof srcval === "undefined") { + delete obj[key]; + } + }); +} + async function getPrettierConfig(file) { return await prettier.resolveConfig(file); } @@ -57,6 +85,8 @@ async function handleJson(file) { data = file.data; } + data = await mapValues(data, currJson); + return JSON.stringify(data, null, 2); } @@ -88,13 +118,13 @@ const mapType = { object: handleJson }; +async function getData(file) { + return isFunction(file.data) ? await file.data(file) : file.data; +} + function getType(file) { let type; - if (isFunction(file.data)) { - return file.data; - } - if (isFunction(file.type)) { return file.type; } @@ -118,7 +148,9 @@ function getType(file) { } async function handler(file) { - return await getType(file)(file); + file.data = await getData(file); + file.type = await getType(file); + return file.type(file); } module.exports = { diff --git a/src/sync.js b/src/sync.js index 282d21d..743fde9 100644 --- a/src/sync.js +++ b/src/sync.js @@ -110,6 +110,8 @@ async function sync(cfg, opt) { // and in the same convention, files at the top level override everything // else before it. for (let file of cfg.files) { + // We copy file so that we can mutate it without affecting the original + // copy. file = { ...cfg.fileDefaults, ...file,