0.0.0 • Published 11 months ago

leserve v0.0.0

Weekly downloads
-
License
MIT
Repository
github
Last release
11 months ago

LeServe

npm version License: MIT

A simple HTTP server with support for modern JavaScript features.

LeServe works greate with LeRoute, a library for routing requests.

Installation

npm install leserve

Usage: serve

(See similar: Deno.serve)

import serve from "leserve/serve";

const handler = (request) => {
  return new Response("Hello, World!", {
    status: 200,
    headers: { "Content-Type": "text/plain" },
  });
};

const server = serve(handler, { port: 3000 });

API

serve(handlerOrOptions, maybeHandler)

  • handlerOrOptions: Either a handler function or an options object.
  • maybeHandler: If the first argument is an options object, this should be the handler function.
Options
  • port: Port number (default: 8000)
  • hostname: Hostname (default: 'localhost')
  • cert: SSL certificate for HTTPS (optional)
  • key: SSL key for HTTPS (optional)
Handler Function

The handler function receives a Request object and should return a Response object or a Promise that resolves to a Response object.

Usage: events + controls

(See similar: WinterJS)

import "leserve/events";
import { start } from "leserve/controls";
start({ port: 3000 });
addEventListener("fetch", (event) => {
  event.respondWith(new Response("Hello, World!", { status: 200 }));
});

Features

Event Listeners

  • addEventListener(event, handler): Add an event listener
  • removeEventListener(event, handler): Remove an event listener

Available events:

EventDescription
fetchEmitted for handling HTTP requests
startEmitted when the server starts
stopEmitted when the server stops
errorEmitted when a server error occurs
requestEmitted for every incoming request
websocketEmitted when a new WebSocket connection is established

Server Control

  • start(options): Start the server
  • stop(): Stop the server
  • emit(event, ...args): Emit a custom event

Middleware

use(async (req, res) => {
  console.log(`[Middleware] ${req.method} ${req.url}`);
  return req;
});

Routing

route("GET", "/hello/:name", async (req, params) => {
  return new Response(`Hello, ${params.name}!`, { status: 200 });
});

WebSockets

addEventListener("websocket", (ws) => {
  ws.on("message", (message) => {
    console.log("Received:", message);
    ws.send(`Echo: ${message}`);
  });
});

Server-Sent Events

addEventListener("fetch", async (event) => {
  if (event.request.url.endsWith("/sse")) {
    const headers = new Headers({
      "Content-Type": "text/event-stream",
      "Cache-Control": "no-cache",
      Connection: "keep-alive",
    });
    const response = new Response(null, { headers });

    const stream = new ReadableStream({
      start(controller) {
        setInterval(() => {
          const event = createServerSentEvent(
            { time: new Date().toISOString() },
            "update"
          );
          controller.enqueue(event);
        }, 1000);
      },
    });

    response.body = stream;
    event.respondWith(response);
  }
});

API Reference

Server Options

type ServerOptions = {
  port: number;
  https?: {
    key: string;
    cert: string;
  };
};

Middleware Function

type MiddlewareFunction = (
  req: Request,
  res: Response
) => Promise<Request | Response | void>;

Route Handler

type RouteHandler = (
  req: Request,
  params: Record<string, string>
) => Promise<Response>;

Global Functions

  • addEventListener(event: string, handler: Function): void
  • removeEventListener(event: string, handler: Function): void

Controls

  • start(options: ServerOptions): Promise<void>
  • stop(): Promise<void>
  • emit(event: string, ...args: any[]): boolean
  • use(middleware: MiddlewareFunction): void
  • route(method: string, path: string, handler: RouteHandler): void
  • createServerSentEvent(data: any, event?: string, id?: string): string

Global Types

The following Web API types are made available globally:

  • Request
  • Response
  • Headers
  • URL
  • URLSearchParams
  • WebSocket

Examples

Starting an HTTPS Server

import fs from "fs";

const httpsOptions = {
  key: fs.readFileSync("path/to/key.pem"),
  cert: fs.readFileSync("path/to/cert.pem"),
};

start({ port: 3000, https: httpsOptions });

Using Middleware and Routing

use(async (req, res) => {
  console.log(`[Middleware] ${req.method} ${req.url}`);
  return req;
});

route("GET", "/hello/:name", async (req, params) => {
  return new Response(`Hello, ${params.name}!`, { status: 200 });
});

route("POST", "/echo", async (req) => {
  const body = await req.json();
  return new Response(JSON.stringify(body), {
    status: 200,
    headers: { "Content-Type": "application/json" },
  });
});

WebSocket Echo Server

addEventListener("websocket", (ws) => {
  console.log("New WebSocket connection");
  ws.on("message", (message) => {
    console.log("Received:", message);
    ws.send(`Echo: ${message}`);
  });
});

Server-Sent Events

addEventListener("fetch", async (event) => {
  if (event.request.url.endsWith("/sse")) {
    const headers = new Headers({
      "Content-Type": "text/event-stream",
      "Cache-Control": "no-cache",
      Connection: "keep-alive",
    });
    const response = new Response(null, { headers });
    let counter = 0;

    const stream = new ReadableStream({
      start(controller) {
        const interval = setInterval(() => {
          const event = createServerSentEvent({ counter: counter++ }, "update");
          controller.enqueue(event);
        }, 1000);

        setTimeout(() => {
          clearInterval(interval);
          controller.close();
        }, 10000);
      },
    });

    response.body = stream;
    event.respondWith(response);
  }
});

Usage: CLI

A flexible CLI tool for serving JavaScript modules with various options.

Installation

npm install -g leserve

Usage

leserve <path-to-file> [options]

Or

npx leserve <path-to-file> [options]

Options

  • -p, --port <port>: Specify the port number (default: 8000)
  • -e, --export <name>: Specify the export name to use (default: 'default')
  • -E, --events: Enable events mode
  • --echo: Enable echo mode

Default Behavior

By default, leserve serves the default export from the specified file at localhost:8000 using ./serve.mjs.

Example:

// myHandler.mjs
export default (request) => {
  return new Response("Default Handler", {
    headers: {
      "content-type": "text/plain",
    },
  });
};
leserve myHandler.mjs

This serves the default export from myHandler.mjs at localhost:8000.

Port Flag

You can specify a custom port using the -p or --port flag:

leserve myHandler.mjs -p 8001

This serves the default export from myHandler.mjs at localhost:8001.

Export Flag

You can choose an alternative export with the -e or --export flag:

// myHandlers.mjs
export const handler = (request) => {
  return new Response("Named Handler", {
    headers: {
      "content-type": "text/plain",
    },
  });
};
leserve myHandlers.mjs -p 8080 -e handler

This serves the export named 'handler' from myHandlers.mjs at localhost:8080.

Events Mode

Using the -E or --events flag causes the server to respond to events using ./controls.mjs and ./event.mjs.

Example:

// myEventHandler.mjs
addEventListener("fetch", async (event) => {
  event.respondWith(new Response("Event!"));
});
leserve myEventHandler.mjs -E

This listens for events at localhost:8000.

You can still use the port flag in events mode:

leserve myEventHandler.mjs -E -p 8080

This listens for events at localhost:8080.

Echo Mode

Using the -E or --events flag causes the server to respond as an echo server.

leserve --echo

echos back requests as responses in JSON format on port 8000.

License

This project is licensed under the MIT License.

0.0.0

11 months ago