github.com/goldeneggg/goa@v1.3.1/design/apidsl/resource.go (about)

     1  package apidsl
     2  
     3  import (
     4  	"github.com/goadesign/goa/design"
     5  	"github.com/goadesign/goa/dslengine"
     6  )
     7  
     8  // Resource implements the resource definition dsl. There is one resource definition per resource
     9  // exposed by the API. The resource dsl allows setting the resource default media type. This media
    10  // type is used to render the response body of actions that return the OK response (unless the
    11  // action overrides the default). The default media type also sets the properties of the request
    12  // payload attributes with the same name. See DefaultMedia.
    13  //
    14  // The resource dsl also allows listing the supported resource collection and resource collection
    15  // item actions. Each action corresponds to a specific API endpoint. See Action.
    16  //
    17  // The resource dsl can also specify a parent resource. Parent resources have two effects.
    18  // First, they set the prefix of all resource action paths to the parent resource href. Note that
    19  // actions can override the path using an absolute path (that is a path starting with "//").
    20  // Second, goa uses the parent resource href coupled with the resource BasePath if any to build
    21  // hrefs to the resource collection or resource collection items. By default goa uses the show
    22  // action if present to compute a resource href (basically concatenating the parent resource href
    23  // with the base path and show action path). The resource definition may specify a canonical action
    24  // via CanonicalActionName to override that default. Here is an example of a resource definition:
    25  //
    26  //	Resource("bottle", func() {
    27  //		Description("A wine bottle")	// Resource description
    28  //		DefaultMedia(BottleMedia)	// Resource default media type
    29  //		BasePath("/bottles")		// Common resource action path prefix if not ""
    30  //		Parent("account")		// Name of parent resource if any
    31  //		CanonicalActionName("get")	// Name of action that returns canonical representation if not "show"
    32  //		UseTrait("Authenticated")	// Included trait if any, can appear more than once
    33  //
    34  //		Origin("http://swagger.goa.design", func() { // Define CORS policy, may be prefixed with "*" wildcard
    35  //			Headers("X-Shared-Secret")           // One or more authorized headers, use "*" to authorize all
    36  //			Methods("GET", "POST")               // One or more authorized HTTP methods
    37  //			Expose("X-Time")                     // One or more headers exposed to clients
    38  //			MaxAge(600)                          // How long to cache a prefligh request response
    39  //			Credentials()                        // Sets Access-Control-Allow-Credentials header
    40  //		})
    41  //
    42  //		Response(Unauthorized, ErrorMedia) // Common responses to all actions
    43  //		Response(BadRequest, ErrorMedia)
    44  //
    45  //		Action("show", func() {		// Action definition, can appear more than once
    46  //			// ... Action dsl
    47  //		})
    48  //	})
    49  func Resource(name string, dsl func()) *design.ResourceDefinition {
    50  	if design.Design.Resources == nil {
    51  		design.Design.Resources = make(map[string]*design.ResourceDefinition)
    52  	}
    53  	if !dslengine.IsTopLevelDefinition() {
    54  		dslengine.IncompatibleDSL()
    55  		return nil
    56  	}
    57  
    58  	if _, ok := design.Design.Resources[name]; ok {
    59  		dslengine.ReportError("resource %#v is defined twice", name)
    60  		return nil
    61  	}
    62  	resource := design.NewResourceDefinition(name, dsl)
    63  	design.Design.Resources[name] = resource
    64  	return resource
    65  }
    66  
    67  // DefaultMedia sets a resource default media type by identifier or by reference using a value
    68  // returned by MediaType:
    69  //
    70  //	var _ = Resource("bottle", func() {
    71  //		DefaultMedia(BottleMedia)
    72  //		// ...
    73  //	})
    74  //
    75  //	var _ = Resource("region", func() {
    76  //		DefaultMedia("vnd.goa.region")
    77  //		// ...
    78  //	})
    79  //
    80  // The default media type is used to build OK response definitions when no specific media type is
    81  // given in the Response function call. The default media type is also used to set the default
    82  // properties of attributes listed in action payloads and params. So if a media type defines an
    83  // attribute "name" with associated validations then simply calling Attribute("name") inside a
    84  // request Payload or Param defines the attribute with the same type and validations.
    85  func DefaultMedia(val interface{}, viewName ...string) {
    86  	if r, ok := resourceDefinition(); ok {
    87  		if m, ok := val.(*design.MediaTypeDefinition); ok {
    88  			if m.UserTypeDefinition == nil {
    89  				dslengine.ReportError("invalid media type specification, media type is not initialized")
    90  			} else {
    91  				r.MediaType = m.Identifier
    92  				m.Resource = r
    93  			}
    94  		} else if identifier, ok := val.(string); ok {
    95  			r.MediaType = identifier
    96  		} else {
    97  			dslengine.ReportError("media type must be a string or a *design.MediaTypeDefinition, got %#v", val)
    98  			return
    99  		}
   100  		if len(viewName) == 1 {
   101  			r.DefaultViewName = viewName[0]
   102  		} else if len(viewName) > 1 {
   103  			dslengine.ReportError("too many arguments given to DefaultMedia")
   104  		}
   105  	}
   106  }
   107  
   108  // Parent sets the resource parent. The parent resource is used to compute the path to the resource
   109  // actions as well as resource collection item hrefs. See Resource.
   110  func Parent(p string) {
   111  	if r, ok := resourceDefinition(); ok {
   112  		r.ParentName = p
   113  	}
   114  }
   115  
   116  // CanonicalActionName sets the name of the action used to compute the resource collection and
   117  // resource collection items hrefs. See Resource.
   118  func CanonicalActionName(a string) {
   119  	if r, ok := resourceDefinition(); ok {
   120  		r.CanonicalActionName = a
   121  	}
   122  }