Compare commits

..

2 Commits

12 changed files with 180 additions and 128 deletions

BIN
bun.lockb

Binary file not shown.

View File

@ -1,12 +0,0 @@
title = "davesmithhayes.com"
[owner]
name = "Dave Smith-Hayes"
email = "me@davesmithhayes.com"
[site]
description = "Personal website of Dave Smith-Hayes - a father, developer, and musician."
url = "https://davesmithhayes.com"
repo = "https://git.davesmithhayes.com/dsh/blog"
language = "en"
copyright = "All rights reserved, Dave Smith-Hayes"

View File

@ -5,13 +5,11 @@
},
"dependencies": {
"@types/yaml-front-matter": "^4.1.3",
"feed": "^4.2.2",
"highlight.js": "^11.10.0",
"hono": "^4.4.13",
"marked": "^13.0.2",
"marked-highlight": "^2.1.3",
"remark": "^15.0.1",
"smol-toml": "^1.3.0",
"yaml-front-matter": "^4.1.1"
},
"devDependencies": {

View File

@ -1,6 +1,8 @@
---
title: Thoughts on JavaScript
description: Describing the architecture of Handlers, Services, (Domains), and Presentation
description: |>
Describing the architecture of Handlers, Services, (Domains), and
Presentation
date: 2024-08-11
tags:
- development
@ -12,16 +14,35 @@ draft: true
## My History With JavaScript
I think the first time I wrote JavaScript and got paid for it, I was young, dumb, and willing to work at a design agency for nearly minimum wage making WordPress templates and CakePHP applications. The team I worked with had adopted jQuery for all things front-end - which was the style at the time. I think this time was about 2014.
I think the first time I wrote JavaScript and got paid for it, I was young,
dumb, and willing to work at a design agency for nearly minimum wage making
WordPress templates and CakePHP applications. The team I worked with had
adopted jQuery for all things front-end - _which was the style at the time_. I
think this time was about 2014.
From there, I moved on to other Agency jobs and finally ended up at my current place of employment as a lowly _PHP Developer_. This role was designed to solely work on a single Magento 1 codebase. Again, jQuery was the tool of choice. Of course the JavaScript landscape was changing rapidly with the introductions of Node.js, and frameworks like Angular and React. I paid no mind to these since the bulk of my work was still in the world of Magento 1 and working on a plan to migrate to Magento 2.
From there, I moved on to other agency jobs and finally ended up at my current
place of employment as a lowly _PHP Developer_. This role was designed to
solely work on a single Magento 1 codebase. Again, jQuery was the tool of
choice. Of course the JavaScript landscape was changing rapidly with the
introductions of Node.js, and frameworks like Angular and React. I paid no
mind to these since the bulk of my work was still in the world of Magento 1
and working on a plan to migrate to Magento 2.
It wouldn't be until 2018 (or maybe 2019?) that I would write a line of JavaScript for Node.js. We had decided to go all-in on AWS Lambda. I worked on a service that would push order data out of our Magento instance into our Production Facility's database. Let's call this _The Bridge_. This Lambda was invoked by API Gateway. This was a very small web service, essentially. This was, also, my first experience with _Callback Hell_. There was no `await` and no real `Promise` API (except, _I think_ Bluebird, but I never knew about it at the time) yet. The service actually needed to do a lot of queries, and use those results for other queries, so on, and so forth. If you're familiar with working on Callback Hell you will recognize this:
It wouldn't be until 2018 (or maybe 2019?) that I would write a line of
JavaScript for Node.js. We had decided to go all-in on AWS Lambda. I worked on
a service that would push order data out of our Magento instance into our
Production Facility's database. Let's call this _The Bridge_. This Lambda was
invoked by API Gateway. This was a very small web service, essentially. This
was, also, my first experience with _Callback Hell_. There was no `await` and
no real `Promise` API (except, _I think_ Bluebird, but I never knew about it
at the time) yet. The service actually needed to do a lot of queries, and use
those results for other queries, so on, and so forth. If you're familiar with
working on Callback Hell you will recognize this:
```javascript
var mysql = require("mysql");
var config = {...};
var config = { ... };
mysql.connect(config, function (err, conn) {
// handle the error
@ -50,15 +71,28 @@ mysql.connect(config, function (err, conn) {
});
});
```
_This sucks._
We ended up rewriting this service in C# as that was the most popular language within the organization at the time. Honestly, thank god. I didn't need to write or maintain the service once it fell into the hands of the .NET team.
We ended up rewriting this service in C# as that was the most popular language
within the organization at the time. Honestly, thank god. I didn't need to
write or maintain the service once it fell into the hands of the .NET team.
## How I Approached Big Applications
Eventually all the .NET guys left the company. My boss left the company. I was put in charge and the first thing I did was deploy an Express.js application to completely rewrite the service discussed above. I did this because this was actually faster to do than figure out how the build system (Jenkins, Ansible, and TeamCity _I think_) and deploy it to our common pattern architecture. It was also a way for me to prove to my new boss that I can get things done and that moving to slowly remove our reliance on .NET and IIS for our services was a worthy endeavor.
Eventually all the .NET guys left the company. My boss left the company. I was
put in charge and the first thing I did was deploy an Express.js application to
completely rewrite the service discussed above. I did this because this was
actually faster to do than figure out how the build system (Jenkins, Ansible,
and TeamCity _I think_) and deploy it to our common pattern architecture. It
was also a way for me to prove to my new boss that I can get things done and
that moving to slowly remove our reliance on .NET and IIS for our services was
a worthy endeavor.
A lot of my experience up until that point was mostly working in Magento 2, which is a massive, Enterprisey, PHP application. Modern PHP tends look more and more like C# or Java as the years go on. So that's where my mind is - poisoned by web MVC and Enterprise OOP (_tm_).
A lot of my experience up until that point was mostly working in Magento 2,
which is a massive, Enterprisey, PHP application. Modern PHP tends look more
and more like C# or Java as the years go on. So that's where my mind is -
poisoned by web MVC and Enterprise OOP (_tm_).

View File

@ -27,7 +27,7 @@ callbacks to events that will be run when that particular event is emitted.
import EventEmitter from "node:events";
const em = new EventEmitter();
em.on("home-event", function () {
em.on("some-event", function () {
console.log("Something happened.");
});
@ -65,6 +65,14 @@ class SomePool extends EventEmitter {
public getFreeConnectionCount(): number {
return this.freeConnections;
}
public function getConnection() {
this.emit("pre-connect");
if (this.freeConnections) {
// get a connection
}
}
}
```
@ -72,5 +80,37 @@ So now, in any callback function* we can get the total number of free
connections in the `SomePool` class.
```typescript
title=
const pool = new SomePool();
pool.on("pre-connect", function () {
if (this.freeConnections) {
this.freeConnection = this.freeConnection - 1;
}
});
```
This is a really impractical use of `EventEmitter`, but I think it does a good
job at illustrating the scope of the callback function on the `on` method and
how it can alter the state of the `SomePool` class. There is definitely a case
for when this can be super helpful and useful.
## The Arrow Function
One of the big things in JavaScript is to use this nifty little short-hand to
create a function:
```typescript
[1, 2, 3].map((i) => i + 1);
```
This is super useful to keeping code clean and concise - but there is a huge
caveat using the arrow function over the classic function definition. When you
do an arrow function, you are not inheriting the scope of the object you are
attaching the callback to.
So in the example above, the object is the Array object, implicitly
instantiated, and having its method `map` called (which iterates over each of
the items in an Array, and does something, in this case, adding 1 to it).

View File

@ -0,0 +1,96 @@
---
title: The Absolute Basics on Web Development
description: A post en which I talk about the basics of web development.
date: 2024-11-18
tags:
- development
- html
- css
- javascript
slug: the-basics-of-web-development
draft: true
---
## The Server & Client
At the time of this posting, I have already conducted a workshop at a Hackathon
for High School students in my city. My workshop took the kids from nothing to
a very basic HTML document published on to the internet. I ended up using
Github Codespaces, and Github Pages to get them from 0 to Web Page with the
least amount of friction. Those technologies aside, this whole endeaver
inspired me to write down what I think are the absolute basics, as I understand
them from my own experience as a professional web developer.
The first thing to truly understand is the relationsihp between a Server and
the Client. The Server is a piece of software that reacts to requests from a
Client. The Client is you - probably using a web browser like Firefox or
Chrome.
I think its important to talk about TCP/IP, the packet, and the structure of
the Request and Response data.
## The Document
The best way to conceptualize what a web page is, is to look at what it
actually is - a document. The Document is made up of a special Markup language
called Hyper Text Markup Language (HTML). This is a form of Hypermedia - a
concept we don't have to fully invest in yet.
HTML describes structure and classification of data. There are three main
parts of an HTML document:
1. The Document Type
2. The Header
3. The Body
The Document Type simply states "Hey, this document is of this format." We wont
go into the history of the HTML Document Type tag since once HTML was
standardized we perfected the notion of how to declare a document type.
If you're curious about the history of this line and what it used to look like,
feel free to look at [the Wikipedia article on the subject](https://en.wikipedia.org/wiki/Document_type_declaration).
The Header is _meta data about the document_. This is where things like the
Title of the document is declared, where character set in the document is
defined, and other things like injecting remote files like stylesheets and
JavaScript.
The Body is where the content for the document actually lives. This is where we
will write a majority of our HTML and present the information we want to share
with the world.
Let's take a look at the document we are going to craft. By the end of this
blog, if you wish to follow along, you will have a very basic understanding of
how the web works.
```html
<!DOCTYPE html>
<html lang="en">
<head>
<title>A simple web page.</title>
</head>
<body>
<!-- This is a comment, this is not rendered to the page. -->
<h1>Level 1 Header</h1>
<p>This is a paragraph that will live on the page.</p>
<p>This paragraph has a <a href="https://tildes.net">Link to Tildes</a> on it!</p>
</body>
</html>
```
## The Stylesheet
Styling HTML is usually done through a language called Cascading Style Sheets.
This language allows you to define things like font families, sizes, colours,
and even placement on the document itself. CSS has gone through a huge
evolution since I first learned it in 2004(ish). While I am no designer (that's
my wife), I have learned some really basic skills over the years that allow me
to get a basic, legible, site styled. Case and point: this blog.
## Interactivity
The only real way to add interactivity to an HTML document these days is to add
some JavaScript. JavaScript is a temultuous topic in and of itself but I think
understanding the basics, especially within the context of a Web Browser and
on an HTML document, can help you appreciate what a little of client-side code
can do to improve the experience of reading some documents.

View File

@ -1,4 +1,3 @@
export const POST_PATH: string = __dirname + '/../posts';
export const CONFIG_PATH: string = __dirname + '/../config';
export const STATIC_PATH: string = __dirname + '/assets';
export const POST_ROUTE_PREFIX: string = '/posts'

View File

@ -1,26 +0,0 @@
import { Hono, Context } from 'hono';
import { PostService } from '@blog/services/post-file';
import { Feed } from 'feed';
const feed = new Hono<{ Variables: { postService: PostService }}>();
let feedBuffer: string = "";
export async function getFeedFile(c: Context) {
c.header('Content-Type', 'text/xml');
if (!feedBuffer) {
const postService: PostService = c.get('postService');
const posts = postService.getPublishedPosts();
// get the site meta
// create the feed
// get the feed data
feedBuffer = "";
}
c.body(feedBuffer);
}
feed.get('/rss.xml', getFeedFile);
export default feed;

View File

@ -1,6 +1,3 @@
/**
* SiteMeta is often used for the `<meta />` tags in the document header
*/
export type SiteMeta = {
description?: string,
tags?: string[],

View File

@ -1,9 +0,0 @@
import { describe, expect, test } from 'bun:test'
import { getSiteConfig } from '@blog/services/config';
describe("Test the global config for the site", () => {
test("Parses the Owner", async () => {
const siteConfig = await getSiteConfig();
expect(siteConfig.owner.email).toBe("me@davesmithhayes.com");
})
})

View File

@ -1,24 +0,0 @@
import TOML from 'smol-toml';
import { CONFIG_PATH } from '@blog/config';
export type SiteConfig = {
title: string;
owner: {
name: string;
email: string;
};
site: {
description: string;
url: string;
repo: string;
language: string;
copyright: string;
}
}
export async function getSiteConfig(): Promise<SiteConfig> {
const siteConfig = CONFIG_PATH + '/site.toml';
const file = Bun.file(siteConfig);
const data = await file.text();
return TOML.parse(data) as SiteConfig;
}

View File

@ -1,41 +0,0 @@
import { Feed, FeedOptions } from 'feed';
import { getSiteConfig } from '@blog/services/config';
import { PostService } from '@blog/services/post-file';
import type { Post } from '@blog/models/post';
const updatedDate = new Date();
export async function getFeed(postService: PostService): Feed {
const config = getSiteConfig();
const feed = new Feed({
title: config.title,
description: config.site.description,
link: config.site.link,
language: config.site.language,
copyright: config.site.copyright,
generator: "dsh feed gen",
updated: updatedDate,
author: {
name: "Dave Smith-Hayes",
email: "me@davesmithhayes.com",
link: "davesmithhayes.com"
}
});
postService.getAllPosts().map((post: Post) => {
feed.addItem({
title: post.meta.title,
id: post.meta.slug,
link: post.meta.slug,
description: post.meta.description,
content: post.html,
author: [
name: config.author,
email: config.email
]
});
});
return feed;
}