332 lines
8.8 KiB
Bash
Executable File
332 lines
8.8 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
|
|
# ============================================================================
|
|
# Field Checker Script
|
|
# ============================================================================
|
|
# Purpose: Verify required and recommended fields in plugin/marketplace configs
|
|
# Version: 1.0.0
|
|
# Usage: ./field-checker.sh <config-file> <type> [strict]
|
|
# Returns: 0=all required present, 1=missing required, 2=error
|
|
# ============================================================================
|
|
|
|
set -euo pipefail
|
|
|
|
# Source shared library
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
source "${SCRIPT_DIR}/../../../scripts/validate-lib.sh"
|
|
|
|
# ====================
|
|
# Configuration
|
|
# ====================
|
|
|
|
readonly CONFIG_FILE="${1:-}"
|
|
readonly TYPE="${2:-}"
|
|
readonly STRICT="${3:-false}"
|
|
|
|
# ====================
|
|
# Field Definitions
|
|
# ====================
|
|
|
|
# Plugin required fields
|
|
PLUGIN_REQUIRED_FIELDS=(
|
|
"name"
|
|
"version"
|
|
"description"
|
|
"author"
|
|
"license"
|
|
)
|
|
|
|
# Plugin recommended fields
|
|
PLUGIN_RECOMMENDED_FIELDS=(
|
|
"repository"
|
|
"homepage"
|
|
"keywords"
|
|
"category"
|
|
)
|
|
|
|
# Marketplace required fields
|
|
MARKETPLACE_REQUIRED_FIELDS=(
|
|
"name"
|
|
"owner"
|
|
"owner.name"
|
|
"owner.email"
|
|
"plugins"
|
|
)
|
|
|
|
# Marketplace recommended fields
|
|
MARKETPLACE_RECOMMENDED_FIELDS=(
|
|
"version"
|
|
"metadata.description"
|
|
"metadata.homepage"
|
|
"metadata.repository"
|
|
)
|
|
|
|
# ====================
|
|
# Validation Functions
|
|
# ====================
|
|
|
|
check_field_exists() {
|
|
local file="$1"
|
|
local field="$2"
|
|
local value
|
|
|
|
# Use json_get from validate-lib.sh
|
|
value=$(json_get "${file}" ".${field}")
|
|
|
|
if [[ -n "${value}" && "${value}" != "null" ]]; then
|
|
return 0
|
|
else
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
get_field_value() {
|
|
local file="$1"
|
|
local field="$2"
|
|
|
|
json_get "${file}" ".${field}"
|
|
}
|
|
|
|
check_field_empty() {
|
|
local value="$1"
|
|
|
|
if [[ -z "${value}" || "${value}" == "null" || "${value}" == '""' || "${value}" == "[]" || "${value}" == "{}" ]]; then
|
|
return 0 # Is empty
|
|
else
|
|
return 1 # Not empty
|
|
fi
|
|
}
|
|
|
|
# ====================
|
|
# Plugin Validation
|
|
# ====================
|
|
|
|
validate_plugin_fields() {
|
|
local file="$1"
|
|
local strict="$2"
|
|
local missing_required=0
|
|
local missing_recommended=0
|
|
|
|
print_section "Required Fields (${#PLUGIN_REQUIRED_FIELDS[@]})"
|
|
|
|
for field in "${PLUGIN_REQUIRED_FIELDS[@]}"; do
|
|
if check_field_exists "${file}" "${field}"; then
|
|
local value
|
|
value=$(get_field_value "${file}" "${field}")
|
|
|
|
# Check if empty
|
|
if check_field_empty "${value}"; then
|
|
print_error "${field}: Present but empty (REQUIRED)"
|
|
((missing_required++))
|
|
else
|
|
# Truncate long values for display
|
|
if [[ "${#value}" -gt 50 ]]; then
|
|
value="${value:0:47}..."
|
|
fi
|
|
print_success "${field}: \"${value}\""
|
|
fi
|
|
else
|
|
print_error "${field}: Missing (REQUIRED)"
|
|
((missing_required++))
|
|
fi
|
|
done
|
|
|
|
echo ""
|
|
print_section "Recommended Fields (${#PLUGIN_RECOMMENDED_FIELDS[@]})"
|
|
|
|
for field in "${PLUGIN_RECOMMENDED_FIELDS[@]}"; do
|
|
if check_field_exists "${file}" "${field}"; then
|
|
print_success "${field}: Present"
|
|
else
|
|
print_warning "${field}: Missing (improves quality)"
|
|
((missing_recommended++))
|
|
fi
|
|
done
|
|
|
|
echo ""
|
|
|
|
# Summary
|
|
if [[ ${missing_required} -eq 0 ]]; then
|
|
print_success "All required fields present"
|
|
else
|
|
print_error "Missing ${missing_required} required field(s)"
|
|
fi
|
|
|
|
if [[ ${missing_recommended} -gt 0 ]]; then
|
|
print_info "Missing ${missing_recommended} recommended field(s)"
|
|
fi
|
|
|
|
# Determine exit code
|
|
if [[ ${missing_required} -gt 0 ]]; then
|
|
return 1
|
|
elif [[ "${strict}" == "true" && ${missing_recommended} -gt 0 ]]; then
|
|
print_warning "Strict mode: Recommended fields are required"
|
|
return 1
|
|
else
|
|
return 0
|
|
fi
|
|
}
|
|
|
|
# ====================
|
|
# Marketplace Validation
|
|
# ====================
|
|
|
|
validate_marketplace_fields() {
|
|
local file="$1"
|
|
local strict="$2"
|
|
local missing_required=0
|
|
local missing_recommended=0
|
|
|
|
print_section "Required Fields (${#MARKETPLACE_REQUIRED_FIELDS[@]})"
|
|
|
|
for field in "${MARKETPLACE_REQUIRED_FIELDS[@]}"; do
|
|
if check_field_exists "${file}" "${field}"; then
|
|
local value
|
|
value=$(get_field_value "${file}" "${field}")
|
|
|
|
# Special handling for plugins array
|
|
if [[ "${field}" == "plugins" ]]; then
|
|
local count
|
|
count=$(get_json_array_length "${file}" ".plugins")
|
|
if [[ ${count} -gt 0 ]]; then
|
|
print_success "${field}: Array with ${count} entries"
|
|
else
|
|
print_error "${field}: Present but empty (REQUIRED)"
|
|
((missing_required++))
|
|
fi
|
|
elif check_field_empty "${value}"; then
|
|
print_error "${field}: Present but empty (REQUIRED)"
|
|
((missing_required++))
|
|
else
|
|
# Truncate long values
|
|
if [[ "${#value}" -gt 50 ]]; then
|
|
value="${value:0:47}..."
|
|
fi
|
|
print_success "${field}: \"${value}\""
|
|
fi
|
|
else
|
|
print_error "${field}: Missing (REQUIRED)"
|
|
((missing_required++))
|
|
fi
|
|
done
|
|
|
|
echo ""
|
|
print_section "Recommended Fields (${#MARKETPLACE_RECOMMENDED_FIELDS[@]})"
|
|
|
|
for field in "${MARKETPLACE_RECOMMENDED_FIELDS[@]}"; do
|
|
if check_field_exists "${file}" "${field}"; then
|
|
print_success "${field}: Present"
|
|
else
|
|
print_warning "${field}: Missing (improves quality)"
|
|
((missing_recommended++))
|
|
fi
|
|
done
|
|
|
|
echo ""
|
|
|
|
# Summary
|
|
if [[ ${missing_required} -eq 0 ]]; then
|
|
print_success "All required fields present"
|
|
else
|
|
print_error "Missing ${missing_required} required field(s)"
|
|
fi
|
|
|
|
if [[ ${missing_recommended} -gt 0 ]]; then
|
|
print_info "Missing ${missing_recommended} recommended field(s)"
|
|
fi
|
|
|
|
# Determine exit code
|
|
if [[ ${missing_required} -gt 0 ]]; then
|
|
return 1
|
|
elif [[ "${strict}" == "true" && ${missing_recommended} -gt 0 ]]; then
|
|
print_warning "Strict mode: Recommended fields are required"
|
|
return 1
|
|
else
|
|
return 0
|
|
fi
|
|
}
|
|
|
|
# ====================
|
|
# Main Logic
|
|
# ====================
|
|
|
|
main() {
|
|
# Validate arguments
|
|
if [[ -z "${CONFIG_FILE}" ]]; then
|
|
print_error "Usage: $0 <config-file> <type> [strict]"
|
|
print_info "Types: plugin, marketplace"
|
|
exit 2
|
|
fi
|
|
|
|
if [[ ! -f "${CONFIG_FILE}" ]]; then
|
|
print_error "Configuration file not found: ${CONFIG_FILE}"
|
|
exit 2
|
|
fi
|
|
|
|
if [[ -z "${TYPE}" ]]; then
|
|
print_error "Type required: plugin or marketplace"
|
|
exit 2
|
|
fi
|
|
|
|
# Validate JSON syntax first
|
|
if ! validate_json_syntax "${CONFIG_FILE}"; then
|
|
print_error "Invalid JSON syntax in ${CONFIG_FILE}"
|
|
print_info "Run JSON validation first to fix syntax errors"
|
|
exit 2
|
|
fi
|
|
|
|
# Print header
|
|
print_header "Required Fields Validation"
|
|
echo "Target: ${CONFIG_FILE}"
|
|
echo "Type: ${TYPE}"
|
|
echo "Strict Mode: ${STRICT}"
|
|
echo ""
|
|
|
|
# Validate based on type
|
|
case "${TYPE}" in
|
|
plugin)
|
|
if validate_plugin_fields "${CONFIG_FILE}" "${STRICT}"; then
|
|
echo ""
|
|
print_header "✅ PASS: All required fields present"
|
|
exit 0
|
|
else
|
|
echo ""
|
|
print_header "❌ FAIL: Missing required fields"
|
|
|
|
# Show remediation
|
|
echo ""
|
|
print_info "Action Required:"
|
|
echo " Add missing required fields to ${CONFIG_FILE}"
|
|
echo " Refer to plugin schema: .claude/docs/plugins/plugins-reference.md"
|
|
|
|
exit 1
|
|
fi
|
|
;;
|
|
marketplace)
|
|
if validate_marketplace_fields "${CONFIG_FILE}" "${STRICT}"; then
|
|
echo ""
|
|
print_header "✅ PASS: All required fields present"
|
|
exit 0
|
|
else
|
|
echo ""
|
|
print_header "❌ FAIL: Missing required fields"
|
|
|
|
# Show remediation
|
|
echo ""
|
|
print_info "Action Required:"
|
|
echo " Add missing required fields to ${CONFIG_FILE}"
|
|
echo " Refer to marketplace schema: .claude/docs/plugins/plugin-marketplaces.md"
|
|
|
|
exit 1
|
|
fi
|
|
;;
|
|
*)
|
|
print_error "Unknown type: ${TYPE}"
|
|
print_info "Valid types: plugin, marketplace"
|
|
exit 2
|
|
;;
|
|
esac
|
|
}
|
|
|
|
main "$@"
|