parent
fb85e42dee
commit
cae260b9ce
@ -0,0 +1,9 @@
|
||||
import {UniversalPath} from '@extollo/util'
|
||||
|
||||
export interface Template {
|
||||
name: string,
|
||||
fileSuffix: string,
|
||||
description: string,
|
||||
baseAppPath: string[],
|
||||
render: (name: string, fullCanonicalName: string, targetFilePath: UniversalPath) => string | Promise<string>
|
||||
}
|
@ -0,0 +1,87 @@
|
||||
import {Directive, OptionDefinition} from "../Directive"
|
||||
import {Injectable, Inject} from "@extollo/di"
|
||||
import {ErrorWithContext} from "@extollo/util"
|
||||
import {PositionalOption} from "./options/PositionalOption"
|
||||
import {CommandLine} from "../service"
|
||||
|
||||
@Injectable()
|
||||
export class TemplateDirective extends Directive {
|
||||
@Inject()
|
||||
protected readonly cli!: CommandLine
|
||||
|
||||
getKeywords(): string | string[] {
|
||||
return ['new', 'make']
|
||||
}
|
||||
|
||||
getDescription(): string {
|
||||
return 'create a new file from a registered template'
|
||||
}
|
||||
|
||||
getOptions(): OptionDefinition[] {
|
||||
const registeredTemplates = this.cli.getTemplates()
|
||||
const template = new PositionalOption('template_name', 'the template to base the new file on (e.g. model, controller)')
|
||||
template.whitelist(...registeredTemplates.pluck('name'))
|
||||
|
||||
const destination = new PositionalOption('file_name', 'canonical name of the file to create (e.g. auth:Group, dash:Activity)')
|
||||
|
||||
return [template, destination]
|
||||
}
|
||||
|
||||
getHelpText(): string {
|
||||
const registeredTemplates = this.cli.getTemplates()
|
||||
|
||||
return [
|
||||
'Modules in Extollo register templates that can be used to quickly create common file types.',
|
||||
'',
|
||||
'For example, you can create a new model from @extollo/orm using the "model" template:',
|
||||
'',
|
||||
'./ex new model auth:Group',
|
||||
'',
|
||||
'This would create a new Group model in the ./src/app/models/auth/Group.model.ts file.',
|
||||
'',
|
||||
'AVAILABLE TEMPLATES:',
|
||||
'',
|
||||
...(registeredTemplates.map(template => {
|
||||
return ` - ${template.name}: ${template.description}`
|
||||
}))
|
||||
].join('\n')
|
||||
}
|
||||
|
||||
async handle(argv: string[]) {
|
||||
const templateName: string = this.option('template_name')
|
||||
const destinationName: string = this.option('file_name')
|
||||
|
||||
if ( destinationName.includes('/') || destinationName.includes('\\') ) {
|
||||
this.error(`The destination should be a canonical name, not a file path.`)
|
||||
this.error(`Reference sub-directories using the : character instead.`)
|
||||
this.error(`Did you mean ${destinationName.replace(/\/|\\/g, ':')}?`)
|
||||
process.exitCode = 1
|
||||
return
|
||||
}
|
||||
|
||||
const template = this.cli.getTemplate(templateName)
|
||||
if ( !template ) {
|
||||
throw new ErrorWithContext(`Unable to find template supposedly registered with name: ${templateName}`, {
|
||||
templateName,
|
||||
destinationName,
|
||||
})
|
||||
}
|
||||
|
||||
const name = destinationName.split(':').reverse()[0]
|
||||
const path = this.app().path('..', 'src', 'app', ...template.baseAppPath, ...(`${destinationName}${template.fileSuffix}`).split(':'))
|
||||
|
||||
if ( await path.exists() ) {
|
||||
this.error(`File already exists: ${path}`)
|
||||
process.exitCode = 1
|
||||
return
|
||||
}
|
||||
|
||||
// Make sure the parent direction exists
|
||||
await path.concat('..').mkdir()
|
||||
|
||||
const contents = await template.render(name, destinationName, path.clone())
|
||||
await path.write(contents)
|
||||
|
||||
this.success(`Created new ${template.name} in ${path}`)
|
||||
}
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
import {Template} from "../Template"
|
||||
import {UniversalPath} from "@extollo/util"
|
||||
|
||||
const directive_template: Template = {
|
||||
name: 'directive',
|
||||
fileSuffix: '.directive.ts',
|
||||
description: 'Create a new Directive class which adds functionality to the ./ex command.',
|
||||
baseAppPath: ['directives'],
|
||||
render(name: string, fullCanonicalName: string, targetFilePath: UniversalPath) {
|
||||
return `import {Directive, OptionDefinition} from "@extollo/cli"
|
||||
import {Injectable} from "@extollo/di"
|
||||
|
||||
/**
|
||||
* ${name} Directive
|
||||
* ---------------------------------------------------
|
||||
* Put some description here.
|
||||
*/
|
||||
@Injectable()
|
||||
export class ${name}Directive extends Directive {
|
||||
getKeywords(): string | string[] {
|
||||
return ['${name.toLowerCase()}']
|
||||
}
|
||||
|
||||
getDescription(): string {
|
||||
return ''
|
||||
}
|
||||
|
||||
getOptions(): OptionDefinition[] {
|
||||
return []
|
||||
}
|
||||
|
||||
async handle(argv: string[]) {
|
||||
|
||||
}
|
||||
}
|
||||
`
|
||||
}
|
||||
}
|
||||
|
||||
export { directive_template }
|
@ -0,0 +1,10 @@
|
||||
`{
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"target": "es5",
|
||||
"sourceMap": true
|
||||
},
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
]
|
||||
}
|
Loading…
Reference in new issue