@hla4ts/spacekit 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,154 +1,154 @@
1
- # @hla4ts/spacekit
2
-
3
- SEE-first application layer for HLA federates.
4
-
5
- `@hla4ts/spacekit` is now the default entry point for new users, especially for
6
- SEE and SpaceFOM federates. It sits on top of `@hla4ts/hla-api` and bundles the
7
- runtime pieces most users actually need:
8
-
9
- - `SpacekitApp`: opinionated SEE/SpaceFOM app runtime
10
- - canonical SpaceFOM entity and interaction classes
11
- - late-joiner bootstrap and typed bootstrap state
12
- - run loop, `tick()`, and logical-time send-time helpers
13
- - declarative object/interaction schemas and decorator-based registration
14
- - entity sync, environment parsing, and console logging helpers
15
-
16
- `@hla4ts/spacefom` is now the thinner helper layer underneath it. Use that
17
- package directly only when you need raw SpaceFOM assets such as bundled XML
18
- modules or low-level coders.
19
-
20
- ## Install
21
-
22
- ```bash
23
- bun add @hla4ts/spacekit
24
- ```
25
-
26
- ## Recommended Entry Point
27
-
28
- ```ts
29
- import { PhysicalEntity, SpacekitApp } from "@hla4ts/spacekit";
30
-
31
- const app = new SpacekitApp({
32
- federationName: "SpaceFederation",
33
- federateName: "LunarRover-1",
34
- federateType: "LunarRover",
35
- });
36
-
37
- const rover = new PhysicalEntity("LunarRover-1", {
38
- parent_reference_frame: "AitkenBasinLocalFixed",
39
- });
40
-
41
- await app.start();
42
- await app.registerEntity(rover);
43
-
44
- await app.run({
45
- entities: [rover],
46
- onTick: ({ timeSeconds }) => {
47
- rover.state = {
48
- translation: {
49
- position: [0.5 * timeSeconds, 0, 0],
50
- velocity: [0.5, 0, 0],
51
- },
52
- rotation: {
53
- attitude: { scalar: 1, vector: [0, 0, 0] },
54
- angularVelocity: [0, 0, 0],
55
- },
56
- time: timeSeconds,
57
- };
58
- },
59
- });
60
- ```
61
-
62
- ## What `SpacekitApp` Adds
63
-
64
- - SEE-oriented environment defaults
65
- - built-in `SpaceFomLateJoinerBootstrap`
66
- - automatic reference-frame waiting for `PhysicalEntity` registration
67
- - `tick()` and `run()` for paced logical-time loops
68
- - `getSendTimeMicros()` for timestamped updates/interactions
69
- - `spacefomState` for typed bootstrap state access
70
- - configurable missing-reference-frame behavior via `missingReferenceFrameMode`
71
- - graceful shutdown wiring by default
72
-
73
- If you want an app to keep running when a configured parent reference frame is
74
- not yet available, set `missingReferenceFrameMode: "continue"` on
75
- `SpacekitApp`. The app will warn and proceed instead of throwing during entity
76
- registration.
77
-
78
- ## Canonical SpaceFOM Types
79
-
80
- The canonical decorated SpaceFOM classes now live in `@hla4ts/spacekit`:
81
-
82
- - `ExecutionConfiguration`
83
- - `ReferenceFrame`
84
- - `PhysicalEntity`
85
- - `DynamicalEntity`
86
- - `ModeTransitionRequest`
87
-
88
- These classes are the single source of truth for the runtime adapters,
89
- bootstrap subscriptions, and extension-FOM generation.
90
-
91
- ## Lower-Level Escape Hatches
92
-
93
- If you need to drop below the SEE-first app layer, `@hla4ts/spacekit` still
94
- exports the generic framework primitives:
95
-
96
- - `BaseSpacekitApp`
97
- - `SpacekitFederate`
98
- - `DeclarativeFom`
99
- - `DeclarativeRuntime`
100
- - `SpacekitEntity`
101
- - decorators such as `FomObjectClass` and `FomInteractionClass`
102
-
103
- ## SpaceFOM Assets and Coders
104
-
105
- `@hla4ts/spacekit` re-exports the common SpaceFOM helpers so most SEE users do
106
- not need a second package import:
107
-
108
- ```ts
109
- import {
110
- HLAunicodeStringCoder,
111
- SpaceFomExecutionMode,
112
- encodeSpaceTimeCoordinateState,
113
- loadSpaceFomModules,
114
- } from "@hla4ts/spacekit";
115
- ```
116
-
117
- ## E2E Validation
118
-
119
- The repo includes an opt-in real-stack validation path built around the
120
- `lunar-rover` and `lunar-rover-tracker` examples.
121
-
122
- Prerequisites:
123
-
124
- - target RTI already running
125
- - SpaceMaster already running
126
- - Root Reference Frame Publisher already running
127
-
128
- Command:
129
-
130
- ```bash
131
- RTI_HOST=localhost bun run e2e:spacekit-see
132
- ```
133
-
134
- The command fails on timeout or missing success markers and validates:
135
-
136
- - join/bootstrap completion
137
- - reference-frame discovery
138
- - rover state publication
139
- - tracker receipt of rover updates
140
- - interaction round-trip plus ACK
141
- - multiple logical ticks for both federates
142
-
143
- ## Package Split
144
-
145
- - `@hla4ts/spacekit`: default SEE/SpaceFOM app layer
146
- - `@hla4ts/spacefom`: bundled SpaceFOM XML modules, coders, constants, and optional dashboard loader
147
- - `@hla4ts/hla-api`: direct HLA API surface when you do not want the framework
148
-
149
- ## Test
150
-
151
- ```bash
152
- cd packages/spacekit
153
- bun test
154
- ```
1
+ # @hla4ts/spacekit
2
+
3
+ SEE-first application layer for HLA federates.
4
+
5
+ `@hla4ts/spacekit` is now the default entry point for new users, especially for
6
+ SEE and SpaceFOM federates. It sits on top of `@hla4ts/hla-api` and bundles the
7
+ runtime pieces most users actually need:
8
+
9
+ - `SpacekitApp`: opinionated SEE/SpaceFOM app runtime
10
+ - canonical SpaceFOM entity and interaction classes
11
+ - late-joiner bootstrap and typed bootstrap state
12
+ - run loop, `tick()`, and logical-time send-time helpers
13
+ - declarative object/interaction schemas and decorator-based registration
14
+ - entity sync, environment parsing, and console logging helpers
15
+
16
+ `@hla4ts/spacefom` is now the thinner helper layer underneath it. Use that
17
+ package directly only when you need raw SpaceFOM assets such as bundled XML
18
+ modules or low-level coders.
19
+
20
+ ## Install
21
+
22
+ ```bash
23
+ bun add @hla4ts/spacekit
24
+ ```
25
+
26
+ ## Recommended Entry Point
27
+
28
+ ```ts
29
+ import { PhysicalEntity, SpacekitApp } from "@hla4ts/spacekit";
30
+
31
+ const app = new SpacekitApp({
32
+ federationName: "SpaceFederation",
33
+ federateName: "LunarRover-1",
34
+ federateType: "LunarRover",
35
+ });
36
+
37
+ const rover = new PhysicalEntity("LunarRover-1", {
38
+ parent_reference_frame: "AitkenBasinLocalFixed",
39
+ });
40
+
41
+ await app.start();
42
+ await app.registerEntity(rover);
43
+
44
+ await app.run({
45
+ entities: [rover],
46
+ onTick: ({ timeSeconds }) => {
47
+ rover.state = {
48
+ translation: {
49
+ position: [0.5 * timeSeconds, 0, 0],
50
+ velocity: [0.5, 0, 0],
51
+ },
52
+ rotation: {
53
+ attitude: { scalar: 1, vector: [0, 0, 0] },
54
+ angularVelocity: [0, 0, 0],
55
+ },
56
+ time: timeSeconds,
57
+ };
58
+ },
59
+ });
60
+ ```
61
+
62
+ ## What `SpacekitApp` Adds
63
+
64
+ - SEE-oriented environment defaults
65
+ - built-in `SpaceFomLateJoinerBootstrap`
66
+ - automatic reference-frame waiting for `PhysicalEntity` registration
67
+ - `tick()` and `run()` for paced logical-time loops
68
+ - `getSendTimeMicros()` for timestamped updates/interactions
69
+ - `spacefomState` for typed bootstrap state access
70
+ - configurable missing-reference-frame behavior via `missingReferenceFrameMode`
71
+ - graceful shutdown wiring by default
72
+
73
+ If you want an app to keep running when a configured parent reference frame is
74
+ not yet available, set `missingReferenceFrameMode: "continue"` on
75
+ `SpacekitApp`. The app will warn and proceed instead of throwing during entity
76
+ registration.
77
+
78
+ ## Canonical SpaceFOM Types
79
+
80
+ The canonical decorated SpaceFOM classes now live in `@hla4ts/spacekit`:
81
+
82
+ - `ExecutionConfiguration`
83
+ - `ReferenceFrame`
84
+ - `PhysicalEntity`
85
+ - `DynamicalEntity`
86
+ - `ModeTransitionRequest`
87
+
88
+ These classes are the single source of truth for the runtime adapters,
89
+ bootstrap subscriptions, and extension-FOM generation.
90
+
91
+ ## Lower-Level Escape Hatches
92
+
93
+ If you need to drop below the SEE-first app layer, `@hla4ts/spacekit` still
94
+ exports the generic framework primitives:
95
+
96
+ - `BaseSpacekitApp`
97
+ - `SpacekitFederate`
98
+ - `DeclarativeFom`
99
+ - `DeclarativeRuntime`
100
+ - `SpacekitEntity`
101
+ - decorators such as `FomObjectClass` and `FomInteractionClass`
102
+
103
+ ## SpaceFOM Assets and Coders
104
+
105
+ `@hla4ts/spacekit` re-exports the common SpaceFOM helpers so most SEE users do
106
+ not need a second package import:
107
+
108
+ ```ts
109
+ import {
110
+ HLAunicodeStringCoder,
111
+ SpaceFomExecutionMode,
112
+ encodeSpaceTimeCoordinateState,
113
+ loadSpaceFomModules,
114
+ } from "@hla4ts/spacekit";
115
+ ```
116
+
117
+ ## E2E Validation
118
+
119
+ The repo includes an opt-in real-stack validation path built around the
120
+ `lunar-rover` and `lunar-rover-tracker` examples.
121
+
122
+ Prerequisites:
123
+
124
+ - target RTI already running
125
+ - SpaceMaster already running
126
+ - Root Reference Frame Publisher already running
127
+
128
+ Command:
129
+
130
+ ```bash
131
+ RTI_HOST=localhost bun run e2e:spacekit-see
132
+ ```
133
+
134
+ The command fails on timeout or missing success markers and validates:
135
+
136
+ - join/bootstrap completion
137
+ - reference-frame discovery
138
+ - rover state publication
139
+ - tracker receipt of rover updates
140
+ - interaction round-trip plus ACK
141
+ - multiple logical ticks for both federates
142
+
143
+ ## Package Split
144
+
145
+ - `@hla4ts/spacekit`: default SEE/SpaceFOM app layer
146
+ - `@hla4ts/spacefom`: bundled SpaceFOM XML modules, coders, constants, and optional dashboard loader
147
+ - `@hla4ts/hla-api`: direct HLA API surface when you do not want the framework
148
+
149
+ ## Test
150
+
151
+ ```bash
152
+ cd packages/spacekit
153
+ bun test
154
+ ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hla4ts/spacekit",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "SEE-first starter kit and default application layer for hla4typescript federates",
5
5
  "type": "module",
6
6
  "main": "src/index.ts",
@@ -16,9 +16,9 @@
16
16
  "access": "public"
17
17
  },
18
18
  "dependencies": {
19
- "@hla4ts/hla-api": "^0.1.0",
20
- "@hla4ts/fom-codegen": "^0.1.0",
21
- "@hla4ts/spacefom": "^0.1.0"
19
+ "@hla4ts/hla-api": "^0.1.1",
20
+ "@hla4ts/fom-codegen": "^0.1.1",
21
+ "@hla4ts/spacefom": "^0.1.1"
22
22
  },
23
23
  "scripts": {
24
24
  "typecheck": "tsc --noEmit",
@@ -46,4 +46,4 @@ test("DeclarativeFom registers object and interaction schemas", () => {
46
46
  expect(model.objectClasses[0]?.attributes?.[0]?.name).toBe("name");
47
47
  expect(model.interactionClasses[0]?.name).toBe("HLAinteractionRoot.TestInteraction");
48
48
  expect(model.interactionClasses[0]?.parameters?.[0]?.name).toBe("count");
49
- });
49
+ });
@@ -1,14 +1,14 @@
1
- import { buildDeclarativeFomFromDecorators, type FomClassConstructor } from "./decorators.ts";
2
- import type { DeclarativeFom } from "./declarative.ts";
3
-
4
- export interface DeclareSpaceFomOptions {
5
- objectClasses?: FomClassConstructor[];
6
- interactionClasses?: FomClassConstructor[];
7
- }
8
-
9
- export function declareSpaceFom(options: DeclareSpaceFomOptions = {}): DeclarativeFom {
10
- return buildDeclarativeFomFromDecorators({
11
- objectClasses: options.objectClasses ?? [],
12
- interactionClasses: options.interactionClasses ?? [],
13
- });
14
- }
1
+ import { buildDeclarativeFomFromDecorators, type FomClassConstructor } from "./decorators.ts";
2
+ import type { DeclarativeFom } from "./declarative.ts";
3
+
4
+ export interface DeclareSpaceFomOptions {
5
+ objectClasses?: FomClassConstructor[];
6
+ interactionClasses?: FomClassConstructor[];
7
+ }
8
+
9
+ export function declareSpaceFom(options: DeclareSpaceFomOptions = {}): DeclarativeFom {
10
+ return buildDeclarativeFomFromDecorators({
11
+ objectClasses: options.objectClasses ?? [],
12
+ interactionClasses: options.interactionClasses ?? [],
13
+ });
14
+ }
package/src/index.ts CHANGED
@@ -1,51 +1,51 @@
1
- /**
2
- * @hla4ts/spacekit
3
- *
4
- * SEE-first lifecycle + declarative helpers for HLA federates.
5
- */
6
-
7
- export { SpacekitFederate } from "./federate.ts";
8
- export type { SpacekitFederateConfig, SpacekitFomConfig, FederateHandlers } from "./types.ts";
9
- export * from "./object-model.ts";
10
- export * from "./declarative.ts";
11
- export * from "./declarative-runtime.ts";
12
- export * from "./decorators.ts";
13
- export * from "./entity.ts";
14
- export {
15
- SpacekitApp as BaseSpacekitApp,
16
- } from "./app.ts";
17
- export type {
18
- SpacekitBootstrapper,
19
- SpacekitAppConfig as BaseSpacekitAppConfig,
20
- RegisterObjectOptions,
21
- TrackOptions,
22
- TrackRecord,
23
- } from "./app.ts";
24
- export { SpacekitApp } from "./see-app.ts";
25
- export type { MissingReferenceFrameMode, SpacekitAppOptions } from "./see-app.ts";
26
- export * from "./time-advance.ts";
27
- export * from "./env.ts";
28
- export * from "./logger.ts";
29
- export * from "./spacefom-entities.ts";
30
- export * from "./spacefom-interactions.ts";
31
- export * from "./spacefom-bootstrap.ts";
32
- export * from "./spacefom-config.ts";
33
- export * from "./declare-spacefom.ts";
34
- export {
35
- HLAunicodeStringCoder,
36
- SpaceFomExecutionMode,
37
- SpaceFomMtrMode,
38
- SpaceFomSyncPointLabels,
39
- loadSpaceFomModules,
40
- SpaceFomBaseModules,
41
- } from "@hla4ts/spacefom";
42
- export type {
43
- SpaceFomBaseModuleName,
44
- SpaceFomModuleFormat,
45
- SpaceFomCoder,
46
- AttitudeQuaternion,
47
- Matrix3,
48
- SpaceTimeCoordinateState,
49
- Vector3,
50
- } from "@hla4ts/spacefom";
51
- export * from "@hla4ts/spacefom";
1
+ /**
2
+ * @hla4ts/spacekit
3
+ *
4
+ * SEE-first lifecycle + declarative helpers for HLA federates.
5
+ */
6
+
7
+ export { SpacekitFederate } from "./federate.ts";
8
+ export type { SpacekitFederateConfig, SpacekitFomConfig, FederateHandlers } from "./types.ts";
9
+ export * from "./object-model.ts";
10
+ export * from "./declarative.ts";
11
+ export * from "./declarative-runtime.ts";
12
+ export * from "./decorators.ts";
13
+ export * from "./entity.ts";
14
+ export {
15
+ SpacekitApp as BaseSpacekitApp,
16
+ } from "./app.ts";
17
+ export type {
18
+ SpacekitBootstrapper,
19
+ SpacekitAppConfig as BaseSpacekitAppConfig,
20
+ RegisterObjectOptions,
21
+ TrackOptions,
22
+ TrackRecord,
23
+ } from "./app.ts";
24
+ export { SpacekitApp } from "./see-app.ts";
25
+ export type { MissingReferenceFrameMode, SpacekitAppOptions } from "./see-app.ts";
26
+ export * from "./time-advance.ts";
27
+ export * from "./env.ts";
28
+ export * from "./logger.ts";
29
+ export * from "./spacefom-entities.ts";
30
+ export * from "./spacefom-interactions.ts";
31
+ export * from "./spacefom-bootstrap.ts";
32
+ export * from "./spacefom-config.ts";
33
+ export * from "./declare-spacefom.ts";
34
+ export {
35
+ HLAunicodeStringCoder,
36
+ SpaceFomExecutionMode,
37
+ SpaceFomMtrMode,
38
+ SpaceFomSyncPointLabels,
39
+ loadSpaceFomModules,
40
+ SpaceFomBaseModules,
41
+ } from "@hla4ts/spacefom";
42
+ export type {
43
+ SpaceFomBaseModuleName,
44
+ SpaceFomModuleFormat,
45
+ SpaceFomCoder,
46
+ AttitudeQuaternion,
47
+ Matrix3,
48
+ SpaceTimeCoordinateState,
49
+ Vector3,
50
+ } from "@hla4ts/spacefom";
51
+ export * from "@hla4ts/spacefom";
@@ -272,4 +272,4 @@ export class InteractionClassAdapter<T extends object> {
272
272
  await rti.sendInteraction(this.interactionHandle, payload, userSuppliedTag);
273
273
  }
274
274
  }
275
- }
275
+ }
@@ -1,62 +1,62 @@
1
- import { expect, test } from "bun:test";
2
- import { SpacekitApp } from "./see-app.ts";
3
-
4
- test("SpacekitApp exposes SEE timing helpers", () => {
5
- const app = new SpacekitApp({
6
- federationName: "SpaceFederation",
7
- federateName: "TestFederate",
8
- federateType: "TestFederate",
9
- lookaheadMicros: 500_000n,
10
- updatePeriodMicros: 1_000_000n,
11
- });
12
-
13
- expect(app.lookaheadMicros).toBe(500_000n);
14
- expect(app.updatePeriodMicros).toBe(1_000_000n);
15
- expect(app.getSendTimeMicros(10_000_000n)).toBe(10_500_000n);
16
- expect(app.shouldLogTick(1)).toBe(true);
17
- });
18
-
19
- test("SpacekitApp can continue when a reference frame is missing", async () => {
20
- const warnings: Array<{ message: string; data?: Record<string, unknown> }> = [];
21
- const app = new SpacekitApp({
22
- federationName: "SpaceFederation",
23
- federateName: "TestFederate",
24
- federateType: "TestFederate",
25
- referenceFrameTimeoutMs: 1,
26
- missingReferenceFrameMode: "continue",
27
- logger: {
28
- debug() {},
29
- info() {},
30
- warn(message, data) {
31
- warnings.push({ message, data });
32
- },
33
- error() {},
34
- },
35
- });
36
-
37
- (app as unknown as { _bootstrapState: unknown })._bootstrapState = {
38
- referenceFrames: [],
39
- };
40
-
41
- await expect(app.waitForReferenceFrame("MissingFrame", 1)).resolves.toBeUndefined();
42
- expect(
43
- warnings.some((entry) => entry.message === "Proceeding without discovered reference frame.")
44
- ).toBe(true);
45
- });
46
-
47
- test("SpacekitApp still errors by default when a reference frame is missing", async () => {
48
- const app = new SpacekitApp({
49
- federationName: "SpaceFederation",
50
- federateName: "TestFederate",
51
- federateType: "TestFederate",
52
- referenceFrameTimeoutMs: 1,
53
- });
54
-
55
- (app as unknown as { _bootstrapState: unknown })._bootstrapState = {
56
- referenceFrames: [],
57
- };
58
-
59
- await expect(app.waitForReferenceFrame("MissingFrame", 1)).rejects.toThrow(
60
- "Reference frame not discovered: MissingFrame"
61
- );
62
- });
1
+ import { expect, test } from "bun:test";
2
+ import { SpacekitApp } from "./see-app.ts";
3
+
4
+ test("SpacekitApp exposes SEE timing helpers", () => {
5
+ const app = new SpacekitApp({
6
+ federationName: "SpaceFederation",
7
+ federateName: "TestFederate",
8
+ federateType: "TestFederate",
9
+ lookaheadMicros: 500_000n,
10
+ updatePeriodMicros: 1_000_000n,
11
+ });
12
+
13
+ expect(app.lookaheadMicros).toBe(500_000n);
14
+ expect(app.updatePeriodMicros).toBe(1_000_000n);
15
+ expect(app.getSendTimeMicros(10_000_000n)).toBe(10_500_000n);
16
+ expect(app.shouldLogTick(1)).toBe(true);
17
+ });
18
+
19
+ test("SpacekitApp can continue when a reference frame is missing", async () => {
20
+ const warnings: Array<{ message: string; data?: Record<string, unknown> }> = [];
21
+ const app = new SpacekitApp({
22
+ federationName: "SpaceFederation",
23
+ federateName: "TestFederate",
24
+ federateType: "TestFederate",
25
+ referenceFrameTimeoutMs: 1,
26
+ missingReferenceFrameMode: "continue",
27
+ logger: {
28
+ debug() {},
29
+ info() {},
30
+ warn(message, data) {
31
+ warnings.push({ message, data });
32
+ },
33
+ error() {},
34
+ },
35
+ });
36
+
37
+ (app as unknown as { _bootstrapState: unknown })._bootstrapState = {
38
+ referenceFrames: [],
39
+ };
40
+
41
+ await expect(app.waitForReferenceFrame("MissingFrame", 1)).resolves.toBeUndefined();
42
+ expect(
43
+ warnings.some((entry) => entry.message === "Proceeding without discovered reference frame.")
44
+ ).toBe(true);
45
+ });
46
+
47
+ test("SpacekitApp still errors by default when a reference frame is missing", async () => {
48
+ const app = new SpacekitApp({
49
+ federationName: "SpaceFederation",
50
+ federateName: "TestFederate",
51
+ federateType: "TestFederate",
52
+ referenceFrameTimeoutMs: 1,
53
+ });
54
+
55
+ (app as unknown as { _bootstrapState: unknown })._bootstrapState = {
56
+ referenceFrames: [],
57
+ };
58
+
59
+ await expect(app.waitForReferenceFrame("MissingFrame", 1)).rejects.toThrow(
60
+ "Reference frame not discovered: MissingFrame"
61
+ );
62
+ });