diff --git a/src/services/angular-generator.service.ts b/src/services/angular-generator.service.ts
index 71d84d8..ab843a3 100644
--- a/src/services/angular-generator.service.ts
+++ b/src/services/angular-generator.service.ts
@@ -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 `
${label}\n ${input}
`;
}
- 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();
- }
+
}
\ No newline at end of file
diff --git a/src/services/crud-generator.service.ts b/src/services/crud-generator.service.ts
index 3fc505f..06bbc26 100644
--- a/src/services/crud-generator.service.ts
+++ b/src/services/crud-generator.service.ts
@@ -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();
- }
+
}
\ No newline at end of file
diff --git a/src/services/entity-generator.service.ts b/src/services/entity-generator.service.ts
index 7ff29b2..76ccbe8 100644
--- a/src/services/entity-generator.service.ts
+++ b/src/services/entity-generator.service.ts
@@ -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();
- }
}
\ No newline at end of file
diff --git a/src/services/generic-table-generator.service.ts b/src/services/generic-table-generator.service.ts
index 3b1a269..43f25bf 100644
--- a/src/services/generic-table-generator.service.ts
+++ b/src/services/generic-table-generator.service.ts
@@ -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';
- }
+
}
\ No newline at end of file
diff --git a/src/utils/naming.utils.ts b/src/utils/naming.utils.ts
new file mode 100644
index 0000000..f6b7511
--- /dev/null
+++ b/src/utils/naming.utils.ts
@@ -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';
+}
\ No newline at end of file