Get Started

Module

Modules are the building blocks of your Antelopejs app. They talk to each other through interfaces - exporting features others can use, and importing features they need.

Managing Modules

Antelopejs modules are self-contained units that implement and expose functionality through interfaces. In this guide, you'll learn how to create and configure modules.

Creating a Module

Making a new module is easy with the CLI:

npx ajs module init <module-name>

The CLI will ask you to pick a template and choose which interfaces you want to use.

Module Configuration

Every module needs some settings in its package.json file to tell Antelopejs how it works with other modules.

Key Settings

{
  "name": "my-module",
  "version": "1.0.0",
  "antelopeJs": {
    "imports": ["interface@version"],
    "exportsPath": "dist/interfaces",
    "baseUrl": "dist",
    "paths": {
      "@/*": ["*"]
    }
  }
}

Here's what each setting does:

SettingWhat it does
importsLists interfaces you want to use from other modules
exportsPathWhere to find interfaces your module provides
baseUrlWhere module files are located
pathsShortcuts for importing files (like in TypeScript)

Managing Configuration

You can change these settings using the CLI:

#### Add an interface import
ajs module imports add payment@1

#### View current configuration
ajs module config show

#### Update configuration fields
ajs module config set exportsPath dist/interfaces

For more CLI commands, check out the Module CLI guide.

Module Lifecycle

Every module needs four main functions that control its life:

export function construct(config: any): void {
  // Set things up
  // Don't start any processes yet
}

export function start(): void {
  // Turn everything on
  // Start connections, listeners, and processing
}

export function stop(): void {
  // Pause everything
  // Keep state for later restart
}

export function destroy(): void {
  // Clean up everything
  // Release all resources
}

How Modules Flow

Here's how a module moves through its lifecycle:

The Four Phases

  1. Construct
    • Your module gets its settings
    • You set up resources and connections
    • But nothing is active yet
  2. Start
    • Connections go live
    • Listeners turn on
    • Your module starts working
  3. Stop
    • Pause operations
    • Keep your state intact
    • Ready to start again
  4. Destroy
    • Close all connections
    • Release all resources
    • Clean up completely

When hot reloading happens, the system will destroy the old version and construct the new one, letting you update code without stopping everything.

Always implement all four functions properly to avoid memory leaks and keep things running smoothly during updates.

Importing Interfaces

To use features from other modules, you need to import their interfaces. Here's how:

Step 1: Tell Your Module What to Import

Add the interface to your package.json:

{
  "antelopeJs": {
    "imports": ["api@dev"]
  }
}

You can also manage imports with these commands:

#### Add an interface import
ajs module imports add api@dev

#### List current imports
ajs module imports list

#### Remove an interface import
ajs module imports remove api@dev

Step 2: Use It in Your Code

Once configured, you can use the interface in your code like this:

// Import what you need from the API interface
import { Controller, Get, Post, HTTPResult, Parameter } from "@ajs/api/dev";

// Create a controller for users
class UsersController extends Controller("/users") {
  // GET /users - List all users
  @Get("/")
  async listUsers() {
    return {
      users: [
        { id: "user1", name: "John Doe" },
        { id: "user2", name: "Jane Smith" },
      ],
    };
  }

  // GET /users/:id - Get a specific user
  @Get(":id")
  async getUser(@Parameter("id") userId: string) {
    // Return user data (simplified example)
    return { id: userId, name: "John Doe" };
  }

  // POST /users - Create a new user
  @Post("/")
  async createUser() {
    // Return created status with new resource
    return new HTTPResult(201, { id: "new-user", name: "New User" });
  }
}

Interface Versioning

When importing interfaces, you specify both the name and version (e.g., api@dev). This allows:

  • Using multiple versions of the same interface simultaneously
  • Gradually migrating from older to newer versions
  • Maintaining backward compatibility

For example, you could use both stable and development versions of the API:

import { Controller as StableController } from "@ajs/api/1";
import { Controller as DevController } from "@ajs/api/dev";

// Use stable API for production features
class StableApiController extends StableController("/api/v1") {
  // Production-ready endpoints
}

// Use development API for experimental features
class DevApiController extends DevController("/api/experimental") {
  // New features still in development
}