@hla4ts/hla-api 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,127 +1,127 @@
1
- # @hla4ts/hla-api
2
-
3
- **High-level HLA 4 API for TypeScript**
4
-
5
- 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.
6
-
7
- ## Overview
8
-
9
- The HLA API package provides:
10
-
11
- - **RTIAmbassador** - Main interface for federate-to-RTI communication
12
- - **FederateAmbassador** - Callback interface for RTI-to-federate communication
13
- - **Exception classes** - Type-safe HLA exception handling
14
- - **Type definitions** - Handle types, value maps, and configuration types
15
-
16
- ## Installation
17
-
18
- ```bash
19
- bun add @hla4ts/hla-api
20
- ```
21
-
1
+ # @hla4ts/hla-api
2
+
3
+ **High-level HLA 4 API for TypeScript**
4
+
5
+ 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.
6
+
7
+ ## Overview
8
+
9
+ The HLA API package provides:
10
+
11
+ - **RTIAmbassador** - Main interface for federate-to-RTI communication
12
+ - **FederateAmbassador** - Callback interface for RTI-to-federate communication
13
+ - **Exception classes** - Type-safe HLA exception handling
14
+ - **Type definitions** - Handle types, value maps, and configuration types
15
+
16
+ ## Installation
17
+
18
+ ```bash
19
+ bun add @hla4ts/hla-api
20
+ ```
21
+
22
22
  ## Quick Start
23
23
 
