General-purpose utility functions for class name merging, async delays, string manipulation, JSON-LD serialization, object cloning, and environment-based Slack URL resolution. ## Key Components | Export | Signature | Description | |---|---|---| | `cn` | `(...inputs: ClassValue[]) => string` | Merges Tailwind CSS class names using `clsx` + `tailwind-merge` | | `delay` | `(ms: number) => Promise` | Async sleep helper | | `generateRandomString` | `(length?: number) => string` | Alphanumeric random string generator (default length: 8) | | `truncateString` | `(str, maxLength, suffix?) => string` | Truncates with configurable suffix (default: `"..."`) | | `serializeJsonLd` | `(schema: unknown) => string` | XSS-safe JSON-LD serializer — escapes `<` as `\u003c` | | `deepClone` | `(obj: T) => T` | Structural clone via JSON round-trip | | `getSlackCommunityJoinUrl` | `() => string` | Reads `NEXT_PUBLIC_SLACK_COMMUNITY_JOIN_URL` with fallback to OpenMSP invite | ## Usage Example ```typescript import { cn, delay, generateRandomString, truncateString, serializeJsonLd, deepClone, getSlackCommunityJoinUrl, } from "@/lib/utils/common" // Merge Tailwind classes (handles conflicts) const cls = cn("px-4 py-2", isActive && "bg-blue-500", "px-6") // "py-2 bg-blue-500 px-6" // Async delay in an async function await delay(1500) // waits 1.5 seconds // Random token generation const token = generateRandomString(16) // e.g. "aZ3kR8mQpL2nWx7T" // Safe truncation truncateString("OpenFrame AI Platform", 14) // "OpenFrame AI..." // Safe JSON-LD for attack" }) // → '{"@type":"WebSite","name":"\\u003c/script>attack"}' // Deep clone without reference sharing const copy = deepClone({ nested: { value: 42 } }) // Slack community URL (set via env or uses OpenMSP fallback) const slackUrl = getSlackCommunityJoinUrl() ``` > **Security note:** `serializeJsonLd` must be used for all `