Skip to content
/ raptor Public

Raptor is a lightweight middleware framework for Deno, focusing on readability and clean code.

License

Notifications You must be signed in to change notification settings

briward/raptor

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

80 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Build Status

Introduction

Raptor is a lightweight middleware framework for Deno, focusing on readability and clear code. It balances functionality and simplicity, enabling you to express complex logic concisely.

Usage

Note

This is currently under heavy development and is not yet suitable for production use. Please proceed with caution.

Installation

To start using Raptor, simply install it through the CLI or import it directly from JSR.

Using the Deno CLI

deno add jsr:@raptor/framework

Importing with JSR

Raptor is also available to import directly via JSR: https://jsr.io/@raptor/framework

Middleware

Raptor's kernel will run through and process each middleware in the order they were added to the stack. However, if you wish to process the next middleware within another, you can use the built-in next argument which is provided to the callback (see "Calling the next middleware").

// main.ts

import { type Context, Kernel } from "jsr:@raptor/framework";

const app = new Kernel();

app.add(() => 'Hello, Dr Malcolm!');

app.serve({ port: 8000 });

To run this code with Deno:

> deno run --allow-net main.ts

Response

In Raptor, at least one middleware function is required to return a body response to ensure that the request cycle completes successfully. The Content-Type of your response will be automatically determined by the framework, allowing you to focus on your own application code.

Returning JSON

If the middleware response body is an object, it will be automatically recognized as application/json. Consequently, both the Content-Type header and the response body will be appropriately set to reflect this format.

app.add(() => ({
  name: 'Dr Ian Malcolm',
}));

Returning HTML

When a string is returned, the Content-Type header is automatically set to text/plain. However, if the string is detected to contain HTML, the Content-Type header will be automatically adjusted to text/html.

app.add(() => '<h1>Hello, Dr Malcolm!</h1>');

Overriding headers

Although it's convenient to return data without configuring a Content-Type, there may be instances where you need to specify a particular header. In such cases, you can proceed as follows:

app.add((context: Context) => {
  context.response.headers.set('Content-Type', 'application/hal+json');

  return {
    name: 'Dr Ian Malcolm'
  }
});

Context

The context object is passed as the first parameter to a middleware function. It includes the HTTP request, the HTTP response, and any additional properties added by previous middleware calls.

Calling the next middleware

The next middleware function is responsible for invoking the subsequent middleware in the stack. It must be called if the current middleware doesn't handle the request and provide a response; otherwise, the system will respond with an error. As an example, the following script demonstrates how to calculate runtime across two middleware:

app.add(async (_context: Context, next: CallableFunction) => {
  const start = Date.now();

  await next();

  const ms = Date.now() - start;

  console.log(`${ms}ms`);
});

app.add(async () => {
  await new Promise(resolve => setTimeout(resolve, 3000));

  return 'Hello, Dr Malcolm!';
});

// console: ~3004ms

Error handling

Errors thrown in middleware are picked up and added to the Context object, allowing you to catch and handle them in a final middleware callback. By default, the system automatically catches errors for you. If you wish to change this behaviour, you can adjust the settings in the Kernel options (see below). As with standard middleware responses, content types and HTTP status codes are automatically assigned, but you can override them if needed.

The following errors are currently available to import and throw from within the framework:

  • NotFound
  • BadRequest
  • ServerError
  • TypeError

You can create your own errors by implementing the Error interface.

Disable automatic error catching

If you prefer to manage errors manually, you can disable the automatic error catching feature in the Kernel options. When you do this, it's essential to add a middleware callback (see example below) to check for errors and handle the responses accordingly.

import { type Context, Kernel, NotFound } from "jsr:@raptor/framework";

// Disable automatic error catching.
const app = new Kernel({
  catchErrors: false,
});

// Simulate an application error.
app.add(() => {
  throw new NotFound();
});

// Catch our error and handle response.
app.add((context: Context) => {
  const { error, response } = context;

  if (error?.status === 404) {
    return {
      message: 'No page could be found'
    }
  }

  response.status = 500;

  return {
    message: 'There was an internal server error'
  }
});

app.serve({ port: 8000 });

Deployment

Deno Deploy

Raptor was built with Deno in mind, meaning that deploying to Deno Deploy is easy. Within your root directory (alongside your main.ts entry file) you can run:

deployctl deploy

Cloudflare Worker

You can also deploy your application to a Cloudflare Worker by simply using the respond method of the Kernel. This allows you to bypass the usual serve method and return a Response directly.

/* ... */

export default {
  fetch: (request: Request) => {
    return kernel.respond(request);
  }
}

Once you've setup your application for Cloudflare Workers, you can run the deployment as usual:

npx wrangler deploy

Available extensions

Raptor is built as an unopinionated modular framework, giving you the flexibility to choose which components to include. Below is a list of available first-party extensions:

License

Copyright 2024, @briward. All rights reserved. The framework is licensed under the MIT license.

About

Raptor is a lightweight middleware framework for Deno, focusing on readability and clean code.

Topics

Resources

License

Stars

Watchers

Forks