@kemu-io/hs 0.4.52 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/cjs/service.d.ts CHANGED
@@ -171,6 +171,9 @@ export type TargetOutput = {
171
171
  /** id of the variant that defined the output */
172
172
  variantId?: string;
173
173
  };
174
+ export type ValidEventContextValue = string | number | boolean | null | ValidEventContextValue[] | {
175
+ [key: string]: ValidEventContextValue;
176
+ };
174
177
  export type WidgetType = string;
175
178
  export type SerializableWidgetInfo<T> = {
176
179
  /** the id of the current widget in the recipe */
@@ -212,6 +215,26 @@ export type WidgetContext<T extends WidgetState = WidgetState> = SerializableWid
212
215
  * @param finalState is the new state of the widget after the event is processed.
213
216
  */
214
217
  setOutputs: (outputs: TargetOutput[], finalState?: T) => Promise<void>;
218
+ /**
219
+ * Sends the given value to the next widget attached to the given ports
220
+ * with a context that can be used by the next widget to process the data.
221
+ * @param config the configuration of the output to send.
222
+ */
223
+ setOutputsWithContext: (config: {
224
+ /** A list of outputs to send data to. The order in which the outputs are defined
225
+ * is the order in which the data will be sent.
226
+ */
227
+ outputs: TargetOutput[];
228
+ /**
229
+ * The new state of the widget after the event is processed.
230
+ */
231
+ finalState?: T;
232
+ /**
233
+ * The event context to use when sending the outputs.
234
+ * This will be available to any child widget down the line that is a variant of the current widget.
235
+ */
236
+ eventContext?: ValidEventContextValue;
237
+ }) => Promise<void>;
215
238
  };
