@ultrst-armada/krnl 1.0.7 → 1.0.8
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/package.json +14 -2
- package/packages/cli/dist/bin/krnl.cjs +3 -15
- package/packages/cli/dist/bin/krnl.js +1 -1
- package/packages/cli/dist/{chunk-GHWYEAPD.js → chunk-3DD775A7.js} +2 -14
- package/packages/cli/dist/index.cjs +3 -15
- package/packages/cli/dist/index.js +1 -1
- package/packages/core/dist/index.cjs +244 -57
- package/packages/core/dist/index.d.cts +161 -24
- package/packages/core/dist/index.d.ts +161 -24
- package/packages/core/dist/index.js +240 -57
- package/packages/core/package.json +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ultrst-armada/krnl",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.8",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "KrnlTS backend semantic kernel for authoring, validating, and running modular TypeScript services",
|
|
6
6
|
"type": "module",
|
|
@@ -79,9 +79,21 @@
|
|
|
79
79
|
"url": "git+https://github.com/dinilmusick/KrnlTS.git"
|
|
80
80
|
},
|
|
81
81
|
"dependencies": {
|
|
82
|
-
"@dinilmusick/gutts": "^0.
|
|
82
|
+
"@dinilmusick/gutts": "^1.0.0",
|
|
83
83
|
"esbuild": "^0.28.2",
|
|
84
84
|
"ts-morph": "^25.0.1",
|
|
85
85
|
"ws": "^8.20.0"
|
|
86
|
+
},
|
|
87
|
+
"packageManager": "pnpm@10.33.0",
|
|
88
|
+
"pnpm": {
|
|
89
|
+
"overrides": {
|
|
90
|
+
"onnxruntime-node": "1.20.1"
|
|
91
|
+
},
|
|
92
|
+
"onlyBuiltDependencies": [
|
|
93
|
+
"better-sqlite3",
|
|
94
|
+
"esbuild",
|
|
95
|
+
"onnxruntime-node",
|
|
96
|
+
"protobufjs"
|
|
97
|
+
]
|
|
86
98
|
}
|
|
87
99
|
}
|
|
@@ -919,20 +919,8 @@ var path7 = __toESM(require("path"), 1);
|
|
|
919
919
|
// ../core/dist/index.js
|
|
920
920
|
var fs5 = __toESM(require("fs"), 1);
|
|
921
921
|
var path6 = __toESM(require("path"), 1);
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
function parseJson(text) {
|
|
925
|
-
return JSON.parse(text);
|
|
926
|
-
}
|
|
927
|
-
function tryParseJson(text) {
|
|
928
|
-
try {
|
|
929
|
-
return parseJson(text);
|
|
930
|
-
} catch {
|
|
931
|
-
return void 0;
|
|
932
|
-
}
|
|
933
|
-
}
|
|
934
|
-
|
|
935
|
-
// ../core/dist/index.js
|
|
922
|
+
var import_gutts = require("@dinilmusick/gutts");
|
|
923
|
+
var gutts = __toESM(require("@dinilmusick/gutts"), 1);
|
|
936
924
|
var asyncHooks = globalThis.process?.getBuiltinModule?.("node:async_hooks");
|
|
937
925
|
var KrnlPackageReconciler = class {
|
|
938
926
|
/**
|
|
@@ -945,7 +933,7 @@ var KrnlPackageReconciler = class {
|
|
|
945
933
|
for (const mPath of manifests) {
|
|
946
934
|
try {
|
|
947
935
|
const raw = fs5.readFileSync(mPath, "utf8");
|
|
948
|
-
const json = tryParseJson(raw) ?? {};
|
|
936
|
+
const json = (0, import_gutts.tryParseJson)(raw) ?? {};
|
|
949
937
|
if (json.dependencies && typeof json.dependencies === "object") {
|
|
950
938
|
for (const [pkg, ver] of Object.entries(json.dependencies)) {
|
|
951
939
|
if (!aggregatedDeps[pkg]) aggregatedDeps[pkg] = [];
|
|
@@ -814,20 +814,8 @@ async function runValidate(projectRoot = process.cwd()) {
|
|
|
814
814
|
// ../core/dist/index.js
|
|
815
815
|
import * as fs3 from "fs";
|
|
816
816
|
import * as path4 from "path";
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
function parseJson(text) {
|
|
820
|
-
return JSON.parse(text);
|
|
821
|
-
}
|
|
822
|
-
function tryParseJson(text) {
|
|
823
|
-
try {
|
|
824
|
-
return parseJson(text);
|
|
825
|
-
} catch {
|
|
826
|
-
return void 0;
|
|
827
|
-
}
|
|
828
|
-
}
|
|
829
|
-
|
|
830
|
-
// ../core/dist/index.js
|
|
817
|
+
import { tryParseJson } from "@dinilmusick/gutts";
|
|
818
|
+
import * as gutts from "@dinilmusick/gutts";
|
|
831
819
|
var asyncHooks = globalThis.process?.getBuiltinModule?.("node:async_hooks");
|
|
832
820
|
var KrnlPackageReconciler = class {
|
|
833
821
|
/**
|
|
@@ -930,20 +930,8 @@ var path7 = __toESM(require("path"), 1);
|
|
|
930
930
|
// ../core/dist/index.js
|
|
931
931
|
var fs5 = __toESM(require("fs"), 1);
|
|
932
932
|
var path6 = __toESM(require("path"), 1);
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
function parseJson(text) {
|
|
936
|
-
return JSON.parse(text);
|
|
937
|
-
}
|
|
938
|
-
function tryParseJson(text) {
|
|
939
|
-
try {
|
|
940
|
-
return parseJson(text);
|
|
941
|
-
} catch {
|
|
942
|
-
return void 0;
|
|
943
|
-
}
|
|
944
|
-
}
|
|
945
|
-
|
|
946
|
-
// ../core/dist/index.js
|
|
933
|
+
var import_gutts = require("@dinilmusick/gutts");
|
|
934
|
+
var gutts = __toESM(require("@dinilmusick/gutts"), 1);
|
|
947
935
|
var asyncHooks = globalThis.process?.getBuiltinModule?.("node:async_hooks");
|
|
948
936
|
var KrnlPackageReconciler = class {
|
|
949
937
|
/**
|
|
@@ -956,7 +944,7 @@ var KrnlPackageReconciler = class {
|
|
|
956
944
|
for (const mPath of manifests) {
|
|
957
945
|
try {
|
|
958
946
|
const raw = fs5.readFileSync(mPath, "utf8");
|
|
959
|
-
const json = tryParseJson(raw) ?? {};
|
|
947
|
+
const json = (0, import_gutts.tryParseJson)(raw) ?? {};
|
|
960
948
|
if (json.dependencies && typeof json.dependencies === "object") {
|
|
961
949
|
for (const [pkg, ver] of Object.entries(json.dependencies)) {
|
|
962
950
|
if (!aggregatedDeps[pkg]) aggregatedDeps[pkg] = [];
|
|
@@ -30,6 +30,8 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
30
30
|
// src/index.ts
|
|
31
31
|
var index_exports = {};
|
|
32
32
|
__export(index_exports, {
|
|
33
|
+
EventBus: () => EventBus,
|
|
34
|
+
FunctionalityFacade: () => FunctionalityFacade,
|
|
33
35
|
FunctionalityOrchestration: () => FunctionalityOrchestration,
|
|
34
36
|
HttpProtocolAdapter: () => HttpProtocolAdapter,
|
|
35
37
|
KrnlPackageReconciler: () => KrnlPackageReconciler,
|
|
@@ -37,6 +39,7 @@ __export(index_exports, {
|
|
|
37
39
|
KrnlWorkerPool: () => KrnlWorkerPool,
|
|
38
40
|
LifecycleManager: () => LifecycleManager,
|
|
39
41
|
MemoryTransport: () => MemoryTransport,
|
|
42
|
+
OrchestrationEventFacade: () => OrchestrationEventFacade,
|
|
40
43
|
P2PProtocolAdapter: () => P2PProtocolAdapter,
|
|
41
44
|
ProtocolResolver: () => ProtocolResolver,
|
|
42
45
|
ServiceDiscovery: () => ServiceDiscovery,
|
|
@@ -50,6 +53,7 @@ __export(index_exports, {
|
|
|
50
53
|
UdpProtocolAdapter: () => UdpProtocolAdapter,
|
|
51
54
|
WebSocketProtocolAdapter: () => WebSocketProtocolAdapter,
|
|
52
55
|
WorkerExecutionBoundary: () => WorkerExecutionBoundary,
|
|
56
|
+
createEventChannels: () => createEventChannels,
|
|
53
57
|
createService: () => createService,
|
|
54
58
|
createServiceDefinition: () => createServiceDefinition,
|
|
55
59
|
createServiceFacade: () => createServiceFacade,
|
|
@@ -88,35 +92,6 @@ var ServiceStateStore = class {
|
|
|
88
92
|
}
|
|
89
93
|
};
|
|
90
94
|
|
|
91
|
-
// src/events/ServiceEventBus.ts
|
|
92
|
-
var ServiceEventBus = class {
|
|
93
|
-
handlers = /* @__PURE__ */ new Map();
|
|
94
|
-
on(event, handler) {
|
|
95
|
-
if (!this.handlers.has(event)) {
|
|
96
|
-
this.handlers.set(event, /* @__PURE__ */ new Set());
|
|
97
|
-
}
|
|
98
|
-
const set = this.handlers.get(event);
|
|
99
|
-
set.add(handler);
|
|
100
|
-
return () => {
|
|
101
|
-
set.delete(handler);
|
|
102
|
-
};
|
|
103
|
-
}
|
|
104
|
-
emit(event, payload) {
|
|
105
|
-
const set = this.handlers.get(event);
|
|
106
|
-
if (!set) return;
|
|
107
|
-
for (const handler of Array.from(set)) {
|
|
108
|
-
try {
|
|
109
|
-
handler(payload);
|
|
110
|
-
} catch (err) {
|
|
111
|
-
console.error(`[ServiceEventBus] Handler error for '${event}':`, err);
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
clear() {
|
|
116
|
-
this.handlers.clear();
|
|
117
|
-
}
|
|
118
|
-
};
|
|
119
|
-
|
|
120
95
|
// src/lifecycle/LifecycleManager.ts
|
|
121
96
|
var TRANSITIONS = {
|
|
122
97
|
uninitialized: ["initializing"],
|
|
@@ -161,7 +136,6 @@ var ServiceInstance = class {
|
|
|
161
136
|
this.name = definition.name;
|
|
162
137
|
this.version = definition.version;
|
|
163
138
|
this.lifecycle = new LifecycleManager();
|
|
164
|
-
this.eventBus = new ServiceEventBus();
|
|
165
139
|
if (definition.state) {
|
|
166
140
|
this.stateStore = new ServiceStateStore(definition.state.initial);
|
|
167
141
|
}
|
|
@@ -171,7 +145,6 @@ var ServiceInstance = class {
|
|
|
171
145
|
name;
|
|
172
146
|
version;
|
|
173
147
|
stateStore;
|
|
174
|
-
eventBus;
|
|
175
148
|
lifecycle;
|
|
176
149
|
initialized = false;
|
|
177
150
|
disposed = false;
|
|
@@ -247,12 +220,6 @@ var ServiceInstance = class {
|
|
|
247
220
|
}
|
|
248
221
|
this.stateStore.setState(mutation);
|
|
249
222
|
}
|
|
250
|
-
on(event, handler) {
|
|
251
|
-
return this.eventBus.on(event, handler);
|
|
252
|
-
}
|
|
253
|
-
emit(event, payload) {
|
|
254
|
-
this.eventBus.emit(event, payload);
|
|
255
|
-
}
|
|
256
223
|
};
|
|
257
224
|
|
|
258
225
|
// src/services/ServiceProxy.ts
|
|
@@ -402,12 +369,6 @@ function validateServiceDefinition(definition) {
|
|
|
402
369
|
throw new Error("[Service:" + definition.name + "] Operation '" + key + "' must define a handler.");
|
|
403
370
|
}
|
|
404
371
|
}
|
|
405
|
-
for (const [key, event] of Object.entries(definition.events ?? {})) {
|
|
406
|
-
if (!event || typeof event !== "object") {
|
|
407
|
-
throw new Error("[Service:" + definition.name + "] Invalid event '" + key + "'.");
|
|
408
|
-
}
|
|
409
|
-
assertNonEmptyString(event.name, "events." + key + ".name");
|
|
410
|
-
}
|
|
411
372
|
for (const [key, schema] of Object.entries(definition.inputs ?? {})) assertRecord(schema, "inputs." + key);
|
|
412
373
|
for (const [key, schema] of Object.entries(definition.outputs ?? {})) assertRecord(schema, "outputs." + key);
|
|
413
374
|
if (definition.state?.schema !== void 0) assertRecord(definition.state.schema, "state.schema");
|
|
@@ -440,6 +401,137 @@ function createServiceProxy(definition, adapter, endpoint) {
|
|
|
440
401
|
return new ServiceProxy(definition, adapter, endpoint);
|
|
441
402
|
}
|
|
442
403
|
|
|
404
|
+
// src/events/EventBus.ts
|
|
405
|
+
var EventBus = class {
|
|
406
|
+
handlers = /* @__PURE__ */ new Map();
|
|
407
|
+
subscribe(event, handler) {
|
|
408
|
+
let listeners = this.handlers.get(event);
|
|
409
|
+
if (!listeners) {
|
|
410
|
+
listeners = /* @__PURE__ */ new Set();
|
|
411
|
+
this.handlers.set(event, listeners);
|
|
412
|
+
}
|
|
413
|
+
listeners.add(handler);
|
|
414
|
+
return {
|
|
415
|
+
unsubscribe: () => {
|
|
416
|
+
listeners?.delete(handler);
|
|
417
|
+
if (listeners && listeners.size === 0) this.handlers.delete(event);
|
|
418
|
+
}
|
|
419
|
+
};
|
|
420
|
+
}
|
|
421
|
+
on(event, handler) {
|
|
422
|
+
return this.subscribe(event, handler).unsubscribe;
|
|
423
|
+
}
|
|
424
|
+
emit(event, payload) {
|
|
425
|
+
const listeners = this.handlers.get(event);
|
|
426
|
+
if (!listeners) return;
|
|
427
|
+
for (const listener of Array.from(listeners)) {
|
|
428
|
+
try {
|
|
429
|
+
listener(payload);
|
|
430
|
+
} catch (error) {
|
|
431
|
+
console.error(`[EventBus] Handler error for '${event}':`, error);
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
clear() {
|
|
436
|
+
this.handlers.clear();
|
|
437
|
+
}
|
|
438
|
+
};
|
|
439
|
+
function createEventChannels(bus, names) {
|
|
440
|
+
const channels = {};
|
|
441
|
+
for (const name of names) {
|
|
442
|
+
channels[name] = {
|
|
443
|
+
name,
|
|
444
|
+
subscribe: (handler) => bus.subscribe(name, handler),
|
|
445
|
+
on: (handler) => bus.on(name, handler)
|
|
446
|
+
};
|
|
447
|
+
}
|
|
448
|
+
return channels;
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
// src/functionalities/FunctionalityFacade.ts
|
|
452
|
+
var FunctionalityFacade = class {
|
|
453
|
+
id;
|
|
454
|
+
name;
|
|
455
|
+
description;
|
|
456
|
+
bubbleEvents;
|
|
457
|
+
definition;
|
|
458
|
+
eventBus;
|
|
459
|
+
events;
|
|
460
|
+
constructor(id, definition, options = {}) {
|
|
461
|
+
if (!id || typeof id !== "string") {
|
|
462
|
+
throw new Error("[FunctionalityFacade] Functionality id must be a non-empty string.");
|
|
463
|
+
}
|
|
464
|
+
if (!definition || typeof definition.execute !== "function") {
|
|
465
|
+
throw new Error(`[FunctionalityFacade:${id}] Functionality must define execute().`);
|
|
466
|
+
}
|
|
467
|
+
this.id = id;
|
|
468
|
+
this.name = definition.name || id;
|
|
469
|
+
this.description = definition.description || "";
|
|
470
|
+
this.bubbleEvents = options.bubbleEvents ?? definition.bubbleEvents ?? true;
|
|
471
|
+
this.definition = definition;
|
|
472
|
+
this.eventBus = new EventBus();
|
|
473
|
+
for (const reserved of ["triggered", "completed", "failed"]) {
|
|
474
|
+
if (definition.events && reserved in definition.events) {
|
|
475
|
+
throw new Error(`[FunctionalityFacade:${id}] Event '${reserved}' is reserved for functionality lifecycle.`);
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
const eventNames = [
|
|
479
|
+
"triggered",
|
|
480
|
+
"completed",
|
|
481
|
+
"failed",
|
|
482
|
+
...Object.keys(definition.events ?? {})
|
|
483
|
+
];
|
|
484
|
+
this.events = createEventChannels(this.eventBus, eventNames);
|
|
485
|
+
}
|
|
486
|
+
getEventDefinitions() {
|
|
487
|
+
return {
|
|
488
|
+
triggered: { name: "triggered", description: "Functionality execution started." },
|
|
489
|
+
completed: { name: "completed", description: "Functionality execution completed successfully." },
|
|
490
|
+
failed: { name: "failed", description: "Functionality execution failed." },
|
|
491
|
+
...this.definition.events ?? {}
|
|
492
|
+
};
|
|
493
|
+
}
|
|
494
|
+
subscribe(event, handler) {
|
|
495
|
+
return this.eventBus.on(event, handler);
|
|
496
|
+
}
|
|
497
|
+
emit(event, payload) {
|
|
498
|
+
this.eventBus.emit(event, payload);
|
|
499
|
+
}
|
|
500
|
+
async execute(input, context) {
|
|
501
|
+
const lifecycle = {
|
|
502
|
+
serviceId: context.serviceId,
|
|
503
|
+
functionalityId: this.id,
|
|
504
|
+
functionalityName: this.name,
|
|
505
|
+
correlationId: context.correlationId,
|
|
506
|
+
timestamp: Date.now(),
|
|
507
|
+
input
|
|
508
|
+
};
|
|
509
|
+
this.emit("triggered", lifecycle);
|
|
510
|
+
try {
|
|
511
|
+
const output = await this.definition.execute(input, {
|
|
512
|
+
...context,
|
|
513
|
+
emit: (event, payload) => this.emit(event, payload)
|
|
514
|
+
});
|
|
515
|
+
this.emit("completed", {
|
|
516
|
+
...lifecycle,
|
|
517
|
+
timestamp: Date.now(),
|
|
518
|
+
output
|
|
519
|
+
});
|
|
520
|
+
return output;
|
|
521
|
+
} catch (error) {
|
|
522
|
+
this.emit("failed", {
|
|
523
|
+
...lifecycle,
|
|
524
|
+
timestamp: Date.now(),
|
|
525
|
+
error: error?.message || String(error)
|
|
526
|
+
});
|
|
527
|
+
throw error;
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
clearEventSubscriptions() {
|
|
531
|
+
this.eventBus.clear();
|
|
532
|
+
}
|
|
533
|
+
};
|
|
534
|
+
|
|
443
535
|
// ../../node_modules/.pnpm/p-queue@10.0.0/node_modules/p-queue/dist/lower-bound.js
|
|
444
536
|
function lowerBound(array, value, comparator) {
|
|
445
537
|
let first = 0;
|
|
@@ -2360,7 +2452,10 @@ var ServiceFacade = class {
|
|
|
2360
2452
|
this.name = config.name || config.id;
|
|
2361
2453
|
this.version = config.version || "1.0.0";
|
|
2362
2454
|
this.description = config.description || "";
|
|
2363
|
-
this.functionalities =
|
|
2455
|
+
this.functionalities = {};
|
|
2456
|
+
for (const [name, functionality] of Object.entries(config.functionalities ?? {})) {
|
|
2457
|
+
this.registerFunctionality(name, functionality);
|
|
2458
|
+
}
|
|
2364
2459
|
this.functionalityOrchestrations = config.functionalityOrchestrations ? { ...config.functionalityOrchestrations } : config.orchestrations ? { ...config.orchestrations } : {};
|
|
2365
2460
|
this.libraries = config.libraries ? { ...config.libraries } : {};
|
|
2366
2461
|
this.dependencies = Object.freeze(config.dependencies ? [...config.dependencies] : []);
|
|
@@ -2432,8 +2527,11 @@ var ServiceFacade = class {
|
|
|
2432
2527
|
};
|
|
2433
2528
|
const result = await this.queue.executeCommand(command, async (payload, workerCtx) => {
|
|
2434
2529
|
WorkerExecutionBoundary.assertWorkerContext(workerCtx);
|
|
2435
|
-
|
|
2436
|
-
|
|
2530
|
+
const functionality = this.functionalities[op];
|
|
2531
|
+
if (functionality) {
|
|
2532
|
+
return await functionality.execute(payload, {
|
|
2533
|
+
serviceId: this.id,
|
|
2534
|
+
functionalityId: functionality.id,
|
|
2437
2535
|
correlationId: workerCtx.correlationId,
|
|
2438
2536
|
state: this.instance.getState()
|
|
2439
2537
|
});
|
|
@@ -2469,6 +2567,13 @@ var ServiceFacade = class {
|
|
|
2469
2567
|
idempotencyKey: options.idempotencyKey,
|
|
2470
2568
|
createdAt: Date.now()
|
|
2471
2569
|
};
|
|
2570
|
+
orch.events.emit("triggered", {
|
|
2571
|
+
serviceId: this.id,
|
|
2572
|
+
orchestrationId: orch.id,
|
|
2573
|
+
orchestrationName: orch.name,
|
|
2574
|
+
correlationId,
|
|
2575
|
+
timestamp: Date.now()
|
|
2576
|
+
});
|
|
2472
2577
|
const cmdResult = await this.queue.executeCommand(
|
|
2473
2578
|
command,
|
|
2474
2579
|
async (payload, workerCtx) => {
|
|
@@ -2558,8 +2663,33 @@ var ServiceFacade = class {
|
|
|
2558
2663
|
);
|
|
2559
2664
|
}
|
|
2560
2665
|
);
|
|
2561
|
-
|
|
2562
|
-
|
|
2666
|
+
const orchestrationResult = cmdResult.data;
|
|
2667
|
+
if (cmdResult.status === "COMPLETED" && orchestrationResult) {
|
|
2668
|
+
const lifecycleEvent = orchestrationResult.status === "COMPLETED" ? "completed" : "failed";
|
|
2669
|
+
orch.events.emit(lifecycleEvent, {
|
|
2670
|
+
serviceId: this.id,
|
|
2671
|
+
orchestrationId: orch.id,
|
|
2672
|
+
orchestrationName: orch.name,
|
|
2673
|
+
correlationId,
|
|
2674
|
+
executionId: String(orchestrationResult.executionMetadata.executionId ?? ""),
|
|
2675
|
+
timestamp: Date.now(),
|
|
2676
|
+
status: orchestrationResult.status,
|
|
2677
|
+
output: orchestrationResult.output,
|
|
2678
|
+
error: orchestrationResult.error
|
|
2679
|
+
});
|
|
2680
|
+
} else {
|
|
2681
|
+
orch.events.emit("failed", {
|
|
2682
|
+
serviceId: this.id,
|
|
2683
|
+
orchestrationId: orch.id,
|
|
2684
|
+
orchestrationName: orch.name,
|
|
2685
|
+
correlationId,
|
|
2686
|
+
timestamp: Date.now(),
|
|
2687
|
+
status: cmdResult.status,
|
|
2688
|
+
error: cmdResult.error
|
|
2689
|
+
});
|
|
2690
|
+
}
|
|
2691
|
+
if (cmdResult.status === "FAILED" || orchestrationResult?.status === "FAILED") {
|
|
2692
|
+
throw new Error(orchestrationResult?.error || cmdResult.error || `[ServiceFacade:${this.id}] Orchestration failed.`);
|
|
2563
2693
|
}
|
|
2564
2694
|
return cmdResult.data;
|
|
2565
2695
|
}
|
|
@@ -2587,17 +2717,29 @@ var ServiceFacade = class {
|
|
|
2587
2717
|
setState(mutation) {
|
|
2588
2718
|
this.instance.setState(mutation);
|
|
2589
2719
|
}
|
|
2590
|
-
|
|
2591
|
-
|
|
2592
|
-
|
|
2593
|
-
|
|
2594
|
-
|
|
2720
|
+
getFunctionality(name) {
|
|
2721
|
+
const functionality = this.functionalities[name];
|
|
2722
|
+
if (!functionality) {
|
|
2723
|
+
throw new Error(`[ServiceFacade:${this.id}] Functionality "${name}" not found.`);
|
|
2724
|
+
}
|
|
2725
|
+
return functionality;
|
|
2595
2726
|
}
|
|
2596
|
-
registerFunctionality(name, functionality) {
|
|
2727
|
+
registerFunctionality(name, functionality, options = {}) {
|
|
2597
2728
|
if (!name || typeof name !== "string") {
|
|
2598
2729
|
throw new Error("[ServiceFacade] Functionality name must be a non-empty string.");
|
|
2599
2730
|
}
|
|
2600
|
-
|
|
2731
|
+
if (functionality instanceof FunctionalityFacade) {
|
|
2732
|
+
this.functionalities[name] = functionality;
|
|
2733
|
+
return this;
|
|
2734
|
+
}
|
|
2735
|
+
if (!functionality || typeof functionality !== "object" || typeof functionality.execute !== "function") {
|
|
2736
|
+
throw new Error(`[ServiceFacade:${this.id}] Functionality "${name}" must define execute().`);
|
|
2737
|
+
}
|
|
2738
|
+
this.functionalities[name] = new FunctionalityFacade(
|
|
2739
|
+
name,
|
|
2740
|
+
functionality,
|
|
2741
|
+
options
|
|
2742
|
+
);
|
|
2601
2743
|
return this;
|
|
2602
2744
|
}
|
|
2603
2745
|
registerFunctionalityOrchestration(name, orchestration) {
|
|
@@ -2635,14 +2777,22 @@ var ServiceFacade = class {
|
|
|
2635
2777
|
return this.getNamespace();
|
|
2636
2778
|
}
|
|
2637
2779
|
getNamespace() {
|
|
2780
|
+
const bubbledFunctionalities = {};
|
|
2781
|
+
for (const [name, functionality] of Object.entries(this.functionalities)) {
|
|
2782
|
+
if (functionality.bubbleEvents) bubbledFunctionalities[name] = functionality;
|
|
2783
|
+
}
|
|
2784
|
+
const bubbledOrchestrations = {};
|
|
2785
|
+
for (const [name, orchestration] of Object.entries(this.functionalityOrchestrations)) {
|
|
2786
|
+
if (orchestration.bubbleEvents) bubbledOrchestrations[name] = orchestration;
|
|
2787
|
+
}
|
|
2638
2788
|
return {
|
|
2639
2789
|
serviceId: this.id,
|
|
2640
2790
|
serviceName: this.name,
|
|
2641
2791
|
version: this.version,
|
|
2642
2792
|
description: this.description,
|
|
2643
2793
|
libraries: { ...this.libraries },
|
|
2644
|
-
functionalities:
|
|
2645
|
-
functionalityOrchestrations:
|
|
2794
|
+
functionalities: bubbledFunctionalities,
|
|
2795
|
+
functionalityOrchestrations: bubbledOrchestrations,
|
|
2646
2796
|
capabilities: this.capabilities,
|
|
2647
2797
|
dependencies: this.dependencies
|
|
2648
2798
|
};
|
|
@@ -3339,6 +3489,34 @@ var KrnlPackageReconciler = class {
|
|
|
3339
3489
|
}
|
|
3340
3490
|
};
|
|
3341
3491
|
|
|
3492
|
+
// src/events/ServiceEventBus.ts
|
|
3493
|
+
var ServiceEventBus = class extends EventBus {
|
|
3494
|
+
};
|
|
3495
|
+
|
|
3496
|
+
// src/events/OrchestrationEventFacade.ts
|
|
3497
|
+
var OrchestrationEventFacade = class {
|
|
3498
|
+
eventBus = new EventBus();
|
|
3499
|
+
events;
|
|
3500
|
+
constructor() {
|
|
3501
|
+
this.events = createEventChannels(this.eventBus, ["triggered", "completed", "failed"]);
|
|
3502
|
+
}
|
|
3503
|
+
get triggered() {
|
|
3504
|
+
return this.events.triggered;
|
|
3505
|
+
}
|
|
3506
|
+
get completed() {
|
|
3507
|
+
return this.events.completed;
|
|
3508
|
+
}
|
|
3509
|
+
get failed() {
|
|
3510
|
+
return this.events.failed;
|
|
3511
|
+
}
|
|
3512
|
+
emit(event, payload) {
|
|
3513
|
+
this.eventBus.emit(event, payload);
|
|
3514
|
+
}
|
|
3515
|
+
clear() {
|
|
3516
|
+
this.eventBus.clear();
|
|
3517
|
+
}
|
|
3518
|
+
};
|
|
3519
|
+
|
|
3342
3520
|
// src/connectivity/ProtocolResolver.ts
|
|
3343
3521
|
var ProtocolResolver = class {
|
|
3344
3522
|
static selectProtocol(requiredCapabilities, availableEndpoints) {
|
|
@@ -3359,6 +3537,8 @@ var FunctionalityOrchestration = class {
|
|
|
3359
3537
|
description;
|
|
3360
3538
|
timeoutMs;
|
|
3361
3539
|
scope = "functionality";
|
|
3540
|
+
bubbleEvents;
|
|
3541
|
+
events;
|
|
3362
3542
|
steps = [];
|
|
3363
3543
|
flows = /* @__PURE__ */ new Map();
|
|
3364
3544
|
constructor(descriptor) {
|
|
@@ -3370,6 +3550,8 @@ var FunctionalityOrchestration = class {
|
|
|
3370
3550
|
this.version = descriptor.version || "1.0.0";
|
|
3371
3551
|
this.description = descriptor.description || "";
|
|
3372
3552
|
this.timeoutMs = descriptor.timeoutMs;
|
|
3553
|
+
this.bubbleEvents = descriptor.bubbleEvents ?? true;
|
|
3554
|
+
this.events = new OrchestrationEventFacade();
|
|
3373
3555
|
}
|
|
3374
3556
|
/**
|
|
3375
3557
|
* Adds a sequential functionality step to the DAG.
|
|
@@ -3530,6 +3712,7 @@ var FunctionalityOrchestration = class {
|
|
|
3530
3712
|
description: this.description,
|
|
3531
3713
|
timeoutMs: this.timeoutMs,
|
|
3532
3714
|
scope: "functionality",
|
|
3715
|
+
bubbleEvents: this.bubbleEvents,
|
|
3533
3716
|
dependencies: [],
|
|
3534
3717
|
steps: this.steps.map((s) => ({
|
|
3535
3718
|
id: s.id,
|
|
@@ -3634,6 +3817,8 @@ var FunctionalityOrchestration = class {
|
|
|
3634
3817
|
var gutts = __toESM(require("@dinilmusick/gutts"), 1);
|
|
3635
3818
|
// Annotate the CommonJS export names for ESM import in node:
|
|
3636
3819
|
0 && (module.exports = {
|
|
3820
|
+
EventBus,
|
|
3821
|
+
FunctionalityFacade,
|
|
3637
3822
|
FunctionalityOrchestration,
|
|
3638
3823
|
HttpProtocolAdapter,
|
|
3639
3824
|
KrnlPackageReconciler,
|
|
@@ -3641,6 +3826,7 @@ var gutts = __toESM(require("@dinilmusick/gutts"), 1);
|
|
|
3641
3826
|
KrnlWorkerPool,
|
|
3642
3827
|
LifecycleManager,
|
|
3643
3828
|
MemoryTransport,
|
|
3829
|
+
OrchestrationEventFacade,
|
|
3644
3830
|
P2PProtocolAdapter,
|
|
3645
3831
|
ProtocolResolver,
|
|
3646
3832
|
ServiceDiscovery,
|
|
@@ -3654,6 +3840,7 @@ var gutts = __toESM(require("@dinilmusick/gutts"), 1);
|
|
|
3654
3840
|
UdpProtocolAdapter,
|
|
3655
3841
|
WebSocketProtocolAdapter,
|
|
3656
3842
|
WorkerExecutionBoundary,
|
|
3843
|
+
createEventChannels,
|
|
3657
3844
|
createService,
|
|
3658
3845
|
createServiceDefinition,
|
|
3659
3846
|
createServiceFacade,
|