TypeScript Client¶
TypeScript/JavaScript client for ORMDB with adapters for popular ORMs.
Installation¶
Direct Client¶
Basic Usage¶
import { OrmdbClient } from "@ormdb/client";
const client = new OrmdbClient("http://localhost:8080");
// Query
const result = await client.query("User", {
fields: ["id", "name", "email"],
filter: { field: "status", op: "eq", value: "active" },
limit: 10,
});
// Insert
const insertResult = await client.insert("User", {
name: "Alice",
email: "alice@example.com",
});
// Update
await client.update("User", insertResult.insertedIds[0], {
name: "Alice Smith",
});
// Delete
await client.delete("User", insertResult.insertedIds[0]);
Configuration¶
const client = new OrmdbClient({
baseUrl: "http://localhost:8080",
timeout: 30000,
headers: {
Authorization: "Bearer token",
},
retry: {
maxRetries: 3,
retryDelay: 1000,
},
});
Type Safety¶
interface User {
id: string;
name: string;
email: string;
age?: number;
}
const result = await client.query<User>("User", {
fields: ["id", "name", "email", "age"],
});
// result.entities is User[]
for (const user of result.entities) {
console.log(user.name); // TypeScript knows this is string
}
Prisma Adapter¶
Use familiar Prisma-style API:
import { createPrismaClient } from "@ormdb/client/prisma";
const prisma = createPrismaClient("http://localhost:8080");
// Find many
const users = await prisma.user.findMany({
where: {
status: "active",
age: { gte: 18 },
},
orderBy: { name: "asc" },
take: 10,
});
// Find unique
const user = await prisma.user.findUnique({
where: { id: userId },
});
// Create
const newUser = await prisma.user.create({
data: { name: "Alice", email: "alice@example.com" },
});
// Update
await prisma.user.update({
where: { id: userId },
data: { status: "inactive" },
});
// Delete
await prisma.user.delete({
where: { id: userId },
});
// Include relations
const usersWithPosts = await prisma.user.findMany({
include: {
posts: {
where: { published: true },
},
},
});
Drizzle Adapter¶
Type-safe queries with Drizzle-style API:
import { drizzle, ormdbTable, text, integer, boolean, eq } from "@ormdb/client/drizzle";
// Define schema
const users = ormdbTable("User", {
id: text("id").primaryKey(),
name: text("name").notNull(),
email: text("email").notNull(),
age: integer("age"),
active: boolean("active").default(true),
});
const db = drizzle("http://localhost:8080");
// Select
const activeUsers = await db
.select()
.from(users)
.where(eq(users.active, true));
// Insert
await db.insert(users).values({
name: "Alice",
email: "alice@example.com",
});
// Update
await db
.update(users)
.set({ active: false })
.where(eq(users.id, "some-id"));
// Delete
await db.delete(users).where(eq(users.id, "some-id"));
TypeORM Adapter¶
import { OrmdbDataSource, Entity, Column, PrimaryGeneratedColumn } from "@ormdb/client/typeorm";
@Entity()
class User {
@PrimaryGeneratedColumn("uuid")
id: string;
@Column()
name: string;
@Column()
email: string;
}
const dataSource = new OrmdbDataSource({
url: "http://localhost:8080",
entities: [User],
});
await dataSource.initialize();
const userRepo = dataSource.getRepository(User);
// Find
const users = await userRepo.find({
where: { name: "Alice" },
});
// Create
const user = await userRepo.save({
name: "Alice",
email: "alice@example.com",
});
// Query builder
const results = await userRepo
.createQueryBuilder("user")
.where("user.age > :age", { age: 18 })
.getMany();
Kysely Adapter¶
import { Kysely } from "kysely";
import { OrmdbDialect } from "@ormdb/client/kysely";
interface Database {
User: { id: string; name: string; email: string };
Post: { id: string; title: string; userId: string };
}
const db = new Kysely<Database>({
dialect: new OrmdbDialect({ baseUrl: "http://localhost:8080" }),
});
const users = await db
.selectFrom("User")
.selectAll()
.where("age", ">", 18)
.orderBy("name", "asc")
.execute();
Error Handling¶
import { OrmdbError } from "@ormdb/client";
try {
await client.insert("User", { email: "existing@example.com" });
} catch (error) {
if (error instanceof OrmdbError) {
switch (error.code) {
case "UNIQUE_VIOLATION":
console.log("Email already exists");
break;
case "FOREIGN_KEY_VIOLATION":
console.log("Invalid reference");
break;
case "VALIDATION_ERROR":
console.log("Invalid data:", error.message);
break;
default:
console.log("Error:", error.message);
}
}
}
Best Practices¶
- Use typed clients for compile-time safety
- Choose the right adapter for your existing codebase
- Handle errors appropriately
- Use includes sparingly - deep nesting impacts performance