# dty-fy

> Librería completa para gestionar Documentos Tributarios Electrónicos (DTE) del SII de Chile. Soporta Facturas, Boletas, Notas de Crédito/Débito, Guías de Despacho y documentos de Exportación.

Latest version **0.5.1** (published 2026-09-24) · SEE LICENSE IN LICENSE license · 0 weekly downloads

## Install

```sh
npm install dty-fy
pnpm add dty-fy
yarn add dty-fy
bun add dty-fy
```

## Health

**Score 70/100 (B)** — status: active.

Positive: has types; esm support; no vulnerabilities; recently updated; high maintenance score; high quality score.

Warnings: low downloads; pre 1.0.

## Facts

| | |
|---|---|
| Version | 0.5.1 |
| Published | 2026-09-24 |
| First published | 2026-05-26 |
| Weekly downloads | 0 |
| License | SEE LICENSE IN LICENSE |
| TypeScript types | bundled |
| Module format | ESM + CommonJS |
| Node | >=18.0.0 |
| Dependencies | 5 |
| Unpacked size | 385.1 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| Author | bm0x |
| Maintainers | bm0x |
| Keywords | chile, sii, dte, factura, boleta, factura-electronica, boleta-electronica, nota-credito, nota-debito, guia-despacho, impuestos, tributario, xml, firma-digital, timbre-electronico |

## Links

- npm: https://www.npmjs.com/package/dty-fy
- Repository: https://github.com/bm0x/dty-fy
- Homepage: https://github.com/bm0x/dty-fy#readme
- Issues: https://github.com/bm0x/dty-fy/issues
- npm.io page: https://npm.io/package/dty-fy

## Dependencies (5)

