Библиотека для JavaScript
Конвертация, сжатие и обработка файлов из вашего кода. Один вызов делает весь путь: загрузить, поставить задачу, дождаться, отдать результат.
Установка
Работает везде, где работает fetch: Node 20 и новее, Bun, Deno, среды на границе сети. Ничего из node: пакет не импортирует, и подменять сборщику нечего.
npm install @formatika/sdkПервый вызов
Ключ не нужен: без него действует та же бесплатная суточная норма, что и у человека в браузере.
import { readFile, writeFile } from 'node:fs/promises'
import { Formatika } from '@formatika/sdk'
const formatika = new Formatika()
const result = await formatika.run({
tool: 'image.convert',
files: { filename: 'photo.heic', data: await readFile('photo.heic') },
params: { format: 'webp', quality: 82 },
})
for (const file of result.files) {
await writeFile(file.filename, await file.download())
}Ссылки на результат подписаны и живут недолго — они сделаны, чтобы скачать сейчас, а не чтобы хранить.
Ключ и лимиты
Ключ увеличивает суточную норму, а работа сверх неё оплачивается кредитами. Создаётся в аккаунте.
const formatika = new Formatika({ apiKey: process.env.FORMATIKA_API_KEY })FORMATIKA_API_KEY подхватывается из окружения сам, поэтому передавать apiKey нужно только если ключ лежит где-то ещё.
Инструменты и их параметры: 43
Список приходит с сервиса, а не зашит в пакет: инструмент, добавленный на сайте, появляется здесь без нового выпуска библиотеки. В params лежит та самая схема, по которой сервер проверяет запрос, — её можно скормить генератору форм, валидатору или агенту, не переписывая руками.
const tools = await formatika.tools()
// { id: 'image.convert', title, description, accept, maxFiles, params: <JSON Schema> }Прогресс, отмена и таймауты
Отмена останавливает работу и на сервере, а не только ожидание: идущее перекодирование прерывается за секунду.
const controller = new AbortController()
setTimeout(() => controller.abort(), 30_000)
const result = await formatika.run({
tool: 'video.compress',
files: bigVideo,
params: { targetMB: 24 },
onProgress: (percent) => console.log(percent),
signal: controller.signal,
})То же происходит, когда кончается timeoutMs — по умолчанию три минуты. Никто не жжёт процессор ради результата, которого уже не ждут.
Ошибки
У провалившейся задачи поднимается её собственный код, а не код HTTP: запрос прошёл, работа — нет.
import { FormatikaError } from '@formatika/sdk'
try {
await formatika.run({ tool: 'image.convert', files, params: { format: 'webp' } })
} catch (error) {
if (error instanceof FormatikaError) {
error.code // 'RATE_LIMITED' | 'QUOTA_EXCEEDED' | 'UNSUPPORTED_FORMAT' | …
error.retryable // имеет ли смысл повторять
error.retryAfterSeconds
}
}Повторы библиотека не делает намеренно. Повторить задачу — значит создать вторую и списать второй раз; клиент, который делает это молча, однажды выставит счёт за то, чего не просили. Поэтому наружу отдаются retryable и retryAfterSeconds, а решение остаётся за вами.
По шагам
run — это весь путь целиком. Шаги доступны и по отдельности, когда нужно держать их самому: своя очередь, прогресс в базе, задача, живущая дольше процесса.
const upload = await formatika.upload('pdf.merge', file)
const job = await formatika.createJob({ tool: 'pdf.merge', uploadIds: [upload.id] })
const done = await formatika.wait(job.id)
const bytes = await formatika.download(done.files[0])
await formatika.cancel(job.id)Что происходит с файлами
Файл обрабатывается и удаляется, результат живёт ограниченное время и тоже уходит. Ничего не остаётся для обучения, анализа или перепродажи — в этом смысл сервиса, а не сноска к нему.