Skip to content

Instantly share code, notes, and snippets.

@aslakknutsen
Last active September 28, 2017 08:52
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save aslakknutsen/990669608934dfcf080a611a7e8ae3a4 to your computer and use it in GitHub Desktop.
Save aslakknutsen/990669608934dfcf080a611a7e8ae3a4 to your computer and use it in GitHub Desktop.
JSON API ResourceObject GOA
// Definition
/*
func test() {
account := app.AccountSingle{}
account.Data.ID
account.Data.Type
account.Data.Attributes.Name
account.Data.Relationships.OwnedBy
account.Data.Relationships.OwnedBy.Meta
account.Data.Relationships.OwnedBy.Related
account.Data.Relationships.OwnedBy.Self
account.Links.Self
account.Meta
account.Included
}
*/
var account = ResourceObject(
"Account",
"Account is the representation of the owning entity of a Space. Account could be owned by either a User or a Org.",
ResourceObjectData("AccountData", func() {
a.Attribute("name", d.String)
}, "owned-by"),
"self")
var _ = ResourceObject(
"Organization",
"Organization is the representation of the owning entity of a Space",
ResourceObjectData("Organization", func() {
a.Attribute("name", d.String)
}, "belongs-to", "paied-by"),
"self")
var _ = ResourceObjectEntrypoint(account, "create", "show", "update", "delete", "list")
// helpers
func ResourceObjectData(name string, attrs func(), relations ...string) *d.UserTypeDefinition {
return a.Type(name, func() {
a.Attribute("type", d.String)
a.Attribute("id", d.String, "UUID of the object", func() {
a.Example("6c5610be-30b2-4880-9fec-81e4f8e4fd76")
})
a.Attribute("attributes", attrs)
if relations != nil {
a.Attribute("relationships", func() {
for _, link := range relations {
a.Attribute(link, resourceLink)
}
})
}
})
}
func ResourceObject(name, description string, data *d.UserTypeDefinition, links ...string) *d.MediaTypeDefinition {
return a.MediaType("application/vnd."+strings.ToLower(name)+"+json", func() {
a.UseTrait("jsonapi-media-type")
a.TypeName(name + "Single")
a.Description(description)
if links != nil {
a.Attribute("links", func() {
for _, link := range links {
a.Attribute(link, resourceLink)
}
})
}
a.Attribute("data", data)
a.Attribute("meta", a.HashOf(d.String, d.Any))
a.Attribute("included", a.ArrayOf(d.Any), "An array of mixed types")
a.Required("data")
a.View("default", func() {
if links != nil {
a.Attribute("links")
}
a.Attribute("data")
a.Attribute("included")
a.Attribute("meta")
a.Required("data")
})
})
}
func ResourceObjectEntrypoint(media *d.MediaTypeDefinition, actions ...string) *d.ResourceDefinition {
name := strings.Replace(strings.ToLower(media.TypeName), "single", "", -1)
return a.Resource(name, func() {
fmt.Println(name)
a.BasePath("/" + name)
for _, action := range actions {
switch action {
case "show":
a.Action("show", func() {
a.Routing(
a.GET("/:" + name + "ID"),
)
a.Description("Retrieve " + name + " (as JSONAPI) for the given ID.")
a.Params(func() {
a.Param(name+"ID", d.UUID, "ID of the "+name)
})
a.UseTrait("conditional")
a.Response(d.OK, media)
a.Response(d.NotModified)
a.Response(d.BadRequest, JSONAPIErrors)
a.Response(d.InternalServerError, JSONAPIErrors)
a.Response(d.NotFound, JSONAPIErrors)
})
case "list":
a.Action("list", func() {
a.Security("jwt")
a.Routing(
a.GET(""),
)
a.Description("List " + name + "s.")
a.Params(func() {
a.Param("page[offset]", d.String, "Paging start position")
a.Param("page[limit]", d.Integer, "Paging size")
})
a.UseTrait("conditional")
a.Response(d.OK, media)
a.Response(d.NotModified)
a.Response(d.BadRequest, JSONAPIErrors)
a.Response(d.InternalServerError, JSONAPIErrors)
a.Response(d.Unauthorized, JSONAPIErrors)
})
case "create":
a.Action("create", func() {
a.Security("jwt")
a.Routing(
a.POST(""),
)
a.Description("Create a " + name)
a.Payload(media)
a.Response(d.Created, "/"+name+"s/.*", func() {
a.Media(media)
})
a.Response(d.BadRequest, JSONAPIErrors)
a.Response(d.InternalServerError, JSONAPIErrors)
a.Response(d.Unauthorized, JSONAPIErrors)
a.Response(d.Conflict, JSONAPIErrors)
})
case "update":
a.Action("delete", func() {
a.Security("jwt")
a.Routing(
a.DELETE("/:" + name + "ID"),
)
a.Description("Delete a " + name + " with the given ID.")
a.Params(func() {
a.Param(name+"ID", d.UUID, "ID of the "+name+" to delete")
})
a.Response(d.OK)
a.Response(d.BadRequest, JSONAPIErrors)
a.Response(d.InternalServerError, JSONAPIErrors)
a.Response(d.NotFound, JSONAPIErrors)
a.Response(d.Unauthorized, JSONAPIErrors)
a.Response(d.Forbidden, JSONAPIErrors)
})
case "delete":
a.Action("update", func() {
a.Security("jwt")
a.Routing(
a.PATCH("/:" + name + "ID"),
)
a.Description("Update the " + name + " with the given ID.")
a.Params(func() {
a.Param(name+"ID", d.UUID, "ID of the "+name+" to update")
})
a.Payload(media)
a.Response(d.OK, func() {
a.Media(media)
})
a.Response(d.BadRequest, JSONAPIErrors)
a.Response(d.Conflict, JSONAPIErrors)
a.Response(d.InternalServerError, JSONAPIErrors)
a.Response(d.NotFound, JSONAPIErrors)
a.Response(d.Unauthorized, JSONAPIErrors)
a.Response(d.Forbidden, JSONAPIErrors)
})
}
}
})
}
var resourceLink = a.Type("ResourceLink", func() {
a.Attribute("self", d.String)
a.Attribute("related", d.String)
a.Attribute("meta", a.HashOf(d.String, d.Any))
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment