refactor utility methods to naming.utils.ts
This commit is contained in:
parent
ed2388d7f6
commit
61338cc377
@ -8,6 +8,7 @@ import * as fs from 'fs';
|
||||
import { promises as fsPromises } from 'fs';
|
||||
import { TableColumn } from 'typeorm';
|
||||
import { GenericTableGeneratorService } from './generic-table-generator.service';
|
||||
import { mapDbToTsType, toCamelCase, toKebabCase, toPascalCase, toSingular } from '../utils/naming.utils';
|
||||
|
||||
// Interface for structured field metadata passed to templates
|
||||
interface FieldDefinition {
|
||||
@ -42,7 +43,7 @@ export class AngularGeneratorService {
|
||||
const fields: FieldDefinition[] = (columns || [])
|
||||
.map(c => ({
|
||||
name: c.name,
|
||||
tsType: this.mapDbToTsType(c.type),
|
||||
tsType: mapDbToTsType(c.type),
|
||||
}));
|
||||
|
||||
names['modelProperties'] = fields.map(f => `${f.name}: ${f.tsType};`).join('\n ');
|
||||
@ -126,15 +127,6 @@ private async generateTableComponent(tableName: string, columns: TableColumn[],
|
||||
return `<div class="form-control">${label}\n ${input}</div>`;
|
||||
}
|
||||
|
||||
private mapDbToTsType(dbType: string): string {
|
||||
if (dbType.includes('int') || dbType.includes('serial')) return 'number';
|
||||
if (['float', 'double', 'decimal', 'numeric', 'real'].includes(dbType)) return 'number';
|
||||
if (dbType.includes('char') || dbType.includes('text') || dbType === 'uuid') return 'string';
|
||||
if (dbType === 'boolean' || dbType === 'bool') return 'boolean';
|
||||
if (dbType.includes('date') || dbType.includes('time')) return 'Date';
|
||||
return 'any';
|
||||
}
|
||||
|
||||
// ... (All other generate... and naming methods are unchanged)
|
||||
private async generateModel(names: NamingConvention, featureDir: string) {
|
||||
const modelsDir = path.join(featureDir, 'models');
|
||||
@ -183,36 +175,16 @@ private async generateTableComponent(tableName: string, columns: TableColumn[],
|
||||
fs.writeFileSync(path.join(compDir, `${names.singular}-form.component.html`), htmlContent);
|
||||
}
|
||||
private getNamingConvention(tableName: string): NamingConvention {
|
||||
const singular = this.toSingular(tableName);
|
||||
const pascal = this.toPascalCase(singular);
|
||||
const singular = toSingular(tableName);
|
||||
const pascal = toPascalCase(singular);
|
||||
return {
|
||||
singular: this.toKebabCase(singular),
|
||||
plural: this.toKebabCase(tableName),
|
||||
singular: toKebabCase(singular),
|
||||
plural: toKebabCase(tableName),
|
||||
pascal: pascal,
|
||||
camel: this.toCamelCase(singular),
|
||||
camel: toCamelCase(singular),
|
||||
title: pascal,
|
||||
kebab: this.toKebabCase(singular),
|
||||
kebab: toKebabCase(singular),
|
||||
};
|
||||
}
|
||||
private toSingular(name: string): string {
|
||||
const kebab = this.toKebabCase(name);
|
||||
if (kebab.endsWith('ies')) return kebab.slice(0, -3) + 'y';
|
||||
return kebab.endsWith('s') ? kebab.slice(0, -1) : kebab;
|
||||
}
|
||||
private toPascalCase(text: string): string {
|
||||
return this.toKebabCase(text)
|
||||
.split('-')
|
||||
.map(word => word.charAt(0).toUpperCase() + word.slice(1))
|
||||
.join('');
|
||||
}
|
||||
private toCamelCase(text: string): string {
|
||||
const pascal = this.toPascalCase(text);
|
||||
return pascal.charAt(0).toLowerCase() + pascal.slice(1);
|
||||
}
|
||||
private toKebabCase(text: string): string {
|
||||
return text
|
||||
.replace(/_/g, '-') // Replace underscores with hyphens
|
||||
.replace(/([a-z0-9]|(?=[A-Z]))([A-Z])/g, '$1-$2') // Add hyphen before uppercase letters
|
||||
.toLowerCase();
|
||||
}
|
||||
|
||||
}
|
||||
@ -7,6 +7,7 @@ import { TableColumn } from 'typeorm';
|
||||
import * as path from 'path';
|
||||
import * as fs from 'fs';
|
||||
import { promises as fsPromises } from 'fs';
|
||||
import { toCamelCase, toKebabCase, toPascalCase, toSingular } from '../utils/naming.utils';
|
||||
|
||||
interface NamingConvention {
|
||||
[key: string]: string;
|
||||
@ -98,34 +99,21 @@ export class CrudGeneratorService {
|
||||
}
|
||||
|
||||
private getNamingConvention(tableName: string, columns?: TableColumn[]): NamingConvention {
|
||||
const singular = this.toSingular(tableName);
|
||||
const pascal = this.toPascalCase(singular);
|
||||
const singular = toSingular(tableName);
|
||||
const pascal = toPascalCase(singular);
|
||||
const searchableFields = (columns || [])
|
||||
.filter(c => this.isStringBasedType(c.type))
|
||||
.map(c => `'${c.name}'`)
|
||||
.join(',\n ');
|
||||
|
||||
return {
|
||||
singular: this.toKebabCase(singular),
|
||||
plural: this.toKebabCase(tableName),
|
||||
singular: toKebabCase(singular),
|
||||
plural: toKebabCase(tableName),
|
||||
pascal: pascal,
|
||||
camel: this.toCamelCase(singular),
|
||||
camel: toCamelCase(singular),
|
||||
kebab: toKebabCase(singular),
|
||||
searchableFields: searchableFields
|
||||
};
|
||||
}
|
||||
private toSingular(name: string): string {
|
||||
const kebab = this.toKebabCase(name);
|
||||
if (kebab.endsWith('ies')) return kebab.slice(0, -3) + 'y';
|
||||
return kebab.endsWith('s') ? kebab.slice(0, -1) : kebab;
|
||||
}
|
||||
private toPascalCase(text: string): string {
|
||||
return this.toKebabCase(text).split('-').map(word => word.charAt(0).toUpperCase() + word.slice(1)).join('');
|
||||
}
|
||||
private toCamelCase(text: string): string {
|
||||
const pascal = this.toPascalCase(text);
|
||||
return pascal.charAt(0).toLowerCase() + pascal.slice(1);
|
||||
}
|
||||
private toKebabCase(text: string): string {
|
||||
return text.replace(/_/g, '-').replace(/([a-z0-9]|(?=[A-Z]))([A-Z])/g, '$1-$2').toLowerCase();
|
||||
}
|
||||
|
||||
}
|
||||
@ -7,6 +7,7 @@ import { TemplateService } from './template.service'; // <-- 1. IMPORT TemplateS
|
||||
import * as path from 'path';
|
||||
import * as fs from 'fs';
|
||||
import { promises as fsPromises } from 'fs';
|
||||
import { mapDbToTsType, toPascalCase, toSingular } from '../utils/naming.utils';
|
||||
|
||||
@Injectable()
|
||||
export class EntityGeneratorService {
|
||||
@ -38,14 +39,14 @@ export class EntityGeneratorService {
|
||||
const columns = table.columns;
|
||||
console.log(`Found ${columns.length} columns in table "${tableName}".`);
|
||||
|
||||
const singularName = this.toSingular(tableName);
|
||||
const className = this.toPascalCase(singularName);
|
||||
const singularName = toSingular(tableName);
|
||||
const className = toPascalCase(singularName);
|
||||
|
||||
const props = columns
|
||||
.map((col) => {
|
||||
const typeormDecorator = this.getDecorator(col);
|
||||
const validationDecorators = this.getValidationDecorators(col);
|
||||
const tsType = this.mapDbToTsType(col.type);
|
||||
const tsType = mapDbToTsType(col.type);
|
||||
const nullable = col.isNullable ? ' | null' : '';
|
||||
const defaultValue = col.default ? ` = ${this.formatDefaultValue(col)}` : '';
|
||||
const allDecorators = [typeormDecorator, validationDecorators].filter(Boolean).join('\n ');
|
||||
@ -96,7 +97,7 @@ export class EntityGeneratorService {
|
||||
decorators.push('@IsOptional()');
|
||||
}
|
||||
|
||||
const tsType = this.mapDbToTsType(column.type);
|
||||
const tsType = mapDbToTsType(column.type);
|
||||
switch (tsType) {
|
||||
case 'string':
|
||||
decorators.push('@IsString()');
|
||||
@ -160,38 +161,4 @@ export class EntityGeneratorService {
|
||||
return column.default;
|
||||
}
|
||||
|
||||
private mapDbToTsType(dbType: string): string {
|
||||
if (dbType.includes('int') || dbType.includes('serial')) return 'number';
|
||||
if (['float', 'double', 'decimal', 'numeric', 'real'].includes(dbType)) return 'number';
|
||||
if (dbType.includes('char') || dbType.includes('text') || dbType === 'uuid') return 'string';
|
||||
if (dbType === 'boolean' || dbType === 'bool') return 'boolean';
|
||||
if (dbType.includes('date') || dbType.includes('time')) return 'Date';
|
||||
return 'any';
|
||||
}
|
||||
|
||||
private toSingular(name: string): string {
|
||||
if (name.endsWith('ies')) {
|
||||
return name.slice(0, -3) + 'y';
|
||||
}
|
||||
return name.endsWith('s') ? name.slice(0, -1) : name;
|
||||
}
|
||||
|
||||
private toPascalCase(text: string): string {
|
||||
return this.toKebabCase(text)
|
||||
.split('-')
|
||||
.map(word => word.charAt(0).toUpperCase() + word.slice(1))
|
||||
.join('');
|
||||
}
|
||||
|
||||
private toCamelCase(text: string): string {
|
||||
const pascal = this.toPascalCase(text);
|
||||
return pascal.charAt(0).toLowerCase() + pascal.slice(1);
|
||||
}
|
||||
|
||||
private toKebabCase(text: string): string {
|
||||
return text
|
||||
.replace(/_/g, '-') // Replace underscores with hyphens
|
||||
.replace(/([a-z0-9]|(?=[A-Z]))([A-Z])/g, '$1-$2') // Add hyphen before uppercase letters
|
||||
.toLowerCase();
|
||||
}
|
||||
}
|
||||
@ -5,6 +5,7 @@ import { TableColumn } from 'typeorm';
|
||||
import * as path from 'path';
|
||||
import * as fs from 'fs';
|
||||
import { promises as fsPromises } from 'fs';
|
||||
import { mapDbToTsType } from '../utils/naming.utils';
|
||||
|
||||
interface FieldDefinition { name: string; tsType: string; }
|
||||
interface NamingConvention { [key: string]: string; /*...*/ }
|
||||
@ -23,7 +24,7 @@ export class GenericTableGeneratorService {
|
||||
|
||||
const fields: FieldDefinition[] = columns.map(c => ({
|
||||
name: c.name,
|
||||
tsType: this.mapDbToTsType(c.type),
|
||||
tsType: mapDbToTsType(c.type),
|
||||
}));
|
||||
|
||||
names['columnDefinitions'] = this.buildColumnDefinitions(fields);
|
||||
@ -75,12 +76,5 @@ export class GenericTableGeneratorService {
|
||||
.join('\n');
|
||||
}
|
||||
|
||||
private mapDbToTsType(dbType: string): string {
|
||||
if (dbType.includes('int') || dbType.includes('serial')) return 'number';
|
||||
if (['float', 'double', 'decimal', 'numeric', 'real'].includes(dbType)) return 'number';
|
||||
if (dbType.includes('char') || dbType.includes('text') || dbType === 'uuid') return 'string';
|
||||
if (dbType === 'boolean' || dbType === 'bool') return 'boolean';
|
||||
if (dbType.includes('date') || dbType.includes('time')) return 'Date';
|
||||
return 'any';
|
||||
}
|
||||
|
||||
}
|
||||
51
src/utils/naming.utils.ts
Normal file
51
src/utils/naming.utils.ts
Normal file
@ -0,0 +1,51 @@
|
||||
// dvbooking-cli/src/utils/naming.utils.ts
|
||||
|
||||
/**
|
||||
* Converts any string to kebab-case.
|
||||
* e.g., 'user_roles' -> 'user-roles', 'UserRoles' -> 'user-roles'
|
||||
*/
|
||||
export function toKebabCase(text: string): string {
|
||||
return text
|
||||
.replace(/_/g, '-') // Replace underscores with hyphens
|
||||
.replace(/([a-z0-9]|(?=[A-Z]))([A-Z])/g, '$1-$2') // Add hyphen before uppercase letters
|
||||
.toLowerCase();
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a kebab-cased string to its singular form.
|
||||
*/
|
||||
export function toSingular(name: string): string {
|
||||
const kebab = toKebabCase(name);
|
||||
if (kebab.endsWith('ies')) return kebab.slice(0, -3) + 'y';
|
||||
return kebab.endsWith('s') ? kebab.slice(0, -1) : kebab;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a kebab-cased string to PascalCase.
|
||||
*/
|
||||
export function toPascalCase(text: string): string {
|
||||
return toKebabCase(text)
|
||||
.split('-')
|
||||
.map(word => word.charAt(0).toUpperCase() + word.slice(1))
|
||||
.join('');
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a kebab-cased string to camelCase.
|
||||
*/
|
||||
export function toCamelCase(text: string): string {
|
||||
const pascal = toPascalCase(text);
|
||||
return pascal.charAt(0).toLowerCase() + pascal.slice(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps database types to TypeScript types.
|
||||
*/
|
||||
export function mapDbToTsType(dbType: string): string {
|
||||
if (dbType.includes('int') || dbType.includes('serial')) return 'number';
|
||||
if (['float', 'double', 'decimal', 'numeric', 'real'].includes(dbType)) return 'number';
|
||||
if (dbType.includes('char') || dbType.includes('text') || dbType === 'uuid') return 'string';
|
||||
if (dbType === 'boolean' || dbType === 'bool') return 'boolean';
|
||||
if (dbType.includes('date') || dbType.includes('time')) return 'Date';
|
||||
return 'any';
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user