Skip to content

AegisFramework/Nymph

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

16 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Aegis Framework: Nymph

Nymph is the Bun/TypeScript flavor of the Aegis Framework. It's a minimal but full-featured microframework for building web applications, ported from Ikaros (the PHP flavor) with idiomatic TypeScript patterns.

Requirements

Getting Started

1. Install dependencies

bun install

2. Create your app

import { Nymph, Router, HTTP } from '@aegis-framework/nymph';

const nymph = new Nymph();
const router = nymph.container().get<Router>('Router');

router.get('/', () => {
  return 'Hello, World!';
});

router.get('/api/greet/{name}', (name: string) => {
  return { message: `Hello, ${name}!` };
});

router.port(3000);
router.listen();

console.log('Listening on http://localhost:3000');

3. Run

bun run app.ts

Features

Routing

Register routes by HTTP method with parameter extraction:

router.get('/users/{id}', (id: string) => { /* ... */ });
router.post('/users', async () => { /* ... */ });
router.put('/users/{id}', (id: string) => { /* ... */ });
router.delete('/users/{id}', (id: string) => { /* ... */ });
router.any('/health', () => ({ status: 'ok' }));

Route handlers that return objects are automatically serialized as JSON.

Dependency Injection

PSR-11 style container with lazy singletons:

import { Container } from '@aegis-framework/nymph';

const container = new Container();
container.set('db', () => DB.connect('user', 'pass', 'mydb'));
container.set('userService', (c) => new UserService(c.get('db')));

const users = container.get<UserService>('userService');

Database & Query Builder

Fluent SQL query builder with parameter binding (no SQL injection):

import { DB, Query } from '@aegis-framework/nymph';

const db = await DB.connect('user', 'pass', 'mydb');

const query = new Query(db);
await query
  .select(['id', 'name', 'email'])
  .from('users')
  .where('active').equals(1)
  .and('role').like('%admin%')
  .orderBy([['name', 'ASC']])
  .limit(10)
  .commit();

const results = query.results();

Schema ORM

Abstract base class for database models:

import { Schema, Scheme } from '@aegis-framework/nymph';

class User extends Schema {
  protected static name_ = 'users';
  protected static hash_ = ['password'];
  protected static invisible = ['password'];

  static init() {
    super.init();
    this.scheme!
      .string('name', 255).notNull('name')
      .string('email', 255).notNull('email').unique('email')
      .string('password', 255).notNull('password');
  }
}

Schema.setDB(db);
User.init();

// CRUD
const user = await User.create({ name: 'Jane', email: 'jane@example.com', password: 'secret' });
const found = await User.get(1);
await User.update(1, { name: 'Jane Doe' });
await User.delete(1);

Authentication

Session and token-based auth with CSRF protection:

import { Session, Token, Authenticator, Password } from '@aegis-framework/nymph';

const session = new Session();
const token = new Token('32-byte-secret-key-for-branca!!', router);
const password = new Password();
const auth = new Authenticator(session, token, password, http);

// Session-based login
const hash = await password.hash('secret');
await auth.login('session', 'secret', hash, { id: 1 }, sessionId);

// Token-based login
const jwt = await auth.login('token', 'secret', hash, { id: 1 });

Template Engine

Variable interpolation with XSS escaping, conditionals, and includes:

import { Template } from '@aegis-framework/nymph';

const tmpl = new Template(fileSystem, router);
tmpl.setContent(`
  <h1>{{title}}</h1>
  <p>{{{rawHtml}}}</p>
  {{if loggedIn}}
    <a href="/dashboard">Dashboard</a>
  {{else}}
    <a href="/login">Log in</a>
  {{/if}}
`);
tmpl.setData('title', 'Welcome');
tmpl.setData('rawHtml', '<em>unescaped</em>');
tmpl.setData('loggedIn', true);
tmpl.compile();
  • {{var}} — escaped output (XSS safe)
  • {{{var}}} — raw output
  • {{if var}}...{{/if}} — conditionals
  • {{if var}}...{{else}}...{{/if}} — if/else
  • {>{scripts}<} / {>{styles}<} — asset linking

Collections

Generic iterable that works as both list and dictionary:

import { Collection } from '@aegis-framework/nymph';

const c = new Collection({ name: 'Nymph', version: '1.0' });
c.hasKey('name');    // true
c.get('name');       // 'Nymph'
c.set('lang', 'ts');
c.length();          // 3

for (const [key, value] of c) {
  console.log(key, value);
}

Encryption & Passwords

import { Crypt, Password } from '@aegis-framework/nymph';

// AES-256-GCM encryption
const crypt = await Crypt.create('my-secret-key');
const encrypted = await crypt.encrypt('sensitive data');
const decrypted = await crypt.decrypt(encrypted);

// Password hashing (Bun.password - argon2/bcrypt)
const pw = new Password();
const hash = await pw.hash('my-password');
const valid = await pw.compare('my-password', hash);
const generated = pw.generate(16);

Architecture

src/
├── Enum/                  # HttpMethod, ContentType, DebugLevel, HttpStatus
├── Container/             # DI Container + NotFoundException
├── Collection.ts          # Generic iterable collection
├── Util.ts                # UUID generation
├── Text.ts                # String manipulation
├── Json.ts                # JSON parsing and access
├── FileSystem.ts          # File operations (Bun.file)
├── Crypt.ts               # AES-256-GCM encryption (Web Crypto)
├── Password.ts            # Hashing (Bun.password)
├── Configuration.ts       # Config file loading
├── DB.ts                  # MySQL connection (mysql2/promise)
├── Query.ts               # SQL query builder
├── Scheme.ts              # Table schema builder
├── Schema.ts              # Abstract ORM base class
├── HTTP.ts                # Content types and error responses
├── Route.ts               # Route pattern matching
├── Request.ts             # Web Standard Request wrapper
├── Router.ts              # Bun.serve() router
├── Template.ts            # Template engine
├── Debug.ts               # Error handling
├── Session.ts             # In-memory sessions + CSRF
├── Token.ts               # Branca token encoding
├── Authenticator.ts       # Session/token auth
├── Upload.ts              # File upload handling
├── Nymph.ts               # Bootstrap / service registration
└── index.ts               # Barrel export

Development

# Type check
bun run check

# Run tests
bun test

Dependencies

Package Purpose
branca Token encoding (Branca/Fernet)
mysql2 MySQL database driver

Everything else uses Bun built-ins: Bun.password, Bun.file(), Bun.write(), Bun.serve(), Bun.CryptoHasher, crypto.randomUUID(), Web Crypto API.

License

MIT

About

Aegis Framework for Node JS

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors