Types API Reference¶
This guide documents all TypeScript types exported by Dynamite ORM.
Table of Contents¶
- Attribute Marker Types
- CreationOptional\<T>
- NonAttribute\<T>
- Inference Types
- InferAttributes\<T>
- InferRelations\<T>
- PickRelations\<T>
- Input Types
- CreateInput\<T>
- UpdateInput\<T>
- Query Types
- QueryOperator
- WhereOptions\<T>
- QueryResult\<T>
- Mutation Types
- MutationOptions
- DynamiteConfig
Attribute Marker Types¶
CreationOptional\<T>¶
Marks a field as optional during creation but present after saving. Use for fields with default values, auto-generated values, or auto-calculated values.
Syntax:
Characteristics: - Field is optional when calling Model.create() - Field is present in the instance after saving - Ideal for auto-generated IDs, timestamps, and default values
Examples:
import { Table, PrimaryKey, Default, CreatedAt, UpdatedAt, CreationOptional } from '@arcaelas/dynamite';
class User extends Table<User> {
// Auto-generated primary key
@PrimaryKey()
declare id: CreationOptional<string>;
// Required field (no CreationOptional)
declare email: string;
// Field with default value
@Default(() => "customer")
declare role: CreationOptional<string>;
// Auto-set timestamps
@CreatedAt()
declare created_at: CreationOptional<string>;
@UpdatedAt()
declare updated_at: CreationOptional<string>;
}
// Only email is required during creation
const user = await User.create({
email: "john@example.com"
// id, role, created_at, updated_at are optional
});
// After creation, all fields are present
console.log(user.id); // "01ARZ3NDEKTSV4RRFFQ69G5FAV"
console.log(user.role); // "customer"
console.log(user.created_at); // "2025-01-15T10:30:00.000Z"
NonAttribute\<T>¶
Marks a field that is NOT stored in the database. Use for computed properties, relationships, and virtual getters.
Syntax:
Characteristics: - Field is excluded from database operations - Ideal for relationships and computed values - Does not appear in toJSON() unless explicitly added
Examples:
import { Table, HasMany, BelongsTo, NonAttribute, CreationOptional } from '@arcaelas/dynamite';
class User extends Table<User> {
@PrimaryKey()
declare id: CreationOptional<string>;
declare name: string;
// Relationship - not stored in database
@HasMany(() => Order, "user_id")
declare orders: NonAttribute<Order[]>;
// Computed property
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>;
}
Inference Types¶
InferAttributes\<T>¶
Extracts only the database attributes from a model, excluding methods, relationships, and non-attribute fields.
Usage:
import type { InferAttributes } from '@arcaelas/dynamite';
type UserAttributes = InferAttributes<User>;
// Result:
// {
// id?: string; // CreationOptional becomes optional
// email: string; // Required
// name: string; // Required
// role?: string; // CreationOptional becomes optional
// created_at?: string; // CreationOptional becomes optional
// updated_at?: string; // CreationOptional becomes optional
// }
Use Cases: - Type-safe function parameters - DTO (Data Transfer Object) definitions - API response types
Example:
import type { InferAttributes } from '@arcaelas/dynamite';
// Function with type-safe input
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;
}
// Usage
await updateUser("user-123", { name: "New Name", role: "admin" });
InferRelations\<T>¶
Extracts only the relationship fields from a model (fields marked with NonAttribute).
Usage:
import type { InferRelations } from '@arcaelas/dynamite';
type UserRelations = InferRelations<User>;
// Result:
// {
// orders: Order[]; // HasMany resolves to array
// profile: Profile; // HasOne resolves to single
// }
Example:
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>¶
Extracts only relationship fields. Used internally for validation.
Usage:
import type { PickRelations } from '@arcaelas/dynamite';
type UserRelations = PickRelations<User>;
// { posts: Post[], profile: Profile | null }
Input Types¶
CreateInput\<T>¶
Type for Model.create() input. Alias of InferAttributes<T>.
Usage:
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 are optional
};
await User.create(data);
UpdateInput\<T>¶
Type for instance.update() input. All fields are optional.
Usage:
import type { UpdateInput } from '@arcaelas/dynamite';
type UserUpdateData = UpdateInput<User>;
// { email?: string; name?: string; role?: string; ... }
const data: UpdateInput<User> = {
name: "New Name"
// All fields are optional
};
await user.update(data);
Query Types¶
QueryOperator¶
Union type of all supported query operators.
Definition:
type QueryOperator =
| "=" // Equal
| "$eq" // Equal (alias)
| "<>" // Not equal
| "!=" // Not equal (alias)
| "$ne" // Not equal (alias)
| "<" // Less than
| "$lt" // Less than (alias)
| "<=" // Less than or equal
| "$lte" // Less than or equal (alias)
| ">" // Greater than
| "$gt" // Greater than (alias)
| ">=" // Greater than or equal
| "$gte" // Greater than or equal (alias)
| "in" // In array
| "$in" // In array (alias)
| "include" // Contains substring
| "$include" // Contains (alias)
| "contains" // Contains (alias for include)
| "$contains" // Contains (alias)
Usage:
// Equality
await User.where("role", "=", "admin");
await User.where("role", "$eq", "admin");
// Comparison
await User.where("age", ">=", 18);
await User.where("age", "$gte", 18);
await User.where("balance", "<", 100);
await User.where("balance", "$lt", 100);
// Not equal
await User.where("status", "!=", "banned");
await User.where("status", "<>", "banned");
await User.where("status", "$ne", "banned");
// Array membership
await User.where("status", "in", ["active", "pending"]);
await User.where("status", "$in", ["active", "pending"]);
// Contains substring (all equivalent)
await User.where("email", "include", "@gmail.com");
await User.where("email", "contains", "@gmail.com");
await User.where("email", "$include", "@gmail.com");
await User.where("email", "$contains", "@gmail.com");
WhereOptions\<T>¶
Options for configuring query behavior.
Definition:
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 of offset
offset?: number; // Number of records to skip
limit?: number; // Maximum records to return
attributes?: (keyof InferAttributes<T>)[]; // Fields to select
include?: { // Relationships to include
[relation: string]: boolean | WhereOptions<any>;
};
cursor?: Record<string, any>; // Cursor of the next page, returned by the previous query
deleted?: boolean; // Include soft-deleted records
}
Properties:
| Property | Type | Description |
|---|---|---|
where | object | Filter conditions with operator support |
order | "ASC" \| "DESC" \| object | Sort order. A bare string sorts by the @CreatedAt column |
skip | number | Number of records to skip (alias: offset) |
offset | number | Number of records to skip |
limit | number | Maximum records to return |
attributes | string[] | Specific fields to select |
include | object | Relationships to include |
cursor | Record<string, any> | Cursor of the next page |
deleted | boolean | Include soft-deleted records |
Example:
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>¶
The array where() returns, with the cursor of the next page attached.
Definition:
cursor is non-enumerable, so it survives neither JSON.stringify nor a spread. It carries a value while there are more pages to read.
Example:
let page = await User.where({}, { limit: 50 });
while (page.cursor) {
page = await User.where({}, { limit: 50, cursor: page.cursor });
}
Mutation Types¶
MutationOptions¶
The options object every mutation takes as its last argument.
Definition:
| Property | Type | Description |
|---|---|---|
hook | boolean | Runs the lifecycle hooks of the operation. Off by default |
tx | TransactionContext | Queues the operation in an atomic transaction |
Example:
await User.create({ name: "Ana" }, { hook: true });
await dynamite.tx(async (tx) => { await User.create({ name: "Ana" }, { tx }); });
DynamiteConfig¶
The client configuration. Extends DynamoDBClientConfig from the AWS SDK.
Definition:
interface DynamiteConfig extends DynamoDBClientConfig {
tables: Array<new (...args: any[]) => any>;
}
Example:
Best Practices¶
1. Always Use CreationOptional for Fields with Defaults¶
// Good
@Default(() => "active")
declare status: CreationOptional<string>;
// Bad - TypeScript will require status in create()
@Default(() => "active")
declare status: string;
2. Always Wrap Relationships in NonAttribute¶
// Good
@HasMany(() => Post, "user_id")
declare posts: NonAttribute<Post[]>;
// Bad - posts would be treated as a database column
@HasMany(() => Post, "user_id")
declare posts: Post[];
3. Use InferAttributes for Type-Safe Functions¶
// Good - type-safe parameter
function processUser(data: InferAttributes<User>) { ... }
// Bad - no type safety
function processUser(data: any) { ... }
4. Define Foreign Keys Explicitly¶
// Good - foreign key is declared
class Post extends Table<Post> {
declare user_id: string; // FK field
@BelongsTo(() => User, "id", "user_id")
declare author: NonAttribute<User | null>;
}
// Bad - foreign key not declared
class Post extends Table<Post> {
@BelongsTo(() => User, "id", "user_id")
declare author: NonAttribute<User | null>;
}