Перейти к основному содержимому

Примеры использования

Практические примеры использования EMD Cloud SDK для решения типовых задач.

Авторизация

Полный цикл авторизации

import { EmdCloud, AppEnvironment } from '@emd-cloud/sdk';

const emdCloud = new EmdCloud({
environment: AppEnvironment.Client,
appId: 'your-app-id'
});

// Регистрация
async function registerUser(email, password, name) {
try {
const user = await emdCloud.auth.register({
email,
password,
name
});

localStorage.setItem('auth_token', user.token);
return user;
} catch (error) {
console.error('Ошибка регистрации:', error);
throw error;
}
}

// Вход
async function loginUser(email, password) {
try {
const user = await emdCloud.auth.login({
login: email,
password
});

localStorage.setItem('auth_token', user.token);
return user;
} catch (error) {
console.error('Ошибка входа:', error);
throw error;
}
}

// Проверка авторизации
async function checkAuth() {
const token = localStorage.getItem('auth_token');

if (!token) {
return null;
}

emdCloud.setAuthToken(token);

try {
const user = await emdCloud.auth.authorization();
return user;
} catch (error) {
localStorage.removeItem('auth_token');
return null;
}
}

// Выход
async function logoutUser() {
try {
await emdCloud.auth.logout();
localStorage.removeItem('auth_token');
} catch (error) {
console.error('Ошибка выхода:', error);
}
}

База данных

CRUD приложение

class ProductManager {
constructor(emdCloud, collectionId) {
this.db = emdCloud.database(collectionId);
}

// Получить все продукты
async getProducts(filters = {}) {
const query = {};

if (filters.category) {
query["$and"] = [
{ "data.category": { "$eq": filters.category } }
];
}

if (filters.minPrice) {
query["$and"] = query["$and"] || [];
query["$and"].push({
"data.price": { "$gte": filters.minPrice }
});
}

const result = await this.db.getRows({
query: Object.keys(query).length > 0 ? query : undefined,
sort: [{ column: "createdAt", sort: "desc" }],
limit: 50,
useHumanReadableNames: true
});

return result.data;
}

// Создать продукт
async createProduct(productData) {
const result = await this.db.createRow(productData, {
notice: 'Создан новый продукт'
});

return result;
}

// Обновить продукт
async updateProduct(productId, updates) {
const result = await this.db.updateRow(
productId,
updates,
{
notice: 'Обновлен продукт',
saveMode: 'SYNC'
}
);

return result;
}

// Удалить продукт
async deleteProduct(productId) {
await this.db.deleteRow(productId);
}

// Поиск продуктов
async searchProducts(searchTerm) {
const result = await this.db.getRows({
search: searchTerm,
limit: 20,
useHumanReadableNames: true
});

return result.data;
}
}

// Использование
const productManager = new ProductManager(emdCloud, 'products-collection-id');

// Получить все продукты категории "electronics"
const electronics = await productManager.getProducts({
category: 'electronics',
minPrice: 1000
});

// Создать новый продукт
const newProduct = await productManager.createProduct({
name: 'Ноутбук',
price: 50000,
category: 'electronics',
inStock: true
});

// Обновить продукт
await productManager.updateProduct(newProduct._id, {
price: 45000,
discount: 10
});

// Поиск
const results = await productManager.searchProducts('ноутбук');

Чаты

Real-time чат приложение

