JavaScript

Рабочий процесс: JavaScriptCommunity Edition+

Введение

Узел «JavaScript» позволяет пользователям выполнять пользовательский серверный JavaScript-скрипт внутри рабочего процесса. Скрипт может использовать переменные из вышестоящих узлов рабочего процесса как параметры, а его возвращаемое значение может передаваться в нижестоящие узлы.

Скрипт запускается в рабочем потоке на сервере приложения NocoBase и поддерживает большинство возможностей Node.js, но имеет некоторые отличия от нативного окружения выполнения. Подробнее см. в разделе Список возможностей.

Создание узла

В интерфейсе настройки рабочего процесса нажмите кнопку плюса ("+") в потоке, чтобы добавить узел «JavaScript»:

20241202203457

Настройка узла

20241202203655

Параметры

Используется для передачи переменных или статических значений из контекста рабочего процесса в скрипт для использования в логике кода. name — имя параметра, которое становится именем переменной внутри скрипта. value — значение параметра; это может быть переменная или константа.

Содержимое скрипта

Содержимое скрипта можно рассматривать как функцию. Можно писать любой JavaScript-код, поддерживаемый окружением Node.js, и использовать оператор return, чтобы вернуть значение как результат выполнения узла, который затем может использоваться как переменная в последующих узлах.

После написания кода можно нажать кнопку теста под редактором, чтобы открыть диалог тестового выполнения, где параметры заполняются статическими значениями для имитации запуска. После выполнения в диалоге будет видно возвращаемое значение и вывод (лог).

20241202203833

Настройка тайм-аута

Единица измерения — миллисекунды. Значение 0 означает, что тайм-аут не задан.

Продолжать при ошибке

Если опция включена, последующие узлы будут выполняться даже если в скрипте произошла ошибка или сработал тайм-аут.

Примечание

Если скрипт завершился с ошибкой, возвращаемого значения не будет, а в результате узла появится сообщение об ошибке. Если последующие узлы используют переменную результата этого узла, ее нужно обрабатывать с осторожностью.

Движок выполнения

Узел JavaScript поддерживает два движка выполнения. Они выбираются автоматически в зависимости от того, задана ли переменная среды WORKFLOW_SCRIPT_MODULES.

Безопасный режим (по умолчанию)

Если переменная WORKFLOW_SCRIPT_MODULES не задана, скрипты выполняются с помощью движка QuickJS на базе WebAssembly. Он запускает код в изолированной среде выполнения JavaScript со следующими особенностями:

  • Не поддерживает require — импортировать модули нельзя
  • Не поддерживает встроенные API Node.js (такие как process, Buffer, global и др.)
  • Доступны только встроенные объекты стандарта ECMAScript (такие как JSON, Math, Promise, Date и др.)
  • Поддерживает передачу данных через параметры, console для логирования и async/await

Это рекомендуемый режим по умолчанию. Он подходит для чистых вычислений и логики обработки данных и обеспечивает максимальную изоляцию.

Небезопасный режим (поддержка модулей)

Если переменная WORKFLOW_SCRIPT_MODULES задана, скрипты переключаются на встроенный движок Node.js vm, чтобы можно было использовать require.

Предупреждение безопасности

Небезопасный режим использует модуль Node.js vm только для поддержки CommonJS require. Модуль Node.js vm не является безопасной песочницей. Включение этого режима означает, что пользователям, которые могут редактировать, тестировать или запускать скрипты рабочих процессов, предоставляется возможность выполнять код с привилегиями сервера NocoBase.

WORKFLOW_SCRIPT_MODULES не является границей безопасности или моделью разрешений. Эта переменная только определяет, какие имена модулей будут приниматься require() перед выполнением кода скрипта.

Модули в скрипте можно использовать с ограничениями, в стиле CommonJS, через директиву require() для импорта модулей.

Поддерживаются нативные модули Node.js и модули, установленные в node_modules (включая зависимости, уже используемые NocoBase). Модули, доступные коду, должны быть объявлены в переменной окружения приложения WORKFLOW_SCRIPT_MODULES; имена пакетов перечисляются через запятую, например:

WORKFLOW_SCRIPT_MODULES=crypto,timers,lodash,dayjs
Примечание

Модули, не объявленные в переменной окружения WORKFLOW_SCRIPT_MODULES, нельзя использовать в скрипте, даже если они нативные для Node.js или уже установлены в node_modules. Эта политика позволяет на уровне эксплуатации контролировать список модулей, доступных пользователям, чтобы в некоторых сценариях не давать скриптам избыточные права.

В окружении без развертывания из исходного кода, если модуль не установлен в node_modules, можно вручную установить нужный пакет в каталог storage. Например, чтобы использовать пакет exceljs, выполните следующие шаги:

cd storage
npm i --no-save --no-package-lock --prefix . exceljs

Затем добавьте относительный (или абсолютный) путь к пакету от рабочего каталога приложения в переменную окружения WORKFLOW_SCRIPT_MODULES:

WORKFLOW_SCRIPT_MODULES=./storage/node_modules/exceljs

После этого можно использовать пакет exceljs в скрипте (имя в require должно точно совпадать с тем, что задано в переменной окружения):

const ExcelJS = require('./storage/node_modules/exceljs');
// ...

Список возможностей

Версия Node.js

Та же версия, что и у Node.js, на которой работает основное приложение.

Глобальные переменные

Не поддерживаются глобальные переменные вроде global, process, __dirname, __filename.

console.log(global); // will throw error: "global is not defined"

Входные параметры

Параметры, настроенные в узле, становятся глобальными переменными внутри скрипта и могут использоваться напрямую. В скрипт передаются только базовые типы: boolean, number, string, object, массивы. Объект Date при передаче преобразуется в строку ISO-формата. Другие сложные типы, например экземпляры пользовательских классов, напрямую передавать нельзя.

Возвращаемое значение

Оператор return можно использовать для возврата базовых типов данных (по тем же правилам, что и для параметров) в узел как результат выполнения. Если return в коде не вызывается, у выполнения узла не будет возвращаемого значения.

return 123;

Вывод (лог)

Поддерживается использование console для вывода логов.

console.log('hello world!');

При выполнении рабочего процесса вывод скриптового узла также записывается в соответствующий файл журнала рабочего процесса.

Асинхронность

Поддерживается использование async для определения асинхронных функций и await для их вызова. Также поддерживается глобальный объект Promise.

async function test() {
  return Promise.resolve(1);
}

const value = await test();
return value;

Таймеры

Чтобы использовать методы setTimeout, setInterval, setImmediate, их нужно импортировать из пакета Node.js timers.

const { setTimeout, setInterval, setImmediate, clearTimeout, clearInterval, clearImmediate } = require('timers');

async function sleep(time) {
  return new Promise((resolve) => setTimeout(resolve, time));
}

await sleep(1000);

return 123;