Skip to content

Instantly share code, notes, and snippets.

@mritzco
Created March 8, 2018 08:09
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save mritzco/88306b56c0184e66e33374d6b6ed2751 to your computer and use it in GitHub Desktop.
Save mritzco/88306b56c0184e66e33374d6b6ed2751 to your computer and use it in GitHub Desktop.
Custom action for plop. Appends data to JSON files
const fs = require('fs-extra');
const methods = {}, priv = {};
// Private methods to do string replacement. Not optimized and cummulative trying to keep it simple.
// far better options here: https://stackoverflow.com/questions/5069464/replace-multiple-strings-at-once
priv.replaceObj = function(value, vars) {
let obj = value;
Object.keys(obj).forEach(function(item) {
obj[item] = priv.replaceStr(obj[item], vars);
});
return obj;
}
priv.replaceStr = function(value, vars) {
let val = value;
Object.keys(vars).forEach(function(var_key) {
let find = new RegExp( '{{' + var_key + '}}' , "g");
val = val.replace(find, vars[var_key]);
});
return val;
}
// Replaces in string or all object values. Arrays not considered
priv.replace = function(value, vars) {
return (typeof value === "object") ? priv.replaceObj(value, vars) : priv.replaceStr(value, vars);
}
/**
* Inserts entries into JSON arrays or objects
*
* To use with objects be sure to pass the property JSONEntryKey,
* otherwise the value is inserted as arrays
* @method
* @param {string} file filename with the JSONKey
* @param {string} key JSON attribute (the array or object) to append to
* @param {string || object} value The string or object to appendJSON
* @param {object} vars User input on prompts passed by plop
* @param {Function} cb callback, after file has been saveSidebarRef
* @return {callback(err)} Async callback with err or null if success.
*/
methods.appendJSON = function (config, vars, cb) {
fs.readJSON(config.JSONFile, {}, (err, json) => {
// Object or array
let attribute_name = config.hasOwnProperty("JSONEntryKey") ?
priv.replaceStr(config.JSONEntryKey, vars) : null;
// Validate JSON is correct - we don't autoadd only append top level
if (!json.hasOwnProperty(config.JSONKey)) {
return cb('JSON has no property: ' + config.JSONKey);
}
// Follow plop style, don't override existing entries unless force is true.
if (!config.force && attribute_name && json[config.JSONKey].hasOwnProperty(attribute_name)) {
return cb("Attribute: " + attribute_name + ' already exist in ' + config.JSONKey)
}
// Do replacements in value (value can be a string or an object)
let insert_val = priv.replace(config.JSONEntryValue, vars);
// Choosing object (key:value) OR push(value)
if (attribute_name) {
json[config.JSONKey][attribute_name] = insert_val;
} else {
json[config.JSONKey].push( insert_val);
}
fs.writeJSON(config.JSONFile, json, {spaces: 2}, err => {
cb(err);
});
});
}
// Finally the action type.
plop.setActionType('appendJSON', function(answers, config, plop) {
return new Promise((resolve, reject) => {
methods.appendJSON(
config,
answers,
function callback(err){
if (!err) {
resolve('JSON File has been updated');
} else {
reject('appendJSON failed: ' + err);
}
}
);
});
});
plop.setGenerator( "package", {
description: "Creates a new package",
prompts: [
{
type: "input",
name: "name",
message: "What is your package name?"
}
],
actions: [
{
type: "add",
path: "lib/{{name}}/{{name}}.js",
templateFile: ".plop-templates/module.js"
},
{ // push an object in array packages
type: 'appendJSON',
JSONFile: "config.json",
JSONKey: "packages",
JSONEntryValue: { "mountpath": "/{{name}}","module": "{{name}}/{{name}}_router"}
},
{ // adds an attribute: {{name}}, with value: {object} in object packages
type: 'appendJSON',
JSONFile: "config.json",
JSONKey: "packages",
JSONEntryKey: "{{name}}",
JSONEntryValue: { "mountpath": "/{{name}}","module": "{{name}}/{{name}}_router"}
}
]
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment