UNPKG

template-kit

Version:
564 lines (425 loc) 23.9 kB
# template-kit [![NPM Version][npm-image]][npm-url] [![NPM Downloads][downloads-image]][downloads-url] [![Deps][david-image]][david-url] [![Dev Deps][david-dev-image]][david-dev-url] Library for creating projects from templates. ## Features * Project generation using local template as a directory, archive file, or globally installed npm package * Download templates from git, npm, or a URL to a archive file * Support for `.zip`, `.gz`, `.bz2`, `.tar`, `tar.gz`, `tar.bz2`, `.tgz`, and `.tbz2` archives * Run text files through [`ejs`][ejs] during file copy * JavaScript lifecycle hooks * User-defined copy file inclusion/exclusion filters * Data-driven destination directory and filenames * npm dependency installation * git repository initialization ## Installation npm install template-kit --save ## Example ```javascript import TemplateEngine from 'template-kit'; (async () => { const engine = new TemplateEngine(); engine.on('create', async (state, next) => { console.log('Creating the project from the template'); await next(); console.log('Project created!'); }); await engine.run({ src: 'git@github.com:appcelerator/template-kit-test.git', dest: '/path/to/new/project' }); console.log('Project created successfully!'); })(); ``` ## Template Specification ### Structure A template can be an empty directory or a massive collection of files and subdirectories. All of the files in the template can be compressed in a single archive file (.zip, .tgz, etc) for distribution. Templates do _not_ need to be npm packages and they do _not_ need to have a `package.json`. If they do, template-kit will happily call `npm install` after generation. Any file that is _not_ binary will be treated as an [ejs][ejs] template regardless of extension. ejs templates have access to any variable or function in the `data` object including the `opts.data` passed into the `TemplateEngine` constructor, the `data` export from the `meta.js`, or any data that has be injected via a hook. Directories and filenames may contain a `{{variable}}` sequence which will be replaced with the corresponding value in the `data` object. By default, template-kit will treat the root of the template directory as the actual template. However, the template may contain several project templates or place all of the template files in a single subdirectory. The relative project template path is defined by setting the `template` property in the `meta.js` file. If there are multiple project templates, then you can present them by using the prompts mechanism. ### Metadata template-kit will load the template's metadata from a `meta.js` file or the package's "main" file. The metadata can be an object or an async function that returns an object. The object contains the following properties: | Property | Type | Description | | -------- | ---------------- | ----------- | | complete | `Function` | A function to call after the project generation is complete. Useful for displaying post create steps. | | data | `Object` | Arbitrary data to mix in with the `run()` data and pass into `ejs` when copying a text file. | | filters | `Array.<String>` | An array of file patterns to copy. The patterns follow the gitignore rules. | | prompts | `Object` | An array of prompt descriptors that is used to select the template and template data. | | template | `String` | Relative path to the template files. Defaults to `'.'` | ## API ### `TemplateEngine` Resolves a template source, installs the template, and manages the install lifecycle. * [`new TemplateEngine(opts)`](#TemplateEngine+constructor) * _methods_ * [`.run(opts)`](#TemplateEngine+run) * _inherited from [`HookEmitter`](https://www.npmjs.com/package/hook-emitter)_ * [`.on(event, listener)`](https://www.npmjs.com/package/hook-emitter#onevent-listener) ➚ * [`.once(event, listener)`](https://www.npmjs.com/package/hook-emitter#onceevent-listener) ➚ * [`.off(event, listener)`](https://www.npmjs.com/package/hook-emitter#offevent-listener) ➚ * _events_ * [`#init`](#TemplateEngine+event+init) * [`#git-clone`](#TemplateEngine+event+git-clone) * [`#download`](#TemplateEngine+event+download) * [`#extract`](#TemplateEngine+event+extract) * [`#extract-file`](#TemplateEngine+event+extract-file) * [`#extract-progress`](#TemplateEngine+event+extract-progress) * [`#npm-download`](#TemplateEngine+event+npm-download) * [`#create`](#TemplateEngine+event+create) * [`#load-meta`](#TemplateEngine+event+load-meta) * [`#prompt`](#TemplateEngine+event+prompt) * [`#copy`](#TemplateEngine+event+copy) * [`#copy-file`](#TemplateEngine+event+copy-file) * [`#npm-install`](#TemplateEngine+event+npm-install) * [`#git-init`](#TemplateEngine+event+git-init) * [`#cleanup`](#TemplateEngine+event+cleanup) ### Constructor <a name="TemplateEngine+constructor"></a> #### `new TemplateEngine(opts)` Initializes the template engine. | Param | Type | Description | | ------------------------------- | --------- | ------------------------------------------------------------ | | [opts] | `Object` | Various options. | | [opts.requestOptions] | `Object` | `got` HTTP client options and proxy/security settings below. | | [opts.requestOptions.caFile] | `String` | A path to a PEM-formatted certificate authority bundle. | | [opts.requestOptions.certFile] | `String` | A path to a client cert file used for authentication. | | [opts.requestOptions.keyFile] | `String` | A path to a private key file used for authentication. | | [opts.requestOptions.proxy] | `String` | A proxy server URL. Can be `http` or `https`. | | [opts.requestOptions.strictSSL] | `Boolean` | When falsey, disables TLS/SSL certificate validation for both `https` requests and `https` proxy servers. | ### Methods <a name="TemplateEngine+run"></a> #### `.run(opts)` ⇒ `Promise` Builds a project based on the specified template and options. | Param | Type | Description | | ------------------- | ------------------------- | --------------- | | opts | `Object` | Various options | | [opts.data] | `Object` | A data object that is passed into `ejs` when copying template files. | | opts.dest | `String` | The destination directory to create the project in. | | [opts.filters] | `Set` \| `Array.<String>` | A list of file patterns to pass into `micromatch` when copying files. | | [opts.force] | `Boolean` | When `true`, overrides the destination if it already exists. | | [opts.git=true] | `Boolean` | When `true` and `git` executable is found, after the the project is generated, initialize a git repo in the project directory. | | [opts.npmArgs] | `Array.<String>` | An array of additional parameters to pass into npm. Useful if you need to add extra arguments for things such as skipping shrinkwrap or production only. | | opts.src | `String` | The path to a directory, archive file, globally installed npm package, archive URL, npm package name, or git repo. | | [opts.template='.'] | `String` | Relative path to the directory containing the template files. This value overrides the default template from the `meta.js`, but not the `template` value returned from prompting. | ##### Run State Every time `run()` is invoked, a new `state` object is created and passed through the various stages. The contents of the `state` depends on the Source Type. | Property | Type | Description | | ----------- | ------------------------- | ------------------------------------------------------------ | | dest | `String` | The destination directory to create the project in. | | destFile | `String` | When copying files, this is the destination file path. | | disposables | `Array.<String>` | A list of temp directories to cleanup. | | extractDest | `String` | The temporary directory where the archive was extracted to. | | filters | `Set` \| `Array.<String>` | A list of file patterns to copy. | | force | `Boolean` | When `true`, overrides the destination if it already exists. | | git | `Boolean` | When `true` and `git` executable is found, after the the project is generated, initialize a git repo in the project directory. | | gitInfo | `Object` | The parsed git repo information. | | npmArgs | `Array.<String>` | An array of additional parameters to pass into npm. Useful if you need to add extra arguments for things such as skipping shrinkwrap. | | npmManifest | `Object` | The npm package information | | prompts | `Array.<Object>` | A list of prompt descriptors. | | src | `String` | The path to a directory, archive file, globally installed npm package, archive URL, npm package name, or git repo. | | srcFile | `String` | When copying files, this is the source file path. | | template | `String` | Relative path to the directory containing the template files. Defaults to `'.'` | ### Events The `TemplateEngine` emits several events. It uses the [hook-emitter][hook-emitter] package which supports async event listeners. Some events are only emitted depending on the source type (e.g. the `src` passed into `run()`). ``` Event Flow ┌───────┐ │ run() │ └───┬───┘ ┌───────┐ ├─────┤ #init │ │ └───────┘ ┌──────────────┬───────────┼────────┬──────────┬──────────┐ git URL Local Local Global npm │ ┌─────┴─────┐ File Directory npm Package │ │ │ #download │ │ │ │ │ │ └─────┬─────┘ │ │ │ │ ┌─────┴──────┐ └─────┬─────┘ │ │ ┌───────┴───────┐ │ #git-clone │ ┌─────────┴─────────┐ │ │ │ #npm-download │ └─────┬──────┘ │ #extract │ │ │ └───────┬───────┘ │ │ #extract-file │ │ │ │ │ │ #extract-progress │ │ │ │ │ └─────────┬─────────┘ │ │ │ └────────────────────┴───────┬──────┴──────────┴──────────┘ ┌─────┴──────┐ │ #load-meta │ └─────┬──────┘ ┌─────────┐ ├────────┤ #prompt │ ┌────┴────┐ └─────────┘ │ #create │ └────┬────┘ ┌───────┐ ├────────┤ #copy │ │ └───┬───┘ ┌────────────┐ │ └────────┤ #copy-file │ │ ┌──────────────┐ └────────────┘ ├────┤ #npm-install │ │ └──────────────┘ │ ┌───────────┐ ├────┤ #git-init │ │ └───────────┘ ┌────┴─────┐ │ #cleanup │ └──────────┘ ``` <a name="TemplateEngine+event+init"></a> #### `#init` Initialize the run state with the options passed into `run()`. **Source Type:** Local file, local directory, global npm package, npm, git, URL | Param | Type | Description | | ------------------ | ---------- | -------------------------------- | | opts | `Object` | The options passed into `run()`. | | [async next(opts)] | `Function` | Continue to next hook. | ```javascript engine.on('init', async opts => { // before the run state has been initialized }); ``` or ```javascript engine.on('init', async (opts, next) => { // before the run state has been initialized await next(); // after initialization }); ``` <a name="TemplateEngine+event+git-clone"></a> #### `#git-clone` Emitted when `git clone` is called. **Source Type:** git | Param | Type | Description | | ------------------ | ---------------- | -------------------------------------------- | | state | `Object` | The run state. | | args | `Array.<String>` | The arguments passed into the `git` command. | | opts | `Object` | `spawn()` options. | | [async next(opts)] | `Function` | Continue to next hook. | ```javascript engine.on('git-clone', async (state, args, opts, next) => { // before the git clone call await next(); // after the clone }); ``` <a name="TemplateEngine+event+download"></a> #### `#download` Emitted when downloading a file based on a http/https URL. **Source Type:** URL | Param | Type | Description | | ------------------ | ---------- | ---------------------- | | state | `Object` | The run state. | | [async next(opts)] | `Function` | Continue to next hook. | ```javascript engine.on('download', async (state, next) => { // before the download begins await next(); // after the clone }); ``` <a name="TemplateEngine+event+extract"></a> #### `#extract` Emitted when extracting the downloaded or local archive file. **Source Type:** Local directory, URL | Param | Type | Description | | ------------------ | ---------- | ---------------------- | | state | `Object` | The run state. | | [async next(opts)] | `Function` | Continue to next hook. | ```javascript engine.on('extract', async (state, next) => { // before the archive is extracted await next(); // after extraction }); ``` <a name="TemplateEngine+event+extract-file"></a> #### `#extract-file` Emits the current file being extracted from the archive. **Source Type:** Local directory, URL | Param | Type | Description | | ------------------ | ---------- | ------------------------------------- | | state | `Object` | The run state. | | file | `String` | The name of the file being extracted. | ```javascript engine.on('extract-file', async (state, file) => { console.log(`Extracting ${file}`); }); ``` <a name="TemplateEngine+event+extract-progress"></a> #### `#extract-progress` Emits the current progress of the file extraction from `0` to `100`. **Source Type:** Local directory, URL | Param | Type | Description | | ------------------ | ---------- | ------------------------ | | state | `Object` | The run state. | | percent | `Number` | The percentage complete. | ```javascript engine.on('extract-progress', async (state, percent) => { console.log(`Extracted ${percent}%`); }); ``` <a name="TemplateEngine+event+npm-download"></a> #### `#npm-download` Emitted when downloading and extracting an npm package. **Source Type:** npm | Param | Type | Description | | ------------------ | ---------- | ---------------------- | | state | `Object` | The run state. | | [async next(opts)] | `Function` | Continue to next hook. | ```javascript engine.on('npm-download', async (state, next) => { // before downloading and extracting the npm package await next(); // after extraction }); ``` <a name="TemplateEngine+event+create"></a> #### `#create` Emitted when about to populate the destination directory. **Source Type:** All sources. | Param | Type | Description | | ------------------ | ---------- | ---------------------- | | state | `Object` | The run state. | | [async next(opts)] | `Function` | Continue to next hook. | ```javascript engine.on('create', async (state, next) => { // before the project is generated await next(); // after project is generated }); ``` <a name="TemplateEngine+event+load-meta"></a> #### `#load-meta` Emitted when attempting to load the template's `meta.js` or "main" file. **Source Type:** Any source with a meta script. | Param | Type | Description | | ------------------ | ---------------- | ------------------------ | | state | `Object` | The run state. | | [async next(opts)] | `Function` | Continue to next hook. | ```javascript engine.on('load-meta', async (state, next) => { // before npm dependencies have been installed await next(); // after installation }); ``` <a name="TemplateEngine+event+prompt"></a> #### `#prompt` Allows application opportunity to prompt for missing data, then populate state's `data` property. **Source Type:** Any source with a meta script. | Param | Type | Description | | ------------------ | ---------- | -------------------------------------- | | state | `Object` | The run state. | ```javascript engine.on('prompt', async state => { // prompt for `state.prompts` and store results in `state.data` }); ``` <a name="TemplateEngine+event+copy"></a> #### `#copy` Emitted when copying the template files to the destination. **Source Type:** All sources. | Param | Type | Description | | ------------------ | ---------- | ------------------------------------ | | state | `Object` | The run state. | | [async next(opts)] | `Function` | Continue to next hook. | ```javascript engine.on('copy', async (state, next) => { // before copying has begun await next(); // after files have been copied }); ``` <a name="TemplateEngine+event+copy-file"></a> #### `#copy-file` Emitted for each file copied. **Source Type:** All sources. | Param | Type | Description | | ------------------ | ---------- | ----------------------------------- | | state | `Object` | The run state. | | [async next(opts)] | `Function` | Continue to next hook. | ```javascript engine.on('copy-file', async (state, next) => { // before a specific file is to be copied await next(); // file has been copied }); ``` <a name="TemplateEngine+event+npm-install"></a> #### `#npm-install` Emitted when installing npm dependencies in the destination directory. **Source Type:** Any source with a `package.json`. | Param | Type | Description | | ------------------ | ---------------- | ------------------------ | | state | `Object` | The run state. | | cmd | `String` | The path to npm command. | | args | `Array.<String>` | The npm arguments. | | opts | `Object` | `spawn()` options. | | [async next(opts)] | `Function` | Continue to next hook. | ```javascript engine.on('npm-install', async (state, cmd, args, opts, next) => { // before npm dependencies have been installed await next(); // after installation }); ``` <a name="TemplateEngine+event+git-init"></a> #### `#git-init` Emitted when a git repository is being initialized in the project directory. **Source Type:** Any source. | Param | Type | Description | | ------------------ | ---------------- | ---------------------- | | state | `Object` | The run state. | | args | `Array.<String>` | `git` arguments. | | opts | `Object` | `spawn()` options. | | [async next(opts)] | `Function` | Continue to next hook. | ```javascript engine.on('git-init`', async (state, args, opts, next) => { // before the git repo has been initialized await next(); // after initialization }); ``` <a name="TemplateEngine+event+cleanup"></a> #### `#cleanup` Emitted after the project has been created and the temp directories are to be deleted. **Source Type:** Any source. | Param | Type | Description | | ------------------ | ---------- | ---------------------- | | state | `Object` | The run state. | | [async next(opts)] | `Function` | Continue to next hook. | ```javascript engine.on('cleanup`', async (state, next) => { // before temp directories have been deleted await next(); // after cleanup }); ``` ## Legal This project is open source under the [Apache Public License v2][1] and is developed by [Axway, Inc](http://www.axway.com/) and the community. Please read the [`LICENSE`][1] file included in this distribution for more information. [1]: https://github.com/appcelerator/template-kit/blob/master/LICENSE [npm-image]: https://img.shields.io/npm/v/template-kit.svg [npm-url]: https://npmjs.org/package/template-kit [downloads-image]: https://img.shields.io/npm/dm/template-kit.svg [downloads-url]: https://npmjs.org/package/template-kit [david-image]: https://img.shields.io/david/appcelerator/template-kit.svg [david-url]: https://david-dm.org/appcelerator/template-kit [david-dev-image]: https://img.shields.io/david/dev/appcelerator/template-kit.svg [david-dev-url]: https://david-dm.org/appcelerator/template-kit#info=devDependencies [ejs]: https://www.npmjs.com/package/ejs [hook-emitter]: https://www.npmjs.com/package/hook-emitter