| Crates.io | revelation-songbook |
| lib.rs | revelation-songbook |
| version | 0.1.1 |
| created_at | 2025-12-26 10:53:17.430777+00 |
| updated_at | 2026-01-04 04:34:11.85036+00 |
| description | Songbook domain with ChordPro parser for Revelation project |
| homepage | |
| repository | https://github.com/Revelation-Path/revelation-songbook |
| max_upload_size | |
| id | 2005564 |
| size | 180,003 |
Songbook domain types with ChordPro parser for Rust applications.
revelation-songbook provides a complete solution for managing worship songs and hymnals in Rust applications. It includes:
Add to your Cargo.toml:
[dependencies]
revelation-songbook = "0.1"
With specific features:
[dependencies]
revelation-songbook = { version = "0.1", features = ["db", "api", "backend"] }
┌─────────────────────────────────────────────────────────────┐
│ Your Application │
├─────────────────────────────────────────────────────────────┤
│ revelation-songbook │
│ ┌─────────────────────┐ ┌─────────────────────────────┐ │
│ │ Domain Types │ │ Port Traits │ │
│ │ ───────────────── │ │ ───────────────────────── │ │
│ │ Song, Songbook │ │ SongRead, SongWrite │ │
│ │ Playlist, Edition │◄───│ SongbookRead, Search │ │
│ │ Chord, Note │ │ Favorites, History │ │
│ │ ParsedSong │ │ Playlist, Tags │ │
│ └─────────────────────┘ └─────────────────────────────┘ │
│ ┌─────────────────────────────────────────────────────────┐│
│ │ ChordPro Parser ││
│ │ Parse → Sections → Lines → Chords → Transpose ││
│ └─────────────────────────────────────────────────────────┘│
└─────────────────────────────────────────────────────────────┘
| Type | Description |
|---|---|
Song |
Full song with metadata, content, categories, tags |
SongSummary |
Lightweight song for lists |
Songbook |
Collection of songs (hymnal, songbook) |
SongbookEdition |
Specific edition of a songbook |
Playlist |
User-created song collection |
PlaylistItem |
Song in a playlist with ordering |
| Type | Description |
|---|---|
Chord |
Parsed chord with root, quality, bass note |
PositionedChord |
Chord with position in text |
Note |
Musical note (A-G with sharps/flats) |
ParsedSong |
Structured song from ChordPro parsing |
SongSection |
Verse, chorus, bridge, etc. |
SongLine |
Line of text with positioned chords |
| Type | Description |
|---|---|
SongCategory |
Enum: Worship, Hymn, Christmas, Easter, etc. |
SongTag |
User-defined tags |
SongFilters |
Filter criteria for song queries |
SongHistory |
User view history entry |
Parse ChordPro format into structured data:
use revelation_songbook::ChordProParser;
let content = r#"
{title: Amazing Grace}
{artist: John Newton}
{key: G}
{tempo: 80}
{start_of_verse: Verse 1}
[G]Amazing [G7]grace, how [C]sweet the [G]sound
That [G]saved a [Em]wretch like [D]me
{end_of_verse}
{start_of_chorus}
[G]I once was [G7]lost, but [C]now am [G]found
Was [G]blind, but [D]now I [G]see
{end_of_chorus}
"#;
let song = ChordProParser::parse(content);
assert_eq!(song.title, Some("Amazing Grace".into()));
assert_eq!(song.key, Some("G".into()));
assert_eq!(song.sections.len(), 2);
| Directive | Description |
|---|---|
{title: ...} |
Song title |
{subtitle: ...} |
Subtitle |
{artist: ...} |
Artist/composer |
{key: ...} |
Original key |
{tempo: ...} |
BPM |
{capo: ...} |
Capo position |
{start_of_verse} |
Begin verse section |
{start_of_chorus} |
Begin chorus section |
{start_of_bridge} |
Begin bridge section |
{end_of_*} |
End section |
Transpose chords with proper enharmonic handling:
use revelation_songbook::Chord;
let chord = Chord::parse("Am7").unwrap();
// Transpose up 2 semitones (use sharps)
let up = chord.transpose(2, false);
assert_eq!(up.to_string(), "Bm7");
// Transpose down 1 semitone (use flats)
let down = chord.transpose(-1, true);
assert_eq!(down.to_string(), "Abm7");
// Chord with bass note
let slash = Chord::parse("G/B").unwrap();
let transposed = slash.transpose(2, false);
assert_eq!(transposed.to_string(), "A/C#");
Port traits define interfaces for data access. Implement these in your adapters:
SongReadRead operations for songs:
pub trait SongRead: Send + Sync {
fn get_song(&self, id: Uuid) -> impl Future<Output = AppResult<Option<Song>>> + Send;
fn get_songs(&self, filters: &SongFilters) -> impl Future<Output = AppResult<Vec<SongSummary>>> + Send;
fn get_songs_by_songbook(&self, songbook_id: Uuid) -> impl Future<Output = AppResult<Vec<SongSummary>>> + Send;
}
SongWriteWrite operations for songs:
pub trait SongWrite: Send + Sync {
fn create_song(&self, song: CreateSong) -> impl Future<Output = AppResult<Song>> + Send;
fn update_song(&self, id: Uuid, song: UpdateSong) -> impl Future<Output = AppResult<Song>> + Send;
fn delete_song(&self, id: Uuid) -> impl Future<Output = AppResult<()>> + Send;
}
SongSearchFull-text search:
pub trait SongSearch: Send + Sync {
fn search(&self, query: &str, limit: i64) -> impl Future<Output = AppResult<Vec<SearchResult>>> + Send;
}
use revelation_songbook::{Song, SongCategory, CreateSong};
use uuid::Uuid;
let create = CreateSong {
songbook_id: None,
number: Some(1),
title: "Amazing Grace".into(),
title_alt: None,
author_lyrics: Some("John Newton".into()),
author_music: None,
translator: None,
year_written: Some(1779),
copyright: None,
original_key: Some("G".into()),
tempo: Some(80),
time_signature: Some("4/4".into()),
content: "{title: Amazing Grace}\n[G]Amazing grace...".into(),
categories: vec![SongCategory::Hymn],
tag_ids: vec![],
source_url: None,
};
use revelation_songbook::{Playlist, PlaylistItem};
let playlist = Playlist {
id: Uuid::new_v4(),
user_id: user_id,
name: "Sunday Service".into(),
description: Some("Songs for this week".into()),
is_public: false,
songs_count: 5,
};
| Feature | Default | Description |
|---|---|---|
db |
No | Adds sqlx::Type derives for PostgreSQL enum mapping |
api |
No | Adds utoipa::ToSchema derives for OpenAPI documentation |
backend |
No | Enables port traits (requires masterror for error handling) |
# Frontend/WASM - minimal, just types and parser
revelation-songbook = "0.1"
# Backend with PostgreSQL
revelation-songbook = { version = "0.1", features = ["db", "backend"] }
# Full backend with OpenAPI docs
revelation-songbook = { version = "0.1", features = ["db", "api", "backend"] }
We maintain high test coverage to ensure reliability:
The inner circle represents the entire project. Moving outward: folders, then individual files.
Each block represents a file. Size = number of statements, color = coverage level.
Hierarchical view from project to individual files.
| Crate | Purpose |
|---|---|
serde |
Serialization/deserialization |
uuid |
Unique identifiers |
chrono |
Date/time handling |
validator |
Input validation |
regex |
ChordPro parsing |
sqlx |
Database type derives (optional) |
utoipa |
OpenAPI schemas (optional) |
masterror |
Error handling for ports (optional) |
revelation-server - PostgreSQL adapters and REST APIrevelation-bible - Bible domain typesrevelation-user - User domain typesThis project is licensed under the MIT License (SPDX: MIT).
All files include SPDX license identifiers for REUSE compliance.
Part of the Revelation Project - Building tools for Bible study and worship.