'Add a component in declarations NgModule using ts-morph

I'm using ts-morph library and I want to insert in the declarations a component:

This is what I have:
@NgModule({
declarations: [],
imports: [],
providers: [],
})

This is what I want:

@NgModule({
declarations: [ExampleComponent],
imports: [],
providers: [],
})

I try this, but no results:

 const decorator = classDeclaration.getDecorator("NgModule"); 
 const arg = decorator.getArguments()[0];
 
 const declarationsProp = arg.getDescendants()
    .find(d => d.getKind() === SyntaxKind.PropertyAssignment &&
    (d.compilerNode as ts.PropertyAssignment).name === "declarations");

const array = declarationsProp.getFirstChildByKindOrThrow(SyntaxKind.ArrayLiteralExpression);
const closeBracketToken = array.getLastChildByKindOrThrow(SyntaxKind.CloseBracketToken);
 
sourceFile.insertText(closeBracketToken.getPos(), `, "something new!"`);

And these other solution but I couldn't find a way to insert the component

 const classDeclaration = sourceFile
      .getClasses()
      .find(
        (classDeclaration) =>
          classDeclaration.getName() === 'ExampleModule'
      );

    (classDeclaration.getDecorator('NgModule').getStructure()
      .arguments as any[]).forEach((element) => {
      addLog(LogType.Info, LogMode.Always, element);
    });


Solution 1:[1]

I just had the same issue and this is how I handled it

const classDeclaration = sourceFile
    .getClasses()
    .find(
      (classDeclaration) =>
        classDeclaration.getName() === 'ExampleModule'
    )!;

  const moduleArguments = classDeclaration!.getDecorator('NgModule')!.getArguments()!;
  const imports = moduleArguments[0];
  const fullText = imports.getFullText();

  const sliceIndex = fullText.indexOf('declarations: [');
  let text = '';
  text = fullText.slice(0, fullText.indexOf(']', sliceIndex));
  text += `, "something new!"],`;
  text += fullText.slice(fullText.indexOf('],', sliceIndex) + 2);

  imports.replaceWithText((writer) => {
    writer.writeLine(text);
  });

Probably there's a nicer way to achieve it but me also struggled with it...

Solution 2:[2]

for anyone else looking for an updated syntax

const ngModuleClass = editCodeBlockInput.sourceFile.getClass(c => c.getText().includes('@NgModule'));
  const ngModuleDecorator = ngModuleClass.getDecorator('NgModule');
  const moduleArguments = ngModuleDecorator.getArguments()[0];

  const declarationsProp = moduleArguments.getDescendants()
    .find(d => d.getKind() === SyntaxKind.PropertyAssignment &&
        (d.compilerNode as ts.PropertyAssignment).name.getText() === "imports");

  const array = declarationsProp.getFirstChildByKindOrThrow(SyntaxKind.ArrayLiteralExpression);
  array.addElement("newImportGoesHere");

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Dharman
Solution 2 Charlie-Greenman