Skip to content

Commit 49ca4ad

Browse files
committed
Initial closure-tree crate scaffolding
0 parents  commit 49ca4ad

File tree

14 files changed

+1416
-0
lines changed

14 files changed

+1416
-0
lines changed

.github/workflows/ci.yml

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
- master
8+
pull_request:
9+
10+
env:
11+
CARGO_TERM_COLOR: always
12+
13+
jobs:
14+
test:
15+
runs-on: ubuntu-latest
16+
env:
17+
CLOSURE_TREE_TEST_DATABASE_URL: postgres://closure_tree:closure_tree_pass@localhost:5432/closure_tree_test
18+
services:
19+
postgres:
20+
image: postgres:17
21+
env:
22+
POSTGRES_USER: closure_tree
23+
POSTGRES_PASSWORD: closure_tree_pass
24+
POSTGRES_DB: closure_tree_test
25+
ports:
26+
- 5432:5432
27+
options: >-
28+
--health-cmd="pg_isready -U postgres"
29+
--health-interval=10s
30+
--health-timeout=5s
31+
--health-retries=5
32+
33+
steps:
34+
- uses: actions/checkout@v5
35+
36+
- name: Install Rust toolchain
37+
uses: dtolnay/rust-toolchain@stable
38+
with:
39+
components: clippy,rustfmt
40+
41+
- name: Check formatting
42+
run: cargo fmt --all -- --check
43+
44+
- name: Lint
45+
run: cargo clippy --all-targets -- -D warnings
46+
47+
- name: Run tests
48+
run: cargo test

Cargo.toml

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
[package]
2+
name = "closure-tree"
3+
version = "0.0.1"
4+
edition = "2021"
5+
description = "Closure Tree support for SeaORM (PostgreSQL)."
6+
readme = "README.md"
7+
license = "MIT"
8+
repository = "https://github.com/ClosureTree/closure-tree-rs"
9+
homepage = "https://github.com/ClosureTree/closure-tree-rs"
10+
keywords = ["sea-orm", "hierarchy", "tree", "postgres", "closure-tree"]
11+
categories = ["database", "data-structures"]
12+
13+
[dependencies]
14+
sea-orm = { version = "1.1", default-features = false, features = [
15+
"macros",
16+
"runtime-tokio-rustls",
17+
"sqlx-postgres",
18+
"mock",
19+
] }
20+
sqlx = { version = "0.8", default-features = false, features = [
21+
"runtime-tokio-rustls",
22+
"postgres",
23+
] }
24+
async-trait = "0.1"
25+
thiserror = "2"
26+
once_cell = "1"
27+
serde = { version = "1", features = ["derive"] }
28+
serde_json = "1"
29+
crc32fast = "1"
30+
closure-tree-macros = { version = "0.0.1", path = "closure-tree-macros" }
31+
32+
[dev-dependencies]
33+
tokio = { version = "1.47", features = ["rt-multi-thread", "macros"] }
34+
35+
[patch.crates-io]
36+
closure-tree-macros = { path = "closure-tree-macros" }

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2024 ClosureTree
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
# closure-tree (Rust)
2+
3+
A SeaORM-friendly port of Ruby's [`closure_tree`](https://github.com/ClosureTree/closure_tree).
4+
5+
## Status
6+
7+
Early preview (`0.0.1`). PostgreSQL only. Contributions welcome.
8+
9+
## Quickstart
10+
11+
```toml
12+
[dependencies]
13+
closure-tree = "0.0.1"
14+
```
15+
16+
```rust
17+
use closure_tree::ClosureTreeRepository;
18+
use closure_tree::ClosureTreeModelDerive as ClosureTreeModel;
19+
use sea_orm::entity::prelude::*;
20+
21+
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, ClosureTreeModel)]
22+
#[sea_orm(table_name = "nodes")]
23+
#[closure_tree(hierarchy_module = "crate::entity::node_hierarchy", hierarchy_table = "node_hierarchies")]
24+
pub struct Model {
25+
#[sea_orm(primary_key)]
26+
pub id: i32,
27+
pub parent_id: Option<i32>,
28+
pub name: String,
29+
}
30+
31+
#[tokio::main]
32+
async fn main() -> Result<(), Box<dyn std::error::Error>> {
33+
let db = sea_orm::Database::connect("postgres://...").await?;
34+
let repo = ClosureTreeRepository::<entity::node::Model>::new();
35+
36+
let _leaf = repo
37+
.find_or_create_by_path(&db, &["root", "child", "leaf"])
38+
.await?;
39+
40+
Ok(())
41+
}
42+
```
43+
44+
## Features
45+
46+
* Derive macro for SeaORM models (`#[derive(ClosureTreeModel)]`).
47+
* Repository helpers (`parent`, `descendants`, `find_by_path`, `find_or_create_by_path`, etc.).
48+
* Advisory locks via `pg_advisory_lock`, rebuild utilities.
49+
* Integration test against a Docker Postgres instance.
50+
51+
## Limitations
52+
53+
* PostgreSQL only.
54+
* Ordering, `hash_tree`, dependent strategies, and some Ruby APIs are not yet ported.
55+
* Advisory lock is limited to Postgres advisory locks; no MySQL adapter yet.
56+
57+
## Development
58+
59+
```
60+
cargo fmt
61+
cargo clippy --all-targets -- -D warnings
62+
cargo test
63+
```
64+
65+
Requires Docker Postgres at `postgres://closure_tree:closure_tree_pass@localhost:5434/closure_tree_test` (see `tests/postgres.rs`).

closure-tree-macros/Cargo.toml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
[package]
2+
name = "closure-tree-macros"
3+
version = "0.0.1"
4+
edition = "2021"
5+
description = "Procedural macros for closure-tree."
6+
readme = "../README.md"
7+
license = "MIT"
8+
repository = "https://github.com/ClosureTree/closure-tree-rs"
9+
homepage = "https://github.com/ClosureTree/closure-tree-rs"
10+
11+
[lib]
12+
proc-macro = true
13+
14+
[dependencies]
15+
proc-macro2 = "1"
16+
quote = "1"
17+
syn = { version = "2", features = ["full"] }

0 commit comments

Comments
 (0)