@kemu-io/hs 0.4.42
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 +437 -0
- package/cjs/service.js +1 -0
- package/mjs/service.d.ts +437 -0
- package/mjs/service.js +1 -0
- package/package.json +34 -0
package/cjs/service.d.ts
ADDED
|
@@ -0,0 +1,437 @@
|
|
|
1
|
+
// Generated by dts-bundle-generator v9.5.1
|
|
2
|
+
|
|
3
|
+
export type KemuObjectWrapper<O, DT extends DataType> = O & {
|
|
4
|
+
_kemuType: DT;
|
|
5
|
+
};
|
|
6
|
+
export type ImageDataLike = KemuObjectWrapper<{
|
|
7
|
+
/** the raw image data */
|
|
8
|
+
data: Uint8ClampedArray;
|
|
9
|
+
/** the width of the image */
|
|
10
|
+
width: number;
|
|
11
|
+
/** the height of the image */
|
|
12
|
+
height: number;
|
|
13
|
+
colorSpace: string;
|
|
14
|
+
}, DataType.ImageData>;
|
|
15
|
+
export type Rect = {
|
|
16
|
+
width: number;
|
|
17
|
+
height: number;
|
|
18
|
+
top: number;
|
|
19
|
+
left: number;
|
|
20
|
+
};
|
|
21
|
+
export type Point = {
|
|
22
|
+
x: number;
|
|
23
|
+
y: number;
|
|
24
|
+
};
|
|
25
|
+
declare enum RecipeType {
|
|
26
|
+
Browser = "browser",
|
|
27
|
+
Cloud = "cloud",
|
|
28
|
+
Desktop = "desktop"
|
|
29
|
+
}
|
|
30
|
+
export type BinaryFile<D extends ArrayBuffer | Uint8Array | Uint8ClampedArray | Buffer = ArrayBuffer> = {
|
|
31
|
+
format: string;
|
|
32
|
+
data: D;
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* Valid Kemu Data types
|
|
36
|
+
**/
|
|
37
|
+
export declare enum DataType {
|
|
38
|
+
Number = 0,
|
|
39
|
+
String = 1,
|
|
40
|
+
ArrayBuffer = 2,
|
|
41
|
+
Array = 3,
|
|
42
|
+
Boolean = 4,
|
|
43
|
+
/** a javascript object */
|
|
44
|
+
JsonObj = 5,
|
|
45
|
+
/**
|
|
46
|
+
* Does not care; mostly used by actions to indicate they accept anything since they probably won't use the
|
|
47
|
+
* value.
|
|
48
|
+
**/
|
|
49
|
+
Anything = 6,
|
|
50
|
+
/** Raw image data, produced in browser environments */
|
|
51
|
+
ImageData = 7,
|
|
52
|
+
/** Raw audio data fraction */
|
|
53
|
+
AudioBuffer = 8,
|
|
54
|
+
Rect = 9,
|
|
55
|
+
Point = 10,
|
|
56
|
+
ImageBitmap = 11,
|
|
57
|
+
/**
|
|
58
|
+
* Custom binary data. Use the `format` property to specify the type of data, i.e. 'image/png', 'audio/mp3', etc.
|
|
59
|
+
**/
|
|
60
|
+
BinaryFile = 12
|
|
61
|
+
}
|
|
62
|
+
export type JsonType = {
|
|
63
|
+
[key: string]: SupportedTypes;
|
|
64
|
+
};
|
|
65
|
+
export type KemuType = number | string | ArrayBuffer | JsonType | boolean | ImageData | AudioBuffer | Rect | Point | ImageBitmap | BinaryFile;
|
|
66
|
+
export type SupportedTypes = KemuType | KemuType[];
|
|
67
|
+
/** Type passed around between gates and blocks */
|
|
68
|
+
export type Data = {
|
|
69
|
+
/** the type of data represented */
|
|
70
|
+
type: DataType;
|
|
71
|
+
value: SupportedTypes;
|
|
72
|
+
/** original time when the event was first picked up by an input gate. */
|
|
73
|
+
timestamp: number;
|
|
74
|
+
};
|
|
75
|
+
export type PartialData = Omit<Data, "timestamp">;
|
|
76
|
+
/**
|
|
77
|
+
* Describe the shape of objects. For example:
|
|
78
|
+
*
|
|
79
|
+
* Given the following object:
|
|
80
|
+
* ```
|
|
81
|
+
* const obj = {
|
|
82
|
+
* property1: 12,
|
|
83
|
+
* property2: 'Hello'
|
|
84
|
+
* };
|
|
85
|
+
* ```
|
|
86
|
+
*
|
|
87
|
+
* The shape definition would be:
|
|
88
|
+
* ```
|
|
89
|
+
* {
|
|
90
|
+
* 'property1': DataType.Number,
|
|
91
|
+
* 'property2': DataType.String,
|
|
92
|
+
* }
|
|
93
|
+
* ```
|
|
94
|
+
*
|
|
95
|
+
* Use a JsonPrimitiveFormat (`$$primitive_{x}`) to specify the type of an array of primitive objects,
|
|
96
|
+
* where 'x' is the index in the array the value of the property belongs to. For example:
|
|
97
|
+
*
|
|
98
|
+
* An event with `[1, 'hi', {other: 'yes}]` would produce the following jsonShape:
|
|
99
|
+
*
|
|
100
|
+
* ```
|
|
101
|
+
* {
|
|
102
|
+
* '$$primitive_0': DataType.Number,
|
|
103
|
+
* '$$primitive_1': DataType.String,
|
|
104
|
+
* '$$primitive_2': DataType.JsonObj,
|
|
105
|
+
* }
|
|
106
|
+
* ```
|
|
107
|
+
*
|
|
108
|
+
* If no primitive index is specified, the system assumes all the items in the array
|
|
109
|
+
* will have the given primitive type. For example:
|
|
110
|
+
*
|
|
111
|
+
* An array of `[1, 2, 3, 4]` should be described as:
|
|
112
|
+
* ```
|
|
113
|
+
* {
|
|
114
|
+
* '$$primitive': DataType.Number
|
|
115
|
+
* }
|
|
116
|
+
* ```
|
|
117
|
+
*/
|
|
118
|
+
export type JsonTypeShape = {
|
|
119
|
+
[key: string]: DataType;
|
|
120
|
+
};
|
|
121
|
+
/**
|
|
122
|
+
* Used by Widget (formerly known as Gates) modules when defining their
|
|
123
|
+
* input/output port list
|
|
124
|
+
*/
|
|
125
|
+
export type WidgetPort = {
|
|
126
|
+
/** a unique identifier (in the context of the widget) for this port. */
|
|
127
|
+
name: string;
|
|
128
|
+
/** alternative label used to replace the name for presentation purposes only */
|
|
129
|
+
label?: string;
|
|
130
|
+
/** Type of data the port accepts or produces, an array indicates the gate can receive multiple types */
|
|
131
|
+
type: DataType | DataType[];
|
|
132
|
+
/**
|
|
133
|
+
* If true, processors won't be invoked until at least an event is received in this port.
|
|
134
|
+
*/
|
|
135
|
+
required?: boolean;
|
|
136
|
+
/**
|
|
137
|
+
* Describes the shape of a JSON object when dataType == JsonObj. Or the shape of items
|
|
138
|
+
* when dataType == Array
|
|
139
|
+
*/
|
|
140
|
+
jsonShape?: JsonTypeShape;
|
|
141
|
+
/** help description markdown */
|
|
142
|
+
description?: string;
|
|
143
|
+
};
|
|
144
|
+
export type WidgetState<T extends Record<string, any> = Record<string, unknown>> = T;
|
|
145
|
+
export type TargetOutput = {
|
|
146
|
+
/**
|
|
147
|
+
* the name of the port the `data` will be sent from.
|
|
148
|
+
* This name MUST match one of the ports
|
|
149
|
+
* returned by the `getOutputs` function or defined in the widget
|
|
150
|
+
* manifest. If the name does not match, the data will not be sent.
|
|
151
|
+
**/
|
|
152
|
+
name: string;
|
|
153
|
+
/**
|
|
154
|
+
* The data to send to the output port.
|
|
155
|
+
* If the value is `undefined` or `null`, no data will be sent.
|
|
156
|
+
* Also, the data type MUST match the type defined in the widget manifest.
|
|
157
|
+
*/
|
|
158
|
+
value: SupportedTypes | undefined | null;
|
|
159
|
+
/**
|
|
160
|
+
* the data type of the value being sent.
|
|
161
|
+
* This value is automatically inferred from the widget manifest.
|
|
162
|
+
**/
|
|
163
|
+
type: DataType;
|
|
164
|
+
/** id of the variant that defined the output */
|
|
165
|
+
variantId?: string;
|
|
166
|
+
};
|
|
167
|
+
export type WidgetType = string;
|
|
168
|
+
export type SerializableWidgetInfo<T> = {
|
|
169
|
+
/** the id of the current widget in the recipe */
|
|
170
|
+
readonly widgetId: string;
|
|
171
|
+
readonly type: WidgetType;
|
|
172
|
+
readonly recipeId: string;
|
|
173
|
+
readonly variantId?: string;
|
|
174
|
+
/** the state of the widget at the time the event was produced */
|
|
175
|
+
readonly currentState: Readonly<T>;
|
|
176
|
+
};
|
|
177
|
+
export type WidgetContext<T extends WidgetState = WidgetState> = SerializableWidgetInfo<T> & {
|
|
178
|
+
/**
|
|
179
|
+
* Changes the current state of the gate.
|
|
180
|
+
* Calling this method has a performance cost as it requires a round trip to the recipe
|
|
181
|
+
* execution environment. Use it sparingly. When possible, pass the new state as an argument
|
|
182
|
+
* to the `nextWidget` method.
|
|
183
|
+
*
|
|
184
|
+
* @param newState the new state of the widget. This method merges the new state with the current state using
|
|
185
|
+
* a shallow merge:
|
|
186
|
+
*
|
|
187
|
+
* ```ts
|
|
188
|
+
* const finalState = {
|
|
189
|
+
* ...currentState,
|
|
190
|
+
* ...newState
|
|
191
|
+
* }
|
|
192
|
+
* ```
|
|
193
|
+
*/
|
|
194
|
+
setState: (newState: Partial<T>) => Promise<void>;
|
|
195
|
+
/**
|
|
196
|
+
* Returns the current state of the gate.
|
|
197
|
+
* Calling this method has a performance cost as it requires a round trip to the recipe
|
|
198
|
+
* execution environment. Use it sparingly. When possible, use the `currentState` property.
|
|
199
|
+
*/
|
|
200
|
+
getState: () => Promise<Readonly<T>>;
|
|
201
|
+
/**
|
|
202
|
+
* Sends the given value to the next widget attached to the given port.
|
|
203
|
+
* @param outputs a list of outputs to send data to. The order in which the outputs are defined
|
|
204
|
+
* is the order in which the data will be sent.
|
|
205
|
+
* @param finalState is the new state of the widget after the event is processed.
|
|
206
|
+
*/
|
|
207
|
+
setOutputs: (outputs: TargetOutput[], finalState?: T) => Promise<void>;
|
|
208
|
+
};
|
|
209
|
+
export type PortEventInfo = {
|
|
210
|
+
/** the unique name of the port */
|
|
211
|
+
portName: string;
|
|
212
|
+
widgetId: string;
|
|
213
|
+
widgetType: WidgetType;
|
|
214
|
+
};
|
|
215
|
+
export type RIExecuteConfig = {
|
|
216
|
+
/**
|
|
217
|
+
* Number of milliseconds to wait for the response.
|
|
218
|
+
* Set to 0 to disable the timeouts (the function will wait indefinitely).
|
|
219
|
+
*/
|
|
220
|
+
timeout?: number;
|
|
221
|
+
/**
|
|
222
|
+
* when true, the response is resolved immediately after sending the request.
|
|
223
|
+
**/
|
|
224
|
+
async?: boolean;
|
|
225
|
+
};
|
|
226
|
+
export type ParentEventHandlerEvent<T extends WidgetState = WidgetState> = {
|
|
227
|
+
/** id of the service the event is intended for */
|
|
228
|
+
targetServiceSessionId: number;
|
|
229
|
+
/** event value */
|
|
230
|
+
data: PartialData;
|
|
231
|
+
/** information about the source widget producing the event */
|
|
232
|
+
source: WidgetPort;
|
|
233
|
+
/** information about the target (this) widget */
|
|
234
|
+
target: PortEventInfo;
|
|
235
|
+
targetVariantId?: string;
|
|
236
|
+
recipeId: string;
|
|
237
|
+
/** when data.value is binary (ImageData, etc) */
|
|
238
|
+
/** the current state of the widget at the time of invocation */
|
|
239
|
+
currentState: T;
|
|
240
|
+
config?: RIExecuteConfig;
|
|
241
|
+
};
|
|
242
|
+
export type ServiceParentEvent<WS extends WidgetState = WidgetState> = Pick<ParentEventHandlerEvent<WS>, "data" | "source" | "target">;
|
|
243
|
+
export type ServiceParentEventHandler<T extends WidgetState = WidgetState> = (event: ServiceParentEvent<T>, context: WidgetContext<T>) => Promise<void>;
|
|
244
|
+
/**
|
|
245
|
+
* Handles custom ui events. Any returned value will be passed back to the caller.
|
|
246
|
+
*/
|
|
247
|
+
export type UIEventHandler<N extends string = string, T extends Record<string, unknown> = Record<string, unknown>> = (context: EnvironmentInfo,
|
|
248
|
+
/** name of the event being invoked */
|
|
249
|
+
name: N,
|
|
250
|
+
/** data sent by the UI instance */
|
|
251
|
+
data?: T) => any | Promise<any>;
|
|
252
|
+
/**
|
|
253
|
+
* Information about a widget in the recipe.
|
|
254
|
+
*/
|
|
255
|
+
export type EnvironmentInfo<T extends WidgetState = WidgetState> = {
|
|
256
|
+
/** the id of the widget in the recipe */
|
|
257
|
+
widgetId: string;
|
|
258
|
+
/** the id of the widget variant */
|
|
259
|
+
variantId?: string;
|
|
260
|
+
/** the id of the recipe in the pool. */
|
|
261
|
+
recipeId: string;
|
|
262
|
+
/** the current state of the widget */
|
|
263
|
+
currentState: Readonly<T>;
|
|
264
|
+
/**
|
|
265
|
+
* The type of recipe being executed.
|
|
266
|
+
* In browser environments the value will be 'Browser'
|
|
267
|
+
* while in runner mode the value will be 'Desktop'
|
|
268
|
+
* */
|
|
269
|
+
recipeType: RecipeType;
|
|
270
|
+
};
|
|
271
|
+
/**
|
|
272
|
+
* A function that is expected to return the default state of a Service when
|
|
273
|
+
* first added into the workspace.
|
|
274
|
+
*/
|
|
275
|
+
export type GetDefaultStateHandler<T extends WidgetState = WidgetState> = () => T | Promise<T>;
|
|
276
|
+
export type TerminateContext<T extends WidgetState = WidgetState> = {
|
|
277
|
+
recipeId: string;
|
|
278
|
+
widgetId: string;
|
|
279
|
+
variantId?: string;
|
|
280
|
+
currentState: Readonly<T>;
|
|
281
|
+
};
|
|
282
|
+
export type InitializeContext<T extends WidgetState = WidgetState> = {
|
|
283
|
+
recipeId: string;
|
|
284
|
+
widgetId: string;
|
|
285
|
+
variantId?: string;
|
|
286
|
+
currentState: Readonly<T>;
|
|
287
|
+
recipeType: RecipeType;
|
|
288
|
+
currentDependencies: Record<string, string | null>;
|
|
289
|
+
};
|
|
290
|
+
export type InitializeServiceHandler<T extends WidgetState = WidgetState> = (context: InitializeContext<T>) => Promise<T | null | void | undefined>;
|
|
291
|
+
export type TerminateServiceHandler<T extends WidgetState = WidgetState> = (context: TerminateContext<T>) => Promise<void>;
|
|
292
|
+
/**
|
|
293
|
+
* Instance of a Kemu Widget library. Used by Widget services to integrate with the Kemu Hub.
|
|
294
|
+
*/
|
|
295
|
+
export type KemuService<T extends Record<string, any> = Record<string, any>> = {
|
|
296
|
+
/**
|
|
297
|
+
* Initializes the service
|
|
298
|
+
* @param manifestPath the path to the manifest file. If not provided,
|
|
299
|
+
* the service will look for a `manifest.json` file in the root directory.
|
|
300
|
+
* @param sessionId the unique identifier of the session provided by the Kemu Hub during
|
|
301
|
+
* the widget spawn process. If not provided the service will attempt to read the
|
|
302
|
+
* environment variable `KEMU_WIDGET_SESSION_ID` and if missing, from the first command line arg.
|
|
303
|
+
*
|
|
304
|
+
* This method automatically connects to the Kemu Hub server.
|
|
305
|
+
*/
|
|
306
|
+
start: (manifestPath?: string, sessionId?: number) => Promise<void>;
|
|
307
|
+
/**
|
|
308
|
+
* Invoked before a service instance is terminated.
|
|
309
|
+
* Use it to clean up resources of an instance before it is terminated.
|
|
310
|
+
*/
|
|
311
|
+
onTerminate: (cb: TerminateServiceHandler<T>) => void;
|
|
312
|
+
/**
|
|
313
|
+
* Invoked when a service instance is added to the workspace (in Kemu Compose)
|
|
314
|
+
* or a recipe is loaded.
|
|
315
|
+
* @returns the updated service state or null or undefined if the state does not need
|
|
316
|
+
* to be updated.
|
|
317
|
+
*/
|
|
318
|
+
onInitialize: (cb: InitializeServiceHandler<T>) => void;
|
|
319
|
+
/**
|
|
320
|
+
* Invoked when a parent widget sends an event to this widget.
|
|
321
|
+
*/
|
|
322
|
+
onParentEvent: (cb: ServiceParentEventHandler<T>) => void;
|
|
323
|
+
/**
|
|
324
|
+
* Declares an event listener to process custom events invoked
|
|
325
|
+
* by the UI instance. Any returned value will be passed back to the caller.
|
|
326
|
+
*/
|
|
327
|
+
onUIEvent: <N extends string, D extends Record<string, any> = Record<string, any>>(cb: UIEventHandler<N, D> | null) => void;
|
|
328
|
+
/**
|
|
329
|
+
* Registers a function to be called when the widget is connected to the Kemu Hub.
|
|
330
|
+
*/
|
|
331
|
+
onConnected: (cb: () => void) => void;
|
|
332
|
+
/**
|
|
333
|
+
* Registers a function to be called when the widget is first added to the canvas.
|
|
334
|
+
* @param cb a function that is expected to return the default state of a Service when
|
|
335
|
+
* first added into the workspace.
|
|
336
|
+
*/
|
|
337
|
+
onGetDefaultState: (cb: GetDefaultStateHandler<T>) => void;
|
|
338
|
+
/**
|
|
339
|
+
* Invoked when there is at least a single subscriber to the service.
|
|
340
|
+
* @param cb the function to call when the Hub requests the service to start broadcasting events.
|
|
341
|
+
*/
|
|
342
|
+
onStartBroadcast: (cb: () => void) => void;
|
|
343
|
+
/**
|
|
344
|
+
* Invoked when there are no more subscribers to the service.
|
|
345
|
+
* @param cb the function to call when the Hub requests the service to stop broadcasting events.
|
|
346
|
+
*/
|
|
347
|
+
onStopBroadcast: (cb: () => void) => void;
|
|
348
|
+
/**
|
|
349
|
+
* Emits data to all the given ports to any widget service that is connected to the Kemu Hub
|
|
350
|
+
* and subscribed to events from this service.
|
|
351
|
+
* IMPORTANT: You must set `eventEmitter` to `true` in the manifest file to use this method.
|
|
352
|
+
*
|
|
353
|
+
* @param outputs a list of outputs to send data to. The order in which the outputs are defined
|
|
354
|
+
* is the order in which the data will be sent.
|
|
355
|
+
* The data type and port name MUST match the type defined in the widget manifest's output ports.
|
|
356
|
+
* @param variantId the id of the variant to broadcast the data to. If not provided the data
|
|
357
|
+
* is assumed to be broadcast to the default service instance.
|
|
358
|
+
*/
|
|
359
|
+
broadcast: (outputs: TargetOutput[], variantId?: string) => Promise<void>;
|
|
360
|
+
/**
|
|
361
|
+
* Registers the path to a file or folder the recipe depends on. When the recipe is exported,
|
|
362
|
+
* the dependency will be included in the generated package.
|
|
363
|
+
* @param key the key to use to reference the dependency.
|
|
364
|
+
* @param path the full path in the local disk where the dependency is located. This could be a file or a directory.
|
|
365
|
+
* @param widgetId the id of the widget to associate the dependency with.
|
|
366
|
+
*/
|
|
367
|
+
addDependencyPath: (key: string, path: string, widgetId: string) => Promise<void>;
|
|
368
|
+
/**
|
|
369
|
+
* Returns the full path of a dependency registered via `addDependencyPath`. If the dependency
|
|
370
|
+
* is not found, the method returns `null`. During compose time, the method is likely to
|
|
371
|
+
* return the path of the dependency in the local file system. However, during runtime, the
|
|
372
|
+
* method may return a different within the execution environment.
|
|
373
|
+
* @param key the key to use to reference the dependency.
|
|
374
|
+
* @param widgetId the id of the widget to associate the dependency with.
|
|
375
|
+
* @returns the full path of the dependency or `null` if the dependency is not found.
|
|
376
|
+
*/
|
|
377
|
+
getDependencyPath: (key: string, widgetId: string) => Promise<string | null>;
|
|
378
|
+
/**
|
|
379
|
+
* Generates a unique id guaranteed to be unique across all services and widget instances.
|
|
380
|
+
* Calling this function multiple times will return different ids.
|
|
381
|
+
*/
|
|
382
|
+
getUniqueId: () => Promise<string>;
|
|
383
|
+
/**
|
|
384
|
+
* IMPORTANT: Only use this method when recipeType is 'Desktop'.
|
|
385
|
+
* @returns the full path of the dependency in Desktop (Edge) mode.
|
|
386
|
+
* @param depPath the relative path of the dependency in the recipe.
|
|
387
|
+
*/
|
|
388
|
+
resolveRuntimeDependencyPath: (depPath: string) => string;
|
|
389
|
+
};
|
|
390
|
+
export type CreateServiceConfig = {
|
|
391
|
+
/** ipc client configuration */
|
|
392
|
+
ipc?: {
|
|
393
|
+
/** defaults to `kemu.` */
|
|
394
|
+
appSpace?: string;
|
|
395
|
+
/** defaults to `widgets` */
|
|
396
|
+
id?: string;
|
|
397
|
+
};
|
|
398
|
+
};
|
|
399
|
+
export type KemuServiceConstructor = {
|
|
400
|
+
new <T extends WidgetState = WidgetState>(config?: CreateServiceConfig): KemuService<T>;
|
|
401
|
+
};
|
|
402
|
+
export type ExecuteConfig = {
|
|
403
|
+
timeout?: number;
|
|
404
|
+
/**
|
|
405
|
+
* when true, the response is resolved immediately after sending the request.
|
|
406
|
+
**/
|
|
407
|
+
async?: boolean;
|
|
408
|
+
};
|
|
409
|
+
/**
|
|
410
|
+
* Builds an ImageDataLike object from a buffer, width, height and colorSpace.
|
|
411
|
+
* @param buffer the raw image data
|
|
412
|
+
* @param width the width of the image
|
|
413
|
+
* @param height the height of the image
|
|
414
|
+
* @param colorSpace the color space of the image. Default is 'srgb'
|
|
415
|
+
* @returns an object with the image data, width, height and color space.
|
|
416
|
+
*/
|
|
417
|
+
export declare const createImageDataLike: (buffer: Uint8ClampedArray | ArrayBuffer | Buffer, width: number, height: number, colorSpace?: string) => ImageDataLike;
|
|
418
|
+
export declare const KemuHubServiceId = 0;
|
|
419
|
+
export type PrivateMethods = {
|
|
420
|
+
/**
|
|
421
|
+
* Only available to internal services. The Hub will ignore requests
|
|
422
|
+
* from services not spawned by itself.
|
|
423
|
+
* @param fn the name of the function in the HUB to execute
|
|
424
|
+
* @param args the arguments to pass to the function
|
|
425
|
+
* @param config optional configuration for the execution.
|
|
426
|
+
* @returns a Promise that will resolve with the result of the invocation.
|
|
427
|
+
*/
|
|
428
|
+
executeHubFunction: <T>(fn: string, args: any[], config?: ExecuteConfig) => Promise<T>;
|
|
429
|
+
};
|
|
430
|
+
export type InternalServiceInstance = KemuService<WidgetState> & PrivateMethods;
|
|
431
|
+
declare const _default: KemuServiceConstructor;
|
|
432
|
+
|
|
433
|
+
export {
|
|
434
|
+
_default as default,
|
|
435
|
+
};
|
|
436
|
+
|
|
437
|
+
export {};
|
package/cjs/service.js
ADDED
|
@@ -0,0 +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.InitializeInstance="initializeInstance",e.TerminateInstance="terminateInstance",e.ChooseDirectoryDialog="chooseDirectoryDialog",e.ChooseFileDialog="chooseFileDialog",e.GetUniqueId="getUniqueId"}(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,z={};function _(){return j||(j=1,e=z,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)),z;var e}var D,U={};function M(){if(D)return U;D=1,Object.defineProperty(U,"__esModule",{value:!0}),U.setNestedProperty=U.decodeMap=U.isSupportedBinaryType=U.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};U.isSupportedBinaryType=t;U.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};U.setNestedProperty=r;return U.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},U}var k,E,O={};function R(){if(k)return O;k=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 $(){if(E)return f;E=1,Object.defineProperty(f,"__esModule",{value:!0});const e=C(),t=_(),r=M(),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,T,F={};function N(){if(x)return F;x=1,Object.defineProperty(F,"__esModule",{value:!0});const e=_(),t=R(),r=M(),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 G(){if(T)return l;T=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($()),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($()),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=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=C();var i;r((X||(X=1,Object.defineProperty(ee,"__esModule",{value:!0}),ee.RemoveInvokeError=void 0,function(e){e.FunctionNotFound="FNC_NOT_FOUND"}(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,_),A.registerFunction(d.KemuHubFunctions.InitializeInstance,j),A.registerFunction(d.KemuHubFunctions.TerminateInstance,z),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)}};y(`Invoking user-defined onParentEvent callback for event id "${e.messageId}"`),await v({data:a,source:r,target:o},f),y(`Replying SUCCESS to event id "${e.messageId}"`),e.reply({success:[]})}},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"})},z=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:[]})},_=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;
|
package/mjs/service.d.ts
ADDED
|
@@ -0,0 +1,437 @@
|
|
|
1
|
+
// Generated by dts-bundle-generator v9.5.1
|
|
2
|
+
|
|
3
|
+
export type KemuObjectWrapper<O, DT extends DataType> = O & {
|
|
4
|
+
_kemuType: DT;
|
|
5
|
+
};
|
|
6
|
+
export type ImageDataLike = KemuObjectWrapper<{
|
|
7
|
+
/** the raw image data */
|
|
8
|
+
data: Uint8ClampedArray;
|
|
9
|
+
/** the width of the image */
|
|
10
|
+
width: number;
|
|
11
|
+
/** the height of the image */
|
|
12
|
+
height: number;
|
|
13
|
+
colorSpace: string;
|
|
14
|
+
}, DataType.ImageData>;
|
|
15
|
+
export type Rect = {
|
|
16
|
+
width: number;
|
|
17
|
+
height: number;
|
|
18
|
+
top: number;
|
|
19
|
+
left: number;
|
|
20
|
+
};
|
|
21
|
+
export type Point = {
|
|
22
|
+
x: number;
|
|
23
|
+
y: number;
|
|
24
|
+
};
|
|
25
|
+
declare enum RecipeType {
|
|
26
|
+
Browser = "browser",
|
|
27
|
+
Cloud = "cloud",
|
|
28
|
+
Desktop = "desktop"
|
|
29
|
+
}
|
|
30
|
+
export type BinaryFile<D extends ArrayBuffer | Uint8Array | Uint8ClampedArray | Buffer = ArrayBuffer> = {
|
|
31
|
+
format: string;
|
|
32
|
+
data: D;
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* Valid Kemu Data types
|
|
36
|
+
**/
|
|
37
|
+
export declare enum DataType {
|
|
38
|
+
Number = 0,
|
|
39
|
+
String = 1,
|
|
40
|
+
ArrayBuffer = 2,
|
|
41
|
+
Array = 3,
|
|
42
|
+
Boolean = 4,
|
|
43
|
+
/** a javascript object */
|
|
44
|
+
JsonObj = 5,
|
|
45
|
+
/**
|
|
46
|
+
* Does not care; mostly used by actions to indicate they accept anything since they probably won't use the
|
|
47
|
+
* value.
|
|
48
|
+
**/
|
|
49
|
+
Anything = 6,
|
|
50
|
+
/** Raw image data, produced in browser environments */
|
|
51
|
+
ImageData = 7,
|
|
52
|
+
/** Raw audio data fraction */
|
|
53
|
+
AudioBuffer = 8,
|
|
54
|
+
Rect = 9,
|
|
55
|
+
Point = 10,
|
|
56
|
+
ImageBitmap = 11,
|
|
57
|
+
/**
|
|
58
|
+
* Custom binary data. Use the `format` property to specify the type of data, i.e. 'image/png', 'audio/mp3', etc.
|
|
59
|
+
**/
|
|
60
|
+
BinaryFile = 12
|
|
61
|
+
}
|
|
62
|
+
export type JsonType = {
|
|
63
|
+
[key: string]: SupportedTypes;
|
|
64
|
+
};
|
|
65
|
+
export type KemuType = number | string | ArrayBuffer | JsonType | boolean | ImageData | AudioBuffer | Rect | Point | ImageBitmap | BinaryFile;
|
|
66
|
+
export type SupportedTypes = KemuType | KemuType[];
|
|
67
|
+
/** Type passed around between gates and blocks */
|
|
68
|
+
export type Data = {
|
|
69
|
+
/** the type of data represented */
|
|
70
|
+
type: DataType;
|
|
71
|
+
value: SupportedTypes;
|
|
72
|
+
/** original time when the event was first picked up by an input gate. */
|
|
73
|
+
timestamp: number;
|
|
74
|
+
};
|
|
75
|
+
export type PartialData = Omit<Data, "timestamp">;
|
|
76
|
+
/**
|
|
77
|
+
* Describe the shape of objects. For example:
|
|
78
|
+
*
|
|
79
|
+
* Given the following object:
|
|
80
|
+
* ```
|
|
81
|
+
* const obj = {
|
|
82
|
+
* property1: 12,
|
|
83
|
+
* property2: 'Hello'
|
|
84
|
+
* };
|
|
85
|
+
* ```
|
|
86
|
+
*
|
|
87
|
+
* The shape definition would be:
|
|
88
|
+
* ```
|
|
89
|
+
* {
|
|
90
|
+
* 'property1': DataType.Number,
|
|
91
|
+
* 'property2': DataType.String,
|
|
92
|
+
* }
|
|
93
|
+
* ```
|
|
94
|
+
*
|
|
95
|
+
* Use a JsonPrimitiveFormat (`$$primitive_{x}`) to specify the type of an array of primitive objects,
|
|
96
|
+
* where 'x' is the index in the array the value of the property belongs to. For example:
|
|
97
|
+
*
|
|
98
|
+
* An event with `[1, 'hi', {other: 'yes}]` would produce the following jsonShape:
|
|
99
|
+
*
|
|
100
|
+
* ```
|
|
101
|
+
* {
|
|
102
|
+
* '$$primitive_0': DataType.Number,
|
|
103
|
+
* '$$primitive_1': DataType.String,
|
|
104
|
+
* '$$primitive_2': DataType.JsonObj,
|
|
105
|
+
* }
|
|
106
|
+
* ```
|
|
107
|
+
*
|
|
108
|
+
* If no primitive index is specified, the system assumes all the items in the array
|
|
109
|
+
* will have the given primitive type. For example:
|
|
110
|
+
*
|
|
111
|
+
* An array of `[1, 2, 3, 4]` should be described as:
|
|
112
|
+
* ```
|
|
113
|
+
* {
|
|
114
|
+
* '$$primitive': DataType.Number
|
|
115
|
+
* }
|
|
116
|
+
* ```
|
|
117
|
+
*/
|
|
118
|
+
export type JsonTypeShape = {
|
|
119
|
+
[key: string]: DataType;
|
|
120
|
+
};
|
|
121
|
+
/**
|
|
122
|
+
* Used by Widget (formerly known as Gates) modules when defining their
|
|
123
|
+
* input/output port list
|
|
124
|
+
*/
|
|
125
|
+
export type WidgetPort = {
|
|
126
|
+
/** a unique identifier (in the context of the widget) for this port. */
|
|
127
|
+
name: string;
|
|
128
|
+
/** alternative label used to replace the name for presentation purposes only */
|
|
129
|
+
label?: string;
|
|
130
|
+
/** Type of data the port accepts or produces, an array indicates the gate can receive multiple types */
|
|
131
|
+
type: DataType | DataType[];
|
|
132
|
+
/**
|
|
133
|
+
* If true, processors won't be invoked until at least an event is received in this port.
|
|
134
|
+
*/
|
|
135
|
+
required?: boolean;
|
|
136
|
+
/**
|
|
137
|
+
* Describes the shape of a JSON object when dataType == JsonObj. Or the shape of items
|
|
138
|
+
* when dataType == Array
|
|
139
|
+
*/
|
|
140
|
+
jsonShape?: JsonTypeShape;
|
|
141
|
+
/** help description markdown */
|
|
142
|
+
description?: string;
|
|
143
|
+
};
|
|
144
|
+
export type WidgetState<T extends Record<string, any> = Record<string, unknown>> = T;
|
|
145
|
+
export type TargetOutput = {
|
|
146
|
+
/**
|
|
147
|
+
* the name of the port the `data` will be sent from.
|
|
148
|
+
* This name MUST match one of the ports
|
|
149
|
+
* returned by the `getOutputs` function or defined in the widget
|
|
150
|
+
* manifest. If the name does not match, the data will not be sent.
|
|
151
|
+
**/
|
|
152
|
+
name: string;
|
|
153
|
+
/**
|
|
154
|
+
* The data to send to the output port.
|
|
155
|
+
* If the value is `undefined` or `null`, no data will be sent.
|
|
156
|
+
* Also, the data type MUST match the type defined in the widget manifest.
|
|
157
|
+
*/
|
|
158
|
+
value: SupportedTypes | undefined | null;
|
|
159
|
+
/**
|
|
160
|
+
* the data type of the value being sent.
|
|
161
|
+
* This value is automatically inferred from the widget manifest.
|
|
162
|
+
**/
|
|
163
|
+
type: DataType;
|
|
164
|
+
/** id of the variant that defined the output */
|
|
165
|
+
variantId?: string;
|
|
166
|
+
};
|
|
167
|
+
export type WidgetType = string;
|
|
168
|
+
export type SerializableWidgetInfo<T> = {
|
|
169
|
+
/** the id of the current widget in the recipe */
|
|
170
|
+
readonly widgetId: string;
|
|
171
|
+
readonly type: WidgetType;
|
|
172
|
+
readonly recipeId: string;
|
|
173
|
+
readonly variantId?: string;
|
|
174
|
+
/** the state of the widget at the time the event was produced */
|
|
175
|
+
readonly currentState: Readonly<T>;
|
|
176
|
+
};
|
|
177
|
+
export type WidgetContext<T extends WidgetState = WidgetState> = SerializableWidgetInfo<T> & {
|
|
178
|
+
/**
|
|
179
|
+
* Changes the current state of the gate.
|
|
180
|
+
* Calling this method has a performance cost as it requires a round trip to the recipe
|
|
181
|
+
* execution environment. Use it sparingly. When possible, pass the new state as an argument
|
|
182
|
+
* to the `nextWidget` method.
|
|
183
|
+
*
|
|
184
|
+
* @param newState the new state of the widget. This method merges the new state with the current state using
|
|
185
|
+
* a shallow merge:
|
|
186
|
+
*
|
|
187
|
+
* ```ts
|
|
188
|
+
* const finalState = {
|
|
189
|
+
* ...currentState,
|
|
190
|
+
* ...newState
|
|
191
|
+
* }
|
|
192
|
+
* ```
|
|
193
|
+
*/
|
|
194
|
+
setState: (newState: Partial<T>) => Promise<void>;
|
|
195
|
+
/**
|
|
196
|
+
* Returns the current state of the gate.
|
|
197
|
+
* Calling this method has a performance cost as it requires a round trip to the recipe
|
|
198
|
+
* execution environment. Use it sparingly. When possible, use the `currentState` property.
|
|
199
|
+
*/
|
|
200
|
+
getState: () => Promise<Readonly<T>>;
|
|
201
|
+
/**
|
|
202
|
+
* Sends the given value to the next widget attached to the given port.
|
|
203
|
+
* @param outputs a list of outputs to send data to. The order in which the outputs are defined
|
|
204
|
+
* is the order in which the data will be sent.
|
|
205
|
+
* @param finalState is the new state of the widget after the event is processed.
|
|
206
|
+
*/
|
|
207
|
+
setOutputs: (outputs: TargetOutput[], finalState?: T) => Promise<void>;
|
|
208
|
+
};
|
|
209
|
+
export type PortEventInfo = {
|
|
210
|
+
/** the unique name of the port */
|
|
211
|
+
portName: string;
|
|
212
|
+
widgetId: string;
|
|
213
|
+
widgetType: WidgetType;
|
|
214
|
+
};
|
|
215
|
+
export type RIExecuteConfig = {
|
|
216
|
+
/**
|
|
217
|
+
* Number of milliseconds to wait for the response.
|
|
218
|
+
* Set to 0 to disable the timeouts (the function will wait indefinitely).
|
|
219
|
+
*/
|
|
220
|
+
timeout?: number;
|
|
221
|
+
/**
|
|
222
|
+
* when true, the response is resolved immediately after sending the request.
|
|
223
|
+
**/
|
|
224
|
+
async?: boolean;
|
|
225
|
+
};
|
|
226
|
+
export type ParentEventHandlerEvent<T extends WidgetState = WidgetState> = {
|
|
227
|
+
/** id of the service the event is intended for */
|
|
228
|
+
targetServiceSessionId: number;
|
|
229
|
+
/** event value */
|
|
230
|
+
data: PartialData;
|
|
231
|
+
/** information about the source widget producing the event */
|
|
232
|
+
source: WidgetPort;
|
|
233
|
+
/** information about the target (this) widget */
|
|
234
|
+
target: PortEventInfo;
|
|
235
|
+
targetVariantId?: string;
|
|
236
|
+
recipeId: string;
|
|
237
|
+
/** when data.value is binary (ImageData, etc) */
|
|
238
|
+
/** the current state of the widget at the time of invocation */
|
|
239
|
+
currentState: T;
|
|
240
|
+
config?: RIExecuteConfig;
|
|
241
|
+
};
|
|
242
|
+
export type ServiceParentEvent<WS extends WidgetState = WidgetState> = Pick<ParentEventHandlerEvent<WS>, "data" | "source" | "target">;
|
|
243
|
+
export type ServiceParentEventHandler<T extends WidgetState = WidgetState> = (event: ServiceParentEvent<T>, context: WidgetContext<T>) => Promise<void>;
|
|
244
|
+
/**
|
|
245
|
+
* Handles custom ui events. Any returned value will be passed back to the caller.
|
|
246
|
+
*/
|
|
247
|
+
export type UIEventHandler<N extends string = string, T extends Record<string, unknown> = Record<string, unknown>> = (context: EnvironmentInfo,
|
|
248
|
+
/** name of the event being invoked */
|
|
249
|
+
name: N,
|
|
250
|
+
/** data sent by the UI instance */
|
|
251
|
+
data?: T) => any | Promise<any>;
|
|
252
|
+
/**
|
|
253
|
+
* Information about a widget in the recipe.
|
|
254
|
+
*/
|
|
255
|
+
export type EnvironmentInfo<T extends WidgetState = WidgetState> = {
|
|
256
|
+
/** the id of the widget in the recipe */
|
|
257
|
+
widgetId: string;
|
|
258
|
+
/** the id of the widget variant */
|
|
259
|
+
variantId?: string;
|
|
260
|
+
/** the id of the recipe in the pool. */
|
|
261
|
+
recipeId: string;
|
|
262
|
+
/** the current state of the widget */
|
|
263
|
+
currentState: Readonly<T>;
|
|
264
|
+
/**
|
|
265
|
+
* The type of recipe being executed.
|
|
266
|
+
* In browser environments the value will be 'Browser'
|
|
267
|
+
* while in runner mode the value will be 'Desktop'
|
|
268
|
+
* */
|
|
269
|
+
recipeType: RecipeType;
|
|
270
|
+
};
|
|
271
|
+
/**
|
|
272
|
+
* A function that is expected to return the default state of a Service when
|
|
273
|
+
* first added into the workspace.
|
|
274
|
+
*/
|
|
275
|
+
export type GetDefaultStateHandler<T extends WidgetState = WidgetState> = () => T | Promise<T>;
|
|
276
|
+
export type TerminateContext<T extends WidgetState = WidgetState> = {
|
|
277
|
+
recipeId: string;
|
|
278
|
+
widgetId: string;
|
|
279
|
+
variantId?: string;
|
|
280
|
+
currentState: Readonly<T>;
|
|
281
|
+
};
|
|
282
|
+
export type InitializeContext<T extends WidgetState = WidgetState> = {
|
|
283
|
+
recipeId: string;
|
|
284
|
+
widgetId: string;
|
|
285
|
+
variantId?: string;
|
|
286
|
+
currentState: Readonly<T>;
|
|
287
|
+
recipeType: RecipeType;
|
|
288
|
+
currentDependencies: Record<string, string | null>;
|
|
289
|
+
};
|
|
290
|
+
export type InitializeServiceHandler<T extends WidgetState = WidgetState> = (context: InitializeContext<T>) => Promise<T | null | void | undefined>;
|
|
291
|
+
export type TerminateServiceHandler<T extends WidgetState = WidgetState> = (context: TerminateContext<T>) => Promise<void>;
|
|
292
|
+
/**
|
|
293
|
+
* Instance of a Kemu Widget library. Used by Widget services to integrate with the Kemu Hub.
|
|
294
|
+
*/
|
|
295
|
+
export type KemuService<T extends Record<string, any> = Record<string, any>> = {
|
|
296
|
+
/**
|
|
297
|
+
* Initializes the service
|
|
298
|
+
* @param manifestPath the path to the manifest file. If not provided,
|
|
299
|
+
* the service will look for a `manifest.json` file in the root directory.
|
|
300
|
+
* @param sessionId the unique identifier of the session provided by the Kemu Hub during
|
|
301
|
+
* the widget spawn process. If not provided the service will attempt to read the
|
|
302
|
+
* environment variable `KEMU_WIDGET_SESSION_ID` and if missing, from the first command line arg.
|
|
303
|
+
*
|
|
304
|
+
* This method automatically connects to the Kemu Hub server.
|
|
305
|
+
*/
|
|
306
|
+
start: (manifestPath?: string, sessionId?: number) => Promise<void>;
|
|
307
|
+
/**
|
|
308
|
+
* Invoked before a service instance is terminated.
|
|
309
|
+
* Use it to clean up resources of an instance before it is terminated.
|
|
310
|
+
*/
|
|
311
|
+
onTerminate: (cb: TerminateServiceHandler<T>) => void;
|
|
312
|
+
/**
|
|
313
|
+
* Invoked when a service instance is added to the workspace (in Kemu Compose)
|
|
314
|
+
* or a recipe is loaded.
|
|
315
|
+
* @returns the updated service state or null or undefined if the state does not need
|
|
316
|
+
* to be updated.
|
|
317
|
+
*/
|
|
318
|
+
onInitialize: (cb: InitializeServiceHandler<T>) => void;
|
|
319
|
+
/**
|
|
320
|
+
* Invoked when a parent widget sends an event to this widget.
|
|
321
|
+
*/
|
|
322
|
+
onParentEvent: (cb: ServiceParentEventHandler<T>) => void;
|
|
323
|
+
/**
|
|
324
|
+
* Declares an event listener to process custom events invoked
|
|
325
|
+
* by the UI instance. Any returned value will be passed back to the caller.
|
|
326
|
+
*/
|
|
327
|
+
onUIEvent: <N extends string, D extends Record<string, any> = Record<string, any>>(cb: UIEventHandler<N, D> | null) => void;
|
|
328
|
+
/**
|
|
329
|
+
* Registers a function to be called when the widget is connected to the Kemu Hub.
|
|
330
|
+
*/
|
|
331
|
+
onConnected: (cb: () => void) => void;
|
|
332
|
+
/**
|
|
333
|
+
* Registers a function to be called when the widget is first added to the canvas.
|
|
334
|
+
* @param cb a function that is expected to return the default state of a Service when
|
|
335
|
+
* first added into the workspace.
|
|
336
|
+
*/
|
|
337
|
+
onGetDefaultState: (cb: GetDefaultStateHandler<T>) => void;
|
|
338
|
+
/**
|
|
339
|
+
* Invoked when there is at least a single subscriber to the service.
|
|
340
|
+
* @param cb the function to call when the Hub requests the service to start broadcasting events.
|
|
341
|
+
*/
|
|
342
|
+
onStartBroadcast: (cb: () => void) => void;
|
|
343
|
+
/**
|
|
344
|
+
* Invoked when there are no more subscribers to the service.
|
|
345
|
+
* @param cb the function to call when the Hub requests the service to stop broadcasting events.
|
|
346
|
+
*/
|
|
347
|
+
onStopBroadcast: (cb: () => void) => void;
|
|
348
|
+
/**
|
|
349
|
+
* Emits data to all the given ports to any widget service that is connected to the Kemu Hub
|
|
350
|
+
* and subscribed to events from this service.
|
|
351
|
+
* IMPORTANT: You must set `eventEmitter` to `true` in the manifest file to use this method.
|
|
352
|
+
*
|
|
353
|
+
* @param outputs a list of outputs to send data to. The order in which the outputs are defined
|
|
354
|
+
* is the order in which the data will be sent.
|
|
355
|
+
* The data type and port name MUST match the type defined in the widget manifest's output ports.
|
|
356
|
+
* @param variantId the id of the variant to broadcast the data to. If not provided the data
|
|
357
|
+
* is assumed to be broadcast to the default service instance.
|
|
358
|
+
*/
|
|
359
|
+
broadcast: (outputs: TargetOutput[], variantId?: string) => Promise<void>;
|
|
360
|
+
/**
|
|
361
|
+
* Registers the path to a file or folder the recipe depends on. When the recipe is exported,
|
|
362
|
+
* the dependency will be included in the generated package.
|
|
363
|
+
* @param key the key to use to reference the dependency.
|
|
364
|
+
* @param path the full path in the local disk where the dependency is located. This could be a file or a directory.
|
|
365
|
+
* @param widgetId the id of the widget to associate the dependency with.
|
|
366
|
+
*/
|
|
367
|
+
addDependencyPath: (key: string, path: string, widgetId: string) => Promise<void>;
|
|
368
|
+
/**
|
|
369
|
+
* Returns the full path of a dependency registered via `addDependencyPath`. If the dependency
|
|
370
|
+
* is not found, the method returns `null`. During compose time, the method is likely to
|
|
371
|
+
* return the path of the dependency in the local file system. However, during runtime, the
|
|
372
|
+
* method may return a different within the execution environment.
|
|
373
|
+
* @param key the key to use to reference the dependency.
|
|
374
|
+
* @param widgetId the id of the widget to associate the dependency with.
|
|
375
|
+
* @returns the full path of the dependency or `null` if the dependency is not found.
|
|
376
|
+
*/
|
|
377
|
+
getDependencyPath: (key: string, widgetId: string) => Promise<string | null>;
|
|
378
|
+
/**
|
|
379
|
+
* Generates a unique id guaranteed to be unique across all services and widget instances.
|
|
380
|
+
* Calling this function multiple times will return different ids.
|
|
381
|
+
*/
|
|
382
|
+
getUniqueId: () => Promise<string>;
|
|
383
|
+
/**
|
|
384
|
+
* IMPORTANT: Only use this method when recipeType is 'Desktop'.
|
|
385
|
+
* @returns the full path of the dependency in Desktop (Edge) mode.
|
|
386
|
+
* @param depPath the relative path of the dependency in the recipe.
|
|
387
|
+
*/
|
|
388
|
+
resolveRuntimeDependencyPath: (depPath: string) => string;
|
|
389
|
+
};
|
|
390
|
+
export type CreateServiceConfig = {
|
|
391
|
+
/** ipc client configuration */
|
|
392
|
+
ipc?: {
|
|
393
|
+
/** defaults to `kemu.` */
|
|
394
|
+
appSpace?: string;
|
|
395
|
+
/** defaults to `widgets` */
|
|
396
|
+
id?: string;
|
|
397
|
+
};
|
|
398
|
+
};
|
|
399
|
+
export type KemuServiceConstructor = {
|
|
400
|
+
new <T extends WidgetState = WidgetState>(config?: CreateServiceConfig): KemuService<T>;
|
|
401
|
+
};
|
|
402
|
+
export type ExecuteConfig = {
|
|
403
|
+
timeout?: number;
|
|
404
|
+
/**
|
|
405
|
+
* when true, the response is resolved immediately after sending the request.
|
|
406
|
+
**/
|
|
407
|
+
async?: boolean;
|
|
408
|
+
};
|
|
409
|
+
/**
|
|
410
|
+
* Builds an ImageDataLike object from a buffer, width, height and colorSpace.
|
|
411
|
+
* @param buffer the raw image data
|
|
412
|
+
* @param width the width of the image
|
|
413
|
+
* @param height the height of the image
|
|
414
|
+
* @param colorSpace the color space of the image. Default is 'srgb'
|
|
415
|
+
* @returns an object with the image data, width, height and color space.
|
|
416
|
+
*/
|
|
417
|
+
export declare const createImageDataLike: (buffer: Uint8ClampedArray | ArrayBuffer | Buffer, width: number, height: number, colorSpace?: string) => ImageDataLike;
|
|
418
|
+
export declare const KemuHubServiceId = 0;
|
|
419
|
+
export type PrivateMethods = {
|
|
420
|
+
/**
|
|
421
|
+
* Only available to internal services. The Hub will ignore requests
|
|
422
|
+
* from services not spawned by itself.
|
|
423
|
+
* @param fn the name of the function in the HUB to execute
|
|
424
|
+
* @param args the arguments to pass to the function
|
|
425
|
+
* @param config optional configuration for the execution.
|
|
426
|
+
* @returns a Promise that will resolve with the result of the invocation.
|
|
427
|
+
*/
|
|
428
|
+
executeHubFunction: <T>(fn: string, args: any[], config?: ExecuteConfig) => Promise<T>;
|
|
429
|
+
};
|
|
430
|
+
export type InternalServiceInstance = KemuService<WidgetState> & PrivateMethods;
|
|
431
|
+
declare const _default: KemuServiceConstructor;
|
|
432
|
+
|
|
433
|
+
export {
|
|
434
|
+
_default as default,
|
|
435
|
+
};
|
|
436
|
+
|
|
437
|
+
export {};
|
package/mjs/service.js
ADDED
|
@@ -0,0 +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 i,o,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"}(i||(i={})),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"}(o||(o={})),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.InitializeInstance="initializeInstance",e.TerminateInstance="terminateInstance",e.ChooseDirectoryDialog="chooseDirectoryDialog",e.ChooseFileDialog="chooseFileDialog",e.GetUniqueId="getUniqueId"}(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,i=Array.isArray(e)?[]:{};const o=(e,i)=>{const s=(e=>{const t="undefined"!=typeof Buffer&&e instanceof Buffer,n=e instanceof ArrayBuffer,r=e instanceof Uint8ClampedArray,a=e instanceof Uint8Array,i=e instanceof Int8Array;return t?"Buffer":n?"ArrayBuffer":r?"Uint8ClampedArray":a?"Uint8Array":i?"Int8Array":null})(e);if(!s){if(Array.isArray(e)){const t=[];for(let n=0;n<e.length;n++)t[n]=o(e[n],`${i}[${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,i=e instanceof Float32Array,o=e instanceof Float64Array,s=e instanceof BigInt64Array,c=e instanceof BigUint64Array;return t?"Int16Array":n?"Uint16Array":r?"Int32Array":a?"Uint32Array":i?"Float32Array":o?"Float64Array":s?"BigInt64Array":c?"BigUint64Array":null})(e);if(n)throw new Error(`Unsupported binary type [${n}] at path "${i}"`);for(const n in e)e.hasOwnProperty(n)||S.includes(n)||console.warn(`Allowing inherited property: ${n} from path: ${i}`),t[n]=o(e[n],`${i.length?`${i}.`:""}${n}`);return t}return e}n[i]={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};i=o(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:i}:null},b=(e,t,n,r)=>{const a=t.match(/(\[\d+\])|([^[\].]+)/g)||[];let i=e;for(let e=0;e<a.length;e++){let t=a[e];const r=t.startsWith("[")&&t.endsWith("]"),o=e===a.length-1;if(r){t=t.slice(1,-1);const r=parseInt(t,10);if(!Array.isArray(i))throw new Error(`Expected an array at key "${a.slice(0,e).join(".")}" but found an object.`);o?i[r]=n:(i[r]||(i[r]=a[e+1].startsWith("[")?[]:{}),i=i[r])}else o?i[t]=n:(i[t]||(i[t]=a[e+1].startsWith("[")?[]:{}),i=i[t])}return e},A=(e,t,n)=>{const r="undefined"!=typeof Buffer,a=t instanceof Uint8Array;for(const i in n)if(n.hasOwnProperty(i)){const{index:o,length:s,binaryType:c}=n[i];let d=null;if(r&&t instanceof Buffer)switch(c){case"Buffer":d=t.subarray(o,o+s);break;case"ArrayBuffer":d=t.buffer.slice(t.byteOffset,t.byteOffset+t.byteLength).slice(o,o+s);break;case"Uint8Array":d=new Uint8Array(t.subarray(o,o+s));break;case"Uint8ClampedArray":d=new Uint8ClampedArray(t.subarray(o,o+s));break;case"Int8Array":d=new Int8Array(t.subarray(o,o+s))}else if(t instanceof ArrayBuffer||t instanceof Uint8Array)switch(c){case"Buffer":if(r){d=Buffer.from(t.slice(o,o+s));break}case"ArrayBuffer":d=a?t.buffer.slice(t.byteOffset,t.byteOffset+t.byteLength).slice(o,o+s):t.slice(o,o+s);break;case"Uint8Array":d=a?t.slice(o,o+s):new Uint8Array(t.slice(o,o+s));break;case"Uint8ClampedArray":d=new Uint8ClampedArray(t.slice(o,o+s));break;case"Int8Array":d=new Int8Array(t.slice(o,o+s))}d&&b(e,i,d)}return e},B=e=>n(e),L="KMSG",U="KCMD",E=B("klProtocol");var D={encode:(e,t,n)=>{const r={json:e.json},a=w(r.json,"Buffer"),i=a?.combinedData;a&&(r.jsonBinaryMap=a.map,r.json=a.sourceCopy);const o=i?i.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+o,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(o,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,i&&o&&i.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 i=e.readUInt32LE(t);t+=m.binaryLength;const o=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+i,u=e.subarray(t,t+d),l=e.subarray(0,I);let f=null;return e.byteLength-I-a-i>0&&(f=e.subarray(I+a+i)),{header:{protocolVersion:r,jsonLength:a,binaryLength:i,fromServiceId:o,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 i=Buffer.concat([e.headerPackage,t]);let o=i,s=null;const c=I+e.jsonLength+e.binaryLength;return i.byteLength>c&&(s=i.subarray(c),o=i.subarray(0,c)),{message:{json:a.json,rawMessage:o},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,i=Buffer.alloc(a);return i.write(U,t),t+=h.protocolPrefix,i.writeUint32LE(r,t),t+=h.txtLength,n.copy(i,t),i},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),i=e.byteLength-v-r;let o=null;i>0&&(o=e.subarray(v+r));let s=0;return i<0&&(s=Math.abs(i)),{command:a,remainingData:o,missing:s}}};const C="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"),i=a?.combinedData;a&&(r.jsonBinaryMap=a.map,r.json=a.sourceCopy);const o=i?i.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+o),l=new DataView(u),f=new Uint8Array(u),g=Date.now();let y=0;for(let e=0;e<4;++e)f[y++]=C.charCodeAt(e);return l.setUint8(y,1),y+=m.protocolVersion,l.setUint32(y,d,!0),y+=m.jsonLength,l.setUint32(y,o,!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,i&&o&&f.set(new Uint8Array(i),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!==C)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 i=t.getUint32(n,!0);n+=m.jsonLength;const o=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=i+o,l=e.slice(n,n+u),f=new Uint8Array(e,0,I);let g=null;if(e.byteLength-I-i-o>0){g=new Uint8Array(e,I+i+o).slice().buffer}return{header:{protocolVersion:a,jsonLength:i,binaryLength:o,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 i=(new TextDecoder).decode(n.subarray(0,e.jsonLength)),o=n.subarray(e.jsonLength,e.jsonLength+e.binaryLength),s=y(i);if(!s?.json)return k.log("Invalid JSON in KL message"),null;s.jsonBinaryMap&&o.byteLength&&A(s.json,o,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,...o.length?{binaryData:o.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),i=new DataView(a),o=new Uint8Array(a);for(let e=0;e<4;++e)o[t++]=j.charCodeAt(e);return i.setUint32(t,r,!0),t+=h.txtLength,o.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 i=e.byteLength-v-a,o=new Uint8Array(e,n,Math.min(a,e.byteLength-v)),s=(new TextDecoder).decode(o);let c=null;i>0&&(c=e.slice(v+a));let d=0;return i<0&&(d=Math.abs(i)),{command:s,remainingData:c,missing:d}}};const $=B("klTransmissionManager");let M=D;p&&(M=P);var N=M;let R,O,F,T,H=null;const G=(()=>{const e=(t,n,r,a)=>{let i=n,o=null;const s=t instanceof ArrayBuffer;if($(`RAW: ${t.toString()}`),!i||i.partialHeaderData){let c;if(s?(c=i?.partialHeaderData?new Uint8Array([...new Uint8Array(i.partialHeaderData),...new Uint8Array(t)]).buffer:t,o=P.decodeHeader(c)):(c=i?.partialHeaderData?Buffer.concat([i.partialHeaderData,t]):t,o=D.decodeHeader(c)),!o){const{command:t,missing:i,remainingData:o}=s?P.decodeCommand(c):D.decodeCommand(c);return t?a({command:t,complete:!0,rawMessage:c}):$(i?`ERROR: Missing ${i} 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`),o?($(`${o.byteLength} bytes remain after processing command. Re-analyzing...`),e(o,n,r,a)):void 0}if(o.partialHeader)return i={firstPackageAt:Date.now(),partialHeaderData:c},r(i);if(!o.header)return $(`ERROR: Invalid state, message was decoded without a header or partial header data. Discarding ${c.byteLength} bytes`);const d=o.header;i={firstPackageAt:Date.now(),header:{...d,totalBytesReceived:d.packages[0].byteLength,totalBytesExpected:d.binaryLength+d.jsonLength,remaining:o.remaining}},r(i)}else i.header&&i.header.totalBytesReceived<i.header.totalBytesExpected&&(i.header.packages.push(t),i.header.totalBytesReceived+=t.byteLength,r(i));if(i.header&&i.header.totalBytesReceived>=i.header.totalBytesExpected){const t=Date.now()-i.header.sentAt.getTime(),n=Date.now()-i.firstPackageAt;$(`Received ${i.header.totalBytesReceived} of ${i.header.totalBytesExpected} expected in ${t} ms, elapsed since first package: ${n}ms`);const o=s?P.decodeFullKlMessage(i.header):D.decodeFullKlMessage(i.header),c=i.header.totalBytesReceived,d=i.header.remaining;r(null),o&&a({klMessage:o.message,complete:!0,sourceServiceId:i.header.fromServiceId,targetServiceId:i.header.toServiceId,rawMessage:o.message.rawMessage});let u=d;if(o?.remaining&&(u=s?d?((e,t)=>{const n=e.byteLength+t.byteLength,r=new ArrayBuffer(n),a=new Uint8Array(e),i=new Uint8Array(t),o=new Uint8Array(r);return o.set(a),o.set(i,a.length),r})(d,o.remaining):o.remaining:d?Buffer.concat([d,o.remaining]):o.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"),_=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=>{G(e,H,(e=>H=e),(e=>{if(e.complete)return e.command?(V(`Received command: ${e.command}`),void(R&&R(e.command))):void(e.klMessage&&F&&F({send:_,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,T&&T()}))}))},sendCommand:e=>{const n=g.id,r=N.encodeCommand(e);t.of[n].emit(r)},sendBuffer:_,onCommand:e=>R=e,onMessageReceived:e=>F=e,onClientConnected:e=>O=e,onClientDisconnected:e=>T=e};!function(e){e.FunctionNotFound="FNC_NOT_FOUND"}(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 i={},o=e=>!i[e],s=(e,t,n,r,a,i)=>{let s=p?new ArrayBuffer(0):Buffer.alloc(0);const c={json:{functionName:e,args:i.success?i.success:[i],messageId:t,type:i.success?"response":"error"}};return o(r)&&(s=N.encode(c,n,r)),a(s,{msg:c,sourceServiceId:n,targetServiceId:r})};return{setLogger:e=>{n=e},processMessage:(e,a,i,o)=>{if(!o)return!1;const c=o;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,i.targetServiceId,i.sourceServiceId,a,e)};t({transport:e,args:c.args,reply:n,messageId:c.messageId,sourceServiceId:i.sourceServiceId,send:a})}else{const e=`Function "${c.functionName}" not found.`;n&&n(e),s(c.functionName,c.messageId,i.targetServiceId,i.sourceServiceId,a,{error:e,errCode:"FNC_NOT_FOUND"})}return!0}return!1},execute:async(e,r,i,s,c,d)=>{if(!i){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:i,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"}};o(c)&&(f=N.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)),i(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,i)=>{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=o(r[0].serviceId);u&&(c=N.encode(d,i,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=o(a.serviceId),u&&(c=N.patchEncodedHeader(c,{toServiceId:a.serviceId}))),a.sendFn(c,{msg:d,sourceServiceId:i,targetServiceId:a.serviceId})}catch(e){n&&n(`Error broadcasting to client at index ${t}`)}},disableServiceEncoding:(e,t)=>{i[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:o.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 i,o,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}`)}o=((e,t,n)=>({...e,path:t,...e.widgetUI&&n?.widgetUIContents?{widgetUIContents:n.widgetUIContents}:{}}))(p,s,{widgetUIContents:m}),c=o.name.startsWith("test."),o.path=s,o.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.");i=parseInt(String(t))})(d),Y(`Starting Kemu Service with session id: ${i}`)),A.setServiceName(`${o.name}_${o.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,C),A.registerFunction(u.InitializeInstance,E),A.registerFunction(u.TerminateInstance,D),W.onClientConnected((()=>{w&&w()})),W.onClientDisconnected((()=>{c&&(i=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),i=e.startsWith(r);if(a||i){const i=e.split(a?n:r),o=parseInt(i[1]);return t&&t(o),o}})(e,(e=>{W.sendCommand(((e,t)=>`${d.AcknowledgeResponse}${e}:${t||""}`)(e,i||void 0)),!i&&c&&(Y("Dev mode detected, assuming service session id from ack request:",e),i=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"),i?A.execute(u.ServiceManifest,[{...o,devMode:c}],W.sendBuffer,i,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=>{i=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:o,currentState:s,targetVariantId:c}=t;if(!i)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:o,getState:async()=>{const t=[r.widgetId,o];return A.execute(u.GetState,t,d,i,e.sourceServiceId)},setState:async t=>{const n={widgetId:r.widgetId,variantId:c,recipeId:o,newState:t};return A.execute(u.SetState,[n],d,i,e.sourceServiceId)},setOutputs:async(t,n)=>{const a={widgetId:r.widgetId,recipeId:o,outputs:t,finalState:n};await A.execute(u.SetOutputs,[a],d,i,e.sourceServiceId)}};Y(`Invoking user-defined onParentEvent callback for event id "${e.messageId}"`),await p({data:a,source:n,target:r},l),Y(`Replying SUCCESS to event id "${e.messageId}"`),e.reply({success:[]})}},E=async e=>{const[{currentState:t,recipeId:n,widgetId:r,variantId:a,recipeType:i,currentDependencies:o}]=e.args;if(g[r]={currentRecipeId:n,variantId:a,currentSourceServiceId:e.sourceServiceId},v){const s={currentState:t,recipeId:n,widgetId:r,variantId:a,recipeType:i,currentDependencies:o||{}},c=await v(s);e.reply({success:[c]})}else e.reply({error:"Not implemented",errCode:"FNC_NOT_FOUND"})},D=async e=>{if(S){const[{currentState:t,recipeId:n,widgetId:r,variantId:a}]=e.args,i={currentState:t,recipeId:n,widgetId:r,variantId:a};await S(i),delete g[r]}e.reply({success:[]})},C=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."})};return n.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(!i)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,i,0,{async:!0})},n.addDependencyPath=async(e,t,n)=>{if(!i)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,i,r.currentSourceServiceId)},n.getDependencyPath=async(e,t)=>{if(!i)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,i,n.currentSourceServiceId);return Y("Dependency path response:",a),a},n.getUniqueId=async()=>{if(!i)throw new Error("Not yet registered with the Hub");const[e]=await A.execute(u.GetUniqueId,[],W.sendBuffer,i,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(i)return A.execute(e,t,W.sendBuffer,i,0,n);Y("Service session id is not set. Cannot execute hub function.")}),n._getRemoteInvoker=()=>A,n}export{o as DataType,X as KemuHubServiceId,Q as createImageDataLike,ee as default};
|
package/package.json
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@kemu-io/hs",
|
|
3
|
+
"type": "module",
|
|
4
|
+
"version": "0.4.42",
|
|
5
|
+
"description": "Kemu Hub Service - NodeJs library for creating Kemu Services",
|
|
6
|
+
"author": "Kemu Pty Ltd",
|
|
7
|
+
"main": "service.js",
|
|
8
|
+
"module": "mjs/service.js",
|
|
9
|
+
"types": "mjs/service.d.ts",
|
|
10
|
+
"publishConfig": {
|
|
11
|
+
"registry": "https://registry.npmjs.org/"
|
|
12
|
+
},
|
|
13
|
+
"exports": {
|
|
14
|
+
".": {
|
|
15
|
+
"import": "./mjs/service.js",
|
|
16
|
+
"require": "./cjs/service.js"
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"files": [
|
|
20
|
+
"mjs/service.js",
|
|
21
|
+
"mjs/service.d.ts",
|
|
22
|
+
"cjs/service.js",
|
|
23
|
+
"cjs/service.d.ts"
|
|
24
|
+
],
|
|
25
|
+
"dependencies": {
|
|
26
|
+
"debug": "^4.3.5",
|
|
27
|
+
"minimist": "^1.2.8",
|
|
28
|
+
"node-ipc": "10.1.0"
|
|
29
|
+
},
|
|
30
|
+
"overrides": {
|
|
31
|
+
"node-ipc@>9.2.1 <10": "9.2.1",
|
|
32
|
+
"node-ipc@>10.1.0": "10.1.0"
|
|
33
|
+
}
|
|
34
|
+
}
|