Exemple #1
0
func makeCodegenModel(name, pkg string, schema spec.Schema, specDoc *spec.Document) *genModel {
	receiver := "m"
	props := make(map[string]genModelProperty)
	for pn, p := range schema.Properties {
		var required bool
		for _, v := range schema.Required {
			if v == pn {
				required = true
				break
			}
		}
		props[swag.ToJSONName(pn)] = makeGenModelProperty(
			"\""+pn+"\"",
			swag.ToJSONName(pn),
			swag.ToGoName(pn),
			receiver,
			"i",
			receiver+"."+swag.ToGoName(pn),
			p,
			required)
	}
	for _, p := range schema.AllOf {
		if p.Ref.GetURL() != nil {
			tn := filepath.Base(p.Ref.GetURL().Fragment)
			p = specDoc.Spec().Definitions[tn]
		}
		mod := makeCodegenModel(name, pkg, p, specDoc)
		if mod != nil {
			for _, prop := range mod.Properties {
				props[prop.ParamName] = prop
			}
		}
	}

	var properties []genModelProperty
	var hasValidations bool
	for _, v := range props {
		if v.HasValidations {
			hasValidations = v.HasValidations
		}
		properties = append(properties, v)
	}

	return &genModel{
		Package:        filepath.Base(pkg),
		ClassName:      swag.ToGoName(name),
		Name:           swag.ToJSONName(name),
		ReceiverName:   receiver,
		Properties:     properties,
		Description:    schema.Description,
		DocString:      modelDocString(swag.ToGoName(name), schema.Description),
		HumanClassName: swag.ToHumanNameLower(swag.ToGoName(name)),
		HasValidations: hasValidations,
	}
}
Exemple #2
0
func makeCodegenParameter(receiver, modelsPkg string, param spec.Parameter) genParameter {
	var ctx sharedParam
	var child *genParameterItem

	if param.In == "body" {
		ctx = makeGenValidations(modelValidations(
			"\""+swag.ToJSONName(param.Name)+"\"",
			swag.ToJSONName(param.Name),
			swag.ToGoName(param.Name),
			"i",
			receiver+"."+swag.ToGoName(param.Name),
			modelsPkg,
			param.Required,
			*param.Schema))

	} else {
		ctx = makeGenValidations(paramValidations(receiver, param))
		thisItem := genParameterItem{}
		thisItem.sharedParam = ctx
		thisItem.ValueExpression = ctx.IndexVar + "c"
		thisItem.CollectionFormat = param.CollectionFormat
		thisItem.Converter = stringConverters[ctx.Type]
		thisItem.Location = param.In

		if param.Items != nil {
			it := makeCodegenParamItem(
				"fmt.Sprintf(\"%s.%v\", "+ctx.Path+", "+ctx.IndexVar+")",
				ctx.ParamName,
				ctx.PropertyName,
				ctx.IndexVar+"i",
				ctx.IndexVar+"c["+ctx.IndexVar+"]",
				thisItem,
				*param.Items,
			)
			child = &it
		}

	}

	return genParameter{
		sharedParam:      ctx,
		Description:      param.Description,
		ReceiverName:     receiver,
		IsQueryParam:     param.In == "query",
		IsBodyParam:      param.In == "body",
		IsHeaderParam:    param.In == "header",
		IsPathParam:      param.In == "path",
		IsFormParam:      param.In == "formData",
		IsFileParam:      param.Type == "file",
		CollectionFormat: param.CollectionFormat,
		Child:            child,
		Location:         param.In,
		Converter:        stringConverters[ctx.Type],
	}
}
Exemple #3
0
func typeForSchema(schema *spec.Schema, modelsPkg string) string {
	if schema == nil {
		return "interface{}"
	}
	if schema.Ref.GetURL() != nil {
		tn := swag.ToGoName(filepath.Base(schema.Ref.GetURL().Fragment))
		if modelsPkg != "" {
			return modelsPkg + "." + tn
		}
		return tn
	}
	if schema.Format != "" {
		if tpe, ok := typeMapping[strings.Replace(schema.Format, "-", "", -1)]; ok {
			return tpe
		}
	}
	if schema.Type.Contains("array") {
		return "[]" + typeForSchemaOrArray(schema.Items, modelsPkg)
	}
	if schema.Type.Contains("file") {
		return typeMapping["file"]
	}
	if schema.Type.Contains("number") {
		return typeMapping["number"]
	}
	if schema.Type.Contains("integer") {
		return typeMapping["integer"]
	}
	if schema.Type.Contains("boolean") {
		return typeMapping["boolean"]
	}
	if schema.Type.Contains("string") {
		return "string"
	}
	if schema.AdditionalProperties != nil && schema.AdditionalProperties.Schema != nil {
		return "map[string]" + typeForSchema(schema.AdditionalProperties.Schema, modelsPkg)
	}
	if schema.Type.Contains("object") || schema.Type.Contains("") || len(schema.Type) == 0 {
		return "map[string]interface{}"
	}
	return "interface{}"
}
Exemple #4
0
func paramValidations(receiver string, param spec.Parameter) commonValidations {
	accessor := swag.ToGoName(param.Name)
	paramName := swag.ToJSONName(param.Name)

	tpe := typeForParameter(param)
	_, isPrimitive := primitives[tpe]
	_, isCustomFormatter := customFormatters[tpe]

	return commonValidations{
		propertyDescriptor: propertyDescriptor{
			PropertyName:      accessor,
			ParamName:         paramName,
			ValueExpression:   fmt.Sprintf("%s.%s", receiver, accessor),
			IndexVar:          "i",
			Path:              "\"" + paramName + "\"",
			IsContainer:       param.Items != nil || tpe == "array",
			IsPrimitive:       isPrimitive,
			IsCustomFormatter: isCustomFormatter,
			IsMap:             strings.HasPrefix(tpe, "map"),
		},
		Required:         param.Required,
		Type:             tpe,
		Format:           param.Format,
		Items:            param.Items,
		Default:          param.Default,
		Maximum:          param.Maximum,
		ExclusiveMaximum: param.ExclusiveMaximum,
		Minimum:          param.Minimum,
		ExclusiveMinimum: param.ExclusiveMinimum,
		MaxLength:        param.MaxLength,
		MinLength:        param.MinLength,
		Pattern:          param.Pattern,
		MaxItems:         param.MaxItems,
		MinItems:         param.MinItems,
		UniqueItems:      param.UniqueItems,
		MultipleOf:       param.MultipleOf,
		Enum:             param.Enum,
	}
}
Exemple #5
0
// GenerateSupport generates the supporting files for an API
func GenerateSupport(name string, modelNames, operationIDs []string, includeUI bool, opts GenOpts) error {
	// Load the spec
	_, specDoc, err := loadSpec(opts.Spec)
	if err != nil {
		return err
	}

	models, mnc := make(map[string]spec.Schema), len(modelNames)
	for k, v := range specDoc.Spec().Definitions {
		for _, nm := range modelNames {
			if mnc == 0 || k == nm {
				models[k] = v
			}
		}
	}

	operations := make(map[string]spec.Operation)
	if len(modelNames) == 0 {
		for _, k := range specDoc.OperationIDs() {
			if op, ok := specDoc.OperationForName(k); ok {
				operations[k] = *op
			}
		}
	} else {
		for _, k := range specDoc.OperationIDs() {
			for _, nm := range operationIDs {
				if k == nm {
					if op, ok := specDoc.OperationForName(k); ok {
						operations[k] = *op
					}
				}
			}
		}
	}

	if name == "" {
		if specDoc.Spec().Info != nil && specDoc.Spec().Info.Title != "" {
			name = swag.ToGoName(specDoc.Spec().Info.Title)
		} else {
			name = "swagger"
		}
	}

	generator := appGenerator{
		Name:       name,
		SpecDoc:    specDoc,
		Models:     models,
		Operations: operations,
		Target:     opts.Target,
		// Package:       filepath.Base(opts.Target),
		DumpData:      opts.DumpData,
		Package:       opts.APIPackage,
		APIPackage:    opts.APIPackage,
		ModelsPackage: opts.ModelPackage,
		ServerPackage: opts.ServerPackage,
		ClientPackage: opts.ClientPackage,
		Principal:     opts.Principal,
		IncludeUI:     includeUI,
	}

	return generator.Generate()
}
Exemple #6
0
// func makeCodegenApp(operations map[string]spec.Operation, includeUI bool) genApp {
func (a *appGenerator) makeCodegenApp() genApp {
	sw := a.SpecDoc.Spec()
	// app := makeCodegenApp(a.Operations, a.IncludeUI)
	receiver := strings.ToLower(a.Name[:1])
	appName := swag.ToGoName(a.Name)
	var defaultImports []string

	jsonb, _ := json.MarshalIndent(a.SpecDoc.Spec(), "", "  ")

	consumesJSON := false
	var consumes []genSerGroup
	for _, cons := range a.SpecDoc.RequiredConsumes() {
		cn, ok := mediaTypeNames[cons]
		if !ok {
			continue
		}
		nm := swag.ToJSONName(cn)
		if nm == "json" {
			consumesJSON = true
		}

		if ser, ok := getSerializer(consumes, cn); ok {
			ser.AllSerializers = append(ser.AllSerializers, genSerializer{
				AppName:        ser.AppName,
				ReceiverName:   ser.ReceiverName,
				ClassName:      ser.ClassName,
				HumanClassName: ser.HumanClassName,
				Name:           ser.Name,
				MediaType:      cons,
				Implementation: knownConsumers[nm],
			})
			continue
		}

		ser := genSerializer{
			AppName:        appName,
			ReceiverName:   receiver,
			ClassName:      swag.ToGoName(cn),
			HumanClassName: swag.ToHumanNameLower(cn),
			Name:           nm,
			MediaType:      cons,
			Implementation: knownConsumers[nm],
		}

		consumes = append(consumes, genSerGroup{
			AppName:        ser.AppName,
			ReceiverName:   ser.ReceiverName,
			ClassName:      ser.ClassName,
			HumanClassName: ser.HumanClassName,
			Name:           ser.Name,
			MediaType:      cons,
			AllSerializers: []genSerializer{ser},
			Implementation: ser.Implementation,
		})
	}

	producesJSON := false
	var produces []genSerGroup
	for _, prod := range a.SpecDoc.RequiredProduces() {
		pn, ok := mediaTypeNames[prod]
		if !ok {
			continue
		}
		nm := swag.ToJSONName(pn)
		if nm == "json" {
			producesJSON = true
		}

		if ser, ok := getSerializer(produces, pn); ok {
			ser.AllSerializers = append(ser.AllSerializers, genSerializer{
				AppName:        ser.AppName,
				ReceiverName:   ser.ReceiverName,
				ClassName:      ser.ClassName,
				HumanClassName: ser.HumanClassName,
				Name:           ser.Name,
				MediaType:      prod,
				Implementation: knownProducers[nm],
			})
			continue
		}
		ser := genSerializer{
			AppName:        appName,
			ReceiverName:   receiver,
			ClassName:      swag.ToGoName(pn),
			HumanClassName: swag.ToHumanNameLower(pn),
			Name:           nm,
			MediaType:      prod,
			Implementation: knownProducers[nm],
		}
		produces = append(produces, genSerGroup{
			AppName:        ser.AppName,
			ReceiverName:   ser.ReceiverName,
			ClassName:      ser.ClassName,
			HumanClassName: ser.HumanClassName,
			Name:           ser.Name,
			MediaType:      prod,
			Implementation: ser.Implementation,
			AllSerializers: []genSerializer{ser},
		})
	}

	var security []genSecurityScheme
	for _, scheme := range a.SpecDoc.RequiredSchemes() {
		if req, ok := a.SpecDoc.Spec().SecurityDefinitions[scheme]; ok {
			if req.Type == "basic" || req.Type == "apiKey" {
				security = append(security, genSecurityScheme{
					AppName:        appName,
					ReceiverName:   receiver,
					ClassName:      swag.ToGoName(req.Name),
					HumanClassName: swag.ToHumanNameLower(req.Name),
					Name:           swag.ToJSONName(req.Name),
					IsBasicAuth:    strings.ToLower(req.Type) == "basic",
					IsAPIKeyAuth:   strings.ToLower(req.Type) == "apikey",
					Principal:      a.Principal,
					Source:         req.In,
				})
			}
		}
	}

	var genMods []genModel
	defaultImports = append(defaultImports, filepath.Join(baseImport(a.Target), a.ModelsPackage))
	for mn, m := range a.Models {
		mod := *makeCodegenModel(
			mn,
			a.ModelsPackage,
			m,
			a.SpecDoc,
		)
		mod.ReceiverName = receiver
		genMods = append(genMods, mod)
	}

	var genOps []genOperation
	tns := make(map[string]struct{})
	for on, o := range a.Operations {
		authed := len(a.SpecDoc.SecurityRequirementsFor(&o)) > 0
		ap := a.APIPackage
		if a.APIPackage == a.Package {
			ap = ""
		}
		if len(o.Tags) > 0 {
			for _, tag := range o.Tags {
				tns[tag] = struct{}{}
				op := makeCodegenOperation(on, tag, a.ModelsPackage, a.Principal, a.Target, o, authed)
				op.ReceiverName = receiver
				genOps = append(genOps, op)
			}
		} else {
			op := makeCodegenOperation(on, ap, a.ModelsPackage, a.Principal, a.Target, o, authed)
			op.ReceiverName = receiver
			genOps = append(genOps, op)
		}
	}
	for k := range tns {
		defaultImports = append(defaultImports, filepath.Join(baseImport(a.Target), a.ServerPackage, a.APIPackage, k))
	}

	defaultConsumes := "application/json"
	rc := a.SpecDoc.RequiredConsumes()
	if !consumesJSON && len(rc) > 0 {
		defaultConsumes = rc[0]
	}

	defaultProduces := "application/json"
	rp := a.SpecDoc.RequiredProduces()
	if !producesJSON && len(rp) > 0 {
		defaultProduces = rp[0]
	}

	return genApp{
		Package:             a.Package,
		ReceiverName:        receiver,
		AppName:             swag.ToGoName(a.Name),
		HumanAppName:        swag.ToHumanNameLower(a.Name),
		Name:                swag.ToJSONName(a.Name),
		ExternalDocs:        sw.ExternalDocs,
		Info:                sw.Info,
		Consumes:            consumes,
		Produces:            produces,
		DefaultConsumes:     defaultConsumes,
		DefaultProduces:     defaultProduces,
		DefaultImports:      defaultImports,
		SecurityDefinitions: security,
		Models:              genMods,
		Operations:          genOps,
		IncludeUI:           a.IncludeUI,
		Principal:           a.Principal,
		SwaggerJSON:         fmt.Sprintf("%#v", jsonb),
	}
}
Exemple #7
0
func fieldNameFromParam(param *Parameter) string {
	if nm, ok := param.Extensions.GetString("go-name"); ok {
		return nm
	}
	return swag.ToGoName(param.Name)
}
Exemple #8
0
func makeCodegenOperation(name, pkg, modelsPkg, principal, target string, operation spec.Operation, authorized bool) genOperation {
	receiver := "o"

	var params, qp, pp, hp, fp []genParameter
	var hasQueryParams bool
	for _, p := range operation.Parameters {
		cp := makeCodegenParameter(receiver, modelsPkg, p)
		if cp.IsQueryParam {
			hasQueryParams = true
			qp = append(qp, cp)
		}
		if cp.IsFormParam {
			fp = append(fp, cp)
		}
		if cp.IsPathParam {
			pp = append(pp, cp)
		}
		if cp.IsHeaderParam {
			hp = append(hp, cp)
		}
		params = append(params, cp)
	}

	var successModel string
	var returnsPrimitive, returnsFormatted, returnsContainer, returnsMap bool
	if operation.Responses != nil {
		if r, ok := operation.Responses.StatusCodeResponses[200]; ok {
			tn := typeForSchema(r.Schema, modelsPkg)
			_, returnsPrimitive = primitives[tn]
			_, returnsFormatted = customFormatters[tn]
			returnsContainer = r.Schema.Items != nil || r.Schema.Type.Contains("array")
			returnsMap = strings.HasPrefix(tn, "map")
			successModel = tn
		}
	}

	prin := principal
	if prin == "" {
		prin = "interface{}"
	}

	zero, ok := zeroes[successModel]
	if !ok {
		zero = "nil"
	}

	return genOperation{
		Package:              pkg,
		ClassName:            swag.ToGoName(name),
		Name:                 swag.ToJSONName(name),
		Description:          operation.Description,
		DocString:            operationDocString(swag.ToGoName(name), operation),
		ReceiverName:         receiver,
		HumanClassName:       swag.ToHumanNameLower(swag.ToGoName(name)),
		DefaultImports:       []string{filepath.Join(baseImport(filepath.Join(target, "..")), modelsPkg)},
		Params:               params,
		Summary:              operation.Summary,
		QueryParams:          qp,
		PathParams:           pp,
		HeaderParams:         hp,
		FormParams:           fp,
		HasQueryParams:       hasQueryParams,
		SuccessModel:         successModel,
		SuccessZero:          zero,
		ReturnsPrimitive:     returnsPrimitive,
		ReturnsFormatted:     returnsFormatted,
		ReturnsContainer:     returnsContainer,
		ReturnsMap:           returnsMap,
		ReturnsComplexObject: !returnsPrimitive && !returnsFormatted && !returnsContainer && !returnsMap,
		Authorized:           authorized,
		Principal:            prin,
	}
}