Initial commit
This commit is contained in:
331
commands/schema-validation/.scripts/field-checker.sh
Executable file
331
commands/schema-validation/.scripts/field-checker.sh
Executable file
@@ -0,0 +1,331 @@
|
||||
#!/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 "$@"
|
||||
Reference in New Issue
Block a user