@twin.org/node-core 0.9.2-next.5 → 0.9.2-next.7

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.
@@ -1,12 +1,14 @@
1
1
  // Copyright 2024 IOTA Stiftung.
2
2
  // SPDX-License-Identifier: Apache-2.0.
3
3
  import path from "node:path";
4
- import { Coerce, Is, Mutex } from "@twin.org/core";
5
- import { AttestationComponentType, AttestationConnectorType, AuditableItemGraphComponentType, AuditableItemStreamComponentType, AutomationComponentType, BackgroundTaskComponentType, BlobStorageComponentType, BlobStorageConnectorType, ContextIdHandlerComponentType, DataProcessingComponentType, DataspaceControlPlaneComponentType, DataspaceDataPlaneComponentType, DltConfigType, DocumentManagementComponentType, EngineTypeHelper, EntityStorageConnectorType, EventBusComponentType, EventBusConnectorType, FaucetConnectorType, FederatedCatalogueComponentType, HealthComponentType, IdentityComponentType, IdentityConnectorType, IdentityProfileComponentType, IdentityProfileConnectorType, IdentityResolverComponentType, IdentityResolverConnectorType, ImmutableProofComponentType, LoggingComponentType, LoggingConnectorType, MessagingAdminComponentType, MessagingComponentType, MessagingEmailConnectorType, MessagingPushNotificationConnectorType, MessagingSmsConnectorType, MetricsCollectorComponentType, MetricsProducerComponentType, NftComponentType, NftConnectorType, NotarizationComponentType, NotarizationConnectorType, PlatformComponentType, RightsManagementPapComponentType, RightsManagementPdpComponentType, RightsManagementPepComponentType, RightsManagementPipComponentType, RightsManagementPmpComponentType, RightsManagementPnapComponentType, RightsManagementPnpComponentType, RightsManagementPxpComponentType, SchemaVersionMigrationComponentType, TaskSchedulerComponentType, TelemetryComponentType, TelemetryConnectorType, TenantAdminComponentType, TrustComponentType, TrustVerifierComponentType, VaultConnectorType, WalletConnectorType } from "@twin.org/engine-types";
4
+ import { Is, Mutex } from "@twin.org/core";
5
+ import { AttestationComponentType, AttestationConnectorType, AuditableItemGraphComponentType, AuditableItemStreamComponentType, AutomationComponentType, BackgroundTaskComponentType, BlobStorageComponentType, BlobStorageConnectorType, ContextIdHandlerComponentType, DataProcessingComponentType, DataspaceControlPlaneComponentType, DataspaceDataPlaneComponentType, DltConfigType, DocumentManagementComponentType, EngineTypeHelper, EntityStorageConnectorType, EventBusComponentType, EventBusConnectorType, FaucetConnectorType, FederatedCatalogueComponentType, HealthComponentType, IdentityComponentType, IdentityConnectorType, IdentityProfileComponentType, IdentityProfileConnectorType, IdentityResolverComponentType, IdentityResolverConnectorType, ImmutableProofComponentType, LoggingComponentType, LoggingConnectorType, MessagingAdminComponentType, MessagingComponentType, MessagingEmailConnectorType, MessagingPushNotificationConnectorType, MessagingSmsConnectorType, MetricsCollectorComponentType, MetricsProducerComponentType, NftComponentType, NftConnectorType, NotarizationComponentType, NotarizationConnectorType, PlatformComponentType, RightsManagementPapComponentType, RightsManagementPdpComponentType, RightsManagementPepComponentType, RightsManagementPipComponentType, RightsManagementPmpComponentType, RightsManagementPnapComponentType, RightsManagementPnpComponentType, RightsManagementPxpComponentType, SchemaVersionMigrationComponentType, TaskSchedulerComponentType, TelemetryComponentType, TelemetryConnectorType, TenantAdminComponentType, TracingComponentType, TracingConnectorType, TrustComponentType, TrustVerifierComponentType, VaultConnectorType, WalletConnectorType } from "@twin.org/engine-types";
6
6
  import { OpenTelemetryExporterTypes } from "@twin.org/logging-connector-opentelemetry";
7
7
  import { OpenTelemetryReaderTypes } from "@twin.org/telemetry-connector-opentelemetry";
8
+ import { OpenTelemetryProcessorTypes } from "@twin.org/tracing-connector-opentelemetry";
8
9
  import { CONTEXT_ID_HANDLER_FEATURE_DID, CONTEXT_ID_HANDLER_FEATURE_TENANT } from "../defaults.js";
9
10
  import { isAuthEntityStorageRequired } from "./engineServerEnvBuilder.js";
