@pachca/cli 2026.10.4 → 2026.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +10 -0
- package/dist/commands/bots/create.js +13 -7
- package/dist/commands/bots/list.js +1 -1
- package/dist/commands/bots/update-webhook.js +8 -1
- package/dist/commands/bots/update.js +11 -5
- package/dist/commands/chats/update.js +1 -1
- package/dist/commands/drafts/create.js +1 -1
- package/dist/commands/drafts/update.js +1 -1
- package/dist/commands/messages/create.js +2 -2
- package/dist/commands/messages/update.js +12 -2
- package/dist/commands/profile/update-status.js +5 -4
- package/dist/commands/reactions/add.js +9 -2
- package/dist/commands/reactions/remove.js +1 -28
- package/dist/commands/search/list-chats.js +1 -1
- package/dist/commands/search/list-messages.js +1 -1
- package/dist/commands/search/list-users.js +1 -1
- package/dist/commands/security/list.js +1 -1
- package/dist/commands/tasks/create.js +0 -28
- package/dist/commands/tasks/update.js +1 -1
- package/dist/commands/users/create.js +5 -2
- package/dist/commands/users/list.js +1 -1
- package/dist/commands/users/update-status.js +5 -4
- package/dist/commands/users/update.js +7 -4
- package/dist/data/changelog.json +39 -0
- package/dist/data/endpoints.json +1 -1
- package/oclif.manifest.json +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 2026.11.0 (4 ноября 2026)
|
|
4
|
+
|
|
5
|
+
- **Изменено** (tasks create): Работает без `--kind` и не спрашивает тип в терминале: по умолчанию создаётся простое напоминание
|
|
6
|
+
- **Изменено** (reactions remove): Снимает реакцию по `--name` без `--code`
|
|
7
|
+
- **Добавлено** (profile update-status, users update-status): `--expires-at null` убирает срок статуса, а `--away-message null` убирает текст «Нет на месте»
|
|
8
|
+
- **Добавлено** (bots create, bots update, bots update-webhook, messages update, reactions add, users create, users update): Длина значений проверяется до запроса: `--outgoing-url`, `--challenge-key`, `--display-avatar-url`, `--display-name` и `--title` до 255 символов, а `--code` у `reactions add` до 16
|
|
9
|
+
- **Добавлено**: В выводе команд с сообщениями и черновиками есть поле `voice_content.transcript_status`: статус расшифровки голосового сообщения
|
|
10
|
+
- **Изменено** (api): Справка `--docs` и схема `--spec` показывают необязательными поля деталей журнала аудита, которых нет в записи без значения, а список скоупов без `files:write`, `webhooks:read` и `webhooks:write`
|
|
11
|
+
- **Изменено**: Справка команд следует уточнённым описаниям API: ник сотрудника и бота, пустой бот, события, команды и `--ignore-self-messages` бота, поиск сотрудников и ботов, длина поискового запроса, подпись сообщения бота, название чата, упоминания в черновике, текст «Нет на месте», смена почты, приостановка владельца, `--actor-id` у `pachca security list` и `--done-at` у `pachca tasks update`
|
|
12
|
+
|
|
3
13
|
## 2026.10.4 (31 октября 2026)
|
|
4
14
|
|
|
5
15
|
- **Исправлено** (api): Справка `--docs` и схема `--spec` показывают `dlp_rule_id` в деталях события `dlp_violation_detected` строкой, как его отдаёт API
|
|
@@ -16,19 +16,19 @@ export default class BotsCreate extends BaseCommand {
|
|
|
16
16
|
description: "Имя бота (макс. 255 символов)",
|
|
17
17
|
}),
|
|
18
18
|
'nickname': Flags.string({
|
|
19
|
-
description: "Никнейм
|
|
19
|
+
description: "Никнейм бота: латинские буквы, цифры и `_`, в конце `_bot`, свободный в пространстве. Ник не по формату отвечает `400` на поле `bot.nickname` с кодом `invalid`, а занятый ник — с кодом `taken`. Без поля ник собирается из имени в латинской транслитерации с `_bot` в конце, а если такой ник занят, с `_2_bot`, `_3_bot` и далее. (макс. 255 символов)",
|
|
20
20
|
}),
|
|
21
21
|
'outgoing-url': Flags.string({
|
|
22
|
-
description: "URL исходящего вебхука",
|
|
22
|
+
description: "URL исходящего вебхука (макс. 255 символов)",
|
|
23
23
|
}),
|
|
24
24
|
'events': Flags.string({
|
|
25
|
-
description: "События, на которые подписан бот",
|
|
25
|
+
description: "События, на которые подписан бот. Без поля бот подписан на `message_new`.",
|
|
26
26
|
}),
|
|
27
27
|
'trigger-on': Flags.string({
|
|
28
28
|
description: "Условие срабатывания исходящего вебхука",
|
|
29
29
|
}),
|
|
30
30
|
'commands': Flags.string({
|
|
31
|
-
description: "Команды бота (триггер-слова), на которые он реагирует при trigger_on = commands. Событие о сообщении приходит боту, когда первое слово текста совпадает с одной из команд целиком, с учётом регистра. Команду можно задать и без слэша в начале. Суммарная длина
|
|
31
|
+
description: "Команды бота (триггер-слова), на которые он реагирует при trigger_on = commands. Событие о сообщении приходит боту, когда первое слово текста совпадает с одной из команд целиком, с учётом регистра. Команду можно задать и без слэша в начале. Суммарная длина команд вместе с разделителями `, ` (запятая и пробел) не должна превышать 255 символов.",
|
|
32
32
|
}),
|
|
33
33
|
'scopes': Flags.string({
|
|
34
34
|
description: "Скоупы (права доступа) токена бота. Если не указано, бот получает набор по умолчанию. Боту доступны не все скоупы: часть из них разрешена только пользовательским ролям, и попытка назначить такой скоуп возвращает `400`. Служебные значения `bot` и `all` назначать нельзя.",
|
|
@@ -40,14 +40,14 @@ export default class BotsCreate extends BaseCommand {
|
|
|
40
40
|
description: "Шаблонизатор для обработки шаблона входящего вебхука. Без этого поля бот получает `liquid`, а пустой бот (`empty: true`) — `mustache`.",
|
|
41
41
|
}),
|
|
42
42
|
'challenge-key': Flags.string({
|
|
43
|
-
description: "Название поля проверки для верификации входящего вебхука",
|
|
43
|
+
description: "Название поля проверки для верификации входящего вебхука (макс. 255 символов)",
|
|
44
44
|
}),
|
|
45
45
|
'link-preview-enabled': Flags.boolean({
|
|
46
46
|
description: "Показывать превью ссылок в сообщениях входящего вебхука",
|
|
47
47
|
allowNo: true,
|
|
48
48
|
}),
|
|
49
49
|
'ignore-self-messages': Flags.boolean({
|
|
50
|
-
description: "Не присылать боту события о
|
|
50
|
+
description: "Не присылать боту события о сообщениях, которые он отправил сам, и о реакциях на эти сообщения, кто бы их ни поставил или снял. Нажатия кнопок приходят всегда.",
|
|
51
51
|
allowNo: true,
|
|
52
52
|
}),
|
|
53
53
|
'events-history-enabled': Flags.boolean({
|
|
@@ -71,7 +71,7 @@ export default class BotsCreate extends BaseCommand {
|
|
|
71
71
|
description: "Домены, ссылки на которые бот разворачивает, не больше 5. Работают вместе с событием `message_link_shared`.",
|
|
72
72
|
}),
|
|
73
73
|
'empty': Flags.boolean({
|
|
74
|
-
description: "Создать пустого бота: без
|
|
74
|
+
description: "Создать пустого бота: без входящего вебхука и, если не переданы скоупы, без токена. Без этого поля бот создаётся с входящим вебхуком в своём формате, а его токен приходит в `access_token`.",
|
|
75
75
|
allowNo: true,
|
|
76
76
|
}),
|
|
77
77
|
'oauth-client': Flags.string({
|
|
@@ -117,6 +117,12 @@ export default class BotsCreate extends BaseCommand {
|
|
|
117
117
|
if (flags['nickname'] && String(flags['nickname']).length > 255) {
|
|
118
118
|
validationErrors.push({ message: `--nickname: максимум 255 символов (передано: ${String(flags['nickname']).length})`, flag: 'nickname' });
|
|
119
119
|
}
|
|
120
|
+
if (flags['outgoing-url'] && String(flags['outgoing-url']).length > 255) {
|
|
121
|
+
validationErrors.push({ message: `--outgoing-url: максимум 255 символов (передано: ${String(flags['outgoing-url']).length})`, flag: 'outgoing-url' });
|
|
122
|
+
}
|
|
123
|
+
if (flags['challenge-key'] && String(flags['challenge-key']).length > 255) {
|
|
124
|
+
validationErrors.push({ message: `--challenge-key: максимум 255 символов (передано: ${String(flags['challenge-key']).length})`, flag: 'challenge-key' });
|
|
125
|
+
}
|
|
120
126
|
if (validationErrors.length > 0) {
|
|
121
127
|
this.validationError(validationErrors);
|
|
122
128
|
}
|
|
@@ -11,7 +11,7 @@ export default class BotsList extends BaseCommand {
|
|
|
11
11
|
static flags = {
|
|
12
12
|
...BaseCommand.baseFlags,
|
|
13
13
|
'query': Flags.string({
|
|
14
|
-
description: "Поисковая фраза для фильтрации ботов по имени",
|
|
14
|
+
description: "Поисковая фраза для фильтрации ботов по имени или нику",
|
|
15
15
|
}),
|
|
16
16
|
limit: Flags.integer({
|
|
17
17
|
description: 'Количество результатов на страницу',
|
|
@@ -13,7 +13,7 @@ export default class BotsUpdateWebhook extends BaseCommand {
|
|
|
13
13
|
static flags = {
|
|
14
14
|
...BaseCommand.baseFlags,
|
|
15
15
|
'outgoing-url': Flags.string({
|
|
16
|
-
description: "URL исходящего вебхука. Пустая строка отключает вебхук.",
|
|
16
|
+
description: "URL исходящего вебхука. Пустая строка отключает вебхук. (макс. 255 символов)",
|
|
17
17
|
}),
|
|
18
18
|
};
|
|
19
19
|
async run() {
|
|
@@ -45,6 +45,13 @@ export default class BotsUpdateWebhook extends BaseCommand {
|
|
|
45
45
|
this.validationError(missingRequired.map((f) => ({ message: `Обязательный флаг --${f.flag} не передан`, flag: f.flag })), { hint: "Обязательные: --outgoing-url <string>. pachca introspect bots update-webhook" });
|
|
46
46
|
}
|
|
47
47
|
}
|
|
48
|
+
const validationErrors = [];
|
|
49
|
+
if (flags['outgoing-url'] && String(flags['outgoing-url']).length > 255) {
|
|
50
|
+
validationErrors.push({ message: `--outgoing-url: максимум 255 символов (передано: ${String(flags['outgoing-url']).length})`, flag: 'outgoing-url' });
|
|
51
|
+
}
|
|
52
|
+
if (validationErrors.length > 0) {
|
|
53
|
+
this.validationError(validationErrors);
|
|
54
|
+
}
|
|
48
55
|
const body = { webhook: {
|
|
49
56
|
outgoing_url: flags['outgoing-url'],
|
|
50
57
|
} };
|
|
@@ -20,10 +20,10 @@ export default class BotsUpdate extends BaseCommand {
|
|
|
20
20
|
description: "Имя бота (макс. 255 символов)",
|
|
21
21
|
}),
|
|
22
22
|
'nickname': Flags.string({
|
|
23
|
-
description: "Никнейм
|
|
23
|
+
description: "Никнейм бота: латинские буквы, цифры и `_`, в конце `_bot`, свободный в пространстве. Ник не по формату отвечает `400` на поле `bot.nickname` с кодом `invalid`, а занятый ник — с кодом `taken`. (макс. 255 символов)",
|
|
24
24
|
}),
|
|
25
25
|
'outgoing-url': Flags.string({
|
|
26
|
-
description: "URL исходящего вебхука",
|
|
26
|
+
description: "URL исходящего вебхука (макс. 255 символов)",
|
|
27
27
|
}),
|
|
28
28
|
'events': Flags.string({
|
|
29
29
|
description: "События, на которые подписан бот. Список заменяется целиком.",
|
|
@@ -32,7 +32,7 @@ export default class BotsUpdate extends BaseCommand {
|
|
|
32
32
|
description: "Условие срабатывания исходящего вебхука",
|
|
33
33
|
}),
|
|
34
34
|
'commands': Flags.string({
|
|
35
|
-
description: "Команды бота (триггер-слова), на которые он реагирует при trigger_on = commands. Событие о сообщении приходит боту, когда первое слово текста совпадает с одной из команд целиком, с учётом регистра. Команду можно задать и без слэша в начале. Суммарная длина
|
|
35
|
+
description: "Команды бота (триггер-слова), на которые он реагирует при trigger_on = commands. Событие о сообщении приходит боту, когда первое слово текста совпадает с одной из команд целиком, с учётом регистра. Команду можно задать и без слэша в начале. Суммарная длина команд вместе с разделителями `, ` (запятая и пробел) не должна превышать 255 символов.",
|
|
36
36
|
}),
|
|
37
37
|
'scopes': Flags.string({
|
|
38
38
|
description: "Скоупы (права доступа) токена бота. Если не указано, бот получает набор по умолчанию. Боту доступны не все скоупы: часть из них разрешена только пользовательским ролям, и попытка назначить такой скоуп возвращает `400`. Служебные значения `bot` и `all` назначать нельзя.",
|
|
@@ -44,14 +44,14 @@ export default class BotsUpdate extends BaseCommand {
|
|
|
44
44
|
description: "Шаблонизатор для обработки шаблона входящего вебхука",
|
|
45
45
|
}),
|
|
46
46
|
'challenge-key': Flags.string({
|
|
47
|
-
description: "Название поля проверки для верификации входящего вебхука",
|
|
47
|
+
description: "Название поля проверки для верификации входящего вебхука (макс. 255 символов)",
|
|
48
48
|
}),
|
|
49
49
|
'link-preview-enabled': Flags.boolean({
|
|
50
50
|
description: "Показывать превью ссылок в сообщениях входящего вебхука",
|
|
51
51
|
allowNo: true,
|
|
52
52
|
}),
|
|
53
53
|
'ignore-self-messages': Flags.boolean({
|
|
54
|
-
description: "Не присылать боту события о
|
|
54
|
+
description: "Не присылать боту события о сообщениях, которые он отправил сам, и о реакциях на эти сообщения, кто бы их ни поставил или снял. Нажатия кнопок приходят всегда.",
|
|
55
55
|
allowNo: true,
|
|
56
56
|
}),
|
|
57
57
|
'events-history-enabled': Flags.boolean({
|
|
@@ -91,6 +91,12 @@ export default class BotsUpdate extends BaseCommand {
|
|
|
91
91
|
if (flags['nickname'] && String(flags['nickname']).length > 255) {
|
|
92
92
|
validationErrors.push({ message: `--nickname: максимум 255 символов (передано: ${String(flags['nickname']).length})`, flag: 'nickname' });
|
|
93
93
|
}
|
|
94
|
+
if (flags['outgoing-url'] && String(flags['outgoing-url']).length > 255) {
|
|
95
|
+
validationErrors.push({ message: `--outgoing-url: максимум 255 символов (передано: ${String(flags['outgoing-url']).length})`, flag: 'outgoing-url' });
|
|
96
|
+
}
|
|
97
|
+
if (flags['challenge-key'] && String(flags['challenge-key']).length > 255) {
|
|
98
|
+
validationErrors.push({ message: `--challenge-key: максимум 255 символов (передано: ${String(flags['challenge-key']).length})`, flag: 'challenge-key' });
|
|
99
|
+
}
|
|
94
100
|
if (validationErrors.length > 0) {
|
|
95
101
|
this.validationError(validationErrors);
|
|
96
102
|
}
|
|
@@ -16,7 +16,7 @@ export default class ChatsUpdate extends BaseCommand {
|
|
|
16
16
|
static flags = {
|
|
17
17
|
...BaseCommand.baseFlags,
|
|
18
18
|
'name': Flags.string({
|
|
19
|
-
description: "Название (макс. 255 символов)",
|
|
19
|
+
description: "Название беседы или канала. Пустое название или название из одних пробелов отвечает `400` с кодом `blank`. (макс. 255 символов)",
|
|
20
20
|
}),
|
|
21
21
|
'public': Flags.boolean({
|
|
22
22
|
description: "Открытый доступ",
|
|
@@ -20,7 +20,7 @@ export default class DraftsCreate extends BaseCommand {
|
|
|
20
20
|
description: "Идентификатор того, что названо в `entity_type`: беседы или канала, треда либо сотрудника (pachca chats list | pachca users list)",
|
|
21
21
|
}),
|
|
22
22
|
'content': Flags.string({
|
|
23
|
-
description: "Текст черновика. Можно не передавать, если есть вложения, но пустым черновик быть не может. До 40 000 байт в UTF-8.",
|
|
23
|
+
description: "Текст черновика. Можно не передавать, если есть вложения, но пустым черновик быть не может. Поддерживает упоминания, как текст в методе [Новое сообщение](POST /messages). `<@user_id>` остаётся в тексте черновика как передан, а при отправке становится `@nickname`. До 40 000 байт в UTF-8.",
|
|
24
24
|
}),
|
|
25
25
|
'parent-message-id': nullableInteger({
|
|
26
26
|
description: "Идентификатор сообщения, ответом на которое уйдёт черновик. Сообщение должно быть в том же чате.",
|
|
@@ -17,7 +17,7 @@ export default class DraftsUpdate extends BaseCommand {
|
|
|
17
17
|
static flags = {
|
|
18
18
|
...BaseCommand.baseFlags,
|
|
19
19
|
'content': Flags.string({
|
|
20
|
-
description: "Текст черновика. До 40 000 байт в UTF-8.",
|
|
20
|
+
description: "Текст черновика. Поддерживает упоминания, как текст в методе [Новое сообщение](POST /messages). `<@user_id>` остаётся в тексте черновика как передан, а при отправке становится `@nickname`. До 40 000 байт в UTF-8.",
|
|
21
21
|
}),
|
|
22
22
|
'parent-message-id': nullableInteger({
|
|
23
23
|
description: "Идентификатор сообщения, ответом на которое уйдёт черновик. `null` снимает ответ. Чтобы передать null, укажите `--parent-message-id null`.",
|
|
@@ -31,10 +31,10 @@ export default class MessagesCreate extends BaseCommand {
|
|
|
31
31
|
description: "Идентификатор сообщения, на которое вы отвечаете с цитатой. Ответить можно на сообщение в любом чате, в том числе в треде: ответ отправляют в тот же чат или тред, где лежит это сообщение, иначе запрос вернёт ошибку `422`. Чтобы написать в тред под сообщением, укажите `entity_type: \"thread\"` и `id` треда в `entity_id`.",
|
|
32
32
|
}),
|
|
33
33
|
'display-avatar-url': Flags.string({
|
|
34
|
-
description: "Ссылка на специальную аватарку отправителя для этого сообщения. Использование этого поля возможно только с access_token бота. (макс. 255 символов)",
|
|
34
|
+
description: "Ссылка на специальную аватарку отправителя для этого сообщения. Использование этого поля возможно только с access_token бота. До 255 байт в UTF-8. (макс. 255 символов)",
|
|
35
35
|
}),
|
|
36
36
|
'display-name': Flags.string({
|
|
37
|
-
description: "Полное специальное имя отправителя для этого сообщения. Вместе с `display_avatar_url` бот подписывает сообщение чужим именем и аватаром, и только это сообщение. Бейдж «Бот» остаётся, а в профиле отправителя видно настоящего бота. Так показывают автора из другой системы, когда переносят в Пачку чужую переписку. С личным токеном поле недоступно, ответ `403`. Подробности — в разделе [Боты](https://dev.pachca.com/guides/bots/overview). (макс. 255 символов)",
|
|
37
|
+
description: "Полное специальное имя отправителя для этого сообщения. Вместе с `display_avatar_url` бот подписывает сообщение чужим именем и аватаром, и только это сообщение. Бейдж «Бот» остаётся, а в профиле отправителя видно настоящего бота. Так показывают автора из другой системы, когда переносят в Пачку чужую переписку. С личным токеном поле недоступно, ответ `403`. До 255 байт в UTF-8, для кириллицы это около 127 символов. Подробности — в разделе [Боты](https://dev.pachca.com/guides/bots/overview). (макс. 255 символов)",
|
|
38
38
|
}),
|
|
39
39
|
'skip-invite-mentions': Flags.boolean({
|
|
40
40
|
description: "Пропуск добавления упомянутых сотрудников в тред. В треде упоминание работает ещё и как приглашение: упомянутого сотрудника, которого в треде нет, Пачка туда добавляет, и он получает доступ к треду и родительскому сообщению. Если в пространстве включена настройка «Использовать сквозные треды» (так по умолчанию), упоминание добавляет и сотрудника не из родительского чата, а с `true` в этом поле упоминание никого не добавляет, и тот, кого в треде нет, не получает и уведомления. Упоминание от гостя или мульти-гостя при этом добавляет только тех, с кем у автора есть общий чат. Если настройка выключена, упоминание добавляет только участников родительского чата, и это поле ничего не меняет. В беседе и канале упоминание никого не добавляет, и этот параметр там ничего не меняет.",
|
|
@@ -25,10 +25,10 @@ export default class MessagesUpdate extends BaseCommand {
|
|
|
25
25
|
description: "Массив строк, каждая из которых представлена массивом кнопок. Максимум 100 кнопок у сообщения, до 8 кнопок в строке. Для удаления кнопок пришлите пустой массив.",
|
|
26
26
|
}),
|
|
27
27
|
'display-avatar-url': Flags.string({
|
|
28
|
-
description: "Ссылка на специальную аватарку отправителя для этого сообщения. Использование этого поля возможно только с access_token бота.",
|
|
28
|
+
description: "Ссылка на специальную аватарку отправителя для этого сообщения. Использование этого поля возможно только с access_token бота. До 255 байт в UTF-8. (макс. 255 символов)",
|
|
29
29
|
}),
|
|
30
30
|
'display-name': Flags.string({
|
|
31
|
-
description: "Полное специальное имя отправителя для этого сообщения. Использование этого поля возможно только с access_token бота.",
|
|
31
|
+
description: "Полное специальное имя отправителя для этого сообщения. Использование этого поля возможно только с access_token бота. До 255 байт в UTF-8, для кириллицы это около 127 символов. (макс. 255 символов)",
|
|
32
32
|
}),
|
|
33
33
|
};
|
|
34
34
|
async run() {
|
|
@@ -44,6 +44,16 @@ export default class MessagesUpdate extends BaseCommand {
|
|
|
44
44
|
if (piped)
|
|
45
45
|
flags['content'] = piped;
|
|
46
46
|
}
|
|
47
|
+
const validationErrors = [];
|
|
48
|
+
if (flags['display-avatar-url'] && String(flags['display-avatar-url']).length > 255) {
|
|
49
|
+
validationErrors.push({ message: `--display-avatar-url: максимум 255 символов (передано: ${String(flags['display-avatar-url']).length})`, flag: 'display-avatar-url' });
|
|
50
|
+
}
|
|
51
|
+
if (flags['display-name'] && String(flags['display-name']).length > 255) {
|
|
52
|
+
validationErrors.push({ message: `--display-name: максимум 255 символов (передано: ${String(flags['display-name']).length})`, flag: 'display-name' });
|
|
53
|
+
}
|
|
54
|
+
if (validationErrors.length > 0) {
|
|
55
|
+
this.validationError(validationErrors);
|
|
56
|
+
}
|
|
47
57
|
const body = { message: {
|
|
48
58
|
content: flags['content'],
|
|
49
59
|
files: flags['files'] ? this.parseJSON(flags['files'], 'files') : undefined,
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// Auto-generated from openapi.yaml — DO NOT EDIT
|
|
2
2
|
import { Flags } from '@oclif/core';
|
|
3
3
|
import { BaseCommand } from '../../base-command.js';
|
|
4
|
+
import { nullableString } from '../../lib/flags.js';
|
|
4
5
|
export default class ProfileUpdateStatus extends BaseCommand {
|
|
5
6
|
static description = "Новый свой статус";
|
|
6
7
|
static scope = "profile_status:write";
|
|
@@ -16,15 +17,15 @@ export default class ProfileUpdateStatus extends BaseCommand {
|
|
|
16
17
|
'title': Flags.string({
|
|
17
18
|
description: "Текст статуса. Обязателен, если статуса ещё нет. (макс. 50 символов)",
|
|
18
19
|
}),
|
|
19
|
-
'expires-at':
|
|
20
|
-
description: "Срок жизни статуса (ISO-8601). Смещение вида `+03:00` учитывается, время без смещения считается UTC.",
|
|
20
|
+
'expires-at': nullableString({
|
|
21
|
+
description: "Срок жизни статуса (ISO-8601). Смещение вида `+03:00` учитывается, время без смещения считается UTC. `null` убирает срок: статус не снимется сам. Чтобы передать null, укажите `--expires-at null`.",
|
|
21
22
|
}),
|
|
22
23
|
'is-away': Flags.boolean({
|
|
23
24
|
description: "Режим «Нет на месте»",
|
|
24
25
|
allowNo: true,
|
|
25
26
|
}),
|
|
26
|
-
'away-message':
|
|
27
|
-
description: "Текст сообщения при режиме «Нет на месте». Отображается в профиле и при личных сообщениях/упоминаниях. (макс. 1024 символов)",
|
|
27
|
+
'away-message': nullableString({
|
|
28
|
+
description: "Текст сообщения при режиме «Нет на месте». Отображается в профиле и при личных сообщениях/упоминаниях. Поддерживает Markdown и упоминания `@nickname` и `<@user_id>`, но сохраняется и возвращается обычным текстом: разметка убирается, а упоминание сотрудника заменяется на `@` с его именем и фамилией. Предел 1024 символа действует и на присланный текст, и на получившийся, сверх него ответ `400` с кодом `too_long`. `null` или пустая строка убирает текст. Чтобы передать null, укажите `--away-message null`. (макс. 1024 символов)",
|
|
28
29
|
}),
|
|
29
30
|
};
|
|
30
31
|
async run() {
|
|
@@ -18,7 +18,7 @@ export default class ReactionsAdd extends BaseCommand {
|
|
|
18
18
|
static flags = {
|
|
19
19
|
...BaseCommand.baseFlags,
|
|
20
20
|
'code': Flags.string({
|
|
21
|
-
description: "Emoji символ реакции. Без `name` нужен именно символ: текстовые записи вроде `+1` или `:+1:` отклоняются как неизвестный эмодзи. С `name` подходит любое непустое
|
|
21
|
+
description: "Emoji символ реакции. Без `name` нужен именно символ: текстовые записи вроде `+1` или `:+1:` отклоняются как неизвестный эмодзи. С `name` подходит любое непустое значение до 16 символов: оно сохраняется как передано. (макс. 16 символов)",
|
|
22
22
|
}),
|
|
23
23
|
'name': Flags.string({
|
|
24
24
|
description: "Имя кастомного эмодзи пространства. С ним реакцией ставится этот эмодзи, а если его в пространстве нет, ответ `404`.",
|
|
@@ -28,7 +28,7 @@ export default class ReactionsAdd extends BaseCommand {
|
|
|
28
28
|
const { args, flags } = await this.parse(ReactionsAdd);
|
|
29
29
|
this.parsedFlags = flags;
|
|
30
30
|
const missingRequired = [
|
|
31
|
-
{ flag: 'code', label: "Emoji символ реакции. Без `name` нужен именно символ: текстовые записи вроде `+1` или `:+1:` отклоняются как неизвестный эмодзи. С `name` подходит любое непустое
|
|
31
|
+
{ flag: 'code', label: "Emoji символ реакции. Без `name` нужен именно символ: текстовые записи вроде `+1` или `:+1:` отклоняются как неизвестный эмодзи. С `name` подходит любое непустое значение до 16 символов: оно сохраняется как передано.", type: 'string' },
|
|
32
32
|
].filter((f) => flags[f.flag] === undefined || flags[f.flag] === null);
|
|
33
33
|
if (missingRequired.length > 0) {
|
|
34
34
|
if (this.isInteractive()) {
|
|
@@ -53,6 +53,13 @@ export default class ReactionsAdd extends BaseCommand {
|
|
|
53
53
|
this.validationError(missingRequired.map((f) => ({ message: `Обязательный флаг --${f.flag} не передан`, flag: f.flag })), { hint: "Обязательные: --code <string>. pachca introspect reactions add" });
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
|
+
const validationErrors = [];
|
|
57
|
+
if (flags['code'] && String(flags['code']).length > 16) {
|
|
58
|
+
validationErrors.push({ message: `--code: максимум 16 символов (передано: ${String(flags['code']).length})`, flag: 'code' });
|
|
59
|
+
}
|
|
60
|
+
if (validationErrors.length > 0) {
|
|
61
|
+
this.validationError(validationErrors);
|
|
62
|
+
}
|
|
56
63
|
const body = {
|
|
57
64
|
code: flags['code'],
|
|
58
65
|
name: flags['name'],
|
|
@@ -7,7 +7,6 @@ export default class ReactionsRemove extends BaseCommand {
|
|
|
7
7
|
static scope = "reactions:write";
|
|
8
8
|
static apiMethod = "DELETE";
|
|
9
9
|
static apiPath = "/messages/{id}/reactions";
|
|
10
|
-
static requiredFlags = ["code"];
|
|
11
10
|
static args = {
|
|
12
11
|
id: Args.integer({
|
|
13
12
|
description: "Идентификатор сообщения",
|
|
@@ -17,7 +16,7 @@ export default class ReactionsRemove extends BaseCommand {
|
|
|
17
16
|
static flags = {
|
|
18
17
|
...BaseCommand.baseFlags,
|
|
19
18
|
'code': Flags.string({
|
|
20
|
-
description: "Emoji символ реакции.
|
|
19
|
+
description: "Emoji символ реакции. Обязателен без `name`: нужен именно символ, текстовые записи вроде `+1` или `:+1:` отклоняются как неизвестный эмодзи. С `name` не используется.",
|
|
21
20
|
}),
|
|
22
21
|
'name': Flags.string({
|
|
23
22
|
description: "Имя реакции, как в её поле `name`. С ним реакция ищется по имени, так снимается и кастомный эмодзи пространства.",
|
|
@@ -30,32 +29,6 @@ export default class ReactionsRemove extends BaseCommand {
|
|
|
30
29
|
async run() {
|
|
31
30
|
const { args, flags } = await this.parse(ReactionsRemove);
|
|
32
31
|
this.parsedFlags = flags;
|
|
33
|
-
const missingRequired = [
|
|
34
|
-
{ flag: 'code', label: "Emoji символ реакции. Без `name` нужен именно символ: текстовые записи вроде `+1` или `:+1:` отклоняются как неизвестный эмодзи.", type: 'string' },
|
|
35
|
-
].filter((f) => flags[f.flag] === undefined || flags[f.flag] === null);
|
|
36
|
-
if (missingRequired.length > 0) {
|
|
37
|
-
if (this.isInteractive()) {
|
|
38
|
-
for (const field of missingRequired) {
|
|
39
|
-
const value = await clack.text({ message: field.label, validate: (v) => v.length === 0 ? 'Обязательное поле' : undefined });
|
|
40
|
-
if (clack.isCancel(value)) {
|
|
41
|
-
process.stderr.write('Отменено.\n');
|
|
42
|
-
this.exit(0);
|
|
43
|
-
}
|
|
44
|
-
if (field.type === 'integer') {
|
|
45
|
-
flags[field.flag] = Number.parseInt(value, 10);
|
|
46
|
-
}
|
|
47
|
-
else if (field.type === 'boolean') {
|
|
48
|
-
flags[field.flag] = value === 'true';
|
|
49
|
-
}
|
|
50
|
-
else {
|
|
51
|
-
flags[field.flag] = value;
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
else {
|
|
56
|
-
this.validationError(missingRequired.map((f) => ({ message: `Обязательный флаг --${f.flag} не передан`, flag: f.flag })), { hint: "Обязательные: --code <string>. pachca introspect reactions remove" });
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
32
|
if (!flags.force) {
|
|
60
33
|
if (!this.isInteractive()) {
|
|
61
34
|
this.validationError([{ message: 'Деструктивная операция требует флага --force', flag: 'force' }], { type: 'PACHCA_DESTRUCTIVE_OP_ERROR', hint: "pachca reactions remove <id> --force" });
|
|
@@ -11,7 +11,7 @@ export default class SearchListChats extends BaseCommand {
|
|
|
11
11
|
static flags = {
|
|
12
12
|
...BaseCommand.baseFlags,
|
|
13
13
|
'query': Flags.string({
|
|
14
|
-
description: "Текст поискового запроса. Запрос длиннее
|
|
14
|
+
description: "Текст поискового запроса. Запрос длиннее 256 знаков обрезается.",
|
|
15
15
|
}),
|
|
16
16
|
'order': Flags.string({
|
|
17
17
|
description: "Направление сортировки",
|
|
@@ -11,7 +11,7 @@ export default class SearchListMessages extends BaseCommand {
|
|
|
11
11
|
static flags = {
|
|
12
12
|
...BaseCommand.baseFlags,
|
|
13
13
|
'query': Flags.string({
|
|
14
|
-
description: "Текст поискового запроса. Без него сообщения отбираются только фильтрами. Запрос длиннее
|
|
14
|
+
description: "Текст поискового запроса. Без него сообщения отбираются только фильтрами. Запрос длиннее 256 знаков обрезается.",
|
|
15
15
|
}),
|
|
16
16
|
'order': Flags.string({
|
|
17
17
|
description: "Направление сортировки",
|
|
@@ -11,7 +11,7 @@ export default class SearchListUsers extends BaseCommand {
|
|
|
11
11
|
static flags = {
|
|
12
12
|
...BaseCommand.baseFlags,
|
|
13
13
|
'query': Flags.string({
|
|
14
|
-
description: "Текст поискового запроса. Запрос длиннее
|
|
14
|
+
description: "Текст поискового запроса. Запрос длиннее 256 знаков обрезается.",
|
|
15
15
|
}),
|
|
16
16
|
'sort': Flags.string({
|
|
17
17
|
description: "Сортировка результатов",
|
|
@@ -22,7 +22,7 @@ export default class SecurityList extends BaseCommand {
|
|
|
22
22
|
options: ["user_login", "user_logout", "user_2fa_fail", "user_2fa_success", "user_2fa_disabled", "login_grant_created", "login_grant_approved", "login_grant_denied", "user_created", "user_deleted", "user_role_changed", "user_updated", "tag_created", "tag_deleted", "user_added_to_tag", "user_removed_from_tag", "chat_created", "chat_renamed", "chat_permission_changed", "user_chat_join", "user_chat_leave", "tag_added_to_chat", "tag_removed_from_chat", "message_updated", "message_deleted", "message_created", "reaction_created", "reaction_deleted", "thread_created", "access_token_created", "access_token_updated", "access_token_destroy", "kms_encrypt", "kms_decrypt", "audit_events_accessed", "company_chats_accessed", "company_bots_accessed", "dlp_violation_detected", "search_users_api", "search_chats_api", "search_messages_api", "bot_scopes_updated", "bot_webhook_settings_updated", "bot_token_recreated", "bot_deleted", "bot_oauth_client_updated", "bot_oauth_client_disabled", "bot_oauth_client_secret_rotated", "bot_oauth_client_secret_issued", "bot_token_created", "bot_token_updated", "bot_token_reissued", "bot_token_deleted", "oauth_authorization_granted", "oauth_authorization_revoked", "oauth_token_revoked", "oauth_device_authorization_approved", "oauth_device_authorization_denied", "video_call_started", "video_call_finished", "video_call_recording_ready", "exchange_disabled"],
|
|
23
23
|
}),
|
|
24
24
|
'actor-id': Flags.string({
|
|
25
|
-
description: "Идентификатор
|
|
25
|
+
description: "Идентификатор актора события, как в поле `actor_id` записи. Смену роли, добавление в чат и исключение из чата, назначение и снятие тегов фильтр находит по сотруднику, которого они коснулись.",
|
|
26
26
|
}),
|
|
27
27
|
'actor-type': Flags.string({
|
|
28
28
|
description: "Тип актора",
|
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
// Auto-generated from openapi.yaml — DO NOT EDIT
|
|
2
2
|
import { Flags } from '@oclif/core';
|
|
3
3
|
import { BaseCommand } from '../../base-command.js';
|
|
4
|
-
import * as clack from '@clack/prompts';
|
|
5
4
|
export default class TasksCreate extends BaseCommand {
|
|
6
5
|
static description = "Новое напоминание";
|
|
7
6
|
static scope = "tasks:create";
|
|
8
7
|
static apiMethod = "POST";
|
|
9
8
|
static apiPath = "/tasks";
|
|
10
9
|
static defaultColumns = ["id", "content", "created_at", "kind", "due_at"];
|
|
11
|
-
static requiredFlags = ["kind"];
|
|
12
10
|
static args = {};
|
|
13
11
|
static flags = {
|
|
14
12
|
...BaseCommand.baseFlags,
|
|
@@ -51,32 +49,6 @@ export default class TasksCreate extends BaseCommand {
|
|
|
51
49
|
if (piped)
|
|
52
50
|
flags['content'] = piped;
|
|
53
51
|
}
|
|
54
|
-
const missingRequired = [
|
|
55
|
-
{ flag: 'kind', label: "Тип", type: 'string' },
|
|
56
|
-
].filter((f) => flags[f.flag] === undefined || flags[f.flag] === null);
|
|
57
|
-
if (missingRequired.length > 0) {
|
|
58
|
-
if (this.isInteractive()) {
|
|
59
|
-
for (const field of missingRequired) {
|
|
60
|
-
const value = await clack.text({ message: field.label, validate: (v) => v.length === 0 ? 'Обязательное поле' : undefined });
|
|
61
|
-
if (clack.isCancel(value)) {
|
|
62
|
-
process.stderr.write('Отменено.\n');
|
|
63
|
-
this.exit(0);
|
|
64
|
-
}
|
|
65
|
-
if (field.type === 'integer') {
|
|
66
|
-
flags[field.flag] = Number.parseInt(value, 10);
|
|
67
|
-
}
|
|
68
|
-
else if (field.type === 'boolean') {
|
|
69
|
-
flags[field.flag] = value === 'true';
|
|
70
|
-
}
|
|
71
|
-
else {
|
|
72
|
-
flags[field.flag] = value;
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
else {
|
|
77
|
-
this.validationError(missingRequired.map((f) => ({ message: `Обязательный флаг --${f.flag} не передан`, flag: f.flag })), { hint: "Обязательные: --kind <string>. pachca introspect tasks create" });
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
52
|
const body = { task: {
|
|
81
53
|
kind: flags['kind'],
|
|
82
54
|
content: flags['content'],
|
|
@@ -38,7 +38,7 @@ export default class TasksUpdate extends BaseCommand {
|
|
|
38
38
|
allowNo: true,
|
|
39
39
|
}),
|
|
40
40
|
'done-at': Flags.string({
|
|
41
|
-
description: "Дата и время выполнения напоминания (ISO-8601). Смещение вида `+03:00` учитывается, время без смещения считается UTC. Значение, которое не удалось разобрать, отметку о выполнении снимает: ответ придёт успешный, а в нём `
|
|
41
|
+
description: "Дата и время выполнения напоминания (ISO-8601). Смещение вида `+03:00` учитывается, время без смещения считается UTC. Значение, которое не удалось разобрать, отметку о выполнении снимает: ответ придёт успешный, а в нём `status` будет `undone`.",
|
|
42
42
|
}),
|
|
43
43
|
'custom-properties': Flags.string({
|
|
44
44
|
description: "Задаваемые дополнительные поля",
|
|
@@ -25,13 +25,13 @@ export default class UsersCreate extends BaseCommand {
|
|
|
25
25
|
description: "Телефон (макс. 255 символов)",
|
|
26
26
|
}),
|
|
27
27
|
'nickname': Flags.string({
|
|
28
|
-
description: "Имя
|
|
28
|
+
description: "Имя пользователя: латинские и кириллические буквы, цифры, `_`, `-` и `.`, иначе ответ `400` с кодом `invalid`. Ники `here` и `all` зарезервированы: на них ответ `400` с кодом `use_of_system_words`. (макс. 255 символов)",
|
|
29
29
|
}),
|
|
30
30
|
'department': Flags.string({
|
|
31
31
|
description: "Департамент (макс. 255 символов)",
|
|
32
32
|
}),
|
|
33
33
|
'title': Flags.string({
|
|
34
|
-
description: "Должность",
|
|
34
|
+
description: "Должность (макс. 255 символов)",
|
|
35
35
|
}),
|
|
36
36
|
'role': Flags.string({
|
|
37
37
|
description: "Уровень доступа",
|
|
@@ -102,6 +102,9 @@ export default class UsersCreate extends BaseCommand {
|
|
|
102
102
|
if (flags['department'] && String(flags['department']).length > 255) {
|
|
103
103
|
validationErrors.push({ message: `--department: максимум 255 символов (передано: ${String(flags['department']).length})`, flag: 'department' });
|
|
104
104
|
}
|
|
105
|
+
if (flags['title'] && String(flags['title']).length > 255) {
|
|
106
|
+
validationErrors.push({ message: `--title: максимум 255 символов (передано: ${String(flags['title']).length})`, flag: 'title' });
|
|
107
|
+
}
|
|
105
108
|
if (validationErrors.length > 0) {
|
|
106
109
|
this.validationError(validationErrors);
|
|
107
110
|
}
|
|
@@ -11,7 +11,7 @@ export default class UsersList extends BaseCommand {
|
|
|
11
11
|
static flags = {
|
|
12
12
|
...BaseCommand.baseFlags,
|
|
13
13
|
'query': Flags.string({
|
|
14
|
-
description: "Поисковая фраза для фильтрации результатов. Поиск работает по полям: `first_name` (имя), `last_name` (фамилия), `
|
|
14
|
+
description: "Поисковая фраза для фильтрации результатов. Поиск работает по полям: `first_name` (имя), `last_name` (фамилия), `nickname` (никнейм), `title` (должность) и `department` (департамент). Если вызывающему видны персональные данные (правило то же, что у поля `email`), поиск идёт ещё по `phone_number` (телефон), значениям дополнительных полей и по полному адресу `email`.",
|
|
15
15
|
}),
|
|
16
16
|
limit: Flags.integer({
|
|
17
17
|
description: 'Количество результатов на страницу',
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// Auto-generated from openapi.yaml — DO NOT EDIT
|
|
2
2
|
import { Args, Flags } from '@oclif/core';
|
|
3
3
|
import { BaseCommand } from '../../base-command.js';
|
|
4
|
+
import { nullableString } from '../../lib/flags.js';
|
|
4
5
|
export default class UsersUpdateStatus extends BaseCommand {
|
|
5
6
|
static description = "Новый статус сотрудника";
|
|
6
7
|
static scope = "user_status:write";
|
|
@@ -21,15 +22,15 @@ export default class UsersUpdateStatus extends BaseCommand {
|
|
|
21
22
|
'title': Flags.string({
|
|
22
23
|
description: "Текст статуса. Обязателен, если статуса ещё нет. (макс. 50 символов)",
|
|
23
24
|
}),
|
|
24
|
-
'expires-at':
|
|
25
|
-
description: "Срок жизни статуса (ISO-8601). Смещение вида `+03:00` учитывается, время без смещения считается UTC.",
|
|
25
|
+
'expires-at': nullableString({
|
|
26
|
+
description: "Срок жизни статуса (ISO-8601). Смещение вида `+03:00` учитывается, время без смещения считается UTC. `null` убирает срок: статус не снимется сам. Чтобы передать null, укажите `--expires-at null`.",
|
|
26
27
|
}),
|
|
27
28
|
'is-away': Flags.boolean({
|
|
28
29
|
description: "Режим «Нет на месте»",
|
|
29
30
|
allowNo: true,
|
|
30
31
|
}),
|
|
31
|
-
'away-message':
|
|
32
|
-
description: "Текст сообщения при режиме «Нет на месте». Отображается в профиле и при личных сообщениях/упоминаниях. (макс. 1024 символов)",
|
|
32
|
+
'away-message': nullableString({
|
|
33
|
+
description: "Текст сообщения при режиме «Нет на месте». Отображается в профиле и при личных сообщениях/упоминаниях. Поддерживает Markdown и упоминания `@nickname` и `<@user_id>`, но сохраняется и возвращается обычным текстом: разметка убирается, а упоминание сотрудника заменяется на `@` с его именем и фамилией. Предел 1024 символа действует и на присланный текст, и на получившийся, сверх него ответ `400` с кодом `too_long`. `null` или пустая строка убирает текст. Чтобы передать null, укажите `--away-message null`. (макс. 1024 символов)",
|
|
33
34
|
}),
|
|
34
35
|
};
|
|
35
36
|
async run() {
|
|
@@ -22,19 +22,19 @@ export default class UsersUpdate extends BaseCommand {
|
|
|
22
22
|
description: "Фамилия (макс. 255 символов)",
|
|
23
23
|
}),
|
|
24
24
|
'email': Flags.string({
|
|
25
|
-
description: "Электронная
|
|
25
|
+
description: "Электронная почта. После её смены сотрудник считается ещё не входившим: `invite_status` приходит `sent`, а `last_activity_at` — `null`, пока он снова не зайдёт в Пачку. (макс. 255 символов)",
|
|
26
26
|
}),
|
|
27
27
|
'phone-number': Flags.string({
|
|
28
28
|
description: "Телефон (макс. 255 символов)",
|
|
29
29
|
}),
|
|
30
30
|
'nickname': Flags.string({
|
|
31
|
-
description: "Имя
|
|
31
|
+
description: "Имя пользователя: латинские и кириллические буквы, цифры, `_`, `-` и `.`, иначе ответ `400` с кодом `invalid`. Ники `here` и `all` зарезервированы: на них ответ `400` с кодом `use_of_system_words`. Ник, занятый другим сотрудником без учёта регистра, отвечает `400` с кодом `already_exists`: случайные символы, как в методе [Новый сотрудник](POST /users), здесь не дописываются. У сотрудника с `sso: true` занятый ник молча остаётся прежним. Ник бота состоит из латинских букв, цифр и `_`, оканчивается на `_bot` и уникален в пространстве, иначе метод отвечает `422` с ошибкой на поле `nickname`: `invalid` или `already_exists`. Другие ошибки ника бота при его смене, например `blank` или `too_long`, тоже приходят с `422`. Прежний ник бота проверяется, только когда его меняют. (макс. 255 символов)",
|
|
32
32
|
}),
|
|
33
33
|
'department': Flags.string({
|
|
34
34
|
description: "Департамент (макс. 255 символов)",
|
|
35
35
|
}),
|
|
36
36
|
'title': Flags.string({
|
|
37
|
-
description: "Должность",
|
|
37
|
+
description: "Должность (макс. 255 символов)",
|
|
38
38
|
}),
|
|
39
39
|
'role': Flags.string({
|
|
40
40
|
description: "Уровень доступа",
|
|
@@ -43,7 +43,7 @@ export default class UsersUpdate extends BaseCommand {
|
|
|
43
43
|
description: "Чат, в котором останется сотрудник при переводе в гости (`role: \"guest\"`): ровно одна активная беседа или канал, куда у токена есть право добавлять участников. Без такого чата ответ `400` по этому полю, и не меняется ничего. При других ролях и у того, кто уже гость, поле не учитывается.",
|
|
44
44
|
}),
|
|
45
45
|
'suspended': Flags.boolean({
|
|
46
|
-
description: "Деактивация
|
|
46
|
+
description: "Деактивация пользователя. Владельца пространства приостановить нельзя никому, в том числе ему самому: ответ `403`.",
|
|
47
47
|
allowNo: true,
|
|
48
48
|
}),
|
|
49
49
|
'list-tags': Flags.string({
|
|
@@ -75,6 +75,9 @@ export default class UsersUpdate extends BaseCommand {
|
|
|
75
75
|
if (flags['department'] && String(flags['department']).length > 255) {
|
|
76
76
|
validationErrors.push({ message: `--department: максимум 255 символов (передано: ${String(flags['department']).length})`, flag: 'department' });
|
|
77
77
|
}
|
|
78
|
+
if (flags['title'] && String(flags['title']).length > 255) {
|
|
79
|
+
validationErrors.push({ message: `--title: максимум 255 символов (передано: ${String(flags['title']).length})`, flag: 'title' });
|
|
80
|
+
}
|
|
78
81
|
if (validationErrors.length > 0) {
|
|
79
82
|
this.validationError(validationErrors);
|
|
80
83
|
}
|