diff --git a/src/db/init.ts b/src/db/init.ts new file mode 100644 index 0000000..424e73f --- /dev/null +++ b/src/db/init.ts @@ -0,0 +1,95 @@ +import { readdir } from 'node:fs/promises'; +import { openPostMarkdownFile, parsePostMetadata } from '@blog/post/post-reader'; +import { PostMeta } from '@blog/model/PostMeta'; +import db from '@blog/db/memory'; + +const createPostSql: string = ` +CREATE TABLE posts ( + id INTEGER PRIMARY KEY, + title TEXT NOT NULL, + slug TEXT NOT NULL, + is_draft INTEGER DEFAULT 0, + description TEXT, + published_date DATE, + raw_content TEXT +) +`; + +const createAuthorSql: string = ` +CREATE TABLE authors ( + id INTEGER PRIMARY KEY, + name TEXT, + email TEXT +) +`; + +const createTagsSql: string = ` +CREATE TABLE tags ( + id INTEGER PRIMARY KEY, + tag TEXT UNIQUE +) +`; + +const createPostsTagsSql: string = ` +CREATE TABLE posts_tags ( + tag_id TEXT, + post_id INTEGER, + + FOREIGN KEY (tag_id) REFERENCES tags(id) ON DELETE CASCADE, + FOREIGN KEY (post_id) REFERENCES posts(id) ON DELETE CASCADE +) +`; + +const createPostHtmlCache = ` +CREATE TABLE post_html_cache ( + id INTEGER PRIMARY KEY, + post_id INTEGER, + content TEXT, + + FOREIGN KEY (post_id) REFERENCES posts(id) ON DELETE CASCADE +); +`; + +export async function setupDb(): Promise { + console.log({ message: "Setting up the Database..." }); + console.log({ message: "Creating the Posts table..." }); + db.query(createPostSql).run(); + + console.log({ message: "Creating Authors table..." }); + db.query(createAuthorSql).run(); + + console.log({ message: "Creating Tags table..." }); + db.query(createTagsSql).run(); + + console.log({ message: "Creating Post and Tags relationships..." }); + db.query(createPostsTagsSql).run(); + + console.log({ message: "Creating HTML cache table..." }); + db.query(createPostHtmlCache).run(); +} + + +export async function readPostsToDatabase(postPath: string): Promise { + const posts = new Array(); + const createPostSql: string = ` +INSERT INTO posts (title, slug, description, is_draft, published_date, raw_content) +VALUES ($title, $slug, $description, $is_draft, $published_date, $raw_content); +`; + + const fileList = await readdir(postPath); + for (const file of fileList) { + const contents: string = await openPostMarkdownFile(postPath + "/" + file); + const post = parsePostMetadata(contents); + + const postQuery = db.prepare(createPostSql); + postQuery.run({ + $title: post.meta.title, + $slug: file, + $description: post.meta.description, + $is_draft: post.meta.draft ?? false, + $published_date: post.meta.date.toString(), + $raw_content: post.content + }); + console.log({ message: "Added " + post.meta.title + " to the database." }); + } +} diff --git a/src/db/memory.ts b/src/db/memory.ts new file mode 100644 index 0000000..a48a547 --- /dev/null +++ b/src/db/memory.ts @@ -0,0 +1,4 @@ +import { Database } from 'bun:sqlite'; + +const db = new Database(":memory:"); +export default db; diff --git a/src/index.tsx b/src/index.tsx index 7436dbd..2bae649 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -4,6 +4,7 @@ import { Page } from '@blog/templates/Page'; import home from '@blog/routes/home'; import posts from '@blog/routes/posts'; import type { SiteMeta } from '@blog/model/SiteMeta'; +import { setupDb, readPostsToDatabase } from '@blog/db/init'; declare module 'hono' { interface ContextRenderer { @@ -11,25 +12,38 @@ declare module 'hono' { } } -const app = new Hono(); +async function main() { + console.log({ message: "Starting the Blog application..." }); + const app = new Hono(); -// Render the JSX views -app.get( - '*', - jsxRenderer( - ({ children, meta }) => { - return ({children}); - }, - { - docType: true - } - ) -); + // Render the JSX views + console.log({ message: "Bootstrapping the view layer..." }); + app.get( + '*', + jsxRenderer( + ({ children, meta }) => { + return ({children}); + }, + { + docType: true + } + ) + ); -// read all posts -// create listing of posts + // Bootstrap the Database + console.log({ message: "Bootstrapping the database..." }); + setupDb(); + await readPostsToDatabase(__dirname + "/../posts"); -app.route('/', home); -app.route('/posts', posts); + // read all posts + // create listing of posts + + console.log({ message: "Bootstrapping the routes..." }); + app.route('/', home); + app.route('/posts', posts); + + return app; +} + +export default main(); -export default app; diff --git a/src/post/post-reader.ts b/src/post/post-reader.ts index bf2ab34..6fbcae2 100644 --- a/src/post/post-reader.ts +++ b/src/post/post-reader.ts @@ -31,7 +31,6 @@ export function parsePostMetadata(post: string): PostMetaWithRawContent { export async function getPostList(path: string): Promise { const postList: PostMeta[] = new Array(); - console.log(path); const dir = await readdir(path); if (!dir.length) {