Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Document usage of JS Date object discouraged in Datastore #332

Open
peterpeterparker opened this issue Feb 26, 2025 · 0 comments
Open

Document usage of JS Date object discouraged in Datastore #332

peterpeterparker opened this issue Feb 26, 2025 · 0 comments
Labels
good first issue Good for newcomers

Comments

@peterpeterparker
Copy link
Contributor

peterpeterparker commented Feb 26, 2025

Motivation

Data saved in the datastore is stored as a Blob, which we stringify and parse on write and read. To handle types not natively supported by the APIs, such as BigInt or Principal, we use reviver and replacer functions.

Today, we discussed extending support for mapping dates.

const tmp = {date: new Date()};
const tmp1 = JSON.stringify(tmp);
console.log(JSON.parse(tmp1));
// { date: "2025-02-26T12:37:47.624Z" } <---- a string

Our original intention was to improve the functions to map those types, but unfortunately, when I started the implementation, I realized this wasn't a perfect solution because it would come with a performance cost. Indeed, in a JSON replacer, it isn't possible to detect if an unknown value is a date by checking first if it's an instanceof Date. This is because JavaScript already transforms dates before calling the replacer.

export const jsonReplacer = (_key: string, value: unknown): unknown => {
  if (typeof value === "bigint") {
    return { [JSON_KEY_BIGINT]: `${value}` };
  }

  if (nonNullish(value) && value instanceof Principal) {
    return { [JSON_KEY_PRINCIPAL]: value.toText() };
  }

  if (nonNullish(value) && value instanceof Uint8Array) {
    return { [JSON_KEY_UINT8ARRAY]: Array.from(value) };
  }

  const isValidDate = (value: unknown): value is Date =>  value instanceof Date && !isNaN(value.getTime());

  // ❌ Does not work
  // value is not a Date object but already a string. As for example `2023-11-14T22:13:20.000Z`.
  if (nonNullish(value) && isValidDate(value)) {
    return { [JSON_KEY_DATE]: value.getTime() };
  }

  return value;
};

Potentially, we could use a regex or even try to construct a Date object, but given that the replacer is recursive, doing so would have quite a performance impact.

That's why I stopped working on this and why I think it's best to add a note in the documentation to advise developers not to use the Date object in their data types.

Source

OC: https://oc.app/community/vxgpi-nqaaa-aaaar-ar4lq-cai/channel/321040078/391

Follow-up of #1283

What to do

In the documentation of the Datastore, either in an existing chapter, a new chapter, or even a new page—open to suggestion—add a note that it's advised not to use the Date object for the data of documents.

Provide a short explanation based on the reasons above.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
good first issue Good for newcomers
Projects
None yet
Development

No branches or pull requests

1 participant