Skip to content

ivncmp/crayfish-js

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

20 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

🦐 CrayfishJS

CrayfishJS

The easiest TypeScript Backend Framework specially built for AWS Lambda Serverless.

npm version TypeScript Node.js License


πŸš€ Quick Start

Install globally

npm install -g crayfish-js

Create a new project

crayfish init my-api
cd my-api

Start development server

crayfish start-server staging

πŸŽ‰ Your API is running at http://localhost:3000

Test it:

curl http://localhost:3000/health
# {"status": "OK"}

✨ Features

βœ… Instant Scaffolding - Full serverless project in one command
βœ… TypeScript-First - Full type safety with decorators
βœ… Zero Config Routing - Auto-discovery via @Route decorator
βœ… AWS Ready - Cognito auth, Lambda handler pre-configured
βœ… MVC Pattern - Controllers, services, models with DI
βœ… Local Dev Server - Express.js for rapid development
βœ… Production Ready - Pack and deploy to AWS Lambda


πŸ“¦ What's Included?

When you run crayfish init my-api, you get:

my-api/
β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ controller/
β”‚   β”‚   β”œβ”€β”€ auth-controller.ts     # Example auth endpoints
β”‚   β”‚   └── health-controller.ts   # Health check endpoint
β”‚   β”œβ”€β”€ service/
β”‚   β”‚   └── health-service.ts      # Example service
β”‚   β”œβ”€β”€ model/
β”‚   β”‚   └── user-model.ts          # Example user model
β”‚   β”œβ”€β”€ environments/
β”‚   β”‚   β”œβ”€β”€ production.ts          # Production config
β”‚   β”‚   └── staging.ts             # Staging config
β”‚   β”œβ”€β”€ types/
β”‚   β”‚   └── project-types.ts       # Custom types
β”‚   β”œβ”€β”€ index.ts                   # Main entry point
β”‚   └── environment.ts             # Environment loader
β”œβ”€β”€ package.json
β”œβ”€β”€ tsconfig.json
└── .gitignore

Auto-installed dependencies:

  • crayfish-js - The framework
  • express - Dev server
  • typescript, ts-node - TypeScript runtime
  • @types/express, @types/node - Type definitions

🎯 Core Concepts

1️⃣ Controllers

Controllers handle HTTP requests using the @Route decorator.

Example:

import { BaseController, Route } from "crayfish-js";

export default class UserController extends BaseController {
  
  @Route({ method: "get", path: "/users" })
  async getUsers(event: any) {
    return this.success({ users: [] });
  }
  
  @Route({ method: "post", path: "/users", authenticated: true })
  async createUser(event: any) {
    const body = JSON.parse(event.body);
    return this.success({ user: body });
  }
}

2️⃣ Services

Services contain business logic and can be injected into controllers.

Example:

import { BaseService } from "crayfish-js";

export default class UserService extends BaseService {
  
  async findAll() {
    // Fetch from database
    return [{ id: 1, name: "John" }];
  }
}

Inject into controller:

import { BaseController, Route, Inject } from "crayfish-js";
import UserService from "../service/user-service";

export default class UserController extends BaseController {
  
  @Inject(UserService)
  private userService!: UserService;
  
  @Route({ method: "get", path: "/users" })
  async getUsers() {
    const users = await this.userService.findAll();
    return this.success({ users });
  }
}

3️⃣ Models

Models define your data structures.

Example:

import { BaseModel } from "crayfish-js";

export default class User extends BaseModel {
  id: string;
  email: string;
  name: string;
  
  constructor(data: any) {
    super();
    Object.assign(this, data);
  }
}

4️⃣ Authentication

CrayfishJS supports JWT and AWS Cognito authentication.

JWT Example

import { JwtAuthentication } from "crayfish-js";

const jwt = new JwtAuthentication({
  secret: process.env.JWT_SECRET || "my-secret",
  expiresIn: "7d"
});

@Route({ method: "post", path: "/login" })
async login(event: any) {
  const { email, password } = JSON.parse(event.body);
  
  // Verify credentials...
  
  const token = jwt.sign({ userId: "123", email });
  return this.success({ token });
}

@Route({ method: "get", path: "/me", authenticated: true })
async getMe(event: any) {
  const user = jwt.verify(event.headers.Authorization);
  return this.success({ user });
}

AWS Cognito Example

import { CognitoAuthentication } from "crayfish-js";

const cognito = new CognitoAuthentication({
  region: "us-east-1",
  userPoolId: process.env.COGNITO_USER_POOL_ID!,
  clientId: process.env.COGNITO_CLIENT_ID!
});

@Route({ method: "post", path: "/signup" })
async signup(event: any) {
  const { email, password } = JSON.parse(event.body);
  const result = await cognito.signUp(email, password);
  return this.success(result);
}

