#!/bin/bash set -euo pipefail # Exit on error, undefined vars, and pipe failures # Configuration HEADER_KEY="THIS HEADER IS AUTOGENERATED. DO NOT MODIFY MANUALLY." HEADER=" /** * ${HEADER_KEY} * ! For any changes, please update the '/openvidu-meet/typings' directory. **/" SOURCE_DIR="src" # Color codes for output readonly RED='\033[0;31m' readonly GREEN='\033[0;32m' readonly YELLOW='\033[1;33m' readonly BLUE='\033[0;34m' readonly NC='\033[0m' # No Color # Directory mapping configuration declare -A TARGET_DIRECTORIES=( ["frontend"]="../frontend/projects/shared-meet-components/src/lib/typings/ce" ["backend"]="../backend/src/typings/ce" ["webcomponent"]="../frontend/webcomponent/src/typings/ce" ["pro"]="../../openvidu-meet-pro/types/src/ce" ) # Target groups for convenience declare -A TARGET_GROUPS=( ["ce"]="frontend backend webcomponent" ["pro"]="pro" ["all"]="frontend backend webcomponent pro" ) # Logging functions log_info() { echo -e "${BLUE}[INFO]${NC} $1" } log_success() { echo -e "${GREEN}[SUCCESS]${NC} $1" } log_warning() { echo -e "${YELLOW}[WARNING]${NC} $1" } log_error() { echo -e "${RED}[ERROR]${NC} $1" >&2 } # Help function show_help() { cat </dev/null | wc -l) if [ "$d_ts_files" -eq 0 ]; then log_warning "No TypeScript declaration files found in source directory '$SOURCE_DIR'" return 1 fi log_info "Found $d_ts_files TypeScript declaration files in source directory" return 0 } # Validate and prepare target directories validate_targets() { local targets="$1" local failed_targets="" log_info "Validating target directories..." for target in $targets; do local target_dir="${TARGET_DIRECTORIES[$target]}" if [ -z "$target_dir" ]; then log_error "No directory configured for target: $target" failed_targets="$failed_targets $target" continue fi # Try to create the directory structure to validate the path if [ "$DRY_RUN" = "false" ]; then local test_dir="$target_dir" if ! mkdir -p "$test_dir" 2>/dev/null; then log_error "Cannot create directory for target '$target': $test_dir" failed_targets="$failed_targets $target" continue fi fi [ "$VERBOSE" = "true" ] && log_info "Target '$target' validated: $target_dir" done if [ -n "$failed_targets" ]; then log_error "Failed to validate targets:$failed_targets" return 1 fi return 0 } # Add headers to source files add_headers_to_source() { log_info "Adding headers to source files..." local count=0 local temp_file_list temp_file_list=$(mktemp) find "$SOURCE_DIR" -type f -name "*.ts" >"$temp_file_list" while IFS= read -r file; do if ! grep -qF "$HEADER_KEY" "$file"; then if [ "$DRY_RUN" = "true" ]; then echo " Would add header to: $file" else if printf "%s\n\n%s" "$HEADER" "$(cat "$file")" >"${file}.tmp" && mv "${file}.tmp" "$file"; then [ "$VERBOSE" = "true" ] && echo " Added header to: $file" count=$((count + 1)) else log_error "Failed to add header to: $file" rm -f "$temp_file_list" return 1 fi fi else [ "$VERBOSE" = "true" ] && echo " Header already exists in: $file" fi done <"$temp_file_list" rm -f "$temp_file_list" if [ "$DRY_RUN" = "false" ]; then log_success "Headers added to $count files" fi } # Copy files with headers to target directory copy_files_with_headers() { local target_dir="$1" local target_name="$2" log_info "Syncing types to $target_name ($target_dir)..." # Create target directory and all necessary parent directories if [ "$DRY_RUN" = "true" ]; then echo " Would create directory: $target_dir" else if ! mkdir -p "$target_dir"; then log_error "Failed to create target directory: $target_dir" return 1 fi [ "$VERBOSE" = "true" ] && log_info "Created/verified target directory: $target_dir" fi # Determine source path based on target local source_path="$SOURCE_DIR" if [ "$target_name" = "webcomponent" ]; then source_path="$SOURCE_DIR/webcomponent" if [ ! -d "$source_path" ]; then log_warning "Webcomponent source directory '$source_path' does not exist. Skipping webcomponent sync." return 0 fi fi local file_count=0 local temp_file_list temp_file_list=$(mktemp) find "$source_path" -type f -name "*.ts" >"$temp_file_list" while IFS= read -r file; do local relative_path if [ "$target_name" = "webcomponent" ]; then # For webcomponent, remove the webcomponent prefix from path relative_path="${file#$SOURCE_DIR/webcomponent/}" else relative_path="${file#$SOURCE_DIR/}" fi local dest_file="$target_dir/$relative_path" local dest_dir dest_dir=$(dirname "$dest_file") if [ "$DRY_RUN" = "true" ]; then echo " Would copy: $file -> $dest_file" else if ! mkdir -p "$dest_dir"; then log_error "Failed to create directory: $dest_dir" rm -f "$temp_file_list" return 1 fi if printf "%s\n\n%s" "$HEADER" "$(cat "$file")" >"$dest_file"; then [ "$VERBOSE" = "true" ] && echo " Copied: $file -> $dest_file" file_count=$((file_count + 1)) else log_error "Failed to copy: $file -> $dest_file" rm -f "$temp_file_list" return 1 fi fi done <"$temp_file_list" rm -f "$temp_file_list" if [ "$DRY_RUN" = "false" ]; then log_success "Synced $file_count files to $target_name" fi } # Resolve targets from input resolve_targets() { local input="$1" local targets="" # Check if input is a group if [ -n "${TARGET_GROUPS[$input]:-}" ]; then targets="${TARGET_GROUPS[$input]}" # Check if input is a single target elif [ -n "${TARGET_DIRECTORIES[$input]:-}" ]; then targets="$input" else log_error "Unknown target or group: '$input'" log_info "Use --list-targets to see available options" exit 1 fi echo "$targets" } # Main sync function sync_types() { local targets="$1" log_info "Starting type declaration synchronization..." [ "$DRY_RUN" = "true" ] && log_warning "DRY RUN MODE - No files will be modified" # Validate source directory validate_source || exit 1 # Validate target directories validate_targets "$targets" || exit 1 # Add headers to source if requested [ "$ADD_HEADERS" = "true" ] && add_headers_to_source # Process each target local success_count=0 local total_count=0 for target in $targets; do total_count=$((total_count + 1)) local target_dir="${TARGET_DIRECTORIES[$target]}" if [ -z "$target_dir" ]; then log_error "No directory configured for target: $target" continue fi if copy_files_with_headers "$target_dir" "$target"; then success_count=$((success_count + 1)) fi done # Summary echo if [ "$DRY_RUN" = "true" ]; then log_info "Dry run completed. $total_count targets would be processed." else log_success "Type declaration synchronization completed: $success_count/$total_count targets successful" fi } # Parse command line arguments DRY_RUN="false" VERBOSE="false" ADD_HEADERS="false" TARGET_INPUT="" while [ $# -gt 0 ]; do case $1 in -h | --help) show_help exit 0 ;; -v | --verbose) VERBOSE="true" shift ;; -n | --dry-run) DRY_RUN="true" shift ;; --add-headers) ADD_HEADERS="true" shift ;; --list-targets) list_targets exit 0 ;; -*) log_error "Unknown option: $1" show_help exit 1 ;; *) if [ -n "$TARGET_INPUT" ]; then log_error "Multiple targets specified. Use 'all' or a specific target/group." exit 1 fi TARGET_INPUT="$1" shift ;; esac done # Default to 'all' if no target specified TARGET_INPUT="${TARGET_INPUT:-all}" # Resolve and execute targets=$(resolve_targets "$TARGET_INPUT") sync_types "$targets"