diff --git a/src/codebaseHelpers/ImportAndAddItemToInitializerArrayProperty.ts b/src/codebaseHelpers/ImportAndAddItemToInitializerArrayProperty.ts index 07bf100..38d9b32 100644 --- a/src/codebaseHelpers/ImportAndAddItemToInitializerArrayProperty.ts +++ b/src/codebaseHelpers/ImportAndAddItemToInitializerArrayProperty.ts @@ -21,7 +21,7 @@ export class ImportAndAddItemToInitializerArrayProperty { private referenceAdded: boolean = false; private importAdded: boolean = false; private filesToAddImportInFilePaths = new Set(); - private variableDeclarationReplacementMap = new Map(); + private declarationReplacementMap = new Map(); private linkingError: boolean = false; @@ -441,38 +441,60 @@ export class ImportAndAddItemToInitializerArrayProperty { declaration, declaration.name, declaration.exclamationToken, declaration.type, updateWithTypeExpression(declaration.initializer, (valueExpression) => { - if (ts.isArrayLiteralExpression(valueExpression)) { - const resExpression = this.updateArrayLiteralExpression(valueExpression, undefined); + const resExpression = this.updateExpression(valueExpression, valueExpression.getSourceFile()); - if (valueExpression != (resExpression)) - declarationUpdated = true; + if (valueExpression != resExpression) + declarationUpdated = true; - return resExpression; - } + return resExpression; + } + ) + ); - if (ts.isObjectLiteralExpression(valueExpression) && this.treatObjectLiteralExpressionValuesAsList) { - const resExpression = this.updateObjectLiteralExpression(valueExpression, undefined); + if (declarationUpdated) { + this.declarationReplacementMap.set(declaration, newDeclaration); - if (valueExpression != (resExpression)) - declarationUpdated = true; + this.codebase.markSourceFileAsUpdated(declaration.getSourceFile()); + } + } else if ( + // *export []* + // *export {}* + ts.isExportAssignment(declaration) + ) { + if ( + !this.updateOtherRelevantFiles && + path.resolve(sourceFile.fileName) != path.resolve(this.codebase.entryFilePath) + ) + return; - return resExpression; - } + let declarationUpdated = false; + const newDeclaration = ts.factory.updateExportAssignment( + declaration, declaration.decorators, declaration.modifiers, + updateWithTypeExpression(declaration.expression, + (valueExpression) => { + const resExpression = this.updateExpression(valueExpression, valueExpression.getSourceFile()); - return valueExpression; + if (valueExpression != resExpression) + declarationUpdated = true; + + return resExpression; } ) ); if (declarationUpdated) { - this.variableDeclarationReplacementMap.set(declaration, newDeclaration); + this.declarationReplacementMap.set(declaration, newDeclaration); this.codebase.markSourceFileAsUpdated(declaration.getSourceFile()); } } else if ( // *import {value} from "./somewhere"* - ts.isImportSpecifier(declaration) + ts.isImportSpecifier(declaration) || + ts.isImportClause(declaration) ) { + if (declaration.name == null) + return; + const declarationNamedImportSymbol = this.codebase.checker.getSymbolAtLocation(declaration.name); if (declarationNamedImportSymbol == null) @@ -570,12 +592,12 @@ export class ImportAndAddItemToInitializerArrayProperty { ]); } - private updateDeclaration(declaration: ts.VariableDeclaration): ts.VariableDeclaration { - const res = this.variableDeclarationReplacementMap.get(declaration); + private updateDeclaration(declaration: T): T { + const res = this.declarationReplacementMap.get(declaration); if (res != null) { - this.variableDeclarationReplacementMap.delete(declaration); - return res; + this.declarationReplacementMap.delete(declaration); + return res as T; } return declaration; @@ -590,7 +612,8 @@ export class ImportAndAddItemToInitializerArrayProperty { statement.declarationList.declarations.map(this.updateDeclaration) ) ); - } + } else if (ts.isExportAssignment(statement)) + return this.updateDeclaration(statement); return statement; }) diff --git a/src/commands/AddReferencesCommand.ts b/src/commands/AddReferencesCommand.ts index 73b0b47..4e3f7ef 100644 --- a/src/commands/AddReferencesCommand.ts +++ b/src/commands/AddReferencesCommand.ts @@ -10,10 +10,6 @@ export class AddReferencesCommand implements yargs.CommandModule [options]`) @@ -50,7 +46,7 @@ export class AddReferencesCommand implements yargs.CommandModule { const cwd = this.cwd ?? process.cwd(); let addedMigrationFiles: string[] = []; let addedEntityFiles: string[] = []; diff --git a/test/codebaseHelpers/ImportAndAddItemToInitializerArrayProperty.test.ts b/test/codebaseHelpers/ImportAndAddItemToInitializerArrayProperty.test.ts index c8af2df..0465055 100644 --- a/test/codebaseHelpers/ImportAndAddItemToInitializerArrayProperty.test.ts +++ b/test/codebaseHelpers/ImportAndAddItemToInitializerArrayProperty.test.ts @@ -318,6 +318,156 @@ describe("Update DataSource initializer in data-source.ts file", () => { }); }); + it("external file with default exported variable list", async () => { + await testDataSourceFileWithLinkToEntitiesInOtherFile({ + entityName, + dataSourceCode: ` + import entities from "./entities.js" + + export const AppDataSource = new DataSource({ + type: "sqlite", + database: "database.db", + entities: entities + }); + `, + files: [{ + path: "entities.ts", + content: ` + import { SomeModal } from "./entities/SomeModal.js"; + + const entities1 = [ + SomeModal + ]; + + export default entities1; + ` + }, { + path: "entities/SomeModal.ts", + content: ` + export class SomeModal {} + ` + }], + testCode: ` + const entities: any = dataSourceResult.AppDataSource.options.entities; + expect(entities).to.be.an("array"); + expect(entities.length).to.be.gt(0); + expect(entities[entities.length - 1].name).to.be.eq(${JSON.stringify(entityName)}); + ` + }); + }); + + it("external file with default exported list", async () => { + await testDataSourceFileWithLinkToEntitiesInOtherFile({ + entityName, + dataSourceCode: ` + import entities from "./entities.js" + + export const AppDataSource = new DataSource({ + type: "sqlite", + database: "database.db", + entities: entities + }); + `, + files: [{ + path: "entities.ts", + content: ` + import { SomeModal } from "./entities/SomeModal.js"; + + export default [ + SomeModal + ]; + ` + }, { + path: "entities/SomeModal.ts", + content: ` + export class SomeModal {} + ` + }], + testCode: ` + const entities: any = dataSourceResult.AppDataSource.options.entities; + expect(entities).to.be.an("array"); + expect(entities.length).to.be.gt(0); + expect(entities[entities.length - 1].name).to.be.eq(${JSON.stringify(entityName)}); + ` + }); + }); + + it("external file with default exported variable object", async () => { + await testDataSourceFileWithLinkToEntitiesInOtherFile({ + entityName, + dataSourceCode: ` + import entities from "./entities.js" + + export const AppDataSource = new DataSource({ + type: "sqlite", + database: "database.db", + entities: entities + }); + `, + files: [{ + path: "entities.ts", + content: ` + import { SomeModal } from "./entities/SomeModal.js"; + + const entities1 = { + SomeModal + }; + + export default entities1; + ` + }, { + path: "entities/SomeModal.ts", + content: ` + export class SomeModal {} + ` + }], + testCode: ` + const entities: any = dataSourceResult.AppDataSource.options.entities; + expect(entities).to.be.an("object"); + const entityNamesList: (string | undefined)[] = Object.values(entities).map((entity: any) => entity?.name); + expect(entityNamesList.length).to.be.gt(0); + expect(entityNamesList).to.include(${JSON.stringify(entityName)}); + ` + }); + }); + + it("external file with default exported object", async () => { + await testDataSourceFileWithLinkToEntitiesInOtherFile({ + entityName, + dataSourceCode: ` + import entities from "./entities.js" + + export const AppDataSource = new DataSource({ + type: "sqlite", + database: "database.db", + entities: entities + }); + `, + files: [{ + path: "entities.ts", + content: ` + import { SomeModal } from "./entities/SomeModal.js"; + + export default { + SomeModal + }; + ` + }, { + path: "entities/SomeModal.ts", + content: ` + export class SomeModal {} + ` + }], + testCode: ` + const entities: any = dataSourceResult.AppDataSource.options.entities; + expect(entities).to.be.an("object"); + const entityNamesList: (string | undefined)[] = Object.values(entities).map((entity: any) => entity?.name); + expect(entityNamesList.length).to.be.gt(0); + expect(entityNamesList).to.include(${JSON.stringify(entityName)}); + ` + }); + }); + it("external file with exported list - shorthand property assignment", async () => { await testDataSourceFileWithLinkToEntitiesInOtherFile({ entityName,