realm / realm-js

Realm is a mobile database: an alternative to SQLite & key-value stores
https://realm.io
Apache License 2.0
5.67k stars 561 forks source link

Babel plugin does not cover all type-infer situations #5111

Open XHMM opened 1 year ago

XHMM commented 1 year ago

How frequently does the bug occur?

All the time

Description

Demo code when working with @realm/babel-plugin@0.1.0 and realm@11.1.0 :

import Realm from "realm";

export class NoteSchema extends Realm.Object<NoteSchema, "content"> {
  // @ts-ignore
  static name = "MyNote"
  _id = new Realm.BSON.ObjectId()
  createdAt = Date.now()
  content!: string
}

After babel transformation, createdAt was missed in schema:

NoteSchema.schema = {
    name: "NoteSchema",
    properties: {
      _id: {
        type: "objectId",
        default: function _default() {
          return new _realm.default.BSON.ObjectId();
        }
      },
      content: {
        type: "string"
      }
    },
    name: "MyNote"
  };

Stacktrace & log output

No response

Can you reproduce the bug?

Yes, always

Reproduction Steps

No response

Version

@realm/babel-plugin@0.1.0 and realm@11.1.0

What SDK flavour are you using?

Local Database only

Are you using encryption?

No, not using encryption

Platform OS and version(s)

it's just a js side issue

Build environment

No response

Cocoapods version

No response

kneth commented 1 year ago

@XHMM Thank you for reporting. Do you also observe it if you only have one function (yeah, I am mentally debugging already)?

XHMM commented 1 year ago

Did you mean this code?

export class NoteSchema extends Realm.Object<NoteSchema> {
  createdAt = Date.now()
}

The above code still does not work, and the console logged "transform[stderr]: Unable to determine type of 'createdAt' property"

kneth commented 1 year ago

Date.now() returns a number (milliseconds after epoc) while new Date() returns a Date object as we expect. You should try to use new Date() instead.

XHMM commented 1 year ago

You're right, but here what I want is to store the timestamp(number) but not date. (sorry for the field name mislead you)

Also I tried write createdAt = new Date() and babel transformation was right, but createdAt = Date.now() didn't transform correctly as the issue showed, what I expect should be:

createdAt: {
  type: "int", 
  default: function _default() {
    return Date.now();
  }
}
takameyer commented 1 year ago

Hi all, I've been updating some of our templates to use the new babel plugin and I also ran into this issue. The solution is to explicitly declare the types in your class and not infer them. The babel plugin doesn't seem to be able to retrieve the inferred type (perhaps we can improve this somehow).

export class NoteSchema extends Realm.Object<NoteSchema, "content"> {
  // @ts-ignore
  static name = "MyNote"
  _id: Realm.BSON.ObjectId = new Realm.BSON.ObjectId()  // Set Realm.BSON.ObjectId explicitly
  createdAt: Realm.Types.Int = Date.now() // Set to Int explicitly
  content!: string
}

Let us know if that helps!

kneth commented 1 year ago

The babel plugin doesn't seem to be able to retrieve the inferred type (perhaps we can improve this somehow)

I leave the issue open, and we can return to it for a future improvement.

XHMM commented 1 year ago

Hi all, I've been updating some of our templates to use the new babel plugin and I also ran into this issue. The solution is to explicitly declare the types in your class and not infer them. The babel plugin doesn't seem to be able to retrieve the inferred type (perhaps we can improve this somehow).

export class NoteSchema extends Realm.Object<NoteSchema, "content"> {
  // @ts-ignore
  static name = "MyNote"
  _id: Realm.BSON.ObjectId = new Realm.BSON.ObjectId()  // Set Realm.BSON.ObjectId explicitly
  createdAt: Realm.Types.Int = Date.now() // Set to Int explicitly
  content!: string
}

Let us know if that helps!

Yes this way works, and waiting for a fix so we can fully leverage typescript types without worry😊