πŸ› οΈ CLI Commands

crayfish init <project-name>

Scaffold a new serverless project.

Example:

crayfish init my-api

crayfish generate-controller <name>

Generate a new controller.

Example:

cd my-api
crayfish generate-controller user
# Creates src/controller/user-controller.ts

crayfish generate-service <name>

Generate a new service.

Example:

crayfish generate-service user
# Creates src/service/user-service.ts

crayfish start-server <environment>

Start local Express dev server (NOT for production).

Example:

crayfish start-server staging
# Loads src/environments/staging.ts
# Server: http://localhost:3000

crayfish pack

Build and package for AWS Lambda deployment.

Example:

npm run build
crayfish pack
# Ready to deploy to AWS Lambda

πŸš€ Deployment to AWS Lambda

1. Build your project

npm run build

2. Package for Lambda

crayfish pack

3. Deploy to AWS

  • Create a new Lambda function in AWS Console
  • Upload the packaged code
  • Set handler: index.handler
  • Add API Gateway trigger

Or use AWS SAM / Serverless Framework:

sam deploy
# or
serverless deploy

🧩 Decorators API

@Route(config: RouteConfig)

Declares an HTTP route.

Config:

{
  method: "get" | "post" | "put" | "delete" | "patch",
  path: string,
  authenticated?: boolean  // Require auth (default: false)
}

@Inject(ServiceClass)

Dependency injection for services.

Example:

@Inject(UserService)
private userService!: UserService;

@Authenticated

Enforces authentication on a route.

Example:

@Authenticated
@Route({ method: "delete", path: "/users/:id" })
async deleteUser(event: any) {
  // Only authenticated users can access
}

πŸ“š Base Classes

BaseController

All controllers extend this class.

Methods:

  • success(data, statusCode = 200) - Return success response
  • error(message, statusCode = 500) - Return error response
  • unauthorized(message) - Return 401
  • notFound(message) - Return 404

BaseService

All services extend this class.


BaseModel

Base class for models (optional).


BaseUserModel

Pre-configured user model with common fields (id, email, password, createdAt).


🌍 Environment Configuration

File: src/environments/production.ts

export const environment = {
  production: true,
  apiUrl: "https://api.example.com",
  jwtSecret: process.env.JWT_SECRET,
};

Load environment:

import { environment } from "./environments/production";
console.log(environment.apiUrl);

πŸ§ͺ Testing

Currently: No testing framework included.

Recommendation: Add Vitest or Jest manually.

npm install -D vitest @vitest/ui

πŸ”§ Advanced Usage

Custom Response Format

Override BaseController methods:

export default class MyController extends BaseController {
  
  success(data: any) {
    return {
      statusCode: 200,
      body: JSON.stringify({ success: true, data }),
    };
  }
}

Middleware Pattern

Add custom middleware logic in src/index.ts:

export const handler = async (event: any) => {
  // Custom middleware logic
  console.log("Request:", event);
  
  // Call router
  return router.handle(event);
};

πŸ›‘οΈ Security Best Practices

βœ… Never hardcode secrets - Use environment variables
βœ… Hash passwords - Use bcrypt (included)
βœ… Validate inputs - Add Zod or Joi validation
βœ… Use HTTPS - Always in production
βœ… Enable CORS - Configure API Gateway properly


πŸ“ Conventions

  • Controllers: PascalCase, suffix with Controller
  • Services: PascalCase, suffix with Service
  • Models: PascalCase (e.g., User, Product)
  • Files: kebab-case (e.g., user-controller.ts)
  • Routes: lowercase with hyphens (/users, /auth/login)

🚧 Limitations

⚠️ Express dev server is NOT for production - Use AWS Lambda
⚠️ No ORM - Bring your own (TypeORM, Prisma, etc.)
⚠️ No validation - Add Zod, Joi, etc. manually
⚠️ No testing utilities - Add Vitest/Jest manually


🀝 Contributing

Contributions welcome! Please:

  1. Fork the repo
  2. Create a feature branch: git checkout -b feature/my-feature
  3. Commit changes: git commit -m 'feat: add my feature'
  4. Push: git push origin feature/my-feature
  5. Open a Pull Request

πŸ“„ License

GPL-3.0-only

See LICENSE file for details.


πŸ”— Links


πŸ™ Acknowledgments

Built with ❀️ by IvÑn Campillo

Inspired by modern backend frameworks like NestJS, but optimized for serverless environments.


πŸ“– Documentation

For detailed technical documentation, see CLAUDE.md


Last updated: 22/03/2026
Version: 1.3.0

About

🦐 Lightweight TypeScript framework for AWS Lambda serverless - MVC architecture with decorators, auto-routing, JWT/Cognito auth, and instant scaffolding via CLI

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors