export function addToNgModule()

in src/schematics/utils.ts [180:314]


export function addToNgModule(host: Tree, options: { sourcePath: string, features: FEATURES[]}) {

  const modulePath = `/${options.sourcePath}/app/app.module.ts`;

  if (!host.exists(modulePath)) {
    throw new Error(`Specified module path ${modulePath} does not exist`);
  }

  const text = host.read(modulePath);
  if (text === null) {
    throw new SchematicsException(`File ${modulePath} does not exist.`);
  }
  const sourceText = text.toString('utf-8');

  const source = ts.createSourceFile(
    modulePath,
    sourceText,
    ts.ScriptTarget.Latest,
    true
  );

  const environmentsPath = buildRelativePath(
    modulePath,
    `/${options.sourcePath}/environments/environment`
  );

  const changes: Array<Change> = [];

  if (!findNode(source, ts.SyntaxKind.Identifier, 'provideFirebaseApp')) {
    changes.push(
      insertImport(source, modulePath, ['initializeApp', 'provideFirebaseApp'] as any, '@angular/fire/app'),
      insertImport(source, modulePath, 'environment', environmentsPath),
      ...addImportToModule(source, modulePath, `provideFirebaseApp(() => initializeApp(environment.firebase))`, null as any),
    );
  }

  if (
    options.features.includes(FEATURES.Analytics) &&
    !findNode(source, ts.SyntaxKind.Identifier, 'provideAnalytics')
  ) {
    changes.push(
      insertImport(source, modulePath, ['provideAnalytics', 'getAnalytics', 'ScreenTrackingService', 'UserTrackingService'] as any, '@angular/fire/analytics'),
      ...addImportToModule(source, modulePath, `provideAnalytics(() => getAnalytics())`, null as any),
      ...addProviderToModule(source, modulePath, ['ScreenTrackingService', 'UserTrackingService'] as any, null as any),
    );
  }

  if (
    options.features.includes(FEATURES.Authentication) &&
    !findNode(source, ts.SyntaxKind.Identifier, 'provideAuth')
  ) {
    changes.push(
      insertImport(source, modulePath, ['provideAuth', 'getAuth'] as any, '@angular/fire/auth'),
      ...addImportToModule(source, modulePath, `provideAuth(() => getAuth())`, null as any),
    );
  }

  if (
    options.features.includes(FEATURES.Database) &&
    !findNode(source, ts.SyntaxKind.Identifier, 'provideDatabase')
  ) {
    changes.push(
      insertImport(source, modulePath, ['provideDatabase', 'getDatabase'] as any, '@angular/fire/database'),
      ...addImportToModule(source, modulePath, `provideDatabase(() => getDatabase())`, null as any),
    );
  }

  if (
    options.features.includes(FEATURES.Firestore) &&
    !findNode(source, ts.SyntaxKind.Identifier, 'provideFirestore')
  ) {
    changes.push(
      insertImport(source, modulePath, ['provideFirestore', 'getFirestore'] as any, '@angular/fire/firestore'),
      ...addImportToModule(source, modulePath, `provideFirestore(() => getFirestore())`, null as any),
    );
  }

  if (
    options.features.includes(FEATURES.Functions) &&
    !findNode(source, ts.SyntaxKind.Identifier, 'provideFunctions')
  ) {
    changes.push(
      insertImport(source, modulePath, ['provideFunctions', 'getFunctions'] as any, '@angular/fire/functions'),
      ...addImportToModule(source, modulePath, `provideFunctions(() => getFunctions())`, null as any),
    );
  }

  if (
    options.features.includes(FEATURES.Messaging) &&
    !findNode(source, ts.SyntaxKind.Identifier, 'provideMessaging')
  ) {
    // TODO add the service worker
    changes.push(
      insertImport(source, modulePath, ['provideMessaging', 'getMessaging'] as any, '@angular/fire/messaging'),
      ...addImportToModule(source, modulePath, `provideMessaging(() => getMessaging())`, null as any),
    );
  }

  if (
    options.features.includes(FEATURES.Performance) &&
    !findNode(source, ts.SyntaxKind.Identifier, 'providePerformance')
  ) {
    // TODO performance monitor service
    changes.push(
      insertImport(source, modulePath, ['providePerformance', 'getPerformance'] as any, '@angular/fire/performance'),
      ...addImportToModule(source, modulePath, `providePerformance(() => getPerformance())`, null as any),
    );
  }

  if (
    options.features.includes(FEATURES.RemoteConfig) &&
    !findNode(source, ts.SyntaxKind.Identifier, 'provideRemoteConfig')
  ) {
    changes.push(
      insertImport(source, modulePath, ['provideRemoteConfig', 'getRemoteConfig'] as any, '@angular/fire/remote-config'),
      ...addImportToModule(source, modulePath, `provideRemoteConfig(() => getRemoteConfig())`, null as any),
    );
  }

  if (
    options.features.includes(FEATURES.Storage) &&
    !findNode(source, ts.SyntaxKind.Identifier, 'provideStorage')
  ) {
    changes.push(
      insertImport(source, modulePath, ['provideStorage', 'getStorage'] as any, '@angular/fire/storage'),
      ...addImportToModule(source, modulePath, `provideStorage(() => getStorage())`, null as any),
    );
  }

  const recorder = host.beginUpdate(modulePath);
  applyToUpdateRecorder(recorder, changes);
  host.commitUpdate(recorder);

  return host;
}