class ChatApplication {
constructor(emdCloud) {
this.emdCloud = emdCloud;
this.chatWs = null;
this.currentChannel = null;
this.messageHandlers = [];
}

// Инициализация
async init() {
this.chatWs = this.emdCloud.chatWebSocket({
autoReconnect: true,
callbacks: {
onMessageReceived: (message) => {
this.handleNewMessage(message);
},
onConnectionStateChange: (state) => {
console.log('Connection state:', state);
}
}
});

await this.chatWs.connect();
}

// Получить список каналов
async getChannels() {
const result = await this.emdCloud.chat.listChannels({
type: ChatChannelType.Public,
limit: 50
});

return result.data;
}

// Открыть канал
async openChannel(channelId) {
// Отписаться от предыдущего канала
if (this.currentChannel) {
this.chatWs.unsubscribeFromChannel(this.currentChannel);
}

// Подписаться на новый канал
await this.chatWs.subscribeToChannel(channelId);
this.currentChannel = channelId;

// Загрузить историю сообщений
const messages = await this.emdCloud.chat.listMessages(channelId, {
limit: 50,
page: 0
});

return messages.data;
}

// Отправить сообщение
async sendMessage(text, attachments = []) {
await this.emdCloud.chat.sendMessage(this.currentChannel, {
message: text,
attaches: attachments
});
}

// Обработка новых сообщений
handleNewMessage(message) {
if (message.channel === this.currentChannel) {
this.messageHandlers.forEach(handler => handler(message));
}
}

// Подписка на новые сообщения
onMessage(handler) {
this.messageHandlers.push(handler);
}

// Отключение
disconnect() {
if (this.chatWs) {
this.chatWs.disconnect();
}
}
}

// Использование
const chat = new ChatApplication(emdCloud);
await chat.init();

// Получить каналы
const channels = await chat.getChannels();

// Открыть канал
const messages = await chat.openChannel(channels[0].id);

// Подписаться на новые сообщения
chat.onMessage((message) => {
console.log('Новое сообщение:', message.message);
// Обновить UI
});

// Отправить сообщение
await chat.sendMessage('Привет всем!');

Загрузка файлов

Загрузка с прогресс-баром

