✨ Create Initializer
Create your own `create-something` app.
NOTE
This is a forked and modified version of create-create-app. Modifications may be differ from the initial design of the original project so this will not be merged to the upstream and will be made into a seperate package.
Why?
- ⚖️ Built-in License selector No need to manually add license things.
- 🎩 Template engine Mustache will do things all.
- 💄 Highly customizable Changable caveat text, and add extra cli options.
Table of contents
Quick Start
Let's create create-greet
package in four steps.
1. npm create initializer
npm create initializer greet
or if you use yarn
, then run yarn create initializer greet
2. Edit templates
cd create-greet
and edit files inside templates/default
.
TypeScript
Run npm run build
or yarn build
to transpile TypeScript code into JavaScript.
3. Publish package to npm
Run npm publish
or yarn publish
to publish your create-greet
app to npm.
4. PROFIT!
npm create greet ohayo
Template
Edit files inside templates/default
. File names, directory names, and text files will be processed through Handlebars template engine to replace all template strings with respective value.
Built-in variables are:
{{name}}
package name{{description}}
package description{{author}}
author name{{email}}
author email{{contact}}
author name formatted with {{name}} <{{email}}>
if email given, otherwise {{name}}
{{license}}
package license (e.g. MIT
){{year}}
current year (e.g. 2020
)
Adding a template
Add new directory to the location defined in templateRoot
; it will be accessible in --template
flag (e.g. create-something <name> --template <template>
).
Besides, set promptForTemplate
true to explicitly ask users to pick a template in initialization phase, otherwise default
will be used.
Helper functions
In the following example, we assume that variable name
is create-react-app
.
upper
Output text in UPPERCASE.
{{upper name}}
becomes CREATE-REACT-APP
.
lower
Output text in lowercase.
{{lower name}}
becomes create-react-app
.
capital
Output text in CapitalCase.
{{capital name}}
becomes CreateReactApp
{{capital name space=true}}
becomes Create React App
.
camel
Output text in camelCase.
{{camel name}}
becomes createReactApp
.
snake
Output text in snake_case.
{{snake name}}
becomes create_react_app
.
kebab
Output text in kebab-case.
{{kebab name}}
becomes create-react-app
.
space
Replace all word separators with single space.
{{space name}}
becomes create react app
uuid
Generates unique UUID string.
{{uuid}} // => a5df7100-da46-47a6-907e-afe861f48b39
{{upper (uuid)}} // => A5DF7100-DA46-47A6-907E-AFE861F48B39
Config
You can find the app config in src/cli.js
(or src/cli.ts
if you chose typescript
template).
import { resolve } from 'path';
import { create } from 'create-initializer';
create('create-greet', {
templateRoot: resolve(__dirname, '..', 'templates'),
defaultTemplate: 'my-template',
templatePrefix: 'template-',
extra: {
language: {
type: 'input',
describe: 'greeting language',
default: 'en',
prompt: 'if-no-arg',
},
},
modifyName: (name) => `package-prefix-${name}`,
after: ({ installNpmPackage }) => installNpmPackage('chalk'),
caveat: `Your app has been created successfully!`,
});
templateRoot (required)
templateRoot
set to path.resolve(__dirname, '../templates')
. You can change it to whereever you want.
templatePrefix (default: <empty string>
)
Set the prefix for template folder. Template prefix will be removed when displaying choices for the template.
For example: we have a template folder named template-awesome
, we set templatePrefix
to template-
, then
create-something <name> --template awesome
will copy template-awesome
to the destination dir.
promptForTemplate (default: false
)
Ask users to choose a template to be used for initialization only if promptForTemplate
is set true
AND there's multiple templates found in templates/
.
With promptForTemplate
set false
, users still can specify template via command-line flag --template
:
create-something <name> --template <template>
defaultTemplate (default: default
)
Set the default template choice. Works both when promptForTemplate
is true
or false
.
object | undefined
Extra options passed to the app. These options will be accessible as a cli option, interactive question, and template string. In this case, --language
cli option and {{language}}
template string will be available.
You can find all possible options in yargs-interactive documentation.
modifyName (default: undefined
)
(name: string) => string | Promise<string>
Modify name
property.
after (default: undefined
)
(options: AfterHookOptions) => void
After hook script that runs after the initialization.
caveat (default: undefined
)
string | ((options: AfterHookOptions) => string | void) | undefined
The caveat message will be shown after the entire process completed.
create('create-greet', {
caveat: 'Happy coding!',
});
create('create-greet', {
caveat: ({ answers }) => `Run -> cd ${answers.name} && make`,
});
create('create-greet', {
caveat: async ({ packageDir, answers }) => {
const { plugin } = answers;
await execa('npm', ['install', '--prefix', packageDir, '-S', plugin]);
console.log(`"${plugin}" has been added`);
},
});
AfterHookOptions
{
packageDir: string;
templateDir: string;
year: number;
answers: {
name: string;
description: string;
author: string;
email: string;
contact: string;
license: string;
[key: string]: string | number | boolean | any[];
};
run: (command: string, options?: CommonOptions<string>) => ExecaChildProcess<string>;
installNpmPackage: (packageName: string) => Promise<void>;
}
Contribution
PRs are always welcome!