mswjs / data

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

Support for typing nested Arrays #174

Open roertbb opened 2 years ago

roertbb commented 2 years ago

Currently, there is a possibility to define some model property to be an Array (if I got it correctly, it was introduced in #113). Example use of it can be found in #169 and it can look like that

const db = factory({
  user: {
    id: primaryKey(datatype.uuid),
    notes: Array,
  },
});

const user = db.user.create({
  id: 'abc-123',
  notes: [
    {
      key: '001',
      value: 'Buy groceries',
    },
    {
      key: '002',
      value: 'Call grandpa on Friday',
    },
  ],
});

Recently, in a project I'm working on, we used that feature to model some nested properties of one of the models. What we were missing is the possibility to provide types for the objects included in an array.

Let's consider a case of some notification model. It has an primary key id and the second property is some array of objects and it could be typed as follows:

type NotificationData = { type: 'email'; address: string } | { type: 'slack'; channel: string };

type Notification = {
  id: string;
  notificationsData: NotificationData[];
};

The Array can be used to to define that property of a model, but there is no limitation in terms of types of the array elements.

const db = factory({
  notification: {
    id: primaryKey(datatype.uuid),
    notificationsData: Array,
  },
});

const notification = db.user.create({
  id: 'some-notification',
  notificationsData: [
    {
      type: 'email',
      address: 'test@example.com',
    },
    {
      type: 'slack',
      channel: 'some-slack-channel',
    },
    {
      key: "value"
    },
    "some-text",
    123
  ],
});

I'm aware that for some cases, defining another model and using manyOf relation could be used, however there may be other ones, that the objects defined in an array cannot be resources on it's own (they are some more complex data than primitive value, but there is no field that can be used as primaryKey and it does not make sense for them to exist on its own).

I checked other issues / PRs and couldn't find anything covering that use-case, that's why I decided to submit an issue, but maybe I missed something or there are some workarounds I'm not aware of? I feel like it could be a valid use case - I'm wondering what's your opinion on that and if you consider it as a valid addition to the library to handle such cases.

roertbb commented 2 years ago

I tried to dive in a little bit in the code and I was wondering if extending the ModelValueType to include an array of... objects including only primitive types could do the trick.

I figured out some working solution in https://github.com/roertbb/data/commit/2e206a86965d62afaf6b55d1d1eb143a095b5530, that's leveraging the type inference from the init function for given property, but I'm not entirely sure about the API or continuing with the work in other places :wink:

asherccohen commented 2 years ago

Hi, I'm super interested in this same case. We have large nested arrays in some of our resources and having to use manyOf for something that is not a resource feels unintuitive and doesn't reflect the reality of the db.

An n example is that if we use manyOf, it means we can technically query by that collection, which shouldn't be accessible on its own.

Any thoughts?

kettanaito commented 2 years ago

I agree that using a manyOf relationship for non-relational properties is off semantically. It's a dirty hack. I've been working on a full rewrite of the library before I took some time off open source. I may come back to that. Perhaps I'll tackle better support for arrays there.

asherccohen commented 2 years ago

That's cool, your work is much appreciated.

The library has a lot of potential, we use it to maintain complex mocks that allow our apps to be developed offline as well as showcase features that don't have a backend yet.

I'm also in touch with @zoubingwu maintainer of msw-auto-mock to potentially auto-generate models from openapi specs and integrate mocks with faker.

Let's stay tuned!

kettanaito commented 2 years ago

Thank you for your kind words. I'm always happy to hear when my projects help someone. I took on this rewrite rather silently and I think that's how I will continue with it. I can't give any estimated but I'd love to finish it by the end of the year.

Please, if you use my projects to build yours, consider supporting MSW on GitHub. I'd like to build more great things around it but I won't be doing that in my personal time anymore. Thanks for considering that.

tarun9927 commented 1 year ago

is support for Enum[] available? if yes - can someone share an example? if no - what are the alternatives?