Unable to build Go SDK from OpenAPI (failures in accounting schema)
Uh Oh - no matter the tools, we're unable to generate a buildable SDK for Golang using the Xero OpenAPI schema. The previous SDK is deprecated and we're looking to accelerate our development using the official tooling from Xero.
Is there a known working process you guys are able to share that outlines the process, i've worked in the space for a while and this is the first time that all tools seem to be unable to parse spec files and give something buildable 😬
Expected Behavior
Ability to build a working Golang SDK/client from the in-repo schema
Current Behavior
When building with either the recommended tool - https://github.com/OpenAPITools/openapi-generator or the popular tool oapi-codegen from https://github.com/deepmap/oapi-codegen - many issues arise due to the way that the schema has been structured.
The below is one example trying to validate the schema using a common tool.
go run github.com/getkin/kin-openapi/cmd/validate@latest -- xero_accounting.yaml
2023/06/23 11:59:11 Loading error: kin-openapi bug found: circular schema reference not handled - #/components/schemas/Payment -> #/components/schemas/CreditNote -> #/components/schemas/Allocation -> #/components/schemas/CreditNote -> #/components/schemas/Payment -> #/components/schemas/Invoice -> #/components/schemas/Prepayment -> #/components/schemas/Allocation -> #/components/schemas/Invoice -> #/components/schemas/Overpayment -> #/components/schemas/Payment -> #/components/schemas/Overpayment -> #/components/schemas/Allocation -> #/components/schemas/Prepayment -> #/components/schemas/Payment
exit status 1
Possible Solution
I wrote a script to contribute that i'll paste below that can go some way to generating the required SDK - including commented out ability to switch generators as needed:
#!/usr/bin/env bash
# Depending on choice, either:
# brew install openapi-generator
# or
# go install github.com/deepmap/oapi-codegen/cmd/oapi-codegen@latest
PACKAGE_NAME=xero
[ -d "$PACKAGE_NAME" ] || mkdir -p "$PACKAGE_NAME"
rm -rf "$PACKAGE_NAME"/
for FILE in *.yaml; do
# echo $FILE;
ORIGINAL_STRIPPED=$(basename $FILE .yaml);
# Normalise lower case/hyphens
NEW=$(echo $ORIGINAL_STRIPPED | tr 'xero-' 'xero_' | sed 's/xero_//')
# Generate the API spec
echo Generating from "$ORIGINAL_STRIPPED"
mkdir -p "$PACKAGE_NAME/$NEW/"
oapi-codegen --package=main -generate=types,client -package "$PACKAGE_NAME" "$FILE" > "$PACKAGE_NAME/$NEW".gen.go
# openapi-generator generate -i "$FILE" -g go --additional-properties packageName="$NEW" -o ./"$PACKAGE_NAME/$NEW/"
done
However these result in duplicate values in packages, unresolvable references or bad type definitions.
Context
We are currently building a financial services integration and would like to be able to use Xero as an approved accounting platform.
Your Environment
- Version used:
main - Browser Name and version:
Chrome or Safari - any - Operating System and version (desktop or mobile): MacOSX
- Link to your project: n/a at this time.
PETOSS-307
Thanks for raising an issue, a ticket has been created to track your request
In addition, after taking advice - I tried using redoc to reformat the YAML before parsing but that gets sad too:
$ redocly bundle --dereferenced xero_accounting.yaml > new.yaml
bundling xero_accounting.yaml...
📦 Created a bundle for xero_accounting.yaml at stdout 267ms.
$ go run github.com/getkin/kin-openapi/cmd/validate@latest -- new.yaml
2023/06/23 11:56:27 error converting YAML to JSON: yaml: anchor 'ref_20' value contains itself
exit status 1
After the linked issue was solved I was able to generate types using oapi-codegen:
# install v2.0
$ go install github.com/deepmap/oapi-codegen/v2/cmd/[email protected]
# create config.yaml with circular reference limit (potentially can lower)
$ cat ./config.yaml
package: xero
generate:
models: true
compatibility:
circular-reference-limit: 10
# generate
$ oapi-codegen -config ./config.yaml xero_accounting.yaml > accounting.go
accounting.go:
$ head -n 30 accounting.go
// Package xero provides primitives to interact with the openapi HTTP API.
//
// Code generated by github.com/deepmap/oapi-codegen/v2 version v2.0.0 DO NOT EDIT.
package xero
import (
"bytes"
// snip
"github.com/oapi-codegen/runtime"
openapi_types "github.com/oapi-codegen/runtime/types"
)
const (
OAuth2Scopes = "OAuth2.Scopes"
)
// Defines values for AccountBankAccountType.
const (
AccountBankAccountTypeBANK AccountBankAccountType = "BANK"
AccountBankAccountTypeCREDITCARD AccountBankAccountType = "CREDITCARD"
AccountBankAccountTypeEmpty AccountBankAccountType = ""
AccountBankAccountTypeNONE AccountBankAccountType = "NONE"