Skip to content

Commit

Permalink
Merge pull request #1138 from blackflux/dev
Browse files Browse the repository at this point in the history
[Gally]: master <- dev
  • Loading branch information
simlu committed May 29, 2020
2 parents e62b483 + 2ce57d5 commit 568cfc4
Show file tree
Hide file tree
Showing 27 changed files with 411 additions and 69 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
"@babel/core": "7.10.1",
"@babel/plugin-proposal-object-rest-spread": "7.10.1",
"@babel/register": "7.10.1",
"@blackflux/eslint-plugin-rules": "1.3.28",
"@blackflux/eslint-plugin-rules": "1.3.29",
"@blackflux/robo-config-plugin": "3.4.1",
"babel-eslint": "10.1.0",
"chai": "4.2.0",
Expand Down
13 changes: 12 additions & 1 deletion src/load.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ const fs = require('smart-fs');
const Joi = require('joi-strict');
const { syncDocs, generateDocs } = require('./plugin/docs');
const { applyTasksRec, listPublicTasks, extractMeta } = require('./plugin/task');
const { populateVars } = require('./plugin/vars');
const { populateVars, varTypes } = require('./plugin/vars');

module.exports = (pl) => {
Joi.assert(pl, Joi.object().keys({
Expand All @@ -17,6 +17,10 @@ module.exports = (pl) => {
exports: Joi.any().optional()
}), 'Bad Plugin Definition.');

const var2Type = fs.walkDir(pl.varDir).reduce((p, f) => Object.assign(p, {
[f.slice(0, -5)]: fs.smartRead(path.join(pl.varDir, f)).type
}), {});

const applyTasks = (projectRoot, tasks, variables, exclude) => {
assert(typeof projectRoot === 'string');
assert(
Expand All @@ -43,6 +47,13 @@ module.exports = (pl) => {
syncDocs: () => syncDocs(pl.name, pl.taskDir, pl.reqDir, pl.varDir, pl.targetDir, pl.docDir),
generateDocs: (tasks, exclude) => genDocs(tasks, exclude),
apply: applyTasks,
validateVars: (vars) => {
Object.entries(vars).forEach(([k, v]) => {
if (varTypes[var2Type[k]](v) !== true) {
throw new Error(`Invalid variable type for "${k}". Expected "${var2Type[k]}".`);
}
});
},
test: (testRoot, variables = {}) => {
const knownTargets = fs
.walkDir(testRoot)
Expand Down
4 changes: 2 additions & 2 deletions src/plugin/docs.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ const path = require('path');
const Joi = require('joi-strict');
const sfs = require('smart-fs');
const treeify = require('object-treeify');
const { determineVars } = require('./vars');
const { determineVars, varTypes } = require('./vars');
const { listPublicTasks } = require('./task');

const normalizeRef = (input) => input
Expand Down Expand Up @@ -217,7 +217,7 @@ const generateDocs = (plName, taskDir, reqDir, varDir, targetDir, tasks, exclude
schema: Joi.object().keys({
description: Joi.string(),
details: Joi.array().items(Joi.string()).optional(),
type: Joi.string().valid('string', 'boolean', 'object', 'array', 'number', 'integer')
type: Joi.string().valid(...Object.keys(varTypes))
})
},
{
Expand Down
2 changes: 1 addition & 1 deletion src/plugin/task.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
const assert = require('assert');
const fs = require('fs');
const fs = require('smart-fs');
const path = require('path');
const get = require('lodash.get');
const deepmerge = require('deepmerge');
Expand Down
24 changes: 18 additions & 6 deletions src/plugin/vars.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@ const objectScan = require('object-scan');

const modifiers = {
UPPER: (input) => input.toUpperCase(),
TITLE: (input) => `${input.slice(0, 1).toUpperCase()}${input.slice(1).toLowerCase()}`,
LOWER: (input) => input.toLowerCase()
TITLE: (input) => input.toLowerCase().replace(/(?<![a-z])[a-z]/g, (m) => m.toUpperCase()),
LOWER: (input) => input.toLowerCase(),
KEBAB: (input) => input.replace(/[^a-zA-Z0-9]+/g, '-'),
SNAKE: (input) => input.replace(/[^a-zA-Z0-9]+/g, '_'),
STRIP: (input) => input.replace(/[^a-zA-Z0-9]+/g, '')
};
const applyModifier = (input, modifier) => {
if (typeof input !== 'string') {
Expand All @@ -15,14 +18,14 @@ const applyModifier = (input, modifier) => {
if (modifier === undefined) {
return input;
}
return modifiers[modifier](input);
return modifier.slice(1).split('|').reduce((value, m) => modifiers[m](value), input);
};

const varNameGroup = new RegExp([
/(?<varName>[-_a-zA-Z0-9]+)/.source,
'(?:\\|(?<modifier>',
'(?<modifier>(?:\\|(?:',
Object.keys(modifiers).join('|'),
'))?'
'))+)?'
].join(''), 'g');

const varRegex = new RegExp([
Expand Down Expand Up @@ -60,7 +63,7 @@ const substituteVariables = (input, variables, allowFullMatch, usedVars) => {
const { varName, modifier } = args[args.length - 1];
const r = applyModifier(variables[varName], modifier);
assert(r !== undefined, `Unmatched Variable Found: $\{${varName}}`);
assert(typeof r === 'string', `Variable Expected to be String: $\{${varName}}`);
assert(!(r instanceof Object), `Variable Expected to be Primitive: $\{${varName}}`);
usedVars.add(varName);
return r;
});
Expand Down Expand Up @@ -138,3 +141,12 @@ module.exports.determineVars = (data) => {
})(data);
return result;
};

module.exports.varTypes = {
string: (v) => typeof v === 'string',
boolean: (v) => typeof v === 'boolean',
object: (v) => v instanceof Object && !Array.isArray(v),
array: (v) => Array.isArray(v),
number: (v) => typeof v === 'number',
integer: (v) => Number.isInteger(v)
};
6 changes: 6 additions & 0 deletions src/process.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ const path = require('path');
const Joi = require('joi-strict');
const appRoot = require('app-root-path');
const sfs = require('smart-fs');
const objectScan = require('object-scan');
const load = require('./load');
const lockFile = require('./lock-file');

Expand Down Expand Up @@ -63,6 +64,11 @@ module.exports = (projectRoot = appRoot.path) => {
.forEach(([pluginName, pluginPayload]) => {
// eslint-disable-next-line import/no-dynamic-require,global-require
const plugin = load(require(pluginName));
objectScan(['**.variables'], {
filterFn: ({ value }) => {
plugin.validateVars(value);
}
})(pluginPayload);
Object.assign(pluginPayload, { plugin });
});

Expand Down
50 changes: 42 additions & 8 deletions test/index.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,31 @@ describe('Robo + Plugin Integration Tests', { useTmpDir: true }, () => {
);
});

it('Testing Bad Variable Format', ({ dir }) => {
sfs.smartWrite(path.join(dir, '.roboconfig.json'), {
[pluginFile]: {
tasks: [
{
name: 'misc/@default',
variables: {
misc: 'target1'
}
}
],
variables: {
variable: 123,
string: 'string',
boolean: true,
object: {},
array: [],
number: 123.1,
integer: 113
}
}
});
expect(() => robo(dir)).to.throw('Invalid variable type for "variable". Expected "string".');
});

it('Testing Multi Task', ({ dir }) => {
sfs.smartWrite(path.join(dir, '.roboconfig.json'), {
[pluginFile]: {
Expand All @@ -120,21 +145,30 @@ describe('Robo + Plugin Integration Tests', { useTmpDir: true }, () => {
}
],
variables: {
variable: 'var'
variable: 'var',
string: 'string',
boolean: true,
object: {},
array: [],
number: 123.1,
integer: 113
}
}
});
expect(robo(dir)).to.deep.equal([
'Updated: target1.txt',
'Updated: target2.txt',
'Updated: target1.yml',
'Updated: target2.yml',
'Updated: CONFDOCS.md'
]);
expect(robo(dir)).to.deep.equal([]);
expect(sfs.smartRead(path.join(dir, 'target1.txt')))
.to.deep.equal(['var', 'VAR', 'Var', 'var']);
expect(sfs.smartRead(path.join(dir, 'target2.txt')))
.to.deep.equal(['var', 'VAR', 'Var', 'var']);
const data = [
'var', 'VAR', 'Var', 'var',
'some-words', 'some_words', 'somewords', 'SomeWords', 'SOME_WORDS', 'some-words',
'string', true, {}, [], 123.1, 113
];
expect(sfs.smartRead(path.join(dir, 'target1.yml'))).to.deep.equal({ data });
expect(sfs.smartRead(path.join(dir, 'target2.yml'))).to.deep.equal({ data });
expect(sfs.smartRead(path.join(dir, '.roboconfig.lock'), { treatAs: 'json' }))
.to.deep.equal({ 'mock-plugin': ['target1.txt', 'target2.txt'] });
.to.deep.equal({ 'mock-plugin': ['target1.yml', 'target2.yml'] });
});
});
8 changes: 4 additions & 4 deletions test/load.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,11 @@ describe('Testing Test Plugin', { useTmpDir: true }, () => {
'Updated: CONFDOCS.md'
],
'misc/@other': [
'Updated: misc.txt',
'Updated: misc.yml',
'Updated: CONFDOCS.md'
],
'misc/@default': [
'Updated: misc.txt',
'Updated: misc.yml',
'Updated: CONFDOCS.md'
],
'nested-txt-overwrite/@default': [
Expand Down Expand Up @@ -108,10 +108,10 @@ describe('Testing Test Plugin', { useTmpDir: true }, () => {
'txt-overwrite/@default': [],
'txt-merge-below-title/@default': [],
'misc/@other': [
'Updated: misc.txt'
'Updated: misc.yml'
],
'misc/@default': [
'Updated: misc.txt'
'Updated: misc.yml'
],
'nested-txt-overwrite/@default': [],
'txt-create-only/@default': [],
Expand Down
Loading

0 comments on commit 568cfc4

Please sign in to comment.