Skip to content

Фреймворк на движке onescript, созданный для разработки web-приложений любой сложности, используя компонентный подход.

License

Notifications You must be signed in to change notification settings

oscript-library/onecore

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

81 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

OneCore - web framework

GitHub Release GitHub License

OneCore - это web-фреймворк на движке onescript, созданный для разработки web-приложений любой сложности, используя компонентный подход.

Проект находится в активной разработке. Фреймворк перешёл на onescript 2.0!!!

Содержание

Возможности

Реализовано:

  • Компонентный подход
  • Маршрутизация с поддержкой параметров
  • Шаблонизатор (jinja-подобный)
  • Поддержка статических файлов
  • Middleware (перехватчики)
  • ORM для работы с БД
  • Сервисы для разработки бизнес-логики
  • Встроенный веб-сервер
  • Сеансы и параметры сеансов

В планах:

  • Сервер регламентных заданий
  • WebSocket сервер
  • CLI для удобства работы (создание проекта, компонентов и т.д.)
  • Запуск приложения как службы windows (mssm)
  • Продвинутое логирование в файл или базу данных

Описанные возможности позволяют разрабатывать приложения со сложной поддерживаемой структурой, внешний программный интерфейс (API), сайты и web-приложения по технологии SSR, бэкенд для web-приложений (react, vue и подобные), можно внедрить HTMX и делать SPA, а в будущем и просто приложения для фоновых операций без использования web-сервера.

Установка

Перед установкой у вас уже должна быть установлена платформа onescript версией не менее 2.0RC5 ветка develop. Рекомендовано использовать OVM для установки платформы onescript.

  1. Скачать ospx файл с релизов (onecore-х.х.х.ospx)
  2. Из каталога "simple" корневого каталога репозитория скопируйте содержимое нужного примера в каталог вашего проекта
  3. В каталоге вашего проекта разместите скачанный файл библиотеки (onecore-х.х.х.ospx)
  4. Выполнить консольную команду: opm i -l -f onecore-x.x.x.ospx где "x.x.x" версия фреймворка (библиотеки)
  5. Дождаться завершения установки зависимостей, далее для запуска используется команда 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
        }
    ]
}

Далее запускаем отладку привычным нам способом.

Вернуться к началу

Шаблонизатор (jinja)

Для формирования пользовательского интерфейса фреймворк использует шаблонизатор, другими словами, создаётся обычный 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

Вернуться к началу

Перехватчики (Middleware)

Фреймворк позволяет перехватывать выполнение запроса перед обработкой представлением и перед отправкой ответа, это позволяет гибко управлять данными для отправки. Перехватчики отрабатывают в той очередности, в которой они указаны разработчиком, при этом сначала запускаются процедуры "ПередВыполнениемПредставления" перед отправкой в представление, и уже после обработки представлением в том же порядке выполняются процедуры "ПослеВыполненияПредставления". Для написания обработчиков перехватчиков используются сервисы, а в стартовом файле прописываются пути к сервисам перехватчиков. Для того, чтобы обработать событие, необходимо создать экспортные процедуры "ПередВыполнениемПредставления" или/и ПослеВыполненияПредставления, указав в них 2 параметра: Контекст и ПродолжитьОбработку. Для инициализации сервисов перехватчиков нужно воспользоваться объектом "МенеджерОбъектов", получить его можно с помощью модуля глобального контекста "Приложение", "Приложение.МенеджерКомпонентов()".

Пример стартового скрипта:

#Использовать onecore

// Подключение компонентов
Приложение.ПодключитьКомпонент("Ядро", "core", Истина);

// Подключение перехватчиков
Приложение.ПодключитьПерехватчик("Ядро.Перехватчики.ПроверкаТокена");

// Инициализация и запуск
Приложение.Инициализировать();
Приложение.Запустить();

В метод ИнициализироватьПерехватчики менеджера объектов можно передавать сервисы через запятую или массивом строк, как вам будет удобнее.

Пример сервиса перехватчика по пути: Ядро/Сервисы/Перехватчики/ПроверкаТокена.os

Процедура ПередВыполнениемПредставления(Контекст, ПродолжитьОбработку) Экспорт

    Лог.Отладка("Проверяю токен");
    Токен = Контекст.Запрос.Заголовки.Получить("Token");

    Если НЕ ЗначениеЗаполнено(Токен) Тогда
        Ответ.Отправить(401);
        Лог.Отладка("Отсутствует токен в заголовках");
    КонецЕсли;

    Лог.Отладка("Токен типа проверен");

КонецПроцедуры

Процедура ПослеВыполненияПредставления(Контекст, ПродолжитьОбработку) Экспорт

    Лог.Отладка("Что-то делаем после того, как обработалось представление");

КонецПроцедуры

Перед выполнением каждой процедуры сервиса перехватчика проверяется признак отправленности ответа, в случае, если ответ отправлен, процедура не будет выполнена. Если необходимо прервать дальнейшее выполнение обработки запроса необходмо параметр "ПродолжитьОбработку" установить в Ложь.

Вернуться к началу

Работа с базой данных (ORM)

Для работы с базами данных во фреймворк встроена ORM entity, так же вас никто не ограничивает использовать и другие библиотеки по работе с базами данных, но именно entity интегрирована в onecore. Интеграция заключается в том, что фреймворк автоматически сканирует все скрипты в каталогах компонентов "Модели" и добавляет их в entity, так же проводит инициализацию моделей при инициализации приложения.

Таблицы в базе данных автоматически синхронизируются с моделями при инициализации приложения

Чтобы использовать entity в onecore нужно, в первую очередь, включить поддержку ORM и указать, какую базу использовать в файле main.os:

#Использовать "onecore"

// Подключение функционала
Приложение.ИспользоватьORM();
Приложение.ПодключитьБазуДанныхORM("Основная");
Приложение.ПодключитьБазуДанныхORM("Файловая", "КоннекторSQLite", "FullUri=file:main.db");

// Подключение компонентов
Приложение.ПодключитьКомпонент("Ядро", "core", Истина);

// Подключение перехватчиков
Приложение.ПодключитьПерехватчик("Ядро.Перехватчики.ПроверкаТокена");

// Инициализация и запуск
Приложение.Инициализировать();
Приложение.Запустить();

Процедура ПодключитьБазуДанныхORM принимает в себя 3 параметра:

  1. Ключ - Строка - Ключ, по которому будет определяться, какой конкретно менеджер сущностей использовать
  2. ТипКоннектора - Строка - Тип коннектора строкой, см. документацию entity (не обязательно)
  3. СтрокаСоединения - Строка - Строка соединения по формату выбранного коннектора (не обязательно)

Из выше описанного следует, что есть возможность использовать несколько менеджеров сущностей и, следовательно, несколько баз данных, если второй и третий параметры не указаны, то их необходимо будет указать в файле 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, деталей и примеров, в связи с этим, принято решение разработать сайт для документации, ожидается "когда-то" :)

Вернуться к началу

About

Фреймворк на движке onescript, созданный для разработки web-приложений любой сложности, используя компонентный подход.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • 1C Enterprise 99.1%
  • HTML 0.9%