11
+ import { commaSeparatedListToArray, envBoolean, envCount, envDateTime, envInteger, envMinToMs, envMinutes, envMs, envSecToMs, envSeconds } from "./helper/envHelpers.js";
10
12
  /**
11
13
  * Build the engine core configuration from environment variables.
12
14
  * @param envVars The environment variables.
@@ -19,12 +21,12 @@ export async function buildEngineConfiguration(envVars) {
19
21
  envVars.stateFilename = path.join(envVars.storageFileRoot, envVars.stateFilename);
20
22
  }
21
23
  const coreConfig = {
22
- debug: Coerce.boolean(envVars.debug) ?? false,
23
- silent: Coerce.boolean(envVars.silent) ?? false,
24
+ debug: envBoolean(envVars, "debug", false),
25
+ silent: envBoolean(envVars, "silent", false),
24
26
  silentLoggers: commaSeparatedListToArray(envVars.loggingSilentComponents),
25
27
  types: {}
26
28
  };
27
- const mutexTimeoutMs = Coerce.integer(envVars.mutexTimeoutMsDefault);
29
+ const mutexTimeoutMs = envMs(envVars, "mutexTimeoutMsDefault");
28
30
  if (!Is.empty(mutexTimeoutMs)) {
29
31
  Mutex.setDefaultTimeoutMs(mutexTimeoutMs);
30
32
  }
@@ -42,6 +44,7 @@ export async function buildEngineConfiguration(envVars) {
42
44
  await configureEventBus(coreConfig, envVars);
43
45
  await configureTelemetry(coreConfig, envVars);
44
46
  await configureMetricsCollector(coreConfig, envVars);
47
+ await configureTracing(coreConfig, envVars);
45
48
  await configureMessaging(coreConfig, envVars);
46
49
  await configureAutomation(coreConfig, envVars);
47
50
  await configureHealth(coreConfig, envVars);
@@ -79,7 +82,7 @@ async function configureEntityStorage(coreConfig, envVars) {
79
82
  type: EntityStorageConnectorType.Memory,
80
83
  options: {
81
84
  config: {
82
- mutexTimeoutMs: Coerce.integer(envVars.entityStorageMemoryMutexTimeout)
85
+ mutexTimeoutMs: envMs(envVars, "entityStorageMutexTimeout")
83
86
  }
84
87
  }
85
88
  });
@@ -90,7 +93,7 @@ async function configureEntityStorage(coreConfig, envVars) {
90
93
  options: {
91
94
  config: {
92
95
  directory: envVars.storageFileRoot ?? "",
93
- mutexTimeoutMs: Coerce.integer(envVars.entityStorageFileMutexTimeout)
96
+ mutexTimeoutMs: envMs(envVars, "entityStorageMutexTimeout")
94
97
  },
95
98
  folderPrefix: envVars.entityStorageTablePrefix
96
99
  }
@@ -106,7 +109,7 @@ async function configureEntityStorage(coreConfig, envVars) {
106
109
  accessKeyId: envVars.awsDynamodbAccessKeyId,
107
110
  secretAccessKey: envVars.awsDynamodbSecretAccessKey,
108
111
  endpoint: envVars.awsDynamodbEndpoint,
109
- connectionTimeoutMs: Coerce.integer(envVars.awsDynamodbConnectionTimeout)
112
+ connectionTimeoutMs: envMs(envVars, "awsDynamodbConnectionTimeout")
110
113
  },
111
114
  tablePrefix: envVars.entityStorageTablePrefix
112
115
  }
@@ -149,7 +152,7 @@ async function configureEntityStorage(coreConfig, envVars) {
149
152
  hosts: commaSeparatedListToArray(envVars.scylladbHosts),
150
153
  localDataCenter: envVars.scylladbLocalDataCenter ?? "",
151
154
  keyspace: envVars.scylladbKeyspace ?? "",
152
- port: Coerce.integer(envVars.scylladbPort)
155
+ port: envInteger(envVars, "scylladbPort")
153
156
  },
154
157
  tablePrefix: envVars.entityStorageTablePrefix
155
158
  }
@@ -161,7 +164,7 @@ async function configureEntityStorage(coreConfig, envVars) {
161
164
  options: {
162
165
  config: {
163
166
  host: envVars.mySqlHost ?? "",
164
- port: Coerce.integer(envVars.mySqlPort),
167
+ port: envInteger(envVars, "mySqlPort"),
165
168
  user: envVars.mySqlUser ?? "",
166
169
  password: envVars.mySqlPassword ?? "",
167
170
  database: envVars.mySqlDatabase ?? ""
@@ -176,7 +179,7 @@ async function configureEntityStorage(coreConfig, envVars) {
176
179
  options: {
177
180
  config: {
178
181
  host: envVars.mongoDbHost ?? "",
179
- port: Coerce.integer(envVars.mongoDbPort),
182
+ port: envInteger(envVars, "mongoDbPort"),
180
183
  user: envVars.mongoDbUser ?? "",
181
184
  password: envVars.mongoDbPassword ?? "",
182
185
  database: envVars.mongoDbDatabase ?? ""
@@ -191,7 +194,7 @@ async function configureEntityStorage(coreConfig, envVars) {
191
194
  options: {
192
195
  config: {
193
196
  host: envVars.postgreSqlHost ?? "",
194
- port: Coerce.integer(envVars.postgreSqlPort),
197
+ port: envInteger(envVars, "postgreSqlPort"),
195
198
  user: envVars.postgreSqlUser ?? "",
196
199
  password: envVars.postgreSqlPassword ?? "",
197
200
  database: envVars.postgreSqlDatabase ?? ""
@@ -342,19 +345,19 @@ async function configureLogging(coreConfig, envVars) {
342
345
  type: LoggingConnectorType.EntityStorage,
343
346
  options: {
344
347
  config: {
345
- batchSize: Coerce.integer(envVars.loggingBatchSize),
346
- batchIntervalMs: (Coerce.integer(envVars.loggingBatchFlushInterval) ?? 5) * 1000,
347
- retainForMs: (Coerce.integer(envVars.loggingRetainFor) ?? 2880) * 60_000,
348
- maxEntries: Coerce.integer(envVars.loggingMaxEntries),
349
- retentionIntervalMs: (Coerce.integer(envVars.loggingRetentionInterval) ?? 5) * 60_000,
350
- retentionBatchSize: Coerce.integer(envVars.loggingRetentionBatchSize),
351
- mutexTimeoutMs: Coerce.integer(envVars.loggingMutexTimeout)
348
+ batchSize: envCount(envVars, "loggingBatchSize"),
349
+ batchIntervalMs: envSecToMs(envVars, "loggingBatchFlushInterval"),
350
+ retainForMs: envMinToMs(envVars, "loggingRetainFor"),
351
+ maxEntries: envCount(envVars, "loggingMaxEntries"),
352
+ retentionIntervalMs: envMinToMs(envVars, "loggingRetentionInterval"),
353
+ retentionBatchSize: envCount(envVars, "loggingRetentionBatchSize"),
354
+ mutexTimeoutMs: envMs(envVars, "loggingMutexTimeout")
352
355
  }
353
356
  }
354
357
  });
355
358
  additionalConnectorCount++;
356
359
  }
357
- else if (loggingConnector === LoggingConnectorType.Otel) {
360
+ else if (loggingConnector === LoggingConnectorType.OpenTelemetry) {
358
361
  const otelLoggingConfig = {
359
362
  loggerName: envVars.openTelemetryLoggingLoggerName,
360
363
  loggerVersion: envVars.openTelemetryLoggingLoggerVersion
@@ -370,7 +373,7 @@ async function configureLogging(coreConfig, envVars) {
370
373
  };
371
374
  }
372
375
  coreConfig.types.loggingConnector.push({
373
- type: LoggingConnectorType.Otel,
376
+ type: LoggingConnectorType.OpenTelemetry,
374
377
  options: {
375
378
  config: otelLoggingConfig
376
379
  }
@@ -384,9 +387,9 @@ async function configureLogging(coreConfig, envVars) {
384
387
  config: {
385
388
  directory: envVars.loggingFileDirectory ?? envVars.storageFileRoot ?? "",
386
389
  filename: envVars.loggingFileFilename,
387
- maxFileSizeBytes: Coerce.integer(envVars.loggingFileMaxFileSizeBytes),
388
- maxRetainedFiles: Coerce.integer(envVars.loggingFileMaxRetainedFiles),
389
- mutexTimeoutMs: Coerce.integer(envVars.loggingMutexTimeout)
390
+ maxFileSizeBytes: envCount(envVars, "loggingFileMaxFileSizeBytes"),
391
+ maxRetainedFiles: envCount(envVars, "loggingFileMaxRetainedFiles"),
392
+ mutexTimeoutMs: envMs(envVars, "loggingMutexTimeout")
390
393
  }
391
394
  }
392
395
  });
@@ -492,18 +495,18 @@ async function configureTelemetry(coreConfig, envVars) {
492
495
  type: TelemetryConnectorType.EntityStorage,
493
496
  options: {
494
497
  config: {
495
- mutexTimeoutMs: Coerce.integer(envVars.telemetryMutexTimeout)
498
+ mutexTimeoutMs: envMs(envVars, "telemetryMutexTimeout")
496
499
  }
497
500
  }
498
501
  });
499
502
  }
500
503
  else if (envVars.telemetryConnector === TelemetryConnectorType.OpenTelemetry) {
501
504
  let readers;
502
- if (envVars.openTelemetryReader === "prometheus") {
505
+ if (envVars.openTelemetryReader === OpenTelemetryReaderTypes.Prometheus) {
503
506
  readers = {
504
507
  prometheus: {
505
508
  type: OpenTelemetryReaderTypes.Prometheus,
506
- port: Coerce.integer(envVars.openTelemetryPrometheusPort)
509
+ port: envCount(envVars, "openTelemetryPrometheusPort")
507
510
  }
508
511
  };
509
512
  }
@@ -511,7 +514,7 @@ async function configureTelemetry(coreConfig, envVars) {
511
514
  type: TelemetryConnectorType.OpenTelemetry,
512
515
  options: {
513
516
  config: {
514
- mutexTimeoutMs: Coerce.integer(envVars.telemetryMutexTimeout),
517
+ mutexTimeoutMs: envMs(envVars, "telemetryMutexTimeout"),
515
518
  meterName: envVars.openTelemetryMeterName,
516
519
  meterVersion: envVars.openTelemetryMeterVersion,
517
520
  readers
@@ -532,26 +535,72 @@ async function configureTelemetry(coreConfig, envVars) {
532
535
  */
