Обзор
В каждом приложении должен быть ровно один вызовdefineApplication. Он объявляет:
- Идентификация — универсальный идентификатор, отображаемое имя, описание.
- Разрешения — от имени какой роли выполняются его логические функции и фронтенд-компоненты.
- Возможности доступа к медиа (необязательно): доступ к микрофону или камере, запрашиваемый фронтенд-компонентами, утверждается отдельно от ролевых разрешений.
- Переменные (необязательно) — пары ключ–значение, доступные вашему коду как переменные окружения.
- Хуки предустановки / постустановки / удаления (необязательно) — см. Логические функции.
- Платёжные данные (необязательно) —
billing.recurringдля автоматически взимаемых платформой платежей за подписку,billing.operationsдля операций, за которые ваше приложение списывает кредиты, иbilling.descriptionдля маркетплейса; см. Списание кредитов.
src/application-config.ts
- Поля
universalIdentifier— это UUID, которые вы создаёте один раз и которыми владеете. Сохраняйте их неизменными при синхронизации. СобственныйuniversalIdentifierприложения должен быть допустимым UUID: сервер отклоняет манифест, идентификатор которого не является UUID. Он уникален в пределах всего экземпляра и привязан к рабочему пространству, которому принадлежит его регистрация, поэтому синхронизировать приложение может только это рабочее пространство — см. Владение регистрацией. applicationVariablesпринимает необязательный параметрlabel— понятное пользователю имя, отображаемое на странице настроек приложения вместо исходного ключа переменной.applicationVariablesстановятся переменными окружения для ваших функций и фронтенд-компонентов. В логических функциях (на стороне сервера) они доступны какprocess.env.VARIABLE_NAME. Во фронтенд-компонентах используйтеgetApplicationVariable('VARIABLE_NAME')изtwenty-sdk/front-component. Переменные, помеченные какisSecret: true, внедряются только в логические функции. Фронтенд-компоненты получают только несекретные переменные. Переменная сscope: 'USER'хранит значение участника, для которого выполняется код: см. Переменные рабочей области и пользователя.- Ваше приложение также может считывать и обновлять значения собственных переменных во время выполнения. Именно так пользовательский компонент настроек сохраняет введённые пользователем данные: см. Чтение и обновление переменных во время выполнения. Приложение имеет доступ только к собственным переменным в собственном рабочем пространстве.
- Роль по умолчанию автоматически определяется из файла роли, помеченного с помощью
defineApplicationRole()— вам не нужно ссылаться на неё изdefineApplication(). - Функции предустановки, постустановки и удаления, а также проверки работоспособности, обнаруживаются автоматически во время сборки манифеста — вам не нужно указывать их в
defineApplication(). - Явная передача
defaultRoleUniversalIdentifierпо-прежнему поддерживается для обратной совместимости, но считается устаревшей и вместо неё рекомендуется использоватьdefineApplicationRole(). serverVariables— это параметры конфигурации и секреты в области экземпляра (например, ключи API). В отличие отapplicationVariables, значения для них не указываются в манифесте — оператор рабочего пространства заполняет их в настройках приложения, и они внедряются в логические функции только после того, как будут заданы.- Приложение может сообщать о собственном состоянии конфигурации с помощью
defineHealthCheck()для того, о чём может знать только само приложение, — например, ключ присутствует, но отозван, или сторонняя учётная запись использует неподходящий тарифный план.isRequiredохватывает то, что Twenty может увидеть самостоятельно; проверка работоспособности охватывает остальное. УстановитеrunOnUserPreferences: true, чтобы проверять собственные настройки каждого участника на странице настроек Apps вместо настроек приложений рабочего пространства. Если не указывать этот параметр или установить для него значениеfalse, будет сохранена существующая проверка рабочего пространства. - Оба типа переменных принимают
isRequired: true. Обязательная переменная, которую рабочая область ещё не заполнила, оставляет приложение ненастроенным: на странице его настроек отображается баннер с указанием отсутствующих переменных и кнопкой для перехода на вкладку, где они задаются. Отмечайте как обязательное только то, без чего приложение действительно не может работать — необязательная переменная с разумным значением по умолчанию должна оставаться необязательной. - Оба типа переменных принимают
isDeprecated: true. Используйте это, чтобы вывести переменную из обращения вместо её удаления: сохранение объявленного ключа сохраняет хранимое значение (удаление уничтожает значение, введённое пользователем), а переменная по-прежнему внедряется, поэтому код сможет обратиться к ней —process.env.NEW_API_KEY ?? process.env.API_KEY. Устаревшая переменная исчезает из настроек приложения, как только у неё больше нет значения, и никогда не учитывается при проверке конфигурации приложения, поэтомуisDeprecatedимеет приоритет надisRequired. - Twenty задает эти имена для каждого запуска функции логики, поэтому они зарезервированы:
TWENTY_API_URL,TWENTY_APP_ACCESS_TOKEN,TWENTY_APP_APPLICATION_ACCESS_TOKEN,TWENTY_API_KEY,TWENTY_FUNCTIONS_URL,TWENTY_SERVER_ROUTES_URLиAPPLICATION_ID. Все остальные имена, начинающиеся сTWENTY_, также зарезервированы для переменных, которые Twenty добавит позже. Манифест, объявляющий зарезервированное имя в качестве переменной приложения или сервера, отклоняется при синхронизации или публикации приложения. - Чтобы добавить собственные элементы в меню настроек приложения (вместо созданной страницы Variables), объявите фронтенд-компонент и укажите его в
defineSettingsMenuItem()в отдельном файле. Объявите столько элементов, сколько необходимо, и упорядочьте их с помощьюposition;scopeразмещает элемент в настройках рабочего пространства или в настройках каждого участника. Системный элемент Общие (автообновление, URL приложения, подключения) всегда отображается первым, а URL приложения показывается только если в приложении есть функции, запускаемые по HTTP.
Запрашиваемые возможности доступа к медиа
УкажитеrequestedCapabilities, когда фронтенд-компонент использует navigator.mediaDevices.getUserMedia(). Необязательный массив принимает 'microphone', 'camera' или оба значения. Не указывайте его или используйте пустой массив, если приложению не требуется захват медиа.
Типы переменных
ИapplicationVariables, и serverVariables принимают необязательный type (а для SELECT / MULTI_SELECT — список options). Поддерживаемые типы: TEXT (по умолчанию), BOOLEAN, NUMBER, NUMERIC, DATE, DATE_TIME, SELECT, MULTI_SELECT, ARRAY, RAW_JSON, RICH_TEXT.
src/application-config.ts
type влияет только на отображение и валидацию — оно выбирает соответствующий ввод в UI настроек рабочего пространства (переключатель, числовое поле, раскрывающийся список, выбор даты, JSON‑редактор, …) и позволяет сборке проверить вашу конфигурацию (например, SELECT / MULTI_SELECT должны объявить непустой список options). Оно не меняет то, как значение попадает в ваш код.
Значения всегда внедряются как строки — это заложено в природу переменных окружения (process.env.* содержит только строки). Когда выполняется ваша логическая функция, исполнитель сериализует каждое значение в соответствии с объявленным type при построении process.env, так что строковый формат остается единым, независимо от того, как было задано значение (значение по умолчанию в манифесте, UI настроек или предыдущая версия):
Преобразуйте строку обратно в ожидаемый вами тип:
getApplicationVariable('VARIABLE_NAME') — возвращаемое значение является строкой; при необходимости преобразуйте его.
Переменные рабочей области и пользователя
У каждой переменной приложения естьscope:
WORKSPACE(по умолчанию): одно значение для всей рабочей области, заданное участником, который может управлять приложениями.USER: каждый участник хранит собственное значение.
src/application-config.ts
value пользовательской переменной является её значением по умолчанию: участник, не задавший собственное значение, читает его, а новая версия вашего приложения может его изменить. Секретная переменная не может иметь значения по умолчанию. Без него участник, не задавший собственное значение, читает пустую строку, поэтому ваше приложение определяет, что означает незаданное значение.
Администратор рабочей области не может задать значение для пользовательской переменной: её значения принадлежат каждому участнику.
Область действия переменной задаётся при её создании и не может быть изменена. Чтобы изменить её, объявите переменную с новым universalIdentifier: синхронизация удалит старую переменную вместе со значениями её участников и создаст новую.
Пользовательские переменные могут быть isSecret, isRequired или обоими. Например, для личного ключа API можно объявить scope: 'USER', isSecret: true, isRequired: true. Значения шифруются при хранении.
Для пользовательских переменных isRequired описывает требование для каждого участника. Участник, для которого не задано значение, собственное или по умолчанию, видит ваше приложение с пометкой Отсутствует конфигурация в настройках приложений и баннером с названиями переменных. Это не влияет на предупреждение о конфигурации рабочего пространства, и ничто не обеспечивает это во время выполнения: ваш код по-прежнему определяет, что означает неустановленное значение.
Пользовательская переменная внедряется со значением участника, для которого выполняется ваш код, или со значением по умолчанию, пока он не задаст собственное:
- В логической функции
process.envсодержит значения участника, который инициировал запуск, то есть того же участника, от имени которого действуетTWENTY_APP_ACCESS_TOKEN. Запуск, за которым никто не стоит, например задание cron или хук установки, вообще не получает пользовательских переменных. - Во фронтальном компоненте
getApplicationVariableвозвращает значения участника, который его просматривает. Секретные пользовательские переменные исключаются, как и секретные переменные рабочей области.
myUserApplicationVariables через MetadataApiClient. Он перечисляет всех участников со значениями пользовательских переменных вашего приложения и работает при каждом запуске логической функции, включая задания cron и вебхуки. Каждая запись содержит userWorkspaceId, workspaceMemberId и variables участника: объявление каждой пользовательской переменной (label, description, type, options, isSecret, isRequired, isDeprecated) и значение участника либо значение по умолчанию, пока он не задаст собственное. Запрашивайте его как приложение, чтобы получить фактические значения: с токеном, за которым стоит пользователь, он возвращает только запись этого пользователя с замаскированными секретами.
process.env (см. Типы переменных).
updateMyUserApplicationVariable сохраняет собственное значение участника. Он получает applicationUniversalIdentifier вашего приложения и записывает значение человека, стоящего за токеном: собственный сеанс участника или токен вашего приложения, когда за ним стоит участник, например во фронтенд-компоненте или логической функции, выполняемой для участника. Токен вашего приложения может указывать только ваше собственное приложение, а токен, за которым никто не стоит, например в задании cron или хуке установки, отклоняется. Пустое значение удаляет собственное значение участника, поэтому он снова получает значение по умолчанию или пустую строку для переменной без значения по умолчанию.
Ему не требуется разрешение приложений рабочего пространства, но требуется разрешение пользовательских приложений: в роли участника и, когда вызов выполняется с токеном вашего приложения, также в роли вашего приложения по умолчанию, если она объявлена. Если ваше приложение сохраняет пользовательские переменные, добавьте SystemPermissionFlag.USER_APPS в permissionFlagUniversalIdentifiers его роли.
Роль функции по умолчанию
Роль, объявленная с помощьюdefineApplicationRole(), определяет, к чему могут получать доступ логические функции и фронтенд‑компоненты приложения:
- Токены времени выполнения, подставляемые в ваши функции логики, формируются из этой роли. Вызов, выполняемый от имени пользователя, дополнительно ограничен тем, что может делать этот пользователь, поэтому он никогда не может превышать ни один из них. См. Чей доступ использует вызов.
- Типизированный клиент API ограничен правами, предоставленными этой роли.
- Следуйте принципу наименьших привилегий: объявляйте только те разрешения, которые действительно нужны вашим функциям.
src/roles/default-role.ts. Полную справочную информацию см. в разделе Роли и разрешения.
Метаданные маркетплейса
Если вы планируете опубликовать приложение, эти необязательные поля определяют, как оно отображается в маркетплейсе:«logoUrl» и «screenshots» являются устаревшими псевдонимами «logo» и «galleryImages». Внешние абсолютные URL-адреса (
http:// или https://) не поддерживаются для этих полей: они удаляются с предупреждением на время сборки. Вместо этого объедините изображения в папку public/ вашего приложения.