Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions gen.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,9 +102,9 @@ func (s *Schema) Resolve(r *Schema, rs ResolvedSet) *Schema {
for {
if s.Ref != nil {
s = s.Ref.Resolve(r)
} else if len(s.OneOf) > 0 {
} else if len(s.OneOf) > 0 && s.OneOf[0].Ref != nil {
s = s.OneOf[0].Ref.Resolve(r)
} else if len(s.AnyOf) > 0 {
} else if len(s.AnyOf) > 0 && s.AnyOf[0].Ref != nil {
s = s.AnyOf[0].Ref.Resolve(r)
} else {
break
Expand Down
166 changes: 166 additions & 0 deletions gen_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,81 @@ var generateTests = []struct {
},
},
},
{
ExpectedServiceFunctions: []string{"ResourceCreate", "ResourceInfoSpecial"},
Schema: &Schema{
Title: "Bug Reproducer API",
Properties: map[string]*Schema{
"resource": {
Ref: NewReference("#/definitions/resource"),
},
},
Definitions: map[string]*Schema{
"resource": {
Title: "Resource",
Type: "object",
Definitions: map[string]*Schema{
"id": {
Type: "string",
},
"name": {
Type: "string",
},
},
Links: []*Link{
{
Title: "Create",
Rel: "create",
HRef: NewHRef("/resources"),
Method: "POST",
Schema: &Schema{
Type: "object",
Properties: map[string]*Schema{
"name": {
Ref: NewReference("#/definitions/resource/definitions/name"),
},
},
AnyOf: []Schema{
{
Required: []string{"name"},
},
{
Required: []string{"option"},
},
},
},
TargetSchema: &Schema{
Ref: NewReference("#/definitions/resource"),
},
},
{
Title: "Info (Special)",
Rel: "self",
HRef: NewHRef("/resources/{(%23%2Fdefinitions%2Fresource%2Fdefinitions%2Fid)}"),
Method: "GET",
TargetSchema: &Schema{
Ref: NewReference("#/definitions/resource"),
},
},
},
Properties: map[string]*Schema{
"id": {
Ref: NewReference("#/definitions/resource/definitions/id"),
},
"name": {
Ref: NewReference("#/definitions/resource/definitions/name"),
},
},
},
},
Links: []*Link{
{
Rel: "self",
HRef: NewHRef("https://api.example.com"),
},
},
},
},
}

func TestGenerate(t *testing.T) {
Expand Down Expand Up @@ -194,6 +269,97 @@ var resolveTests = []struct {
},
},
},
{
Schema: &Schema{
Title: "AnyOfWithoutRef",
Type: "object",
Definitions: map[string]*Schema{
"resource": {
Title: "Resource",
Type: "object",
Links: []*Link{
{
Title: "Create",
Rel: "create",
HRef: NewHRef("/resources"),
Method: "POST",
Schema: &Schema{
Type: "object",
Properties: map[string]*Schema{
"name": {
Type: "string",
},
},
AnyOf: []Schema{
{
Required: []string{"name"},
},
{
Required: []string{"option"},
},
},
},
},
},
Definitions: map[string]*Schema{
"id": {
Type: "string",
},
},
Properties: map[string]*Schema{
"id": {
Ref: NewReference("#/definitions/resource/definitions/id"),
},
},
},
},
Properties: map[string]*Schema{
"resource": {
Ref: NewReference("#/definitions/resource"),
},
},
},
},
{
Schema: &Schema{
Title: "OneOfWithoutRef",
Type: "object",
Definitions: map[string]*Schema{
"resource": {
Title: "Resource",
Type: "object",
Links: []*Link{
{
Title: "Update",
Rel: "update",
HRef: NewHRef("/resources"),
Method: "PATCH",
Schema: &Schema{
Type: "object",
OneOf: []Schema{
{
Properties: map[string]*Schema{
"name": {Type: "string"},
},
},
{
Properties: map[string]*Schema{
"value": {Type: "integer"},
},
},
},
},
},
},
},
},
Properties: map[string]*Schema{
"resource": {
Ref: NewReference("#/definitions/resource"),
},
},
},
},
}

func TestResolve(t *testing.T) {
Expand Down
3 changes: 3 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module github.com/interagent/schematic

go 1.25.1
11 changes: 8 additions & 3 deletions helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ var helpers = template.FuncMap{
var (
newlines = regexp.MustCompile(`(?m:\s*$)`)
acronyms = regexp.MustCompile(`(Url|Http|Id|Io|Ip|Ike|Uuid|Api|Uri|Ssl|Cname|Oauth|Otp|Cidr|Nat|Vpn)$`)
camelcase = regexp.MustCompile(`(?m)[-.$/:_{}\s]+`)
camelcase = regexp.MustCompile(`(?m)[-.$/:_{}()\s]+`)
)

func goType(p *Schema) string {
Expand Down Expand Up @@ -108,18 +108,23 @@ func initialLow(ident string) string {

func depunct(ident string, initialCap bool) string {
matches := camelcase.Split(ident, -1)
var result []string
for i, m := range matches {
if m == "" {
continue
}
if initialCap || i > 0 {
m = capFirst(m)
}
matches[i] = acronyms.ReplaceAllStringFunc(m, func(c string) string {
var replaced = acronyms.ReplaceAllStringFunc(m, func(c string) string {
if len(c) > 4 {
return strings.ToUpper(c[:2]) + c[2:]
}
return strings.ToUpper(c)
})
result = append(result, replaced)
}
return strings.Join(matches, "")
return strings.Join(result, "")
}

func capFirst(ident string) string {
Expand Down
16 changes: 16 additions & 0 deletions helpers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,22 @@ var initialCapTests = []struct {
In: "Dyno all",
Out: "DynoAll",
},
{
In: "Info (Consecutive)",
Out: "InfoConsecutive",
},
{
In: "Get (Special)",
Out: "GetSpecial",
},
{
In: "List (All Items)",
Out: "ListAllItems",
},
{
In: "Update(Force)",
Out: "UpdateForce",
},
}

func TestInitialCap(t *testing.T) {
Expand Down