Common changes for simplicity
Changed fastify handler to handle the actual registration of the rout file with the routeinfo. changed all ' to " instead moves types and interfaces to the respective folders and files
This commit is contained in:
parent
7d77e73030
commit
1ccf80474c
11 changed files with 88 additions and 54 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -90,7 +90,7 @@ web_modules/
|
||||||
|
|
||||||
.node_repl_history
|
.node_repl_history
|
||||||
|
|
||||||
# Output of 'npm pack'
|
# Output of "npm pack"
|
||||||
|
|
||||||
*.tgz
|
*.tgz
|
||||||
|
|
||||||
|
|
2
LICENCE
2
LICENCE
|
@ -1,6 +1,6 @@
|
||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2024 Creation's // [creations@creations.works]
|
Copyright (c) 2024 Creation"s // [creations@creations.works]
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# TS Fastify Example
|
# TS Fastify Example
|
||||||
|
|
||||||
This is just an example/template to get you started with Fastify and TypeScript. It starts off using EJS, but you can use something else if you'd like.
|
This is just an example/template to get you started with Fastify and TypeScript. It starts off using EJS, but you can use something else if you"d like.
|
||||||
|
|
||||||
## Getting Started
|
## Getting Started
|
||||||
|
|
||||||
|
|
BIN
bun.lockb
Normal file
BIN
bun.lockb
Normal file
Binary file not shown.
|
@ -1,23 +1,7 @@
|
||||||
import { dirname, join } from "path";
|
import { dirname, join } from "path";
|
||||||
import { fileURLToPath } from "url";
|
import { fileURLToPath } from "url";
|
||||||
|
|
||||||
export interface IEnvironment {
|
import type{ IEnvironment } from "../interfaces/environment";
|
||||||
development: boolean;
|
|
||||||
|
|
||||||
fastify: {
|
|
||||||
host: string;
|
|
||||||
port: number;
|
|
||||||
};
|
|
||||||
|
|
||||||
paths: {
|
|
||||||
src: string;
|
|
||||||
www: {
|
|
||||||
root: string;
|
|
||||||
views: string;
|
|
||||||
public: string;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const __dirname : string = join(dirname(fileURLToPath(import.meta.url)), "..");
|
const __dirname : string = join(dirname(fileURLToPath(import.meta.url)), "..");
|
||||||
|
|
||||||
|
|
17
interfaces/environment.ts
Normal file
17
interfaces/environment.ts
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
export interface IEnvironment {
|
||||||
|
development: boolean;
|
||||||
|
|
||||||
|
fastify: {
|
||||||
|
host: string;
|
||||||
|
port: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
paths: {
|
||||||
|
src: string;
|
||||||
|
www: {
|
||||||
|
root: string;
|
||||||
|
views: string;
|
||||||
|
public: string;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
7
interfaces/routes.ts
Normal file
7
interfaces/routes.ts
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
import type { TMethod } from "../types/routes";
|
||||||
|
|
||||||
|
export interface IRouteInfo {
|
||||||
|
enabled: boolean;
|
||||||
|
path: string;
|
||||||
|
method: TMethod | TMethod[];
|
||||||
|
}
|
|
@ -8,7 +8,7 @@ import { join } from "path";
|
||||||
import { environment } from "../../config/environment";
|
import { environment } from "../../config/environment";
|
||||||
|
|
||||||
// types
|
// types
|
||||||
import type { FastifyInstance, FastifyReply, FastifyRequest, RouteShorthandMethod } from "fastify";
|
import type { FastifyInstance } from "fastify";
|
||||||
import type { Stats } from "fs";
|
import type { Stats } from "fs";
|
||||||
import type { AddressInfo } from "net";
|
import type { AddressInfo } from "net";
|
||||||
|
|
||||||
|
@ -31,8 +31,6 @@ class FastifyManager {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
private async registerPlugins() : Promise<void> {
|
private async registerPlugins() : Promise<void> {
|
||||||
console.log(environment.paths.www.views);
|
|
||||||
|
|
||||||
// official plugins
|
// official plugins
|
||||||
this.server.register(fastifyView, {
|
this.server.register(fastifyView, {
|
||||||
engine: {
|
engine: {
|
||||||
|
@ -55,9 +53,8 @@ class FastifyManager {
|
||||||
// dynamic route loading
|
// dynamic route loading
|
||||||
private async loadRoutes(): Promise<void> {
|
private async loadRoutes(): Promise<void> {
|
||||||
// you can specify a route path, prefix, and whether to load routes recursively e.g. ["routes", "/", true] will load all routes in the /routes directory with the prefix / and recursively load all routes in subdirectories
|
// you can specify a route path, prefix, and whether to load routes recursively e.g. ["routes", "/", true] will load all routes in the /routes directory with the prefix / and recursively load all routes in subdirectories
|
||||||
|
|
||||||
const routePaths: [string, string, boolean][] = [
|
const routePaths: [string, string, boolean][] = [
|
||||||
["routes", '/', false]
|
["routes", "/", false]
|
||||||
];
|
];
|
||||||
|
|
||||||
for (const [routePath, prefix, recursive] of routePaths) {
|
for (const [routePath, prefix, recursive] of routePaths) {
|
||||||
|
@ -73,12 +70,39 @@ class FastifyManager {
|
||||||
|
|
||||||
for (const file of files) {
|
for (const file of files) {
|
||||||
try {
|
try {
|
||||||
const route = await import(file);
|
const routeModule = await import(file);
|
||||||
if (route.default) {
|
const { default: routeData } = routeModule;
|
||||||
this.server.register(route.default, { prefix });
|
|
||||||
|
if ( !routeData || !routeData.routeInfo || !routeData.route ) {
|
||||||
|
console.error(`Failed to load route from ${file}:`, "Route data is missing");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (routeData.routeInfo.enabled && routeData.route) {
|
||||||
|
const { routeInfo, route } = routeData;
|
||||||
|
|
||||||
|
let routePath = routeInfo.path || "/";
|
||||||
|
|
||||||
|
// Handle prefix and leading/trailing slashes
|
||||||
|
if (prefix) {
|
||||||
|
routePath = routePath === "/" ? prefix : join(prefix, routePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Normalize the path to avoid duplicate slashes
|
||||||
|
routePath = routePath.replace(/\/+/g, "/");
|
||||||
|
|
||||||
|
const methods = Array.isArray(routeInfo.method) ? routeInfo.method : [routeInfo.method];
|
||||||
|
|
||||||
|
for (const method of methods) {
|
||||||
|
this.server.route({
|
||||||
|
method,
|
||||||
|
url: routePath,
|
||||||
|
handler: route
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error("Failed to load route", file, "error:", err);
|
console.error(`Failed to load route from ${file}:`, err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -115,7 +139,7 @@ class FastifyManager {
|
||||||
|
|
||||||
const [_address, _port, scheme]: [string, number, string] = (() : [string, number, string] => {
|
const [_address, _port, scheme]: [string, number, string] = (() : [string, number, string] => {
|
||||||
const address: string | AddressInfo | null = this.server.server.address();
|
const address: string | AddressInfo | null = this.server.server.address();
|
||||||
const resolvedAddress: [string, number] = (address && typeof address === 'object') ? [( address.address.startsWith("::") || address.address === "0.0.0.0") ? "localhost" : address.address, address.port] : ["localhost", this.port];
|
const resolvedAddress: [string, number] = (address && typeof address === "object") ? [( address.address.startsWith("::") || address.address === "0.0.0.0") ? "localhost" : address.address, address.port] : ["localhost", this.port];
|
||||||
const resolvedScheme: string = resolvedAddress[0] === "localhost" ? "http" : "https";
|
const resolvedScheme: string = resolvedAddress[0] === "localhost" ? "http" : "https";
|
||||||
|
|
||||||
return [...resolvedAddress, resolvedScheme];
|
return [...resolvedAddress, resolvedScheme];
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { readFile } from 'fs/promises';
|
import { readFile } from "fs/promises";
|
||||||
|
|
||||||
import type { FastifyInstance, FastifyPluginAsync } from 'fastify';
|
import type { FastifyInstance, FastifyPluginAsync } from "fastify";
|
||||||
import type { FastifyRequest } from "fastify/types/request";
|
import type { FastifyRequest } from "fastify/types/request";
|
||||||
import type { FastifyReply } from "fastify/types/reply";
|
import type { FastifyReply } from "fastify/types/reply";
|
||||||
|
|
||||||
|
@ -17,16 +17,16 @@ const faviconPlugin: FastifyPluginAsync<FaviconOptions> = async (fastify: Fastif
|
||||||
console.error("Error reading favicon:", err);
|
console.error("Error reading favicon:", err);
|
||||||
}
|
}
|
||||||
|
|
||||||
fastify.get('/favicon.ico', async (_request: FastifyRequest, reply: FastifyReply): Promise<void> => {
|
fastify.get("/favicon.ico", async (_request: FastifyRequest, reply: FastifyReply): Promise<void> => {
|
||||||
if (faviconData) {
|
if (faviconData) {
|
||||||
reply.header('Content-Type', 'image/x-icon')
|
reply.header("Content-Type", "image/x-icon")
|
||||||
.header('Cache-Control', 'public, max-age=86400') // 1 day
|
.header("Cache-Control", "public, max-age=86400") // 1 day
|
||||||
.send(faviconData);
|
.send(faviconData);
|
||||||
} else {
|
} else {
|
||||||
reply.status(404).send({
|
reply.status(404).send({
|
||||||
code: 404,
|
code: 404,
|
||||||
error: 'FILE_NOT_FOUND',
|
error: "FILE_NOT_FOUND",
|
||||||
message: 'Favicon not found'
|
message: "Favicon not found"
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,17 +1,18 @@
|
||||||
import type { FastifyInstance, FastifyReply, FastifyRequest } from "fastify";
|
import type { FastifyReply, FastifyRequest } from "fastify";
|
||||||
|
import type { IRouteInfo } from "../../../interfaces/routes";
|
||||||
|
|
||||||
const route : (fastify: FastifyInstance) => Promise<void> = async (fastify: FastifyInstance) : Promise<void> => {
|
const routeInfo: IRouteInfo = {
|
||||||
const handleRequest: (request : FastifyRequest, reply : FastifyReply) => Promise<void> = async (request : FastifyRequest, reply : FastifyReply) : Promise<void> => {
|
enabled: true,
|
||||||
|
path: "/",
|
||||||
|
method: "GET"
|
||||||
|
};
|
||||||
|
|
||||||
return reply.view("index.ejs", {
|
async function route(request : FastifyRequest, reply : FastifyReply) : Promise<string> {
|
||||||
h1: "Hello, World!",
|
return reply.viewAsync("index", {
|
||||||
p: "This is a placeholder page.",
|
h1: "Hello, World!",
|
||||||
discord: "https://discord.gg/DxFhhbr2pm",
|
p: "This is a placeholder page.",
|
||||||
});
|
discord: "https://discord.gg/DxFhhbr2pm",
|
||||||
|
});
|
||||||
}
|
|
||||||
|
|
||||||
fastify.get("/", handleRequest);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default route as (fastify: FastifyInstance) => Promise<void>;
|
export default { routeInfo, route }
|
1
types/routes.ts
Normal file
1
types/routes.ts
Normal file
|
@ -0,0 +1 @@
|
||||||
|
export type TMethod = "GET" | "POST" | "PUT" | "DELETE" | "PATCH" | "OPTIONS" | "HEAD";
|
Loading…
Reference in a new issue