npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@hla4ts/hla-api

v0.1.1

Published

High-level HLA 4 API facade for TypeScript - RTI Ambassador and Federate Ambassador

Readme

@hla4ts/hla-api

High-level HLA 4 API for TypeScript

This package provides a TypeScript-friendly API for building HLA 4 (IEEE 1516-2025) federates using the Federate Protocol. It wraps the low-level session and transport layers with a familiar RTI Ambassador / Federate Ambassador pattern.

Overview

The HLA API package provides:

  • RTIAmbassador - Main interface for federate-to-RTI communication
  • FederateAmbassador - Callback interface for RTI-to-federate communication
  • Exception classes - Type-safe HLA exception handling
  • Type definitions - Handle types, value maps, and configuration types

Installation

bun add @hla4ts/hla-api

Quick Start

import {
  RTIAmbassador,
  BaseFederateAmbassador,
  CallbackModel,
  ResignAction,
} from '@hla4ts/hla-api';

// 1. Create your Federate Ambassador by extending the base class
class MyFederateAmbassador extends BaseFederateAmbassador {
  override discoverObjectInstance(
    objectInstance: Uint8Array,
    objectClass: Uint8Array,
    objectInstanceName: string,
    producingFederate: Uint8Array
  ): void {
    console.log(`Discovered object: ${objectInstanceName}`);
  }

  override reflectAttributeValues(
    objectInstance: Uint8Array,
    attributeValues: Array<{ attributeHandle: Uint8Array; value: Uint8Array }>,
    userSuppliedTag: Uint8Array,
    transportationType: Uint8Array,
    producingFederate: Uint8Array
  ): void {
    console.log(`Received ${attributeValues.length} attribute updates`);
  }

  override receiveInteraction(
    interactionClass: Uint8Array,
    parameterValues: Array<{ parameterHandle: Uint8Array; value: Uint8Array }>,
    userSuppliedTag: Uint8Array,
    transportationType: Uint8Array,
    producingFederate: Uint8Array
  ): void {
    console.log(`Received interaction with ${parameterValues.length} parameters`);
  }
}

// 2. Create the RTI Ambassador
const rtiAmbassador = new RTIAmbassador({
  host: 'rti.example.com',
  port: 15165,  // TLS port (default)
  useTls: true,
});

// 3. Connect to the RTI
const federateAmbassador = new MyFederateAmbassador();
await rtiAmbassador.connect(federateAmbassador, {
  callbackModel: CallbackModel.EVOKED,
});

// 4. Join a federation
const joinResult = await rtiAmbassador.joinFederationExecution(
  'MyFederateType',
  'TestFederation'
);
console.log(`Joined as federate with handle: ${joinResult.federateHandle}`);

// 5. Get handles for FOM elements
const objectClassHandle = await rtiAmbassador.getObjectClassHandle(
  'HLAobjectRoot.MyClass'
);
const attributeHandle = await rtiAmbassador.getAttributeHandle(
  objectClassHandle,
  'MyAttribute'
);

// 6. Publish and subscribe
await rtiAmbassador.publishObjectClassAttributes(objectClassHandle, [attributeHandle]);
await rtiAmbassador.subscribeObjectClassAttributes(objectClassHandle, [attributeHandle]);

// 7. Register an object instance
const objectInstance = await rtiAmbassador.registerObjectInstance(objectClassHandle);

// 8. Update attributes
await rtiAmbassador.updateAttributeValues(
  objectInstance,
  [{ attributeHandle, value: new TextEncoder().encode('Hello HLA!') }],
  new Uint8Array() // user-supplied tag
);

// 9. Send an interaction
const interactionClass = await rtiAmbassador.getInteractionClassHandle(
  'HLAinteractionRoot.MyInteraction'
);
const parameterHandle = await rtiAmbassador.getParameterHandle(
  interactionClass,
  'MyParameter'
);

await rtiAmbassador.publishInteractionClass(interactionClass);
await rtiAmbassador.sendInteraction(
  interactionClass,
  [{ parameterHandle, value: new TextEncoder().encode('Hello!') }],
  new Uint8Array()
);

