use v6.e.PREVIEW; #| Post database unit module DB; use Pandoc; use JSON::Class:auth; use DB::Post; use DB::BlogMeta; use DB::MarkdownPost; use DB::IdrisPost; use DB::PlaceholderPost; subset PostTypes where MarkdownPost:D | IdrisPost:D | PlaceholderPost:D; #| The top level posts database 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{Int} of PostTypes = %(); #| The post id to use for placeholder posts has Int $.placeholder-id = 0; #| Get the next unused post ID method next-post-id(--> Int) { if %!posts.elems > 0 { %!posts.keys.max + 1 } else { 0 } } #| Insert a new post to the DB, returning its id method insert-post(PostTypes $post --> Int) { my $id = self.next-post-id; %!posts{$id} = $post; $id } #| Initialize a new database method init(BlogMeta:D $meta --> PostDB:D) { 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 }