firecmsco / firecms

Awesome Firebase/Firestore-based CMS. The missing admin panel for your Firebase project!
https://firecms.co
Other
1.12k stars 184 forks source link

Allow FireCMS to accept Timestamp type #643

Closed KalebKloppe closed 1 month ago

KalebKloppe commented 3 months ago
Background

FireCMS uses the Javascript Date internally. The Date is converted to a Firestore Timestamp when saved in Firestore.

Issue

This conversion creates a mismatch between the FireCMS and frontend types. Having two different types for the same data complicates everything.

Example

In FireCMS, a user's dateJoined field is defined as a JavaScript Date:

type UserType = {
  dateJoined: Date
}

const collection = buildCollection<UserType>({
  name: "Users",
  fields: {
    dateJoined: {
      name: "Date Joined",
      dataType: "date"
    }
  }
});

In the frontend, however, the same data is expected to be a Firestore Timestamp:

import { Timestamp } from "firebase/firestore";  

type UserType = {
  dateJoined: Timestamp
}

const UserComponent = ({ user }: { user: UserType}) => (
  <div>Date Joined: {user.dateJoined.toDate().toDateString()}</div>
)

In my project both the Frontend and FireCMS use the same type definitions. There is a danger that the frontend could incorrectly expect a Date instead of a Firestore Timestamp.

Proposed Solution

Allow developers to type dates as a Timestamp, so their data is consistent.

import { UserType } from "@types"

const collection = buildCollection<UserType>({
  name: "Users",
  fields: {
    dateJoined: {
      name: "Date Joined",
      dataType: "timestamp"  //  saved as Timestamp, typed as Timestamp
    }
  }
});

// for backwards compatibility, developers could continue to use "date" as a dataType.
dateJoined: {
  name: "Date Joined",
  dataType: "date"
}
import { UserType } from "@types"

const UserComponent: = ({ user }: { user: UserType }) => (
    <div>Date Joined: {user.dateJoined.toDate().toDateString()}</div>
)

Types shared by frontend and FireCMS

import { Timestamp } from "firebase/firestore";  

export type UserType = {
  dateJoined: Timestamp
}

Addendum

Regardless of the ultimate decision on this issue, the documentation adds to the confusion and should be made more consistent and detailed:

It would be helpful to explain the internal conversion that FireCMS does here, and mention what type of data developers should expect Firebase to have stored.

Screenshot 2024-04-12 100750

fgatti675 commented 3 months ago

Hi Kaleb, thank you for your suggestion.

I am providing a little bit of context as of why this is tricky to implement in our side.

FireCMS is split into different packages. It's core it not related at all to Firebase, it is simply a set of JS and React components that include all the main functionality of the CMS. Because of that, all the code is related to JS only, so Dates are regular JS dates. This allows us to keep a good separation of concerns and have an agnostic core that can be used with different backends (we also have implementation for Firebase RTDB, and MongoDB, for example).

I understand your use case as to why you would like to reuse types between projects. I will try to give it some thought and see if we can come with a solution.

I will fix the doc inconsistencies though! Thank you

fgatti675 commented 1 month ago

Closing this for now, feel free to reach out if you need further assistance!