@uns-kit/core 3.0.36 → 3.0.37

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.
Files changed (33) hide show
  1. package/MIGRATIONS.md +55 -0
  2. package/dist/index.d.ts +2 -0
  3. package/dist/index.d.ts.map +1 -1
  4. package/dist/index.js +2 -0
  5. package/dist/index.js.map +1 -1
  6. package/dist/runtime/application-handover-state.d.ts +13 -0
  7. package/dist/runtime/application-handover-state.d.ts.map +1 -0
  8. package/dist/runtime/application-handover-state.js +43 -0
  9. package/dist/runtime/application-handover-state.js.map +1 -0
  10. package/dist/runtime/mqtt-handover-state.d.ts +4 -0
  11. package/dist/runtime/mqtt-handover-state.d.ts.map +1 -1
  12. package/dist/runtime/mqtt-handover-state.js +6 -1
  13. package/dist/runtime/mqtt-handover-state.js.map +1 -1
  14. package/dist/runtime/process-work.d.ts +16 -0
  15. package/dist/runtime/process-work.d.ts.map +1 -0
  16. package/dist/runtime/process-work.js +34 -0
  17. package/dist/runtime/process-work.js.map +1 -0
  18. package/dist/uns/handover-manager.d.ts +5 -1
  19. package/dist/uns/handover-manager.d.ts.map +1 -1
  20. package/dist/uns/handover-manager.js +69 -15
  21. package/dist/uns/handover-manager.js.map +1 -1
  22. package/dist/uns/handover-shutdown.d.ts +2 -0
  23. package/dist/uns/handover-shutdown.d.ts.map +1 -1
  24. package/dist/uns/handover-shutdown.js +1 -1
  25. package/dist/uns/handover-shutdown.js.map +1 -1
  26. package/dist/uns/uns-interfaces.d.ts +5 -0
  27. package/dist/uns/uns-interfaces.d.ts.map +1 -1
  28. package/dist/uns/uns-interfaces.js.map +1 -1
  29. package/dist/uns/uns-proxy-process.d.ts +14 -0
  30. package/dist/uns/uns-proxy-process.d.ts.map +1 -1
  31. package/dist/uns/uns-proxy-process.js +94 -7
  32. package/dist/uns/uns-proxy-process.js.map +1 -1
  33. package/package.json +1 -1
@@ -1,3 +1,4 @@
1
+ import { validateApplicationHandoverContract } from "../runtime/application-handover-state.js";
1
2
  import { MQTT_DRAIN_HANDLER, MQTT_DRAIN_READY_EVENT, drainMqttForMigration } from "../runtime/mqtt-drain.js";
2
3
  import { randomBytes } from "crypto";
3
4
  import logger from "../logger.js";
