Implementación de JSON Schema basada en TypeScript y colección de herramientas de desarrollo
(github.com/imhonglu)Este es un proyecto que comenzó con la idea de “crear una librería type-safe a mi gusto”.
Este proyecto se expandió de forma natural, comenzando con una implementación type-safe de JSON Schema y extendiéndose a diversas herramientas necesarias durante el proceso de desarrollo.
Por ahora le he puesto un primer punto final mientras busco trabajo.
Principios del proyecto
Fue desarrollado respetando los siguientes principios clave:
- Uso de un sistema de tipos estricto
- Mantener al mínimo las dependencias externas
- Diseño de un sistema de tipos reutilizable
- Documentación de la API
- Mantener una alta cobertura de pruebas
- Implementación en TypeScript puro
Librerías
@imhonglu/json-schema
Es una implementación en TypeScript que cumple con la especificación JSON Schema draft 2020-12.
- Repositorio: https://github.com/imhonglu/new-wheels/…
- Validación mediante
JSON-Schema-Test-Suite - Los tipos de las palabras clave disponibles se infieren automáticamente según la definición del esquema.
import { Schema, SchemaDefinition } from "@imhonglu/json-schema";
export const Address = new Schema({
type: "object",
properties: {
street: { type: "string" },
city: { type: "string" },
zip: { type: "string" },
},
required: ["street"] as const,
});
export type Address = SchemaDefinition.Instance<typeof Address>;
// {
// street: string;
// city?: string;
// zip?: string;
// }
@imhonglu/format
Es un proyecto que comenzó para implementar la palabra clave format de JSON Schema.
- Repositorio: https://github.com/imhonglu/new-wheels/…
- Implementación basada en especificaciones RFC
- Validación basada en
JSON-Schema-Test-Suite - Ofrece una interfaz similar a la API nativa de
JSON
import { FullTime } from '@imhonglu/format';
const time = FullTime.parse('00:00:00.000Z');
// { hour: 0, minute: 0, second: 0, secfrac: '.000', offset: undefined }
console.log(time.toString()); // '00:00:00.000Z'
console.log(JSON.stringify(time)); // '"00:00:00.000Z"'
const result = FullTime.safeParse('invalid');
if (!result.ok) {
console.error(result.error);
}
@imhonglu/pattern-builder
Es un regex builder creado para mejorar la legibilidad de las expresiones regulares durante la implementación de la gramática ABNF de las RFC.
- Repositorio: https://github.com/imhonglu/new-wheels/…
import { characterSet, concat, hexDigit } from "@imhonglu/pattern-builder";
// pct-encoded = "%" HEXDIG HEXDIG
export const pctEncoded = concat(
"%",
hexDigit.clone().exact(2),
);
// unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
export const unreserved = characterSet(
alpha,
digit,
/[\-._~]/,
);
@imhonglu/type-guard
Es una librería de type guards creada para mejorar la legibilidad de los type guards.
- Repositorio: https://github.com/imhonglu/new-wheels/…
- Implementación basada en Proxy para minimizar el overhead
- Proporciona la palabra clave
not
import { composeGuards } from "@imhonglu/type-guard";
const is = composeGuards({
string: (value: unknown): value is string => typeof value === "string",
number: (value: unknown): value is number => typeof value === "number"
});
is.string("hello"); // true
is.not.string(42); // true
let value: string | number | undefined;
if (is.number(value)) {
value.toFixed(2); // 'value' is number
}
if (is.not.number(value)) {
value.toFixed(2); // error: Property 'toFixed' does not exist on type 'undefined'.
}
@imhonglu/type-object
Es una librería wrapper type-safe de la API nativa de Object. Proporciona tipos cercanos al comportamiento nativo.
- Repositorio: https://github.com/imhonglu/new-wheels/…
import * as TypeObject from '@imhonglu/type-object';
const data = { a: 1, b: 2, c: 3 };
for (const key of TypeObject.keys(data)) {
// key: "a" | "b" | "c"
console.log(data[key]); // number
}
const string = 'hello';
for (const index of TypeObject.keys(string)) {
// index: number & keyof string
console.log(string[index]); // string
}
@imhonglu/toolkit
Es una colección de tipos utilitarios y funciones utilitarias que se usan dentro del proyecto.
- Repositorio: https://github.com/imhonglu/new-wheels/…
import type { Fn } from '@imhonglu/toolkit';
// Proporciona un alias de tipo para el tipo de función '(...args: any[]) => any'.
Fn.Callable // (...args: any[]) => any
// A través de genéricos, solo se puede definir el tipo de los argumentos.
Fn.Callable<{ args: [number, number] }> // (...args: [number, number]) => any
// A través de genéricos, solo se puede definir el tipo de retorno.
Fn.Callable<{ return: string }> // (...args: any[]) => string
// A través de genéricos, se pueden definir tanto el tipo de los argumentos como el tipo de retorno.
Fn.Callable<{ args: [number, number], return: string }> // (...args: [number, number]) => string
Planes a futuro y búsqueda laboral
La siguiente etapa del proyecto en curso es terminar la implementación de la especificación JSON Schema,
y también me gustaría intentar crear un framework backend.
Actualmente estoy buscando trabajo, así que agradeceré mucho su interés.
Gracias por leer.
¡Que tengas un gran día!
2 comentarios
En este ámbito existe una opción excelente llamada zod, así que la estamos usando en el producto, pero me parece interesante.
Proyectos ya consolidados como ajv, typia y zod también son proyectos que sigo con mucho interés.
En el caso de
safeParsede@imhonglu/format, también es una función influenciada por la API de zod.¡Gracias por el interés!