Codync
무료 오픈소스 1:1 대안, Grok Bot과 Muse 대신
TypeScript용 타입 안전 PostgreSQL 전용 ORM으로, 깊은 관계 쿼리·미들웨어 지원·선언형 스키마 정의 제공
A type-safe, PostgreSQL-native ORM for TypeScript with deep relational querying, middleware support, and declarative schema definitions
개발 도구TypeScript · JavaScriptGitHub @casekit온라인운영자 미확인
써 보셨어요? 한 번만 눌러 주세요. 로그인은 필요 없어요.
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기메이커가 쓴 소개는 위의 한 줄이 전부입니다. 더 자세한 내용은 저장소 README에서 읽을 수 있습니다. 저장소 README ↗
README 전체를 불러오는 중입니다.
README 전문 보기 ↗A type-safe, PostgreSQL-native ORM for TypeScript with deep relational querying, middleware support, and declarative schema definitions.
npm add @casekit/orm @casekit/orm-cli @casekit/orm-migrate pg zod
pnpm orm init --directory ./src/db
// src/db/models/author.ts
import type { ModelDefinition } from "@casekit/orm";
import { sql } from "@casekit/sql";
export const author = {
fields: {
id: { type: "serial", primaryKey: true },
name: { type: "text" },
email: { type: "text", unique: true },
createdAt: { type: "timestamptz", default: sql`now()` },
},
relations: {
books: {
type: "1:N",
model: "book",
fromField: "id",
toField: "authorId",
},
},
} as const satisfies ModelDefinition;
// src/db/index.ts
import { orm, type Config } from "@casekit/orm";
import { snakeCase } from "es-toolkit";
import * as models from "./models/index.js";
const config = {
models,
naming: { column: snakeCase },
connection: { database: "myapp" },
} as const satisfies Config;
export const db = orm(config);
pnpm orm db push
import { $ilike } from "@casekit/orm";
const authorsWithBooks = await db.findMany("author", {
select: ["id", "name"],
include: {
books: {
select: ["id", "title"],
where: { published: true },
orderBy: [["title", "asc"]],
limit: 5,
},
},
where: {
email: { [$ilike]: "%@example.com" },
},
});
// Create
const author = await db.createOne("author", {
values: { name: "Jane", email: "[email protected]" },
returning: ["id", "createdAt"],
});
// Read
const authors = await db.findMany("author", {
select: ["id", "name"],
where: { name: { [$ilike]: "%john%" } },
orderBy: [["name", "asc"]],
limit: 10,
});
// Update
await db.updateOne("author", {
set: { name: "Jane Doe" },
where: { id: 1 },
});
// Delete
await db.deleteOne("author", {
where: { id: 1 },
});
await db.transact(async (tx) => {
const author = await tx.createOne("author", {
values: { name: "New Author", email: "[email protected]" },
returning: ["id"],
});
await tx.createOne("book", {
values: { title: "New Book", authorId: author.id },
});
});
Apply cross-cutting concerns like multi-tenancy or automatic timestamps:
const dbWithMiddleware = db.middleware([
tenancy({ org: currentOrg }),
userstamps({ user: currentUser }),
]);
// All queries automatically filtered by org and stamped with user
For complex queries, use raw SQL with type safety via Zod:
import { z } from "zod";
import { sql } from "@casekit/sql";
const results = await db.query(
z.object({ total: z.number() }),
sql`SELECT COUNT(*) as total FROM authors WHERE active = true`
);
| Package | Description |
|---|---|
@casekit/orm | Core ORM library |
@casekit/orm-cli | CLI for init, push, pull, generate |
@casekit/orm-migrate | Schema migration engine |
@casekit/orm-schema | Type definitions |
@casekit/orm-config | Configuration normalization |
@casekit/sql | SQL template literal builder |
Full documentation available at the docs site.
MIT