genmodel

package
v0.1.12 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 13, 2026 License: MIT Imports: 11 Imported by: 0

README

internal/genmodel

외부 OpenAPI 문서 → Go HTTP 클라이언트 코드 생성기. internal/gen/gogin의 Model 생성과는 역할이 다름 — 이 패키지는 "외부 서비스 연동용 클라이언트"를 만든다.

gogin의 Model 생성과의 차이

항목 genmodel gen/gogin
입력 OpenAPI 문서 (파일/URL) DDL + sqlc 쿼리 + OpenAPI 인터페이스
산출 패키지 package external package model
산출물 성격 HTTP 클라이언트 구현 DB 접근 구현
호출 대상 외부 HTTP 서비스 로컬 DB
서로 연결 없음 (독립) 없음 (독립)

즉 Escrow, Payment 같은 외부 서비스의 OpenAPI를 받아서 Go에서 쓸 수 있는 클라이언트(EscrowModel 인터페이스 + escrowClient 구조체)를 만든다. gogin이 이 산출물을 읽거나 참조하지 않는다 — 완전 독립.

진입점

함수 파일 역할
Generate(source, outputDir) generate.go:16 파일 I/O 래퍼: source 로드 → generate → 쓰기
GenerateBytes(source, data) generate_bytes.go:12 테스트용: 바이트 받아 바이트 반환
generateCode(svcName, doc) generate_code.go:13 코어 생성 로직
Generate 시그니처
func Generate(source, outputDir string) error
  • source — OpenAPI 문서의 파일 경로 또는 http(s):// URL.
  • outputDir — 산출 .go 파일 출력 경로.
  • 산출물 이름 — {serviceName}.go (lowercase).
readSource

read_source.go:13:

  • http:// / https:// 접두 시 HTTP GET.
  • 아니면 로컬 파일 읽기.
서비스명 추론

inferServiceName infer_service_name.go:12:

  • 우선: OpenAPI.Info.Title 에서 PascalCase 추출.
  • fallback: 파일명에서 .openapi.yaml 제거 후 PascalCase.

산출물 형태

// Code generated by fullend gen-model. DO NOT EDIT.
package external

import (
    "bytes"
    "context"
    "encoding/json"
    "fmt"
    "net/http"
    "time"   // date-time 필드 존재 시만
)

type EscrowModel interface {
    Hold(ctx context.Context, gigId int64, amount int64) (*HoldResponse, error)
    GetStatus(ctx context.Context, id int64) (*GetStatusResponse, error)
    Cancel(ctx context.Context, id int64) error
}

type HoldResponse struct {
    ID     int64  `json:"id"`
    Status string `json:"status"`
}

type escrowClient struct {
    baseURL string
    client  *http.Client
}

func NewEscrowModel(baseURL string) EscrowModel {
    return &escrowClient{baseURL: baseURL, client: &http.Client{}}
}

func (c *escrowClient) Hold(ctx context.Context, gigId int64, amount int64) (*HoldResponse, error) {
    body := map[string]any{"gigId": gigId, "amount": amount}
    var resp HoldResponse
    if err := c.do(ctx, "POST", "/escrow/hold", body, &resp); err != nil {
        return nil, err
    }
    return &resp, nil
}

func (c *escrowClient) do(ctx context.Context, method, path string, body any, out any) error {
    // JSON marshal → http.NewRequest → c.client.Do → JSON unmarshal
}

핵심 파이프라인

generateCode generate_code.go:13-77:

  1. 메서드 추출extractMethods(doc)[]methodInfo.
  2. 응답 타입 추출extractResponseTypes(svc, methods, doc)[]structType.
  3. time 필요 여부typesNeedTime(types)time.Time 필드 존재 시 import 추가.
  4. 인터페이스 렌더{ServiceName}Model interface { … }.
  5. 응답 구조체 렌더 — 각 method의 200 응답을 struct로.
  6. 클라이언트 구조체{lowerSvc}Client { baseURL, client }.
  7. 생성자New{ServiceName}Model(baseURL) …Model.
  8. 메서드 구현 — 각 methodInfo.implementation().
  9. do() 헬퍼do_helper.go:7.
  10. gofmtformat.Source().

OpenAPI 파싱 단계

