Skip to content

Commit

Permalink
fix: Regenerate model ignoring existing data
Browse files Browse the repository at this point in the history
BREAKING CHANGE:
Model is regenerating ignoring existing data, any manual changes will be discarded

close: #45
  • Loading branch information
unlight committed Aug 28, 2021
1 parent c581bc7 commit 62ffd83
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 83 deletions.
113 changes: 36 additions & 77 deletions src/handlers/model-output-type.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
import { ok } from 'assert';
import JSON5 from 'json5';
import { castArray, remove, trim } from 'lodash';
import { castArray, trim } from 'lodash';
import { PlainObject } from 'simplytyped';
import {
ClassDeclarationStructure,
CommentStatement,
ExportSpecifierStructure,
ImportDeclarationStructure,
ImportSpecifierStructure,
OptionalKind,
StatementStructures,
StructureKind,
} from 'ts-morph';
Expand All @@ -31,47 +28,28 @@ export function modelOutputType(outputType: OutputType, args: EventArguments) {
type: 'model',
});
const sourceFileStructure = sourceFile.getStructure();
const imports = remove(
const exportDeclaration = getExportDeclaration(
model.name,
sourceFileStructure.statements as StatementStructures[],
s => s.kind === StructureKind.ImportDeclaration,
).flatMap(s => {
return (
(s as ImportDeclarationStructure)
.namedImports as OptionalKind<ImportSpecifierStructure>[]
).map(x => [
x.name || x.alias,
);
const importDeclarations = new ImportDeclarationMap();
const classStructure: ClassDeclarationStructure = {
kind: StructureKind.Class,
isExported: true,
name: outputType.name,
decorators: [
{
moduleSpecifier: (s as ImportDeclarationStructure).moduleSpecifier,
namedImports: [{ name: x.name, alias: x.alias }],
name: 'ObjectType',
arguments: [],
},
]);
}) as Array<[string, OptionalKind<ImportDeclarationStructure>]>;
const importDeclarations = new ImportDeclarationMap(imports);

let classStructure = (sourceFileStructure.statements as StatementStructures[]).find(
(s: StatementStructures) => s.kind === StructureKind.Class,
) as ClassDeclarationStructure | undefined;

if (!classStructure) {
classStructure = {
kind: StructureKind.Class,
isExported: true,
name: outputType.name,
decorators: [
{
name: 'ObjectType',
arguments: [],
},
],
properties: [],
};
(sourceFileStructure.statements as StatementStructures[]).push(classStructure);
}

],
properties: [],
};
(sourceFileStructure.statements as StatementStructures[]).push(classStructure);
const decorator = classStructure.decorators?.find(d => d.name === 'ObjectType');
ok(decorator, 'ObjectType decorator not found');
const decoratorArgument = decorator.arguments?.[0]
? JSON5.parse(decorator.arguments[0])
? JSON5.parse<PlainObject>(decorator.arguments[0])
: {};
if (model.documentation) {
if (!classStructure.leadingTrivia) {
Expand All @@ -91,15 +69,6 @@ export function modelOutputType(outputType: OutputType, args: EventArguments) {
importDeclarations.add('ObjectType', nestjsGraphql);

for (const field of outputType.fields) {
// if (model.name === 'Comment') {
// console.dir(field);
// }

// Do not generate already defined properties for model
if (classStructure.properties?.some(p => p.name === field.name)) {
continue;
}

let fileType = 'model';
const { location, isList, type, namespace } = field.outputType;

Expand Down Expand Up @@ -228,41 +197,31 @@ export function modelOutputType(outputType: OutputType, args: EventArguments) {
eventEmitter.emitSync('ClassProperty', property, { location, isList });
}

const hasExportDeclaration = (
sourceFileStructure.statements as StatementStructures[]
).some(structure => {
return (
structure.kind === StructureKind.ExportDeclaration &&
(structure.namedExports as ExportSpecifierStructure[]).some(
o => (o.alias || o.name) === model.name,
)
);
});

// Check re-export, comment generated class if found
if (hasExportDeclaration) {
let commentStatement: CommentStatement | undefined;
while (
(commentStatement = sourceFile.getStatementByKind(
2 /* SingleLineCommentTrivia */,
))
) {
commentStatement.remove();
}

sourceFile.addStatements([classStructure]);
if (exportDeclaration) {
sourceFile.set({
statements: [exportDeclaration, '\n', classStructure],
});
const classDeclaration = sourceFile.getClassOrThrow(model.name);

const commentedText = classDeclaration
.getText()
.split('\n')
.map(x => `// ${x}`);
classDeclaration.remove();
sourceFile.addStatements(['\n', ...commentedText]);
} else {
(sourceFileStructure.statements as StatementStructures[]).unshift(
...importDeclarations.toStatements(),
);
sourceFile.set(sourceFileStructure);
sourceFile.set({
statements: [...importDeclarations.toStatements(), classStructure],
});
}
}

function getExportDeclaration(name: string, statements: StatementStructures[]) {
return statements.find(structure => {
return (
structure.kind === StructureKind.ExportDeclaration &&
(structure.namedExports as ExportSpecifierStructure[]).some(
o => (o.alias || o.name) === name,
)
);
});
}
7 changes: 1 addition & 6 deletions src/test/generate.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -931,12 +931,7 @@ describe('model with one id string', () => {
`,
},
}));
sourceFile = project.getSourceFile(s =>
s.getFilePath().endsWith('user.model.ts'),
)!;
sourceText = sourceFile.getText();
const sourceClass = sourceFile.getClasses();
expect(sourceClass).toHaveLength(0);
setSourceFile('user.model.ts');
expect(sourceText).toContain(`export { User } from 'src/user/model'`);
expect(sourceText).toContain(`// export class User`);
});
Expand Down

0 comments on commit 62ffd83

Please sign in to comment.