126 lines
3.3 KiB
JavaScript
126 lines
3.3 KiB
JavaScript
|
|
const path = require('path')
|
||
|
|
|
||
|
|
module.exports = function (plop) {
|
||
|
|
// -------------------------
|
||
|
|
// Case helpers
|
||
|
|
// -------------------------
|
||
|
|
const toKebab = str =>
|
||
|
|
str
|
||
|
|
.replace(/([a-z])([A-Z])/g, '$1-$2')
|
||
|
|
.replace(/\s+/g, '-')
|
||
|
|
.toLowerCase()
|
||
|
|
|
||
|
|
const toPascal = str =>
|
||
|
|
str
|
||
|
|
.split(/[-_\s]+/)
|
||
|
|
.map(part => part.charAt(0).toUpperCase() + part.slice(1))
|
||
|
|
.join('')
|
||
|
|
|
||
|
|
const toCamel = str => {
|
||
|
|
const pascal = toPascal(str)
|
||
|
|
return pascal.charAt(0).toLowerCase() + pascal.slice(1)
|
||
|
|
}
|
||
|
|
|
||
|
|
plop.setHelper('kebabCase', toKebab)
|
||
|
|
plop.setHelper('pascalCase', toPascal)
|
||
|
|
plop.setHelper('camelCase', toCamel)
|
||
|
|
|
||
|
|
// -------------------------
|
||
|
|
// Dynamic relative import helper
|
||
|
|
// -------------------------
|
||
|
|
plop.setHelper('prismaImportPath', (modulePath, name) => {
|
||
|
|
return '@/prisma/prisma.service'
|
||
|
|
})
|
||
|
|
|
||
|
|
// -------------------------
|
||
|
|
// Generator
|
||
|
|
// -------------------------
|
||
|
|
plop.setGenerator('resource', {
|
||
|
|
description: 'Generate Nested NestJS Prisma Resource',
|
||
|
|
prompts: [
|
||
|
|
{
|
||
|
|
type: 'input',
|
||
|
|
name: 'name',
|
||
|
|
message: 'Module name (e.g. user, blog-post):',
|
||
|
|
},
|
||
|
|
{
|
||
|
|
type: 'input',
|
||
|
|
name: 'modulePath',
|
||
|
|
message: 'Nested path inside modules (e.g. admin/users) — leave empty for root:',
|
||
|
|
default: '',
|
||
|
|
},
|
||
|
|
{
|
||
|
|
type: 'input',
|
||
|
|
name: 'fields',
|
||
|
|
message:
|
||
|
|
'DTO fields (comma-separated, e.g. name:string,email:email,age:number,isActive:boolean):',
|
||
|
|
},
|
||
|
|
],
|
||
|
|
actions(data) {
|
||
|
|
// sanitize path
|
||
|
|
data.modulePath = data.modulePath.replace(/^\/+|\/+$/g, '')
|
||
|
|
|
||
|
|
// Parse fields
|
||
|
|
const rawFields = data.fields || ''
|
||
|
|
data.parsedFields = rawFields
|
||
|
|
.split(',')
|
||
|
|
.filter(Boolean)
|
||
|
|
.map(field => {
|
||
|
|
const [name, type] = field.split(':').map(v => v.trim())
|
||
|
|
|
||
|
|
let validator = 'IsString'
|
||
|
|
let finalType = 'string'
|
||
|
|
|
||
|
|
if (type === 'number') {
|
||
|
|
validator = 'IsNumber'
|
||
|
|
finalType = 'number'
|
||
|
|
}
|
||
|
|
|
||
|
|
if (type === 'boolean') {
|
||
|
|
validator = 'IsBoolean'
|
||
|
|
finalType = 'boolean'
|
||
|
|
}
|
||
|
|
|
||
|
|
if (type === 'email') {
|
||
|
|
validator = 'IsEmail'
|
||
|
|
finalType = 'string'
|
||
|
|
}
|
||
|
|
|
||
|
|
return { name, validator, type: finalType }
|
||
|
|
})
|
||
|
|
|
||
|
|
const basePath = data.modulePath
|
||
|
|
? `src/modules/${data.modulePath}/{{kebabCase name}}`
|
||
|
|
: `src/modules/{{kebabCase name}}`
|
||
|
|
|
||
|
|
return [
|
||
|
|
{
|
||
|
|
type: 'add',
|
||
|
|
path: `${basePath}/{{kebabCase name}}.module.ts`,
|
||
|
|
templateFile: 'plop-templates/module.hbs',
|
||
|
|
},
|
||
|
|
{
|
||
|
|
type: 'add',
|
||
|
|
path: `${basePath}/{{kebabCase name}}.service.ts`,
|
||
|
|
templateFile: 'plop-templates/service.hbs',
|
||
|
|
},
|
||
|
|
{
|
||
|
|
type: 'add',
|
||
|
|
path: `${basePath}/{{kebabCase name}}.controller.ts`,
|
||
|
|
templateFile: 'plop-templates/controller.hbs',
|
||
|
|
},
|
||
|
|
{
|
||
|
|
type: 'add',
|
||
|
|
path: `${basePath}/dto/create-{{kebabCase name}}.dto.ts`,
|
||
|
|
templateFile: 'plop-templates/create-dto.hbs',
|
||
|
|
},
|
||
|
|
{
|
||
|
|
type: 'add',
|
||
|
|
path: `${basePath}/dto/update-{{kebabCase name}}.dto.ts`,
|
||
|
|
templateFile: 'plop-templates/update-dto.hbs',
|
||
|
|
},
|
||
|
|
]
|
||
|
|
},
|
||
|
|
})
|
||
|
|
}
|