Info: Docs for SAO v1 can be found here.
SAO v2 is currently in beta:
npm i -g sao@betasao nm my-projectRunning this command will download the generator from npm (sao-nm) and generate a new project to ./my-project directory.
You can also use any GitHub repo:
sao egoist/graphql-api-starter new-projectWhen the generator does not include a file called saofile.js, SAO will simply copy it to output directory. In this case it works kinda like git clone but without git history and the generator will be cached locally.
Starting by creating a new folder, let's call it sao-npm because we want to use it to scaffold out a npm package. Then create a saofile.js inside the folder:
module.exports = {
prompts: [
{
type: 'input',
name: 'name',
message: 'What is the name of this package',
},
{
type: 'input',
name: 'description',
message: 'How would you describe this package',
},
],
actions: [
{
type: 'add',
files: '**',
},
],
}Here we use prompts to ask users some questions and retrieve answers as an object which looks like { name: '..', description: '...' }.
Next we use actions to define a series of actions, the add action will copy files from template/ folder within your generator to the output directory.
Now let's create some template files, for example, template/package.json:
{
"name": "<%= name %>",
"description": "<%= description %>",
"version": "0.0.0"
}Template files supports ejs template engine, and the answers we retrieved will be available here as local variables.
prompts is a list of questions you want the user to answer.
Each prompt object has a type property, which can be either:
"input" | "invisible" | "list" | "password" | "text": StringPromptOptions"confirm": BooleanPromptOptions"autocomplete" | "editable" | "form" | "multiselect" | "select" | "survey" | "list" | "scale": ArrayPromptOptions
Check out the GeneratorConfig['prompts'] type for details.
Sub generators are usually used to process files in an already generated project, for example you can use a sub generator to add a LICENSE file:
module.exports = {
subGenerators: [
{
name: 'license',
generator: './generators/license',
},
],
}The sub generator can be a local folder like ./generators/license or an npm package (like sao-license) which can be resolved in your generator.
Then you can invoke this sub generator like this:
sao {root_generator_name}:license
Using the testing framework Jest as example:
import { SAO } from 'sao'
test('it works', () => {
const sao = new SAO({
generator: '/absolute/path/to/your/generator',
// `mock` make SAO run in mock mode
// then it will use default value for prompts
// It defaults to `process.env.NODE_ENV === 'test'`
// if it's not specified explicitly
mock: true
})
await sao.run()
expect(sao.answers).toEqual({
answerA: true,
answerB: 'foo'
})
expect(await sao.getOutputFiles()).toEqual([
'a.js',
'b.js'
])
expect(await sao.readOutputFile('foo.js')).toBe(`const foo = 'foo'`)
})Setting the option mock to true or setting process.env.NODE_ENV to test will make SAO run in mock mode:
- All prompts will use default value instead of asking user for input, you can also pass a custom
answersobject if you want. - Use mocked value for git user information.
- Logger won't output text to terminal, instead they're saved to
sao.logger.lines outDirwill be a random temporary directory.
By setting mock: true you are essentially making all prompts use their default values, however you can provide custom answers:
const sao = new SAO({
generator: '/absolute/path/to/your/generator',
mock: true,
answers: {
unitTest: true,
},
})With above code you can test if you generator works properly when the answer of unitTest is true