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

Support relations when generating REST handlers #56

Open
kettanaito opened this issue Apr 7, 2021 · 4 comments
Open

Support relations when generating REST handlers #56

kettanaito opened this issue Apr 7, 2021 · 4 comments
Assignees
Labels
api:rest feature New feature or request

Comments

@kettanaito
Copy link
Member

kettanaito commented Apr 7, 2021

GitHub

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?
@marcosvega91
Copy link
Member

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

@kettanaito
Copy link
Member Author

Makes perfect sense, @marcosvega91!

@kettanaito
Copy link
Member Author

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.

@ruisaraiva19
Copy link
Contributor

FYI: I'm working on this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
api:rest feature New feature or request
Projects
None yet
Development

No branches or pull requests

3 participants