Коллеги всем привет!
Я бы хотел представить на суд уважаемого Сommunity стабильную версию свой библиотеки для работы с SimpleOne, под названием SOAgent.
Работал я над ней с переменным успехом уже года два, несколько раз переписывал практически с нуля. В последнее время библиотека стала работать гораздо быстрее и стабильнее и я использую её в своей работе каждый день.
А о чем собственно речь?
Коллеги, мы с вами пишем бизнес приложения на платформе SimpleOne, и очень часто сталкиваемся с одними и теми же проблемами.
- Фича работает на dev-е и не работает на prod-е.
- Фича работает на dev-е и prod-е но ломает старый функционал.
- Фича работает правильно по мнению разработчика и не правильно по мнению аналитика или бизнес-пользователя, при этом каждый тестирует фичу по-своему и проходит какое-то значительное время прежде чем все участники синхронизируют свое видение о том как и что должно работать правильно.
Конечно же проблемы эти связаны не какими-то архитектурными особенностями SimpleOne, это проблема разработки в целом. Очевидным ответом на эти вызовы является тестирование. И вы вероятно скажите что надо больше тестировать фичи, глубже погружаться в контекст задачи и бюрократизировать процесс так, чтобы подобное не повторилось в будущем. И все это конечно же правильно, но жизнь такова, что очередной хитрый баг тем не менее проскальзывает через барьеры, прямо в production-среду буквально с очередным релизом.
К сожалению у меня нет для вас 100% решения всех этих проблем, тем не менее я бы хотел представить одно небольшое техническое средство которое кажется может значительно улучшить положение наших с вами дел.
Что это такое и как работает?
SOAgent (https://github.com/MShamhalov/SOAgent) - это библиотека написанная на языке JavaScript для среды исполнения Bun (bun.com). SOAgent позволяет удаленно вызывать API функции SimpleOne (как документированные TableAPI функции (Table API | SimpleOne Documentation) так и недокументированные). Таким образом вам как разработчикам становится доступным управление платформой SimpleOne прямо из вашей любимой IDE (или из консоли). На всякий случай проговорю, что библиотека работает c SimpleOne поверх её функциональности таким образом все изменения которые вы отправите на сервер будут вызывать бизнес-правила и рабочие процессы (то есть речь не о прямой работе с базой данных).
Несколько слов о среде исполнения - использование Bun (вместо NodeJS) позволяет решить сразу несколько задач:
- Исключено использование сторонних решений из библиотеки node modules (никакого npm -install при установке SOAgent делать не придется). Все работает из коробки так как надо и без зависимостей.
- Bun работает гораздо быстрее NodeJS.
- Совместимость с NodeJS.
- Для установки Bun не требуются права администратора (подходит для корпоративных сред с выкрученной до максимума ручкой безопасности).
Далее я не буду петь дифирамб Bun-у, если хотите то можете ознакомиться с её возможностями на официальном сайте. Скажу лишь, что если бы я попал на необитаемый остров, Bun это именно тот инструмент, который я бы хотел иметь там при себе ).
Как установить библиотеку?
Соответственно алгоритм установки и настройки SOAgent выглядит так:
- Устанавливаете себе Bun (команда установки для windows:
powershell -c "irm bun.sh/install.ps1 | iex") - Скачиваем и распаковываем SOAgent себе в локальную директорию, (например при помощи git:
git clone https://github.com/MShamhalov/SOAgent). - В файле
./accounts.confв блокеfirstInstanceпрописываем адрес инстанса и токен пользователя чтобы получить токен надо в консоли браузера набратьs_user.accessToken(можно вообще обойтись без ввода логина с паролем). - Чтобы проверить что все работает корректно, введите в консоли вашей операционной системы ./sosh/sosh.cmd (если вы используете Windows) или
bun ./sosh/sosh.js(если вы работаете в MacOS или Linux). - В приглашении
sosh>введите командуinstance(илиi)
В результате вы должны получить две строки с адресом вашего инстанса первая строка получена из файлаaccounts.conf, а вторая с инстанса (из системного свойства simple.instance.uri).
То есть, если вы увидели две строки:
sosh> Local File Path: xxxx.simpleone.ru
simple.instance.uri: xxxx.simpleone.ru
значит все готово к использованию!
Как подключить библиотеку из своих скриптов?
На данный момент подключение библиотеки выглядит так:
const { envFilePath } = require('#conf');
const { SOAgentInterface } = require('#SOAgentInterface');
const sa = new SOAgentInterface(envFilePath);
Если вы хотите использовать библиотечные файлы из вне каталога библиотеки, скопируйте себе в каталог файл package.json из корня библиотеки и исправьте пути в блоке imports.
"imports": {
"#SOAgentCoreMethods": "./src/core_layer/SOAgentCore.js",
"#SOAgentInterface": "./src/core_layer/SOAgentInterface.js",
"#SOAgentLogin": "./src/core_layer/SOAgentLogin.js",
"#SOAgentTableDictionary": "./src/core_layer/SOAgentTableDictionary.js",
"#SOAgentTableHelper": "./src/app_layer/SOAgentTableHelper.js",
"#conf": "./SOAgent.conf"
}
А что можно делать при помощи библиотеки?
Само-собой вам доступны CRUD операции с таблицами.
const { envFilePath } = require('#conf');
const { SOAgentInterface } = require('#SOAgentInterface');
const sa = new SOAgentInterface(envFilePath);
(async function () {
// Создаем запись в таблице task
const insertObject = {
subject: 'Не работает беспроводная клавиатура Roxy M17',
};
const insertRecord = await sa.insertRecord('task', insertObject);
recordId = sa.getValue(insertRecord, 'sys_id');
console.log("Created Record: /record/task/" + recordId);
// Обновляем запись в таблице task
const updateObject = {
subject: 'Не работает беспроводная мышь Proxy M18',
};
const updatedRecord = await sa.updateRecord('task', recordId, updateObject);
const sysId = sa.getValue(updatedRecord, 'sys_id');
console.log("Updated Record: /record/task/" + sysId);
// Запрашиваем данные из таблицы task
const queryParams = new Map([
['sysparm_query', ''],
['sysparm_display_value', '0'],
['sysparm_exclude_reference_link', '0'],
['sysparm_fields', ['path_name', 'sys_id']],
['sysparm_view', ''],
['sysparm_limit', '1'],
['sysparm_page', '1'],
]);
const getRecordsByQuery = await sa.queryRecord('page', queryParams);
recordId = sa.getValue(getRecordsByQuery, 'sys_id');
// Удаляем данные из таблицы
await sa.deleteRecord('task', recordId);
})();
Кроме того можно запустить на сервере произвольный скрипт (для экономии места я не дублирую строки с подключением библиотек)
getDocIdScript = `
const recordDocID = ss.getDocIdByIds('${taskTableSysId}', '${recordId}');
ss.debug(recordDocID);
`;
const recordDocIdFromSimpleOne = await sa.runScript(getDocIdScript);
ss.debug выступает тут некоторым подобием return.
Можно запускать скрипты из внешних файлов.
...
const content = Bun.file('./tmp/snippet.js').text();
const result = await sa.runScript(content);
...
Можно работать с вложениями:
// Загрузить вложение на иснтанс
const filePath = './file.svg';
const recordId = '156828511504252176';
await sa.attachmentsUpload(filePath, 'task', recordId);
// Загрузить файл на инстанс "быстрым импортом"
const result = await sa.quickImport('./uploadFile.json');
За более подробными примерами использования библиотеки SOAgent отсылаю вас в каталог examples в корне директории проекта.
Зачем нужен sosh?
Sosh это очень простая консольная оболочка для выполнения каких-то простых действий на платформе SimpleOne, например нужно быстро вычислить DoсID по известной таблице и записи:
sosh> getDocId itsm_incident 156828511504252176
для выполнения того же действия можно использовать алиас короче
sosh> gdi itsm_incident 156828511504252176
или например нам срочно надо найти запись по известному sys_id:
sosh> findById 156828511504252176
короткая версия:
sosh> fbi 156828511504252176
или почистить серверный кэш (сокращение от Clear Cache)
sosh> cc
Ладно, это все понятно, что там по поводу тестов?
Вместе со средой Bun идет тест-ранер, совместимый с Jest (https://jestjs.io/). Так что мне даже не пришлось переписывать свои тесты которыми я проверяю не поломалось ли чего после очередного апдейта.
Скелет типичного теста выглядит так:
const { envFilePath } = require('#conf');
const { SOAgentInterface } = require('#SOAgentInterface');
const sa = new SOAgentInterface(envFilePath);
beforeAll(async () => {
});
describe('Последовательные тесты', () => {
test('Первый тест', async () => {
});
test('Второй тест', async () => {
});
});
Далее в тесте вы можете использовать необходимые в работе expect - методы
// Проверка на корректный sys_id
expect(recordId).toMatch(new RegExp(/\d{18}/));
// Проверка на корректный DocID
expect(recordDocId).toMatch(new RegExp(/[0-9a-f]{32}/));
// Проверка на значение true
expect('active').toBe(true);
Подробнее со списком методов можно ознакомиться по ссылке Expect · Jest
Далее после того как ваши тесты готовы, позаботьтесь о том, чтобы в имени вашего теста был какой-то номер и слово test, и можно вызывать тест при помощи команды
bun test 0004 // Если ваш тест назвается например 0004_Check_BP.text.js
Так же помните, что в каталоге tests уже содержатся тесты проверяющие корректность работы библиотеки SOAgent, поэтому если ввести bun test без параметров, запустятся все тесты которые тест-раннер bun найдет в директории. И вы возможно не захотите чтобы на вашей продуктовой среде создавались тестовые записи.
Как лицензируется SOAgent
Полный текст лицензии на русском языке присутствует в файле LICENCE (сполер - я не стал ничего изобретать и использовал MIT) в корне библиотеки и в некоторых значимых файлах. Лицензия распространяется на весь исходный код, файлы примеров, документацию и прочие файлы. Перед использованием библиотеки вы должны ознакомиться с лицензией и принять её, если она вас не устраивает или она вам не понятна, пожалуйста воздержитесь от использования SOAgent.
Также отмечу, что сохранение таких данных как токен, логин и пароль в открытом виде в локальном файле может нарушать политику информационной безопасности вашей компании или компаний ваших клиентов и привести к негативным последствиям для вас. Если вы читали лицензию (а если нет то обязательно прочитайте её прямо сейчас), то уже наверняка догадались, что за все последствия использования библиотеки SOAgent ответственность несете только вы.
Где ещё можно применить SOAgent?
- Автоматизация деплоя.
- Создание интеграций для SimpleOne
- Создание единого инструмента автоматизированного тестирования (UI и API)
- Отладка бизнес-логики - например при помощи дополнения Bun for Visual Studio Code можно подстроить свою работу так, чтобы вам была доступна полноценная отладка с breckpoint-ами и выполнением скрипта (и проверкой результата) step by step.
Что дальше?
Взглянув мельком на свой бэклог я просто в ужасе, тут не паханое поле для развития, надо подружиться с встроенным в SimpleOne - RabbitMQ и Attachment Service-ом, сделать методы для автоматизированного создания отчетов SimpleOne (кажется было бы классно собрать в одном месте конфиг, и штопать отчеты без необходимости прожимать все кнопками в UI но пока даже не проверял можно ли так сделать), а что если получится делать скелеты рабочих процессов из UML-диаграмм? Или представьте себе эдакий Ansible уровня бизнес-приложения, который позволит установить только необходимые части большого бизнес-приложения (с тестовыми данными и предзаполненными таблицами нормативно-справочной информации)… Ухх, аж дух захватывает… ) Но кажется я взялся за что-то непосильное для одного человека. Так что если есть желание - проект открытый и я буду рад мердж-реквестам, идеям, баг-репортам и возможно даже хорошим форкам.
P.S.
За пару дней до публикации этого текста, этот бренный мир покинул мой кот, так что посвящаю эту работу ему. Толстопуз - дружище, я скучаю по тебе.