npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@cambusa/core

v0.9.8

Published

<p align="center"> <img width="150" height="150" src="https://github.com/user-attachments/assets/11d40fd1-69b3-4b95-ac0b-065b45395204" /> </p>

Downloads

34

Readme

Cambusa

🚣 A modern, high-performance web framework built with Bun and modern JavaScript.

Table of Contents

Introduction

Cambusa is a web framework designed to provide a comfortable developer experience with modern JavaScript syntax and enhanced performance using Bun as the runtime. Inspired by Sails.js, if you want to build applications using the latest JavaScript features while enjoying better performance, Cambusa is the framework for you.

Why Cambusa?

In Italian, cambusa means "ship's pantry" or "galley"—the place where provisions are stored on a vessel. Just like a cambusa supplies sailors with essential provisions for their journey, this framework aims to supply developers with the essential tools and conventions needed for building scalable and efficient applications.

The name reflects my modest approach to web development, inspired by Sails.js but streamlined for modern development practices.

Features

  • Sails.js-Inspired Conventions: Familiar MVC structure, blueprints, and configuration patterns.
  • Modern JavaScript Syntax: Utilize the latest ES modules, async/await, and other modern language features.
  • Powered by Bun: Experience significantly faster performance with Bun's high-speed runtime and bundler.
  • Flexible Configuration: Manage settings via config files, environment variables, or command-line arguments.
  • Automatic Routing: Define routes in configuration files that map directly to controller actions.
  • Modular Architecture: Organize your codebase with a clear structure for controllers, services, and utilities.
  • WebSocket Support: Easily integrate WebSocket functionality for real-time communication.

Getting Started

Prerequisites

Installation

# Clone the repository (assuming Cambusa is hosted on GitHub)
git clone https://github.com/cambusaHQ/core.git
cd cambusa

# Install dependencies
bun install

Project Structure

cambusa-app/
├── api
│   ├── controllers
│   ├── helpers
│   ├── hooks
│   ├── middlewares
│   └── models
├── app.js
├── config
│   ├── database.js
│   ├── index.js
│   ├── logger.js
│   ├── middlewares.js
│   ├── routes.js
│   ├── security.js
│   ├── server.js
│   └── swagger.js

Run

bun run app.js

Configuration

Cambusa uses a flexible configuration system. Configurations are split into files within the config/ directory, allowing you to manage settings for different aspects of your application.

Cambusa automatically supports environment variables and command line arguments, blending them into configuration properties.

For detailed information on configuration options and best practices, see the Configuration Guide.

The cambusa Global Object

The cambusa global object is a central part of the Cambusa framework, providing access to various components and utilities throughout your application.

Key Properties and Methods

  • cambusa.config: Contains all configuration settings for your application.
  • cambusa.app: The main Elysia application instance.
  • cambusa.log: The Pino logger instance for logging.
  • cambusa.db: The TypeORM DataSource instance for database operations.
  • cambusa.models: Holding all the defined models for direct operations.
  • cambusa.helpers: Contains all loaded helper functions.

Example Usage:

// Accessing configuration
const serverPort = cambusa.config.server.port;

// Logging
cambusa.log.info('Application started');

// Database
await cambusa.db.synchronize();

// Models operations
const users = await cambusa.models.User.find();

// Using a helper
const formattedDate = cambusa.helpers.formatDate(new Date());

The cambusa object is automatically available in your controllers, models, and other parts of your application, allowing easy access to core functionalities without the need for manual imports.

Creating Routes and Controllers

Defining Routes

You can define your application's custom routes in config/routes.js, where you map HTTP methods and paths to controller actions. These routes are manually defined and give you fine-grained control over the behavior of your API.

Example config/routes.js:

export default {
  routes: {
    'GET /users': 'users/read',
    'DELETE /users/:id': 'users/delete',
  },
};

Creating Controllers

Controllers handle the business logic for your routes. These should be placed in the api/controllers/ directory and correspond to the actions defined in your config/routes.js.

Example api/controllers/users/read.js:

export async function getUsers({ request, response }) {
  // Your logic to retrieve users
  return [
    { id: 1, name: 'Alice' },
    { id: 2, name: 'Bob' },
  ];
}

