Описание кода пользовательской интеграцииBETA
Этот раздел описывает структуру кода пользовательской интеграции, используемой в редакторе, и основные принципы работы с блоками, подключениями, полями ввода и встроенными объектами (service
, bundle
).
В рамках каждой интеграции выполняется соединение с внешними ресурсами, такими как API, базы данных или другие сервисы, с использованием настроек, указанных в блоках интеграции. Разделение интеграции на компоненты позволяет гибко настроить и адаптировать интеграции под различные требования.
Описание кода
Файл index.ts
Файл index.ts
является точкой входа пользовательской интеграции. В нем собираются все блоки и подключения. На основе этого файла формируется объект интеграции.
Пример файла index.ts
:
import { Integration } from "@infomaximum/integration-sdk";
import { BasicAuthConnect } from "./connections/BasicAuth";
import { SearchIssues } from "./modules/issues/SearchIssues";
import { GetIssueByKeys } from "./modules/issues/getIssueByKey";
import { AddAttachment } from "./modules/issues/AddAttachment";
import { AddWather } from "./modules/issues/AddWatcher";
import { AddComment } from "./modules/issues/AddComment";
import { LinkingIssue } from "./modules/issues/LinkingIssue";
import { CreateIssue } from "./modules/issues/CreateIssue";
import { EditIssue } from "./modules/issues/EditIssue";
import { DeleteIssue } from "./modules/issues/DeleteIssue";
import { WorkLog } from "./modules/logs/Worklog";
import { ChangeLog } from "./modules/logs/ChangeLog";
import { FindGroups } from "./modules/groups/FindGroups";
import { GetGroupMember } from "./modules/groups/GetGroupMember";
import { AddGroupMember } from "./modules/groups/AddGroupMember";
import { DeleteGropupMember } from "./modules/groups/DeleteGroupMember";
app = {
schema: 2,
version: "2.1.0",
label: "Jira Software",
description: "",
blocks: {
SearchIssues,
GetIssueByKeys,
ChangeLog,
WorkLog,
CreateIssue,
EditIssue,
DeleteIssue,
AddWatcher,
AddComment,
AddAttachment,
LinkingIssue,
FindGroups,
GetGroupMember,
AddGroupMember,
DeleteGroupMember,
},
connections: {
BasicAuthConnect,
},
} satisfies Integration;
В этом файле:
blocks
— перечисление всех блоков, реализующих действия интеграцииconnections
— все типы подключения к внешним сервисам- Используется TypeScript-сигнатура
satisfies Integration
для проверки корректности структуры интеграции
Структура интеграции
Интеграция представляет собой объект с описанием блоков и подключений:
schema
— версия структуры интеграцииversion
— номер версии интеграцииlabel
— название интеграцииdescription
— описание интеграции- blocks — основные элементы интеграции, которые выполняют определенные действия. Каждый блок выполняет свою специфическую задачу, например, отправку данных в API, получение информации или выполнение вычислений.
- connections — параметры подключения к внешним системам и сервисам
Блоки интеграции могут содержать поля ввода, которые задают параметры для выполнения действий, а также объекты bundle и service для обработки данных и взаимодействия с API. Для отправки файлов во внешние системы предусмотрена поддержка передачи файлов.
Пример структуры интеграции:
app = {
schema: 1,
version: 'Номер версии',
label: 'Название интеграции',
description: 'Описание интеграции',
blocks: [],
connections: []
}
Шаблон интеграции подробно описан в разделе Пример создания пользовательской интеграции.
Blocks
Компоненты интеграции blocks
— это основные элементы интеграции, выполняющие определенные задачи. Например, блок может получать данные из API или отправлять их в определенное приложение. Блоки необходимы для структурирования и выполнения конкретных шагов в процессе интеграции.
Пример структуры блока с полями ввода inputFields
:
{
label: "Блок получения данных",
description: "Блок получает данные из внешнего API",
inputFields: [
{
key: "api_endpoint",
type: "text",
label: "API Endpoint",
required: true
},
{
key: "access_token",
type: "text",
label: "Access Token",
required: true
}
],
executePagination: (service, bundle,context) => {
var state = context || {
page:0
}
var response = service.request({
url: bundle.inputData.api_endpoint,
method: 'GET',
headers: {
Authorization: 'Bearer ' + bundle.inputData.access_token
}
});
if (response.status !== 200) {
service.error.stringError('Ошибка запроса: ' + response.status);
}
return {
output:[response.json],
output_variables:[
{
type:"String",
name:"text"
}
],
state:state,
hasNext:false
};
}
}
Поля ввода inputFields
Поля inputFields
— это поля ввода, которые позволяют пользователю задавать параметры для блоков интеграции, которые будут использоваться в ходе выполнения блока.
Ниже приведены примеры различных полей ввода.
Тип поля | Назначение | Пример использования |
---|---|---|
array | Ввод списка элементов (с вложенными полями) | Несколько файлов, адресов |
boolean | Переключатель (включение/выключение) | Флаг активации, режим сессии |
button | Кнопка с действием | Запуск запроса, редирект |
code | Ввод кода с подсветкой синтаксиса | SQL, JavaScript, JSON |
cron | Настройка расписания CRON | Периодичность запуска |
date | Выбор даты через календарь | Дата начала |
datetime | Выбор даты и времени | Время события |
Ввод email-адреса | Получатели писем | |
group | Группировка нескольких полей | Адрес, настройки подключения |
integer | Ввод целого числа | ID, количество, порт |
keyValue | Ввод пар ключ-значение | Заголовки, параметры запроса |
multiselect | Выбор нескольких значений из списка | Роли, теги, категории |
number | Ввод числа с плавающей точкой | Сумма, коэффициент |
password | Ввод секретных данных (скрытое отображение) | Пароль, API-ключ |
select | Выбор одного значения из списка | HTTP-метод, страна |
text | Ввод текста | Имя, комментарий, метка |
timezone | Выбор часового пояса по IANA | Настройка локализации |
upload | Загрузка файлов | Прикрепление документа |
uuid | Поле для уникального идентификатора | ID блока |
Поле array
Поле array
— предназначено для ввода списка однотипных элементов с вложенными полями. Позволяет указать несколько значений для одного атрибута.
{
key: "example_1",
type: "array",
props: {
key: "name",
},
},
Поле boolean
Поле boolean
— предназначено для включения или выключения какой-либо настройки или функциональности.
{
type: "boolean",
key: "batching",
label: "Пакетная обработка",
hint: "Несколько запросов объединяются в один",
readOnly: false,
default: true,
placeholder: "false", //только для mappable: true
},
Поле button
Поле button
— кнопка для выполнения запросов в API.
{
key: "OK",
type: "button",
action: {
redirect: (service, bundle) => {…},
},
},
Поле code
Поле code
— редактор кода с подсветкой и автоформатированием.
{
key: "query",
type: "code",
label: "Запрос",
required: true,
hint: " ",
readOnly: false,
default: "const ",
placeholder: "Введите код",
editor: "sql",
sqlDialect: "ClickHouse",
typeOptions: {
minLength: 0,
maxLength: 100,
pattern: "r'^\s*SELECT\s+.*\s+FROM\s+.+;$'",
errorMessage: "Это не select-запрос",
}
},
Поле cron
Поле cron
— предназначено для задания расписания в формате cron.
{
key: "schedule",
type: "cron",
label: "Запускать скрипт",
required: true,
hint: "Расписание в формате CRON",
readOnly: false,
default: "*/15 * * * ?",
},
Поле date
Поле date
— предназначено для выбора даты с помощью встроенного календаря.
{
key: "arrival",
type: "date",
label: "Дата прибытия",
required: true,
hint: "Посмотрите в билете",
readOnly: false,
default: "1998-12-31" | 915051600,
placeholder: "Введите дату",
typeOptions: {
min: 1726146320,
max: 1735041540,
disabledDate: [1726146320, 1735041540],
},
},
Поле datetime
Поле datetime
— позволяет выбрать дату и время с помощью встроенного календаря и часов.
{
key: "arrival",
type: "datetime",
label: "Дата прибытия",
required: true,
hint: "Посмотрите в билете",
readOnly: false,
default: "1998.12.31, 11:59:59pm" | 915137999,
placeholder: "Введите дату",
typeOptions: {
min: 1726146320,
max: 1735041550,
disabledDate: [1726146320, 1735041540],
},
},
Поле email
Поле email
— предназначено для ввода email-адресов, поддерживает ввод нескольких адресов, разделенных запятыми. Позволяет проверить корректность формата введенного адреса.
{
key: "to",
type: "email",
label: "Адрес",
required: true,
hint: "Можно ввести несколько адресов, разделенных запятыми",
readOnly: false,
placeholder: "example@mail.com",
typeOptions: {
pattern: "^\p{Lu}",
errorMessage: "Напишите с большой буквы",
validationDuringExecution: false,
}
},
Поле group
Поле group
— позволяет сгруппировать несколько полей.
{
type: "group",
key: 'expected_fields',
label: 'Ожидаемые поля',
required: true,
hint: "Формирует поле ввода для модального окна",
readOnly: false,
mappable: true,
default: [
{
"name": "Имя",
"type": "string",
"is_required": true,
}
],
properties: [
{
key: 'name',
type: 'text',
label: 'Название поля',
required: true,
default: 'Новое поле',
},
{
key: 'type',
type: 'select',
label: 'Тип данных',
mappable: false,
required: true,
default: "string",
options: [
{
label: 'Стандартный',
options: [
string: 'Строка',
number: 'Число',
integer: 'Целое число',
date: 'Дата',
datetime: 'Дата и время',
boolean: 'Логический',
]
},
{
label: 'Расширенный',
options: ['BigInteger', 'BigDecimal']
}
],
},
{
key: 'is_array',
type: 'boolean',
label: 'Массив',
},
{
key: 'is_required',
type: 'boolean',
label: 'Обязательное поле',
},
{
key: 'is_required',
type: 'button',
}
],
},
Поле integer
Поле integer
— предназначено для ввода целых чисел (от -9007199254740991 до 9007199254740991). Позволяет проверить корректность введенных данных.
{
key: "count",
type: "integer",
label: "Кол-во",
required: true,
hint: "В штуках",
readOnly: false,
default: 10,
placeholder: "Целое число",
typeOptions: {
min: 10,
max: 20,
}
},
Поле keyValue
Поле keyValue
— предназначено для ввода пар «ключ-значение» и может быть использовано при создании параметров запроса.
{
key: "headers",
type: "keyValue",
label: "Заголовки",
required: true,
hint: "Смотрите в API",
readOnly: false,
default: {
Content-Type: "application/json",
Accept: "application/json",
},
placeholder: '{"key": "value"}',
typeOptions: {
sortable: true,
}
},
Поле number
Поле number
— предназначено для ввода чисел любого размера. Позволяет проверить корректность введенных значений.
{
key: "weight",
type: "number",
label: "Вес",
required: true,
hint: "В кг",
readOnly: false,
default: 1.0,
placeholder: "Количество",
typeOptions: {
min: 0.2,
max: 10.0,
}
},
Поле password
Поле password
— позволяет вводить секретную информацию (например, пароль), которая будет скрыта при вводе.
{
type: "password",
key: "apikey",
label: "Ключ API",
required: true,
hint: "Ищите в настройках платформы",
},
Поля select и multiSelect
Поля select
и multiSelect
— предназначены для выбора из предопределенных значений в виде раскрывающегося списка:
select
— поле для выбора одного значения из спискаmultiSelect
— поле для выбора нескольких значений из списка
Пример использования select
:
{
key: "currency",
type: "select",
label: "Валюта",
required: true,
hint: "Если нет подходящей валюты, введите свою",
readOnly: false,
default: "EUR",
placeholder: "Выберите или введите",
options: {
USD: "United States Dollar",
EUR: "Euro",
GBP: "British Pound",
}
},
Пример использования multiSelect
:
{
key: "currency",
type: "multiselect",
label: "Валюта",
required: true,
hint: "Если нет подходящей валюты, введите свою",
readOnly: false,
default: "EUR",
placeholder: "Выберите или введите",
options: {
USD: "United States Dollar",
EUR: "Euro",
GBP: "British Pound",
},
typeOptions: {
minItems: 1,
maxItems: 2,
delimiter: ";",
}
},
Поле text
Поле text
— однострочное текстовое поле для ввода строковых значений.
{
key: "name",
type: "text",
label: "Имя",
required: true,
hint: " ",
readOnly: false,
default: "Новая задача",
placeholder: "Введите текст",
typeOptions: {
enableFullscreen: true,
minLength: 3,
maxLength: 100,
pattern: "^\p{Lu}",
errorMessage: "Напишите с большой буквы",
}
},
Поле timezone
Поле timezone
— предназначено для выбора часового пояса.
{
key: "tz",
type: "timezone",
label: "Часовой пояс",
required: true,
hint: " ",
readOnly: false,
mappable: true,
default: "Europe/Moscow",
placeholder: "Выберите из списка",
},
Поле upload
Поле upload
— предоставляет интерфейс для загрузки файлов с устройства пользователя.
{
key: "image",
type: "upload",
label: "Изображение для профиля",
required: true,
hint: "до 2 МБ, svg или png от 256x256",
readOnly: false,
typeOptions: {
extension: ["png", "svg"],
maxSize: 2000000,
},
},
Поле uuid
Поле uuid
— уникальный идентификатор. Автоматически проверяется на глобальную уникальность.
{
key: "uuid",
type: "uuid",
label: "UUID",
required: false,
readOnly: false,
typeOptions: {
flow: "webhook",
}
},
Общие атрибуты
Все поля поддерживают следующие атрибуты:
Атрибут | Тип | Описание |
---|---|---|
key | string | Уникальный идентификатор поля. Используется для доступа к значению через bundle.inputData[key] |
type | string | Тип поля |
label | string | Текст метки поля |
required | boolean | Обязательно ли поле для заполнения. По умолчанию false |
hint | string | Подсказка под полем. Поддерживает Markdown |
default | any | Значение по умолчанию, если пользователь не ввел данные |
placeholder | string | Текст-заполнитель внутри поля |
readOnly | boolean | Поле нельзя редактировать. По умолчанию false |
mappable | boolean | Разрешает использовать переменные из других блоков. По умолчанию true |
Connections
Компонент интеграции connections
— это параметры подключения к внешним системам и сервисам, которые используются для установления связи между интеграцией и внешними API или базами данных.
Пример структуры подключения с использованием аутентификации Basic Auth:
{
label: "Подключение к Jira",
description: "Подключение по логину/паролю к Jira",
inputFields: [
{
key: "connection_login",
type: "textPlain",
label: "Логин",
required: true
},
{
key: "connection_password",
type: "password",
label: "Пароль",
required: true
},
{
key: "connection_base_url",
type: "textPlain",
label: "URL сервера Jira",
required: true
},
{
key: "authorize_button",
type: "button",
label: "Авторизоваться",
required: false,
executeWithSaveFields: (service, bundle) => {
return {
url: bundle.authData.connection_base_url,
passHash:
"Basic " + service.base64Encode(bundle.authData.connection_login + ":" + bundle.authData.connection_password)
};
},
executeWithMessage: (service, bundle) => {
if (bundle.authData.url && bundle.authData.passHash !== "") return "Успешно авторизован!";
service.error.stringError("Не удалось авторизоваться!");
}
}
],
execute: (service, bundle) => {}
}
Пример структуры подключения с использованием аутентификации OAuth 2.0 представлен ниже.
{
label: "Подключение OAuth 2.0",
description: "Подключение OAuth 2.0"
inputFields: [
{
key: "subdomain_amo_crm",
type: "textPlain",
label: "Cубдомен AmoCRM",
required: true,
},
{
key: "client_id",
type: "password",
label: "Client ID",
required: true,
},
{
key: "client_secret",
type: "password",
label: "Client secret",
required: true,
},
{
key: "show_button",
type: "button",
label: "Получить redirect URL",
required: false,
executeWithSaveFields: (service, bundle) => {
return { redirect_url: bundle.authData.BASE_URL };
},
},
{
key: "redirect_url",
type: "textPlain",
label: "Redirect URL",
required: false,
},
{
key: "authorize_button",
type: "button",
label: "Авторизоваться",
required: false,
executeWithRedirect: (z, bundle) => {
return (
"https://www.amocrm.ru/oauth" +
"?mode=post_message" +
"&client_id=" +
bundle.authData.client_id +
"&redirect_uri=" +
bundle.authData.redirect_url
);
},
executeWithMessage: (service, bundle) => {
if (bundle.authData.accessToken && bundle.authData.accessToken !== "")
return "Успешно авторизован!";
service.error.stringError("Не удалось авторизоваться!");
},
executeWithSaveFields: (z, bundle) => {
const CLIENT_id = bundle.authData.client_id;
const CLIENT_secret = bundle.authData.client_secret;
const guid = bundle.authData.redirect_url
.match(/\/webhook\/.+/)[0]
.replace("/webhook/", "");
const AUTH_Code = z.hook(
(url, headers) => {
return url
.match(/code=[^&]+&?/)[0]
.replace("code=", "")
.replace("&", "");
},
guid,
20
);
if (AUTH_Code === undefined)
z.error.stringError("Не удалось получить Authorization Code.");
const exchangeCode = z.request({
url:
"https://" + bundle.authData.subdomain_amo_crm + ".amocrm.ru/oauth2/access_token",
method: "POST",
headers: {
["Content-Type"]: "application/json",
},
jsonBody: {
client_id: CLIENT_id,
client_secret: CLIENT_secret,
grant_type: "authorization_code",
code: AUTH_Code,
redirect_uri: bundle.authData.redirect_url,
},
});
var accTok = exchangeCode.response.access_token;
if (accTok === undefined)
service.error.stringError(
"Не удалось выполнить обмен Authorization Code на access_token.\n" +
JSON.stringify(exchangeCode.response)
);
return {
accessToken: accTok,
refreshToken: exchangeCode.response.refresh_token,
};
},
},
{
key: "test_button",
type: "button",
label: "Проверить подключение",
required: true,
executeWithMessage: (z, bundle) => {
if (!bundle.authData.accessToken && bundle.authData.accessToken !== "")
return "Не удалось авторизоваться!";
const req = z.request({
url:
"https://" +
bundle.authData.subdomain_amo_crm +
".amocrm.ru/api/v4/leads/pipelines",
method: "GET",
headers: {
Authorization: "Bearer " + bundle.authData.accessToken,
},
});
const status = req.status;
if (Number(status) >= 200 && Number(status) < 300)
return "Успешное подключение! Статус: " + status;
z.error.stringError(
"Не удалось подключиться! Статус: " + status + "\n" + JSON.stringify(req)
);
},
},
{
key: "un_authorize_button",
type: "button",
label: "Забыть учетную запись",
required: false,
executeWithMessage: (z, bundle) => {
return "Я забыл твой токен.";
},
executeWithSaveFields: (z, bundle) => {
return { accessToken: "", refreshToken: "" };
},
},
],
execute: (z, bundle) => {},
}
Использование объекта service
Объект service
предоставляет набор методов для взаимодействия c API, вывода ошибок, а также работы с хуками и итераторами.
Доступные методы объекта service
Метод base64Encode
— производит base64-кодирование входной строки. На вход принимает строку, которую необходимо закодировать.
service.base64Encode()
Метод base64Decode
— производит base64-декодирование входной строки. На вход принимает строку, которую необходимо декодировать в формате base64
.
service.base64Decode()
Метод request
— выполняет HTTP-запрос. Ожидает на вход объект с конфигурацией запроса. Параметры этого объекта указаны в таблице ниже.
Параметр | Обязательный | Описание |
---|---|---|
url | Да | Ссылка на ресурс, на который нужно выполнить запрос |
method | Да | Метод с которым будет выполнен запрос. Доступные методы: - GET - POST - PATCH - PUT - DELETE |
headers | Нет | Список заголовков для HTTP/1.1 |
jsonBody multipartBody | Зависит от метода | Обязательный для POST /PATCH /PUT |
service.request({
url: request_url,
method: "POST",
headers: {
Authorization: `Bearer ${bundle.authData.access_token}`,
"Content-Type": "application/json"
},
jsonBody: {
note: bundle.inputData.note
}
})
Метод hasNext
— возвращает true
или false
в зависимости от того, есть ли еще элементы во входном итераторе блока.
service.hasNext()
Метод next
— если есть следующий элемент в итераторе, вызов этого метода обновит все значения полей маппинга на значения соответствующие следующему элементу итератора. Вызов этого метода автоматически сокращает количество элементов в выходном итераторе.
service.next()
Метод index
— возвращает текущий номер итерации.
service.index()
Метод hook
— обрабатывает ответ от ресурса, к которому происходит подключение.
{
key: "authorize",
type: "button",
label: "Авторизоваться",
required: false,
executeWithRedirect: (service, bundle) => {
return `https://gitlab.com/oauth/authorize?client_id=${bundle.authData.client_id}&redirect_uri=${bundle.authData.redirect_url}&response_type=code`;
},
executeWithSaveFields: (service, bundle) => {
const match = bundle.authData.redirect_url.match(/\/webhook\/.+/);
let guid = "";
if (match) {
guid = match[0].replace("/webhook/", "");
const AUTH_Code = service.hook(
(url, headers) => {
return url
.match(/code=[^&]+&?/)[0]
.replace("code=", "")
.replace("&", "");
},
guid,
20
);
if (AUTH_Code === undefined) service.error.stringError("Не удалось получить Authorization Code.");
const exchangeCode = service.request({
url: `https://gitlab.com/oauth/token`,
method: "POST",
headers: {
["Content-Type"]: "application/json"
},
jsonBody: {
client_id: bundle.authData.client_id,
client_secret: bundle.authData.client_secret,
grant_type: "authorization_code",
code: AUTH_Code,
redirect_uri: bundle.authData.redirect_url
}
});
var accTok = exchangeCode.response.access_token;
if (accTok === undefined)
service.error.stringError(
"Не удалось выполнить обмен Authorization Code на access_token.\n" + JSON.stringify(exchangeCode.response)
);
return {
access_token: accTok,
refresh_token: exchangeCode.response.refresh_token
};
} else {
service.error.stringError("Не удалось авторизоваться!");
}
},
executeWithMessage: (service, bundle) => {
if (bundle.authData.access_token && bundle.authData.access_token !== "") return "Успешно авторизован!";
service.error.stringError("Не удалось авторизоваться!");
}
}
Метод error.stringError
— служит для вывода текста ошибки. В качестве параметра принимает строку, которая отобразится в блоке в случае возникновения ошибки.
service.error.stringError()
Использование объекта bundle
Пользовательские данные из полей ввода доступны в коде интеграции через объект bundle
.
Объект bundle
содержит два основных компонента, которые предоставляют доступ к введенной информации:
С помощью этих данных блок настраивает запросы и выполняет необходимые действия.
bundle.authData
Компонент bundle.authData
хранит учетные данные, которые настраиваются в разделе подключений (connections
).
Все поля ввода из подключения автоматически становятся доступны через bundle.authData
. Эти данные необходимы для взаимодействия с API и внешними сервисами.
Пример:
При настройке подключения с полями api_key
и api_url
эти значения станут доступны через bundle.authData
для использования в запросах вашего блока.
execute: (service, bundle) => {
var response = service.request({
url: bundle.authData.api_url + '/data',
method: 'GET',
headers: {
Authorization: 'Bearer ' + bundle.authData.api_key
}
});
if (response.status !== 200) {
service.error.stringError('Ошибка запроса: ' + response.status);
}
return {
output: () => ({
data: response.json
})
};
}
bundle.inputData
Компонент bundle.inputData
хранит данные, которые пользователь вводит в поля ввода блока (inputFields
).
Эти данные позволяют настраивать параметры запросов и выполнять другие действия внутри блока.
Все поля ввода, настроенные в блоке, автоматически становятся доступными через bundle.inputData
.
Пример:
Если в блоке есть поля ввода api_endpoint
и access_token
, их значения будут доступны через bundle.inputData
для использования при настройке запроса.
execute: (service, bundle) => {
var response = service.request({
url: bundle.inputData.api_endpoint,
method: 'GET',
headers: {
Authorization: 'Bearer ' + bundle.inputData.access_token
}
});
if (response.status !== 200) {
service.error.stringError('Ошибка запроса: ' + response.status);
}
return {
output: () => ({
data: response.json
})
};
}
Передача файлов
Интеграции поддерживают передачу файлов во внешние системы с помощью multipartBody
. Это используется, например, для прикрепления файлов к задачам в сторонних системах.
Для загрузки файлов в систему используйте блоки автоматизации для работы с файлами.
multipartBody
— это массив объектов, каждый из которых представляет собой часть данных, отправляемых в запросе.
В представленном ниже примере multipartBody
содержит один объект, который описывает файл, предназначенный для прикрепления к задаче.
Пример:
var response = service.request({
url: `${bundle.authData.url}/rest/api/2/issue/${bundle.inputData.issueIdOrKey}/attachments`,
method: "POST",
headers: {
Authorization: bundle.authData.passHash,
"X-Atlassian-Token": "nocheck"
},
multipartBody: [
{
key: "file",
fileValue: bundle.inputData.attachment,
fileName: bundle.inputData.attachment_name,
contentType: "application/octet-stream"
}
]
});
Структура объекта в multipartBody
:
key: "file"
— имя поля, под которым файл будет доступен на сервере. В приведенном примере поле называется"file"
, что соответствует ожиданиям API для загрузки вложенийfileValue: bundle.inputData.attachment
— значение, представляющее собой сам файл, который будет загружен. Оно должно содержать данные файла, которые вы хотите прикрепитьfileName: bundle.inputData.attachment_name
— имя файла, которое будет использоваться на сервере. Оно может включать расширение файла, чтобы сервер мог правильно определить тип содержимогоcontentType: "application/octet-stream"
— это MIME-тип файла. В приведенном примере используется общий тип для двоичных данных, что позволяет серверу обрабатывать файл как поток байтов. В зависимости от типа файла, можно указать более специфичный MIME-тип (например,image/jpeg
для изображений илиapplication/pdf
для PDF-документов)
Была ли статья полезна?