533
536
  async function configureMetricsCollector(coreConfig, envVars) {
534
537
  if (isTelemetryRequired(envVars)) {
535
- const intervalSec = Coerce.integer(envVars.telemetryMetricsCollectorInterval) ?? 60;
536
538
  coreConfig.types.metricsCollectorComponent ??= [];
537
539
  coreConfig.types.metricsCollectorComponent.push({
538
540
  type: MetricsCollectorComponentType.Service,
539
- options: { config: { intervalMs: intervalSec * 1000 } },
541
+ options: {
542
+ config: {
543
+ intervalMs: envSecToMs(envVars, "telemetryMetricsCollectorInterval")
544
+ }
545
+ },
540
546
  isCloneable: false
541
547
  });
542
- const maxHistory = Coerce.integer(envVars.telemetryMetricsProducerMaxHistory) ?? 1440;
543
548
  coreConfig.types.metricsProducerComponent ??= [];
544
549
  const metricsProducers = commaSeparatedListToArray(envVars.telemetryMetricsProducers ??
545
550
  [MetricsProducerComponentType.System, MetricsProducerComponentType.Process].join(","));
546
551
  for (const producerType of metricsProducers) {
547
552
  coreConfig.types.metricsProducerComponent.push({
548
553
  type: producerType,
549
- options: { maxHistory },
554
+ options: { maxHistory: envCount(envVars, "telemetryMetricsProducerMaxHistory") },
550
555
  isCloneable: false
551
556
  });
552
557
  }
553
558
  }
554
559
  }
