UNPKG

@set2333/upload-script-helpers

Version:

Helper library for upload scripts

529 lines (424 loc) 15 kB
# Upload Scripts Helpers Набор утилит для загрузки и обработки данных для дальнейшей обработки в Pentaho. ## Установка ```bash npm install @set2333/upload-script-helpers ``` ## Требования - Node.js >= 12.0.0 ## Быстрый старт ```typescript import { EmailManager, FileManager, Logger, ParserXLS, Validator, ApiManager, JsonMapper } from '@set2333/upload-script-helpers' // Создание логгера const logger = new Logger({ displayTypes: ['console', { type: 'file', options: { logFile: 'app.log' } }] }) // Управление файлами const fileManager = new FileManager({ workDirectory: './work-dir', logger }) // Работа с API const apiManager = new ApiManager({ baseUrl: 'https://api.example.com', headers: { 'Authorization': 'Bearer token' } }) // Получение данных const apiData = await apiManager.fetch({ page: 1, limit: 100 }) // Сохранение данных fileManager.saveJSONFile(apiData, 'api-response.json') ``` ## Модули ### Logger Система логирования с поддержкой консоли и файлов. **Опции:** - `messageTypes` - типы сообщений для логирования: `['log', 'warn', 'error']` - `displayTypes` - способы вывода: `['console']` или `[{ type: 'file', options: { logFile: 'app.log', logDir: './logs' } }]` **Методы:** - `log(message: string, ...args: unknown[])` - обычное сообщение - `warn(message: string, ...args: unknown[])` - предупреждение - `error(message: string, ...args: unknown[])` - ошибка - `start(message: string)` - начало процесса с временной меткой - `end(message: string)` - конец процесса с временной меткой - `duration(processName: string)` - длительность процесса **Пример:** ```typescript const logger = new Logger({ displayTypes: [ 'console', { type: 'file', options: { logFile: 'app.log', logDir: './logs' } } ] }) logger.start('Обработка данных') logger.log('Загружаем файл...') logger.warn('Файл большой, это может занять время') logger.duration('Обработка данных') logger.end('Обработка завершена') ``` ### FileManager Управление файлами и рабочими директориями. **Опции:** - `workDirectory` (string) - путь к рабочей директории - `logger` (ILogger | null) - логгер для вывода сообщений **Методы:** - `saveJSONFile(data: unknown, fileName: string)` - сохранение JSON файла - `saveAttachment(attachmentData: Buffer, fileName: string)` - сохранение вложения **Пример:** ```typescript const fileManager = new FileManager({ workDirectory: './work-dir', logger }) // Сохранение JSON данных const userData = { users: [{ name: 'John', age: 30 }] } fileManager.saveJSONFile(userData, 'users.json') // Сохранение вложения из email const attachmentBuffer = Buffer.from('file content') fileManager.saveAttachment(attachmentBuffer, 'document.xlsx') ``` ### EmailManager Работа с email через IMAP и SMTP. **Опции:** - `credentials` - данные для подключения к почтовому серверу - `searchRules` - правила поиска писем - `logger` - логгер для вывода сообщений **Методы:** - `connect()` - подключение к серверу - `disconnect()` - отключение от сервера - `getEmails()` - получение писем с вложениями - `sendEmail(options)` - отправка письма **Пример:** ```typescript const emailManager = new EmailManager({ credentials: { host: 'imap.gmail.com', port: 993, user: 'your-email@gmail.com', pass: 'your-password', smtpHost: 'smtp.gmail.com', smtpPort: 587, smtpUser: 'your-email@gmail.com', smtpPass: 'your-password' }, searchRules: { since: '2024-01-01', before: '2024-12-31', attachmentMask: /\.xlsx$/ }, logger }) await emailManager.connect() const emails = await emailManager.getEmails() for (const email of emails) { fileManager.saveAttachment(email.buffer, email.attachment) } await emailManager.sendEmail({ to: 'recipient@example.com', subject: 'Обработка завершена', text: 'Данные успешно обработаны' }) await emailManager.disconnect() ``` ### ParserXLS Парсинг Excel файлов (.xlsx). **Опции:** - `data` - Buffer с данными Excel файла - `fileName` - имя файла - `usedSheet` - название листа для парсинга - `logger` - логгер для вывода сообщений **Методы:** - `getColumnNames()` - получение названий колонок - `parse(options)` - парсинг данных в объекты **Пример:** ```typescript const parser = new ParserXLS({ data: excelBuffer, fileName: 'data.xlsx', usedSheet: 'Sheet1', logger }) // Получение названий колонок const columns = parser.getColumnNames() console.log('Колонки:', columns) // Парсинг данных const parsedData = await parser.parse({ fieldNames: ['name', 'age', 'email', null], // null игнорирует колонку initDataRow: (fileName) => ({ source: fileName, processed: false }) }) console.log('Данные:', parsedData) ``` ### Validator Валидация Excel файлов перед обработкой. **Опции:** - `validationRules` - массив правил валидации - `usedSheet` - название листа для валидации - `logger` - логгер для вывода сообщений **Типы правил:** - `sheetExists` - проверка существования листа - `sheetHasData` - проверка наличия данных - `columnHasName` - проверка названия колонки - `columnHasType` - проверка типа данных в колонке **Пример:** ```typescript const validator = new Validator({ validationRules: [ { type: 'sheetExists' }, { type: 'sheetHasData' }, { type: 'columnHasName', options: [0, 'Name'] }, { type: 'columnHasType', options: [1, 'number'] } ], usedSheet: 'Sheet1', logger }) const errors = await validator.validate(excelBuffer) if (errors) { console.error('Ошибки валидации:', errors) } else { console.log('Файл прошел валидацию') } ``` ### ApiManager Работа с HTTP API. **Опции:** - `baseUrl` - базовый URL API - `headers` - заголовки запросов - `method` - HTTP метод (по умолчанию GET) - `logger` - логгер для вывода сообщений **Методы:** - `fetch(params?)` - выполнение HTTP запроса **Пример:** ```typescript const apiManager = new ApiManager({ baseUrl: 'https://api.example.com', headers: { 'Authorization': 'Bearer your-token', 'Content-Type': 'application/json' }, method: 'GET', logger }) // GET запрос с параметрами const data = await apiManager.fetch({ page: 1, limit: 100, search: 'test' }) // POST запрос (изменяем метод) apiManager['method'] = 'POST' const result = await apiManager.fetch({ name: 'New Item' }) ``` ### JsonMapper Преобразование JSON данных. **Опции:** - `nameRules` - правила переименования полей - `valueRules` - правила преобразования значений - `excludeRules` - поля для исключения - `dataExpansion` - функция для расширения данных **Методы:** - `map(data)` - преобразование данных **Пример:** ```typescript const jsonMapper = new JsonMapper({ nameRules: { 'user_name': 'name', 'user_age': 'age' }, valueRules: { 'age': (value) => Number(value), 'email': (value) => String(value).toLowerCase() }, excludeRules: ['password', 'secret'], dataExpansion: (data) => ({ ...data, processedAt: new Date().toISOString() }) }) const originalData = { user_name: 'John', user_age: '30', email: 'JOHN@EXAMPLE.COM', password: 'secret123' } const mappedData = jsonMapper.map(originalData) console.log(mappedData) // { name: 'John', age: 30, email: 'john@example.com', processedAt: '2024-01-01T12:00:00.000Z' } ``` ## Полный пример использования Пример скрипта, который получает данные из email, валидирует Excel файлы, парсит их и сохраняет результат: ```typescript import { EmailManager, FileManager, Logger, ParserXLS, Validator, JsonMapper } from '@set2333/upload-script-helpers' async function processEmailAttachments() { const logger = new Logger({ displayTypes: ['console', { type: 'file', options: { logFile: 'process.log' } }] }) const fileManager = new FileManager({ workDirectory: './processed-data', logger }) const emailManager = new EmailManager({ credentials: { host: 'imap.gmail.com', port: 993, user: process.env.EMAIL_USER!, pass: process.env.EMAIL_PASS!, smtpHost: 'smtp.gmail.com', smtpPort: 587, smtpUser: process.env.EMAIL_USER!, smtpPass: process.env.EMAIL_PASS! }, searchRules: { since: '2024-01-01', before: '2024-12-31', attachmentMask: /\.xlsx$/ }, logger }) const validator = new Validator({ validationRules: [ { type: 'sheetExists' }, { type: 'sheetHasData' }, { type: 'columnHasName', options: [0, 'Name'] }, { type: 'columnHasType', options: [1, 'number'] } ], usedSheet: 'Data', logger }) const jsonMapper = new JsonMapper({ nameRules: { 'Name': 'name', 'Age': 'age', 'Email': 'email' }, valueRules: { 'age': (value) => Number(value), 'email': (value) => String(value).toLowerCase() }, dataExpansion: (data) => ({ ...data, processedAt: new Date().toISOString(), source: 'email-attachment' }) }) try { logger.start('Обработка email вложений') await emailManager.connect() const emails = await emailManager.getEmails() logger.log(`Найдено писем с вложениями: ${emails.length}`) for (const email of emails) { logger.log(`Обрабатываем файл: ${email.attachment}`) // Валидация файла const validationErrors = await validator.validate(email.buffer) if (validationErrors) { logger.error(`Файл ${email.attachment} не прошел валидацию:`, validationErrors) continue } // Парсинг Excel файла const parser = new ParserXLS({ data: email.buffer, fileName: email.attachment, usedSheet: 'Data', logger }) const parsedData = await parser.parse({ fieldNames: ['name', 'age', 'email'] }) // Преобразование данных const mappedData = parsedData.map(row => jsonMapper.map(row)) // Сохранение результата const resultFileName = `processed_${email.attachment.replace('.xlsx', '.json')}` fileManager.saveJSONFile(mappedData, resultFileName) logger.log(`Файл ${email.attachment} успешно обработан`) } await emailManager.sendEmail({ to: 'admin@example.com', subject: 'Обработка завершена', text: `Обработано файлов: ${emails.length}` }) await emailManager.disconnect() logger.end('Обработка email вложений') } catch (error) { logger.error('Ошибка при обработке:', error) throw error } } // Запуск скрипта processEmailAttachments().catch(console.error) ``` ## Готовый к использованию пакет Пакет поставляется уже скомпилированным и готовым к использованию: - `dist/index.js` - CommonJS версия (минифицированная) - `dist/index.mjs` - ES модули версия (минифицированная) - `dist/index.d.ts` - TypeScript типы ## Разработка ```bash # Установка зависимостей npm install # Сборка npm run build # Разработка с отслеживанием изменений npm run dev # Проверка типов npm run typecheck # Запуск тестов npm test # Запуск тестов один раз npm run test:run # Проверка линтера npm run lint # Автоисправление ошибок линтера npm run lint:fix # Запуск pre-commit проверок npm run pre-commit # Запуск pre-publish проверок npm run pre-publish ``` ## Git хуки Проект использует Husky для автоматических проверок: ### Pre-commit хук Автоматически запускается перед каждым коммитом: - Исправляет ошибки ESLint в измененных файлах - Проверяет типы TypeScript - Запускает `lint-staged` ### Pre-publish хук Автоматически запускается перед публикацией: - Проверяет код линтером - Проверяет типы TypeScript - Запускает все тесты - Собирает проект Хуки настроены в `.husky/` директории и автоматически устанавливаются при `npm install`. ## Публикация ```bash # Публикация с поднятием patch версии (1.0.0 -> 1.0.1) npm run publish:patch # Публикация с поднятием minor версии (1.0.0 -> 1.1.0) npm run publish:minor # Публикация с поднятием major версии (1.0.0 -> 2.0.0) npm run publish:major ``` Скрипт автоматически: - Поднимает версию в package.json - Собирает проект - Публикует в npm > **Примечание**: Git команды убраны из скрипта. Версию нужно обновлять в git вручную. ## Поддерживаемые форматы - CommonJS (`require`) - ES модули (`import`) - TypeScript типы