Fix some of the blog post, get the container built, and remove config for the database.
This commit is contained in:
parent
4c8f3063b2
commit
bd883ac4ef
1
.env.sample
Normal file
1
.env.sample
Normal file
@ -0,0 +1 @@
|
||||
DEPLOY_MODE="development"
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,2 +1,3 @@
|
||||
# deps
|
||||
node_modules/
|
||||
.env
|
||||
|
@ -4,9 +4,9 @@ WORKDIR /app
|
||||
|
||||
COPY bun.lockb .
|
||||
COPY package.json .
|
||||
COPY tsconfig.json .
|
||||
|
||||
RUN bun install --frozen-lockfile
|
||||
RUN mkdir src posts
|
||||
COPY ./src ./src
|
||||
COPY ./posts ./posts
|
||||
|
||||
|
3
build.sh
Executable file
3
build.sh
Executable file
@ -0,0 +1,3 @@
|
||||
#!/bin/bash
|
||||
|
||||
docker build --pull -t dsh-blog . --no-cache
|
@ -11,7 +11,7 @@ slug: fullstack-hono
|
||||
draft: true
|
||||
---
|
||||
|
||||
# Context and My Blog
|
||||
## Context and My Blog
|
||||
|
||||
I like my blog. I don't write nearly as much as I should for it but at the endof the day I like the three small posts that I have put into it. However, I never really liked how I had it set up. I have no real qualms with the SSG I chose ([11ty](https://www.11ty.dev/)) or the web server to host the HTML (NGiNX) but I never really felt like it was _mine_.
|
||||
|
||||
@ -27,7 +27,7 @@ But that made no sense once I _actually_ thought it. What advantage does having
|
||||
|
||||
_Note:_ I am going to talk a lot about JavaScript and TypeScript, and I want to make it very clear that I am talking about running JavaScript on the server. I feel like when people talk about JavaScript, there is an assumption we are talking about building frontend SPAs and not high-IO server applications (for good reasons, honestly). However, in my career and experience, the bulk of JavaScript I have written runs on Node.js. Anyways, after such a long introduction, here is my blog post about what I learned building a very basic blog with Hono and Bun.
|
||||
|
||||
# Organizing Hono applications
|
||||
## Organizing Hono applications
|
||||
|
||||
I make no effort to hide the fact that I come from the MVC Web Framework world. I have spent a lot of time in my career thinking of web applications in the terms of Models, Views, and Controllers. This has made a lot of sense to me over the years, and I posit that it's still a great framework for organizing your code. However when it comes to JavaScript, it feels verbose to create classes full of methods to handle requests and responses. I think this verbosity comes from how JavaScript code is actually organized for Node.js (Deno, Bun, etc).
|
||||
|
||||
@ -37,7 +37,7 @@ So with my understanding that a Class in JavaScript should be a collection of me
|
||||
|
||||
I like to call this pattern Handler, Service, Presentation. This pattern is nearly identical to MVC and you can immediately see the analogues to the original acronym. I don't think there is a clear advantage of using these words in particular, other than it can hopefully erode some of the _web-brainrot_ on how we organize our we applications.
|
||||
|
||||
## An Example of a Service
|
||||
### An Example of a Service
|
||||
|
||||
Let's think of a Blog. This blog. What services do we have in the code for this blog? Right now, it is solely the `PostService`. This is a class that is given a list of `Post` types, and creates an internal Map of that with the `slug` as a key. From there we can do things like, get all the posts, get the latest post, get a post by slugs, get un-published posts, etc.
|
||||
|
||||
@ -45,7 +45,7 @@ Within the `PostService` module is two helper functions. One of these is an `asy
|
||||
|
||||
Another good way to think of a service, is a Repository class. Think of a class that should handle querying data to and from a database. If you need another example, image an HTTP Client for a specific HTTP API. Think of something that provides data to something else. I guess that's how I'd describe it.
|
||||
|
||||
## What Handlers Are
|
||||
### What Handlers Are
|
||||
|
||||
Handlers should be thought of as callback functions for particular requests and responses. The _handle_ the request and response. In the world of Hono, we get to decide what Middleware is type'd into the Application and can be accessed within a handler. This allows us to bootstrap our middleware elsewhere and be assured it will be there when it runs.
|
||||
|
||||
@ -95,7 +95,7 @@ _`src/handlers/posts.tsx`_
|
||||
|
||||
Now I haven't done this yet - but if I need to test the `handleSinglePost` function, I can properly mock the `Context` object with the right `PostService` class.
|
||||
|
||||
## How Presentation Works
|
||||
### How Presentation Works
|
||||
|
||||
Like I mentioned earlier, one of the selling points of using Hono for the framework was its suppose of rendering JSX with `jsxRenderer` middleware. Its trivial to set up, but you have to remember to re-save your files as `tsx` and `jsx` if you want to use it. I have not spent a lot of time writing JSX in my life but once I got some of the basics it became super easy to understand. I can understand why people like React, honestly.
|
||||
|
||||
@ -151,12 +151,12 @@ app.get(
|
||||
);
|
||||
```
|
||||
|
||||
# Development
|
||||
## Development
|
||||
|
||||
If the environment variable `ENVIRONMENT` is set and the value is `DEVELOPMENT`
|
||||
then we can easily grab all the Posts, including Drafts, from the
|
||||
`PostService`.
|
||||
|
||||
# Deployment
|
||||
## Deployment
|
||||
|
||||
We can simply depoy the application within a Docker container into Dokku.
|
||||
|
@ -1,4 +1,3 @@
|
||||
export const POST_PATH: string = __dirname + '/../posts';
|
||||
export const STATIC_PATH: string = __dirname + '/assets';
|
||||
export const POST_ROUTE_PREFIX: string = '/posts'
|
||||
export const SQLITE_DATABASE_FILE: string = __dirname + '/../db/blog.sqlite';
|
||||
|
@ -61,6 +61,16 @@ export async function createPostService(path: string): Promise<PostService> {
|
||||
return new PostService(posts);
|
||||
}
|
||||
|
||||
export function sortPostsByDate(posts: Post[], desc: boolean = true): Post[] {
|
||||
return posts.sort((p1: Post, p2: Post) => {
|
||||
if (desc) {
|
||||
return p2.meta.date.getTime() - p1.meta.date.getTime();
|
||||
}
|
||||
|
||||
return p1.meta.date.getTime() - p2.meta.date.getTime();
|
||||
});
|
||||
}
|
||||
|
||||
export class PostService {
|
||||
private posts: Map<string, Post>;
|
||||
|
||||
@ -73,28 +83,19 @@ export class PostService {
|
||||
}
|
||||
|
||||
public getAllPosts(): Post[] {
|
||||
return Array.from(this.posts.values());
|
||||
return this.getPostsSortedByDate();
|
||||
}
|
||||
|
||||
public getPostsSortedByDate(desc: boolean = true): Post[] {
|
||||
return Array.from(this.posts.values())
|
||||
.sort((p1: Post, p2: Post) => {
|
||||
if (desc) {
|
||||
return p2.meta.date.getTime() - p1.meta.date.getTime();
|
||||
return sortPostsByDate(Array.from(this.getPosts().values()), desc);
|
||||
}
|
||||
|
||||
return p1.meta.date.getTime() - p2.meta.date.getTime();
|
||||
});
|
||||
public getPublishedPosts(): Post[] {
|
||||
return this.getAllPosts().filter((p: Post) => p.meta.draft == false);
|
||||
}
|
||||
|
||||
public getPublishedPosts(desc: boolean = true): Post[] {
|
||||
return this.getPostsSortedByDate(desc)
|
||||
.filter((p: Post) => p.meta.draft == false);
|
||||
}
|
||||
|
||||
public getDraftPosts(desc: boolean = true): Post[] {
|
||||
return this.getPostsSortedByDate(desc)
|
||||
.filter((p: Post) => p.meta.draft == true);
|
||||
public getDraftPosts(): Post[] {
|
||||
return this.getAllPosts().filter((p: Post) => p.meta.draft == true);
|
||||
}
|
||||
|
||||
public getPost(slug: string): Post {
|
||||
|
Loading…
Reference in New Issue
Block a user