@shadowob/shared
Advanced tools
| // src/constants/events.ts | ||
| var CLIENT_EVENTS = { | ||
| CHANNEL_JOIN: "channel:join", | ||
| CHANNEL_LEAVE: "channel:leave", | ||
| MESSAGE_SEND: "message:send", | ||
| MESSAGE_TYPING: "message:typing", | ||
| PRESENCE_UPDATE: "presence:update" | ||
| }; | ||
| var SERVER_EVENTS = { | ||
| MESSAGE_NEW: "message:new", | ||
| MESSAGE_UPDATE: "message:update", | ||
| MESSAGE_DELETE: "message:delete", | ||
| MEMBER_TYPING: "member:typing", | ||
| MEMBER_JOIN: "member:join", | ||
| MEMBER_LEAVE: "member:leave", | ||
| PRESENCE_CHANGE: "presence:change", | ||
| REACTION_ADD: "reaction:add", | ||
| REACTION_REMOVE: "reaction:remove", | ||
| NOTIFICATION_NEW: "notification:new", | ||
| DM_MESSAGE_NEW: "dm:message:new" | ||
| }; | ||
| // src/constants/limits.ts | ||
| var LIMITS = { | ||
| /** Max message content length */ | ||
| MESSAGE_CONTENT_MAX: 4e3, | ||
| /** Max username length */ | ||
| USERNAME_MAX: 32, | ||
| /** Min username length */ | ||
| USERNAME_MIN: 3, | ||
| /** Max display name length */ | ||
| DISPLAY_NAME_MAX: 64, | ||
| /** Max server name length */ | ||
| SERVER_NAME_MAX: 100, | ||
| /** Max channel name length */ | ||
| CHANNEL_NAME_MAX: 100, | ||
| /** Max thread name length */ | ||
| THREAD_NAME_MAX: 100, | ||
| /** Max file upload size (10MB) */ | ||
| FILE_UPLOAD_MAX_SIZE: 10 * 1024 * 1024, | ||
| /** Messages per page (cursor pagination) */ | ||
| MESSAGES_PER_PAGE: 50, | ||
| /** Max servers per user */ | ||
| SERVERS_PER_USER_MAX: 100, | ||
| /** Max channels per server */ | ||
| CHANNELS_PER_SERVER_MAX: 200, | ||
| /** Invite code length */ | ||
| INVITE_CODE_LENGTH: 8, | ||
| /** Password min length */ | ||
| PASSWORD_MIN: 8, | ||
| /** Max reactions per message per user */ | ||
| REACTIONS_PER_MESSAGE_MAX: 20 | ||
| }; | ||
| export { | ||
| CLIENT_EVENTS, | ||
| SERVER_EVENTS, | ||
| LIMITS | ||
| }; |
| // src/utils/index.ts | ||
| import { customAlphabet } from "nanoid"; | ||
| // src/utils/avatar-generator.ts | ||
| var COLORS = { | ||
| bg: [ | ||
| "transparent", | ||
| "#1e1f22", | ||
| "#313338", | ||
| "#5865F2", | ||
| "#23a559", | ||
| "#da373c", | ||
| "#f472b6", | ||
| "#3b82f6", | ||
| "#fbbf24", | ||
| "#a855f7", | ||
| "#1abc9c", | ||
| "#f39c12", | ||
| "#e74c3c" | ||
| ], | ||
| body: [ | ||
| "#2d2d30", | ||
| "#e8842c", | ||
| "#e8e8e8", | ||
| "#7a7a80", | ||
| "#d4a574", | ||
| "#6b8094", | ||
| "#f472b6", | ||
| "#c8d6e5", | ||
| "#3e2723", | ||
| "#bdc3c7", | ||
| "#ffb8b8" | ||
| ], | ||
| eyes: [ | ||
| "#f8e71c", | ||
| "#00f3ff", | ||
| "#4ade80", | ||
| "#60a5fa", | ||
| "#a855f7", | ||
| "#fbbf24", | ||
| "#f87171", | ||
| "#ffc0cb", | ||
| "#1dd1a1", | ||
| "#e056fd" | ||
| ], | ||
| pattern: ["#1a1a1c", "#ffffff", "#5a4a46", "#3d3d40", "#9a9aa0", "#d1ccc0", "#2d3436"] | ||
| }; | ||
| function getRandomElement(arr) { | ||
| return arr[Math.floor(Math.random() * arr.length)]; | ||
| } | ||
| function generateRandomCatConfig() { | ||
| return { | ||
| bg: getRandomElement(COLORS.bg), | ||
| bgPattern: getRandomElement(["none", "dots", "stripes", "grid", "stars"]), | ||
| body: getRandomElement(COLORS.body), | ||
| pattern: getRandomElement([ | ||
| "none", | ||
| "tabby", | ||
| "tuxedo", | ||
| "siamese", | ||
| "calico", | ||
| "bicolor" | ||
| ]), | ||
| patternColor: getRandomElement(COLORS.pattern), | ||
| eyeColor: getRandomElement(COLORS.eyes), | ||
| expression: getRandomElement([ | ||
| "smile", | ||
| "open", | ||
| "flat", | ||
| "sad", | ||
| "surprised", | ||
| "kawaii", | ||
| "winking", | ||
| "smirk" | ||
| ]), | ||
| decoration: getRandomElement([ | ||
| "none", | ||
| "glasses", | ||
| "blush", | ||
| "scar", | ||
| "flower", | ||
| "fish", | ||
| "headband" | ||
| ]) | ||
| }; | ||
| } | ||
| function renderCatSvg(config) { | ||
| const { bg, bgPattern, body, pattern, patternColor, eyeColor, expression, decoration } = config; | ||
| const stroke = "#1a1a1c"; | ||
| let svg = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">`; | ||
| if (bg && bg !== "transparent") { | ||
| svg += `<rect width="100" height="100" fill="${bg}" rx="20" />`; | ||
| const pColor = `rgba(255,255,255,0.15)`; | ||
| const cleanBg = bg.replace("#", ""); | ||
| if (bgPattern === "dots") { | ||
| svg += `<pattern id="p-${cleanBg}-dots" x="0" y="0" width="10" height="10" patternUnits="userSpaceOnUse"><circle cx="2" cy="2" r="2" fill="${pColor}"/></pattern><rect width="100" height="100" fill="url(#p-${cleanBg}-dots)" rx="20" />`; | ||
| } else if (bgPattern === "stripes") { | ||
| svg += `<pattern id="p-${cleanBg}-str" x="0" y="0" width="12" height="12" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="12" stroke="${pColor}" stroke-width="4"/></pattern><rect width="100" height="100" fill="url(#p-${cleanBg}-str)" rx="20" />`; | ||
| } else if (bgPattern === "grid") { | ||
| svg += `<pattern id="p-${cleanBg}-grid" width="16" height="16" patternUnits="userSpaceOnUse"><path d="M 16 0 L 0 0 0 16" fill="none" stroke="${pColor}" stroke-width="1"/></pattern><rect width="100" height="100" fill="url(#p-${cleanBg}-grid)" rx="20" />`; | ||
| } else if (bgPattern === "stars") { | ||
| svg += `<pattern id="p-${cleanBg}-star" width="20" height="20" patternUnits="userSpaceOnUse"><path d="M10,2 L12,8 L18,8 L13,12 L15,18 L10,14 L5,18 L7,12 L2,8 L8,8 Z" fill="${pColor}" transform="scale(0.5) translate(5,5)"/></pattern><rect width="100" height="100" fill="url(#p-${cleanBg}-star)" rx="20" />`; | ||
| } | ||
| } | ||
| svg += `<ellipse cx="50" cy="85" rx="30" ry="6" fill="rgba(0,0,0,0.2)"/>`; | ||
| svg += `<path d="M22,45 C15,22 28,18 34,22 C38,25 40,38 40,38" fill="${body}" stroke="${stroke}" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"/>`; | ||
| svg += `<path d="M78,45 C85,22 72,18 66,22 C62,25 60,38 60,38" fill="${body}" stroke="${stroke}" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"/>`; | ||
| svg += `<path d="M26,38 C22,26 29,24 33,26 C35,28 36,34 36,34" fill="#ffb8b8" opacity="0.8"/>`; | ||
| svg += `<path d="M74,38 C78,26 71,24 67,26 C65,28 64,34 64,34" fill="#ffb8b8" opacity="0.8"/>`; | ||
| svg += `<ellipse cx="50" cy="58" rx="38" ry="30" fill="${body}" stroke="${stroke}" stroke-width="2.5"/>`; | ||
| if (pattern === "tabby") { | ||
| svg += `<path d="M50,30 L50,40 M42,32 L46,39 M58,32 L54,39" stroke="${patternColor}" stroke-width="3" stroke-linecap="round" opacity="0.7"/>`; | ||
| svg += `<path d="M18,55 L26,57 M20,62 L27,62" stroke="${patternColor}" stroke-width="2.5" stroke-linecap="round" opacity="0.7"/>`; | ||
| svg += `<path d="M82,55 L74,57 M80,62 L73,62" stroke="${patternColor}" stroke-width="2.5" stroke-linecap="round" opacity="0.7"/>`; | ||
| } else if (pattern === "tuxedo") { | ||
| svg += `<path d="M50,56 C30,68 28,88 50,88 C72,88 70,68 50,56" fill="${patternColor}" opacity="0.95"/>`; | ||
| svg += `<ellipse cx="50" cy="65" rx="16" ry="12" fill="${patternColor}" opacity="0.95"/>`; | ||
| } else if (pattern === "siamese") { | ||
| svg += `<ellipse cx="50" cy="62" rx="20" ry="16" fill="${patternColor}" opacity="0.6"/>`; | ||
| } else if (pattern === "calico") { | ||
| svg += `<path d="M25,40 Q35,30 45,45 Q35,55 25,40" fill="${patternColor}" opacity="0.8"/>`; | ||
| svg += `<path d="M75,45 Q65,60 55,50 Q65,35 75,45" fill="#e8842c" opacity="0.8"/>`; | ||
| } else if (pattern === "bicolor") { | ||
| svg += `<path d="M12,58 Q30,30 50,40 Q60,70 50,88 Q12,88 12,58 Z" fill="${patternColor}" opacity="0.8"/>`; | ||
| } | ||
| if (decoration === "blush") { | ||
| svg += `<ellipse cx="28" cy="62" rx="5" ry="3" fill="#ff7675" opacity="0.7"/>`; | ||
| svg += `<ellipse cx="72" cy="62" rx="5" ry="3" fill="#ff7675" opacity="0.7"/>`; | ||
| } | ||
| if (decoration === "scar") { | ||
| svg += `<path d="M28,42 L40,52 M30,48 L35,43 M34,51 L39,46 M32,53 L37,48" stroke="#d63031" stroke-width="1.5" stroke-linecap="round"/>`; | ||
| } | ||
| const drawEye = (cx, cy, lookDir = 0) => { | ||
| if (expression === "kawaii") { | ||
| return `<path d="M${cx - 8},${cy} Q${cx},${cy - 8} ${cx + 8},${cy} Q${cx},${cy - 3} ${cx - 8},${cy}" fill="${eyeColor}" stroke="${stroke}" stroke-width="1.5"/><circle cx="${cx + lookDir}" cy="${cy - 2}" r="3" fill="white"/><circle cx="${cx - 3 + lookDir}" cy="${cy}" r="1" fill="white"/>`; | ||
| } else if (expression === "winking" && cx > 50) { | ||
| return `<path d="M${cx - 7},${cy + 2} Q${cx},${cy - 4} ${cx + 7},${cy + 2}" fill="none" stroke="${stroke}" stroke-width="2.5" stroke-linecap="round"/>`; | ||
| } else if (expression === "surprised") { | ||
| return `<circle cx="${cx}" cy="${cy}" r="8" fill="white" stroke="${stroke}" stroke-width="1.5"/><circle cx="${cx}" cy="${cy}" r="3" fill="${eyeColor}"/>`; | ||
| } else { | ||
| return `<circle cx="${cx}" cy="${cy}" r="7.5" fill="${eyeColor}" stroke="${stroke}" stroke-width="1.5"/><circle cx="${cx - 2 + lookDir}" cy="${cy - 2}" r="2.5" fill="white"/><circle cx="${cx + 2 + lookDir}" cy="${cy + 1}" r="1" fill="white"/>`; | ||
| } | ||
| }; | ||
| if (expression === "smirk") { | ||
| svg += `<path d="M26,50 L42,50" stroke="${stroke}" stroke-width="2.5" stroke-linecap="round"/>`; | ||
| svg += drawEye(66, 52, 2); | ||
| } else { | ||
| svg += drawEye(34, 52, 0); | ||
| svg += drawEye(66, 52, 0); | ||
| } | ||
| if (decoration === "glasses") { | ||
| svg += `<circle cx="34" cy="52" r="11" fill="rgba(255,255,255,0.2)" stroke="#2d3436" stroke-width="2.5"/>`; | ||
| svg += `<circle cx="66" cy="52" r="11" fill="rgba(255,255,255,0.2)" stroke="#2d3436" stroke-width="2.5"/>`; | ||
| svg += `<path d="M45,50 Q50,48 55,50" fill="none" stroke="#2d3436" stroke-width="2.5" stroke-linecap="round"/>`; | ||
| } | ||
| svg += `<path d="M47,62 L53,62 L50,65 Z" fill="#ff9ff3" stroke="${stroke}" stroke-width="1" stroke-linejoin="round"/>`; | ||
| if (expression === "smile" || expression === "kawaii" || expression === "winking") { | ||
| svg += `<path d="M42,67 Q46,72 50,67 M50,67 Q54,72 58,67" fill="none" stroke="${stroke}" stroke-width="2" stroke-linecap="round"/>`; | ||
| } else if (expression === "open") { | ||
| svg += `<path d="M46,67 Q50,75 54,67 Z" fill="#ff7675" stroke="${stroke}" stroke-width="1.5" stroke-linejoin="round"/>`; | ||
| } else if (expression === "flat") { | ||
| svg += `<path d="M47,68 L53,68" stroke="${stroke}" stroke-width="2" stroke-linecap="round"/>`; | ||
| } else if (expression === "sad") { | ||
| svg += `<path d="M43,70 Q50,64 57,70" fill="none" stroke="${stroke}" stroke-width="2" stroke-linecap="round"/>`; | ||
| } else if (expression === "surprised") { | ||
| svg += `<circle cx="50" cy="70" r="3" fill="#1a1a1c"/>`; | ||
| } else if (expression === "smirk") { | ||
| svg += `<path d="M46,67 Q52,69 56,64" fill="none" stroke="${stroke}" stroke-width="2" stroke-linecap="round"/>`; | ||
| } | ||
| svg += `<path d="M28,62 L15,60 M28,65 L14,66" stroke="${stroke}" stroke-width="1.5" stroke-linecap="round" opacity="0.6"/>`; | ||
| svg += `<path d="M72,62 L85,60 M72,65 L86,66" stroke="${stroke}" stroke-width="1.5" stroke-linecap="round" opacity="0.6"/>`; | ||
| if (decoration === "headband") { | ||
| svg += `<path d="M16,35 Q50,20 84,35" fill="none" stroke="#e17055" stroke-width="6" stroke-linecap="round"/>`; | ||
| svg += `<path d="M50,15 L60,25 L50,28 L40,25 Z" fill="#fab1a0" stroke="#e17055" stroke-width="2"/>`; | ||
| } else if (decoration === "flower") { | ||
| svg += `<path d="M75,30 Q80,20 85,30 Q95,25 85,35 Q90,45 80,40 Q70,45 75,35 Q65,25 75,30 Z" fill="#ffeaa7" stroke="#fdcb6e" stroke-width="1.5"/>`; | ||
| svg += `<circle cx="80" cy="33" r="3" fill="#d63031"/>`; | ||
| } else if (decoration === "fish") { | ||
| svg += `<path d="M40,82 Q50,75 60,82 L65,78 L65,86 L60,82 Q50,89 40,82 Z" fill="#81ecec" stroke="${stroke}" stroke-width="1.5"/>`; | ||
| svg += `<circle cx="45" cy="81" r="1" fill="${stroke}"/>`; | ||
| } | ||
| svg += `</svg>`; | ||
| return `data:image/svg+xml,${encodeURIComponent(svg.replace(/\n\s*/g, ""))}`; | ||
| } | ||
| // src/utils/pixel-cats.ts | ||
| var variants = [ | ||
| // 0: Shadow — Black cat (logo style) | ||
| { | ||
| body: "#2d2d30", | ||
| stroke: "#1a1a1c", | ||
| earInner: "#3d3d40", | ||
| eyeL: "#f8e71c", | ||
| eyeR: "#00f3ff", | ||
| nose: "#3a2a26" | ||
| }, | ||
| // 1: Mikan — Orange tabby | ||
| { | ||
| body: "#e8842c", | ||
| stroke: "#1a1a1c", | ||
| earInner: "#f5a623", | ||
| eyeL: "#4ade80", | ||
| eyeR: "#4ade80", | ||
| nose: "#d46b1a" | ||
| }, | ||
| // 2: Yuki — White cat | ||
| { | ||
| body: "#e8e8e8", | ||
| stroke: "#a0a0a0", | ||
| earInner: "#ffc0cb", | ||
| eyeL: "#60a5fa", | ||
| eyeR: "#60a5fa", | ||
| nose: "#f5a0b0" | ||
| }, | ||
| // 3: Haiiro — Gray cat | ||
| { | ||
| body: "#7a7a80", | ||
| stroke: "#4a4a50", | ||
| earInner: "#9a9aa0", | ||
| eyeL: "#fbbf24", | ||
| eyeR: "#fbbf24", | ||
| nose: "#5a4a46" | ||
| }, | ||
| // 4: Tuxedo — Black & white accents | ||
| { | ||
| body: "#2d2d30", | ||
| stroke: "#1a1a1c", | ||
| earInner: "#e0e0e0", | ||
| eyeL: "#22c55e", | ||
| eyeR: "#22c55e", | ||
| nose: "#3a2a26" | ||
| }, | ||
| // 5: Mocha — Cream/beige | ||
| { | ||
| body: "#d4a574", | ||
| stroke: "#8b6914", | ||
| earInner: "#e8c9a0", | ||
| eyeL: "#d97706", | ||
| eyeR: "#d97706", | ||
| nose: "#a0705a" | ||
| }, | ||
| // 6: Blue — Russian blue | ||
| { | ||
| body: "#6b8094", | ||
| stroke: "#3d5060", | ||
| earInner: "#8ba0b4", | ||
| eyeL: "#22c55e", | ||
| eyeR: "#22c55e", | ||
| nose: "#5a6a76" | ||
| }, | ||
| // 7: Sakura — Fantasy pink | ||
| { | ||
| body: "#f472b6", | ||
| stroke: "#be185d", | ||
| earInner: "#f9a8d4", | ||
| eyeL: "#a855f7", | ||
| eyeR: "#c084fc", | ||
| nose: "#d44a8c" | ||
| } | ||
| ]; | ||
| function makeCatSvg(c) { | ||
| return [ | ||
| '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">', | ||
| `<path d="M22,45 Q15,22 28,22 Q34,22 40,38" fill="${c.body}" stroke="${c.stroke}" stroke-width="2.5" stroke-linecap="round"/>`, | ||
| `<path d="M78,45 Q85,22 72,22 Q66,22 60,38" fill="${c.body}" stroke="${c.stroke}" stroke-width="2.5" stroke-linecap="round"/>`, | ||
| `<path d="M26,38 Q22,26 29,26 Q33,26 36,34" fill="${c.earInner}" opacity="0.5"/>`, | ||
| `<path d="M74,38 Q78,26 71,26 Q67,26 64,34" fill="${c.earInner}" opacity="0.5"/>`, | ||
| `<ellipse cx="50" cy="58" rx="36" ry="28" fill="${c.body}" stroke="${c.stroke}" stroke-width="2.5"/>`, | ||
| `<circle cx="35" cy="52" r="7" fill="${c.eyeL}" stroke="${c.stroke}" stroke-width="1.5"/>`, | ||
| `<circle cx="33" cy="49" r="2.5" fill="white"/>`, | ||
| `<circle cx="65" cy="52" r="7" fill="${c.eyeR}" stroke="${c.stroke}" stroke-width="1.5"/>`, | ||
| `<circle cx="63" cy="49" r="2.5" fill="white"/>`, | ||
| `<ellipse cx="50" cy="62" rx="3.5" ry="2.2" fill="${c.nose}"/>`, | ||
| `<path d="M42,67 Q46,72 50,67" fill="none" stroke="${c.stroke}" stroke-width="2" stroke-linecap="round"/>`, | ||
| `<path d="M50,67 Q54,72 58,67" fill="none" stroke="${c.stroke}" stroke-width="2" stroke-linecap="round"/>`, | ||
| "</svg>" | ||
| ].join(""); | ||
| } | ||
| var catDataUris = variants.map((v) => { | ||
| const svg = makeCatSvg(v); | ||
| return `data:image/svg+xml,${encodeURIComponent(svg)}`; | ||
| }); | ||
| function getCatAvatar(index) { | ||
| return catDataUris[index % catDataUris.length]; | ||
| } | ||
| function getCatAvatarByUserId(userId) { | ||
| let hash = 0; | ||
| for (let i = 0; i < userId.length; i++) { | ||
| hash = (hash << 5) - hash + userId.charCodeAt(i) | 0; | ||
| } | ||
| return getCatAvatar(Math.abs(hash) % catDataUris.length); | ||
| } | ||
| function getAllCatAvatars() { | ||
| const names = ["\u5F71\u5B50", "\u871C\u67D1", "\u5C0F\u96EA", "\u7070\u7070", "\u71D5\u5C3E\u670D", "\u6469\u5361", "\u84DD\u84DD", "\u5C0F\u6A31"]; | ||
| return catDataUris.map((uri, i) => ({ index: i, name: names[i], dataUri: uri })); | ||
| } | ||
| function getCatSvgString(index) { | ||
| return makeCatSvg(variants[index % variants.length]); | ||
| } | ||
| var CAT_AVATAR_COUNT = variants.length; | ||
| // src/utils/index.ts | ||
| var alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; | ||
| var generateInviteCode = customAlphabet(alphabet, 8); | ||
| function formatDate(date) { | ||
| const d = typeof date === "string" ? new Date(date) : date; | ||
| return d.toISOString(); | ||
| } | ||
| function isValidEmail(email) { | ||
| return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email); | ||
| } | ||
| function slugify(text) { | ||
| return text.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, ""); | ||
| } | ||
| export { | ||
| generateRandomCatConfig, | ||
| renderCatSvg, | ||
| getCatAvatar, | ||
| getCatAvatarByUserId, | ||
| getAllCatAvatars, | ||
| getCatSvgString, | ||
| CAT_AVATAR_COUNT, | ||
| generateInviteCode, | ||
| formatDate, | ||
| isValidEmail, | ||
| slugify | ||
| }; |
| "use strict"; | ||
| var __defProp = Object.defineProperty; | ||
| var __getOwnPropDesc = Object.getOwnPropertyDescriptor; | ||
| var __getOwnPropNames = Object.getOwnPropertyNames; | ||
| var __hasOwnProp = Object.prototype.hasOwnProperty; | ||
| var __export = (target, all) => { | ||
| for (var name in all) | ||
| __defProp(target, name, { get: all[name], enumerable: true }); | ||
| }; | ||
| var __copyProps = (to, from, except, desc) => { | ||
| if (from && typeof from === "object" || typeof from === "function") { | ||
| for (let key of __getOwnPropNames(from)) | ||
| if (!__hasOwnProp.call(to, key) && key !== except) | ||
| __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); | ||
| } | ||
| return to; | ||
| }; | ||
| var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); | ||
| // src/constants/index.ts | ||
| var constants_exports = {}; | ||
| __export(constants_exports, { | ||
| CLIENT_EVENTS: () => CLIENT_EVENTS, | ||
| LIMITS: () => LIMITS, | ||
| SERVER_EVENTS: () => SERVER_EVENTS | ||
| }); | ||
| module.exports = __toCommonJS(constants_exports); | ||
| // src/constants/events.ts | ||
| var CLIENT_EVENTS = { | ||
| CHANNEL_JOIN: "channel:join", | ||
| CHANNEL_LEAVE: "channel:leave", | ||
| MESSAGE_SEND: "message:send", | ||
| MESSAGE_TYPING: "message:typing", | ||
| PRESENCE_UPDATE: "presence:update" | ||
| }; | ||
| var SERVER_EVENTS = { | ||
| MESSAGE_NEW: "message:new", | ||
| MESSAGE_UPDATE: "message:update", | ||
| MESSAGE_DELETE: "message:delete", | ||
| MEMBER_TYPING: "member:typing", | ||
| MEMBER_JOIN: "member:join", | ||
| MEMBER_LEAVE: "member:leave", | ||
| PRESENCE_CHANGE: "presence:change", | ||
| REACTION_ADD: "reaction:add", | ||
| REACTION_REMOVE: "reaction:remove", | ||
| NOTIFICATION_NEW: "notification:new", | ||
| DM_MESSAGE_NEW: "dm:message:new" | ||
| }; | ||
| // src/constants/limits.ts | ||
| var LIMITS = { | ||
| /** Max message content length */ | ||
| MESSAGE_CONTENT_MAX: 4e3, | ||
| /** Max username length */ | ||
| USERNAME_MAX: 32, | ||
| /** Min username length */ | ||
| USERNAME_MIN: 3, | ||
| /** Max display name length */ | ||
| DISPLAY_NAME_MAX: 64, | ||
| /** Max server name length */ | ||
| SERVER_NAME_MAX: 100, | ||
| /** Max channel name length */ | ||
| CHANNEL_NAME_MAX: 100, | ||
| /** Max thread name length */ | ||
| THREAD_NAME_MAX: 100, | ||
| /** Max file upload size (10MB) */ | ||
| FILE_UPLOAD_MAX_SIZE: 10 * 1024 * 1024, | ||
| /** Messages per page (cursor pagination) */ | ||
| MESSAGES_PER_PAGE: 50, | ||
| /** Max servers per user */ | ||
| SERVERS_PER_USER_MAX: 100, | ||
| /** Max channels per server */ | ||
| CHANNELS_PER_SERVER_MAX: 200, | ||
| /** Invite code length */ | ||
| INVITE_CODE_LENGTH: 8, | ||
| /** Password min length */ | ||
| PASSWORD_MIN: 8, | ||
| /** Max reactions per message per user */ | ||
| REACTIONS_PER_MESSAGE_MAX: 20 | ||
| }; | ||
| // Annotate the CommonJS export names for ESM import in node: | ||
| 0 && (module.exports = { | ||
| CLIENT_EVENTS, | ||
| LIMITS, | ||
| SERVER_EVENTS | ||
| }); |
| declare const CLIENT_EVENTS: { | ||
| readonly CHANNEL_JOIN: "channel:join"; | ||
| readonly CHANNEL_LEAVE: "channel:leave"; | ||
| readonly MESSAGE_SEND: "message:send"; | ||
| readonly MESSAGE_TYPING: "message:typing"; | ||
| readonly PRESENCE_UPDATE: "presence:update"; | ||
| }; | ||
| declare const SERVER_EVENTS: { | ||
| readonly MESSAGE_NEW: "message:new"; | ||
| readonly MESSAGE_UPDATE: "message:update"; | ||
| readonly MESSAGE_DELETE: "message:delete"; | ||
| readonly MEMBER_TYPING: "member:typing"; | ||
| readonly MEMBER_JOIN: "member:join"; | ||
| readonly MEMBER_LEAVE: "member:leave"; | ||
| readonly PRESENCE_CHANGE: "presence:change"; | ||
| readonly REACTION_ADD: "reaction:add"; | ||
| readonly REACTION_REMOVE: "reaction:remove"; | ||
| readonly NOTIFICATION_NEW: "notification:new"; | ||
| readonly DM_MESSAGE_NEW: "dm:message:new"; | ||
| }; | ||
| type ClientEvent = (typeof CLIENT_EVENTS)[keyof typeof CLIENT_EVENTS]; | ||
| type ServerEvent = (typeof SERVER_EVENTS)[keyof typeof SERVER_EVENTS]; | ||
| declare const LIMITS: { | ||
| /** Max message content length */ | ||
| readonly MESSAGE_CONTENT_MAX: 4000; | ||
| /** Max username length */ | ||
| readonly USERNAME_MAX: 32; | ||
| /** Min username length */ | ||
| readonly USERNAME_MIN: 3; | ||
| /** Max display name length */ | ||
| readonly DISPLAY_NAME_MAX: 64; | ||
| /** Max server name length */ | ||
| readonly SERVER_NAME_MAX: 100; | ||
| /** Max channel name length */ | ||
| readonly CHANNEL_NAME_MAX: 100; | ||
| /** Max thread name length */ | ||
| readonly THREAD_NAME_MAX: 100; | ||
| /** Max file upload size (10MB) */ | ||
| readonly FILE_UPLOAD_MAX_SIZE: number; | ||
| /** Messages per page (cursor pagination) */ | ||
| readonly MESSAGES_PER_PAGE: 50; | ||
| /** Max servers per user */ | ||
| readonly SERVERS_PER_USER_MAX: 100; | ||
| /** Max channels per server */ | ||
| readonly CHANNELS_PER_SERVER_MAX: 200; | ||
| /** Invite code length */ | ||
| readonly INVITE_CODE_LENGTH: 8; | ||
| /** Password min length */ | ||
| readonly PASSWORD_MIN: 8; | ||
| /** Max reactions per message per user */ | ||
| readonly REACTIONS_PER_MESSAGE_MAX: 20; | ||
| }; | ||
| export { CLIENT_EVENTS, type ClientEvent, LIMITS, SERVER_EVENTS, type ServerEvent }; |
| declare const CLIENT_EVENTS: { | ||
| readonly CHANNEL_JOIN: "channel:join"; | ||
| readonly CHANNEL_LEAVE: "channel:leave"; | ||
| readonly MESSAGE_SEND: "message:send"; | ||
| readonly MESSAGE_TYPING: "message:typing"; | ||
| readonly PRESENCE_UPDATE: "presence:update"; | ||
| }; | ||
| declare const SERVER_EVENTS: { | ||
| readonly MESSAGE_NEW: "message:new"; | ||
| readonly MESSAGE_UPDATE: "message:update"; | ||
| readonly MESSAGE_DELETE: "message:delete"; | ||
| readonly MEMBER_TYPING: "member:typing"; | ||
| readonly MEMBER_JOIN: "member:join"; | ||
| readonly MEMBER_LEAVE: "member:leave"; | ||
| readonly PRESENCE_CHANGE: "presence:change"; | ||
| readonly REACTION_ADD: "reaction:add"; | ||
| readonly REACTION_REMOVE: "reaction:remove"; | ||
| readonly NOTIFICATION_NEW: "notification:new"; | ||
| readonly DM_MESSAGE_NEW: "dm:message:new"; | ||
| }; | ||
| type ClientEvent = (typeof CLIENT_EVENTS)[keyof typeof CLIENT_EVENTS]; | ||
| type ServerEvent = (typeof SERVER_EVENTS)[keyof typeof SERVER_EVENTS]; | ||
| declare const LIMITS: { | ||
| /** Max message content length */ | ||
| readonly MESSAGE_CONTENT_MAX: 4000; | ||
| /** Max username length */ | ||
| readonly USERNAME_MAX: 32; | ||
| /** Min username length */ | ||
| readonly USERNAME_MIN: 3; | ||
| /** Max display name length */ | ||
| readonly DISPLAY_NAME_MAX: 64; | ||
| /** Max server name length */ | ||
| readonly SERVER_NAME_MAX: 100; | ||
| /** Max channel name length */ | ||
| readonly CHANNEL_NAME_MAX: 100; | ||
| /** Max thread name length */ | ||
| readonly THREAD_NAME_MAX: 100; | ||
| /** Max file upload size (10MB) */ | ||
| readonly FILE_UPLOAD_MAX_SIZE: number; | ||
| /** Messages per page (cursor pagination) */ | ||
| readonly MESSAGES_PER_PAGE: 50; | ||
| /** Max servers per user */ | ||
| readonly SERVERS_PER_USER_MAX: 100; | ||
| /** Max channels per server */ | ||
| readonly CHANNELS_PER_SERVER_MAX: 200; | ||
| /** Invite code length */ | ||
| readonly INVITE_CODE_LENGTH: 8; | ||
| /** Password min length */ | ||
| readonly PASSWORD_MIN: 8; | ||
| /** Max reactions per message per user */ | ||
| readonly REACTIONS_PER_MESSAGE_MAX: 20; | ||
| }; | ||
| export { CLIENT_EVENTS, type ClientEvent, LIMITS, SERVER_EVENTS, type ServerEvent }; |
| import { | ||
| CLIENT_EVENTS, | ||
| LIMITS, | ||
| SERVER_EVENTS | ||
| } from "../chunk-EMLX23LF.js"; | ||
| export { | ||
| CLIENT_EVENTS, | ||
| LIMITS, | ||
| SERVER_EVENTS | ||
| }; |
+424
| "use strict"; | ||
| var __defProp = Object.defineProperty; | ||
| var __getOwnPropDesc = Object.getOwnPropertyDescriptor; | ||
| var __getOwnPropNames = Object.getOwnPropertyNames; | ||
| var __hasOwnProp = Object.prototype.hasOwnProperty; | ||
| var __export = (target, all) => { | ||
| for (var name in all) | ||
| __defProp(target, name, { get: all[name], enumerable: true }); | ||
| }; | ||
| var __copyProps = (to, from, except, desc) => { | ||
| if (from && typeof from === "object" || typeof from === "function") { | ||
| for (let key of __getOwnPropNames(from)) | ||
| if (!__hasOwnProp.call(to, key) && key !== except) | ||
| __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); | ||
| } | ||
| return to; | ||
| }; | ||
| var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); | ||
| // src/index.ts | ||
| var index_exports = {}; | ||
| __export(index_exports, { | ||
| CAT_AVATAR_COUNT: () => CAT_AVATAR_COUNT, | ||
| CLIENT_EVENTS: () => CLIENT_EVENTS, | ||
| LIMITS: () => LIMITS, | ||
| SERVER_EVENTS: () => SERVER_EVENTS, | ||
| formatDate: () => formatDate, | ||
| generateInviteCode: () => generateInviteCode, | ||
| generateRandomCatConfig: () => generateRandomCatConfig, | ||
| getAllCatAvatars: () => getAllCatAvatars, | ||
| getCatAvatar: () => getCatAvatar, | ||
| getCatAvatarByUserId: () => getCatAvatarByUserId, | ||
| getCatSvgString: () => getCatSvgString, | ||
| isValidEmail: () => isValidEmail, | ||
| renderCatSvg: () => renderCatSvg, | ||
| slugify: () => slugify | ||
| }); | ||
| module.exports = __toCommonJS(index_exports); | ||
| // src/constants/events.ts | ||
| var CLIENT_EVENTS = { | ||
| CHANNEL_JOIN: "channel:join", | ||
| CHANNEL_LEAVE: "channel:leave", | ||
| MESSAGE_SEND: "message:send", | ||
| MESSAGE_TYPING: "message:typing", | ||
| PRESENCE_UPDATE: "presence:update" | ||
| }; | ||
| var SERVER_EVENTS = { | ||
| MESSAGE_NEW: "message:new", | ||
| MESSAGE_UPDATE: "message:update", | ||
| MESSAGE_DELETE: "message:delete", | ||
| MEMBER_TYPING: "member:typing", | ||
| MEMBER_JOIN: "member:join", | ||
| MEMBER_LEAVE: "member:leave", | ||
| PRESENCE_CHANGE: "presence:change", | ||
| REACTION_ADD: "reaction:add", | ||
| REACTION_REMOVE: "reaction:remove", | ||
| NOTIFICATION_NEW: "notification:new", | ||
| DM_MESSAGE_NEW: "dm:message:new" | ||
| }; | ||
| // src/constants/limits.ts | ||
| var LIMITS = { | ||
| /** Max message content length */ | ||
| MESSAGE_CONTENT_MAX: 4e3, | ||
| /** Max username length */ | ||
| USERNAME_MAX: 32, | ||
| /** Min username length */ | ||
| USERNAME_MIN: 3, | ||
| /** Max display name length */ | ||
| DISPLAY_NAME_MAX: 64, | ||
| /** Max server name length */ | ||
| SERVER_NAME_MAX: 100, | ||
| /** Max channel name length */ | ||
| CHANNEL_NAME_MAX: 100, | ||
| /** Max thread name length */ | ||
| THREAD_NAME_MAX: 100, | ||
| /** Max file upload size (10MB) */ | ||
| FILE_UPLOAD_MAX_SIZE: 10 * 1024 * 1024, | ||
| /** Messages per page (cursor pagination) */ | ||
| MESSAGES_PER_PAGE: 50, | ||
| /** Max servers per user */ | ||
| SERVERS_PER_USER_MAX: 100, | ||
| /** Max channels per server */ | ||
| CHANNELS_PER_SERVER_MAX: 200, | ||
| /** Invite code length */ | ||
| INVITE_CODE_LENGTH: 8, | ||
| /** Password min length */ | ||
| PASSWORD_MIN: 8, | ||
| /** Max reactions per message per user */ | ||
| REACTIONS_PER_MESSAGE_MAX: 20 | ||
| }; | ||
| // src/utils/index.ts | ||
| var import_nanoid = require("nanoid"); | ||
| // src/utils/avatar-generator.ts | ||
| var COLORS = { | ||
| bg: [ | ||
| "transparent", | ||
| "#1e1f22", | ||
| "#313338", | ||
| "#5865F2", | ||
| "#23a559", | ||
| "#da373c", | ||
| "#f472b6", | ||
| "#3b82f6", | ||
| "#fbbf24", | ||
| "#a855f7", | ||
| "#1abc9c", | ||
| "#f39c12", | ||
| "#e74c3c" | ||
| ], | ||
| body: [ | ||
| "#2d2d30", | ||
| "#e8842c", | ||
| "#e8e8e8", | ||
| "#7a7a80", | ||
| "#d4a574", | ||
| "#6b8094", | ||
| "#f472b6", | ||
| "#c8d6e5", | ||
| "#3e2723", | ||
| "#bdc3c7", | ||
| "#ffb8b8" | ||
| ], | ||
| eyes: [ | ||
| "#f8e71c", | ||
| "#00f3ff", | ||
| "#4ade80", | ||
| "#60a5fa", | ||
| "#a855f7", | ||
| "#fbbf24", | ||
| "#f87171", | ||
| "#ffc0cb", | ||
| "#1dd1a1", | ||
| "#e056fd" | ||
| ], | ||
| pattern: ["#1a1a1c", "#ffffff", "#5a4a46", "#3d3d40", "#9a9aa0", "#d1ccc0", "#2d3436"] | ||
| }; | ||
| function getRandomElement(arr) { | ||
| return arr[Math.floor(Math.random() * arr.length)]; | ||
| } | ||
| function generateRandomCatConfig() { | ||
| return { | ||
| bg: getRandomElement(COLORS.bg), | ||
| bgPattern: getRandomElement(["none", "dots", "stripes", "grid", "stars"]), | ||
| body: getRandomElement(COLORS.body), | ||
| pattern: getRandomElement([ | ||
| "none", | ||
| "tabby", | ||
| "tuxedo", | ||
| "siamese", | ||
| "calico", | ||
| "bicolor" | ||
| ]), | ||
| patternColor: getRandomElement(COLORS.pattern), | ||
| eyeColor: getRandomElement(COLORS.eyes), | ||
| expression: getRandomElement([ | ||
| "smile", | ||
| "open", | ||
| "flat", | ||
| "sad", | ||
| "surprised", | ||
| "kawaii", | ||
| "winking", | ||
| "smirk" | ||
| ]), | ||
| decoration: getRandomElement([ | ||
| "none", | ||
| "glasses", | ||
| "blush", | ||
| "scar", | ||
| "flower", | ||
| "fish", | ||
| "headband" | ||
| ]) | ||
| }; | ||
| } | ||
| function renderCatSvg(config) { | ||
| const { bg, bgPattern, body, pattern, patternColor, eyeColor, expression, decoration } = config; | ||
| const stroke = "#1a1a1c"; | ||
| let svg = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">`; | ||
| if (bg && bg !== "transparent") { | ||
| svg += `<rect width="100" height="100" fill="${bg}" rx="20" />`; | ||
| const pColor = `rgba(255,255,255,0.15)`; | ||
| const cleanBg = bg.replace("#", ""); | ||
| if (bgPattern === "dots") { | ||
| svg += `<pattern id="p-${cleanBg}-dots" x="0" y="0" width="10" height="10" patternUnits="userSpaceOnUse"><circle cx="2" cy="2" r="2" fill="${pColor}"/></pattern><rect width="100" height="100" fill="url(#p-${cleanBg}-dots)" rx="20" />`; | ||
| } else if (bgPattern === "stripes") { | ||
| svg += `<pattern id="p-${cleanBg}-str" x="0" y="0" width="12" height="12" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="12" stroke="${pColor}" stroke-width="4"/></pattern><rect width="100" height="100" fill="url(#p-${cleanBg}-str)" rx="20" />`; | ||
| } else if (bgPattern === "grid") { | ||
| svg += `<pattern id="p-${cleanBg}-grid" width="16" height="16" patternUnits="userSpaceOnUse"><path d="M 16 0 L 0 0 0 16" fill="none" stroke="${pColor}" stroke-width="1"/></pattern><rect width="100" height="100" fill="url(#p-${cleanBg}-grid)" rx="20" />`; | ||
| } else if (bgPattern === "stars") { | ||
| svg += `<pattern id="p-${cleanBg}-star" width="20" height="20" patternUnits="userSpaceOnUse"><path d="M10,2 L12,8 L18,8 L13,12 L15,18 L10,14 L5,18 L7,12 L2,8 L8,8 Z" fill="${pColor}" transform="scale(0.5) translate(5,5)"/></pattern><rect width="100" height="100" fill="url(#p-${cleanBg}-star)" rx="20" />`; | ||
| } | ||
| } | ||
| svg += `<ellipse cx="50" cy="85" rx="30" ry="6" fill="rgba(0,0,0,0.2)"/>`; | ||
| svg += `<path d="M22,45 C15,22 28,18 34,22 C38,25 40,38 40,38" fill="${body}" stroke="${stroke}" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"/>`; | ||
| svg += `<path d="M78,45 C85,22 72,18 66,22 C62,25 60,38 60,38" fill="${body}" stroke="${stroke}" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"/>`; | ||
| svg += `<path d="M26,38 C22,26 29,24 33,26 C35,28 36,34 36,34" fill="#ffb8b8" opacity="0.8"/>`; | ||
| svg += `<path d="M74,38 C78,26 71,24 67,26 C65,28 64,34 64,34" fill="#ffb8b8" opacity="0.8"/>`; | ||
| svg += `<ellipse cx="50" cy="58" rx="38" ry="30" fill="${body}" stroke="${stroke}" stroke-width="2.5"/>`; | ||
| if (pattern === "tabby") { | ||
| svg += `<path d="M50,30 L50,40 M42,32 L46,39 M58,32 L54,39" stroke="${patternColor}" stroke-width="3" stroke-linecap="round" opacity="0.7"/>`; | ||
| svg += `<path d="M18,55 L26,57 M20,62 L27,62" stroke="${patternColor}" stroke-width="2.5" stroke-linecap="round" opacity="0.7"/>`; | ||
| svg += `<path d="M82,55 L74,57 M80,62 L73,62" stroke="${patternColor}" stroke-width="2.5" stroke-linecap="round" opacity="0.7"/>`; | ||
| } else if (pattern === "tuxedo") { | ||
| svg += `<path d="M50,56 C30,68 28,88 50,88 C72,88 70,68 50,56" fill="${patternColor}" opacity="0.95"/>`; | ||
| svg += `<ellipse cx="50" cy="65" rx="16" ry="12" fill="${patternColor}" opacity="0.95"/>`; | ||
| } else if (pattern === "siamese") { | ||
| svg += `<ellipse cx="50" cy="62" rx="20" ry="16" fill="${patternColor}" opacity="0.6"/>`; | ||
| } else if (pattern === "calico") { | ||
| svg += `<path d="M25,40 Q35,30 45,45 Q35,55 25,40" fill="${patternColor}" opacity="0.8"/>`; | ||
| svg += `<path d="M75,45 Q65,60 55,50 Q65,35 75,45" fill="#e8842c" opacity="0.8"/>`; | ||
| } else if (pattern === "bicolor") { | ||
| svg += `<path d="M12,58 Q30,30 50,40 Q60,70 50,88 Q12,88 12,58 Z" fill="${patternColor}" opacity="0.8"/>`; | ||
| } | ||
| if (decoration === "blush") { | ||
| svg += `<ellipse cx="28" cy="62" rx="5" ry="3" fill="#ff7675" opacity="0.7"/>`; | ||
| svg += `<ellipse cx="72" cy="62" rx="5" ry="3" fill="#ff7675" opacity="0.7"/>`; | ||
| } | ||
| if (decoration === "scar") { | ||
| svg += `<path d="M28,42 L40,52 M30,48 L35,43 M34,51 L39,46 M32,53 L37,48" stroke="#d63031" stroke-width="1.5" stroke-linecap="round"/>`; | ||
| } | ||
| const drawEye = (cx, cy, lookDir = 0) => { | ||
| if (expression === "kawaii") { | ||
| return `<path d="M${cx - 8},${cy} Q${cx},${cy - 8} ${cx + 8},${cy} Q${cx},${cy - 3} ${cx - 8},${cy}" fill="${eyeColor}" stroke="${stroke}" stroke-width="1.5"/><circle cx="${cx + lookDir}" cy="${cy - 2}" r="3" fill="white"/><circle cx="${cx - 3 + lookDir}" cy="${cy}" r="1" fill="white"/>`; | ||
| } else if (expression === "winking" && cx > 50) { | ||
| return `<path d="M${cx - 7},${cy + 2} Q${cx},${cy - 4} ${cx + 7},${cy + 2}" fill="none" stroke="${stroke}" stroke-width="2.5" stroke-linecap="round"/>`; | ||
| } else if (expression === "surprised") { | ||
| return `<circle cx="${cx}" cy="${cy}" r="8" fill="white" stroke="${stroke}" stroke-width="1.5"/><circle cx="${cx}" cy="${cy}" r="3" fill="${eyeColor}"/>`; | ||
| } else { | ||
| return `<circle cx="${cx}" cy="${cy}" r="7.5" fill="${eyeColor}" stroke="${stroke}" stroke-width="1.5"/><circle cx="${cx - 2 + lookDir}" cy="${cy - 2}" r="2.5" fill="white"/><circle cx="${cx + 2 + lookDir}" cy="${cy + 1}" r="1" fill="white"/>`; | ||
| } | ||
| }; | ||
| if (expression === "smirk") { | ||
| svg += `<path d="M26,50 L42,50" stroke="${stroke}" stroke-width="2.5" stroke-linecap="round"/>`; | ||
| svg += drawEye(66, 52, 2); | ||
| } else { | ||
| svg += drawEye(34, 52, 0); | ||
| svg += drawEye(66, 52, 0); | ||
| } | ||
| if (decoration === "glasses") { | ||
| svg += `<circle cx="34" cy="52" r="11" fill="rgba(255,255,255,0.2)" stroke="#2d3436" stroke-width="2.5"/>`; | ||
| svg += `<circle cx="66" cy="52" r="11" fill="rgba(255,255,255,0.2)" stroke="#2d3436" stroke-width="2.5"/>`; | ||
| svg += `<path d="M45,50 Q50,48 55,50" fill="none" stroke="#2d3436" stroke-width="2.5" stroke-linecap="round"/>`; | ||
| } | ||
| svg += `<path d="M47,62 L53,62 L50,65 Z" fill="#ff9ff3" stroke="${stroke}" stroke-width="1" stroke-linejoin="round"/>`; | ||
| if (expression === "smile" || expression === "kawaii" || expression === "winking") { | ||
| svg += `<path d="M42,67 Q46,72 50,67 M50,67 Q54,72 58,67" fill="none" stroke="${stroke}" stroke-width="2" stroke-linecap="round"/>`; | ||
| } else if (expression === "open") { | ||
| svg += `<path d="M46,67 Q50,75 54,67 Z" fill="#ff7675" stroke="${stroke}" stroke-width="1.5" stroke-linejoin="round"/>`; | ||
| } else if (expression === "flat") { | ||
| svg += `<path d="M47,68 L53,68" stroke="${stroke}" stroke-width="2" stroke-linecap="round"/>`; | ||
| } else if (expression === "sad") { | ||
| svg += `<path d="M43,70 Q50,64 57,70" fill="none" stroke="${stroke}" stroke-width="2" stroke-linecap="round"/>`; | ||
| } else if (expression === "surprised") { | ||
| svg += `<circle cx="50" cy="70" r="3" fill="#1a1a1c"/>`; | ||
| } else if (expression === "smirk") { | ||
| svg += `<path d="M46,67 Q52,69 56,64" fill="none" stroke="${stroke}" stroke-width="2" stroke-linecap="round"/>`; | ||
| } | ||
| svg += `<path d="M28,62 L15,60 M28,65 L14,66" stroke="${stroke}" stroke-width="1.5" stroke-linecap="round" opacity="0.6"/>`; | ||
| svg += `<path d="M72,62 L85,60 M72,65 L86,66" stroke="${stroke}" stroke-width="1.5" stroke-linecap="round" opacity="0.6"/>`; | ||
| if (decoration === "headband") { | ||
| svg += `<path d="M16,35 Q50,20 84,35" fill="none" stroke="#e17055" stroke-width="6" stroke-linecap="round"/>`; | ||
| svg += `<path d="M50,15 L60,25 L50,28 L40,25 Z" fill="#fab1a0" stroke="#e17055" stroke-width="2"/>`; | ||
| } else if (decoration === "flower") { | ||
| svg += `<path d="M75,30 Q80,20 85,30 Q95,25 85,35 Q90,45 80,40 Q70,45 75,35 Q65,25 75,30 Z" fill="#ffeaa7" stroke="#fdcb6e" stroke-width="1.5"/>`; | ||
| svg += `<circle cx="80" cy="33" r="3" fill="#d63031"/>`; | ||
| } else if (decoration === "fish") { | ||
| svg += `<path d="M40,82 Q50,75 60,82 L65,78 L65,86 L60,82 Q50,89 40,82 Z" fill="#81ecec" stroke="${stroke}" stroke-width="1.5"/>`; | ||
| svg += `<circle cx="45" cy="81" r="1" fill="${stroke}"/>`; | ||
| } | ||
| svg += `</svg>`; | ||
| return `data:image/svg+xml,${encodeURIComponent(svg.replace(/\n\s*/g, ""))}`; | ||
| } | ||
| // src/utils/pixel-cats.ts | ||
| var variants = [ | ||
| // 0: Shadow — Black cat (logo style) | ||
| { | ||
| body: "#2d2d30", | ||
| stroke: "#1a1a1c", | ||
| earInner: "#3d3d40", | ||
| eyeL: "#f8e71c", | ||
| eyeR: "#00f3ff", | ||
| nose: "#3a2a26" | ||
| }, | ||
| // 1: Mikan — Orange tabby | ||
| { | ||
| body: "#e8842c", | ||
| stroke: "#1a1a1c", | ||
| earInner: "#f5a623", | ||
| eyeL: "#4ade80", | ||
| eyeR: "#4ade80", | ||
| nose: "#d46b1a" | ||
| }, | ||
| // 2: Yuki — White cat | ||
| { | ||
| body: "#e8e8e8", | ||
| stroke: "#a0a0a0", | ||
| earInner: "#ffc0cb", | ||
| eyeL: "#60a5fa", | ||
| eyeR: "#60a5fa", | ||
| nose: "#f5a0b0" | ||
| }, | ||
| // 3: Haiiro — Gray cat | ||
| { | ||
| body: "#7a7a80", | ||
| stroke: "#4a4a50", | ||
| earInner: "#9a9aa0", | ||
| eyeL: "#fbbf24", | ||
| eyeR: "#fbbf24", | ||
| nose: "#5a4a46" | ||
| }, | ||
| // 4: Tuxedo — Black & white accents | ||
| { | ||
| body: "#2d2d30", | ||
| stroke: "#1a1a1c", | ||
| earInner: "#e0e0e0", | ||
| eyeL: "#22c55e", | ||
| eyeR: "#22c55e", | ||
| nose: "#3a2a26" | ||
| }, | ||
| // 5: Mocha — Cream/beige | ||
| { | ||
| body: "#d4a574", | ||
| stroke: "#8b6914", | ||
| earInner: "#e8c9a0", | ||
| eyeL: "#d97706", | ||
| eyeR: "#d97706", | ||
| nose: "#a0705a" | ||
| }, | ||
| // 6: Blue — Russian blue | ||
| { | ||
| body: "#6b8094", | ||
| stroke: "#3d5060", | ||
| earInner: "#8ba0b4", | ||
| eyeL: "#22c55e", | ||
| eyeR: "#22c55e", | ||
| nose: "#5a6a76" | ||
| }, | ||
| // 7: Sakura — Fantasy pink | ||
| { | ||
| body: "#f472b6", | ||
| stroke: "#be185d", | ||
| earInner: "#f9a8d4", | ||
| eyeL: "#a855f7", | ||
| eyeR: "#c084fc", | ||
| nose: "#d44a8c" | ||
| } | ||
| ]; | ||
| function makeCatSvg(c) { | ||
| return [ | ||
| '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">', | ||
| `<path d="M22,45 Q15,22 28,22 Q34,22 40,38" fill="${c.body}" stroke="${c.stroke}" stroke-width="2.5" stroke-linecap="round"/>`, | ||
| `<path d="M78,45 Q85,22 72,22 Q66,22 60,38" fill="${c.body}" stroke="${c.stroke}" stroke-width="2.5" stroke-linecap="round"/>`, | ||
| `<path d="M26,38 Q22,26 29,26 Q33,26 36,34" fill="${c.earInner}" opacity="0.5"/>`, | ||
| `<path d="M74,38 Q78,26 71,26 Q67,26 64,34" fill="${c.earInner}" opacity="0.5"/>`, | ||
| `<ellipse cx="50" cy="58" rx="36" ry="28" fill="${c.body}" stroke="${c.stroke}" stroke-width="2.5"/>`, | ||
| `<circle cx="35" cy="52" r="7" fill="${c.eyeL}" stroke="${c.stroke}" stroke-width="1.5"/>`, | ||
| `<circle cx="33" cy="49" r="2.5" fill="white"/>`, | ||
| `<circle cx="65" cy="52" r="7" fill="${c.eyeR}" stroke="${c.stroke}" stroke-width="1.5"/>`, | ||
| `<circle cx="63" cy="49" r="2.5" fill="white"/>`, | ||
| `<ellipse cx="50" cy="62" rx="3.5" ry="2.2" fill="${c.nose}"/>`, | ||
| `<path d="M42,67 Q46,72 50,67" fill="none" stroke="${c.stroke}" stroke-width="2" stroke-linecap="round"/>`, | ||
| `<path d="M50,67 Q54,72 58,67" fill="none" stroke="${c.stroke}" stroke-width="2" stroke-linecap="round"/>`, | ||
| "</svg>" | ||
| ].join(""); | ||
| } | ||
| var catDataUris = variants.map((v) => { | ||
| const svg = makeCatSvg(v); | ||
| return `data:image/svg+xml,${encodeURIComponent(svg)}`; | ||
| }); | ||
| function getCatAvatar(index) { | ||
| return catDataUris[index % catDataUris.length]; | ||
| } | ||
| function getCatAvatarByUserId(userId) { | ||
| let hash = 0; | ||
| for (let i = 0; i < userId.length; i++) { | ||
| hash = (hash << 5) - hash + userId.charCodeAt(i) | 0; | ||
| } | ||
| return getCatAvatar(Math.abs(hash) % catDataUris.length); | ||
| } | ||
| function getAllCatAvatars() { | ||
| const names = ["\u5F71\u5B50", "\u871C\u67D1", "\u5C0F\u96EA", "\u7070\u7070", "\u71D5\u5C3E\u670D", "\u6469\u5361", "\u84DD\u84DD", "\u5C0F\u6A31"]; | ||
| return catDataUris.map((uri, i) => ({ index: i, name: names[i], dataUri: uri })); | ||
| } | ||
| function getCatSvgString(index) { | ||
| return makeCatSvg(variants[index % variants.length]); | ||
| } | ||
| var CAT_AVATAR_COUNT = variants.length; | ||
| // src/utils/index.ts | ||
| var alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; | ||
| var generateInviteCode = (0, import_nanoid.customAlphabet)(alphabet, 8); | ||
| function formatDate(date) { | ||
| const d = typeof date === "string" ? new Date(date) : date; | ||
| return d.toISOString(); | ||
| } | ||
| function isValidEmail(email) { | ||
| return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email); | ||
| } | ||
| function slugify(text) { | ||
| return text.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, ""); | ||
| } | ||
| // Annotate the CommonJS export names for ESM import in node: | ||
| 0 && (module.exports = { | ||
| CAT_AVATAR_COUNT, | ||
| CLIENT_EVENTS, | ||
| LIMITS, | ||
| SERVER_EVENTS, | ||
| formatDate, | ||
| generateInviteCode, | ||
| generateRandomCatConfig, | ||
| getAllCatAvatars, | ||
| getCatAvatar, | ||
| getCatAvatarByUserId, | ||
| getCatSvgString, | ||
| isValidEmail, | ||
| renderCatSvg, | ||
| slugify | ||
| }); |
| export { CLIENT_EVENTS, ClientEvent, LIMITS, SERVER_EVENTS, ServerEvent } from './constants/index.cjs'; | ||
| export { Agent, AgentCapability, AgentInfo, AgentKernelType, AgentStatus, Attachment, AuthResponse, Channel, ChannelSortBy, ChannelSortDirection, ChannelSortOptions, ChannelType, CreateAgentRequest, CreateChannelRequest, CreateServerRequest, DmAttachment, DmChannel, DmMessage, FriendEntry, FriendSource, Friendship, FriendshipStatus, LoginRequest, Member, MemberRole, Message, Notification, NotificationType, ReactionGroup, RegisterRequest, SendMessageRequest, Server, Thread, UpdateChannelRequest, UpdateDmMessageRequest, UpdateMessageRequest, UpdateServerRequest, User, UserProfile, UserStatus } from './types/index.cjs'; | ||
| export { BgPattern, CAT_AVATAR_COUNT, CatConfig, CatDecoration, CatExpression, CatPattern, formatDate, generateInviteCode, generateRandomCatConfig, getAllCatAvatars, getCatAvatar, getCatAvatarByUserId, getCatSvgString, isValidEmail, renderCatSvg, slugify } from './utils/index.cjs'; |
| export { CLIENT_EVENTS, ClientEvent, LIMITS, SERVER_EVENTS, ServerEvent } from './constants/index.js'; | ||
| export { Agent, AgentCapability, AgentInfo, AgentKernelType, AgentStatus, Attachment, AuthResponse, Channel, ChannelSortBy, ChannelSortDirection, ChannelSortOptions, ChannelType, CreateAgentRequest, CreateChannelRequest, CreateServerRequest, DmAttachment, DmChannel, DmMessage, FriendEntry, FriendSource, Friendship, FriendshipStatus, LoginRequest, Member, MemberRole, Message, Notification, NotificationType, ReactionGroup, RegisterRequest, SendMessageRequest, Server, Thread, UpdateChannelRequest, UpdateDmMessageRequest, UpdateMessageRequest, UpdateServerRequest, User, UserProfile, UserStatus } from './types/index.js'; | ||
| export { BgPattern, CAT_AVATAR_COUNT, CatConfig, CatDecoration, CatExpression, CatPattern, formatDate, generateInviteCode, generateRandomCatConfig, getAllCatAvatars, getCatAvatar, getCatAvatarByUserId, getCatSvgString, isValidEmail, renderCatSvg, slugify } from './utils/index.js'; |
| import { | ||
| CLIENT_EVENTS, | ||
| LIMITS, | ||
| SERVER_EVENTS | ||
| } from "./chunk-EMLX23LF.js"; | ||
| import "./chunk-6H4LIJZC.js"; | ||
| import { | ||
| CAT_AVATAR_COUNT, | ||
| formatDate, | ||
| generateInviteCode, | ||
| generateRandomCatConfig, | ||
| getAllCatAvatars, | ||
| getCatAvatar, | ||
| getCatAvatarByUserId, | ||
| getCatSvgString, | ||
| isValidEmail, | ||
| renderCatSvg, | ||
| slugify | ||
| } from "./chunk-PXKHJSTK.js"; | ||
| export { | ||
| CAT_AVATAR_COUNT, | ||
| CLIENT_EVENTS, | ||
| LIMITS, | ||
| SERVER_EVENTS, | ||
| formatDate, | ||
| generateInviteCode, | ||
| generateRandomCatConfig, | ||
| getAllCatAvatars, | ||
| getCatAvatar, | ||
| getCatAvatarByUserId, | ||
| getCatSvgString, | ||
| isValidEmail, | ||
| renderCatSvg, | ||
| slugify | ||
| }; |
| "use strict"; | ||
| var __defProp = Object.defineProperty; | ||
| var __getOwnPropDesc = Object.getOwnPropertyDescriptor; | ||
| var __getOwnPropNames = Object.getOwnPropertyNames; | ||
| var __hasOwnProp = Object.prototype.hasOwnProperty; | ||
| var __copyProps = (to, from, except, desc) => { | ||
| if (from && typeof from === "object" || typeof from === "function") { | ||
| for (let key of __getOwnPropNames(from)) | ||
| if (!__hasOwnProp.call(to, key) && key !== except) | ||
| __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); | ||
| } | ||
| return to; | ||
| }; | ||
| var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); | ||
| // src/types/index.ts | ||
| var types_exports = {}; | ||
| module.exports = __toCommonJS(types_exports); |
| type AgentStatus = 'running' | 'stopped' | 'error'; | ||
| type AgentKernelType = 'claude-code' | 'cursor' | 'mcp-server' | 'custom'; | ||
| type AgentCapability = 'chat' | 'code-gen' | 'code-review' | 'research' | 'tools' | 'file-access'; | ||
| interface Agent { | ||
| id: string; | ||
| userId: string; | ||
| kernelType: AgentKernelType; | ||
| config: Record<string, unknown>; | ||
| containerId: string | null; | ||
| status: AgentStatus; | ||
| ownerId: string; | ||
| createdAt: string; | ||
| updatedAt: string; | ||
| user?: { | ||
| id: string; | ||
| username: string; | ||
| displayName: string; | ||
| avatarUrl: string | null; | ||
| }; | ||
| capabilities?: AgentCapability[]; | ||
| } | ||
| interface CreateAgentRequest { | ||
| name: string; | ||
| kernelType: AgentKernelType; | ||
| config?: Record<string, unknown>; | ||
| } | ||
| interface AgentInfo { | ||
| id: string; | ||
| name: string; | ||
| kernelType: AgentKernelType; | ||
| status: AgentStatus; | ||
| capabilities: AgentCapability[]; | ||
| } | ||
| type ChannelType = 'text' | 'voice' | 'announcement'; | ||
| interface Channel { | ||
| id: string; | ||
| name: string; | ||
| type: ChannelType; | ||
| serverId: string; | ||
| topic: string | null; | ||
| position: number; | ||
| createdAt: string; | ||
| updatedAt: string; | ||
| /** Last message timestamp for sorting by activity */ | ||
| lastMessageAt?: string | null; | ||
| } | ||
| interface CreateChannelRequest { | ||
| name: string; | ||
| type?: ChannelType; | ||
| topic?: string; | ||
| } | ||
| interface UpdateChannelRequest { | ||
| name?: string; | ||
| topic?: string; | ||
| position?: number; | ||
| } | ||
| /** Channel sorting options */ | ||
| type ChannelSortBy = 'position' | 'createdAt' | 'updatedAt' | 'lastMessageAt' | 'lastAccessedAt'; | ||
| type ChannelSortDirection = 'asc' | 'desc'; | ||
| interface ChannelSortOptions { | ||
| by: ChannelSortBy; | ||
| direction: ChannelSortDirection; | ||
| } | ||
| type FriendshipStatus = 'pending' | 'accepted' | 'blocked'; | ||
| interface Friendship { | ||
| id: string; | ||
| requesterId: string; | ||
| addresseeId: string; | ||
| status: FriendshipStatus; | ||
| createdAt: string; | ||
| updatedAt: string; | ||
| } | ||
| type FriendSource = 'friend' | 'owned_claw' | 'rented_claw'; | ||
| interface FriendEntry { | ||
| friendshipId: string; | ||
| /** Where this friend entry comes from */ | ||
| source: FriendSource; | ||
| user: { | ||
| id: string; | ||
| username: string; | ||
| displayName: string | null; | ||
| avatarUrl: string | null; | ||
| status: string; | ||
| isBot: boolean; | ||
| }; | ||
| createdAt: string; | ||
| } | ||
| interface Message { | ||
| id: string; | ||
| content: string; | ||
| channelId: string; | ||
| authorId: string; | ||
| threadId: string | null; | ||
| replyToId: string | null; | ||
| isEdited: boolean; | ||
| isPinned: boolean; | ||
| createdAt: string; | ||
| updatedAt: string; | ||
| author?: { | ||
| id: string; | ||
| username: string; | ||
| displayName: string; | ||
| avatarUrl: string | null; | ||
| isBot: boolean; | ||
| }; | ||
| attachments?: Attachment[]; | ||
| reactions?: ReactionGroup[]; | ||
| } | ||
| interface Attachment { | ||
| id: string; | ||
| messageId: string; | ||
| filename: string; | ||
| url: string; | ||
| contentType: string; | ||
| size: number; | ||
| width: number | null; | ||
| height: number | null; | ||
| createdAt: string; | ||
| } | ||
| interface ReactionGroup { | ||
| emoji: string; | ||
| count: number; | ||
| userIds: string[]; | ||
| } | ||
| interface Thread { | ||
| id: string; | ||
| name: string; | ||
| channelId: string; | ||
| parentMessageId: string; | ||
| creatorId: string; | ||
| isArchived: boolean; | ||
| createdAt: string; | ||
| updatedAt: string; | ||
| } | ||
| interface SendMessageRequest { | ||
| content: string; | ||
| threadId?: string; | ||
| replyToId?: string; | ||
| } | ||
| interface UpdateMessageRequest { | ||
| content: string; | ||
| } | ||
| type NotificationType = 'mention' | 'reply' | 'dm' | 'system'; | ||
| interface Notification { | ||
| id: string; | ||
| userId: string; | ||
| type: NotificationType; | ||
| title: string; | ||
| body: string | null; | ||
| referenceId: string | null; | ||
| referenceType: string | null; | ||
| isRead: boolean; | ||
| createdAt: string; | ||
| } | ||
| interface DmChannel { | ||
| id: string; | ||
| userAId: string; | ||
| userBId: string; | ||
| lastMessageAt: string | null; | ||
| createdAt: string; | ||
| otherUser?: { | ||
| id: string; | ||
| username: string; | ||
| displayName: string; | ||
| avatarUrl: string | null; | ||
| status: string; | ||
| }; | ||
| } | ||
| /** DM message — mirrors channel Message but scoped to DM channels */ | ||
| interface DmMessage { | ||
| id: string; | ||
| content: string; | ||
| dmChannelId: string; | ||
| authorId: string; | ||
| replyToId: string | null; | ||
| isEdited: boolean; | ||
| createdAt: string; | ||
| updatedAt: string; | ||
| author?: { | ||
| id: string; | ||
| username: string; | ||
| displayName: string; | ||
| avatarUrl: string | null; | ||
| isBot: boolean; | ||
| }; | ||
| attachments?: DmAttachment[]; | ||
| reactions?: ReactionGroup[]; | ||
| } | ||
| interface DmAttachment { | ||
| id: string; | ||
| dmMessageId: string; | ||
| filename: string; | ||
| url: string; | ||
| contentType: string; | ||
| size: number; | ||
| width: number | null; | ||
| height: number | null; | ||
| createdAt: string; | ||
| } | ||
| interface UpdateDmMessageRequest { | ||
| content: string; | ||
| } | ||
| interface Server { | ||
| id: string; | ||
| name: string; | ||
| iconUrl: string | null; | ||
| ownerId: string; | ||
| inviteCode: string; | ||
| createdAt: string; | ||
| updatedAt: string; | ||
| } | ||
| interface CreateServerRequest { | ||
| name: string; | ||
| iconUrl?: string; | ||
| } | ||
| interface UpdateServerRequest { | ||
| name?: string; | ||
| iconUrl?: string; | ||
| } | ||
| type MemberRole = 'owner' | 'admin' | 'member'; | ||
| interface Member { | ||
| id: string; | ||
| userId: string; | ||
| serverId: string; | ||
| role: MemberRole; | ||
| nickname: string | null; | ||
| joinedAt: string; | ||
| user?: { | ||
| id: string; | ||
| username: string; | ||
| displayName: string; | ||
| avatarUrl: string | null; | ||
| status: string; | ||
| isBot: boolean; | ||
| }; | ||
| } | ||
| type UserStatus = 'online' | 'idle' | 'dnd' | 'offline'; | ||
| interface User { | ||
| id: string; | ||
| email: string; | ||
| username: string; | ||
| displayName: string; | ||
| avatarUrl: string | null; | ||
| status: UserStatus; | ||
| isBot: boolean; | ||
| createdAt: string; | ||
| updatedAt: string; | ||
| } | ||
| interface UserProfile { | ||
| id: string; | ||
| username: string; | ||
| displayName: string; | ||
| avatarUrl: string | null; | ||
| status: UserStatus; | ||
| isBot: boolean; | ||
| } | ||
| interface LoginRequest { | ||
| email: string; | ||
| password: string; | ||
| } | ||
| interface RegisterRequest { | ||
| email: string; | ||
| username: string; | ||
| displayName: string; | ||
| password: string; | ||
| } | ||
| interface AuthResponse { | ||
| user: User; | ||
| accessToken: string; | ||
| refreshToken: string; | ||
| } | ||
| export type { Agent, AgentCapability, AgentInfo, AgentKernelType, AgentStatus, Attachment, AuthResponse, Channel, ChannelSortBy, ChannelSortDirection, ChannelSortOptions, ChannelType, CreateAgentRequest, CreateChannelRequest, CreateServerRequest, DmAttachment, DmChannel, DmMessage, FriendEntry, FriendSource, Friendship, FriendshipStatus, LoginRequest, Member, MemberRole, Message, Notification, NotificationType, ReactionGroup, RegisterRequest, SendMessageRequest, Server, Thread, UpdateChannelRequest, UpdateDmMessageRequest, UpdateMessageRequest, UpdateServerRequest, User, UserProfile, UserStatus }; |
| type AgentStatus = 'running' | 'stopped' | 'error'; | ||
| type AgentKernelType = 'claude-code' | 'cursor' | 'mcp-server' | 'custom'; | ||
| type AgentCapability = 'chat' | 'code-gen' | 'code-review' | 'research' | 'tools' | 'file-access'; | ||
| interface Agent { | ||
| id: string; | ||
| userId: string; | ||
| kernelType: AgentKernelType; | ||
| config: Record<string, unknown>; | ||
| containerId: string | null; | ||
| status: AgentStatus; | ||
| ownerId: string; | ||
| createdAt: string; | ||
| updatedAt: string; | ||
| user?: { | ||
| id: string; | ||
| username: string; | ||
| displayName: string; | ||
| avatarUrl: string | null; | ||
| }; | ||
| capabilities?: AgentCapability[]; | ||
| } | ||
| interface CreateAgentRequest { | ||
| name: string; | ||
| kernelType: AgentKernelType; | ||
| config?: Record<string, unknown>; | ||
| } | ||
| interface AgentInfo { | ||
| id: string; | ||
| name: string; | ||
| kernelType: AgentKernelType; | ||
| status: AgentStatus; | ||
| capabilities: AgentCapability[]; | ||
| } | ||
| type ChannelType = 'text' | 'voice' | 'announcement'; | ||
| interface Channel { | ||
| id: string; | ||
| name: string; | ||
| type: ChannelType; | ||
| serverId: string; | ||
| topic: string | null; | ||
| position: number; | ||
| createdAt: string; | ||
| updatedAt: string; | ||
| /** Last message timestamp for sorting by activity */ | ||
| lastMessageAt?: string | null; | ||
| } | ||
| interface CreateChannelRequest { | ||
| name: string; | ||
| type?: ChannelType; | ||
| topic?: string; | ||
| } | ||
| interface UpdateChannelRequest { | ||
| name?: string; | ||
| topic?: string; | ||
| position?: number; | ||
| } | ||
| /** Channel sorting options */ | ||
| type ChannelSortBy = 'position' | 'createdAt' | 'updatedAt' | 'lastMessageAt' | 'lastAccessedAt'; | ||
| type ChannelSortDirection = 'asc' | 'desc'; | ||
| interface ChannelSortOptions { | ||
| by: ChannelSortBy; | ||
| direction: ChannelSortDirection; | ||
| } | ||
| type FriendshipStatus = 'pending' | 'accepted' | 'blocked'; | ||
| interface Friendship { | ||
| id: string; | ||
| requesterId: string; | ||
| addresseeId: string; | ||
| status: FriendshipStatus; | ||
| createdAt: string; | ||
| updatedAt: string; | ||
| } | ||
| type FriendSource = 'friend' | 'owned_claw' | 'rented_claw'; | ||
| interface FriendEntry { | ||
| friendshipId: string; | ||
| /** Where this friend entry comes from */ | ||
| source: FriendSource; | ||
| user: { | ||
| id: string; | ||
| username: string; | ||
| displayName: string | null; | ||
| avatarUrl: string | null; | ||
| status: string; | ||
| isBot: boolean; | ||
| }; | ||
| createdAt: string; | ||
| } | ||
| interface Message { | ||
| id: string; | ||
| content: string; | ||
| channelId: string; | ||
| authorId: string; | ||
| threadId: string | null; | ||
| replyToId: string | null; | ||
| isEdited: boolean; | ||
| isPinned: boolean; | ||
| createdAt: string; | ||
| updatedAt: string; | ||
| author?: { | ||
| id: string; | ||
| username: string; | ||
| displayName: string; | ||
| avatarUrl: string | null; | ||
| isBot: boolean; | ||
| }; | ||
| attachments?: Attachment[]; | ||
| reactions?: ReactionGroup[]; | ||
| } | ||
| interface Attachment { | ||
| id: string; | ||
| messageId: string; | ||
| filename: string; | ||
| url: string; | ||
| contentType: string; | ||
| size: number; | ||
| width: number | null; | ||
| height: number | null; | ||
| createdAt: string; | ||
| } | ||
| interface ReactionGroup { | ||
| emoji: string; | ||
| count: number; | ||
| userIds: string[]; | ||
| } | ||
| interface Thread { | ||
| id: string; | ||
| name: string; | ||
| channelId: string; | ||
| parentMessageId: string; | ||
| creatorId: string; | ||
| isArchived: boolean; | ||
| createdAt: string; | ||
| updatedAt: string; | ||
| } | ||
| interface SendMessageRequest { | ||
| content: string; | ||
| threadId?: string; | ||
| replyToId?: string; | ||
| } | ||
| interface UpdateMessageRequest { | ||
| content: string; | ||
| } | ||
| type NotificationType = 'mention' | 'reply' | 'dm' | 'system'; | ||
| interface Notification { | ||
| id: string; | ||
| userId: string; | ||
| type: NotificationType; | ||
| title: string; | ||
| body: string | null; | ||
| referenceId: string | null; | ||
| referenceType: string | null; | ||
| isRead: boolean; | ||
| createdAt: string; | ||
| } | ||
| interface DmChannel { | ||
| id: string; | ||
| userAId: string; | ||
| userBId: string; | ||
| lastMessageAt: string | null; | ||
| createdAt: string; | ||
| otherUser?: { | ||
| id: string; | ||
| username: string; | ||
| displayName: string; | ||
| avatarUrl: string | null; | ||
| status: string; | ||
| }; | ||
| } | ||
| /** DM message — mirrors channel Message but scoped to DM channels */ | ||
| interface DmMessage { | ||
| id: string; | ||
| content: string; | ||
| dmChannelId: string; | ||
| authorId: string; | ||
| replyToId: string | null; | ||
| isEdited: boolean; | ||
| createdAt: string; | ||
| updatedAt: string; | ||
| author?: { | ||
| id: string; | ||
| username: string; | ||
| displayName: string; | ||
| avatarUrl: string | null; | ||
| isBot: boolean; | ||
| }; | ||
| attachments?: DmAttachment[]; | ||
| reactions?: ReactionGroup[]; | ||
| } | ||
| interface DmAttachment { | ||
| id: string; | ||
| dmMessageId: string; | ||
| filename: string; | ||
| url: string; | ||
| contentType: string; | ||
| size: number; | ||
| width: number | null; | ||
| height: number | null; | ||
| createdAt: string; | ||
| } | ||
| interface UpdateDmMessageRequest { | ||
| content: string; | ||
| } | ||
| interface Server { | ||
| id: string; | ||
| name: string; | ||
| iconUrl: string | null; | ||
| ownerId: string; | ||
| inviteCode: string; | ||
| createdAt: string; | ||
| updatedAt: string; | ||
| } | ||
| interface CreateServerRequest { | ||
| name: string; | ||
| iconUrl?: string; | ||
| } | ||
| interface UpdateServerRequest { | ||
| name?: string; | ||
| iconUrl?: string; | ||
| } | ||
| type MemberRole = 'owner' | 'admin' | 'member'; | ||
| interface Member { | ||
| id: string; | ||
| userId: string; | ||
| serverId: string; | ||
| role: MemberRole; | ||
| nickname: string | null; | ||
| joinedAt: string; | ||
| user?: { | ||
| id: string; | ||
| username: string; | ||
| displayName: string; | ||
| avatarUrl: string | null; | ||
| status: string; | ||
| isBot: boolean; | ||
| }; | ||
| } | ||
| type UserStatus = 'online' | 'idle' | 'dnd' | 'offline'; | ||
| interface User { | ||
| id: string; | ||
| email: string; | ||
| username: string; | ||
| displayName: string; | ||
| avatarUrl: string | null; | ||
| status: UserStatus; | ||
| isBot: boolean; | ||
| createdAt: string; | ||
| updatedAt: string; | ||
| } | ||
| interface UserProfile { | ||
| id: string; | ||
| username: string; | ||
| displayName: string; | ||
| avatarUrl: string | null; | ||
| status: UserStatus; | ||
| isBot: boolean; | ||
| } | ||
| interface LoginRequest { | ||
| email: string; | ||
| password: string; | ||
| } | ||
| interface RegisterRequest { | ||
| email: string; | ||
| username: string; | ||
| displayName: string; | ||
| password: string; | ||
| } | ||
| interface AuthResponse { | ||
| user: User; | ||
| accessToken: string; | ||
| refreshToken: string; | ||
| } | ||
| export type { Agent, AgentCapability, AgentInfo, AgentKernelType, AgentStatus, Attachment, AuthResponse, Channel, ChannelSortBy, ChannelSortDirection, ChannelSortOptions, ChannelType, CreateAgentRequest, CreateChannelRequest, CreateServerRequest, DmAttachment, DmChannel, DmMessage, FriendEntry, FriendSource, Friendship, FriendshipStatus, LoginRequest, Member, MemberRole, Message, Notification, NotificationType, ReactionGroup, RegisterRequest, SendMessageRequest, Server, Thread, UpdateChannelRequest, UpdateDmMessageRequest, UpdateMessageRequest, UpdateServerRequest, User, UserProfile, UserStatus }; |
| import "../chunk-6H4LIJZC.js"; |
| "use strict"; | ||
| var __defProp = Object.defineProperty; | ||
| var __getOwnPropDesc = Object.getOwnPropertyDescriptor; | ||
| var __getOwnPropNames = Object.getOwnPropertyNames; | ||
| var __hasOwnProp = Object.prototype.hasOwnProperty; | ||
| var __export = (target, all) => { | ||
| for (var name in all) | ||
| __defProp(target, name, { get: all[name], enumerable: true }); | ||
| }; | ||
| var __copyProps = (to, from, except, desc) => { | ||
| if (from && typeof from === "object" || typeof from === "function") { | ||
| for (let key of __getOwnPropNames(from)) | ||
| if (!__hasOwnProp.call(to, key) && key !== except) | ||
| __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); | ||
| } | ||
| return to; | ||
| }; | ||
| var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); | ||
| // src/utils/index.ts | ||
| var utils_exports = {}; | ||
| __export(utils_exports, { | ||
| CAT_AVATAR_COUNT: () => CAT_AVATAR_COUNT, | ||
| formatDate: () => formatDate, | ||
| generateInviteCode: () => generateInviteCode, | ||
| generateRandomCatConfig: () => generateRandomCatConfig, | ||
| getAllCatAvatars: () => getAllCatAvatars, | ||
| getCatAvatar: () => getCatAvatar, | ||
| getCatAvatarByUserId: () => getCatAvatarByUserId, | ||
| getCatSvgString: () => getCatSvgString, | ||
| isValidEmail: () => isValidEmail, | ||
| renderCatSvg: () => renderCatSvg, | ||
| slugify: () => slugify | ||
| }); | ||
| module.exports = __toCommonJS(utils_exports); | ||
| var import_nanoid = require("nanoid"); | ||
| // src/utils/avatar-generator.ts | ||
| var COLORS = { | ||
| bg: [ | ||
| "transparent", | ||
| "#1e1f22", | ||
| "#313338", | ||
| "#5865F2", | ||
| "#23a559", | ||
| "#da373c", | ||
| "#f472b6", | ||
| "#3b82f6", | ||
| "#fbbf24", | ||
| "#a855f7", | ||
| "#1abc9c", | ||
| "#f39c12", | ||
| "#e74c3c" | ||
| ], | ||
| body: [ | ||
| "#2d2d30", | ||
| "#e8842c", | ||
| "#e8e8e8", | ||
| "#7a7a80", | ||
| "#d4a574", | ||
| "#6b8094", | ||
| "#f472b6", | ||
| "#c8d6e5", | ||
| "#3e2723", | ||
| "#bdc3c7", | ||
| "#ffb8b8" | ||
| ], | ||
| eyes: [ | ||
| "#f8e71c", | ||
| "#00f3ff", | ||
| "#4ade80", | ||
| "#60a5fa", | ||
| "#a855f7", | ||
| "#fbbf24", | ||
| "#f87171", | ||
| "#ffc0cb", | ||
| "#1dd1a1", | ||
| "#e056fd" | ||
| ], | ||
| pattern: ["#1a1a1c", "#ffffff", "#5a4a46", "#3d3d40", "#9a9aa0", "#d1ccc0", "#2d3436"] | ||
| }; | ||
| function getRandomElement(arr) { | ||
| return arr[Math.floor(Math.random() * arr.length)]; | ||
| } | ||
| function generateRandomCatConfig() { | ||
| return { | ||
| bg: getRandomElement(COLORS.bg), | ||
| bgPattern: getRandomElement(["none", "dots", "stripes", "grid", "stars"]), | ||
| body: getRandomElement(COLORS.body), | ||
| pattern: getRandomElement([ | ||
| "none", | ||
| "tabby", | ||
| "tuxedo", | ||
| "siamese", | ||
| "calico", | ||
| "bicolor" | ||
| ]), | ||
| patternColor: getRandomElement(COLORS.pattern), | ||
| eyeColor: getRandomElement(COLORS.eyes), | ||
| expression: getRandomElement([ | ||
| "smile", | ||
| "open", | ||
| "flat", | ||
| "sad", | ||
| "surprised", | ||
| "kawaii", | ||
| "winking", | ||
| "smirk" | ||
| ]), | ||
| decoration: getRandomElement([ | ||
| "none", | ||
| "glasses", | ||
| "blush", | ||
| "scar", | ||
| "flower", | ||
| "fish", | ||
| "headband" | ||
| ]) | ||
| }; | ||
| } | ||
| function renderCatSvg(config) { | ||
| const { bg, bgPattern, body, pattern, patternColor, eyeColor, expression, decoration } = config; | ||
| const stroke = "#1a1a1c"; | ||
| let svg = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">`; | ||
| if (bg && bg !== "transparent") { | ||
| svg += `<rect width="100" height="100" fill="${bg}" rx="20" />`; | ||
| const pColor = `rgba(255,255,255,0.15)`; | ||
| const cleanBg = bg.replace("#", ""); | ||
| if (bgPattern === "dots") { | ||
| svg += `<pattern id="p-${cleanBg}-dots" x="0" y="0" width="10" height="10" patternUnits="userSpaceOnUse"><circle cx="2" cy="2" r="2" fill="${pColor}"/></pattern><rect width="100" height="100" fill="url(#p-${cleanBg}-dots)" rx="20" />`; | ||
| } else if (bgPattern === "stripes") { | ||
| svg += `<pattern id="p-${cleanBg}-str" x="0" y="0" width="12" height="12" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="12" stroke="${pColor}" stroke-width="4"/></pattern><rect width="100" height="100" fill="url(#p-${cleanBg}-str)" rx="20" />`; | ||
| } else if (bgPattern === "grid") { | ||
| svg += `<pattern id="p-${cleanBg}-grid" width="16" height="16" patternUnits="userSpaceOnUse"><path d="M 16 0 L 0 0 0 16" fill="none" stroke="${pColor}" stroke-width="1"/></pattern><rect width="100" height="100" fill="url(#p-${cleanBg}-grid)" rx="20" />`; | ||
| } else if (bgPattern === "stars") { | ||
| svg += `<pattern id="p-${cleanBg}-star" width="20" height="20" patternUnits="userSpaceOnUse"><path d="M10,2 L12,8 L18,8 L13,12 L15,18 L10,14 L5,18 L7,12 L2,8 L8,8 Z" fill="${pColor}" transform="scale(0.5) translate(5,5)"/></pattern><rect width="100" height="100" fill="url(#p-${cleanBg}-star)" rx="20" />`; | ||
| } | ||
| } | ||
| svg += `<ellipse cx="50" cy="85" rx="30" ry="6" fill="rgba(0,0,0,0.2)"/>`; | ||
| svg += `<path d="M22,45 C15,22 28,18 34,22 C38,25 40,38 40,38" fill="${body}" stroke="${stroke}" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"/>`; | ||
| svg += `<path d="M78,45 C85,22 72,18 66,22 C62,25 60,38 60,38" fill="${body}" stroke="${stroke}" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"/>`; | ||
| svg += `<path d="M26,38 C22,26 29,24 33,26 C35,28 36,34 36,34" fill="#ffb8b8" opacity="0.8"/>`; | ||
| svg += `<path d="M74,38 C78,26 71,24 67,26 C65,28 64,34 64,34" fill="#ffb8b8" opacity="0.8"/>`; | ||
| svg += `<ellipse cx="50" cy="58" rx="38" ry="30" fill="${body}" stroke="${stroke}" stroke-width="2.5"/>`; | ||
| if (pattern === "tabby") { | ||
| svg += `<path d="M50,30 L50,40 M42,32 L46,39 M58,32 L54,39" stroke="${patternColor}" stroke-width="3" stroke-linecap="round" opacity="0.7"/>`; | ||
| svg += `<path d="M18,55 L26,57 M20,62 L27,62" stroke="${patternColor}" stroke-width="2.5" stroke-linecap="round" opacity="0.7"/>`; | ||
| svg += `<path d="M82,55 L74,57 M80,62 L73,62" stroke="${patternColor}" stroke-width="2.5" stroke-linecap="round" opacity="0.7"/>`; | ||
| } else if (pattern === "tuxedo") { | ||
| svg += `<path d="M50,56 C30,68 28,88 50,88 C72,88 70,68 50,56" fill="${patternColor}" opacity="0.95"/>`; | ||
| svg += `<ellipse cx="50" cy="65" rx="16" ry="12" fill="${patternColor}" opacity="0.95"/>`; | ||
| } else if (pattern === "siamese") { | ||
| svg += `<ellipse cx="50" cy="62" rx="20" ry="16" fill="${patternColor}" opacity="0.6"/>`; | ||
| } else if (pattern === "calico") { | ||
| svg += `<path d="M25,40 Q35,30 45,45 Q35,55 25,40" fill="${patternColor}" opacity="0.8"/>`; | ||
| svg += `<path d="M75,45 Q65,60 55,50 Q65,35 75,45" fill="#e8842c" opacity="0.8"/>`; | ||
| } else if (pattern === "bicolor") { | ||
| svg += `<path d="M12,58 Q30,30 50,40 Q60,70 50,88 Q12,88 12,58 Z" fill="${patternColor}" opacity="0.8"/>`; | ||
| } | ||
| if (decoration === "blush") { | ||
| svg += `<ellipse cx="28" cy="62" rx="5" ry="3" fill="#ff7675" opacity="0.7"/>`; | ||
| svg += `<ellipse cx="72" cy="62" rx="5" ry="3" fill="#ff7675" opacity="0.7"/>`; | ||
| } | ||
| if (decoration === "scar") { | ||
| svg += `<path d="M28,42 L40,52 M30,48 L35,43 M34,51 L39,46 M32,53 L37,48" stroke="#d63031" stroke-width="1.5" stroke-linecap="round"/>`; | ||
| } | ||
| const drawEye = (cx, cy, lookDir = 0) => { | ||
| if (expression === "kawaii") { | ||
| return `<path d="M${cx - 8},${cy} Q${cx},${cy - 8} ${cx + 8},${cy} Q${cx},${cy - 3} ${cx - 8},${cy}" fill="${eyeColor}" stroke="${stroke}" stroke-width="1.5"/><circle cx="${cx + lookDir}" cy="${cy - 2}" r="3" fill="white"/><circle cx="${cx - 3 + lookDir}" cy="${cy}" r="1" fill="white"/>`; | ||
| } else if (expression === "winking" && cx > 50) { | ||
| return `<path d="M${cx - 7},${cy + 2} Q${cx},${cy - 4} ${cx + 7},${cy + 2}" fill="none" stroke="${stroke}" stroke-width="2.5" stroke-linecap="round"/>`; | ||
| } else if (expression === "surprised") { | ||
| return `<circle cx="${cx}" cy="${cy}" r="8" fill="white" stroke="${stroke}" stroke-width="1.5"/><circle cx="${cx}" cy="${cy}" r="3" fill="${eyeColor}"/>`; | ||
| } else { | ||
| return `<circle cx="${cx}" cy="${cy}" r="7.5" fill="${eyeColor}" stroke="${stroke}" stroke-width="1.5"/><circle cx="${cx - 2 + lookDir}" cy="${cy - 2}" r="2.5" fill="white"/><circle cx="${cx + 2 + lookDir}" cy="${cy + 1}" r="1" fill="white"/>`; | ||
| } | ||
| }; | ||
| if (expression === "smirk") { | ||
| svg += `<path d="M26,50 L42,50" stroke="${stroke}" stroke-width="2.5" stroke-linecap="round"/>`; | ||
| svg += drawEye(66, 52, 2); | ||
| } else { | ||
| svg += drawEye(34, 52, 0); | ||
| svg += drawEye(66, 52, 0); | ||
| } | ||
| if (decoration === "glasses") { | ||
| svg += `<circle cx="34" cy="52" r="11" fill="rgba(255,255,255,0.2)" stroke="#2d3436" stroke-width="2.5"/>`; | ||
| svg += `<circle cx="66" cy="52" r="11" fill="rgba(255,255,255,0.2)" stroke="#2d3436" stroke-width="2.5"/>`; | ||
| svg += `<path d="M45,50 Q50,48 55,50" fill="none" stroke="#2d3436" stroke-width="2.5" stroke-linecap="round"/>`; | ||
| } | ||
| svg += `<path d="M47,62 L53,62 L50,65 Z" fill="#ff9ff3" stroke="${stroke}" stroke-width="1" stroke-linejoin="round"/>`; | ||
| if (expression === "smile" || expression === "kawaii" || expression === "winking") { | ||
| svg += `<path d="M42,67 Q46,72 50,67 M50,67 Q54,72 58,67" fill="none" stroke="${stroke}" stroke-width="2" stroke-linecap="round"/>`; | ||
| } else if (expression === "open") { | ||
| svg += `<path d="M46,67 Q50,75 54,67 Z" fill="#ff7675" stroke="${stroke}" stroke-width="1.5" stroke-linejoin="round"/>`; | ||
| } else if (expression === "flat") { | ||
| svg += `<path d="M47,68 L53,68" stroke="${stroke}" stroke-width="2" stroke-linecap="round"/>`; | ||
| } else if (expression === "sad") { | ||
| svg += `<path d="M43,70 Q50,64 57,70" fill="none" stroke="${stroke}" stroke-width="2" stroke-linecap="round"/>`; | ||
| } else if (expression === "surprised") { | ||
| svg += `<circle cx="50" cy="70" r="3" fill="#1a1a1c"/>`; | ||
| } else if (expression === "smirk") { | ||
| svg += `<path d="M46,67 Q52,69 56,64" fill="none" stroke="${stroke}" stroke-width="2" stroke-linecap="round"/>`; | ||
| } | ||
| svg += `<path d="M28,62 L15,60 M28,65 L14,66" stroke="${stroke}" stroke-width="1.5" stroke-linecap="round" opacity="0.6"/>`; | ||
| svg += `<path d="M72,62 L85,60 M72,65 L86,66" stroke="${stroke}" stroke-width="1.5" stroke-linecap="round" opacity="0.6"/>`; | ||
| if (decoration === "headband") { | ||
| svg += `<path d="M16,35 Q50,20 84,35" fill="none" stroke="#e17055" stroke-width="6" stroke-linecap="round"/>`; | ||
| svg += `<path d="M50,15 L60,25 L50,28 L40,25 Z" fill="#fab1a0" stroke="#e17055" stroke-width="2"/>`; | ||
| } else if (decoration === "flower") { | ||
| svg += `<path d="M75,30 Q80,20 85,30 Q95,25 85,35 Q90,45 80,40 Q70,45 75,35 Q65,25 75,30 Z" fill="#ffeaa7" stroke="#fdcb6e" stroke-width="1.5"/>`; | ||
| svg += `<circle cx="80" cy="33" r="3" fill="#d63031"/>`; | ||
| } else if (decoration === "fish") { | ||
| svg += `<path d="M40,82 Q50,75 60,82 L65,78 L65,86 L60,82 Q50,89 40,82 Z" fill="#81ecec" stroke="${stroke}" stroke-width="1.5"/>`; | ||
| svg += `<circle cx="45" cy="81" r="1" fill="${stroke}"/>`; | ||
| } | ||
| svg += `</svg>`; | ||
| return `data:image/svg+xml,${encodeURIComponent(svg.replace(/\n\s*/g, ""))}`; | ||
| } | ||
| // src/utils/pixel-cats.ts | ||
| var variants = [ | ||
| // 0: Shadow — Black cat (logo style) | ||
| { | ||
| body: "#2d2d30", | ||
| stroke: "#1a1a1c", | ||
| earInner: "#3d3d40", | ||
| eyeL: "#f8e71c", | ||
| eyeR: "#00f3ff", | ||
| nose: "#3a2a26" | ||
| }, | ||
| // 1: Mikan — Orange tabby | ||
| { | ||
| body: "#e8842c", | ||
| stroke: "#1a1a1c", | ||
| earInner: "#f5a623", | ||
| eyeL: "#4ade80", | ||
| eyeR: "#4ade80", | ||
| nose: "#d46b1a" | ||
| }, | ||
| // 2: Yuki — White cat | ||
| { | ||
| body: "#e8e8e8", | ||
| stroke: "#a0a0a0", | ||
| earInner: "#ffc0cb", | ||
| eyeL: "#60a5fa", | ||
| eyeR: "#60a5fa", | ||
| nose: "#f5a0b0" | ||
| }, | ||
| // 3: Haiiro — Gray cat | ||
| { | ||
| body: "#7a7a80", | ||
| stroke: "#4a4a50", | ||
| earInner: "#9a9aa0", | ||
| eyeL: "#fbbf24", | ||
| eyeR: "#fbbf24", | ||
| nose: "#5a4a46" | ||
| }, | ||
| // 4: Tuxedo — Black & white accents | ||
| { | ||
| body: "#2d2d30", | ||
| stroke: "#1a1a1c", | ||
| earInner: "#e0e0e0", | ||
| eyeL: "#22c55e", | ||
| eyeR: "#22c55e", | ||
| nose: "#3a2a26" | ||
| }, | ||
| // 5: Mocha — Cream/beige | ||
| { | ||
| body: "#d4a574", | ||
| stroke: "#8b6914", | ||
| earInner: "#e8c9a0", | ||
| eyeL: "#d97706", | ||
| eyeR: "#d97706", | ||
| nose: "#a0705a" | ||
| }, | ||
| // 6: Blue — Russian blue | ||
| { | ||
| body: "#6b8094", | ||
| stroke: "#3d5060", | ||
| earInner: "#8ba0b4", | ||
| eyeL: "#22c55e", | ||
| eyeR: "#22c55e", | ||
| nose: "#5a6a76" | ||
| }, | ||
| // 7: Sakura — Fantasy pink | ||
| { | ||
| body: "#f472b6", | ||
| stroke: "#be185d", | ||
| earInner: "#f9a8d4", | ||
| eyeL: "#a855f7", | ||
| eyeR: "#c084fc", | ||
| nose: "#d44a8c" | ||
| } | ||
| ]; | ||
| function makeCatSvg(c) { | ||
| return [ | ||
| '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">', | ||
| `<path d="M22,45 Q15,22 28,22 Q34,22 40,38" fill="${c.body}" stroke="${c.stroke}" stroke-width="2.5" stroke-linecap="round"/>`, | ||
| `<path d="M78,45 Q85,22 72,22 Q66,22 60,38" fill="${c.body}" stroke="${c.stroke}" stroke-width="2.5" stroke-linecap="round"/>`, | ||
| `<path d="M26,38 Q22,26 29,26 Q33,26 36,34" fill="${c.earInner}" opacity="0.5"/>`, | ||
| `<path d="M74,38 Q78,26 71,26 Q67,26 64,34" fill="${c.earInner}" opacity="0.5"/>`, | ||
| `<ellipse cx="50" cy="58" rx="36" ry="28" fill="${c.body}" stroke="${c.stroke}" stroke-width="2.5"/>`, | ||
| `<circle cx="35" cy="52" r="7" fill="${c.eyeL}" stroke="${c.stroke}" stroke-width="1.5"/>`, | ||
| `<circle cx="33" cy="49" r="2.5" fill="white"/>`, | ||
| `<circle cx="65" cy="52" r="7" fill="${c.eyeR}" stroke="${c.stroke}" stroke-width="1.5"/>`, | ||
| `<circle cx="63" cy="49" r="2.5" fill="white"/>`, | ||
| `<ellipse cx="50" cy="62" rx="3.5" ry="2.2" fill="${c.nose}"/>`, | ||
| `<path d="M42,67 Q46,72 50,67" fill="none" stroke="${c.stroke}" stroke-width="2" stroke-linecap="round"/>`, | ||
| `<path d="M50,67 Q54,72 58,67" fill="none" stroke="${c.stroke}" stroke-width="2" stroke-linecap="round"/>`, | ||
| "</svg>" | ||
| ].join(""); | ||
| } | ||
| var catDataUris = variants.map((v) => { | ||
| const svg = makeCatSvg(v); | ||
| return `data:image/svg+xml,${encodeURIComponent(svg)}`; | ||
| }); | ||
| function getCatAvatar(index) { | ||
| return catDataUris[index % catDataUris.length]; | ||
| } | ||
| function getCatAvatarByUserId(userId) { | ||
| let hash = 0; | ||
| for (let i = 0; i < userId.length; i++) { | ||
| hash = (hash << 5) - hash + userId.charCodeAt(i) | 0; | ||
| } | ||
| return getCatAvatar(Math.abs(hash) % catDataUris.length); | ||
| } | ||
| function getAllCatAvatars() { | ||
| const names = ["\u5F71\u5B50", "\u871C\u67D1", "\u5C0F\u96EA", "\u7070\u7070", "\u71D5\u5C3E\u670D", "\u6469\u5361", "\u84DD\u84DD", "\u5C0F\u6A31"]; | ||
| return catDataUris.map((uri, i) => ({ index: i, name: names[i], dataUri: uri })); | ||
| } | ||
| function getCatSvgString(index) { | ||
| return makeCatSvg(variants[index % variants.length]); | ||
| } | ||
| var CAT_AVATAR_COUNT = variants.length; | ||
| // src/utils/index.ts | ||
| var alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; | ||
| var generateInviteCode = (0, import_nanoid.customAlphabet)(alphabet, 8); | ||
| function formatDate(date) { | ||
| const d = typeof date === "string" ? new Date(date) : date; | ||
| return d.toISOString(); | ||
| } | ||
| function isValidEmail(email) { | ||
| return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email); | ||
| } | ||
| function slugify(text) { | ||
| return text.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, ""); | ||
| } | ||
| // Annotate the CommonJS export names for ESM import in node: | ||
| 0 && (module.exports = { | ||
| CAT_AVATAR_COUNT, | ||
| formatDate, | ||
| generateInviteCode, | ||
| generateRandomCatConfig, | ||
| getAllCatAvatars, | ||
| getCatAvatar, | ||
| getCatAvatarByUserId, | ||
| getCatSvgString, | ||
| isValidEmail, | ||
| renderCatSvg, | ||
| slugify | ||
| }); |
| type CatPattern = 'none' | 'tabby' | 'tuxedo' | 'siamese' | 'calico' | 'bicolor'; | ||
| type CatExpression = 'smile' | 'open' | 'flat' | 'sad' | 'surprised' | 'kawaii' | 'winking' | 'smirk'; | ||
| type CatDecoration = 'none' | 'glasses' | 'blush' | 'scar' | 'flower' | 'fish' | 'headband'; | ||
| type BgPattern = 'none' | 'dots' | 'stripes' | 'grid' | 'stars'; | ||
| interface CatConfig { | ||
| bg: string; | ||
| bgPattern: BgPattern; | ||
| body: string; | ||
| pattern: CatPattern; | ||
| patternColor: string; | ||
| eyeColor: string; | ||
| expression: CatExpression; | ||
| decoration: CatDecoration; | ||
| } | ||
| declare function generateRandomCatConfig(): CatConfig; | ||
| declare function renderCatSvg(config: CatConfig): string; | ||
| /** | ||
| * Pixel Art Cat Avatar System | ||
| * 8 unique cat variants with distinct color schemes inspired by the Shadow logo | ||
| */ | ||
| /** Get avatar data URI by index (0-7) */ | ||
| declare function getCatAvatar(index: number): string; | ||
| /** Get deterministic avatar by user ID string */ | ||
| declare function getCatAvatarByUserId(userId: string): string; | ||
| /** Get all cat avatars for selection UI */ | ||
| declare function getAllCatAvatars(): { | ||
| index: number; | ||
| name: string; | ||
| dataUri: string; | ||
| }[]; | ||
| /** Get the raw SVG string for a cat variant (useful for generating PNG files) */ | ||
| declare function getCatSvgString(index: number): string; | ||
| declare const CAT_AVATAR_COUNT: number; | ||
| declare const generateInviteCode: (size?: number) => string; | ||
| declare function formatDate(date: string | Date): string; | ||
| declare function isValidEmail(email: string): boolean; | ||
| declare function slugify(text: string): string; | ||
| export { type BgPattern, CAT_AVATAR_COUNT, type CatConfig, type CatDecoration, type CatExpression, type CatPattern, formatDate, generateInviteCode, generateRandomCatConfig, getAllCatAvatars, getCatAvatar, getCatAvatarByUserId, getCatSvgString, isValidEmail, renderCatSvg, slugify }; |
| type CatPattern = 'none' | 'tabby' | 'tuxedo' | 'siamese' | 'calico' | 'bicolor'; | ||
| type CatExpression = 'smile' | 'open' | 'flat' | 'sad' | 'surprised' | 'kawaii' | 'winking' | 'smirk'; | ||
| type CatDecoration = 'none' | 'glasses' | 'blush' | 'scar' | 'flower' | 'fish' | 'headband'; | ||
| type BgPattern = 'none' | 'dots' | 'stripes' | 'grid' | 'stars'; | ||
| interface CatConfig { | ||
| bg: string; | ||
| bgPattern: BgPattern; | ||
| body: string; | ||
| pattern: CatPattern; | ||
| patternColor: string; | ||
| eyeColor: string; | ||
| expression: CatExpression; | ||
| decoration: CatDecoration; | ||
| } | ||
| declare function generateRandomCatConfig(): CatConfig; | ||
| declare function renderCatSvg(config: CatConfig): string; | ||
| /** | ||
| * Pixel Art Cat Avatar System | ||
| * 8 unique cat variants with distinct color schemes inspired by the Shadow logo | ||
| */ | ||
| /** Get avatar data URI by index (0-7) */ | ||
| declare function getCatAvatar(index: number): string; | ||
| /** Get deterministic avatar by user ID string */ | ||
| declare function getCatAvatarByUserId(userId: string): string; | ||
| /** Get all cat avatars for selection UI */ | ||
| declare function getAllCatAvatars(): { | ||
| index: number; | ||
| name: string; | ||
| dataUri: string; | ||
| }[]; | ||
| /** Get the raw SVG string for a cat variant (useful for generating PNG files) */ | ||
| declare function getCatSvgString(index: number): string; | ||
| declare const CAT_AVATAR_COUNT: number; | ||
| declare const generateInviteCode: (size?: number) => string; | ||
| declare function formatDate(date: string | Date): string; | ||
| declare function isValidEmail(email: string): boolean; | ||
| declare function slugify(text: string): string; | ||
| export { type BgPattern, CAT_AVATAR_COUNT, type CatConfig, type CatDecoration, type CatExpression, type CatPattern, formatDate, generateInviteCode, generateRandomCatConfig, getAllCatAvatars, getCatAvatar, getCatAvatarByUserId, getCatSvgString, isValidEmail, renderCatSvg, slugify }; |
| import { | ||
| CAT_AVATAR_COUNT, | ||
| formatDate, | ||
| generateInviteCode, | ||
| generateRandomCatConfig, | ||
| getAllCatAvatars, | ||
| getCatAvatar, | ||
| getCatAvatarByUserId, | ||
| getCatSvgString, | ||
| isValidEmail, | ||
| renderCatSvg, | ||
| slugify | ||
| } from "../chunk-PXKHJSTK.js"; | ||
| export { | ||
| CAT_AVATAR_COUNT, | ||
| formatDate, | ||
| generateInviteCode, | ||
| generateRandomCatConfig, | ||
| getAllCatAvatars, | ||
| getCatAvatar, | ||
| getCatAvatarByUserId, | ||
| getCatSvgString, | ||
| isValidEmail, | ||
| renderCatSvg, | ||
| slugify | ||
| }; |
+22
-5
| { | ||
| "name": "@shadowob/shared", | ||
| "version": "0.4.0", | ||
| "version": "0.4.1", | ||
| "type": "module", | ||
| "main": "./dist/index.js", | ||
| "module": "./dist/index.js", | ||
| "require": "./dist/index.cjs", | ||
| "types": "./dist/index.d.ts", | ||
| "exports": { | ||
| ".": { | ||
| "types": "./dist/index.d.ts", | ||
| "development": "./src/index.ts", | ||
| "import": "./dist/index.js", | ||
| "types": "./dist/index.d.ts" | ||
| "require": "./dist/index.cjs", | ||
| "default": "./dist/index.js" | ||
| }, | ||
| "./types": { | ||
| "types": "./dist/types/index.d.ts", | ||
| "development": "./src/types/index.ts", | ||
| "import": "./dist/types/index.js", | ||
| "types": "./dist/types/index.d.ts" | ||
| "require": "./dist/types/index.cjs", | ||
| "default": "./dist/types/index.js" | ||
| }, | ||
| "./constants": { | ||
| "types": "./dist/constants/index.d.ts", | ||
| "development": "./src/constants/index.ts", | ||
| "import": "./dist/constants/index.js", | ||
| "types": "./dist/constants/index.d.ts" | ||
| "require": "./dist/constants/index.cjs", | ||
| "default": "./dist/constants/index.js" | ||
| }, | ||
| "./utils": { | ||
| "types": "./dist/utils/index.d.ts", | ||
| "development": "./src/utils/index.ts", | ||
| "import": "./dist/utils/index.js", | ||
| "types": "./dist/utils/index.d.ts" | ||
| "require": "./dist/utils/index.cjs", | ||
| "default": "./dist/utils/index.js" | ||
| } | ||
@@ -35,2 +49,5 @@ }, | ||
| }, | ||
| "publishConfig": { | ||
| "access": "public" | ||
| }, | ||
| "scripts": { | ||
@@ -37,0 +54,0 @@ "build": "tsup", |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Empty package
Supply chain riskPackage does not contain any code. It may be removed, is name squatting, or the result of a faulty package publish.
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
111002
218.42%21
950%1707
Infinity%1
-50%2
100%