nlf / mudskipper

a resourceful router plugin for hapi
15 stars 3 forks source link

design a generic hypermedia request obj #8

Closed joshua-mcginnis closed 10 years ago

joshua-mcginnis commented 10 years ago

hypermedia json

route: /users

{
  methods: ['get', 'post'],
  links: {
    up: { href: '/' },
    self: { href: '/users' },
    item: { href: '/users/{id}' } // template for how to fetch an object out of a collection
  },
  items: {} // since users is a collection and collections don't have children -yup!
}

route: /users/12

{
  methods: ['get', 'put', 'patch', 'delete'],
  links: {
    up: { href: '/users' },
    self: { href: '/users/12' },
    avatar: { href: '/somewhere/else.jpg' }
    external_foo: { href: 'http://foo.com/{some_field}' } //some_field is a field in the users payload
  },
  items: {
    articles: { href: '/users/12/articles', methods: [ 'get', 'post' ] }
  }
}

route: /phonesheets/123/calls

{
  methods: ['get', 'post'],
  links: {
    up: { href: '/phonesheets/123' },
    self: { href: '/phonesheets/123/calls' },
    item: { href: '/phonesheets/123/calls/{id}' }
  },
  items: {}
}

route: /phonesheets/123/calls/123

{
  methods: ['get', 'put', 'patch', 'delete'],
  links: {
    up: { href: '/phonesheets/123/calls' },
    self: { href: '/phonesheets/123/calls/123' }
  },
  items: {}
}

override example

{
  phonesheets: {
    hypermedia: { // maybe "links" instead?
      collection: {
        randomcollection: { href: '/bananas' }
      },
      item: {
        randomthing: { href: '/bananas/12' }
      }
    },
    index: {
      handler: function (request) {
        // do stuff
      }
    }
  }
}

use-cases we need to think through: api changes: route change etc

what other properties about a link might be we need, besides href? what should be generated automatically in mudskipper (for up, self, and item)?

we'll be using up, self as the rel values for collection+json and siren, they'll be the keys for hal.

what other properties can we reliably generate and repurpose?

things we need to figure out: curies templates queries

my understanding was that "links" was for things relating to the current object, and children is for things that are resource below the current object. so since avatar would be a direct relation to the user, and not a child object altogether, it would be a link (i.e. there's no "avatars" resource)

but up and self are going to end up in the same links obj within the top-level collection, alongside avatar, so im wondering if they should all go together

sure, we could move up and self to the links, i only had them separate because it seemed cleaner

i think it is safe to assume that links will always contain an up and self, and for root, up will just be the same as self

I'm alittle curious about the links.item being a template. shouldnt all these links be hydrated and ready to go? the alternative is that the hypermedia object has to be aware of what the item ids all are, and populate them so you would end up with "items" instead of "item" and it would be an array like [ "/users/1", "/users/2", "/users/3" ] I think then were splitting off the standard. what else would we put for "item" ? you would link to items. So there would be no item/2 in the links. that requires mudskipper to have knowledge as to what items are available, which it doesn't. could leave it blank and let the request handler fill it in.. yea, i'm checking out the standard right quick.

I'm totally sorry nlf, I thought you were writing json fro the collection+json spec. This is all mudskipper defs. my bad. sorry fot he noise. no worries :) just trying to figure out how to expose all the information so it can be leveraged to create real collection+json/siren/whatever output got it. I was thinking man thats some wacky looking collection+json lol. wacky is what i do.

nlf commented 10 years ago

as part of this, I'll also be implementing the ability to have a special "root" resource with a default path of "/"

this resource will only support one method - a GET request to /

hypermedia generated for it will have each top level resource listed in the "links" property

joshua-mcginnis commented 10 years ago

@nlf designate a resource (root) to return a list of top-level links to all other top-level resources.

joshua-mcginnis commented 10 years ago

Also, links in the above examples should probably be an array of objs instead of nested obj, I think.

nlf commented 10 years ago

hrm, i was thinking a nested object so it's simpler to merge and find specific links (i.e. request.context.hypermedia.links.up)

joshua-mcginnis commented 10 years ago

I don't think we would/should be referring to a specific link in the formatters, just looping through them and adding them to the response obj in the right format on the fly.

Sent from my iPhone

On Dec 6, 2013, at 5:14 PM, "Nathan LaFreniere" notifications@github.com<mailto:notifications@github.com> wrote:

hrm, i was thinking a nested object so it's simpler to merge and find specific links (i.e. request.context.hypermedia.links.up)

— Reply to this email directly or view it on GitHubhttps://github.com/nlf/mudskipper/issues/8#issuecomment-30043458.


This e-mail and any files transmitted with it are intended solely for the use of the individual or entity to whom they are addressed. If the reader of this e-mail is not the intended recipient or the employee or agent responsible for delivering the message to the intended recipient, you are hereby notified that any use dissemination, forwarding, printing or copying of this e-mail is strictly prohibited. If you have received this e-mail in error, please e-mail us at caasecurity@caa.com or call 424-288-2000.

nlf commented 10 years ago

added special "root" resource that defaults path to / note that for this resource you do not specify methods, as only one method is available and it's a GET request

added auto generation of hypermedia to all routes note that i did change links and items to be an array of objects rather than nested objects, such as

links: [{ name: 'self', href: '/articles' }, { name: 'up', href: '/' }]

still working on figuring out overrides. the trick here is since i add them to route context as an array, how would you specify overrides? do i make you specify it as an object and i convert it to an array? do i make you specify it as an array similar to the above and iterate over what i have checking the "name" field for self, up, and item?

joshua-mcginnis commented 10 years ago

@nlf After thinking about it, I think you're right in that an obj for links would be best. An array makes logical sense in my mind since links is a collection of sorts, but that is negated by the fact it that makes it more difficult to do the merge/overrides. Also, for all of the specs, we will need to pick off the self link directly so it also makes that easier.