@wandelbots/nova-js 4.5.0-pr.322.aa66640 → 4.5.0-pr.324.1203649

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.
@@ -1,6 +1,5 @@
1
1
  import { t as Nova } from "../../Nova-DdbUm145.mjs";
2
- import { JsMsg } from "@nats-io/jetstream";
3
- import { ConnectionOptions, Msg, NatsConnection } from "@nats-io/nats-core";
2
+ import { ConnectionOptions, MsgHdrs, NatsConnection } from "@nats-io/nats-core";
4
3
  //#region src/lib/experimental/nats/buildNatsServerUrl.d.ts
5
4
  /**
6
5
  * Builds the WebSocket URL for a NOVA instance's NATS gateway from its
@@ -2859,23 +2858,6 @@ interface NatsSubscribePayloads {
2859
2858
  "nova.v2.events.cells.{cell}.controllers.{controller}.deleted": RobotControllerDeletedEvent;
2860
2859
  }
2861
2860
  type NatsSubscribeSubject = keyof NatsSubscribePayloads;
2862
- /**
2863
- * The JetStream stream backing each subject that retains only its latest
2864
- * message (`max_msgs_per_subject: 1` in src/asyncapi.yaml), so that
2865
- * message is the subject's current state.
2866
- */
2867
- declare const natsStreamBySubject: {
2868
- readonly "nova.v2.cells.{cell}": "system-state";
2869
- readonly "nova.v2.cells.{cell}.apps.{app}": "system-state";
2870
- readonly "nova.v2.cells.{cell}.controllers.{controller}": "system-state";
2871
- readonly "nova.v2.cells.{cell}.status": "system-state";
2872
- readonly "nova.v2.system.status": "system-state";
2873
- readonly "nova.v2.cells.{cell}.collision.setups.{setup}": "system-state";
2874
- readonly "nova.v2.cells.{cell}.bus-ios.status": "system-state";
2875
- readonly "nova.v2.cells.{cell}.controllers.{controller}.motion-groups.{motion-group}.description": "system-state";
2876
- };
2877
- /** Subjects whose current value can be replayed via `{ replayLast: true }`. */
2878
- type NatsPersistedSubject = keyof typeof natsStreamBySubject;
2879
2861
  /** Request payload types for subjects the client sends requests to. */
