From ad5ba7106a230f948317acc41bd145fd7f459398 Mon Sep 17 00:00:00 2001 From: Chris Tran Date: Thu, 19 Dec 2024 17:53:56 -0600 Subject: [PATCH] build: rewrites generate script to use cli-supported codemod configs like the name normalizer output option and oapi overlay spec file --- cfg.yml | 9 ++++ generate.sh | 84 +++------------------------------- overlay.yml | 122 +++++++++++++++++++++++++++++++++++++++++++++++++ passage.gen.go | 52 ++++++++++----------- 4 files changed, 164 insertions(+), 103 deletions(-) create mode 100644 cfg.yml create mode 100644 overlay.yml diff --git a/cfg.yml b/cfg.yml new file mode 100644 index 0000000..58d7079 --- /dev/null +++ b/cfg.yml @@ -0,0 +1,9 @@ +package: passage +generate: + client: true + models: true +output: passage.gen.go +output-options: + name-normalizer: ToCamelCaseWithInitialisms + overlay: + path: overlay.yml diff --git a/generate.sh b/generate.sh index c97f0a9..140c893 100755 --- a/generate.sh +++ b/generate.sh @@ -1,84 +1,14 @@ # #!/bin/bash set -euo pipefail -output_file="passage.gen.go" +if [ -z "$1" ]; then + echo "Required generator file is missing." + exit 1 +fi -# Skip pointer on optional fields -fields="\ -.components.schemas.CreateUserRequest.properties.email \ -.components.schemas.CreateUserRequest.properties.phone \ -.components.schemas.CreateUserRequest.properties.user_metadata \ -.components.schemas.UpdateUserRequest.properties.email \ -.components.schemas.UpdateUserRequest.properties.phone \ -.components.schemas.UpdateUserRequest.properties.user_metadata \ -.components.schemas.CreateMagicLinkRequest.properties.channel \ -.components.schemas.CreateMagicLinkRequest.properties.email \ -.components.schemas.CreateMagicLinkRequest.properties.language \ -.components.schemas.CreateMagicLinkRequest.properties.magic_link_path \ -.components.schemas.CreateMagicLinkRequest.properties.phone \ -.components.schemas.CreateMagicLinkRequest.properties.redirect_url \ -.components.schemas.CreateMagicLinkRequest.properties.send \ -.components.schemas.CreateMagicLinkRequest.properties.ttl \ -.components.schemas.CreateMagicLinkRequest.properties.type \ -.components.schemas.CreateMagicLinkRequest.properties.user_id \ -.components.schemas.MagicLinkType \ -.components.schemas.MagicLinkChannel \ -.components.schemas.UserInfo.properties.user_metadata \ -.components.schemas.UserInfo.properties.webauthn_types" -for field in $fields; do - jq "$field |= . + {\"x-go-type-skip-optional-pointer\": true}" openapi.json > tmp.json && mv tmp.json openapi.json -done - -# Rename component to avoid name clash with generated struct -jq ".components.schemas.ListPaginatedUsersResponse |= . + {\"x-go-name\": \"PaginatedUsersResponse\"}" openapi.json > tmp.json && mv tmp.json openapi.json - -# JSON string of key-value pairs -transforms='{ - "Active": "StatusActive", - "CreateMagicLinkRequest": "CreateMagicLinkBody", - "CreateUserRequest": "CreateUserBody", - "Inactive": "StatusInactive", - "MagicLinkTypeLogin": "LoginType", - "MagicLinkTypeVerifyIdentifier": "VerifyIdentifierType", - "MagicLinkChannel": "ChannelType", - "MagicLinkChannelEmail": "EmailChannel", - "MagicLinkChannelPhone": "PhoneChannel", - "Pending": "StatusPending", - "UpdateUserRequest": "UpdateBody", - "UserInfo": "User", - "UserMetadataFieldTypeBoolean": "BooleanMD", - "UserMetadataFieldTypeDate": "DateMD", - "UserMetadataFieldTypeEmail": "EmailMD", - "UserMetadataFieldTypeInteger": "IntegerMD", - "UserMetadataFieldTypePhone": "PhoneMD", - "UserMetadataFieldTypeString": "StringMD" -}' - -# Function to perform replacements -command -v gorename &> /dev/null || go install golang.org/x/tools/cmd/gorename@v0.24.0 -replace() { - local in=$1 out=$2 - gorename -from "\"github.com/passageidentity/passage-go\".$in" -to "$out" -force -} - -# Un-apply transforms -echo "$transforms" | jq -r 'to_entries[] | "\(.key) \(.value)"' | while read -r key value; do - replace "$value" "$key" -done +file="$1" # Run codegen go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen@v2.4.1 \ - -generate types,client \ - -package passage \ - -o "$output_file" \ - -initialism-overrides \ - openapi.json - -# Replace initialisms with uppercase versions -perl -pe 's/(Url|Uri|Ttl|Id|Rsa|Ip)(s?)(?=\b|[A-Z])/\U$1\E$2/g' "$output_file" > tmp.txt && mv tmp.txt "$output_file" - -# Apply transforms -echo "$transforms" | jq -r 'to_entries[] | "\(.key) \(.value)"' | while read -r key value; do - replace "$key" "$value" -done - + -config cfg.yml \ + $file diff --git a/overlay.yml b/overlay.yml new file mode 100644 index 0000000..2f17438 --- /dev/null +++ b/overlay.yml @@ -0,0 +1,122 @@ +overlay: 1.0.0 +info: + title: "passage-go-specific codegen updates via the OpenAPI Overlay specification (https://github.com/OAI/Overlay-Specification)" + version: 1.0.0 +actions: + +# rename types + +- target: $.components.schemas.CreateUserRequest + description: Rename the generated Go type name + update: + x-go-name: CreateUserArgs + +- target: $.components.schemas.UpdateUserRequest + description: Rename the generated Go type name + update: + x-go-name: UpdateUserOptions + +- target: $.components.schemas.ListPaginatedUsersResponse + description: Rename the generated Go type name + update: + x-go-name: PaginatedUsersResponse + +- target: $.components.schemas.UserInfo + description: Rename the generated Go type name + update: + x-go-name: PassageUser + +- target: $.components.schemas.MagicLinkChannel + description: Rename the generated Go type name + update: + x-go-name: ChannelType + +- target: $.components.schemas.CreateMagicLinkRequest + description: Rename the generated Go type name and make it private + update: + x-go-name: magicLinkArgs + +- target: $.components.schemas.ListPaginatedUsersResponse + description: Rename the generated Go type name and make it private + update: + x-go-name: paginatedUsersResponse + +# rename enums + +- target: $.components.schemas.UserStatus + description: Rename the generated Go enum name + update: + x-enumNames: + - StatusActive + - StatusInactive + - StatusPending + +- target: $.components.schemas.MagicLinkType + description: Rename the generated Go enum name + update: + x-enumNames: + - LoginType + - VerifyIdentifierType + +- target: $.components.schemas.MagicLinkChannel + description: Rename the generated Go enum name + update: + x-enumNames: + - EmailChannel + - PhoneChannel + +- target: $.components.schemas.UserMetadataFieldType + description: Rename the generated Go enum name + update: + x-enumNames: + - StringMD + - BooleanMD + - IntegerMD + - DateMD + - PhoneMD + - EmailMD + +- target: $.components.schemas.UserEventAction + description: Rename the generated Go enum name + update: + x-enumNames: + - UserEventActionRegister + - UserEventActionLogin + - UserEventActionOther + +# skip optional pointers + +- target: $.components.schemas.CreateUserRequest.properties.* + description: Don't use pointers for optional properties in the generated Go type + update: + x-go-type-skip-optional-pointer: true + +- target: $.components.schemas.UpdateUserRequest.properties.* + description: Don't use pointers for optional properties in the generated Go type + update: + x-go-type-skip-optional-pointer: true + +- target: $.components.schemas.CreateMagicLinkRequest.properties.* + description: Don't use pointers for optional properties in the generated Go type + update: + x-go-type-skip-optional-pointer: true + +- target: $.components.schemas.MagicLinkType + description: Don't use pointers for optional properties in the generated Go type + update: + x-go-type-skip-optional-pointer: true + +- target: $.components.schemas.MagicLinkChannel + description: Don't use pointers for optional properties in the generated Go type + update: + x-go-type-skip-optional-pointer: true + +- target: $.components.schemas.UserInfo.properties.user_metadata + description: Don't use pointers for optional properties in the generated Go type + update: + x-go-type-skip-optional-pointer: true + +- target: $.components.schemas.UserInfo.properties.webauthn_types + description: Don't use pointers for optional properties in the generated Go type + update: + x-go-type-skip-optional-pointer: true diff --git a/passage.gen.go b/passage.gen.go index 3193d98..1917082 100644 --- a/passage.gen.go +++ b/passage.gen.go @@ -45,8 +45,8 @@ const ( // Defines values for N404ErrorCode. const ( + APIKeyNotFound N404ErrorCode = "api_key_not_found" AdminNotFound N404ErrorCode = "admin_not_found" - ApiKeyNotFound N404ErrorCode = "api_key_not_found" AppNotFound N404ErrorCode = "app_not_found" DeviceNotFound N404ErrorCode = "device_not_found" DomainNotFound N404ErrorCode = "domain_not_found" @@ -101,7 +101,7 @@ const ( Verdana FontFamily = "Verdana" ) -// Defines values for MagicLinkChannel. +// Defines values for ChannelType. const ( EmailChannel ChannelType = "email" PhoneChannel ChannelType = "phone" @@ -233,12 +233,12 @@ type N500ErrorCode string type AppInfo struct { AdditionalAuthOrigins []string `json:"additional_auth_origins"` - // AllowedCallbackURLs The valid URLs where users can be redirected after authentication. - AllowedCallbackURLs []string `json:"allowed_callback_urls"` + // AllowedCallbackUrls The valid URLs where users can be redirected after authentication. + AllowedCallbackUrls []string `json:"allowed_callback_urls"` AllowedIdentifier string `json:"allowed_identifier"` - // AllowedLogoutURLs The valid URLs where users can be redirected after logging out. - AllowedLogoutURLs []string `json:"allowed_logout_urls"` + // AllowedLogoutUrls The valid URLs where users can be redirected after logging out. + AllowedLogoutUrls []string `json:"allowed_logout_urls"` // ApplicationLoginURI A route within your application that redirects to the Authorization URL endpoint. ApplicationLoginURI string `json:"application_login_uri"` @@ -287,7 +287,7 @@ type AppInfo struct { RequireIdentifierVerification bool `json:"require_identifier_verification"` RequiredIdentifier string `json:"required_identifier"` Role string `json:"role"` - RSAPublicKey string `json:"rsa_public_key"` + RsaPublicKey string `json:"rsa_public_key"` // Secret can only be retrieved by an app admin Secret *string `json:"secret,omitempty"` @@ -324,10 +324,10 @@ type AuthMethods struct { Passkeys PasskeysAuthMethod `json:"passkeys"` } -// CreateMagicLinkBody defines model for CreateMagicLinkBody. -type CreateMagicLinkBody struct { - Channel ChannelType `json:"channel,omitempty"` - Email string `json:"email,omitempty"` +// magicLinkArgs defines model for CreateMagicLinkRequest. +type magicLinkArgs struct { + ChannelType ChannelType `json:"channel,omitempty"` + Email string `json:"email,omitempty"` // Language language of the email to send (optional) Language string `json:"language,omitempty"` @@ -342,8 +342,8 @@ type CreateMagicLinkBody struct { UserID string `json:"user_id,omitempty"` } -// CreateUserBody defines model for CreateUserBody. -type CreateUserBody struct { +// CreateUserArgs defines model for CreateUserRequest. +type CreateUserArgs struct { // Email Email of the new user. Either this or `phone` is required; both may be provided. Email string `json:"email,omitempty"` @@ -489,8 +489,8 @@ type ListPaginatedUsersItem struct { UserMetadata *map[string]interface{} `json:"user_metadata"` } -// PaginatedUsersResponse defines model for ListPaginatedUsersResponse. -type PaginatedUsersResponse struct { +// paginatedUsersResponse defines model for ListPaginatedUsersResponse. +type paginatedUsersResponse struct { Links PaginatedLinks `json:"_links"` // CreatedBefore time anchor (Unix timestamp) --> all users returned created before this timestamp @@ -533,7 +533,7 @@ type MagicLinkAuthMethod struct { TTLDisplayUnit TTLDisplayUnit `json:"ttl_display_unit"` } -// ChannelType defines model for ChannelType. +// ChannelType defines model for MagicLinkChannel. type ChannelType string // MagicLinkResponse defines model for MagicLinkResponse. @@ -590,8 +590,8 @@ type ThemeType string // * `d` - days type TTLDisplayUnit string -// UpdateBody defines model for UpdateBody. -type UpdateBody struct { +// UpdateUserOptions defines model for UpdateUserRequest. +type UpdateUserOptions struct { Email string `json:"email,omitempty"` Phone string `json:"phone,omitempty"` UserMetadata map[string]interface{} `json:"user_metadata,omitempty"` @@ -603,8 +603,8 @@ type UserEventAction string // UserEventStatus defines model for UserEventStatus. type UserEventStatus string -// User defines model for User. -type User struct { +// PassageUser defines model for UserInfo. +type PassageUser struct { CreatedAt time.Time `json:"created_at"` Email string `json:"email"` EmailVerified bool `json:"email_verified"` @@ -661,7 +661,7 @@ type UserRecentEvent struct { // UserResponse defines model for UserResponse. type UserResponse struct { - User User `json:"user"` + PassageUser PassageUser `json:"user"` } // UserSocialConnections defines model for UserSocialConnections. @@ -775,13 +775,13 @@ type ListPaginatedUsersParams struct { } // CreateMagicLinkJSONRequestBody defines body for CreateMagicLink for application/json ContentType. -type CreateMagicLinkJSONRequestBody = CreateMagicLinkBody +type CreateMagicLinkJSONRequestBody = magicLinkArgs // CreateUserJSONRequestBody defines body for CreateUser for application/json ContentType. -type CreateUserJSONRequestBody = CreateUserBody +type CreateUserJSONRequestBody = CreateUserArgs // UpdateUserJSONRequestBody defines body for UpdateUser for application/json ContentType. -type UpdateUserJSONRequestBody = UpdateBody +type UpdateUserJSONRequestBody = UpdateUserOptions // RequestEditorFn is the function signature for the RequestEditor callback function type RequestEditorFn func(ctx context.Context, req *http.Request) error @@ -1912,7 +1912,7 @@ func (r CreateMagicLinkResponse) StatusCode() int { type ListPaginatedUsersResponse struct { Body []byte HTTPResponse *http.Response - JSON200 *PaginatedUsersResponse + JSON200 *paginatedUsersResponse JSON400 *N400Error JSON401 *N401Error JSON404 *N404Error @@ -2415,7 +2415,7 @@ func ParseListPaginatedUsersResponse(rsp *http.Response) (*ListPaginatedUsersRes switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest PaginatedUsersResponse + var dest paginatedUsersResponse if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err }