Compare commits
7 Commits
Author | SHA1 | Date | |
---|---|---|---|
db0836a499 | |||
4c78f3f83e | |||
e21de55d3f | |||
34a215eb7b | |||
21fb068901 | |||
ab5a83202e | |||
c8b5f72657 |
12
config/site.toml
Normal file
12
config/site.toml
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
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"
|
@ -5,11 +5,13 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/yaml-front-matter": "^4.1.3",
|
"@types/yaml-front-matter": "^4.1.3",
|
||||||
|
"feed": "^4.2.2",
|
||||||
"highlight.js": "^11.10.0",
|
"highlight.js": "^11.10.0",
|
||||||
"hono": "^4.4.13",
|
"hono": "^4.4.13",
|
||||||
"marked": "^13.0.2",
|
"marked": "^13.0.2",
|
||||||
"marked-highlight": "^2.1.3",
|
"marked-highlight": "^2.1.3",
|
||||||
"remark": "^15.0.1",
|
"remark": "^15.0.1",
|
||||||
|
"smol-toml": "^1.3.0",
|
||||||
"yaml-front-matter": "^4.1.1"
|
"yaml-front-matter": "^4.1.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
---
|
---
|
||||||
title: Thoughts on JavaScript
|
title: Thoughts on JavaScript
|
||||||
description: |>
|
description: Describing the architecture of Handlers, Services, (Domains), and Presentation
|
||||||
Describing the architecture of Handlers, Services, (Domains), and
|
|
||||||
Presentation
|
|
||||||
date: 2024-08-11
|
date: 2024-08-11
|
||||||
tags:
|
tags:
|
||||||
- development
|
- development
|
||||||
@ -14,35 +12,16 @@ draft: true
|
|||||||
|
|
||||||
## My History With JavaScript
|
## My History With JavaScript
|
||||||
|
|
||||||
I think the first time I wrote JavaScript and got paid for it, I was young,
|
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.
|
||||||
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
|
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.
|
||||||
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
|
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 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
|
```javascript
|
||||||
var mysql = require("mysql");
|
var mysql = require("mysql");
|
||||||
|
|
||||||
var config = { ... };
|
var config = {...};
|
||||||
|
|
||||||
mysql.connect(config, function (err, conn) {
|
mysql.connect(config, function (err, conn) {
|
||||||
// handle the error
|
// handle the error
|
||||||
@ -71,28 +50,15 @@ mysql.connect(config, function (err, conn) {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
_This sucks._
|
_This sucks._
|
||||||
|
|
||||||
We ended up rewriting this service in C# as that was the most popular language
|
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.
|
||||||
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
|
## How I Approached Big Applications
|
||||||
|
|
||||||
Eventually all the .NET guys left the company. My boss left the company. I was
|
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.
|
||||||
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,
|
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_).
|
||||||
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_).
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ callbacks to events that will be run when that particular event is emitted.
|
|||||||
import EventEmitter from "node:events";
|
import EventEmitter from "node:events";
|
||||||
|
|
||||||
const em = new EventEmitter();
|
const em = new EventEmitter();
|
||||||
em.on("some-event", function () {
|
em.on("home-event", function () {
|
||||||
console.log("Something happened.");
|
console.log("Something happened.");
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -65,14 +65,6 @@ class SomePool extends EventEmitter {
|
|||||||
public getFreeConnectionCount(): number {
|
public getFreeConnectionCount(): number {
|
||||||
return this.freeConnections;
|
return this.freeConnections;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getConnection() {
|
|
||||||
this.emit("pre-connect");
|
|
||||||
|
|
||||||
if (this.freeConnections) {
|
|
||||||
// get a connection
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -80,37 +72,5 @@ So now, in any callback function* we can get the total number of free
|
|||||||
connections in the `SomePool` class.
|
connections in the `SomePool` class.
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
const pool = new SomePool();
|
title=
|
||||||
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).
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,96 +0,0 @@
|
|||||||
---
|
|
||||||
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.
|
|
@ -1,3 +1,4 @@
|
|||||||
export const POST_PATH: string = __dirname + '/../posts';
|
export const POST_PATH: string = __dirname + '/../posts';
|
||||||
|
export const CONFIG_PATH: string = __dirname + '/../config';
|
||||||
export const STATIC_PATH: string = __dirname + '/assets';
|
export const STATIC_PATH: string = __dirname + '/assets';
|
||||||
export const POST_ROUTE_PREFIX: string = '/posts'
|
export const POST_ROUTE_PREFIX: string = '/posts'
|
||||||
|
26
src/handlers/feed.ts
Normal file
26
src/handlers/feed.ts
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
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;
|
@ -1,3 +1,6 @@
|
|||||||
|
/**
|
||||||
|
* SiteMeta is often used for the `<meta />` tags in the document header
|
||||||
|
*/
|
||||||
export type SiteMeta = {
|
export type SiteMeta = {
|
||||||
description?: string,
|
description?: string,
|
||||||
tags?: string[],
|
tags?: string[],
|
||||||
|
9
src/services/config.test.ts
Normal file
9
src/services/config.test.ts
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
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");
|
||||||
|
})
|
||||||
|
})
|
24
src/services/config.ts
Normal file
24
src/services/config.ts
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
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;
|
||||||
|
}
|
41
src/services/feed-generator.ts
Normal file
41
src/services/feed-generator.ts
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
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;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user