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": {
|
||||
"@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": {
|
||||
|
@ -1,8 +1,6 @@
|
||||
---
|
||||
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
|
||||
@ -14,35 +12,16 @@ 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
|
||||
@ -71,28 +50,15 @@ 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_).
|
||||
|
||||
|
||||
|
||||
|
@ -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("some-event", function () {
|
||||
em.on("home-event", function () {
|
||||
console.log("Something happened.");
|
||||
});
|
||||
|
||||
@ -65,14 +65,6 @@ class SomePool extends EventEmitter {
|
||||
public getFreeConnectionCount(): number {
|
||||
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.
|
||||
|
||||
```typescript
|
||||
const pool = new SomePool();
|
||||
pool.on("pre-connect", function () {
|
||||
if (this.freeConnections) {
|
||||
this.freeConnection = this.freeConnection - 1;
|
||||
}
|
||||
});
|
||||
title=
|
||||
```
|
||||
|
||||
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 CONFIG_PATH: string = __dirname + '/../config';
|
||||
export const STATIC_PATH: string = __dirname + '/assets';
|
||||
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 = {
|
||||
description?: 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