0

How can I share Firestore collection path and model type mapping between TypeScript Firebase SDK and Firebase Admin SDK?

Example

Following code works, but it does not share collection path and model type mapping like { "courses": Course, "sections": Section }.

types.ts

export interface Course {
  id: string;
}

export interface Section {
  id: string;
}

collectionPath.ts

export const collectionPaths = {
  courses: "courses",
  sections: "sections",
};

orm.ts

import {
  collection,
  Firestore,
  FirestoreDataConverter,
  PartialWithFieldValue,
  QueryDocumentSnapshot,
  DocumentData,
} from "firebase/firestore";
import { collectionPaths } from "./collectionPaths";
import { Course, Section } from "./types";

const converter = <T>(): FirestoreDataConverter<T> => ({
  toFirestore: (data: PartialWithFieldValue<T>) => data as DocumentData,
  fromFirestore: (snap: QueryDocumentSnapshot) => snap.data() as T,
});

export const admin = (firestore: Firestore) => {
  const dataPoint = <T>(collectionPath: string) =>
    collection(firestore, collectionPath).withConverter(converter<T>());

  return {
    couses: dataPoint<Course>(collectionPaths.courses),
    sections: dataPoint<Section>(collectionPaths.sections),
  };
};

adminOrm.ts

import { firestore } from "firebase-admin";
import {
  FirestoreDataConverter,
  WithFieldValue,
  QueryDocumentSnapshot,
  DocumentData,
} from "firebase-admin/firestore";
import { collectionPaths } from "./collectionPaths";
import { Course, Section } from "./types";

const converter = <T>(): FirestoreDataConverter<T> => ({
  toFirestore: (data: WithFieldValue<T>) => data as DocumentData,
  fromFirestore: (snap: QueryDocumentSnapshot) => snap.data() as T,
});

export const adminOrm = (firestore: firestore.Firestore) => {
  const dataPoint = <T>(collectionPath: string) =>
    firestore.collection(collectionPath).withConverter(converter<T>());

  return {
    couses: dataPoint<Course>(collectionPaths.courses),
    sections: dataPoint<Section>(collectionPaths.sections),
  };
};

What I've tried

I've tried following code, but it loses ModelType for CollectionReference<ModelType>.

collectionPaths.ts

import { Course, Section } from "./types";

export class CollectionPath<T> {
  path: string;

  constructor(path: string) {
    this.path = path;
  }
}

export const collectionPaths = {
  courses: new CollectionPath<Course>("courses"),
  sections: new CollectionPath<Section>("sections"),
};

adminOrm.ts

import { firestore } from "firebase-admin";
import {
  FirestoreDataConverter,
  WithFieldValue,
  QueryDocumentSnapshot,
  DocumentData,
  CollectionReference,
} from "firebase-admin/firestore";
import { collectionPaths } from "./collectionPaths";

const converter = <T>(): FirestoreDataConverter<T> => ({
  toFirestore: (data: WithFieldValue<T>) => data as DocumentData,
  fromFirestore: (snap: QueryDocumentSnapshot) => snap.data() as T,
});

export const adminOrm = (firestore: firestore.Firestore) => {
  const dataPoint = <T>(collectionPath: string) =>
    firestore.collection(collectionPath).withConverter(converter<T>());

  return <{ [key in keyof typeof collectionPaths]: CollectionReference }>(
    Object.entries(collectionPaths).reduce(
      (p, [k, v]) => Object.assign(p, { [k]: dataPoint(v.path) }),
      {}
    )
  );
};
4

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.