class FileUploadManager {
constructor(emdCloud) {
this.emdCloud = emdCloud;
this.uploads = new Map();
}

async uploadFile(file, onProgress) {
const uploadId = this.generateId();

this.uploads.set(uploadId, {
file,
progress: 0,
status: 'uploading'
});

try {
const result = await this.emdCloud.uploader.upload(file, {
onProgress: (uploaded, total) => {
const progress = Math.round((uploaded / total) * 100);
this.updateProgress(uploadId, progress);
onProgress?.(progress);
},
onSuccess: () => {
this.updateStatus(uploadId, 'completed');
},
onError: (error) => {
this.updateStatus(uploadId, 'error');
console.error('Upload error:', error);
}
});

return result;
} catch (error) {
this.updateStatus(uploadId, 'error');
throw error;
}
}

async uploadMultiple(files, onProgress) {
const uploads = Array.from(files).map((file, index) => {
return this.uploadFile(file, (progress) => {
onProgress?.(index, progress);
});
});

return Promise.all(uploads);
}

updateProgress(id, progress) {
const upload = this.uploads.get(id);
if (upload) {
upload.progress = progress;
}
}

updateStatus(id, status) {
const upload = this.uploads.get(id);
if (upload) {
upload.status = status;
}
}

generateId() {
return `upload-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
}
}

// Использование
const uploader = new FileUploadManager(emdCloud);

// Загрузка одного файла
const file = document.querySelector('input[type="file"]').files[0];
const result = await uploader.uploadFile(file, (progress) => {
console.log(`Прогресс: ${progress}%`);
document.getElementById('progress').value = progress;
});

console.log('Файл загружен:', result.url);

// Загрузка нескольких файлов
const files = document.querySelector('input[type="file"][multiple]').files;
const results = await uploader.uploadMultiple(files, (index, progress) => {
console.log(`Файл ${index + 1}: ${progress}%`);
});

React приложение

Полное приложение с авторизацией и данными

import { ApplicationProvider, useAuth, useDatabase } from '@emd-cloud/react-components';
import { useState, useEffect } from 'react';

// Главный компонент приложения
function App() {
return (
<ApplicationProvider app="your-app-id">
<Main />
</ApplicationProvider>
);
}

// Основной компонент
function Main() {
const { user, loading } = useAuth();

if (loading) {
return <div>Загрузка...</div>;
}

return user ? <Dashboard /> : <AuthPage />;
}

// Страница авторизации
function AuthPage() {
const [isLogin, setIsLogin] = useState(true);

return (
<div className="auth-page">
<h1>EMD Cloud App</h1>
{isLogin ? <LoginForm /> : <RegisterForm />}
<button onClick={() => setIsLogin(!isLogin)}>
{isLogin ? 'Нет аккаунта? Зарегистрироваться' : 'Есть аккаунт? Войти'}
</button>
</div>
);
}

// Форма входа
function LoginForm() {
const { login } = useAuth();
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');

const handleSubmit = async (e) => {
e.preventDefault();
await login({ login: email, password });
};

return (
<form onSubmit={handleSubmit}>
<input
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
placeholder="Email"
required
/>
<input
type="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
placeholder="Пароль"
required
/>
<button type="submit">Войти</button>
</form>
);
}

// Форма регистрации
function RegisterForm() {
const { register } = useAuth();
const [formData, setFormData] = useState({
email: '',
password: '',
name: ''
});

const handleSubmit = async (e) => {
e.preventDefault();
await register(formData);
};

return (
<form onSubmit={handleSubmit}>
<input
value={formData.name}
onChange={(e) => setFormData({ ...formData, name: e.target.value })}
placeholder="Имя"
required
/>
<input
type="email"
value={formData.email}
onChange={(e) => setFormData({ ...formData, email: e.target.value })}
placeholder="Email"
required
/>
<input
type="password"
value={formData.password}
onChange={(e) => setFormData({ ...formData, password: e.target.value })}
placeholder="Пароль"
required
/>
<button type="submit">Зарегистрироваться</button>
</form>
);
}

// Dashboard
function Dashboard() {
const { user, logout } = useAuth();

return (
<div className="dashboard">
<header>
<h1>Привет, {user.name}!</h1>
<button onClick={logout}>Выйти</button>
</header>

<ProductList />
</div>
);
}

// Список продуктов
function ProductList() {
const { getRows, createRow } = useDatabase('products');
const [products, setProducts] = useState([]);
const [loading, setLoading] = useState(true);

useEffect(() => {
loadProducts();
}, []);

async function loadProducts() {
const result = await getRows({
limit: 50,
useHumanReadableNames: true
});

setProducts(result.data);
setLoading(false);
}

async function addProduct(productData) {
const newProduct = await createRow(productData);
setProducts([...products, newProduct]);
}

if (loading) return <div>Загрузка продуктов...</div>;

return (
<div>
<h2>Продукты</h2>
<AddProductForm onAdd={addProduct} />

<div className="products">
{products.map(product => (
<div key={product._id} className="product">
<h3>{product.name}</h3>
<p>{product.price}</p>
</div>
))}
</div>
</div>
);
}

// Форма добавления продукта
function AddProductForm({ onAdd }) {
const [formData, setFormData] = useState({ name: '', price: 0 });

const handleSubmit = async (e) => {
e.preventDefault();
await onAdd(formData);
setFormData({ name: '', price: 0 });
};

return (
<form onSubmit={handleSubmit}>
<input
value={formData.name}
onChange={(e) => setFormData({ ...formData, name: e.target.value })}
placeholder="Название"
required
/>
<input
type="number"
value={formData.price}
onChange={(e) => setFormData({ ...formData, price: Number(e.target.value) })}
placeholder="Цена"
required
/>
<button type="submit">Добавить</button>
</form>
);
}

export default App;

Best Practices

Обработка ошибок

async function safeApiCall(apiFunction, errorMessage) {
try {
return await apiFunction();
} catch (error) {
console.error(errorMessage, error);

// Показать уведомление пользователю
showNotification({
type: 'error',
message: errorMessage
});

// Логирование в сервис мониторинга
logError(error);

throw error;
}
}

Кеширование данных

class DataCache {
constructor(ttl = 5 * 60 * 1000) { // 5 минут
this.cache = new Map();
this.ttl = ttl;
}

set(key, value) {
this.cache.set(key, {
value,
timestamp: Date.now()
});
}

get(key) {
const item = this.cache.get(key);

if (!item) return null;

if (Date.now() - item.timestamp > this.ttl) {
this.cache.delete(key);
return null;
}

return item.value;
}

clear() {
this.cache.clear();
}
}

const cache = new DataCache();

async function getProductsWithCache() {
const cached = cache.get('products');

if (cached) {
return cached;
}

const products = await productsDb.getRows({ limit: 50 });
cache.set('products', products);

return products;
}

Следующие шаги

Полезные ссылки