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 @antelopejs/core 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

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@beta"]
  }
}

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/beta";

// 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" });
  }
}

Module Structure

In Antelopejs, your business logic lives in modules. An Antelopejs project is primarily composed of an antelope.json file and one or more modules that work together. Let's explore how modules are structured and how they connect through the project configuration.

Each module in Antelopejs follows a consistent pattern:

module-name/
├── .antelope/             # Generated automatically by the CLI
│   ├── interface.d        # Contains definition files for interfaces your module imports
├── src/
│   ├── index.ts           # Main entry point
│   ├── interfaces/        # Interfaces this module provides
│   │   └── 1/             # Version 1
│   │       └── index.ts
│   └── implementations/   # Implementations of the interfaces
│   │   └── 1/             # Version 1
│   │       └── index.ts
├── dist/
├── package.json
└── tsconfig.json

Source Files

Let's examine the key files in a module:

src/index.ts

This is the entry point for your module. It exports these important lifecycle functions:

export function construct(config: any): void {
  // Set things up when module is loaded
}

export function start(): void {
  // Start the module's functionality
}

export function stop(): void {
  // Pause operation
}

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

These functions are called automatically by the Antelopejs runtime at appropriate times.

src/interfaces/

This directory contains the interfaces your module provides to others:

interfaces/
└── payment/           # Interface name
    ├── 1/             # Version 1
    │   └── index.ts   # Interface code
    └── 2/             # Version 2
        └── index.ts   # Updated interface code

Each interface has its own folder with versioned implementations. These interfaces are exposed for other modules to consume. For a detailed explanation of how to design and export interfaces, see the Export Interfaces chapter.

src/implementations/

This is where you implement interfaces that you export in your src/interfaces/ directory:

implementations/
└── database/          # Interface name
    └── dev/           # Version
        └── index.ts   # Your implementation

The implementations directory contains the actual code that fulfills the contract defined by your interfaces. For in-depth information about this pattern and how the proxy system works, refer to the Proxy System chapter.

Configuration Files

Each module has its own configuration files:

package.json

This file tells Antelopejs about your module:

{
  "name": "payment-module",
  "version": "1.0.0",
  "main": "dist/index.js",
  "antelopeJs": {
    "imports": ["database@beta", "logger@1"],
    "exportsPath": "dist/interfaces",
    "baseUrl": "dist",
    "paths": {
      "@/*": ["*"]
    }
  }
}

The antelopeJs section defines:

  • imports: Interfaces your module needs from other modules
  • exportsPath: Where your interfaces are located
  • baseUrl and paths: Path mappings for your code

tsconfig.json

Standard TypeScript configuration for your module:

{
  "compilerOptions": {
    "target": "ES2020",
    "module": "CommonJS",
    "moduleResolution": "node",
    "esModuleInterop": true,
    "outDir": "./dist",
    "rootDir": "./src",
    "baseUrl": "./src",
    "paths": {
      "@ajs.local/*": ["interfaces/*"],
      "@ajs/*": ["../.antelope/interfaces.d/*"],
      "@/*": ["*"]
    }
  },
  "include": ["src/**/*"]
}

The paths mappings in your tsconfig.json serve important purposes:

  • @ajs.local/*: Maps to your module's own interfaces, allowing you to import interfaces your module exports
  • @ajs/*: Maps to interfaces imported from other modules (in .antelope/interfaces.d/)
  • @/*: A shorthand for importing files from your source directory

Typical Module Development Workflow

When developing a module:

  1. Define interfaces in src/interfaces/ if your module provides functionality to others
  2. Create implementations in src/implementations/ for interfaces your module export
  3. Write your core business logic in src/index.ts and additional files
  4. Build your module with TypeScript (tsc or your preferred build tool)
  5. Configure it in your project's antelope.json (see the Project chapter for details)