OneCore - это web-фреймворк на движке onescript, созданный для разработки web-приложений любой сложности, используя компонентный подход.
Проект находится в активной разработке. Фреймворк перешёл на onescript 2.0!!!
- OneCore - web framework
Реализовано:
- Компонентный подход
- Маршрутизация с поддержкой параметров
- Шаблонизатор (jinja-подобный)
- Поддержка статических файлов
- Middleware (перехватчики)
- ORM для работы с БД
- Сервисы для разработки бизнес-логики
- Встроенный веб-сервер
- Сеансы и параметры сеансов
В планах:
- Сервер регламентных заданий
- WebSocket сервер
- CLI для удобства работы (создание проекта, компонентов и т.д.)
- Запуск приложения как службы windows (mssm)
- Продвинутое логирование в файл или базу данных
Описанные возможности позволяют разрабатывать приложения со сложной поддерживаемой структурой, внешний программный интерфейс (API), сайты и web-приложения по технологии SSR, бэкенд для web-приложений (react, vue и подобные), можно внедрить HTMX и делать SPA, а в будущем и просто приложения для фоновых операций без использования web-сервера.
Перед установкой у вас уже должна быть установлена платформа onescript версией не менее 2.0RC5 ветка develop. Рекомендовано использовать OVM для установки платформы onescript.
- Скачать ospx файл с релизов (onecore-х.х.х.ospx)
- Из каталога "simple" корневого каталога репозитория скопируйте содержимое нужного примера в каталог вашего проекта
- В каталоге вашего проекта разместите скачанный файл библиотеки (onecore-х.х.х.ospx)
- Выполнить консольную команду:
opm i -l -f onecore-x.x.x.ospx
где "x.x.x" версия фреймворка (библиотеки) - Дождаться завершения установки зависимостей, далее для запуска используется команда
oscript main.os
или отладчик VSCode
└── Компонент # Каталог компонента, имя каталога соответствует имени компонента
├── Модели # Модели ORM
├── Представления # Представления данных, они же контроллеры
├── Ресурсы # Статические данные (скрипты, картинки и т. д)
├── Сервисы # Произвольные сервисы, реализующие бизнес-логику
├── Шаблоны # HTML шаблоны для шаблонизатора
└── МодульКомпонента.os # Скрипт модуля компонента
├── main.os # Стартовый скрипт
├── oscript.cfg # Конфигурационный файл onescript
└── settings.json # Системный файл с информацией о текущей версии (создаётся автоматически при первом запуске)
В корне каталога проекта создаются каталоги компонентов, внутри которых реализуется логика отдельно взятого компонента. При разработке компонентов, желательно, соблюдать изолированность. В служебных каталогах компонента (Модели, Представления, Ресурсы, Сервисы, Шаблоны) разрешено использовать вложенные каталоги для удобной структуризации логики.
Создание любого приложения на onecore начинается с создания компонента, так как компонент приложения является обособленной функциональной областью, при желании, он может быть один, но не советую так поступать.
Для создания компонента необходимо создать каталог в корне проекта и указать имя каталога в соответствии с именем планируемого компонента, например, "Ядро", и создать служебные каталоги компонента (см. Структура проекта), также скрипт МодульКомпонента.os с следующим содержимым:
Процедура ПриИнициализацииКомпонента() Экспорт
// Код, выполняемый при инициализации приложения до его запуска
КонецПроцедуры
Процедура ПриФормированииМаршрутов(Маршруты) Экспорт
// Код, заполняющий коллекцию маршрутов
КонецПроцедуры
Процедура ПриУстановкеПараметровСеанса(ПараметрыСеанса) Экспорт
// Код, выполняемый при создании нового сеанса
КонецПроцедуры
Для того, чтобы приложение использовало созданный компонент, его необходимо проинициализировать перед запуском приложения в файле main.os:
#Использовать onecore
// Подключение компонентов
Приложение.ПодключитьКомпонент("Ядро", "core");
// Инициализация и запуск
Приложение.Инициализировать();
Приложение.Запустить();
При выполнении процедуры "Инициализировать" будет вызвана процедура "ПриИнициализацииКомпонента" модуля компонента, в данной процедуре можно выполнять любые действия, например, объявить настройки приложения для файла settings.json.
Для того, чтобы ваше приложение принимало запросы, необходимо создать контроллер, контроллеры в onecore называются представлениями, так как они обязаны формировать ответ, в котором данные могут быть представлены в разном формате, например, как html, или внешний api для интеграции и т.д.
Для того, чтобы создать контроллер, необходимо в каталоге "Представления" вашего компонента создать скрипт и назвать его так, как далее вы хотите его использовать, например, "Приветствие.os" и обязательно заполнить его по шаблону:
// Обязательное свойство, без него представление не зарегистрируется
Перем Контекст;
// Служит для выполнения общих действий для всех методов запросов
Процедура Инициализация() Экспорт
КонецПроцедуры
// Обрабатывает запрос с методом GET
Процедура GET() Экспорт
// Код обработчика запроса
КонецПроцедуры
Процедуры обработчиков запросов должны обязательно называться в соответствии с методами HTTP, которые необходимо обработать (GET, POST, PUT, DELETE, HEAD, CONNECT, OPTIONS, PATCH, TRACE), маршрутизатор самостоятельно запустит выполнение нужной процедуры в зависимости от метода поступившего запроса.
Для тестирования сразу напишем код обработчика:
Процедура GET() Экспорт
Контекст.Ответ.ТипКонтента = "html";
Контекст.Ответ.Записать("<h1>Привет мир!!! Как банально...</h1>");
КонецПроцедуры
На данный момент, мы имеем объект контроллера, но непонятно, как приложение будет понимать, что запрос адресован именно ему, для этого существует маршрутизация, и указать соответствие адреса с обработчиком мы должны в том же модуле компонента в процедуре "ПриФормированииМаршрутов":
Процедура ПриФормированииМаршрутов(Маршруты) Экспорт
Маршруты.Добавить("/", "Приветствие");
КонецПроцедуры
Помимо обычного указания адреса и представления, в маршруте доступно указание индивидуального имени для каждого из маршрутов, имя маршрута должно быть индивидуальное в рамках компонента, при указании имени к нему добавляется имя компонента, это нужно учесть при поиске маршрута по имени.
Пример указания имени:
Процедура ПриФормированииМаршрутов(Маршруты) Экспорт
Маршруты.Добавить("/", "Приветствие").Имя("Главная");
КонецПроцедуры
Процедура ПриФормированииМаршрутов(Маршруты) Экспорт
Маршрут = Маршруты.Добавить("/", "Приветствие");
Маршрут.Имя("Главная");
КонецПроцедуры
Именованные маршруты созданы для быстрого и удобного формирования адресов, так же они позволяют менять адрес маршрута, и во всех местах получения адреса по имени маршрута есть возможность подставить нужный адрес.
Пример использования подстановки адреса именованного маршрута в шаблонах:
<a href='{{ Маршрут("Ядро.Главная") }}'><button>На главную</button></a>
После формирования шаблона мы получим резутат:
<a href="/"><button>На главную</button></a>
Функция Маршрут
, помимо имени маршрута, ещё и принимает параметры, которые необходимо подставить, если именнованный маршрут их содержит, доступно до 6-ти параметров.
Пример использования:
{% Для каждого Элемент из Контекст Цикл %}
<a href='{{ Маршрут("Ядро.КарточкаФизЛица", Элемент.Идентификатор) }}'><li>Элемент.Имя</li></a>
{% КонецЦикла; %}
Результат:
<a href="/persons/1"><li>Андрей</li></a>
<a href="/persons/1"><li>Леонид</li></a>
<a href="/persons/1"><li>Иван</li></a>
В общем объекте маршрутизатора доступны методы:
НайтиМаршрутПоИмени(Имя)
- Возвращает найденный объект маршрута по имени или неопределенноАдресМаршрутаПоИмени(Имя)
- Ищет маршрут и подставляет в него переданные параметры после параметра "Имя", используется для маршрутов, в адресах которых содержатся параметры
Процедура МетодЛюбогоСервисаИлиПредставления(Идентификатор) Экспорт
Маршрутизатор = Приложение.Маршрутизатор();
МаршрутГлавной = Маршрутизатор.НайтиМаршрутПоИмени("Главная");
АдресГлавной = Маршрутизатор.АдресМаршрутаПоИмени("Главная");
// ИЛИ
АдресГлавной = МаршрутГлавной.Адрес();
МаршрутФизЛица = Маршрутизатор.НайтиМаршрутПоИмени("КарточкаФизЛица");
АдресФизЛица = Маршрутизатор.АдресМаршрутаПоИмени("КарточкаФизЛица", Идентификатор);
КонецПроцедуры
Для более гибкого управления маршрутизацией добавлен механизм свойств маршрутов, свойства представляют из себя структуру (ключ и значение) и находятся в одноименном свойстве объекта Маршрут
.
Свойства можно указать глобально для всех маршрутов приложения в файле main.os
:
// Установка свойств для маршрутов по умолчанию
СвойстваМаршрутовПоУмолчанию = Новый Структура();
СвойстваМаршрутовПоУмолчанию.Вставить("СвойствоВообщеДляВсех", 0);
Приложение.УстановитьСвойстваМаршрутовПоУмолчанию(СвойстваМаршрутовПоУмолчанию);
Указанные свойства будут автоматически подставлены во все маршруты при их добавлении в модулях компонентов.
Так же свойства можно указать глобально, но в рамках одного компонента в модуле компонента в процедуре ПриФормированииМаршрутов
:
Процедура ПриФормированииМаршрутов(Маршруты) Экспорт
СвойстваПоУмолчанию = Новый Структура();
СвойстваПоУмолчанию.Вставить("Общедоступный", Истина);
Маршруты.СвойстваМаршрутовПоУмолчанию(СвойстваПоУмолчанию);
Маршруты.Добавить("/", "Главная").Имя("Главная");
Маршруты.Добавить("/about", "ОПроекте").Имя("ОПроекте");
Маршруты.Добавить("/whois", "ОбАвторе").Имя("ОбАвторе");
Маршруты.Добавить("/galerey", "Галерея").Имя("Галерея");
Маршруты.Добавить("/persons", "ФизическиеЛица.Список").Имя("СписокФизЛиц");
Маршруты.Добавить("/persons/create", "ФизическиеЛица.Элемент").Имя("СозданиеФизЛица");
Маршруты.Добавить("/persons/<Число:ИдентификаторПользователя>", "ФизическиеЛица.Элемент").Имя("СтраницаФизЛица");
КонецПроцедуры
Указанные свойства таким образом будут подставлены во все добавляемые маршруты компонента.
Так же свойство можно добавить индивидуально к определенному маршруту:
Процедура ПриФормированииМаршрутов(Маршруты) Экспорт
Маршруты.Добавить("/", "Главная").Имя("Главная").ДобавитьСвойство("Общедоступный", Истина);
КонецПроцедуры
Сценарий использоваия разнообразен, наример, в перехватчиках для определения доступности конкретному пользователю открываемой старницы или метода api.
Для обособленности компонентов и уменьшения сценариев, при которых возможны совпадения адресов маршрутов, существует функционал перфисации, но префикс устанавливается не любой, а берется из латинского имени компонента, которое указывается при инициализации.
Пример использования префиксации:
Процедура ПриФормированииМаршрутов(Маршруты) Экспорт
Маршруты.ИспользоватьПрефиксКомпонента();
Маршруты.Добавить("/", "Главная").Имя("Главная").ДобавитьСвойство("Общедоступный", Истина);
КонецПроцедуры
Так как латинское имя у компонента указано "core", то маршрут будет добавлен не с адресом "/", а с адресом "/core".
Перенаправление реализовано очень просто, достаточно указать в контексте адрес перенаправления и после обработки веб-сервер самостоятельно установит нужные заголовки и коды ответов, например, в перехватчике:
Процедура ПередВыполнениемПредставления(Контекст, ПродолжитьОбработку) Экспорт
Адрес = Контекст.Маршрут.Адрес();
Если СтрНайти(Адрес, "whois") Тогда
Контекст.АдресПеренаправления = "/";
ПродолжитьОбработку = Ложь;
Возврат;
КонецЕсли;
КонецПроцедуры
Или в представлении:
Процедура POST() Экспорт
Контекст.АдресПеренаправления = "/";
КонецПроцедуры
Перенаправление происходит ещё до автоматического формирования шаблонов и до выполнения обработчика пердставления в случае указания в перехватчике с обязательным прерыванием.
Согласно тому, что мы указали, сервер, при обращении клиента к корневому адресу, будет переадресовывать выполнение в наш контроллер. Процедура "Добавить" принимает в себя 2 параметра, первый - это шаблон адреса, второй - строковый путь к объекту обработчика запроса через точку, при этом, если бы у нас объект обработчика находился не в корневом каталоге "Представления", а, например, в каталоге "Тестирование", тогда указание маршрута выглядело бы так Маршруты.Добавить("/", "Тестирование.Приветствие");
.
Шаблоны адресов могут содержать параметры, например: /users/<Число:Идентификатор>
, что позволяет нам создавать динамические маршруты, сами же параметры части маршрута передаются в качестве параметров в обработчик запроса:
Процедура GET(Идентификатор) Экспорт
Контекст.Ответ.ТипКонтента = "html";
Контекст.Ответ.Записать("Идентификатор пользователя" + Строка(Идентификатор));
КонецПроцедуры
Так же доступен сокращенный способ указания типа контента и кода:
&ПараметрыОтвета(ТипСодержимого = "html", КодОтвета = 200)
Процедура GET(Идентификатор) Экспорт
Контекст.Ответ.Записать("Идентификатор пользователя" + Строка(Идентификатор));
КонецПроцедуры
Теперь приложение понимает, куда адресовать запросы.
Для запуска приложения достаточно выполнить команду oscript main.os
, и перейти по адресу, указанному в консоли. Второй вариант - это настроить отладку, для этого нужно создать файл отладки по инструкции платформы onescript и указать следующее содержимое:
{
// Используйте IntelliSense, чтобы узнать о возможных атрибутах.
// Наведите указатель мыши, чтобы просмотреть описания существующих атрибутов.
// Для получения дополнительной информации посетите: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Приложение",
"type": "oscript",
"request": "launch",
"program": "${workspaceRoot}\/main.os",
"args": [],
"cwd": "${workspaceRoot}",
"env": {},
"runtimeExecutable": null,
"runtimeArgs": [],
"debugPort": 2801
}
]
}
Далее запускаем отладку привычным нам способом.
Для формирования пользовательского интерфейса фреймворк использует шаблонизатор, другими словами, создаётся обычный html файл и в нем уже создаются вкрапления кода onescript, что позволяет реализовывать динамический вывод. При формировании шаблона в него передаётся контекст представления, из которого он был вызван, что позволяет использовать его в верстке, например:
<div>"Привет {{Контекст.Данные.Имя}}</div>
Так же поддерживаются любые конструкции и методы onescript:
<div>"Сейчас {{ТекущаяДата()}}</div>
Как вы могли заметить, подставление данных в html происходит с помощью конструкции {{ЗначениеИЛИФункция()}}
Конструкции языка должны быть заключены в {%... %}
, например:
<div>
{% Если Контекст.Данные.Число > 3 Тогда %}
Контекст {{Контекст.Данные.Число}} больше 3
{% Иначе %}
Контекст {{Контекст.Данные.Число}} меньше 3
{% КонецЕсли; %}
</div>
То же самое касается и циклов:
<div>
{% Для Каждого Элемент Из Контекст.Данные.Список Цикл %}
Элемент <h2>{{Элемент}}</h2>
{% КонецЦикла; %}
</div>
Реализован механизм вложенности шаблонов с помощью встроенной функции Вложить(<путь к шаблону>)
, он позволяет декомпозировать и переиспользовать одни шаблоны в других, например, вы создали следующие шаблоны:
Ядро.Шапка
:
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{Контекст.Данные.Заголовок}}</title>
</head>
<body>
Ядро.Подвал
:
</body>
</html>
Теперь их можно использовать, например:
Ядро.Главная
:
{{ Вложить("Ядро.Шапка") }}
<h1>{{Контекст.Данные.ВыводимыйТекст}}</h1>
{{ Вложить("Ядро.Подвал") }}
Есть возможность использовать наследование шаблонов, расширив один шаблон другим, это означает, что формируемый шаблон будет помещён в именованный блок расширяемого шаблона. Например в базовом шаблоне указывается блок:
Ядро.БазовыйШаблон
:
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Страница</title>
</head>
<body>
<h1>Заголовок</h1>
{{ Блок("Контент") }}
<h1>Подвал</h1>
</body>
</html>
Теперь расширим шаблон Ядро.Главная
:
{{ Расширить("Ядро.БазовыйШаблон") }}
{{ Поместить("Контент") }}
<span>{{ Контекст.Данные.ЗаголовокВкладки }}</span>
{{ КонецПомещения() }}
После формирования получим следующий результат:
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Страница</title>
</head>
<body>
<h1>Заголовок</h1>
<span>Текст из другого шаблона</span>
<h1>Подвал</h1>
</body>
</html>
Функция Блок(ИмяБлока)
указывает место в html, куда будет выведено содержимое другого шаблона, который расширяется текущим. Блоков в шаблоне может быть сколько угодно, они должны быть разных имён, чтобы можно было явно указывать, куда помещать содержимое расширяемых шаблонов.
В самих же расширяемых шаблонах нужно указать, какой шаблон будет расширяться (по другому, от какого будем наследоваться), сделать это можно с помощью функции Расширить(ПутьКШаблону)
, вызывать эту функцию стоит только один раз в шаблоне, в противном случае, повторный вызов просто перезапишет предыдущий (или же, можно придумать сценарий с этим учетом).
Далее необходимо указать область, которая будет помещаться в расширяемый шаблон, делается это функциями Поместить(ИмяБлока)
и КонецПомещения()
, вызывая первую, вы передаете в неё имя блока расширяемого шаблона, а вторую - вы закрываете область, которая будет помещаться в указанный блок, то есть всё то, что находится между этими функциями.
Для формирования шаблона используется встроенный класс "Шаблонизатор", в него передаётся представление и путь к шаблону, далее вызывается функция "Сформировать" с передачей в неё контекста, она вернет уже сформированный шаблон и его можно будет отправлять в теле ответа, например:
&ПараметрыОтвета(ТипСодержимого = "html", КодОтвета = 200)
Процедура GET(Идентификатор) Экспорт
Шаблонизатор = Новый Шаблонизатор(ЭтотОбъект, "Ядро.Главная");
ТекстШаблона = Шаблонизатор.Сформировать(Контекст);
Контекст.Ответ.Записать(ТекстШаблона);
КонецПроцедуры
Так же есть более удобная и сокращенная запись:
&ПараметрыОтвета(ТипСодержимого = "html", КодОтвета = 200)
&ФормироватьШаблон("Ядро.Главная")
Процедура GET(Идентификатор) Экспорт
// Код обработки
КонецПроцедуры
При наличии у процедуры обработчика запроса аннотации &ФормироватьШаблон(<путь к шаблону>)
автоматически формирует нужный шаблон, передавая в него текущее представление и контекст, и отправляет ответ, если этого не было сделано раннее, формирование шаблона происходит после выполнения кода обработчика запроса.
Сервисы - это слой, в котором реализуется бизнес-логика компонента, каждый созданный сервис создаётся как обычный скрипт, определяется фреймворком как класс и доступен для использования во всём приложении. Создавать сервисы можно во вложенных каталогах в целях структуризации.
Например, создадим несколько сервисов:
└── Компонент
└── Сервисы
└── ОбщегоНазначения
├── ДатаВремя.os
└── СтроковыеФункции.os
Для того, чтобы использовать программный интерфейс, в объекте, где его нужно использовать, необходимо создать свойство и присвоить ему специальную аннотацию, пример:
&Сервис("ОбщегоНазначения.СтроковыеФункции")
Перем СтроковыеФункции;
Следует учесть, что если сервис используется в объекте компонента, который находится в том же компоненте, что и сам сервис, то указание параметра аннотации "Сервис" должен писаться в сокращенном виде:
&Сервис("ОбщегоНазначения.СтроковыеФункции")
Перем СтроковыеФункции;
Если же сервис используется в другом компоненте, тогда необходимо прописать полный путь:
&Сервис("Ядро.Сервисы.ОбщегоНазначения.СтроковыеФункции")
Перем СтроковыеФункции;
Далее сервисы можно использовать в других сервисах и в представлениях любых компонентов приложения.
Встроенный web-сервер позволяет отдавать статические файлы, для этого необходимо разместить файл в каталоге "Ресурсы" вашего компонента. При этом струкура каталогов в каталоге "Ресурсы" учитывается при генерации маршрутов.
Адрес к каждому статическому файлу будет формироваться по следующему шаблону:
<адрес сервера или ip>/<латинское имя компонента>/<путь к статическому файлу>
Например, если в компоненте Ядро (core), в ресурсах размещен файл index.html:
http://127.0.0.1:5555/core/index.html
Если необходимо, чтобы статический файл был доступен в корне приложения, то есть возможность при инициализации компонента установить третий параметр в "Истина":
#Использовать onecore
// Подключение компонентов
Приложение.ПодключитьКомпонент("Ядро", "core", Истина);
// Инициализация и запуск
Приложение.Инициализировать();
Приложение.Запустить();
Далее все ресурсы компонента будут доступны по нескольким адресам:
http://127.0.0.1:5555/index.html
и http://127.0.0.1:5555/core/index.html
Фреймворк позволяет перехватывать выполнение запроса перед обработкой представлением и перед отправкой ответа, это позволяет гибко управлять данными для отправки. Перехватчики отрабатывают в той очередности, в которой они указаны разработчиком, при этом сначала запускаются процедуры "ПередВыполнениемПредставления" перед отправкой в представление, и уже после обработки представлением в том же порядке выполняются процедуры "ПослеВыполненияПредставления". Для написания обработчиков перехватчиков используются сервисы, а в стартовом файле прописываются пути к сервисам перехватчиков. Для того, чтобы обработать событие, необходимо создать экспортные процедуры "ПередВыполнениемПредставления" или/и ПослеВыполненияПредставления, указав в них 2 параметра: Контекст и ПродолжитьОбработку. Для инициализации сервисов перехватчиков нужно воспользоваться объектом "МенеджерОбъектов", получить его можно с помощью модуля глобального контекста "Приложение", "Приложение.МенеджерКомпонентов()".
Пример стартового скрипта:
#Использовать onecore
// Подключение компонентов
Приложение.ПодключитьКомпонент("Ядро", "core", Истина);
// Подключение перехватчиков
Приложение.ПодключитьПерехватчик("Ядро.Перехватчики.ПроверкаТокена");
// Инициализация и запуск
Приложение.Инициализировать();
Приложение.Запустить();
В метод ИнициализироватьПерехватчики менеджера объектов можно передавать сервисы через запятую или массивом строк, как вам будет удобнее.
Пример сервиса перехватчика по пути: Ядро/Сервисы/Перехватчики/ПроверкаТокена.os
Процедура ПередВыполнениемПредставления(Контекст, ПродолжитьОбработку) Экспорт
Лог.Отладка("Проверяю токен");
Токен = Контекст.Запрос.Заголовки.Получить("Token");
Если НЕ ЗначениеЗаполнено(Токен) Тогда
Ответ.Отправить(401);
Лог.Отладка("Отсутствует токен в заголовках");
КонецЕсли;
Лог.Отладка("Токен типа проверен");
КонецПроцедуры
Процедура ПослеВыполненияПредставления(Контекст, ПродолжитьОбработку) Экспорт
Лог.Отладка("Что-то делаем после того, как обработалось представление");
КонецПроцедуры
Перед выполнением каждой процедуры сервиса перехватчика проверяется признак отправленности ответа, в случае, если ответ отправлен, процедура не будет выполнена. Если необходимо прервать дальнейшее выполнение обработки запроса необходмо параметр "ПродолжитьОбработку" установить в Ложь.
Для работы с базами данных во фреймворк встроена ORM entity, так же вас никто не ограничивает использовать и другие библиотеки по работе с базами данных, но именно entity интегрирована в onecore. Интеграция заключается в том, что фреймворк автоматически сканирует все скрипты в каталогах компонентов "Модели" и добавляет их в entity, так же проводит инициализацию моделей при инициализации приложения.
Таблицы в базе данных автоматически синхронизируются с моделями при инициализации приложения
Чтобы использовать entity в onecore нужно, в первую очередь, включить поддержку ORM и указать, какую базу использовать в файле main.os
:
#Использовать "onecore"
// Подключение функционала
Приложение.ИспользоватьORM();
Приложение.ПодключитьБазуДанныхORM("Основная");
Приложение.ПодключитьБазуДанныхORM("Файловая", "КоннекторSQLite", "FullUri=file:main.db");
// Подключение компонентов
Приложение.ПодключитьКомпонент("Ядро", "core", Истина);
// Подключение перехватчиков
Приложение.ПодключитьПерехватчик("Ядро.Перехватчики.ПроверкаТокена");
// Инициализация и запуск
Приложение.Инициализировать();
Приложение.Запустить();
Процедура ПодключитьБазуДанныхORM
принимает в себя 3 параметра:
- Ключ - Строка - Ключ, по которому будет определяться, какой конкретно менеджер сущностей использовать
- ТипКоннектора - Строка - Тип коннектора строкой, см. документацию entity (не обязательно)
- СтрокаСоединения - Строка - Строка соединения по формату выбранного коннектора (не обязательно)
Из выше описанного следует, что есть возможность использовать несколько менеджеров сущностей и, следовательно, несколько баз данных, если второй и третий параметры не указаны, то их необходимо будет указать в файле settings.json
:
{
"Приложение": {
"ПортПрослушивания": 8572,
"РежимРазработки": true,
"УровеньВыводаЛогов": "Отладка",
"БазыДанныхORM": {
"Основная": {
"ТипКоннектора": "КоннекторPostgreSQL",
"СтрокаСоединения": "Host=***;Username=***;Password=***;Database=***;port=5432;"
}
}
}
}
Данный инструментарий позволяет задать настройки подключения к базе данных программным путем, используя механизм настроек.
После включения поддержки ORM и указания параметров для подключения к базе данных менеджеры сущностей можно использовать в любом месте программы, для этого потребуется использовать аннотацию &МенеджерСущностей(<Ключ>)
, например, в модуле представления (но лучше только в сервисах):
Перем Контекст;
&МенеджерСущностей("Основная")
Перем МенеджерСущностей;
Процедура Инициализация() Экспорт
Контекст.Данные.Вставить("ЗаголовокВкладки", "Физические лица");
КонецПроцедуры
&ПараметрыОтвета(ТипСодержимого = "html", КодОтвета = 200)
&ФормироватьШаблон("Ядро.Шаблоны.Справочники.ФизическиеЛица.Список")
Процедура GET() Экспорт
ОпцииПоиска = Новый ОпцииПоиска().СортироватьПо("Идентификатор", НаправлениеСортировки.Возр);
СписокФизЛиц = МенеджерСущностей.Получить(Тип("ЯдроФизическоеЛицо"), ОпцииПоиска);
Таблица.Колонки.Добавить("Идентификатор");
Таблица.Колонки.Добавить("Номер");
Таблица.Колонки.Добавить("Фамилия");
Таблица.Колонки.Добавить("Имя");
Таблица.Колонки.Добавить("Отчество");
Номер = 1;
Для каждого ФизЛицо Из СписокФизЛиц Цикл
НоваяСтрока = Таблица.Добавить();
НоваяСтрока.Идентификатор = ФизЛицо.Идентификатор;
НоваяСтрока.Номер = Номер;
НоваяСтрока.Фамилия = ФизЛицо.Фамилия;
НоваяСтрока.Имя = ФизЛицо.Имя;
НоваяСтрока.Отчество = ФизЛицо.ВтороеИмя;
Номер = Номер + 1;
КонецЦикла;
Контекст.Данные.Вставить("Список", Таблица);
КонецПроцедуры
Из примера следует, что в переменную МенеджерСущностей
с помощью аннотации был помещен экзепляр класса МенеджерСущностей
библиотеки entity, и далее, согласно документации этой библиотеки, вы можете осуществлять все доступные действия с объектами ORM.
Для корректной работы с ORM необходимо следовать правилам описания моделей, в противном случае фреймворк не добавит модель в контекст ORM, и с ней невозможно будет работать.
Правила:
- В модуле должна быть процедура
ПриСозданииОбъекта
- Процедура
ПриСозданииОбъекта
не должна принимать параметры - У процедуры
ПриСозданииОбъекта
должна быть аннотация&Сущность
с параметрами:ИмяТаблицы
- Строка - обязательный, содержит имя таблицы, сохраняемой в базе данныхКлючБазы
- Строка - необязательный, содержит ключ базы данных ORM, в которой будет использоваться модель, если не указать, будет использоваться во всех, если требуется использовать модель в нескольких базах, но не во всех, возможно указать ключи через запятую
- В модуле должно быть экспортное свойство с аннотацией
&Идентификатор
- Каждое экспортное свойство должно быть с аннотацией Колонка с параметрами:
Имя
- Строка - имя сохраняемой колонкиТип
- Строка - имя типа, поддерживаемого библиотекой entity
Пример:
&Идентификатор
&ГенерируемоеЗначение
&Колонка(Имя = "Идентификатор", Тип = "Целое")
Перем Идентификатор Экспорт;
&Колонка(Имя = "Фамилия", Тип = "Строка")
Перем Фамилия Экспорт;
&Колонка(Имя = "Имя", Тип = "Строка")
Перем Имя Экспорт;
&Колонка(Имя = "Отчество", Тип = "Строка")
Перем ВтороеИмя Экспорт;
&Колонка(Имя = "ДатаРождения", Тип = "Дата")
Перем ДатаРождения Экспорт;
&Сущность(ИмяТаблицы = "ФизическиеЛица", КлючБазы = "Основная")
Процедура ПриСозданииОбъекта()
КонецПроцедуры
P.S: Документация ещё не дописана полностью, не хватает полного API, деталей и примеров, в связи с этим, принято решение разработать сайт для документации, ожидается "когда-то" :)