Rails-inspired generator system that provides scaffolding for your apps
Template rendering, file copying, and destination management with support for EJS templating and conflict resolution through mem-fs-editor integration.
Methods for reading, copying, and rendering template files with EJS processing.
/**
* Read file from templates folder
* Shortcut for this.fs.read(this.templatePath(filepath))
*/
readTemplate(...args: Parameters<MemFsEditor['read']>): ReturnType<MemFsEditor['read']>;
/**
* Copy file from templates folder to destination folder
* Shortcut for this.fs.copy(this.templatePath(from), this.destinationPath(to))
*/
copyTemplate(...args: Parameters<MemFsEditor['copy']>): ReturnType<MemFsEditor['copy']>;
/**
* Async copy file from templates folder to destination folder
*/
async copyTemplateAsync(...args: Parameters<MemFsEditor['copyAsync']>): ReturnType<MemFsEditor['copyAsync']>;Usage Examples:
export default class MyGenerator extends Generator {
writing() {
// Read template content
const content = this.readTemplate('config.json');
// Copy template file
this.copyTemplate('static-file.js', 'src/static-file.js');
// Copy multiple files with options
this.copyTemplate(
'assets/**/*',
'public/',
{ globOptions: { dot: true } }
);
}
async install() {
// Async copy for large files
await this.copyTemplateAsync('large-asset.bin', 'assets/large-asset.bin');
}
}Render EJS templates with data substitution and processing.
/**
* Copy a template from templates folder to the destination with EJS processing
* @param source - Template file, absolute or relative to templatePath()
* @param destination - Destination, absolute or relative to destinationPath()
* @param templateData - EJS data for template processing
* @param templateOptions - EJS processing options
* @param copyOptions - mem-fs-editor copy options
*/
renderTemplate<D extends TemplateData = TemplateData>(
source: string | string[],
destination: string | string[],
templateData?: string | D,
templateOptions?: TemplateOptions,
copyOptions?: CopyOptions
): void;
/**
* Async version of renderTemplate
*/
async renderTemplateAsync<D extends TemplateData = TemplateData>(
source: string | string[],
destination: string | string[],
templateData?: string | D,
templateOptions?: TemplateOptions,
copyOptions?: CopyOptions
): Promise<void>;Usage Examples:
export default class MyGenerator extends Generator {
async prompting() {
this.answers = await this.prompt([
{ name: 'name', message: 'Project name?' },
{ name: 'author', message: 'Author name?' }
]);
}
writing() {
// Render template with data
this.renderTemplate(
'package.json.ejs',
'package.json',
{
name: this.answers.name,
author: this.answers.author,
version: '1.0.0'
}
);
// Render with custom EJS options
this.renderTemplate(
'config.js.ejs',
'config/config.js',
this.answers,
{
delimiter: '?', // Use <?= %> instead of <%= %>
openDelimiter: '[',
closeDelimiter: ']'
}
);
}
}Render multiple templates with conditional logic.
/**
* Copy multiple templates from templates folder to the destination
* @param templates - Array of template configurations
* @param templateData - Default EJS data for all templates
*/
renderTemplates<D extends TemplateData = TemplateData>(
templates: Templates<D, typeof this>,
templateData?: string | D
): void;
/**
* Async version of renderTemplates
*/
async renderTemplatesAsync<D extends TemplateData = TemplateData>(
templates: Templates<D, typeof this>,
templateData?: string | D
): Promise<void>;
// Template configuration type
interface Template<D extends TemplateData, G> {
source: string;
destination?: string;
when?: (data: D, generator: G) => boolean;
copyOptions?: CopyOptions;
templateData?: TemplateData;
templateOptions?: TemplateOptions;
}
type Templates<D extends TemplateData, G> = Array<Template<D, G>>;Usage Examples:
export default class MyGenerator extends Generator {
writing() {
const templates = [
{
source: 'src/index.js.ejs',
destination: 'src/index.js'
},
{
source: 'test/test.js.ejs',
destination: 'test/index.test.js',
when: (data) => data.includeTests
},
{
source: 'docker/Dockerfile.ejs',
destination: 'Dockerfile',
when: (data) => data.useDocker,
templateData: { baseImage: 'node:18' }
}
];
this.renderTemplates(templates, this.answers);
}
}Methods for reading, writing, and manipulating files in the destination directory.
/**
* Read file from destination folder
* Shortcut for this.fs.read(this.destinationPath(filepath))
*/
readDestination(...args: Parameters<MemFsEditor['read']>): ReturnType<MemFsEditor['read']>;
/**
* Read JSON file from destination folder
* Shortcut for this.fs.readJSON(this.destinationPath(filepath))
*/
readDestinationJSON(...args: Parameters<MemFsEditor['readJSON']>): ReturnType<MemFsEditor['readJSON']>;
/**
* Write file to destination folder
* Shortcut for this.fs.write(this.destinationPath(filepath))
*/
writeDestination(...args: Parameters<MemFsEditor['write']>): ReturnType<MemFsEditor['write']>;
/**
* Write JSON file to destination folder
* Shortcut for this.fs.writeJSON(this.destinationPath(filepath))
*/
writeDestinationJSON(...args: Parameters<MemFsEditor['writeJSON']>): ReturnType<MemFsEditor['writeJSON']>;
/**
* Delete file from destination folder
* Shortcut for this.fs.delete(this.destinationPath(filepath))
*/
deleteDestination(...args: Parameters<MemFsEditor['delete']>): ReturnType<MemFsEditor['delete']>;
/**
* Check if file exists in destination folder
* Shortcut for this.fs.exists(this.destinationPath(filepath))
*/
existsDestination(...args: Parameters<MemFsEditor['exists']>): ReturnType<MemFsEditor['exists']>;
/**
* Copy file within destination folder
* Shortcut for this.fs.copy(this.destinationPath(from), this.destinationPath(to))
*/
copyDestination(...args: Parameters<MemFsEditor['copy']>): ReturnType<MemFsEditor['copy']>;
/**
* Move file within destination folder
* Shortcut for this.fs.move(this.destinationPath(from), this.destinationPath(to))
*/
moveDestination(...args: Parameters<MemFsEditor['move']>): ReturnType<MemFsEditor['move']>;Usage Examples:
export default class MyGenerator extends Generator {
writing() {
// Check if file exists before overwriting
if (!this.existsDestination('src/config.js')) {
this.writeDestination('src/config.js', 'module.exports = {};');
}
// Read existing package.json and modify
const pkg = this.readDestinationJSON('package.json', {});
pkg.scripts = pkg.scripts || {};
pkg.scripts.start = 'node src/index.js';
this.writeDestinationJSON('package.json', pkg);
// Backup existing file
if (this.existsDestination('config.json')) {
this.copyDestination('config.json', 'config.json.bak');
}
}
end() {
// Clean up temporary files
this.deleteDestination('temp-config.json');
}
}Utility methods for preparing template data from configuration.
/**
* Utility method to get formatted data for templates
* @param path - Path to the storage key, or undefined for all config
* @returns Data to be passed to the templates
*/
_templateData<D extends TemplateData = TemplateData>(path?: string): D;Usage Example:
export default class MyGenerator extends Generator {
writing() {
// Get all configuration as template data
const allData = this._templateData();
// Get specific configuration path
const userPrefs = this._templateData('user.preferences');
this.renderTemplate('app.js.ejs', 'src/app.js', allData);
}
}// Template data (EJS data)
type TemplateData = Record<string, any>;
// Template options (EJS options)
interface TemplateOptions {
context?: any;
delimiter?: string;
openDelimiter?: string;
closeDelimiter?: string;
debug?: boolean;
compileDebug?: boolean;
client?: boolean;
escape?: (markup: string) => string;
filename?: string;
root?: string | string[];
views?: string[];
cache?: boolean;
outputFunctionName?: string;
localsName?: string;
rmWhitespace?: boolean;
async?: boolean;
}
// Copy options from mem-fs-editor
interface CopyOptions {
fromBasePath?: string;
ignoreNoMatch?: boolean;
globOptions?: any;
processDestinationPath?: (dest: string) => string;
}
// Template configuration for batch rendering
interface Template<D extends TemplateData, G> {
source: string;
destination?: string;
when?: (data: D, generator: G) => boolean;
copyOptions?: CopyOptions;
templateData?: TemplateData;
templateOptions?: TemplateOptions;
}
type Templates<D extends TemplateData, G> = Array<Template<D, G>>;Install with Tessl CLI
npx tessl i tessl/npm-yeoman-generator