use database directory instead of database file

This commit is contained in:
Nathan McCarty 2025-02-02 17:57:27 -05:00
parent fc04245162
commit 3b0e34e66e
7 changed files with 80 additions and 51 deletions

View file

@ -12,29 +12,18 @@ use DB::MarkdownPost;
use DB::IdrisPost;
use DB::PlaceholderPost;
class Posts is json(
:dictionary()
:keyof(Int:D),
MarkdownPost:D,
IdrisPost:D,
PlaceholderPost:D,
)) {}
subset PostTypes where MarkdownPost:D | IdrisPost:D | PlaceholderPost:D;
#| The top level posts database
class PostDB is json(:pretty) {
#| The metadat for the blog
class PostDB {
#| The metadata for the blog
has BlogMeta:D $.meta is required;
#| A mapping from post ids to posts
has %.posts is Posts;
# has %.posts is Posts;
has %.posts{Int} of PostTypes = %();
#| The post id to use for placeholder posts
has Int $.placeholder-id = 0;
method TWEAK() {
%!posts := Posts.new unless %!posts;
}
#| Get the next unused post ID
method next-post-id(--> Int) {
if %!posts.elems > 0 {
@ -53,11 +42,57 @@ class PostDB is json(:pretty) {
#| Initialize a new database
method init(BlogMeta:D $meta --> PostDB:D) {
my %posts is Posts = Posts.new;
my %posts{Int} of PostTypes = %();
%posts{0} = PlaceholderPost.empty;
PostDB.new(
meta => $meta,
posts => %posts,
)
}
#| Write a database to a directory
method write(IO::Path:D $dir) {
my $posts-dir = $dir.add('posts/');
# Make sure directory structrue exists
mkdir $dir unless $dir.e;
mkdir $posts-dir unless $posts-dir.e;
# Write out metadata
# TODO: Track changes and only write changed files
$dir.add('meta.json').spurt: $!meta.to-json;
# Write out posts (ids are the filename)
for %!posts.kv -> $key, $value {
$posts-dir.add("$key.json").spurt: $value.to-json;
}
}
}
sub read-db(IO::Path:D $dir --> PostDB:D) is export {
my $posts-dir = $dir.add('posts/');
die "DB directory does not exist" unless $dir.e;
die "posts directory does not exist" unless $posts-dir.e;
# Read metadata
my $meta = BlogMeta.from-json: $dir.add('meta.json').slurp;
# Read posts
my %posts{Int} of PostTypes = %();
for dir $posts-dir -> $post {
my $id = $post.extension("").basename.Int;
# TODO: Dejankify this, maybe see if we can work with parsed, but
# unmarshalled json
given $post.slurp {
when /'"placeholder": true'/ {
%posts{$id} = PlaceholderPost.from-json: $_;
}
when /'"markdown": true'/ {
%posts{$id} = MarkdownPost.from-json: $_;
}
when /'"idris": true'/ {
%posts{$id} = IdrisPost.from-json: $_;
}
default {
die "Unsupported post type: $post";
}
}
}
# Build db structure
PostDB.new: meta => $meta, posts => %posts
}