Initial Commit
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
import { clsx, type ClassValue } from "clsx"
|
||||
import { twMerge } from "tailwind-merge"
|
||||
|
||||
export function cn(...inputs: ClassValue[]) {
|
||||
return twMerge(clsx(inputs))
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
// crypto.randomUUID() 는 secure context (HTTPS / localhost) 전용.
|
||||
// HTTP 환경에서도 깨지지 않도록 fallback 둠.
|
||||
//
|
||||
// 1) crypto.randomUUID() 가능하면 그대로 — RFC4122 v4 보장
|
||||
// 2) 안 되면 crypto.getRandomValues() 로 v4 형식 직접 조립 (HTTP에서도 동작)
|
||||
// 3) 최후 fallback — Math.random + Date.now (충돌 가능성 있지만 메시지 id 용도면 충분)
|
||||
export function randomId(): string {
|
||||
const c = globalThis.crypto
|
||||
|
||||
if (c?.randomUUID) {
|
||||
return c.randomUUID()
|
||||
}
|
||||
|
||||
if (c?.getRandomValues) {
|
||||
const bytes = new Uint8Array(16)
|
||||
c.getRandomValues(bytes)
|
||||
bytes[6] = (bytes[6] & 0x0f) | 0x40 // version 4
|
||||
bytes[8] = (bytes[8] & 0x3f) | 0x80 // variant 10
|
||||
const hex = Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("")
|
||||
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`
|
||||
}
|
||||
|
||||
return `${Date.now().toString(16)}-${Math.random().toString(16).slice(2, 10)}`
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
import { describe, it, expect } from "vitest"
|
||||
import { formatRelativeKo } from "./relativeTime"
|
||||
|
||||
describe("formatRelativeKo", () => {
|
||||
it("몇 분 전 한글 접미사를 낸다", () => {
|
||||
const fiveMinAgo = new Date(Date.now() - 5 * 60_000).toISOString()
|
||||
const out = formatRelativeKo(fiveMinAgo)
|
||||
expect(out).toContain("분")
|
||||
expect(out).toContain("전")
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,7 @@
|
||||
import { formatDistanceToNow } from "date-fns"
|
||||
import { ko } from "date-fns/locale"
|
||||
|
||||
/** ISO 시각을 "5분 전" 같은 한글 상대시간으로. */
|
||||
export function formatRelativeKo(iso: string): string {
|
||||
return formatDistanceToNow(new Date(iso), { addSuffix: true, locale: ko })
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
export function sleep(ms: number): Promise<void> {
|
||||
return new Promise((resolve) => setTimeout(resolve, ms))
|
||||
}
|
||||
Reference in New Issue
Block a user