@cadenza.io/service 2.17.74 → 2.17.76

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.d.mts CHANGED
@@ -319,6 +319,9 @@ declare class ServiceRegistry {
319
319
  private getTransportById;
320
320
  private getRouteableTransport;
321
321
  private getTransportClientKey;
322
+ private resolveCommunicationTypesForService;
323
+ private ensureDependeeClientForInstance;
324
+ private ensureDependeeClientsForService;
322
325
  private hasTransportClientCreated;
323
326
  private markTransportClientCreated;
324
327
  private registerDependee;
@@ -22926,6 +22929,8 @@ declare class RestController {
22926
22929
  private resolveTransportDiagnosticsOptions;
22927
22930
  private ensureFetchClientDiagnostics;
22928
22931
  private getErrorMessage;
22932
+ private resolveJsonBodyLimit;
22933
+ private parseFetchResponse;
22929
22934
  private resolveDelegationTimeoutMs;
22930
22935
  private recordFetchClientError;
22931
22936
  private collectFetchTransportDiagnostics;
package/dist/index.d.ts CHANGED
@@ -319,6 +319,9 @@ declare class ServiceRegistry {
319
319
  private getTransportById;
320
320
  private getRouteableTransport;
321
321
  private getTransportClientKey;
322
+ private resolveCommunicationTypesForService;
323
+ private ensureDependeeClientForInstance;
324
+ private ensureDependeeClientsForService;
322
325
  private hasTransportClientCreated;
323
326
  private markTransportClientCreated;
324
327
  private registerDependee;
@@ -22926,6 +22929,8 @@ declare class RestController {
22926
22929
  private resolveTransportDiagnosticsOptions;
22927
22930
  private ensureFetchClientDiagnostics;
22928
22931
  private getErrorMessage;
22932
+ private resolveJsonBodyLimit;
22933
+ private parseFetchResponse;
22929
22934
  private resolveDelegationTimeoutMs;
22930
22935
  private recordFetchClientError;
22931
22936
  private collectFetchTransportDiagnostics;
package/dist/index.js CHANGED
@@ -1212,39 +1212,12 @@ var ServiceRegistry = class _ServiceRegistry {
1212
1212
  if (trackedInstance?.isFrontend) {
1213
1213
  return true;
1214
1214
  }
1215
- const trackedTransport = this.getRouteableTransport(
1216
- trackedInstance,
1217
- this.useSocket ? "socket" : "rest"
1218
- );
1219
1215
  if (this.deputies.has(serviceName) || this.remoteIntents.has(serviceName) || this.remoteSignals.has(serviceName)) {
1220
- const communicationTypes = Array.from(
1221
- new Set(
1222
- this.deputies.get(serviceName)?.map((d) => d.communicationType) ?? []
1223
- )
1216
+ const connected = this.ensureDependeeClientForInstance(
1217
+ trackedInstance,
1218
+ emit
1224
1219
  );
1225
- if (!communicationTypes.includes("signal") && this.remoteSignals.has(serviceName)) {
1226
- communicationTypes.push("signal");
1227
- }
1228
- if (trackedTransport) {
1229
- const clientCreated = this.hasTransportClientCreated(
1230
- trackedInstance,
1231
- trackedTransport.uuid
1232
- );
1233
- if (!clientCreated) {
1234
- emit("meta.service_registry.dependee_registered", {
1235
- serviceName,
1236
- serviceInstanceId: uuid8,
1237
- serviceTransportId: trackedTransport.uuid,
1238
- serviceOrigin: trackedTransport.origin,
1239
- transportProtocols: trackedTransport.protocols,
1240
- communicationTypes
1241
- });
1242
- this.markTransportClientCreated(
1243
- trackedInstance,
1244
- trackedTransport.uuid
1245
- );
1246
- }
1247
- } else {
1220
+ if (!connected) {
1248
1221
  emit("meta.service_registry.routeable_transport_missing", {
1249
1222
  serviceName,
1250
1223
  serviceInstanceId: uuid8,
@@ -1310,25 +1283,7 @@ var ServiceRegistry = class _ServiceRegistry {
1310
1283
  if (!hasRemoteInterest) {
1311
1284
  return true;
1312
1285
  }
1313
- if (!this.hasTransportClientCreated(ownerInstance, transport.uuid)) {
1314
- const communicationTypes = Array.from(
1315
- new Set(
1316
- this.deputies.get(ownerInstance.serviceName)?.map((descriptor) => descriptor.communicationType) ?? []
1317
- )
1318
- );
1319
- if (!communicationTypes.includes("signal") && this.remoteSignals.has(ownerInstance.serviceName)) {
1320
- communicationTypes.push("signal");
1321
- }
1322
- emit("meta.service_registry.dependee_registered", {
1323
- serviceName: ownerInstance.serviceName,
1324
- serviceInstanceId: ownerInstance.uuid,
1325
- serviceTransportId: transport.uuid,
1326
- serviceOrigin: transport.origin,
1327
- transportProtocols: transport.protocols,
1328
- communicationTypes
1329
- });
1330
- this.markTransportClientCreated(ownerInstance, transport.uuid);
1331
- }
1286
+ this.ensureDependeeClientForInstance(ownerInstance, emit);
1332
1287
  return true;
1333
1288
  },
1334
1289
  "Handles service transport updates independently from instance rows."
@@ -1409,7 +1364,7 @@ var ServiceRegistry = class _ServiceRegistry {
1409
1364
  ).emits("meta.service_registry.registered_global_signals").doOn("global.meta.cadenza_db.gathered_sync_data");
1410
1365
  this.handleGlobalIntentRegistrationTask = CadenzaService.createMetaTask(
1411
1366
  "Handle global intent registration",
1412
- (ctx) => {
1367
+ (ctx, emit) => {
1413
1368
  const intentToTaskMaps = this.normalizeIntentMaps(ctx);
1414
1369
  const sorted = intentToTaskMaps.sort((a, b) => {
1415
1370
  if (a.deleted && !b.deleted) return -1;
@@ -1425,6 +1380,7 @@ var ServiceRegistry = class _ServiceRegistry {
1425
1380
  name: map.intentName
1426
1381
  });
1427
1382
  this.registerRemoteIntentDeputy(map);
1383
+ this.ensureDependeeClientsForService(map.serviceName, emit);
1428
1384
  }
1429
1385
  return true;
1430
1386
  },
@@ -2850,6 +2806,49 @@ var ServiceRegistry = class _ServiceRegistry {
2850
2806
  }
2851
2807
  return buildTransportClientKey(transport);
2852
2808
  }
2809
+ resolveCommunicationTypesForService(serviceName) {
2810
+ const communicationTypes = Array.from(
2811
+ new Set(
2812
+ this.deputies.get(serviceName)?.map((descriptor) => descriptor.communicationType) ?? []
2813
+ )
2814
+ );
2815
+ if (!communicationTypes.includes("signal") && this.remoteSignals.has(serviceName)) {
2816
+ communicationTypes.push("signal");
2817
+ }
2818
+ return communicationTypes;
2819
+ }
2820
+ ensureDependeeClientForInstance(instance, emit) {
2821
+ if (!instance || instance.uuid === this.serviceInstanceId || instance.isFrontend || !instance.isActive || instance.isNonResponsive || instance.isBlocked) {
2822
+ return false;
2823
+ }
2824
+ if (!this.deputies.has(instance.serviceName) && !this.remoteIntents.has(instance.serviceName) && !this.remoteSignals.has(instance.serviceName)) {
2825
+ return false;
2826
+ }
2827
+ const transport = this.getRouteableTransport(
2828
+ instance,
2829
+ this.useSocket ? "socket" : "rest"
2830
+ );
2831
+ if (!transport || this.hasTransportClientCreated(instance, transport.uuid)) {
2832
+ return false;
2833
+ }
2834
+ emit("meta.service_registry.dependee_registered", {
2835
+ serviceName: instance.serviceName,
2836
+ serviceInstanceId: instance.uuid,
2837
+ serviceTransportId: transport.uuid,
2838
+ serviceOrigin: transport.origin,
2839
+ transportProtocols: transport.protocols,
2840
+ communicationTypes: this.resolveCommunicationTypesForService(
2841
+ instance.serviceName
2842
+ )
2843
+ });
2844
+ this.markTransportClientCreated(instance, transport.uuid);
2845
+ return true;
2846
+ }
2847
+ ensureDependeeClientsForService(serviceName, emit) {
2848
+ for (const instance of this.instances.get(serviceName) ?? []) {
2849
+ this.ensureDependeeClientForInstance(instance, emit);
2850
+ }
2851
+ }
2853
2852
  hasTransportClientCreated(instance, transportId) {
2854
2853
  return (instance.clientCreatedTransportIds ?? []).includes(transportId);
2855
2854
  }
@@ -3663,11 +3662,12 @@ var RestController = class _RestController {
3663
3662
  * @returns {Promise<any>} A promise that resolves to the parsed response data if the request is successful.
3664
3663
  * @throws {Error} Throws an error if the request fails due to issues such as timeout or other unexpected errors.
3665
3664
  */
3666
- this.fetchDataWithTimeout = async function(url, requestInit, timeoutMs) {
3665
+ this.fetchDataWithTimeout = async (url, requestInit, timeoutMs) => {
3667
3666
  const signal = AbortSignal.timeout(timeoutMs);
3668
3667
  try {
3669
3668
  const response = await (0, import_node_fetch.default)(url, { ...requestInit, signal });
3670
- return await response.json();
3669
+ const parsedResponse = await this.parseFetchResponse(response);
3670
+ return parsedResponse.data;
3671
3671
  } catch (error) {
3672
3672
  if (error?.name === "AbortError") {
3673
3673
  CadenzaService.log(
@@ -3733,7 +3733,11 @@ var RestController = class _RestController {
3733
3733
  }
3734
3734
  console.log("Service inserted...");
3735
3735
  const app = (0, import_express.default)();
3736
- app.use(import_body_parser.default.json());
3736
+ app.use(
3737
+ import_body_parser.default.json({
3738
+ limit: this.resolveJsonBodyLimit()
3739
+ })
3740
+ );
3737
3741
  switch (ctx.__securityProfile) {
3738
3742
  case "low":
3739
3743
  app.use((0, import_helmet.default)());
@@ -3906,6 +3910,32 @@ var RestController = class _RestController {
3906
3910
  )
3907
3911
  );
3908
3912
  });
3913
+ app.use(
3914
+ (error, _req, res, next) => {
3915
+ if (!error) {
3916
+ next();
3917
+ return;
3918
+ }
3919
+ const statusCode = typeof error.statusCode === "number" ? error.statusCode : typeof error.status === "number" ? error.status : error.type === "entity.too.large" ? 413 : 500;
3920
+ const message = error.type === "entity.too.large" ? `Request payload exceeded REST body limit ${this.resolveJsonBodyLimit()}.` : this.getErrorMessage(error);
3921
+ CadenzaService.log(
3922
+ "REST request failed before route completion.",
3923
+ {
3924
+ error: message,
3925
+ type: error.type,
3926
+ statusCode,
3927
+ path: _req?.path,
3928
+ method: _req?.method
3929
+ },
3930
+ statusCode >= 500 ? "error" : "warning"
3931
+ );
3932
+ res.status(statusCode).json({
3933
+ __status: "error",
3934
+ errored: true,
3935
+ __error: message
3936
+ });
3937
+ }
3938
+ );
3909
3939
  return true;
3910
3940
  },
3911
3941
  "Starts REST server and initiates meta-handling"
@@ -4444,6 +4474,42 @@ var RestController = class _RestController {
4444
4474
  return String(error);
4445
4475
  }
4446
4476
  }
4477
+ resolveJsonBodyLimit() {
4478
+ const configuredLimit = process.env.CADENZA_REST_BODY_LIMIT?.trim();
4479
+ return configuredLimit && configuredLimit.length > 0 ? configuredLimit : "10mb";
4480
+ }
4481
+ async parseFetchResponse(response) {
4482
+ const contentType = response.headers.get("content-type") ?? "";
4483
+ const rawText = await response.text();
4484
+ const headers = Object.fromEntries(response.headers.entries());
4485
+ if (rawText.length === 0) {
4486
+ return {
4487
+ ok: response.ok,
4488
+ status: response.status,
4489
+ statusText: response.statusText,
4490
+ headers,
4491
+ data: {}
4492
+ };
4493
+ }
4494
+ if (!contentType.toLowerCase().includes("application/json")) {
4495
+ throw new Error(
4496
+ `Expected JSON response from ${response.url ?? "remote service"} but received ${contentType || "unknown content type"} (HTTP ${response.status}). Body preview: ${rawText.slice(0, 200)}`
4497
+ );
4498
+ }
4499
+ try {
4500
+ return {
4501
+ ok: response.ok,
4502
+ status: response.status,
4503
+ statusText: response.statusText,
4504
+ headers,
4505
+ data: JSON.parse(rawText)
4506
+ };
4507
+ } catch (error) {
4508
+ throw new Error(
4509
+ `Failed to parse JSON response from ${response.url ?? "remote service"} (HTTP ${response.status}). Body preview: ${rawText.slice(0, 200)}. Parse error: ${this.getErrorMessage(error)}`
4510
+ );
4511
+ }
4512
+ }
4447
4513
  resolveDelegationTimeoutMs(ctx) {
4448
4514
  const syncing = ctx?.__syncing === true || ctx?.__metadata?.__syncing === true || Array.isArray(ctx?.joinedContexts) && ctx.joinedContexts.some(
4449
4515
  (joinedCtx) => joinedCtx?.__syncing === true || joinedCtx?.__metadata?.__syncing === true