Files
Bruno GaoandQwen-Coder a88085a6c1 feat: implement batch 6 BaseAuditPO, MapStruct, Docker, and init script
- Add BaseAuditPO with audit fields (createUserId, updateUserId, createTime, updateTime, deleted, version)
- Implement MapStruct for Order ↔ OrderPO mapping with @BeanMapping(ignoreByDefault=true)
- Create Dockerfile with multi-stage build and runtime-only mode support
- Add .dockerignore for optimized build context
- Create init.sh script for project scaffolding with macOS/Linux compatibility
- Update OrderPO to extend BaseAuditPO
- Update OrderDao to use MapStruct mapper
- Add MapStruct processor dependency to infrastructure module
- Follow M2 v5 frozen contracts for audit trail and persistence layer

Co-authored-by: Qwen-Coder <[email protected]>
2026-02-12 14:18:07 +08:00

190 lines
7.0 KiB
Bash
Executable File

#!/usr/bin/env bash
# ============================================================
# init.sh — Scaffold a new service from java-service-template
# ============================================================
# Usage:
# ./init.sh --service order-service
# ./init.sh --service user-service --package com.acme
# ./init.sh --service device-service --sample none
# ./init.sh --service order-service --no-table-prefix
#
# Parameters:
# --service <name> Service name, lowercase with hyphens (required)
# --package <pkg> Root package (default: com.ljwx)
# --sample order|none Keep sample order code or remove (default: order)
# --no-table-prefix Remove "t_" prefix from table names
# ============================================================
set -euo pipefail
# ── macOS / Linux sed compatibility ──
SED_INPLACE=(-i)
if [[ "$(uname)" == "Darwin" ]]; then
SED_INPLACE=(-i '')
fi
# ── Defaults ──
SERVICE=""
PACKAGE="com.ljwx"
SAMPLE="order"
NO_TABLE_PREFIX=false
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
# ── Parse arguments ──
while [[ $# -gt 0 ]]; do
case "$1" in
--service) SERVICE="$2"; shift 2 ;;
--package) PACKAGE="$2"; shift 2 ;;
--sample) SAMPLE="$2"; shift 2 ;;
--no-table-prefix) NO_TABLE_PREFIX=true; shift ;;
-h|--help)
head -14 "$0" | grep '^#' | sed 's/^# \?//'
exit 0 ;;
*) echo "ERROR: Unknown option: $1" >&2; exit 1 ;;
esac
done
# ── Validate ──
if [[ -z "$SERVICE" ]]; then
echo "ERROR: --service is required." >&2; exit 1
fi
if [[ ! "$SERVICE" =~ ^[a-z][a-z0-9-]*$ ]]; then
echo "ERROR: --service must be lowercase alphanumeric with hyphens." >&2; exit 1
fi
if [[ "$SAMPLE" != "order" && "$SAMPLE" != "none" ]]; then
echo "ERROR: --sample must be 'order' or 'none'." >&2; exit 1
fi
# ── Derived values ──
# For Java package: "order-service" → "order_service"
SERVICE_PKG="${SERVICE//-/_}"
# For PascalCase: "order-service" → "OrderService"
SERVICE_PASCAL="$(echo "$SERVICE" | sed -E 's/(^|-)([a-z])/\U\2/g')"
# Package paths
PACKAGE_PATH="${PACKAGE//./\/}"
OLD_PKG_FULL="com.ljwx.tmpl"
OLD_PKG_PATH="com/ljwx/tmpl"
NEW_PKG_FULL="${PACKAGE}.${SERVICE_PKG}"
NEW_PKG_PATH="${PACKAGE_PATH}/${SERVICE_PKG}"
# Old / new identifiers
OLD_PREFIX="tmpl"
OLD_APP_CLASS="TmplApplication"
NEW_APP_CLASS="${SERVICE_PASCAL}Application"
OLD_GROUP_ID="com.ljwx.tmpl"
NEW_GROUP_ID="${PACKAGE}.${SERVICE_PKG}"
echo "============================================================"
echo " Service: ${SERVICE}"
echo " Package: ${NEW_PKG_FULL}"
echo " GroupId: ${NEW_GROUP_ID}"
echo " Sample: ${SAMPLE}"
echo " Table prefix: $(${NO_TABLE_PREFIX} && echo 'none' || echo 't_')"
echo "============================================================"
echo ""
# ── Step 1: Rename module directories (keep hyphens in dir names) ──
echo "[1/7] Renaming module directories..."
for MODULE in domain application infrastructure api; do
OLD_DIR="${SCRIPT_DIR}/${OLD_PREFIX}-${MODULE}"
NEW_DIR="${SCRIPT_DIR}/${SERVICE}-${MODULE}"
if [[ -d "$OLD_DIR" ]]; then
mv "$OLD_DIR" "$NEW_DIR"
echo " ${OLD_PREFIX}-${MODULE} → ${SERVICE}-${MODULE}"
fi
done
# ── Step 2: Rename Java package directories ──
echo "[2/7] Renaming Java package directories..."
# Process deepest paths first (sort -r) to avoid mv conflicts
find "${SCRIPT_DIR}" -type d -path "*/${OLD_PKG_PATH}" | sort -r | while read -r DIR; do
PARENT="$(dirname "$(dirname "$(dirname "$DIR")")")"
RELATIVE="${DIR#"${PARENT}/"}"
NEW_REL="${RELATIVE/${OLD_PKG_PATH}/${NEW_PKG_PATH}}"
TARGET="${PARENT}/${NEW_REL}"
mkdir -p "$(dirname "$TARGET")"
mv "$DIR" "$TARGET"
done
# Clean up empty directories left behind
find "${SCRIPT_DIR}" -type d -empty -delete 2>/dev/null || true
# ── Step 3: Update POM files ──
echo "[3/7] Updating POM files..."
find "${SCRIPT_DIR}" -name "pom.xml" -exec sed "${SED_INPLACE[@]}" \
-e "s|<groupId>${OLD_GROUP_ID}</groupId>|<groupId>${NEW_GROUP_ID}</groupId>|g" \
-e "s|<artifactId>java-service-template</artifactId>|<artifactId>${SERVICE}</artifactId>|g" \
-e "s|<artifactId>${OLD_PREFIX}-|<artifactId>${SERVICE}-|g" \
-e "s|<module>${OLD_PREFIX}-|<module>${SERVICE}-|g" \
{} +
# ── Step 4: Update Java source (package declarations, imports, class refs) ──
echo "[4/7] Updating Java source files..."
find "${SCRIPT_DIR}" -type f \( -name "*.java" -o -name "*.xml" -o -name "*.yml" \
-o -name "*.yaml" -o -name "*.properties" \) \
-exec sed "${SED_INPLACE[@]}" \
-e "s|${OLD_PKG_FULL}|${NEW_PKG_FULL}|g" \
-e "s|${OLD_APP_CLASS}|${NEW_APP_CLASS}|g" \
{} +
# Rename main application class file
find "${SCRIPT_DIR}" -name "${OLD_APP_CLASS}.java" | while read -r FILE; do
mv "$FILE" "$(dirname "$FILE")/${NEW_APP_CLASS}.java"
echo " Renamed ${OLD_APP_CLASS}.java → ${NEW_APP_CLASS}.java"
done
# ── Step 5: Update config files ──
echo "[5/7] Updating configuration files..."
find "${SCRIPT_DIR}" -type f \( -name "*.yml" -o -name "*.yaml" \
-o -name "*.properties" -o -name "docker-compose.yml" \) \
-exec sed "${SED_INPLACE[@]}" \
-e "s|java-service-template|${SERVICE}|g" \
-e "s|tmpl_db|${SERVICE_PKG}_db|g" \
-e "s|tmpl_test|${SERVICE_PKG}_test|g" \
-e "s|tmpl-postgres|${SERVICE}-postgres|g" \
-e "s|tmpl-redis|${SERVICE}-redis|g" \
{} +
# Update Dockerfile image references
if [[ -f "${SCRIPT_DIR}/Dockerfile" ]]; then
sed "${SED_INPLACE[@]}" \
-e "s|${OLD_PREFIX}-api|${SERVICE}-api|g" \
"${SCRIPT_DIR}/Dockerfile"
fi
# ── Step 6: Handle --sample ──
if [[ "$SAMPLE" == "none" ]]; then
echo "[6/7] Removing sample order code..."
find "${SCRIPT_DIR}" -type f -path "*/order/*" -delete 2>/dev/null || true
find "${SCRIPT_DIR}" -type d -name "order" -exec rmdir {} + 2>/dev/null || true
find "${SCRIPT_DIR}" -name "V2__*" -delete 2>/dev/null || true
echo " Removed order domain model, persistence adapter, and V2 migration."
else
echo "[6/7] Keeping sample order code."
fi
# ── Step 7: Handle --no-table-prefix ──
if ${NO_TABLE_PREFIX}; then
echo "[7/7] Removing table prefix 't_'..."
find "${SCRIPT_DIR}" -type f \( -name "*.sql" -o -name "*.java" \) \
-exec sed "${SED_INPLACE[@]}" \
-e 's/t_order/order/g' \
-e 's/t_app_meta/app_meta/g' \
{} +
echo " Replaced t_order → order, t_app_meta → app_meta."
else
echo "[7/7] Table prefix 't_' unchanged."
fi
# ── Done ──
echo ""
echo "============================================================"
echo " Done! Project scaffolded as: ${SERVICE}"
echo ""
echo " Next steps:"
echo " cd $(basename "${SCRIPT_DIR}")"
echo " docker compose up -d"
echo " mvn clean test"
echo " mvn spring-boot:run -pl ${SERVICE}-api \\"
echo " -Dspring-boot.run.profiles=dev"
echo "============================================================"