“before” and “after” tasks
“makes” work flow
The whole work flow is not complex.
- download skeleton.
- read skeleton optional files
questions.js
,transforms.js
,before.js
, andafter.js
. - runs optional “before” task defined by
before.js
. - run through questions, gather
properties
andfeatures
. - write out project.
- runs optional “after” task defined by
after.js
.
“after” task
We start with the more common “after” task.
“after” task happens after “makes” finished writing out project.
For example you can follow up in a JavaScript project to install npm dependencies.
The dumberjs/new
after.js
is a great example.
For more information, please review CommonJS/ESM support.
const {execSync} = require('child_process');
function isAvailable(bin) {
try {
execSync(bin + ' -v')
return true;
} catch (e) {
return false;
}
}
module.exports = async function({
unattended, here, prompts, run, properties, features, notDefaultFeatures, ansiColors
}) {
const c = ansiColors;
let depsInstalled = false;
if (!unattended) {
const choices = [
{title: 'No'},
{value: 'npm', title: 'Yes, use npm'}
];
if (isAvailable('yarn')) {
choices.push({value: 'yarn', title: 'Yes, use yarn'});
}
if (isAvailable('pnpm')) {
choices.push({value: 'pnpm', title: 'Yes, use pnpm'});
}
const result = await prompts.select({
message: 'Do you want to install npm dependencies now?',
choices
});
if (result) {
await run(result, ['install']);
depsInstalled = true;
}
console.log(`\nNext time, you can try to create similar project in silent mode:`);
console.log(c.inverse(` npx makes dumberjs new-project-name${here ? ' --here' : ''} -s ${notDefaultFeatures.length ? (notDefaultFeatures.join(',') + ' ') : ''}`));
}
console.log(`\n${c.underline.bold('Get Started')}`);
console.log('cd ' + properties.name);
if (!depsInstalled) console.log('npm install');
console.log('npm start\n');
};
You define a function in after.js
.
- the single input argument has following fields:
unattended
is true when in silent mode.here
is true when in here mode.features
is the selected features array from select prompts.notDefaultFeatures
is a sub-set offeatures
array, only contains non-default choices. You can use this array to construct a clear silent mode command, as the above example showed.properties
is theproperties
hash object from text prompts.prompts
is the exposed “makes” inner prompts implementation. You can callprompts.text(opts)
andprompts.select(opts)
to ask user questions, more details in prompts api doc.ansiColors
is the exposed “ansi-colors” npm package. This is provided for skeleton to avoid some runtime dependencies.sisteransi
is the exposed “sisteransi” npm package. This is provided for skeleton to avoid some runtime dependencies.run(cmd, args)
is a convenient function to run command. It runs the command with optional arguments in the final project folder. The above example showsrun('npm', ['install'])
.
- the result value is ignored. But “after” task can be async (returns a promise).
“before” task
The optional “before” task happens right before prompting questions, it can:
- silence the questions defined in
questions.js
. For example, “before” task can let user to choose a preset to skip detailed questionnaire. - override preselectedFeatures.
- override predefinedProperties.
- or maybe just print out some greetings.
“before” task should also respect existing silent mode (aka unattended).
You define a function in before.js
.
- the single input argument has following fields:
unattended
is true when in silent mode.here
is true when in here mode.preselectedFeatures
is the pre-selected features array from optional command line switch-s x,y,z
, default to an empty array.predefinedProperties
is the pre-defined properties hash object gathered from command line, default to an empty object.prompts
is the exposed “makes” inner prompts implementation. You can callprompts.text(opts)
andprompts.select(opts)
to ask user questions, more details in prompts api doc.ansiColors
is the exposed “ansi-colors” npm package. This is provided for skeleton to avoid some runtime dependencies.sisteransi
is the exposed “sisteransi” npm package. This is provided for skeleton to avoid some runtime dependencies.
- “before” task can be async (returns a promise). The result value is optional, but when you return a value object, it can have following optional fields:
silentQuestions
, if set totrue
, the questions defined inquestions.js
will be silenced.preselectedFeatures
, overrides existingpreselectedFeatures
.predefinedProperties
, overrides existingpredefinedProperties
.
For example, aurelia/new skeleton use “before” task to ask user to:
- pick a preset (silence questionnaire, plus override
preselectedFeatures
). - or use custom mode (does nothing, run through questions interactively).
The aurelia/new
before.js
is a great example. It asks user to pick a preset, if user picked one, it will skip following questionnaire and overwrite preselectedFeatures.
const PRESETS = {
'default-esnext': ['webpack', 'babel'],
'default-typescript': ['webpack', 'typescript'],
};
module.exports = async function({unattended, prompts}) {
// don't ask when running in silent mode.
if (unattended) return;
const preset = await prompts.select({
message: 'Would you like to use the default setup or customize your choices?',
choices: [
{
value: 'default-esnext',
title: 'Default ESNext Aurelia 2 App',
hint: 'A basic Aurelia 2 App with Babel and Webpack'
}, {
value: 'default-typescript',
title: 'Default TypeScript Aurelia 2 App',
hint: 'A basic Aurelia 2 App with TypeScript and Webpack'
}, {
title: 'Custom Aurelia 2 App',
hint: 'Select bundler, transpiler, and more.'
}
]
});
if (preset) {
const preselectedFeatures = PRESETS[preset];
if (preselectedFeatures) {
return {
silentQuestions: true, // skip following questionnaire
preselectedFeatures
};
}
}
};