2880
2862
  interface NatsRequestPayloads {
2881
2863
  /**
@@ -3191,6 +3173,24 @@ type NatsPublishSubject = keyof NatsPublishPayloads;
3191
3173
  //#endregion
3192
3174
  //#region src/lib/experimental/nats/NovaNatsClient.d.ts
3193
3175
  type NovaNatsClientConfig = ConnectionOptions;
3176
+ /**
3177
+ * The fields of a received message that exist on both a core NATS `Msg` and
3178
+ * a JetStream `JsMsg` — a subscription delivers the former by default and
3179
+ * the latter with `lastMessage: true` (see {@link NatsSubscribeOptions}),
3180
+ * so handlers see only what both have in common.
3181
+ */
3182
+ interface NatsReceivedMsg {
3183
+ /** The concrete subject the message was published to. */
3184
+ subject: string;
3185
+ /** The message's raw payload bytes. */
3186
+ data: Uint8Array;
3187
+ /** Headers set by the server or the publisher, if any. */
3188
+ headers?: MsgHdrs;
3189
+ /** The payload decoded as JSON. */
3190
+ json<T>(): T;
3191
+ /** The payload decoded as a string. */
3192
+ string(): string;
3193
+ }
3194
3194
  /**
3195
3195
  * A received message, annotated with the values of the subject template's
3196
3196
  * `{param}` placeholders as extracted from the message's concrete subject.
@@ -3198,27 +3198,21 @@ type NovaNatsClientConfig = ConnectionOptions;
3198
3198
  * a handler knows which entity a message belongs to. Typed per subject via
3199
3199
  * the generated `NatsOperationParams`.
3200
3200
  */
3201
- type NatsSubscribeMsg<K extends NatsSubscribeSubject> = (Msg | JsMsg) & {
3201
+ type NatsSubscribeMsg<K extends NatsSubscribeSubject> = NatsReceivedMsg & {
3202
3202
  subjectParams: NatsOperationParams[K];
3203
3203
  };
3204
- type NatsMessageHandler<K extends NatsSubscribeSubject> = (payload: NatsSubscribePayloads[K], msg: NatsSubscribeMsg<K>) => void | Promise<void>;
3205
- /**
3206
- * Extra options for {@link NovaNatsClient.subscribe}. `replayLast` is only
3207
- * offered on subjects the spec marks as retaining their latest message, so
3208
- * asking for a replay that could never arrive is a compile error.
3209
- */
3210
- type NatsSubscribeOptions<K extends NatsSubscribeSubject> = K extends NatsPersistedSubject ? {
3204
+ type NatsSubscribeOptions = {
3211
3205
  /**
3212
- * Deliver the subject's current value immediately on subscribe,
3213
- * before any subsequent updates. With a wildcard subscription (e.g.
3214
- * `{ cell: "*" }`) the current value of every matching subject is
3215
- * delivered, not just one.
3206
+ * When true, the subscription immediately replays the last JetStream
3207
+ * message persisted for each subject matching the subscription (one per
3208
+ * concrete subject when subscribing with wildcards), then continues with
3209
+ * live messages. Requires the server to have a JetStream stream capturing
3210
+ * the subscribed subject; subscribing fails with an error if none exists.
3216
3211
  */
3217
- replayLast?: boolean;
3218
- } : {
3219
- replayLast?: never;
3212
+ lastMessage?: boolean;
3220
3213
  };
3221
- type SubscribeArgs<K extends NatsSubscribeSubject> = keyof NatsOperationParams[K] extends never ? [handler: NatsMessageHandler<K>, opts?: NatsSubscribeOptions<K>] : [params: NatsOperationParams[K], handler: NatsMessageHandler<K>, opts?: NatsSubscribeOptions<K>];
3214
+ type NatsMessageHandler<K extends NatsSubscribeSubject> = (payload: NatsSubscribePayloads[K], msg: NatsSubscribeMsg<K>) => void | Promise<void>;
3215
+ type SubscribeArgs<K extends NatsSubscribeSubject> = keyof NatsOperationParams[K] extends never ? [handler: NatsMessageHandler<K>, options?: NatsSubscribeOptions] : [params: NatsOperationParams[K], handler: NatsMessageHandler<K>, options?: NatsSubscribeOptions];
3222
3216
  /**
3223
3217
  * Typed NATS client for the Wandelbots NOVA messaging API, generated from
3224
3218
  * src/asyncapi.yaml (see scripts/generate-nats-client.ts).
@@ -3256,11 +3250,9 @@ declare class NovaNatsClient {
3256
3250
  * nats.subscribe("nova.v2.cells.{cell}.status", { cell: "*" },
3257
3251
  * (services, msg) => console.log(msg.subjectParams.cell, services))
3258
3252
  *
3259
- * On subjects that retain their latest message, pass `{ replayLast: true }`
3260
- * to receive the current value immediately instead of waiting for the next
3261
- * update — useful for a subscriber that starts after the last change:
3262
- *
3263
- * nats.subscribe("nova.v2.system.status", onStatus, { replayLast: true })
3253
+ * With `{ lastMessage: true }` as the final argument, the last JetStream
3254
+ * message persisted for each matching subject is replayed to the handler
3255
+ * immediately, before live messages (see {@link NatsSubscribeOptions}).
3264
3256
  *
3265
3257
  * Returns a function that unsubscribes when called.
3266
3258
  */
@@ -3287,5 +3279,5 @@ declare class NovaNatsClient {
3287
3279
  publish<K extends NatsPublishSubject>(subject: K, params: NatsOperationParams[K], payload: NatsPublishPayloads[K]): Promise<void>;
3288
3280
  }
3289
3281
  //#endregion
3290
- export { type AbbController, type AddVirtualControllerMotionGroupRequest, type App, type AppCreatedEvent, type AppDeletedEvent, type AppEventData, type AppUpdatedEvent, type Box, type BusIOsState, type BusIOsStateEnum, type Capacity, type Capsule, type CartesianLimits, type Cell, type CellCreatedEvent, type CellCycleEvent, type CellDeletedEvent, type CellDescription, type CellEventData, type CellName, type CellUpdatedEvent, type CloudEvent, type Collider, type ColliderDictionary, type ColliderDictionary1, type ColliderDictionary2, type CollisionMotionGroupLink, type CollisionMotionGroupTool, type CollisionMotionGroupTool1, type CollisionSetup, type ContainerEnvironment, type ContainerImage, type ContainerResources, type ContainerStorage, type ControllerNetworkInterface, type ConvexHull, type Cylinder, type DHParameter, type Execute, type Execute1, type FanucController, type IOBooleanValue, type IOFloatValue, type IOIntegerValue, type IOValue, type ImageCredentials, type JoggingDetails, type JoggingPausedByUser, type JoggingPausedNearCollision, type JoggingPausedNearJointLimit, type JoggingPausedNearSingularity, type JoggingPausedOnIO, type JoggingRunning, type JointLimits, type JointTypeEnum, type Joints, type Joints1, type Joints2, type Joints3, type KukaController, type LimitRange, type LimitSet, type LinkChain, type LinkChain1, type ListIOValuesResponse, type Location, type Manufacturer, type MotionGroupDescription, type MotionGroupFromJSON, type MotionGroupFromModel, type MotionGroupModel, type MotionGroupState, type MotionGroupState1, type MotionGroupState_JointLimitReached, type MotionGroupState_JointLimitReached1, type NatsErrorPayload, type NatsOperationParams, type NatsPersistedSubject, type NatsPublishPayloads, type NatsPublishSubject, type NatsReplyPayloads, type NatsRequestPayloads, type NatsRequestSubject, type NatsSubscribeMsg, type NatsSubscribeOptions, type NatsSubscribePayloads, type NatsSubscribeSubject, type NetworkState, type NetworkStatusChangedEvent, NovaNatsClient, type NovaNatsClientConfig, type OperatingState, type OperationLimits, type OperationMode, type Payload, type PayloadDictionary, type Plane, type Pose, type Pose1, type Pose2, type Pose3, type Pose4, type Pose5, type ProgramRunState, type ProgramRunState1, type ProgramStatus, type Rectangle, type RectangularCapsule, type RobotController, type RobotControllerCreatedEvent, type RobotControllerDeletedEvent, type RobotControllerEventData, type RobotControllerState, type RobotControllerUpdatedEvent, type RobotSystemMode, type RotationVector, type SafetyStateType, type SafetyToolColliders, type SelectIOs, type ServiceGroup, type ServiceStatus, type ServiceStatusList, type ServiceStatusPhase, type ServiceStatusSeverity, type Sphere, type StreamIOValuesResponse, type SystemUpdateCompletedEvent, type SystemUpdateStartedEvent, type TcpOffset, type TcpOffsetDictionary, type TrajectoryDetails, type TrajectoryEnded, type TrajectoryPausedByUser, type TrajectoryPausedOnIO, type TrajectoryRunning, type TrajectoryWaitForIO, type UniversalrobotsController, type Vector3D, type Vector3D1, type Vector3D2, type VirtualController, type YaskawaController, buildNatsServerUrl, natsStreamBySubject };
3282
+ export { type AbbController, type AddVirtualControllerMotionGroupRequest, type App, type AppCreatedEvent, type AppDeletedEvent, type AppEventData, type AppUpdatedEvent, type Box, type BusIOsState, type BusIOsStateEnum, type Capacity, type Capsule, type CartesianLimits, type Cell, type CellCreatedEvent, type CellCycleEvent, type CellDeletedEvent, type CellDescription, type CellEventData, type CellName, type CellUpdatedEvent, type CloudEvent, type Collider, type ColliderDictionary, type ColliderDictionary1, type ColliderDictionary2, type CollisionMotionGroupLink, type CollisionMotionGroupTool, type CollisionMotionGroupTool1, type CollisionSetup, type ContainerEnvironment, type ContainerImage, type ContainerResources, type ContainerStorage, type ControllerNetworkInterface, type ConvexHull, type Cylinder, type DHParameter, type Execute, type Execute1, type FanucController, type IOBooleanValue, type IOFloatValue, type IOIntegerValue, type IOValue, type ImageCredentials, type JoggingDetails, type JoggingPausedByUser, type JoggingPausedNearCollision, type JoggingPausedNearJointLimit, type JoggingPausedNearSingularity, type JoggingPausedOnIO, type JoggingRunning, type JointLimits, type JointTypeEnum, type Joints, type Joints1, type Joints2, type Joints3, type KukaController, type LimitRange, type LimitSet, type LinkChain, type LinkChain1, type ListIOValuesResponse, type Location, type Manufacturer, type MotionGroupDescription, type MotionGroupFromJSON, type MotionGroupFromModel, type MotionGroupModel, type MotionGroupState, type MotionGroupState1, type MotionGroupState_JointLimitReached, type MotionGroupState_JointLimitReached1, type NatsErrorPayload, type NatsOperationParams, type NatsPublishPayloads, type NatsPublishSubject, type NatsReceivedMsg, type NatsReplyPayloads, type NatsRequestPayloads, type NatsRequestSubject, type NatsSubscribeMsg, type NatsSubscribeOptions, type NatsSubscribePayloads, type NatsSubscribeSubject, type NetworkState, type NetworkStatusChangedEvent, NovaNatsClient, type NovaNatsClientConfig, type OperatingState, type OperationLimits, type OperationMode, type Payload, type PayloadDictionary, type Plane, type Pose, type Pose1, type Pose2, type Pose3, type Pose4, type Pose5, type ProgramRunState, type ProgramRunState1, type ProgramStatus, type Rectangle, type RectangularCapsule, type RobotController, type RobotControllerCreatedEvent, type RobotControllerDeletedEvent, type RobotControllerEventData, type RobotControllerState, type RobotControllerUpdatedEvent, type RobotSystemMode, type RotationVector, type SafetyStateType, type SafetyToolColliders, type SelectIOs, type ServiceGroup, type ServiceStatus, type ServiceStatusList, type ServiceStatusPhase, type ServiceStatusSeverity, type Sphere, type StreamIOValuesResponse, type SystemUpdateCompletedEvent, type SystemUpdateStartedEvent, type TcpOffset, type TcpOffsetDictionary, type TrajectoryDetails, type TrajectoryEnded, type TrajectoryPausedByUser, type TrajectoryPausedOnIO, type TrajectoryRunning, type TrajectoryWaitForIO, type UniversalrobotsController, type Vector3D, type Vector3D1, type Vector3D2, type VirtualController, type YaskawaController, buildNatsServerUrl };
3291
3283
  //# sourceMappingURL=index.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../../../src/lib/experimental/nats/buildNatsServerUrl.ts","../../../src/lib/experimental/nats/generated/types.ts","../../../src/lib/experimental/nats/generated/operations.ts","../../../src/lib/experimental/nats/NovaNatsClient.ts"],"mappings":"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"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../../../src/lib/experimental/nats/buildNatsServerUrl.ts","../../../src/lib/experimental/nats/generated/types.ts","../../../src/lib/experimental/nats/generated/operations.ts","../../../src/lib/experimental/nats/NovaNatsClient.ts"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import { a as parseNovaInstanceUrl } from "../../converters-DnG1fX23.mjs";
2
- import { DeliverPolicy, jetstream } from "@nats-io/jetstream";
2
+ import { DeliverPolicy, jetstream, jetstreamManager } from "@nats-io/jetstream";
3
3
  import { wsconnect } from "@nats-io/nats-core";
4
4
  //#region src/lib/experimental/nats/buildNatsServerUrl.ts
5
5
  /**
@@ -15,23 +15,6 @@ function buildNatsServerUrl(instanceUrl) {
15
15
  return `${url.protocol === "https:" ? "wss:" : "ws:"}//${url.host}/api/nats`;
16
16
  }
17
17
  //#endregion
18
- //#region src/lib/experimental/nats/generated/operations.ts
19
- /**
20
- * The JetStream stream backing each subject that retains only its latest
21
- * message (`max_msgs_per_subject: 1` in src/asyncapi.yaml), so that
22
- * message is the subject's current state.
23
- */
24
- const natsStreamBySubject = {
25
- "nova.v2.cells.{cell}": "system-state",
26
- "nova.v2.cells.{cell}.apps.{app}": "system-state",
27
- "nova.v2.cells.{cell}.controllers.{controller}": "system-state",
28
- "nova.v2.cells.{cell}.status": "system-state",
29
- "nova.v2.system.status": "system-state",
30
- "nova.v2.cells.{cell}.collision.setups.{setup}": "system-state",
31
- "nova.v2.cells.{cell}.bus-ios.status": "system-state",
32
- "nova.v2.cells.{cell}.controllers.{controller}.motion-groups.{motion-group}.description": "system-state"
33
- };
34
- //#endregion
35
18
  //#region src/lib/experimental/nats/buildSubject.ts
36
19
  /**
37
20
  * Builds a NATS subject from an AsyncAPI-style channel address template
@@ -130,51 +113,50 @@ var NovaNatsClient = class {
130
113
  * nats.subscribe("nova.v2.cells.{cell}.status", { cell: "*" },
131
114
  * (services, msg) => console.log(msg.subjectParams.cell, services))
132
115
  *
133
- * On subjects that retain their latest message, pass `{ replayLast: true }`
134
- * to receive the current value immediately instead of waiting for the next
135
- * update — useful for a subscriber that starts after the last change:
136
- *
137
- * nats.subscribe("nova.v2.system.status", onStatus, { replayLast: true })
116
+ * With `{ lastMessage: true }` as the final argument, the last JetStream
117
+ * message persisted for each matching subject is replayed to the handler
118
+ * immediately, before live messages (see {@link NatsSubscribeOptions}).
138
119
  *
139
120
  * Returns a function that unsubscribes when called.
140
121
  */
141
122
  async subscribe(subject, ...args) {
142
- const hasParams = typeof args[0] !== "function";
143
- const params = hasParams ? args[0] : {};
144
- const handler = hasParams ? args[1] : args[0];
145
- const opts = hasParams ? args[2] : args[1];
123
+ const [params, handler, options] = typeof args[0] === "function" ? [
124
+ {},
125
+ args[0],
126
+ args[1]
127
+ ] : [
128
+ args[0],
129
+ args[1],
130
+ args[2]
131
+ ];
146
132
  const nc = await this.connect();
147
133
  const resolvedSubject = buildSubject(subject, params);
148
134
  const paramPositions = [];
149
135
  for (const [index, token] of subject.split(".").entries()) if (token.startsWith("{") && token.endsWith("}")) paramPositions.push([token.slice(1, -1), index]);
150
- const deliver = async (msg) => {
151
- try {
152
- const subjectTokens = msg.subject.split(".");
153
- const subjectParams = Object.fromEntries(paramPositions.map(([name, index]) => [name, subjectTokens[index] ?? ""]));
154
- await handler(msg.json(), Object.assign(msg, { subjectParams }));
155
- } catch (err) {
156
- console.error(`Error handling NATS message on subject "${resolvedSubject}"`, err);
157
- }
158
- };
159
- const deliverAll = (messages) => {
136
+ const dispatch = (messages) => {
160
137
  (async () => {
161
- for await (const msg of messages) await deliver(msg);
138
+ for await (const msg of messages) try {
139
+ const subjectTokens = msg.subject.split(".");
140
+ const subjectParams = Object.fromEntries(paramPositions.map(([name, index]) => [name, subjectTokens[index] ?? ""]));
141
+ await handler(msg.json(), Object.assign(msg, { subjectParams }));
142
+ } catch (err) {
143
+ console.error(`Error handling NATS message on subject "${resolvedSubject}"`, err);
144
+ }
162
145
  })().catch((err) => {
163
146
  console.error(`NATS subscription iterator failed for "${resolvedSubject}"`, err);
164
147
  });
165
148
  };
166
- if (opts?.replayLast) {
167
- const messages = await (await jetstream(nc).consumers.get(natsStreamBySubject[subject], {
149
+ if (options?.lastMessage) {
150
+ const streamName = await (await jetstreamManager(nc)).streams.find(resolvedSubject);
151
+ const messages = await (await jetstream(nc).consumers.get(streamName, {
168
152
  filter_subjects: [resolvedSubject],
169
153
  deliver_policy: DeliverPolicy.LastPerSubject
170
154
  })).consume();
171
- deliverAll(messages);
172
- return () => {
173
- messages.stop();
174
- };
155
+ dispatch(messages);
156
+ return () => void messages.close();
175
157
  }
176
158
  const sub = nc.subscribe(resolvedSubject);
177
- deliverAll(sub);
159
+ dispatch(sub);
178
160
  return () => sub.unsubscribe();
179
161
  }
180
162
  /**
@@ -205,6 +187,6 @@ var NovaNatsClient = class {
205
187
  }
206
188
  };
207
189
  //#endregion
208
- export { NovaNatsClient, buildNatsServerUrl, natsStreamBySubject };
190
+ export { NovaNatsClient, buildNatsServerUrl };
209
191
 
210
192
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../../../src/lib/experimental/nats/buildNatsServerUrl.ts","../../../src/lib/experimental/nats/generated/operations.ts","../../../src/lib/experimental/nats/buildSubject.ts","../../../src/lib/experimental/nats/NovaNatsClient.ts"],"sourcesContent":["import { parseNovaInstanceUrl } from \"../../converters.ts\"\n\n/**\n * Builds the WebSocket URL for a NOVA instance's NATS gateway from its\n * instance URL, e.g. `https://foo.instance.wandelbots.io` becomes\n * `wss://foo.instance.wandelbots.io/api/nats`.\n *\n * Pass the result as `servers` in the `NovaNatsClientConfig` passed to\n * `NovaNatsClient`.\n */\nexport function buildNatsServerUrl(instanceUrl: string): string {\n const url = parseNovaInstanceUrl(instanceUrl)\n const protocol = url.protocol === \"https:\" ? \"wss:\" : \"ws:\"\n return `${protocol}//${url.host}/api/nats`\n}\n","/**\n * AUTO-GENERATED FILE - DO NOT EDIT.\n * Generated from src/asyncapi.yaml by scripts/generate-nats-client.ts.\n * Run `pnpm generate:nats` to regenerate.\n */\n\nimport type {\n App,\n AppCreatedEvent,\n AppDeletedEvent,\n AppUpdatedEvent,\n BusIOsState,\n Cell,\n CellCreatedEvent,\n CellCycleEvent,\n CellDeletedEvent,\n CellUpdatedEvent,\n CollisionSetup,\n ListIOValuesResponse,\n MotionGroupDescription,\n NatsErrorPayload,\n NetworkStatusChangedEvent,\n ProgramStatus,\n RobotController,\n RobotControllerCreatedEvent,\n RobotControllerDeletedEvent,\n RobotControllerState,\n RobotControllerUpdatedEvent,\n SelectIOs,\n ServiceStatusList,\n StreamIOValuesResponse,\n SystemUpdateCompletedEvent,\n SystemUpdateStartedEvent,\n} from \"./types.ts\"\n\n/** Subject parameters required by each NATS subject, e.g. \"nova.v2.cells.{cell}\". */\nexport interface NatsOperationParams {\n /**\n * Cell Configuration\n *\n * Publishes the configuration for a cell.\n *\n * The latest status message is persisted NATS JetStream, documented in `x-nats-jetstream-stream`\n *\n * @operationId publishCell\n */\n \"nova.v2.cells.{cell}\": {\n /**\n * Unique identifier addressing a cell in all API calls.\n */\n cell: string\n }\n /**\n * App Configuration\n *\n * Publishes the configuration for a GUI application in the cell.\n *\n * The latest status message is persisted NATS JetStream, documented in `x-nats-jetstream-stream`\n *\n * @operationId publishApp\n */\n \"nova.v2.cells.{cell}.apps.{app}\": {\n /**\n * Unique identifier addressing a cell in all API calls.\n */\n cell: string\n /**\n * Name of the provided application.\n * Must be unique within the cell and is used as an identifier for addressing the application in all API calls, e.g., when updating the application.\n */\n app: string\n }\n /**\n * Program Status\n *\n * Publishes status messages for programs running in an app within a cell.\n * The status messages provide information about the current state of a program run.\n *\n * @operationId publishProgramStatus\n */\n \"nova.v2.cells.{cell}.programs\": {\n /**\n * Unique identifier addressing a cell in all API calls.\n */\n cell: string\n }\n /**\n * Robot Controller Configuration\n *\n * Publishes the configuration of a robot controller.\n *\n * @operationId publishRobotController\n */\n \"nova.v2.cells.{cell}.controllers.{controller}\": {\n /**\n * Unique identifier addressing a cell in all API calls.\n */\n cell: string\n /**\n * Unique identifier to address a controller in the cell.\n */\n controller: string\n }\n /**\n * Service Status\n *\n * Publishes the status of all cell resources.\n *\n * The latest status message is persisted NATS JetStream, documented in `x-nats-jetstream-stream`\n *\n * @operationId publishCellStatus\n */\n \"nova.v2.cells.{cell}.status\": {\n /**\n * Unique identifier addressing a cell in all API calls.\n */\n cell: string\n }\n /**\n * Cell Cycle Event\n *\n * Publishes the cycle events for a cell.\n *\n * @operationId publishCellCycle\n */\n \"nova.v2.cells.{cell}.cycle\": {\n /**\n * Unique identifier addressing a cell in all API calls.\n */\n cell: string\n }\n /**\n * Wandelbots NOVA status\n *\n * Publishes the status of all system services.\n *\n * The latest status message is persisted NATS JetStream, documented in `x-nats-jetstream-stream`\n *\n * @operationId publishSystemStatus\n */\n \"nova.v2.system.status\": Record<never, never>\n /**\n * Collision Setup\n *\n * Publishes the stored collision setup.\n *\n * The latest status message is persisted NATS JetStream, documented in `x-nats-jetstream-stream`\n *\n * @operationId publishCollisionSetup\n */\n \"nova.v2.cells.{cell}.collision.setups.{setup}\": {\n /**\n * Unique identifier addressing a cell in all API calls.\n */\n cell: string\n /**\n * Unique identifier addressing a collision setup.\n */\n setup: string\n }\n /**\n * BUS Inputs/Outputs Service Status\n *\n * Publishes the status of BUS inputs/outputs service.\n *\n * The latest status message is persisted NATS JetStream, documented in `x-nats-jetstream-stream`.\n *\n * @operationId publishBUSIOStatus\n */\n \"nova.v2.cells.{cell}.bus-ios.status\": {\n /**\n * Unique identifier addressing a cell in all API calls.\n */\n cell: string\n }\n /**\n * BUS Input/Output Values\n *\n * Publishes updates of BUS input/output values.\n *\n * @operationId publishBUSIOsIOs\n */\n \"nova.v2.cells.{cell}.bus-ios.ios\": {\n /**\n * Unique identifier addressing a cell in all API calls.\n */\n cell: string\n }\n /**\n * Set Output Values\n *\n * Set output values published with the BUS inputs/outputs service.\n * If you're using a virtual service, you can set inputs as well.\n *\n * @operationId setBUSIOsIOs\n */\n \"nova.v2.cells.{cell}.bus-ios.ios.set\": {\n /**\n * Unique identifier addressing a cell in all API calls.\n */\n cell: string\n }\n /**\n * Select Input/Output Values\n *\n * Select input/output values published by the controller.\n *\n * @operationId selectRobotControllerIOs\n */\n \"nova.v2.cells.{cell}.controllers.{controller}.ios.select\": {\n /**\n * Unique identifier addressing a cell in all API calls.\n */\n cell: string\n /**\n * Unique identifier to address a controller in a cell.\n */\n controller: string\n }\n /**\n * Input/Output Values\n *\n * Publishes updates of input/output values.\n *\n * @operationId publishRobotControllerIOs\n */\n \"nova.v2.cells.{cell}.controllers.{controller}.ios\": {\n /**\n * Unique identifier addressing a cell in all API calls.\n */\n cell: string\n /**\n * Unique identifier to address a controller in the cell.\n */\n controller: string\n }\n /**\n * State of Robot Controller\n *\n * Publishes the current state of a robot controller.\n *\n * @operationId publishRobotControllersState\n */\n \"nova.v2.cells.{cell}.controllers.{controller}.state\": {\n /**\n * Unique identifier addressing a cell in all API calls.\n */\n cell: string\n /**\n * Unique identifier to address a controller in the cell.\n */\n controller: string\n }\n /**\n * Description of Motion Group\n *\n * Publishes the description of a motion group, including TCPs, mounting, safety zones, limits, etc.\n *\n * @operationId publishMotionGroupDescription\n */\n \"nova.v2.cells.{cell}.controllers.{controller}.motion-groups.{motion-group}.description\": {\n /**\n * Unique identifier addressing a cell in all API calls.\n */\n cell: string\n /**\n * Unique identifier addressing a controller in the cell.\n */\n controller: string\n /**\n * Motion group identifier.\n */\n \"motion-group\": string\n }\n /**\n * System Update Started\n *\n * Publishes an event when a system update process is initiated.\n *\n * This event is triggered once the service-manager begins a system update process,\n * providing details about the update metadata, trigger information, and pre-update checks.\n *\n * The event follows CloudEvents v1.0 specification and is persisted in NATS JetStream\n * for reliable delivery and event replay capabilities.\n *\n * @operationId eventSystemUpdateStarted\n */\n \"nova.v2.events.system.update.started\": Record<never, never>\n /**\n * System Update Completed\n *\n * Publishes an event when a system update process is completed.\n *\n * This event is triggered once the service-manager completes a system update process,\n * providing comprehensive results including success status, component outcomes,\n * error details, and post-update validation results.\n *\n * The event follows CloudEvents v1.0 specification and is persisted in NATS JetStream\n * for reliable delivery and event replay capabilities.\n *\n * @operationId eventSystemUpdateCompleted\n */\n \"nova.v2.events.system.update.completed\": Record<never, never>\n /**\n * System Network Status Changed\n *\n * Publishes an event when a system network status changes.\n *\n * This event is triggered once system-info service detects a change in the system network status,\n * providing details about the new network state and related information.\n *\n * The event follows CloudEvents v1.0 specification and is persisted in NATS JetStream\n * for reliable delivery and event replay capabilities.\n *\n * @operationId eventSystemNetworkStatusChanged\n */\n \"nova.v2.events.system.network.status.changed\": Record<never, never>\n /**\n * Cell Created\n *\n * Publishes an event when a cell foundation release is created.\n *\n * The event follows CloudEvents v1.0 and is persisted in NATS JetStream for reliable delivery and replay capabilities.\n *\n * @operationId eventCellCreated\n */\n \"nova.v2.events.cells.{cell}.created\": {\n /**\n * Unique identifier addressing a cell in all API calls.\n */\n cell: string\n }\n /**\n * Cell Updated\n *\n * Publishes an event when a cell foundation release is updated.\n *\n * The event follows CloudEvents v1.0 and is persisted in NATS JetStream for reliable delivery and replay capabilities.\n *\n * @operationId eventCellUpdated\n */\n \"nova.v2.events.cells.{cell}.updated\": {\n /**\n * Unique identifier addressing a cell in all API calls.\n */\n cell: string\n }\n /**\n * Cell Deleted\n *\n * Publishes an event when a cell foundation release is deleted.\n *\n * The event follows CloudEvents v1.0 and is persisted in NATS JetStream for reliable delivery and replay capabilities.\n *\n * @operationId eventCellDeleted\n */\n \"nova.v2.events.cells.{cell}.deleted\": {\n /**\n * Unique identifier addressing a cell in all API calls.\n */\n cell: string\n }\n /**\n * App Created\n *\n * Publishes an event when an app release is created in a cell.\n *\n * The event follows CloudEvents v1.0 and is persisted in NATS JetStream for reliable delivery and replay capabilities.\n *\n * @operationId eventAppCreated\n */\n \"nova.v2.events.cells.{cell}.apps.{app}.created\": {\n /**\n * Unique identifier addressing a cell in all API calls.\n */\n cell: string\n /**\n * Unique identifier addressing an app in the cell.\n */\n app: string\n }\n /**\n * App Updated\n *\n * Publishes an event when an app release is updated in a cell.\n *\n * The event follows CloudEvents v1.0 and is persisted in NATS JetStream for reliable delivery and replay capabilities.\n *\n * @operationId eventAppUpdated\n */\n \"nova.v2.events.cells.{cell}.apps.{app}.updated\": {\n /**\n * Unique identifier addressing a cell in all API calls.\n */\n cell: string\n /**\n * Unique identifier addressing an app in the cell.\n */\n app: string\n }\n /**\n * App Deleted\n *\n * Publishes an event when an app release is deleted from a cell.\n *\n * The event follows CloudEvents v1.0 and is persisted in NATS JetStream for reliable delivery and replay capabilities.\n *\n * @operationId eventAppDeleted\n */\n \"nova.v2.events.cells.{cell}.apps.{app}.deleted\": {\n /**\n * Unique identifier addressing a cell in all API calls.\n */\n cell: string\n /**\n * Unique identifier addressing an app in the cell.\n */\n app: string\n }\n /**\n * Robot Controller Created\n *\n * Publishes an event when a robot controller release is created in a cell.\n *\n * The event follows CloudEvents v1.0 and is persisted in NATS JetStream for reliable delivery and replay capabilities.\n *\n * @operationId eventRobotControllerCreated\n */\n \"nova.v2.events.cells.{cell}.controllers.{controller}.created\": {\n /**\n * Unique identifier addressing a cell in all API calls.\n */\n cell: string\n /**\n * Unique identifier to address a controller in the cell.\n */\n controller: string\n }\n /**\n * Robot Controller Updated\n *\n * Publishes an event when a robot controller release is updated in a cell.\n *\n * The event follows CloudEvents v1.0 and is persisted in NATS JetStream for reliable delivery and replay capabilities.\n *\n * @operationId eventRobotControllerUpdated\n */\n \"nova.v2.events.cells.{cell}.controllers.{controller}.updated\": {\n /**\n * Unique identifier addressing a cell in all API calls.\n */\n cell: string\n /**\n * Unique identifier to address a controller in the cell.\n */\n controller: string\n }\n /**\n * Robot Controller Deleted\n *\n * Publishes an event when a robot controller release is deleted from a cell.\n *\n * The event follows CloudEvents v1.0 and is persisted in NATS JetStream for reliable delivery and replay capabilities.\n *\n * @operationId eventRobotControllerDeleted\n */\n \"nova.v2.events.cells.{cell}.controllers.{controller}.deleted\": {\n /**\n * Unique identifier addressing a cell in all API calls.\n */\n cell: string\n /**\n * Unique identifier to address a controller in the cell.\n */\n controller: string\n }\n}\n\n/** Payload types for subjects the server publishes and the client subscribes to. */\nexport interface NatsSubscribePayloads {\n /**\n * Cell Configuration\n *\n * Publishes the configuration for a cell.\n *\n * The latest status message is persisted NATS JetStream, documented in `x-nats-jetstream-stream`\n *\n * @operationId publishCell\n */\n \"nova.v2.cells.{cell}\": Cell\n /**\n * App Configuration\n *\n * Publishes the configuration for a GUI application in the cell.\n *\n * The latest status message is persisted NATS JetStream, documented in `x-nats-jetstream-stream`\n *\n * @operationId publishApp\n */\n \"nova.v2.cells.{cell}.apps.{app}\": App\n /**\n * Program Status\n *\n * Publishes status messages for programs running in an app within a cell.\n * The status messages provide information about the current state of a program run.\n *\n * @operationId publishProgramStatus\n */\n \"nova.v2.cells.{cell}.programs\": ProgramStatus\n /**\n * Robot Controller Configuration\n *\n * Publishes the configuration of a robot controller.\n *\n * @operationId publishRobotController\n */\n \"nova.v2.cells.{cell}.controllers.{controller}\": RobotController\n /**\n * Service Status\n *\n * Publishes the status of all cell resources.\n *\n * The latest status message is persisted NATS JetStream, documented in `x-nats-jetstream-stream`\n *\n * @operationId publishCellStatus\n */\n \"nova.v2.cells.{cell}.status\": ServiceStatusList\n /**\n * Cell Cycle Event\n *\n * Publishes the cycle events for a cell.\n *\n * @operationId publishCellCycle\n */\n \"nova.v2.cells.{cell}.cycle\": CellCycleEvent\n /**\n * Wandelbots NOVA status\n *\n * Publishes the status of all system services.\n *\n * The latest status message is persisted NATS JetStream, documented in `x-nats-jetstream-stream`\n *\n * @operationId publishSystemStatus\n */\n \"nova.v2.system.status\": ServiceStatusList\n /**\n * Collision Setup\n *\n * Publishes the stored collision setup.\n *\n * The latest status message is persisted NATS JetStream, documented in `x-nats-jetstream-stream`\n *\n * @operationId publishCollisionSetup\n */\n \"nova.v2.cells.{cell}.collision.setups.{setup}\": CollisionSetup\n /**\n * BUS Inputs/Outputs Service Status\n *\n * Publishes the status of BUS inputs/outputs service.\n *\n * The latest status message is persisted NATS JetStream, documented in `x-nats-jetstream-stream`.\n *\n * @operationId publishBUSIOStatus\n */\n \"nova.v2.cells.{cell}.bus-ios.status\": BusIOsState\n /**\n * BUS Input/Output Values\n *\n * Publishes updates of BUS input/output values.\n *\n * @operationId publishBUSIOsIOs\n */\n \"nova.v2.cells.{cell}.bus-ios.ios\": ListIOValuesResponse\n /**\n * Input/Output Values\n *\n * Publishes updates of input/output values.\n *\n * @operationId publishRobotControllerIOs\n */\n \"nova.v2.cells.{cell}.controllers.{controller}.ios\": StreamIOValuesResponse\n /**\n * State of Robot Controller\n *\n * Publishes the current state of a robot controller.\n *\n * @operationId publishRobotControllersState\n */\n \"nova.v2.cells.{cell}.controllers.{controller}.state\": RobotControllerState\n /**\n * Description of Motion Group\n *\n * Publishes the description of a motion group, including TCPs, mounting, safety zones, limits, etc.\n *\n * @operationId publishMotionGroupDescription\n */\n \"nova.v2.cells.{cell}.controllers.{controller}.motion-groups.{motion-group}.description\": MotionGroupDescription\n /**\n * System Update Started\n *\n * Publishes an event when a system update process is initiated.\n *\n * This event is triggered once the service-manager begins a system update process,\n * providing details about the update metadata, trigger information, and pre-update checks.\n *\n * The event follows CloudEvents v1.0 specification and is persisted in NATS JetStream\n * for reliable delivery and event replay capabilities.\n *\n * @operationId eventSystemUpdateStarted\n */\n \"nova.v2.events.system.update.started\": SystemUpdateStartedEvent\n /**\n * System Update Completed\n *\n * Publishes an event when a system update process is completed.\n *\n * This event is triggered once the service-manager completes a system update process,\n * providing comprehensive results including success status, component outcomes,\n * error details, and post-update validation results.\n *\n * The event follows CloudEvents v1.0 specification and is persisted in NATS JetStream\n * for reliable delivery and event replay capabilities.\n *\n * @operationId eventSystemUpdateCompleted\n */\n \"nova.v2.events.system.update.completed\": SystemUpdateCompletedEvent\n /**\n * System Network Status Changed\n *\n * Publishes an event when a system network status changes.\n *\n * This event is triggered once system-info service detects a change in the system network status,\n * providing details about the new network state and related information.\n *\n * The event follows CloudEvents v1.0 specification and is persisted in NATS JetStream\n * for reliable delivery and event replay capabilities.\n *\n * @operationId eventSystemNetworkStatusChanged\n */\n \"nova.v2.events.system.network.status.changed\": NetworkStatusChangedEvent\n /**\n * Cell Created\n *\n * Publishes an event when a cell foundation release is created.\n *\n * The event follows CloudEvents v1.0 and is persisted in NATS JetStream for reliable delivery and replay capabilities.\n *\n * @operationId eventCellCreated\n */\n \"nova.v2.events.cells.{cell}.created\": CellCreatedEvent\n /**\n * Cell Updated\n *\n * Publishes an event when a cell foundation release is updated.\n *\n * The event follows CloudEvents v1.0 and is persisted in NATS JetStream for reliable delivery and replay capabilities.\n *\n * @operationId eventCellUpdated\n */\n \"nova.v2.events.cells.{cell}.updated\": CellUpdatedEvent\n /**\n * Cell Deleted\n *\n * Publishes an event when a cell foundation release is deleted.\n *\n * The event follows CloudEvents v1.0 and is persisted in NATS JetStream for reliable delivery and replay capabilities.\n *\n * @operationId eventCellDeleted\n */\n \"nova.v2.events.cells.{cell}.deleted\": CellDeletedEvent\n /**\n * App Created\n *\n * Publishes an event when an app release is created in a cell.\n *\n * The event follows CloudEvents v1.0 and is persisted in NATS JetStream for reliable delivery and replay capabilities.\n *\n * @operationId eventAppCreated\n */\n \"nova.v2.events.cells.{cell}.apps.{app}.created\": AppCreatedEvent\n /**\n * App Updated\n *\n * Publishes an event when an app release is updated in a cell.\n *\n * The event follows CloudEvents v1.0 and is persisted in NATS JetStream for reliable delivery and replay capabilities.\n *\n * @operationId eventAppUpdated\n */\n \"nova.v2.events.cells.{cell}.apps.{app}.updated\": AppUpdatedEvent\n /**\n * App Deleted\n *\n * Publishes an event when an app release is deleted from a cell.\n *\n * The event follows CloudEvents v1.0 and is persisted in NATS JetStream for reliable delivery and replay capabilities.\n *\n * @operationId eventAppDeleted\n */\n \"nova.v2.events.cells.{cell}.apps.{app}.deleted\": AppDeletedEvent\n /**\n * Robot Controller Created\n *\n * Publishes an event when a robot controller release is created in a cell.\n *\n * The event follows CloudEvents v1.0 and is persisted in NATS JetStream for reliable delivery and replay capabilities.\n *\n * @operationId eventRobotControllerCreated\n */\n \"nova.v2.events.cells.{cell}.controllers.{controller}.created\": RobotControllerCreatedEvent\n /**\n * Robot Controller Updated\n *\n * Publishes an event when a robot controller release is updated in a cell.\n *\n * The event follows CloudEvents v1.0 and is persisted in NATS JetStream for reliable delivery and replay capabilities.\n *\n * @operationId eventRobotControllerUpdated\n */\n \"nova.v2.events.cells.{cell}.controllers.{controller}.updated\": RobotControllerUpdatedEvent\n /**\n * Robot Controller Deleted\n *\n * Publishes an event when a robot controller release is deleted from a cell.\n *\n * The event follows CloudEvents v1.0 and is persisted in NATS JetStream for reliable delivery and replay capabilities.\n *\n * @operationId eventRobotControllerDeleted\n */\n \"nova.v2.events.cells.{cell}.controllers.{controller}.deleted\": RobotControllerDeletedEvent\n}\n\nexport type NatsSubscribeSubject = keyof NatsSubscribePayloads\n\n/**\n * The JetStream stream backing each subject that retains only its latest\n * message (`max_msgs_per_subject: 1` in src/asyncapi.yaml), so that\n * message is the subject's current state.\n */\nexport const natsStreamBySubject = {\n \"nova.v2.cells.{cell}\": \"system-state\",\n \"nova.v2.cells.{cell}.apps.{app}\": \"system-state\",\n \"nova.v2.cells.{cell}.controllers.{controller}\": \"system-state\",\n \"nova.v2.cells.{cell}.status\": \"system-state\",\n \"nova.v2.system.status\": \"system-state\",\n \"nova.v2.cells.{cell}.collision.setups.{setup}\": \"system-state\",\n \"nova.v2.cells.{cell}.bus-ios.status\": \"system-state\",\n \"nova.v2.cells.{cell}.controllers.{controller}.motion-groups.{motion-group}.description\":\n \"system-state\",\n} as const\n\n/** Subjects whose current value can be replayed via `{ replayLast: true }`. */\nexport type NatsPersistedSubject = keyof typeof natsStreamBySubject\n\n/** Request payload types for subjects the client sends requests to. */\nexport interface NatsRequestPayloads {\n /**\n * Set Output Values\n *\n * Set output values published with the BUS inputs/outputs service.\n * If you're using a virtual service, you can set inputs as well.\n *\n * @operationId setBUSIOsIOs\n */\n \"nova.v2.cells.{cell}.bus-ios.ios.set\": ListIOValuesResponse\n /**\n * Select Input/Output Values\n *\n * Select input/output values published by the controller.\n *\n * @operationId selectRobotControllerIOs\n */\n \"nova.v2.cells.{cell}.controllers.{controller}.ios.select\": SelectIOs\n}\n\n/** Reply payload types for request/reply subjects. */\nexport interface NatsReplyPayloads {\n /**\n * Set Output Values\n *\n * Set output values published with the BUS inputs/outputs service.\n * If you're using a virtual service, you can set inputs as well.\n *\n * @operationId setBUSIOsIOs\n */\n \"nova.v2.cells.{cell}.bus-ios.ios.set\": NatsErrorPayload\n /**\n * Select Input/Output Values\n *\n * Select input/output values published by the controller.\n *\n * @operationId selectRobotControllerIOs\n */\n \"nova.v2.cells.{cell}.controllers.{controller}.ios.select\": NatsErrorPayload\n}\n\nexport type NatsRequestSubject = keyof NatsRequestPayloads\n\n/** Payload types for every subject defined in the spec, publishable via NovaNatsClient#publish. */\nexport interface NatsPublishPayloads {\n /**\n * Cell Configuration\n *\n * Publishes the configuration for a cell.\n *\n * The latest status message is persisted NATS JetStream, documented in `x-nats-jetstream-stream`\n *\n * @operationId publishCell\n */\n \"nova.v2.cells.{cell}\": Cell\n /**\n * App Configuration\n *\n * Publishes the configuration for a GUI application in the cell.\n *\n * The latest status message is persisted NATS JetStream, documented in `x-nats-jetstream-stream`\n *\n * @operationId publishApp\n */\n \"nova.v2.cells.{cell}.apps.{app}\": App\n /**\n * Program Status\n *\n * Publishes status messages for programs running in an app within a cell.\n * The status messages provide information about the current state of a program run.\n *\n * @operationId publishProgramStatus\n */\n \"nova.v2.cells.{cell}.programs\": ProgramStatus\n /**\n * Robot Controller Configuration\n *\n * Publishes the configuration of a robot controller.\n *\n * @operationId publishRobotController\n */\n \"nova.v2.cells.{cell}.controllers.{controller}\": RobotController\n /**\n * Service Status\n *\n * Publishes the status of all cell resources.\n *\n * The latest status message is persisted NATS JetStream, documented in `x-nats-jetstream-stream`\n *\n * @operationId publishCellStatus\n */\n \"nova.v2.cells.{cell}.status\": ServiceStatusList\n /**\n * Cell Cycle Event\n *\n * Publishes the cycle events for a cell.\n *\n * @operationId publishCellCycle\n */\n \"nova.v2.cells.{cell}.cycle\": CellCycleEvent\n /**\n * Wandelbots NOVA status\n *\n * Publishes the status of all system services.\n *\n * The latest status message is persisted NATS JetStream, documented in `x-nats-jetstream-stream`\n *\n * @operationId publishSystemStatus\n */\n \"nova.v2.system.status\": ServiceStatusList\n /**\n * Collision Setup\n *\n * Publishes the stored collision setup.\n *\n * The latest status message is persisted NATS JetStream, documented in `x-nats-jetstream-stream`\n *\n * @operationId publishCollisionSetup\n */\n \"nova.v2.cells.{cell}.collision.setups.{setup}\": CollisionSetup\n /**\n * BUS Inputs/Outputs Service Status\n *\n * Publishes the status of BUS inputs/outputs service.\n *\n * The latest status message is persisted NATS JetStream, documented in `x-nats-jetstream-stream`.\n *\n * @operationId publishBUSIOStatus\n */\n \"nova.v2.cells.{cell}.bus-ios.status\": BusIOsState\n /**\n * BUS Input/Output Values\n *\n * Publishes updates of BUS input/output values.\n *\n * @operationId publishBUSIOsIOs\n */\n \"nova.v2.cells.{cell}.bus-ios.ios\": ListIOValuesResponse\n /**\n * Set Output Values\n *\n * Set output values published with the BUS inputs/outputs service.\n * If you're using a virtual service, you can set inputs as well.\n *\n * @operationId setBUSIOsIOs\n */\n \"nova.v2.cells.{cell}.bus-ios.ios.set\": ListIOValuesResponse\n /**\n * Select Input/Output Values\n *\n * Select input/output values published by the controller.\n *\n * @operationId selectRobotControllerIOs\n */\n \"nova.v2.cells.{cell}.controllers.{controller}.ios.select\": SelectIOs\n /**\n * Input/Output Values\n *\n * Publishes updates of input/output values.\n *\n * @operationId publishRobotControllerIOs\n */\n \"nova.v2.cells.{cell}.controllers.{controller}.ios\": StreamIOValuesResponse\n /**\n * State of Robot Controller\n *\n * Publishes the current state of a robot controller.\n *\n * @operationId publishRobotControllersState\n */\n \"nova.v2.cells.{cell}.controllers.{controller}.state\": RobotControllerState\n /**\n * Description of Motion Group\n *\n * Publishes the description of a motion group, including TCPs, mounting, safety zones, limits, etc.\n *\n * @operationId publishMotionGroupDescription\n */\n \"nova.v2.cells.{cell}.controllers.{controller}.motion-groups.{motion-group}.description\": MotionGroupDescription\n /**\n * System Update Started\n *\n * Publishes an event when a system update process is initiated.\n *\n * This event is triggered once the service-manager begins a system update process,\n * providing details about the update metadata, trigger information, and pre-update checks.\n *\n * The event follows CloudEvents v1.0 specification and is persisted in NATS JetStream\n * for reliable delivery and event replay capabilities.\n *\n * @operationId eventSystemUpdateStarted\n */\n \"nova.v2.events.system.update.started\": SystemUpdateStartedEvent\n /**\n * System Update Completed\n *\n * Publishes an event when a system update process is completed.\n *\n * This event is triggered once the service-manager completes a system update process,\n * providing comprehensive results including success status, component outcomes,\n * error details, and post-update validation results.\n *\n * The event follows CloudEvents v1.0 specification and is persisted in NATS JetStream\n * for reliable delivery and event replay capabilities.\n *\n * @operationId eventSystemUpdateCompleted\n */\n \"nova.v2.events.system.update.completed\": SystemUpdateCompletedEvent\n /**\n * System Network Status Changed\n *\n * Publishes an event when a system network status changes.\n *\n * This event is triggered once system-info service detects a change in the system network status,\n * providing details about the new network state and related information.\n *\n * The event follows CloudEvents v1.0 specification and is persisted in NATS JetStream\n * for reliable delivery and event replay capabilities.\n *\n * @operationId eventSystemNetworkStatusChanged\n */\n \"nova.v2.events.system.network.status.changed\": NetworkStatusChangedEvent\n /**\n * Cell Created\n *\n * Publishes an event when a cell foundation release is created.\n *\n * The event follows CloudEvents v1.0 and is persisted in NATS JetStream for reliable delivery and replay capabilities.\n *\n * @operationId eventCellCreated\n */\n \"nova.v2.events.cells.{cell}.created\": CellCreatedEvent\n /**\n * Cell Updated\n *\n * Publishes an event when a cell foundation release is updated.\n *\n * The event follows CloudEvents v1.0 and is persisted in NATS JetStream for reliable delivery and replay capabilities.\n *\n * @operationId eventCellUpdated\n */\n \"nova.v2.events.cells.{cell}.updated\": CellUpdatedEvent\n /**\n * Cell Deleted\n *\n * Publishes an event when a cell foundation release is deleted.\n *\n * The event follows CloudEvents v1.0 and is persisted in NATS JetStream for reliable delivery and replay capabilities.\n *\n * @operationId eventCellDeleted\n */\n \"nova.v2.events.cells.{cell}.deleted\": CellDeletedEvent\n /**\n * App Created\n *\n * Publishes an event when an app release is created in a cell.\n *\n * The event follows CloudEvents v1.0 and is persisted in NATS JetStream for reliable delivery and replay capabilities.\n *\n * @operationId eventAppCreated\n */\n \"nova.v2.events.cells.{cell}.apps.{app}.created\": AppCreatedEvent\n /**\n * App Updated\n *\n * Publishes an event when an app release is updated in a cell.\n *\n * The event follows CloudEvents v1.0 and is persisted in NATS JetStream for reliable delivery and replay capabilities.\n *\n * @operationId eventAppUpdated\n */\n \"nova.v2.events.cells.{cell}.apps.{app}.updated\": AppUpdatedEvent\n /**\n * App Deleted\n *\n * Publishes an event when an app release is deleted from a cell.\n *\n * The event follows CloudEvents v1.0 and is persisted in NATS JetStream for reliable delivery and replay capabilities.\n *\n * @operationId eventAppDeleted\n */\n \"nova.v2.events.cells.{cell}.apps.{app}.deleted\": AppDeletedEvent\n /**\n * Robot Controller Created\n *\n * Publishes an event when a robot controller release is created in a cell.\n *\n * The event follows CloudEvents v1.0 and is persisted in NATS JetStream for reliable delivery and replay capabilities.\n *\n * @operationId eventRobotControllerCreated\n */\n \"nova.v2.events.cells.{cell}.controllers.{controller}.created\": RobotControllerCreatedEvent\n /**\n * Robot Controller Updated\n *\n * Publishes an event when a robot controller release is updated in a cell.\n *\n * The event follows CloudEvents v1.0 and is persisted in NATS JetStream for reliable delivery and replay capabilities.\n *\n * @operationId eventRobotControllerUpdated\n */\n \"nova.v2.events.cells.{cell}.controllers.{controller}.updated\": RobotControllerUpdatedEvent\n /**\n * Robot Controller Deleted\n *\n * Publishes an event when a robot controller release is deleted from a cell.\n *\n * The event follows CloudEvents v1.0 and is persisted in NATS JetStream for reliable delivery and replay capabilities.\n *\n * @operationId eventRobotControllerDeleted\n */\n \"nova.v2.events.cells.{cell}.controllers.{controller}.deleted\": RobotControllerDeletedEvent\n}\n\nexport type NatsPublishSubject = keyof NatsPublishPayloads\n","/**\n * Builds a NATS subject from an AsyncAPI-style channel address template\n * (e.g. `\"{instance}.v2.cells.{cell}\"`) by substituting each `{param}`\n * placeholder with the corresponding value from `params`.\n */\n\nfunction isValidSubjectChar(char: string): boolean {\n const code = char.charCodeAt(0)\n return (\n (code >= 48 && code <= 57) || // 0-9\n (code >= 65 && code <= 90) || // A-Z\n (code >= 97 && code <= 122) || // a-z\n char === \"-\" ||\n char === \"_\"\n )\n}\n\nfunction isValidSubjectValue(value: string): boolean {\n // A bare \"*\" is the NATS single-token wildcard, allowed on its own (e.g.\n // subscribing to all cells with `{ cell: \"*\" }\") but not as part of a\n // larger value, since it wouldn't act as a wildcard there anyway.\n if (value === \"*\") return true\n if (value.length === 0) return false\n for (const char of value) {\n if (!isValidSubjectChar(char)) return false\n }\n return true\n}\n\nexport function buildSubject(\n template: string,\n params: Record<string, string>,\n): string {\n // Scanned manually (rather than with a regex like /\\{([^}]+)\\}/g) to avoid\n // a polynomial-time backtracking blowup on pathological input, e.g. a\n // template consisting of many \"{\" characters with no closing \"}\".\n let result = \"\"\n let cursor = 0\n\n while (cursor < template.length) {\n const openIndex = template.indexOf(\"{\", cursor)\n if (openIndex === -1) {\n result += template.slice(cursor)\n break\n }\n\n const closeIndex = template.indexOf(\"}\", openIndex + 1)\n if (closeIndex === -1) {\n result += template.slice(cursor)\n break\n }\n\n result += template.slice(cursor, openIndex)\n const paramName = template.slice(openIndex + 1, closeIndex)\n const value = params[paramName]\n if (value === undefined) {\n throw new Error(\n `Missing value for subject parameter \"${paramName}\" in template \"${template}\"`,\n )\n }\n if (!isValidSubjectValue(value)) {\n throw new Error(\n `Invalid value for subject parameter \"${paramName}\": \"${value}\" (must be non-empty and contain only letters, digits, \"-\", and \"_\")`,\n )\n }\n result += value\n\n cursor = closeIndex + 1\n }\n\n return result\n}\n","import { DeliverPolicy, jetstream, type JsMsg } from \"@nats-io/jetstream\"\nimport {\n type ConnectionOptions,\n type Msg,\n type NatsConnection,\n wsconnect,\n} from \"@nats-io/nats-core\"\nimport type { Nova } from \"../../Nova.ts\"\nimport { buildNatsServerUrl } from \"./buildNatsServerUrl.ts\"\nimport { buildSubject } from \"./buildSubject.ts\"\nimport {\n type NatsOperationParams,\n type NatsPersistedSubject,\n type NatsPublishPayloads,\n type NatsPublishSubject,\n type NatsReplyPayloads,\n type NatsRequestPayloads,\n type NatsRequestSubject,\n natsStreamBySubject,\n type NatsSubscribePayloads,\n type NatsSubscribeSubject,\n} from \"./generated/operations.ts\"\n\nexport type NovaNatsClientConfig = ConnectionOptions\n\n/**\n * A received message, annotated with the values of the subject template's\n * `{param}` placeholders as extracted from the message's concrete subject.\n * With a wildcard subscription (e.g. `{ cell: \"*\" }`), `subjectParams` is how\n * a handler knows which entity a message belongs to. Typed per subject via\n * the generated `NatsOperationParams`.\n */\nexport type NatsSubscribeMsg<K extends NatsSubscribeSubject> = (Msg | JsMsg) & {\n subjectParams: NatsOperationParams[K]\n}\n\ntype NatsMessageHandler<K extends NatsSubscribeSubject> = (\n payload: NatsSubscribePayloads[K],\n msg: NatsSubscribeMsg<K>,\n) => void | Promise<void>\n\n/**\n * Extra options for {@link NovaNatsClient.subscribe}. `replayLast` is only\n * offered on subjects the spec marks as retaining their latest message, so\n * asking for a replay that could never arrive is a compile error.\n */\nexport type NatsSubscribeOptions<K extends NatsSubscribeSubject> =\n K extends NatsPersistedSubject\n ? {\n /**\n * Deliver the subject's current value immediately on subscribe,\n * before any subsequent updates. With a wildcard subscription (e.g.\n * `{ cell: \"*\" }`) the current value of every matching subject is\n * delivered, not just one.\n */\n replayLast?: boolean\n }\n : // Not `Record<never, never>`: that behaves like `{}` and so accepts any\n // object, letting `replayLast` through unchecked. Typing the property as\n // `never` is what makes passing it an error.\n { replayLast?: never }\n\ntype SubscribeArgs<K extends NatsSubscribeSubject> =\n keyof NatsOperationParams[K] extends never\n ? [handler: NatsMessageHandler<K>, opts?: NatsSubscribeOptions<K>]\n : [\n params: NatsOperationParams[K],\n handler: NatsMessageHandler<K>,\n opts?: NatsSubscribeOptions<K>,\n ]\n\n/**\n * Typed NATS client for the Wandelbots NOVA messaging API, generated from\n * src/asyncapi.yaml (see scripts/generate-nats-client.ts).\n *\n * Connects over WebSocket via `@nats-io/nats-core`'s `wsconnect`.\n */\nexport class NovaNatsClient {\n readonly config: NovaNatsClientConfig\n private connectionPromise: Promise<NatsConnection> | null = null\n\n constructor(nova: Nova, config: NovaNatsClientConfig = {}) {\n this.config = {\n servers: buildNatsServerUrl(nova.instanceUrl.href),\n // Reuse the Nova instance's access token for NATS auth, if it has one\n // (e.g. from login or a passed-in config.accessToken). Explicit auth\n // options in `config` (token/user/pass/authenticator) still win.\n ...(nova.accessToken ? { token: nova.accessToken } : {}),\n ...config,\n }\n }\n\n /**\n * Connects to NATS if not already connected or connecting, and returns the\n * connection. Safe to call concurrently: all callers share the same\n * in-flight connection attempt instead of each starting their own.\n */\n connect(): Promise<NatsConnection> {\n if (!this.connectionPromise) {\n this.connectionPromise = wsconnect(this.config).catch((err: unknown) => {\n // Allow a subsequent connect() call to retry after a failed attempt.\n this.connectionPromise = null\n throw err\n })\n }\n return this.connectionPromise\n }\n\n /** Closes the underlying NATS connection, if open or connecting. */\n async close(): Promise<void> {\n const connectionPromise = this.connectionPromise\n this.connectionPromise = null\n if (!connectionPromise) return\n try {\n const nc = await connectionPromise\n await nc.close()\n } catch {\n // Connection never succeeded; nothing to close.\n }\n }\n\n /**\n * Subscribes to a NATS subject published by the server, invoking `handler`\n * with the JSON-decoded payload of every message received.\n *\n * `subject` is the subject template as it appears on the wire, e.g.\n * `\"nova.v2.cells.{cell}\"`, with `{param}` placeholders filled in from\n * `params`.\n *\n * Errors decoding a message or thrown/rejected by `handler` are caught and\n * logged per-message, so one bad message doesn't stop later messages on\n * the same subscription from being handled.\n *\n * Each message is annotated with `msg.subjectParams` — the template's\n * `{param}` values extracted from the message's concrete subject — so a\n * wildcard subscriber knows which entity a message belongs to:\n *\n * nats.subscribe(\"nova.v2.cells.{cell}.status\", { cell: \"*\" },\n * (services, msg) => console.log(msg.subjectParams.cell, services))\n *\n * On subjects that retain their latest message, pass `{ replayLast: true }`\n * to receive the current value immediately instead of waiting for the next\n * update — useful for a subscriber that starts after the last change:\n *\n * nats.subscribe(\"nova.v2.system.status\", onStatus, { replayLast: true })\n *\n * Returns a function that unsubscribes when called.\n */\n async subscribe<K extends NatsSubscribeSubject>(\n subject: K,\n ...args: SubscribeArgs<K>\n ): Promise<() => void> {\n // `params` is omitted for subjects with no {param} placeholders, so the\n // handler is the first argument in that case.\n const hasParams = typeof args[0] !== \"function\"\n const params = (hasParams ? args[0] : {}) as NatsOperationParams[K]\n const handler = (hasParams ? args[1] : args[0]) as NatsMessageHandler<K>\n const opts = (hasParams ? args[2] : args[1]) as\n | { replayLast?: boolean }\n | undefined\n\n const nc = await this.connect()\n const resolvedSubject = buildSubject(subject, params)\n\n // The token positions of the template's {param} placeholders, computed\n // once here so each message's subjectParams is a plain index pick: a\n // delivered message always matches the subscribed pattern token for\n // token, so its params sit at the same positions as in the template.\n const paramPositions: [name: string, index: number][] = []\n for (const [index, token] of subject.split(\".\").entries()) {\n if (token.startsWith(\"{\") && token.endsWith(\"}\")) {\n paramPositions.push([token.slice(1, -1), index])\n }\n }\n\n const deliver = async (msg: Msg | JsMsg) => {\n // Handled per-message: a bad payload or a throwing/rejecting handler\n // should not stop the subscription from processing later messages.\n try {\n const subjectTokens = msg.subject.split(\".\")\n const subjectParams = Object.fromEntries(\n paramPositions.map(([name, index]) => [\n name,\n subjectTokens[index] ?? \"\",\n ]),\n ) as NatsOperationParams[K]\n await handler(\n msg.json<NatsSubscribePayloads[K]>(),\n Object.assign(msg, { subjectParams }),\n )\n } catch (err) {\n console.error(\n `Error handling NATS message on subject \"${resolvedSubject}\"`,\n err,\n )\n }\n }\n\n const deliverAll = (messages: AsyncIterable<Msg | JsMsg>) => {\n ;(async () => {\n for await (const msg of messages) {\n await deliver(msg)\n }\n })().catch((err: unknown) => {\n console.error(\n `NATS subscription iterator failed for \"${resolvedSubject}\"`,\n err,\n )\n })\n }\n\n if (opts?.replayLast) {\n // Delivered by JetStream rather than core NATS: an ordered consumer\n // starting at `last_per_subject` yields each matching subject's retained\n // message and then continues with live ones on the same iterator, so\n // there is no gap — and no possible duplicate — between the replayed\n // value and the updates that follow it. Ordered consumers are ephemeral\n // and need no acking, so stopping the iterator is the whole teardown.\n const consumer = await jetstream(nc).consumers.get(\n natsStreamBySubject[subject as NatsPersistedSubject],\n {\n filter_subjects: [resolvedSubject],\n deliver_policy: DeliverPolicy.LastPerSubject,\n },\n )\n const messages = await consumer.consume()\n deliverAll(messages)\n return () => {\n messages.stop()\n }\n }\n\n const sub = nc.subscribe(resolvedSubject)\n deliverAll(sub)\n return () => sub.unsubscribe()\n }\n\n /**\n * Sends a request payload for a NATS subject the server receives, and\n * waits for the JSON-decoded reply.\n *\n * `subject` is the subject template as it appears on the wire, e.g.\n * `\"nova.v2.cells.{cell}.bus-ios.ios.set\"`, with `{param}` placeholders\n * filled in from `params`.\n */\n async request<K extends NatsRequestSubject>(\n subject: K,\n params: NatsOperationParams[K],\n payload: NatsRequestPayloads[K],\n opts: { timeout?: number } = {},\n ): Promise<NatsReplyPayloads[K]> {\n const nc = await this.connect()\n const resolvedSubject = buildSubject(subject, params)\n const msg = await nc.request(resolvedSubject, JSON.stringify(payload), {\n timeout: opts.timeout ?? 5000,\n })\n return msg.json<NatsReplyPayloads[K]>()\n }\n\n /**\n * Publishes a JSON payload to any NATS subject defined in the spec,\n * without waiting for a reply.\n *\n * `subject` is the subject template as it appears on the wire, e.g.\n * `\"nova.v2.cells.{cell}.bus-ios.ios.set\"`, with `{param}` placeholders\n * filled in from `params`.\n */\n async publish<K extends NatsPublishSubject>(\n subject: K,\n params: NatsOperationParams[K],\n payload: NatsPublishPayloads[K],\n ): Promise<void> {\n const nc = await this.connect()\n const resolvedSubject = buildSubject(subject, params)\n nc.publish(resolvedSubject, JSON.stringify(payload))\n }\n}\n"],"mappings":";;;;;;;;;;;;AAUA,SAAgB,mBAAmB,aAA6B;CAC9D,MAAM,MAAM,qBAAqB,WAAW;CAE5C,OAAO,GADU,IAAI,aAAa,WAAW,SAAS,MACnC,IAAI,IAAI,KAAK;AAClC;;;;;;;;ACqtBA,MAAa,sBAAsB;CACjC,wBAAwB;CACxB,mCAAmC;CACnC,iDAAiD;CACjD,+BAA+B;CAC/B,yBAAyB;CACzB,iDAAiD;CACjD,uCAAuC;CACvC,0FACE;AACJ;;;;;;;;ACvuBA,SAAS,mBAAmB,MAAuB;CACjD,MAAM,OAAO,KAAK,WAAW,CAAC;CAC9B,OACG,QAAQ,MAAM,QAAQ,MACtB,QAAQ,MAAM,QAAQ,MACtB,QAAQ,MAAM,QAAQ,OACvB,SAAS,OACT,SAAS;AAEb;AAEA,SAAS,oBAAoB,OAAwB;CAInD,IAAI,UAAU,KAAK,OAAO;CAC1B,IAAI,MAAM,WAAW,GAAG,OAAO;CAC/B,KAAK,MAAM,QAAQ,OACjB,IAAI,CAAC,mBAAmB,IAAI,GAAG,OAAO;CAExC,OAAO;AACT;AAEA,SAAgB,aACd,UACA,QACQ;CAIR,IAAI,SAAS;CACb,IAAI,SAAS;CAEb,OAAO,SAAS,SAAS,QAAQ;EAC/B,MAAM,YAAY,SAAS,QAAQ,KAAK,MAAM;EAC9C,IAAI,cAAc,IAAI;GACpB,UAAU,SAAS,MAAM,MAAM;GAC/B;EACF;EAEA,MAAM,aAAa,SAAS,QAAQ,KAAK,YAAY,CAAC;EACtD,IAAI,eAAe,IAAI;GACrB,UAAU,SAAS,MAAM,MAAM;GAC/B;EACF;EAEA,UAAU,SAAS,MAAM,QAAQ,SAAS;EAC1C,MAAM,YAAY,SAAS,MAAM,YAAY,GAAG,UAAU;EAC1D,MAAM,QAAQ,OAAO;EACrB,IAAI,UAAU,KAAA,GACZ,MAAM,IAAI,MACR,wCAAwC,UAAU,iBAAiB,SAAS,EAC9E;EAEF,IAAI,CAAC,oBAAoB,KAAK,GAC5B,MAAM,IAAI,MACR,wCAAwC,UAAU,MAAM,MAAM,qEAChE;EAEF,UAAU;EAEV,SAAS,aAAa;CACxB;CAEA,OAAO;AACT;;;;;;;;;ACMA,IAAa,iBAAb,MAA4B;CAC1B;CACA,oBAA4D;CAE5D,YAAY,MAAY,SAA+B,CAAC,GAAG;EACzD,KAAK,SAAS;GACZ,SAAS,mBAAmB,KAAK,YAAY,IAAI;GAIjD,GAAI,KAAK,cAAc,EAAE,OAAO,KAAK,YAAY,IAAI,CAAC;GACtD,GAAG;EACL;CACF;;;;;;CAOA,UAAmC;EACjC,IAAI,CAAC,KAAK,mBACR,KAAK,oBAAoB,UAAU,KAAK,MAAM,CAAC,CAAC,OAAO,QAAiB;GAEtE,KAAK,oBAAoB;GACzB,MAAM;EACR,CAAC;EAEH,OAAO,KAAK;CACd;;CAGA,MAAM,QAAuB;EAC3B,MAAM,oBAAoB,KAAK;EAC/B,KAAK,oBAAoB;EACzB,IAAI,CAAC,mBAAmB;EACxB,IAAI;GAEF,OAAM,MADW,kBAAA,CACR,MAAM;EACjB,QAAQ,CAER;CACF;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6BA,MAAM,UACJ,SACA,GAAG,MACkB;EAGrB,MAAM,YAAY,OAAO,KAAK,OAAO;EACrC,MAAM,SAAU,YAAY,KAAK,KAAK,CAAC;EACvC,MAAM,UAAW,YAAY,KAAK,KAAK,KAAK;EAC5C,MAAM,OAAQ,YAAY,KAAK,KAAK,KAAK;EAIzC,MAAM,KAAK,MAAM,KAAK,QAAQ;EAC9B,MAAM,kBAAkB,aAAa,SAAS,MAAM;EAMpD,MAAM,iBAAkD,CAAC;EACzD,KAAK,MAAM,CAAC,OAAO,UAAU,QAAQ,MAAM,GAAG,CAAC,CAAC,QAAQ,GACtD,IAAI,MAAM,WAAW,GAAG,KAAK,MAAM,SAAS,GAAG,GAC7C,eAAe,KAAK,CAAC,MAAM,MAAM,GAAG,EAAE,GAAG,KAAK,CAAC;EAInD,MAAM,UAAU,OAAO,QAAqB;GAG1C,IAAI;IACF,MAAM,gBAAgB,IAAI,QAAQ,MAAM,GAAG;IAC3C,MAAM,gBAAgB,OAAO,YAC3B,eAAe,KAAK,CAAC,MAAM,WAAW,CACpC,MACA,cAAc,UAAU,EAC1B,CAAC,CACH;IACA,MAAM,QACJ,IAAI,KAA+B,GACnC,OAAO,OAAO,KAAK,EAAE,cAAc,CAAC,CACtC;GACF,SAAS,KAAK;IACZ,QAAQ,MACN,2CAA2C,gBAAgB,IAC3D,GACF;GACF;EACF;EAEA,MAAM,cAAc,aAAyC;GAC1D,CAAC,YAAY;IACZ,WAAW,MAAM,OAAO,UACtB,MAAM,QAAQ,GAAG;GAErB,EAAA,CAAG,CAAC,CAAC,OAAO,QAAiB;IAC3B,QAAQ,MACN,0CAA0C,gBAAgB,IAC1D,GACF;GACF,CAAC;EACH;EAEA,IAAI,MAAM,YAAY;GAcpB,MAAM,WAAW,OAAM,MAPA,UAAU,EAAE,CAAC,CAAC,UAAU,IAC7C,oBAAoB,UACpB;IACE,iBAAiB,CAAC,eAAe;IACjC,gBAAgB,cAAc;GAChC,CACF,EAAA,CACgC,QAAQ;GACxC,WAAW,QAAQ;GACnB,aAAa;IACX,SAAS,KAAK;GAChB;EACF;EAEA,MAAM,MAAM,GAAG,UAAU,eAAe;EACxC,WAAW,GAAG;EACd,aAAa,IAAI,YAAY;CAC/B;;;;;;;;;CAUA,MAAM,QACJ,SACA,QACA,SACA,OAA6B,CAAC,GACC;EAC/B,MAAM,KAAK,MAAM,KAAK,QAAQ;EAC9B,MAAM,kBAAkB,aAAa,SAAS,MAAM;EAIpD,QAAO,MAHW,GAAG,QAAQ,iBAAiB,KAAK,UAAU,OAAO,GAAG,EACrE,SAAS,KAAK,WAAW,IAC3B,CAAC,EAAA,CACU,KAA2B;CACxC;;;;;;;;;CAUA,MAAM,QACJ,SACA,QACA,SACe;EACf,MAAM,KAAK,MAAM,KAAK,QAAQ;EAC9B,MAAM,kBAAkB,aAAa,SAAS,MAAM;EACpD,GAAG,QAAQ,iBAAiB,KAAK,UAAU,OAAO,CAAC;CACrD;AACF"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../../../src/lib/experimental/nats/buildNatsServerUrl.ts","../../../src/lib/experimental/nats/buildSubject.ts","../../../src/lib/experimental/nats/NovaNatsClient.ts"],"sourcesContent":["import { parseNovaInstanceUrl } from \"../../converters.ts\"\n\n/**\n * Builds the WebSocket URL for a NOVA instance's NATS gateway from its\n * instance URL, e.g. `https://foo.instance.wandelbots.io` becomes\n * `wss://foo.instance.wandelbots.io/api/nats`.\n *\n * Pass the result as `servers` in the `NovaNatsClientConfig` passed to\n * `NovaNatsClient`.\n */\nexport function buildNatsServerUrl(instanceUrl: string): string {\n const url = parseNovaInstanceUrl(instanceUrl)\n const protocol = url.protocol === \"https:\" ? \"wss:\" : \"ws:\"\n return `${protocol}//${url.host}/api/nats`\n}\n","/**\n * Builds a NATS subject from an AsyncAPI-style channel address template\n * (e.g. `\"{instance}.v2.cells.{cell}\"`) by substituting each `{param}`\n * placeholder with the corresponding value from `params`.\n */\n\nfunction isValidSubjectChar(char: string): boolean {\n const code = char.charCodeAt(0)\n return (\n (code >= 48 && code <= 57) || // 0-9\n (code >= 65 && code <= 90) || // A-Z\n (code >= 97 && code <= 122) || // a-z\n char === \"-\" ||\n char === \"_\"\n )\n}\n\nfunction isValidSubjectValue(value: string): boolean {\n // A bare \"*\" is the NATS single-token wildcard, allowed on its own (e.g.\n // subscribing to all cells with `{ cell: \"*\" }\") but not as part of a\n // larger value, since it wouldn't act as a wildcard there anyway.\n if (value === \"*\") return true\n if (value.length === 0) return false\n for (const char of value) {\n if (!isValidSubjectChar(char)) return false\n }\n return true\n}\n\nexport function buildSubject(\n template: string,\n params: Record<string, string>,\n): string {\n // Scanned manually (rather than with a regex like /\\{([^}]+)\\}/g) to avoid\n // a polynomial-time backtracking blowup on pathological input, e.g. a\n // template consisting of many \"{\" characters with no closing \"}\".\n let result = \"\"\n let cursor = 0\n\n while (cursor < template.length) {\n const openIndex = template.indexOf(\"{\", cursor)\n if (openIndex === -1) {\n result += template.slice(cursor)\n break\n }\n\n const closeIndex = template.indexOf(\"}\", openIndex + 1)\n if (closeIndex === -1) {\n result += template.slice(cursor)\n break\n }\n\n result += template.slice(cursor, openIndex)\n const paramName = template.slice(openIndex + 1, closeIndex)\n const value = params[paramName]\n if (value === undefined) {\n throw new Error(\n `Missing value for subject parameter \"${paramName}\" in template \"${template}\"`,\n )\n }\n if (!isValidSubjectValue(value)) {\n throw new Error(\n `Invalid value for subject parameter \"${paramName}\": \"${value}\" (must be non-empty and contain only letters, digits, \"-\", and \"_\")`,\n )\n }\n result += value\n\n cursor = closeIndex + 1\n }\n\n return result\n}\n","import { DeliverPolicy, jetstream, jetstreamManager } from \"@nats-io/jetstream\"\nimport {\n type ConnectionOptions,\n type MsgHdrs,\n type NatsConnection,\n wsconnect,\n} from \"@nats-io/nats-core\"\nimport type { Nova } from \"../../Nova.ts\"\nimport { buildNatsServerUrl } from \"./buildNatsServerUrl.ts\"\nimport { buildSubject } from \"./buildSubject.ts\"\nimport type {\n NatsOperationParams,\n NatsPublishPayloads,\n NatsPublishSubject,\n NatsReplyPayloads,\n NatsRequestPayloads,\n NatsRequestSubject,\n NatsSubscribePayloads,\n NatsSubscribeSubject,\n} from \"./generated/operations.ts\"\n\nexport type NovaNatsClientConfig = ConnectionOptions\n\n/**\n * The fields of a received message that exist on both a core NATS `Msg` and\n * a JetStream `JsMsg` — a subscription delivers the former by default and\n * the latter with `lastMessage: true` (see {@link NatsSubscribeOptions}),\n * so handlers see only what both have in common.\n */\nexport interface NatsReceivedMsg {\n /** The concrete subject the message was published to. */\n subject: string\n /** The message's raw payload bytes. */\n data: Uint8Array\n /** Headers set by the server or the publisher, if any. */\n headers?: MsgHdrs\n /** The payload decoded as JSON. */\n json<T>(): T\n /** The payload decoded as a string. */\n string(): string\n}\n\n/**\n * A received message, annotated with the values of the subject template's\n * `{param}` placeholders as extracted from the message's concrete subject.\n * With a wildcard subscription (e.g. `{ cell: \"*\" }`), `subjectParams` is how\n * a handler knows which entity a message belongs to. Typed per subject via\n * the generated `NatsOperationParams`.\n */\nexport type NatsSubscribeMsg<K extends NatsSubscribeSubject> =\n NatsReceivedMsg & {\n subjectParams: NatsOperationParams[K]\n }\n\nexport type NatsSubscribeOptions = {\n /**\n * When true, the subscription immediately replays the last JetStream\n * message persisted for each subject matching the subscription (one per\n * concrete subject when subscribing with wildcards), then continues with\n * live messages. Requires the server to have a JetStream stream capturing\n * the subscribed subject; subscribing fails with an error if none exists.\n */\n lastMessage?: boolean\n}\n\ntype NatsMessageHandler<K extends NatsSubscribeSubject> = (\n payload: NatsSubscribePayloads[K],\n msg: NatsSubscribeMsg<K>,\n) => void | Promise<void>\n\ntype SubscribeArgs<K extends NatsSubscribeSubject> =\n keyof NatsOperationParams[K] extends never\n ? [handler: NatsMessageHandler<K>, options?: NatsSubscribeOptions]\n : [\n params: NatsOperationParams[K],\n handler: NatsMessageHandler<K>,\n options?: NatsSubscribeOptions,\n ]\n\n/**\n * Typed NATS client for the Wandelbots NOVA messaging API, generated from\n * src/asyncapi.yaml (see scripts/generate-nats-client.ts).\n *\n * Connects over WebSocket via `@nats-io/nats-core`'s `wsconnect`.\n */\nexport class NovaNatsClient {\n readonly config: NovaNatsClientConfig\n private connectionPromise: Promise<NatsConnection> | null = null\n\n constructor(nova: Nova, config: NovaNatsClientConfig = {}) {\n this.config = {\n servers: buildNatsServerUrl(nova.instanceUrl.href),\n // Reuse the Nova instance's access token for NATS auth, if it has one\n // (e.g. from login or a passed-in config.accessToken). Explicit auth\n // options in `config` (token/user/pass/authenticator) still win.\n ...(nova.accessToken ? { token: nova.accessToken } : {}),\n ...config,\n }\n }\n\n /**\n * Connects to NATS if not already connected or connecting, and returns the\n * connection. Safe to call concurrently: all callers share the same\n * in-flight connection attempt instead of each starting their own.\n */\n connect(): Promise<NatsConnection> {\n if (!this.connectionPromise) {\n this.connectionPromise = wsconnect(this.config).catch((err: unknown) => {\n // Allow a subsequent connect() call to retry after a failed attempt.\n this.connectionPromise = null\n throw err\n })\n }\n return this.connectionPromise\n }\n\n /** Closes the underlying NATS connection, if open or connecting. */\n async close(): Promise<void> {\n const connectionPromise = this.connectionPromise\n this.connectionPromise = null\n if (!connectionPromise) return\n try {\n const nc = await connectionPromise\n await nc.close()\n } catch {\n // Connection never succeeded; nothing to close.\n }\n }\n\n /**\n * Subscribes to a NATS subject published by the server, invoking `handler`\n * with the JSON-decoded payload of every message received.\n *\n * `subject` is the subject template as it appears on the wire, e.g.\n * `\"nova.v2.cells.{cell}\"`, with `{param}` placeholders filled in from\n * `params`.\n *\n * Errors decoding a message or thrown/rejected by `handler` are caught and\n * logged per-message, so one bad message doesn't stop later messages on\n * the same subscription from being handled.\n *\n * Each message is annotated with `msg.subjectParams` — the template's\n * `{param}` values extracted from the message's concrete subject — so a\n * wildcard subscriber knows which entity a message belongs to:\n *\n * nats.subscribe(\"nova.v2.cells.{cell}.status\", { cell: \"*\" },\n * (services, msg) => console.log(msg.subjectParams.cell, services))\n *\n * With `{ lastMessage: true }` as the final argument, the last JetStream\n * message persisted for each matching subject is replayed to the handler\n * immediately, before live messages (see {@link NatsSubscribeOptions}).\n *\n * Returns a function that unsubscribes when called.\n */\n async subscribe<K extends NatsSubscribeSubject>(\n subject: K,\n ...args: SubscribeArgs<K>\n ): Promise<() => void> {\n const [params, handler, options] =\n typeof args[0] === \"function\"\n ? ([{}, args[0], args[1] as NatsSubscribeOptions | undefined] as const)\n : ([args[0], args[1] as NatsMessageHandler<K>, args[2]] as const)\n\n const nc = await this.connect()\n const resolvedSubject = buildSubject(subject, params)\n\n // The token positions of the template's {param} placeholders, computed\n // once here so each message's subjectParams is a plain index pick: a\n // delivered message always matches the subscribed pattern token for\n // token, so its params sit at the same positions as in the template.\n const paramPositions: [name: string, index: number][] = []\n for (const [index, token] of subject.split(\".\").entries()) {\n if (token.startsWith(\"{\") && token.endsWith(\"}\")) {\n paramPositions.push([token.slice(1, -1), index])\n }\n }\n\n const dispatch = (messages: AsyncIterable<NatsReceivedMsg>) => {\n ;(async () => {\n for await (const msg of messages) {\n // Handled per-message: a bad payload or a throwing/rejecting\n // handler should not stop the subscription from processing later\n // messages.\n try {\n const subjectTokens = msg.subject.split(\".\")\n const subjectParams = Object.fromEntries(\n paramPositions.map(([name, index]) => [\n name,\n subjectTokens[index] ?? \"\",\n ]),\n ) as NatsOperationParams[K]\n await handler(\n msg.json<NatsSubscribePayloads[K]>(),\n Object.assign(msg, { subjectParams }),\n )\n } catch (err) {\n console.error(\n `Error handling NATS message on subject \"${resolvedSubject}\"`,\n err,\n )\n }\n }\n })().catch((err: unknown) => {\n console.error(\n `NATS subscription iterator failed for \"${resolvedSubject}\"`,\n err,\n )\n })\n }\n\n if (options?.lastMessage) {\n // Delivered through JetStream instead of a core subscription: an\n // ordered (ephemeral, auto-acked, auto-cleaned-up) consumer with\n // \"last per subject\" delivery replays the last persisted message of\n // each matching subject, then seamlessly continues with live messages.\n const jsm = await jetstreamManager(nc)\n // Throws if no stream captures the subject, rather than silently\n // never delivering anything.\n const streamName = await jsm.streams.find(resolvedSubject)\n const consumer = await jetstream(nc).consumers.get(streamName, {\n filter_subjects: [resolvedSubject],\n deliver_policy: DeliverPolicy.LastPerSubject,\n })\n const messages = await consumer.consume()\n dispatch(messages)\n return () => void messages.close()\n }\n\n const sub = nc.subscribe(resolvedSubject)\n dispatch(sub)\n return () => sub.unsubscribe()\n }\n\n /**\n * Sends a request payload for a NATS subject the server receives, and\n * waits for the JSON-decoded reply.\n *\n * `subject` is the subject template as it appears on the wire, e.g.\n * `\"nova.v2.cells.{cell}.bus-ios.ios.set\"`, with `{param}` placeholders\n * filled in from `params`.\n */\n async request<K extends NatsRequestSubject>(\n subject: K,\n params: NatsOperationParams[K],\n payload: NatsRequestPayloads[K],\n opts: { timeout?: number } = {},\n ): Promise<NatsReplyPayloads[K]> {\n const nc = await this.connect()\n const resolvedSubject = buildSubject(subject, params)\n const msg = await nc.request(resolvedSubject, JSON.stringify(payload), {\n timeout: opts.timeout ?? 5000,\n })\n return msg.json<NatsReplyPayloads[K]>()\n }\n\n /**\n * Publishes a JSON payload to any NATS subject defined in the spec,\n * without waiting for a reply.\n *\n * `subject` is the subject template as it appears on the wire, e.g.\n * `\"nova.v2.cells.{cell}.bus-ios.ios.set\"`, with `{param}` placeholders\n * filled in from `params`.\n */\n async publish<K extends NatsPublishSubject>(\n subject: K,\n params: NatsOperationParams[K],\n payload: NatsPublishPayloads[K],\n ): Promise<void> {\n const nc = await this.connect()\n const resolvedSubject = buildSubject(subject, params)\n nc.publish(resolvedSubject, JSON.stringify(payload))\n }\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@wandelbots/nova-js",
3
3
  "type": "module",
4
- "version": "4.5.0-pr.322.aa66640",
4
+ "version": "4.5.0-pr.324.1203649",
5
5
  "description": "Official JS client for the Wandelbots API",
6
6
  "sideEffects": false,
7
7
  "packageManager": "pnpm@11.9.0+sha512.bd682d5d03fe525ef7c9fd6780c6884d1e756ac4c9c9fe00c538782824310dcf90e3ddc4f53835f06dfaebd5085e41855e0bcbb3b60de2ac5bbab89e5036f03b",
@@ -5,17 +5,15 @@
5
5
  * This API is experimental and may change without a major version bump.
6
6
  */
7
7
  export { buildNatsServerUrl } from "../../lib/experimental/nats/buildNatsServerUrl.ts"
8
- export {
9
- type NatsOperationParams,
10
- type NatsPersistedSubject,
11
- type NatsPublishPayloads,
12
- type NatsPublishSubject,
13
- type NatsReplyPayloads,
14
- type NatsRequestPayloads,
15
- type NatsRequestSubject,
16
- natsStreamBySubject,
17
- type NatsSubscribePayloads,
18
- type NatsSubscribeSubject,
8
+ export type {
9
+ NatsOperationParams,
10
+ NatsPublishPayloads,
11
+ NatsPublishSubject,
12
+ NatsReplyPayloads,
13
+ NatsRequestPayloads,
14
+ NatsRequestSubject,
15
+ NatsSubscribePayloads,
16
+ NatsSubscribeSubject,
19
17
  } from "../../lib/experimental/nats/generated/operations.ts"
20
18
  // Message payload types for every schema in src/asyncapi.yaml, e.g. `Cell`,
21
19
  // `App`, `ProgramStatus` (see NatsSubscribePayloads/NatsRequestPayloads for
@@ -23,6 +21,7 @@ export {
23
21
  export type * from "../../lib/experimental/nats/generated/types.ts"
24
22
  export { NovaNatsClient } from "../../lib/experimental/nats/NovaNatsClient.ts"
25
23
  export type {
24
+ NatsReceivedMsg,
26
25
  NatsSubscribeMsg,
27
26
  NatsSubscribeOptions,
28
27
  NovaNatsClientConfig,
@@ -1,28 +1,45 @@
1
- import { DeliverPolicy, jetstream, type JsMsg } from "@nats-io/jetstream"
1
+ import { DeliverPolicy, jetstream, jetstreamManager } from "@nats-io/jetstream"
2
2
  import {
3
3
  type ConnectionOptions,
4
- type Msg,
4
+ type MsgHdrs,
5
5
  type NatsConnection,
6
6
  wsconnect,
7
7
  } from "@nats-io/nats-core"
8
8
  import type { Nova } from "../../Nova.ts"
9
9
  import { buildNatsServerUrl } from "./buildNatsServerUrl.ts"
10
10
  import { buildSubject } from "./buildSubject.ts"
11
- import {
12
- type NatsOperationParams,
13
- type NatsPersistedSubject,
14
- type NatsPublishPayloads,
15
- type NatsPublishSubject,
16
- type NatsReplyPayloads,
17
- type NatsRequestPayloads,
18
- type NatsRequestSubject,
19
- natsStreamBySubject,
20
- type NatsSubscribePayloads,
21
- type NatsSubscribeSubject,
11
+ import type {
12
+ NatsOperationParams,
13
+ NatsPublishPayloads,
14
+ NatsPublishSubject,
15
+ NatsReplyPayloads,
16
+ NatsRequestPayloads,
17
+ NatsRequestSubject,
18
+ NatsSubscribePayloads,
19
+ NatsSubscribeSubject,
22
20
  } from "./generated/operations.ts"
23
21
 
24
22
  export type NovaNatsClientConfig = ConnectionOptions
25
23
 
24
+ /**
25
+ * The fields of a received message that exist on both a core NATS `Msg` and
26
+ * a JetStream `JsMsg` — a subscription delivers the former by default and
27
+ * the latter with `lastMessage: true` (see {@link NatsSubscribeOptions}),
28
+ * so handlers see only what both have in common.
29
+ */
30
+ export interface NatsReceivedMsg {
31
+ /** The concrete subject the message was published to. */
32
+ subject: string
33
+ /** The message's raw payload bytes. */
34
+ data: Uint8Array
35
+ /** Headers set by the server or the publisher, if any. */
36
+ headers?: MsgHdrs
37
+ /** The payload decoded as JSON. */
38
+ json<T>(): T
39
+ /** The payload decoded as a string. */
40
+ string(): string
41
+ }
42
+
26
43
  /**
27
44
  * A received message, annotated with the values of the subject template's
28
45
  * `{param}` placeholders as extracted from the message's concrete subject.
@@ -30,8 +47,20 @@ export type NovaNatsClientConfig = ConnectionOptions
30
47
  * a handler knows which entity a message belongs to. Typed per subject via
31
48
  * the generated `NatsOperationParams`.
32
49
  */
33
- export type NatsSubscribeMsg<K extends NatsSubscribeSubject> = (Msg | JsMsg) & {
34
- subjectParams: NatsOperationParams[K]
50
+ export type NatsSubscribeMsg<K extends NatsSubscribeSubject> =
51
+ NatsReceivedMsg & {
52
+ subjectParams: NatsOperationParams[K]
53
+ }
54
+
55
+ export type NatsSubscribeOptions = {
56
+ /**
57
+ * When true, the subscription immediately replays the last JetStream
58
+ * message persisted for each subject matching the subscription (one per
59
+ * concrete subject when subscribing with wildcards), then continues with
60
+ * live messages. Requires the server to have a JetStream stream capturing
61
+ * the subscribed subject; subscribing fails with an error if none exists.
62
+ */
63
+ lastMessage?: boolean
35
64
  }
36
65
 
37
66
  type NatsMessageHandler<K extends NatsSubscribeSubject> = (
@@ -39,34 +68,13 @@ type NatsMessageHandler<K extends NatsSubscribeSubject> = (
39
68
  msg: NatsSubscribeMsg<K>,
40
69
  ) => void | Promise<void>
41
70
 
42
- /**
43
- * Extra options for {@link NovaNatsClient.subscribe}. `replayLast` is only
44
- * offered on subjects the spec marks as retaining their latest message, so
45
- * asking for a replay that could never arrive is a compile error.
46
- */
47
- export type NatsSubscribeOptions<K extends NatsSubscribeSubject> =
48
- K extends NatsPersistedSubject
49
- ? {
50
- /**
51
- * Deliver the subject's current value immediately on subscribe,
52
- * before any subsequent updates. With a wildcard subscription (e.g.
53
- * `{ cell: "*" }`) the current value of every matching subject is
54
- * delivered, not just one.
55
- */
56
- replayLast?: boolean
57
- }
58
- : // Not `Record<never, never>`: that behaves like `{}` and so accepts any
59
- // object, letting `replayLast` through unchecked. Typing the property as
60
- // `never` is what makes passing it an error.
61
- { replayLast?: never }
62
-
63
71
  type SubscribeArgs<K extends NatsSubscribeSubject> =
64
72
  keyof NatsOperationParams[K] extends never
65
- ? [handler: NatsMessageHandler<K>, opts?: NatsSubscribeOptions<K>]
73
+ ? [handler: NatsMessageHandler<K>, options?: NatsSubscribeOptions]
66
74
  : [
67
75
  params: NatsOperationParams[K],
68
76
  handler: NatsMessageHandler<K>,
69
- opts?: NatsSubscribeOptions<K>,
77
+ options?: NatsSubscribeOptions,
70
78
  ]
71
79
 
72
80
  /**
@@ -138,11 +146,9 @@ export class NovaNatsClient {
138
146
  * nats.subscribe("nova.v2.cells.{cell}.status", { cell: "*" },
139
147
  * (services, msg) => console.log(msg.subjectParams.cell, services))
140
148
  *
141
- * On subjects that retain their latest message, pass `{ replayLast: true }`
142
- * to receive the current value immediately instead of waiting for the next
143
- * update — useful for a subscriber that starts after the last change:
144
- *
145
- * nats.subscribe("nova.v2.system.status", onStatus, { replayLast: true })
149
+ * With `{ lastMessage: true }` as the final argument, the last JetStream
150
+ * message persisted for each matching subject is replayed to the handler
151
+ * immediately, before live messages (see {@link NatsSubscribeOptions}).
146
152
  *
147
153
  * Returns a function that unsubscribes when called.
148
154
  */
@@ -150,14 +156,10 @@ export class NovaNatsClient {
150
156
  subject: K,
151
157
  ...args: SubscribeArgs<K>
152
158
  ): Promise<() => void> {
153
- // `params` is omitted for subjects with no {param} placeholders, so the
154
- // handler is the first argument in that case.
155
- const hasParams = typeof args[0] !== "function"
156
- const params = (hasParams ? args[0] : {}) as NatsOperationParams[K]
157
- const handler = (hasParams ? args[1] : args[0]) as NatsMessageHandler<K>
158
- const opts = (hasParams ? args[2] : args[1]) as
159
- | { replayLast?: boolean }
160
- | undefined
159
+ const [params, handler, options] =
160
+ typeof args[0] === "function"
161
+ ? ([{}, args[0], args[1] as NatsSubscribeOptions | undefined] as const)
162
+ : ([args[0], args[1] as NatsMessageHandler<K>, args[2]] as const)
161
163
 
162
164
  const nc = await this.connect()
163
165
  const resolvedSubject = buildSubject(subject, params)
@@ -173,33 +175,30 @@ export class NovaNatsClient {
173
175
  }
174
176
  }
175
177
 
176
- const deliver = async (msg: Msg | JsMsg) => {
177
- // Handled per-message: a bad payload or a throwing/rejecting handler
178
- // should not stop the subscription from processing later messages.
179
- try {
180
- const subjectTokens = msg.subject.split(".")
181
- const subjectParams = Object.fromEntries(
182
- paramPositions.map(([name, index]) => [
183
- name,
184
- subjectTokens[index] ?? "",
185
- ]),
186
- ) as NatsOperationParams[K]
187
- await handler(
188
- msg.json<NatsSubscribePayloads[K]>(),
189
- Object.assign(msg, { subjectParams }),
190
- )
191
- } catch (err) {
192
- console.error(
193
- `Error handling NATS message on subject "${resolvedSubject}"`,
194
- err,
195
- )
196
- }
197
- }
198
-
199
- const deliverAll = (messages: AsyncIterable<Msg | JsMsg>) => {
178
+ const dispatch = (messages: AsyncIterable<NatsReceivedMsg>) => {
200
179
  ;(async () => {
201
180
  for await (const msg of messages) {
202
- await deliver(msg)
181
+ // Handled per-message: a bad payload or a throwing/rejecting
182
+ // handler should not stop the subscription from processing later
183
+ // messages.
184
+ try {
185
+ const subjectTokens = msg.subject.split(".")
186
+ const subjectParams = Object.fromEntries(
187
+ paramPositions.map(([name, index]) => [
188
+ name,
189
+ subjectTokens[index] ?? "",
190
+ ]),
191
+ ) as NatsOperationParams[K]
192
+ await handler(
193
+ msg.json<NatsSubscribePayloads[K]>(),
194
+ Object.assign(msg, { subjectParams }),
195
+ )
196
+ } catch (err) {
197
+ console.error(
198
+ `Error handling NATS message on subject "${resolvedSubject}"`,
199
+ err,
200
+ )
201
+ }
203
202
  }
204
203
  })().catch((err: unknown) => {
205
204
  console.error(
@@ -209,29 +208,26 @@ export class NovaNatsClient {
209
208
  })
210
209
  }
211
210
 
212
- if (opts?.replayLast) {
213
- // Delivered by JetStream rather than core NATS: an ordered consumer
214
- // starting at `last_per_subject` yields each matching subject's retained
215
- // message and then continues with live ones on the same iterator, so
216
- // there is no gap — and no possible duplicate — between the replayed
217
- // value and the updates that follow it. Ordered consumers are ephemeral
218
- // and need no acking, so stopping the iterator is the whole teardown.
219
- const consumer = await jetstream(nc).consumers.get(
220
- natsStreamBySubject[subject as NatsPersistedSubject],
221
- {
222
- filter_subjects: [resolvedSubject],
223
- deliver_policy: DeliverPolicy.LastPerSubject,
224
- },
225
- )
211
+ if (options?.lastMessage) {
212
+ // Delivered through JetStream instead of a core subscription: an
213
+ // ordered (ephemeral, auto-acked, auto-cleaned-up) consumer with
214
+ // "last per subject" delivery replays the last persisted message of
215
+ // each matching subject, then seamlessly continues with live messages.
216
+ const jsm = await jetstreamManager(nc)
217
+ // Throws if no stream captures the subject, rather than silently
218
+ // never delivering anything.
219
+ const streamName = await jsm.streams.find(resolvedSubject)
220
+ const consumer = await jetstream(nc).consumers.get(streamName, {
221
+ filter_subjects: [resolvedSubject],
222
+ deliver_policy: DeliverPolicy.LastPerSubject,
223
+ })
226
224
  const messages = await consumer.consume()
227
- deliverAll(messages)
228
- return () => {
229
- messages.stop()
230
- }
225
+ dispatch(messages)
226
+ return () => void messages.close()
231
227
  }
232
228
 
233
229
  const sub = nc.subscribe(resolvedSubject)
234
- deliverAll(sub)
230
+ dispatch(sub)
235
231
  return () => sub.unsubscribe()
236
232
  }
237
233
 
@@ -732,26 +732,6 @@ export interface NatsSubscribePayloads {
732
732
 
733
733
  export type NatsSubscribeSubject = keyof NatsSubscribePayloads
734
734
 
735
- /**
736
- * The JetStream stream backing each subject that retains only its latest
737
- * message (`max_msgs_per_subject: 1` in src/asyncapi.yaml), so that
738
- * message is the subject's current state.
739
- */
740
- export const natsStreamBySubject = {
741
- "nova.v2.cells.{cell}": "system-state",
742
- "nova.v2.cells.{cell}.apps.{app}": "system-state",
743
- "nova.v2.cells.{cell}.controllers.{controller}": "system-state",
744
- "nova.v2.cells.{cell}.status": "system-state",
745
- "nova.v2.system.status": "system-state",
746
- "nova.v2.cells.{cell}.collision.setups.{setup}": "system-state",
747
- "nova.v2.cells.{cell}.bus-ios.status": "system-state",
748
- "nova.v2.cells.{cell}.controllers.{controller}.motion-groups.{motion-group}.description":
749
- "system-state",
750
- } as const
751
-
752
- /** Subjects whose current value can be replayed via `{ replayLast: true }`. */
753
- export type NatsPersistedSubject = keyof typeof natsStreamBySubject
754
-
755
735
  /** Request payload types for subjects the client sends requests to. */
756
736
  export interface NatsRequestPayloads {
757
737
  /**