- [bwip-js](https://npm.io/package/bwip-js.md) ^4.10.1
- [node-forge](https://npm.io/package/node-forge.md) ^1.3.1
- [xml-crypto](https://npm.io/package/xml-crypto.md) ^6.0.0
- [xmlbuilder2](https://npm.io/package/xmlbuilder2.md) ^4.0.3
- [fast-xml-parser](https://npm.io/package/fast-xml-parser.md) ^5.8.0

## Alternatives

- [babylon](https://npm.io/package/babylon.md) — 5.1M weekly downloads
- [csscolorparser](https://npm.io/package/csscolorparser.md) — 3.7M weekly downloads
- [expr-eval-fork](https://npm.io/package/expr-eval-fork.md) — 1.5M weekly downloads
- [@leeoniya/ufuzzy](https://npm.io/package/@leeoniya/ufuzzy.md) — 247.7K weekly downloads
- [xml-parser](https://npm.io/package/xml-parser.md) — 78.4K weekly downloads

## Recent versions

- 0.5.1 (latest) — 2026-09-24
- 0.5.0 — 2026-09-23
- 0.4.0 — 2026-05-26
- 0.3.3 — 2026-05-26
- 0.3.2 — 2026-05-26
- 0.3.1 — 2026-05-26
- 0.3.0 — 2026-05-26

## README

# dty-fy

[![npm version](https://img.shields.io/npm/v/dty-fy)](https://www.npmjs.com/package/dty-fy)
[![License: EULA](https://img.shields.io/badge/License-EULA-blue)](#licencia)
[![Node](https://img.shields.io/badge/node-%3E%3D18-brightgreen)](https://nodejs.org)
[![TypeScript](https://img.shields.io/badge/TypeScript-5.6-blue)](https://www.typescriptlang.org)

Libreria completa para gestionar **Documentos Tributarios Electronicos (DTE)** ante el **Servicio de Impuestos Internos (SII) de Chile**.

Soporta los 12 tipos de DTE: facturas, boletas, notas de credito/debito, guias de despacho y documentos de exportacion.

---

## Tabla de Contenidos

- [Instalacion](#instalacion)
- [Inicio Rapido](#inicio-rapido)
- [Arquitectura](#arquitectura)
- [Certificados Digitales](#certificados-digitales)
- [Gestion de CAF](#gestion-de-caf)
- [Constructor de DTE](#constructor-de-dte)
- [Timbre Electronico y Codigo PDF417](#timbre-electronico-y-codigo-pdf417)
- [Cliente SII](#cliente-sii)
- [Funciones Utiles](#funciones-utiles)
- [Constantes y Tipos](#constantes-y-tipos)
- [Manejo de Errores](#manejo-de-errores)
- [Ambientes](#ambientes)
- [Licencia](#licencia)

---

## Instalacion

```bash
npm install dty-fy
```

### Requisitos

- Node.js 18+
- Certificado digital (.pfx/.p12) de una CA acreditada por el SII
- Archivos CAF (Codigo de Autorizacion de Folios) entregados por el SII

### Formatos de Modulo

La libreria distribuye tanto ESM como CommonJS:

```typescript
// ESM (recomendado)
import { DteBuilder, SiiClient } from 'dty-fy';

// CommonJS
const { DteBuilder, SiiClient } = require('dty-fy');
```

---

## Inicio Rapido

```typescript
import { SiiClient, DteBuilder, CafManager, CertificateLoader } from 'dty-fy';

// 1. Cargar certificado digital
const cert = await CertificateLoader.fromPfx('./certificado.pfx', 'password');

// 2. Cargar folios autorizados (CAF)
const cafManager = new CafManager();
await cafManager.loadCaf('./caf-factura-33.xml');

// 3. Configurar cliente SII
const sii = new SiiClient({
  environment: 'certification',
  certificate: cert,
  rutSender: '11111111-1',
  rutCompany: '76543210-3',
  fechaResolucion: '2024-01-15',
  numeroResolucion: 0,
});

// 4. Construir una Factura Electronica (TipoDTE 33)
const factura = new DteBuilder()
  .tipo(33)
  .folio(cafManager.nextFolio(33))
  .emisor({
    rut: '76543210-3',
    razonSocial: 'Mi Empresa SpA',
    giro: 'Desarrollo de Software',
    acteco: 620200,
    direccion: 'Av. Providencia 1234',
    comuna: 'Providencia',
  })
  .receptor({
    rut: '87654321-4',
    razonSocial: 'Cliente Ejemplo Ltda',
    giro: 'Comercio',
    direccion: 'Los Leones 999',
    comuna: 'Providencia',
  })
  .addDetalle({ nombre: 'Servicio de desarrollo', cantidad: 1, precioUnitario: 500000 })
  .addDetalle({ nombre: 'Hosting anual', cantidad: 12, unidad: 'mes', precioUnitario: 15000 })
  .formaPago('credito')
  .build();

// 5. Firmar, timbrar y enviar al SII
const result = await sii.emitir(factura, cafManager);

if (result.success) {
  console.log(`DTE enviado! TrackID: ${result.trackId}`);
  console.log(`Folio: ${result.folio}`);

  const estado = await sii.consultarEstadoEnvio(result.trackId!);
  console.log(`Estado: ${estado.status} - ${estado.glosa}`);
} else {
  console.error(`Error: ${result.error}`);
}
```

---

## Arquitectura

```
┌─────────────────────────────────────────────────────────┐
│                     SiiClient                           │
│  (orquestador: autenticacion, firma, envio, consulta)  │
└──────┬───────────────────────────────────────┬─────────┘
       │                                       │
       ▼                                       ▼
┌──────────────┐  ┌──────────┐  ┌──────────────────────┐
│  DteBuilder  │  │ XmlSigner│  │  CertificateLoader    │
│  (fluido)    │  │(XMLDSig) │  │  (.pfx, .pem, base64) │
└──────┬───────┘  └──────────┘  └──────────────────────┘
       │              │                    │
       ▼              ▼                    ▼
┌──────────┐  ┌──────────────┐  ┌──────────────────────┐
│ CafManager│  │ TED Generator│  │  SII Auth & Sender   │
│ (folios)  │  │(Timbre Elec)│  │  (seed, token, POST)  │
└──────────┘  └──────────────┘  └──────────────────────┘
```

---

## Certificados Digitales

El certificado digital se obtiene a traves de una **Autoridad Certificadora (CA) acreditada** por el SII, no directamente desde el SII. La CA entrega un archivo `.pfx` (o `.p12`) que contiene la llave privada y el certificado X.509, protegido por una contrasena.

### Metodos de Carga

```typescript
import { CertificateLoader } from 'dty-fy';

// Desde archivo .pfx (el mas comun)
const cert = await CertificateLoader.fromPfx('./cert.pfx', 'password');

// Desde Buffer (base de datos, S3, cloud storage)
const cert = CertificateLoader.fromPfxBuffer(buffer, 'password');

// Desde string base64 (variables de entorno, serverless, CI/CD)
const cert = CertificateLoader.fromPfxBase64(process.env.CERT_PFX_B64!, process.env.CERT_PASSWORD!);

// Desde archivos PEM separados
const cert = await CertificateLoader.fromPem('./cert.pem', './key.pem');

// Desde strings PEM en memoria
const cert = CertificateLoader.fromPemStrings(certPem, keyPem);
```

### Utilidades del Certificado

```typescript
import {
  isCertificateValid,
  daysUntilCertExpiry,
  getRutFromCertificate,
  getCertificateSummary,
} from 'dty-fy';

const cert = await CertificateLoader.fromPfx('./cert.pfx', 'pass');

isCertificateValid(cert);                // boolean — esta vigente?
daysUntilCertExpiry(cert);               // number | null — dias restantes
getRutFromCertificate(cert);             // string | null — RUT embebido por la CA
getCertificateSummary(cert);             // string — resumen legible
```

---

## Gestion de CAF

`CafParser` y `CafManager` administran la ingesta, validación criptográfica y asignación de folios desde los archivos CAF (Código de Autorización de Folios) entregados por el SII.

### Parseo y Validación Criptográfica (`CafParser`)

`CafParser` valida que el CAF coincida con el RUT emisor, tipo de DTE, rango de folios ($D \le F \le H$) y verifica la firma digital `<FRMA>` del SII sobre `<DA>`:

```typescript
import { CafParser } from 'dty-fy';

// Parsear desde string XML o Buffer (ej. subido vía API o leído de S3/GCS)
const cafData = CafParser.fromXml(xmlBuffer, {
  expectedRut: '76543210-3',       // Valida RUT emisor
  expectedTipoDte: 33,              // Valida TipoDTE
  targetFolio: 15,                  // Valida que el folio esté en el rango autorizado
  verifySignature: true,            // Verifica firma <FRMA> con clave pública SII
  siiPublicKey: process.env.SII_CAF_PUBKEY,
});

// O parsear directamente desde archivo en disco
const cafData = await CafParser.fromFile('./caf-33.xml');
```

### Asignación y Ciclo de Vida de Folios (`CafManager`)

```typescript
import { CafManager } from 'dty-fy';

const caf = new CafManager();

// Cargar desde archivo XML
await caf.loadCaf('./caf-33.xml');

// Cargar desde string XML
caf.addCaf(xmlString);

// Cargar datos CAF pre-parseados directamente
caf.addCafData(cafData);

// Obtener siguiente folio disponible (lanza CafFolioExhaustedError si se agotan)
const folio = caf.nextFolio(33);

// Consultar folios restantes
const remaining = caf.remainingFolios(33);

// Obtener datos CAF para un folio especifico
const cafData = caf.getCaf(33, folio);

// Verificar y marcar uso manualmente
caf.isFolioUsed(33, folio);       // boolean
caf.markFolioUsed(33, folio);     // void

// Listar todos los CAF cargados para un tipo de DTE
const cafs = caf.getCafsForType(33);

// Reiniciar todo el estado
caf.clearAll();
```

---

## Constructor de DTE

`DteBuilder` proporciona una API fluida (builder pattern) para construir documentos DTE. Todos los metodos son encadenables.

### Metodos

| Metodo | Parametros | Descripcion |
|--------|-----------|-------------|
| `tipo` | `code: TipoDteCode` | Establecer tipo de DTE (33, 39, 61, etc.) |
| `folio` | `n: number` | Establecer numero de folio |
| `fechaEmision` | `date: string \| Date` | Fecha de emision (default: hoy) |
| `fechaVencimiento` | `date: string \| Date` | Fecha de vencimiento (facturas credito) |
| `formaPago` | `tipo: 'contado' \| 'credito' \| 'gratis'` | Establecer forma de pago |
| `montoBruto` | `bruto: boolean` | Activar montos brutos (requerido para boletas) |
| `emisor` | `data: EmisorInput` | Datos del emisor |
| `receptor` | `data: ReceptorInput` | Datos del receptor |
| `indTraslado` | `code: number` | Establecer indicador de traslado (obligatorio para DTE 52) |
| `tipoDespacho` | `code: number` | Establecer tipo de despacho (para DTE 52: 1, 2 o 3) |
| `tpoImpresion` | `code: number` | Establecer tipo de impresión (opcional) |
| `transporte` | `data: TransporteInput` | Establecer datos logísticos del transporte terrestre (DTE 52) |
| `addDetalle` | `data: DetalleInput` | Agregar linea de detalle |
| `addReferencia` | `data: ReferenciaInput` | Agregar referencia a otro documento (requerido para NC/ND) |
| `addDescuento` | `data: DescuentoRecargoInput` | Agregar descuento o recargo global |
| `build` | — | Validar y retornar `DteDocument` |

### Tipos de Entrada

```typescript
interface EmisorInput {
  rut: string;
  razonSocial: string;
  giro: string;
  acteco: number;
  direccion: string;
  comuna: string;
  ciudad?: string;
  telefono?: string;
  correo?: string;
  sucursal?: string;
}

interface ReceptorInput {
  rut: string;
  razonSocial?: string;
  giro?: string;
  direccion?: string;
  comuna?: string;
  ciudad?: string;
  contacto?: string;
  correo?: string;
}

interface DetalleInput {
  nombre: string;
  descripcion?: string;
  cantidad?: number;        // default: 1
  unidad?: string;          // default: 'unidad'
  precioUnitario: number;
  montoItem?: number;
  descuentoPct?: number;
  descuentoMonto?: number;
  exento?: boolean;
  codigos?: Array<{ tipo: string; valor: string }>;
}

interface ReferenciaInput {
  tipoDocRef: number;
  folioRef: number;
  fechaRef: string;
  codigoRef?: number;       // 1=anula, 2=corrige texto, 3=corrige montos
  razon?: string;
}

interface DescuentoRecargoInput {
  tipo: 'descuento' | 'recargo';
  glosa?: string;
  tipoValor: 'porcentaje' | 'monto';
  valor: number;
}

interface ChoferInput {
  rut?: string;
  nombre?: string;
}

interface TransporteInput {
  patente?: string;
  patenteCarro?: string;
  rutTrans?: string;
  chofer?: ChoferInput;
  fchSalida?: string | Date;
  hraSalida?: string;
  fchLlegada?: string | Date;
  dirDest?: string;
  cmnaDest?: string;
  ciudadDest?: string;
}
```

### Ejemplos

**Factura con descuento global:**
```typescript
const factura = new DteBuilder()
  .tipo(33)
  .folio(1)
  .emisor(emisorData)
  .receptor(receptorData)
  .addDetalle({ nombre: 'Producto A', cantidad: 10, precioUnitario: 5000 })
  .addDetalle({ nombre: 'Producto B', cantidad: 5, precioUnitario: 8000 })
  .addDescuento({ tipo: 'descuento', tipoValor: 'porcentaje', valor: 10, glosa: 'Volumen' })
  .build();
// IVA se calcula sobre el neto posterior al descuento
```

**Nota de Credito referenciando una factura:**
```typescript
const notaCredito = new DteBuilder()
  .tipo(61)
  .folio(cafManager.nextFolio(61))
  .emisor(emisorData)
  .receptor(receptorData)
  .addDetalle({ nombre: 'Servicio web', cantidad: 1, precioUnitario: 500000 })
  .addReferencia({
    tipoDocRef: 33,
    folioRef: 123,
    fechaRef: '2024-03-15',
    codigoRef: 1,
    razon: 'Anulacion por devolucion',
  })
  .build();
```

**Boleta Electronica con montos brutos:**
```typescript
const boleta = new DteBuilder()
  .tipo(39)
  .folio(cafManager.nextFolio(39))
  .emisor({ rut: '76543210-3', razonSocial: 'Mi Tienda', giro: 'Venta al detalle', acteco: 471100, direccion: 'Calle 1', comuna: 'Santiago' })
  .receptor({ rut: '66666666-6', razonSocial: 'Consumidor Final' })
  .montoBruto(true)
  .addDetalle({ nombre: 'Cafe Latte', cantidad: 2, precioUnitario: 3500 })
  .addDetalle({ nombre: 'Croissant', cantidad: 1, precioUnitario: 2500 })
  .build();
// Los montos de boleta incluyen IVA (MntBruto=true)
```

**Guía de Despacho (DTE 52) con datos de transporte:**
```typescript
const guiaDespacho = new DteBuilder()
  .tipo(52)
  .folio(cafManager.nextFolio(52))
  .emisor(emisorData)
  .receptor(receptorData)
  .indTraslado(5) // 5 = Traslados internos (obligatorio para DTE 52)
  .transporte({
    patente: 'AA1122',
    patenteCarro: 'BB3344',
    rutTrans: '77777777-7',
    chofer: {
      rut: '11111111-1',
      nombre: 'Juan Pérez'
    },
    dirDest: 'Av. Vitacura 5000',
    cmnaDest: 'Vitacura',
    ciudadDest: 'Santiago'
  })
  .addDetalle({ nombre: 'Pallets de madera', cantidad: 50, precioUnitario: 3500 })
  .build();
```

---

## Timbre Electronico y Codigo PDF417

El Timbre Electrónico DTE (TED) y su representación bidimensional PDF417 constituyen la firma gráfica y mecanismo de verificación offline exigido por el SII (Resolución Ex. SII N° 11 de 2003).

### Generación de Código PDF417 (`renderPdf417`)

Genera el código de barras PDF417 conforme al estándar del SII: nivel de corrección de error ECL 5 y ancho de 10 a 14 columnas.

```typescript
import { renderPdf417 } from 'dty-fy';

// Renderizar SVG vectorial (ideal para facturas en PDF, impresión térmica o web)
const svg = await renderPdf417(tedXml, {
  format: 'svg',
  columns: 12,                  // 10 a 14 (default: 12)
  errorCorrectionLevel: 5,      // Estándar SII: nivel 5 (default: 5)
  scale: 2,
});

// Renderizar PNG en Buffer (ideal para canvas o guardado directo a archivo)
const pngBuffer = await renderPdf417(tedXml, {
  format: 'png',
  columns: 12,
  errorCorrectionLevel: 5,
  scale: 3,
});
```

### Generación y Firma de TED

```typescript
import { generateTed, buildTedXml, signTed, verifyTed } from 'dty-fy';

// Generar estructura TED a partir del documento y datos CAF
const ted = generateTed(documento, cafData);

// Construir XML del TED
const tedXml = buildTedXml(ted);

// O firmar y verificar manualmente con clave privada CAF y codificación ISO-8859-1
const signedTed = signTed(rawTedXml, cafData.privateKey);
const isValid = verifyTed(signedTed, cafData.publicKey);
```

---

## Cliente SII

`SiiClient` orquesta el ciclo de vida completo del DTE: autenticacion, generacion de TED, firma XML, construccion del sobre de envio y envio al SII.

### Constructor

```typescript
import { SiiClient } from 'dty-fy';

const sii = new SiiClient({
  environment: 'certification' | 'production',
  certificate: certificateData,
  rutSender: string,      // RUT de la persona/sistema que envia
  rutCompany: string,     // RUT de la empresa (emisor)
  fechaResolucion?: string, // YYYY-MM-DD (default: vacio)
  numeroResolucion?: number, // 0 para certificacion (default: 0)
});
```

### Metodos

| Metodo | Firma | Descripcion |
|--------|-------|-------------|
| `authenticate` | `(): Promise<string>` | Obtener y cachear token de sesion SII (gestión automática de TTL y concurrencia) |
| `emitir` | `(doc: DteDocument, caf: CafManager): Promise<EmitirResult>` | Flujo completo individual: TED -> firma DTE -> sobre -> envio |
| `emitirBatch` | `(docs: DteDocument[], caf: CafManager): Promise<{ trackId?: string; results: EmitirResult[] }>` | Emisión en lote dentro de un único sobre (hasta 2000 DTEs) |
| `consultarEstadoEnvio` | `(trackId: string): Promise<EstadoEnvio>` | Consultar estado de envio por TrackID (inmediato) |
| `pollEnvio` | `(trackId: string, options?: Partial<PollTrackIdOptions>): Promise<EstadoEnvio>` | Sondeo automático de TrackID con backoff exponencial y jitter |
| `consultarEstadoDte` | `(tipoDte, folio, fechaEmision, montoTotal, rutReceptor): Promise<EstadoDte>` | Consultar estado de un DTE especifico |

### Sondeo de Envío con Backoff (`pollEnvio`)

El SII procesa los envíos de forma asíncrona. `pollEnvio` realiza consultas periódicas con retroceso exponencial (*exponential backoff*) y fluctuación (*jitter*) hasta obtener un estado terminal (`EPR`, `RCT`, `RFL`, `RFR`, `RSC`):

```typescript
const estado = await sii.pollEnvio(result.trackId!, {
  maxAttempts: 10,
  initialDelayMs: 3000,
  backoffFactor: 1.5,
  maxDelayMs: 60000,
  onAttempt: (attempt, delayMs) => {
    console.log(`Intento ${attempt}: esperando ${delayMs}ms...`);
  },
});

console.log(`Estado final: ${estado.status} - ${estado.glosa}`);
```

### Gestión de Tokens de Sesión (`TokenManager`)

`TokenManager` encapsula la obtención y renovación de tokens con el SII:
- **TTL de 50 minutos** (los tokens del SII expiran tras 60 minutos de inactividad).
- **Deduplicación concurrente**: múltiples solicitudes simultáneas comparten la misma promesa de autenticación para evitar saturar el endpoint de semillas.

```typescript
import { TokenManager } from 'dty-fy';

const tokenManager = new TokenManager(cert, 'certification', 50);
const token = await tokenManager.getToken(); // Reutiliza el token activo o renueva si caducó
```

### Resultado de Emision

```typescript
interface EmitirResult {
  success: boolean;
  trackId?: string;     // TrackID del SII (en exito)
  folio: number;
  tipoDte: TipoDteCode;
  xml: string;          // XML del sobre firmado
  error?: string;       // Mensaje de error (en fallo)
}
```

### Resultados de Estado

```typescript
interface EstadoEnvio {
  status: string;       // 'SOK' | 'CRT' | 'EPR' | 'RSC' | 'RFR' | 'RCT' | 'RPS'
  glosa: string;        // Descripcion legible
  trackId: string;
  numDtes?: number;
  informados?: number;
  aceptados?: number;
  rechazados?: number;
  reparos?: number;
}

interface EstadoDte {
  status: string;       // 'DOK' | 'RCH' | 'RPR' | 'DNK'
  glosa: string;
  tipoDte: number;
  folio: number;
  fechaEmision?: string;
  rutEmisor?: string;
  rutReceptor?: string;
  montoTotal?: number;
  errorCode?: string;
}
```

---

## Funciones Utiles

### Validacion y Formateo de RUT

```typescript
import { validateRut, formatRut, formatRutPretty, cleanRut, calculateDv } from 'dty-fy';

validateRut('11111111-1');      // true
validateRut('11111111-2');      // false
formatRut('111111111');         // '11111111-1'
formatRutPretty('111111111');   // '11.111.111-1'
cleanRut('11.111.111-1');       // '11111111-1'
calculateDv('11111111');        // '1'
```

### Calculos de Impuestos

```typescript
import { calculateIva, calculateNetoFromBruto, calculateTotals, calculateMontoItem } from 'dty-fy';

calculateIva(100000);              // 19000 (IVA 19%)
calculateIva(100000, 10);          // 10000 (tasa personalizada)
calculateNetoFromBruto(119000);    // 100000
calculateMontoItem(10, 5000);      // 50000
calculateMontoItem(10, 5000, 10);  // 45000 (10% descuento)
```

### Construccion XML (Bajo Nivel)

```typescript
import { buildDocumentoXml, buildEnvioDteXml, buildEnvioBoletaXml } from 'dty-fy';

const docXml: string = buildDocumentoXml(dteDocument);
const envelope: string = buildEnvioDteXml([signedDocXml], caratula);
const boletaEnvelope: string = buildEnvioBoletaXml([signedBoletaXml], caratula);
```

### Parseo XML

```typescript
import { parseSiiResponse, parseUploadResponse } from 'dty-fy';

const result = parseSiiResponse(siiXmlResponse);        // { estado, seed?, token?, glosa? }
const upload = parseUploadResponse(siiHtmlResponse);    // { success, trackId?, error? }
```

### Fechas y Zona Horaria

Todas las fechas y marcas de tiempo operan de manera determinista bajo la zona horaria chilena (`America/Santiago`, GMT-3 / GMT-4 según horario de verano):

```typescript
import { formatDate, formatTimestamp, CHILE_TIMEZONE } from 'dty-fy';

CHILE_TIMEZONE;                        // 'America/Santiago'
formatDate();                          // '2024-01-15' (fecha actual en Chile)
formatDate(new Date('2024-06-01'));    // '2024-06-01'
formatTimestamp();                     // '2024-01-15T14:30:00' (timestamp ISO local sin offset)
```

### Manejo de Codificación ISO-8859-1 (Latin-1)

El SII rechaza documentos que contengan caracteres fuera del repertorio ISO-8859-1. La librería provee sanitización y validación a nivel de bytes:

```typescript
import { sanitizeToLatin1, isLatin1, toLatin1Buffer } from 'dty-fy';

isLatin1('Factura Nº 123');            // true
isLatin1('Producto \u2014 test');       // false (contiene em-dash)

sanitizeToLatin1('Cotización — $500'); // 'Cotizacion - $500' (translitera caracteres incompatibles)
const buf: Buffer = toLatin1Buffer('Texto legal'); // Buffer en codificación latin1
```

---

## Constantes y Tipos

### Codigos de Tipo de DTE

```typescript
import { TipoDTE, TIPO_DTE_DESCRIPTIONS, VALID_DTE_CODES } from 'dty-fy';

TipoDTE.FacturaElectronica           // 33
TipoDTE.FacturaExenta               // 34
TipoDTE.BoletaElectronica           // 39
TipoDTE.BoletaExenta               // 41
TipoDTE.LiquidacionFactura          // 43
TipoDTE.FacturaCompra               // 46
TipoDTE.GuiaDespacho                // 52
TipoDTE.NotaDebito                  // 56
TipoDTE.NotaCredito                 // 61
TipoDTE.FacturaExportacion          // 110
TipoDTE.NotaDebitoExportacion       // 111
TipoDTE.NotaCreditoExportacion      // 112

TIPO_DTE_DESCRIPTIONS[33];           // 'Factura Electronica'
VALID_DTE_CODES;                     // Set { 33, 34, 39, 41, 43, 46, 52, 56, 61, 110, 111, 112 }
```

### Conjuntos por Tipo

```typescript
import { BOLETA_TYPES, EXPORT_TYPES, EXENTO_TYPES } from 'dty-fy';

BOLETA_TYPES  // Set { 39, 41 }
EXPORT_TYPES  // Set { 110, 111, 112 }
EXENTO_TYPES  // Set { 34, 41 }
```

### Constantes del Sistema

```typescript
import { IVA_RATE, RUT_SII, SII_URLS, SII_NAMESPACES } from 'dty-fy';

IVA_RATE                    // 19
RUT_SII                     // '60803000-K'
SII_URLS.certification      // { host, getSeed, getToken, upload, ... }
SII_NAMESPACES              // { DTE, DS, C14N, SHA1, RSA_SHA1, ... }
```

### Codigos de Estado

```typescript
import { ESTADO_ENVIO, ESTADO_DTE } from 'dty-fy';

ESTADO_ENVIO.SOK  // '0' — Aceptado OK
ESTADO_ENVIO.CRT  // '?' — En proceso / carátula recibida
ESTADO_ENVIO.EPR  // 'EPR' — Envío Procesado
ESTADO_ENVIO.RFL  // 'RFL' — Rechazado por Firma/Línea
ESTADO_DTE.DOK    // '0' — DTE Aceptado OK
ESTADO_DTE.RCH    // '1' — DTE Rechazado
```

### Tipos Principales

```typescript
import type {
  DteDocument,            // Estructura completa del documento DTE
  TipoDteCode,            // 33 | 34 | 39 | 41 | 43 | 46 | 52 | 56 | 61 | 110 | 111 | 112
  SiiEnvironment,         // 'certification' | 'production'
  SiiConfig,              // Objeto de configuracion del cliente
  EmitirResult,           // Resultado de emision
  EstadoEnvio,            // Estado del envio batch
  EstadoDte,              // Estado del DTE individual
  CafData,                // Datos de CAF parseados
  CertificateData,        // Datos del certificado parseados
  PollTrackIdOptions,     // Opciones para sondeo de TrackID
  Pdf417RenderOptions,    // Opciones para renderizado de código de barras
} from 'dty-fy';
```

---

## Manejo de Errores

La librería define una jerarquía estricta de errores con propiedades tipadas para capturar fallos específicos de negocio, CAF y comunicación con el SII:

### Excepciones Tipadas de Dominio

| Clase de Error | Cuándo se lanza | Propiedades clave |
|----------------|-----------------|-------------------|
| `DteSchemaValidationError` | Violación de reglas de esquema/negocio (ej. DTE 61 sin CodRef 1, 2 o 3; DTE 52 sin IndTraslado) | `field`, `value` |
| `CafFolioExhaustedError` | Se agotan los folios autorizados en el rango del CAF | `tipoDte`, `requestedFolio`, `availableRange` |
| `CafInvalidSignatureError` | La firma `<FRMA>` sobre `<DA>` en el CAF no coincide o el CAF fue alterado | `tipoDte`, `folioRange` |
| `SiiTokenExpiredError` | La sesión del token ha expirado o el SII retorna código de rechazo de sesión | `token` |
| `SiiWafBlockedError` | El cortafuegos/WAF del SII bloquea la petición (HTML de error, HTTP 403/503) | `url`, `statusCode` |
| `SiiRejectedStatusError` | El envío o documento fue formalmente rechazado por el SII (`RSC`, `RFR`, `RCT`, `RFL`) | `status`, `glosa`, `trackId`, `detalles` |

```typescript
import {
  SiiError,
  DteSchemaValidationError,
  CafFolioExhaustedError,
  CafInvalidSignatureError,
  SiiTokenExpiredError,
  SiiWafBlockedError,
  SiiRejectedStatusError,
} from 'dty-fy';

try {
  const result = await sii.emitir(factura, cafManager);
} catch (error) {
  if (error instanceof CafFolioExhaustedError) {
    console.error(`Folios agotados para tipo ${error.tipoDte}: rango ${error.availableRange.desde}-${error.availableRange.hasta}`);
  } else if (error instanceof DteSchemaValidationError) {
    console.error(`Validación fallida en campo ${error.field}: valor '${error.value}'`);
  } else if (error instanceof SiiWafBlockedError) {
    console.error(`Petición bloqueada por WAF en ${error.url} (HTTP ${error.statusCode})`);
  } else if (error instanceof SiiRejectedStatusError) {
    console.error(`Rechazado por SII [${error.status}]: ${error.glosa} (TrackID: ${error.trackId})`);
  } else if (error instanceof SiiError) {
    console.error(`Error general SII: ${error.message}`);
  }
}
```

---

## Ambientes

| Ambiente | Host SII | Uso |
|----------|----------|-----|
| `certification` | `maullin.sii.cl` | Pruebas y certificacion |
| `production` | `palena.sii.cl` | Produccion |

```typescript
const sii = new SiiClient({
  environment: 'certification',  // o 'production'
  // ...
});
```
---

## Licencia

**EULA** (End User License Agreement) — Copyright (c) 2026 bm0x.

Ver el archivo [LICENSE](./LICENSE) para los terminos completos.

---
_Source: https://npm.io/package/dty-fy · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
