generate server side
This commit is contained in:
parent
e352f161bc
commit
c5addf58d3
98
package-lock.json
generated
98
package-lock.json
generated
@ -17,6 +17,7 @@
|
|||||||
"pg": "^8.16.3",
|
"pg": "^8.16.3",
|
||||||
"reflect-metadata": "^0.2.2",
|
"reflect-metadata": "^0.2.2",
|
||||||
"rxjs": "^7.8.1",
|
"rxjs": "^7.8.1",
|
||||||
|
"ts-morph": "^27.0.2",
|
||||||
"typeorm": "^0.3.27"
|
"typeorm": "^0.3.27"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
@ -1369,7 +1370,6 @@
|
|||||||
"version": "4.0.1",
|
"version": "4.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/@isaacs/balanced-match/-/balanced-match-4.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/@isaacs/balanced-match/-/balanced-match-4.0.1.tgz",
|
||||||
"integrity": "sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==",
|
"integrity": "sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "20 || >=22"
|
"node": "20 || >=22"
|
||||||
@ -1379,7 +1379,6 @@
|
|||||||
"version": "5.0.0",
|
"version": "5.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/@isaacs/brace-expansion/-/brace-expansion-5.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/@isaacs/brace-expansion/-/brace-expansion-5.0.0.tgz",
|
||||||
"integrity": "sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA==",
|
"integrity": "sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@isaacs/balanced-match": "^4.0.1"
|
"@isaacs/balanced-match": "^4.0.1"
|
||||||
@ -2703,6 +2702,32 @@
|
|||||||
"integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==",
|
"integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/@ts-morph/common": {
|
||||||
|
"version": "0.28.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@ts-morph/common/-/common-0.28.1.tgz",
|
||||||
|
"integrity": "sha512-W74iWf7ILp1ZKNYXY5qbddNaml7e9Sedv5lvU1V8lftlitkc9Pq1A+jlH23ltDgWYeZFFEqGCD1Ies9hqu3O+g==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"minimatch": "^10.0.1",
|
||||||
|
"path-browserify": "^1.0.1",
|
||||||
|
"tinyglobby": "^0.2.14"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@ts-morph/common/node_modules/minimatch": {
|
||||||
|
"version": "10.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.1.1.tgz",
|
||||||
|
"integrity": "sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ==",
|
||||||
|
"license": "BlueOak-1.0.0",
|
||||||
|
"dependencies": {
|
||||||
|
"@isaacs/brace-expansion": "^5.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "20 || >=22"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/isaacs"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@tsconfig/node10": {
|
"node_modules/@tsconfig/node10": {
|
||||||
"version": "1.0.12",
|
"version": "1.0.12",
|
||||||
"resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.12.tgz",
|
"resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.12.tgz",
|
||||||
@ -4652,6 +4677,12 @@
|
|||||||
"node": ">= 0.12.0"
|
"node": ">= 0.12.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/code-block-writer": {
|
||||||
|
"version": "13.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/code-block-writer/-/code-block-writer-13.0.3.tgz",
|
||||||
|
"integrity": "sha512-Oofo0pq3IKnsFtuHqSF7TqBfr71aeyZDVJ0HpmqB7FBM2qEigL0iPONSCZSO9pE9dZTAxANe5XHG9Uy0YMv8cg==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/collect-v8-coverage": {
|
"node_modules/collect-v8-coverage": {
|
||||||
"version": "1.0.3",
|
"version": "1.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.3.tgz",
|
||||||
@ -5621,6 +5652,23 @@
|
|||||||
"bser": "2.1.1"
|
"bser": "2.1.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/fdir": {
|
||||||
|
"version": "6.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
|
||||||
|
"integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12.0.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"picomatch": "^3 || ^4"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"picomatch": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/fflate": {
|
"node_modules/fflate": {
|
||||||
"version": "0.8.2",
|
"version": "0.8.2",
|
||||||
"resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.2.tgz",
|
"resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.2.tgz",
|
||||||
@ -8285,6 +8333,12 @@
|
|||||||
"node": ">= 0.8"
|
"node": ">= 0.8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/path-browserify": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/path-exists": {
|
"node_modules/path-exists": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
|
||||||
@ -8459,7 +8513,7 @@
|
|||||||
"version": "4.0.2",
|
"version": "4.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz",
|
||||||
"integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==",
|
"integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==",
|
||||||
"dev": true,
|
"devOptional": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=12"
|
"node": ">=12"
|
||||||
@ -9827,6 +9881,34 @@
|
|||||||
"integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==",
|
"integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/tinyglobby": {
|
||||||
|
"version": "0.2.15",
|
||||||
|
"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz",
|
||||||
|
"integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"fdir": "^6.5.0",
|
||||||
|
"picomatch": "^4.0.3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/SuperchupuDev"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/tinyglobby/node_modules/picomatch": {
|
||||||
|
"version": "4.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
|
||||||
|
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/jonschlinkert"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/tmpl": {
|
"node_modules/tmpl": {
|
||||||
"version": "1.0.5",
|
"version": "1.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz",
|
||||||
@ -9998,6 +10080,16 @@
|
|||||||
"webpack": "^5.0.0"
|
"webpack": "^5.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/ts-morph": {
|
||||||
|
"version": "27.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/ts-morph/-/ts-morph-27.0.2.tgz",
|
||||||
|
"integrity": "sha512-fhUhgeljcrdZ+9DZND1De1029PrE+cMkIP7ooqkLRTrRLTqcki2AstsyJm0vRNbTbVCNJ0idGlbBrfqc7/nA8w==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@ts-morph/common": "~0.28.1",
|
||||||
|
"code-block-writer": "^13.0.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/ts-node": {
|
"node_modules/ts-node": {
|
||||||
"version": "10.9.2",
|
"version": "10.9.2",
|
||||||
"resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz",
|
"resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz",
|
||||||
|
|||||||
@ -29,6 +29,7 @@
|
|||||||
"pg": "^8.16.3",
|
"pg": "^8.16.3",
|
||||||
"reflect-metadata": "^0.2.2",
|
"reflect-metadata": "^0.2.2",
|
||||||
"rxjs": "^7.8.1",
|
"rxjs": "^7.8.1",
|
||||||
|
"ts-morph": "^27.0.2",
|
||||||
"typeorm": "^0.3.27"
|
"typeorm": "^0.3.27"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|||||||
@ -5,9 +5,10 @@ import { GenerateCommand } from './commands/generate.command';
|
|||||||
import { ConfigService } from './services/config.service';
|
import { ConfigService } from './services/config.service';
|
||||||
import { EntityGeneratorService } from './services/entity-generator.service';
|
import { EntityGeneratorService } from './services/entity-generator.service';
|
||||||
import { CrudGeneratorService } from './services/crud-generator.service';
|
import { CrudGeneratorService } from './services/crud-generator.service';
|
||||||
|
import { ModuleUpdaterService } from './services/module-updater.service';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [],
|
imports: [],
|
||||||
providers: [AppService,GenerateCommand,ConfigService,EntityGeneratorService,CrudGeneratorService],
|
providers: [AppService,GenerateCommand,ConfigService,EntityGeneratorService,CrudGeneratorService,ModuleUpdaterService],
|
||||||
})
|
})
|
||||||
export class AppModule {}
|
export class AppModule {}
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import { ConfigService } from './config.service';
|
|||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
import { promises as fsPromises } from 'fs';
|
import { promises as fsPromises } from 'fs';
|
||||||
|
import { ModuleUpdaterService } from './module-updater.service';
|
||||||
|
|
||||||
interface NamingConvention {
|
interface NamingConvention {
|
||||||
singular: string;
|
singular: string;
|
||||||
@ -14,7 +15,7 @@ interface NamingConvention {
|
|||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class CrudGeneratorService {
|
export class CrudGeneratorService {
|
||||||
constructor(private readonly configService: ConfigService) {
|
constructor(private readonly configService: ConfigService, private readonly moduleUpdaterService: ModuleUpdaterService,) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public async generate(tableName: string): Promise<void> {
|
public async generate(tableName: string): Promise<void> {
|
||||||
@ -31,7 +32,15 @@ export class CrudGeneratorService {
|
|||||||
await this.generateDtoFiles(names, moduleDir);
|
await this.generateDtoFiles(names, moduleDir);
|
||||||
|
|
||||||
console.log(`✅ CRUD module for "${tableName}" created successfully in: ${moduleDir}`);
|
console.log(`✅ CRUD module for "${tableName}" created successfully in: ${moduleDir}`);
|
||||||
console.warn(`\n🔔 Action Required: Remember to import ${names.pascal}sModule into your main app.module.ts!`);
|
|
||||||
|
// --- 3. CALL THE UPDATER ---
|
||||||
|
const moduleFileName = `${names.plural}.module.ts`;
|
||||||
|
const fullModulePath = path.join(moduleDir, moduleFileName);
|
||||||
|
await this.moduleUpdaterService.addImportToAppModule(`${names.pascal}sModule`, fullModulePath);
|
||||||
|
// --- END OF CALL ---
|
||||||
|
|
||||||
|
// We can now remove the old warning!
|
||||||
|
console.log('\n✨ AppModule has been updated automatically! ✨');
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`❌ An error occurred during CRUD generation:`, error.message);
|
console.error(`❌ An error occurred during CRUD generation:`, error.message);
|
||||||
|
|||||||
@ -5,10 +5,13 @@ import { DataSource, DataSourceOptions, TableColumn } from 'typeorm';
|
|||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
import { promises as fsPromises } from 'fs';
|
import { promises as fsPromises } from 'fs';
|
||||||
|
import { ModuleUpdaterService } from './module-updater.service';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class EntityGeneratorService {
|
export class EntityGeneratorService {
|
||||||
constructor(private readonly configService: ConfigService) {}
|
constructor(private readonly configService: ConfigService,
|
||||||
|
private readonly moduleUpdaterService: ModuleUpdaterService) {}
|
||||||
|
|
||||||
|
|
||||||
public async generate(tableName: string): Promise<void> {
|
public async generate(tableName: string): Promise<void> {
|
||||||
console.log(`Generating entity for table: ${tableName}...`);
|
console.log(`Generating entity for table: ${tableName}...`);
|
||||||
@ -35,6 +38,12 @@ export class EntityGeneratorService {
|
|||||||
const entityContent = this.createEntityTemplate(tableName, columns);
|
const entityContent = this.createEntityTemplate(tableName, columns);
|
||||||
|
|
||||||
const singularName = this.toSingular(tableName);
|
const singularName = this.toSingular(tableName);
|
||||||
|
|
||||||
|
// --- THIS IS THE FIX ---
|
||||||
|
// Define className here so it can be used below.
|
||||||
|
const className = this.toPascalCase(singularName);
|
||||||
|
// --- END OF FIX ---
|
||||||
|
|
||||||
const entityFileName = `${singularName}.entity.ts`;
|
const entityFileName = `${singularName}.entity.ts`;
|
||||||
const serverRoot = path.resolve(process.cwd(), config.server.path);
|
const serverRoot = path.resolve(process.cwd(), config.server.path);
|
||||||
const entitiesDir = path.join(serverRoot, config.server.entitiesPath);
|
const entitiesDir = path.join(serverRoot, config.server.entitiesPath);
|
||||||
@ -44,6 +53,9 @@ export class EntityGeneratorService {
|
|||||||
fs.writeFileSync(outputPath, entityContent);
|
fs.writeFileSync(outputPath, entityContent);
|
||||||
console.log(`✅ Entity created successfully at: ${outputPath}`);
|
console.log(`✅ Entity created successfully at: ${outputPath}`);
|
||||||
|
|
||||||
|
// Now the call will work correctly
|
||||||
|
await this.moduleUpdaterService.addEntityToTypeOrm(className, outputPath);
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('❌ An error occurred:', error.message);
|
console.error('❌ An error occurred:', error.message);
|
||||||
} finally {
|
} finally {
|
||||||
|
|||||||
115
src/services/module-updater.service.ts
Normal file
115
src/services/module-updater.service.ts
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
// src/services/module-updater.service.ts
|
||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
import { ConfigService } from './config.service';
|
||||||
|
import { Project, PropertyAssignment, SyntaxKind, ObjectLiteralExpression, ArrayLiteralExpression, ArrowFunction } from 'ts-morph';
|
||||||
|
import * as path from 'path';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class ModuleUpdaterService {
|
||||||
|
constructor(private readonly configService: ConfigService) {}
|
||||||
|
|
||||||
|
public async addImportToAppModule(moduleNameToAdd: string, modulePath: string): Promise<void> {
|
||||||
|
// ... (this method remains unchanged)
|
||||||
|
const config = this.configService.get();
|
||||||
|
const serverRoot = path.resolve(process.cwd(), config.server.path);
|
||||||
|
const appModulePath = path.join(serverRoot, 'src', 'app.module.ts');
|
||||||
|
|
||||||
|
console.log(`Attempting to update ${appModulePath} for module import...`);
|
||||||
|
|
||||||
|
const project = new Project();
|
||||||
|
const sourceFile = project.addSourceFileAtPath(appModulePath);
|
||||||
|
|
||||||
|
const relativeModulePath = path.relative(path.dirname(appModulePath), modulePath).replace(/\\/g, '/').replace('.ts', '');
|
||||||
|
|
||||||
|
const existingImport = sourceFile.getImportDeclaration(d => d.getModuleSpecifierValue() === `./${relativeModulePath}`);
|
||||||
|
if (!existingImport) {
|
||||||
|
sourceFile.addImportDeclaration({
|
||||||
|
namedImports: [moduleNameToAdd],
|
||||||
|
moduleSpecifier: `./${relativeModulePath}`,
|
||||||
|
});
|
||||||
|
console.log(`Added import for ${moduleNameToAdd}.`);
|
||||||
|
} else {
|
||||||
|
console.log(`Import for ${moduleNameToAdd} already exists.`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const appModuleClass = sourceFile.getClassOrThrow('AppModule');
|
||||||
|
const moduleDecorator = appModuleClass.getDecoratorOrThrow('Module');
|
||||||
|
const decoratorArg = moduleDecorator.getArguments()[0] as ObjectLiteralExpression;
|
||||||
|
|
||||||
|
const importsProperty = decoratorArg.getProperty('imports') as PropertyAssignment;
|
||||||
|
if (!importsProperty) {
|
||||||
|
throw new Error('Could not find "imports" array in AppModule decorator.');
|
||||||
|
}
|
||||||
|
|
||||||
|
const importsArray = importsProperty.getInitializerIfKindOrThrow(SyntaxKind.ArrayLiteralExpression);
|
||||||
|
|
||||||
|
const moduleAlreadyExists = importsArray.getElements().some(elem => elem.getText() === moduleNameToAdd);
|
||||||
|
|
||||||
|
if (!moduleAlreadyExists) {
|
||||||
|
importsArray.addElement(moduleNameToAdd);
|
||||||
|
console.log(`Added ${moduleNameToAdd} to the AppModule imports array.`);
|
||||||
|
} else {
|
||||||
|
console.log(`${moduleNameToAdd} is already present in the AppModule imports array.`);
|
||||||
|
}
|
||||||
|
|
||||||
|
await sourceFile.save();
|
||||||
|
console.log('AppModule saved successfully.');
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- NEW METHOD ---
|
||||||
|
public async addEntityToTypeOrm(entityNameToAdd: string, entityPath: string): Promise<void> {
|
||||||
|
const config = this.configService.get();
|
||||||
|
const serverRoot = path.resolve(process.cwd(), config.server.path);
|
||||||
|
const appModulePath = path.join(serverRoot, 'src', 'app.module.ts');
|
||||||
|
|
||||||
|
console.log(`Attempting to update ${appModulePath} for entity registration...`);
|
||||||
|
|
||||||
|
const project = new Project();
|
||||||
|
const sourceFile = project.addSourceFileAtPath(appModulePath);
|
||||||
|
|
||||||
|
// 1. Add the import for the entity
|
||||||
|
const relativeEntityPath = path.relative(path.dirname(appModulePath), entityPath).replace(/\\/g, '/').replace('.ts', '');
|
||||||
|
|
||||||
|
const existingImport = sourceFile.getImportDeclaration(d => d.getModuleSpecifierValue() === `./${relativeEntityPath}`);
|
||||||
|
if (!existingImport) {
|
||||||
|
sourceFile.addImportDeclaration({
|
||||||
|
namedImports: [entityNameToAdd],
|
||||||
|
moduleSpecifier: `./${relativeEntityPath}`,
|
||||||
|
});
|
||||||
|
console.log(`Added import for entity ${entityNameToAdd}.`);
|
||||||
|
} else {
|
||||||
|
console.log(`Import for entity ${entityNameToAdd} already exists.`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Find the 'moduleTypeOrm' variable declaration
|
||||||
|
const variableDeclaration = sourceFile.getVariableDeclarationOrThrow('moduleTypeOrm');
|
||||||
|
|
||||||
|
// 3. Navigate through the AST to find the 'entities' array
|
||||||
|
const useFactory = variableDeclaration
|
||||||
|
.getInitializerIfKindOrThrow(SyntaxKind.CallExpression)
|
||||||
|
.getArguments()[0]
|
||||||
|
.asKindOrThrow(SyntaxKind.ObjectLiteralExpression)
|
||||||
|
.getPropertyOrThrow('useFactory')
|
||||||
|
.asKindOrThrow(SyntaxKind.PropertyAssignment);
|
||||||
|
|
||||||
|
const factoryFunction = useFactory.getInitializerIfKindOrThrow(SyntaxKind.ArrowFunction);
|
||||||
|
const returnStatement = factoryFunction.getFirstDescendantByKindOrThrow(SyntaxKind.ReturnStatement);
|
||||||
|
|
||||||
|
const returnedObject = returnStatement.getExpressionIfKindOrThrow(SyntaxKind.ObjectLiteralExpression);
|
||||||
|
const entitiesProperty = returnedObject.getProperty('entities')!.asKindOrThrow(SyntaxKind.PropertyAssignment);
|
||||||
|
const entitiesArray = entitiesProperty.getInitializerIfKindOrThrow(SyntaxKind.ArrayLiteralExpression);
|
||||||
|
|
||||||
|
// 4. Check if the entity is already in the array and add it if not
|
||||||
|
const entityAlreadyExists = entitiesArray.getElements().some(elem => elem.getText() === entityNameToAdd);
|
||||||
|
if (!entityAlreadyExists) {
|
||||||
|
entitiesArray.addElement(entityNameToAdd);
|
||||||
|
console.log(`Added ${entityNameToAdd} to the TypeORM entities array.`);
|
||||||
|
} else {
|
||||||
|
console.log(`${entityNameToAdd} is already in the TypeORM entities array.`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5. Save the file
|
||||||
|
await sourceFile.save();
|
||||||
|
console.log('AppModule saved successfully after entity registration.');
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user