Skip to content

Commit 02dc0e5

Browse files
fix(management_api): decode organization connections as plain objects
GetConnectionsResponse.Connections (used by GetOrganizationConnections and GetConnections) decoded each array entry as Connection, the envelope type for a single-connection response ({code, message, connection: {...}}). The Kinde API returns plain connection objects (id, name, display_name, strategy) directly in that array, so every field ended up empty. Add fix_organization_connections.go, a go:generate patch step (matching the existing fix_optstring.go / fix_oneof.go / fix_identity_id.go convention) that types Connections as []ConnectionConnection and updates the encoder/decoder accordingly, with no vendored spec. Reimplements #55's core fix without the unrelated invitation-code changes (already present on main) or the full vendored- spec SDK regen. Test files carried over from that PR. Co-authored-by: BrandtKruger <brandt.kruger087@gmail.com>
1 parent e816055 commit 02dc0e5

7 files changed

Lines changed: 704 additions & 6 deletions

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,7 @@
11
<!-- Ideally, this should get auto-generated via tools like [auto-changelog](https://github.com/CookPete/auto-changelog). Eventually, this will get set up as part of the repository template. -->
2+
3+
## Unreleased
4+
5+
### Bug fixes
6+
7+
- **Management API:** `GetOrganizationConnections` (and other calls returning `get_connections_response`) now decode each entry in `connections` as a plain connection object (`id`, `name`, `display_name`, `strategy`), instead of the single-connection response envelope, which previously left those fields empty.
Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
//go:build ignore
2+
// +build ignore
3+
4+
package main
5+
6+
import (
7+
"bytes"
8+
"fmt"
9+
"os"
10+
)
11+
12+
// This tool patches GetConnectionsResponse.Connections to decode as
13+
// []ConnectionConnection instead of []Connection. The published OpenAPI spec
14+
// defines get_connections_response.connections items as a $ref to the
15+
// "connection" schema, which is really the envelope for a single-connection
16+
// endpoint response ({code, message, connection: {...}}). In practice the
17+
// Kinde API returns plain connection objects (id, name, display_name,
18+
// strategy) directly in that array, so decoding each element as the envelope
19+
// type left every field empty.
20+
21+
const (
22+
schemasFile = "oas_schemas_gen.go"
23+
jsonFile = "oas_json_gen.go"
24+
)
25+
26+
var (
27+
oldSchema = ` Connections []Connection ` + "`json:\"connections\"`" + `
28+
// Whether more records exist.
29+
HasMore OptBool ` + "`json:\"has_more\"`" + `
30+
}
31+
32+
// GetCode returns the value of Code.
33+
func (s *GetConnectionsResponse) GetCode() OptString {
34+
return s.Code
35+
}
36+
37+
// GetMessage returns the value of Message.
38+
func (s *GetConnectionsResponse) GetMessage() OptString {
39+
return s.Message
40+
}
41+
42+
// GetConnections returns the value of Connections.
43+
func (s *GetConnectionsResponse) GetConnections() []Connection {
44+
return s.Connections
45+
}`
46+
47+
newSchema = ` Connections []ConnectionConnection ` + "`json:\"connections\"`" + `
48+
// Whether more records exist.
49+
HasMore OptBool ` + "`json:\"has_more\"`" + `
50+
}
51+
52+
// GetCode returns the value of Code.
53+
func (s *GetConnectionsResponse) GetCode() OptString {
54+
return s.Code
55+
}
56+
57+
// GetMessage returns the value of Message.
58+
func (s *GetConnectionsResponse) GetMessage() OptString {
59+
return s.Message
60+
}
61+
62+
// GetConnections returns the value of Connections.
63+
func (s *GetConnectionsResponse) GetConnections() []ConnectionConnection {
64+
return s.Connections
65+
}`
66+
67+
oldSetter = `// SetConnections sets the value of Connections.
68+
func (s *GetConnectionsResponse) SetConnections(val []Connection) {
69+
s.Connections = val
70+
}`
71+
72+
newSetter = `// SetConnections sets the value of Connections.
73+
func (s *GetConnectionsResponse) SetConnections(val []ConnectionConnection) {
74+
s.Connections = val
75+
}`
76+
77+
oldDecode = ` case "connections":
78+
if err := func() error {
79+
s.Connections = make([]Connection, 0)
80+
if err := d.Arr(func(d *jx.Decoder) error {
81+
var elem Connection
82+
if err := elem.Decode(d); err != nil {
83+
return err
84+
}
85+
s.Connections = append(s.Connections, elem)
86+
return nil
87+
}); err != nil {
88+
return err
89+
}
90+
return nil
91+
}(); err != nil {
92+
return errors.Wrap(err, "decode field \"connections\"")
93+
}`
94+
95+
newDecode = ` case "connections":
96+
if err := func() error {
97+
s.Connections = make([]ConnectionConnection, 0)
98+
if err := d.Arr(func(d *jx.Decoder) error {
99+
var elem ConnectionConnection
100+
if err := elem.Decode(d); err != nil {
101+
return err
102+
}
103+
s.Connections = append(s.Connections, elem)
104+
return nil
105+
}); err != nil {
106+
return err
107+
}
108+
return nil
109+
}(); err != nil {
110+
return errors.Wrap(err, "decode field \"connections\"")
111+
}`
112+
)
113+
114+
func patch(file string, replacements [][2]string) error {
115+
content, err := os.ReadFile(file)
116+
if err != nil {
117+
return fmt.Errorf("reading %s: %w", file, err)
118+
}
119+
120+
newContent := content
121+
for _, r := range replacements {
122+
old, want := r[0], r[1]
123+
if bytes.Contains(newContent, []byte(want)) {
124+
// Already patched.
125+
continue
126+
}
127+
if !bytes.Contains(newContent, []byte(old)) {
128+
return fmt.Errorf("%s: expected pattern not found - the generated shape has likely changed (ogen upgrade?), update fix_organization_connections.go:\n%s", file, old)
129+
}
130+
newContent = bytes.Replace(newContent, []byte(old), []byte(want), 1)
131+
}
132+
133+
if bytes.Equal(content, newContent) {
134+
fmt.Printf("%s already patched, skipping\n", file)
135+
return nil
136+
}
137+
138+
if err := os.WriteFile(file, newContent, 0o644); err != nil {
139+
return fmt.Errorf("writing %s: %w", file, err)
140+
}
141+
fmt.Printf("✅ Patched %s for GetConnectionsResponse.Connections\n", file)
142+
return nil
143+
}
144+
145+
func main() {
146+
if err := patch(schemasFile, [][2]string{{oldSchema, newSchema}, {oldSetter, newSetter}}); err != nil {
147+
fmt.Fprintln(os.Stderr, err)
148+
os.Exit(1)
149+
}
150+
if err := patch(jsonFile, [][2]string{{oldDecode, newDecode}}); err != nil {
151+
fmt.Fprintln(os.Stderr, err)
152+
os.Exit(1)
153+
}
154+
}

kinde/management_api/generate.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@ package management_api
33
//go:generate go run github.com/ogen-go/ogen/cmd/ogen --target . -package management_api --clean https://api-spec.kinde.com/kinde-management-api-spec.yaml
44
//go:generate go run fix_optstring.go
55
//go:generate go run fix_oneof.go
6+
//go:generate go run fix_organization_connections.go

0 commit comments

Comments
 (0)