a database layer insipred by caqti and ecto

chore: prepare for v0.1.0 publication

- Add root README.md with links to docs/
- Fix Error.to_string -> Error.show_db_error in documentation
- Remove placeholder bin/ directory
- Set version 0.1.0 in dune-project and opam files

+86
README.md
··· 1 + # repodb 2 + 3 + An Ecto-inspired database toolkit for OCaml. 4 + 5 + repodb brings the elegance of Elixir's Ecto to OCaml: type-safe queries, composable changesets, and clean separation between your domain and the database. 6 + 7 + ## Features 8 + 9 + - **Schemas** - Define your data structures with typed fields 10 + - **Changesets** - Validate and track changes before persisting 11 + - **Query DSL** - Build type-safe queries with a composable API 12 + - **Repo** - Clean abstraction over database operations 13 + - **Associations** - Define relationships (has_many, belongs_to, many_to_many) 14 + - **Preloading** - Efficiently load associations, avoiding N+1 queries 15 + - **Multi** - Compose multiple operations in a single transaction 16 + - **Migrations** - Version your database schema 17 + 18 + ## Quick Example 19 + 20 + ```ocaml 21 + (* Define a schema *) 22 + let users_table = Schema.table "users" 23 + 24 + type user = { id : int; name : string; email : string; age : int } 25 + 26 + let name_field = 27 + Field.make ~table_name:"users" ~name:"name" ~ty:Types.string 28 + ~get:(fun u -> u.name) ~set:(fun v u -> { u with name = v }) () 29 + 30 + (* Create and validate a changeset *) 31 + let empty_user = { id = 0; name = ""; email = ""; age = 0 } 32 + 33 + let changeset = 34 + Changeset.create empty_user 35 + |> Changeset.cast [("name", "Alice"); ("email", "alice@example.com")] 36 + ~fields:[name_field; email_field] 37 + |> Changeset.validate_required [name_field; email_field] 38 + |> Changeset.validate_format email_field ~pattern:"^[^@]+@[^@]+$" 39 + 40 + (* Build and execute queries *) 41 + let query = 42 + Query.(from users_table 43 + |> where Expr.(raw "age" > int 18) 44 + |> order_by ~direction:Desc (Expr.raw "created_at") 45 + |> limit 10) 46 + 47 + let users = Repo.all_query conn query ~decode:decode_user 48 + ``` 49 + 50 + ## Documentation 51 + 52 + - [Getting Started](docs/getting-started.md) - Installation and basic setup 53 + - [Schemas](docs/schemas.md) - Defining tables and columns 54 + - [Changesets](docs/changesets.md) - Data validation and change tracking 55 + - [Queries](docs/queries.md) - Building and executing queries 56 + - [Repo](docs/repo.md) - Database operations 57 + - [Associations](docs/associations.md) - Relationships and preloading 58 + - [Transactions](docs/transactions.md) - Multi and transaction handling 59 + - [Migrations](docs/migrations.md) - Database schema versioning 60 + 61 + ## Packages 62 + 63 + | Package | Description | 64 + |---------|-------------| 65 + | `repodb` | Core library with schemas, changesets, queries | 66 + | `repodb-sqlite` | SQLite driver | 67 + | `repodb-postgresql` | PostgreSQL driver | 68 + 69 + ## Installation 70 + 71 + ```bash 72 + opam install repodb repodb-sqlite # or repodb-postgresql 73 + ``` 74 + 75 + ## Philosophy 76 + 77 + repodb follows Ecto's philosophy: 78 + 79 + 1. **Explicit over implicit** - No magic, every operation is visible 80 + 2. **Composable** - Small functions that combine well 81 + 3. **Separation of concerns** - Domain logic separate from persistence 82 + 4. **Fail fast** - Validate early with changesets 83 + 84 + ## License 85 + 86 + ISC License
-5
bin/dune
··· 1 - (executable 2 - (package repodb) 3 - (public_name repodb) 4 - (name main) 5 - (libraries repodb))
-1
bin/main.ml
··· 1 - let () = print_endline "repodb - Ecto-like database toolkit for OCaml"
+1 -1
docs/repo.md
··· 394 394 | Error (Error.Query_failed msg) -> Printf.printf "Query error: %s\n" msg 395 395 | Error (Error.Constraint_violation { constraint_name; message }) -> 396 396 Printf.printf "Constraint %s violated: %s\n" constraint_name message 397 - | Error e -> Printf.printf "Error: %s\n" (Error.to_string e) 397 + | Error e -> Printf.printf "Error: %s\n" (Error.show_db_error e) 398 398 ``` 399 399 400 400 ## Next Steps
+2 -2
docs/transactions.md
··· 80 80 let user : user = Multi.get_exn results "user" in 81 81 Printf.printf "Created user with ID: %d\n" user.id 82 82 | Error { failed_operation; error; _ } -> 83 - Printf.printf "Failed at %s: %s\n" failed_operation (Error.to_string error) 83 + Printf.printf "Failed at %s: %s\n" failed_operation (Error.show_db_error error) 84 84 ``` 85 85 86 86 ### Dependent Operations ··· 245 245 246 246 | Error { failed_operation; error; completed } -> 247 247 Printf.printf "Failed at operation: %s\n" failed_operation; 248 - Printf.printf "Error: %s\n" (Error.to_string error); 248 + Printf.printf "Error: %s\n" (Error.show_db_error error); 249 249 (* completed contains results from operations that succeeded before failure *) 250 250 let partial_user : user option = Multi.get completed "user" in 251 251 ...
+1 -1
dune-project
··· 1 1 (lang dune 3.20) 2 2 3 3 (name repodb) 4 - 4 + (version 0.1.0) 5 5 (source 6 6 ; (tangled @gdiazlo.tngl.sh/hcs) 7 7 (uri git+https://tangled.org/gdiazlo.tngl.sh/repodb))
+1
repodb-postgresql.opam
··· 1 1 # This file is generated by dune, edit dune-project instead 2 2 opam-version: "2.0" 3 + version: "0.1.0" 3 4 synopsis: "PostgreSQL driver for repodb" 4 5 description: 5 6 "PostgreSQL driver implementation for repodb using the postgresql-ocaml library."
+1
repodb-sqlite.opam
··· 1 1 # This file is generated by dune, edit dune-project instead 2 2 opam-version: "2.0" 3 + version: "0.1.0" 3 4 synopsis: "SQLite driver for repodb" 4 5 description: 5 6 "SQLite driver implementation for repodb using the sqlite3-ocaml library."
+1
repodb.opam
··· 1 1 # This file is generated by dune, edit dune-project instead 2 2 opam-version: "2.0" 3 + version: "0.1.0" 3 4 synopsis: "Ecto-like database toolkit for OCaml" 4 5 description: 5 6 "repodb is a database toolkit inspired by Elixir's Ecto. It provides type-safe query building, schema definitions, changesets for data validation, and database migrations."