agiletiger / ojotas

The database-first ORM
MIT License
7 stars 4 forks source link
database mysql orm sql

Ojotas database-first ORM

Disclaimer

In the following section I'll do some strong arguments against ORMs. I'm not saying you should not use them if they are working for your use cases.
ORMs are a great tool that work most of the time. Ojotas is here to help in the cases ORMs can't.

Rationale

Key Features

Providing feedback

There is an example app ojotas-test-app to play with ojotas orm and provide feedback

Roadmap

V1

V2

Example

You have this config

{
"aliases": {
"u": "users",
"p": "posts"
},
"relations": {
"users": {
"posts": ["hasMany", "posts"] 
}
}
}

you have a selectAllUsersWithPosts.sql file like this (notice you are using inner join)

select u.name, p.title, p.content from users u inner join posts p on u.id = p.user_id

this is the type the ORM will generate for a query without params

export interface ISelectAllUsersWithPostsQueryResultItem {
name: string;
posts: NonEmptyArray<{ // ojotas will tell you with the type that this array cannot be empty because of the inner join
title?: string;
content?: string;
}>;
}

but if you use a left join

select u.name, p.title, p.content from users u left join posts p on u.id = p.user_id

this is the type the ORM will generate for a query without params

export interface ISelectAllUsersWithPostsQueryResultItem {
name: string;
posts: PossiblyEmptyArray<{ // ojotas will tell you with the type that this array could be empty because of the left join
title?: string;
content?: string;
}>;
}

API

/** 
 * @param {Connection} connection - active connection for the db you want to query.
 * @param {Descriptor<T>} descriptor - generated representation of the original sql file
 */
query<T>(connection: Connection, descriptor: Descriptor<T>): Promise<T[]>;

Previous work that inspired this project

https://jawj.github.io/zapatos/
What I like about Zapatos is the idea of talking to the database to generate types.
It generates types for all tables, in the case of Ojotas we only generate types of what you are using through the queries.
Also the idea of Everyday CRUD is noble and worth exploring for Ojotas see discussion
What I don't like is how the user needs to manually write the types. Ojotas automates that.

https://github.com/adelsz/pgtyped
Ojotas has the same approach of creating types from the queries as pgtyped.
What pgtypes does not provide is the mapping when including 1 to N relations in the query.
I'm not convinced of the magic pgtyped does with the special annotations but I haven't properly tested yet.
Also It does some dark magic at runtime wheareas Ojotas gives you the exact sql it will execute at compile time.
Nonetheless it seems a very good alternative if you are using PostgreSQL.

https://sqlc.dev/
Same ideas as pgtyped but implemented in Go.
I think I like more the macros because I can see the generated code than pgtyped's special annotations.

https://github.com/Seb-C/kiss-orm
I agree a lot with some of their philosophy points:

https://github.com/SweetIQ/schemats
I took the code to query the database and get the types from there.

Interesting links