// 10. Clean up
await rtiAmbassador.resignFederationExecution(ResignAction.DELETE_OBJECTS_THEN_DIVEST);
await rtiAmbassador.disconnect();

Sequence Diagram

sequenceDiagram
  participant App as Federate Code
  participant RTI as RTI
  participant RTIA as RTIAmbassador
  participant Session
  participant CB as CallbackDispatcher
  participant FA as FederateAmbassador
  App->>RTIA: connect(federateAmbassador)
  RTIA->>Session: start()
  Session-->>RTI: HLA_CALL_REQUEST (Connect)
  RTI-->>Session: HLA_CALL_RESPONSE
  App->>RTIA: joinFederationExecution(...)
  RTIA->>Session: HLA_CALL_REQUEST
  RTI-->>Session: HLA_CALL_RESPONSE
  RTI-->>Session: HLA_CALLBACK_REQUEST
  Session-->>CB: callback bytes
  CB-->>FA: dispatch callback
  CB-->>Session: CallbackResponse

API Reference

RTIAmbassador

The main interface for communicating with the RTI.

Constructor

new RTIAmbassador(options: RTIAmbassadorOptions)

Options:

| Option | Type | Default | Description | |--------|------|---------|-------------| | host | string | required | RTI host address | | port | number | 15165 (TLS) / 15164 (TCP) | RTI port | | useTls | boolean | true | Use TLS encryption | | connectionTimeout | number | 30000 | Connection timeout (ms) | | responseTimeout | number | 180000 | Response timeout (ms) | | tlsOptions | object | {} | TLS options (ca, cert, key) |

Connection Methods

// Connect to RTI
await rtiAmbassador.connect(federateAmbassador, {
  callbackModel: CallbackModel.EVOKED,
});

// Check connection status
if (rtiAmbassador.isConnected) {
  // ...
}

// Disconnect
await rtiAmbassador.disconnect();

Federation Management

// Create a federation
await rtiAmbassador.createFederationExecution('FederationName', fomModule);

// Join a federation
const joinResult = await rtiAmbassador.joinFederationExecution(
  'FederateType',
  'FederationName'
);

// Resign from a federation
await rtiAmbassador.resignFederationExecution(ResignAction.DELETE_OBJECTS_THEN_DIVEST);

// Destroy a federation
await rtiAmbassador.destroyFederationExecution('FederationName');

Declaration Management

// Publish object class attributes
await rtiAmbassador.publishObjectClassAttributes(objectClass, [attr1, attr2]);

// Subscribe to object class attributes
await rtiAmbassador.subscribeObjectClassAttributes(objectClass, [attr1, attr2]);

// Publish an interaction class
await rtiAmbassador.publishInteractionClass(interactionClass);

// Subscribe to an interaction class
await rtiAmbassador.subscribeInteractionClass(interactionClass);

// Unsubscribe/unpublish
await rtiAmbassador.unpublishObjectClass(objectClass);
await rtiAmbassador.unsubscribeInteractionClass(interactionClass);

Object Management

// Register an object instance
const objectHandle = await rtiAmbassador.registerObjectInstance(objectClass);

// Register with a specific name
const namedObject = await rtiAmbassador.registerObjectInstanceWithName(
  objectClass,
  'MyObjectName'
);

// Update attribute values
await rtiAmbassador.updateAttributeValues(
  objectHandle,
  [{ attributeHandle: attr1, value: new Uint8Array([1, 2, 3]) }],
  userSuppliedTag
);

// Send an interaction
await rtiAmbassador.sendInteraction(
  interactionClass,
  [{ parameterHandle: param1, value: new Uint8Array([1, 2, 3]) }],
  userSuppliedTag
);

// Delete an object instance
await rtiAmbassador.deleteObjectInstance(objectHandle, userSuppliedTag);

Time Management

// Enable time regulation
await rtiAmbassador.enableTimeRegulation(lookahead);

