Skip to content

Commit

Permalink
Merge pull request #179 from AthennaIO/develop
Browse files Browse the repository at this point in the history
feat(generator): add way to add name to file generator
  • Loading branch information
jlenon7 authored Jan 15, 2024
2 parents 01dd481 + 8796893 commit 482b57e
Show file tree
Hide file tree
Showing 5 changed files with 157 additions and 51 deletions.
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@athenna/artisan",
"version": "4.28.0",
"version": "4.29.0",
"description": "The Athenna CLI application. Built on top of commander and inspired in @adonisjs/ace.",
"license": "MIT",
"author": "João Lenon <[email protected]>",
Expand Down
50 changes: 10 additions & 40 deletions src/commands/MakeCommandCommand.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,8 @@
* file that was distributed with this source code.
*/

import { Path } from '@athenna/common'
import { BaseCommand, Argument } from '#src'
import { Path, String } from '@athenna/common'
import { sep, resolve, isAbsolute } from 'node:path'

export class MakeCommandCommand extends BaseCommand {
@Argument({
Expand All @@ -28,8 +27,14 @@ export class MakeCommandCommand extends BaseCommand {
public async handle(): Promise<void> {
this.logger.simple('({bold,green} [ MAKING COMMAND ])\n')

const destination = Config.get(
'rc.commands.make:command.destination',
Path.commands()
)

const file = await this.generator
.path(this.getFilePath())
.fileName(this.name)
.destination(destination)
.template('command')
.setNameProperties(true)
.make()
Expand All @@ -38,48 +43,13 @@ export class MakeCommandCommand extends BaseCommand {
`Command ({yellow} "${file.name}") successfully created.`
)

const signature = String.toCamelCase(file.name)
const importPath = this.getImportPath(file.name)
const signature = this.generator.getSignature()
const importPath = this.generator.getImportPath()

await this.rc.setTo('commands', signature, importPath).save()

this.logger.success(
`Athenna RC updated: ({dim,yellow} { commands += "${signature}": "${importPath}" })`
)
}

/**
* Get the file path where it will be generated.
*/
private getFilePath(): string {
return this.getDestinationPath().concat(`${sep}${this.name}.${Path.ext()}`)
}

/**
* Get the destination path for the file that will be generated.
*/
private getDestinationPath(): string {
let destination = Config.get(
'rc.commands.make:command.destination',
Path.commands()
)

if (!isAbsolute(destination)) {
destination = resolve(Path.pwd(), destination)
}

return destination
}

/**
* Get the import path that should be registered in RC file.
*/
private getImportPath(fileName: string): string {
const destination = this.getDestinationPath()

return `${destination
.replace(Path.pwd(), '')
.replace(/\\/g, '/')
.replace('/', '#')}/${fileName}`
}
}
130 changes: 122 additions & 8 deletions src/helpers/command/Generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,14 @@

import { View } from '@athenna/view'
import { File, String } from '@athenna/common'
import { resolve, isAbsolute } from 'node:path'
import { sep, resolve, isAbsolute } from 'node:path'
import { AlreadyExistFileException } from '#src/exceptions/AlreadyExistFileException'

export class Generator {
private _path: string
private _fileName: string
private _dest: string
private _ext = Path.ext()
private _template: string
private _properties: any
private _setNameProperties = true
Expand All @@ -22,6 +25,9 @@ export class Generator {
* Set the file path where the file will be generated.
* Remember that the file name in the path will be used
* to define the name properties.
*
* If defining a path, `fileName()`, `destination()` and
* `extension()` will be ignored.
*/
public path(path: string): Generator {
this._path = path
Expand Down Expand Up @@ -77,6 +83,98 @@ export class Generator {
return this
}

/**
* Set the name of the file that will be generated
* and use as reference to define the name properties.
*/
public fileName(name: string) {
this._fileName = name

return this
}

/**
* Set the destination where the file should be generated.
*
* @example
* ```ts
* this.generator
* .name('UserController')
* .destination(Path.controllers())
* ```
*/
public destination(dest: string) {
if (!isAbsolute(dest)) {
dest = resolve(Path.pwd(), dest)
}

this._dest = dest

return this
}

/**
* Set the file extension.
*
* @example
* ```ts
* this.generator
* .name('UserController')
* .extension('ts')
* .destination(Path.controllers())
* ```
*/
public extension(ext: string) {
this._ext = ext

return this
}

/**
* Get the signature that will be used as key
* to be defined in `.athennarc.json` file.
*
* Only works when defining `fileName()`.
*
* @example
* ```ts
* this.generator.fileName('user.controller')
*
* const name = this.generator.getSignature()
*
* // userController
* ```
*/
public getSignature(): string {
return String.toCamelCase(this._fileName)
}

/**
* Create a sub path import path for the file
* from the destination defined and the
* file name.
*
* Only works when defining `destination()` and
* `name()`.
*
* @example
* ```ts
* this.generator
* .fileName('UserController')
* .destination(Path.controllers())
*
* const importPath = this.generator.getImportPath()
*
* /// #app/http/controllers/UserController
* ```
*/
public getImportPath(): string {
return `${this._dest
.replace(Path.pwd(), '')
.replace(/\\/g, '/')
.replace('/', '#')}/${this._fileName}`
}

/**
* Make a new file using templates.
*
Expand All @@ -97,20 +195,32 @@ export class Generator {
* ```
*/
public async make(): Promise<File> {
if (!this._path) {
this._path = this._dest.concat(`${sep}${this._fileName}.${this._ext}`)
}

const file = new File(this._path, '')

if (file.fileExists) {
throw new AlreadyExistFileException(this._path)
}

if (!this._fileName) {
this._fileName = file.name
}

if (this._setNameProperties) {
const timestamp = Date.now()
const nameUp = file.name.toUpperCase()
const nameCamel = String.toCamelCase(file.name)
const namePlural = String.pluralize(file.name)
const namePascal = String.toPascalCase(file.name)
const namePluralCamel = String.toCamelCase(String.pluralize(file.name))
const namePluralPascal = String.toPascalCase(String.pluralize(file.name))
const nameUp = this._fileName.toUpperCase()
const nameCamel = String.toCamelCase(this._fileName)
const namePlural = String.pluralize(this._fileName)
const namePascal = String.toPascalCase(this._fileName)
const namePluralCamel = String.toCamelCase(
String.pluralize(this._fileName)
)
const namePluralPascal = String.toPascalCase(
String.pluralize(this._fileName)
)

this.properties({
nameUp,
Expand All @@ -135,7 +245,11 @@ export class Generator {
return file.setContent(content)
}

let templatePath = Config.get(`rc.templates.${this._template}`)
const templates = Config.get('rc.templates')

// Avoid problems when user define template
// key with dot notation.
let templatePath = templates[this._template]

if (!isAbsolute(templatePath)) {
templatePath = resolve(templatePath)
Expand Down
22 changes: 22 additions & 0 deletions tests/unit/helpers/command/GeneratorTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,4 +89,26 @@ export default class GeneratorTest {
assert.isTrue(await File.exists(path))
assert.isTrue(new File(path).getContentAsStringSync().includes('GeneratorTestCommandd'))
}

@Test()
public async shouldBeAbleToGenerateFilesFromTemplatesSettingFileNameDestinationAndExt({ assert }: Context) {
const path = Path.fixtures('tmp/GeneratorTestCommand.ts')

View.createTemplate('command', await new File('../../../../templates/command.edge').getContentAsString())

assert.isTrue(View.hasTemplate('command'))

await this.generator
.path(path)
.fileName('GeneratorTestCommand')
.extension('ts')
.destination(Path.fixtures('tmp'))
.properties({ namePascal: 'GeneratorTestCommandd' })
.setNameProperties(true)
.template('command')
.make()

assert.isTrue(await File.exists(path))
assert.isTrue(new File(path).getContentAsStringSync().includes('GeneratorTestCommandd'))
}
}

0 comments on commit 482b57e

Please sign in to comment.