[data-reveal]{opacity:1!important;transform:none!important}
Connect modules through interfaces
Core

Connect modules through interfaces

Overview

@antelopejs/interface-core lets one module call a contract implemented by another. The caller imports the interface rather than the provider, so the runtime can connect modules and replace a provider without changing the caller's imports.

If you only need application logs, start with logging. If you are using HTTP routes or authentication, start with those interfaces; you do not need to build a proxy first.

Start with your role

You are…Start hereYou own…
Calling an existing interfaceIts package documentation, then connection lookupThe consuming module and its provider binding.
Defining a new contractHow interfaces work, then proxiesTyped declarations shared by consumers and providers.
Implementing a contractImplementInterfaceEvery declared function and registration callback.
Integrating a module loaderRuntime and module lifecycleOwnership contexts, generations, and cleanup.

Application modules normally import an existing interface rather than construct proxies themselves. The AntelopeJS runtime supplies module context and connections; these primitives do not configure a project or choose a provider for you.

The package exports several key categories of functionality:

  • Proxies - AsyncProxy, EventProxy, and RegisteringProxy manage cross-module function calls, events, and registrations with automatic cleanup when modules are unloaded.
  • Interface functions - InterfaceFunction and ImplementInterface wire up interface declarations to their concrete implementations.
  • Decorator factories - Utilities for building type-safe TypeScript decorators that target classes, properties, methods, and parameters.
  • Metadata - GetMetadata provides reflection-based metadata retrieval with inheritance support.
  • Module lifecycle - Events and functions for managing module construction, startup, shutdown, and destruction.
  • Logging - A structured, channel-based logging system with multiple severity levels.
  • Configuration - TypeScript types and helpers for defining AntelopeJS project configurations.

Import paths

The package exposes several entry points:

// Main entry - proxies, InterfaceFunction, GetMetadata, ImplementInterface, GetInterfaceInstances
import {
  AsyncProxy,
  InterfaceFunction,
  GetMetadata,
} from "@antelopejs/interface-core";

// Decorator factories
import {
  MakeClassDecorator,
  MakeMethodDecorator,
} from "@antelopejs/interface-core/decorators";

// Module lifecycle events and management
import {
  Events,
  ListModules,
  LoadModule,
} from "@antelopejs/interface-core/modules";

// Logging system
import { Logging } from "@antelopejs/interface-core/logging";

// Configuration types and helpers
import { defineConfig } from "@antelopejs/interface-core/config";

How interfaces work

AntelopeJS interfaces act as contracts between modules. One module declares an interface using proxy objects and InterfaceFunction, while another module provides the implementation using ImplementInterface. The proxy layer handles queuing, lifecycle management, and automatic cleanup.

// Declaration side: define what the interface looks like
import { InterfaceFunction, EventProxy } from "@antelopejs/interface-core";

export const GetUser = InterfaceFunction<(id: string) => { name: string }>();
export const OnUserCreated = new EventProxy<(userId: string) => void>();
// Implementation side: provide the concrete behavior
import { ImplementInterface } from "@antelopejs/interface-core";
import * as UserInterface from "./declaration";

ImplementInterface(UserInterface, {
  GetUser(id: string) {
    return { name: "Alice" };
  },
});

The proxy queues calls to GetUser until an implementation attaches. When the implementing module unloads, the proxy detaches and queues new calls again. The queue is bounded (1,000 pending calls by default), and test stub mode rejects missing providers instead of waiting. See proxy failure modes before relying on this behavior during startup.

Choose a communication primitive

NeedPrimitiveWithout an attached provider or listener
Ask for a resultInterfaceFunction / AsyncProxyCalls queue, subject to the queue limit and stub mode.
Notify current listenersEventProxyEmissions are not retained for future listeners.
Keep declarations available across reloadsRegisteringProxyEntries remain available for replay when handlers attach.

Do not use an event for a registration that a replacement provider must recover. Use the registering proxy's paired onHandlers attachment when replay needs both registration and unregistration callbacks.

Next steps

  • Proxies - Deep dive into AsyncProxy, EventProxy, and RegisteringProxy
  • Decorators - Build type-safe decorator factories
  • Modules - Understand module lifecycle events
  • Logging - Use the structured logging system
  • Metadata - Read inherited metadata
  • Configuration - Define project configuration
  • Runtime - Integrate ownership and loader behavior