Skip to content
This repository was archived by the owner on Apr 26, 2022. It is now read-only.

Commit 0f18864

Browse files
committed
adds logic to cleanup action config data after action completes
1 parent b2fedd2 commit 0f18864

File tree

2 files changed

+36
-12
lines changed

2 files changed

+36
-12
lines changed

src/generator-runner.js

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ export default function (plopfileApi, flags) {
3030
});
3131

3232
// Run the actions for this generator
33-
const runGeneratorActions = co.wrap(function* (genObject, data, hooks={}) {
33+
const runGeneratorActions = co.wrap(function* (genObject, data={}, hooks={}) {
3434
const noop = () => {};
3535
const {
3636
onSuccess=noop, // runs after each successful action
@@ -111,28 +111,29 @@ export default function (plopfileApi, flags) {
111111
const executeActionLogic = co.wrap(function* (action, cfg, data) {
112112
const type = cfg.type || '';
113113

114-
// convert any returned data into a promise to
115-
// return and wait on
116114
let cfgData = cfg.data || {};
117115
// data can also be a function that returns a data object
118116
if (typeof cfgData === 'function') { cfgData = yield cfgData(); }
119-
Object.keys(cfgData || {}).forEach(k => {
120-
if (typeof data[k] === 'undefined' || (data[k] && cfgData[k])) {
121-
data[k] = cfgData[k];
122-
}
123-
});
124-
return yield Promise.resolve(action(data, cfg, plopfileApi)).then(
117+
118+
// track data properties that can be applied to the main data scope
119+
const cfgDataProps = Object.keys(cfgData).filter(k => typeof data[k] === 'undefined');
120+
// copy config data into main data scope so it's available for templates
121+
cfgDataProps.forEach(k => {data[k] = cfgData[k];});
122+
123+
return yield (Promise.resolve(action(data, cfg, plopfileApi))
125124
// show the resolved value in the console
126-
result => ({
125+
.then(result => ({
127126
type, path: (typeof result === 'string'
128127
? result
129128
: JSON.stringify(result)
130129
)
131130
}),
132131
// a rejected promise is treated as a failure
133-
function (err) {
132+
err => {
134133
throw { type, path: '', error: err.message || err.toString() };
135-
}
134+
})
135+
// cleanup main data scope so config data doesn't leak
136+
.finally(() => cfgDataProps.forEach(k => {delete data[k];}))
136137
);
137138
});
138139

tests/action-data-cleanup.ava.js

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import co from 'co';
2+
import AvaTest from './_base-ava-test';
3+
const {test, testSrcPath, nodePlop} = (new AvaTest(__filename));
4+
5+
const plop = nodePlop();
6+
7+
// Make sure that props added by the action's data attr are cleaned up
8+
// after the action executes
9+
10+
test('Action data cleanup', co.wrap(function* (t) {
11+
const actions = ['one', 'two', 'three'].map(fName => ({
12+
type: 'add',
13+
template: '',
14+
path: `${testSrcPath}/{{fName}}-{{unchanged}}.txt`,
15+
data: {fName, unchanged: `${fName}-unchanged`}
16+
}));
17+
const g = plop.setGenerator('', {actions});
18+
const {changes, failures} = yield g.runActions({unchanged: 'unchanged'});
19+
const addedFiles = changes.map(c => c.path.split('/').slice(-1)).join('|');
20+
t.is(addedFiles, 'one-unchanged.txt|two-unchanged.txt|three-unchanged.txt');
21+
t.is(changes.length, 3);
22+
t.is(failures.length, 0);
23+
}));

0 commit comments

Comments
 (0)