Referencia de Tipos API¶
Esta guía documenta todos los tipos TypeScript exportados por Dynamite ORM.
Tabla de Contenidos¶
- Tipos Marcadores de Atributos
- CreationOptional\<T>
- NonAttribute\<T>
- Tipos de Inferencia
- InferAttributes\<T>
- InferRelations\<T>
- PickRelations\<T>
- Tipos de Entrada
- CreateInput\<T>
- UpdateInput\<T>
- Tipos de Consulta
- QueryOperator
- WhereOptions\<T>
- QueryResult\<T>
- Tipos de Mutación
- MutationOptions
- DynamiteConfig
Tipos Marcadores de Atributos¶
CreationOptional\<T>¶
Marca un campo como opcional durante la creación pero presente después de guardar. Usar para campos con valores por defecto, valores auto-generados o valores auto-calculados.
Sintaxis:
Características: - El campo es opcional al llamar Model.create() - El campo está presente en la instancia después de guardar - Ideal para IDs auto-generados, timestamps y valores por defecto
Ejemplos:
import { Table, PrimaryKey, Default, CreatedAt, UpdatedAt, CreationOptional } from '@arcaelas/dynamite';
class User extends Table<User> {
// Clave primaria auto-generada
@PrimaryKey()
declare id: CreationOptional<string>;
// Campo requerido (sin CreationOptional)
declare email: string;
// Campo con valor por defecto
@Default(() => "customer")
declare role: CreationOptional<string>;
// Timestamps auto-establecidos
@CreatedAt()
declare created_at: CreationOptional<string>;
@UpdatedAt()
declare updated_at: CreationOptional<string>;
}
// Solo email es requerido durante la creación
const user = await User.create({
email: "john@example.com"
// id, role, created_at, updated_at son opcionales
});
// Después de la creación, todos los campos están presentes
console.log(user.id); // "550e8400-e29b-..."
console.log(user.role); // "customer"
console.log(user.created_at); // "2025-01-15T10:30:00.000Z"
NonAttribute\<T>¶
Marca un campo que NO se almacena en la base de datos. Usar para propiedades calculadas, relaciones y getters virtuales.
Sintaxis:
Características: - El campo se excluye de las operaciones de base de datos - Ideal para relaciones y valores calculados - No aparece en toJSON() a menos que se agregue explícitamente
Ejemplos:
import { Table, HasMany, BelongsTo, NonAttribute, CreationOptional } from '@arcaelas/dynamite';
class User extends Table<User> {
@PrimaryKey()
declare id: CreationOptional<string>;
declare name: string;
// Relación - no se almacena en la base de datos
@HasMany(() => Order, "user_id")
declare orders: NonAttribute<Order[]>;
// Propiedad calculada
declare display_name: NonAttribute<string>;
}
class Order extends Table<Order> {
@PrimaryKey()
declare id: CreationOptional<string>;
declare user_id: string;
@BelongsTo(() => User, "id", "user_id")
declare user: NonAttribute<User | null>;
}
Tipos de Inferencia¶
InferAttributes\<T>¶
Extrae solo los atributos de base de datos de un modelo, excluyendo métodos, relaciones y campos no-atributos.
Uso:
import type { InferAttributes } from '@arcaelas/dynamite';
type UserAttributes = InferAttributes<User>;
// Resultado:
// {
// id?: string; // CreationOptional se vuelve opcional
// email: string; // Requerido
// name: string; // Requerido
// role?: string; // CreationOptional se vuelve opcional
// created_at?: string; // CreationOptional se vuelve opcional
// updated_at?: string; // CreationOptional se vuelve opcional
// }
Casos de Uso: - Parámetros de función type-safe - Definiciones de DTO (Data Transfer Object) - Tipos de respuesta de API
Ejemplo:
import type { InferAttributes } from '@arcaelas/dynamite';
// Función con entrada type-safe
async function updateUser(
id: string,
data: Partial<InferAttributes<User>>
): Promise<boolean> {
const user = await User.first({ id });
if (user) {
return user.update(data);
}
return false;
}
// Uso
await updateUser("user-123", { name: "Nuevo Nombre", role: "admin" });
InferRelations\<T>¶
Extrae solo los campos de relación de un modelo (campos marcados con NonAttribute).
Uso:
import type { InferRelations } from '@arcaelas/dynamite';
type UserRelations = InferRelations<User>;
// Resultado:
// {
// orders: Order[]; // HasMany resuelve a array
// profile: Profile; // HasOne resuelve a singular
// }
Ejemplo:
import type { InferRelations } from '@arcaelas/dynamite';
class User extends Table<User> {
@PrimaryKey()
declare id: CreationOptional<string>;
@HasMany(() => Post, "user_id")
declare posts: NonAttribute<Post[]>;
@HasOne(() => Profile, "user_id")
declare profile: NonAttribute<Profile | null>;
}
// InferRelations<User> = { posts: Post[], profile: Profile | null }
PickRelations\<T>¶
Extrae solo los campos de relación. Usado internamente para validación.
Uso:
import type { PickRelations } from '@arcaelas/dynamite';
type UserRelations = PickRelations<User>;
// { posts: Post[], profile: Profile | null }
Tipos de Entrada¶
CreateInput\<T>¶
Tipo para entrada de Model.create(). Alias de InferAttributes<T>.
Uso:
import type { CreateInput } from '@arcaelas/dynamite';
type UserCreateData = CreateInput<User>;
// { email: string; name: string; id?: string; role?: string; ... }
const data: CreateInput<User> = {
email: "john@example.com",
name: "John"
// id, role, timestamps son opcionales
};
await User.create(data);
UpdateInput\<T>¶
Tipo para entrada de instance.update(). Todos los campos son opcionales.
Uso:
import type { UpdateInput } from '@arcaelas/dynamite';
type UserUpdateData = UpdateInput<User>;
// { email?: string; name?: string; role?: string; ... }
const data: UpdateInput<User> = {
name: "Nuevo Nombre"
// Todos los campos son opcionales
};
await user.update(data);
Tipos de Consulta¶
QueryOperator¶
Tipo union de todos los operadores de consulta soportados.
Definición:
type QueryOperator =
| "=" // Igual
| "$eq" // Igual (alias)
| "<>" // No igual
| "!=" // No igual (alias)
| "$ne" // No igual (alias)
| "<" // Menor que
| "$lt" // Menor que (alias)
| "<=" // Menor o igual
| "$lte" // Menor o igual (alias)
| ">" // Mayor que
| "$gt" // Mayor que (alias)
| ">=" // Mayor o igual
| "$gte" // Mayor o igual (alias)
| "in" // En array
| "$in" // En array (alias)
| "include" // Contiene
| "$include" // Contiene (alias)
Uso:
// Igualdad
await User.where("role", "=", "admin");
await User.where("role", "$eq", "admin");
// Comparación
await User.where("age", ">=", 18);
await User.where("age", "$gte", 18);
await User.where("balance", "<", 100);
await User.where("balance", "$lt", 100);
// No igual
await User.where("status", "!=", "banned");
await User.where("status", "<>", "banned");
await User.where("status", "$ne", "banned");
// Membresía en array
await User.where("status", "in", ["active", "pending"]);
await User.where("status", "$in", ["active", "pending"]);
// Contiene
await User.where("email", "include", "@gmail.com");
await User.where("email", "$include", "@gmail.com");
WhereOptions\<T>¶
Opciones para configurar el comportamiento de las consultas.
Definición:
interface WhereOptions<T> {
where?: {
[K in keyof InferAttributes<T>]?:
| InferAttributes<T>[K]
| { [op in QueryOperator]?: InferAttributes<T>[K] };
};
order?: "ASC" | "DESC" | { [K in keyof InferAttributes<T>]?: "ASC" | "DESC" };
skip?: number; // Alias de offset
offset?: number; // Número de registros a saltar
limit?: number; // Máximo de registros a retornar
attributes?: (keyof InferAttributes<T>)[]; // Campos a seleccionar
include?: { // Relaciones a incluir
[relation: string]: boolean | WhereOptions<any>;
};
cursor?: Record<string, any>; // Cursor de la página siguiente, devuelto por la consulta anterior
deleted?: boolean; // Incluir registros soft-deleted
}
Propiedades:
| Propiedad | Tipo | Descripción |
|---|---|---|
where | object | Condiciones de filtro con soporte de operadores |
order | "ASC" \| "DESC" | Orden de resultados |
skip | number | Número de registros a saltar (alias: offset) |
offset | number | Número de registros a saltar |
limit | number | Máximo de registros a retornar |
attributes | string[] | Campos específicos a seleccionar |
include | object | Relaciones a incluir |
cursor | Record<string, any> | Cursor de la página siguiente |
deleted | boolean | Incluir registros soft-deleted |
Ejemplo:
const users = await User.where({ active: true }, {
order: "DESC",
skip: 20,
limit: 10,
attributes: ["id", "name", "email"],
include: {
orders: {
where: { status: "completed" },
limit: 5,
order: "DESC",
include: {
items: {
include: {
product: true
}
}
}
}
}
});
QueryResult\<T>¶
El arreglo que devuelve where(), con el cursor de la página siguiente adosado.
Definición:
cursor no es enumerable, así que no sobrevive a JSON.stringify ni a un spread. Trae valor mientras queden páginas por leer.
Ejemplo:
let pagina = await User.where({}, { limit: 50 });
while (pagina.cursor) {
pagina = await User.where({}, { limit: 50, cursor: pagina.cursor });
}
Tipos de Mutación¶
MutationOptions¶
El objeto de opciones que recibe toda mutación como último argumento.
Definición:
| Propiedad | Tipo | Descripción |
|---|---|---|
hook | boolean | Ejecuta los hooks de ciclo de vida de la operación. Apagado por defecto |
tx | TransactionContext | Encola la operación en una transacción atómica |
Ejemplo:
await User.create({ name: "Ana" }, { hook: true });
await dynamite.tx(async (tx) => { await User.create({ name: "Ana" }, { tx }); });
DynamiteConfig¶
La configuración del cliente. Extiende DynamoDBClientConfig del SDK de AWS.
Definición:
interface DynamiteConfig extends DynamoDBClientConfig {
tables: Array<new (...args: any[]) => any>;
}
Ejemplo:
Mejores Prácticas¶
1. Siempre Usar CreationOptional para Campos con Defaults¶
// Correcto
@Default(() => "active")
declare status: CreationOptional<string>;
// Incorrecto - TypeScript requerirá status en create()
@Default(() => "active")
declare status: string;
2. Siempre Envolver Relaciones en NonAttribute¶
// Correcto
@HasMany(() => Post, "user_id")
declare posts: NonAttribute<Post[]>;
// Incorrecto - posts sería tratado como columna de base de datos
@HasMany(() => Post, "user_id")
declare posts: Post[];
3. Usar InferAttributes para Funciones Type-Safe¶
// Correcto - parámetro type-safe
function processUser(data: InferAttributes<User>) { ... }
// Incorrecto - sin seguridad de tipos
function processUser(data: any) { ... }
4. Definir Foreign Keys Explícitamente¶
// Correcto - foreign key está declarado
class Post extends Table<Post> {
declare user_id: string; // Campo FK
@BelongsTo(() => User, "id", "user_id")
declare author: NonAttribute<User | null>;
}
// Incorrecto - foreign key no declarado
class Post extends Table<Post> {
@BelongsTo(() => User, "id", "user_id")
declare author: NonAttribute<User | null>;
}