mswjs / data

Data modeling and relation library for testing JavaScript applications.

Home Page:https://npm.im/@mswjs/data

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Support relations when generating REST handlers

kettanaito opened this issue · comments

GitHub

  • Follow up #12

What

Given the following model declarations:

const db = factory({
  user: {
    id: primaryKey(String),
    posts: manyOf('post')
  },
  post: {
    slug: primaryKey(String)
  }
})

And called db.user.toHandlers, the following relation handlers must be created in addition to the default CRUD handlers:

  • GET /users/:id/posts, returns all posts that belong to the user.
  • GET /users/:id/posts/:slug, returns a post by a slug that belongs to the user.

I'd say that PUT and DELETE methods shouldn't be nested in this way, forcing you to update/delete a post instance directly (i.e. PUT /posts/:slug).

Questions

  • Should oneOf relations pluralize the model name in the handler URL?

I think that for oneOf relations is good to have a singular noun. It makes the url self explanatory

Makes perfect sense, @marcosvega91!

The task is focused around the generateRestHandlers function, specifically, where the request handlers are generated:

return [
rest.get(
buildUrl(modelPath),
withErrors<Entity<Dictionary, ModelName>>((req, res, ctx) => {
const { skip, take, cursor, filters } = parseQueryParams(
modelName,
modelDefinition,
req.url.searchParams,
)
let options = { where: filters }
if (take || skip) {
options = Object.assign(options, { take, skip })
}
if (take || cursor) {
options = Object.assign(options, { take, cursor })
}
const records = model.findMany(options)
return res(ctx.json(records))
}),
),

We'd have to append additional handlers based on the model's relational properties (that should be available in the parsed model object). We need to watch out for circular model references when generating handlers:

factory({
  user: { id: primaryKey(String), friends: manyOf('user') }
})

// GET /user/:id/friends
// GET /user/:id/friends/:id
// GET /user/:id/friends/:id/friends/...

It'd be great to generate the handlers for the referenced models standalone, and reference them in the nested paths of the current model. This once again suggests that we need access to the entire dictionary when generating handlers for a single model (also an issue I've encountered when working on #110). This may be a great time to enable this by extending the arguments of the generateRestHandlers function to accept the dictionary object from the factory.

FYI: I'm working on this.