// Enable time constrained
await rtiAmbassador.enableTimeConstrained();

// Query GALT/LITS and lookahead
const galt = await rtiAmbassador.queryGALT();
const lits = await rtiAmbassador.queryLITS();
const lookahead = await rtiAmbassador.queryLookahead();

// Request time advance
await rtiAmbassador.timeAdvanceRequest(targetTime);

// Disable time management
await rtiAmbassador.disableTimeRegulation();
await rtiAmbassador.disableTimeConstrained();

HLAinteger64Time Helpers

import {
  encodeHLAinteger64Time,
  decodeHLAinteger64Time,
} from '@hla4ts/hla-api';

const encodedTime = encodeHLAinteger64Time(1_000_000n);
const decodedTime = decodeHLAinteger64Time(encodedTime);

Support Services

// Get handles by name
const classHandle = await rtiAmbassador.getObjectClassHandle('HLAobjectRoot.MyClass');
const attrHandle = await rtiAmbassador.getAttributeHandle(classHandle, 'MyAttribute');
const interactionHandle = await rtiAmbassador.getInteractionClassHandle('HLAinteractionRoot.MyInteraction');
const paramHandle = await rtiAmbassador.getParameterHandle(interactionHandle, 'MyParameter');

// Get names by handle
const className = await rtiAmbassador.getObjectClassName(classHandle);
const attrName = await rtiAmbassador.getAttributeName(classHandle, attrHandle);

FederateAmbassador

Interface for receiving callbacks from the RTI. Extend BaseFederateAmbassador and override the callbacks you need:

class MyFederateAmbassador extends BaseFederateAmbassador {
  // Object discovery
  override discoverObjectInstance(objectInstance, objectClass, name, producer) {
    // Handle object discovery
  }

  // Attribute updates
  override reflectAttributeValues(objectInstance, attributeValues, tag, transport, producer) {
    // Handle attribute update
  }

  // Interactions
  override receiveInteraction(interactionClass, parameters, tag, transport, producer) {
    // Handle interaction
  }

  // Time management
  override timeAdvanceGrant(time) {
    // Handle time advance grant
  }

  // Object removal
  override removeObjectInstance(objectInstance, tag, producer) {
    // Handle object removal
  }
}

Exception Handling

All HLA exceptions are mapped to TypeScript classes:

import {
  NotConnected,
  FederationExecutionDoesNotExist,
  ObjectClassNotDefined,
  RTIinternalError,
} from '@hla4ts/hla-api';

try {
  await rtiAmbassador.joinFederationExecution('Type', 'NonExistentFederation');
} catch (error) {
  if (error instanceof FederationExecutionDoesNotExist) {
    console.log('Federation does not exist');
  } else if (error instanceof NotConnected) {
    console.log('Not connected to RTI');
  } else if (error instanceof RTIinternalError) {
    console.log('RTI internal error:', error.message);
  }
}

Handle Types

Handles are opaque Uint8Array values. The package provides utility functions:

import { handlesEqual, handleToHex, handleFromHex } from '@hla4ts/hla-api';

// Compare handles
if (handlesEqual(handle1, handle2)) {
  // Handles are equal
}

// Convert to hex string (for debugging)
console.log(handleToHex(handle)); // "0a1b2c3d..."

// Parse from hex string
const handle = handleFromHex("0a1b2c3d");

FOM Module Types

When creating federations, you can provide FOM modules in different formats:

// Inline XML content
const inlineModule: FomModule = {
  type: 'inline',
  content: '<?xml version="1.0"?>...',
};

// File with binary content
const fileModule: FomModule = {
  type: 'file',
  name: 'myFom.xml',
  content: new Uint8Array([...]),
};

// URL reference
const urlModule: FomModule = {
  type: 'url',
  url: 'file:///path/to/fom.xml',
};

await rtiAmbassador.createFederationExecutionWithModules(
  'MyFederation',
  [inlineModule, urlModule]
);

Testing

cd packages/hla-api
bun test

Related Packages

References

License

MIT