#!/usr/bin/env bash # ============================================================================== # OSMAP Embed Map & Token CLI (Multi-Domain Support) # ============================================================================== # Supports: # 1. New Share-Map System -> app.osmap.id (API: api.osmap.id/apps/token/share-map) # 2. OSMAP KAI System -> live.osmap.id & beta.osmap.id (API: /api/apps/token) # ============================================================================== set -e # Color definitions RED='\033[0;31m' GREEN='\033[0;32m' BLUE='\033[0;34m' CYAN='\033[0;36m' YELLOW='\033[1;33m' MAGENTA='\033[0;35m' BOLD='\033[1m' NC='\033[0m' # No Color # Cache directory CACHE_DIR="${HOME}/.cache/osmap" mkdir -p "$CACHE_DIR" # Config file for saved credentials CONFIG_FILE=".osmap_credentials" # ------------------------------------------------------------------------------ # 1. NEW SHARE-MAP SYSTEM (app.osmap.id) # ------------------------------------------------------------------------------ APP_OSMAP_DOMAIN="app.osmap.id" APP_OSMAP_API="https://api.osmap.id" SHARE_MAP_EXPIRES_IN=86400 # Share Map Presets: "Key|Map_ID|Name|App_ID|App_Secret|Description" SHARE_MAP_PRESETS=( "accelerometer|94|Map Accelerometer|6f728437e6c4d361fb811913b8acd70e|ab9419a7fed7c51a6ff6daf501d408f2aed25c0ccd148a6c18b76f54949f55d8|Accelerometer Vibration & Track Monitoring" "rocc|46|Map ROCC|6f728437e6c4d361fb811913b8acd70e|ab9419a7fed7c51a6ff6daf501d408f2aed25c0ccd148a6c18b76f54949f55d8|Railway Operations Control Center" "genset|74|Map Genset|6f728437e6c4d361fb811913b8acd70e|ab9419a7fed7c51a6ff6daf501d408f2aed25c0ccd148a6c18b76f54949f55d8|Genset & Power Telemetry Monitoring" "rcs|72|Map RCS|6f728437e6c4d361fb811913b8acd70e|ab9419a7fed7c51a6ff6daf501d408f2aed25c0ccd148a6c18b76f54949f55d8|Railway Cargo System Monitoring" "jpl|70|Map JPL|2ee1aa4876f6b7fa3c43c75ca1c83139|073d0929a74bb664c402de98d24153c1f9f2f648d59c381f2fef3c32610fa174|Perlintasan Sebidang (JPL) Monitoring" ) SHARE_FALLBACK_APP_ID="6f728437e6c4d361fb811913b8acd70e" SHARE_FALLBACK_APP_SECRET="ab9419a7fed7c51a6ff6daf501d408f2aed25c0ccd148a6c18b76f54949f55d8" # ------------------------------------------------------------------------------ # 2. OSMAP KAI SYSTEM (live.osmap.id & beta.osmap.id) # ------------------------------------------------------------------------------ DEFAULT_KAI_ENV="live" DEFAULT_KAI_APP_ID="IrSIcf06QRwUCmsRCZ0JvsVibSfuPUG4" DEFAULT_KAI_APP_SECRET="Z8tPOBHGbwWu9TrIddRqkiDFDymtiPAhMNbSz6aUOOTkqdZoQYuTWXTra5m2mPQa" KAI_ROUTES=( "executive|Executive Map|/executive" "rolling|Rolling Map|/rolling" "iris-jpl|IRIS JPL|/iris-jpl" "iris-jpl-v2|IRIS JPL (v2)|/v2/iris-jpl" "kai-accelerometer|Executive Accelerometer|/executive/accelerometer" "kai-genset|Genset Monitoring|/genset" "managerial|Managerial / Asset View|/managerial" "fatigue|Fatigue Monitoring|/fatigue" "sigap-tracker|SIGAP Tracker|/sigap-tracker" "sigap-dashboard|SIGAP Dashboard|/sigap-dashboard" "kai-rcs|Railway Cargo System (RCS)|/railway-cargo-system" ) # ------------------------------------------------------------------------------ # Common Utilities # ------------------------------------------------------------------------------ copy_to_clipboard() { local text="$1" if command -v pbcopy >/dev/null 2>&1; then echo -n "$text" | pbcopy return 0 elif command -v xclip >/dev/null 2>&1; then echo -n "$text" | xclip -selection clipboard return 0 elif command -v xsel >/dev/null 2>&1; then echo -n "$text" | xsel --clipboard --input return 0 fi return 1 } open_url() { local url="$1" if command -v open >/dev/null 2>&1; then open "$url" elif command -v xdg-open >/dev/null 2>&1; then xdg-open "$url" >/dev/null 2>&1 & elif command -v start >/dev/null 2>&1; then start "$url" else echo -e "${YELLOW}Could not detect browser launcher. URL:${NC} $url" fi } read_input() { if [[ -t 0 ]]; then read "$@" elif [[ -e /dev/tty ]]; then read "$@" < /dev/tty else read "$@" fi } # ------------------------------------------------------------------------------ # KAI Token Helpers (live / beta / local) # ------------------------------------------------------------------------------ get_kai_base_url() { local env="$1" case "$env" in live) echo "https://live.osmap.id" ;; beta) echo "https://beta.osmap.id" ;; local) echo "http://localhost:8000" ;; demo) echo "https://demo.osmap.id" ;; http*://*) echo "$env" ;; *) echo "https://${env}" ;; esac } get_kai_cache_file() { local base_url="$1" local sanitized sanitized=$(echo "$base_url" | tr -d ':/' | tr '.' '_') echo "${CACHE_DIR}/kai_token_${sanitized}.json" } get_valid_kai_token() { local base_url="$1" local app_id="$2" local app_secret="$3" local cache_file cache_file=$(get_kai_cache_file "$base_url") if [[ -f "$cache_file" ]]; then local token expires_at token=$(jq -r '.access_token // empty' "$cache_file" 2>/dev/null || true) expires_at=$(jq -r '.expires_at // empty' "$cache_file" 2>/dev/null || true) if [[ -n "$token" && -n "$expires_at" ]]; then local expiry_epoch=0 if date -j -f "%Y-%m-%dT%H:%M:%S" "${expires_at:0:19}" +%s >/dev/null 2>&1; then expiry_epoch=$(date -j -f "%Y-%m-%dT%H:%M:%S" "${expires_at:0:19}" +%s) elif date -d "$expires_at" +%s >/dev/null 2>&1; then expiry_epoch=$(date -d "$expires_at" +%s) fi local now_epoch now_epoch=$(date +%s) if [[ $expiry_epoch -gt $((now_epoch + 60)) ]]; then echo "$token" return 0 fi fi fi # Fetch new KAI token local endpoint="${base_url}/api/apps/token" local payload payload=$(jq -n --arg aid "$app_id" --arg asec "$app_secret" '{app_id: $aid, app_secret: $asec, expires_in_hours: 24}') local response response=$(curl -s --location "$endpoint" -H "Content-Type: application/json" -d "$payload") local token token=$(echo "$response" | jq -r '.access_token // empty' 2>/dev/null || true) if [[ -z "$token" ]]; then local err_msg err_msg=$(echo "$response" | jq -r '.message // "Failed to obtain KAI token"' 2>/dev/null || echo "$response") echo -e "${RED}Error fetching KAI token from ${base_url}:${NC} $err_msg" >&2 return 1 fi echo "$response" > "$cache_file" chmod 600 "$cache_file" echo "$token" } # ------------------------------------------------------------------------------ # Share Map Helpers (app.osmap.id) # ------------------------------------------------------------------------------ get_share_cache_file() { local map_id="$1" echo "${CACHE_DIR}/map_${map_id}.json" } generate_share_token() { local map_id="$1" local app_id="$2" local app_secret="$3" local expires_in="${4:-$SHARE_MAP_EXPIRES_IN}" local force_fresh="${5:-false}" if [[ "$force_fresh" != "true" ]]; then local cache_file cache_file=$(get_share_cache_file "$map_id") if [[ -f "$cache_file" ]]; then local token expires_at token=$(jq -r '.token // empty' "$cache_file" 2>/dev/null || true) expires_at=$(jq -r '.expires_at // empty' "$cache_file" 2>/dev/null || true) if [[ -n "$token" && -n "$expires_at" ]]; then local expiry_epoch=0 if date -j -f "%Y-%m-%dT%H:%M:%S" "${expires_at:0:19}" +%s >/dev/null 2>&1; then expiry_epoch=$(date -j -f "%Y-%m-%dT%H:%M:%S" "${expires_at:0:19}" +%s) elif date -d "$expires_at" +%s >/dev/null 2>&1; then expiry_epoch=$(date -d "$expires_at" +%s) fi local now_epoch now_epoch=$(date +%s) if [[ $expiry_epoch -gt $((now_epoch + 60)) ]]; then echo "$token" return 0 fi fi fi fi local endpoint="${APP_OSMAP_API}/apps/token/share-map" local payload payload=$(jq -n \ --arg aid "$app_id" \ --arg asec "$app_secret" \ --argjson exp "$expires_in" \ --argjson mid "$map_id" \ '{app_id: $aid, app_secret: $asec, expires_in: $exp, map_id: $mid}') local response response=$(curl -s -X POST "$endpoint" -H "Content-Type: application/json" -d "$payload") local is_success token is_success=$(echo "$response" | jq -r '.status // .success // false' 2>/dev/null || echo "false") token=$(echo "$response" | jq -r '.data.token // .token // empty' 2>/dev/null || true) # Automatic fallback if first attempt lacked permissions if [[ ("$is_success" != "true" || -z "$token") && "$app_id" != "$SHARE_FALLBACK_APP_ID" ]]; then local error_code error_code=$(echo "$response" | jq -r '.code // empty' 2>/dev/null || true) if [[ "$error_code" == "SHARE_MAP_NO_PERMISSION" || "$error_code" == "UNAUTHORIZED" ]]; then payload=$(jq -n \ --arg aid "$SHARE_FALLBACK_APP_ID" \ --arg asec "$SHARE_FALLBACK_APP_SECRET" \ --argjson exp "$expires_in" \ --argjson mid "$map_id" \ '{app_id: $aid, app_secret: $asec, expires_in: $exp, map_id: $mid}') response=$(curl -s -X POST "$endpoint" -H "Content-Type: application/json" -d "$payload") is_success=$(echo "$response" | jq -r '.status // .success // false' 2>/dev/null || echo "false") token=$(echo "$response" | jq -r '.data.token // .token // empty' 2>/dev/null || true) fi fi if [[ "$is_success" != "true" || -z "$token" ]]; then local error_msg error_msg=$(echo "$response" | jq -r '.message // "Failed to generate share-map token"' 2>/dev/null || echo "$response") echo -e "${RED}Error generating share token for Map ${map_id}:${NC} $error_msg" >&2 return 1 fi local cache_file cache_file=$(get_share_cache_file "$map_id") local expires_at expires_at=$(echo "$response" | jq -r '.data.expires_at // empty' 2>/dev/null || true) jq -n \ --arg token "$token" \ --argjson map_id "$map_id" \ --arg expires_at "$expires_at" \ '{token: $token, map_id: $map_id, expires_at: $expires_at}' > "$cache_file" chmod 600 "$cache_file" echo "$token" } # ------------------------------------------------------------------------------ # Display Functions # ------------------------------------------------------------------------------ display_share_map() { local key="$1" local map_id="$2" local name="$3" local app_id="$4" local app_secret="$5" local desc="$6" local auto_open="$7" local auto_copy="$8" local show_iframe="$9" echo -e "${CYAN}Generating share token for ${BOLD}${name}${NC}${CYAN} (Map ID: ${map_id})...${NC}" local token if ! token=$(generate_share_token "$map_id" "$app_id" "$app_secret" "$SHARE_MAP_EXPIRES_IN" "false"); then return 1 fi local embed_url="https://${APP_OSMAP_DOMAIN}/maps/embed/${map_id}?token=${token}" local iframe_code="" echo "" echo -e "${BOLD}${GREEN}✔ ${name}${NC} (Map ID: ${BOLD}${map_id}${NC})" if [[ -n "$desc" ]]; then echo -e " ${YELLOW}Description:${NC} ${desc}" fi echo -e " ${BOLD}${CYAN}Embed URL:${NC} ${embed_url}" echo -e " ${BOLD}${MAGENTA}Token:${NC} ${token}" if [[ "$show_iframe" == "true" ]]; then echo -e " ${BOLD}${YELLOW}Iframe Code:${NC}" echo " ${iframe_code}" fi echo "" if [[ "$auto_copy" == "true" ]]; then if copy_to_clipboard "$embed_url"; then echo -e " ${GREEN}✓ Copied Embed URL to clipboard!${NC}" fi fi if [[ "$auto_open" == "true" ]]; then echo -e " ${CYAN}Opening in browser...${NC}" open_url "$embed_url" fi } display_kai_map() { local name="$1" local path="$2" local base_url="$3" local app_id="$4" local app_secret="$5" local auto_open="$6" local auto_copy="$7" echo -e "${CYAN}Retrieving token for ${base_url}...${NC}" local token if ! token=$(get_valid_kai_token "$base_url" "$app_id" "$app_secret"); then return 1 fi local full_url="${base_url}${path}?token=${token}" echo "" echo -e "${BOLD}${GREEN}✔ ${name}${NC} (${base_url})" echo -e " ${BOLD}${CYAN}Embed URL:${NC} ${full_url}" echo -e " ${BOLD}${MAGENTA}Token:${NC} ${token}" echo "" if [[ "$auto_copy" == "true" ]]; then if copy_to_clipboard "$full_url"; then echo -e " ${GREEN}✓ Copied URL to clipboard!${NC}" fi fi if [[ "$auto_open" == "true" ]]; then echo -e " ${CYAN}Opening in browser...${NC}" open_url "$full_url" fi } print_all_curls() { echo "" echo -e "${BOLD}${CYAN}========================================================================================${NC}" echo -e "${BOLD}${CYAN} OSMAP cURL Reference (All Domains) ${NC}" echo -e "${BOLD}${CYAN}========================================================================================${NC}" echo "" echo -e "${BOLD}${YELLOW}--- 1. NEW SHARE-MAP SYSTEM (Domain: app.osmap.id) ---${NC}" echo "" local idx=1 for preset in "${SHARE_MAP_PRESETS[@]}"; do IFS="|" read -r key map_id name app_id app_secret desc <<< "$preset" echo -e "${BOLD}${GREEN}${idx}. ${name}${NC} (Map ID: ${map_id})" cat << EOF curl -X POST "https://api.osmap.id/apps/token/share-map" \\ -H "Content-Type: application/json" \\ -d '{"app_id":"${app_id}","app_secret":"${app_secret}","expires_in":86400,"map_id":${map_id}}' EOF echo "" ((idx++)) done echo -e "${BOLD}${YELLOW}--- 2. OSMAP KAI SYSTEM (Domain: live.osmap.id) ---${NC}" echo "" cat << EOF curl -X POST "https://live.osmap.id/api/apps/token" \\ -H "Content-Type: application/json" \\ -d '{"app_id":"${DEFAULT_KAI_APP_ID}","app_secret":"${DEFAULT_KAI_APP_SECRET}","expires_in_hours":24}' EOF echo "" echo -e "${BOLD}${YELLOW}--- 3. OSMAP KAI SYSTEM (Domain: beta.osmap.id) ---${NC}" echo "" cat << EOF curl -X POST "https://beta.osmap.id/api/apps/token" \\ -H "Content-Type: application/json" \\ -d '{"app_id":"${DEFAULT_KAI_APP_ID}","app_secret":"${DEFAULT_KAI_APP_SECRET}","expires_in_hours":24}' EOF echo "" } print_all_share_table() { echo "" echo -e "${BOLD}${CYAN}========================================================================================${NC}" echo -e "${BOLD}${CYAN} OSMAP Share Map Embed URLs (Domain: ${APP_OSMAP_DOMAIN}) ${NC}" echo -e "${BOLD}${CYAN}========================================================================================${NC}" echo "" printf "%-5s | %-20s | %s\n" "ID" "Map Name" "Embed URL with Token" printf "%-5s-+-%-20s-+-%s\n" "-----" "--------------------" "----------------------------------------------------------------------------------" for preset in "${SHARE_MAP_PRESETS[@]}"; do IFS="|" read -r key map_id name app_id app_secret desc <<< "$preset" local token token=$(generate_share_token "$map_id" "$app_id" "$app_secret" "$SHARE_MAP_EXPIRES_IN" "false" 2>/dev/null || echo "") if [[ -n "$token" ]]; then printf "%-5s | %-20s | %s\n" "$map_id" "$name" "https://${APP_OSMAP_DOMAIN}/maps/embed/${map_id}?token=${token}" else printf "%-5s | %-20s | %s\n" "$map_id" "$name" "${RED}[Failed to generate token]${NC}" fi done echo "" } print_all_kai_table() { local env="${1:-live}" local base_url base_url=$(get_kai_base_url "$env") echo "" echo -e "${BOLD}${CYAN}========================================================================================${NC}" echo -e "${BOLD}${CYAN} OSMAP KAI Embed URLs (Domain / Base URL: ${base_url}) ${NC}" echo -e "${BOLD}${CYAN}========================================================================================${NC}" echo "" local token token=$(get_valid_kai_token "$base_url" "$DEFAULT_KAI_APP_ID" "$DEFAULT_KAI_APP_SECRET" 2>/dev/null || echo "") if [[ -z "$token" ]]; then echo -e "${RED}Failed to obtain valid token for ${base_url}${NC}" return 1 fi printf "%-30s | %s\n" "Map Feature" "Complete Embed URL" printf "%-30s-+-%s\n" "------------------------------" "------------------------------------------------------------" for item in "${KAI_ROUTES[@]}"; do IFS="|" read -r key name path <<< "$item" printf "%-30s | %s\n" "$name" "${base_url}${path}?token=${token}" done echo "" } # ------------------------------------------------------------------------------ # Interactive Menu # ------------------------------------------------------------------------------ show_interactive_menu() { local current_kai_env="$DEFAULT_KAI_ENV" while true; do local kai_base kai_base=$(get_kai_base_url "$current_kai_env") echo "" echo -e "${BOLD}${CYAN}╔══════════════════════════════════════════════════════════════════════════╗${NC}" echo -e "${BOLD}${CYAN}║ OSMAP Universal Embed Map Navigator ║${NC}" echo -e "${BOLD}${CYAN}╠══════════════════════════════════════════════════════════════════════════╣${NC}" echo -e "${CYAN}║ 1. Share-Map Domain: ${BOLD}${YELLOW}${APP_OSMAP_DOMAIN}${NC}${CYAN} (API: api.osmap.id/apps/token/share-map)${NC}" echo -e "${CYAN}║ 2. KAI Active Domain: ${BOLD}${YELLOW}${kai_base}${NC}${CYAN} (live.osmap.id / beta.osmap.id)${NC}" echo -e "${BOLD}${CYAN}╚══════════════════════════════════════════════════════════════════════════╝${NC}" echo "" echo -e "${BOLD}${YELLOW}─── [A] SHARE-MAP PRESETS (app.osmap.id) ───${NC}" local idx=1 for preset in "${SHARE_MAP_PRESETS[@]}"; do IFS="|" read -r key map_id name app_id app_secret desc <<< "$preset" printf " ${BOLD}%2d)${NC} %-22s ${CYAN}(Map ID: %-2s)${NC} - %s\n" "$idx" "$name" "$map_id" "$desc" ((idx++)) done echo "" echo -e "${BOLD}${YELLOW}─── [B] OSMAP KAI ROUTES (${current_kai_env}: ${kai_base}) ───${NC}" local kai_start=$idx for item in "${KAI_ROUTES[@]}"; do IFS="|" read -r key name path <<< "$item" printf " ${BOLD}%2d)${NC} %-25s ${CYAN}%s${NC}\n" "$idx" "$name" "$path" ((idx++)) done echo "" echo -e "${BOLD}${YELLOW}─── [C] UTILITIES & SWITCH DOMAIN ───${NC}" printf " ${BOLD}%2d)${NC} %s\n" "$idx" "Display All app.osmap.id Embed URLs Table" local opt_table_share=$idx ((idx++)) printf " ${BOLD}%2d)${NC} %s\n" "$idx" "Display All KAI Embed URLs Table (${current_kai_env})" local opt_table_kai=$idx ((idx++)) printf " ${BOLD}%2d)${NC} %s\n" "$idx" "Print All cURL Commands (app.osmap.id, live.osmap.id, beta.osmap.id)" local opt_curls=$idx ((idx++)) printf " ${BOLD}%2d)${NC} %s\n" "$idx" "Switch KAI Environment (live / beta / local / custom URL)" local opt_switch_env=$idx ((idx++)) printf " ${BOLD}%2d)${NC} %s\n" "$idx" "Custom Map ID (app.osmap.id)" local opt_custom_mid=$idx ((idx++)) printf " ${BOLD} 0)${NC} %s\n" "Exit" echo "" read_input -r -p "Select an option [0-$((idx-1))]: " choice if [[ "$choice" == "0" || "$choice" == "q" || "$choice" == "exit" ]]; then echo -e "${GREEN}Goodbye!${NC}" exit 0 fi # Option: Share Map Presets (1..5) if [[ "$choice" -ge 1 && "$choice" -le ${#SHARE_MAP_PRESETS[@]} ]]; then local selected="${SHARE_MAP_PRESETS[$((choice-1))]}" IFS="|" read -r key map_id name app_id app_secret desc <<< "$selected" display_share_map "$key" "$map_id" "$name" "$app_id" "$app_secret" "$desc" "false" "true" "true" echo "" read_input -r -p "Open this map in default browser? (Y/n): " open_choice if [[ ! "$open_choice" =~ ^[Nn]$ ]]; then local token token=$(generate_share_token "$map_id" "$app_id" "$app_secret" "$SHARE_MAP_EXPIRES_IN" "false") open_url "https://${APP_OSMAP_DOMAIN}/maps/embed/${map_id}?token=${token}" fi # Option: KAI Routes elif [[ "$choice" -ge "$kai_start" && "$choice" -lt "$opt_table_share" ]]; then local kai_idx=$(( choice - kai_start )) local selected_kai="${KAI_ROUTES[$kai_idx]}" IFS="|" read -r key name path <<< "$selected_kai" display_kai_map "$name" "$path" "$kai_base" "$DEFAULT_KAI_APP_ID" "$DEFAULT_KAI_APP_SECRET" "false" "true" echo "" read_input -r -p "Open this route in default browser? (Y/n): " open_choice if [[ ! "$open_choice" =~ ^[Nn]$ ]]; then local token token=$(get_valid_kai_token "$kai_base" "$DEFAULT_KAI_APP_ID" "$DEFAULT_KAI_APP_SECRET") open_url "${kai_base}${path}?token=${token}" fi elif [[ "$choice" -eq "$opt_table_share" ]]; then print_all_share_table elif [[ "$choice" -eq "$opt_table_kai" ]]; then print_all_kai_table "$current_kai_env" elif [[ "$choice" -eq "$opt_curls" ]]; then print_all_curls elif [[ "$choice" -eq "$opt_switch_env" ]]; then echo "" read_input -r -p "Enter environment [live, beta, local, demo, or custom URL]: " new_env if [[ -n "$new_env" ]]; then current_kai_env="$new_env" echo -e "${GREEN}Switched KAI domain to:${NC} $(get_kai_base_url "$current_kai_env")" fi elif [[ "$choice" -eq "$opt_custom_mid" ]]; then echo "" read_input -r -p "Enter Map ID: " custom_mid read_input -r -p "Enter App ID [Press Enter for default]: " custom_aid read_input -r -p "Enter App Secret [Press Enter for default]: " custom_asec custom_aid="${custom_aid:-$SHARE_FALLBACK_APP_ID}" custom_asec="${custom_asec:-$SHARE_FALLBACK_APP_SECRET}" if [[ -n "$custom_mid" ]]; then display_share_map "custom" "$custom_mid" "Custom Map ${custom_mid}" "$custom_aid" "$custom_asec" "Custom Map ID" "false" "true" "true" fi else echo -e "${RED}Invalid selection.${NC}" fi done } # ------------------------------------------------------------------------------ # Help / Usage # ------------------------------------------------------------------------------ show_help() { cat << EOF OSMAP Embed Map & Token CLI Tool (Multi-Domain) Supported Domains & APIs: 1. app.osmap.id -> Share-Map API (https://api.osmap.id/apps/token/share-map) 2. live.osmap.id -> KAI App Token (https://live.osmap.id/api/apps/token) 3. beta.osmap.id -> KAI App Token (https://beta.osmap.id/api/apps/token) Usage: ./osmap-embed.sh [command|map|route] [options] Commands: interactive Launch interactive navigator menu (default) curls Display all cURL commands for app.osmap.id, live.osmap.id, beta.osmap.id all Display embed URLs table for app.osmap.id (or with --env live/beta for KAI) token Generate and print only the token string validate Validate KAI token revoke Revoke KAI app token Share Map Presets (app.osmap.id): accelerometer | 94 Map Accelerometer (Map ID: 94) rocc | 46 Map ROCC (Map ID: 46) genset | 74 Map Genset (Map ID: 74) rcs | 72 Map RCS (Map ID: 72) jpl | 70 Map JPL (Map ID: 70) KAI Routes (live.osmap.id / beta.osmap.id): executive /executive rolling /rolling iris-jpl /iris-jpl iris-jpl-v2 /v2/iris-jpl kai-accelerometer /executive/accelerometer kai-genset /genset managerial /managerial fatigue /fatigue sigap-tracker /sigap-tracker sigap-dashboard /sigap-dashboard kai-rcs /railway-cargo-system Options: -e, --env Environment for KAI: live (default), beta, local, or URL --domain Override Share-Map domain (default: ${APP_OSMAP_DOMAIN}) --map-id Specify custom Map ID for app.osmap.id -o, --open Automatically open URL in default browser -c, --copy Copy URL to clipboard --iframe Show