open-pay / openpay-node

Openpay Node.js bindings
29 stars 16 forks source link

refactor: Typescript, ESM y Async Await #46

Open ChrisGV04 opened 4 months ago

ChrisGV04 commented 4 months ago

Esta PR tiene la intención de actualizar la SDK de Openpay para Node.js a sistemas más modernos, así como actualizar la API disponible y facilitar su uso.

¿Por qué?

Últimamente he intentado crear mis propios sistemas que se integran con Openpay, por lo tanto, requiero de esta SDK para facilitar la interacción con la API de Openpay.

Sin embargo, no dispone de tipos de datos y no soporta promesas async/await, lo que resulta inconveniente de utilizar en aplicaciones modernas sin caer en el famoso "callback hell" o sin errores accidentales por pasar información incorrecta sin saberlo.

Hoy en día, muchas aplicaciones de Node.js están siendo desarrolladas con Typescript y empaquetadas para utilizarse con ESM, lo cual mejora la experiencia de desarrollo y la compatibilidad con sistemas modernos.

¿Qué cambió?

El paquete fue reescrito por completo utilizando Typescript y arquitectura moderna de promesas, async/await y ofetch como librería para realizar las llamadas HTTP a la API de Openpay.

Typescript y ESM

Toda la librería fue reescrita utilizando Typescript, lo cual permite brindar autocompletado y tipos de datos a la hora de integrar la librería en tu proyecto. Actualmente existe el paquete @types/openpay, pero no cuenta con tipos de datos detallados ni la figura de los objetos que maneja la API.

Sin embargo, el proyecto es compilado a Javascript puro ES2018 en ambos cjs y esm para mantener retrocompatibilidad con muchos sistemas. La versión de compilado garantiza el funcionamiento en Node.js v14.0.0 en adelante, pero es posible que funcione en versiones anteriores debido a que no utiliza funciones más modernas.

Por lo tanto, ahora el import de la librería es el siguiente:

// Antes
const Openpay = require("openpay")

// Ahora. CommonJS
const { Openpay } = require("openpay")

// Ahora. ESM
import { Openpay } from "openpay"

Si deseas utilizar los tipos de datos de Openpay en tu aplicación, exponemos todos los tipos mediante el siguiente import:

import type { IOpenpay } from "openpay"

const camposParaCrearCliente: IOpenpay.Customer.CreateInput = {
  // Recibirás sugerencias de autocompletado para este tipo de dato
}

[!NOTE] A pesar de estar escrita en Typescript, la librería es compilada a Javascript puro y puede ser utilizada en ambos Javascript y Typescript por igual.

Configuración

Para facilitar la configuración de la instancia de Openpay, la configuración ha sido convertida en un objeto para que sea muy claro qué información se requiere y no confundir las claves utilizadas. A su vez, podrás recibir sugerencias de autocompletado, pues las opciones están cubiertas por los tipos de Typescript.

Aquí dejo un ejemplo del antes y después:

// Antes
const openpay = new Openpay("tu-merchant-id", "tu-private-key", "mx", true)

// Ahora
const openpay = new Openpay({
  merchantId: "tu-merchant-id",
  privateKey: "tu-private-key",
  isProductionReady: false,
  countryCode: 'mx',
});

Promesas

En la versión original de esta librería, todos los métodos para llamar la API requerían pasar un "callback" para procesar ya sea un error o la respuesta exitosa de la API.

Hoy en día, existen mejores alternativas para facilitar el desarrollo y el funcionamiento de nuestras aplicaciones. Las promesas con uso de async/await facilitan la legibilidad y el funcionamiento de las llamadas asíncronas. Por lo tanto, muchos desarrolladores se podrán beneficiar de utilizar estas características.

Aquí dejo un ejemplo del antes y después de la implementación con promesas:

// Antes
openpay.customers.create(infoCliente, function(error, body, response) {
  // Usa el error, body o la respuesta aquí
})

// Después
const cliente = await openpay.customers.create(infoCliente)

Cualquier error que ocurra durante la llamada a la API lanzará un error de tipo FetchError por parte de ofetch. Para manejar errores, podemos utilizar try/catch de la siguiente manera:

import { FetchError } from "ofetch"

try {
  const cliente = await openpay.customers.create(infoCliente)
} catch (error) {
  if (error instanceof FetchError) {
    error.data; // La información del error de Openpay estará contenida en `error.data`
  }
}

Para más información en cómo manejar errores de ofetch, consulta la documentación oficial.

ofetch

Decidí utilizar ofetch como librería para las llamadas HTTP por su simplicidad de uso, buen rendimiento y debido a que ya devuelve las respuestas del servidor procesadas y listas para utilizarse sin enredos.

Todas las peticiones a la API son realizadas mediante ofetch. Para conocer cómo funciona, visita su documentación oficial.

Emparejamiento con la Documentación Oficial

Al parecer, algunas características han sido removidas o actualizadas desde la última actualización de esta librería. Por ejemplo, ya no hay rastro alguno de los objetos Groups en la documentación de México, Colombia ni Perú; por lo tanto, ha sido removido de la librería.

[!NOTE] En caso de que se haya removido/olvidado alguna API que siga operando y esté documentada oficialmente, por favor háganmelo saber y la añado con gusto.

Pruebas del SDK

Todas las pruebas de la SDK fueron reescritas utilizando Vitest para soportar Typescript, hacerlas más fáciles de entender y separar las pruebas por país.

Para más información acerca de estas pruebas, por favor consulta el archivo README.md de esta PR.

¿Cómo probar esta versión?

Si desean probar esta librería antes de aprobarla oficialmente, la publiqué en NPM como:

npm i @cgvweb/openpay-node

Es una réplica exacta de los cambios propuestos en esta PR.

Conclusión

Espero que esta nueva arquitectura sea agradable para los desarrolladores que implementan Openpay y que facilite su integración en sistemas modernos.

Entiendo que puede conllevar una labor adicional el realizar la migración para aplicaciones muy grandes o complejas. Por lo tanto, sugiero que, si se aprueba esta PR, publicarla bajo una versión mayor v3.0.0 para que sea opcional y los desarrolladores estén conscientes de que hubieron cambios importantes que alteran el uso de la librería.

Por lo pronto, pueden probar esta integración mediante @cgvweb/openpay-node.

Cualquier duda, comentario, corrección o sugerencia estaré al pendiente.

Gracias.

ChrisGV04 commented 4 months ago

Cabe recalcar que, en caso de aprobar esta PR, se deberán actualizar los ejemplos en las documentaciones oficiales de las APIs en México, Colombia y Perú.

cristianPerez commented 1 month ago

Hey @ChrisGV04 thanks for doing this, I'm actually trying to integrate your library in my project. Let's keep in touch.

ChrisGV04 commented 1 month ago

Sure thing. If you have any questions or observations on the refactor please let me know!

Sadly it seems that this project has been inactive for some time and I haven't been able to get in touch with the maintainers. Hopefully they come back soon to have official feedback.