@cadenza.io/service 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js ADDED
@@ -0,0 +1,2391 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __defProps = Object.defineProperties;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
7
+ var __getOwnPropNames = Object.getOwnPropertyNames;
8
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
9
+ var __getProtoOf = Object.getPrototypeOf;
10
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
11
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
12
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
13
+ var __spreadValues = (a, b) => {
14
+ for (var prop in b || (b = {}))
15
+ if (__hasOwnProp.call(b, prop))
16
+ __defNormalProp(a, prop, b[prop]);
17
+ if (__getOwnPropSymbols)
18
+ for (var prop of __getOwnPropSymbols(b)) {
19
+ if (__propIsEnum.call(b, prop))
20
+ __defNormalProp(a, prop, b[prop]);
21
+ }
22
+ return a;
23
+ };
24
+ var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
25
+ var __export = (target, all) => {
26
+ for (var name in all)
27
+ __defProp(target, name, { get: all[name], enumerable: true });
28
+ };
29
+ var __copyProps = (to, from, except, desc) => {
30
+ if (from && typeof from === "object" || typeof from === "function") {
31
+ for (let key of __getOwnPropNames(from))
32
+ if (!__hasOwnProp.call(to, key) && key !== except)
33
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
34
+ }
35
+ return to;
36
+ };
37
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
38
+ // If the importer is in node compatibility mode or this is not an ESM
39
+ // file that has been converted to a CommonJS file using a Babel-
40
+ // compatible transform (i.e. "__esModule" has not been set), then set
41
+ // "default" to the CommonJS "module.exports" for node compatibility.
42
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
43
+ mod
44
+ ));
45
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
46
+ var __async = (__this, __arguments, generator) => {
47
+ return new Promise((resolve, reject) => {
48
+ var fulfilled = (value) => {
49
+ try {
50
+ step(generator.next(value));
51
+ } catch (e) {
52
+ reject(e);
53
+ }
54
+ };
55
+ var rejected = (value) => {
56
+ try {
57
+ step(generator.throw(value));
58
+ } catch (e) {
59
+ reject(e);
60
+ }
61
+ };
62
+ var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
63
+ step((generator = generator.apply(__this, __arguments)).next());
64
+ });
65
+ };
66
+
67
+ // src/index.ts
68
+ var index_exports = {};
69
+ __export(index_exports, {
70
+ DatabaseTask: () => DatabaseTask,
71
+ DeputyTask: () => DeputyTask,
72
+ RestController: () => RestController,
73
+ ServiceRegistry: () => ServiceRegistry,
74
+ SignalController: () => SignalController,
75
+ SignalTransmissionTask: () => SignalTransmissionTask,
76
+ SocketController: () => SocketController,
77
+ TaskController: () => TaskController,
78
+ default: () => index_default
79
+ });
80
+ module.exports = __toCommonJS(index_exports);
81
+
82
+ // src/Cadenza.ts
83
+ var import_core3 = __toESM(require("@cadenza.io/core"));
84
+
85
+ // src/graph/definition/DeputyTask.ts
86
+ var import_uuid = require("uuid");
87
+ var import_core = require("@cadenza.io/core");
88
+ var DeputyTask = class extends import_core.Task {
89
+ /**
90
+ * Constructs a DeputyTask as a proxy for triggering a remote flow.
91
+ * @param name - The local name of the DeputyTask.
92
+ * @param remoteRoutineName - The name of the remote routine or task to trigger.
93
+ * @param serviceName - The target service name (optional, defaults to local service if undefined).
94
+ * @param description - A description of the task's purpose (default: '').
95
+ * @param concurrency - The maximum number of concurrent executions (default: 0, unlimited).
96
+ * @param timeout - Timeout in milliseconds (default: 0, handled by engine).
97
+ * @param register - Whether to register the task in the registry (default: true).
98
+ * @param isUnique - Whether to create a unique task (default: false). A unique task will only be executed once per execution ID, merging parents.
99
+ * @param isMeta - Whether to create a meta task (default: false). A meta task is separate from the user logic and is only used for monitoring, optimization, and feature extensions.
100
+ * @param isSubMeta
101
+ * @param isHidden
102
+ * @param getTagCallback - Callback for dynamic tagging, e.g., 'return "default"'.
103
+ * @param inputSchema - Input schema definition.
104
+ * @param validateInputContext - Whether to validate the input context (default: false).
105
+ * @param outputSchema - Output schema definition.
106
+ * @param validateOutputContext - Whether to validate the output context (default: false).
107
+ * @param retryCount
108
+ * @param retryDelay
109
+ * @param retryDelayMax
110
+ * @param retryDelayFactor
111
+ * @emits {meta.deputy.delegation_requested} - Emitted on construction with task and service details.
112
+ * @note Fallbacks should be handled externally via `.doOnFail`; timeouts are managed by the engine.
113
+ */
114
+ constructor(name, remoteRoutineName, serviceName = void 0, description = "", concurrency = 0, timeout = 0, register = true, isUnique = false, isMeta = false, isSubMeta = false, isHidden = false, getTagCallback = void 0, inputSchema = void 0, validateInputContext = false, outputSchema = void 0, validateOutputContext = false, retryCount = 0, retryDelay = 0, retryDelayMax = 0, retryDelayFactor = 1) {
115
+ const taskFunction = (context, emit, progressCallback) => {
116
+ return new Promise((resolve, reject) => {
117
+ const processId = (0, import_uuid.v4)();
118
+ context.__deputyExecId = processId;
119
+ emit("meta.deputy.delegation_requested", __spreadValues({}, context));
120
+ CadenzaService.createEphemeralMetaTask(
121
+ `Resolve deputy ${this.remoteRoutineName}`,
122
+ (responseCtx) => {
123
+ if (responseCtx.errored) {
124
+ reject(new Error(responseCtx.__error));
125
+ } else {
126
+ resolve(responseCtx);
127
+ }
128
+ },
129
+ `Ephemeral resolver for deputy process ${processId}`
130
+ ).doOn(
131
+ `meta.socket_client.delegated:${processId}`,
132
+ `meta.fetch.delegated:${processId}`,
133
+ `meta.service_registry.load_balance_failed:${processId}`
134
+ );
135
+ CadenzaService.createEphemeralMetaTask(
136
+ `On progress deputy ${this.remoteRoutineName}`,
137
+ (ctx) => {
138
+ if (ctx.progress) progressCallback(ctx.progress * ctx.weight);
139
+ },
140
+ `Ephemeral task for deputy process ${processId}`,
141
+ {
142
+ once: false,
143
+ destroyCondition: (ctx) => ctx.progress === 1 || ctx.progress === void 0
144
+ }
145
+ ).doOn(`meta.socket_client.delegation_progress:${processId}`);
146
+ });
147
+ };
148
+ super(
149
+ name,
150
+ taskFunction,
151
+ description,
152
+ concurrency,
153
+ timeout,
154
+ register,
155
+ isUnique,
156
+ isMeta,
157
+ isSubMeta,
158
+ isHidden,
159
+ getTagCallback,
160
+ inputSchema,
161
+ validateInputContext,
162
+ outputSchema,
163
+ validateOutputContext,
164
+ retryCount,
165
+ retryDelay,
166
+ retryDelayMax,
167
+ retryDelayFactor
168
+ );
169
+ this.isDeputy = true;
170
+ this.remoteRoutineName = remoteRoutineName;
171
+ this.serviceName = serviceName;
172
+ this.emit("meta.deputy.created", {
173
+ __localTaskName: this.name,
174
+ __remoteRoutineName: this.remoteRoutineName,
175
+ __serviceName: this.serviceName
176
+ });
177
+ }
178
+ /**
179
+ * Triggers the delegation flow via a signal to the meta-layer.
180
+ * @param context - The GraphContext containing execution data.
181
+ * @param emit
182
+ * @param progressCallback - Callback to update progress (invoked by meta-layer).
183
+ * @returns A Promise resolving with the task result or rejecting on error.
184
+ * @emits {meta.deputy.executed} - Emitted with context to initiate delegation.
185
+ * @edge Engine handles timeout and error, triggering `.doOnFail` if chained.
186
+ * @note The resolution and progress are managed by ephemeral meta-tasks.
187
+ */
188
+ execute(context, emit, progressCallback) {
189
+ var _a;
190
+ const ctx = context.getContext();
191
+ const metaData = context.getMetaData();
192
+ const deputyContext = __spreadValues({
193
+ __localTaskName: this.name,
194
+ __remoteRoutineName: this.remoteRoutineName,
195
+ __serviceName: this.serviceName,
196
+ __contractId: (_a = metaData.__contractId) != null ? _a : null,
197
+ __metaData: __spreadProps(__spreadValues({}, metaData), {
198
+ __deputyTaskId: this.id
199
+ })
200
+ }, ctx);
201
+ return this.taskFunction(deputyContext, emit, progressCallback);
202
+ }
203
+ };
204
+
205
+ // src/graph/definition/DatabaseTask.ts
206
+ var DatabaseTask = class extends DeputyTask {
207
+ /**
208
+ * Constructs a DatabaseTask to execute a database operation on a remote service.
209
+ * @param name - The local name of the DatabaseTask.
210
+ * @param taskName - The name of the database operation task to trigger (e.g., 'dbQueryTaskExecution').
211
+ * @param serviceName - The target database service name (optional, defaults to 'DatabaseService').
212
+ * @param description - A description of the task's purpose (default: '').
213
+ * @param queryData - The query data object containing operation details (e.g., { __operation: 'query', __table: 'users' }).
214
+ * @param concurrency - The maximum number of concurrent executions (default: 0, unlimited).
215
+ * @param timeout - Timeout in milliseconds (default: 0, handled by engine).
216
+ * @param register - Whether to register the task in the registry (default: true).
217
+ * @param isUnique
218
+ * @param isMeta
219
+ * @param isSubMeta
220
+ * @param isHidden
221
+ * @param getTagCallback - Callback for dynamic tagging, e.g., 'return "default"'.
222
+ * @param inputSchema - Input schema definition.
223
+ * @param validateInputContext - Whether to validate the input context (default: false).
224
+ * @param outputSchema - Output schema definition.
225
+ * @param validateOutputContext - Whether to validate the output context (default: false).
226
+ * @param retryCount
227
+ * @param retryDelay
228
+ * @param retryDelayMax
229
+ * @param retryDelayFactor
230
+ * @emits {meta.deputy.created} - Emitted on construction with task and service details.
231
+ * @note Fallbacks via `.doOnFail` externally; timeouts managed by the engine.
232
+ */
233
+ constructor(name, taskName, serviceName = void 0, description = "", queryData, concurrency = 0, timeout = 0, register = true, isUnique = false, isMeta = false, isSubMeta = false, isHidden = false, getTagCallback = void 0, inputSchema = void 0, validateInputContext = false, outputSchema = void 0, validateOutputContext = false, retryCount = 0, retryDelay = 0, retryDelayMax = 0, retryDelayFactor = 1) {
234
+ super(
235
+ name,
236
+ taskName,
237
+ serviceName,
238
+ description,
239
+ concurrency,
240
+ timeout,
241
+ register,
242
+ isUnique,
243
+ isMeta,
244
+ isSubMeta,
245
+ isHidden,
246
+ getTagCallback,
247
+ inputSchema,
248
+ validateInputContext,
249
+ outputSchema,
250
+ validateOutputContext,
251
+ retryCount,
252
+ retryDelay,
253
+ retryDelayMax,
254
+ retryDelayFactor
255
+ );
256
+ this.queryData = queryData;
257
+ }
258
+ /**
259
+ * Triggers the database operation delegation flow via a signal to the meta-layer.
260
+ * @param context - The GraphContext containing execution data.
261
+ * @param emit
262
+ * @param progressCallback - Callback to update progress (invoked by meta-layer).
263
+ * @returns A Promise resolving with the task result or rejecting on error.
264
+ * @emits {meta.deputy.executed} - Emitted with context including queryData to initiate delegation.
265
+ * @edge Engine handles timeout and error, triggering `.doOnFail` if chained.
266
+ * @note The resolution and progress are managed by ephemeral meta-tasks.
267
+ */
268
+ execute(context, emit, progressCallback) {
269
+ var _a;
270
+ const ctx = context.getContext();
271
+ const metaData = context.getMetaData();
272
+ const dynamicQueryData = ctx.queryData;
273
+ delete ctx.queryData;
274
+ const deputyContext = {
275
+ __localTaskName: this.name,
276
+ __remoteRoutineName: this.remoteRoutineName,
277
+ __serviceName: this.serviceName,
278
+ __contractId: (_a = metaData.__contractId) != null ? _a : null,
279
+ __metaData: __spreadProps(__spreadValues({}, metaData), {
280
+ __deputyTaskId: this.id
281
+ }),
282
+ queryData: __spreadValues(__spreadProps(__spreadValues({}, this.queryData), {
283
+ data: __spreadValues({}, ctx)
284
+ }), dynamicQueryData)
285
+ };
286
+ return this.taskFunction(deputyContext, emit, progressCallback);
287
+ }
288
+ };
289
+
290
+ // src/registry/ServiceRegistry.ts
291
+ var ServiceRegistry = class _ServiceRegistry {
292
+ constructor() {
293
+ this.instances = /* @__PURE__ */ new Map();
294
+ this.deputies = /* @__PURE__ */ new Map();
295
+ this.serviceName = null;
296
+ this.serviceInstanceId = null;
297
+ this.useSocket = false;
298
+ this.retryCount = 3;
299
+ this.handleInstanceUpdateTask = CadenzaService.createMetaTask(
300
+ "Handle Instance Update",
301
+ (ctx, emit) => {
302
+ const { serviceInstance } = ctx;
303
+ const { id, serviceName, address, port, exposed } = serviceInstance;
304
+ if (!this.instances.has(serviceName))
305
+ this.instances.set(serviceName, []);
306
+ const instances = this.instances.get(serviceName);
307
+ const existing = instances.find((i) => i.id === id);
308
+ if (existing) {
309
+ Object.assign(existing, serviceInstance);
310
+ } else {
311
+ if (this.deputies.has(serviceName)) {
312
+ emit("meta.service_registry.dependee_registered", {
313
+ __serviceName: serviceName,
314
+ __serviceInstanceId: id,
315
+ __serviceAddress: address,
316
+ __servicePort: port,
317
+ __protocol: exposed ? "https" : "http"
318
+ });
319
+ }
320
+ instances.push(serviceInstance);
321
+ }
322
+ return true;
323
+ },
324
+ "Handles instance update from DB signal"
325
+ ).emitsAfter("meta.service_registry.service_discovered").doOn(
326
+ "meta.initializing_service",
327
+ "CadenzaDB.meta.service_instance.inserted",
328
+ "CadenzaDB.meta.service_instance.updated"
329
+ );
330
+ this.handleSocketStatusUpdateTask = CadenzaService.createMetaTask(
331
+ "Handle Socket Status Update",
332
+ (ctx) => {
333
+ const instanceId = ctx.__serviceInstanceId;
334
+ const serviceName = ctx.__serviceName;
335
+ const instances = this.instances.get(serviceName);
336
+ const instance = instances == null ? void 0 : instances.find((i) => i.id === instanceId);
337
+ if (instance) {
338
+ instance.health = ctx.health;
339
+ instance.numberOfRunningGraphs = ctx.numberOfRunningGraphs;
340
+ }
341
+ return true;
342
+ },
343
+ "Handles status update from socket broadcast"
344
+ ).doOn("meta.socket_client.status_received");
345
+ this.fullSyncTask = CadenzaService.createCadenzaDBQueryTask("service_instance", {
346
+ filter: {
347
+ deleted: false,
348
+ is_active: true,
349
+ is_non_responsive: false,
350
+ is_blocked: false
351
+ },
352
+ fields: [
353
+ "id",
354
+ "address",
355
+ "port",
356
+ "service_name",
357
+ "is_active",
358
+ "is_non_responsive",
359
+ "is_blocked",
360
+ "health",
361
+ "exposed"
362
+ ]
363
+ }).doOn(
364
+ "meta.service_registry_sync_requested",
365
+ "meta.service_registry.instance_inserted"
366
+ ).then(
367
+ CadenzaService.createMetaTask("Split service instances", function* (ctx) {
368
+ const { __serviceInstances } = ctx;
369
+ for (const serviceInstance of __serviceInstances) {
370
+ yield serviceInstance;
371
+ }
372
+ }).then(this.handleInstanceUpdateTask)
373
+ );
374
+ this.updateInstanceId = CadenzaService.createMetaTask(
375
+ "Update instance id",
376
+ (context) => {
377
+ const { __id, __oldId } = context;
378
+ const instance = this.instances.get(__oldId);
379
+ if (!instance) return context;
380
+ this.instances.set(__id, instance);
381
+ this.instances.delete(__oldId);
382
+ return context;
383
+ },
384
+ "Updates instance id."
385
+ ).doOn("meta.service.global_id_set");
386
+ this.getInstanceById = CadenzaService.createMetaTask(
387
+ "Get instance by id",
388
+ (context) => {
389
+ const { __id } = context;
390
+ let instance;
391
+ for (const instances of this.instances.values()) {
392
+ instance = instances.find((i) => i.id === __id);
393
+ if (instance) break;
394
+ }
395
+ return __spreadProps(__spreadValues({}, context), { __instance: instance });
396
+ },
397
+ "Gets instance by id."
398
+ );
399
+ this.getInstancesByServiceName = CadenzaService.createMetaTask(
400
+ "Get instances by name",
401
+ (context) => {
402
+ const { __serviceName } = context;
403
+ const instances = this.instances.get(__serviceName);
404
+ if (!instances) {
405
+ return false;
406
+ }
407
+ return __spreadProps(__spreadValues({}, context), { __instances: instances });
408
+ },
409
+ "Gets instances by name."
410
+ );
411
+ this.handleDeputyRegistrationTask = CadenzaService.createMetaTask(
412
+ "Handle Deputy Registration",
413
+ (ctx, emit) => {
414
+ const { __serviceName } = ctx;
415
+ this.deputies.set(__serviceName, {
416
+ __serviceName,
417
+ __remoteRoutineName: ctx.__remoteRoutineName,
418
+ __localTaskName: ctx.__localTaskName
419
+ });
420
+ for (const instance of this.instances.get(__serviceName)) {
421
+ emit(`meta.service_registry.dependee_registered:${instance.id}`, {
422
+ __serviceName,
423
+ __serviceInstanceId: instance.id,
424
+ __serviceAddress: instance.address,
425
+ __servicePort: instance.port,
426
+ __protocol: instance.exposed ? "https" : "http"
427
+ });
428
+ }
429
+ }
430
+ ).doOn("meta.deputy.created");
431
+ this.getAllInstances = CadenzaService.createMetaTask(
432
+ "Get all instances",
433
+ (context) => __spreadProps(__spreadValues({}, context), {
434
+ __instances: Array.from(this.instances.values()).flat()
435
+ }),
436
+ "Gets all instances."
437
+ );
438
+ this.doForEachInstance = CadenzaService.createMetaTask(
439
+ "Do for each instance",
440
+ function* (context) {
441
+ for (const instances of this.instances.values()) {
442
+ for (const instance of instances) {
443
+ yield __spreadProps(__spreadValues({}, context), { __instance: instance });
444
+ }
445
+ }
446
+ }.bind(this),
447
+ "Yields each instance for branching."
448
+ );
449
+ this.deleteInstance = CadenzaService.createMetaTask(
450
+ "Delete instance",
451
+ (context) => {
452
+ const { __id } = context;
453
+ this.instances.delete(__id);
454
+ return context;
455
+ },
456
+ "Deletes instance."
457
+ ).doOn("CadenzaDB.meta.service_instance.deleted");
458
+ this.getBalancedInstance = CadenzaService.createMetaTask(
459
+ "Get balanced instance",
460
+ (context, emit) => {
461
+ var _a;
462
+ const { __serviceName, __triedInstances, __retries } = context;
463
+ let retries = __retries != null ? __retries : 0;
464
+ let triedInstances = __triedInstances != null ? __triedInstances : [];
465
+ const instances = (_a = this.instances.get(__serviceName)) == null ? void 0 : _a.filter((i) => i.isActive && !i.isNonResponsive && !i.isBlocked).sort((a, b) => a.numberOfRunningGraphs - b.numberOfRunningGraphs);
466
+ if (!instances || instances.length === 0 || retries > this.retryCount) {
467
+ context.errored = true;
468
+ context.__error = "No active instances";
469
+ emit(
470
+ `meta.service_registry.load_balance_failed:${context.__deputyExecId}`,
471
+ context
472
+ );
473
+ return context;
474
+ }
475
+ let instancesToTry = instances.filter(
476
+ (i) => !(__triedInstances == null ? void 0 : __triedInstances.includes(i.id))
477
+ );
478
+ if (instancesToTry.length === 0) {
479
+ if (this.useSocket) {
480
+ emit(
481
+ `meta.service_registry.socket_failed:${context.__instance}`,
482
+ context
483
+ );
484
+ }
485
+ retries++;
486
+ instancesToTry = instances;
487
+ triedInstances = [];
488
+ }
489
+ let selected = instancesToTry[0];
490
+ if (retries > 0) {
491
+ selected = instancesToTry[Math.floor(Math.random() * instancesToTry.length)];
492
+ }
493
+ context.__instance = selected.id;
494
+ context.__triedInstances = triedInstances;
495
+ context.__triedInstances.push(selected.id);
496
+ context.__retries = retries;
497
+ if (this.useSocket) {
498
+ emit(
499
+ `meta.service_registry.selected_instance_for_socket:${context.__instance}`,
500
+ context
501
+ );
502
+ } else {
503
+ emit(
504
+ `meta.service_registry.selected_instance_for_fetch:${context.__instance}`,
505
+ context
506
+ );
507
+ }
508
+ return context;
509
+ },
510
+ "Gets a balanced instance for load balancing"
511
+ ).doOn(
512
+ "meta.deputy.delegation_requested",
513
+ "meta.signal_transmission.requested",
514
+ "meta.socket_client.delegate_failed",
515
+ "meta.fetch.delegate_failed",
516
+ "meta.socket_client.signal_transmission_failed"
517
+ );
518
+ this.getStatusTask = CadenzaService.createMetaTask("Get status", (ctx) => {
519
+ var _a, _b, _c, _d;
520
+ if (!this.serviceName) {
521
+ return {
522
+ __status: "error",
523
+ __error: "No service name defined",
524
+ errored: true
525
+ };
526
+ }
527
+ if (!this.serviceInstanceId) {
528
+ return {
529
+ __status: "error",
530
+ __error: "No service instance id defined",
531
+ errored: true
532
+ };
533
+ }
534
+ const self = (_a = this.instances.get(this.serviceName)) == null ? void 0 : _a.find((i) => i.id === this.serviceInstanceId);
535
+ return __spreadProps(__spreadValues({}, ctx), {
536
+ __status: "ok",
537
+ __numberOfRunningGraphs: (_b = self == null ? void 0 : self.numberOfRunningGraphs) != null ? _b : 0,
538
+ __health: (_c = self == null ? void 0 : self.health) != null ? _c : {},
539
+ __active: (_d = self == null ? void 0 : self.isActive) != null ? _d : false
540
+ });
541
+ }).doOn("meta.socket.status_check_requested");
542
+ this.insertServiceTask = CadenzaService.createCadenzaDBInsertTask(
543
+ "service",
544
+ {},
545
+ {
546
+ // validateInputContext: true,
547
+ inputSchema: {
548
+ type: "object",
549
+ properties: {
550
+ data: {
551
+ type: "object",
552
+ properties: {
553
+ name: {
554
+ type: "string"
555
+ },
556
+ description: {
557
+ type: "string"
558
+ },
559
+ display_name: {
560
+ type: "string"
561
+ },
562
+ is_meta: {
563
+ type: "boolean"
564
+ }
565
+ },
566
+ required: ["name"]
567
+ }
568
+ },
569
+ required: ["data"]
570
+ },
571
+ outputSchema: {
572
+ type: "object",
573
+ properties: {
574
+ __serviceName: {
575
+ type: "string"
576
+ }
577
+ },
578
+ required: ["__serviceName"]
579
+ },
580
+ retryCount: 100,
581
+ retryDelay: 1e4,
582
+ retryDelayMax: 6e4,
583
+ retryDelayFactor: 1.3
584
+ }
585
+ ).doOn("meta.create_service_requested").then(
586
+ CadenzaService.createMetaTask(
587
+ "Set service name",
588
+ ({ __serviceName }) => {
589
+ this.serviceName = __serviceName;
590
+ return true;
591
+ },
592
+ "Sets service name after insertion"
593
+ )
594
+ ).emitsAfter("meta.service_registry.service_inserted").emitsOnFail("meta.service_registry.service_insertion_failed");
595
+ this.insertServiceInstanceTask = CadenzaService.createCadenzaDBInsertTask(
596
+ "serviceInstance",
597
+ {},
598
+ {
599
+ inputSchema: {
600
+ type: "object",
601
+ properties: {
602
+ id: {
603
+ type: "string"
604
+ },
605
+ address: {
606
+ type: "string"
607
+ },
608
+ port: {
609
+ type: "number"
610
+ },
611
+ process_pid: {
612
+ type: "number"
613
+ },
614
+ is_primary: {
615
+ type: "boolean"
616
+ },
617
+ service_name: {
618
+ type: "string"
619
+ },
620
+ is_active: {
621
+ type: "boolean"
622
+ },
623
+ is_non_responsive: {
624
+ type: "boolean"
625
+ },
626
+ is_blocked: {
627
+ type: "boolean"
628
+ },
629
+ exposed: {
630
+ type: "boolean"
631
+ }
632
+ },
633
+ required: [
634
+ "id",
635
+ "address",
636
+ "port",
637
+ "process_pid",
638
+ "service_name",
639
+ "exposed"
640
+ ]
641
+ },
642
+ validateInputContext: true,
643
+ outputSchema: {
644
+ type: "object",
645
+ properties: {
646
+ id: {
647
+ type: "string"
648
+ }
649
+ },
650
+ required: ["id"]
651
+ },
652
+ validateOutputContext: true,
653
+ retryCount: 5,
654
+ retryDelay: 1e3
655
+ }
656
+ ).doOn("meta.rest.network_configured").then(
657
+ CadenzaService.createMetaTask(
658
+ "Setup service",
659
+ (ctx) => {
660
+ const { serviceInstance, __useSocket, __retryCount } = ctx;
661
+ this.serviceInstanceId = serviceInstance.id;
662
+ this.instances.set(serviceInstance.serviceName, [
663
+ __spreadValues({}, serviceInstance)
664
+ ]);
665
+ this.useSocket = __useSocket;
666
+ this.retryCount = __retryCount;
667
+ return true;
668
+ },
669
+ "Sets service instance id after insertion"
670
+ ).emitsAfter(
671
+ "meta.service_registry.instance_inserted",
672
+ "meta.process_signal_queue_requested"
673
+ )
674
+ );
675
+ }
676
+ static get instance() {
677
+ if (!this._instance) this._instance = new _ServiceRegistry();
678
+ return this._instance;
679
+ }
680
+ reset() {
681
+ this.instances.clear();
682
+ }
683
+ };
684
+
685
+ // src/graph/definition/SignalTransmissionTask.ts
686
+ var import_core2 = require("@cadenza.io/core");
687
+ var import_uuid2 = require("uuid");
688
+ var SignalTransmissionTask = class extends import_core2.Task {
689
+ /**
690
+ * Constructs a DatabaseTask to execute a database operation on a remote service.
691
+ * @param name - The local name of the Task.
692
+ * @param signalName - The name of the signal to transmit to the service.
693
+ * @param serviceName - The target database service name (optional, defaults to 'DatabaseService').
694
+ * @param description - A description of the task's purpose (default: '').
695
+ * @param concurrency - The maximum number of concurrent executions (default: 0, unlimited).
696
+ * @param timeout - Timeout in milliseconds (default: 0, handled by engine).
697
+ * @param register - Whether to register the task in the registry (default: true).
698
+ * @param isUnique
699
+ * @param isMeta
700
+ * @param isSubMeta
701
+ * @param isHidden
702
+ * @param getTagCallback - Callback for dynamic tagging, e.g., 'return "default"'.
703
+ * @param inputSchema - Input schema definition.
704
+ * @param validateInputContext - Whether to validate the input context (default: false).
705
+ * @param outputSchema - Output schema definition.
706
+ * @param validateOutputContext - Whether to validate the output context (default: false).
707
+ * @param retryCount
708
+ * @param retryDelay
709
+ * @param retryDelayMax
710
+ * @param retryDelayFactor
711
+ * @emits {meta.deputy.created} - Emitted on construction with task and service details.
712
+ * @note Fallbacks via `.doOnFail` externally; timeouts managed by the engine.
713
+ */
714
+ constructor(name, signalName, serviceName, description = "", concurrency = 0, timeout = 0, register = true, isUnique = false, isMeta = false, isSubMeta = false, isHidden = false, getTagCallback = void 0, inputSchema = void 0, validateInputContext = false, outputSchema = void 0, validateOutputContext = false, retryCount = 0, retryDelay = 0, retryDelayMax = 0, retryDelayFactor = 1) {
715
+ const taskFunction = (context, emit) => {
716
+ return new Promise((resolve, reject) => {
717
+ const processId = (0, import_uuid2.v4)();
718
+ context.__routineExecId = processId;
719
+ emit("meta.signal_transmission.requested", context);
720
+ CadenzaService.createEphemeralMetaTask(
721
+ `Resolve signal transmission for ${this.signalName}`,
722
+ (responseCtx) => {
723
+ if (responseCtx.errored) {
724
+ reject(new Error(responseCtx.__error));
725
+ } else {
726
+ resolve(responseCtx);
727
+ }
728
+ },
729
+ `Ephemeral resolver for signal transmission ${processId}`
730
+ ).doOn(
731
+ `meta.socket_client.transmitted:${processId}`,
732
+ `meta.fetch.transmitted:${processId}`
733
+ );
734
+ });
735
+ };
736
+ super(
737
+ name,
738
+ taskFunction,
739
+ description,
740
+ concurrency,
741
+ timeout,
742
+ register,
743
+ isUnique,
744
+ isMeta,
745
+ isSubMeta,
746
+ isHidden,
747
+ getTagCallback,
748
+ inputSchema,
749
+ validateInputContext,
750
+ outputSchema,
751
+ validateOutputContext,
752
+ retryCount,
753
+ retryDelay,
754
+ retryDelayMax,
755
+ retryDelayFactor
756
+ );
757
+ this.isDeputy = true;
758
+ this.serviceName = serviceName;
759
+ this.signalName = signalName;
760
+ }
761
+ /**
762
+ * Triggers the database operation delegation flow via a signal to the meta-layer.
763
+ * @param context - The GraphContext containing execution data.
764
+ * @param emit
765
+ * @param progressCallback - Callback to update progress (invoked by meta-layer).
766
+ * @returns A Promise resolving with the task result or rejecting on error.
767
+ * @emits {meta.deputy.executed} - Emitted with context including queryData to initiate delegation.
768
+ * @edge Engine handles timeout and error, triggering `.doOnFail` if chained.
769
+ * @note The resolution and progress are managed by ephemeral meta-tasks.
770
+ */
771
+ execute(context, emit, progressCallback) {
772
+ var _a;
773
+ const ctx = context.getContext();
774
+ const metaData = context.getMetaData();
775
+ const deputyContext = __spreadValues({
776
+ __localTaskName: this.name,
777
+ __serviceName: this.serviceName,
778
+ __contractId: (_a = metaData.__contractId) != null ? _a : null,
779
+ __metaData: __spreadProps(__spreadValues({}, metaData), {
780
+ __deputyTaskId: this.id
781
+ }),
782
+ __signalName: this.signalName
783
+ }, ctx);
784
+ return this.taskFunction(deputyContext, emit, progressCallback);
785
+ }
786
+ };
787
+
788
+ // src/network/RestController.ts
789
+ var import_express = __toESM(require("express"));
790
+ var import_body_parser = __toESM(require("body-parser"));
791
+ var import_helmet = __toESM(require("helmet"));
792
+ var import_cors = __toESM(require("cors"));
793
+ var import_rate_limiter_flexible = require("rate-limiter-flexible");
794
+ var import_uuid3 = require("uuid");
795
+ var import_node_http = __toESM(require("http"));
796
+ var import_node_fs = __toESM(require("fs"));
797
+ var import_node_https = __toESM(require("https"));
798
+ var import_node_fetch = __toESM(require("node-fetch"));
799
+ var RestController = class _RestController {
800
+ static get instance() {
801
+ if (!this._instance) this._instance = new _RestController();
802
+ return this._instance;
803
+ }
804
+ constructor() {
805
+ CadenzaService.createMetaRoutine(
806
+ "RestServer",
807
+ [
808
+ CadenzaService.createMetaTask(
809
+ "Setup Express app security",
810
+ (ctx) => {
811
+ var _a, _b;
812
+ const app = (0, import_express.default)();
813
+ app.use(import_body_parser.default.json());
814
+ switch (ctx.__securityProfile) {
815
+ case "low":
816
+ app.use((0, import_helmet.default)());
817
+ app.use((0, import_cors.default)({ origin: "*" }));
818
+ break;
819
+ case "medium":
820
+ app.use((0, import_helmet.default)());
821
+ app.use(
822
+ (0, import_cors.default)({
823
+ origin: (_a = process.env.CORS_ORIGIN) != null ? _a : "*",
824
+ methods: ["GET", "POST"]
825
+ })
826
+ );
827
+ app.use((req, res, next) => {
828
+ new import_rate_limiter_flexible.RateLimiterMemory({
829
+ points: 100,
830
+ duration: 300
831
+ }).consume(req.ip).then(() => next()).catch(
832
+ () => res.status(429).json({ error: "Too many requests" })
833
+ );
834
+ });
835
+ break;
836
+ case "high":
837
+ app.use(
838
+ (0, import_helmet.default)({
839
+ contentSecurityPolicy: {
840
+ directives: { defaultSrc: ["'self'"] }
841
+ },
842
+ // Strict CSP
843
+ referrerPolicy: { policy: "no-referrer" }
844
+ })
845
+ );
846
+ if (!process.env.CORS_ORIGIN) {
847
+ throw new Error(
848
+ "CORS_ORIGIN must be set for high security profile"
849
+ );
850
+ }
851
+ app.use(
852
+ (0, import_cors.default)({
853
+ origin: (_b = process.env.CORS_ORIGIN) != null ? _b : "*",
854
+ methods: ["GET", "POST"],
855
+ credentials: true
856
+ })
857
+ );
858
+ app.use((req, res, next) => {
859
+ new import_rate_limiter_flexible.RateLimiterMemory({
860
+ points: 50,
861
+ duration: 60,
862
+ blockDuration: 300
863
+ }).consume(req.ip).then(() => next()).catch((rej) => {
864
+ if (rej.msBeforeNext > 0) {
865
+ res.status(429).json({
866
+ error: "Too many requests",
867
+ retryAfter: rej.msBeforeNext / 1e3
868
+ });
869
+ } else {
870
+ res.status(429).json({ error: "Rate limit exceeded, blocked" });
871
+ }
872
+ });
873
+ });
874
+ break;
875
+ }
876
+ return __spreadProps(__spreadValues({}, ctx), { __app: app });
877
+ },
878
+ "Sets up the Express server according to the security profile"
879
+ ).then(
880
+ CadenzaService.createMetaTask(
881
+ "Define RestServer",
882
+ (ctx) => {
883
+ const app = ctx.__app;
884
+ app.post("/handshake", (req, res) => {
885
+ CadenzaService.broker.emit("meta.rest.handshake", req.body);
886
+ res.send({ __status: "success" });
887
+ });
888
+ app.post("/delegation", (req, res) => {
889
+ const ctx2 = req.body;
890
+ const routineExecId = ctx2.__routineExecId || (0, import_uuid3.v4)();
891
+ CadenzaService.createEphemeralMetaTask(
892
+ "Resolve delegation",
893
+ (endCtx) => res.json({
894
+ __status: "success",
895
+ __result: endCtx.__result
896
+ }),
897
+ "Resolves a delegation request"
898
+ ).doOn(`meta.node.ended_routine_execution:${routineExecId}`).emitsAfter(`meta.rest.delegation_resolved:${routineExecId}`);
899
+ CadenzaService.createEphemeralMetaTask(
900
+ "Delegation progress update",
901
+ (progressCtx) => {
902
+ if (progressCtx.__progress !== void 0) {
903
+ }
904
+ },
905
+ "Updates delegation progress (polling-based for REST)",
906
+ {
907
+ once: false,
908
+ destroyCondition: (progressCtx) => progressCtx.__progress === 1 || progressCtx.__graphComplete
909
+ }
910
+ ).doOn(
911
+ `meta.node.routine_execution_progress:${routineExecId}`,
912
+ `meta.node.ended_routine_execution:${routineExecId}`
913
+ );
914
+ CadenzaService.broker.emit("meta.rest.delegation_requested", ctx2);
915
+ });
916
+ app.post("/signal", (req, res) => {
917
+ const ctx2 = req.body;
918
+ res.send({ __status: "success" });
919
+ CadenzaService.broker.emit(ctx2.__signalName, ctx2.__context);
920
+ });
921
+ app.get("/status", (req, res) => {
922
+ CadenzaService.createEphemeralMetaTask(
923
+ "Resolve status check",
924
+ (statusCtx) => res.json(statusCtx),
925
+ "Resolves a status check request"
926
+ ).doAfter(CadenzaService.serviceRegistry.getStatusTask);
927
+ CadenzaService.broker.emit(
928
+ "meta.rest.status_check_requested",
929
+ req.query
930
+ );
931
+ });
932
+ return true;
933
+ },
934
+ "Starts REST server and initiates meta-handling"
935
+ ).then(
936
+ CadenzaService.createMetaTask(
937
+ "Configure network",
938
+ (ctx) => {
939
+ let address = "";
940
+ let port = ctx.__port;
941
+ let exposed = false;
942
+ const createHttpServer = (ctx2) => {
943
+ const server = import_node_http.default.createServer(ctx2.__app);
944
+ ctx2.__httpServer = server;
945
+ server.listen(ctx2.__port, () => {
946
+ var _a, _b;
947
+ if (typeof (server == null ? void 0 : server.address()) === "string") {
948
+ address = server.address();
949
+ } else if (((_a = server == null ? void 0 : server.address()) == null ? void 0 : _a.address) === "::") {
950
+ if (process.env.NODE_ENV === "development") {
951
+ address = "localhost";
952
+ } else if (process.env.IS_DOCKER === "true") {
953
+ address = process.env.PG_GRAPH_SERVER_URL || "localhost";
954
+ }
955
+ } else {
956
+ address = ((_b = server == null ? void 0 : server.address()) == null ? void 0 : _b.address) || "";
957
+ }
958
+ console.log(`Server is running on ${address}:${port}`);
959
+ });
960
+ CadenzaService.createMetaTask(
961
+ "Shutdown HTTP Server",
962
+ () => server.close(),
963
+ "Shuts down the HTTP server"
964
+ ).doOn("meta.server_shutdown_requested").emitsAfter("meta.rest.shutdown:http");
965
+ };
966
+ const createHttpsServer = (ctx2) => {
967
+ if (!process.env.SSL_KEY_PATH || !process.env.SSL_CERT_PATH) {
968
+ throw new Error(
969
+ "SSL_KEY_PATH and SSL_CERT_PATH must be set"
970
+ );
971
+ }
972
+ const options = {
973
+ key: import_node_fs.default.readFileSync(process.env.SSL_KEY_PATH),
974
+ cert: import_node_fs.default.readFileSync(process.env.SSL_CERT_PATH)
975
+ };
976
+ const httpsServer = import_node_https.default.createServer(options, ctx2.__app);
977
+ ctx2.__httpsServer = httpsServer;
978
+ httpsServer.listen(443, () => {
979
+ var _a, _b;
980
+ if (typeof (httpsServer == null ? void 0 : httpsServer.address()) === "string") {
981
+ address = httpsServer.address();
982
+ } else if (((_a = httpsServer == null ? void 0 : httpsServer.address()) == null ? void 0 : _a.address) === "::") {
983
+ if (process.env.IS_DOCKER === "true") {
984
+ address = process.env.PG_GRAPH_SERVER_URL || "localhost";
985
+ }
986
+ } else {
987
+ address = ((_b = httpsServer == null ? void 0 : httpsServer.address()) == null ? void 0 : _b.address) || "";
988
+ }
989
+ exposed = true;
990
+ console.log(`HTTPS Server is running on ${address}:443`);
991
+ });
992
+ CadenzaService.createMetaTask(
993
+ "Shutdown HTTPS Server",
994
+ () => httpsServer.close(),
995
+ "Shuts down the HTTPS server"
996
+ ).doOn("meta.server_shutdown_requested").emitsAfter("meta.rest.shutdown:https");
997
+ };
998
+ if (ctx.__networkMode === "internal") {
999
+ createHttpServer(ctx);
1000
+ } else if (ctx.__networkMode === "exposed") {
1001
+ createHttpServer(ctx);
1002
+ createHttpsServer(ctx);
1003
+ } else if (ctx.__networkMode === "exposed-high-sec") {
1004
+ createHttpsServer(ctx);
1005
+ } else if (ctx.__networkMode === "auto") {
1006
+ createHttpServer(ctx);
1007
+ }
1008
+ ctx.id = (0, import_uuid3.v4)();
1009
+ ctx.address = address;
1010
+ ctx.port = port;
1011
+ ctx.exposed = exposed;
1012
+ ctx.process_pid = process.pid;
1013
+ ctx.service_name = ctx.__serviceName;
1014
+ return ctx;
1015
+ },
1016
+ "Configures network mode"
1017
+ ).emitsAfter("meta.rest.network_configured").emitsOnFail("meta.rest.network_configuration_failed")
1018
+ ).emitsOnFail("meta.rest.failed")
1019
+ )
1020
+ ],
1021
+ "Bootstraps the REST server as socket fallback"
1022
+ ).doOn("meta.service_registry.service_inserted");
1023
+ CadenzaService.createMetaTask(
1024
+ "FetchClient",
1025
+ (ctx) => {
1026
+ const {
1027
+ __serviceName,
1028
+ __serviceInstanceId,
1029
+ __serviceAddress,
1030
+ __servicePort,
1031
+ __protocol
1032
+ } = ctx;
1033
+ const port = __protocol === "https" ? 443 : __servicePort;
1034
+ const URL = `${__protocol}://${__serviceAddress}:${port}`;
1035
+ CadenzaService.createMetaTask(
1036
+ "Send Handshake",
1037
+ (ctx2) => __async(null, null, function* () {
1038
+ const response = yield (0, import_node_fetch.default)(`${URL}/handshake`, {
1039
+ method: "POST",
1040
+ body: JSON.stringify(ctx2)
1041
+ });
1042
+ const result = yield response.json();
1043
+ result.__serviceInstanceId = __serviceInstanceId;
1044
+ return result;
1045
+ }),
1046
+ "Sends handshake request"
1047
+ ).doOn("meta.fetch.handshake_requested").emitsAfter("meta.fetch.handshake_complete");
1048
+ CadenzaService.createMetaTask(
1049
+ "Delegate flow to REST server",
1050
+ (ctx2, emit) => __async(null, null, function* () {
1051
+ if (ctx2.__remoteRoutineName === void 0) {
1052
+ return;
1053
+ }
1054
+ let resultContext;
1055
+ try {
1056
+ const response = yield (0, import_node_fetch.default)(`${URL}/delegation`, {
1057
+ method: "POST",
1058
+ body: JSON.stringify(ctx2)
1059
+ });
1060
+ resultContext = yield response.json();
1061
+ } catch (e) {
1062
+ resultContext = __spreadValues(__spreadValues({
1063
+ __error: `Error: ${e}`,
1064
+ errored: true
1065
+ }, ctx2), ctx2.__metaData);
1066
+ } finally {
1067
+ emit(`meta.fetch.delegated:${ctx2.__deputyExecId}`, resultContext);
1068
+ }
1069
+ return resultContext;
1070
+ }),
1071
+ "Sends delegation request"
1072
+ ).doOn(
1073
+ `meta.service_registry.selected_instance_for_fetch:${__serviceInstanceId}`,
1074
+ `meta.service_registry.socket_failed:${__serviceInstanceId}`
1075
+ ).emitsOnFail("meta.fetch.delegate_failed");
1076
+ CadenzaService.createMetaTask(
1077
+ "Transmit signal to server",
1078
+ (ctx2, emit) => __async(null, null, function* () {
1079
+ if (ctx2.__signalName === void 0) {
1080
+ return;
1081
+ }
1082
+ let response;
1083
+ try {
1084
+ response = yield (0, import_node_fetch.default)(`${URL}/signal`, {
1085
+ method: "POST",
1086
+ body: JSON.stringify(ctx2)
1087
+ });
1088
+ response = yield response.json();
1089
+ if (ctx2.__routineExecId) {
1090
+ emit(`meta.fetch.transmitted:${ctx2.__routineExecId}`, response);
1091
+ }
1092
+ } catch (e) {
1093
+ response = __spreadValues({
1094
+ __error: `Error: ${e}`,
1095
+ errored: true
1096
+ }, ctx2);
1097
+ }
1098
+ return response;
1099
+ }),
1100
+ "Sends signal request"
1101
+ ).doOn(
1102
+ `meta.service_registry.selected_instance_for_fetch:${__serviceInstanceId}`,
1103
+ `meta.signal_controller.remote_signal_registered:${__serviceName}`,
1104
+ "meta.signal_controller.wildcard_signal_registered"
1105
+ ).emitsOnFail("meta.fetch.signal_transmission_failed");
1106
+ CadenzaService.createMetaTask(
1107
+ "Request status",
1108
+ (ctx2) => __async(null, null, function* () {
1109
+ let status;
1110
+ try {
1111
+ const response = yield (0, import_node_fetch.default)(`${URL}/status`, { method: "GET" });
1112
+ status = yield response.json();
1113
+ } catch (e) {
1114
+ status = __spreadValues({
1115
+ __error: `Error: ${e}`,
1116
+ errored: true
1117
+ }, ctx2);
1118
+ }
1119
+ return status;
1120
+ }),
1121
+ "Requests status"
1122
+ ).doOn("meta.fetch.status_check_requested").emitsAfter("meta.fetch.status_checked").emitsOnFail("meta.fetch.status_check_failed");
1123
+ return true;
1124
+ },
1125
+ "Manages REST client requests as fallback"
1126
+ ).doOn("meta.service_registry.dependee_registered").emitsOnFail("meta.fetch.connect_failed");
1127
+ }
1128
+ };
1129
+
1130
+ // src/network/SocketController.ts
1131
+ var import_socket = require("socket.io");
1132
+ var import_rate_limiter_flexible2 = require("rate-limiter-flexible");
1133
+ var import_xss = __toESM(require("xss"));
1134
+ var import_socket2 = require("socket.io-client");
1135
+ var SocketController = class _SocketController {
1136
+ static get instance() {
1137
+ if (!this._instance) this._instance = new _SocketController();
1138
+ return this._instance;
1139
+ }
1140
+ constructor() {
1141
+ CadenzaService.createMetaRoutine(
1142
+ "SocketServer",
1143
+ [
1144
+ CadenzaService.createMetaTask("Setup SocketServer", (ctx) => {
1145
+ var _a, _b;
1146
+ if (!ctx.__useSocket) {
1147
+ return;
1148
+ }
1149
+ const server = new import_socket.Server((_a = ctx.__httpsServer) != null ? _a : ctx.__httpServer);
1150
+ ctx.__socketServer = server;
1151
+ const profile = (_b = ctx.__securityProfile) != null ? _b : "medium";
1152
+ server.use((socket, next) => {
1153
+ var _a2;
1154
+ const origin = socket.handshake.headers.origin;
1155
+ const allowedOrigins = ["*"];
1156
+ const networkType = (_a2 = ctx.__networkType) != null ? _a2 : "internal";
1157
+ let effectiveOrigin = origin || "unknown";
1158
+ if (networkType === "internal") effectiveOrigin = "internal";
1159
+ if (profile !== "low" && !allowedOrigins.includes(effectiveOrigin) && !allowedOrigins.includes("*")) {
1160
+ return next(new Error("Unauthorized origin"));
1161
+ }
1162
+ const limiterOptions = {
1163
+ low: { points: Infinity, duration: 300 },
1164
+ medium: { points: 100, duration: 300 },
1165
+ high: { points: 50, duration: 60, blockDuration: 300 }
1166
+ };
1167
+ const limiter = new import_rate_limiter_flexible2.RateLimiterMemory(limiterOptions[profile]);
1168
+ socket.use((packet, next2) => {
1169
+ limiter.consume(socket.handshake.address).then(() => next2()).catch((rej) => {
1170
+ if (rej.msBeforeNext > 0) {
1171
+ socket.emit("error", {
1172
+ message: "Rate limit exceeded",
1173
+ retryAfter: rej.msBeforeNext / 1e3
1174
+ });
1175
+ } else {
1176
+ socket.disconnect(true);
1177
+ }
1178
+ });
1179
+ });
1180
+ socket.use((packet, next2) => {
1181
+ if (profile !== "low") {
1182
+ const sanitize = (data) => {
1183
+ if (typeof data === "string") return (0, import_xss.default)(data);
1184
+ if (typeof data === "object") {
1185
+ for (const key in data) {
1186
+ data[key] = sanitize(data[key]);
1187
+ }
1188
+ }
1189
+ return data;
1190
+ };
1191
+ packet[1] = sanitize(packet[1]);
1192
+ }
1193
+ next2();
1194
+ });
1195
+ });
1196
+ }).then(
1197
+ CadenzaService.createMetaTask(
1198
+ "Start SocketServer",
1199
+ (ctx) => {
1200
+ const server = ctx.__socketServer;
1201
+ server.on("connection", (ws) => {
1202
+ ws.on(
1203
+ "handshake",
1204
+ (ctx2) => CadenzaService.broker.emit("meta.socket.handshake", ctx2)
1205
+ );
1206
+ ws.on(
1207
+ "delegation",
1208
+ (ctx2, callback) => {
1209
+ CadenzaService.createEphemeralMetaTask(
1210
+ "Resolve delegation",
1211
+ callback,
1212
+ "Resolves a delegation request using the provided callback from the client (.emitWithAck())"
1213
+ ).doOn(
1214
+ `meta.node.ended_routine_execution:${ctx2.__routineExecId}`
1215
+ ).emitsAfter(
1216
+ `meta.socket.delegation_resolved:${ctx2.__routineExecId}`
1217
+ );
1218
+ CadenzaService.createEphemeralMetaTask(
1219
+ "Delegation progress update",
1220
+ (ctx3) => {
1221
+ if (ctx3.__progress !== void 0)
1222
+ ws.emit("delegation_progress", ctx3);
1223
+ },
1224
+ "Updates delegation progress",
1225
+ {
1226
+ once: false,
1227
+ destroyCondition: (ctx3) => ctx3.data.progress === 1
1228
+ }
1229
+ ).doOn(
1230
+ `meta.node.routine_execution_progress:${ctx2.__routineExecId}`,
1231
+ `meta.node.ended_routine_execution:${ctx2.__routineExecId}`
1232
+ ).emitsOnFail(
1233
+ `meta.socket.progress_failed:${ctx2.__routineExecId}`
1234
+ );
1235
+ CadenzaService.broker.emit(
1236
+ "meta.socket.delegation_requested",
1237
+ ctx2
1238
+ );
1239
+ }
1240
+ );
1241
+ ws.on(
1242
+ "signal",
1243
+ (ctx2, callback) => {
1244
+ if (CadenzaService.broker.listObservedSignals().includes(ctx2.__signalName)) {
1245
+ callback({
1246
+ __status: "success",
1247
+ __signalName: ctx2.__signalName
1248
+ });
1249
+ CadenzaService.broker.emit(ctx2.__signalName, ctx2);
1250
+ } else {
1251
+ callback({
1252
+ __status: "error",
1253
+ __error: "No such signal",
1254
+ errored: true
1255
+ });
1256
+ }
1257
+ }
1258
+ );
1259
+ ws.on(
1260
+ "status_check",
1261
+ (ctx2, callback) => {
1262
+ CadenzaService.createEphemeralMetaTask(
1263
+ "Resolve status check",
1264
+ callback,
1265
+ "Resolves a status check request"
1266
+ ).doAfter(CadenzaService.serviceRegistry.getStatusTask);
1267
+ CadenzaService.broker.emit(
1268
+ "meta.socket.status_check_requested",
1269
+ ctx2
1270
+ );
1271
+ }
1272
+ );
1273
+ ws.on("disconnect", () => {
1274
+ CadenzaService.broker.emit("meta.socket.disconnected", {
1275
+ __wsId: ws.id
1276
+ });
1277
+ });
1278
+ CadenzaService.broker.emit("meta.socket.connected", { __wsId: ws.id });
1279
+ });
1280
+ CadenzaService.createMetaTask(
1281
+ "Broadcast status",
1282
+ (ctx2) => server.emit("status_update", ctx2),
1283
+ "Broadcasts the status of the server to all clients"
1284
+ ).doOn("meta.service.updated");
1285
+ CadenzaService.createMetaTask(
1286
+ "Shutdown SocketServer",
1287
+ () => server.close(),
1288
+ "Shuts down the socket server"
1289
+ ).doOn("meta.socket_server_shutdown_requested").emitsAfter("meta.socket.shutdown");
1290
+ return true;
1291
+ },
1292
+ "Starts socket server and initiates meta-handling"
1293
+ ).emitsOnFail("meta.socket.failed")
1294
+ )
1295
+ ],
1296
+ "Bootstraps the socket server"
1297
+ ).doOn("meta.rest.network_configured");
1298
+ CadenzaService.createMetaTask(
1299
+ "Connect to socket server",
1300
+ (ctx) => {
1301
+ const {
1302
+ __serviceName,
1303
+ __serviceInstanceId,
1304
+ __serviceAddress,
1305
+ __servicePort,
1306
+ __protocol
1307
+ } = ctx;
1308
+ const socketProtocol = __protocol === "https" ? "wss" : "ws";
1309
+ const port = __protocol === "https" ? 443 : __servicePort;
1310
+ const socket = (0, import_socket2.io)(`${socketProtocol}://${__serviceAddress}:${port}`, {
1311
+ reconnection: true,
1312
+ reconnectionAttempts: 20,
1313
+ reconnectionDelay: 1e3,
1314
+ reconnectionDelayMax: 1e4,
1315
+ randomizationFactor: 0.5,
1316
+ retries: 5
1317
+ });
1318
+ socket.on("connect", () => {
1319
+ CadenzaService.broker.emit("meta.socket_client.connected", ctx);
1320
+ socket.emit("handshake", {
1321
+ __serviceInstanceId: ctx.__serviceInstanceId
1322
+ });
1323
+ });
1324
+ socket.on("delegation_progress", (ctx2) => {
1325
+ CadenzaService.broker.emit(
1326
+ `meta.socket_client.delegation_progress:${ctx2.__deputyExecId}`,
1327
+ __spreadValues({ __serviceInstanceId }, ctx2)
1328
+ );
1329
+ });
1330
+ socket.on("status_update", (status) => {
1331
+ CadenzaService.broker.emit("meta.socket_client.status_received", status);
1332
+ });
1333
+ socket.on("disconnect", () => {
1334
+ CadenzaService.broker.emit("meta.socket_client.disconnected", {
1335
+ __serviceInstanceId
1336
+ });
1337
+ });
1338
+ CadenzaService.createMetaTask(
1339
+ `Delegate flow to ${__serviceInstanceId}`,
1340
+ (ctx2, emit) => __async(null, null, function* () {
1341
+ var _a;
1342
+ if (ctx2.__remoteRoutineName === void 0) {
1343
+ return;
1344
+ }
1345
+ let resultContext;
1346
+ try {
1347
+ resultContext = yield socket.timeout((_a = ctx2.__timeout) != null ? _a : 0).emitWithAck("delegation", ctx2);
1348
+ emit(
1349
+ `meta.socket_client.delegated:${ctx2.__deputyExecId}`,
1350
+ resultContext
1351
+ );
1352
+ } catch (e) {
1353
+ resultContext = __spreadValues(__spreadValues({
1354
+ __error: `Timeout error: ${e}`,
1355
+ errored: true
1356
+ }, ctx2), ctx2.__metaData);
1357
+ }
1358
+ return resultContext;
1359
+ }),
1360
+ `Delegate flow to instance ${__serviceInstanceId} of service ${__serviceName} with address ${__serviceAddress}:${__servicePort}`
1361
+ ).doOn(
1362
+ `meta.service_registry.selected_instance_for_socket:${__serviceInstanceId}`
1363
+ ).emitsOnFail(
1364
+ `meta.socket_client.delegate_failed:${__serviceInstanceId}`
1365
+ );
1366
+ CadenzaService.createMetaTask(
1367
+ `Transmit signal to ${__serviceInstanceId}`,
1368
+ (ctx2, emit) => __async(null, null, function* () {
1369
+ var _a;
1370
+ if (ctx2.__signalName === void 0) {
1371
+ return;
1372
+ }
1373
+ let response;
1374
+ try {
1375
+ response = yield socket.timeout((_a = ctx2.__timeout) != null ? _a : 0).emitWithAck("signal", ctx2);
1376
+ if (ctx2.__routineExecId) {
1377
+ emit(
1378
+ `meta.socket_client.transmitted:${ctx2.__routineExecId}`,
1379
+ response
1380
+ );
1381
+ }
1382
+ } catch (e) {
1383
+ response = __spreadValues(__spreadValues({
1384
+ __error: `Timeout error: ${e}`,
1385
+ errored: true
1386
+ }, ctx2), ctx2.__metaData);
1387
+ }
1388
+ return response;
1389
+ }),
1390
+ `Transmits signal to instance ${__serviceInstanceId} of service ${__serviceName} with address ${__serviceAddress}:${__servicePort}`
1391
+ ).doOn(
1392
+ `meta.service_registry.selected_instance_for_socket:${__serviceInstanceId}`
1393
+ ).emitsOnFail(
1394
+ `meta.socket_client.signal_transmission_failed:${__serviceInstanceId}`
1395
+ );
1396
+ CadenzaService.createMetaTask(
1397
+ "Shutdown SocketClient",
1398
+ () => socket.close(),
1399
+ "Shuts down the socket client"
1400
+ ).doOn("meta.socket_shutdown_requested").emitsAfter("meta.socket_client_shutdown_complete");
1401
+ return true;
1402
+ },
1403
+ "Connects to a specified socket server"
1404
+ ).doOn("meta.service_registry.dependee_registered").emitsOnFail("meta.socket_client.connect_failed");
1405
+ }
1406
+ };
1407
+
1408
+ // src/signals/SignalController.ts
1409
+ var SignalController = class _SignalController {
1410
+ static get instance() {
1411
+ if (!this._instance) this._instance = new _SignalController();
1412
+ return this._instance;
1413
+ }
1414
+ constructor() {
1415
+ CadenzaService.createMetaTask(
1416
+ "Handle Signal Registration",
1417
+ (ctx, emit) => {
1418
+ const { __signalName } = ctx;
1419
+ const firstChar = __signalName.charAt(0);
1420
+ const parts = __signalName.split(".");
1421
+ const domain = parts[0] === "meta" ? parts[1] : parts[0];
1422
+ const action = parts[parts.length - 1];
1423
+ emit("meta.signal_controller.signal_added", {
1424
+ data: {
1425
+ name: __signalName,
1426
+ domain,
1427
+ action,
1428
+ is_meta: parts[0] === "meta",
1429
+ service_name: CadenzaService.serviceRegistry.serviceName
1430
+ }
1431
+ });
1432
+ if (firstChar === firstChar.toUpperCase() && firstChar !== firstChar.toLowerCase() || firstChar === "*") {
1433
+ const serviceName = __signalName.split(".")[0];
1434
+ ctx.__listenerServiceName = CadenzaService.serviceRegistry.serviceName;
1435
+ ctx.__emitterSignalName = __signalName.split(".").slice(1).join(".");
1436
+ ctx.__signalName = "meta.signal_controller.foreign_signal_registered";
1437
+ if (serviceName === "*") {
1438
+ emit("meta.signal_controller.wildcard_signal_registered", ctx);
1439
+ } else {
1440
+ emit(
1441
+ `meta.signal_controller.remote_signal_registered:${serviceName}`,
1442
+ ctx
1443
+ );
1444
+ }
1445
+ }
1446
+ return ctx;
1447
+ },
1448
+ "Handles signal registration from a service instance"
1449
+ ).doOn("meta.signal_broker.added");
1450
+ CadenzaService.createMetaTask("Handle foreign signal registration", (ctx) => {
1451
+ const { __emitterSignalName, __listenerServiceName } = ctx;
1452
+ CadenzaService.createSignalTransmissionTask(
1453
+ __emitterSignalName,
1454
+ __listenerServiceName
1455
+ ).doOn(__emitterSignalName);
1456
+ return true;
1457
+ }).doOn("meta.signal_controller.foreign_signal_registered");
1458
+ CadenzaService.createMetaTask(
1459
+ "Add data to signal emission",
1460
+ (ctx) => {
1461
+ const signalEmission = ctx.__signalEmission;
1462
+ if (!signalEmission) {
1463
+ return false;
1464
+ }
1465
+ return {
1466
+ data: __spreadProps(__spreadValues({}, signalEmission), {
1467
+ data: ctx,
1468
+ service_name: CadenzaService.serviceRegistry.serviceName,
1469
+ service_instance_id: CadenzaService.serviceRegistry.serviceInstanceId,
1470
+ signal_id: {
1471
+ subOperation: "query",
1472
+ table: "signal_registry",
1473
+ filter: {
1474
+ name: ctx.__signalLog.signal_name,
1475
+ service_name: CadenzaService.serviceRegistry.serviceName
1476
+ },
1477
+ fields: ["id"],
1478
+ return: "id"
1479
+ }
1480
+ }),
1481
+ transaction: true
1482
+ };
1483
+ },
1484
+ "",
1485
+ { isSubMeta: true, concurrency: 50 }
1486
+ ).doOn(".*").emitsAfter("sub_meta.signal_controller.signal_emitted");
1487
+ CadenzaService.createMetaTask(
1488
+ "Add metadata to signal consumption",
1489
+ (ctx) => {
1490
+ return {
1491
+ data: __spreadProps(__spreadValues({}, ctx.__data), {
1492
+ serviceName: CadenzaService.serviceRegistry.serviceName,
1493
+ serviceInstanceId: CadenzaService.serviceRegistry.serviceInstanceId,
1494
+ signalId: {
1495
+ subOperation: "query",
1496
+ table: "signal_registry",
1497
+ filter: {
1498
+ name: ctx.__data.signalName,
1499
+ serviceName: CadenzaService.serviceRegistry.serviceName
1500
+ },
1501
+ fields: ["id"],
1502
+ return: "id"
1503
+ }
1504
+ })
1505
+ };
1506
+ },
1507
+ "",
1508
+ { isSubMeta: true, concurrency: 50 }
1509
+ ).doOn("meta.node.consumed_signal").emitsAfter("sub_meta.signal_controller.signal_consumed");
1510
+ }
1511
+ };
1512
+
1513
+ // src/graph/controllers/TaskController.ts
1514
+ var TaskController = class _TaskController {
1515
+ static get instance() {
1516
+ if (!this._instance) this._instance = new _TaskController();
1517
+ return this._instance;
1518
+ }
1519
+ constructor() {
1520
+ CadenzaService.createMetaTask("Add data to task creation", (ctx) => {
1521
+ return __spreadProps(__spreadValues({}, ctx.__task), {
1522
+ serviceName: CadenzaService.serviceRegistry.serviceName
1523
+ });
1524
+ }).doOn("meta.task.created").emitsAfter("meta.task_controller.task_created");
1525
+ }
1526
+ };
1527
+
1528
+ // src/Cadenza.ts
1529
+ var CadenzaService = class {
1530
+ static bootstrap() {
1531
+ if (this.isBootstrapped) return;
1532
+ this.isBootstrapped = true;
1533
+ import_core3.default.bootstrap();
1534
+ this.broker = import_core3.default.broker;
1535
+ this.runner = import_core3.default.runner;
1536
+ this.metaRunner = import_core3.default.metaRunner;
1537
+ this.registry = import_core3.default.registry;
1538
+ SignalController.instance;
1539
+ TaskController.instance;
1540
+ this.serviceRegistry = ServiceRegistry.instance;
1541
+ RestController.instance;
1542
+ SocketController.instance;
1543
+ console.log("BOOTSTRAPPED");
1544
+ }
1545
+ static validateServiceName(serviceName) {
1546
+ if (serviceName.length > 100) {
1547
+ throw new Error("Service name must be less than 100 characters");
1548
+ }
1549
+ if (serviceName.includes(" ")) {
1550
+ throw new Error("Service name must not contain spaces");
1551
+ }
1552
+ if (serviceName.includes(".")) {
1553
+ throw new Error("Service name must not contain dots");
1554
+ }
1555
+ if (serviceName.includes("\\")) {
1556
+ throw new Error("Service name must not contain backslashes");
1557
+ }
1558
+ if (serviceName.charAt(0) !== serviceName.charAt(0).toUpperCase() && serviceName.charAt(0) === serviceName.charAt(0).toLowerCase()) {
1559
+ throw new Error("Service name must start with a capital letter");
1560
+ }
1561
+ }
1562
+ static validateName(name) {
1563
+ import_core3.default.validateName(name);
1564
+ }
1565
+ static get runStrategy() {
1566
+ return import_core3.default.runStrategy;
1567
+ }
1568
+ static setMode(mode) {
1569
+ import_core3.default.setMode(mode);
1570
+ }
1571
+ static createDeputyTask(routineName, serviceName = void 0, options = {
1572
+ concurrency: 0,
1573
+ timeout: 0,
1574
+ register: true,
1575
+ isUnique: false,
1576
+ isMeta: false,
1577
+ isSubMeta: false,
1578
+ isHidden: false,
1579
+ getTagCallback: void 0,
1580
+ inputSchema: void 0,
1581
+ validateInputContext: false,
1582
+ outputSchema: void 0,
1583
+ validateOutputContext: false,
1584
+ retryCount: 0,
1585
+ retryDelay: 0,
1586
+ retryDelayMax: 0,
1587
+ retryDelayFactor: 1
1588
+ }) {
1589
+ this.bootstrap();
1590
+ this.validateName(routineName);
1591
+ const name = `Deputy task for "${routineName}"`;
1592
+ return new DeputyTask(
1593
+ name,
1594
+ routineName,
1595
+ serviceName,
1596
+ `Referencing routine in service: ${routineName} on service: ${serviceName}.`,
1597
+ options.concurrency,
1598
+ options.timeout,
1599
+ options.register,
1600
+ options.isUnique,
1601
+ options.isMeta,
1602
+ options.isSubMeta,
1603
+ options.isHidden,
1604
+ options.getTagCallback,
1605
+ options.inputSchema,
1606
+ options.validateInputContext,
1607
+ options.outputSchema,
1608
+ options.validateOutputContext,
1609
+ options.retryCount,
1610
+ options.retryDelay,
1611
+ options.retryDelayMax,
1612
+ options.retryDelayFactor
1613
+ );
1614
+ }
1615
+ static createMetaDeputyTask(routineName, serviceName = void 0, options = {
1616
+ concurrency: 0,
1617
+ timeout: 0,
1618
+ register: true,
1619
+ isUnique: false,
1620
+ isMeta: true,
1621
+ isSubMeta: false,
1622
+ isHidden: false,
1623
+ getTagCallback: void 0,
1624
+ inputSchema: void 0,
1625
+ validateInputContext: false,
1626
+ outputSchema: void 0,
1627
+ validateOutputContext: false,
1628
+ retryCount: 0,
1629
+ retryDelay: 0,
1630
+ retryDelayMax: 0,
1631
+ retryDelayFactor: 1
1632
+ }) {
1633
+ options.isMeta = true;
1634
+ return this.createDeputyTask(routineName, serviceName, options);
1635
+ }
1636
+ static createUniqueDeputyTask(routineName, serviceName = void 0, options = {
1637
+ concurrency: 0,
1638
+ timeout: 0,
1639
+ register: true,
1640
+ isUnique: true,
1641
+ isMeta: false,
1642
+ isSubMeta: false,
1643
+ isHidden: false,
1644
+ getTagCallback: void 0,
1645
+ inputSchema: void 0,
1646
+ validateInputContext: false,
1647
+ outputSchema: void 0,
1648
+ validateOutputContext: false,
1649
+ retryCount: 0,
1650
+ retryDelay: 0,
1651
+ retryDelayMax: 0,
1652
+ retryDelayFactor: 1
1653
+ }) {
1654
+ options.isUnique = true;
1655
+ return this.createDeputyTask(routineName, serviceName, options);
1656
+ }
1657
+ static createUniqueMetaDeputyTask(routineName, serviceName = void 0, options = {
1658
+ concurrency: 0,
1659
+ timeout: 0,
1660
+ register: true,
1661
+ isUnique: true,
1662
+ isMeta: true,
1663
+ isSubMeta: false,
1664
+ isHidden: false,
1665
+ getTagCallback: void 0,
1666
+ inputSchema: void 0,
1667
+ validateInputContext: false,
1668
+ outputSchema: void 0,
1669
+ validateOutputContext: false,
1670
+ retryCount: 0,
1671
+ retryDelay: 0,
1672
+ retryDelayMax: 0,
1673
+ retryDelayFactor: 1
1674
+ }) {
1675
+ options.isMeta = true;
1676
+ return this.createUniqueDeputyTask(routineName, serviceName, options);
1677
+ }
1678
+ static createThrottledDeputyTask(routineName, serviceName = void 0, throttledIdGetter = () => "default", options = {
1679
+ concurrency: 0,
1680
+ timeout: 0,
1681
+ register: true,
1682
+ isUnique: false,
1683
+ isMeta: false,
1684
+ isSubMeta: false,
1685
+ isHidden: false,
1686
+ getTagCallback: void 0,
1687
+ inputSchema: void 0,
1688
+ validateInputContext: false,
1689
+ outputSchema: void 0,
1690
+ validateOutputContext: false,
1691
+ retryCount: 0,
1692
+ retryDelay: 0,
1693
+ retryDelayMax: 0,
1694
+ retryDelayFactor: 1
1695
+ }) {
1696
+ options.getTagCallback = throttledIdGetter;
1697
+ return this.createDeputyTask(routineName, serviceName, options);
1698
+ }
1699
+ static createMetaThrottledDeputyTask(routineName, serviceName = void 0, throttledIdGetter = () => "default", options = {
1700
+ concurrency: 0,
1701
+ timeout: 0,
1702
+ register: true,
1703
+ isUnique: false,
1704
+ isMeta: false,
1705
+ isSubMeta: false,
1706
+ isHidden: false,
1707
+ getTagCallback: void 0,
1708
+ inputSchema: void 0,
1709
+ validateInputContext: false,
1710
+ outputSchema: void 0,
1711
+ validateOutputContext: false,
1712
+ retryCount: 0,
1713
+ retryDelay: 0,
1714
+ retryDelayMax: 0,
1715
+ retryDelayFactor: 1
1716
+ }) {
1717
+ options.isMeta = true;
1718
+ return this.createThrottledDeputyTask(
1719
+ routineName,
1720
+ serviceName,
1721
+ throttledIdGetter,
1722
+ options
1723
+ );
1724
+ }
1725
+ static createSignalTransmissionTask(signalName, serviceName, options = {
1726
+ concurrency: 0,
1727
+ timeout: 0,
1728
+ register: true,
1729
+ isUnique: false,
1730
+ isMeta: true,
1731
+ isSubMeta: false,
1732
+ isHidden: false,
1733
+ getTagCallback: void 0,
1734
+ inputSchema: void 0,
1735
+ validateInputContext: false,
1736
+ outputSchema: void 0,
1737
+ validateOutputContext: false,
1738
+ retryCount: 1,
1739
+ retryDelay: 0,
1740
+ retryDelayMax: 0,
1741
+ retryDelayFactor: 1
1742
+ }) {
1743
+ this.bootstrap();
1744
+ import_core3.default.validateName(signalName);
1745
+ import_core3.default.validateName(serviceName);
1746
+ options.isMeta = true;
1747
+ const name = `SignalTransmission task for "${signalName}"`;
1748
+ return new SignalTransmissionTask(
1749
+ name,
1750
+ signalName,
1751
+ serviceName,
1752
+ `Transmits signal "${signalName}" to service "${serviceName}"`,
1753
+ options.concurrency,
1754
+ options.timeout,
1755
+ options.register,
1756
+ options.isUnique,
1757
+ options.isMeta,
1758
+ options.isSubMeta,
1759
+ options.isHidden,
1760
+ options.getTagCallback,
1761
+ options.inputSchema,
1762
+ options.validateInputContext,
1763
+ options.outputSchema,
1764
+ options.validateOutputContext,
1765
+ options.retryCount,
1766
+ options.retryDelay,
1767
+ options.retryDelayMax,
1768
+ options.retryDelayFactor
1769
+ );
1770
+ }
1771
+ static createDatabaseTask(tableName, operation, databaseServiceName = void 0, queryData, options = {
1772
+ concurrency: 0,
1773
+ timeout: 0,
1774
+ register: true,
1775
+ isUnique: false,
1776
+ isMeta: false,
1777
+ isSubMeta: false,
1778
+ isHidden: false,
1779
+ getTagCallback: void 0,
1780
+ inputSchema: void 0,
1781
+ validateInputContext: false,
1782
+ outputSchema: void 0,
1783
+ validateOutputContext: false,
1784
+ retryCount: 1,
1785
+ retryDelay: 0,
1786
+ retryDelayMax: 0,
1787
+ retryDelayFactor: 1
1788
+ }) {
1789
+ this.bootstrap();
1790
+ import_core3.default.validateName(tableName);
1791
+ import_core3.default.validateName(operation);
1792
+ const tableNameFormatted = tableName.split("_").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join("");
1793
+ const name = `${operation} ${tableName} in ${databaseServiceName != null ? databaseServiceName : "default database service"}`;
1794
+ const description = `Executes a database "${operation}" on table "${tableName}" in ${databaseServiceName != null ? databaseServiceName : "default database service"}`;
1795
+ const taskName = `db${operation.charAt(0).toUpperCase() + operation.slice(1)}${tableNameFormatted}`;
1796
+ return new DatabaseTask(
1797
+ name,
1798
+ taskName,
1799
+ databaseServiceName,
1800
+ description,
1801
+ queryData,
1802
+ options.concurrency,
1803
+ options.timeout,
1804
+ options.register,
1805
+ options.isUnique,
1806
+ options.isMeta,
1807
+ options.isSubMeta,
1808
+ options.isHidden,
1809
+ options.getTagCallback,
1810
+ options.inputSchema,
1811
+ options.validateInputContext,
1812
+ options.outputSchema,
1813
+ options.validateOutputContext,
1814
+ options.retryCount,
1815
+ options.retryDelay,
1816
+ options.retryDelayMax,
1817
+ options.retryDelayFactor
1818
+ );
1819
+ }
1820
+ static createDatabaseInertTask(tableName, databaseServiceName = void 0, queryData = {}, options = {
1821
+ concurrency: 0,
1822
+ timeout: 0,
1823
+ register: true,
1824
+ isUnique: false,
1825
+ isMeta: false,
1826
+ isSubMeta: false,
1827
+ isHidden: false,
1828
+ getTagCallback: void 0,
1829
+ inputSchema: void 0,
1830
+ validateInputContext: false,
1831
+ outputSchema: void 0,
1832
+ validateOutputContext: false,
1833
+ retryCount: 1,
1834
+ retryDelay: 0,
1835
+ retryDelayMax: 0,
1836
+ retryDelayFactor: 1
1837
+ }) {
1838
+ return this.createDatabaseTask(
1839
+ tableName,
1840
+ "insert",
1841
+ databaseServiceName,
1842
+ queryData,
1843
+ options
1844
+ );
1845
+ }
1846
+ static createDatabaseQueryTask(tableName, databaseServiceName = void 0, queryData, options = {
1847
+ concurrency: 0,
1848
+ timeout: 0,
1849
+ register: true,
1850
+ isUnique: false,
1851
+ isMeta: false,
1852
+ isSubMeta: false,
1853
+ isHidden: false,
1854
+ getTagCallback: void 0,
1855
+ inputSchema: void 0,
1856
+ validateInputContext: false,
1857
+ outputSchema: void 0,
1858
+ validateOutputContext: false,
1859
+ retryCount: 1,
1860
+ retryDelay: 0,
1861
+ retryDelayMax: 0,
1862
+ retryDelayFactor: 1
1863
+ }) {
1864
+ return this.createDatabaseTask(
1865
+ tableName,
1866
+ "query",
1867
+ databaseServiceName,
1868
+ queryData,
1869
+ options
1870
+ );
1871
+ }
1872
+ static createCadenzaDBTask(tableName, operation, queryData, options = {
1873
+ concurrency: 0,
1874
+ timeout: 0,
1875
+ register: true,
1876
+ isUnique: false,
1877
+ isMeta: true,
1878
+ isSubMeta: false,
1879
+ isHidden: false,
1880
+ getTagCallback: void 0,
1881
+ inputSchema: void 0,
1882
+ validateInputContext: false,
1883
+ outputSchema: void 0,
1884
+ validateOutputContext: false,
1885
+ retryCount: 1,
1886
+ retryDelay: 0,
1887
+ retryDelayMax: 0,
1888
+ retryDelayFactor: 1
1889
+ }) {
1890
+ options.isMeta = true;
1891
+ return this.createDatabaseTask(
1892
+ tableName,
1893
+ operation,
1894
+ "CadenzaDB",
1895
+ queryData,
1896
+ options
1897
+ );
1898
+ }
1899
+ static createCadenzaDBInsertTask(tableName, queryData = {}, options = {
1900
+ concurrency: 0,
1901
+ timeout: 0,
1902
+ register: true,
1903
+ isUnique: false,
1904
+ isMeta: true,
1905
+ isSubMeta: false,
1906
+ isHidden: false,
1907
+ getTagCallback: void 0,
1908
+ inputSchema: void 0,
1909
+ validateInputContext: false,
1910
+ outputSchema: void 0,
1911
+ validateOutputContext: false,
1912
+ retryCount: 1,
1913
+ retryDelay: 0,
1914
+ retryDelayMax: 0,
1915
+ retryDelayFactor: 1
1916
+ }) {
1917
+ options.isMeta = true;
1918
+ return this.createDatabaseInertTask(
1919
+ tableName,
1920
+ "CadenzaDB",
1921
+ queryData,
1922
+ options
1923
+ );
1924
+ }
1925
+ static createCadenzaDBQueryTask(tableName, queryData, options = {
1926
+ concurrency: 0,
1927
+ timeout: 0,
1928
+ register: true,
1929
+ isUnique: false,
1930
+ isMeta: true,
1931
+ isSubMeta: false,
1932
+ isHidden: false,
1933
+ getTagCallback: void 0,
1934
+ inputSchema: void 0,
1935
+ validateInputContext: false,
1936
+ outputSchema: void 0,
1937
+ validateOutputContext: false,
1938
+ retryCount: 1,
1939
+ retryDelay: 0,
1940
+ retryDelayMax: 0,
1941
+ retryDelayFactor: 1
1942
+ }) {
1943
+ options.isMeta = true;
1944
+ return this.createDatabaseQueryTask(
1945
+ tableName,
1946
+ "CadenzaDB",
1947
+ queryData,
1948
+ options
1949
+ );
1950
+ }
1951
+ static createCadenzaService(serviceName, description, options = {
1952
+ loadBalance: true,
1953
+ useSocket: true,
1954
+ displayName: void 0,
1955
+ isMeta: false,
1956
+ port: parseInt(((_a) => (_a = process.env.HTTP_PORT) != null ? _a : "3000")()),
1957
+ securityProfile: ((_b) => (_b = process.env.SECURITY_PROFILE) != null ? _b : "medium")(),
1958
+ networkMode: ((_c) => (_c = process.env.NETWORK_MODE) != null ? _c : "dev")(),
1959
+ retryCount: 3,
1960
+ cadenzaDB: {
1961
+ address: ((_d) => (_d = process.env.CADENZA_DB_ADDRESS) != null ? _d : "localhost")(),
1962
+ port: parseInt(((_e) => (_e = process.env.CADENZA_DB_PORT) != null ? _e : "5000")())
1963
+ }
1964
+ }) {
1965
+ var _a2, _b2;
1966
+ this.bootstrap();
1967
+ import_core3.default.validateName(serviceName);
1968
+ this.validateServiceName(serviceName);
1969
+ import_core3.default.broker.emit("meta.initializing_service", {
1970
+ // Seed the CadenzaDB
1971
+ serviceInstance: {
1972
+ id: "cadenza-db",
1973
+ serviceName: "CadenzaDB",
1974
+ address: (_a2 = options.cadenzaDB) == null ? void 0 : _a2.address,
1975
+ port: (_b2 = options.cadenzaDB) == null ? void 0 : _b2.port,
1976
+ exposed: options.networkMode !== "dev",
1977
+ numberOfRunningGraphs: 0,
1978
+ isActive: true,
1979
+ // Assume it is deployed
1980
+ isNonResponsive: false,
1981
+ isBlocked: false,
1982
+ health: {}
1983
+ }
1984
+ });
1985
+ import_core3.default.broker.emit("meta.create_service_requested", {
1986
+ data: {
1987
+ name: serviceName,
1988
+ description,
1989
+ displayName: options.displayName,
1990
+ isMeta: options.isMeta
1991
+ },
1992
+ __serviceName: serviceName,
1993
+ __port: options.port,
1994
+ __loadBalance: options.loadBalance,
1995
+ __useSocket: options.useSocket,
1996
+ __securityProfile: options.securityProfile,
1997
+ __networkMode: options.networkMode,
1998
+ __retryCount: options.retryCount
1999
+ });
2000
+ }
2001
+ static createCadenzaMetaService(serviceName, description, options = {
2002
+ loadBalance: false,
2003
+ useSocket: false,
2004
+ log: false,
2005
+ displayName: void 0,
2006
+ isMeta: true,
2007
+ port: parseInt(((_f) => (_f = process.env.HTTP_PORT) != null ? _f : "3000")()),
2008
+ securityProfile: ((_g) => (_g = process.env.SECURITY_PROFILE) != null ? _g : "medium")(),
2009
+ networkMode: ((_h) => (_h = process.env.NETWORK_MODE) != null ? _h : "auto")(),
2010
+ retryCount: 3
2011
+ }) {
2012
+ options.isMeta = true;
2013
+ this.createCadenzaService(serviceName, description, options);
2014
+ }
2015
+ /**
2016
+ * Creates a standard Task and registers it in the GraphRegistry.
2017
+ * @param name Unique identifier for the task.
2018
+ * @param func The function or async generator to execute.
2019
+ * @param description Optional human-readable description for introspection.
2020
+ * @param options Optional task options.
2021
+ * @returns The created Task instance.
2022
+ * @throws Error if name is invalid or duplicate in registry.
2023
+ */
2024
+ static createTask(name, func, description, options = {
2025
+ concurrency: 0,
2026
+ timeout: 0,
2027
+ register: true,
2028
+ isUnique: false,
2029
+ isMeta: false,
2030
+ isSubMeta: false,
2031
+ isHidden: false,
2032
+ getTagCallback: void 0,
2033
+ inputSchema: void 0,
2034
+ validateInputContext: false,
2035
+ outputSchema: void 0,
2036
+ validateOutputContext: false,
2037
+ retryCount: 0,
2038
+ retryDelay: 0,
2039
+ retryDelayMax: 0,
2040
+ retryDelayFactor: 1
2041
+ }) {
2042
+ this.bootstrap();
2043
+ return import_core3.default.createTask(name, func, description, options);
2044
+ }
2045
+ /**
2046
+ * Creates a MetaTask (for meta-layer graphs) and registers it.
2047
+ * MetaTasks suppress further meta-signal emissions to prevent loops.
2048
+ * @param name Unique identifier for the meta-task.
2049
+ * @param func The function or async generator to execute.
2050
+ * @param description Optional description.
2051
+ * @param options Optional task options.
2052
+ * @returns The created MetaTask instance.
2053
+ * @throws Error if name invalid or duplicate.
2054
+ */
2055
+ static createMetaTask(name, func, description, options = {
2056
+ concurrency: 0,
2057
+ timeout: 0,
2058
+ register: true,
2059
+ isUnique: false,
2060
+ isMeta: true,
2061
+ isSubMeta: false,
2062
+ isHidden: false,
2063
+ getTagCallback: void 0,
2064
+ inputSchema: void 0,
2065
+ validateInputContext: false,
2066
+ outputSchema: void 0,
2067
+ validateOutputContext: false,
2068
+ retryCount: 0,
2069
+ retryDelay: 0,
2070
+ retryDelayMax: 0,
2071
+ retryDelayFactor: 1
2072
+ }) {
2073
+ this.bootstrap();
2074
+ return import_core3.default.createMetaTask(name, func, description, options);
2075
+ }
2076
+ /**
2077
+ * Creates a UniqueTask (executes once per execution ID, merging parents) and registers it.
2078
+ * Use for fan-in/joins after parallel branches.
2079
+ * @param name Unique identifier.
2080
+ * @param func Function receiving joinedContexts.
2081
+ * @param description Optional description.
2082
+ * @param options Optional task options.
2083
+ * @returns The created UniqueTask.
2084
+ * @throws Error if invalid.
2085
+ */
2086
+ static createUniqueTask(name, func, description, options = {
2087
+ concurrency: 0,
2088
+ timeout: 0,
2089
+ register: true,
2090
+ isUnique: true,
2091
+ isMeta: false,
2092
+ isSubMeta: false,
2093
+ isHidden: false,
2094
+ getTagCallback: void 0,
2095
+ inputSchema: void 0,
2096
+ validateInputContext: false,
2097
+ outputSchema: void 0,
2098
+ validateOutputContext: false,
2099
+ retryCount: 0,
2100
+ retryDelay: 0,
2101
+ retryDelayMax: 0,
2102
+ retryDelayFactor: 1
2103
+ }) {
2104
+ this.bootstrap();
2105
+ return import_core3.default.createUniqueTask(name, func, description, options);
2106
+ }
2107
+ /**
2108
+ * Creates a UniqueMetaTask for meta-layer joins.
2109
+ * @param name Unique identifier.
2110
+ * @param func Function.
2111
+ * @param description Optional.
2112
+ * @param options Optional task options.
2113
+ * @returns The created UniqueMetaTask.
2114
+ */
2115
+ static createUniqueMetaTask(name, func, description, options = {
2116
+ concurrency: 0,
2117
+ timeout: 0,
2118
+ register: true,
2119
+ isUnique: true,
2120
+ isMeta: true,
2121
+ isSubMeta: false,
2122
+ isHidden: false,
2123
+ getTagCallback: void 0,
2124
+ inputSchema: void 0,
2125
+ validateInputContext: false,
2126
+ outputSchema: void 0,
2127
+ validateOutputContext: false,
2128
+ retryCount: 0,
2129
+ retryDelay: 0,
2130
+ retryDelayMax: 0,
2131
+ retryDelayFactor: 1
2132
+ }) {
2133
+ this.bootstrap();
2134
+ return import_core3.default.createUniqueMetaTask(name, func, description, options);
2135
+ }
2136
+ /**
2137
+ * Creates a ThrottledTask (rate-limited by concurrency or custom groups) and registers it.
2138
+ * @param name Unique identifier.
2139
+ * @param func Function.
2140
+ * @param throttledIdGetter Optional getter for dynamic grouping (e.g., per-user).
2141
+ * @param description Optional.
2142
+ * @param options Optional task options.
2143
+ * @returns The created ThrottledTask.
2144
+ * @edge If no getter, throttles per task ID; use for resource protection.
2145
+ */
2146
+ static createThrottledTask(name, func, throttledIdGetter = () => "default", description, options = {
2147
+ concurrency: 1,
2148
+ timeout: 0,
2149
+ register: true,
2150
+ isUnique: false,
2151
+ isMeta: false,
2152
+ isSubMeta: false,
2153
+ isHidden: false,
2154
+ inputSchema: void 0,
2155
+ validateInputContext: false,
2156
+ outputSchema: void 0,
2157
+ validateOutputContext: false,
2158
+ retryCount: 0,
2159
+ retryDelay: 0,
2160
+ retryDelayMax: 0,
2161
+ retryDelayFactor: 1
2162
+ }) {
2163
+ this.bootstrap();
2164
+ return import_core3.default.createThrottledTask(
2165
+ name,
2166
+ func,
2167
+ throttledIdGetter,
2168
+ description,
2169
+ options
2170
+ );
2171
+ }
2172
+ /**
2173
+ * Creates a ThrottledMetaTask for meta-layer throttling.
2174
+ * @param name Identifier.
2175
+ * @param func Function.
2176
+ * @param throttledIdGetter Optional getter.
2177
+ * @param description Optional.
2178
+ * @param options Optional task options.
2179
+ * @returns The created ThrottledMetaTask.
2180
+ */
2181
+ static createThrottledMetaTask(name, func, throttledIdGetter, description, options = {
2182
+ concurrency: 0,
2183
+ timeout: 0,
2184
+ register: true,
2185
+ isUnique: false,
2186
+ isMeta: true,
2187
+ isSubMeta: false,
2188
+ isHidden: false,
2189
+ inputSchema: void 0,
2190
+ validateInputContext: false,
2191
+ outputSchema: void 0,
2192
+ validateOutputContext: false,
2193
+ retryCount: 0,
2194
+ retryDelay: 0,
2195
+ retryDelayMax: 0,
2196
+ retryDelayFactor: 1
2197
+ }) {
2198
+ this.bootstrap();
2199
+ return import_core3.default.createThrottledMetaTask(
2200
+ name,
2201
+ func,
2202
+ throttledIdGetter,
2203
+ description,
2204
+ options
2205
+ );
2206
+ }
2207
+ /**
2208
+ * Creates a DebounceTask (delays exec until quiet period) and registers it.
2209
+ * @param name Identifier.
2210
+ * @param func Function.
2211
+ * @param description Optional.
2212
+ * @param debounceTime Delay in ms (default 1000).
2213
+ * @param options Optional task options plus optional debounce config (e.g., leading/trailing).
2214
+ * @returns The created DebounceTask.
2215
+ * @edge Multiple triggers within time collapse to one exec.
2216
+ */
2217
+ static createDebounceTask(name, func, description, debounceTime = 1e3, options = {
2218
+ concurrency: 0,
2219
+ timeout: 0,
2220
+ register: true,
2221
+ leading: false,
2222
+ trailing: true,
2223
+ maxWait: 0,
2224
+ isUnique: false,
2225
+ isMeta: false,
2226
+ isSubMeta: false,
2227
+ isHidden: false,
2228
+ inputSchema: void 0,
2229
+ validateInputContext: false,
2230
+ outputSchema: void 0,
2231
+ validateOutputContext: false,
2232
+ retryCount: 0,
2233
+ retryDelay: 0,
2234
+ retryDelayMax: 0,
2235
+ retryDelayFactor: 1
2236
+ }) {
2237
+ this.bootstrap();
2238
+ return import_core3.default.createDebounceTask(
2239
+ name,
2240
+ func,
2241
+ description,
2242
+ debounceTime,
2243
+ options
2244
+ );
2245
+ }
2246
+ /**
2247
+ * Creates a DebouncedMetaTask for meta-layer debouncing.
2248
+ * @param name Identifier.
2249
+ * @param func Function.
2250
+ * @param description Optional.
2251
+ * @param debounceTime Delay in ms.
2252
+ * @param options Optional task options plus optional debounce config (e.g., leading/trailing).
2253
+ * @returns The created DebouncedMetaTask.
2254
+ */
2255
+ static createDebounceMetaTask(name, func, description, debounceTime = 1e3, options = {
2256
+ concurrency: 0,
2257
+ timeout: 0,
2258
+ register: true,
2259
+ leading: false,
2260
+ trailing: true,
2261
+ maxWait: 0,
2262
+ isUnique: false,
2263
+ isMeta: false,
2264
+ isSubMeta: false,
2265
+ isHidden: false,
2266
+ inputSchema: void 0,
2267
+ validateInputContext: false,
2268
+ outputSchema: void 0,
2269
+ validateOutputContext: false,
2270
+ retryCount: 0,
2271
+ retryDelay: 0,
2272
+ retryDelayMax: 0,
2273
+ retryDelayFactor: 1
2274
+ }) {
2275
+ this.bootstrap();
2276
+ return import_core3.default.createDebounceMetaTask(
2277
+ name,
2278
+ func,
2279
+ description,
2280
+ debounceTime,
2281
+ options
2282
+ );
2283
+ }
2284
+ /**
2285
+ * Creates an EphemeralTask (self-destructs after exec or condition) without default registration.
2286
+ * Useful for transients; optionally register if needed.
2287
+ * @param name Identifier (may not be unique if not registered).
2288
+ * @param func Function.
2289
+ * @param description Optional.
2290
+ * @param options Optional task options.
2291
+ * @returns The created EphemeralTask.
2292
+ * @edge Destruction triggered post-exec via Node/Builder; emits meta-signal for cleanup.
2293
+ */
2294
+ static createEphemeralTask(name, func, description, options = {
2295
+ concurrency: 0,
2296
+ timeout: 0,
2297
+ register: false,
2298
+ isUnique: false,
2299
+ isMeta: false,
2300
+ isSubMeta: false,
2301
+ isHidden: false,
2302
+ once: true,
2303
+ destroyCondition: () => true,
2304
+ getTagCallback: void 0,
2305
+ inputSchema: void 0,
2306
+ validateInputContext: false,
2307
+ outputSchema: void 0,
2308
+ validateOutputContext: false,
2309
+ retryCount: 0,
2310
+ retryDelay: 0,
2311
+ retryDelayMax: 0,
2312
+ retryDelayFactor: 1
2313
+ }) {
2314
+ this.bootstrap();
2315
+ return import_core3.default.createEphemeralTask(name, func, description, options);
2316
+ }
2317
+ /**
2318
+ * Creates an EphemeralMetaTask for meta-layer transients.
2319
+ * @param name Identifier.
2320
+ * @param func Function.
2321
+ * @param description Optional.
2322
+ * @param options Optional task options.
2323
+ * @returns The created EphemeralMetaTask.
2324
+ */
2325
+ static createEphemeralMetaTask(name, func, description, options = {
2326
+ concurrency: 0,
2327
+ timeout: 0,
2328
+ register: false,
2329
+ isUnique: false,
2330
+ isMeta: true,
2331
+ isSubMeta: false,
2332
+ isHidden: false,
2333
+ once: true,
2334
+ destroyCondition: () => true,
2335
+ getTagCallback: void 0,
2336
+ inputSchema: void 0,
2337
+ validateInputContext: false,
2338
+ outputSchema: void 0,
2339
+ validateOutputContext: false,
2340
+ retryCount: 0,
2341
+ retryDelay: 0,
2342
+ retryDelayMax: 0,
2343
+ retryDelayFactor: 1
2344
+ }) {
2345
+ this.bootstrap();
2346
+ return import_core3.default.createEphemeralMetaTask(name, func, description, options);
2347
+ }
2348
+ /**
2349
+ * Creates a GraphRoutine (named entry to starting tasks) and registers it.
2350
+ * @param name Unique identifier.
2351
+ * @param tasks Starting tasks (can be empty, but warns as no-op).
2352
+ * @param description Optional.
2353
+ * @returns The created GraphRoutine.
2354
+ * @edge If tasks empty, routine is valid but inert.
2355
+ */
2356
+ static createRoutine(name, tasks, description = "") {
2357
+ this.bootstrap();
2358
+ return import_core3.default.createRoutine(name, tasks, description);
2359
+ }
2360
+ /**
2361
+ * Creates a MetaRoutine for meta-layer entry points.
2362
+ * @param name Identifier.
2363
+ * @param tasks Starting tasks.
2364
+ * @param description Optional.
2365
+ * @returns The created MetaRoutine.
2366
+ */
2367
+ static createMetaRoutine(name, tasks, description = "") {
2368
+ this.bootstrap();
2369
+ return import_core3.default.createMetaRoutine(name, tasks, description);
2370
+ }
2371
+ static reset() {
2372
+ import_core3.default.reset();
2373
+ this.serviceRegistry.reset();
2374
+ }
2375
+ };
2376
+ CadenzaService.isBootstrapped = false;
2377
+
2378
+ // src/index.ts
2379
+ var index_default = CadenzaService;
2380
+ // Annotate the CommonJS export names for ESM import in node:
2381
+ 0 && (module.exports = {
2382
+ DatabaseTask,
2383
+ DeputyTask,
2384
+ RestController,
2385
+ ServiceRegistry,
2386
+ SignalController,
2387
+ SignalTransmissionTask,
2388
+ SocketController,
2389
+ TaskController
2390
+ });
2391
+ //# sourceMappingURL=index.js.map