216
239
  export type PortEventInfo = {
217
240
  /** the unique name of the port */
@@ -241,12 +264,16 @@ export type ParentEventHandlerEvent<T extends WidgetState = WidgetState> = {
241
264
  target: PortEventInfo;
242
265
  targetVariantId?: string;
243
266
  recipeId: string;
267
+ /**
268
+ * A context previously set by a parent widget of the same type.
269
+ */
270
+ eventContext?: ValidEventContextValue;
244
271
  /** when data.value is binary (ImageData, etc) */
245
272
  /** the current state of the widget at the time of invocation */
246
273
  currentState: T;
247
274
  config?: RIExecuteConfig;
248
275
  };
249
- export type ServiceParentEvent<WS extends WidgetState = WidgetState> = Pick<ParentEventHandlerEvent<WS>, "data" | "source" | "target">;
276
+ export type ServiceParentEvent<WS extends WidgetState = WidgetState> = Pick<ParentEventHandlerEvent<WS>, "data" | "source" | "target" | "eventContext">;
250
277
  export type ServiceParentEventHandler<T extends WidgetState = WidgetState> = (event: ServiceParentEvent<T>, context: WidgetContext<T>) => Promise<void>;
251
278
  /**
252
279
  * Handles custom ui events. Any returned value will be passed back to the caller.
@@ -362,8 +389,37 @@ export type KemuService<T extends Record<string, any> = Record<string, any>> = {
362
389
  * The data type and port name MUST match the type defined in the widget manifest's output ports.
363
390
  * @param variantId the id of the variant to broadcast the data to. If not provided the data
364
391
  * is assumed to be broadcast to the default service instance.
392
+ *
393
+ * @deprecated Use `broadcastEvent` instead.
365
394
  */
366
395
  broadcast: (outputs: TargetOutput[], variantId?: string) => Promise<void>;
396
+ /**
397
+ * Emits data to all the given ports to any widget service that is connected to the Kemu Hub
398
+ * and subscribed to events from this service.
399
+ *
400
+ * IMPORTANT: You must set `eventEmitter` to `true` in the manifest file to use this method.
401
+ *
402
+ * @param config the configuration of the broadcast event.
403
+ */
404
+ broadcastEvent: (config: {
405
+ /**
406
+ * A list of outputs to send data to. The order in which the outputs are defined
407
+ * is the order in which the data will be sent.
408
+ * The data type and port name MUST match the type defined in the widget manifest's output ports.
409
+ */
410
+ outputs: TargetOutput[];
411
+ /**
412
+ * The id of the variant to broadcast the data to. If not provided the data
413
+ * is assumed to be broadcast to the default service instance.
414
+ */
415
+ variantId?: string;
416
+ /**
417
+ * Custom context for this event. When this event reaches widget variant
418
+ * of the same widget type, this context will be provided to the widget even
419
+ * if the event data has fundamentally changed.
420
+ */
421
+ eventContext?: ValidEventContextValue;
422
+ }) => Promise<void>;
367
423
  /**
368
424
  * Registers the path to a file or folder the recipe depends on. When the recipe is exported,
369
425
  * the dependency will be included in the generated package.
package/cjs/service.js CHANGED
@@ -1 +1 @@
1
- "use strict";var e=require("path"),t=require("node-ipc"),r=require("debug"),n=require("fs/promises"),o=require("minimist");function a(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}var i,s={},c={},d={};var u,l={},f={},g={},m={},p={};var y,S={};var v,b={};var h,I={};var L,w={};var P,H,A,K={};function B(){return H||(H=1,e=m,d=m&&m.__createBinding||(Object.create?function(e,t,r,n){void 0===n&&(n=r);var o=Object.getOwnPropertyDescriptor(t,r);o&&!("get"in o?!t.__esModule:o.writable||o.configurable)||(o={enumerable:!0,get:function(){return t[r]}}),Object.defineProperty(e,n,o)}:function(e,t,r,n){void 0===n&&(n=r),e[n]=t[r]}),l=m&&m.__exportStar||function(e,t){for(var r in e)"default"===r||Object.prototype.hasOwnProperty.call(t,r)||d(t,e,r)},Object.defineProperty(e,"__esModule",{value:!0}),l((u||(u=1,Object.defineProperty(p,"__esModule",{value:!0}),p.DataTypeStr=p.DataType=p.RecipeType=void 0,function(e){e.Browser="browser",e.Cloud="cloud",e.Desktop="desktop"}(t||(p.RecipeType=t={})),function(e){e[e.Number=0]="Number",e[e.String=1]="String",e[e.ArrayBuffer=2]="ArrayBuffer",e[e.Array=3]="Array",e[e.Boolean=4]="Boolean",e[e.JsonObj=5]="JsonObj",e[e.Anything=6]="Anything",e[e.ImageData=7]="ImageData",e[e.AudioBuffer=8]="AudioBuffer",e[e.Rect=9]="Rect",e[e.Point=10]="Point",e[e.ImageBitmap=11]="ImageBitmap",e[e.BinaryFile=12]="BinaryFile"}(r||(p.DataType=r={})),function(e){e.Number="Number",e.String="String",e.ArrayBuffer="ArrayBuffer",e.Array="Array",e.Boolean="Boolean",e.JsonObj="JsonObj",e.Anything="Anything",e.ImageData="ImageData",e.AudioBuffer="AudioBuffer",e.Rect="Rect",e.Point="Point",e.ImageBitmap="ImageBitmap",e.BinaryFile="BinaryFile"}(n||(p.DataTypeStr=n={}))),p),e),l((y||(y=1,Object.defineProperty(S,"__esModule",{value:!0})),S),e),l((v||(v=1,Object.defineProperty(b,"__esModule",{value:!0})),b),e),l((h||(h=1,Object.defineProperty(I,"__esModule",{value:!0}),I.ProcessorType=void 0,function(e){e.Javascript="js",e.Python="py",e.Executable="exe"}(o||(I.ProcessorType=o={}))),I),e),l((L||(L=1,Object.defineProperty(w,"__esModule",{value:!0}),w.Transport=w.ServiceToServiceFunctions=w.KemuHubFunctions=w.KemuHubCommand=void 0,function(e){e.IpcAcknowledge="iack:",e.SocketAcknowledge="sack:",e.AcknowledgeResponse="ackr:",e.ServicesListChanged="update-services",e.SendManifest="send-manifest",e.BroadcastStart="broadcast-start",e.BroadcastEnd="broadcast-end",e.AssumeSession="assume:"}(a||(w.KemuHubCommand=a={})),function(e){e.GetServices="getServices",e.SubscribeToService="subscribeToService",e.UnsubscribeFromService="unsubscribeFromService",e.GetServiceContents="getServiceContents",e.SocketAckResponse="socketAckResponse",e.ShowSecretsConfigScreen="showSecretsConfigScreen",e.GetMappedSecrets="getMappedSecrets",e.GetSecretContexts="getSecretContexts",e.OnParentEvent="onParentEvent",e.GetDefaultState="getDefaultState",e.BroadcastEvent="broadcastEvent",e.HubBroadcastEvent="hubBroadcastEvent",e.ServiceManifest="serviceManifest",e.GetState="getState",e.SetState="setState",e.SetOutputs="setOutputs",e.UIEvent="uiEvent",e.GetSystemInfo="getSystemInfo",e.InitializeInstance="initializeInstance",e.TerminateInstance="terminateInstance",e.UninstallService="uninstallService",e.ChooseDirectoryDialog="chooseDirectoryDialog",e.ChooseFileDialog="chooseFileDialog",e.GetUniqueId="getUniqueId",e.RebootToInstallUpdate="rebootToInstallUpdate"}(i||(w.KemuHubFunctions=i={})),function(e){e.SetDependencyPath="setDependencyPath",e.GetDependencyPath="getDependencyPath"}(s||(w.ServiceToServiceFunctions=s={})),function(e){e.IPC="ipc",e.WS="ws"}(c||(w.Transport=c={}))),w),e),l((P||(P=1,Object.defineProperty(K,"__esModule",{value:!0})),K),e)),m;var e,t,r,n,o,a,i,s,c,d,l}function C(){if(A)return g;A=1,Object.defineProperty(g,"__esModule",{value:!0}),g.onAssumeSession=g.buildIpcAckResponse=g.isBrowser=g.onSendManifestCommand=g.onEndBroadcastCommand=g.onStartBroadcastCommand=g.onAckResponse=g.onAckRequest=g.buildSocketAckRequest=g.buildIpcAckRequest=g.buildAckResponse=g.safeJsonParse=void 0;const e=B();g.safeJsonParse=e=>{try{return JSON.parse(e)}catch(e){return null}};g.buildAckResponse=t=>`${e.KemuHubCommand.AcknowledgeResponse}${t}`;g.buildIpcAckResponse=(t,r)=>`${e.KemuHubCommand.AcknowledgeResponse}${t}:${r||""}`;g.buildIpcAckRequest=()=>`${e.KemuHubCommand.IpcAcknowledge}`;g.buildSocketAckRequest=t=>`${e.KemuHubCommand.SocketAcknowledge}${t}`;g.onAssumeSession=(t,r)=>{if(t.startsWith(e.KemuHubCommand.AssumeSession)){const n=t.split(e.KemuHubCommand.AssumeSession);return r(parseInt(n[1])),!0}return!1};g.onAckResponse=(t,r)=>{if(t.startsWith(e.KemuHubCommand.AcknowledgeResponse)){const n=t.split(e.KemuHubCommand.AcknowledgeResponse),o=parseInt(n[1]);return r&&r(o),o}return null};g.onAckRequest=(t,r)=>{const n=e.KemuHubCommand.SocketAcknowledge,o=e.KemuHubCommand.IpcAcknowledge,a=t.startsWith(n),i=t.startsWith(o);if(a||i){const e=t.split(a?n:o),i=parseInt(e[1]);return r&&r(i),i}return null};g.onStartBroadcastCommand=(t,r)=>t===e.KemuHubCommand.BroadcastStart&&(r(),!0);g.onEndBroadcastCommand=(t,r)=>t===e.KemuHubCommand.BroadcastEnd&&(r(),!0);g.onSendManifestCommand=(t,r)=>t===e.KemuHubCommand.SendManifest&&(r(),!0);const t="undefined"!=typeof window;return g.isBrowser=t,g}var _,j={};function z(){return _||(_=1,e=j,Object.defineProperty(e,"__esModule",{value:!0}),e.KLCmdHeaderSize=e.KLHeaderSize=e.KLCmdProtocolHeaderSize=e.KLProtocolHeadersSize=void 0,e.KLProtocolHeadersSize={protocolPrefix:4,protocolVersion:1,jsonLength:4,binaryLength:4,fromServiceId:4,toServiceId:4,sentAt:8},e.KLCmdProtocolHeaderSize={protocolPrefix:4,txtLength:4},e.KLHeaderSize=Object.values(e.KLProtocolHeadersSize).reduce(((e,t)=>e+t),0),e.KLCmdHeaderSize=Object.values(e.KLCmdProtocolHeaderSize).reduce(((e,t)=>e+t),0)),j;var e}var U,E={};function k(){if(U)return E;U=1,Object.defineProperty(E,"__esModule",{value:!0}),E.setNestedProperty=E.decodeMap=E.isSupportedBinaryType=E.getEncodedMap=void 0;const e=["width","height","colorSpace"],t=e=>{const t="undefined"!=typeof Buffer&&e instanceof Buffer,r=e instanceof ArrayBuffer,n=e instanceof Uint8ClampedArray,o=e instanceof Uint8Array,a=e instanceof Int8Array;return t?"Buffer":r?"ArrayBuffer":n?"Uint8ClampedArray":o?"Uint8Array":a?"Int8Array":null};E.isSupportedBinaryType=t;E.getEncodedMap=(r,n)=>{const o={},a=[];let i=0,s=Array.isArray(r)?[]:{};const c=(r,s)=>{const d=t(r);if(!d){if(Array.isArray(r)){const e=[];for(let t=0;t<r.length;t++)e[t]=c(r[t],`${s}[${t}]`);return e}if("object"==typeof r){const t={},n=(e=>{const t=e instanceof Int16Array,r=e instanceof Uint16Array,n=e instanceof Int32Array,o=e instanceof Uint32Array,a=e instanceof Float32Array,i=e instanceof Float64Array,s=e instanceof BigInt64Array,c=e instanceof BigUint64Array;return t?"Int16Array":r?"Uint16Array":n?"Int32Array":o?"Uint32Array":a?"Float32Array":i?"Float64Array":s?"BigInt64Array":c?"BigUint64Array":null})(r);if(n)throw new Error(`Unsupported binary type [${n}] at path "${s}"`);for(const n in r)r.hasOwnProperty(n)||e.includes(n)||console.warn(`Allowing inherited property: ${n} from path: ${s}`),t[n]=c(r[n],`${s.length?`${s}.`:""}${n}`);return t}return r}o[s]={index:i,length:r.byteLength,binaryType:d},"Buffer"===n?a.push(Buffer.from(r)):"ArrayBuffer"===d?a.push(r):a.push(r.buffer),i+=r.byteLength};s=c(r,"");let d=null;if(a.length>1)if("ArrayBuffer"===n){const e=a.reduce(((e,t)=>e+t.byteLength),0),t=new Uint8Array(e);let r=0;for(let e=0;e<a.length;e++)t.set(new Uint8Array(a[e]),r),r+=a[e].byteLength;d=t.buffer}else{d=Buffer.concat(a)}else 1===a.length&&(d=a[0]);return d?{map:o,combinedData:d,sourceCopy:s}:null};const r=(e,t,r,n)=>{const o=t.match(/(\[\d+\])|([^[\].]+)/g)||[];let a=e;for(let e=0;e<o.length;e++){let t=o[e];const i=t.startsWith("[")&&t.endsWith("]"),s=e===o.length-1;if(i){t=t.slice(1,-1);const i=parseInt(t,10);if(!Array.isArray(a))throw new Error(`Expected an array at key "${o.slice(0,e).join(".")}" but found an object.`);s?n?a.splice(i,1):a[i]=r:(a[i]||(a[i]=o[e+1].startsWith("[")?[]:{}),a=a[i])}else s?n?delete a[t]:a[t]=r:(a[t]||(a[t]=o[e+1].startsWith("[")?[]:{}),a=a[t])}return e};E.setNestedProperty=r;return E.decodeMap=(e,t,n)=>{const o="undefined"!=typeof Buffer,a=t instanceof Uint8Array;for(const i in n)if(n.hasOwnProperty(i)){const{index:s,length:c,binaryType:d}=n[i];let u=null;if(o&&t instanceof Buffer)switch(d){case"Buffer":u=t.subarray(s,s+c);break;case"ArrayBuffer":u=t.buffer.slice(t.byteOffset,t.byteOffset+t.byteLength).slice(s,s+c);break;case"Uint8Array":u=new Uint8Array(t.subarray(s,s+c));break;case"Uint8ClampedArray":u=new Uint8ClampedArray(t.subarray(s,s+c));break;case"Int8Array":u=new Int8Array(t.subarray(s,s+c))}else if(t instanceof ArrayBuffer||t instanceof Uint8Array)switch(d){case"Buffer":if(o){u=Buffer.from(t.slice(s,s+c));break}case"ArrayBuffer":u=a?t.buffer.slice(t.byteOffset,t.byteOffset+t.byteLength).slice(s,s+c):t.slice(s,s+c);break;case"Uint8Array":u=a?t.slice(s,s+c):new Uint8Array(t.slice(s,s+c));break;case"Uint8ClampedArray":u=new Uint8ClampedArray(t.slice(s,s+c));break;case"Int8Array":u=new Int8Array(t.slice(s,s+c))}u&&r(e,i,u)}return e},E}var D,M,O={};function R(){if(D)return O;D=1;var e=O&&O.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(O,"__esModule",{value:!0}),O.createLogger=void 0;const t=e(r);return O.createLogger=e=>(0,t.default)(e),O}function T(){if(M)return f;M=1,Object.defineProperty(f,"__esModule",{value:!0});const e=C(),t=z(),r=k(),n=R(),o="KMSG",a="KCMD",i=(0,n.createLogger)("klProtocol");return f.default={encode:(e,n,a)=>{const i={json:e.json},s=(0,r.getEncodedMap)(i.json,"Buffer"),c=s?.combinedData;s&&(i.jsonBinaryMap=s.map,i.json=s.sourceCopy);const d=c?c.byteLength:0,u=JSON.stringify(i),l=Buffer.from(u),f=l.byteLength,g=t.KLProtocolHeadersSize.protocolPrefix+t.KLProtocolHeadersSize.protocolVersion+t.KLProtocolHeadersSize.jsonLength+t.KLProtocolHeadersSize.binaryLength+t.KLProtocolHeadersSize.fromServiceId+t.KLProtocolHeadersSize.toServiceId+t.KLProtocolHeadersSize.sentAt+f+d,m=Buffer.alloc(g),p=Date.now();let y=0;return m.write(o,y),y+=t.KLProtocolHeadersSize.protocolPrefix,m.writeUInt8(1,y),y+=t.KLProtocolHeadersSize.protocolVersion,m.writeUInt32LE(f,y),y+=t.KLProtocolHeadersSize.jsonLength,m.writeUInt32LE(d,y),y+=t.KLProtocolHeadersSize.binaryLength,m.writeUInt32LE(n,y),y+=t.KLProtocolHeadersSize.fromServiceId,m.writeUInt32LE(a,y),y+=t.KLProtocolHeadersSize.toServiceId,m.writeBigInt64LE(BigInt(p),y),y+=t.KLProtocolHeadersSize.sentAt,l.copy(m,y),y+=f,c&&d&&c.copy(m,y),m},decodeHeader:e=>{let r=0;const n=e.toString("utf-8",r,t.KLProtocolHeadersSize.protocolPrefix);if(r+=t.KLProtocolHeadersSize.protocolPrefix,n!==o)return null;if(e.byteLength<t.KLHeaderSize)return i(`Received a Partial Header with ${e.byteLength} bytes. Waiting for more data.`),{partialHeader:!0,remaining:null};const a=e.readUInt8(r);r+=t.KLProtocolHeadersSize.protocolVersion;const s=e.readUInt32LE(r);r+=t.KLProtocolHeadersSize.jsonLength;const c=e.readUInt32LE(r);r+=t.KLProtocolHeadersSize.binaryLength;const d=e.readUInt32LE(r);r+=t.KLProtocolHeadersSize.fromServiceId;const u=e.readUInt32LE(r);r+=t.KLProtocolHeadersSize.toServiceId;const l=e.readBigInt64LE(r);r+=t.KLProtocolHeadersSize.sentAt;const f=s+c,g=e.subarray(r,r+f),m=e.subarray(0,t.KLHeaderSize);let p=null;return e.byteLength-t.KLHeaderSize-s-c>0&&(p=e.subarray(t.KLHeaderSize+s+c)),{header:{protocolVersion:a,jsonLength:s,binaryLength:c,fromServiceId:d,toServiceId:u,sentAt:new Date(Number(l)),packages:[g],headerPackage:m},remaining:p}},decodeFullKlMessage:n=>{const o=Buffer.concat(n.packages),a=o.subarray(0,n.jsonLength).toString(),s=o.subarray(n.jsonLength,n.jsonLength+n.binaryLength),c=(0,e.safeJsonParse)(a);if(!c?.json)return i("Invalid JSON in KL message"),null;c.jsonBinaryMap&&s.byteLength&&(0,r.decodeMap)(c.json,s,c.jsonBinaryMap);const d=Buffer.concat([n.headerPackage,o]);let u=d,l=null;const f=t.KLHeaderSize+n.jsonLength+n.binaryLength;return d.byteLength>f&&(l=d.subarray(f),u=d.subarray(0,f)),{message:{json:c.json,rawMessage:u},remaining:l}},patchEncodedHeader:(e,r)=>{if(null==r.fromServiceId&&void 0===r.toServiceId)return e;if(e.byteLength<t.KLHeaderSize)return i("Invalid Header Size"),e;let n=0;return n+=t.KLProtocolHeadersSize.protocolPrefix,n+=t.KLProtocolHeadersSize.protocolVersion,n+=t.KLProtocolHeadersSize.jsonLength,n+=t.KLProtocolHeadersSize.binaryLength,void 0!==r.fromServiceId&&e.writeUInt32LE(r.fromServiceId,n),n+=t.KLProtocolHeadersSize.fromServiceId,void 0!==r.toServiceId&&e.writeUInt32LE(r.toServiceId,n),e},encodeCommand:e=>{let r=0;const n=Buffer.from(e),o=n.byteLength,i=t.KLCmdHeaderSize+o,s=Buffer.alloc(i);return s.write(a,r),r+=t.KLCmdProtocolHeaderSize.protocolPrefix,s.writeUint32LE(o,r),r+=t.KLCmdProtocolHeaderSize.txtLength,n.copy(s,r),s},decodeCommand:e=>{let r=0;if(e.byteLength<t.KLCmdHeaderSize)return{command:null};const n=e.toString("utf-8",r,t.KLCmdProtocolHeaderSize.protocolPrefix);if(r+=t.KLCmdProtocolHeaderSize.protocolPrefix,n!==a)return{command:null};const o=e.readUInt32LE(r);r+=t.KLCmdProtocolHeaderSize.txtLength;const i=e.toString("utf-8",r,r+o),s=e.byteLength-t.KLCmdHeaderSize-o;let c=null;s>0&&(c=e.subarray(t.KLCmdHeaderSize+o));let d=0;return s<0&&(d=Math.abs(s)),{command:i,remainingData:c,missing:d}}},f}var $,x,F={};function N(){if($)return F;$=1,Object.defineProperty(F,"__esModule",{value:!0});const e=z(),t=R(),r=k(),n=C(),o="KMSG",a="KCMD",i=(0,t.createLogger)("klProtocol"),s=new TextEncoder;return F.default={encode:(t,n,a)=>{const i={json:t.json},c=(0,r.getEncodedMap)(t.json,"ArrayBuffer"),d=c?.combinedData;c&&(i.jsonBinaryMap=c.map,i.json=c.sourceCopy);const u=d?d.byteLength:0,l=JSON.stringify(i),f=s.encode(l),g=f.byteLength,m=e.KLProtocolHeadersSize.protocolPrefix+e.KLProtocolHeadersSize.protocolVersion+e.KLProtocolHeadersSize.jsonLength+e.KLProtocolHeadersSize.binaryLength+e.KLProtocolHeadersSize.fromServiceId+e.KLProtocolHeadersSize.toServiceId+e.KLProtocolHeadersSize.sentAt+g+u,p=new ArrayBuffer(m),y=new DataView(p),S=new Uint8Array(p),v=Date.now();let b=0;for(let e=0;e<4;++e)S[b++]=o.charCodeAt(e);return y.setUint8(b,1),b+=e.KLProtocolHeadersSize.protocolVersion,y.setUint32(b,g,!0),b+=e.KLProtocolHeadersSize.jsonLength,y.setUint32(b,u,!0),b+=e.KLProtocolHeadersSize.binaryLength,y.setUint32(b,n,!0),b+=e.KLProtocolHeadersSize.fromServiceId,y.setUint32(b,a,!0),b+=e.KLProtocolHeadersSize.toServiceId,y.setBigInt64(b,BigInt(v),!0),b+=e.KLProtocolHeadersSize.sentAt,S.set(f,b),b+=g,d&&u&&S.set(new Uint8Array(d),b),p},decodeHeader:t=>{const r=new DataView(t);let n=0,a="";for(let t=0;t<e.KLProtocolHeadersSize.protocolPrefix;++t)a+=String.fromCharCode(r.getUint8(n++));if(a!==o)return null;if(t.byteLength<e.KLHeaderSize)return i.log(`Received a Partial Header with ${t.byteLength} bytes. Waiting for more data.`),{partialHeader:!0,remaining:null};const s=r.getUint8(n);n+=e.KLProtocolHeadersSize.protocolVersion;const c=r.getUint32(n,!0);n+=e.KLProtocolHeadersSize.jsonLength;const d=r.getUint32(n,!0);n+=e.KLProtocolHeadersSize.binaryLength;const u=r.getUint32(n,!0);n+=e.KLProtocolHeadersSize.fromServiceId;const l=r.getUint32(n,!0);n+=e.KLProtocolHeadersSize.toServiceId;const f=r.getBigInt64(n,!0);n+=e.KLProtocolHeadersSize.sentAt;const g=c+d,m=t.slice(n,n+g),p=new Uint8Array(t,0,e.KLHeaderSize);let y=null;if(t.byteLength-e.KLHeaderSize-c-d>0){y=new Uint8Array(t,e.KLHeaderSize+c+d).slice().buffer}return{header:{protocolVersion:s,jsonLength:c,binaryLength:d,fromServiceId:u,toServiceId:l,sentAt:new Date(Number(f)),packages:[m],headerPackage:p.slice().buffer},remaining:y}},decodeFullKlMessage:t=>{const o=t.packages.reduce(((e,t)=>e+t.byteLength),0),a=new Uint8Array(o);let s,c=0;for(const e of t.packages)s=new Uint8Array(e),a.set(s,c),c+=s.byteLength;const d=(new TextDecoder).decode(a.subarray(0,t.jsonLength)),u=a.subarray(t.jsonLength,t.jsonLength+t.binaryLength),l=(0,n.safeJsonParse)(d);if(!l?.json)return i.log("Invalid JSON in KL message"),null;l.jsonBinaryMap&&u.byteLength&&(0,r.decodeMap)(l.json,u,l.jsonBinaryMap);const f=new Uint8Array(t.headerPackage.byteLength+a.byteLength);f.set(new Uint8Array(t.headerPackage),0),f.set(a,t.headerPackage.byteLength);let g=f,m=null;const p=e.KLHeaderSize+t.jsonLength+t.binaryLength;return f.byteLength>p&&(m=f.subarray(p),g=f.subarray(0,p)),{message:{json:l.json,...u.length?{binaryData:u.buffer}:{},rawMessage:g.buffer},remaining:m?.buffer??null}},patchEncodedHeader:(t,r)=>{if(null==r.fromServiceId&&void 0===r.toServiceId)return t;if(t.byteLength<e.KLHeaderSize)return i("Invalid Header Size"),t;let n=0;n+=e.KLProtocolHeadersSize.protocolPrefix,n+=e.KLProtocolHeadersSize.protocolVersion,n+=e.KLProtocolHeadersSize.jsonLength,n+=e.KLProtocolHeadersSize.binaryLength;const o=new DataView(t);return void 0!==r.fromServiceId&&o.setUint32(n,r.fromServiceId,!0),n+=e.KLProtocolHeadersSize.fromServiceId,void 0!==r.toServiceId&&o.setUint32(n,r.toServiceId,!0),t},encodeCommand:t=>{let r=0;const n=s.encode(t),o=n.byteLength,i=e.KLCmdHeaderSize+o,c=new ArrayBuffer(i),d=new DataView(c),u=new Uint8Array(c);for(let e=0;e<4;++e)u[r++]=a.charCodeAt(e);return d.setUint32(r,o,!0),r+=e.KLCmdProtocolHeaderSize.txtLength,u.set(n,r),c},decodeCommand:t=>{const r=new DataView(t);let n=0;if(t.byteLength<e.KLCmdHeaderSize)return{command:null};let o="";for(let t=0;t<e.KLCmdProtocolHeaderSize.protocolPrefix;++t)o+=String.fromCharCode(r.getUint8(n++));if(o!==a)return{command:null};const i=r.getUint32(n,!0);n+=e.KLCmdProtocolHeaderSize.txtLength;const s=t.byteLength-e.KLCmdHeaderSize-i,c=new Uint8Array(t,n,Math.min(i,t.byteLength-e.KLCmdHeaderSize)),d=(new TextDecoder).decode(c);let u=null;s>0&&(u=t.slice(e.KLCmdHeaderSize+i));let l=0;return s<0&&(l=Math.abs(s)),{command:d,remainingData:u,missing:l}}},F}function V(){if(x)return l;x=1;var e=l&&l.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(l,"__esModule",{value:!0}),l.createTransmissionManager=void 0;const t=e(T()),r=e(N()),n=(0,R().createLogger)("klTransmissionManager");return l.createTransmissionManager=()=>{const e=(o,a,i,s)=>{let c=a,d=null;const u=o instanceof ArrayBuffer;if(n(`RAW: ${o.toString()}`),!c||c.partialHeaderData){let l;if(u?(l=c?.partialHeaderData?new Uint8Array([...new Uint8Array(c.partialHeaderData),...new Uint8Array(o)]).buffer:o,d=r.default.decodeHeader(l)):(l=c?.partialHeaderData?Buffer.concat([c.partialHeaderData,o]):o,d=t.default.decodeHeader(l)),!d){const{command:o,missing:c,remainingData:d}=u?r.default.decodeCommand(l):t.default.decodeCommand(l);return o?s({command:o,complete:!0,rawMessage:l}):n(c?`ERROR: Missing ${c} bytes to complete the command. This partial command will be aborted.`:`ERROR: Invalid state, message was decoded without a header or partial header data. Discarding ${l.byteLength} bytes`),d?(n(`${d.byteLength} bytes remain after processing command. Re-analyzing...`),e(d,a,i,s)):void 0}if(d.partialHeader)return c={firstPackageAt:Date.now(),partialHeaderData:l},i(c);if(!d.header)return n(`ERROR: Invalid state, message was decoded without a header or partial header data. Discarding ${l.byteLength} bytes`);const f=d.header;c={firstPackageAt:Date.now(),header:{...f,totalBytesReceived:f.packages[0].byteLength,totalBytesExpected:f.binaryLength+f.jsonLength,remaining:d.remaining}},i(c)}else c.header&&c.header.totalBytesReceived<c.header.totalBytesExpected&&(c.header.packages.push(o),c.header.totalBytesReceived+=o.byteLength,i(c));if(c.header&&c.header.totalBytesReceived>=c.header.totalBytesExpected){const o=Date.now()-c.header.sentAt.getTime(),a=Date.now()-c.firstPackageAt;n(`Received ${c.header.totalBytesReceived} of ${c.header.totalBytesExpected} expected in ${o} ms, elapsed since first package: ${a}ms`);const d=u?r.default.decodeFullKlMessage(c.header):t.default.decodeFullKlMessage(c.header),l=c.header.totalBytesReceived,f=c.header.remaining;i(null),d&&s({klMessage:d.message,complete:!0,sourceServiceId:c.header.fromServiceId,targetServiceId:c.header.toServiceId,rawMessage:d.message.rawMessage});let g=f;if(d?.remaining&&(g=u?f?((e,t)=>{const r=e.byteLength+t.byteLength,n=new ArrayBuffer(r),o=new Uint8Array(e),a=new Uint8Array(t),i=new Uint8Array(n);return i.set(o),i.set(a,o.length),n})(f,d.remaining):d.remaining:f?Buffer.concat([f,d.remaining]):d.remaining),g)return n(`${g.byteLength} bytes remaining after processing message with ${l} bytes of data. Re-analyzing...`),e(g,null,i,s)}};return e},l}var G,W,q={};function J(){if(G)return q;G=1;var e=q&&q.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(q,"__esModule",{value:!0});const t=e(T()),r=e(N()),n=C();let o=t.default;return n.isBrowser&&(o=r.default),q.default=o,q}function Q(){if(W)return c;W=1;var e=c&&c.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(c,"__esModule",{value:!0});const r=e(t),n=e((i||(i=1,Object.defineProperty(d,"__esModule",{value:!0}),d.default={id:"widgets",retry:1500,silent:!0,rawBuffer:!0,appspace:"kemu.",encoding:"hex"}),d)),o=V(),a=R(),s=e(J());let u,l,f,g,m=null;const p=(0,o.createTransmissionManager)(),y=(0,a.createLogger)("ipcClient"),S=e=>{const t=n.default.id;r.default.of[t].emit(e)};return c.default={connect:e=>{n.default.id=e?.id||n.default.id,n.default.appspace=e?.appSpace||n.default.appspace,r.default.config={...r.default.config,...n.default};const t=n.default.id;r.default.connectTo(t,(()=>{r.default.of[t].on("connect",(()=>{y("Connected to server"),m=null,l&&l()})),r.default.of[t].on("data",(e=>{p(e,m,(e=>m=e),(e=>{if(e.complete)return e.command?(y(`Received command: ${e.command}`),void(u&&u(e.command))):void(e.klMessage&&f&&f({send:S,transmission:{sourceServiceId:e.sourceServiceId??-1,targetServiceId:e.targetServiceId??-1,rawMessage:e.rawMessage},json:e.klMessage.json}))}))})),r.default.of[t].on("disconnect",(()=>{y(`Disconnected from ${t}`),m=null,g&&g()}))}))},sendCommand:e=>{const t=n.default.id,o=s.default.encodeCommand(e);r.default.of[t].emit(o)},sendBuffer:S,onCommand:e=>u=e,onMessageReceived:e=>f=e,onClientConnected:e=>l=e,onClientDisconnected:e=>g=e},c}var X,Y,Z={},ee={};function te(){return Y||(Y=1,function(e){var t=Z&&Z.__createBinding||(Object.create?function(e,t,r,n){void 0===n&&(n=r);var o=Object.getOwnPropertyDescriptor(t,r);o&&!("get"in o?!t.__esModule:o.writable||o.configurable)||(o={enumerable:!0,get:function(){return t[r]}}),Object.defineProperty(e,n,o)}:function(e,t,r,n){void 0===n&&(n=r),e[n]=t[r]}),r=Z&&Z.__exportStar||function(e,r){for(var n in e)"default"===n||Object.prototype.hasOwnProperty.call(r,n)||t(r,e,n)},n=Z&&Z.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(e,"__esModule",{value:!0});const o=n(J()),a=C();var i;r((X||(X=1,Object.defineProperty(ee,"__esModule",{value:!0}),ee.RemoveInvokeError=void 0,function(e){e.FunctionNotFound="FNC_NOT_FOUND",e.ParentEventCallbackError="PARENT_EVENT_CALLBACK_ERROR"}(i||(ee.RemoveInvokeError=i={}))),ee),e);let s=Math.ceil(Date.now()/1e3);e.default=function(e){const t={};let r=console.log;const n={};let i=e||String(Date.now());const c={},d=e=>!c[e],u=(e,t,r,n,i,s)=>{let c=a.isBrowser?new ArrayBuffer(0):Buffer.alloc(0);const u={json:{functionName:e,args:s.success?s.success:[s],messageId:t,type:s.success?"response":"error"}};return d(n)&&(c=o.default.encode(u,r,n)),i(c,{msg:u,sourceServiceId:r,targetServiceId:n})};return{setLogger:e=>{r=e},processMessage:(e,o,a,i)=>{if(!i)return!1;const s=i;if(t[s.messageId]){const e=t[s.messageId];return e&&(clearTimeout(e.timer),e.fulfilled||(e.fulfilled=!0,"response"===s.type?e.resolve(s.args):"error"===s.type&&e.reject(s.args[0])),delete t[s.messageId]),!0}if("execute"!==s.type&&r&&r(`No pending execution found for message id "${s.messageId}"`),"execute"===s.type){const t=n[s.functionName];if(t){const r=e=>{u(s.functionName,s.messageId,a.targetServiceId,a.sourceServiceId,o,e)};t({transport:e,args:s.args,reply:r,messageId:s.messageId,sourceServiceId:a.sourceServiceId,send:o})}else{const e=`Function "${s.functionName}" not found.`;r&&r(e),u(s.functionName,s.messageId,a.targetServiceId,a.sourceServiceId,o,{error:e,errCode:"FNC_NOT_FOUND"})}return!0}return!1},execute:async(e,n,c,u,l,f)=>{if(!c){const e="No send buffer function provided.";throw r&&r(e),e}s+=1;const g=`${i}-${s}-exec-${e.substring(0,10)}`,m={messageId:g,functionName:e,send:c,sourceServiceId:u,targetServiceId:l,args:n||[],fulfilled:!1,resolve:()=>{},reject:()=>{}};m.promise=new Promise(((e,t)=>{m.resolve=e,m.reject=t}));let p=a.isBrowser?new ArrayBuffer(0):Buffer.alloc(0);const y={json:{functionName:e,args:n,messageId:g,type:"execute"}};d(l)&&(p=o.default.encode(y,u,l)),t[g]=m,r&&r(`Calling remote function "${e}" with message id "${g}"`);const S="true"===process.env.NO_INVOKE_TIMEOUT;return f?.async?(m.fulfilled=!0,m.resolve([void 0]),delete t[g]):0===f?.timeout||S||(m.timer=setTimeout((()=>{r&&r(`Remote function ${g} timed out`);const n=t[g];n&&!n.fulfilled&&(n.fulfilled=!0,m.reject(`Function ${e} Timed out`)),delete t[g]}),f?.timeout||3e4)),c(p,{sourceServiceId:u,targetServiceId:l,msg:y}),m.promise},sendResponse:u,registerFunction:(e,t)=>{n[e]=t},getTransportSendFunction:e=>{const r=t[e];return r?r.send:null},setServiceName:e=>{i=e},getPendingExecutions:()=>t,rejectAllPending:e=>{Object.keys(t).forEach((r=>{const n=t[r];n&&!n.fulfilled&&(clearTimeout(n.timer),n.fulfilled=!0,n.reject(e),delete t[r])}))},broadcast:(e,t,n,c)=>{s+=1;const u=`${i}-${s}-multicast-${e.substring(0,10)}`;let l=a.isBrowser?new ArrayBuffer(0):Buffer.alloc(0);const f={json:{functionName:e,args:t,messageId:u,type:"execute"}};let g=d(n[0].serviceId);g&&(l=o.default.encode(f,c,n[0].serviceId));for(let t=0;t<n.length;t++)try{const a=n[t];r&&r(`Broadcasting function "${e}" with message id "${u}" to client [${a.serviceId}]`),0!==t&&(g=d(a.serviceId),g&&(l=o.default.patchEncodedHeader(l,{toServiceId:a.serviceId}))),a.sendFn(l,{msg:f,sourceServiceId:c,targetServiceId:a.serviceId})}catch(e){r&&r(`Error broadcasting to client at index ${t}`)}},disableServiceEncoding:(e,t)=>{c[e]=t}}}}(Z)),Z}var re,ne={};var oe,ae,ie={};var se=a((ae||(ae=1,function(t){var r=s&&s.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.DataType=t.KemuHubServiceId=t.createImageDataLike=void 0;const a=r(e),i=r(Q()),c=r(te()),d=B();Object.defineProperty(t,"DataType",{enumerable:!0,get:function(){return d.DataType}});const u=R(),l=C(),f=function(){if(re)return ne;re=1,Object.defineProperty(ne,"__esModule",{value:!0}),ne.preProcessManifest=ne.portStrToWidgetPort=ne.createImageDataLike=void 0;const e=B();return ne.createImageDataLike=(t,r,n,o="srgb")=>{let a;return a=t instanceof Uint8ClampedArray?t:new Uint8ClampedArray(t),{data:a,width:r,height:n,colorSpace:o,_kemuType:e.DataType.ImageData}},ne.portStrToWidgetPort=t=>({...t,type:e.DataType[t.type]}),ne.preProcessManifest=(e,t,r)=>({...e,path:t,...e.widgetUI&&r?.widgetUIContents?{widgetUIContents:r.widgetUIContents}:{}}),ne}();Object.defineProperty(t,"createImageDataLike",{enumerable:!0,get:function(){return f.createImageDataLike}});const g=(oe||(oe=1,Object.defineProperty(ie,"__esModule",{value:!0}),ie.KemuHubServiceId=void 0,ie.KemuHubServiceId=0),ie);Object.defineProperty(t,"KemuHubServiceId",{enumerable:!0,get:function(){return g.KemuHubServiceId}});const m=n,p=r(o),y=(0,u.createLogger)("kemuWidgetService"),S=(0,p.default)(process.argv.slice(2));t.default=function(e){const t={},r=process.env.KEMU_WIDGET_SESSION_ID;let n,o,s,u=!1;const p={};let v,b,h,I,L,w,P,H=null;const A=new c.default;A.setLogger(y),t.start=async(t,c)=>{const g=t||a.default.resolve(a.default.dirname(process.argv[1]),"manifest.json");s=a.default.dirname(g);const p=await(0,m.readFile)(g,"utf-8"),v=(0,l.safeJsonParse)(p);if(!v)throw new Error("Error parsing manifest file.");let b;if(v.inputs||(v.inputs=[]),v.outputs||(v.outputs=[]),v.widgetUI)try{b=await(0,m.readFile)(a.default.join(s,"widgetUI.js"))}catch(e){y(`Error loading widgetUI file ${v.name}: ${e}`)}if(v.svgIcon)try{const e=await(0,m.readFile)(a.default.join(s,v.svgIcon),"utf-8");v.svgIcon=e}catch(e){y(`Error loading icon for service ${v.name}: ${e}`)}o=(0,f.preProcessManifest)(v,s,{widgetUIContents:b}),u=o.name.startsWith("test."),o.path=s,o.internal=S.internal||!1,u?y("Starting Kemu Service in Dev mode"):((e=>{const t=e||S.sessionId||r;if(!t)throw new Error("Missing sessionId. Expected service to be launched with a sessionId as first argument, or the KEMU_WIDGET_SESSION_ID environment variable to be set.");n=parseInt(String(t))})(c),y(`Starting Kemu Service with session id: ${n}`)),A.setServiceName(`${o.name}_${o.version}`),i.default.onCommand(K),i.default.onMessageReceived((({json:e,transmission:t})=>A.processMessage(d.Transport.IPC,i.default.sendBuffer,t,e))),A.registerFunction(d.KemuHubFunctions.OnParentEvent,C),A.registerFunction(d.KemuHubFunctions.GetDefaultState,B),A.registerFunction(d.KemuHubFunctions.UIEvent,z),A.registerFunction(d.KemuHubFunctions.InitializeInstance,_),A.registerFunction(d.KemuHubFunctions.TerminateInstance,j),i.default.onClientConnected((()=>{P&&P()})),i.default.onClientDisconnected((()=>{u&&(n=void 0)})),i.default.connect({appSpace:S.ipcSpace||e?.ipc?.appSpace,id:S.ipcId||e?.ipc?.id})};const K=e=>{(0,l.onAckRequest)(e,(e=>{i.default.sendCommand((0,l.buildIpcAckResponse)(e,n||void 0)),!n&&u&&(y("Dev mode detected, assuming service session id from ack request:",e),n=e)})),(0,l.onStartBroadcastCommand)(e,(()=>{h&&h()})),(0,l.onEndBroadcastCommand)(e,(()=>{I&&I()})),(0,l.onSendManifestCommand)(e,(()=>{y("Sending manifest to hub"),n?A.execute(d.KemuHubFunctions.ServiceManifest,[{...o,devMode:u}],i.default.sendBuffer,n,g.KemuHubServiceId,{async:!0}):y("Service session id is not set. Cannot send manifest.")})),(0,l.onAssumeSession)(e,(e=>{n=e,y(`Assumed session id ${e}`)}))},B=async e=>{if(b){const t=await b();return e.reply({success:[t]})}return e.reply({success:[{}]})},C=async e=>{if(v){const t=e.args[0],{source:r,target:o,data:a,recipeId:s,currentState:c,targetVariantId:u}=t;if(!n)return void y("Service session id is not set. Cannot process parent event.");if(!r||!o||!a)return e.reply({error:"Invalid arguments, expected [source, target, data, context]"});const l=i.default.sendBuffer,f={currentState:c,type:o.widgetType,widgetId:o.widgetId,variantId:u,recipeId:s,getState:async()=>{const t=[o.widgetId,s];return A.execute(d.KemuHubFunctions.GetState,t,l,n,e.sourceServiceId)},setState:async t=>{const r={widgetId:o.widgetId,variantId:u,recipeId:s,newState:t};return A.execute(d.KemuHubFunctions.SetState,[r],l,n,e.sourceServiceId)},setOutputs:async(t,r)=>{const a={widgetId:o.widgetId,recipeId:s,outputs:t,finalState:r};await A.execute(d.KemuHubFunctions.SetOutputs,[a],l,n,e.sourceServiceId,{timeout:0})}};y(`Invoking user-defined onParentEvent callback for event id "${e.messageId}"`),await v({data:a,source:r,target:o},f).then((()=>{y(`Replying SUCCESS to event id "${e.messageId}"`),e.reply({success:[]})})).catch((t=>{const r="string"==typeof t?t:t.message||t;y(`Error invoking onParentEvent callback: ${r}`),e.reply({error:r,errCode:"PARENT_EVENT_CALLBACK_ERROR"})}))}},_=async e=>{const[{currentState:t,recipeId:r,widgetId:n,variantId:o,recipeType:a,currentDependencies:i}]=e.args;if(p[n]={currentRecipeId:r,variantId:o,currentSourceServiceId:e.sourceServiceId},L){const s={currentState:t,recipeId:r,widgetId:n,variantId:o,recipeType:a,currentDependencies:i||{}},c=await L(s);e.reply({success:[c]})}else e.reply({error:"Not implemented",errCode:"FNC_NOT_FOUND"})},j=async e=>{if(w){const[{currentState:t,recipeId:r,widgetId:n,variantId:o}]=e.args,a={currentState:t,recipeId:r,widgetId:n,variantId:o};await w(a),delete p[n]}e.reply({success:[]})},z=async e=>{if(H)try{const t=await H.apply(void 0,e.args);return e.reply({success:[t]})}catch(t){const r="string"==typeof t?t:JSON.stringify(t);return y(`Error invoking UI Event handler: ${r}`),e.reply({error:r})}e.reply({error:"UI Events are not supported in this service."})};return t.broadcast=async(e,t)=>{if(!o.eventEmitter)throw new Error("This service does not support broadcasting events. Please set `eventEmitter` to true in your manifest file.");if(!n)return void y("Service session id is not set. Cannot broadcast event.");const r=[{outputs:e,variantId:t}];await A.execute(d.KemuHubFunctions.BroadcastEvent,r,i.default.sendBuffer,n,g.KemuHubServiceId,{async:!0})},t.addDependencyPath=async(e,t,r)=>{if(!n)throw new Error("Not yet registered with the Hub");const o=p[r];if(!o.currentSourceServiceId||!o.currentRecipeId)throw new Error("Cannot invoke this method before initialization");const a={key:e,path:t,recipeId:o.currentRecipeId,widgetId:r};y(`Adding dependency path for key "${e}" with path "${t}"`),await A.execute(d.ServiceToServiceFunctions.SetDependencyPath,[a],i.default.sendBuffer,n,o.currentSourceServiceId)},t.getDependencyPath=async(e,t)=>{if(!n)throw new Error("Not yet registered with the Hub");const r=p[t];if(!r.currentSourceServiceId||!r.currentRecipeId)throw new Error("Cannot invoke this method before initialization");y("Getting dependency path for key:",e);const o={key:e,recipeId:r.currentRecipeId,widgetId:t},[a]=await A.execute(d.ServiceToServiceFunctions.GetDependencyPath,[o],i.default.sendBuffer,n,r.currentSourceServiceId);return y("Dependency path response:",a),a},t.getUniqueId=async()=>{if(!n)throw new Error("Not yet registered with the Hub");const[e]=await A.execute(d.KemuHubFunctions.GetUniqueId,[],i.default.sendBuffer,n,g.KemuHubServiceId);return e},t.resolveRuntimeDependencyPath=e=>{if(!S.recipePath)throw new Error("Cannot resolve runtime dependency without a recipe path. Missing [--recipePath] argument.");return a.default.resolve(S.recipePath,e)},t.onGetDefaultState=e=>{b=e},t.onParentEvent=e=>{v=e},t.onTerminate=e=>{w=e},t.onInitialize=e=>{L=e},t.onConnected=e=>{P=e},t.onStartBroadcast=e=>{h=e},t.onStopBroadcast=e=>{I=e},t.onUIEvent=e=>{H=e},S.internal&&(t.executeHubFunction=async(e,t,r)=>{if(n)return A.execute(e,t,i.default.sendBuffer,n,g.KemuHubServiceId,r);y("Service session id is not set. Cannot execute hub function.")}),t._getRemoteInvoker=()=>A,t}}(s)),s));module.exports=se;
1
+ "use strict";var e=require("path"),t=require("node-ipc"),r=require("debug"),n=require("fs/promises"),o=require("minimist");function a(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}var i,s={},c={},d={};var u,l={},f={},g={},m={},p={};var y,S={};var v,b={};var h,I={};var L,w={};var P,H,A,K={};function C(){return H||(H=1,e=m,d=m&&m.__createBinding||(Object.create?function(e,t,r,n){void 0===n&&(n=r);var o=Object.getOwnPropertyDescriptor(t,r);o&&!("get"in o?!t.__esModule:o.writable||o.configurable)||(o={enumerable:!0,get:function(){return t[r]}}),Object.defineProperty(e,n,o)}:function(e,t,r,n){void 0===n&&(n=r),e[n]=t[r]}),l=m&&m.__exportStar||function(e,t){for(var r in e)"default"===r||Object.prototype.hasOwnProperty.call(t,r)||d(t,e,r)},Object.defineProperty(e,"__esModule",{value:!0}),l((u||(u=1,Object.defineProperty(p,"__esModule",{value:!0}),p.DataTypeStr=p.DataType=p.RecipeType=void 0,function(e){e.Browser="browser",e.Cloud="cloud",e.Desktop="desktop"}(t||(p.RecipeType=t={})),function(e){e[e.Number=0]="Number",e[e.String=1]="String",e[e.ArrayBuffer=2]="ArrayBuffer",e[e.Array=3]="Array",e[e.Boolean=4]="Boolean",e[e.JsonObj=5]="JsonObj",e[e.Anything=6]="Anything",e[e.ImageData=7]="ImageData",e[e.AudioBuffer=8]="AudioBuffer",e[e.Rect=9]="Rect",e[e.Point=10]="Point",e[e.ImageBitmap=11]="ImageBitmap",e[e.BinaryFile=12]="BinaryFile"}(r||(p.DataType=r={})),function(e){e.Number="Number",e.String="String",e.ArrayBuffer="ArrayBuffer",e.Array="Array",e.Boolean="Boolean",e.JsonObj="JsonObj",e.Anything="Anything",e.ImageData="ImageData",e.AudioBuffer="AudioBuffer",e.Rect="Rect",e.Point="Point",e.ImageBitmap="ImageBitmap",e.BinaryFile="BinaryFile"}(n||(p.DataTypeStr=n={}))),p),e),l((y||(y=1,Object.defineProperty(S,"__esModule",{value:!0})),S),e),l((v||(v=1,Object.defineProperty(b,"__esModule",{value:!0})),b),e),l((h||(h=1,Object.defineProperty(I,"__esModule",{value:!0}),I.ProcessorType=void 0,function(e){e.Javascript="js",e.Python="py",e.Executable="exe"}(o||(I.ProcessorType=o={}))),I),e),l((L||(L=1,Object.defineProperty(w,"__esModule",{value:!0}),w.Transport=w.ServiceToServiceFunctions=w.KemuHubFunctions=w.KemuHubCommand=void 0,function(e){e.IpcAcknowledge="iack:",e.SocketAcknowledge="sack:",e.AcknowledgeResponse="ackr:",e.ServicesListChanged="update-services",e.SendManifest="send-manifest",e.BroadcastStart="broadcast-start",e.BroadcastEnd="broadcast-end",e.AssumeSession="assume:"}(a||(w.KemuHubCommand=a={})),function(e){e.GetServices="getServices",e.SubscribeToService="subscribeToService",e.UnsubscribeFromService="unsubscribeFromService",e.GetServiceContents="getServiceContents",e.SocketAckResponse="socketAckResponse",e.ShowSecretsConfigScreen="showSecretsConfigScreen",e.GetMappedSecrets="getMappedSecrets",e.GetSecretContexts="getSecretContexts",e.OnParentEvent="onParentEvent",e.GetDefaultState="getDefaultState",e.BroadcastEvent="broadcastEvent",e.HubBroadcastEvent="hubBroadcastEvent",e.ServiceManifest="serviceManifest",e.GetState="getState",e.SetState="setState",e.SetOutputs="setOutputs",e.UIEvent="uiEvent",e.GetSystemInfo="getSystemInfo",e.InitializeInstance="initializeInstance",e.TerminateInstance="terminateInstance",e.UninstallService="uninstallService",e.ChooseDirectoryDialog="chooseDirectoryDialog",e.ChooseFileDialog="chooseFileDialog",e.GetUniqueId="getUniqueId",e.RebootToInstallUpdate="rebootToInstallUpdate",e.GetFileContentFromCacheId="getFileContentFromCacheId"}(i||(w.KemuHubFunctions=i={})),function(e){e.SetDependencyPath="setDependencyPath",e.GetDependencyPath="getDependencyPath"}(s||(w.ServiceToServiceFunctions=s={})),function(e){e.IPC="ipc",e.WS="ws"}(c||(w.Transport=c={}))),w),e),l((P||(P=1,Object.defineProperty(K,"__esModule",{value:!0})),K),e)),m;var e,t,r,n,o,a,i,s,c,d,l}function B(){if(A)return g;A=1,Object.defineProperty(g,"__esModule",{value:!0}),g.onAssumeSession=g.buildIpcAckResponse=g.isBrowser=g.onSendManifestCommand=g.onEndBroadcastCommand=g.onStartBroadcastCommand=g.onAckResponse=g.onAckRequest=g.buildSocketAckRequest=g.buildIpcAckRequest=g.buildAckResponse=g.safeJsonParse=void 0;const e=C();g.safeJsonParse=e=>{try{return JSON.parse(e)}catch(e){return null}};g.buildAckResponse=t=>`${e.KemuHubCommand.AcknowledgeResponse}${t}`;g.buildIpcAckResponse=(t,r)=>`${e.KemuHubCommand.AcknowledgeResponse}${t}:${r||""}`;g.buildIpcAckRequest=()=>`${e.KemuHubCommand.IpcAcknowledge}`;g.buildSocketAckRequest=t=>`${e.KemuHubCommand.SocketAcknowledge}${t}`;g.onAssumeSession=(t,r)=>{if(t.startsWith(e.KemuHubCommand.AssumeSession)){const n=t.split(e.KemuHubCommand.AssumeSession);return r(parseInt(n[1])),!0}return!1};g.onAckResponse=(t,r)=>{if(t.startsWith(e.KemuHubCommand.AcknowledgeResponse)){const n=t.split(e.KemuHubCommand.AcknowledgeResponse),o=parseInt(n[1]);return r&&r(o),o}return null};g.onAckRequest=(t,r)=>{const n=e.KemuHubCommand.SocketAcknowledge,o=e.KemuHubCommand.IpcAcknowledge,a=t.startsWith(n),i=t.startsWith(o);if(a||i){const e=t.split(a?n:o),i=parseInt(e[1]);return r&&r(i),i}return null};g.onStartBroadcastCommand=(t,r)=>t===e.KemuHubCommand.BroadcastStart&&(r(),!0);g.onEndBroadcastCommand=(t,r)=>t===e.KemuHubCommand.BroadcastEnd&&(r(),!0);g.onSendManifestCommand=(t,r)=>t===e.KemuHubCommand.SendManifest&&(r(),!0);const t="undefined"!=typeof window;return g.isBrowser=t,g}var j,_={};function z(){return j||(j=1,e=_,Object.defineProperty(e,"__esModule",{value:!0}),e.KLCmdHeaderSize=e.KLHeaderSize=e.KLCmdProtocolHeaderSize=e.KLProtocolHeadersSize=void 0,e.KLProtocolHeadersSize={protocolPrefix:4,protocolVersion:1,jsonLength:4,binaryLength:4,fromServiceId:4,toServiceId:4,sentAt:8},e.KLCmdProtocolHeaderSize={protocolPrefix:4,txtLength:4},e.KLHeaderSize=Object.values(e.KLProtocolHeadersSize).reduce(((e,t)=>e+t),0),e.KLCmdHeaderSize=Object.values(e.KLCmdProtocolHeaderSize).reduce(((e,t)=>e+t),0)),_;var e}var U,E={};function k(){if(U)return E;U=1,Object.defineProperty(E,"__esModule",{value:!0}),E.setNestedProperty=E.decodeMap=E.isSupportedBinaryType=E.getEncodedMap=void 0;const e=["width","height","colorSpace"],t=e=>{const t="undefined"!=typeof Buffer&&e instanceof Buffer,r=e instanceof ArrayBuffer,n=e instanceof Uint8ClampedArray,o=e instanceof Uint8Array,a=e instanceof Int8Array;return t?"Buffer":r?"ArrayBuffer":n?"Uint8ClampedArray":o?"Uint8Array":a?"Int8Array":null};E.isSupportedBinaryType=t;E.getEncodedMap=(r,n)=>{const o={},a=[];let i=0,s=Array.isArray(r)?[]:{};const c=(r,s)=>{const d=t(r);if(!d){if(Array.isArray(r)){const e=[];for(let t=0;t<r.length;t++)e[t]=c(r[t],`${s}[${t}]`);return e}if("object"==typeof r){const t={},n=(e=>{const t=e instanceof Int16Array,r=e instanceof Uint16Array,n=e instanceof Int32Array,o=e instanceof Uint32Array,a=e instanceof Float32Array,i=e instanceof Float64Array,s=e instanceof BigInt64Array,c=e instanceof BigUint64Array;return t?"Int16Array":r?"Uint16Array":n?"Int32Array":o?"Uint32Array":a?"Float32Array":i?"Float64Array":s?"BigInt64Array":c?"BigUint64Array":null})(r);if(n)throw new Error(`Unsupported binary type [${n}] at path "${s}"`);for(const n in r)Object.hasOwn(r,n)||e.includes(n)||console.warn(`Allowing inherited property: ${n} from path: ${s}`),t[n]=c(r[n],`${s.length?`${s}.`:""}${n}`);return t}return r}o[s]={index:i,length:r.byteLength,binaryType:d},"Buffer"===n?a.push(Buffer.from(r)):"ArrayBuffer"===d?a.push(r):a.push(r.buffer),i+=r.byteLength};s=c(r,"");let d=null;if(a.length>1)if("ArrayBuffer"===n){const e=a.reduce(((e,t)=>e+t.byteLength),0),t=new Uint8Array(e);let r=0;for(let e=0;e<a.length;e++)t.set(new Uint8Array(a[e]),r),r+=a[e].byteLength;d=t.buffer}else{d=Buffer.concat(a)}else 1===a.length&&(d=a[0]);return d?{map:o,combinedData:d,sourceCopy:s}:null};const r=(e,t,r,n)=>{const o=t.match(/(\[\d+\])|([^[\].]+)/g)||[];let a=e;for(let e=0;e<o.length;e++){let t=o[e];const i=t.startsWith("[")&&t.endsWith("]"),s=e===o.length-1;if(i){t=t.slice(1,-1);const i=parseInt(t,10);if(!Array.isArray(a))throw new Error(`Expected an array at key "${o.slice(0,e).join(".")}" but found an object.`);s?n?a.splice(i,1):a[i]=r:(a[i]||(a[i]=o[e+1].startsWith("[")?[]:{}),a=a[i])}else s?n?delete a[t]:a[t]=r:(a[t]||(a[t]=o[e+1].startsWith("[")?[]:{}),a=a[t])}return e};E.setNestedProperty=r;return E.decodeMap=(e,t,n)=>{const o="undefined"!=typeof Buffer,a=t instanceof Uint8Array;for(const i in n)if(Object.hasOwn(n,i)){const{index:s,length:c,binaryType:d}=n[i];let u=null;if(o&&t instanceof Buffer)switch(d){case"Buffer":u=t.subarray(s,s+c);break;case"ArrayBuffer":u=t.buffer.slice(t.byteOffset,t.byteOffset+t.byteLength).slice(s,s+c);break;case"Uint8Array":u=new Uint8Array(t.subarray(s,s+c));break;case"Uint8ClampedArray":u=new Uint8ClampedArray(t.subarray(s,s+c));break;case"Int8Array":u=new Int8Array(t.subarray(s,s+c))}else if(t instanceof ArrayBuffer||t instanceof Uint8Array)switch(d){case"Buffer":if(o){u=Buffer.from(t.slice(s,s+c));break}case"ArrayBuffer":u=a?t.buffer.slice(t.byteOffset,t.byteOffset+t.byteLength).slice(s,s+c):t.slice(s,s+c);break;case"Uint8Array":u=a?t.slice(s,s+c):new Uint8Array(t.slice(s,s+c));break;case"Uint8ClampedArray":u=new Uint8ClampedArray(t.slice(s,s+c));break;case"Int8Array":u=new Int8Array(t.slice(s,s+c))}u&&r(e,i,u)}return e},E}var D,M,O={};function R(){if(D)return O;D=1;var e=O&&O.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(O,"__esModule",{value:!0}),O.createLogger=void 0;const t=e(r);return O.createLogger=e=>(0,t.default)(e),O}function x(){if(M)return f;M=1,Object.defineProperty(f,"__esModule",{value:!0});const e=B(),t=z(),r=k(),n=R(),o="KMSG",a="KCMD",i=(0,n.createLogger)("klProtocol");return f.default={encode:(e,n,a)=>{const i={json:e.json},s=(0,r.getEncodedMap)(i.json,"Buffer"),c=s?.combinedData;s&&(i.jsonBinaryMap=s.map,i.json=s.sourceCopy);const d=c?c.byteLength:0,u=JSON.stringify(i),l=Buffer.from(u),f=l.byteLength,g=t.KLProtocolHeadersSize.protocolPrefix+t.KLProtocolHeadersSize.protocolVersion+t.KLProtocolHeadersSize.jsonLength+t.KLProtocolHeadersSize.binaryLength+t.KLProtocolHeadersSize.fromServiceId+t.KLProtocolHeadersSize.toServiceId+t.KLProtocolHeadersSize.sentAt+f+d,m=Buffer.alloc(g),p=Date.now();let y=0;return m.write(o,y),y+=t.KLProtocolHeadersSize.protocolPrefix,m.writeUInt8(1,y),y+=t.KLProtocolHeadersSize.protocolVersion,m.writeUInt32LE(f,y),y+=t.KLProtocolHeadersSize.jsonLength,m.writeUInt32LE(d,y),y+=t.KLProtocolHeadersSize.binaryLength,m.writeUInt32LE(n,y),y+=t.KLProtocolHeadersSize.fromServiceId,m.writeUInt32LE(a,y),y+=t.KLProtocolHeadersSize.toServiceId,m.writeBigInt64LE(BigInt(p),y),y+=t.KLProtocolHeadersSize.sentAt,l.copy(m,y),y+=f,c&&d&&c.copy(m,y),m},decodeHeader:e=>{let r=0;const n=e.toString("utf-8",r,t.KLProtocolHeadersSize.protocolPrefix);if(r+=t.KLProtocolHeadersSize.protocolPrefix,n!==o)return null;if(e.byteLength<t.KLHeaderSize)return i(`Received a Partial Header with ${e.byteLength} bytes. Waiting for more data.`),{partialHeader:!0,remaining:null};const a=e.readUInt8(r);r+=t.KLProtocolHeadersSize.protocolVersion;const s=e.readUInt32LE(r);r+=t.KLProtocolHeadersSize.jsonLength;const c=e.readUInt32LE(r);r+=t.KLProtocolHeadersSize.binaryLength;const d=e.readUInt32LE(r);r+=t.KLProtocolHeadersSize.fromServiceId;const u=e.readUInt32LE(r);r+=t.KLProtocolHeadersSize.toServiceId;const l=e.readBigInt64LE(r);r+=t.KLProtocolHeadersSize.sentAt;const f=s+c,g=e.subarray(r,r+f),m=e.subarray(0,t.KLHeaderSize);let p=null;return e.byteLength-t.KLHeaderSize-s-c>0&&(p=e.subarray(t.KLHeaderSize+s+c)),{header:{protocolVersion:a,jsonLength:s,binaryLength:c,fromServiceId:d,toServiceId:u,sentAt:new Date(Number(l)),packages:[g],headerPackage:m},remaining:p}},decodeFullKlMessage:n=>{const o=Buffer.concat(n.packages),a=o.subarray(0,n.jsonLength).toString(),s=o.subarray(n.jsonLength,n.jsonLength+n.binaryLength),c=(0,e.safeJsonParse)(a);if(!c?.json)return i("Invalid JSON in KL message"),null;c.jsonBinaryMap&&s.byteLength&&(0,r.decodeMap)(c.json,s,c.jsonBinaryMap);const d=Buffer.concat([n.headerPackage,o]);let u=d,l=null;const f=t.KLHeaderSize+n.jsonLength+n.binaryLength;return d.byteLength>f&&(l=d.subarray(f),u=d.subarray(0,f)),{message:{json:c.json,rawMessage:u},remaining:l}},patchEncodedHeader:(e,r)=>{if(null==r.fromServiceId&&void 0===r.toServiceId)return e;if(e.byteLength<t.KLHeaderSize)return i("Invalid Header Size"),e;let n=0;return n+=t.KLProtocolHeadersSize.protocolPrefix,n+=t.KLProtocolHeadersSize.protocolVersion,n+=t.KLProtocolHeadersSize.jsonLength,n+=t.KLProtocolHeadersSize.binaryLength,void 0!==r.fromServiceId&&e.writeUInt32LE(r.fromServiceId,n),n+=t.KLProtocolHeadersSize.fromServiceId,void 0!==r.toServiceId&&e.writeUInt32LE(r.toServiceId,n),e},encodeCommand:e=>{let r=0;const n=Buffer.from(e),o=n.byteLength,i=t.KLCmdHeaderSize+o,s=Buffer.alloc(i);return s.write(a,r),r+=t.KLCmdProtocolHeaderSize.protocolPrefix,s.writeUint32LE(o,r),r+=t.KLCmdProtocolHeaderSize.txtLength,n.copy(s,r),s},decodeCommand:e=>{let r=0;if(e.byteLength<t.KLCmdHeaderSize)return{command:null};const n=e.toString("utf-8",r,t.KLCmdProtocolHeaderSize.protocolPrefix);if(r+=t.KLCmdProtocolHeaderSize.protocolPrefix,n!==a)return{command:null};const o=e.readUInt32LE(r);r+=t.KLCmdProtocolHeaderSize.txtLength;const i=e.toString("utf-8",r,r+o),s=e.byteLength-t.KLCmdHeaderSize-o;let c=null;s>0&&(c=e.subarray(t.KLCmdHeaderSize+o));let d=0;return s<0&&(d=Math.abs(s)),{command:i,remainingData:c,missing:d}}},f}var T,$,F={};function N(){if(T)return F;T=1,Object.defineProperty(F,"__esModule",{value:!0});const e=z(),t=R(),r=k(),n=B(),o="KMSG",a="KCMD",i=(0,t.createLogger)("klProtocol"),s=new TextEncoder;return F.default={encode:(t,n,a)=>{const i={json:t.json},c=(0,r.getEncodedMap)(t.json,"ArrayBuffer"),d=c?.combinedData;c&&(i.jsonBinaryMap=c.map,i.json=c.sourceCopy);const u=d?d.byteLength:0,l=JSON.stringify(i),f=s.encode(l),g=f.byteLength,m=e.KLProtocolHeadersSize.protocolPrefix+e.KLProtocolHeadersSize.protocolVersion+e.KLProtocolHeadersSize.jsonLength+e.KLProtocolHeadersSize.binaryLength+e.KLProtocolHeadersSize.fromServiceId+e.KLProtocolHeadersSize.toServiceId+e.KLProtocolHeadersSize.sentAt+g+u,p=new ArrayBuffer(m),y=new DataView(p),S=new Uint8Array(p),v=Date.now();let b=0;for(let e=0;e<4;++e)S[b++]=o.charCodeAt(e);return y.setUint8(b,1),b+=e.KLProtocolHeadersSize.protocolVersion,y.setUint32(b,g,!0),b+=e.KLProtocolHeadersSize.jsonLength,y.setUint32(b,u,!0),b+=e.KLProtocolHeadersSize.binaryLength,y.setUint32(b,n,!0),b+=e.KLProtocolHeadersSize.fromServiceId,y.setUint32(b,a,!0),b+=e.KLProtocolHeadersSize.toServiceId,y.setBigInt64(b,BigInt(v),!0),b+=e.KLProtocolHeadersSize.sentAt,S.set(f,b),b+=g,d&&u&&S.set(new Uint8Array(d),b),p},decodeHeader:t=>{const r=new DataView(t);let n=0,a="";for(let t=0;t<e.KLProtocolHeadersSize.protocolPrefix;++t)a+=String.fromCharCode(r.getUint8(n++));if(a!==o)return null;if(t.byteLength<e.KLHeaderSize)return i.log(`Received a Partial Header with ${t.byteLength} bytes. Waiting for more data.`),{partialHeader:!0,remaining:null};const s=r.getUint8(n);n+=e.KLProtocolHeadersSize.protocolVersion;const c=r.getUint32(n,!0);n+=e.KLProtocolHeadersSize.jsonLength;const d=r.getUint32(n,!0);n+=e.KLProtocolHeadersSize.binaryLength;const u=r.getUint32(n,!0);n+=e.KLProtocolHeadersSize.fromServiceId;const l=r.getUint32(n,!0);n+=e.KLProtocolHeadersSize.toServiceId;const f=r.getBigInt64(n,!0);n+=e.KLProtocolHeadersSize.sentAt;const g=c+d,m=t.slice(n,n+g),p=new Uint8Array(t,0,e.KLHeaderSize);let y=null;if(t.byteLength-e.KLHeaderSize-c-d>0){y=new Uint8Array(t,e.KLHeaderSize+c+d).slice().buffer}return{header:{protocolVersion:s,jsonLength:c,binaryLength:d,fromServiceId:u,toServiceId:l,sentAt:new Date(Number(f)),packages:[m],headerPackage:p.slice().buffer},remaining:y}},decodeFullKlMessage:t=>{const o=t.packages.reduce(((e,t)=>e+t.byteLength),0),a=new Uint8Array(o);let s,c=0;for(const e of t.packages)s=new Uint8Array(e),a.set(s,c),c+=s.byteLength;const d=(new TextDecoder).decode(a.subarray(0,t.jsonLength)),u=a.subarray(t.jsonLength,t.jsonLength+t.binaryLength),l=(0,n.safeJsonParse)(d);if(!l?.json)return i.log("Invalid JSON in KL message"),null;l.jsonBinaryMap&&u.byteLength&&(0,r.decodeMap)(l.json,u,l.jsonBinaryMap);const f=new Uint8Array(t.headerPackage.byteLength+a.byteLength);f.set(new Uint8Array(t.headerPackage),0),f.set(a,t.headerPackage.byteLength);let g=f,m=null;const p=e.KLHeaderSize+t.jsonLength+t.binaryLength;return f.byteLength>p&&(m=f.subarray(p),g=f.subarray(0,p)),{message:{json:l.json,...u.length?{binaryData:u.buffer}:{},rawMessage:g.buffer},remaining:m?.buffer??null}},patchEncodedHeader:(t,r)=>{if(null==r.fromServiceId&&void 0===r.toServiceId)return t;if(t.byteLength<e.KLHeaderSize)return i("Invalid Header Size"),t;let n=0;n+=e.KLProtocolHeadersSize.protocolPrefix,n+=e.KLProtocolHeadersSize.protocolVersion,n+=e.KLProtocolHeadersSize.jsonLength,n+=e.KLProtocolHeadersSize.binaryLength;const o=new DataView(t);return void 0!==r.fromServiceId&&o.setUint32(n,r.fromServiceId,!0),n+=e.KLProtocolHeadersSize.fromServiceId,void 0!==r.toServiceId&&o.setUint32(n,r.toServiceId,!0),t},encodeCommand:t=>{let r=0;const n=s.encode(t),o=n.byteLength,i=e.KLCmdHeaderSize+o,c=new ArrayBuffer(i),d=new DataView(c),u=new Uint8Array(c);for(let e=0;e<4;++e)u[r++]=a.charCodeAt(e);return d.setUint32(r,o,!0),r+=e.KLCmdProtocolHeaderSize.txtLength,u.set(n,r),c},decodeCommand:t=>{const r=new DataView(t);let n=0;if(t.byteLength<e.KLCmdHeaderSize)return{command:null};let o="";for(let t=0;t<e.KLCmdProtocolHeaderSize.protocolPrefix;++t)o+=String.fromCharCode(r.getUint8(n++));if(o!==a)return{command:null};const i=r.getUint32(n,!0);n+=e.KLCmdProtocolHeaderSize.txtLength;const s=t.byteLength-e.KLCmdHeaderSize-i,c=new Uint8Array(t,n,Math.min(i,t.byteLength-e.KLCmdHeaderSize)),d=(new TextDecoder).decode(c);let u=null;s>0&&(u=t.slice(e.KLCmdHeaderSize+i));let l=0;return s<0&&(l=Math.abs(s)),{command:d,remainingData:u,missing:l}}},F}function G(){if($)return l;$=1;var e=l&&l.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(l,"__esModule",{value:!0}),l.createTransmissionManager=void 0;const t=e(x()),r=e(N()),n=(0,R().createLogger)("klTransmissionManager");return l.createTransmissionManager=()=>{const e=(o,a,i,s)=>{let c=a,d=null;const u=o instanceof ArrayBuffer;if(n(`RAW: ${o.toString()}`),!c||c.partialHeaderData){let l;if(u?(l=c?.partialHeaderData?new Uint8Array([...new Uint8Array(c.partialHeaderData),...new Uint8Array(o)]).buffer:o,d=r.default.decodeHeader(l)):(l=c?.partialHeaderData?Buffer.concat([c.partialHeaderData,o]):o,d=t.default.decodeHeader(l)),!d){const{command:o,missing:c,remainingData:d}=u?r.default.decodeCommand(l):t.default.decodeCommand(l);return o?s({command:o,complete:!0,rawMessage:l}):n(c?`ERROR: Missing ${c} bytes to complete the command. This partial command will be aborted.`:`ERROR: Invalid state, message was decoded without a header or partial header data. Discarding ${l.byteLength} bytes`),d?(n(`${d.byteLength} bytes remain after processing command. Re-analyzing...`),e(d,a,i,s)):void 0}if(d.partialHeader)return c={firstPackageAt:Date.now(),partialHeaderData:l},i(c);if(!d.header)return n(`ERROR: Invalid state, message was decoded without a header or partial header data. Discarding ${l.byteLength} bytes`);const f=d.header;c={firstPackageAt:Date.now(),header:{...f,totalBytesReceived:f.packages[0].byteLength,totalBytesExpected:f.binaryLength+f.jsonLength,remaining:d.remaining}},i(c)}else c.header&&c.header.totalBytesReceived<c.header.totalBytesExpected&&(c.header.packages.push(o),c.header.totalBytesReceived+=o.byteLength,i(c));if(c.header&&c.header.totalBytesReceived>=c.header.totalBytesExpected){const o=Date.now()-c.header.sentAt.getTime(),a=Date.now()-c.firstPackageAt;n(`Received ${c.header.totalBytesReceived} of ${c.header.totalBytesExpected} expected in ${o} ms, elapsed since first package: ${a}ms`);const d=u?r.default.decodeFullKlMessage(c.header):t.default.decodeFullKlMessage(c.header),l=c.header.totalBytesReceived,f=c.header.remaining;i(null),d&&s({klMessage:d.message,complete:!0,sourceServiceId:c.header.fromServiceId,targetServiceId:c.header.toServiceId,rawMessage:d.message.rawMessage});let g=f;if(d?.remaining&&(g=u?f?((e,t)=>{const r=e.byteLength+t.byteLength,n=new ArrayBuffer(r),o=new Uint8Array(e),a=new Uint8Array(t),i=new Uint8Array(n);return i.set(o),i.set(a,o.length),n})(f,d.remaining):d.remaining:f?Buffer.concat([f,d.remaining]):d.remaining),g)return n(`${g.byteLength} bytes remaining after processing message with ${l} bytes of data. Re-analyzing...`),e(g,null,i,s)}};return e},l}var V,W,q={};function J(){if(V)return q;V=1;var e=q&&q.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(q,"__esModule",{value:!0});const t=e(x()),r=e(N()),n=B();let o=t.default;return n.isBrowser&&(o=r.default),q.default=o,q}function Q(){if(W)return c;W=1;var e=c&&c.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(c,"__esModule",{value:!0});const r=e(t),n=e((i||(i=1,Object.defineProperty(d,"__esModule",{value:!0}),d.default={id:"widgets",retry:1500,silent:!0,rawBuffer:!0,appspace:"kemu.",encoding:"hex"}),d)),o=G(),a=R(),s=e(J());let u,l,f,g,m=null;const p=(0,o.createTransmissionManager)(),y=(0,a.createLogger)("ipcClient"),S=e=>{const t=n.default.id;r.default.of[t].emit(e)};return c.default={connect:e=>{n.default.id=e?.id||n.default.id,n.default.appspace=e?.appSpace||n.default.appspace,r.default.config={...r.default.config,...n.default};const t=n.default.id;r.default.connectTo(t,(()=>{r.default.of[t].on("connect",(()=>{y("Connected to server"),m=null,l&&l()})),r.default.of[t].on("data",(e=>{p(e,m,(e=>m=e),(e=>{if(e.complete)return e.command?(y(`Received command: ${e.command}`),void(u&&u(e.command))):void(e.klMessage&&f&&f({send:S,transmission:{sourceServiceId:e.sourceServiceId??-1,targetServiceId:e.targetServiceId??-1,rawMessage:e.rawMessage},json:e.klMessage.json}))}))})),r.default.of[t].on("disconnect",(()=>{y(`Disconnected from ${t}`),m=null,g&&g()}))}))},sendCommand:e=>{const t=n.default.id,o=s.default.encodeCommand(e);r.default.of[t].emit(o)},sendBuffer:S,onCommand:e=>u=e,onMessageReceived:e=>f=e,onClientConnected:e=>l=e,onClientDisconnected:e=>g=e},c}var X,Y,Z={},ee={};function te(){return Y||(Y=1,function(e){var t=Z&&Z.__createBinding||(Object.create?function(e,t,r,n){void 0===n&&(n=r);var o=Object.getOwnPropertyDescriptor(t,r);o&&!("get"in o?!t.__esModule:o.writable||o.configurable)||(o={enumerable:!0,get:function(){return t[r]}}),Object.defineProperty(e,n,o)}:function(e,t,r,n){void 0===n&&(n=r),e[n]=t[r]}),r=Z&&Z.__exportStar||function(e,r){for(var n in e)"default"===n||Object.prototype.hasOwnProperty.call(r,n)||t(r,e,n)},n=Z&&Z.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(e,"__esModule",{value:!0});const o=n(J()),a=B();var i;r((X||(X=1,Object.defineProperty(ee,"__esModule",{value:!0}),ee.RemoveInvokeError=void 0,function(e){e.FunctionNotFound="FNC_NOT_FOUND",e.ParentEventCallbackError="PARENT_EVENT_CALLBACK_ERROR"}(i||(ee.RemoveInvokeError=i={}))),ee),e);let s=Math.ceil(Date.now()/1e3);e.default=function(e){const t={};let r=console.log;const n={};let i=e||String(Date.now());const c={},d=e=>!c[e],u=(e,t,r,n,i,s)=>{let c=a.isBrowser?new ArrayBuffer(0):Buffer.alloc(0);const u={json:{functionName:e,args:s.success?s.success:[s],messageId:t,type:s.success?"response":"error"}};return d(n)&&(c=o.default.encode(u,r,n)),i(c,{msg:u,sourceServiceId:r,targetServiceId:n})};return{setLogger:e=>{r=e},processMessage:(e,o,a,i)=>{if(!i)return!1;const s=i;if(t[s.messageId]){const e=t[s.messageId];return e&&(clearTimeout(e.timer),e.fulfilled||(e.fulfilled=!0,"response"===s.type?e.resolve(s.args):"error"===s.type&&e.reject(s.args[0])),delete t[s.messageId]),!0}if("execute"!==s.type&&r&&r(`No pending execution found for message id "${s.messageId}"`),"execute"===s.type){const t=n[s.functionName];if(t){const r=e=>{u(s.functionName,s.messageId,a.targetServiceId,a.sourceServiceId,o,e)};t({transport:e,args:s.args,reply:r,messageId:s.messageId,sourceServiceId:a.sourceServiceId,send:o})}else{const e=`Function "${s.functionName}" not found.`;r&&r(e),u(s.functionName,s.messageId,a.targetServiceId,a.sourceServiceId,o,{error:e,errCode:"FNC_NOT_FOUND"})}return!0}return!1},execute:async(e,n,c,u,l,f)=>{if(!c){const e="No send buffer function provided.";throw r&&r(e),e}s+=1;const g=`${i}-${s}-exec-${e.substring(0,10)}`,m={messageId:g,functionName:e,send:c,sourceServiceId:u,targetServiceId:l,args:n||[],fulfilled:!1,resolve:()=>{},reject:()=>{}};m.promise=new Promise(((e,t)=>{m.resolve=e,m.reject=t}));let p=a.isBrowser?new ArrayBuffer(0):Buffer.alloc(0);const y={json:{functionName:e,args:n,messageId:g,type:"execute"}};d(l)&&(p=o.default.encode(y,u,l)),t[g]=m,r&&r(`Calling remote function "${e}" with message id "${g}"`);const S="true"===process.env.NO_INVOKE_TIMEOUT;return f?.async?(m.fulfilled=!0,m.resolve([void 0]),delete t[g]):0===f?.timeout||S||(m.timer=setTimeout((()=>{r&&r(`Remote function ${g} timed out`);const n=t[g];n&&!n.fulfilled&&(n.fulfilled=!0,m.reject(`Function ${e} Timed out`)),delete t[g]}),f?.timeout||3e4)),c(p,{sourceServiceId:u,targetServiceId:l,msg:y}),m.promise},sendResponse:u,registerFunction:(e,t)=>{n[e]=t},getTransportSendFunction:e=>{const r=t[e];return r?r.send:null},setServiceName:e=>{i=e},getPendingExecutions:()=>t,rejectAllPending:e=>{Object.keys(t).forEach((r=>{const n=t[r];n&&!n.fulfilled&&(clearTimeout(n.timer),n.fulfilled=!0,n.reject(e),delete t[r])}))},broadcast:(e,t,n,c)=>{s+=1;const u=`${i}-${s}-multicast-${e.substring(0,10)}`;let l=a.isBrowser?new ArrayBuffer(0):Buffer.alloc(0);const f={json:{functionName:e,args:t,messageId:u,type:"execute"}};let g=d(n[0].serviceId);g&&(l=o.default.encode(f,c,n[0].serviceId));for(let t=0;t<n.length;t++)try{const a=n[t];r&&r(`Broadcasting function "${e}" with message id "${u}" to client [${a.serviceId}]`),0!==t&&(g=d(a.serviceId),g&&(l=o.default.patchEncodedHeader(l,{toServiceId:a.serviceId}))),a.sendFn(l,{msg:f,sourceServiceId:c,targetServiceId:a.serviceId})}catch(e){r&&r(`Error broadcasting to client at index ${t}`)}},disableServiceEncoding:(e,t)=>{c[e]=t}}}}(Z)),Z}var re,ne={};var oe,ae,ie={};var se=a((ae||(ae=1,function(t){var r=s&&s.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.DataType=t.KemuHubServiceId=t.createImageDataLike=void 0;const a=r(e),i=r(Q()),c=r(te()),d=C();Object.defineProperty(t,"DataType",{enumerable:!0,get:function(){return d.DataType}});const u=R(),l=B(),f=function(){if(re)return ne;re=1,Object.defineProperty(ne,"__esModule",{value:!0}),ne.preProcessManifest=ne.portStrToWidgetPort=ne.createImageDataLike=void 0;const e=C();return ne.createImageDataLike=(t,r,n,o="srgb")=>{let a;return a=t instanceof Uint8ClampedArray?t:new Uint8ClampedArray(t),{data:a,width:r,height:n,colorSpace:o,_kemuType:e.DataType.ImageData}},ne.portStrToWidgetPort=t=>({...t,type:e.DataType[t.type]}),ne.preProcessManifest=(e,t,r)=>({...e,path:t,...e.widgetUI&&r?.widgetUIContents?{widgetUIContents:r.widgetUIContents}:{}}),ne}();Object.defineProperty(t,"createImageDataLike",{enumerable:!0,get:function(){return f.createImageDataLike}});const g=(oe||(oe=1,Object.defineProperty(ie,"__esModule",{value:!0}),ie.KemuHubServiceId=void 0,ie.KemuHubServiceId=0),ie);Object.defineProperty(t,"KemuHubServiceId",{enumerable:!0,get:function(){return g.KemuHubServiceId}});const m=n,p=r(o),y=(0,u.createLogger)("kemuWidgetService"),S=(0,p.default)(process.argv.slice(2));t.default=function(e){const t={},r=process.env.KEMU_WIDGET_SESSION_ID;let n,o,s,u=!1;const p={};let v,b,h,I,L,w,P,H=null;const A=new c.default;A.setLogger(y),t.start=async(t,c)=>{const g=t||a.default.resolve(a.default.dirname(process.argv[1]),"manifest.json");s=a.default.dirname(g);const p=await(0,m.readFile)(g,"utf-8"),v=(0,l.safeJsonParse)(p);if(!v)throw new Error("Error parsing manifest file.");let b;if(v.inputs||(v.inputs=[]),v.outputs||(v.outputs=[]),v.widgetUI)try{b=await(0,m.readFile)(a.default.join(s,"widgetUI.js"))}catch(e){y(`Error loading widgetUI file ${v.name}: ${e}`)}if(v.svgIcon)try{const e=await(0,m.readFile)(a.default.join(s,v.svgIcon),"utf-8");v.svgIcon=e}catch(e){y(`Error loading icon for service ${v.name}: ${e}`)}o=(0,f.preProcessManifest)(v,s,{widgetUIContents:b}),u=o.name.startsWith("test."),o.path=s,o.internal=S.internal||!1,u?y("Starting Kemu Service in Dev mode"):((e=>{const t=e||S.sessionId||r;if(!t)throw new Error("Missing sessionId. Expected service to be launched with a sessionId as first argument, or the KEMU_WIDGET_SESSION_ID environment variable to be set.");n=parseInt(String(t))})(c),y(`Starting Kemu Service with session id: ${n}`)),A.setServiceName(`${o.name}_${o.version}`),i.default.onCommand(K),i.default.onMessageReceived((({json:e,transmission:t})=>A.processMessage(d.Transport.IPC,i.default.sendBuffer,t,e))),A.registerFunction(d.KemuHubFunctions.OnParentEvent,B),A.registerFunction(d.KemuHubFunctions.GetDefaultState,C),A.registerFunction(d.KemuHubFunctions.UIEvent,z),A.registerFunction(d.KemuHubFunctions.InitializeInstance,j),A.registerFunction(d.KemuHubFunctions.TerminateInstance,_),i.default.onClientConnected((()=>{P&&P()})),i.default.onClientDisconnected((()=>{u&&(n=void 0)})),i.default.connect({appSpace:S.ipcSpace||e?.ipc?.appSpace,id:S.ipcId||e?.ipc?.id})};const K=e=>{(0,l.onAckRequest)(e,(e=>{i.default.sendCommand((0,l.buildIpcAckResponse)(e,n||void 0)),!n&&u&&(y("Dev mode detected, assuming service session id from ack request:",e),n=e)})),(0,l.onStartBroadcastCommand)(e,(()=>{h&&h()})),(0,l.onEndBroadcastCommand)(e,(()=>{I&&I()})),(0,l.onSendManifestCommand)(e,(()=>{y("Sending manifest to hub"),n?A.execute(d.KemuHubFunctions.ServiceManifest,[{...o,devMode:u}],i.default.sendBuffer,n,g.KemuHubServiceId,{async:!0}):y("Service session id is not set. Cannot send manifest.")})),(0,l.onAssumeSession)(e,(e=>{n=e,y(`Assumed session id ${e}`)}))},C=async e=>{if(b){const t=await b();return e.reply({success:[t]})}return e.reply({success:[{}]})},B=async e=>{if(v){const t=e.args[0],{source:r,target:o,data:a,recipeId:s,currentState:c,targetVariantId:u,eventContext:l}=t;if(!n)return void y("Service session id is not set. Cannot process parent event.");if(!r||!o||!a)return e.reply({error:"Invalid arguments, expected [source, target, data, context]"});const f=i.default.sendBuffer,g=async t=>A.execute(d.KemuHubFunctions.SetOutputs,[t],f,n,e.sourceServiceId,{timeout:0}),m={currentState:c,type:o.widgetType,widgetId:o.widgetId,variantId:u,recipeId:s,getState:async()=>{const t=[o.widgetId,s];return A.execute(d.KemuHubFunctions.GetState,t,f,n,e.sourceServiceId)},setState:async t=>{const r={widgetId:o.widgetId,variantId:u,recipeId:s,newState:t};return A.execute(d.KemuHubFunctions.SetState,[r],f,n,e.sourceServiceId)},setOutputs:async(e,t)=>{const r={widgetId:o.widgetId,recipeId:s,outputs:e,finalState:t};await g(r)},setOutputsWithContext:async e=>{const t={...e,widgetId:o.widgetId,recipeId:s};await g(t)}};y(`Invoking user-defined onParentEvent callback for event id "${e.messageId}"`),await v({data:a,source:r,target:o,eventContext:l},m).then((()=>{y(`Replying SUCCESS to event id "${e.messageId}"`),e.reply({success:[]})})).catch((t=>{const r="string"==typeof t?t:t.message||t;y(`Error invoking onParentEvent callback: ${r}`),e.reply({error:r,errCode:"PARENT_EVENT_CALLBACK_ERROR"})}))}},j=async e=>{const[{currentState:t,recipeId:r,widgetId:n,variantId:o,recipeType:a,currentDependencies:i}]=e.args;if(p[n]={currentRecipeId:r,variantId:o,currentSourceServiceId:e.sourceServiceId},L){const s={currentState:t,recipeId:r,widgetId:n,variantId:o,recipeType:a,currentDependencies:i||{}},c=await L(s);e.reply({success:[c]})}else e.reply({error:"Not implemented",errCode:"FNC_NOT_FOUND"})},_=async e=>{if(w){const[{currentState:t,recipeId:r,widgetId:n,variantId:o}]=e.args,a={currentState:t,recipeId:r,widgetId:n,variantId:o};await w(a),delete p[n]}e.reply({success:[]})},z=async e=>{if(H)try{const t=await H.apply(void 0,e.args);return e.reply({success:[t]})}catch(t){const r="string"==typeof t?t:JSON.stringify(t);return y(`Error invoking UI Event handler: ${r}`),e.reply({error:r})}e.reply({error:"UI Events are not supported in this service."})},U=async e=>{if(!o.eventEmitter)throw new Error("This service does not support broadcasting events. Please set `eventEmitter` to true in your manifest file.");if(n)return A.execute(d.KemuHubFunctions.BroadcastEvent,e,i.default.sendBuffer,n,g.KemuHubServiceId,{async:!0});y("Service session id is not set. Cannot broadcast event.")};return t.broadcast=async(e,t)=>{const r=[{outputs:e,variantId:t}];await U(r)},t.broadcastEvent=async e=>{const t=[{outputs:e.outputs,variantId:e.variantId,eventContext:e.eventContext}];await U(t)},t.addDependencyPath=async(e,t,r)=>{if(!n)throw new Error("Not yet registered with the Hub");const o=p[r];if(!o.currentSourceServiceId||!o.currentRecipeId)throw new Error("Cannot invoke this method before initialization");const a={key:e,path:t,recipeId:o.currentRecipeId,widgetId:r};y(`Adding dependency path for key "${e}" with path "${t}"`),await A.execute(d.ServiceToServiceFunctions.SetDependencyPath,[a],i.default.sendBuffer,n,o.currentSourceServiceId)},t.getDependencyPath=async(e,t)=>{if(!n)throw new Error("Not yet registered with the Hub");const r=p[t];if(!r.currentSourceServiceId||!r.currentRecipeId)throw new Error("Cannot invoke this method before initialization");y("Getting dependency path for key:",e);const o={key:e,recipeId:r.currentRecipeId,widgetId:t},[a]=await A.execute(d.ServiceToServiceFunctions.GetDependencyPath,[o],i.default.sendBuffer,n,r.currentSourceServiceId);return y("Dependency path response:",a),a},t.getUniqueId=async()=>{if(!n)throw new Error("Not yet registered with the Hub");const[e]=await A.execute(d.KemuHubFunctions.GetUniqueId,[],i.default.sendBuffer,n,g.KemuHubServiceId);return e},t.resolveRuntimeDependencyPath=e=>{if(!S.recipePath)throw new Error("Cannot resolve runtime dependency without a recipe path. Missing [--recipePath] argument.");return a.default.resolve(S.recipePath,e)},t.onGetDefaultState=e=>{b=e},t.onParentEvent=e=>{v=e},t.onTerminate=e=>{w=e},t.onInitialize=e=>{L=e},t.onConnected=e=>{P=e},t.onStartBroadcast=e=>{h=e},t.onStopBroadcast=e=>{I=e},t.onUIEvent=e=>{H=e},S.internal&&(t.executeHubFunction=async(e,t,r)=>{if(n)return A.execute(e,t,i.default.sendBuffer,n,g.KemuHubServiceId,r);y("Service session id is not set. Cannot execute hub function.")}),t._getRemoteInvoker=()=>A,t}}(s)),s));module.exports=se;
@@ -145,6 +145,7 @@ function requireKemuHub_t () {
145
145
  KemuHubFunctions["ChooseFileDialog"] = "chooseFileDialog";
146
146
  KemuHubFunctions["GetUniqueId"] = "getUniqueId";
147
147
  KemuHubFunctions["RebootToInstallUpdate"] = "rebootToInstallUpdate";
148
+ KemuHubFunctions["GetFileContentFromCacheId"] = "getFileContentFromCacheId";
148
149
  })(KemuHubFunctions || (kemuHub_t.KemuHubFunctions = KemuHubFunctions = {}));
149
150
  var ServiceToServiceFunctions;
150
151
  (function (ServiceToServiceFunctions) {
package/mjs/service.d.ts CHANGED
@@ -171,6 +171,9 @@ export type TargetOutput = {
171
171
  /** id of the variant that defined the output */
172
172
  variantId?: string;
173
173
  };