560
+ /**
561
+ * Configures the tracing.
562
+ * @param coreConfig The core config.
563
+ * @param envVars The environment variables.
564
+ * @returns A promise that resolves when the tracing configuration has been applied.
565
+ */
566
+ async function configureTracing(coreConfig, envVars) {
567
+ coreConfig.types.tracingConnector ??= [];
568
+ if (envVars.tracingConnector === TracingConnectorType.EntityStorage) {
569
+ coreConfig.types.tracingConnector.push({
570
+ type: TracingConnectorType.EntityStorage,
571
+ options: {
572
+ config: {
573
+ mutexTimeoutMs: envMs(envVars, "tracingMutexTimeout")
574
+ }
575
+ }
576
+ });
577
+ }
578
+ else if (envVars.tracingConnector === TracingConnectorType.OpenTelemetry) {
579
+ const otelTracingConfig = {
580
+ tracerName: envVars.openTelemetryTracingTracerName,
581
+ tracerVersion: envVars.openTelemetryTracingTracerVersion
582
+ };
583
+ if (Is.stringValue(envVars.openTelemetryTracingEndpoint)) {
584
+ otelTracingConfig.exporters = {
585
+ otlp: {
586
+ endpoint: envVars.openTelemetryTracingEndpoint,
587
+ processor: envVars.openTelemetryTracingProcessor ??
588
+ OpenTelemetryProcessorTypes.Batch
589
+ }
590
+ };
591
+ }
592
+ coreConfig.types.tracingConnector.push({
593
+ type: TracingConnectorType.OpenTelemetry,
594
+ options: {
595
+ config: otelTracingConfig
596
+ }
597
+ });
598
+ }
599
+ if (coreConfig.types.tracingConnector.length > 0) {
600
+ coreConfig.types.tracingComponent ??= [];
601
+ coreConfig.types.tracingComponent.push({ type: TracingComponentType.Service });
602
+ }
603
+ }
555
604
  /**
556
605
  * Configures the automation.
557
606
  * @param coreConfig The core config.
@@ -584,13 +633,14 @@ async function configureAutomation(coreConfig, envVars) {
584
633
  */
