Module
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>
yarn dlx ajs module init <module-name>
pnpm dlx 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:
Setting | What it does |
---|---|
imports | Lists interfaces you want to use from other modules |
exportsPath | Where to find interfaces your module provides |
baseUrl | Where module files are located |
paths | Shortcuts 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
- Construct
- Your module gets its settings
- You set up resources and connections
- But nothing is active yet
- Start
- Connections go live
- Listeners turn on
- Your module starts working
- Stop
- Pause operations
- Keep your state intact
- Ready to start again
- 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.
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 modulesexportsPath
: Where your interfaces are locatedbaseUrl
andpaths
: 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:
- Define interfaces in
src/interfaces/
if your module provides functionality to others - Create implementations in
src/implementations/
for interfaces your module export - Write your core business logic in
src/index.ts
and additional files - Build your module with TypeScript (
tsc
or your preferred build tool) - Configure it in your project's
antelope.json
(see the Project chapter for details)