174
+ export type ValidEventContextValue = string | number | boolean | null | ValidEventContextValue[] | {
175
+ [key: string]: ValidEventContextValue;
176
+ };
174
177
  export type WidgetType = string;
175
178
  export type SerializableWidgetInfo<T> = {
176
179
  /** the id of the current widget in the recipe */
@@ -212,6 +215,26 @@ export type WidgetContext<T extends WidgetState = WidgetState> = SerializableWid
212
215
  * @param finalState is the new state of the widget after the event is processed.
213
216
  */
214
217
  setOutputs: (outputs: TargetOutput[], finalState?: T) => Promise<void>;
218
+ /**
219
+ * Sends the given value to the next widget attached to the given ports
220
+ * with a context that can be used by the next widget to process the data.
221
+ * @param config the configuration of the output to send.
222
+ */
223
+ setOutputsWithContext: (config: {
224
+ /** A list of outputs to send data to. The order in which the outputs are defined
225
+ * is the order in which the data will be sent.
226
+ */
227
+ outputs: TargetOutput[];
228
+ /**
229
+ * The new state of the widget after the event is processed.
230
+ */
231
+ finalState?: T;
232
+ /**
233
+ * The event context to use when sending the outputs.
234
+ * This will be available to any child widget down the line that is a variant of the current widget.
235
+ */
236
+ eventContext?: ValidEventContextValue;
237
+ }) => Promise<void>;
215
238
  };
