Initial Commit

This commit is contained in:
Randy Jordan 2024-11-09 08:10:29 -06:00
commit 30231b4ce2
Signed by: Randy-Jordan
GPG Key ID: D57FA29E3B54663E
12 changed files with 1775 additions and 0 deletions

27
README.md Normal file
View File

@ -0,0 +1,27 @@
# fastify-min
## Description
Barebones fastify app to serve static content. Makes use of [icofonts](https://myrepos.xyz/Randy-Jordan/icofonts), [vanilla](https://myrepos.xyz/Randy-Jordan/vanilla), and [bejs](https://myrepos.xyz/Randy-Jordan/bejs). Basic boilerplate to create an app.
## Table of Contents
- [Description](#description)
- [Features](#features)
- [Credits / Resources](#credits--resources)
- [License](#license)
## Features / TODO
- [x] Serve static files
- [x] Server health route
- [x] Icofonts
## Credits / Resources
[Fastify Docs](https://fastify.dev/docs/latest/Guides/Getting-Started/)<br>
[Fastify Example App](https://github.com/delvedor/fastify-example)<br>
[Redis Docs](https://redis.io/)<br>
[Postgresql/PG_Admin](https://www.pgadmin.org/download/)
## License
This project is licensed under GPLv3 - see the [LICENSE](LICENSE) file for details.

24
app.js Normal file
View File

@ -0,0 +1,24 @@
import AutoLoad from '@fastify/autoload'
import path from 'path';
import { dirname } from 'path'
import { fileURLToPath } from 'url'
const __filename = fileURLToPath(import.meta.url)
const __dirname = dirname(__filename)
// Setting up the autoloader for plugins and routes.
export default async function (fastify, opts) {
// Require all the plugins that we'll need in our application.
await fastify.register(AutoLoad, {
dir: path.join(__dirname,'plugins'),
options: Object.assign({}, opts)
})
// Then, we'll load all of our routes.
await fastify.register(AutoLoad, {
dir: path.join(__dirname,'routes'),
dirNameRoutePrefix: false,
options: Object.assign({}, opts)
})
}

22
eslint.config.js Normal file
View File

@ -0,0 +1,22 @@
import globals from "globals";
export default [
{
ignores: ["node_modules/"]
},
{
languageOptions: {
ecmaVersion: 2022,
sourceType: "module",
globals: {
...globals.node,
}
},
rules: {
'no-unused-vars': 'warn',
'no-console': 'warn',
}
}
];

25
index.js Normal file
View File

@ -0,0 +1,25 @@
import Fastify from 'fastify'
import App from './app.js' // Our app instance settings.
async function start () {
// Register our instance
const fastify = Fastify();
await fastify.register(App);
// Set up server settings.
const port = process.env.PORT || 3000
const address = process.env.ADDRESS || "localhost"
// Set up listener and on ready list all routes
fastify.listen({ port, address });
fastify.ready(() => {
const routes = fastify.printRoutes();
console.log(`Available Routes:\n${routes}`);
console.log(`Listening for connections on ${address}:${port}`);
})}
// Start the server and crash on error.
start().catch(err => {
console.error(err)
process.exit(1)
})

1405
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

21
package.json Normal file
View File

@ -0,0 +1,21 @@
{
"name": "fastify-min",
"version": "1.0.0",
"type": "module",
"description": "Barebones fastify app to serve static content",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "node --env-file=.env index.js"
},
"author": "",
"license": "ISC",
"dependencies": {
"@fastify/autoload": "^5.10.0",
"@fastify/static": "^7.0.4",
"fastify": "^4.28.1",
"fastify-healthcheck": "^4.4.0",
"ioredis": "^5.4.1",
"pg": "^8.12.0"
}
}

38
plugins/db.js Normal file
View File

@ -0,0 +1,38 @@
import fp from "fastify-plugin";
import pg from 'pg'
const { Pool } = pg
const pool = new Pool({
user: process.env.DB_USER,
host: process.env.DB_HOST,
database: process.env.DB_NAME,
password: process.env.DB_PASS,
port: process.env.DB_PORT,
})
async function database (fastify){
try {
console.log(`Attempting to connect to ${process.env.DB_NAME}@${process.env.DB_HOST}:${process.env.DB_PORT}`);
const client = await pool.connect()
const res = await client.query('SELECT NOW()');
console.log("Connection success at:",res.rows[0].now)
await client.end()
} catch(err) {
console.error(err)
}
fastify.decorate('db', {pool})
}
export default fp(database, {
// Protip: if you name your plugins, the stack trace in case of errors
// will be easier to read and other plugins can declare their dependency
// on this one. `fastify-autoload` will take care of loading the plugins
// in the correct order.
name: 'database'
})

26
plugins/redis.js Normal file
View File

@ -0,0 +1,26 @@
import fp from 'fastify-plugin';
import Redis from 'ioredis';
// Fastify plugin for ioredis
async function redisPlugin(fastify) {
const redis = new Redis({
host: process.env.REDIS_HOST,
port: process.env.REDIS_PORT,
});
console.log(`Attempting to connect to redis@${process.env.REDIS_HOST}:${process.env.REDIS_PORT} ...`)
redis.on('connect', () => {
console.log(`Connection success to Redis at: ${new Date().toISOString()}`);
});
// Attach redis client to Fastify instance
fastify.decorate('redis', redis);
// Close redis connection on server shutdown
fastify.addHook('onClose', (app, done) => {
app.redis.quit();
done();
});
}
// Export as a fastify plugin
export default fp(redisPlugin);

39
routes/publicRoutes.js Normal file
View File

@ -0,0 +1,39 @@
import fp from "fastify-plugin";
import healthcheck from 'fastify-healthcheck';
import Static from '@fastify/static'
import path from 'path';
import { dirname} from 'path'
import { fileURLToPath } from 'url'
const __filename = fileURLToPath(import.meta.url)
const __dirname = dirname(__filename)
async function publicRoutes (fastify, opts) {
// Register healthcheck plugin
fastify.register(healthcheck, {
healthcheckUrl: '/health',
// healthcheckUrlDisable: true,
// healthcheckUrlAlwaysFail: true,
// underPressureOptions: { } // no under-pressure specific options set here
exposeUptime: true // enable, as a sample
})
await fastify.register(Static, {
root: path.join(__dirname, '..', 'static'),
prefix: '/' ,
wildcard: false,
})
fastify.get("/*", async function(request, reply) {
return reply.send({404: "Not Found"})
})
}
export default fp(publicRoutes, {
// Protip: if you name your plugins, the stack trace in case of errors
// will be easier to read and other plugins can declare their dependency
// on this one. `fastify-autoload` will take care of loading the plugins
// in the correct order.
name: 'publicRoutes'
})

1
static/app.js Normal file
View File

@ -0,0 +1 @@
console.log("Hello world!");

18
static/index.html Normal file
View File

@ -0,0 +1,18 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="https://www.icofonts.com/style.css">
<link rel="stylesheet" href="style.css">
<title>Document</title>
</head>
<body class="theme">
<h1>Hello World! <span class="icon-earth"></span> </h1>
<script src="app.js"></script>
</body>
</html>

129
static/style.css Normal file
View File

@ -0,0 +1,129 @@
:root {
/* Font Sizes */
--fs-100: 0.625rem;
--fs-200: 0.75rem;
--fs-300: 0.875rem;
--fs-400: 1rem;
--fs-500: 1.125rem;
--fs-600: 1.25rem;
--fs-700: 1.5rem;
--fs-800: 2.5rem;
--fs-900: 3.5rem;
--fw-regular: 400;
--fw-semi-bold: 500;
--fw-bold: 700;
/* Color variables */
--clr-bg-ltheme: #edebe9;
--clr-text-ltheme: #1b1b1b;
--clr-accent-ltheme: #ff8000;
--clr-primary-ltheme: #d4d4d2;
--clr-secondary-ltheme: #babcbb;
--clr-link-ltheme: blue;
--clr-border-ltheme: blue;
--clr-bg-dtheme: #121212;
--clr-text-dtheme: #edebe9;
--clr-accent-dtheme: #3a3b9c;
--clr-primary-dtheme: #1b1b1b;
--clr-secondary-dtheme: #2d2d2d;
--clr-link-dtheme: blue;
--clr-border-dtheme: blue;
/* General Colors */
--black: #000; /* Black */
--white: #fff; /* White */
--clr-000: #636363;
--clr-100: #5A5A5A;
--clr-200: #515151;
--clr-300: #484848;
--clr-400: #3F3F3F;
--clr-500: #363636;
--clr-600: #2D2D2D;
--clr-700: #242424;
--clr-800: #1B1B1B;
--clr-900: #121212;
/* Semantic Colors */
--clr-success: #118c11;
--clr-info: #17a2b8;
--clr-warning: #ff8000;
--clr-danger: #d00000;
}
/* CSS Resets */
*, *::before, *::after {
box-sizing: border-box;
}
/* Remove default margins. */
* {
margin: 0;
padding: 0;
}
/* Set core root defaults */
html:focus-within {
scroll-behavior: smooth;
}
/* Make images easiser to work with. */
img,picture,svg, video {
display: block;
max-width: 100%;
}
/* Remove list styles (bullets/numbers) */
ol, ul, menu {
list-style: none;
}
/* Form elements inherit font styles. */
input, textarea, button, select {
font: inherit;
}
/* Motion Reducted Media Query */
@media screen and
(prefers-reduced-motion: reduce),
(update: slow) {
* {
animation-duration: 0.001ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.001ms !important;
}
}
/* Screen reader friendly hidden. */
.visually-hidden:not(:focus):not(:active) {
border: 0;
clip: rect(0 0 0 0);
height: auto;
margin: 0;
overflow: hidden;
padding: 0;
position: absolute;
width: 1px;
white-space: nowrap;
}
/* Body and core Themes */
body{
display: grid;
min-width: 100vw;
min-height: 100vh;
align-items: start;
line-height: 1.5rem;
background-color: var(--clr-bg-ltheme);
color: var(--clr-text-ltheme);
}
@media (prefers-color-scheme: dark) {
body{
background-color: var(--clr-bg-dtheme);
color: var(--clr-text-dtheme);
}
}