@gpkit/core
v1.0.0
Published
Contratos y utilidades agnósticas: errores, tipos transversales, contrato de logger. Cero AWS, cero NestJS.
Readme
@gpkit/core
Errores con código y estado HTTP, tipos de respuesta, logging con formato uniforme, procesamiento por lotes y un decorador que instrumenta la ejecución de un método.
Funciona en cualquier entorno Node. No depende de AWS ni de ningún framework, y
npm run arch:check lo verifica en cada build.
npm i @gpkit/coreTodo se importa desde @gpkit/core. El paquete no tiene subpaths.
Errores
import { CustomException, ValidationException, ErrorDictionary } from '@gpkit/core';| Símbolo | Qué es |
| --------------------- | -------------------------------------------------------------------------------------------------------------------------- |
| CustomException | Error con código, estado HTTP y descripción. Se construye desde una entrada de diccionario |
| ValidationException | Error de validación. Añade el detalle por campo que reporta Zod |
| ErrorDictionary | Cuatro errores transversales con prefijo CORE-: VALIDATION_ERROR, INTERNAL_ERROR, ENV_VAR_MISSING, ACCESS_DENIED |
| InputError | La forma de cada entrada de un diccionario |
throw new CustomException(ErrorDictionary.ACCESS_DENIED);
throw new CustomException(ErrorDictionary.ENV_VAR_MISSING, 'QUOTES_TABLE');El segundo argumento es un detalle que se añade a la descripción y sirve para precisar cuál de los casos ocurrió sin crear una entrada nueva.
Un proyecto define su propio diccionario para los errores de su dominio, con la misma forma
InputError. Los errores de los servicios de AWS están en @gpkit/aws, con prefijo
AWS-.
Respuestas HTTP
import type { ApiSuccessBody, ApiErrorBody, ApiValidationErrorBody } from '@gpkit/core';La forma del cuerpo que se devuelve al cliente: el dato bajo data con un meta opcional,
o el error como { code, description }, con issues si es de validación. ApiGwHelper, en @gpkit/aws-lambda/http, los
serializa para API Gateway.
Procesamiento por lotes
import { executeChunkedBatch, classifyBatchFailure, summarizeBatchResults } from '@gpkit/core';Procesa registros en tandas y devuelve un resultado por cada uno, indicando si el fallo admite reintento. Un registro que falla no aborta el lote.
const records = messages.map((m) => ({ recordId: m.messageId, body: m.body }));
const results = await executeChunkedBatch(records, 10, procesar, classifyBatchFailure);
const { total, success, discarded, retryable } = summarizeBatchResults(results);classifyBatchFailure marca los errores de validación como descartables y el resto como
reintentables. El origen de los registros lo decide quien llama —mensajes de una cola,
registros de un stream o filas de un fichero—; solo se les exige un recordId.
Logging
El formato de los mensajes se define aquí y es el mismo en todos los entornos. Cada runtime aporta el destino de escritura.
import { setLogger, getLogger, createLogger, consoleSink, type LogSink } from '@gpkit/core';| Símbolo | Qué es |
| ------------------------- | ------------------------------------------------------------ |
| Logger | La interfaz: start, end, step, info, warn, error |
| LogSink | El destino: un único write(level, message, context) |
| createLogger(sink) | Crea un Logger con el formato estándar sobre ese destino |
| consoleSink | Escribe en stdout. Es el destino por defecto |
| setLogger / getLogger | El registro, que se fija una vez al arrancar el runtime |
Formato de salida:
--- GetQuote start ---
[PASO 2] consultando tabla
--- GetQuote end --- { durationMs: 120, success: true }Está verificado por tests, de modo que los mismos filtros de logs sirven en cualquier entorno.
Sin registrar nada, escribe por consola, que es lo adecuado en un contenedor. En Lambda,
LambdaHandlerFactory.build() de @gpkit/aws-lambda registra el logger de Powertools.
Para otro destino:
setLogger(createLogger(miSinkDePino));HandleExecution
import { HandleExecution } from '@gpkit/core';
@HandleExecution('GetQuote')
async execute(input: Input): Promise<Output> { … }Loggea el inicio y el fin del método y mide su duración. Con un segundo argumento, delega el error en esa función en lugar de propagarlo:
@HandleExecution('GetQuote', (error) => ApiGwHelper.error(error))Resuelve el logger en cada llamada, así que funciona con independencia del orden en que se carguen los módulos.
