fix: refactor labels to use common entries between model and dto

This commit is contained in:
allanice001
2025-11-04 09:23:31 +00:00
parent 3ca77c097d
commit 2170b9a945
26 changed files with 398 additions and 224 deletions

297
Makefile
View File

@@ -1,3 +1,13 @@
# ========= Makefile (optimized + DRY + annotated) =========
# --- strict shell & make behavior ---
SHELL := /usr/bin/env bash
.SHELLFLAGS := -eu -o pipefail -c
.DELETE_ON_ERROR:
MAKEFLAGS += --warn-undefined-variables
.ONESHELL:
# --- variables ---
GOCMD ?= go
GOINSTALL := $(GOCMD) install
@@ -38,10 +48,26 @@ SWAG := $(shell command -v swag 2>/dev/null)
GMU := $(shell command -v go-mod-upgrade 2>/dev/null)
YARN := $(shell command -v yarn 2>/dev/null)
NPM := $(shell command -v npm 2>/dev/null)
OGC := $(shell command -v openapi-generator-cli 2>/dev/null || command -v openapi-generator 2>/dev/null)
BROTLI := $(shell command -v brotli 2>/dev/null)
GZIP := $(shell command -v gzip 2>/dev/null)
.DEFAULT_GOAL := build
# OpenAPI Generator wrapper (npm) and *core* version pin
OGC_WRAPPER ?= @openapitools/openapi-generator-cli@latest
OPENAPI_GENERATOR_VERSION ?= 7.17.0
OGC_BIN := npx -y $(OGC_WRAPPER)
# Cache the core generator jar (faster CI/local)
export OPENAPI_GENERATOR_CLI_CACHE_DIR ?= $(HOME)/.openapi-generator
# Toggle alias-as-model (can trigger name collisions in some specs)
ALIAS_AS_MODEL ?= true
ALIAS_FLAG := $(if $(filter true,$(ALIAS_AS_MODEL)),--generate-alias-as-model,)
# Post-process generated Go with gofmt (OpenAPI Generator honors this env var)
export GO_POST_PROCESS_FILE := gofmt -w
# Default goal
.DEFAULT_GOAL := help
# --- version metadata (ldflags) ---
VERSION := $(shell git describe --tags --always --dirty 2>/dev/null || echo "dev")
@@ -54,26 +80,74 @@ LDFLAGS := -X '$(MODULE_PATH)/internal/version.Version=$(VERSION)' \
-X '$(MODULE_PATH)/internal/version.Date=$(DATE)' \
-X '$(MODULE_PATH)/internal/version.BuiltBy=$(BUILT_BY)'
# --- whitespace trimming helper ---
trim = $(strip $1)
# sanitized copies (use these everywhere in recipes)
SDK_OUTDIR_CLEAN := $(call trim,$(SDK_OUTDIR))
SDK_TS_DIR_CLEAN := $(call trim,$(SDK_TS_DIR))
SDK_TS_UI_DIR_CLEAN := $(call trim,$(SDK_TS_UI_DIR))
GIT_HOST_CLEAN := $(call trim,$(GIT_HOST))
GIT_USER_CLEAN := $(call trim,$(GIT_USER))
SDK_REPO_CLEAN := $(call trim,$(SDK_REPO))
SDK_PKG_CLEAN := $(call trim,$(SDK_PKG))
# --- phony targets ---
.PHONY: all prepare ui-install ui-build ui swagger build clean fmt vet tidy upgrade \
sdk sdk-go sdk-ts sdk-ts-ui sdk-all worksync wire-sdk-replace help dev ui-compress \
print-version
sdk sdk-go sdk-ts sdk-ts-ui sdk-all help dev ui-compress print-version \
validate-spec check-tags doctor diff-swagger
# --- inputs/outputs for swagger (incremental) ---
DOCS_JSON := docs/swagger.json
DOCS_YAML := docs/swagger.yaml
# Prefer git for speed; fall back to find. Exclude UI dir.
GO_SRCS := $(shell (git ls-files '*.go' ':!$(UI_DIR)/**' 2>/dev/null || find . -name '*.go' -not -path './$(UI_DIR)/*' -type f))
# Rebuild swagger when Go sources change
$(DOCS_JSON) $(DOCS_YAML): $(GO_SRCS)
@echo ">> Generating Swagger docs..."
@if ! command -v swag >/dev/null 2>&1; then \
echo "Installing swag..."; \
$(GOINSTALL) github.com/swaggo/swag/cmd/swag@latest; \
fi
@rm -rf docs/swagger.* docs/docs.go
@swag init -g $(MAIN) -o docs
# --- spec validation + tag guard ---
validate-spec: $(DOCS_JSON) ## Validate docs/swagger.json and pin the core OpenAPI Generator version
@$(OGC_BIN) version-manager set "$(OPENAPI_GENERATOR_VERSION)"
@$(OGC_BIN) version
@$(OGC_BIN) validate -i $(DOCS_JSON)
@echo ">> Spec valid."
check-tags: $(DOCS_JSON) ## Check that Swagger tags contain no spaces/slashes (jq optional)
@echo ">> Checking tags for invalid characters (spaces or slashes)"
@if command -v jq >/dev/null 2>&1; then \
! jq -r '..|.tags? // empty | .[]' $(DOCS_JSON) | grep -Eq '[ /]'; \
else \
echo "jq not found; skipping tag check (install jq to enable)"; \
fi
# Optional: quick diff between JSON & YAML swagger (nice for drift)
diff-swagger: $(DOCS_JSON) $(DOCS_YAML) ## Show diff between swagger.json and swagger.yaml (requires yq)
@command -v yq >/dev/null 2>&1 || { echo "yq not found; brew install yq"; exit 1; }
@diff -u <(jq -S . $(DOCS_JSON)) <(yq -o=json -S '.' $(DOCS_YAML)) || true
# --- meta targets ---
all: build
prepare: fmt vet tidy upgrade
all: build ## Default meta-target: build everything
prepare: fmt vet tidy upgrade ## go fmt, vet, tidy, and upgrade module dependencies
# --- go hygiene ---
fmt:
fmt: ## go fmt ./...
@$(GOCMD) fmt ./...
vet:
vet: ## go vet ./...
@$(GOCMD) vet ./...
tidy:
tidy: ## go mod tidy
@$(GOCMD) mod tidy
upgrade:
upgrade: ## Upgrade module requirements with go-mod-upgrade (best-effort)
@echo ">> Checking go-mod-upgrade..."
@if [ -z "$(GMU)" ]; then \
echo "Installing go-mod-upgrade..."; \
@@ -82,7 +156,7 @@ upgrade:
@go-mod-upgrade -f || true
# --- ui ---
ui-install:
ui-install: ## Install frontend dependencies (yarn or npm)
@echo ">> Installing UI deps in $(UI_DIR)..."
@if [ -n "$(YARN)" ]; then \
cd $(UI_DIR) && yarn install --frozen-lockfile; \
@@ -92,7 +166,7 @@ ui-install:
echo "Error: neither yarn nor npm is installed." >&2; exit 1; \
fi
ui-build: ui-install
ui-build: ui-install ## Build frontend (Vite)
@echo ">> Building UI in $(UI_DIR)..."
@rm -rf $(UI_DEST_DIR)/dist
@if [ -n "$(YARN)" ]; then \
@@ -101,7 +175,7 @@ ui-build: ui-install
cd $(UI_DIR) && npm run build; \
fi
ui-compress: ui-build
ui-compress: ui-build ## Precompress UI assets with brotli/gzip if available
@echo ">> Precompressing assets (brotli + gzip) in $(UI_DEST_DIR)/dist"
@if [ -n "$(BROTLI)" ]; then \
find "$(UI_DEST_DIR)/dist" -type f \( -name '*.js' -o -name '*.css' -o -name '*.html' \) -print0 | \
@@ -112,25 +186,20 @@ ui-compress: ui-build
xargs -0 -I{} gzip -kf {}; \
else echo "gzip not found; skipping .gz"; fi
ui: ui-compress
ui: ui-compress ## Build and precompress UI
# --- swagger ---
swagger:
@echo ">> Generating Swagger docs..."
@if [ -z "$(SWAG)" ]; then \
echo "Installing swag..."; \
$(GOINSTALL) github.com/swaggo/swag/cmd/swag@latest; \
fi
@rm -rf docs/swagger.* docs/docs.go
@swag init -g $(MAIN) -o docs
# --- swagger convenience phony (kept for UX) ---
.PHONY: swagger
swagger: $(DOCS_JSON) ## Generate Swagger docs if stale
@true
# --- build ---
build: prepare ui swagger sdk-all
build: prepare ui swagger sdk-all ## Build everything: Go hygiene, UI, Swagger, SDKs, then Go binary
@echo ">> Building Go binary: $(BIN)"
@$(GOCMD) build -trimpath -ldflags "$(LDFLAGS)" -o $(BIN) $(MAIN)
# Handy: print resolved version metadata
print-version:
print-version: ## Print ldflags/version metadata
@echo "VERSION = $(VERSION)"
@echo "COMMIT = $(COMMIT)"
@echo "DATE = $(DATE)"
@@ -138,7 +207,7 @@ print-version:
@echo "LDFLAGS = $(LDFLAGS)"
# --- development ---
dev: ui-install swagger
dev: ui-install swagger ## Run Vite dev server and Go API (serve)
@echo ">> Starting Vite (frontend) and Go API (backend) with dev env..."
@cd $(UI_DIR) && \
( \
@@ -154,124 +223,92 @@ dev: ui-install swagger
wait \
)
# --- shared generator flags ---
GEN_COMMON := --enable-post-process-file $(ALIAS_FLAG) -i $(DOCS_JSON)
# --- DRY macro for openapi-generator generate ---
# Usage: $(call OGC_GENERATE,<generator>,<outdir>,<extra flags>)
define OGC_GENERATE
$(OGC_BIN) generate \
$(GEN_COMMON) \
-g $(1) \
-o $(2) \
$(3)
endef
# Convenience bundles
OAG_GIT_PROPS := --git-host "$(GIT_HOST_CLEAN)" --git-user-id "$(GIT_USER_CLEAN)" --git-repo-id "$(SDK_REPO_CLEAN)"
TS_PROPS := -p npmName=$(SDK_TS_NPM_NAME) -p npmVersion=$(SDK_TS_NPM_VER) $(SDK_TS_PROPS_FLAGS)
# --- sdk generation (Go) ---
sdk-go: swagger
@echo ">> Generating Go SDK (module $(GIT_HOST)/$(GIT_USER)/$(SDK_REPO), Go $(GO_VERSION))..."
@set -e; \
export GO_POST_PROCESS_FILE="gofmt -w"; \
if [ -z "$(OGC)" ]; then \
if [ -z "$(NPM)" ]; then \
echo "Error: npm is required to install openapi-generator-cli." >&2; exit 1; \
fi; \
echo "Installing openapi-generator-cli..."; \
$(NPM) i -g @openapitools/openapi-generator-cli; \
OGC_BIN=openapi-generator-cli; \
else \
OGC_BIN="$(OGC)"; \
fi; \
rm -rf "$(SDK_OUTDIR)"; \
mkdir -p "$(SDK_OUTDIR)"; \
"$$OGC_BIN" generate \
--enable-post-process-file \
--generate-alias-as-model \
-i docs/swagger.json \
-g go \
-o "$(SDK_OUTDIR)" \
--additional-properties=packageName=$(SDK_PKG) \
--git-host "$(GIT_HOST)" \
--git-user-id "$(GIT_USER)" \
--git-repo-id "$(SDK_REPO)"; \
cd "$(SDK_OUTDIR)"; \
sdk-go: $(DOCS_JSON) validate-spec check-tags ## Generate Go SDK + tidy module
@echo ">> Generating Go SDK (module $(GIT_HOST_CLEAN)/$(GIT_USER_CLEAN)/$(SDK_REPO_CLEAN), Go $(GO_VERSION))..."
@rm -rf "$(SDK_OUTDIR_CLEAN)"; mkdir -p "$(SDK_OUTDIR_CLEAN)"
@$(call OGC_GENERATE,go,$(SDK_OUTDIR_CLEAN),--additional-properties=packageName=$(SDK_PKG_CLEAN) $(OAG_GIT_PROPS))
@cd "$(SDK_OUTDIR_CLEAN)"; \
$(GOCMD) mod edit -go=$(GO_VERSION); \
$(GOCMD) mod tidy
# --- sdk generation (TypeScript) ---
sdk-ts: swagger
@set -e; \
if [ -z "$(OGC)" ]; then \
if [ -z "$(NPM)" ]; then echo "Error: npm is required to install openapi-generator-cli." >&2; exit 1; fi; \
echo "Installing openapi-generator-cli..."; \
$(NPM) i -g @openapitools/openapi-generator-cli; \
OGC_BIN=openapi-generator-cli; \
else \
OGC_BIN="$(OGC)"; \
fi; \
rm -rf "$(SDK_TS_DIR)"; \
mkdir -p "$(SDK_TS_DIR)"; \
"$$OGC_BIN" generate \
-i docs/swagger.json \
-g "$(SDK_TS_GEN)" \
-o "$(SDK_TS_DIR)" \
-p npmName=$(SDK_TS_NPM_NAME) \
-p npmVersion=$(SDK_TS_NPM_VER) \
$(SDK_TS_PROPS_FLAGS); \
if [ ! -d "$(SDK_TS_DIR)" ]; then \
echo "Generation failed: $(SDK_TS_DIR) not found." >&2; exit 1; \
fi; \
if command -v npx >/dev/null 2>&1; then \
sdk-ts: $(DOCS_JSON) validate-spec check-tags ## Generate TypeScript SDK, format, and build
@echo ">> Generating TypeScript SDK in $(SDK_TS_DIR_CLEAN)"
@rm -rf "$(SDK_TS_DIR_CLEAN)"; mkdir -p "$(SDK_TS_DIR_CLEAN)"
@$(call OGC_GENERATE,$(SDK_TS_GEN),$(SDK_TS_DIR_CLEAN),$(TS_PROPS))
@if command -v npx >/dev/null 2>&1; then \
echo ">> Prettier: formatting generated TS SDK"; \
cd "$(SDK_TS_DIR)" && npx --yes prettier -w . || true; \
fi; \
echo ">> Installing & building TS SDK in $(SDK_TS_DIR)"; \
if command -v yarn >/dev/null 2>&1; then \
cd "$(SDK_TS_DIR)" && yarn install --frozen-lockfile || true; \
cd "$(SDK_TS_DIR)" && yarn build || true; \
cd "$(SDK_TS_DIR_CLEAN)" && npx --yes prettier -w . || true; \
fi
@echo ">> Installing & building TS SDK in $(SDK_TS_DIR_CLEAN)"
@if command -v yarn >/dev/null 2>&1; then \
cd "$(SDK_TS_DIR_CLEAN)" && yarn install --frozen-lockfile || true; \
cd "$(SDK_TS_DIR_CLEAN)" && yarn build || true; \
elif command -v npm >/dev/null 2>&1; then \
cd "$(SDK_TS_DIR)" && npm ci || npm install || true; \
cd "$(SDK_TS_DIR)" && npm run build || true; \
cd "$(SDK_TS_DIR_CLEAN)" && npm ci || npm install || true; \
cd "$(SDK_TS_DIR_CLEAN)" && npm run build || true; \
else \
echo "Warning: neither yarn nor npm is installed; skipping install/build for TS SDK."; \
fi
# --- sdk generation (TypeScript into UI/src) ---
sdk-ts-ui: swagger
@echo ">> Generating TypeScript SDK directly into UI source: $(SDK_TS_UI_DIR)"
@set -e; \
if [ -z "$(OGC)" ]; then \
if [ -z "$(NPM)" ]; then \
echo "Error: npm is required to install openapi-generator-cli." >&2; exit 1; \
fi; \
echo "Installing openapi-generator-cli..."; \
$(NPM) i -g @openapitools/openapi-generator-cli; \
OGC_BIN=openapi-generator-cli; \
else \
OGC_BIN="$(OGC)"; \
fi; \
rm -rf "$(SDK_TS_UI_DIR)"; \
mkdir -p "$(SDK_TS_UI_DIR)"; \
"$$OGC_BIN" generate \
-i docs/swagger.json \
-g typescript-fetch \
-o "$(SDK_TS_UI_DIR)" \
-p npmName=$(SDK_TS_NPM_NAME) \
-p npmVersion=$(SDK_TS_NPM_VER) \
$(SDK_TS_PROPS_FLAGS); \
# --- move src/* up one level ---
@if [ -d "$(SDK_TS_UI_DIR)/src" ]; then \
mv "$(SDK_TS_UI_DIR)/src/"* "$(SDK_TS_UI_DIR)/"; \
rm -rf "$(SDK_TS_UI_DIR)/src"; \
fi; \
rm -f "$(SDK_TS_UI_DIR)/package.json" "$(SDK_TS_UI_DIR)/tsconfig.json" "$(SDK_TS_UI_DIR)/README.md"
sdk-ts-ui: $(DOCS_JSON) validate-spec check-tags ## Generate TS SDK directly into UI src (no package files)
@echo ">> Generating TypeScript SDK directly into UI source: $(SDK_TS_UI_DIR_CLEAN)"
@rm -rf "$(SDK_TS_UI_DIR_CLEAN)"; mkdir -p "$(SDK_TS_UI_DIR_CLEAN)"
@$(call OGC_GENERATE,typescript-fetch,$(SDK_TS_UI_DIR_CLEAN),$(TS_PROPS))
@if [ -d "$(SDK_TS_UI_DIR_CLEAN)/src" ]; then \
mv "$(SDK_TS_UI_DIR_CLEAN)/src/"* "$(SDK_TS_UI_DIR_CLEAN)/"; \
rm -rf "$(SDK_TS_UI_DIR_CLEAN)/src"; \
fi
@rm -f "$(SDK_TS_UI_DIR_CLEAN)/package.json" "$(SDK_TS_UI_DIR_CLEAN)/tsconfig.json" "$(SDK_TS_UI_DIR_CLEAN)/README.md"
# convenience
sdk-all: sdk-go sdk-ts sdk-ts-ui
sdk: sdk-go
# --- convenience ---
sdk-all: sdk-go sdk-ts sdk-ts-ui ## Generate Go + TS SDKs (tip: run with "make -j sdk-all" for parallel)
sdk: sdk-go ## Alias for sdk-go
# --- clean/help ---
clean:
clean: ## Clean build artifacts, Swagger outputs, UI dist, and SDKs
@echo ">> Cleaning artifacts..."
@rm -rf "$(BIN)" docs/swagger.* docs/docs.go $(UI_DEST_DIR)/dist $(UI_DIR)/dist $(UI_DIR)/node_modules "$(SDK_OUTDIR)" "$(SDK_TS_OUTDIR)"
@rm -rf "$(BIN)" docs/swagger.* docs/docs.go \
"$(UI_DEST_DIR)/dist" "$(UI_DIR)/dist" "$(UI_DIR)/node_modules" \
"$(SDK_OUTDIR_CLEAN)" "$(SDK_TS_DIR_CLEAN)" "$(SDK_TS_UI_DIR_CLEAN)"
help:
@echo "Targets:"
@echo " build - fmt, vet, tidy, upgrade, build UI, generate Swagger, build Go binary (with ldflags)"
@echo " ui - build the Vite UI and copy to $(UI_DEST_DIR)/dist (with compression)"
@echo " swagger - (re)generate Swagger docs using swag"
@echo " sdk-go (sdk) - generate Go SDK with correct module path and Go version"
@echo " sdk-ts - generate TypeScript SDK (typescript-fetch) with package.json"
@echo " sdk-ts-ui - generate TypeScript SDK directly into ui/src for inline consumption"
@echo " sdk-all - generate both Go and TypeScript SDKs"
@echo " dev - run Vite UI dev server + Go API"
@echo " clean - remove binary, Swagger outputs, UI dist, and SDKs"
@echo " prepare - fmt, vet, tidy, upgrade deps"
@echo " print-version - show computed ldflags values"
doctor: ## Print environment diagnostics (shell, versions, generator availability)
@echo ">> Make is using shell: $(SHELL)"
@{ \
echo ">> Detected runtime shell process: $$0"; \
command -v bash >/dev/null 2>&1 || { echo "bash not found. On macOS: brew install bash"; exit 1; }; \
echo ">> Versions:"; \
bash --version | head -1 || true; \
go version || true; \
node -v || true; \
npm -v || true; \
npx -v || true; \
jq --version || true; \
echo ">> OpenAPI Generator (wrapper) available via npx:"; \
$(OGC_BIN) version || true; \
}
help: ## Show this help
@grep -hE '^[a-zA-Z0-9_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | \
awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
# ========= end Makefile =========