mswjs / data

Data modeling and relation library for testing JavaScript applications.
https://npm.im/@mswjs/data
MIT License
822 stars 52 forks source link

Library's state and future #285

Open kettanaito opened 1 year ago

kettanaito commented 1 year ago

Hello, folks. I think an update is due regarding this library's status and future.

I've been in the progress of rewriting Data for some time now, and it's going to be a full rewrite ground-up. On the bright side, it will fix a bunch of issues and bring in a long-awaited functionality, like type-safe models, static models, more powerful relationships (incl. polymorphic ones), and so forth. The downside is that this kind of rewrite takes time.

I consider the current version of Data to be in maintenance mode. I will do my best to review and merge critical fixes but I won't be accepting new features as you must have noticed in the pending queue of pull requests. This is the best strategy for this library to evolve and also for me to keep its maintenance sensible. Thanks for understanding.

themagickoala commented 1 year ago

Hi @kettanaito, are you working on this rewrite independently? I'm sure there would be plenty of people willing to help if you want to open-source the process!

kettanaito commented 1 year ago

@themagickoala, I plan to open the pull request eventually so others can join the effort! I didn't go that route initially because it was a full rewrite from scratch in an empty repo. That's how my mind performs best sometimes. Once I'm at a stable point, I want to open a pull request here but it will be a complete rug-pull: old code deleted, new code taking its place. This isn't incremental really but I'm doing my best to find the way to develop the software in my free time.

themagickoala commented 1 year ago

Sounds great, looking forward to the PR!

kettanaito commented 11 months ago

I hope to spend some time on Data at the beginning of next year. I'm quite busy until the end of this year but if I get a chance, I will publish the V2 WIP as a pull request here.

kettanaito commented 10 months ago

I think I've finally refined the modeling API to adopt in 2.0. It will look something like this:

class User extends Model {
  // Identifiers.
  @id id = uuid()

  // Plain properties with default value.
  name = 'John'

  // Foreign keys.
  @foreignKey(Comment)
  commentIds: ForeignKey<Comment>[]

  // Relationships over foreign keys.
  @manyOf(Comment, { by: 'commentIds' }
  comments: Comment[]
}

class Comment extends Model {
  @id id = uuid()
  text = 'Default comment text here'
}

Working to see whether this API will suit all the use cases. Looking good so far.

wyozi commented 9 months ago

Would be nice if creating custom handlers was easier in v2 as well. I'd like to work on a PostgREST handler, but effectively waiting for v2 for that

kettanaito commented 8 months ago

Update

The rewrite of Data is in a good state. There are a few design decisions to make regarding relationships in the context of using decorators, and I'm exploring possibilities there.

That being said, I'm not working on the rewrite at the moment. I spent a few weeks in January on it and since then I've been focusing on other things. I'm looking forward to coming back to Data later this year. I cannot give any ETAs because an unemployed engineer my working schedule is unpredictable.

Thanks for your patience.

Why don't you open source the rewrite so others can contribute?

Because I'd still have to supervise and review those contributions, for which I don't have time. It sucks to see great pull requests hanging there forever. This pressures me more than it pressures you to wait for the rewrite.

kettanaito commented 8 months ago

How can we help?

I'd appreciate a discussion around relationship definition. In particular, circular relationship definition:

These cannot be achieved by direct class references as one class will ultimately be referenced before it's defined, which is a no-op:

class User {
  @manyOf(Post)
  posts
}

class Post {
  @oneOf(User)
  author
}

What other tools do for this is make the class references lazy by wrapping them in a function:

class User {
  @manyOf(() => Post)
  posts
}

class Post {
  @oneOf(() => User)
  author
}

This delegates the reference to the runtime and this will resolve correctly.

What do you think about this syntax? What caveats do you see when using it?

SalahAdDin commented 8 months ago

Sounds great, looking forward to the PR!

It seems to be dead.

themagickoala commented 8 months ago

@kettanaito I think circular references are important to have. It's something we are missing in the current version. The lazy syntax feels a bit clumsy but I'm not sure I see a better option!

kettanaito commented 7 months ago

@themagickoala, the current version supports circular references because you reference models by name, not their value.

factory({
  user: {
    posts: manyOf('post')
  },
  post: {
    author: oneOf('user')
  }
})

The references to 'post' and 'user' are resolved on runtime, making such a circular dependency possible.

With the new syntax, I'd much rather you pointed to a model's class, which allows us to infer more things from it (such as its primary key to provide in the relationship). I agree, it seems the lazy reference is the only way to do this in JavaScript. I dislike the syntax as well.

Matt-McConway commented 7 months ago

How can we help?

I'd appreciate a discussion around relationship definition. In particular, circular relationship definition:

  • User.post -> manyOf(Post)
  • Post.author -> oneOf(User)

These cannot be achieved by direct class references as one class will ultimately be referenced before it's defined, which is a no-op:

class User {
  @manyOf(Post)
  posts
}

class Post {
  @oneOf(User)
  author
}

What other tools do for this is make the class references lazy by wrapping them in a function:

class User {
  @manyOf(() => Post)
  posts
}

class Post {
  @oneOf(() => User)
  author
}

This delegates the reference to the runtime and this will resolve correctly.

What do you think about this syntax? What caveats do you see when using it?

Pretty new to MSW but for what it's worth this seems like the best approach. Little weird syntax wise, but like you said the reference to the class itself is more valuable than the 'stringly' typed alternative

kettanaito commented 7 months ago

That lazy syntax is also how other tools in the genre solve the circular reference problem. TypeORM as an example.

patocallaghan commented 1 week ago

@kettanaito Just wondering if there's any update on the progress of the rewrite/new API? Is its progress being tracked separately somewhere?

kettanaito commented 1 week ago

@patocallaghan, hi. No, no meaningful updates so far. I wanted to squeeze this work alongside other tasks in MSW this year, but that didn't happen. That sucks.

I am still going back and forth on the API. Some things are easier to describe with classes. Others with functions. Combining both is confusing. Add the support for type-first models via type arguments, and you get yourself a complete mess of requirements tugging the library in opposite directions. I think right now people use this library for all sorts of things, and I need to start from deciding on what it is not, then what it is, and design the API from there.

I am studying and drawing a lot of inspiration from Eloquent ORM in Laravel. That helps. I have no nearly enough time to allocate to this project, sadly. This is a perfect opportunity for some company to step in and sponsor the rewrite. If anyone reading this works in such a company, reach me on Twitter, let's make this happen.