Korm
KORM, an elegant and lightning-fast ORM for all your concurrent and async needs. Inspired by the highly popular Django Framework, KORM offers similar functionality with the added bonus of performance
Install / Use
/learn @kamalshkeir/KormREADME
Introducing Korm - the elegant, lightning-fast ORM/Framework for all your needs, see benchmarks. Inspired by the highly popular Django Framework, Korm offers similar functionality with the added bonus of performance
It is also composable, allowing for integration with a network websocket PubSub using WithBus when you want to synchronise your data between multiple Korm or WithDashboard to have a complete setup of server bus and Admin Dashboard.
Why settle for less when you can have the best ?
- Django become very hard to work with when you need concurrency and async, you will need django channels and a server like daphne or uvicorn, Go have the perfect implementation
- Django can handle at most 300 request per second, Go handle 44,000 requests per second (benchmarks done on my machine)
- The API is also more user-friendly and less verbose than Django's
- Deploying an executable binary file using Korm , with automatic TLS Let's encrypt, a built-in Admin Dashboard, Interactive Shell, Eventbus to communicate between multiple Korm applications is pretty neat
- Additionally, its caching system uses goroutines and channels to efficiently to clean the cache when rows or tables are created, updated, deleted, or dropped
It Has :
-
<strong>New:</strong> When using korm.WithDashboard, now you have access to all logs in realtime (websockets) from admin dashboard when you log using lg pkg. By default only 10 last logs are keeped in memory, you can increase it using lg.SaveLogs(50) for keeping last 50 logs
-
<strong>New:</strong> Automatic check your structs (schema) against database tables, prompt you with changes, and so it can add or remove columns by adding or removing fields to the struct, it is Disabled by default, use
korm.EnableCheck()to enable it -
<strong>New:</strong> Handle Nested or Embeded structs and slice of structs through joins, like sqlx, but sqlx doesn't handle slice of structs
-
<strong>New:</strong> korm.QueryNamed, QueryNamedS, korm.ExecNamed, korm.ExecContextNamed and WhereNamed(query string, args map[string]any) like :Where("email = :email",map[string]any{"email":"abc@mail.com"})
-
<strong>New:</strong> korm.LogsQueries() that log statements and time tooked by sql queries
-
<a href="#swagger-documentation">Auto Docs with Model API and video tutoriel </a><a href="https://www.youtube.com/watch?v=r7rbMrTkVek"> <img src="https://user-images.githubusercontent.com/54605903/217871012-9c5dc1da-25bd-47d5-ac9e-c3acee7178d5.svg" width="auto" height="50px">
</a> -
<a href="#swagger-documentation">Swagger Documentation and tutorial </a><a href="https://www.youtube.com/watch?v=RupARTkPzf4"> <img src="https://user-images.githubusercontent.com/54605903/217871012-9c5dc1da-25bd-47d5-ac9e-c3acee7178d5.svg" width="auto" height="50px">
</a> -
PPROF Go profiling tool and Metrics Prometheus
-
Admin dashboard with ready offline and installable PWA (using /static/sw.js and /static/manifest.webmanifest). All statics mentionned in
sw.jswill be cached and served by the service worker, you can inspect the Network Tab in the browser to check it -
Shared Network Bus allowing you to send and recv data in realtime using pubsub websockets between your ORMs, so you can decide how you data will be distributed between different databases, see Example
-
Built-in Authentication using
korm.Auth,korm.Adminorkorm.BasicAuthmiddlewares, whenever Auth and Admin middlewares are used, you get access to the.Usermodel and variable.IsAuthenticatedfrom any template html like this example admin_nav.html -
Interactive Shell, to CRUD in your databases from command line, use
korm.WithShell(), ⚠️ if dashboard used, korm.WithShell should be after WithDashboard -
AutoMigrate directly from struct
-
Compatible with official database/sql, so you can do your queries yourself using sql.DB `korm.GetConnection()``, and overall a painless integration of your existing codebases using database/sql
-
Router/Mux accessible from the serverBus after calling
korm.WithBus(...opts)orkorm.WithDashboard(addr, ...opts) -
Hooks : OnInsert OnSet OnDelete and OnDrop
-
many to many relationships
-
GENERATED ALWAYS AS tag added (all dialects)
-
Concatination and Length support for
Whereand for tags:checkandgenerated(all dialects) -
Support for foreign keys, indexes , checks,... See all
-
Kenv load env vars to struct
-
Python Bus Client
pip install ksbus
All drivers concurrent safe read and write
Supported databases:
- Sqlite
- Mysql
- Maria
- Postgres
- Cockroach
Installation
go get -u github.com/kamalshkeir/korm@latest
Drivers moved outside this package to not get them all in your go.mod file
go get -u github.com/kamalshkeir/sqlitedriver@latest
go get -u github.com/kamalshkeir/pgdriver@latest
go get -u github.com/kamalshkeir/mysqldriver@latest
Global Vars
// Debug when true show extra useful logs for queries executed for migrations and queries statements
Debug = false
// FlushCacheEvery execute korm.FlushCache() every 10 min by default, you should not worry about it, but useful that you can change it
FlushCacheEvery = 10 * time.Minute
// SetCacheMaxMemory set max size of each cache cacheAllS AllM ...
korm.SetCacheMaxMemory(megaByte int) // default maximum of 50 Mb , cannot be lower
// Connection pool
MaxOpenConns = 20
MaxIdleConns = 20
MaxLifetime = 30 * time.Minute
MaxIdleTime = 15 * time.Minute
Connect to a database
// sqlite
// go get github.com/kamalshkeir/sqlitedriver
err := korm.New(korm.SQLITE, "dbName", sqlitedriver.Use()) // Connect
// postgres, cockroach
// go get github.com/kamalshkeir/pgdriver
err := korm.New(korm.POSTGRES,"dbName", pgdriver.Use(), "user:password@localhost:5432") // Connect
// mysql, maria
// go get github.com/kamalshkeir/mysqldriver
err := korm.New(korm.MYSQL,"dbName", mysqldriver.Use(), "user:password@localhost:3306") // Connect
korm.Shutdown(databasesName ...string) error
Hello world example
package main
import (
"fmt"
"time"
"github.com/kamalshkeir/lg"
"github.com/kamalshkeir/korm"
"github.com/kamalshkeir/sqlitedriver"
)
type Class struct {
Id uint `korm:"pk"`
Name string
Students []Student
}
type Student struct {
Id uint `korm:"pk"`
Name string
Class uint `korm:"fk:classes.id:cascade:cascade"`
Classes Class
}
func main() {
err := korm.New(korm.SQLITE, "db", sqlitedriver.Use())
if lg.CheckError(err) {
return
}
defer korm.Shutdown()
server := korm.WithDashboard(":9313")
korm.WithShell() // ⚠️ if dashboard used, korm.WithShell should be after WithDashboard
err = korm.AutoMigrate[Class]("classes")
lg.CheckError(err)
err = korm.AutoMigrate[Student]("students")
lg.CheckError(err)
// go run main.go shell to createsuperuser
// connect to admin and create some data to query
// nested