Blueprints: Automatic CRUD Routes for Models

In addition to defining custom routes, Cambusa provides blueprints, which automatically generate RESTful CRUD routes based on your model definitions. This saves you time and effort by automating the creation of common operations like create, read, update, and delete for your database models.

How Blueprints Work

Blueprints are auto-generated routes that are created based on the model definitions in your api/models/ directory. These routes are automatically registered when the server starts, following a standard RESTful pattern:

  • POST /modelName – Create a new record.
  • GET /modelName – Retrieve all records.
  • GET /modelName/:id – Retrieve a specific record by ID.
  • PUT /modelName/:id – Update a specific record by ID.
  • DELETE /modelName/:id – Delete a specific record by ID.

Example of Blueprints in Action

For a model defined in api/models/User.js:

import { t } from 'elysia';

export const User = {
  routes: {
    basePath: 'users', // Custom base path for this model
    disabled: ['delete'], // Disable the DELETE route
  },
  columns: {
    firstName: {
      type: 'string',
      nullable: true,
    },
    lastName: {
      type: 'string',
      nullable: true,
    },
    email: {
      type: 'string',
      unique: true,
      validation: t.String({ format: 'email' }),
    },
  },
};

export default User;

The following routes will be automatically generated:

  • POST /users – Create a new user.
  • GET /users – Retrieve all users.
  • GET /users/:id – Retrieve a user by ID.
  • PUT /users/:id – Update a user by ID.
  • DELETE route is disabled for this model as specified in the disabled property.

Disabling and Customizing Routes

You can easily customize or disable specific routes for each model by defining the routes property in the model:

  • Disable All Routes: Set disabled: true to disable all auto-generated routes for a model.
  • Disable Specific Routes: You can disable individual routes by specifying an array of routes to disable (create, readAll, readOne, update, delete).

Example:

export const Product = {
  routes: {
    disabled: ['delete', 'update'], // Disable DELETE and UPDATE routes
    basePath: 'products', // Custom base path for this model
  },
  columns: {
    name: { type: 'varchar' },
    price: { type: 'decimal' },
  },
};

export default Product;

This will generate routes for POST, GET (all), and GET (by ID), but not for DELETE or UPDATE.

How to Use Blueprints

Blueprints are loaded automatically during the server startup process. Cambusa will scan your model definitions and create the corresponding CRUD routes based on the routes configuration in each model. This allows you to focus on writing the business logic for more complex or custom routes while letting Cambusa handle the basic CRUD operations.

Handling Route Collisions

In cases where a route is defined both in your custom config/routes.js and is automatically generated by the blueprint system, the user-defined route will take precedence over the blueprint route. This allows you to override or extend the behavior of auto-generated routes with custom logic.

For example, if you define a custom GET /users/:id route in config/routes.js, it will override the blueprint route for that path, allowing you to fully control the behavior of that route.

Query Parameters for Blueprints

Blueprints support several query parameters that allow developers to paginate, filter, and sort the returned data in GET requests.

Pagination

  • limit: Specifies the maximum number of results to return per page (default is 20).
  • skip: Specifies the number of records to skip from the beginning (used for pagination).

Example:

GET /users?limit=10&skip=20

This will return 10 users starting from the 21st user.

Pagination Headers: The response will include the following pagination-related headers:

  • X-Pagination-Total-Count: Total number of records for the current query.
  • X-Pagination-Page-Count: Total number of pages based on the query.
  • X-Pagination-Limit: The limit used in the query.
  • X-Pagination-Page: The current page number.

Sorting

sort: Allows sorting by one or more fields. You can specify the field and the direction (asc for ascending or desc for descending) using the format field:direction.

Example:

GET /users?sort=firstName:asc,lastName:desc

Filtering

where: Allows filtering based on specific conditions. The where parameter should be provided as a JSON string that matches TypeORM's find() method syntax.

Example:

GET /users?where={"isActive":true,"age":30}

This will return all active users who are 30 years old.

Population of Related Data

populate: Allows fetching related data by specifying relations to include. Multiple relations can be specified, separated by commas.