단계 함수 파일
path 순회 extractMethods extract_methods.go:9
path 내 메서드 순회 extractPathMethods extract_path_methods.go:9
methodInfo 조립 buildMethodInfo build_method_info.go:9
path 파라미터 추출 extractPathParams extract_path_params.go:9
body 파라미터 추출 extractBodyParams extract_body_params.go:9
반환 타입 감지 detectReturnType detect_return_type.go:9
응답 구조 추출 extractResponseTypes extract_response_types.go:9
오퍼레이션 검색 findOperation find_operation.go:9

methodInfo

method_info_type.go:5

type methodInfo struct {
    Name       string       // Hold, GetStatus
    HTTPMethod string       // POST, GET
    Path       string       // /escrow/hold, /escrow/{id}
    Params     []paramInfo  // Path + Body 파라미터
    ReturnType string       // HoldResponse, ""
}

관련 메서드:

  • signature() method_info_signature.go:10 — 인터페이스 선언 줄
  • implementation() method_info_implementation.go:11 — 구현 본문
  • buildPathExpr() method_info_build_path_expr.go:10/escrow/%d + fmt.Sprintf
  • pathParams() / bodyParams() — 필터링

스키마 → Go 타입

schemaToGoType schema_to_go_type.go:9-53

OpenAPI type format Go
integer int64 int64
integer int32 int32
integer (없음) int
number float float32
number double / (없음) float64
string (없음) string
string date-time time.Time
boolean - bool
array items 있음 []T (재귀)
array items 없음 []any
object - map[string]any
(타입 없음) - any

$ref는 kin-openapi가 자동 해석. time.Time 쓰임 검출: typesNeedTime types_need_time.go:5 + structHasTimeField struct_has_time_field.go:5.

이름 규칙

함수
toPascalCase("escrow_service") "EscrowService"
toCamelCase("escrow_service") "escrowService"
lcFirst("EscrowModel") "escrowModel"

모두 strcase 라이브러리 기반 (to_pascal_case.go:7, to_camel_case.go:7, lc_first.go:7).

정렬

결정적 출력을 위해 맵 키 순회는 항상 정렬:

  • sortedKeys sorted_keys.go:11 — schema property 맵
  • sortedPathKeys sorted_path_keys.go:11 — OpenAPI paths

테스트

testdata/escrow.openapi.yaml — 4개 작업(hold/release/getStatus/cancel), path param 1개(/escrow/{id}), body param 2개, 200 JSON 3개 + 204 1개.

테스트 파일 검증
전체 생성 test_generate_escrow_test.go:11 인터페이스·메서드·응답타입·do헬퍼·context·path 포매팅
스키마 변환 test_schema_to_go_type_test.go:11 12 케이스 매핑 테이블
서비스명 추론 test_infer_service_name_test.go:11 파일명/Title/URL fallback
파일 쓰기 test_generate_write_file_test.go 경로·파일명 검증

파일 맵 (40+)

카테고리 파일
공개 API generate.go, generate_bytes.go, generate_code.go
소스 로딩 read_source.go, infer_service_name.go
추출 extract_methods.go, extract_path_methods.go, extract_path_params.go, extract_body_params.go, extract_response_types.go, detect_return_type.go, find_operation.go
methodInfo method_info_type.go, build_method_info.go, method_info_signature.go, method_info_implementation.go, method_info_build_path_expr.go, method_info_path_params.go, method_info_body_params.go
타입 / 구조 param_info.go, struct_type.go, struct_field.go, schema_to_go_type.go, types_need_time.go, struct_has_time_field.go
렌더 헬퍼 write_body_map.go, write_return_with_result.go, do_helper.go
이름 변환 to_pascal_case.go, to_camel_case.go, lc_first.go
정렬 sorted_keys.go, sorted_path_keys.go

설계 메모

  • 결정적 출력 — 모든 맵 순회를 정렬 기반으로 해서 diff가 안정적.
  • time 의존성 자동화time.Time 필드 없으면 time import도 안 나옴.
  • 최소 표면적 — 공개 함수 2개(Generate, GenerateBytes)만.
  • 외부 서비스 전용 — 내부 DB/Model과 완전 분리. 독립 CLI 하위 명령(fullend gen-model)으로도 사용 가능.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Generate

func Generate(source, outputDir string) error

Generate reads an OpenAPI source (file path or URL), generates a Go model file, and writes it to outputDir.

func GenerateBytes

func GenerateBytes(source string, data []byte) ([]byte, error)

GenerateBytes generates code and returns it as bytes (for testing).

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL