CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-egg

A web application framework for Node.js with enterprise-grade development capabilities through a plugin-based architecture and convention-over-configuration approach

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

base-classes.mddocs/

Base Classes & Components

Foundation classes for building controllers, services, subscriptions, and utility components in Egg.js applications.

Capabilities

BaseContextClass

Base class that provides context-aware functionality for controllers, services, and other context-bound components.

/**
 * BaseContextClass is a base class that can be extended for context-aware components
 * It's instantiated at the context level and provides access to app and ctx
 */
class BaseContextClass extends EggCoreBaseContextClass {
  /** Request context instance */
  ctx: Context;
  
  /** Application instance */
  app: EggApplicationCore;
  
  /** Service container */
  service: BaseContextClass;
  
  /** Component path name for logging */
  pathName?: string;
  
  /** Context-aware logger */
  get logger(): BaseContextLogger;
}

Usage Examples:

// Controller example
export default class UserController extends BaseContextClass {
  async show() {
    const { ctx, app } = this;
    const userId = ctx.params.id;
    
    // Access services through context
    const user = await ctx.service.user.findById(userId);
    
    // Use logger with automatic context information
    this.logger.info('User viewed: %s', userId);
    
    ctx.body = { user };
  }
}

// Service example
export default class UserService extends BaseContextClass {
  async findById(id: string) {
    const { ctx } = this;
    
    // Access database through app
    const user = await this.app.mysql.get('users', { id });
    
    if (!user) {
      this.logger.warn('User not found: %s', id);
      ctx.throw(404, 'User not found');
    }
    
    return user;
  }
  
  async create(userData: CreateUserData) {
    const { ctx, app } = this;
    
    // Validate using context helpers
    ctx.validate(userCreateRule, userData);
    
    // Use logger with service context
    this.logger.info('Creating user: %s', userData.email);
    
    const user = await app.mysql.insert('users', userData);
    return user;
  }
}

Controller Class

Alias for BaseContextClass specifically for controllers.

/**
 * Controller class - alias for BaseContextClass
 * Used for handling HTTP requests and responses
 */
const Controller = BaseContextClass;

Usage Examples:

import { Controller } from 'egg';

export default class HomeController extends Controller {
  async index() {
    const { ctx } = this;
    
    // Access request data
    const { page = 1, limit = 10 } = ctx.query;
    
    // Use services
    const posts = await ctx.service.post.list({ page, limit });
    
    // Set response
    ctx.body = {
      posts,
      pagination: {
        page: Number(page),
        limit: Number(limit),
        total: posts.length
      }
    };
    
    // Log request
    this.logger.info('Home page requested with page=%s, limit=%s', page, limit);
  }
}

Service Class

Alias for BaseContextClass specifically for services.

/**
 * Service class - alias for BaseContextClass
 * Used for business logic and data access
 */
const Service = BaseContextClass;

Usage Examples:

import { Service } from 'egg';

export default class PostService extends Service {
  async list(options: { page: number; limit: number }) {
    const { ctx, app } = this;
    const { page, limit } = options;
    
    // Calculate offset
    const offset = (page - 1) * limit;
    
    // Database query
    const posts = await app.mysql.select('posts', {
      where: { status: 'published' },
      orders: [['created_at', 'desc']],
      limit,
      offset
    });
    
    // Log operation
    this.logger.info('Listed %d posts (page %d)', posts.length, page);
    
    return posts;
  }
  
  async create(postData: CreatePostData) {
    const { ctx, app } = this;
    
    // Validate data
    const errors = await ctx.validate(postCreateRule, postData);
    if (errors) {
      ctx.throw(422, 'Validation failed', { errors });
    }
    
    // Create post
    const result = await app.mysql.insert('posts', {
      ...postData,
      created_at: new Date(),
      updated_at: new Date()
    });
    
    this.logger.info('Created post: %s', result.insertId);
    return result;
  }
}

Subscription Class

Alias for BaseContextClass specifically for scheduled tasks and subscriptions.

/**
 * Subscription class - alias for BaseContextClass
 * Used for scheduled tasks and background subscriptions
 */
const Subscription = BaseContextClass;

Usage Examples:

import { Subscription } from 'egg';

export default class CleanupSubscription extends Subscription {
  // Subscription configuration
  static get schedule() {
    return {
      cron: '0 2 * * *', // Run at 2 AM daily
      type: 'worker',    // Run on all workers
      env: ['prod']      // Only in production
    };
  }
  
  async subscribe() {
    const { ctx, app } = this;
    
    this.logger.info('Starting cleanup job');
    
    try {
      // Clean expired sessions
      await app.redis.del('session:*:expired');
      
      // Clean old logs
      const cutoffDate = new Date(Date.now() - 30 * 24 * 60 * 60 * 1000);
      await app.mysql.delete('logs', {
        created_at: { $lt: cutoffDate }
      });
      
      this.logger.info('Cleanup job completed successfully');
    } catch (error) {
      this.logger.error('Cleanup job failed:', error);
      throw error;
    }
  }
}

Helper Class

Utility class providing common helper functions accessible via context.

/**
 * Helper class providing utility functions
 * Available as ctx.helper in all context-aware components
 */
class Helper extends BaseContextClass {
  /**
   * Generate URL path for route name and parameters
   * @param name - Router route name
   * @param params - Route parameters and query string
   * @returns URL path without host
   */
  pathFor(name: string, params: Record<string, any>): string;
  
  /**
   * Generate full URL for route name and parameters
   * @param name - Router route name
   * @param params - Route parameters and query string
   * @returns Full URL with host
   */
  urlFor(name: string, params: Record<string, any>): string;
}

Usage Examples:

// In controller
export default class LinkController extends Controller {
  async generateLinks() {
    const { ctx } = this;
    
    // Generate path (relative URL)
    const profilePath = ctx.helper.pathFor('user.profile', {
      id: 123,
      tab: 'settings'
    });
    // Result: /user/123/profile?tab=settings
    
    // Generate full URL
    const profileUrl = ctx.helper.urlFor('user.profile', {
      id: 123,
      tab: 'settings'
    });
    // Result: http://localhost:7001/user/123/profile?tab=settings
    
    ctx.body = {
      profilePath,
      profileUrl
    };
  }
}

// In service or other components
export default class EmailService extends Service {
  async sendPasswordReset(user: User) {
    const { ctx } = this;
    
    // Generate reset link
    const resetUrl = ctx.helper.urlFor('auth.reset', {
      token: user.resetToken
    });
    
    await this.sendEmail(user.email, 'Password Reset', {
      resetUrl,
      userName: user.name
    });
    
    this.logger.info('Sent password reset email to %s', user.email);
  }
}

Custom Helper Extensions

Helpers can be extended in your application for project-specific utilities.

Usage Examples:

// app/extend/helper.js - Application helper extensions
export default {
  // Format currency
  formatCurrency(amount: number, currency = 'USD') {
    return new Intl.NumberFormat('en-US', {
      style: 'currency',
      currency
    }).format(amount);
  },
  
  // Generate secure token
  generateToken(length = 32) {
    const { ctx } = this;
    return ctx.app.crypto.randomBytes(length).toString('hex');
  },
  
  // Sanitize HTML
  sanitizeHtml(html: string) {
    // Use sanitization library
    return sanitize(html);
  }
};

// Usage in controllers
export default class ProductController extends Controller {
  async show() {
    const { ctx } = this;
    const product = await ctx.service.product.findById(ctx.params.id);
    
    ctx.body = {
      ...product,
      formattedPrice: ctx.helper.formatCurrency(product.price),
      safeDescription: ctx.helper.sanitizeHtml(product.description)
    };
  }
}

Types

interface BaseContextLogger {
  info(message: string, ...args: any[]): void;
  warn(message: string, ...args: any[]): void;
  error(message: string, ...args: any[]): void;
  debug(message: string, ...args: any[]): void;
}

interface CreateUserData {
  name: string;
  email: string;
  password: string;
}

interface CreatePostData {
  title: string;
  content: string;
  status: 'draft' | 'published';
  author_id: number;
}

Install with Tessl CLI

npx tessl i tessl/npm-egg

docs

application.md

base-classes.md

configuration.md

context.md

http-client.md

index.md

loaders-errors.md

startup.md

tile.json