24
24
  ```typescript
25
- import {
26
- RTIAmbassador,
27
- BaseFederateAmbassador,
28
- CallbackModel,
29
- ResignAction,
30
- } from '@hla4ts/hla-api';
31
-
32
- // 1. Create your Federate Ambassador by extending the base class
33
- class MyFederateAmbassador extends BaseFederateAmbassador {
34
- override discoverObjectInstance(
35
- objectInstance: Uint8Array,
36
- objectClass: Uint8Array,
37
- objectInstanceName: string,
38
- producingFederate: Uint8Array
39
- ): void {
40
- console.log(`Discovered object: ${objectInstanceName}`);
41
- }
42
-
43
- override reflectAttributeValues(
44
- objectInstance: Uint8Array,
45
- attributeValues: Array<{ attributeHandle: Uint8Array; value: Uint8Array }>,
46
- userSuppliedTag: Uint8Array,
47
- transportationType: Uint8Array,
48
- producingFederate: Uint8Array
49
- ): void {
50
- console.log(`Received ${attributeValues.length} attribute updates`);
51
- }
52
-
53
- override receiveInteraction(
54
- interactionClass: Uint8Array,
55
- parameterValues: Array<{ parameterHandle: Uint8Array; value: Uint8Array }>,
56
- userSuppliedTag: Uint8Array,
57
- transportationType: Uint8Array,
58
- producingFederate: Uint8Array
59
- ): void {
60
- console.log(`Received interaction with ${parameterValues.length} parameters`);
61
- }
62
- }
63
-
64
- // 2. Create the RTI Ambassador
65
- const rtiAmbassador = new RTIAmbassador({
66
- host: 'rti.example.com',
67
- port: 15165, // TLS port (default)
68
- useTls: true,
69
- });
70
-
71
- // 3. Connect to the RTI
72
- const federateAmbassador = new MyFederateAmbassador();
73
- await rtiAmbassador.connect(federateAmbassador, {
74
- callbackModel: CallbackModel.EVOKED,
75
- });
76
-
77
- // 4. Join a federation
78
- const joinResult = await rtiAmbassador.joinFederationExecution(
79
- 'MyFederateType',
80
- 'TestFederation'
81
- );
82
- console.log(`Joined as federate with handle: ${joinResult.federateHandle}`);
83
-
84
- // 5. Get handles for FOM elements
85
- const objectClassHandle = await rtiAmbassador.getObjectClassHandle(
86
- 'HLAobjectRoot.MyClass'
87
- );
88
- const attributeHandle = await rtiAmbassador.getAttributeHandle(
89
- objectClassHandle,
90
- 'MyAttribute'
91
- );
92
-
93
- // 6. Publish and subscribe
94
- await rtiAmbassador.publishObjectClassAttributes(objectClassHandle, [attributeHandle]);
95
- await rtiAmbassador.subscribeObjectClassAttributes(objectClassHandle, [attributeHandle]);
96
-
97
- // 7. Register an object instance
98
- const objectInstance = await rtiAmbassador.registerObjectInstance(objectClassHandle);
99
-
100
- // 8. Update attributes
101
- await rtiAmbassador.updateAttributeValues(
102
- objectInstance,
103
- [{ attributeHandle, value: new TextEncoder().encode('Hello HLA!') }],
104
- new Uint8Array() // user-supplied tag
105
- );
106
-
107
- // 9. Send an interaction
108
- const interactionClass = await rtiAmbassador.getInteractionClassHandle(
109
- 'HLAinteractionRoot.MyInteraction'
110
- );
111
- const parameterHandle = await rtiAmbassador.getParameterHandle(
112
- interactionClass,
113
- 'MyParameter'
114
- );
115
-
116
- await rtiAmbassador.publishInteractionClass(interactionClass);
117
- await rtiAmbassador.sendInteraction(
118
- interactionClass,
119
- [{ parameterHandle, value: new TextEncoder().encode('Hello!') }],
120
- new Uint8Array()
121
- );
122
-
123
- // 10. Clean up
124
- await rtiAmbassador.resignFederationExecution(ResignAction.DELETE_OBJECTS_THEN_DIVEST);
25
+ import {
26
+ RTIAmbassador,
27
+ BaseFederateAmbassador,
28
+ CallbackModel,
29
+ ResignAction,
30
+ } from '@hla4ts/hla-api';
31
+
32
+ // 1. Create your Federate Ambassador by extending the base class
33
+ class MyFederateAmbassador extends BaseFederateAmbassador {
34
+ override discoverObjectInstance(
35
+ objectInstance: Uint8Array,
36
+ objectClass: Uint8Array,
37
+ objectInstanceName: string,
38
+ producingFederate: Uint8Array
39
+ ): void {
40
+ console.log(`Discovered object: ${objectInstanceName}`);
41
+ }
42
+
43
+ override reflectAttributeValues(
44
+ objectInstance: Uint8Array,
45
+ attributeValues: Array<{ attributeHandle: Uint8Array; value: Uint8Array }>,
46
+ userSuppliedTag: Uint8Array,
47
+ transportationType: Uint8Array,
48
+ producingFederate: Uint8Array
49
+ ): void {
50
+ console.log(`Received ${attributeValues.length} attribute updates`);
51
+ }
52
+
53
+ override receiveInteraction(
54
+ interactionClass: Uint8Array,
55
+ parameterValues: Array<{ parameterHandle: Uint8Array; value: Uint8Array }>,
56
+ userSuppliedTag: Uint8Array,
57
+ transportationType: Uint8Array,
58
+ producingFederate: Uint8Array
59
+ ): void {
60
+ console.log(`Received interaction with ${parameterValues.length} parameters`);
61
+ }
62
+ }
63
+
64
+ // 2. Create the RTI Ambassador
65
+ const rtiAmbassador = new RTIAmbassador({
66
+ host: 'rti.example.com',
67
+ port: 15165, // TLS port (default)
68
+ useTls: true,
69
+ });
70
+
71
+ // 3. Connect to the RTI
72
+ const federateAmbassador = new MyFederateAmbassador();
73
+ await rtiAmbassador.connect(federateAmbassador, {
74
+ callbackModel: CallbackModel.EVOKED,
75
+ });
76
+
77
+ // 4. Join a federation
78
+ const joinResult = await rtiAmbassador.joinFederationExecution(
79
+ 'MyFederateType',
80
+ 'TestFederation'
81
+ );
82
+ console.log(`Joined as federate with handle: ${joinResult.federateHandle}`);
83
+
84
+ // 5. Get handles for FOM elements
85
+ const objectClassHandle = await rtiAmbassador.getObjectClassHandle(
86
+ 'HLAobjectRoot.MyClass'
87
+ );
88
+ const attributeHandle = await rtiAmbassador.getAttributeHandle(
89
+ objectClassHandle,
90
+ 'MyAttribute'
91
+ );
92
+
93
+ // 6. Publish and subscribe
94
+ await rtiAmbassador.publishObjectClassAttributes(objectClassHandle, [attributeHandle]);
95
+ await rtiAmbassador.subscribeObjectClassAttributes(objectClassHandle, [attributeHandle]);
96
+
97
+ // 7. Register an object instance
98
+ const objectInstance = await rtiAmbassador.registerObjectInstance(objectClassHandle);
99
+
100
+ // 8. Update attributes
101
+ await rtiAmbassador.updateAttributeValues(
102
+ objectInstance,
103
+ [{ attributeHandle, value: new TextEncoder().encode('Hello HLA!') }],
104
+ new Uint8Array() // user-supplied tag
105
+ );
106
+
107
+ // 9. Send an interaction
108
+ const interactionClass = await rtiAmbassador.getInteractionClassHandle(
109
+ 'HLAinteractionRoot.MyInteraction'
110
+ );
111
+ const parameterHandle = await rtiAmbassador.getParameterHandle(
112
+ interactionClass,
113
+ 'MyParameter'
114
+ );
115
+
116
+ await rtiAmbassador.publishInteractionClass(interactionClass);
117
+ await rtiAmbassador.sendInteraction(
118
+ interactionClass,
119
+ [{ parameterHandle, value: new TextEncoder().encode('Hello!') }],
120
+ new Uint8Array()
121
+ );
122
+
123
+ // 10. Clean up
124
+ await rtiAmbassador.resignFederationExecution(ResignAction.DELETE_OBJECTS_THEN_DIVEST);
125
125
  await rtiAmbassador.disconnect();
126
126
  ```