585
634
  async function configureHealth(coreConfig, envVars) {
586
635
  coreConfig.types.healthComponent ??= [];
587
- if (Coerce.boolean(envVars.healthEnabled) ?? false) {
636
+ if (envBoolean(envVars, "healthEnabled", false)) {
588
637
  coreConfig.types.healthComponent.push({
589
638
  type: HealthComponentType.Service,
590
639
  options: {
591
640
  config: {
592
- healthCheckInterval: (Coerce.integer(envVars.healthInterval) ?? 60) * 1000,
593
- initialInterval: (Coerce.integer(envVars.healthStartupInterval) ?? 2) * 1000
641
+ healthCheckInterval: envSecToMs(envVars, "healthInterval"),
642
+ healthCheckApplicationInterval: envSecToMs(envVars, "healthApplicationInterval"),
643
+ initialInterval: envSecToMs(envVars, "healthStartupInterval")
594
644
  }
595
645
  },
596
646
  isCloneable: false
@@ -604,7 +654,7 @@ async function configureHealth(coreConfig, envVars) {
604
654
  * @returns A promise that resolves when the schema migration configuration has been applied.
605
655
  */
606
656
  async function configureSchemaMigration(coreConfig, envVars) {
607
- const isSchemaMigrationEnabled = Coerce.boolean(envVars.schemaMigrationEnabled) ?? true;
657
+ const isSchemaMigrationEnabled = envBoolean(envVars, "schemaMigrationEnabled", true);
608
658
  if (isSchemaMigrationEnabled) {
609
659
  coreConfig.types.schemaVersionMigrationComponent ??= [];
610
660
  coreConfig.types.schemaVersionMigrationComponent.push({
@@ -620,7 +670,7 @@ async function configureSchemaMigration(coreConfig, envVars) {
620
670
  * @returns A promise that resolves when the platform configuration has been applied.
621
671
  */
622
672
  async function configurePlatform(coreConfig, envVars) {
623
- const isTenantEnabled = Coerce.boolean(envVars.tenantEnabled) ?? false;
673
+ const isTenantEnabled = envBoolean(envVars, "tenantEnabled", false);
624
674
  coreConfig.types.platformComponent ??= [];
625
675
  coreConfig.types.platformComponent.push({
626
676
  type: PlatformComponentType.Service,
@@ -638,7 +688,7 @@ async function configurePlatform(coreConfig, envVars) {
638
688
  * @returns A promise that resolves when the tenant configuration has been applied.
639
689
  */
640
690
  async function configureTenant(coreConfig, envVars) {
641
- const isTenantEnabled = Coerce.boolean(envVars.tenantEnabled) ?? false;
691
+ const isTenantEnabled = envBoolean(envVars, "tenantEnabled", false);
642
692
  if (isTenantEnabled) {
643
693
  coreConfig.types.tenantAdminComponent ??= [];
644
694
  coreConfig.types.tenantAdminComponent.push({
@@ -658,7 +708,7 @@ async function configureContextIdHandlers(coreConfig, envVars) {
658
708
  type: ContextIdHandlerComponentType.Did,
659
709
  features: [CONTEXT_ID_HANDLER_FEATURE_DID]
660
710
  });
661
- if (Coerce.boolean(envVars.tenantEnabled) ?? false) {
711
+ if (envBoolean(envVars, "tenantEnabled", false)) {
662
712
  coreConfig.types.contextIdHandlerComponent.push({
663
713
  type: ContextIdHandlerComponentType.Tenant,
664
714
  features: [CONTEXT_ID_HANDLER_FEATURE_TENANT]
@@ -672,7 +722,7 @@ async function configureContextIdHandlers(coreConfig, envVars) {
672
722
  * @returns A promise that resolves when the messaging configuration has been applied.
673
723
  */
674
724
  async function configureMessaging(coreConfig, envVars) {
675
- if (Coerce.boolean(envVars.messagingEnabled) ?? false) {
725
+ if (envBoolean(envVars, "messagingEnabled", false)) {
676
726
  coreConfig.types.messagingEmailConnector ??= [];
677
727
  coreConfig.types.messagingSmsConnector ??= [];
678
728
  coreConfig.types.messagingPushNotificationConnector ??= [];
@@ -766,13 +816,14 @@ async function configureFaucet(coreConfig, envVars) {
766
816
  type: FaucetConnectorType.EntityStorage
767
817
  });
768
818
  }
769
- else if (envVars.faucetConnector === FaucetConnectorType.Iota) {
819
+ else if (envVars.faucetConnector === FaucetConnectorType.Iota &&
820
+ Is.stringValue(envVars.iotaFaucetEndpoint)) {
770
821
  const dltConfig = EngineTypeHelper.getConfigOfType(coreConfig, "dltConfig", DltConfigType.Iota);
771
822
  coreConfig.types.faucetConnector.push({
772
823
  type: FaucetConnectorType.Iota,
773
824
  options: {
774
825
  config: {
775
- endpoint: envVars.iotaFaucetEndpoint ?? "",
826
+ endpoint: envVars.iotaFaucetEndpoint,
776
827
  clientOptions: dltConfig?.options?.config?.clientOptions ?? { url: "" },
777
828
  network: dltConfig?.options?.config?.network ?? ""
778
829
  }
@@ -875,9 +926,15 @@ async function configureImmutableProof(coreConfig, envVars) {
875
926
  options: {
876
927
  config: {
877
928
  verificationMethodId: envVars.immutableProofVerificationMethodId,
878
- taskRetryCount: Coerce.integer(envVars.immutableProofTaskRetryCount),
879
- taskRetryInterval: (Coerce.integer(envVars.immutableProofTaskRetryInterval) ?? 5) * 1000,
880
- taskFailureRetainFor: (Coerce.integer(envVars.immutableProofTaskFailureRetainFor) ?? 10080) * 60_000
929
+ taskRetryCount: envCount(envVars, "immutableProofTaskRetryCount"),
930
+ taskRetryInterval: envSecToMs(envVars, "immutableProofTaskRetryInterval"),
931
+ taskFailureRetainFor: envMinToMs(envVars, "immutableProofTaskFailureRetainFor"),
932
+ sweepIntervalMinutes: envMinutes(envVars, "immutableProofSweepInterval"),
933
+ sweepStaleThresholdMs: envMinToMs(envVars, "immutableProofSweepStaleThreshold"),
934
+ sweepMaxAttempts: envCount(envVars, "immutableProofSweepMaxAttempts"),
935
+ sweepBatchLimit: envCount(envVars, "immutableProofSweepBatchLimit"),
936
+ sweepBackoffMs: envMinToMs(envVars, "immutableProofSweepBackoff"),
937
+ sweepAssumeRetryableBefore: envDateTime(envVars, "immutableProofSweepAssumeRetryableBefore")
881
938
  }
882
939
  }
883
940
  });
@@ -906,8 +963,8 @@ async function configureIdentity(coreConfig, envVars) {
906
963
  identityPkgId: Is.stringValue(envVars.iotaIdentityPackageId)
907
964
  ? envVars.iotaIdentityPackageId
908
965
  : undefined,
909
- walletAddressIndex: Coerce.integer(envVars.identityWalletAddressIndex) ?? 0,
910
- didResolutionCacheTtlMs: Coerce.integer(envVars.identityDidResolutionCacheTtlMs)
966
+ walletAddressIndex: envCount(envVars, "identityWalletAddressIndex") ?? 0,
967
+ didResolutionCacheTtlMs: envMs(envVars, "identityDidResolutionCacheTtlMs")
911
968
  }
912
969
  }
913
970
  });
@@ -1011,13 +1068,13 @@ async function configureAttestation(coreConfig, envVars) {
1011
1068
  * @returns A promise that resolves when the auditable item graph configuration has been applied.
1012
1069
  */
1013
1070
  async function configureAuditableItemGraph(coreConfig, envVars) {
1014
- if (Coerce.boolean(envVars.auditableItemGraphEnabled) ?? false) {
1071
+ if (envBoolean(envVars, "auditableItemGraphEnabled", false)) {
1015
1072
  coreConfig.types.auditableItemGraphComponent ??= [];
1016
1073
  coreConfig.types.auditableItemGraphComponent.push({
1017
1074
  type: AuditableItemGraphComponentType.Service,
1018
1075
  options: {
1019
1076
  config: {
1020
- mutexTimeoutMs: Coerce.integer(envVars.auditableItemGraphMutexTimeout)
1077
+ mutexTimeoutMs: envMs(envVars, "auditableItemGraphMutexTimeout")
1021
1078
  }
1022
1079
  }
1023
1080
  });
@@ -1030,13 +1087,13 @@ async function configureAuditableItemGraph(coreConfig, envVars) {
1030
1087
  * @returns A promise that resolves when the auditable item stream configuration has been applied.
1031
1088
  */
1032
1089
  async function configureAuditableItemStream(coreConfig, envVars) {
1033
- if (Coerce.boolean(envVars.auditableItemStreamEnabled) ?? false) {
1090
+ if (envBoolean(envVars, "auditableItemStreamEnabled", false)) {
1034
1091
  coreConfig.types.auditableItemStreamComponent ??= [];
1035
1092
  coreConfig.types.auditableItemStreamComponent.push({
1036
1093
  type: AuditableItemStreamComponentType.Service,
1037
1094
  options: {
1038
1095
  config: {
1039
- mutexTimeoutMs: Coerce.integer(envVars.auditableItemStreamMutexTimeout)
1096
+ mutexTimeoutMs: envMs(envVars, "auditableItemStreamMutexTimeout")
1040
1097
  }
1041
1098
  }
1042
1099
  });
@@ -1049,7 +1106,7 @@ async function configureAuditableItemStream(coreConfig, envVars) {
1049
1106
  * @returns A promise that resolves when the data processing configuration has been applied.
1050
1107
  */
1051
1108
  async function configureDataProcessing(coreConfig, envVars) {
1052
- if (Coerce.boolean(envVars.dataProcessingEnabled) ?? false) {
1109
+ if (envBoolean(envVars, "dataProcessingEnabled", false)) {
1053
1110
  coreConfig.types.dataProcessingComponent ??= [];
1054
1111
  coreConfig.types.dataProcessingComponent.push({ type: DataProcessingComponentType.Service });
1055
1112
  coreConfig.types.dataConverterConnector ??= [];
@@ -1075,13 +1132,13 @@ async function configureDataProcessing(coreConfig, envVars) {
1075
1132
  * @returns A promise that resolves when the document management configuration has been applied.
1076
1133
  */
1077
1134
  async function configureDocumentManagement(coreConfig, envVars) {
1078
- if (Coerce.boolean(envVars.documentManagementEnabled) ?? false) {
1135
+ if (envBoolean(envVars, "documentManagementEnabled", false)) {
1079
1136
  coreConfig.types.documentManagementComponent ??= [];
1080
1137
  coreConfig.types.documentManagementComponent.push({
1081
1138
  type: DocumentManagementComponentType.Service,
1082
1139
  options: {
1083
1140
  config: {
1084
- mutexTimeoutMs: Coerce.integer(envVars.documentManagementMutexTimeout)
1141
+ mutexTimeoutMs: envMs(envVars, "documentManagementMutexTimeout")
1085
1142
  }
1086
1143
  }
1087
1144
  });
@@ -1107,7 +1164,7 @@ async function configureTrust(coreConfig, envVars) {
1107
1164
  options: {
1108
1165
  config: {
1109
1166
  verificationMethodId: envVars.trustVerificationMethodId ?? "",
1110
- tokenTtlInSeconds: Coerce.integer(envVars.trustJwtTtl)
1167
+ tokenTtlInSeconds: envCount(envVars, "trustJwtTtl")
1111
1168
  }
1112
1169
  }
1113
1170
  });
@@ -1192,7 +1249,7 @@ async function configureRightsManagement(coreConfig, envVars) {
1192
1249
  config: {
1193
1250
  callbackPath: rightsManagementPath,
1194
1251
  includeErrorDetails: coreConfig.debug ?? false,
1195
- mutexTimeoutMs: Coerce.integer(envVars.rightsManagementMutexTimeout)
1252
+ mutexTimeoutMs: envMs(envVars, "rightsManagementMutexTimeout")
1196
1253
  }
1197
1254
  },
1198
1255
  isDefault: true
@@ -1202,7 +1259,7 @@ async function configureRightsManagement(coreConfig, envVars) {
1202
1259
  type: RightsManagementPnapComponentType.Service,
1203
1260
  options: {
1204
1261
  config: {
1205
- mutexTimeoutMs: Coerce.integer(envVars.rightsManagementMutexTimeout)
1262
+ mutexTimeoutMs: envMs(envVars, "rightsManagementMutexTimeout")
1206
1263
  }
1207
1264
  }
1208
1265
  });
@@ -1294,7 +1351,7 @@ async function configureFederatedCatalogue(coreConfig, envVars) {
1294
1351
  type: FederatedCatalogueComponentType.Service,
1295
1352
  options: {
1296
1353
  config: {
1297
- mutexTimeoutMs: Coerce.integer(envVars.federatedCatalogueMutexTimeout)
1354
+ mutexTimeoutMs: envMs(envVars, "federatedCatalogueMutexTimeout")
1298
1355
  }
1299
1356
  }
1300
1357
  });
@@ -1316,7 +1373,7 @@ async function configureFederatedCatalogue(coreConfig, envVars) {
1316
1373
  * @returns A promise that resolves when the dataspace configuration has been applied.
1317
1374
  */
1318
1375
  async function configureDataspace(coreConfig, envVars) {
1319
- if (Coerce.boolean(envVars.dataspaceEnabled) ?? false) {
1376
+ if (envBoolean(envVars, "dataspaceEnabled", false)) {
1320
1377
  coreConfig.types.dataspaceControlPlaneComponent ??= [];
1321
1378
  // We add a multi instance REST client for remote/consumer-initiated transfers.
1322
1379
  coreConfig.types.dataspaceControlPlaneComponent.push({
@@ -1327,8 +1384,6 @@ async function configureDataspace(coreConfig, envVars) {
1327
1384
  isMultiInstance: true,
1328
1385
  features: ["remote"]
1329
1386
  });
1330
- const stalledNegotiationTimeout = Coerce.integer(envVars.dataspaceStalledNegotiationTimeout);
1331
- const stalledTransferTimeout = Coerce.integer(envVars.dataspaceStalledTransferTimeout);
1332
1387
  coreConfig.types.dataspaceControlPlaneComponent.push({
1333
1388
  type: DataspaceControlPlaneComponentType.Service,
1334
1389
  options: {
@@ -1339,30 +1394,22 @@ async function configureDataspace(coreConfig, envVars) {
1339
1394
  // Base mount path of the data plane only; the transfer handlers append the
1340
1395
  // sub-paths themselves (`/entities` for PULL, `/inbox` for PUSH).
1341
1396
  dataPlanePath: envVars.dataspaceDataPlanePath,
1342
- autoStartTransfers: Coerce.boolean(envVars.dataspaceAutoStartTransfers),
1343
- stalledNegotiationTimeoutMs: !Is.empty(stalledNegotiationTimeout)
1344
- ? stalledNegotiationTimeout * 1000
1345
- : undefined,
1346
- stalledTransferTimeoutMs: !Is.empty(stalledTransferTimeout)
1347
- ? stalledTransferTimeout * 1000
1348
- : undefined
1397
+ autoStartTransfers: envBoolean(envVars, "dataspaceAutoStartTransfers", false),
1398
+ stalledNegotiationTimeoutMs: envSecToMs(envVars, "dataspaceStalledNegotiationTimeout"),
1399
+ stalledTransferTimeoutMs: envSecToMs(envVars, "dataspaceStalledTransferTimeout"),
1400
+ providerTransferIdleTimeoutMs: envSecToMs(envVars, "dataspaceProviderTransferIdleTimeout"),
1401
+ providerTransferPolicySweepIntervalMs: envSecToMs(envVars, "dataspaceProviderTransferPolicySweepInterval")
1349
1402
  }
1350
1403
  },
1351
1404
  isDefault: true
1352
1405
  });
1353
- const retainActivityLogsFor = Coerce.integer(envVars.dataspaceRetainActivityLogsFor);
1354
- const activityLogsCleanUpInterval = Coerce.integer(envVars.dataspaceActivityLogsCleanupInterval);
1355
1406
  coreConfig.types.dataspaceDataPlaneComponent ??= [];
1356
1407
  coreConfig.types.dataspaceDataPlaneComponent.push({
1357
1408
  type: DataspaceDataPlaneComponentType.Service,
1358
1409
  options: {
1359
1410
  config: {
1360
- retainActivityLogsForMs: !Is.empty(retainActivityLogsFor)
1361
- ? retainActivityLogsFor * 1000
1362
- : undefined,
1363
- activityLogsCleanUpIntervalMs: !Is.empty(activityLogsCleanUpInterval)
1364
- ? activityLogsCleanUpInterval * 1000
1365
- : undefined
1411
+ retainActivityLogsForMs: envSecToMs(envVars, "dataspaceRetainActivityLogsFor"),
1412
+ activityLogsCleanUpIntervalMs: envSecToMs(envVars, "dataspaceActivityLogsCleanupInterval")
1366
1413
  }
1367
1414
  }
1368
1415
  });
@@ -1394,26 +1441,15 @@ async function configureDlt(coreConfig, envVars) {
1394
1441
  url: envVars.iotaNodeEndpoint ?? ""
1395
1442
  },
1396
1443
  network: envVars.iotaNetwork ?? "",
1397
- coinType: Coerce.integer(envVars.iotaCoinType),
1444
+ coinType: envCount(envVars, "iotaCoinType"),
1398
1445
  gasStation: gasStationConfig,
1399
- gasBudget: Coerce.integer(envVars.iotaGasBudget),
1400
- gasReservationDuration: Coerce.integer(envVars.iotaGasReservationDuration)
1446
+ gasBudget: envCount(envVars, "iotaGasBudget"),
1447
+ gasReservationDuration: envSeconds(envVars, "iotaGasReservationDuration")
1401
1448
  }
1402
1449
  }
1403
1450
  });
1404
1451
  }
1405
1452
  }
1406
- /**
1407
- * Converts a comma separated list to an array.
1408
- * @param value The comma separated list.
1409
- * @returns The array.
1410
- */
1411
- function commaSeparatedListToArray(value) {
1412
- return (value ?? "")
1413
- .split(",")
1414
- .map(item => item.trim())
1415
- .filter(item => item.length > 0);
1416
- }
1417
1453
  /**
1418
1454
  * Checks if the trust subsystem is required.
1419
1455
  * Returns true when any component that depends on the trust subsystem is enabled.
@@ -1422,7 +1458,7 @@ function commaSeparatedListToArray(value) {
1422
1458
  */
1423
1459
  export function isTrustRequired(envVars) {
1424
1460
  return (isRightsManagementRequired(envVars) ||
1425
- (Coerce.boolean(envVars.dataspaceEnabled) ?? false) ||
1461
+ envBoolean(envVars, "dataspaceEnabled", false) ||
1426
1462
  isFederatedCatalogueRequired(envVars));
1427
1463
  }
1428
1464
  /**
@@ -1432,7 +1468,7 @@ export function isTrustRequired(envVars) {
1432
1468
  * @returns True if dataspace or verifiable storage is enabled.
1433
1469
  */
1434
1470
  export function isBackgroundTasksRequired(envVars) {
1435
- return (Coerce.boolean(envVars.dataspaceEnabled) ?? false) || isImmutableProofRequired(envVars);
1471
+ return envBoolean(envVars, "dataspaceEnabled", false) || isImmutableProofRequired(envVars);
1436
1472
  }
1437
1473
  /**
1438
1474
  * Checks if the immutable proof subsystem is required.
@@ -1441,9 +1477,9 @@ export function isBackgroundTasksRequired(envVars) {
1441
1477
  * @returns True if verifiable storage is enabled.
1442
1478
  */
1443
1479
  export function isImmutableProofRequired(envVars) {
1444
- return ((Coerce.boolean(envVars.auditableItemGraphEnabled) ?? false) ||
1445
- (Coerce.boolean(envVars.auditableItemStreamEnabled) ?? false) ||
1446
- (Coerce.boolean(envVars.documentManagementEnabled) ?? false));
1480
+ return (envBoolean(envVars, "auditableItemGraphEnabled", false) ||
1481
+ envBoolean(envVars, "auditableItemStreamEnabled", false) ||
1482
+ envBoolean(envVars, "documentManagementEnabled", false));
1447
1483
  }
1448
1484
  /**
1449
1485
  * Checks if the federated catalogue subsystem is required.
@@ -1452,10 +1488,10 @@ export function isImmutableProofRequired(envVars) {
1452
1488
  * @returns True if the federated catalogue is required.
1453
1489
  */
1454
1490
  export function isFederatedCatalogueRequired(envVars) {
1455
- return ((Coerce.boolean(envVars.federatedCatalogueEnabled) ?? false) ||
1491
+ return (envBoolean(envVars, "federatedCatalogueEnabled", false) ||
1456
1492
  Is.stringValue(envVars.federatedCatalogueRemoteEndpoint) ||
1457
1493
  Is.stringValue(envVars.federatedCatalogueFilters) ||
1458
- (Coerce.boolean(envVars.dataspaceEnabled) ?? false));
1494
+ envBoolean(envVars, "dataspaceEnabled", false));
1459
1495
  }
1460
1496
  /**
1461
1497
  * Checks if the rights management subsystem is required.
@@ -1467,7 +1503,7 @@ export function isFederatedCatalogueRequired(envVars) {
1467
1503
  * @returns True if rights management is enabled.
1468
1504
  */
1469
1505
  export function isRightsManagementRequired(envVars) {
1470
- return Coerce.boolean(envVars.dataspaceEnabled) ?? false;
1506
+ return envBoolean(envVars, "dataspaceEnabled", false);
1471
1507
  }
1472
1508
  /**
1473
1509
  * Checks if the task scheduler subsystem is required.
@@ -1476,10 +1512,11 @@ export function isRightsManagementRequired(envVars) {
1476
1512
  * @returns True if task scheduler is enabled.
1477
1513
  */
1478
1514
  export function isTaskSchedulerRequired(envVars) {
1479
- return ((Coerce.boolean(envVars.taskSchedulerEnabled) ?? false) ||
1480
- (Coerce.boolean(envVars.dataspaceEnabled) ?? false) ||
1515
+ return (envBoolean(envVars, "taskSchedulerEnabled", false) ||
1516
+ envBoolean(envVars, "dataspaceEnabled", false) ||
1481
1517
  isRightsManagementRequired(envVars) ||
1482
- isAuthEntityStorageRequired(envVars));
1518
+ isAuthEntityStorageRequired(envVars) ||
1519
+ isImmutableProofRequired(envVars));
1483
1520
  }
1484
1521
  /**
1485
1522
  * Checks if the automation subsystem is required.