Skip to content

Commit

Permalink
Publish
Browse files Browse the repository at this point in the history
  • Loading branch information
datkat21 committed Nov 7, 2023
1 parent 2d85502 commit f0b82d5
Show file tree
Hide file tree
Showing 11 changed files with 282 additions and 166 deletions.
57 changes: 6 additions & 51 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,58 +3,13 @@
Mini-web server for Bun.js.
This minimal server thing extends `Bun.serve()` and creates a simple wrapper with useful features such as a public directory, websocket support built-in, etc.

## Usage
## Specification

This isn't exactly a library (yet) so you'll have to copy the files from `handlers` into your project.

Here are some server examples:

**Basic HTTP server**
```ts
import { requestHandler } from "./handlers/requestHandler";
import { ReqHandlerType, makeServer } from "./handlers/serverConstructor";

const server = makeServer({
// Set up the server basics
port: 3000,
publicFolderPath: "./public",

// Set up the request handler
requestHandler,
requestHandlerType: ReqHandlerType.UrlOnly
});

console.log(`Listening on localhost:${server.port}`);
```

**Basic websocket server**
```ts
import { requestHandler } from "./handlers/requestHandler";
import { ReqHandlerType, makeServer } from "./handlers/serverConstructor";

const server = makeServer({
// Set up the server basics
port: 3000,
publicFolderPath: "./public",

// Set up the request handler
requestHandler,
requestHandlerType: ReqHandlerType.UrlAndWs,

// Instance of WebSocketHandler
websocketConfig: {
message(ws, message) {
console.log(`${ws.data} said: ${message}`);
},
// . . . (open, close, ping, pong, etc.)
},
// Also see websocketHandler to set custom `ws.data`.
});

console.log(`Listening on localhost:${server.port}`);
```

## Setup
- Custom Handlers
- File-only mode
- WebSockets
- Very easy to understand configuration
- Ease of use handler builders

To install dependencies:

Expand Down
12 changes: 12 additions & 0 deletions examples/helloWorld.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import miniDeluxe from "../index";
const m = miniDeluxe.miniServer({
port: 3000,
handlers: [
{
urlPath: "/",
handler: async function (req: Request) {
return new Response("Hello, world!");
},
},
],
});
29 changes: 29 additions & 0 deletions examples/test_foh.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import {
createCookie,
editCookie,
pageBuilder,
rawFile,
} from "../handlers/handling";
import miniDeluxe from "../index";

function fofHandler() {
return new Response(
`<!DOCTYPE html><html><head><style>html,body{background-color:#1a1a1a;color:#ffffff;font-family:system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;padding: 20px;}</style></head><body><h1>404 Not Found</h1><p>The file you were looking for does not exist.</p></body></html>`,
{
status: 404,
headers: {
"Content-Type": "text/html",
},
statusText: "Not Found",
}
);
}

const m = miniDeluxe.miniServer({
port: 3000,
fofHandler,
options: {
fileOnlyMode: true,
staticFilePath: "../public",
},
});
48 changes: 48 additions & 0 deletions examples/test_server.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import {
createCookie,
editCookie,
pageBuilder,
rawFile,
} from "../handlers/handling";
import miniDeluxe from "../index";

const m = miniDeluxe.miniServer({
port: 3000,
// options: {
// fileOnlyMode: true
// },
handlers: [
{
urlPath: "/",
handler: async function (req: Request) {
return pageBuilder(
"<h1>New Webs</h1><small><em>sponsored by cherries.to & tuck</em></small>"
);
},
},
{
urlPath: "/turtle",
handler: async function (req: Request) {
return rawFile("../public/sample.png");
},
},
{
urlPath: "/cookie/make",
handler: async function (req: Request) {
return createCookie("cherries.to", "yes!");
},
},
{
urlPath: "/cookie/edit",
handler: async function (req: Request) {
return editCookie("cherries.to", "edited");
},
},
{
urlPath: "/error",
handler: async function (req: Request) {
throw new TypeError("Bad Error");
},
},
],
});
113 changes: 113 additions & 0 deletions handlers/handling.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
import { BunFile } from "bun";
import path from "path";

export interface ReqHandler {
urlPath: string;
handler: CallableFunction;
}

export function returnNotFound() {
return new Response("404 Not Found", {
status: 404,
headers: { "Content-Type": "text/html" },
});
}

export interface Route {
/**
* The path of the route, e.g. `/` or `/chat`.
*/
urlPath: string;
handler: CallableFunction;
}

export function fileOnlyHandlers(url: URL) {
return new Response(Bun.file(url.pathname));
}

// austin genius big brain iq momento here
export function generateRequestHandler(handlers: any[], fofHandler: Function = returnNotFound) {
async function requestHandler(req: Request): Promise<Response> {
// Generate URL from request data
const url = new URL(req.url);

// Fall back to public directory
let urlPath = url.pathname;

// default handlers built into the program
if (urlPath.endsWith("/")) {
urlPath = "/index.html";
}

let route: Route | null;
try {
route = handlers.find((r: Route) => {
if (r.urlPath.endsWith(url.pathname))
// if (r.path.exec(url.pathname) !== null && r.method === req.method)
return r;
});
} catch (e: any) {
return new Response(e, { status: 500 });
}

// If there's no such route, show a 404
if (!route) return fofHandler();

// Run the route's handler
return await route?.handler({ req, url, route });
}

return requestHandler;
}

import { join } from "path";

export function fileOnlyReqHandler(staticFilePath: string = "public") {
async function requestHandler(req: Request) {
// Generate URL from request data
const url = new URL(req.url);

// Fall back to public directory
let urlPath = url.pathname;

// default handlers built into the program
if (urlPath.endsWith("/")) {
urlPath = "/index.html";
}

return new Response(Bun.file(join(staticFilePath, urlPath)));
}

return requestHandler;
}

/**
* Build a page and return with content type. Meant for simple API serverside uses like sqlite3 just to return extra comments.
*/
export function pageBuilder(html: string, contentType: string = "text/html") {
return new Response(html, {
headers: { "content-type": contentType },
});
}

/// Create a cookie by ${name} and ${value}
export function createCookie(name: string, value: string) {
return new Response("Cookie Created", {
headers: { "Set-Cookie": `${name}=${value}` },
});
}

/// Edit an already existing cookie by ${name} and ${value}
export function editCookie(name: string, value: string) {
return new Response("Cookie Edited", {
headers: { Cookie: `${name}=${value}` },
status: 301,
statusText: "Moved",
});
}

/// Return any raw file you would like, headers will be filled out by Bun.file()
export function rawFile(path: string) {
// return rawFile = Bun.file -> Response;
return new Response(Bun.file(path));
}
25 changes: 0 additions & 25 deletions handlers/requestHandler.ts

This file was deleted.

Loading

0 comments on commit f0b82d5

Please sign in to comment.