3 ms·
Thank you for creating Kiss ORM. I have even created a HackerNews account to be able to comment on it. I have been searching for this type of ORM in Typescript
by holgerw 6y ago
Thank you for creating Kiss ORM. I have even created a HackerNews account to be able to comment on it.
I have been searching for this type of ORM in Typescript for a while. I agree to write raw SQL for queries. So easy and expressive and one less layer of abstraction. I also agree on the value of the respository pattern and methods for CRUD operations to not write this SQL by hand. Making the loading of associations an explicit decision is also the right way to go. The Rails community has good experience with performance surprises of automatic loading of relationships.
Personally I found the most useful ORM in Ecto for the Elixir (Erlang) language: https://hexdocs.pm/ecto/Ecto.html https://hexdocs.pm/ecto/Ecto.html (ignoring the query capability). It follows very much the repository pattern like Kiss ORM. The API is a bit more succinct (you only define a schema for each table and use a generic repository instead of subclassing for each table) but that might be possible only due to Elixir's language capabilities like meta-programming.
One piece of Ecto that might be a win to implement in Kiss ORM is the "Changeset" pattern to give a canonical, succinct and productive solution to validate data (https://hexdocs.pm/ecto/Ecto.Changeset.html#content https://hexdocs.pm/ecto/Ecto.Changeset.html#content). For example have a look at how Ecto unifies validation (checked without hitting the DB) and constraints (checked by hitting the DB) in a single API. This type of functionality increases the usefulness of the repository's CRUD operations.
Thank's for your initiative to create KISS ORM. I will sure try it out and follow along it's evolution.
- holgerw 6y agoJust forgot to mention Ecto's "Multi API", that is worth knowing. Allows to construct a chain of operations as a data structure and to execute it later transactionally. You may even include operations that are part of transactional business logic but that do not hit the DB (like sending an email). (https://hexdocs.pm/ecto/Ecto.Multi.html#module-run https://hexdocs.pm/ecto/Ecto.Multi.html#module-run) As I understand KISS ORM's sequence function would also allow to express business logic transactionally and operations beyond the DB. Obviously the rollback would only effect the DB, but other failing operations can at least trigger the rollback, right? I think this is usefull as integration with external services (like email providers, payment APIs..) are really the source of runtime surprise that might fail a business operation and demand a DB rollback.
- Seb-C 6y agoThis multi-api indeed seems similar to the sequence function. If you can try-catch the failure in the external service, you can rollback the transaction with kiss-orm. Actually kiss-orm does not abstract the transaction itself, so you can do whatever you want. I just realized a flaw in my current implementation, which is that directly using the repository CRUD methods from inside the sequence (rather than a query) function would execute those operations outside the scope of the sequence.
- Seb-C 6y agoWow, thank you for the kind message! I did not know about Ecto. It is interesting, but I think more abstract than what I would like kiss-orm to become. About the ChangeSet stuff, from what I understood it is actually already possible in kiss-orm. The main difference being that I decided to not do the validation at runtime, but rely on typescript. At worst you could have a runtime SQL error (inserting the wrong type of data in the wrong column for example), but the queries would be safe from injection. You can definitely keep using kiss-orm with the default `any` type for the insert and update operation, but you can also specify it: https://github.com/Seb-C/kiss-orm#advanced-typings https://github.com/Seb-C/kiss-orm#advanced-typings This way, your typings have to be right to use those methods. Runtime validation of inputs should not be done in the repository/database/orm layer anyway :) .