🚀 Socket Launch Week Day 5:Introducing Repository Access Permissions and Custom Roles.Learn more
Sign In

@shadowob/shared

Package Overview
Dependencies
Maintainers
1
Versions
77
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@shadowob/shared - npm Package Compare versions

Comparing version
0.4.0
to
0.4.1
dist/chunk-6H4LIJZC.js
+59
// 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
};
"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",