GET /users?populate=orders,profile

WebSocket

Cambusa uses a WebSocket handler to manage WebSocket connections and messages. It now supports real-time entity updates through subscriptions.

🔗 WebSocket documentation

Middleware System

Cambusa uses a flexible middleware system that allows you to easily add functionality to your application's request/response cycle.

Configuring Middlewares

Middlewares are configured in your application's configuration files. You can specify the order in which middlewares should be applied:

// config/middlewares.js
export default {
  middlewares: ['cors', 'requestLogger', 'swagger'],
};

Creating Custom Middlewares

To create a custom middleware, add a new file in the api/middlewares/ directory. Each middleware should export a default function that returns an Elysia plugin.

Example api/middlewares/cors.js

// Cors support
import { Elysia } from 'elysia';
import { cors } from '@elysiajs/cors';

const plugin = new Elysia({
  name: 'cors',
}).use(cors(cambusa.config.security.cors));

export default plugin;

Cambusa will automatically load and apply middlewares based on the order specified in your configuration.

Helpers

Helpers in Cambusa are utility functions that can be used across your application. They are automatically loaded and made available globally.

Creating Helpers

To create a helper, add a new file in the api/helpers/ directory. Each helper should export a default function.

Example api/helpers/formatDate.js

export default function (date) {
  return date.toISOString().split('T')[0];
}

Using Helpers

Helpers are available globally through the cambusa.helpers object:

const formattedDate = cambusa.helpers.formatDate(new Date());

Models

Models in api/models/ will automatically be available as cambusa.models.ModelName, for example User model will be available as cambusa.models.User.

Cambusa uses TypeORM and you can configure the database used (e.g., PostgreSQL, MySQL, MariaDB, SQLite) by updating the config/datastore.js.

🔗 Database and Models documentation

Swagger documentation

Cambusa dynamically generates a swagger api documentation at /swagger if enabled in config.

Logging

Cambusa uses Pino for fast, structured logging. The logger is available globally as cambusa.log, and its configuration can be customized per environment.

Log Levels

The log level can be configured in the logger section of your configuration files. For example:

// config/logger.js
export default {
  logger: {
    level: 'info', // Default log level
    logRequests: true, // Log requests by default
  },
};

In development, logs are prettified for better readability, while in production, logs are structured JSON for performance and better integration with logging systems.

Request Logging

You can enable or disable logging of each incoming HTTP request. When enabled, each request will be logged with the HTTP method, URL, response status, and duration.

To disable request logging (e.g., in production):

export default {
  logger: {
    logRequests: false,
  },
};

Usage

The logger can be accessed globally via cambusa.log:

cambusa.log.info('Server is starting...');
cambusa.log.error('An error occurred', err);

Hooks

Cambusa's hook system provides a powerful and flexible way to extend and customize your application. By leveraging hooks, you can inject custom logic at various stages of the application lifecycle without modifying the core framework code.

🔗 Hooks documentation

CLI

Cambusa provides a powerful CLI tool to streamline development tasks and manage your application efficiently. The CLI supports a variety of commands, including generating models and controllers, synchronizing the database, running custom scripts, and more.

Key Features

  • Model and Controller Generation: Quickly scaffold new models and controllers with predefined templates.
  • Database Synchronization: Easily synchronize your database schema based on your models.
  • Script Execution: Run custom scripts organized within subdirectories to perform tasks like migrations, data processing, and more.
  • Interactive REPL Session: Start an interactive session to interact directly with your Cambusa application.

For detailed instructions on all available commands, usage examples, and advanced features, please refer to the

🔗 CLI documentation

Philosophy

Cambusa is born out of a deep appreciation for Sails.js and its developer-friendly conventions. The goal is to replicate that enjoyable development experience using modern JavaScript features and harnessing the performance benefits of Bun. By adopting a modest and essentialist approach—just like a ship's cambusa—we focus on providing only what's necessary to build robust applications without unnecessary complexity.

Contributing

Contributions are welcome! Feel free to open issues or submit pull requests to help improve Cambusa.

License

MIT License

Author

Enrico Deleo