angulartypescriptgoogle-cloud-functionsangularfire2angular-signals

Returning a signal in Angular Fire Functions


I'm trying to integrate Angular 18 with Firebase Cloud Functions to read a MongoDB database. I'm using signals because I understand this is the latest way to do this, but I get a type error.

This is my index.js file:

exports.atlasWordObservable = functions.https.onCall((lemma) => {
  const query = { l: lemma };
  return mongodb.connect().then(() => {
    return collection.find(query).toArray();
  });
});

And then I try to call that function:

import { getFunctions, httpsCallable } from '@angular/fire/functions';

...

entrySingleArray$ = signal<Entry[]>([]);
functions = getFunctions();
atlasLemma = httpsCallable(this.functions, 'atlasWordObservable');
emptyEntry: Entry[] = [{ id: 0, alpha: 0, l: ''}];

getFireLemma(lemma?: string): Observable<Entry[]> {
  return (
    lemma
      ? from(this.atlasLemma({name: lemma}))
      : of(this.emptyEntry)
  ).pipe(
    tap((response) => {
      this.entrySingleArray$.set(response);
      console.log(this.entrySingleArray$());
    }),
  );
}

But the IDE gives me the error at the return line, saying:

Type 'Observable<HttpsCallableResult> | Observable<Entry[]>' is not assignable to type 'Observable<Entry[]>'.

I understand that my options are: either converting what the function returns from HttpsCallableResult<unknown> to Entry[] (I don't know how to do that), or getting the javascript code for the function to return the Entry[] type, which I believe is not possible, unless I change the code into TypeScript.

Any help will be appreciated.


Solution

  • You should cast the data from the HttpsCallableResult as an Entry[] type via the map RxJS operator.

    import { from, Observable, of, tap, map } from 'rxjs';
    
    getFireLemma(lemma?: string): Observable<Entry[]> {
      return (
        lemma
          ? from(this.atlasLemma({ name: lemma })).pipe(
              map((x: HttpsCallableResult<unknown>) => x.data as Entry[])
            )
          : of(this.emptyEntry)
      ).pipe(
        tap((response) => {
          this.entrySingleArray$.set(response);
          console.log(this.entrySingleArray$());
        })
      );
    }