127
127
 
@@ -149,114 +149,114 @@ sequenceDiagram
149
149
  ```
150
150
 
151
151
  ## API Reference
152
-
153
- ### RTIAmbassador
154
-
155
- The main interface for communicating with the RTI.
156
-
157
- #### Constructor
158
-
159
- ```typescript
160
- new RTIAmbassador(options: RTIAmbassadorOptions)
161
- ```
162
-
163
- **Options:**
164
-
165
- | Option | Type | Default | Description |
166
- |--------|------|---------|-------------|
167
- | `host` | `string` | *required* | RTI host address |
168
- | `port` | `number` | `15165` (TLS) / `15164` (TCP) | RTI port |
169
- | `useTls` | `boolean` | `true` | Use TLS encryption |
170
- | `connectionTimeout` | `number` | `30000` | Connection timeout (ms) |
171
- | `responseTimeout` | `number` | `180000` | Response timeout (ms) |
172
- | `tlsOptions` | `object` | `{}` | TLS options (ca, cert, key) |
173
-
174
- #### Connection Methods
175
-
176
- ```typescript
177
- // Connect to RTI
178
- await rtiAmbassador.connect(federateAmbassador, {
179
- callbackModel: CallbackModel.EVOKED,
180
- });
181
-
182
- // Check connection status
183
- if (rtiAmbassador.isConnected) {
184
- // ...
185
- }
186
-
187
- // Disconnect
188
- await rtiAmbassador.disconnect();
189
- ```
190
-
191
- #### Federation Management
192
-
193
- ```typescript
194
- // Create a federation
195
- await rtiAmbassador.createFederationExecution('FederationName', fomModule);
196
-
197
- // Join a federation
198
- const joinResult = await rtiAmbassador.joinFederationExecution(
199
- 'FederateType',
200
- 'FederationName'
201
- );
202
-
203
- // Resign from a federation
204
- await rtiAmbassador.resignFederationExecution(ResignAction.DELETE_OBJECTS_THEN_DIVEST);
205
-
206
- // Destroy a federation
207
- await rtiAmbassador.destroyFederationExecution('FederationName');
208
- ```
209
-
210
- #### Declaration Management
211
-
212
- ```typescript
213
- // Publish object class attributes
214
- await rtiAmbassador.publishObjectClassAttributes(objectClass, [attr1, attr2]);
215
-
216
- // Subscribe to object class attributes
217
- await rtiAmbassador.subscribeObjectClassAttributes(objectClass, [attr1, attr2]);
218
-
219
- // Publish an interaction class
220
- await rtiAmbassador.publishInteractionClass(interactionClass);
221
-
222
- // Subscribe to an interaction class
223
- await rtiAmbassador.subscribeInteractionClass(interactionClass);
224
-
225
- // Unsubscribe/unpublish
226
- await rtiAmbassador.unpublishObjectClass(objectClass);
227
- await rtiAmbassador.unsubscribeInteractionClass(interactionClass);
228
- ```
229
-
230
- #### Object Management
231
-
232
- ```typescript
233
- // Register an object instance
234
- const objectHandle = await rtiAmbassador.registerObjectInstance(objectClass);
235
-
236
- // Register with a specific name
237
- const namedObject = await rtiAmbassador.registerObjectInstanceWithName(
238
- objectClass,
239
- 'MyObjectName'
240
- );
241
-
242
- // Update attribute values
243
- await rtiAmbassador.updateAttributeValues(
244
- objectHandle,
245
- [{ attributeHandle: attr1, value: new Uint8Array([1, 2, 3]) }],
246
- userSuppliedTag
247
- );
248
-
249
- // Send an interaction
250
- await rtiAmbassador.sendInteraction(
251
- interactionClass,
252
- [{ parameterHandle: param1, value: new Uint8Array([1, 2, 3]) }],
253
- userSuppliedTag
254
- );
255
-
256
- // Delete an object instance
257
- await rtiAmbassador.deleteObjectInstance(objectHandle, userSuppliedTag);
258
- ```
259
-
152
+
153
+ ### RTIAmbassador
154
+
155
+ The main interface for communicating with the RTI.
156
+
157
+ #### Constructor
158
+
159
+ ```typescript
160
+ new RTIAmbassador(options: RTIAmbassadorOptions)
161
+ ```
162
+
163
+ **Options:**
164
+
165
+ | Option | Type | Default | Description |
166
+ |--------|------|---------|-------------|
167
+ | `host` | `string` | *required* | RTI host address |
168
+ | `port` | `number` | `15165` (TLS) / `15164` (TCP) | RTI port |
169
+ | `useTls` | `boolean` | `true` | Use TLS encryption |
170
+ | `connectionTimeout` | `number` | `30000` | Connection timeout (ms) |
171
+ | `responseTimeout` | `number` | `180000` | Response timeout (ms) |
172
+ | `tlsOptions` | `object` | `{}` | TLS options (ca, cert, key) |
173
+
174
+ #### Connection Methods
175
+
176
+ ```typescript
177
+ // Connect to RTI
178
+ await rtiAmbassador.connect(federateAmbassador, {
179
+ callbackModel: CallbackModel.EVOKED,
180
+ });
181
+
182
+ // Check connection status
183
+ if (rtiAmbassador.isConnected) {
184
+ // ...
185
+ }
186
+
187
+ // Disconnect
188
+ await rtiAmbassador.disconnect();
189
+ ```
190
+
191
+ #### Federation Management
192
+
193
+ ```typescript
194
+ // Create a federation
195
+ await rtiAmbassador.createFederationExecution('FederationName', fomModule);
196
+
197
+ // Join a federation
198
+ const joinResult = await rtiAmbassador.joinFederationExecution(
199
+ 'FederateType',
200
+ 'FederationName'
201
+ );
202
+
203
+ // Resign from a federation
204
+ await rtiAmbassador.resignFederationExecution(ResignAction.DELETE_OBJECTS_THEN_DIVEST);
205
+
206
+ // Destroy a federation
207
+ await rtiAmbassador.destroyFederationExecution('FederationName');
208
+ ```
209
+
210
+ #### Declaration Management
211
+
212
+ ```typescript
213
+ // Publish object class attributes
214
+ await rtiAmbassador.publishObjectClassAttributes(objectClass, [attr1, attr2]);
215
+
216
+ // Subscribe to object class attributes
217
+ await rtiAmbassador.subscribeObjectClassAttributes(objectClass, [attr1, attr2]);
218
+
219
+ // Publish an interaction class
220
+ await rtiAmbassador.publishInteractionClass(interactionClass);
221
+
222
+ // Subscribe to an interaction class
223
+ await rtiAmbassador.subscribeInteractionClass(interactionClass);
224
+
225
+ // Unsubscribe/unpublish
226
+ await rtiAmbassador.unpublishObjectClass(objectClass);
227
+ await rtiAmbassador.unsubscribeInteractionClass(interactionClass);
228
+ ```
229
+
230
+ #### Object Management
231
+
232
+ ```typescript
233
+ // Register an object instance
234
+ const objectHandle = await rtiAmbassador.registerObjectInstance(objectClass);
235
+
236
+ // Register with a specific name
237
+ const namedObject = await rtiAmbassador.registerObjectInstanceWithName(
238
+ objectClass,
239
+ 'MyObjectName'
240
+ );
241
+
242
+ // Update attribute values
243
+ await rtiAmbassador.updateAttributeValues(
244
+ objectHandle,
245
+ [{ attributeHandle: attr1, value: new Uint8Array([1, 2, 3]) }],
246
+ userSuppliedTag
247
+ );
248
+
249
+ // Send an interaction
250
+ await rtiAmbassador.sendInteraction(
251
+ interactionClass,
252
+ [{ parameterHandle: param1, value: new Uint8Array([1, 2, 3]) }],
253
+ userSuppliedTag
254
+ );
255
+
256
+ // Delete an object instance
257
+ await rtiAmbassador.deleteObjectInstance(objectHandle, userSuppliedTag);
258
+ ```
259
+
260
260
  #### Time Management
261
261
 
262
262
  ```typescript
