scripts/apply-wl-custom-branding.sh
Rama main · réplica de lectura del repositorio original.
#!/usr/bin/env bash
# Post-processes white-label SDK artifacts after 'make sdk-all'.
#
# 'make sdk-all' runs merge-custom (copies api/custom/<lang>/ → api/<lang>/)
# and fix-mcp-package-name (hardcodes @flexprice/mcp-server). Those steps
# embed hardcoded Flexprice names that this script replaces with WL values.
#
# Run order in CI:
# generate-wl-configs.sh → make sdk-all → apply-wl-custom-branding.sh → verify-sdk-builds.sh → make ts-sdk-check
#
# Reads from environment (set by the 'Parse and export client config' step):
# WL_SDK_CLASS_NAME, WL_GO_MODULE_PATH, WL_GO_PACKAGE_NAME,
# WL_TS_PACKAGE_NAME, WL_MCP_PACKAGE_NAME
set -euo pipefail
# Portable sed -i: GNU sed uses -i alone; BSD/macOS sed requires -i ''
if sed --version 2>/dev/null | grep -q GNU; then
_sed_i() { sed -i "$@"; }
else
_sed_i() { sed -i '' "$@"; }
fi
: "${WL_SDK_CLASS_NAME:?WL_SDK_CLASS_NAME is required}"
: "${WL_GO_MODULE_PATH:?WL_GO_MODULE_PATH is required}"
: "${WL_GO_PACKAGE_NAME:?WL_GO_PACKAGE_NAME is required}"
: "${WL_TS_PACKAGE_NAME:?WL_TS_PACKAGE_NAME is required}"
: "${WL_MCP_PACKAGE_NAME:?WL_MCP_PACKAGE_NAME is required}"
# Guard: skip entirely for standard (non-WL) builds
if [ "${WL_SDK_CLASS_NAME}" = "Flexprice" ]; then
echo "WL_SDK_CLASS_NAME is 'Flexprice' — standard build, skipping white-label branding."
exit 0
fi
echo "=== Applying white-label branding to merged custom files ==="
echo " SDK class: ${WL_SDK_CLASS_NAME}"
echo " Go module: ${WL_GO_MODULE_PATH}"
echo " Go package: ${WL_GO_PACKAGE_NAME}"
echo " TS package: ${WL_TS_PACKAGE_NAME}"
echo " MCP package: ${WL_MCP_PACKAGE_NAME}"
# ─── Go: api/go/** ───────────────────────────────────────────────────────────
echo ""
echo "--- Go SDK ---"
GO_DIR="api/go"
if [ ! -d "$GO_DIR" ]; then
echo " WARNING: $GO_DIR not found — was 'make sdk-all' run first?"
else
# 1. Fix package declarations: 'package flexprice' → 'package <wl>'
# Only custom-merged files will still have 'package flexprice' after
# Speakeasy generates with sdkPackageName = WL_GO_PACKAGE_NAME.
while IFS= read -r -d '' f; do
if grep -q "^package flexprice$" "$f" 2>/dev/null; then
_sed_i "s/^package flexprice$/package ${WL_GO_PACKAGE_NAME}/" "$f"
echo " [go] package decl: $f"
fi
done < <(find "$GO_DIR" -name "*.go" -print0)
# 2. Fix *Flexprice type references (receiver type, struct field)
# Use -E with character class to avoid \b portability issues across sed variants.
while IFS= read -r -d '' f; do
if grep -q '\*Flexprice' "$f" 2>/dev/null; then
_sed_i -E "s/\*Flexprice([^[:alnum:]_]|$)/*${WL_SDK_CLASS_NAME}\1/g" "$f"
echo " [go] *Flexprice type: $f"
fi
done < <(find "$GO_DIR" -name "*.go" -print0)
# 3. Fix hardcoded import path 'github.com/flexprice/go-sdk'
# This prefix appears in import strings and go.mod files.
# WL_GO_MODULE_PATH must NOT include a /v2 suffix — the /v2 is preserved.
FLEXPRICE_MODULE="github.com/flexprice/go-sdk"
# Escape & and \ so sed treats the replacement as a literal string
WL_GO_MODULE_PATH_ESC=$(printf '%s\n' "${WL_GO_MODULE_PATH}" | sed 's/[&\]/\\&/g')
while IFS= read -r -d '' f; do
if grep -q "${FLEXPRICE_MODULE}" "$f" 2>/dev/null; then
_sed_i "s|${FLEXPRICE_MODULE}|${WL_GO_MODULE_PATH_ESC}|g" "$f"
echo " [go] module path: $f"
fi
done < <(find "$GO_DIR" \( -name "*.go" -o -name "go.mod" \) -print0)
# 4. Fix FlexPrice branding strings in Go files:
# - [FlexPrice Debug] / [FlexPrice Error] log prefixes
# - "for the FlexPrice API" in doc comments (e.g. async.go)
while IFS= read -r -d '' f; do
if grep -qE '\[FlexPrice |for the FlexPrice API' "$f" 2>/dev/null; then
_sed_i "s/\[FlexPrice Debug\]/[${WL_SDK_CLASS_NAME} Debug]/g" "$f"
_sed_i "s/\[FlexPrice Error\]/[${WL_SDK_CLASS_NAME} Error]/g" "$f"
_sed_i "s/for the FlexPrice API/for the ${WL_SDK_CLASS_NAME} API/g" "$f"
echo " [go] branding strings: $f"
fi
done < <(find "$GO_DIR" -name "*.go" -print0)
echo "Go custom branding applied."
fi
# ─── TypeScript: api/typescript/src/sdk/customer-portal.ts + index.extras.ts ─
echo ""
echo "--- TypeScript SDK ---"
PORTAL="api/typescript/src/sdk/customer-portal.ts"
EXTRAS="api/typescript/src/index.extras.ts"
if [ -f "$PORTAL" ]; then
# customer-portal.ts only contains 'Flexprice' (no 'FlexPrice' variant).
# Replace all occurrences: imports, type aliases, field decls, constructor calls.
# No compound identifiers (e.g. FlexpriceClient) exist in this file, so a plain
# replace is safe and avoids \b portability issues across sed variants.
# If new compound identifiers are added, update to word-boundary match.
_sed_i "s/Flexprice/${WL_SDK_CLASS_NAME}/g" "$PORTAL"
echo " [ts] customer-portal.ts → ${WL_SDK_CLASS_NAME}"
else
echo " WARNING: $PORTAL not found"
fi
if [ -f "$EXTRAS" ]; then
# index.extras.ts has 'Flexprice' and 'FlexPriceError' in a comment block.
# Replace FlexPriceError first to avoid double-substitution, then plain Flexprice.
_sed_i "s/FlexPriceError/${WL_SDK_CLASS_NAME}Error/g" "$EXTRAS"
_sed_i "s/Flexprice/${WL_SDK_CLASS_NAME}/g" "$EXTRAS"
# Update the example import package name in the comment.
_sed_i "s|\"@flexprice/sdk\"|\"${WL_TS_PACKAGE_NAME}\"|g" "$EXTRAS"
echo " [ts] index.extras.ts → ${WL_SDK_CLASS_NAME}, ${WL_TS_PACKAGE_NAME}"
else
echo " WARNING: $EXTRAS not found (may be OK if not present)"
fi
echo "TypeScript custom branding applied."
# ─── MCP: api/mcp/package.json ───────────────────────────────────────────────
echo ""
echo "--- MCP ---"
MCP_PKG="api/mcp/package.json"
if [ -f "$MCP_PKG" ]; then
# fix-mcp-package-name hardcoded @flexprice/mcp-server — override with WL name.
trap 'rm -f "${MCP_PKG}.tmp"' ERR
jq --arg name "${WL_MCP_PACKAGE_NAME}" '.name = $name' "$MCP_PKG" > "${MCP_PKG}.tmp"
mv "${MCP_PKG}.tmp" "$MCP_PKG"
trap - ERR
echo " [mcp] package.json name → ${WL_MCP_PACKAGE_NAME}"
else
echo " WARNING: $MCP_PKG not found"
fi
# Also replace "@flexprice/mcp-server" string in any other JSON files (e.g. examples/).
# Escape replacement so & and \ aren't interpreted by sed.
WL_MCP_ESC=$(printf '%s\n' "${WL_MCP_PACKAGE_NAME}" | sed 's/[&\]/\\&/g')
while IFS= read -r -d '' f; do
if grep -q '"@flexprice/mcp-server"' "$f" 2>/dev/null; then
_sed_i "s|\"@flexprice/mcp-server\"|\"${WL_MCP_ESC}\"|g" "$f"
echo " [mcp] json ref: $f"
fi
done < <(find "api/mcp" -name "*.json" -print0)
echo "MCP branding applied."
# ─── Python: api/python/pyproject.toml ───────────────────────────────────────
echo ""
echo "--- Python SDK ---"
PYPROJECT="api/python/pyproject.toml"
if [ -f "$PYPROJECT" ]; then
# merge-custom's sed set: 'for the FlexPrice API.' — replace with WL brand.
_sed_i "s/for the FlexPrice API\./for the ${WL_SDK_CLASS_NAME} API./g" "$PYPROJECT"
echo " [python] pyproject.toml description → for the ${WL_SDK_CLASS_NAME} API."
else
echo " WARNING: $PYPROJECT not found"
fi
echo "Python branding applied."
# ─── Documentation: all *.md files in every SDK output dir ───────────────────
echo ""
echo "--- Documentation ---"
# Derive UPPERCASE class name for env var substitution (Omkar → OMKAR)
WL_SDK_CLASS_NAME_UPPER=$(echo "${WL_SDK_CLASS_NAME}" | tr '[:lower:]' '[:upper:]')
# Derive lowercase class name for brand name substitution (Tirdad → tirdad)
WL_SDK_CLASS_NAME_LOWER=$(echo "${WL_SDK_CLASS_NAME}" | tr '[:upper:]' '[:lower:]')
# Derive Python module name (tirdad-sdk → tirdad_sdk) for import statements
WL_PYTHON_MODULE_NAME="${WL_PYTHON_PACKAGE_NAME//-/_}"
# Escape WL_GO_MODULE_PATH for sed replacement (used in Go README imports)
WL_MOD_ESC=$(printf '%s\n' "${WL_GO_MODULE_PATH}" | sed 's/[&\]/\\&/g')
# Escape WL_API_BASE_URL for sed (replacing the hardcoded default API URL)
WL_URL_ESC=$(printf '%s\n' "${WL_API_BASE_URL}" | sed 's/[&\]/\\&/g')
for SDK_DIR in api/go api/typescript api/python api/mcp; do
[ -d "$SDK_DIR" ] || continue
while IFS= read -r -d '' f; do
CHANGED=0
# Order matters — compound forms first to avoid partial substitution
# 1. Error class names (before plain Flexprice to avoid double-sub)
if grep -qE 'FlexpriceError|FlexPriceError' "$f" 2>/dev/null; then
_sed_i "s/FlexpriceError/${WL_SDK_CLASS_NAME}Error/g" "$f"
_sed_i "s/FlexPriceError/${WL_SDK_CLASS_NAME}Error/g" "$f"
CHANGED=1
fi
# 2. PascalCase and lowercase-p brand name (FlexPrice, Flexprice)
if grep -qE 'FlexPrice|Flexprice' "$f" 2>/dev/null; then
_sed_i "s/FlexPrice/${WL_SDK_CLASS_NAME}/g" "$f"
_sed_i "s/Flexprice/${WL_SDK_CLASS_NAME}/g" "$f"
CHANGED=1
fi
# 3. UPPERCASE brand name → used for env var prefixes (FLEXPRICE_API_KEY → OMKAR_API_KEY)
if grep -q 'FLEXPRICE' "$f" 2>/dev/null; then
_sed_i "s/FLEXPRICE/${WL_SDK_CLASS_NAME_UPPER}/g" "$f"
CHANGED=1
fi
# 4. TypeScript package name in install/import examples
if grep -q '@flexprice/sdk' "$f" 2>/dev/null; then
_sed_i "s|@flexprice/sdk|${WL_TS_PACKAGE_NAME}|g" "$f"
CHANGED=1
fi
# 5. MCP package name in config examples
if grep -q '@flexprice/mcp-server' "$f" 2>/dev/null; then
_sed_i "s|@flexprice/mcp-server|${WL_MCP_PACKAGE_NAME}|g" "$f"
CHANGED=1
fi
# 6. Go module path in import examples
if grep -q 'github\.com/flexprice/go-sdk' "$f" 2>/dev/null; then
_sed_i "s|github\.com/flexprice/go-sdk|${WL_MOD_ESC}|g" "$f"
CHANGED=1
fi
# 7. Default API URL (us.api.flexprice.io/v1 → WL_API_BASE_URL)
if grep -q 'us\.api\.flexprice\.io' "$f" 2>/dev/null; then
_sed_i "s|https://us\.api\.flexprice\.io/v1|${WL_URL_ESC}|g" "$f"
CHANGED=1
fi
# 8. Python package/module name — lowercase 'flexprice' in install commands and imports
# install: pip/uv/poetry use the PyPI name (dashes) → WL_PYTHON_PACKAGE_NAME
# import: Python source uses the module name (underscores) → WL_PYTHON_MODULE_NAME
if grep -qE 'pip install flexprice|uv add flexprice|poetry add flexprice|from flexprice|import flexprice' "$f" 2>/dev/null; then
_sed_i "s|pip install flexprice|pip install ${WL_PYTHON_PACKAGE_NAME}|g" "$f"
_sed_i "s|uv add flexprice|uv add ${WL_PYTHON_PACKAGE_NAME}|g" "$f"
_sed_i "s|poetry add flexprice|poetry add ${WL_PYTHON_PACKAGE_NAME}|g" "$f"
_sed_i "s|from flexprice|from ${WL_PYTHON_MODULE_NAME}|g" "$f"
_sed_i "s|import flexprice|import ${WL_PYTHON_MODULE_NAME}|g" "$f"
CHANGED=1
fi
# 9. camelCase variable name 'flexPrice' in TS README examples
# (e.g. "const flexPrice = new Tirdad(...)") — not caught by step 2 or 10
if grep -q 'flexPrice' "$f" 2>/dev/null; then
_sed_i "s/flexPrice/${WL_SDK_CLASS_NAME_LOWER}/g" "$f"
CHANGED=1
fi
# 10. All-lowercase brand name — catches remaining 'flexprice' after steps 1-9
# (e.g. "flexprice MCP Server", "flexprice-mcp" Docker image, JSON key "flexprice")
# Run LAST so Python import/install replacements (step 8) fire first.
if grep -q 'flexprice' "$f" 2>/dev/null; then
_sed_i "s/flexprice/${WL_SDK_CLASS_NAME_LOWER}/g" "$f"
CHANGED=1
fi
[ "$CHANGED" -eq 1 ] && echo " [docs] $f"
done < <(find "$SDK_DIR" -name "*.md" -print0)
done
echo "Documentation branding applied."
echo ""
echo "=== White-label custom branding complete ==="