Skip to content

Commit

Permalink
feat: added support for more code variations
Browse files Browse the repository at this point in the history
  • Loading branch information
giladgd committed Apr 4, 2022
1 parent 5ebce9a commit 0cd600b
Show file tree
Hide file tree
Showing 3 changed files with 195 additions and 26 deletions.
65 changes: 44 additions & 21 deletions src/codebaseHelpers/ImportAndAddItemToInitializerArrayProperty.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export class ImportAndAddItemToInitializerArrayProperty {
private referenceAdded: boolean = false;
private importAdded: boolean = false;
private filesToAddImportInFilePaths = new Set<string>();
private variableDeclarationReplacementMap = new Map<ts.VariableDeclaration, ts.VariableDeclaration>();
private declarationReplacementMap = new Map<ts.Declaration, ts.Declaration>();

private linkingError: boolean = false;

Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -570,12 +592,12 @@ export class ImportAndAddItemToInitializerArrayProperty {
]);
}

private updateDeclaration(declaration: ts.VariableDeclaration): ts.VariableDeclaration {
const res = this.variableDeclarationReplacementMap.get(declaration);
private updateDeclaration<T extends ts.Declaration>(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;
Expand All @@ -590,7 +612,8 @@ export class ImportAndAddItemToInitializerArrayProperty {
statement.declarationList.declarations.map(this.updateDeclaration)
)
);
}
} else if (ts.isExportAssignment(statement))
return this.updateDeclaration(statement);

return statement;
})
Expand Down
6 changes: 1 addition & 5 deletions src/commands/AddReferencesCommand.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,6 @@ export class AddReferencesCommand implements yargs.CommandModule<object, command

cwd = process.cwd();

constructor() {
this.builder = this.builder.bind(this);
}

builder(args: yargs.Argv) {
return args
.usage(`Usage: $0 ${this.command} --dataSource <path> [options]`)
Expand Down Expand Up @@ -50,7 +46,7 @@ export class AddReferencesCommand implements yargs.CommandModule<object, command
});
}

async handler(args: commandArgs) {
handler = async (args: commandArgs) => {
const cwd = this.cwd ?? process.cwd();
let addedMigrationFiles: string[] = [];
let addedEntityFiles: string[] = [];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down

0 comments on commit 0cd600b

Please sign in to comment.