@@ -290,147 +290,147 @@ import {
290
290
  const encodedTime = encodeHLAinteger64Time(1_000_000n);
291
291
  const decodedTime = decodeHLAinteger64Time(encodedTime);
292
292
  ```
293
-
294
- #### Support Services
295
-
296
- ```typescript
297
- // Get handles by name
298
- const classHandle = await rtiAmbassador.getObjectClassHandle('HLAobjectRoot.MyClass');
299
- const attrHandle = await rtiAmbassador.getAttributeHandle(classHandle, 'MyAttribute');
300
- const interactionHandle = await rtiAmbassador.getInteractionClassHandle('HLAinteractionRoot.MyInteraction');
301
- const paramHandle = await rtiAmbassador.getParameterHandle(interactionHandle, 'MyParameter');
302
-
303
- // Get names by handle
304
- const className = await rtiAmbassador.getObjectClassName(classHandle);
305
- const attrName = await rtiAmbassador.getAttributeName(classHandle, attrHandle);
306
- ```
307
-
308
- ### FederateAmbassador
309
-
310
- Interface for receiving callbacks from the RTI. Extend `BaseFederateAmbassador` and override the callbacks you need:
311
-
312
- ```typescript
313
- class MyFederateAmbassador extends BaseFederateAmbassador {
314
- // Object discovery
315
- override discoverObjectInstance(objectInstance, objectClass, name, producer) {
316
- // Handle object discovery
317
- }
318
-
319
- // Attribute updates
320
- override reflectAttributeValues(objectInstance, attributeValues, tag, transport, producer) {
321
- // Handle attribute update
322
- }
323
-
324
- // Interactions
325
- override receiveInteraction(interactionClass, parameters, tag, transport, producer) {
326
- // Handle interaction
327
- }
328
-
329
- // Time management
330
- override timeAdvanceGrant(time) {
331
- // Handle time advance grant
332
- }
333
-
334
- // Object removal
335
- override removeObjectInstance(objectInstance, tag, producer) {
336
- // Handle object removal
337
- }
338
- }
339
- ```
340
-
341
- ### Exception Handling
342
-
343
- All HLA exceptions are mapped to TypeScript classes:
344
-
345
- ```typescript
346
- import {
347
- NotConnected,
348
- FederationExecutionDoesNotExist,
349
- ObjectClassNotDefined,
350
- RTIinternalError,
351
- } from '@hla4ts/hla-api';
352
-
353
- try {
354
- await rtiAmbassador.joinFederationExecution('Type', 'NonExistentFederation');
355
- } catch (error) {
356
- if (error instanceof FederationExecutionDoesNotExist) {
357
- console.log('Federation does not exist');
358
- } else if (error instanceof NotConnected) {
359
- console.log('Not connected to RTI');
360
- } else if (error instanceof RTIinternalError) {
361
- console.log('RTI internal error:', error.message);
362
- }
363
- }
364
- ```
365
-
366
- ## Handle Types
367
-
368
- Handles are opaque `Uint8Array` values. The package provides utility functions:
369
-
370
- ```typescript
371
- import { handlesEqual, handleToHex, handleFromHex } from '@hla4ts/hla-api';
372
-
373
- // Compare handles
374
- if (handlesEqual(handle1, handle2)) {
375
- // Handles are equal
376
- }
377
-
378
- // Convert to hex string (for debugging)
379
- console.log(handleToHex(handle)); // "0a1b2c3d..."
380
-
381
- // Parse from hex string
382
- const handle = handleFromHex("0a1b2c3d");
383
- ```
384
-
385
- ## FOM Module Types
386
-
387
- When creating federations, you can provide FOM modules in different formats:
388
-
389
- ```typescript
390
- // Inline XML content
391
- const inlineModule: FomModule = {
392
- type: 'inline',
393
- content: '<?xml version="1.0"?>...',
394
- };
395
-
396
- // File with binary content
397
- const fileModule: FomModule = {
398
- type: 'file',
399
- name: 'myFom.xml',
400
- content: new Uint8Array([...]),
401
- };
402
-
403
- // URL reference
404
- const urlModule: FomModule = {
405
- type: 'url',
406
- url: 'file:///path/to/fom.xml',
407
- };
408
-
409
- await rtiAmbassador.createFederationExecutionWithModules(
410
- 'MyFederation',
411
- [inlineModule, urlModule]
412
- );
413
- ```
414
-
415
- ## Testing
416
-
417
- ```bash
418
- cd packages/hla-api
419
- bun test
420
- ```
421
-
422
- ## Related Packages
423
-
424
- - [`@hla4ts/proto`](../proto) - Protocol buffer types
425
- - [`@hla4ts/transport`](../transport) - Transport layer (TCP/TLS)
426
- - [`@hla4ts/session`](../session) - Session management
427
-
428
- ## References
429
-
430
- - [IEEE 1516-2025](https://standards.ieee.org/standard/1516-2025.html) - HLA 4 Standard
431
- - [Pitch FedProClient](https://github.com/Pitch-Technologies/FedProClient) - Reference implementation
432
- - [HLA 4 Overview](https://onearc.com/articles/what-is-hla-4/) - Introduction to HLA 4
433
-
434
- ## License
435
-
436
- MIT
293
+
294
+ #### Support Services
295
+
296
+ ```typescript
297
+ // Get handles by name
298
+ const classHandle = await rtiAmbassador.getObjectClassHandle('HLAobjectRoot.MyClass');
299
+ const attrHandle = await rtiAmbassador.getAttributeHandle(classHandle, 'MyAttribute');
300
+ const interactionHandle = await rtiAmbassador.getInteractionClassHandle('HLAinteractionRoot.MyInteraction');
301
+ const paramHandle = await rtiAmbassador.getParameterHandle(interactionHandle, 'MyParameter');
302
+
303
+ // Get names by handle
304
+ const className = await rtiAmbassador.getObjectClassName(classHandle);
305
+ const attrName = await rtiAmbassador.getAttributeName(classHandle, attrHandle);
306
+ ```
307
+
308
+ ### FederateAmbassador
309
+
310
+ Interface for receiving callbacks from the RTI. Extend `BaseFederateAmbassador` and override the callbacks you need:
311
+
312
+ ```typescript
313
+ class MyFederateAmbassador extends BaseFederateAmbassador {
314
+ // Object discovery
315
+ override discoverObjectInstance(objectInstance, objectClass, name, producer) {
316
+ // Handle object discovery
317
+ }
318
+
319
+ // Attribute updates
320
+ override reflectAttributeValues(objectInstance, attributeValues, tag, transport, producer) {
321
+ // Handle attribute update
322
+ }
323
+
324
+ // Interactions
325
+ override receiveInteraction(interactionClass, parameters, tag, transport, producer) {
326
+ // Handle interaction
327
+ }
328
+
329
+ // Time management
330
+ override timeAdvanceGrant(time) {
331
+ // Handle time advance grant
332
+ }
333
+
334
+ // Object removal
335
+ override removeObjectInstance(objectInstance, tag, producer) {
336
+ // Handle object removal
337
+ }
338
+ }
339
+ ```
340
+
341
+ ### Exception Handling
342
+
343
+ All HLA exceptions are mapped to TypeScript classes:
344
+
345
+ ```typescript
346
+ import {
347
+ NotConnected,
348
+ FederationExecutionDoesNotExist,
349
+ ObjectClassNotDefined,
350
+ RTIinternalError,
351
+ } from '@hla4ts/hla-api';
352
+
353
+ try {
354
+ await rtiAmbassador.joinFederationExecution('Type', 'NonExistentFederation');
355
+ } catch (error) {
356
+ if (error instanceof FederationExecutionDoesNotExist) {
357
+ console.log('Federation does not exist');
358
+ } else if (error instanceof NotConnected) {
359
+ console.log('Not connected to RTI');
360
+ } else if (error instanceof RTIinternalError) {
361
+ console.log('RTI internal error:', error.message);
362
+ }
363
+ }
364
+ ```
365
+
366
+ ## Handle Types
367
+
368
+ Handles are opaque `Uint8Array` values. The package provides utility functions:
369
+
370
+ ```typescript
371
+ import { handlesEqual, handleToHex, handleFromHex } from '@hla4ts/hla-api';
372
+
373
+ // Compare handles
374
+ if (handlesEqual(handle1, handle2)) {
375
+ // Handles are equal
376
+ }
377
+
378
+ // Convert to hex string (for debugging)
379
+ console.log(handleToHex(handle)); // "0a1b2c3d..."
380
+
381
+ // Parse from hex string
382
+ const handle = handleFromHex("0a1b2c3d");
383
+ ```
384
+
385
+ ## FOM Module Types
386
+
387
+ When creating federations, you can provide FOM modules in different formats:
388
+
389
+ ```typescript
390
+ // Inline XML content
391
+ const inlineModule: FomModule = {
392
+ type: 'inline',
393
+ content: '<?xml version="1.0"?>...',
394
+ };
395
+
396
+ // File with binary content
397
+ const fileModule: FomModule = {
398
+ type: 'file',
399
+ name: 'myFom.xml',
400
+ content: new Uint8Array([...]),
401
+ };
402
+
403
+ // URL reference
404
+ const urlModule: FomModule = {
405
+ type: 'url',
406
+ url: 'file:///path/to/fom.xml',
407
+ };
408
+
409
+ await rtiAmbassador.createFederationExecutionWithModules(
410
+ 'MyFederation',
411
+ [inlineModule, urlModule]
412
+ );
413
+ ```
414
+
415
+ ## Testing
416
+
417
+ ```bash
418
+ cd packages/hla-api
419
+ bun test
420
+ ```
421
+
422
+ ## Related Packages
423
+
424
+ - [`@hla4ts/proto`](../proto) - Protocol buffer types
425
+ - [`@hla4ts/transport`](../transport) - Transport layer (TCP/TLS)
426
+ - [`@hla4ts/session`](../session) - Session management
427
+
428
+ ## References
429
+
430
+ - [IEEE 1516-2025](https://standards.ieee.org/standard/1516-2025.html) - HLA 4 Standard
431
+ - [Pitch FedProClient](https://github.com/Pitch-Technologies/FedProClient) - Reference implementation
432
+ - [HLA 4 Overview](https://onearc.com/articles/what-is-hla-4/) - Introduction to HLA 4
433
+
434
+ ## License
435
+
436
+ MIT