Un ORM ligero y type-safe construido sobre Git como almacenamiento. Perfect para aplicaciones que necesitan versionado, auditoría y sincronización distribuida de datos.
GitDB transforma repositorios Git en bases de datos relacionales, permitiendo CRUD operations con control de versiones automático, relaciones tipadas y queries type-safe.
- 🔐 Type-Safe: TypeScript first, validación de tipos en tiempo de compilación
- 📦 Git-Powered: Cada cambio es un commit automático con historial completo
- 🔗 Relaciones Tipadas: Soporte para relaciones One-to-Many y Many-to-One
- 🎯 Queries Type-Safe: Operadores WHERE validados por tipos
- 📊 Agregaciones: Soporte para COUNT, SUM, AVG
- 🚀 Ligero: Sin dependencias externas, basado en Git nativo
npm install @getgitops/gitdbRequisitos:
- Node.js >= 20
- Git 2.20+
import { entity, uuid, text, int, timestamp } from '@getgitops/gitdb';
export const User = entity('users', {
id: uuid().primary(),
email: text().unique(),
name: text(),
age: int(),
createdAt: timestamp()
});
export const Post = entity('posts', {
id: uuid().primary(),
userId: uuid(),
title: text(),
content: text(),
createdAt: timestamp()
});import { gitDb } from '@getgitops/gitdb';
const db = gitDb('https://github.com/org/repo.git', {
gitUserName: 'App Bot',
gitUserEmail: 'bot@example.com',
});
await db.ready();Por defecto, las tablas cuyo JSON serializado supera 20 MiB (20 * 1024 * 1024 bytes) se guardan en fragmentos de hasta 20 MiB. Las tablas menores o iguales al umbral siguen siendo un unico array JSON. Tambien se fragmentan filas individuales que superen el limite, sin perder caracteres Unicode.
<tabla>.json pasa a ser un indice de los archivos .part de un directorio
<tabla>.chunks-<id>/. GitDB reconstruye la tabla y la mantiene en memoria para
las siguientes lecturas; CRUD, relaciones, agregaciones y auditoria conservan su API.
Los fragmentos no se deben editar individualmente.
Al inicializar, await db.ready() espera la migracion automatica de las tablas
grandes existentes. Los cambios se registran con el motivo migrate:chunks y se
sincronizan con la politica habitual del repositorio. Al reducir una tabla por
debajo del umbral, vuelve a un unico JSON y se eliminan los fragmentos sobrantes.
Para desactivar la fragmentacion por tabla:
const Settings = entity('settings', { value: text() }, { chunk: false });
const db = gitDb('https://github.com/org/repo.git', {
entities: [Settings],
});
await db.ready();Pasa las entidades con excepciones en entities para que se respeten tambien
durante la migracion inicial. No es necesario registrar entidades para activar
el comportamiento por defecto. Desactivar chunks permite archivos grandes que
el proveedor Git podria rechazar.
La migracion no reescribe el historial Git. Si ya hay blobs de mas de 100 MB en commits pendientes de subir, borrarlos de la ultima version no basta: hay que retirarlos de esos commits mediante una limpieza explicita del historial antes de hacer push. Las versiones anteriores de GitDB no pueden leer el nuevo formato.
Si el repositorio remoto es privado, pasa un token de acceso personal de GitHub vía authToken (recomendado tomarlo de una variable de entorno) o simplemente define GITDB_GITHUB_TOKEN/GITHUB_TOKEN en el entorno y gitDb lo detecta automáticamente:
const db = gitDb('https://github.com/org/repo.git', {
authToken: process.env.GITHUB_TOKEN,
});El token nunca se define en repositoryUrl; gitdb lo agrega automáticamente como credenciales en la URL del remoto (origin) al clonar/sincronizar el repo local.
const newUser = await db.insert(User).values({
id: 'uuid-1',
email: 'john@example.com',
name: 'John Doe',
age: 30,
createdAt: new Date()
});// Obtener todos
const allUsers = await db.select().from(User);
// Con WHERE
const adults = await db
.select()
.from(User)
.where(gte('age', 18));
// Campos específicos
const emails = await db
.select(['email', 'name'])
.from(User);
// Con AND/OR
const filtered = await db
.select()
.from(User)
.where(
and(
eq('age', 30),
ilike('email', '%@example.com')
)
);await db
.update(User)
.set({ name: 'Jane Doe', age: 31 })
.where(eq('id', 'uuid-1'));await db
.delete()
.from(User)
.where(eq('id', 'uuid-1'));import { defineRelations } from '@getgitops/gitdb';
defineRelations(User, {
posts: {
type: 'many',
entity: Post,
foreignKey: 'userId'
}
});
defineRelations(Post, {
author: {
type: 'one',
entity: User,
foreignKey: 'userId'
}
});
// Usar con include
const userWithPosts = await db
.select()
.from(User)
.where(eq('id', 'uuid-1'))
.include({
posts: true
});// COUNT
const totalUsers = await db.$count(User);
const adults = await db.$count(User, gte('age', 18));
// SUM
const totalAge = await db.$sum(User, 'age');
// AVG
const avgAge = await db.$avg(User, 'age');uuid()- UUID/GUIDtext()- Textovarchar(n)- Texto con límiteint()/integer()- Enterosbigint()- Enteros grandesreal()/double()/doublePrecision()- Decimalesnumeric(precision, scale)- Decimales precisosbool()/boolean()- Booleanosdate()- Solo fechatimestamp()- Fecha y horachar(n)- Carácter fijojson()- Objeto JSON
eq(field, value)- Igualne(field, value)- No igualgt(field, value)- Mayor quegte(field, value)- Mayor o iguallt(field, value)- Menor quelte(field, value)- Menor o igualilike(field, pattern)- Case-insensitive LIKEand(...predicates)- AND lógicoor(...predicates)- OR lógiconot(predicate)- Negación
npm run build # Build distribución
npm run typecheck # Verificar tipos TypeScript
npm run test # Ejecutar tests
npm run test:watch # Tests en modo watch
npm run dev # Build en watch mode
npm run demo # Demo interactivoLos releases son manuales, con tags de Git. No se usa changesets.
- Asegúrate de estar en
maincon los cambios ya mergeados y el árbol limpio. - Sube la versión en
package.jsony crea el tagvX.Y.Zen un solo paso:npm version patch # o: npm version minor / npm version major - Sube el commit de versión y el tag:
git push && git push --tags - El push del tag
vX.Y.Zdispara el workflow.github/workflows/release.yml, que compila, testea y publica el paquete en NPM.
Requiere sesión activa con npm login y permisos de publish en el paquete:
npm run releaseEsto ejecuta clean, build, typecheck, test y npm publish.
Configura en GitHub (Settings → Secrets):
NPM_TOKEN- Token de acceso a NPM (con permiso de publish)
- Job
test: corre typecheck y tests en cada push/PR amain/develop, con Node 20 y 22. - Job
publish: solo corre cuando se pushea un tagvX.Y.Z(por ejemplo trasnpm version patch && git push --tags); compila, testea y publica en NPM usandoNPM_TOKEN.
.
├── src/
│ ├── core/
│ │ ├── gitdb.ts # Clase principal GitDB
│ │ ├── schema.ts # Builder de schema y tipos
│ │ └── relations.ts # Definición de relaciones
│ ├── infrastructure/
│ │ ├── git-repository.ts # Abstracciones Git
│ │ ├── file-manager.ts # Operaciones con filesystem
│ │ └── logger.ts # Logging
│ ├── queries/
│ │ ├── select-query.ts
│ │ ├── insert-query.ts
│ │ ├── update-query.ts
│ │ ├── delete-query.ts
│ │ └── where-operators.ts
│ ├── types.ts # Tipos globales
│ └── index.ts # Exports públicos
├── tests/ # E2E tests
MIT