javascript
examples
examples.js⚡javascript
/**
* 21.5 Capstone Projects - Examples
*
* Complete implementation examples for capstone projects
*/
// ============================================================
// PROJECT 1: Task Management System Core
// ============================================================
/**
* Event Bus - Central event management
*/
class EventBus {
constructor() {
this.events = new Map();
}
on(event, handler) {
if (!this.events.has(event)) {
this.events.set(event, new Set());
}
this.events.get(event).add(handler);
return () => this.off(event, handler);
}
off(event, handler) {
const handlers = this.events.get(event);
if (handlers) {
handlers.delete(handler);
}
}
emit(event, data) {
const handlers = this.events.get(event);
if (handlers) {
handlers.forEach((handler) => {
try {
handler(data);
} catch (error) {
console.error(`Error in event handler for ${event}:`, error);
}
});
}
}
}
/**
* Store - State management with persistence
*/
class Store {
constructor(name, initialState = {}) {
this.name = name;
this.state = this.loadState() || initialState;
this.listeners = new Set();
}
loadState() {
try {
const saved = localStorage.getItem(`store_${this.name}`);
return saved ? JSON.parse(saved) : null;
} catch {
return null;
}
}
saveState() {
try {
localStorage.setItem(`store_${this.name}`, JSON.stringify(this.state));
} catch (error) {
console.error('Failed to save state:', error);
}
}
getState() {
return { ...this.state };
}
setState(updater) {
const newState =
typeof updater === 'function'
? updater(this.state)
: { ...this.state, ...updater };
this.state = newState;
this.saveState();
this.notify();
}
subscribe(listener) {
this.listeners.add(listener);
return () => this.listeners.delete(listener);
}
notify() {
this.listeners.forEach((listener) => listener(this.state));
}
}
/**
* Auth Module - Secure authentication
*/
const AuthModule = (() => {
const store = new Store('auth', { user: null, token: null });
const eventBus = new EventBus();
// Token management
const TOKEN_KEY = 'auth_token';
function getToken() {
return sessionStorage.getItem(TOKEN_KEY);
}
function setToken(token) {
if (token) {
sessionStorage.setItem(TOKEN_KEY, token);
} else {
sessionStorage.removeItem(TOKEN_KEY);
}
}
// Password validation
function validatePassword(password) {
const errors = [];
if (password.length < 8) errors.push('At least 8 characters');
if (!/[A-Z]/.test(password)) errors.push('At least one uppercase');
if (!/[a-z]/.test(password)) errors.push('At least one lowercase');
if (!/[0-9]/.test(password)) errors.push('At least one number');
if (!/[^A-Za-z0-9]/.test(password))
errors.push('At least one special character');
return { valid: errors.length === 0, errors };
}
// Email validation
function validateEmail(email) {
const re = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return re.test(email);
}
// Simulated API calls
async function login(email, password) {
if (!validateEmail(email)) {
throw new Error('Invalid email format');
}
// Simulate API call
await new Promise((resolve) => setTimeout(resolve, 500));
// In real app, this would be an API call
const mockUser = { id: '1', email, name: email.split('@')[0] };
const mockToken = btoa(
JSON.stringify({ userId: mockUser.id, exp: Date.now() + 3600000 })
);
setToken(mockToken);
store.setState({ user: mockUser, token: mockToken });
eventBus.emit('auth:login', mockUser);
return mockUser;
}
async function logout() {
setToken(null);
store.setState({ user: null, token: null });
eventBus.emit('auth:logout');
}
async function register(email, password, name) {
if (!validateEmail(email)) {
throw new Error('Invalid email format');
}
const passwordValidation = validatePassword(password);
if (!passwordValidation.valid) {
throw new Error(
`Password requirements: ${passwordValidation.errors.join(', ')}`
);
}
// Simulate API call
await new Promise((resolve) => setTimeout(resolve, 500));
return { success: true, message: 'Registration successful' };
}
function isAuthenticated() {
const token = getToken();
if (!token) return false;
try {
const payload = JSON.parse(atob(token));
return payload.exp > Date.now();
} catch {
return false;
}
}
function getCurrentUser() {
return store.getState().user;
}
return {
login,
logout,
register,
isAuthenticated,
getCurrentUser,
validatePassword,
validateEmail,
on: eventBus.on.bind(eventBus),
subscribe: store.subscribe.bind(store),
};
})();
/**
* Task Module - Task management with offline support
*/
const TaskModule = (() => {
const store = new Store('tasks', { tasks: [], filters: {} });
const eventBus = new EventBus();
// Generate unique ID
function generateId() {
return `task_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
}
// Sanitize task input
function sanitizeTask(task) {
return {
id: task.id || generateId(),
title: String(task.title || '')
.slice(0, 200)
.trim(),
description: String(task.description || '')
.slice(0, 2000)
.trim(),
status: ['todo', 'in-progress', 'done'].includes(task.status)
? task.status
: 'todo',
priority: ['low', 'medium', 'high'].includes(task.priority)
? task.priority
: 'medium',
dueDate: task.dueDate ? new Date(task.dueDate).toISOString() : null,
labels: Array.isArray(task.labels)
? task.labels.slice(0, 10).map((l) => String(l).slice(0, 50))
: [],
assignee: task.assignee ? String(task.assignee).slice(0, 100) : null,
createdAt: task.createdAt || new Date().toISOString(),
updatedAt: new Date().toISOString(),
};
}
// CRUD Operations
function createTask(taskData) {
const task = sanitizeTask(taskData);
store.setState((state) => ({
...state,
tasks: [...state.tasks, task],
}));
eventBus.emit('task:created', task);
return task;
}
function updateTask(id, updates) {
let updatedTask = null;
store.setState((state) => ({
...state,
tasks: state.tasks.map((task) => {
if (task.id === id) {
updatedTask = sanitizeTask({ ...task, ...updates, id });
return updatedTask;
}
return task;
}),
}));
if (updatedTask) {
eventBus.emit('task:updated', updatedTask);
}
return updatedTask;
}
function deleteTask(id) {
const task = getTask(id);
if (task) {
store.setState((state) => ({
...state,
tasks: state.tasks.filter((t) => t.id !== id),
}));
eventBus.emit('task:deleted', task);
}
return task;
}
function getTask(id) {
return store.getState().tasks.find((t) => t.id === id);
}
function getAllTasks() {
return [...store.getState().tasks];
}
// Filtering and sorting
function getTasks(options = {}) {
let tasks = getAllTasks();
// Apply filters
if (options.status) {
tasks = tasks.filter((t) => t.status === options.status);
}
if (options.priority) {
tasks = tasks.filter((t) => t.priority === options.priority);
}
if (options.search) {
const search = options.search.toLowerCase();
tasks = tasks.filter(
(t) =>
t.title.toLowerCase().includes(search) ||
t.description.toLowerCase().includes(search)
);
}
if (options.labels && options.labels.length) {
tasks = tasks.filter((t) =>
options.labels.some((label) => t.labels.includes(label))
);
}
// Apply sorting
if (options.sortBy) {
const sortOrder = options.sortOrder === 'desc' ? -1 : 1;
tasks.sort((a, b) => {
if (options.sortBy === 'dueDate') {
return (
sortOrder * (new Date(a.dueDate || 0) - new Date(b.dueDate || 0))
);
}
if (options.sortBy === 'priority') {
const priorityOrder = { high: 3, medium: 2, low: 1 };
return (
sortOrder * (priorityOrder[b.priority] - priorityOrder[a.priority])
);
}
if (options.sortBy === 'createdAt') {
return sortOrder * (new Date(b.createdAt) - new Date(a.createdAt));
}
return 0;
});
}
return tasks;
}
return {
createTask,
updateTask,
deleteTask,
getTask,
getAllTasks,
getTasks,
on: eventBus.on.bind(eventBus),
subscribe: store.subscribe.bind(store),
};
})();
// ============================================================
// PROJECT 2: E-Commerce Dashboard Components
// ============================================================
/**
* Virtual List - Efficient rendering of large lists
*/
class VirtualList {
constructor(container, options = {}) {
this.container = container;
this.itemHeight = options.itemHeight || 50;
this.bufferSize = options.bufferSize || 5;
this.items = [];
this.renderedItems = new Map();
this.viewport = document.createElement('div');
this.viewport.style.cssText = 'overflow-y: auto; height: 100%;';
this.content = document.createElement('div');
this.content.style.position = 'relative';
this.viewport.appendChild(this.content);
this.container.appendChild(this.viewport);
this.viewport.addEventListener('scroll', this.handleScroll.bind(this));
this.renderItem =
options.renderItem ||
((item) => {
const el = document.createElement('div');
el.textContent = JSON.stringify(item);
return el;
});
}
setItems(items) {
this.items = items;
this.content.style.height = `${items.length * this.itemHeight}px`;
this.render();
}
handleScroll() {
requestAnimationFrame(() => this.render());
}
render() {
const scrollTop = this.viewport.scrollTop;
const viewportHeight = this.viewport.clientHeight;
const startIndex = Math.max(
0,
Math.floor(scrollTop / this.itemHeight) - this.bufferSize
);
const endIndex = Math.min(
this.items.length,
Math.ceil((scrollTop + viewportHeight) / this.itemHeight) +
this.bufferSize
);
// Remove items outside viewport
for (const [index, element] of this.renderedItems) {
if (index < startIndex || index >= endIndex) {
element.remove();
this.renderedItems.delete(index);
}
}
// Add items in viewport
for (let i = startIndex; i < endIndex; i++) {
if (!this.renderedItems.has(i)) {
const element = this.renderItem(this.items[i], i);
element.style.cssText = `position: absolute; top: ${
i * this.itemHeight
}px; width: 100%; height: ${this.itemHeight}px;`;
this.content.appendChild(element);
this.renderedItems.set(i, element);
}
}
}
destroy() {
this.viewport.removeEventListener('scroll', this.handleScroll);
this.container.innerHTML = '';
}
}
/**
* Chart Component - Simple chart rendering
*/
class SimpleChart {
constructor(canvas, options = {}) {
this.canvas = canvas;
this.ctx = canvas.getContext('2d');
this.options = {
padding: 40,
gridLines: 5,
colors: ['#4A90D9', '#7BC67E', '#F5A623', '#D0021B', '#9013FE'],
...options,
};
this.data = [];
}
setData(data) {
this.data = data;
this.render();
}
clear() {
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
}
drawLine(data) {
this.clear();
const { width, height } = this.canvas;
const { padding, colors } = this.options;
const chartWidth = width - padding * 2;
const chartHeight = height - padding * 2;
if (data.length === 0) return;
const maxValue = Math.max(...data.map((d) => d.value));
const minValue = Math.min(...data.map((d) => d.value));
const range = maxValue - minValue || 1;
// Draw grid
this.ctx.strokeStyle = '#eee';
this.ctx.lineWidth = 1;
for (let i = 0; i <= this.options.gridLines; i++) {
const y = padding + (chartHeight / this.options.gridLines) * i;
this.ctx.beginPath();
this.ctx.moveTo(padding, y);
this.ctx.lineTo(width - padding, y);
this.ctx.stroke();
}
// Draw line
this.ctx.strokeStyle = colors[0];
this.ctx.lineWidth = 2;
this.ctx.beginPath();
data.forEach((point, i) => {
const x = padding + (chartWidth / (data.length - 1)) * i;
const y =
padding +
chartHeight -
((point.value - minValue) / range) * chartHeight;
if (i === 0) {
this.ctx.moveTo(x, y);
} else {
this.ctx.lineTo(x, y);
}
});
this.ctx.stroke();
// Draw points
this.ctx.fillStyle = colors[0];
data.forEach((point, i) => {
const x = padding + (chartWidth / (data.length - 1)) * i;
const y =
padding +
chartHeight -
((point.value - minValue) / range) * chartHeight;
this.ctx.beginPath();
this.ctx.arc(x, y, 4, 0, Math.PI * 2);
this.ctx.fill();
});
}
drawBar(data) {
this.clear();
const { width, height } = this.canvas;
const { padding, colors } = this.options;
const chartWidth = width - padding * 2;
const chartHeight = height - padding * 2;
if (data.length === 0) return;
const maxValue = Math.max(...data.map((d) => d.value));
const barWidth = (chartWidth / data.length) * 0.8;
const gap = (chartWidth / data.length) * 0.2;
data.forEach((point, i) => {
const barHeight = (point.value / maxValue) * chartHeight;
const x = padding + (chartWidth / data.length) * i + gap / 2;
const y = padding + chartHeight - barHeight;
this.ctx.fillStyle = colors[i % colors.length];
this.ctx.fillRect(x, y, barWidth, barHeight);
// Label
this.ctx.fillStyle = '#333';
this.ctx.font = '12px sans-serif';
this.ctx.textAlign = 'center';
this.ctx.fillText(point.label || '', x + barWidth / 2, height - 10);
});
}
}
/**
* Dashboard Analytics
*/
class DashboardAnalytics {
constructor() {
this.data = new Map();
this.cache = new Map();
this.cacheTimeout = 5 * 60 * 1000; // 5 minutes
}
async fetchMetrics(timeRange = '7d') {
const cacheKey = `metrics_${timeRange}`;
const cached = this.cache.get(cacheKey);
if (cached && Date.now() - cached.timestamp < this.cacheTimeout) {
return cached.data;
}
// Simulate API call
await new Promise((resolve) => setTimeout(resolve, 300));
const metrics = {
revenue: { value: 42350, change: 12.5 },
orders: { value: 1234, change: 8.2 },
customers: { value: 5678, change: 15.3 },
conversionRate: { value: 3.42, change: -2.1 },
};
this.cache.set(cacheKey, { data: metrics, timestamp: Date.now() });
return metrics;
}
async fetchSalesData(timeRange = '7d') {
const cacheKey = `sales_${timeRange}`;
const cached = this.cache.get(cacheKey);
if (cached && Date.now() - cached.timestamp < this.cacheTimeout) {
return cached.data;
}
// Simulate API call
await new Promise((resolve) => setTimeout(resolve, 300));
const days = timeRange === '7d' ? 7 : timeRange === '30d' ? 30 : 90;
const data = Array.from({ length: days }, (_, i) => ({
date: new Date(Date.now() - (days - i - 1) * 86400000)
.toISOString()
.split('T')[0],
value: Math.floor(Math.random() * 5000) + 1000,
orders: Math.floor(Math.random() * 100) + 20,
}));
this.cache.set(cacheKey, { data, timestamp: Date.now() });
return data;
}
clearCache() {
this.cache.clear();
}
}
// ============================================================
// PROJECT 3: Real-Time Chat Core
// ============================================================
/**
* Message Encryption (simplified for demo)
*/
class MessageEncryption {
constructor() {
this.encoder = new TextEncoder();
this.decoder = new TextDecoder();
}
async generateKeyPair() {
// In real app, use Web Crypto API
const keyPair = {
publicKey: this.generateRandomKey(),
privateKey: this.generateRandomKey(),
};
return keyPair;
}
generateRandomKey() {
return Array.from({ length: 32 }, () =>
Math.floor(Math.random() * 256)
.toString(16)
.padStart(2, '0')
).join('');
}
async encrypt(message, key) {
// Simplified XOR encryption for demo (use AES in production)
const messageBytes = this.encoder.encode(message);
const keyBytes = this.encoder.encode(key);
const encrypted = new Uint8Array(messageBytes.length);
for (let i = 0; i < messageBytes.length; i++) {
encrypted[i] = messageBytes[i] ^ keyBytes[i % keyBytes.length];
}
return btoa(String.fromCharCode(...encrypted));
}
async decrypt(encryptedMessage, key) {
const encrypted = new Uint8Array(
atob(encryptedMessage)
.split('')
.map((c) => c.charCodeAt(0))
);
const keyBytes = this.encoder.encode(key);
const decrypted = new Uint8Array(encrypted.length);
for (let i = 0; i < encrypted.length; i++) {
decrypted[i] = encrypted[i] ^ keyBytes[i % keyBytes.length];
}
return this.decoder.decode(decrypted);
}
}
/**
* Chat Room Manager
*/
class ChatRoom {
constructor(id, options = {}) {
this.id = id;
this.name = options.name || `Room ${id}`;
this.messages = [];
this.participants = new Map();
this.typing = new Set();
this.eventBus = new EventBus();
this.encryption = new MessageEncryption();
this.maxMessages = options.maxMessages || 1000;
}
join(user) {
this.participants.set(user.id, {
...user,
joinedAt: new Date(),
status: 'online',
});
this.eventBus.emit('participant:joined', user);
}
leave(userId) {
const user = this.participants.get(userId);
if (user) {
this.participants.delete(userId);
this.eventBus.emit('participant:left', user);
}
}
async sendMessage(userId, content, options = {}) {
const sender = this.participants.get(userId);
if (!sender) {
throw new Error('User not in room');
}
// Sanitize content
const sanitizedContent = this.sanitizeMessage(content);
const message = {
id: `msg_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
roomId: this.id,
senderId: userId,
senderName: sender.name,
content: sanitizedContent,
type: options.type || 'text',
timestamp: new Date().toISOString(),
status: 'sent',
reactions: [],
replyTo: options.replyTo || null,
};
// Add to messages (with limit)
this.messages.push(message);
if (this.messages.length > this.maxMessages) {
this.messages = this.messages.slice(-this.maxMessages);
}
this.eventBus.emit('message:sent', message);
// Simulate delivery
setTimeout(() => {
message.status = 'delivered';
this.eventBus.emit('message:delivered', message);
}, 100);
return message;
}
sanitizeMessage(content) {
// Basic XSS prevention
return String(content)
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/"/g, '"')
.replace(/'/g, ''')
.slice(0, 5000); // Limit length
}
setTyping(userId, isTyping) {
if (isTyping) {
this.typing.add(userId);
} else {
this.typing.delete(userId);
}
this.eventBus.emit('typing:changed', Array.from(this.typing));
}
getTypingUsers() {
return Array.from(this.typing)
.map((id) => this.participants.get(id))
.filter(Boolean);
}
addReaction(messageId, userId, reaction) {
const message = this.messages.find((m) => m.id === messageId);
if (message) {
const existing = message.reactions.findIndex(
(r) => r.userId === userId && r.reaction === reaction
);
if (existing > -1) {
message.reactions.splice(existing, 1);
} else {
message.reactions.push({
userId,
reaction,
timestamp: new Date().toISOString(),
});
}
this.eventBus.emit('message:reaction', {
messageId,
reactions: message.reactions,
});
}
}
getMessages(options = {}) {
let messages = [...this.messages];
if (options.before) {
const beforeIndex = messages.findIndex((m) => m.id === options.before);
if (beforeIndex > 0) {
messages = messages.slice(
Math.max(0, beforeIndex - (options.limit || 50)),
beforeIndex
);
}
} else if (options.limit) {
messages = messages.slice(-options.limit);
}
return messages;
}
on(event, handler) {
return this.eventBus.on(event, handler);
}
}
/**
* Chat Manager - Manages multiple rooms
*/
class ChatManager {
constructor() {
this.rooms = new Map();
this.users = new Map();
this.eventBus = new EventBus();
}
createRoom(id, options = {}) {
if (this.rooms.has(id)) {
throw new Error(`Room ${id} already exists`);
}
const room = new ChatRoom(id, options);
this.rooms.set(id, room);
this.eventBus.emit('room:created', room);
return room;
}
getRoom(id) {
return this.rooms.get(id);
}
deleteRoom(id) {
const room = this.rooms.get(id);
if (room) {
this.rooms.delete(id);
this.eventBus.emit('room:deleted', { id });
}
}
registerUser(user) {
this.users.set(user.id, {
...user,
status: 'online',
lastSeen: new Date(),
});
}
setUserStatus(userId, status) {
const user = this.users.get(userId);
if (user) {
user.status = status;
user.lastSeen = new Date();
this.eventBus.emit('user:status', { userId, status });
}
}
on(event, handler) {
return this.eventBus.on(event, handler);
}
}
// ============================================================
// PROJECT 4: Code Playground Core
// ============================================================
/**
* Code Sandbox - Safe code execution
*/
class CodeSandbox {
constructor(options = {}) {
this.timeout = options.timeout || 5000;
this.maxLogs = options.maxLogs || 100;
this.iframe = null;
this.logs = [];
}
createSandbox() {
// Create sandboxed iframe
this.iframe = document.createElement('iframe');
this.iframe.sandbox = 'allow-scripts';
this.iframe.style.cssText = 'display: none;';
document.body.appendChild(this.iframe);
return this.iframe;
}
async execute(code, options = {}) {
this.logs = [];
return new Promise((resolve, reject) => {
const timeoutId = setTimeout(() => {
this.destroy();
reject(new Error('Execution timeout'));
}, this.timeout);
try {
const sandbox = this.createSandbox();
const contentWindow = sandbox.contentWindow;
// Override console
const wrappedCode = `
(function() {
const logs = [];
const originalConsole = console;
window.console = {
log: (...args) => {
logs.push({ type: 'log', args: args.map(String) });
if (logs.length > ${this.maxLogs}) logs.shift();
},
error: (...args) => {
logs.push({ type: 'error', args: args.map(String) });
},
warn: (...args) => {
logs.push({ type: 'warn', args: args.map(String) });
}
};
try {
${code}
window.parent.postMessage({ type: 'success', logs }, '*');
} catch (error) {
window.parent.postMessage({
type: 'error',
error: error.message,
logs
}, '*');
}
})();
`;
// Listen for results
const handleMessage = (event) => {
if (event.source === contentWindow) {
clearTimeout(timeoutId);
window.removeEventListener('message', handleMessage);
this.logs = event.data.logs || [];
this.destroy();
if (event.data.type === 'success') {
resolve({ logs: this.logs });
} else {
reject(new Error(event.data.error));
}
}
};
window.addEventListener('message', handleMessage);
// Execute code
const script = contentWindow.document.createElement('script');
script.textContent = wrappedCode;
contentWindow.document.body.appendChild(script);
} catch (error) {
clearTimeout(timeoutId);
this.destroy();
reject(error);
}
});
}
destroy() {
if (this.iframe && this.iframe.parentNode) {
this.iframe.parentNode.removeChild(this.iframe);
}
this.iframe = null;
}
}
/**
* Code Editor State
*/
class CodeEditorState {
constructor() {
this.files = new Map();
this.history = [];
this.historyIndex = -1;
this.maxHistory = 100;
}
setFile(name, content) {
const previous = this.files.get(name);
this.files.set(name, content);
// Add to history
this.history = this.history.slice(0, this.historyIndex + 1);
this.history.push({ name, previous, current: content });
if (this.history.length > this.maxHistory) {
this.history.shift();
}
this.historyIndex = this.history.length - 1;
}
getFile(name) {
return this.files.get(name);
}
deleteFile(name) {
const previous = this.files.get(name);
this.files.delete(name);
this.history.push({ name, previous, current: null, deleted: true });
this.historyIndex = this.history.length - 1;
}
undo() {
if (this.historyIndex < 0) return false;
const entry = this.history[this.historyIndex];
if (entry.deleted) {
this.files.set(entry.name, entry.previous);
} else if (entry.previous === undefined) {
this.files.delete(entry.name);
} else {
this.files.set(entry.name, entry.previous);
}
this.historyIndex--;
return true;
}
redo() {
if (this.historyIndex >= this.history.length - 1) return false;
this.historyIndex++;
const entry = this.history[this.historyIndex];
if (entry.deleted) {
this.files.delete(entry.name);
} else {
this.files.set(entry.name, entry.current);
}
return true;
}
getAllFiles() {
return Object.fromEntries(this.files);
}
toJSON() {
return {
files: Object.fromEntries(this.files),
};
}
fromJSON(data) {
this.files = new Map(Object.entries(data.files || {}));
this.history = [];
this.historyIndex = -1;
}
}
// ============================================================
// DEMO & TESTING
// ============================================================
console.log('=== Capstone Project Examples ===');
// Demo Task Module
console.log('\n--- Task Management Demo ---');
const task1 = TaskModule.createTask({
title: 'Complete JavaScript course',
description: 'Finish all 21 modules',
priority: 'high',
labels: ['learning', 'coding'],
});
console.log('Created task:', task1.title);
const task2 = TaskModule.createTask({
title: 'Build portfolio project',
priority: 'medium',
status: 'in-progress',
});
console.log('Created task:', task2.title);
console.log('All tasks:', TaskModule.getAllTasks().length);
console.log('High priority:', TaskModule.getTasks({ priority: 'high' }).length);
// Demo Dashboard Analytics
console.log('\n--- Dashboard Analytics Demo ---');
const analytics = new DashboardAnalytics();
// Demo Chat Manager
console.log('\n--- Chat System Demo ---');
const chatManager = new ChatManager();
const room = chatManager.createRoom('general', { name: 'General Chat' });
room.join({ id: 'user1', name: 'Alice' });
room.join({ id: 'user2', name: 'Bob' });
room.sendMessage('user1', 'Hello everyone!');
room.sendMessage('user2', 'Hi Alice!');
console.log('Room participants:', room.participants.size);
console.log('Messages:', room.getMessages().length);
// Demo Code Sandbox
console.log('\n--- Code Sandbox Demo ---');
console.log('CodeSandbox ready for browser execution');
// Export for use
if (typeof module !== 'undefined' && module.exports) {
module.exports = {
EventBus,
Store,
AuthModule,
TaskModule,
VirtualList,
SimpleChart,
DashboardAnalytics,
MessageEncryption,
ChatRoom,
ChatManager,
CodeSandbox,
CodeEditorState,
};
}