216
239
  export type PortEventInfo = {
217
240
  /** the unique name of the port */
@@ -241,12 +264,16 @@ export type ParentEventHandlerEvent<T extends WidgetState = WidgetState> = {
241
264
  target: PortEventInfo;
242
265
  targetVariantId?: string;
243
266
  recipeId: string;
267
+ /**
268
+ * A context previously set by a parent widget of the same type.
269
+ */
270
+ eventContext?: ValidEventContextValue;
244
271
  /** when data.value is binary (ImageData, etc) */
245
272
  /** the current state of the widget at the time of invocation */
246
273
  currentState: T;
247
274
  config?: RIExecuteConfig;
248
275
  };
249
- export type ServiceParentEvent<WS extends WidgetState = WidgetState> = Pick<ParentEventHandlerEvent<WS>, "data" | "source" | "target">;
276
+ export type ServiceParentEvent<WS extends WidgetState = WidgetState> = Pick<ParentEventHandlerEvent<WS>, "data" | "source" | "target" | "eventContext">;
250
277
  export type ServiceParentEventHandler<T extends WidgetState = WidgetState> = (event: ServiceParentEvent<T>, context: WidgetContext<T>) => Promise<void>;
251
278
  /**
252
279
  * Handles custom ui events. Any returned value will be passed back to the caller.
@@ -362,8 +389,37 @@ export type KemuService<T extends Record<string, any> = Record<string, any>> = {
362
389
  * The data type and port name MUST match the type defined in the widget manifest's output ports.
363
390
  * @param variantId the id of the variant to broadcast the data to. If not provided the data
364
391
  * is assumed to be broadcast to the default service instance.
392
+ *
393
+ * @deprecated Use `broadcastEvent` instead.
365
394
  */
366
395
  broadcast: (outputs: TargetOutput[], variantId?: string) => Promise<void>;
396
+ /**
397
+ * Emits data to all the given ports to any widget service that is connected to the Kemu Hub
398
+ * and subscribed to events from this service.
399
+ *
400
+ * IMPORTANT: You must set `eventEmitter` to `true` in the manifest file to use this method.
401
+ *
402
+ * @param config the configuration of the broadcast event.
403
+ */
404
+ broadcastEvent: (config: {
405
+ /**
406
+ * A list of outputs to send data to. The order in which the outputs are defined
407
+ * is the order in which the data will be sent.
408
+ * The data type and port name MUST match the type defined in the widget manifest's output ports.
409
+ */
410
+ outputs: TargetOutput[];
411
+ /**
412
+ * The id of the variant to broadcast the data to. If not provided the data
413
+ * is assumed to be broadcast to the default service instance.
414
+ */
415
+ variantId?: string;
416
+ /**
417
+ * Custom context for this event. When this event reaches widget variant
418
+ * of the same widget type, this context will be provided to the widget even
419
+ * if the event data has fundamentally changed.
420
+ */
421
+ eventContext?: ValidEventContextValue;
422
+ }) => Promise<void>;
367
423
  /**
368
424
  * Registers the path to a file or folder the recipe depends on. When the recipe is exported,
369
425
  * the dependency will be included in the generated package.
package/mjs/service.js CHANGED
@@ -1 +1 @@
1
- import e from"path";import t from"node-ipc";import n from"debug";import{readFile as r}from"fs/promises";import a from"minimist";var o,i,s,c,d,u,l,f,g={id:"widgets",retry:1500,silent:!0,rawBuffer:!0,appspace:"kemu.",encoding:"hex"};!function(e){e.Browser="browser",e.Cloud="cloud",e.Desktop="desktop"}(o||(o={})),function(e){e[e.Number=0]="Number",e[e.String=1]="String",e[e.ArrayBuffer=2]="ArrayBuffer",e[e.Array=3]="Array",e[e.Boolean=4]="Boolean",e[e.JsonObj=5]="JsonObj",e[e.Anything=6]="Anything",e[e.ImageData=7]="ImageData",e[e.AudioBuffer=8]="AudioBuffer",e[e.Rect=9]="Rect",e[e.Point=10]="Point",e[e.ImageBitmap=11]="ImageBitmap",e[e.BinaryFile=12]="BinaryFile"}(i||(i={})),function(e){e.Number="Number",e.String="String",e.ArrayBuffer="ArrayBuffer",e.Array="Array",e.Boolean="Boolean",e.JsonObj="JsonObj",e.Anything="Anything",e.ImageData="ImageData",e.AudioBuffer="AudioBuffer",e.Rect="Rect",e.Point="Point",e.ImageBitmap="ImageBitmap",e.BinaryFile="BinaryFile"}(s||(s={})),function(e){e.Javascript="js",e.Python="py",e.Executable="exe"}(c||(c={})),function(e){e.IpcAcknowledge="iack:",e.SocketAcknowledge="sack:",e.AcknowledgeResponse="ackr:",e.ServicesListChanged="update-services",e.SendManifest="send-manifest",e.BroadcastStart="broadcast-start",e.BroadcastEnd="broadcast-end",e.AssumeSession="assume:"}(d||(d={})),function(e){e.GetServices="getServices",e.SubscribeToService="subscribeToService",e.UnsubscribeFromService="unsubscribeFromService",e.GetServiceContents="getServiceContents",e.SocketAckResponse="socketAckResponse",e.ShowSecretsConfigScreen="showSecretsConfigScreen",e.GetMappedSecrets="getMappedSecrets",e.GetSecretContexts="getSecretContexts",e.OnParentEvent="onParentEvent",e.GetDefaultState="getDefaultState",e.BroadcastEvent="broadcastEvent",e.HubBroadcastEvent="hubBroadcastEvent",e.ServiceManifest="serviceManifest",e.GetState="getState",e.SetState="setState",e.SetOutputs="setOutputs",e.UIEvent="uiEvent",e.GetSystemInfo="getSystemInfo",e.InitializeInstance="initializeInstance",e.TerminateInstance="terminateInstance",e.UninstallService="uninstallService",e.ChooseDirectoryDialog="chooseDirectoryDialog",e.ChooseFileDialog="chooseFileDialog",e.GetUniqueId="getUniqueId",e.RebootToInstallUpdate="rebootToInstallUpdate"}(u||(u={})),function(e){e.SetDependencyPath="setDependencyPath",e.GetDependencyPath="getDependencyPath"}(l||(l={})),function(e){e.IPC="ipc",e.WS="ws"}(f||(f={}));const y=e=>{try{return JSON.parse(e)}catch(e){return null}},p="undefined"!=typeof window,m={protocolPrefix:4,protocolVersion:1,jsonLength:4,binaryLength:4,fromServiceId:4,toServiceId:4,sentAt:8},h={protocolPrefix:4,txtLength:4},I=Object.values(m).reduce(((e,t)=>e+t),0),v=Object.values(h).reduce(((e,t)=>e+t),0),S=["width","height","colorSpace"],b=(e,t)=>{const n={},r=[];let a=0,o=Array.isArray(e)?[]:{};const i=(e,o)=>{const s=(e=>{const t="undefined"!=typeof Buffer&&e instanceof Buffer,n=e instanceof ArrayBuffer,r=e instanceof Uint8ClampedArray,a=e instanceof Uint8Array,o=e instanceof Int8Array;return t?"Buffer":n?"ArrayBuffer":r?"Uint8ClampedArray":a?"Uint8Array":o?"Int8Array":null})(e);if(!s){if(Array.isArray(e)){const t=[];for(let n=0;n<e.length;n++)t[n]=i(e[n],`${o}[${n}]`);return t}if("object"==typeof e){const t={},n=(e=>{const t=e instanceof Int16Array,n=e instanceof Uint16Array,r=e instanceof Int32Array,a=e instanceof Uint32Array,o=e instanceof Float32Array,i=e instanceof Float64Array,s=e instanceof BigInt64Array,c=e instanceof BigUint64Array;return t?"Int16Array":n?"Uint16Array":r?"Int32Array":a?"Uint32Array":o?"Float32Array":i?"Float64Array":s?"BigInt64Array":c?"BigUint64Array":null})(e);if(n)throw new Error(`Unsupported binary type [${n}] at path "${o}"`);for(const n in e)e.hasOwnProperty(n)||S.includes(n)||console.warn(`Allowing inherited property: ${n} from path: ${o}`),t[n]=i(e[n],`${o.length?`${o}.`:""}${n}`);return t}return e}n[o]={index:a,length:e.byteLength,binaryType:s},"Buffer"===t?r.push(Buffer.from(e)):"ArrayBuffer"===s?r.push(e):r.push(e.buffer),a+=e.byteLength};o=i(e,"");let s=null;if(r.length>1)if("ArrayBuffer"===t){const e=r.reduce(((e,t)=>e+t.byteLength),0),t=new Uint8Array(e);let n=0;for(let e=0;e<r.length;e++)t.set(new Uint8Array(r[e]),n),n+=r[e].byteLength;s=t.buffer}else{s=Buffer.concat(r)}else 1===r.length&&(s=r[0]);return s?{map:n,combinedData:s,sourceCopy:o}:null},w=(e,t,n,r)=>{const a=t.match(/(\[\d+\])|([^[\].]+)/g)||[];let o=e;for(let e=0;e<a.length;e++){let t=a[e];const r=t.startsWith("[")&&t.endsWith("]"),i=e===a.length-1;if(r){t=t.slice(1,-1);const r=parseInt(t,10);if(!Array.isArray(o))throw new Error(`Expected an array at key "${a.slice(0,e).join(".")}" but found an object.`);i?o[r]=n:(o[r]||(o[r]=a[e+1].startsWith("[")?[]:{}),o=o[r])}else i?o[t]=n:(o[t]||(o[t]=a[e+1].startsWith("[")?[]:{}),o=o[t])}return e},A=(e,t,n)=>{const r="undefined"!=typeof Buffer,a=t instanceof Uint8Array;for(const o in n)if(n.hasOwnProperty(o)){const{index:i,length:s,binaryType:c}=n[o];let d=null;if(r&&t instanceof Buffer)switch(c){case"Buffer":d=t.subarray(i,i+s);break;case"ArrayBuffer":d=t.buffer.slice(t.byteOffset,t.byteOffset+t.byteLength).slice(i,i+s);break;case"Uint8Array":d=new Uint8Array(t.subarray(i,i+s));break;case"Uint8ClampedArray":d=new Uint8ClampedArray(t.subarray(i,i+s));break;case"Int8Array":d=new Int8Array(t.subarray(i,i+s))}else if(t instanceof ArrayBuffer||t instanceof Uint8Array)switch(c){case"Buffer":if(r){d=Buffer.from(t.slice(i,i+s));break}case"ArrayBuffer":d=a?t.buffer.slice(t.byteOffset,t.byteOffset+t.byteLength).slice(i,i+s):t.slice(i,i+s);break;case"Uint8Array":d=a?t.slice(i,i+s):new Uint8Array(t.slice(i,i+s));break;case"Uint8ClampedArray":d=new Uint8ClampedArray(t.slice(i,i+s));break;case"Int8Array":d=new Int8Array(t.slice(i,i+s))}d&&w(e,o,d)}return e},B=e=>n(e),L="KMSG",U="KCMD",E=B("klProtocol");var C={encode:(e,t,n)=>{const r={json:e.json},a=b(r.json,"Buffer"),o=a?.combinedData;a&&(r.jsonBinaryMap=a.map,r.json=a.sourceCopy);const i=o?o.byteLength:0,s=JSON.stringify(r),c=Buffer.from(s),d=c.byteLength,u=m.protocolPrefix+m.protocolVersion+m.jsonLength+m.binaryLength+m.fromServiceId+m.toServiceId+m.sentAt+d+i,l=Buffer.alloc(u),f=Date.now();let g=0;return l.write(L,g),g+=m.protocolPrefix,l.writeUInt8(1,g),g+=m.protocolVersion,l.writeUInt32LE(d,g),g+=m.jsonLength,l.writeUInt32LE(i,g),g+=m.binaryLength,l.writeUInt32LE(t,g),g+=m.fromServiceId,l.writeUInt32LE(n,g),g+=m.toServiceId,l.writeBigInt64LE(BigInt(f),g),g+=m.sentAt,c.copy(l,g),g+=d,o&&i&&o.copy(l,g),l},decodeHeader:e=>{let t=0;const n=e.toString("utf-8",t,m.protocolPrefix);if(t+=m.protocolPrefix,n!==L)return null;if(e.byteLength<I)return E(`Received a Partial Header with ${e.byteLength} bytes. Waiting for more data.`),{partialHeader:!0,remaining:null};const r=e.readUInt8(t);t+=m.protocolVersion;const a=e.readUInt32LE(t);t+=m.jsonLength;const o=e.readUInt32LE(t);t+=m.binaryLength;const i=e.readUInt32LE(t);t+=m.fromServiceId;const s=e.readUInt32LE(t);t+=m.toServiceId;const c=e.readBigInt64LE(t);t+=m.sentAt;const d=a+o,u=e.subarray(t,t+d),l=e.subarray(0,I);let f=null;return e.byteLength-I-a-o>0&&(f=e.subarray(I+a+o)),{header:{protocolVersion:r,jsonLength:a,binaryLength:o,fromServiceId:i,toServiceId:s,sentAt:new Date(Number(c)),packages:[u],headerPackage:l},remaining:f}},decodeFullKlMessage:e=>{const t=Buffer.concat(e.packages),n=t.subarray(0,e.jsonLength).toString(),r=t.subarray(e.jsonLength,e.jsonLength+e.binaryLength),a=y(n);if(!a?.json)return E("Invalid JSON in KL message"),null;a.jsonBinaryMap&&r.byteLength&&A(a.json,r,a.jsonBinaryMap);const o=Buffer.concat([e.headerPackage,t]);let i=o,s=null;const c=I+e.jsonLength+e.binaryLength;return o.byteLength>c&&(s=o.subarray(c),i=o.subarray(0,c)),{message:{json:a.json,rawMessage:i},remaining:s}},patchEncodedHeader:(e,t)=>{if(null==t.fromServiceId&&void 0===t.toServiceId)return e;if(e.byteLength<I)return E("Invalid Header Size"),e;let n=0;return n+=m.protocolPrefix,n+=m.protocolVersion,n+=m.jsonLength,n+=m.binaryLength,void 0!==t.fromServiceId&&e.writeUInt32LE(t.fromServiceId,n),n+=m.fromServiceId,void 0!==t.toServiceId&&e.writeUInt32LE(t.toServiceId,n),e},encodeCommand:e=>{let t=0;const n=Buffer.from(e),r=n.byteLength,a=v+r,o=Buffer.alloc(a);return o.write(U,t),t+=h.protocolPrefix,o.writeUint32LE(r,t),t+=h.txtLength,n.copy(o,t),o},decodeCommand:e=>{let t=0;if(e.byteLength<v)return{command:null};const n=e.toString("utf-8",t,h.protocolPrefix);if(t+=h.protocolPrefix,n!==U)return{command:null};const r=e.readUInt32LE(t);t+=h.txtLength;const a=e.toString("utf-8",t,t+r),o=e.byteLength-v-r;let i=null;o>0&&(i=e.subarray(v+r));let s=0;return o<0&&(s=Math.abs(o)),{command:a,remainingData:i,missing:s}}};const D="KMSG",j="KCMD",k=B("klProtocol"),P=new TextEncoder;var x={encode:(e,t,n)=>{const r={json:e.json},a=b(e.json,"ArrayBuffer"),o=a?.combinedData;a&&(r.jsonBinaryMap=a.map,r.json=a.sourceCopy);const i=o?o.byteLength:0,s=JSON.stringify(r),c=P.encode(s),d=c.byteLength,u=new ArrayBuffer(m.protocolPrefix+m.protocolVersion+m.jsonLength+m.binaryLength+m.fromServiceId+m.toServiceId+m.sentAt+d+i),l=new DataView(u),f=new Uint8Array(u),g=Date.now();let y=0;for(let e=0;e<4;++e)f[y++]=D.charCodeAt(e);return l.setUint8(y,1),y+=m.protocolVersion,l.setUint32(y,d,!0),y+=m.jsonLength,l.setUint32(y,i,!0),y+=m.binaryLength,l.setUint32(y,t,!0),y+=m.fromServiceId,l.setUint32(y,n,!0),y+=m.toServiceId,l.setBigInt64(y,BigInt(g),!0),y+=m.sentAt,f.set(c,y),y+=d,o&&i&&f.set(new Uint8Array(o),y),u},decodeHeader:e=>{const t=new DataView(e);let n=0,r="";for(let e=0;e<m.protocolPrefix;++e)r+=String.fromCharCode(t.getUint8(n++));if(r!==D)return null;if(e.byteLength<I)return k.log(`Received a Partial Header with ${e.byteLength} bytes. Waiting for more data.`),{partialHeader:!0,remaining:null};const a=t.getUint8(n);n+=m.protocolVersion;const o=t.getUint32(n,!0);n+=m.jsonLength;const i=t.getUint32(n,!0);n+=m.binaryLength;const s=t.getUint32(n,!0);n+=m.fromServiceId;const c=t.getUint32(n,!0);n+=m.toServiceId;const d=t.getBigInt64(n,!0);n+=m.sentAt;const u=o+i,l=e.slice(n,n+u),f=new Uint8Array(e,0,I);let g=null;if(e.byteLength-I-o-i>0){g=new Uint8Array(e,I+o+i).slice().buffer}return{header:{protocolVersion:a,jsonLength:o,binaryLength:i,fromServiceId:s,toServiceId:c,sentAt:new Date(Number(d)),packages:[l],headerPackage:f.slice().buffer},remaining:g}},decodeFullKlMessage:e=>{const t=e.packages.reduce(((e,t)=>e+t.byteLength),0),n=new Uint8Array(t);let r,a=0;for(const t of e.packages)r=new Uint8Array(t),n.set(r,a),a+=r.byteLength;const o=(new TextDecoder).decode(n.subarray(0,e.jsonLength)),i=n.subarray(e.jsonLength,e.jsonLength+e.binaryLength),s=y(o);if(!s?.json)return k.log("Invalid JSON in KL message"),null;s.jsonBinaryMap&&i.byteLength&&A(s.json,i,s.jsonBinaryMap);const c=new Uint8Array(e.headerPackage.byteLength+n.byteLength);c.set(new Uint8Array(e.headerPackage),0),c.set(n,e.headerPackage.byteLength);let d=c,u=null;const l=I+e.jsonLength+e.binaryLength;return c.byteLength>l&&(u=c.subarray(l),d=c.subarray(0,l)),{message:{json:s.json,...i.length?{binaryData:i.buffer}:{},rawMessage:d.buffer},remaining:u?.buffer??null}},patchEncodedHeader:(e,t)=>{if(null==t.fromServiceId&&void 0===t.toServiceId)return e;if(e.byteLength<I)return k("Invalid Header Size"),e;let n=0;n+=m.protocolPrefix,n+=m.protocolVersion,n+=m.jsonLength,n+=m.binaryLength;const r=new DataView(e);return void 0!==t.fromServiceId&&r.setUint32(n,t.fromServiceId,!0),n+=m.fromServiceId,void 0!==t.toServiceId&&r.setUint32(n,t.toServiceId,!0),e},encodeCommand:e=>{let t=0;const n=P.encode(e),r=n.byteLength,a=new ArrayBuffer(v+r),o=new DataView(a),i=new Uint8Array(a);for(let e=0;e<4;++e)i[t++]=j.charCodeAt(e);return o.setUint32(t,r,!0),t+=h.txtLength,i.set(n,t),a},decodeCommand:e=>{const t=new DataView(e);let n=0;if(e.byteLength<v)return{command:null};let r="";for(let e=0;e<h.protocolPrefix;++e)r+=String.fromCharCode(t.getUint8(n++));if(r!==j)return{command:null};const a=t.getUint32(n,!0);n+=h.txtLength;const o=e.byteLength-v-a,i=new Uint8Array(e,n,Math.min(a,e.byteLength-v)),s=(new TextDecoder).decode(i);let c=null;o>0&&(c=e.slice(v+a));let d=0;return o<0&&(d=Math.abs(o)),{command:s,remainingData:c,missing:d}}};const $=B("klTransmissionManager");let R=C;p&&(R=x);var M=R;let N,O,T,F,H=null;const _=(()=>{const e=(t,n,r,a)=>{let o=n,i=null;const s=t instanceof ArrayBuffer;if($(`RAW: ${t.toString()}`),!o||o.partialHeaderData){let c;if(s?(c=o?.partialHeaderData?new Uint8Array([...new Uint8Array(o.partialHeaderData),...new Uint8Array(t)]).buffer:t,i=x.decodeHeader(c)):(c=o?.partialHeaderData?Buffer.concat([o.partialHeaderData,t]):t,i=C.decodeHeader(c)),!i){const{command:t,missing:o,remainingData:i}=s?x.decodeCommand(c):C.decodeCommand(c);return t?a({command:t,complete:!0,rawMessage:c}):$(o?`ERROR: Missing ${o} bytes to complete the command. This partial command will be aborted.`:`ERROR: Invalid state, message was decoded without a header or partial header data. Discarding ${c.byteLength} bytes`),i?($(`${i.byteLength} bytes remain after processing command. Re-analyzing...`),e(i,n,r,a)):void 0}if(i.partialHeader)return o={firstPackageAt:Date.now(),partialHeaderData:c},r(o);if(!i.header)return $(`ERROR: Invalid state, message was decoded without a header or partial header data. Discarding ${c.byteLength} bytes`);const d=i.header;o={firstPackageAt:Date.now(),header:{...d,totalBytesReceived:d.packages[0].byteLength,totalBytesExpected:d.binaryLength+d.jsonLength,remaining:i.remaining}},r(o)}else o.header&&o.header.totalBytesReceived<o.header.totalBytesExpected&&(o.header.packages.push(t),o.header.totalBytesReceived+=t.byteLength,r(o));if(o.header&&o.header.totalBytesReceived>=o.header.totalBytesExpected){const t=Date.now()-o.header.sentAt.getTime(),n=Date.now()-o.firstPackageAt;$(`Received ${o.header.totalBytesReceived} of ${o.header.totalBytesExpected} expected in ${t} ms, elapsed since first package: ${n}ms`);const i=s?x.decodeFullKlMessage(o.header):C.decodeFullKlMessage(o.header),c=o.header.totalBytesReceived,d=o.header.remaining;r(null),i&&a({klMessage:i.message,complete:!0,sourceServiceId:o.header.fromServiceId,targetServiceId:o.header.toServiceId,rawMessage:i.message.rawMessage});let u=d;if(i?.remaining&&(u=s?d?((e,t)=>{const n=e.byteLength+t.byteLength,r=new ArrayBuffer(n),a=new Uint8Array(e),o=new Uint8Array(t),i=new Uint8Array(r);return i.set(a),i.set(o,a.length),r})(d,i.remaining):i.remaining:d?Buffer.concat([d,i.remaining]):i.remaining),u)return $(`${u.byteLength} bytes remaining after processing message with ${c} bytes of data. Re-analyzing...`),e(u,null,r,a)}};return e})(),V=B("ipcClient"),G=e=>{const n=g.id;t.of[n].emit(e)};var K,W={connect:e=>{g.id=e?.id||g.id,g.appspace=e?.appSpace||g.appspace,t.config={...t.config,...g};const n=g.id;t.connectTo(n,(()=>{t.of[n].on("connect",(()=>{V("Connected to server"),H=null,O&&O()})),t.of[n].on("data",(e=>{_(e,H,(e=>H=e),(e=>{if(e.complete)return e.command?(V(`Received command: ${e.command}`),void(N&&N(e.command))):void(e.klMessage&&T&&T({send:G,transmission:{sourceServiceId:e.sourceServiceId??-1,targetServiceId:e.targetServiceId??-1,rawMessage:e.rawMessage},json:e.klMessage.json}))}))})),t.of[n].on("disconnect",(()=>{V(`Disconnected from ${n}`),H=null,F&&F()}))}))},sendCommand:e=>{const n=g.id,r=M.encodeCommand(e);t.of[n].emit(r)},sendBuffer:G,onCommand:e=>N=e,onMessageReceived:e=>T=e,onClientConnected:e=>O=e,onClientDisconnected:e=>F=e};!function(e){e.FunctionNotFound="FNC_NOT_FOUND",e.ParentEventCallbackError="PARENT_EVENT_CALLBACK_ERROR"}(K||(K={}));const J=3e4;let z=Math.ceil(Date.now()/1e3);function q(e){const t={};let n=console.log;const r={};let a=e||String(Date.now());const o={},i=e=>!o[e],s=(e,t,n,r,a,o)=>{let s=p?new ArrayBuffer(0):Buffer.alloc(0);const c={json:{functionName:e,args:o.success?o.success:[o],messageId:t,type:o.success?"response":"error"}};return i(r)&&(s=M.encode(c,n,r)),a(s,{msg:c,sourceServiceId:n,targetServiceId:r})};return{setLogger:e=>{n=e},processMessage:(e,a,o,i)=>{if(!i)return!1;const c=i;if(t[c.messageId]){const e=t[c.messageId];return e&&(clearTimeout(e.timer),e.fulfilled||(e.fulfilled=!0,"response"===c.type?e.resolve(c.args):"error"===c.type&&e.reject(c.args[0])),delete t[c.messageId]),!0}if("execute"!==c.type&&n&&n(`No pending execution found for message id "${c.messageId}"`),"execute"===c.type){const t=r[c.functionName];if(t){const n=e=>{s(c.functionName,c.messageId,o.targetServiceId,o.sourceServiceId,a,e)};t({transport:e,args:c.args,reply:n,messageId:c.messageId,sourceServiceId:o.sourceServiceId,send:a})}else{const e=`Function "${c.functionName}" not found.`;n&&n(e),s(c.functionName,c.messageId,o.targetServiceId,o.sourceServiceId,a,{error:e,errCode:"FNC_NOT_FOUND"})}return!0}return!1},execute:async(e,r,o,s,c,d)=>{if(!o){const e="No send buffer function provided.";throw n&&n(e),e}z+=1;const u=`${a}-${z}-exec-${e.substring(0,10)}`,l={messageId:u,functionName:e,send:o,sourceServiceId:s,targetServiceId:c,args:r||[],fulfilled:!1,resolve:()=>{},reject:()=>{}};l.promise=new Promise(((e,t)=>{l.resolve=e,l.reject=t}));let f=p?new ArrayBuffer(0):Buffer.alloc(0);const g={json:{functionName:e,args:r,messageId:u,type:"execute"}};i(c)&&(f=M.encode(g,s,c)),t[u]=l,n&&n(`Calling remote function "${e}" with message id "${u}"`);const y="true"===process.env.NO_INVOKE_TIMEOUT;return d?.async?(l.fulfilled=!0,l.resolve([void 0]),delete t[u]):0===d?.timeout||y||(l.timer=setTimeout((()=>{n&&n(`Remote function ${u} timed out`);const r=t[u];r&&!r.fulfilled&&(r.fulfilled=!0,l.reject(`Function ${e} Timed out`)),delete t[u]}),d?.timeout||J)),o(f,{sourceServiceId:s,targetServiceId:c,msg:g}),l.promise},sendResponse:s,registerFunction:(e,t)=>{r[e]=t},getTransportSendFunction:e=>{const n=t[e];return n?n.send:null},setServiceName:e=>{a=e},getPendingExecutions:()=>t,rejectAllPending:e=>{Object.keys(t).forEach((n=>{const r=t[n];r&&!r.fulfilled&&(clearTimeout(r.timer),r.fulfilled=!0,r.reject(e),delete t[n])}))},broadcast:(e,t,r,o)=>{z+=1;const s=`${a}-${z}-multicast-${e.substring(0,10)}`;let c=p?new ArrayBuffer(0):Buffer.alloc(0);const d={json:{functionName:e,args:t,messageId:s,type:"execute"}};let u=i(r[0].serviceId);u&&(c=M.encode(d,o,r[0].serviceId));for(let t=0;t<r.length;t++)try{const a=r[t];n&&n(`Broadcasting function "${e}" with message id "${s}" to client [${a.serviceId}]`),0!==t&&(u=i(a.serviceId),u&&(c=M.patchEncodedHeader(c,{toServiceId:a.serviceId}))),a.sendFn(c,{msg:d,sourceServiceId:o,targetServiceId:a.serviceId})}catch(e){n&&n(`Error broadcasting to client at index ${t}`)}},disableServiceEncoding:(e,t)=>{o[e]=t}}}const Q=(e,t,n,r="srgb")=>{let a;return a=e instanceof Uint8ClampedArray?e:new Uint8ClampedArray(e),{data:a,width:t,height:n,colorSpace:r,_kemuType:i.ImageData}},X=0,Y=B("kemuWidgetService"),Z=a(process.argv.slice(2));function ee(t){const n={},a=process.env.KEMU_WIDGET_SESSION_ID;let o,i,s,c=!1;const g={};let p,m,h,I,v,S,b,w=null;const A=new q;A.setLogger(Y);n.start=async(n,d)=>{const l=n||e.resolve(e.dirname(process.argv[1]),"manifest.json");s=e.dirname(l);const g=await r(l,"utf-8"),p=y(g);if(!p)throw new Error("Error parsing manifest file.");let m;if(p.inputs||(p.inputs=[]),p.outputs||(p.outputs=[]),p.widgetUI)try{m=await r(e.join(s,"widgetUI.js"))}catch(e){Y(`Error loading widgetUI file ${p.name}: ${e}`)}if(p.svgIcon)try{const t=await r(e.join(s,p.svgIcon),"utf-8");p.svgIcon=t}catch(e){Y(`Error loading icon for service ${p.name}: ${e}`)}i=((e,t,n)=>({...e,path:t,...e.widgetUI&&n?.widgetUIContents?{widgetUIContents:n.widgetUIContents}:{}}))(p,s,{widgetUIContents:m}),c=i.name.startsWith("test."),i.path=s,i.internal=Z.internal||!1,c?Y("Starting Kemu Service in Dev mode"):((e=>{const t=e||Z.sessionId||a;if(!t)throw new Error("Missing sessionId. Expected service to be launched with a sessionId as first argument, or the KEMU_WIDGET_SESSION_ID environment variable to be set.");o=parseInt(String(t))})(d),Y(`Starting Kemu Service with session id: ${o}`)),A.setServiceName(`${i.name}_${i.version}`),W.onCommand(B),W.onMessageReceived((({json:e,transmission:t})=>A.processMessage(f.IPC,W.sendBuffer,t,e))),A.registerFunction(u.OnParentEvent,U),A.registerFunction(u.GetDefaultState,L),A.registerFunction(u.UIEvent,D),A.registerFunction(u.InitializeInstance,E),A.registerFunction(u.TerminateInstance,C),W.onClientConnected((()=>{b&&b()})),W.onClientDisconnected((()=>{c&&(o=void 0)})),W.connect({appSpace:Z.ipcSpace||t?.ipc?.appSpace,id:Z.ipcId||t?.ipc?.id})};const B=e=>{((e,t)=>{const n=d.SocketAcknowledge,r=d.IpcAcknowledge,a=e.startsWith(n),o=e.startsWith(r);if(a||o){const o=e.split(a?n:r),i=parseInt(o[1]);return t&&t(i),i}})(e,(e=>{W.sendCommand(((e,t)=>`${d.AcknowledgeResponse}${e}:${t||""}`)(e,o||void 0)),!o&&c&&(Y("Dev mode detected, assuming service session id from ack request:",e),o=e)})),((e,t)=>{e===d.BroadcastStart&&t()})(e,(()=>{h&&h()})),((e,t)=>{e===d.BroadcastEnd&&t()})(e,(()=>{I&&I()})),((e,t)=>{e===d.SendManifest&&t()})(e,(()=>{Y("Sending manifest to hub"),o?A.execute(u.ServiceManifest,[{...i,devMode:c}],W.sendBuffer,o,0,{async:!0}):Y("Service session id is not set. Cannot send manifest.")})),((e,t)=>{if(e.startsWith(d.AssumeSession)){const n=e.split(d.AssumeSession);return t(parseInt(n[1])),!0}})(e,(e=>{o=e,Y(`Assumed session id ${e}`)}))},L=async e=>{if(m){const t=await m();return e.reply({success:[t]})}return e.reply({success:[{}]})},U=async e=>{if(p){const t=e.args[0],{source:n,target:r,data:a,recipeId:i,currentState:s,targetVariantId:c}=t;if(!o)return void Y("Service session id is not set. Cannot process parent event.");if(!n||!r||!a)return e.reply({error:"Invalid arguments, expected [source, target, data, context]"});const d=W.sendBuffer,l={currentState:s,type:r.widgetType,widgetId:r.widgetId,variantId:c,recipeId:i,getState:async()=>{const t=[r.widgetId,i];return A.execute(u.GetState,t,d,o,e.sourceServiceId)},setState:async t=>{const n={widgetId:r.widgetId,variantId:c,recipeId:i,newState:t};return A.execute(u.SetState,[n],d,o,e.sourceServiceId)},setOutputs:async(t,n)=>{const a={widgetId:r.widgetId,recipeId:i,outputs:t,finalState:n};await A.execute(u.SetOutputs,[a],d,o,e.sourceServiceId,{timeout:0})}};Y(`Invoking user-defined onParentEvent callback for event id "${e.messageId}"`),await p({data:a,source:n,target:r},l).then((()=>{Y(`Replying SUCCESS to event id "${e.messageId}"`),e.reply({success:[]})})).catch((t=>{const n="string"==typeof t?t:t.message||t;Y(`Error invoking onParentEvent callback: ${n}`),e.reply({error:n,errCode:"PARENT_EVENT_CALLBACK_ERROR"})}))}},E=async e=>{const[{currentState:t,recipeId:n,widgetId:r,variantId:a,recipeType:o,currentDependencies:i}]=e.args;if(g[r]={currentRecipeId:n,variantId:a,currentSourceServiceId:e.sourceServiceId},v){const s={currentState:t,recipeId:n,widgetId:r,variantId:a,recipeType:o,currentDependencies:i||{}},c=await v(s);e.reply({success:[c]})}else e.reply({error:"Not implemented",errCode:"FNC_NOT_FOUND"})},C=async e=>{if(S){const[{currentState:t,recipeId:n,widgetId:r,variantId:a}]=e.args,o={currentState:t,recipeId:n,widgetId:r,variantId:a};await S(o),delete g[r]}e.reply({success:[]})},D=async e=>{if(w)try{const t=await w.apply(void 0,e.args);return e.reply({success:[t]})}catch(t){const n="string"==typeof t?t:JSON.stringify(t);return Y(`Error invoking UI Event handler: ${n}`),e.reply({error:n})}e.reply({error:"UI Events are not supported in this service."})};return n.broadcast=async(e,t)=>{if(!i.eventEmitter)throw new Error("This service does not support broadcasting events. Please set `eventEmitter` to true in your manifest file.");if(!o)return void Y("Service session id is not set. Cannot broadcast event.");const n=[{outputs:e,variantId:t}];await A.execute(u.BroadcastEvent,n,W.sendBuffer,o,0,{async:!0})},n.addDependencyPath=async(e,t,n)=>{if(!o)throw new Error("Not yet registered with the Hub");const r=g[n];if(!r.currentSourceServiceId||!r.currentRecipeId)throw new Error("Cannot invoke this method before initialization");const a={key:e,path:t,recipeId:r.currentRecipeId,widgetId:n};Y(`Adding dependency path for key "${e}" with path "${t}"`),await A.execute(l.SetDependencyPath,[a],W.sendBuffer,o,r.currentSourceServiceId)},n.getDependencyPath=async(e,t)=>{if(!o)throw new Error("Not yet registered with the Hub");const n=g[t];if(!n.currentSourceServiceId||!n.currentRecipeId)throw new Error("Cannot invoke this method before initialization");Y("Getting dependency path for key:",e);const r={key:e,recipeId:n.currentRecipeId,widgetId:t},[a]=await A.execute(l.GetDependencyPath,[r],W.sendBuffer,o,n.currentSourceServiceId);return Y("Dependency path response:",a),a},n.getUniqueId=async()=>{if(!o)throw new Error("Not yet registered with the Hub");const[e]=await A.execute(u.GetUniqueId,[],W.sendBuffer,o,0);return e},n.resolveRuntimeDependencyPath=t=>{if(!Z.recipePath)throw new Error("Cannot resolve runtime dependency without a recipe path. Missing [--recipePath] argument.");return e.resolve(Z.recipePath,t)},n.onGetDefaultState=e=>{m=e},n.onParentEvent=e=>{p=e},n.onTerminate=e=>{S=e},n.onInitialize=e=>{v=e},n.onConnected=e=>{b=e},n.onStartBroadcast=e=>{h=e},n.onStopBroadcast=e=>{I=e},n.onUIEvent=e=>{w=e},Z.internal&&(n.executeHubFunction=async(e,t,n)=>{if(o)return A.execute(e,t,W.sendBuffer,o,0,n);Y("Service session id is not set. Cannot execute hub function.")}),n._getRemoteInvoker=()=>A,n}export{i as DataType,X as KemuHubServiceId,Q as createImageDataLike,ee as default};
1
+ import e from"path";import t from"node-ipc";import n from"debug";import{readFile as r}from"fs/promises";import a from"minimist";var o,i,s,c,d,u,l,f,g={id:"widgets",retry:1500,silent:!0,rawBuffer:!0,appspace:"kemu.",encoding:"hex"};!function(e){e.Browser="browser",e.Cloud="cloud",e.Desktop="desktop"}(o||(o={})),function(e){e[e.Number=0]="Number",e[e.String=1]="String",e[e.ArrayBuffer=2]="ArrayBuffer",e[e.Array=3]="Array",e[e.Boolean=4]="Boolean",e[e.JsonObj=5]="JsonObj",e[e.Anything=6]="Anything",e[e.ImageData=7]="ImageData",e[e.AudioBuffer=8]="AudioBuffer",e[e.Rect=9]="Rect",e[e.Point=10]="Point",e[e.ImageBitmap=11]="ImageBitmap",e[e.BinaryFile=12]="BinaryFile"}(i||(i={})),function(e){e.Number="Number",e.String="String",e.ArrayBuffer="ArrayBuffer",e.Array="Array",e.Boolean="Boolean",e.JsonObj="JsonObj",e.Anything="Anything",e.ImageData="ImageData",e.AudioBuffer="AudioBuffer",e.Rect="Rect",e.Point="Point",e.ImageBitmap="ImageBitmap",e.BinaryFile="BinaryFile"}(s||(s={})),function(e){e.Javascript="js",e.Python="py",e.Executable="exe"}(c||(c={})),function(e){e.IpcAcknowledge="iack:",e.SocketAcknowledge="sack:",e.AcknowledgeResponse="ackr:",e.ServicesListChanged="update-services",e.SendManifest="send-manifest",e.BroadcastStart="broadcast-start",e.BroadcastEnd="broadcast-end",e.AssumeSession="assume:"}(d||(d={})),function(e){e.GetServices="getServices",e.SubscribeToService="subscribeToService",e.UnsubscribeFromService="unsubscribeFromService",e.GetServiceContents="getServiceContents",e.SocketAckResponse="socketAckResponse",e.ShowSecretsConfigScreen="showSecretsConfigScreen",e.GetMappedSecrets="getMappedSecrets",e.GetSecretContexts="getSecretContexts",e.OnParentEvent="onParentEvent",e.GetDefaultState="getDefaultState",e.BroadcastEvent="broadcastEvent",e.HubBroadcastEvent="hubBroadcastEvent",e.ServiceManifest="serviceManifest",e.GetState="getState",e.SetState="setState",e.SetOutputs="setOutputs",e.UIEvent="uiEvent",e.GetSystemInfo="getSystemInfo",e.InitializeInstance="initializeInstance",e.TerminateInstance="terminateInstance",e.UninstallService="uninstallService",e.ChooseDirectoryDialog="chooseDirectoryDialog",e.ChooseFileDialog="chooseFileDialog",e.GetUniqueId="getUniqueId",e.RebootToInstallUpdate="rebootToInstallUpdate",e.GetFileContentFromCacheId="getFileContentFromCacheId"}(u||(u={})),function(e){e.SetDependencyPath="setDependencyPath",e.GetDependencyPath="getDependencyPath"}(l||(l={})),function(e){e.IPC="ipc",e.WS="ws"}(f||(f={}));const y=e=>{try{return JSON.parse(e)}catch(e){return null}},p="undefined"!=typeof window,m={protocolPrefix:4,protocolVersion:1,jsonLength:4,binaryLength:4,fromServiceId:4,toServiceId:4,sentAt:8},h={protocolPrefix:4,txtLength:4},I=Object.values(m).reduce(((e,t)=>e+t),0),v=Object.values(h).reduce(((e,t)=>e+t),0),S=["width","height","colorSpace"],w=(e,t)=>{const n={},r=[];let a=0,o=Array.isArray(e)?[]:{};const i=(e,o)=>{const s=(e=>{const t="undefined"!=typeof Buffer&&e instanceof Buffer,n=e instanceof ArrayBuffer,r=e instanceof Uint8ClampedArray,a=e instanceof Uint8Array,o=e instanceof Int8Array;return t?"Buffer":n?"ArrayBuffer":r?"Uint8ClampedArray":a?"Uint8Array":o?"Int8Array":null})(e);if(!s){if(Array.isArray(e)){const t=[];for(let n=0;n<e.length;n++)t[n]=i(e[n],`${o}[${n}]`);return t}if("object"==typeof e){const t={},n=(e=>{const t=e instanceof Int16Array,n=e instanceof Uint16Array,r=e instanceof Int32Array,a=e instanceof Uint32Array,o=e instanceof Float32Array,i=e instanceof Float64Array,s=e instanceof BigInt64Array,c=e instanceof BigUint64Array;return t?"Int16Array":n?"Uint16Array":r?"Int32Array":a?"Uint32Array":o?"Float32Array":i?"Float64Array":s?"BigInt64Array":c?"BigUint64Array":null})(e);if(n)throw new Error(`Unsupported binary type [${n}] at path "${o}"`);for(const n in e)Object.hasOwn(e,n)||S.includes(n)||console.warn(`Allowing inherited property: ${n} from path: ${o}`),t[n]=i(e[n],`${o.length?`${o}.`:""}${n}`);return t}return e}n[o]={index:a,length:e.byteLength,binaryType:s},"Buffer"===t?r.push(Buffer.from(e)):"ArrayBuffer"===s?r.push(e):r.push(e.buffer),a+=e.byteLength};o=i(e,"");let s=null;if(r.length>1)if("ArrayBuffer"===t){const e=r.reduce(((e,t)=>e+t.byteLength),0),t=new Uint8Array(e);let n=0;for(let e=0;e<r.length;e++)t.set(new Uint8Array(r[e]),n),n+=r[e].byteLength;s=t.buffer}else{s=Buffer.concat(r)}else 1===r.length&&(s=r[0]);return s?{map:n,combinedData:s,sourceCopy:o}:null},b=(e,t,n,r)=>{const a=t.match(/(\[\d+\])|([^[\].]+)/g)||[];let o=e;for(let e=0;e<a.length;e++){let t=a[e];const r=t.startsWith("[")&&t.endsWith("]"),i=e===a.length-1;if(r){t=t.slice(1,-1);const r=parseInt(t,10);if(!Array.isArray(o))throw new Error(`Expected an array at key "${a.slice(0,e).join(".")}" but found an object.`);i?o[r]=n:(o[r]||(o[r]=a[e+1].startsWith("[")?[]:{}),o=o[r])}else i?o[t]=n:(o[t]||(o[t]=a[e+1].startsWith("[")?[]:{}),o=o[t])}return e},A=(e,t,n)=>{const r="undefined"!=typeof Buffer,a=t instanceof Uint8Array;for(const o in n)if(Object.hasOwn(n,o)){const{index:i,length:s,binaryType:c}=n[o];let d=null;if(r&&t instanceof Buffer)switch(c){case"Buffer":d=t.subarray(i,i+s);break;case"ArrayBuffer":d=t.buffer.slice(t.byteOffset,t.byteOffset+t.byteLength).slice(i,i+s);break;case"Uint8Array":d=new Uint8Array(t.subarray(i,i+s));break;case"Uint8ClampedArray":d=new Uint8ClampedArray(t.subarray(i,i+s));break;case"Int8Array":d=new Int8Array(t.subarray(i,i+s))}else if(t instanceof ArrayBuffer||t instanceof Uint8Array)switch(c){case"Buffer":if(r){d=Buffer.from(t.slice(i,i+s));break}case"ArrayBuffer":d=a?t.buffer.slice(t.byteOffset,t.byteOffset+t.byteLength).slice(i,i+s):t.slice(i,i+s);break;case"Uint8Array":d=a?t.slice(i,i+s):new Uint8Array(t.slice(i,i+s));break;case"Uint8ClampedArray":d=new Uint8ClampedArray(t.slice(i,i+s));break;case"Int8Array":d=new Int8Array(t.slice(i,i+s))}d&&b(e,o,d)}return e},B=e=>n(e),L="KMSG",U="KCMD",E=B("klProtocol");var C={encode:(e,t,n)=>{const r={json:e.json},a=w(r.json,"Buffer"),o=a?.combinedData;a&&(r.jsonBinaryMap=a.map,r.json=a.sourceCopy);const i=o?o.byteLength:0,s=JSON.stringify(r),c=Buffer.from(s),d=c.byteLength,u=m.protocolPrefix+m.protocolVersion+m.jsonLength+m.binaryLength+m.fromServiceId+m.toServiceId+m.sentAt+d+i,l=Buffer.alloc(u),f=Date.now();let g=0;return l.write(L,g),g+=m.protocolPrefix,l.writeUInt8(1,g),g+=m.protocolVersion,l.writeUInt32LE(d,g),g+=m.jsonLength,l.writeUInt32LE(i,g),g+=m.binaryLength,l.writeUInt32LE(t,g),g+=m.fromServiceId,l.writeUInt32LE(n,g),g+=m.toServiceId,l.writeBigInt64LE(BigInt(f),g),g+=m.sentAt,c.copy(l,g),g+=d,o&&i&&o.copy(l,g),l},decodeHeader:e=>{let t=0;const n=e.toString("utf-8",t,m.protocolPrefix);if(t+=m.protocolPrefix,n!==L)return null;if(e.byteLength<I)return E(`Received a Partial Header with ${e.byteLength} bytes. Waiting for more data.`),{partialHeader:!0,remaining:null};const r=e.readUInt8(t);t+=m.protocolVersion;const a=e.readUInt32LE(t);t+=m.jsonLength;const o=e.readUInt32LE(t);t+=m.binaryLength;const i=e.readUInt32LE(t);t+=m.fromServiceId;const s=e.readUInt32LE(t);t+=m.toServiceId;const c=e.readBigInt64LE(t);t+=m.sentAt;const d=a+o,u=e.subarray(t,t+d),l=e.subarray(0,I);let f=null;return e.byteLength-I-a-o>0&&(f=e.subarray(I+a+o)),{header:{protocolVersion:r,jsonLength:a,binaryLength:o,fromServiceId:i,toServiceId:s,sentAt:new Date(Number(c)),packages:[u],headerPackage:l},remaining:f}},decodeFullKlMessage:e=>{const t=Buffer.concat(e.packages),n=t.subarray(0,e.jsonLength).toString(),r=t.subarray(e.jsonLength,e.jsonLength+e.binaryLength),a=y(n);if(!a?.json)return E("Invalid JSON in KL message"),null;a.jsonBinaryMap&&r.byteLength&&A(a.json,r,a.jsonBinaryMap);const o=Buffer.concat([e.headerPackage,t]);let i=o,s=null;const c=I+e.jsonLength+e.binaryLength;return o.byteLength>c&&(s=o.subarray(c),i=o.subarray(0,c)),{message:{json:a.json,rawMessage:i},remaining:s}},patchEncodedHeader:(e,t)=>{if(null==t.fromServiceId&&void 0===t.toServiceId)return e;if(e.byteLength<I)return E("Invalid Header Size"),e;let n=0;return n+=m.protocolPrefix,n+=m.protocolVersion,n+=m.jsonLength,n+=m.binaryLength,void 0!==t.fromServiceId&&e.writeUInt32LE(t.fromServiceId,n),n+=m.fromServiceId,void 0!==t.toServiceId&&e.writeUInt32LE(t.toServiceId,n),e},encodeCommand:e=>{let t=0;const n=Buffer.from(e),r=n.byteLength,a=v+r,o=Buffer.alloc(a);return o.write(U,t),t+=h.protocolPrefix,o.writeUint32LE(r,t),t+=h.txtLength,n.copy(o,t),o},decodeCommand:e=>{let t=0;if(e.byteLength<v)return{command:null};const n=e.toString("utf-8",t,h.protocolPrefix);if(t+=h.protocolPrefix,n!==U)return{command:null};const r=e.readUInt32LE(t);t+=h.txtLength;const a=e.toString("utf-8",t,t+r),o=e.byteLength-v-r;let i=null;o>0&&(i=e.subarray(v+r));let s=0;return o<0&&(s=Math.abs(o)),{command:a,remainingData:i,missing:s}}};const D="KMSG",j="KCMD",k=B("klProtocol"),x=new TextEncoder;var P={encode:(e,t,n)=>{const r={json:e.json},a=w(e.json,"ArrayBuffer"),o=a?.combinedData;a&&(r.jsonBinaryMap=a.map,r.json=a.sourceCopy);const i=o?o.byteLength:0,s=JSON.stringify(r),c=x.encode(s),d=c.byteLength,u=new ArrayBuffer(m.protocolPrefix+m.protocolVersion+m.jsonLength+m.binaryLength+m.fromServiceId+m.toServiceId+m.sentAt+d+i),l=new DataView(u),f=new Uint8Array(u),g=Date.now();let y=0;for(let e=0;e<4;++e)f[y++]=D.charCodeAt(e);return l.setUint8(y,1),y+=m.protocolVersion,l.setUint32(y,d,!0),y+=m.jsonLength,l.setUint32(y,i,!0),y+=m.binaryLength,l.setUint32(y,t,!0),y+=m.fromServiceId,l.setUint32(y,n,!0),y+=m.toServiceId,l.setBigInt64(y,BigInt(g),!0),y+=m.sentAt,f.set(c,y),y+=d,o&&i&&f.set(new Uint8Array(o),y),u},decodeHeader:e=>{const t=new DataView(e);let n=0,r="";for(let e=0;e<m.protocolPrefix;++e)r+=String.fromCharCode(t.getUint8(n++));if(r!==D)return null;if(e.byteLength<I)return k.log(`Received a Partial Header with ${e.byteLength} bytes. Waiting for more data.`),{partialHeader:!0,remaining:null};const a=t.getUint8(n);n+=m.protocolVersion;const o=t.getUint32(n,!0);n+=m.jsonLength;const i=t.getUint32(n,!0);n+=m.binaryLength;const s=t.getUint32(n,!0);n+=m.fromServiceId;const c=t.getUint32(n,!0);n+=m.toServiceId;const d=t.getBigInt64(n,!0);n+=m.sentAt;const u=o+i,l=e.slice(n,n+u),f=new Uint8Array(e,0,I);let g=null;if(e.byteLength-I-o-i>0){g=new Uint8Array(e,I+o+i).slice().buffer}return{header:{protocolVersion:a,jsonLength:o,binaryLength:i,fromServiceId:s,toServiceId:c,sentAt:new Date(Number(d)),packages:[l],headerPackage:f.slice().buffer},remaining:g}},decodeFullKlMessage:e=>{const t=e.packages.reduce(((e,t)=>e+t.byteLength),0),n=new Uint8Array(t);let r,a=0;for(const t of e.packages)r=new Uint8Array(t),n.set(r,a),a+=r.byteLength;const o=(new TextDecoder).decode(n.subarray(0,e.jsonLength)),i=n.subarray(e.jsonLength,e.jsonLength+e.binaryLength),s=y(o);if(!s?.json)return k.log("Invalid JSON in KL message"),null;s.jsonBinaryMap&&i.byteLength&&A(s.json,i,s.jsonBinaryMap);const c=new Uint8Array(e.headerPackage.byteLength+n.byteLength);c.set(new Uint8Array(e.headerPackage),0),c.set(n,e.headerPackage.byteLength);let d=c,u=null;const l=I+e.jsonLength+e.binaryLength;return c.byteLength>l&&(u=c.subarray(l),d=c.subarray(0,l)),{message:{json:s.json,...i.length?{binaryData:i.buffer}:{},rawMessage:d.buffer},remaining:u?.buffer??null}},patchEncodedHeader:(e,t)=>{if(null==t.fromServiceId&&void 0===t.toServiceId)return e;if(e.byteLength<I)return k("Invalid Header Size"),e;let n=0;n+=m.protocolPrefix,n+=m.protocolVersion,n+=m.jsonLength,n+=m.binaryLength;const r=new DataView(e);return void 0!==t.fromServiceId&&r.setUint32(n,t.fromServiceId,!0),n+=m.fromServiceId,void 0!==t.toServiceId&&r.setUint32(n,t.toServiceId,!0),e},encodeCommand:e=>{let t=0;const n=x.encode(e),r=n.byteLength,a=new ArrayBuffer(v+r),o=new DataView(a),i=new Uint8Array(a);for(let e=0;e<4;++e)i[t++]=j.charCodeAt(e);return o.setUint32(t,r,!0),t+=h.txtLength,i.set(n,t),a},decodeCommand:e=>{const t=new DataView(e);let n=0;if(e.byteLength<v)return{command:null};let r="";for(let e=0;e<h.protocolPrefix;++e)r+=String.fromCharCode(t.getUint8(n++));if(r!==j)return{command:null};const a=t.getUint32(n,!0);n+=h.txtLength;const o=e.byteLength-v-a,i=new Uint8Array(e,n,Math.min(a,e.byteLength-v)),s=(new TextDecoder).decode(i);let c=null;o>0&&(c=e.slice(v+a));let d=0;return o<0&&(d=Math.abs(o)),{command:s,remainingData:c,missing:d}}};const $=B("klTransmissionManager");let R=C;p&&(R=P);var M=R;let N,O,F,T,H=null;const _=(()=>{const e=(t,n,r,a)=>{let o=n,i=null;const s=t instanceof ArrayBuffer;if($(`RAW: ${t.toString()}`),!o||o.partialHeaderData){let c;if(s?(c=o?.partialHeaderData?new Uint8Array([...new Uint8Array(o.partialHeaderData),...new Uint8Array(t)]).buffer:t,i=P.decodeHeader(c)):(c=o?.partialHeaderData?Buffer.concat([o.partialHeaderData,t]):t,i=C.decodeHeader(c)),!i){const{command:t,missing:o,remainingData:i}=s?P.decodeCommand(c):C.decodeCommand(c);return t?a({command:t,complete:!0,rawMessage:c}):$(o?`ERROR: Missing ${o} bytes to complete the command. This partial command will be aborted.`:`ERROR: Invalid state, message was decoded without a header or partial header data. Discarding ${c.byteLength} bytes`),i?($(`${i.byteLength} bytes remain after processing command. Re-analyzing...`),e(i,n,r,a)):void 0}if(i.partialHeader)return o={firstPackageAt:Date.now(),partialHeaderData:c},r(o);if(!i.header)return $(`ERROR: Invalid state, message was decoded without a header or partial header data. Discarding ${c.byteLength} bytes`);const d=i.header;o={firstPackageAt:Date.now(),header:{...d,totalBytesReceived:d.packages[0].byteLength,totalBytesExpected:d.binaryLength+d.jsonLength,remaining:i.remaining}},r(o)}else o.header&&o.header.totalBytesReceived<o.header.totalBytesExpected&&(o.header.packages.push(t),o.header.totalBytesReceived+=t.byteLength,r(o));if(o.header&&o.header.totalBytesReceived>=o.header.totalBytesExpected){const t=Date.now()-o.header.sentAt.getTime(),n=Date.now()-o.firstPackageAt;$(`Received ${o.header.totalBytesReceived} of ${o.header.totalBytesExpected} expected in ${t} ms, elapsed since first package: ${n}ms`);const i=s?P.decodeFullKlMessage(o.header):C.decodeFullKlMessage(o.header),c=o.header.totalBytesReceived,d=o.header.remaining;r(null),i&&a({klMessage:i.message,complete:!0,sourceServiceId:o.header.fromServiceId,targetServiceId:o.header.toServiceId,rawMessage:i.message.rawMessage});let u=d;if(i?.remaining&&(u=s?d?((e,t)=>{const n=e.byteLength+t.byteLength,r=new ArrayBuffer(n),a=new Uint8Array(e),o=new Uint8Array(t),i=new Uint8Array(r);return i.set(a),i.set(o,a.length),r})(d,i.remaining):i.remaining:d?Buffer.concat([d,i.remaining]):i.remaining),u)return $(`${u.byteLength} bytes remaining after processing message with ${c} bytes of data. Re-analyzing...`),e(u,null,r,a)}};return e})(),G=B("ipcClient"),V=e=>{const n=g.id;t.of[n].emit(e)};var K,W={connect:e=>{g.id=e?.id||g.id,g.appspace=e?.appSpace||g.appspace,t.config={...t.config,...g};const n=g.id;t.connectTo(n,(()=>{t.of[n].on("connect",(()=>{G("Connected to server"),H=null,O&&O()})),t.of[n].on("data",(e=>{_(e,H,(e=>H=e),(e=>{if(e.complete)return e.command?(G(`Received command: ${e.command}`),void(N&&N(e.command))):void(e.klMessage&&F&&F({send:V,transmission:{sourceServiceId:e.sourceServiceId??-1,targetServiceId:e.targetServiceId??-1,rawMessage:e.rawMessage},json:e.klMessage.json}))}))})),t.of[n].on("disconnect",(()=>{G(`Disconnected from ${n}`),H=null,T&&T()}))}))},sendCommand:e=>{const n=g.id,r=M.encodeCommand(e);t.of[n].emit(r)},sendBuffer:V,onCommand:e=>N=e,onMessageReceived:e=>F=e,onClientConnected:e=>O=e,onClientDisconnected:e=>T=e};!function(e){e.FunctionNotFound="FNC_NOT_FOUND",e.ParentEventCallbackError="PARENT_EVENT_CALLBACK_ERROR"}(K||(K={}));const J=3e4;let z=Math.ceil(Date.now()/1e3);function q(e){const t={};let n=console.log;const r={};let a=e||String(Date.now());const o={},i=e=>!o[e],s=(e,t,n,r,a,o)=>{let s=p?new ArrayBuffer(0):Buffer.alloc(0);const c={json:{functionName:e,args:o.success?o.success:[o],messageId:t,type:o.success?"response":"error"}};return i(r)&&(s=M.encode(c,n,r)),a(s,{msg:c,sourceServiceId:n,targetServiceId:r})};return{setLogger:e=>{n=e},processMessage:(e,a,o,i)=>{if(!i)return!1;const c=i;if(t[c.messageId]){const e=t[c.messageId];return e&&(clearTimeout(e.timer),e.fulfilled||(e.fulfilled=!0,"response"===c.type?e.resolve(c.args):"error"===c.type&&e.reject(c.args[0])),delete t[c.messageId]),!0}if("execute"!==c.type&&n&&n(`No pending execution found for message id "${c.messageId}"`),"execute"===c.type){const t=r[c.functionName];if(t){const n=e=>{s(c.functionName,c.messageId,o.targetServiceId,o.sourceServiceId,a,e)};t({transport:e,args:c.args,reply:n,messageId:c.messageId,sourceServiceId:o.sourceServiceId,send:a})}else{const e=`Function "${c.functionName}" not found.`;n&&n(e),s(c.functionName,c.messageId,o.targetServiceId,o.sourceServiceId,a,{error:e,errCode:"FNC_NOT_FOUND"})}return!0}return!1},execute:async(e,r,o,s,c,d)=>{if(!o){const e="No send buffer function provided.";throw n&&n(e),e}z+=1;const u=`${a}-${z}-exec-${e.substring(0,10)}`,l={messageId:u,functionName:e,send:o,sourceServiceId:s,targetServiceId:c,args:r||[],fulfilled:!1,resolve:()=>{},reject:()=>{}};l.promise=new Promise(((e,t)=>{l.resolve=e,l.reject=t}));let f=p?new ArrayBuffer(0):Buffer.alloc(0);const g={json:{functionName:e,args:r,messageId:u,type:"execute"}};i(c)&&(f=M.encode(g,s,c)),t[u]=l,n&&n(`Calling remote function "${e}" with message id "${u}"`);const y="true"===process.env.NO_INVOKE_TIMEOUT;return d?.async?(l.fulfilled=!0,l.resolve([void 0]),delete t[u]):0===d?.timeout||y||(l.timer=setTimeout((()=>{n&&n(`Remote function ${u} timed out`);const r=t[u];r&&!r.fulfilled&&(r.fulfilled=!0,l.reject(`Function ${e} Timed out`)),delete t[u]}),d?.timeout||J)),o(f,{sourceServiceId:s,targetServiceId:c,msg:g}),l.promise},sendResponse:s,registerFunction:(e,t)=>{r[e]=t},getTransportSendFunction:e=>{const n=t[e];return n?n.send:null},setServiceName:e=>{a=e},getPendingExecutions:()=>t,rejectAllPending:e=>{Object.keys(t).forEach((n=>{const r=t[n];r&&!r.fulfilled&&(clearTimeout(r.timer),r.fulfilled=!0,r.reject(e),delete t[n])}))},broadcast:(e,t,r,o)=>{z+=1;const s=`${a}-${z}-multicast-${e.substring(0,10)}`;let c=p?new ArrayBuffer(0):Buffer.alloc(0);const d={json:{functionName:e,args:t,messageId:s,type:"execute"}};let u=i(r[0].serviceId);u&&(c=M.encode(d,o,r[0].serviceId));for(let t=0;t<r.length;t++)try{const a=r[t];n&&n(`Broadcasting function "${e}" with message id "${s}" to client [${a.serviceId}]`),0!==t&&(u=i(a.serviceId),u&&(c=M.patchEncodedHeader(c,{toServiceId:a.serviceId}))),a.sendFn(c,{msg:d,sourceServiceId:o,targetServiceId:a.serviceId})}catch(e){n&&n(`Error broadcasting to client at index ${t}`)}},disableServiceEncoding:(e,t)=>{o[e]=t}}}const Q=(e,t,n,r="srgb")=>{let a;return a=e instanceof Uint8ClampedArray?e:new Uint8ClampedArray(e),{data:a,width:t,height:n,colorSpace:r,_kemuType:i.ImageData}},X=0,Y=B("kemuWidgetService"),Z=a(process.argv.slice(2));function ee(t){const n={},a=process.env.KEMU_WIDGET_SESSION_ID;let o,i,s,c=!1;const g={};let p,m,h,I,v,S,w,b=null;const A=new q;A.setLogger(Y);n.start=async(n,d)=>{const l=n||e.resolve(e.dirname(process.argv[1]),"manifest.json");s=e.dirname(l);const g=await r(l,"utf-8"),p=y(g);if(!p)throw new Error("Error parsing manifest file.");let m;if(p.inputs||(p.inputs=[]),p.outputs||(p.outputs=[]),p.widgetUI)try{m=await r(e.join(s,"widgetUI.js"))}catch(e){Y(`Error loading widgetUI file ${p.name}: ${e}`)}if(p.svgIcon)try{const t=await r(e.join(s,p.svgIcon),"utf-8");p.svgIcon=t}catch(e){Y(`Error loading icon for service ${p.name}: ${e}`)}i=((e,t,n)=>({...e,path:t,...e.widgetUI&&n?.widgetUIContents?{widgetUIContents:n.widgetUIContents}:{}}))(p,s,{widgetUIContents:m}),c=i.name.startsWith("test."),i.path=s,i.internal=Z.internal||!1,c?Y("Starting Kemu Service in Dev mode"):((e=>{const t=e||Z.sessionId||a;if(!t)throw new Error("Missing sessionId. Expected service to be launched with a sessionId as first argument, or the KEMU_WIDGET_SESSION_ID environment variable to be set.");o=parseInt(String(t))})(d),Y(`Starting Kemu Service with session id: ${o}`)),A.setServiceName(`${i.name}_${i.version}`),W.onCommand(B),W.onMessageReceived((({json:e,transmission:t})=>A.processMessage(f.IPC,W.sendBuffer,t,e))),A.registerFunction(u.OnParentEvent,U),A.registerFunction(u.GetDefaultState,L),A.registerFunction(u.UIEvent,D),A.registerFunction(u.InitializeInstance,E),A.registerFunction(u.TerminateInstance,C),W.onClientConnected((()=>{w&&w()})),W.onClientDisconnected((()=>{c&&(o=void 0)})),W.connect({appSpace:Z.ipcSpace||t?.ipc?.appSpace,id:Z.ipcId||t?.ipc?.id})};const B=e=>{((e,t)=>{const n=d.SocketAcknowledge,r=d.IpcAcknowledge,a=e.startsWith(n),o=e.startsWith(r);if(a||o){const o=e.split(a?n:r),i=parseInt(o[1]);return t&&t(i),i}})(e,(e=>{W.sendCommand(((e,t)=>`${d.AcknowledgeResponse}${e}:${t||""}`)(e,o||void 0)),!o&&c&&(Y("Dev mode detected, assuming service session id from ack request:",e),o=e)})),((e,t)=>{e===d.BroadcastStart&&t()})(e,(()=>{h&&h()})),((e,t)=>{e===d.BroadcastEnd&&t()})(e,(()=>{I&&I()})),((e,t)=>{e===d.SendManifest&&t()})(e,(()=>{Y("Sending manifest to hub"),o?A.execute(u.ServiceManifest,[{...i,devMode:c}],W.sendBuffer,o,0,{async:!0}):Y("Service session id is not set. Cannot send manifest.")})),((e,t)=>{if(e.startsWith(d.AssumeSession)){const n=e.split(d.AssumeSession);return t(parseInt(n[1])),!0}})(e,(e=>{o=e,Y(`Assumed session id ${e}`)}))},L=async e=>{if(m){const t=await m();return e.reply({success:[t]})}return e.reply({success:[{}]})},U=async e=>{if(p){const t=e.args[0],{source:n,target:r,data:a,recipeId:i,currentState:s,targetVariantId:c,eventContext:d}=t;if(!o)return void Y("Service session id is not set. Cannot process parent event.");if(!n||!r||!a)return e.reply({error:"Invalid arguments, expected [source, target, data, context]"});const l=W.sendBuffer,f=async t=>A.execute(u.SetOutputs,[t],l,o,e.sourceServiceId,{timeout:0}),g={currentState:s,type:r.widgetType,widgetId:r.widgetId,variantId:c,recipeId:i,getState:async()=>{const t=[r.widgetId,i];return A.execute(u.GetState,t,l,o,e.sourceServiceId)},setState:async t=>{const n={widgetId:r.widgetId,variantId:c,recipeId:i,newState:t};return A.execute(u.SetState,[n],l,o,e.sourceServiceId)},setOutputs:async(e,t)=>{const n={widgetId:r.widgetId,recipeId:i,outputs:e,finalState:t};await f(n)},setOutputsWithContext:async e=>{const t={...e,widgetId:r.widgetId,recipeId:i};await f(t)}};Y(`Invoking user-defined onParentEvent callback for event id "${e.messageId}"`),await p({data:a,source:n,target:r,eventContext:d},g).then((()=>{Y(`Replying SUCCESS to event id "${e.messageId}"`),e.reply({success:[]})})).catch((t=>{const n="string"==typeof t?t:t.message||t;Y(`Error invoking onParentEvent callback: ${n}`),e.reply({error:n,errCode:"PARENT_EVENT_CALLBACK_ERROR"})}))}},E=async e=>{const[{currentState:t,recipeId:n,widgetId:r,variantId:a,recipeType:o,currentDependencies:i}]=e.args;if(g[r]={currentRecipeId:n,variantId:a,currentSourceServiceId:e.sourceServiceId},v){const s={currentState:t,recipeId:n,widgetId:r,variantId:a,recipeType:o,currentDependencies:i||{}},c=await v(s);e.reply({success:[c]})}else e.reply({error:"Not implemented",errCode:"FNC_NOT_FOUND"})},C=async e=>{if(S){const[{currentState:t,recipeId:n,widgetId:r,variantId:a}]=e.args,o={currentState:t,recipeId:n,widgetId:r,variantId:a};await S(o),delete g[r]}e.reply({success:[]})},D=async e=>{if(b)try{const t=await b.apply(void 0,e.args);return e.reply({success:[t]})}catch(t){const n="string"==typeof t?t:JSON.stringify(t);return Y(`Error invoking UI Event handler: ${n}`),e.reply({error:n})}e.reply({error:"UI Events are not supported in this service."})},j=async e=>{if(!i.eventEmitter)throw new Error("This service does not support broadcasting events. Please set `eventEmitter` to true in your manifest file.");if(o)return A.execute(u.BroadcastEvent,e,W.sendBuffer,o,0,{async:!0});Y("Service session id is not set. Cannot broadcast event.")};return n.broadcast=async(e,t)=>{const n=[{outputs:e,variantId:t}];await j(n)},n.broadcastEvent=async e=>{const t=[{outputs:e.outputs,variantId:e.variantId,eventContext:e.eventContext}];await j(t)},n.addDependencyPath=async(e,t,n)=>{if(!o)throw new Error("Not yet registered with the Hub");const r=g[n];if(!r.currentSourceServiceId||!r.currentRecipeId)throw new Error("Cannot invoke this method before initialization");const a={key:e,path:t,recipeId:r.currentRecipeId,widgetId:n};Y(`Adding dependency path for key "${e}" with path "${t}"`),await A.execute(l.SetDependencyPath,[a],W.sendBuffer,o,r.currentSourceServiceId)},n.getDependencyPath=async(e,t)=>{if(!o)throw new Error("Not yet registered with the Hub");const n=g[t];if(!n.currentSourceServiceId||!n.currentRecipeId)throw new Error("Cannot invoke this method before initialization");Y("Getting dependency path for key:",e);const r={key:e,recipeId:n.currentRecipeId,widgetId:t},[a]=await A.execute(l.GetDependencyPath,[r],W.sendBuffer,o,n.currentSourceServiceId);return Y("Dependency path response:",a),a},n.getUniqueId=async()=>{if(!o)throw new Error("Not yet registered with the Hub");const[e]=await A.execute(u.GetUniqueId,[],W.sendBuffer,o,0);return e},n.resolveRuntimeDependencyPath=t=>{if(!Z.recipePath)throw new Error("Cannot resolve runtime dependency without a recipe path. Missing [--recipePath] argument.");return e.resolve(Z.recipePath,t)},n.onGetDefaultState=e=>{m=e},n.onParentEvent=e=>{p=e},n.onTerminate=e=>{S=e},n.onInitialize=e=>{v=e},n.onConnected=e=>{w=e},n.onStartBroadcast=e=>{h=e},n.onStopBroadcast=e=>{I=e},n.onUIEvent=e=>{b=e},Z.internal&&(n.executeHubFunction=async(e,t,n)=>{if(o)return A.execute(e,t,W.sendBuffer,o,0,n);Y("Service session id is not set. Cannot execute hub function.")}),n._getRemoteInvoker=()=>A,n}export{i as DataType,X as KemuHubServiceId,Q as createImageDataLike,ee as default};
@@ -82,6 +82,7 @@ var KemuHubFunctions;
82
82
  KemuHubFunctions["ChooseFileDialog"] = "chooseFileDialog";
83
83
  KemuHubFunctions["GetUniqueId"] = "getUniqueId";
84
84
  KemuHubFunctions["RebootToInstallUpdate"] = "rebootToInstallUpdate";
85
+ KemuHubFunctions["GetFileContentFromCacheId"] = "getFileContentFromCacheId";
85
86
  })(KemuHubFunctions || (KemuHubFunctions = {}));
86
87
  var ServiceToServiceFunctions;
87
88
  (function (ServiceToServiceFunctions) {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@kemu-io/hs",
3
3
  "type": "module",
4
- "version": "0.4.52",
4
+ "version": "0.5.0",
5
5
  "description": "Kemu Hub Service - NodeJs library for creating Kemu Services",
6
6
  "author": "Kemu Pty Ltd",
7
7
  "main": "service.js",