Серверные сценарии
Как говорилось выше, использование серверных сценариев — это чаще всего затратная операция. Но есть случаи, когда без использования серверных сценариев задачу выполнить невозможно. Разберём самые популярные случаи.
Получение настроек модулей
В системе ELMA365 для получения настроек модуля можно использовать только серверные сценарии. Такое ограничение определено подходом к безопасности хранения данных, так как в настройках часто используются ключи и токены для доступа к сторонним системам.
Код для получения настроек достаточно простой. Предположим, что у нас есть модуль предпросмотра, и у него в настройках задаётся список расширений файлов, которые модуль может обрабатывать:
![[IMG]](https://community.elma365.com/ru/assets/MzAg0L3QsNGB0YLRgNC+0LnQutC4INC80L7QtNGD0LvRjzE2OTIxNzc1NTU=.png)
Пример виджета для прослушивания файлов формата .mp3, который создан внутри модуля предпросмотра:
Спойлер: Виджет «Код»
Код:
<% if (Context.data.link) { %>
<audio controls src="<%= Context.data.link%>">
Ваш браузер не поддерживает встроенное аудио. Попробуйте скачать его
<a href="<%= Context.data.link%>" download>по ссылке</a>.
</audio>
<% } %>
Спойлер: Сценарий (Клиент)
Код:
/** Загрузка виджета */
async function onInit() {
if (Context.data.extension![0] !== 'mp3') {
return;
}
if (!await Allow()) {
return;
}
const file_link = await Context.data.file?.getDownloadUrl();
if (!file_link) {
return;
}
Context.data.link = file_link;
}
/** Проверить, разрешено ли данное расширение */
async function Allow(): Promise<boolean> {
if (typeof Context.data.allow === 'undefined') {
await LoadSettings();
}
return Context.data.allow!;
}
async function LoadSettings(): Promise<void> {
Context.data.allow = false;
await Server.rpc.LoadSettings();
}
/** Загрузить настройки модуля */
async function LoadSettings(): Promise<void> {
const extension = Namespace.params.data.extensions.find(ext => ext.extension === 'mp3');
Context.data.allow = extension?.allow;
}
Данный подход можно улучшить, сохранив результат получения настроек в кэш. Подробный пример описан в статье «Работа с настройками модуля» в ELMA365 Community.
Обход CORS
Вторая причина для использования серверных сценариев — обход запрета с кроссдоменными запросами (CORS). Браузер защищает пользователя, отслеживая запросы, которые выполняются на сайте. Если вы зашли на домен my-elma.com, а запросы уходят на домен other-site.com, то браузер заблокирует такие запросы и выдаст ошибку в консоли.
При выполнении запроса через серверные сценарии запрос будет выполняться не в браузере, а с сервера, где таких блокировок нет.
Чтобы адаптировать свой клиентский метод с запросом к внешнему источнику, достаточно просто перенести его в серверную часть. Главное требование — сигнатура метода должна быть следующей:
Код:
async function MyServerFunc(): Promise<void> {}
На клиентской стороне метод можно использовать через следующую конструкцию:
Код:
await Server.rpc.MyServerFunc();
Поиск с повышенными привилегиями
Мы создали виджет, который находит пересечения по отпускам. Если поиск будет осуществляться на клиенте, то мы получим только свои отпуска и отпуска подчинённых (если вы руководитель). Чтобы иметь возможность получить все отпуска, достаточно перенести метод в серверные сценарии.
На данный момент клиентский сценарий для поиска отпусков выглядит следующим образом:
Код:
async function mySearch(): Promise<void> {
Context.data.result = await Application.search()
.where(item => item.__deletedAt.eq(null))
.all();
for(let item of Context.data.result) {
/* обработка списка */
}
}
Перенесём получение данных в серверный сценарий, а в клиентском просто выполняем вызов серверного метода.
Серверный сценарий
Код:
async function mySearch(): Promise<void> {
Context.data.result = await Application.search()
.where(item => item.__deletedAt.eq(null))
.all();
}
Клиентский сценарий
Код:
async function mySearch(): Promise<void> {
await Server.rpc.mySearch();
for(let item of Context.data.result) {
/* обработка списка */
}
}