Helper library for upload scripts
npm install @set2333/upload-script-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')
`
Опции:
- 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('Обработка завершена')
`
Опции:
- 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')
`
Опции:
- 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()
`
Опции:
- 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)
`
Опции:
- 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('Файл прошел валидацию')
}
`
Опции:
- baseUrl - базовый URL APIheaders
- - заголовки запросов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' })
`
Опции:
- 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
Git хуки
Проект использует Husky для автоматических проверок:
$3
Автоматически запускается перед каждым коммитом:
- Исправляет ошибки ESLint в измененных файлах
- Проверяет типы TypeScript
- Запускает lint-staged$3
Автоматически запускается перед публикацией:
- Проверяет код линтером
- Проверяет типы 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`)