@dimerso/farol
v0.2.0
Published
Cliente TypeScript oficial de la API de Farol (facturación electrónica y gestión para pymes en Costa Rica).
Maintainers
Readme
@dimerso/farol
Cliente TypeScript oficial de la API de Farol. Sin dependencias; funciona en Node ≥ 18, Deno, Bun y Workers (usa fetch y WebCrypto).
npm install @dimerso/farolimport { Farol } from '@dimerso/farol';
const farol = new Farol({ apiKey: process.env.FAROL_API_KEY! });
const me = await farol.me();
console.log(me.tenant?.name, me.apiKey.environment, me.rateLimits);
// Clientes y productos, con paginación por cursor
for await (const customer of farol.customers.iterate({ isActive: true })) {
console.log(customer.name);
}
// Emitir un tiquete (202: queda encolado hacia Hacienda)
const doc = await farol.documents.create(
{
type: '04',
lines: [
{
cabysCode: '0702000000100',
description: 'Tomate',
quantity: 2,
unitPrice: 500,
taxRate: 0.01,
isProduct: true,
},
],
payment: { method: '01', condition: '01' },
},
{ idempotencyKey: 'pedido-1234' }, // reusá la misma clave al reintentar
);
// Estado final: por webhook o consultando
const detail = await farol.documents.get(doc.id);
if (detail.status === 'ACCEPTED') {
const xml = await farol.documents.xml(doc.id);
}Errores
Toda respuesta no-2xx lanza FarolError con code estable (unauthorized, forbidden_scope, validation_failed, rate_limited, fiscal_config_missing, …), status, requestId, problem.errors por campo y retryAfterSeconds cuando aplica.
import { FarolError } from '@dimerso/farol';
try {
await farol.customers.create({
name: 'Ana',
identification: { type: '01', number: '101110111' },
});
} catch (e) {
if (e instanceof FarolError && e.code === 'conflict') {
/* ya existe */
}
}Webhooks
import { verifySignature } from '@dimerso/farol';
app.post('/farol/webhook', express.raw({ type: '*/*' }), async (req, res) => {
const ok = await verifySignature(
process.env.FAROL_WEBHOOK_SECRET!,
req.body.toString('utf8'),
req.header('Farol-Signature'),
);
if (!ok) return res.sendStatus(400);
const event = JSON.parse(req.body.toString('utf8'));
// event.id (dedupe), event.event, event.data
res.sendStatus(200);
});Verificá siempre sobre el cuerpo crudo (no re-serialices el JSON). Tolerancia de 5 minutos por defecto.
Entornos
Las llaves sk_test_ leen y escriben todo, pero no emiten documentos fiscales reales (fiscal_config_missing). Especificación completa: https://farol.dimerso.com/api/v1/openapi.json.
