UNPKG

umbot

Version:

Мультиплатформенный фреймворк для создания голосовых навыков и чат-ботов с единой бизнес-логикой. Встроенная поддержка ВКонтакте, Telegram, Viber, MAX, Яндекс Алисы, Маруси и Сбера SmartApp. Архитектура на адаптерах позволяет подключать любые другие платф

337 lines (336 loc) 10.6 kB
/** * Модуль базовой модели для работы с данными * * Предоставляет абстрактный класс для: * - Взаимодействия с базой данных * - Валидации данных * - Управления состоянием модели * - Выполнения CRUD операций */ import { IDataValue, IModelRes, IModelRules, TQueryCb } from '../interface'; import { IQueryData, IQuery, TKey } from './QueryData'; import { AppContext, IDbResult } from '../../core'; export interface IModelState { [key: string]: unknown; } /** * Интерфейс для описания результата выполнения операции с поиском 1 значения */ export interface ISelectOneModelRes extends Omit<IModelRes, 'data'> { /** * Результат выполнения операции. * Присутствует только при status = true. * Может содержать любые данные в зависимости от операции */ data?: IDataValue; } /** * Абстрактный класс для создания моделей данных * Предоставляет базовую функциональность для работы с данными в базе данных * * @example * ```ts * class UserModel extends Model<UserState> { * // Определение правил валидации * rules(): IModelRules[] { * return [ * { name: ['username'], type: 'string', max: 50 }, * { name: ['age'], type: 'integer' } * ]; * } * * // Определение меток атрибутов * attributeLabels(): UserState { * return { * id: 'ID', * username: 'Имя пользователя', * age: 'Возраст' * }; * } * * // Определение имени таблицы * tableName(): string { * return 'users'; * } * } * * // Использование модели * const user = new UserModel(); * user.state.username = 'John'; * user.state.age = 25; * await user.save(); * ``` * * @template TState - Тип состояния модели * @class Model */ export declare abstract class Model<TState extends IModelState> { #private; /** * Объект для хранения параметров запроса. * Содержит условия поиска и данные для обновления */ queryData: IQuery; /** * Начальный индекс для итерации по данным. * Используется при инициализации модели из массива */ startIndex: number; /** * Состояние модели. * Содержит текущие значения всех атрибутов * * @example * ```ts * // Установка значений * this.state.username = 'John'; * this.state.age = 25; * * // Получение значений * console.log(this.state.username); * ``` */ state: Partial<TState>; /** * Контекст приложения. */ protected _appContext: AppContext; /** * Определяет правила валидации для полей модели * Должен быть реализован в дочерних классах * * @example * ```ts * rules(): IModelRules[] { * return [ * { name: ['username'], type: 'string', max: 50 }, * { name: ['age'], type: 'integer' } * ]; * } * ``` * * @returns Массив правил валидации * @virtual */ abstract rules(): IModelRules[]; /** * Определяет метки атрибутов модели * Должен быть реализован в дочерних классах * * @example * ```ts * attributeLabels(): UserState { * return { * id: 'ID', * username: 'Имя пользователя', * age: 'Возраст' * }; * } * ``` * * @returns Объект с метками атрибутов * @virtual */ abstract attributeLabels(): TState; /** * Определяет имя таблицы в базе данных * Должен быть реализован в дочерних классах * * @example * ```ts * tableName(): string { * return 'users'; * } * ``` * * @returns Имя таблицы * @virtual */ abstract tableName(): string; /** * Создает новый экземпляр модели. * Инициализирует контроллер базы данных и состояние модели * * @example * ```ts * const user = new UserModel(); * ``` */ protected constructor(appContext: AppContext); /** * Проверяет состояние подключения к базе данных * * @example * ```ts * const isConnected = await model.isConnected(); * if (isConnected) { * // Выполнение операций с базой данных * } * ``` * * @returns Promise<boolean> - true если подключение активно */ isConnected(): Promise<boolean> | boolean; /** * Экранирует специальные символы в строке * * @example * ```ts * const safe = model.escapeString("O'Connor"); * ``` * * @param text - Текст для экранирования * @returns Экранированная строка */ escapeString(text: string | number): string; /** * Выполняет валидацию данных модели * Может быть переопределен в дочерних классах * * @example * ```ts * validate(): void { * if (!this.state.username) { * throw new Error('Username is required'); * } * } * ``` */ validate(): void; /** * Определяет имя первичного ключа таблицы. * Ищет поле с меткой 'id' или 'ID' * * @returns Имя первичного ключа или null */ protected getId(): TKey; /** * Инициализирует модель данными * * @example * ```ts * model.init({ * id: 1, * username: 'John', * age: 25 * }); * ``` * * @param data - Данные для инициализации */ init(data: IDbResult[] | IDbResult | null): void; /** * Выполняет поиск записи по первичному ключу * * @example * ```ts * const result = await model.selectOne(); * if (result.status) { * model.init(result.data); * } * ``` * * @returns Promise с результатом запроса */ selectOne(): Promise<ISelectOneModelRes>; /** * Сохраняет данные модели в базу данных * Если запись существует - обновляет, иначе создает новую * * @example * ```ts * model.state.name = 'John'; * await model.save(); // Обновление существующей записи * await model.save(true); // Создание новой записи * ``` * * @param isNew - Флаг создания новой записи * @returns Promise с результатом операции */ save(isNew?: boolean): Promise<boolean>; /** * Обновляет существующую запись в базе данных * * @example * ```ts * model.state.name = 'John'; * await model.update(); * ``` * * @returns Promise с результатом операции */ update(): Promise<boolean>; /** * Добавляет новую запись в базу данных * * @example * ```ts * model.state.name = 'John'; * await model.add(); * ``` * * @returns Promise с результатом операции */ add(): Promise<boolean>; /** * Удаляет запись из базы данных * * @example * ```ts * await model.remove(); * ``` * * @returns Promise<boolean> - true если удаление успешно */ remove(): Promise<boolean>; /** * Выполняет произвольный запрос к базе данных * * @param where - Условия запроса * @param isOne - Флаг выборки одной записи * @returns Promise с результатом запроса */ where(where?: string | IQueryData, isOne?: boolean): Promise<IModelRes>; /** * Выполняет запрос с выборкой одной записи * * @example * ```ts * const found = await model.whereOne({ id: 1 }); * if (found) { * console.log('Record found'); * } * ``` * * @param where - Условия запроса * @returns Promise<boolean> - true если запись найдена */ whereOne(where?: string | IQueryData): Promise<boolean>; /** * Выполняет произвольный запрос к базе данных * * @example * ```ts * const result = await model.query(async (client, db) => { * const collection = db.collection('users'); * return await collection.aggregate([ * { $match: { age: { $gt: 18 } } }, * { $group: { _id: '$city', count: { $sum: 1 } } } * ]).toArray(); * }); * ``` * * @param callback - Функция обратного вызова для выполнения запроса * @returns Результат выполнения запроса */ query(callback: TQueryCb): unknown; /** * Закрывает соединение с базой данных * * @example * ```ts * model.destroy(); * ``` */ destroy(): void | Promise<void>; }