@@ -20,6 +21,31 @@ class UnsProxyProcess {
20
21
  processId;
21
22
  handoverId;
22
23
  statefulHandover = false;
24
+ applicationHandoverState;
25
+ handoverReady = true;
26
+ pendingHandover;
27
+ readyToActivate = Promise.resolve();
28
+ markReady;
29
+ signalCleanupInstalled = false;
30
+ lifecycleParticipants = [];
31
+ usesStatefulHandover() { return this.statefulHandover; }
32
+ registerLifecycleParticipant(hooks) {
33
+ validateHandoverShutdown(hooks);
34
+ this.lifecycleParticipants.push(hooks);
35
+ }
36
+ /** API-only runtimes explicitly initialize the same ownership protocol as MQTT apps. */
37
+ async prepareHandover(instanceMode, handover) {
38
+ await this.waitForProcessConnection();
39
+ if (!this.handoverManager) {
40
+ if (!this.handoverReady) {
41
+ if (this.pendingHandover && (this.pendingHandover.instanceMode !== instanceMode || this.pendingHandover.handover !== handover))
42
+ throw Error("All proxies in one owner must use the same handover configuration");
43
+ this.pendingHandover = { instanceMode, handover };
44
+ }
45
+ else
46
+ this.initHandoverManager(instanceMode, handover, this.handoverId);
47
+ }
48
+ }
23
49
  handoverShutdown;
24
50
  unsMqttProxies;
25
51
  unsApiProxies;
@@ -84,8 +110,33 @@ class UnsProxyProcess {
84
110
  throw new Error("UnsProxyProcess requires a processName in configuration.");
85
111
  }
86
112
  validateHandoverShutdown(unsProxyProcessParameters.handoverShutdown);
87
- this.handoverShutdown = unsProxyProcessParameters.handoverShutdown
88
- ? { ...unsProxyProcessParameters.handoverShutdown } : undefined;
113
+ validateApplicationHandoverContract(unsProxyProcessParameters.handoverState);
114
+ this.applicationHandoverState = unsProxyProcessParameters.handoverState;
115
+ if (unsProxyProcessParameters.deferHandoverUntilReady) {
116
+ this.handoverReady = false;
117
+ this.readyToActivate = new Promise(resolve => { this.markReady = resolve; });
118
+ }
119
+ const suppliedHooks = unsProxyProcessParameters.handoverShutdown;
120
+ this.handoverShutdown = {
121
+ timeoutMs: suppliedHooks?.timeoutMs ?? 30_000,
122
+ onRelease: () => {
123
+ suppliedHooks?.onRelease?.();
124
+ for (const hooks of this.lifecycleParticipants)
125
+ hooks.onRelease?.();
126
+ },
127
+ onActivate: async () => {
128
+ await this.readyToActivate;
129
+ await suppliedHooks?.onActivate?.();
130
+ for (const hooks of this.lifecycleParticipants)
131
+ await hooks.onActivate?.();
132
+ },
133
+ drain: async () => {
134
+ // HTTP requests finish before application-owned resources are closed.
135
+ for (const hooks of this.lifecycleParticipants)
136
+ await hooks.drain();
137
+ await suppliedHooks?.drain();
138
+ },
139
+ };
89
140
  this.statefulHandover = unsProxyProcessParameters.handoverProtocol === "correlated-v2";
90
141
  this.processName = unsProxyProcessParameters.processName;
91
142
  this.processId = randomBytes(16).toString("hex");
@@ -141,13 +192,15 @@ class UnsProxyProcess {
141
192
  initHandoverManager(instanceMode, handover, handoverId) {
142
193
  const handoverRequestEnabled = instanceMode == "handover" ? true : false;
143
194
  const forceStartEnabled = instanceMode == "force" ? true : false;
144
- this.handoverManager = new HandoverManager(this.processName, this.processId, this.processMqttProxy, this.unsMqttProxies, handoverRequestEnabled, handover ?? true, forceStartEnabled, handoverId, this.handoverShutdown, this.statefulHandover);
195
+ this.handoverManager = new HandoverManager(this.processName, this.processId, this.processMqttProxy, this.unsMqttProxies, handoverRequestEnabled, handover ?? true, forceStartEnabled, handoverId, this.handoverShutdown, this.statefulHandover, this.applicationHandoverState);
145
196
  // Listen for handover events.
146
197
  this.handoverManager.event.on("handoverManager", (event) => {
147
198
  this.active = event.active;
148
199
  });
149
200
  // Delegate MQTT events to the HandoverManager.
150
201
  this.mqttInputHandler = async (event) => {
202
+ if (this.handoverReady === false)
203
+ return;
151
204
  await this.handoverManager.handleMqttMessage(event);
152
205
  };
153
206
  this.processMqttProxy.event.on("input", this.mqttInputHandler);
@@ -161,16 +214,16 @@ class UnsProxyProcess {
161
214
  }
162
215
  // Wait until the MQTT connection is established before proceeding.
163
216
  await this.waitForProcessConnection();
164
- // Currently handover manager can handle only mqtt events
165
- if (!this.handoverManager) {
166
- this.initHandoverManager(instanceMode, handover, this.handoverId);
167
- }
217
+ await this.prepareHandover(instanceMode, handover);
168
218
  const resolvedUnsParameters = {
169
219
  ...(unsParameters ?? {}),
170
220
  clientId: unsParameters?.clientId ?? `${this.processName}-${instanceName}-${this.processId}`,
171
221
  };
172
222
  if (this.statefulHandover && !resolvedUnsParameters?.handoverStateContract)
173
223
  throw Error("correlated-v2 requires a calculation-state contract for every MQTT proxy");
224
+ if (this.statefulHandover && this.applicationHandoverState) {
225
+ resolvedUnsParameters.handoverStateContract += `|application:${this.applicationHandoverState.contract}`;
226
+ }
174
227
  const unsMqttProxy = new UnsMqttProxy(mqttHost, this.processName, instanceName, resolvedUnsParameters);
175
228
  // Listen for UNS proxy producing topics and publish them via MQTT.
176
229
  unsMqttProxy.event.on("unsProxyProducedTopics", (event) => {
@@ -211,6 +264,12 @@ class UnsProxyProcess {
211
264
  }
212
265
  /** Call after application input handlers and shutdown hooks are prepared. */
213
266
  enableMigrationDrain() {
267
+ this.handoverReady = true;
268
+ this.markReady?.();
269
+ if (this.pendingHandover && !this.handoverManager)
270
+ this.initHandoverManager(this.pendingHandover.instanceMode, this.pendingHandover.handover, this.handoverId);
271
+ if (this.statefulHandover && !this.handoverManager)
272
+ throw Error("Initialize handover before advertising runtime readiness");
214
273
  const registry = globalThis;
215
274
  if (this.migrationDrainHandler)
216
275
  return;
@@ -220,6 +279,17 @@ class UnsProxyProcess {
220
279
  registry[MQTT_DRAIN_HANDLER] = this.migrationDrainHandler;
221
280
  process.emit(MQTT_DRAIN_READY_EVENT, { protocol: 1, ...(this.statefulHandover ? { handoverProtocol: 2 } : {}) });
222
281
  }
282
+ /** Optional single signal owner for applications without their own cleanup handler. */
283
+ installSignalHandlers() {
284
+ if (this.signalCleanupInstalled)
285
+ return;
286
+ this.signalCleanupInstalled = true;
287
+ const stop = () => {
288
+ void this.drainForMigration().then(() => process.exit(0), () => process.exit(1));
289
+ };
290
+ process.once("SIGINT", stop);
291
+ process.once("SIGTERM", stop);
292
+ }
223
293
  /** Works without a Controller too; success means confirmed empty output and closed owners. */
224
294
  drainForMigration(timeoutMs = this.handoverShutdown?.timeoutMs ?? 30_000) {
225
295
  if (this.migrationDrainPromise)
@@ -269,6 +339,23 @@ class UnsProxyProcess {
269
339
  shutdownErrors.push(reason);
270
340
  }
271
341
  }
342
+ for (const hooks of this.lifecycleParticipants) {
343
+ try {
344
+ hooks.onRelease?.();
345
+ await hooks.drain();
346
+ }
347
+ catch (e) {
348
+ shutdownErrors.push(e instanceof Error ? e : new Error("Lifecycle cleanup failed"));
349
+ }
350
+ }
351
+ for (const proxy of this.unsApiProxies) {
352
+ try {
353
+ await proxy.stop();
354
+ }
355
+ catch (e) {
356
+ shutdownErrors.push(e instanceof Error ? e : new Error("API cleanup failed"));
357
+ }
358
+ }
272
359
  const proxyStopResults = await Promise.allSettled(this.unsMqttProxies.map((proxy) => proxy.stop(options)));
273
360
  for (const result of proxyStopResults) {
274
361
  if (result.status === "rejected") {
@@ -1 +1 @@
1
- {"version":3,"file":"uns-proxy-process.js","sourceRoot":"","sources":["../../src/uns/uns-proxy-process.ts"],"names":[],"mappings":"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","sourcesContent":["import { MQTT_DRAIN_HANDLER, MQTT_DRAIN_READY_EVENT, drainMqttForMigration, type MqttDrainReceipt } from \"../runtime/mqtt-drain.js\";\nimport { randomBytes } from \"crypto\";\n\nimport logger from \"../logger.js\";\nimport { IMqttParameters } from \"../uns-mqtt/mqtt-interfaces.js\";\nimport MqttProxy from \"../uns-mqtt/mqtt-proxy.js\";\nimport { MqttTopicBuilder } from \"../uns-mqtt/mqtt-topic-builder.js\";\nimport UnsMqttProxy from \"../uns-mqtt/uns-mqtt-proxy.js\";\nimport type { UnsMqttProxyStopOptions } from \"../uns-mqtt/uns-mqtt-proxy.js\";\nimport { HandoverManager } from \"./handover-manager.js\";\nimport { validateHandoverShutdown, type HandoverShutdownHooks } from \"./handover-shutdown.js\";\n// Import configuration and initialization modules.\nimport { MQTT_UPDATE_INTERVAL, PACKAGE_INFO } from \"./process-config.js\";\nimport { type UnsServiceMetadata, type UnsServiceMetadataInput, buildUnsServiceMetadata } from \"./service-metadata.js\";\nimport { StatusMonitor } from \"./status-monitor.js\";\nimport { IUnsMessage, IUnsParameters, IUnsProcessParameters, UnsEvents } from \"./uns-interfaces.js\";\nimport { UnsPacket } from \"./uns-packet.js\";\n\n/**\n * UnsProxyProcess is responsible for managing the process lifecycle,\n * configuring MQTT (subscriptions and publishing for status updates), and\n * handling UNS proxy instances.\n *\n * It leverages HandoverManager for handover events and StatusMonitor for health reporting.\n */\nexport type UnsProxyProcessPluginMethod = (this: UnsProxyProcess, ...args: unknown[]) => unknown;\n\nexport type UnsProxyProcessPluginMethods = Record<string, UnsProxyProcessPluginMethod>;\n\nexport interface UnsProxyProcessPluginApi {\n version: number;\n define(methods: UnsProxyProcessPluginMethods): void;\n UnsProxyProcess: typeof UnsProxyProcess;\n}\n\nexport type UnsProxyProcessPlugin = (api: UnsProxyProcessPluginApi) => void;\n\nclass UnsProxyProcess {\n private active: boolean = false;\n /** Ownership gate for timers/pollers. Not transport readiness or durability. */\n public isActive(): boolean { return this.active && !this.shutdownPromise && !this.migrationDrainPromise; }\n private processStatusTopic: string;\n private processName: string;\n private processId: string;\n private handoverId: string | undefined;\n private statefulHandover: boolean = false;\n private handoverShutdown: HandoverShutdownHooks | undefined;\n private unsMqttProxies: UnsMqttProxy[];\n private unsApiProxies: unknown[];\n private processMqttProxy: MqttProxy;\n private handoverManager: HandoverManager;\n private statusMonitor: StatusMonitor;\n private serviceMetadataTopic: string;\n private shutdownPromise: Promise<void> | null = null;\n private migrationDrainPromise: Promise<MqttDrainReceipt> | null = null;\n private migrationDrainHandler?: () => Promise<MqttDrainReceipt>;\n\n // Plugin\n static pluginApiVersion = 1;\n private static registered = new Set<UnsProxyProcessPlugin>();\n private static registeredMethodNames = new Set<string>();\n private static applied = false;\n\n static use(plugin: UnsProxyProcessPlugin) {\n if (this.registered.has(plugin)) return this;\n this.registered.add(plugin);\n if (this.applied) this.applyPlugin(plugin);\n return this;\n }\n\n private static applyPlugin(plugin: UnsProxyProcessPlugin) {\n const define: UnsProxyProcessPluginApi[\"define\"] = (methods) => {\n for (const [name, fn] of Object.entries(methods)) {\n if (typeof fn !== \"function\") {\n throw new TypeError(`UnsProxyProcess plugin attempted to register non-function member \\\"${name}\\\".`);\n }\n if (this.registeredMethodNames.has(name) || Reflect.has(this.prototype, name)) {\n throw new Error(`UnsProxyProcess plugin attempted to overwrite existing member \\\"${name}\\\".`);\n }\n Object.defineProperty(this.prototype, name, {\n value: fn,\n writable: true,\n configurable: true,\n enumerable: false,\n });\n this.registeredMethodNames.add(name);\n }\n };\n\n plugin({\n define,\n version: this.pluginApiVersion,\n UnsProxyProcess: this,\n });\n }\n\n private static applyAll() {\n if (this.applied) return;\n this.applied = true;\n for (const p of this.registered) this.applyPlugin(p);\n }\n\n // References for cleanup.\n private mqttInputHandler: (event: any) => void;\n\n constructor(mqttHost: string, unsProxyProcessParameters: IUnsProcessParameters) {\n (this.constructor as typeof UnsProxyProcess).applyAll(); // Activate all the plugins\n\n this.unsMqttProxies = [];\n this.unsApiProxies = [];\n if (!unsProxyProcessParameters?.processName) {\n throw new Error(\"UnsProxyProcess requires a processName in configuration.\");\n }\n validateHandoverShutdown(unsProxyProcessParameters.handoverShutdown);\n this.handoverShutdown = unsProxyProcessParameters.handoverShutdown\n ? { ...unsProxyProcessParameters.handoverShutdown } : undefined;\n this.statefulHandover = unsProxyProcessParameters.handoverProtocol === \"correlated-v2\";\n this.processName = unsProxyProcessParameters.processName;\n this.processId = randomBytes(16).toString(\"hex\");\n this.handoverId = unsProxyProcessParameters.handoverId ?? process.env[\"UNS_HANDOVER_ID\"];\n const { name: packageName, version } = PACKAGE_INFO;\n\n // Instantiate the topic builder.\n const topicBuilder = new MqttTopicBuilder(\n `uns-infra/${MqttTopicBuilder.sanitizeTopicPart(packageName)}/${MqttTopicBuilder.sanitizeTopicPart(version)}/${MqttTopicBuilder.sanitizeTopicPart(this.processName)}/`,\n );\n\n // Generate topics.\n const processStatusTopic = topicBuilder.getProcessStatusTopic();\n const handoverTopic = topicBuilder.getHandoverTopic();\n const wildcardActiveTopic = topicBuilder.getWildcardActiveTopic();\n const serviceMetadataTopic = topicBuilder.getServiceMetadataTopic();\n\n this.processStatusTopic = processStatusTopic;\n this.serviceMetadataTopic = serviceMetadataTopic;\n\n // Configure MQTT topics for subscription.\n const mqttSubToTopics = unsProxyProcessParameters?.mqttSubToTopics ?? [wildcardActiveTopic, handoverTopic];\n const mqttParameters: IMqttParameters = {\n mqttSubToTopics,\n username: unsProxyProcessParameters?.username ?? \"\",\n password: unsProxyProcessParameters?.password ?? \"\",\n mqttSSL: unsProxyProcessParameters?.mqttSSL ?? false,\n statusTopic: this.processStatusTopic,\n clientId: unsProxyProcessParameters?.clientId ?? `${this.processName}-${this.processId}`,\n hosts: unsProxyProcessParameters?.hosts,\n servers: unsProxyProcessParameters?.servers,\n port: unsProxyProcessParameters?.port,\n protocol: unsProxyProcessParameters?.protocol,\n keepalive: unsProxyProcessParameters?.keepalive,\n clean: unsProxyProcessParameters?.clean,\n connectTimeout: unsProxyProcessParameters?.connectTimeout,\n reconnectPeriod: unsProxyProcessParameters?.reconnectPeriod,\n reconnectOnConnackError: unsProxyProcessParameters?.reconnectOnConnackError,\n resubscribe: unsProxyProcessParameters?.resubscribe,\n queueQoSZero: unsProxyProcessParameters?.queueQoSZero,\n rejectUnauthorized: unsProxyProcessParameters?.rejectUnauthorized ?? false,\n properties: unsProxyProcessParameters?.properties,\n ca: unsProxyProcessParameters?.ca,\n cert: unsProxyProcessParameters?.cert,\n key: unsProxyProcessParameters?.key,\n servername: unsProxyProcessParameters?.servername,\n };\n\n // Initialize MQTT proxy and start connection.\n this.processMqttProxy = new MqttProxy(mqttHost, this.processName, mqttParameters);\n this.processMqttProxy.start();\n\n // Instantiate and start the StatusMonitor for memory and status updates.\n this.statusMonitor = new StatusMonitor(\n this.processMqttProxy,\n this.processStatusTopic,\n () => this.active,\n MQTT_UPDATE_INTERVAL,\n MQTT_UPDATE_INTERVAL,\n { processName: this.processName, processId: this.processId },\n );\n this.statusMonitor.start();\n }\n\n /**\n * Initializes the HandoverManager instance and sets up event listeners for handover and MQTT input events.\n * Determines handover and force start modes based on process arguments.\n */\n private initHandoverManager(instanceMode: string, handover: boolean, handoverId?: string) {\n const handoverRequestEnabled = instanceMode == \"handover\" ? true : false;\n const forceStartEnabled = instanceMode == \"force\" ? true : false;\n\n this.handoverManager = new HandoverManager(\n this.processName,\n this.processId,\n this.processMqttProxy,\n this.unsMqttProxies,\n handoverRequestEnabled,\n handover ?? true,\n forceStartEnabled,\n handoverId,\n this.handoverShutdown,\n this.statefulHandover,\n );\n\n // Listen for handover events.\n this.handoverManager.event.on(\"handoverManager\", (event) => {\n this.active = event.active;\n });\n\n // Delegate MQTT events to the HandoverManager.\n this.mqttInputHandler = async (event: UnsEvents[\"input\"]) => {\n await this.handoverManager.handleMqttMessage(event);\n };\n this.processMqttProxy.event.on(\"input\", this.mqttInputHandler);\n }\n\n /**\n * Creates a new UNS proxy instance and stores it for future management.\n */\n public async createUnsMqttProxy(\n mqttHost: string,\n instanceName: string,\n instanceMode: string,\n handover: boolean,\n unsParameters?: IUnsParameters,\n ): Promise<UnsMqttProxy> {\n if (unsParameters?.publishQueue && unsParameters.publishQueue.enabled !== false && handover) {\n throw new Error(\"Persistent MQTT output requires handover=false and one owner; legacy RAM handover does not transfer an outbox\");\n }\n // Wait until the MQTT connection is established before proceeding.\n await this.waitForProcessConnection();\n\n // Currently handover manager can handle only mqtt events\n if (!this.handoverManager) {\n this.initHandoverManager(\n instanceMode,\n handover,\n this.handoverId,\n );\n }\n\n const resolvedUnsParameters: IUnsParameters = {\n ...(unsParameters ?? {}),\n clientId: unsParameters?.clientId ?? `${this.processName}-${instanceName}-${this.processId}`,\n };\n if (this.statefulHandover && !resolvedUnsParameters?.handoverStateContract) throw Error(\"correlated-v2 requires a calculation-state contract for every MQTT proxy\");\n const unsMqttProxy = new UnsMqttProxy(mqttHost, this.processName, instanceName, resolvedUnsParameters);\n\n // Listen for UNS proxy producing topics and publish them via MQTT.\n unsMqttProxy.event.on(\"unsProxyProducedTopics\", (event) => {\n this.processMqttProxy.publish(event.statusTopic, JSON.stringify(event.producedTopics));\n });\n\n // Listen for UNS proxy status events and publish them via MQTT.\n unsMqttProxy.event.on(\"mqttProxyStatus\", (event) => {\n const time = UnsPacket.formatToISO8601(new Date());\n const unsMessage: IUnsMessage = { data: { time, value: event.value, uom: event.uom } };\n UnsPacket.unsPacketFromUnsMessage(unsMessage).then((packet) => {\n this.processMqttProxy.publish(event.statusTopic, JSON.stringify(packet));\n });\n });\n\n this.unsMqttProxies.push(unsMqttProxy);\n return unsMqttProxy;\n }\n\n public async waitForProcessConnection(): Promise<void> {\n while (!this.processMqttProxy?.isConnected) {\n await new Promise((resolve) => setTimeout(resolve, 100));\n }\n }\n\n /**\n * Publishes retained product/system service metadata for controller discovery.\n *\n * The payload is intentionally separate from the volatile active/alive status\n * topics. Controllers can combine this retained identity/capability metadata\n * with live process status to decide whether a service is currently healthy.\n */\n public async publishServiceMetadata(metadata: UnsServiceMetadataInput): Promise<UnsServiceMetadata> {\n await this.waitForProcessConnection();\n const resolved = buildUnsServiceMetadata({\n processName: this.processName,\n processId: this.processId,\n metadata,\n });\n await this.processMqttProxy.publish(this.serviceMetadataTopic, JSON.stringify(resolved), { retain: true });\n return resolved;\n }\n\n /** Call after application input handlers and shutdown hooks are prepared. */\n public enableMigrationDrain(): void {\n const registry = globalThis as unknown as Record<symbol, unknown>;\n if (this.migrationDrainHandler) return;\n if (registry[MQTT_DRAIN_HANDLER]) throw Error(\"One migration drain owner is allowed per process\");\n this.migrationDrainHandler = () => this.drainForMigration();\n registry[MQTT_DRAIN_HANDLER] = this.migrationDrainHandler;\n (process as unknown as { emit(event: string, value: unknown): boolean }).emit(MQTT_DRAIN_READY_EVENT, { protocol: 1, ...(this.statefulHandover ? { handoverProtocol: 2 } : {}) });\n }\n\n /** Works without a Controller too; success means confirmed empty output and closed owners. */\n public drainForMigration(timeoutMs = this.handoverShutdown?.timeoutMs ?? 30_000): Promise<MqttDrainReceipt> {\n if (this.migrationDrainPromise) return this.migrationDrainPromise;\n this.migrationDrainPromise = (async () => {\n const receipt = await drainMqttForMigration({\n quiesce: async () => {\n this.handoverShutdown?.onRelease?.();\n await Promise.all(this.unsMqttProxies.map(proxy => proxy.setSubscriberPassiveAndDrainQueue()));\n },\n finishAccepted: async () => { await this.handoverShutdown?.drain(); },\n outputs: this.unsMqttProxies,\n timeoutMs,\n });\n await this.shutdown({ drain: true, timeoutMs });\n return receipt;\n })().catch(error => { this.migrationDrainPromise = null; throw error; });\n return this.migrationDrainPromise;\n }\n\n /** Stop process timers, status publication and all owned MQTT proxies. */\n public shutdown(options: UnsMqttProxyStopOptions = {}): Promise<void> {\n if (this.shutdownPromise) {\n return this.shutdownPromise;\n }\n\n this.shutdownPromise = this.performShutdown(options);\n return this.shutdownPromise;\n }\n\n private async performShutdown(options: UnsMqttProxyStopOptions): Promise<void> {\n logger.info(`${this.processName} - Shutting down UnsProxyProcess...`);\n const shutdownErrors: Error[] = [];\n\n try {\n this.statusMonitor.stop();\n await this.statusMonitor.publishInactiveStatus();\n } catch (e: any) {\n const reason = e instanceof Error ? e : new Error(String(e));\n logger.error(`${this.processName} - Error stopping StatusMonitor or publishing passive state: ${reason.message}`);\n shutdownErrors.push(reason);\n }\n\n if (this.mqttInputHandler) {\n try {\n this.processMqttProxy.event.off(\"input\", this.mqttInputHandler);\n } catch (e: any) {\n const reason = e instanceof Error ? e : new Error(String(e));\n logger.error(`${this.processName} - Error removing MQTT input handler: ${reason.message}`);\n shutdownErrors.push(reason);\n }\n }\n\n const proxyStopResults = await Promise.allSettled(this.unsMqttProxies.map((proxy) => proxy.stop(options)));\n for (const result of proxyStopResults) {\n if (result.status === \"rejected\") {\n const reason = result.reason instanceof Error ? result.reason : new Error(String(result.reason));\n logger.error(`${this.processName} - Error stopping UNS MQTT proxy: ${reason.message}`);\n shutdownErrors.push(reason);\n }\n }\n\n try {\n if (typeof this.processMqttProxy.stop === \"function\") {\n await this.processMqttProxy.stop();\n }\n } catch (e: any) {\n const reason = e instanceof Error ? e : new Error(String(e));\n logger.error(`${this.processName} - Error stopping MQTT proxy: ${reason.message}`);\n shutdownErrors.push(reason);\n }\n\n if (shutdownErrors.length > 0) {\n throw new AggregateError(shutdownErrors, `${this.processName} - Shutdown completed with errors.`);\n }\n\n if (this.migrationDrainHandler) {\n const registry = globalThis as unknown as Record<symbol, unknown>;\n if (registry[MQTT_DRAIN_HANDLER] === this.migrationDrainHandler) delete registry[MQTT_DRAIN_HANDLER];\n process.channel?.unref();\n }\n logger.info(`${this.processName} - Shutdown complete.`);\n }\n}\n\ninterface UnsProxyProcess {}\n\nexport default UnsProxyProcess;\nexport type { UnsServiceMetadata, UnsServiceMetadataInput };\nexport { UnsProxyProcess };\n"]}
1
+ {"version":3,"file":"uns-proxy-process.js","sourceRoot":"","sources":["../../src/uns/uns-proxy-process.ts"],"names":[],"mappings":"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","sourcesContent":["import { validateApplicationHandoverContract, type ApplicationHandoverState } from \"../runtime/application-handover-state.js\";\nimport { MQTT_DRAIN_HANDLER, MQTT_DRAIN_READY_EVENT, drainMqttForMigration, type MqttDrainReceipt } from \"../runtime/mqtt-drain.js\";\nimport { randomBytes } from \"crypto\";\n\nimport logger from \"../logger.js\";\nimport { IMqttParameters } from \"../uns-mqtt/mqtt-interfaces.js\";\nimport MqttProxy from \"../uns-mqtt/mqtt-proxy.js\";\nimport { MqttTopicBuilder } from \"../uns-mqtt/mqtt-topic-builder.js\";\nimport UnsMqttProxy from \"../uns-mqtt/uns-mqtt-proxy.js\";\nimport type { UnsMqttProxyStopOptions } from \"../uns-mqtt/uns-mqtt-proxy.js\";\nimport { HandoverManager } from \"./handover-manager.js\";\nimport { validateHandoverShutdown, type HandoverShutdownHooks } from \"./handover-shutdown.js\";\n// Import configuration and initialization modules.\nimport { MQTT_UPDATE_INTERVAL, PACKAGE_INFO } from \"./process-config.js\";\nimport { type UnsServiceMetadata, type UnsServiceMetadataInput, buildUnsServiceMetadata } from \"./service-metadata.js\";\nimport { StatusMonitor } from \"./status-monitor.js\";\nimport { IUnsMessage, IUnsParameters, IUnsProcessParameters, UnsEvents } from \"./uns-interfaces.js\";\nimport { UnsPacket } from \"./uns-packet.js\";\n\n/**\n * UnsProxyProcess is responsible for managing the process lifecycle,\n * configuring MQTT (subscriptions and publishing for status updates), and\n * handling UNS proxy instances.\n *\n * It leverages HandoverManager for handover events and StatusMonitor for health reporting.\n */\nexport type UnsProxyProcessPluginMethod = (this: UnsProxyProcess, ...args: unknown[]) => unknown;\n\nexport type UnsProxyProcessPluginMethods = Record<string, UnsProxyProcessPluginMethod>;\n\nexport interface UnsProxyProcessPluginApi {\n version: number;\n define(methods: UnsProxyProcessPluginMethods): void;\n UnsProxyProcess: typeof UnsProxyProcess;\n}\n\nexport type UnsProxyProcessPlugin = (api: UnsProxyProcessPluginApi) => void;\n\nclass UnsProxyProcess {\n private active: boolean = false;\n /** Ownership gate for timers/pollers. Not transport readiness or durability. */\n public isActive(): boolean { return this.active && !this.shutdownPromise && !this.migrationDrainPromise; }\n private processStatusTopic: string;\n private processName: string;\n private processId: string;\n private handoverId: string | undefined;\n private statefulHandover: boolean = false;\n private applicationHandoverState?: ApplicationHandoverState;\n private handoverReady = true;\n private pendingHandover?: { instanceMode: string; handover: boolean };\n private readyToActivate: Promise<void> = Promise.resolve();\n private markReady?: () => void;\n private signalCleanupInstalled = false;\n private lifecycleParticipants: HandoverShutdownHooks[] = [];\n public usesStatefulHandover(): boolean { return this.statefulHandover; }\n public registerLifecycleParticipant(hooks: HandoverShutdownHooks): void {\n validateHandoverShutdown(hooks);\n this.lifecycleParticipants.push(hooks);\n }\n /** API-only runtimes explicitly initialize the same ownership protocol as MQTT apps. */\n public async prepareHandover(instanceMode: string, handover: boolean): Promise<void> {\n await this.waitForProcessConnection();\n if (!this.handoverManager) {\n if (!this.handoverReady) {\n if (this.pendingHandover && (this.pendingHandover.instanceMode !== instanceMode || this.pendingHandover.handover !== handover))\n throw Error(\"All proxies in one owner must use the same handover configuration\");\n this.pendingHandover = { instanceMode, handover };\n } else this.initHandoverManager(instanceMode, handover, this.handoverId);\n }\n }\n private handoverShutdown: HandoverShutdownHooks | undefined;\n private unsMqttProxies: UnsMqttProxy[];\n private unsApiProxies: unknown[];\n private processMqttProxy: MqttProxy;\n private handoverManager: HandoverManager;\n private statusMonitor: StatusMonitor;\n private serviceMetadataTopic: string;\n private shutdownPromise: Promise<void> | null = null;\n private migrationDrainPromise: Promise<MqttDrainReceipt> | null = null;\n private migrationDrainHandler?: () => Promise<MqttDrainReceipt>;\n\n // Plugin\n static pluginApiVersion = 1;\n private static registered = new Set<UnsProxyProcessPlugin>();\n private static registeredMethodNames = new Set<string>();\n private static applied = false;\n\n static use(plugin: UnsProxyProcessPlugin) {\n if (this.registered.has(plugin)) return this;\n this.registered.add(plugin);\n if (this.applied) this.applyPlugin(plugin);\n return this;\n }\n\n private static applyPlugin(plugin: UnsProxyProcessPlugin) {\n const define: UnsProxyProcessPluginApi[\"define\"] = (methods) => {\n for (const [name, fn] of Object.entries(methods)) {\n if (typeof fn !== \"function\") {\n throw new TypeError(`UnsProxyProcess plugin attempted to register non-function member \\\"${name}\\\".`);\n }\n if (this.registeredMethodNames.has(name) || Reflect.has(this.prototype, name)) {\n throw new Error(`UnsProxyProcess plugin attempted to overwrite existing member \\\"${name}\\\".`);\n }\n Object.defineProperty(this.prototype, name, {\n value: fn,\n writable: true,\n configurable: true,\n enumerable: false,\n });\n this.registeredMethodNames.add(name);\n }\n };\n\n plugin({\n define,\n version: this.pluginApiVersion,\n UnsProxyProcess: this,\n });\n }\n\n private static applyAll() {\n if (this.applied) return;\n this.applied = true;\n for (const p of this.registered) this.applyPlugin(p);\n }\n\n // References for cleanup.\n private mqttInputHandler: (event: any) => void;\n\n constructor(mqttHost: string, unsProxyProcessParameters: IUnsProcessParameters) {\n (this.constructor as typeof UnsProxyProcess).applyAll(); // Activate all the plugins\n\n this.unsMqttProxies = [];\n this.unsApiProxies = [];\n if (!unsProxyProcessParameters?.processName) {\n throw new Error(\"UnsProxyProcess requires a processName in configuration.\");\n }\n validateHandoverShutdown(unsProxyProcessParameters.handoverShutdown);\n validateApplicationHandoverContract(unsProxyProcessParameters.handoverState);\n this.applicationHandoverState = unsProxyProcessParameters.handoverState;\n if (unsProxyProcessParameters.deferHandoverUntilReady) {\n this.handoverReady = false;\n this.readyToActivate = new Promise(resolve => { this.markReady = resolve; });\n }\n const suppliedHooks = unsProxyProcessParameters.handoverShutdown;\n this.handoverShutdown = {\n timeoutMs: suppliedHooks?.timeoutMs ?? 30_000,\n onRelease: () => {\n suppliedHooks?.onRelease?.();\n for (const hooks of this.lifecycleParticipants) hooks.onRelease?.();\n },\n onActivate: async () => {\n await this.readyToActivate;\n await suppliedHooks?.onActivate?.();\n for (const hooks of this.lifecycleParticipants) await hooks.onActivate?.();\n },\n drain: async () => {\n // HTTP requests finish before application-owned resources are closed.\n for (const hooks of this.lifecycleParticipants) await hooks.drain();\n await suppliedHooks?.drain();\n },\n };\n this.statefulHandover = unsProxyProcessParameters.handoverProtocol === \"correlated-v2\";\n this.processName = unsProxyProcessParameters.processName;\n this.processId = randomBytes(16).toString(\"hex\");\n this.handoverId = unsProxyProcessParameters.handoverId ?? process.env[\"UNS_HANDOVER_ID\"];\n const { name: packageName, version } = PACKAGE_INFO;\n\n // Instantiate the topic builder.\n const topicBuilder = new MqttTopicBuilder(\n `uns-infra/${MqttTopicBuilder.sanitizeTopicPart(packageName)}/${MqttTopicBuilder.sanitizeTopicPart(version)}/${MqttTopicBuilder.sanitizeTopicPart(this.processName)}/`,\n );\n\n // Generate topics.\n const processStatusTopic = topicBuilder.getProcessStatusTopic();\n const handoverTopic = topicBuilder.getHandoverTopic();\n const wildcardActiveTopic = topicBuilder.getWildcardActiveTopic();\n const serviceMetadataTopic = topicBuilder.getServiceMetadataTopic();\n\n this.processStatusTopic = processStatusTopic;\n this.serviceMetadataTopic = serviceMetadataTopic;\n\n // Configure MQTT topics for subscription.\n const mqttSubToTopics = unsProxyProcessParameters?.mqttSubToTopics ?? [wildcardActiveTopic, handoverTopic];\n const mqttParameters: IMqttParameters = {\n mqttSubToTopics,\n username: unsProxyProcessParameters?.username ?? \"\",\n password: unsProxyProcessParameters?.password ?? \"\",\n mqttSSL: unsProxyProcessParameters?.mqttSSL ?? false,\n statusTopic: this.processStatusTopic,\n clientId: unsProxyProcessParameters?.clientId ?? `${this.processName}-${this.processId}`,\n hosts: unsProxyProcessParameters?.hosts,\n servers: unsProxyProcessParameters?.servers,\n port: unsProxyProcessParameters?.port,\n protocol: unsProxyProcessParameters?.protocol,\n keepalive: unsProxyProcessParameters?.keepalive,\n clean: unsProxyProcessParameters?.clean,\n connectTimeout: unsProxyProcessParameters?.connectTimeout,\n reconnectPeriod: unsProxyProcessParameters?.reconnectPeriod,\n reconnectOnConnackError: unsProxyProcessParameters?.reconnectOnConnackError,\n resubscribe: unsProxyProcessParameters?.resubscribe,\n queueQoSZero: unsProxyProcessParameters?.queueQoSZero,\n rejectUnauthorized: unsProxyProcessParameters?.rejectUnauthorized ?? false,\n properties: unsProxyProcessParameters?.properties,\n ca: unsProxyProcessParameters?.ca,\n cert: unsProxyProcessParameters?.cert,\n key: unsProxyProcessParameters?.key,\n servername: unsProxyProcessParameters?.servername,\n };\n\n // Initialize MQTT proxy and start connection.\n this.processMqttProxy = new MqttProxy(mqttHost, this.processName, mqttParameters);\n this.processMqttProxy.start();\n\n // Instantiate and start the StatusMonitor for memory and status updates.\n this.statusMonitor = new StatusMonitor(\n this.processMqttProxy,\n this.processStatusTopic,\n () => this.active,\n MQTT_UPDATE_INTERVAL,\n MQTT_UPDATE_INTERVAL,\n { processName: this.processName, processId: this.processId },\n );\n this.statusMonitor.start();\n }\n\n /**\n * Initializes the HandoverManager instance and sets up event listeners for handover and MQTT input events.\n * Determines handover and force start modes based on process arguments.\n */\n private initHandoverManager(instanceMode: string, handover: boolean, handoverId?: string) {\n const handoverRequestEnabled = instanceMode == \"handover\" ? true : false;\n const forceStartEnabled = instanceMode == \"force\" ? true : false;\n\n this.handoverManager = new HandoverManager(\n this.processName,\n this.processId,\n this.processMqttProxy,\n this.unsMqttProxies,\n handoverRequestEnabled,\n handover ?? true,\n forceStartEnabled,\n handoverId,\n this.handoverShutdown,\n this.statefulHandover,\n this.applicationHandoverState,\n );\n\n // Listen for handover events.\n this.handoverManager.event.on(\"handoverManager\", (event) => {\n this.active = event.active;\n });\n\n // Delegate MQTT events to the HandoverManager.\n this.mqttInputHandler = async (event: UnsEvents[\"input\"]) => {\n if (this.handoverReady === false) return;\n await this.handoverManager.handleMqttMessage(event);\n };\n this.processMqttProxy.event.on(\"input\", this.mqttInputHandler);\n }\n\n /**\n * Creates a new UNS proxy instance and stores it for future management.\n */\n public async createUnsMqttProxy(\n mqttHost: string,\n instanceName: string,\n instanceMode: string,\n handover: boolean,\n unsParameters?: IUnsParameters,\n ): Promise<UnsMqttProxy> {\n if (unsParameters?.publishQueue && unsParameters.publishQueue.enabled !== false && handover) {\n throw new Error(\"Persistent MQTT output requires handover=false and one owner; legacy RAM handover does not transfer an outbox\");\n }\n // Wait until the MQTT connection is established before proceeding.\n await this.waitForProcessConnection();\n\n await this.prepareHandover(instanceMode, handover);\n\n const resolvedUnsParameters: IUnsParameters = {\n ...(unsParameters ?? {}),\n clientId: unsParameters?.clientId ?? `${this.processName}-${instanceName}-${this.processId}`,\n };\n if (this.statefulHandover && !resolvedUnsParameters?.handoverStateContract) throw Error(\"correlated-v2 requires a calculation-state contract for every MQTT proxy\");\n if (this.statefulHandover && this.applicationHandoverState) {\n resolvedUnsParameters.handoverStateContract += `|application:${this.applicationHandoverState.contract}`;\n }\n const unsMqttProxy = new UnsMqttProxy(mqttHost, this.processName, instanceName, resolvedUnsParameters);\n\n // Listen for UNS proxy producing topics and publish them via MQTT.\n unsMqttProxy.event.on(\"unsProxyProducedTopics\", (event) => {\n this.processMqttProxy.publish(event.statusTopic, JSON.stringify(event.producedTopics));\n });\n\n // Listen for UNS proxy status events and publish them via MQTT.\n unsMqttProxy.event.on(\"mqttProxyStatus\", (event) => {\n const time = UnsPacket.formatToISO8601(new Date());\n const unsMessage: IUnsMessage = { data: { time, value: event.value, uom: event.uom } };\n UnsPacket.unsPacketFromUnsMessage(unsMessage).then((packet) => {\n this.processMqttProxy.publish(event.statusTopic, JSON.stringify(packet));\n });\n });\n\n this.unsMqttProxies.push(unsMqttProxy);\n return unsMqttProxy;\n }\n\n public async waitForProcessConnection(): Promise<void> {\n while (!this.processMqttProxy?.isConnected) {\n await new Promise((resolve) => setTimeout(resolve, 100));\n }\n }\n\n /**\n * Publishes retained product/system service metadata for controller discovery.\n *\n * The payload is intentionally separate from the volatile active/alive status\n * topics. Controllers can combine this retained identity/capability metadata\n * with live process status to decide whether a service is currently healthy.\n */\n public async publishServiceMetadata(metadata: UnsServiceMetadataInput): Promise<UnsServiceMetadata> {\n await this.waitForProcessConnection();\n const resolved = buildUnsServiceMetadata({\n processName: this.processName,\n processId: this.processId,\n metadata,\n });\n await this.processMqttProxy.publish(this.serviceMetadataTopic, JSON.stringify(resolved), { retain: true });\n return resolved;\n }\n\n /** Call after application input handlers and shutdown hooks are prepared. */\n public enableMigrationDrain(): void {\n this.handoverReady = true;\n this.markReady?.();\n if (this.pendingHandover && !this.handoverManager)\n this.initHandoverManager(this.pendingHandover.instanceMode, this.pendingHandover.handover, this.handoverId);\n if (this.statefulHandover && !this.handoverManager) throw Error(\"Initialize handover before advertising runtime readiness\");\n const registry = globalThis as unknown as Record<symbol, unknown>;\n if (this.migrationDrainHandler) return;\n if (registry[MQTT_DRAIN_HANDLER]) throw Error(\"One migration drain owner is allowed per process\");\n this.migrationDrainHandler = () => this.drainForMigration();\n registry[MQTT_DRAIN_HANDLER] = this.migrationDrainHandler;\n (process as unknown as { emit(event: string, value: unknown): boolean }).emit(MQTT_DRAIN_READY_EVENT, { protocol: 1, ...(this.statefulHandover ? { handoverProtocol: 2 } : {}) });\n }\n\n /** Optional single signal owner for applications without their own cleanup handler. */\n public installSignalHandlers(): void {\n if (this.signalCleanupInstalled) return;\n this.signalCleanupInstalled = true;\n const stop = () => {\n void this.drainForMigration().then(() => process.exit(0), () => process.exit(1));\n };\n process.once(\"SIGINT\", stop);\n process.once(\"SIGTERM\", stop);\n }\n\n /** Works without a Controller too; success means confirmed empty output and closed owners. */\n public drainForMigration(timeoutMs = this.handoverShutdown?.timeoutMs ?? 30_000): Promise<MqttDrainReceipt> {\n if (this.migrationDrainPromise) return this.migrationDrainPromise;\n this.migrationDrainPromise = (async () => {\n const receipt = await drainMqttForMigration({\n quiesce: async () => {\n this.handoverShutdown?.onRelease?.();\n await Promise.all(this.unsMqttProxies.map(proxy => proxy.setSubscriberPassiveAndDrainQueue()));\n },\n finishAccepted: async () => { await this.handoverShutdown?.drain(); },\n outputs: this.unsMqttProxies,\n timeoutMs,\n });\n await this.shutdown({ drain: true, timeoutMs });\n return receipt;\n })().catch(error => { this.migrationDrainPromise = null; throw error; });\n return this.migrationDrainPromise;\n }\n\n /** Stop process timers, status publication and all owned MQTT proxies. */\n public shutdown(options: UnsMqttProxyStopOptions = {}): Promise<void> {\n if (this.shutdownPromise) {\n return this.shutdownPromise;\n }\n\n this.shutdownPromise = this.performShutdown(options);\n return this.shutdownPromise;\n }\n\n private async performShutdown(options: UnsMqttProxyStopOptions): Promise<void> {\n logger.info(`${this.processName} - Shutting down UnsProxyProcess...`);\n const shutdownErrors: Error[] = [];\n\n try {\n this.statusMonitor.stop();\n await this.statusMonitor.publishInactiveStatus();\n } catch (e: any) {\n const reason = e instanceof Error ? e : new Error(String(e));\n logger.error(`${this.processName} - Error stopping StatusMonitor or publishing passive state: ${reason.message}`);\n shutdownErrors.push(reason);\n }\n\n if (this.mqttInputHandler) {\n try {\n this.processMqttProxy.event.off(\"input\", this.mqttInputHandler);\n } catch (e: any) {\n const reason = e instanceof Error ? e : new Error(String(e));\n logger.error(`${this.processName} - Error removing MQTT input handler: ${reason.message}`);\n shutdownErrors.push(reason);\n }\n }\n\n for (const hooks of this.lifecycleParticipants) {\n try { hooks.onRelease?.(); await hooks.drain(); } catch (e) { shutdownErrors.push(e instanceof Error ? e : new Error(\"Lifecycle cleanup failed\")); }\n }\n for (const proxy of this.unsApiProxies as { stop(): Promise<void> }[]) {\n try { await proxy.stop(); } catch (e) { shutdownErrors.push(e instanceof Error ? e : new Error(\"API cleanup failed\")); }\n }\n const proxyStopResults = await Promise.allSettled(this.unsMqttProxies.map((proxy) => proxy.stop(options)));\n for (const result of proxyStopResults) {\n if (result.status === \"rejected\") {\n const reason = result.reason instanceof Error ? result.reason : new Error(String(result.reason));\n logger.error(`${this.processName} - Error stopping UNS MQTT proxy: ${reason.message}`);\n shutdownErrors.push(reason);\n }\n }\n\n try {\n if (typeof this.processMqttProxy.stop === \"function\") {\n await this.processMqttProxy.stop();\n }\n } catch (e: any) {\n const reason = e instanceof Error ? e : new Error(String(e));\n logger.error(`${this.processName} - Error stopping MQTT proxy: ${reason.message}`);\n shutdownErrors.push(reason);\n }\n\n if (shutdownErrors.length > 0) {\n throw new AggregateError(shutdownErrors, `${this.processName} - Shutdown completed with errors.`);\n }\n\n if (this.migrationDrainHandler) {\n const registry = globalThis as unknown as Record<symbol, unknown>;\n if (registry[MQTT_DRAIN_HANDLER] === this.migrationDrainHandler) delete registry[MQTT_DRAIN_HANDLER];\n process.channel?.unref();\n }\n logger.info(`${this.processName} - Shutdown complete.`);\n }\n}\n\ninterface UnsProxyProcess {}\n\nexport default UnsProxyProcess;\nexport type { UnsServiceMetadata, UnsServiceMetadataInput };\nexport { UnsProxyProcess };\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uns-kit/core",
3
- "version": "3.0.36",
3
+ "version": "3.0.37",
4
4
  "description": "Core utilities and runtime building blocks for UNS-based realtime transformers.",
5
5
  "type": "module",
6
6
  "license": "MIT",