@twin.org/node-core 0.0.1-next.9 → 0.0.1

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.
Files changed (37) hide show
  1. package/dist/cjs/index.cjs +1140 -53
  2. package/dist/esm/index.mjs +1141 -57
  3. package/dist/types/bootstrap.d.ts +9 -10
  4. package/dist/types/builders/engineEnvBuilder.d.ts +8 -0
  5. package/dist/types/builders/engineServerEnvBuilder.d.ts +13 -0
  6. package/dist/types/index.d.ts +5 -3
  7. package/dist/types/models/IEngineEnvironmentVariables.d.ts +389 -0
  8. package/dist/types/models/IEngineServerEnvironmentVariables.d.ts +49 -0
  9. package/dist/types/models/{INodeVariables.d.ts → INodeEnvironmentVariables.d.ts} +3 -3
  10. package/dist/types/models/{IRunOptions.d.ts → INodeOptions.d.ts} +17 -1
  11. package/dist/types/node.d.ts +22 -3
  12. package/dist/types/server.d.ts +7 -14
  13. package/dist/types/utils.d.ts +8 -2
  14. package/docs/changelog.md +42 -0
  15. package/docs/reference/functions/bootstrap.md +2 -2
  16. package/docs/reference/functions/bootstrapAttestationMethod.md +2 -2
  17. package/docs/reference/functions/bootstrapAuth.md +2 -2
  18. package/docs/reference/functions/bootstrapBlobEncryption.md +2 -2
  19. package/docs/reference/functions/bootstrapImmutableProofMethod.md +2 -2
  20. package/docs/reference/functions/bootstrapNodeIdentity.md +2 -2
  21. package/docs/reference/functions/bootstrapNodeUser.md +2 -2
  22. package/docs/reference/functions/buildConfiguration.md +30 -0
  23. package/docs/reference/functions/buildEngineConfiguration.md +19 -0
  24. package/docs/reference/functions/getFeatures.md +1 -1
  25. package/docs/reference/functions/loadJsonFile.md +25 -0
  26. package/docs/reference/functions/run.md +3 -3
  27. package/docs/reference/functions/start.md +9 -39
  28. package/docs/reference/index.md +7 -3
  29. package/docs/reference/interfaces/IEngineEnvironmentVariables.md +775 -0
  30. package/docs/reference/interfaces/IEngineServerEnvironmentVariables.md +95 -0
  31. package/docs/reference/interfaces/INodeEnvironmentVariables.md +1343 -0
  32. package/docs/reference/interfaces/{IRunOptions.md → INodeOptions.md} +38 -1
  33. package/locales/en.json +0 -1
  34. package/package.json +15 -15
  35. package/dist/types/models/INodeState.d.ts +0 -10
  36. package/docs/reference/interfaces/INodeState.md +0 -15
  37. package/docs/reference/interfaces/INodeVariables.md +0 -59
@@ -11,10 +11,11 @@ var walletModels = require('@twin.org/wallet-models');
11
11
  var promises = require('node:fs/promises');
12
12
  var path = require('node:path');
13
13
  var dotenv = require('dotenv');
14
+ var engineServer = require('@twin.org/engine-server');
15
+ var engineServerTypes = require('@twin.org/engine-server-types');
14
16
  var engine = require('@twin.org/engine');
15
17
  var engineCore = require('@twin.org/engine-core');
16
18
  var engineModels = require('@twin.org/engine-models');
17
- var engineServer = require('@twin.org/engine-server');
18
19
 
19
20
  function _interopNamespaceDefault(e) {
20
21
  var n = Object.create(null);
@@ -91,6 +92,15 @@ async function fileExists(filename) {
91
92
  return false;
92
93
  }
93
94
  }
95
+ /**
96
+ * Load the JSON file.
97
+ * @param filename The filename of the JSON file to load.
98
+ * @returns The contents of the JSON file or null if it could not be loaded.
99
+ */
100
+ async function loadJsonFile(filename) {
101
+ const content = await promises.readFile(filename, "utf8");
102
+ return JSON.parse(content);
103
+ }
94
104
  /**
95
105
  * Get the features that are enabled on the node.
96
106
  * @param env The environment variables for the node.
@@ -155,7 +165,6 @@ async function bootstrapNodeIdentity(engineCore, context, envVars, features) {
155
165
  await finaliseWallet(engineCore, envVars, features, finalIdentity, addresses);
156
166
  await finaliseMnemonic(vaultConnector, workingIdentity, finalIdentity);
157
167
  context.state.nodeIdentity = finalIdentity;
158
- context.state.addresses = addresses;
159
168
  context.stateDirty = true;
160
169
  engineCore.logInfo(core.I18n.formatMessage("node.nodeIdentity", {
161
170
  identity: context.state.nodeIdentity
@@ -508,51 +517,1061 @@ async function bootstrapAuth(engineCore, context, envVars, features) {
508
517
  }
509
518
  }
510
519
 
520
+ // Copyright 2024 IOTA Stiftung.
521
+ // SPDX-License-Identifier: Apache-2.0.
511
522
  /**
512
- * Start the engine server.
523
+ * Build the engine core configuration from environment variables.
524
+ * @param envVars The environment variables.
525
+ * @returns The config for the core.
526
+ */
527
+ function buildEngineConfiguration(envVars) {
528
+ if (core.Is.stringValue(envVars.storageFileRoot)) {
529
+ envVars.stateFilename ??= "engine-state.json";
530
+ envVars.storageFileRoot = path.resolve(envVars.storageFileRoot);
531
+ envVars.stateFilename = path.join(envVars.storageFileRoot, envVars.stateFilename);
532
+ }
533
+ envVars.attestationVerificationMethodId ??= "attestation-assertion";
534
+ envVars.immutableProofVerificationMethodId ??= "immutable-proof-assertion";
535
+ envVars.blobStorageEnableEncryption ??= "false";
536
+ envVars.blobStorageEncryptionKey ??= "blob-encryption";
537
+ const coreConfig = {
538
+ debug: core.Coerce.boolean(envVars.debug) ?? false,
539
+ types: {}
540
+ };
541
+ configureEntityStorage(coreConfig, envVars);
542
+ configureBlobStorage(coreConfig, envVars);
543
+ configureVault(coreConfig, envVars);
544
+ configureDlt(coreConfig, envVars);
545
+ configureLogging(coreConfig, envVars);
546
+ configureBackgroundTask(coreConfig, envVars);
547
+ configureEventBus(coreConfig, envVars);
548
+ configureTelemetry(coreConfig, envVars);
549
+ configureMessaging(coreConfig, envVars);
550
+ configureFaucet(coreConfig, envVars);
551
+ configureWallet(coreConfig, envVars);
552
+ configureNft(coreConfig, envVars);
553
+ configureVerifiableStorage(coreConfig, envVars);
554
+ configureIdentity(coreConfig, envVars);
555
+ configureIdentityResolver(coreConfig, envVars);
556
+ configureIdentityProfile(coreConfig, envVars);
557
+ configureAttestation(coreConfig, envVars);
558
+ configureDataProcessing(coreConfig, envVars);
559
+ configureAuditableItemGraph(coreConfig);
560
+ configureAuditableItemStream(coreConfig);
561
+ configureDocumentManagement(coreConfig);
562
+ configureFederatedCatalogue(coreConfig, envVars);
563
+ configureRightsManagement(coreConfig, envVars);
564
+ configureTaskScheduler(coreConfig, envVars);
565
+ return coreConfig;
566
+ }
567
+ /**
568
+ * Helper function to get IOTA configuration from centralized dltConfig.
569
+ * @param coreConfig The core config.
570
+ * @returns The IOTA configuration if found, undefined otherwise.
571
+ */
572
+ function getIotaConfig(coreConfig) {
573
+ const dltConfig = coreConfig.types.dltConfig?.find(config => config.type === engineTypes.DltConfigType.Iota && config.isDefault);
574
+ return dltConfig?.options?.config;
575
+ }
576
+ /**
577
+ * Configures the entity storage.
578
+ * @param coreConfig The core config.
579
+ * @param envVars The environment variables.
580
+ */
581
+ function configureEntityStorage(coreConfig, envVars) {
582
+ coreConfig.types ??= {};
583
+ coreConfig.types.entityStorageConnector ??= [];
584
+ if ((core.Coerce.boolean(envVars.entityMemoryEnable) ?? false) ||
585
+ envVars.entityStorageConnectorType === engineTypes.EntityStorageConnectorType.Memory) {
586
+ coreConfig.types.entityStorageConnector.push({
587
+ type: engineTypes.EntityStorageConnectorType.Memory
588
+ });
589
+ }
590
+ if ((core.Coerce.boolean(envVars.entityFileEnable) ?? false) ||
591
+ envVars.entityStorageConnectorType === engineTypes.EntityStorageConnectorType.File) {
592
+ coreConfig.types.entityStorageConnector.push({
593
+ type: engineTypes.EntityStorageConnectorType.File,
594
+ options: {
595
+ config: { directory: envVars.storageFileRoot ?? "" },
596
+ folderPrefix: envVars.entityStorageTablePrefix
597
+ }
598
+ });
599
+ }
600
+ if (core.Is.stringValue(envVars.awsDynamodbAccessKeyId)) {
601
+ coreConfig.types.entityStorageConnector.push({
602
+ type: engineTypes.EntityStorageConnectorType.AwsDynamoDb,
603
+ options: {
604
+ config: {
605
+ region: envVars.awsDynamodbRegion ?? "",
606
+ accessKeyId: envVars.awsDynamodbAccessKeyId ?? "",
607
+ secretAccessKey: envVars.awsDynamodbSecretAccessKey ?? "",
608
+ endpoint: envVars.awsDynamodbEndpoint ?? ""
609
+ },
610
+ tablePrefix: envVars.entityStorageTablePrefix
611
+ }
612
+ });
613
+ }
614
+ if (core.Is.stringValue(envVars.azureCosmosdbKey)) {
615
+ coreConfig.types.entityStorageConnector.push({
616
+ type: engineTypes.EntityStorageConnectorType.AzureCosmosDb,
617
+ options: {
618
+ config: {
619
+ endpoint: envVars.azureCosmosdbEndpoint ?? "",
620
+ key: envVars.azureCosmosdbKey ?? "",
621
+ databaseId: envVars.azureCosmosdbDatabaseId ?? "",
622
+ containerId: envVars.azureCosmosdbContainerId ?? ""
623
+ },
624
+ tablePrefix: envVars.entityStorageTablePrefix
625
+ }
626
+ });
627
+ }
628
+ if (core.Is.stringValue(envVars.gcpFirestoreCredentials)) {
629
+ coreConfig.types.entityStorageConnector.push({
630
+ type: engineTypes.EntityStorageConnectorType.GcpFirestoreDb,
631
+ options: {
632
+ config: {
633
+ projectId: envVars.gcpFirestoreProjectId ?? "",
634
+ credentials: envVars.gcpFirestoreCredentials ?? "",
635
+ databaseId: envVars.gcpFirestoreDatabaseId ?? "",
636
+ collectionName: envVars.gcpFirestoreCollectionName ?? "",
637
+ endpoint: envVars.gcpFirestoreApiEndpoint ?? ""
638
+ },
639
+ tablePrefix: envVars.entityStorageTablePrefix
640
+ }
641
+ });
642
+ }
643
+ if (core.Is.stringValue(envVars.scylladbHosts)) {
644
+ coreConfig.types.entityStorageConnector.push({
645
+ type: engineTypes.EntityStorageConnectorType.ScyllaDb,
646
+ options: {
647
+ config: {
648
+ hosts: envVars.scylladbHosts.split(",") ?? "",
649
+ localDataCenter: envVars.scylladbLocalDataCenter ?? "",
650
+ keyspace: envVars.scylladbKeyspace ?? ""
651
+ },
652
+ tablePrefix: envVars.entityStorageTablePrefix
653
+ }
654
+ });
655
+ }
656
+ if (core.Is.stringValue(envVars.mySqlHost)) {
657
+ coreConfig.types.entityStorageConnector.push({
658
+ type: engineTypes.EntityStorageConnectorType.MySqlDb,
659
+ options: {
660
+ config: {
661
+ host: envVars.mySqlHost,
662
+ port: envVars.mySqlPort ?? 3306,
663
+ user: envVars.mySqlUser ?? "",
664
+ password: envVars.mySqlPassword ?? "",
665
+ database: envVars.mySqlDatabase ?? ""
666
+ },
667
+ tablePrefix: envVars.entityStorageTablePrefix
668
+ }
669
+ });
670
+ }
671
+ if (core.Is.stringValue(envVars.mySqlHost)) {
672
+ coreConfig.types.entityStorageConnector.push({
673
+ type: engineTypes.EntityStorageConnectorType.MySqlDb,
674
+ options: {
675
+ config: {
676
+ host: envVars.mySqlHost,
677
+ port: envVars.mySqlPort ?? 3306,
678
+ user: envVars.mySqlUser ?? "",
679
+ password: envVars.mySqlPassword ?? "",
680
+ database: envVars.mySqlDatabase ?? ""
681
+ },
682
+ tablePrefix: envVars.entityStorageTablePrefix
683
+ }
684
+ });
685
+ }
686
+ if (core.Is.stringValue(envVars.mongoDbHost)) {
687
+ coreConfig.types.entityStorageConnector.push({
688
+ type: engineTypes.EntityStorageConnectorType.MongoDb,
689
+ options: {
690
+ config: {
691
+ host: envVars.mongoDbHost,
692
+ port: envVars.mongoDbPort,
693
+ user: envVars.mongoDbUser ?? "",
694
+ password: envVars.mongoDbPassword ?? "",
695
+ database: envVars.mongoDbDatabase ?? ""
696
+ },
697
+ tablePrefix: envVars.entityStorageTablePrefix
698
+ }
699
+ });
700
+ }
701
+ if (core.Is.stringValue(envVars.postgreSqlHost)) {
702
+ coreConfig.types.entityStorageConnector.push({
703
+ type: engineTypes.EntityStorageConnectorType.PostgreSql,
704
+ options: {
705
+ config: {
706
+ host: envVars.postgreSqlHost,
707
+ port: envVars.postgreSqlPort,
708
+ user: envVars.postgreSqlUser ?? "",
709
+ password: envVars.postgreSqlPassword ?? "",
710
+ database: envVars.postgreSqlDatabase ?? ""
711
+ },
712
+ tablePrefix: envVars.entityStorageTablePrefix
713
+ }
714
+ });
715
+ }
716
+ const defaultStorageConnector = envVars.entityStorageConnectorType;
717
+ if (core.Is.stringValue(defaultStorageConnector)) {
718
+ for (const config of coreConfig.types.entityStorageConnector) {
719
+ if (config.type === defaultStorageConnector) {
720
+ config.isDefault = true;
721
+ }
722
+ }
723
+ }
724
+ }
725
+ /**
726
+ * Configures the blob storage.
727
+ * @param coreConfig The core config.
728
+ * @param envVars The environment variables.
729
+ */
730
+ function configureBlobStorage(coreConfig, envVars) {
731
+ coreConfig.types.blobStorageConnector ??= [];
732
+ if ((core.Coerce.boolean(envVars.blobMemoryEnable) ?? false) ||
733
+ envVars.blobStorageConnectorType === engineTypes.BlobStorageConnectorType.Memory) {
734
+ coreConfig.types.blobStorageConnector.push({
735
+ type: engineTypes.BlobStorageConnectorType.Memory
736
+ });
737
+ }
738
+ if ((core.Coerce.boolean(envVars.blobFileEnable) ?? false) ||
739
+ envVars.blobStorageConnectorType === engineTypes.BlobStorageConnectorType.File) {
740
+ coreConfig.types.blobStorageConnector.push({
741
+ type: engineTypes.BlobStorageConnectorType.File,
742
+ options: {
743
+ config: {
744
+ directory: core.Is.stringValue(envVars.storageFileRoot)
745
+ ? path.join(envVars.storageFileRoot, "blob-storage")
746
+ : ""
747
+ },
748
+ storagePrefix: envVars.blobStoragePrefix
749
+ }
750
+ });
751
+ }
752
+ if (core.Is.stringValue(envVars.ipfsApiUrl)) {
753
+ coreConfig.types.blobStorageConnector.push({
754
+ type: engineTypes.BlobStorageConnectorType.Ipfs,
755
+ options: {
756
+ config: {
757
+ apiUrl: envVars.ipfsApiUrl,
758
+ bearerToken: envVars.ipfsBearerToken
759
+ }
760
+ }
761
+ });
762
+ }
763
+ if (core.Is.stringValue(envVars.awsS3AccessKeyId)) {
764
+ coreConfig.types.blobStorageConnector.push({
765
+ type: engineTypes.BlobStorageConnectorType.AwsS3,
766
+ options: {
767
+ config: {
768
+ region: envVars.awsS3Region ?? "",
769
+ bucketName: envVars.awsS3BucketName ?? "",
770
+ accessKeyId: envVars.awsS3AccessKeyId ?? "",
771
+ secretAccessKey: envVars.awsS3SecretAccessKey ?? "",
772
+ endpoint: envVars.awsS3Endpoint ?? ""
773
+ },
774
+ storagePrefix: envVars.blobStoragePrefix
775
+ }
776
+ });
777
+ }
778
+ if (core.Is.stringValue(envVars.azureStorageAccountKey)) {
779
+ coreConfig.types.blobStorageConnector.push({
780
+ type: engineTypes.BlobStorageConnectorType.AzureStorage,
781
+ options: {
782
+ config: {
783
+ accountName: envVars.azureStorageAccountName ?? "",
784
+ accountKey: envVars.azureStorageAccountKey ?? "",
785
+ containerName: envVars.azureStorageContainerName ?? "",
786
+ endpoint: envVars.azureStorageEndpoint ?? ""
787
+ },
788
+ storagePrefix: envVars.blobStoragePrefix
789
+ }
790
+ });
791
+ }
792
+ if (core.Is.stringValue(envVars.gcpStorageCredentials)) {
793
+ coreConfig.types.blobStorageConnector.push({
794
+ type: engineTypes.BlobStorageConnectorType.GcpStorage,
795
+ options: {
796
+ config: {
797
+ projectId: envVars.gcpStorageProjectId ?? "",
798
+ credentials: envVars.gcpStorageCredentials ?? "",
799
+ bucketName: envVars.gcpStorageBucketName ?? "",
800
+ apiEndpoint: envVars.gcpFirestoreApiEndpoint
801
+ },
802
+ storagePrefix: envVars.blobStoragePrefix
803
+ }
804
+ });
805
+ }
806
+ const defaultStorageConnectorType = envVars.blobStorageConnectorType;
807
+ if (core.Is.stringValue(defaultStorageConnectorType)) {
808
+ for (const config of coreConfig.types.blobStorageConnector) {
809
+ if (config.type === defaultStorageConnectorType) {
810
+ config.isDefault = true;
811
+ }
812
+ }
813
+ }
814
+ if (coreConfig.types.blobStorageConnector.length > 0) {
815
+ coreConfig.types.blobStorageComponent ??= [];
816
+ coreConfig.types.blobStorageComponent.push({
817
+ type: engineTypes.BlobStorageComponentType.Service,
818
+ options: {
819
+ config: {
820
+ vaultKeyId: (envVars.blobStorageEnableEncryption ?? false)
821
+ ? envVars.blobStorageEncryptionKey
822
+ : undefined
823
+ }
824
+ }
825
+ });
826
+ }
827
+ }
828
+ /**
829
+ * Configures the logging.
830
+ * @param coreConfig The core config.
831
+ * @param envVars The environment variables.
832
+ */
833
+ function configureLogging(coreConfig, envVars) {
834
+ coreConfig.types.loggingConnector ??= [];
835
+ const loggingConnectors = (envVars.loggingConnector ?? "").split(",");
836
+ for (const loggingConnector of loggingConnectors) {
837
+ if (loggingConnector === engineTypes.LoggingConnectorType.Console) {
838
+ coreConfig.types.loggingConnector?.push({
839
+ type: engineTypes.LoggingConnectorType.Console,
840
+ options: {
841
+ config: {
842
+ translateMessages: true,
843
+ hideGroups: true
844
+ }
845
+ },
846
+ isDefault: loggingConnectors.length === 1
847
+ });
848
+ }
849
+ else if (loggingConnector === engineTypes.LoggingConnectorType.EntityStorage) {
850
+ coreConfig.types.loggingConnector?.push({
851
+ type: engineTypes.LoggingConnectorType.EntityStorage,
852
+ isDefault: loggingConnectors.length === 1
853
+ });
854
+ }
855
+ }
856
+ if (loggingConnectors.length > 1) {
857
+ coreConfig.types.loggingConnector?.push({
858
+ type: engineTypes.LoggingConnectorType.Multi,
859
+ isDefault: true,
860
+ options: {
861
+ loggingConnectorTypes: loggingConnectors
862
+ }
863
+ });
864
+ }
865
+ if (loggingConnectors.length > 0) {
866
+ coreConfig.types.loggingComponent ??= [];
867
+ coreConfig.types.loggingComponent.push({ type: engineTypes.LoggingComponentType.Service });
868
+ }
869
+ }
870
+ /**
871
+ * Configures the vault.
872
+ * @param coreConfig The core config.
873
+ * @param envVars The environment variables.
874
+ */
875
+ function configureVault(coreConfig, envVars) {
876
+ coreConfig.types.vaultConnector ??= [];
877
+ if (envVars.vaultConnector === engineTypes.VaultConnectorType.EntityStorage) {
878
+ coreConfig.types.vaultConnector.push({
879
+ type: engineTypes.VaultConnectorType.EntityStorage
880
+ });
881
+ }
882
+ else if (envVars.vaultConnector === engineTypes.VaultConnectorType.Hashicorp) {
883
+ coreConfig.types.vaultConnector.push({
884
+ type: engineTypes.VaultConnectorType.Hashicorp,
885
+ options: {
886
+ config: {
887
+ endpoint: envVars.hashicorpVaultEndpoint ?? "",
888
+ token: envVars.hashicorpVaultToken ?? ""
889
+ }
890
+ }
891
+ });
892
+ }
893
+ }
894
+ /**
895
+ * Configures the background task.
896
+ * @param coreConfig The core config.
897
+ * @param envVars The environment variables.
898
+ */
899
+ function configureBackgroundTask(coreConfig, envVars) {
900
+ coreConfig.types.backgroundTaskConnector ??= [];
901
+ if (envVars.backgroundTaskConnector === engineTypes.BackgroundTaskConnectorType.EntityStorage) {
902
+ coreConfig.types.backgroundTaskConnector.push({
903
+ type: engineTypes.BackgroundTaskConnectorType.EntityStorage
904
+ });
905
+ }
906
+ }
907
+ /**
908
+ * Configures the event bud.
909
+ * @param coreConfig The core config.
910
+ * @param envVars The environment variables.
911
+ */
912
+ function configureEventBus(coreConfig, envVars) {
913
+ coreConfig.types.eventBusConnector ??= [];
914
+ if (envVars.eventBusConnector === engineTypes.EventBusConnectorType.Local) {
915
+ coreConfig.types.eventBusConnector.push({
916
+ type: engineTypes.EventBusConnectorType.Local
917
+ });
918
+ }
919
+ if (coreConfig.types.eventBusConnector.length > 0) {
920
+ coreConfig.types.eventBusComponent ??= [];
921
+ coreConfig.types.eventBusComponent.push({ type: engineTypes.EventBusComponentType.Service });
922
+ }
923
+ }
924
+ /**
925
+ * Configures the telemetry.
926
+ * @param coreConfig The core config.
927
+ * @param envVars The environment variables.
928
+ */
929
+ function configureTelemetry(coreConfig, envVars) {
930
+ coreConfig.types.telemetryConnector ??= [];
931
+ if (envVars.telemetryConnector === engineTypes.TelemetryConnectorType.EntityStorage) {
932
+ coreConfig.types.telemetryConnector.push({
933
+ type: engineTypes.TelemetryConnectorType.EntityStorage
934
+ });
935
+ }
936
+ if (coreConfig.types.telemetryConnector.length > 0) {
937
+ coreConfig.types.telemetryComponent ??= [];
938
+ coreConfig.types.telemetryComponent.push({ type: engineTypes.TelemetryComponentType.Service });
939
+ }
940
+ }
941
+ /**
942
+ * Configures the messaging.
943
+ * @param coreConfig The core config.
944
+ * @param envVars The environment variables.
945
+ */
946
+ function configureMessaging(coreConfig, envVars) {
947
+ coreConfig.types.messagingEmailConnector ??= [];
948
+ coreConfig.types.messagingSmsConnector ??= [];
949
+ coreConfig.types.messagingPushNotificationConnector ??= [];
950
+ if (envVars.messagingEmailConnector === engineTypes.MessagingEmailConnectorType.EntityStorage) {
951
+ coreConfig.types.messagingEmailConnector.push({
952
+ type: engineTypes.MessagingEmailConnectorType.EntityStorage
953
+ });
954
+ }
955
+ else if (envVars.messagingEmailConnector === engineTypes.MessagingEmailConnectorType.Aws) {
956
+ coreConfig.types.messagingEmailConnector.push({
957
+ type: engineTypes.MessagingEmailConnectorType.Aws,
958
+ options: {
959
+ config: {
960
+ region: envVars.awsS3Region ?? "",
961
+ accessKeyId: envVars.awsS3AccessKeyId ?? "",
962
+ secretAccessKey: envVars.awsS3SecretAccessKey ?? "",
963
+ endpoint: envVars.awsS3Endpoint ?? ""
964
+ }
965
+ }
966
+ });
967
+ }
968
+ if (envVars.messagingSmsConnector === engineTypes.MessagingSmsConnectorType.EntityStorage) {
969
+ coreConfig.types.messagingSmsConnector.push({
970
+ type: engineTypes.MessagingSmsConnectorType.EntityStorage
971
+ });
972
+ }
973
+ else if (envVars.messagingSmsConnector === engineTypes.MessagingSmsConnectorType.Aws) {
974
+ coreConfig.types.messagingSmsConnector.push({
975
+ type: engineTypes.MessagingSmsConnectorType.Aws,
976
+ options: {
977
+ config: {
978
+ region: envVars.awsS3Region ?? "",
979
+ accessKeyId: envVars.awsS3AccessKeyId ?? "",
980
+ secretAccessKey: envVars.awsS3SecretAccessKey ?? "",
981
+ endpoint: envVars.awsS3Endpoint ?? ""
982
+ }
983
+ }
984
+ });
985
+ }
986
+ if (envVars.messagingPushNotificationConnector ===
987
+ engineTypes.MessagingPushNotificationConnectorType.EntityStorage) {
988
+ coreConfig.types.messagingPushNotificationConnector.push({
989
+ type: engineTypes.MessagingPushNotificationConnectorType.EntityStorage
990
+ });
991
+ }
992
+ else if (envVars.messagingPushNotificationConnector === engineTypes.MessagingPushNotificationConnectorType.Aws) {
993
+ coreConfig.types.messagingPushNotificationConnector.push({
994
+ type: engineTypes.MessagingPushNotificationConnectorType.Aws,
995
+ options: {
996
+ config: {
997
+ region: envVars.awsS3Region ?? "",
998
+ accessKeyId: envVars.awsS3AccessKeyId ?? "",
999
+ secretAccessKey: envVars.awsS3SecretAccessKey ?? "",
1000
+ endpoint: envVars.awsS3Endpoint ?? "",
1001
+ applicationsSettings: core.Is.json(envVars.awsMessagingPushNotificationApplications)
1002
+ ? JSON.parse(envVars.awsMessagingPushNotificationApplications)
1003
+ : []
1004
+ }
1005
+ }
1006
+ });
1007
+ }
1008
+ if (coreConfig.types.messagingEmailConnector.length > 0 ||
1009
+ coreConfig.types.messagingSmsConnector.length > 0 ||
1010
+ coreConfig.types.messagingPushNotificationConnector.length > 0) {
1011
+ coreConfig.types.messagingComponent ??= [];
1012
+ coreConfig.types.messagingComponent.push({ type: engineTypes.MessagingComponentType.Service });
1013
+ }
1014
+ }
1015
+ /**
1016
+ * Configures the faucet.
1017
+ * @param coreConfig The core config.
1018
+ * @param envVars The environment variables.
1019
+ */
1020
+ function configureFaucet(coreConfig, envVars) {
1021
+ coreConfig.types.faucetConnector ??= [];
1022
+ if (envVars.faucetConnector === engineTypes.FaucetConnectorType.EntityStorage) {
1023
+ coreConfig.types.faucetConnector.push({
1024
+ type: engineTypes.FaucetConnectorType.EntityStorage
1025
+ });
1026
+ }
1027
+ else if (envVars.faucetConnector === engineTypes.FaucetConnectorType.Iota) {
1028
+ const iotaConfig = getIotaConfig(coreConfig);
1029
+ coreConfig.types.faucetConnector.push({
1030
+ type: engineTypes.FaucetConnectorType.Iota,
1031
+ options: {
1032
+ config: {
1033
+ endpoint: envVars.iotaFaucetEndpoint ?? "",
1034
+ clientOptions: iotaConfig?.clientOptions ?? { url: "" },
1035
+ network: iotaConfig?.network ?? ""
1036
+ }
1037
+ }
1038
+ });
1039
+ }
1040
+ }
1041
+ /**
1042
+ * Configures the wallet.
1043
+ * @param coreConfig The core config.
1044
+ * @param envVars The environment variables.
1045
+ */
1046
+ function configureWallet(coreConfig, envVars) {
1047
+ coreConfig.types.walletConnector ??= [];
1048
+ if (envVars.walletConnector === engineTypes.WalletConnectorType.EntityStorage) {
1049
+ coreConfig.types.walletConnector.push({
1050
+ type: engineTypes.WalletConnectorType.EntityStorage
1051
+ });
1052
+ }
1053
+ else if (envVars.walletConnector === engineTypes.WalletConnectorType.Iota) {
1054
+ const iotaConfig = getIotaConfig(coreConfig);
1055
+ coreConfig.types.walletConnector.push({
1056
+ type: engineTypes.WalletConnectorType.Iota,
1057
+ options: {
1058
+ config: iotaConfig ?? {}
1059
+ }
1060
+ });
1061
+ }
1062
+ }
1063
+ /**
1064
+ * Configures the NFT.
1065
+ * @param coreConfig The core config.
1066
+ * @param envVars The environment variables.
1067
+ */
1068
+ function configureNft(coreConfig, envVars) {
1069
+ coreConfig.types.nftConnector ??= [];
1070
+ if (envVars.nftConnector === engineTypes.NftConnectorType.EntityStorage) {
1071
+ coreConfig.types.nftConnector.push({
1072
+ type: engineTypes.NftConnectorType.EntityStorage
1073
+ });
1074
+ }
1075
+ else if (envVars.nftConnector === engineTypes.NftConnectorType.Iota) {
1076
+ const iotaConfig = getIotaConfig(coreConfig);
1077
+ coreConfig.types.nftConnector.push({
1078
+ type: engineTypes.NftConnectorType.Iota,
1079
+ options: {
1080
+ config: iotaConfig ?? {}
1081
+ }
1082
+ });
1083
+ }
1084
+ if (coreConfig.types.nftConnector.length > 0) {
1085
+ coreConfig.types.nftComponent ??= [];
1086
+ coreConfig.types.nftComponent.push({ type: engineTypes.NftComponentType.Service });
1087
+ }
1088
+ }
1089
+ /**
1090
+ * Configures the verifiable storage.
1091
+ * @param coreConfig The core config.
1092
+ * @param envVars The environment variables.
1093
+ */
1094
+ function configureVerifiableStorage(coreConfig, envVars) {
1095
+ coreConfig.types.verifiableStorageConnector ??= [];
1096
+ if (envVars.verifiableStorageConnector === engineTypes.VerifiableStorageConnectorType.EntityStorage) {
1097
+ coreConfig.types.verifiableStorageConnector.push({
1098
+ type: engineTypes.VerifiableStorageConnectorType.EntityStorage
1099
+ });
1100
+ }
1101
+ else if (envVars.verifiableStorageConnector === engineTypes.VerifiableStorageConnectorType.Iota) {
1102
+ const iotaConfig = getIotaConfig(coreConfig);
1103
+ coreConfig.types.verifiableStorageConnector.push({
1104
+ type: engineTypes.VerifiableStorageConnectorType.Iota,
1105
+ options: {
1106
+ config: iotaConfig ?? {}
1107
+ }
1108
+ });
1109
+ }
1110
+ if (coreConfig.types.verifiableStorageConnector.length > 0) {
1111
+ coreConfig.types.verifiableStorageComponent ??= [];
1112
+ coreConfig.types.verifiableStorageComponent.push({
1113
+ type: engineTypes.VerifiableStorageComponentType.Service
1114
+ });
1115
+ coreConfig.types.immutableProofComponent ??= [];
1116
+ coreConfig.types.immutableProofComponent.push({
1117
+ type: engineTypes.ImmutableProofComponentType.Service,
1118
+ options: {
1119
+ config: {
1120
+ verificationMethodId: envVars.immutableProofVerificationMethodId
1121
+ }
1122
+ }
1123
+ });
1124
+ coreConfig.types.auditableItemGraphComponent ??= [];
1125
+ coreConfig.types.auditableItemGraphComponent.push({
1126
+ type: engineTypes.AuditableItemGraphComponentType.Service
1127
+ });
1128
+ coreConfig.types.auditableItemStreamComponent ??= [];
1129
+ coreConfig.types.auditableItemStreamComponent.push({
1130
+ type: engineTypes.AuditableItemStreamComponentType.Service
1131
+ });
1132
+ }
1133
+ }
1134
+ /**
1135
+ * Configures the identity.
1136
+ * @param coreConfig The core config.
1137
+ * @param envVars The environment variables.
1138
+ */
1139
+ function configureIdentity(coreConfig, envVars) {
1140
+ coreConfig.types.identityConnector ??= [];
1141
+ if (envVars.identityConnector === engineTypes.IdentityConnectorType.EntityStorage) {
1142
+ coreConfig.types.identityConnector.push({
1143
+ type: engineTypes.IdentityConnectorType.EntityStorage
1144
+ });
1145
+ }
1146
+ else if (envVars.identityConnector === engineTypes.IdentityConnectorType.Iota) {
1147
+ const iotaConfig = getIotaConfig(coreConfig);
1148
+ coreConfig.types.identityConnector.push({
1149
+ type: engineTypes.IdentityConnectorType.Iota,
1150
+ options: {
1151
+ config: iotaConfig ?? {}
1152
+ }
1153
+ });
1154
+ }
1155
+ if (coreConfig.types.identityConnector.length > 0) {
1156
+ coreConfig.types.identityComponent ??= [];
1157
+ coreConfig.types.identityComponent.push({ type: engineTypes.IdentityComponentType.Service });
1158
+ }
1159
+ }
1160
+ /**
1161
+ * Configures the identity resolver.
1162
+ * @param coreConfig The core config.
1163
+ * @param envVars The environment variables.
1164
+ */
1165
+ function configureIdentityResolver(coreConfig, envVars) {
1166
+ coreConfig.types.identityResolverConnector ??= [];
1167
+ if (envVars.identityResolverConnector === engineTypes.IdentityResolverConnectorType.EntityStorage) {
1168
+ coreConfig.types.identityResolverConnector.push({
1169
+ type: engineTypes.IdentityResolverConnectorType.EntityStorage
1170
+ });
1171
+ }
1172
+ else if (envVars.identityResolverConnector === engineTypes.IdentityResolverConnectorType.Iota) {
1173
+ const iotaConfig = getIotaConfig(coreConfig);
1174
+ coreConfig.types.identityResolverConnector.push({
1175
+ type: engineTypes.IdentityResolverConnectorType.Iota,
1176
+ options: {
1177
+ config: iotaConfig ?? {}
1178
+ }
1179
+ });
1180
+ }
1181
+ else if (envVars.identityResolverConnector === engineTypes.IdentityResolverConnectorType.Universal) {
1182
+ coreConfig.types.identityResolverConnector.push({
1183
+ type: engineTypes.IdentityResolverConnectorType.Universal,
1184
+ options: {
1185
+ config: {
1186
+ endpoint: envVars.universalResolverEndpoint ?? ""
1187
+ }
1188
+ }
1189
+ });
1190
+ }
1191
+ if (coreConfig.types.identityResolverConnector.length > 0) {
1192
+ coreConfig.types.identityResolverComponent ??= [];
1193
+ coreConfig.types.identityResolverComponent.push({
1194
+ type: engineTypes.IdentityResolverComponentType.Service
1195
+ });
1196
+ }
1197
+ }
1198
+ /**
1199
+ * Configures the identity profile.
1200
+ * @param coreConfig The core config.
1201
+ * @param envVars The environment variables.
1202
+ */
1203
+ function configureIdentityProfile(coreConfig, envVars) {
1204
+ coreConfig.types.identityProfileConnector ??= [];
1205
+ if (envVars.identityProfileConnector === engineTypes.IdentityConnectorType.EntityStorage) {
1206
+ coreConfig.types.identityProfileConnector.push({
1207
+ type: engineTypes.IdentityProfileConnectorType.EntityStorage
1208
+ });
1209
+ }
1210
+ if (coreConfig.types.identityProfileConnector.length > 0) {
1211
+ coreConfig.types.identityProfileComponent ??= [];
1212
+ coreConfig.types.identityProfileComponent.push({ type: engineTypes.IdentityProfileComponentType.Service });
1213
+ }
1214
+ }
1215
+ /**
1216
+ * Configures the attestation.
1217
+ * @param coreConfig The core config.
1218
+ * @param envVars The environment variables.
1219
+ */
1220
+ function configureAttestation(coreConfig, envVars) {
1221
+ coreConfig.types.attestationConnector ??= [];
1222
+ if (envVars.attestationConnector === engineTypes.AttestationConnectorType.Nft) {
1223
+ coreConfig.types.attestationConnector.push({
1224
+ type: engineTypes.AttestationConnectorType.Nft
1225
+ });
1226
+ }
1227
+ if (coreConfig.types.attestationConnector.length > 0) {
1228
+ coreConfig.types.attestationComponent ??= [];
1229
+ coreConfig.types.attestationComponent.push({
1230
+ type: engineTypes.AttestationComponentType.Service,
1231
+ options: {
1232
+ config: {
1233
+ verificationMethodId: envVars.attestationVerificationMethodId
1234
+ }
1235
+ }
1236
+ });
1237
+ }
1238
+ }
1239
+ /**
1240
+ * Configures the auditable item graph.
1241
+ * @param coreConfig The core config.
1242
+ * @param envVars The environment variables.
1243
+ */
1244
+ function configureAuditableItemGraph(coreConfig, envVars) {
1245
+ if (core.Is.arrayValue(coreConfig.types.verifiableStorageConnector)) {
1246
+ coreConfig.types.auditableItemGraphComponent ??= [];
1247
+ coreConfig.types.auditableItemGraphComponent.push({
1248
+ type: engineTypes.AuditableItemGraphComponentType.Service
1249
+ });
1250
+ }
1251
+ }
1252
+ /**
1253
+ * Configures the auditable item stream.
1254
+ * @param coreConfig The core config.
1255
+ * @param envVars The environment variables.
1256
+ */
1257
+ function configureAuditableItemStream(coreConfig, envVars) {
1258
+ if (core.Is.arrayValue(coreConfig.types.verifiableStorageConnector)) {
1259
+ coreConfig.types.auditableItemStreamComponent ??= [];
1260
+ coreConfig.types.auditableItemStreamComponent.push({
1261
+ type: engineTypes.AuditableItemStreamComponentType.Service
1262
+ });
1263
+ }
1264
+ }
1265
+ /**
1266
+ * Configures the data processing.
1267
+ * @param coreConfig The core config.
1268
+ * @param envVars The environment variables.
1269
+ */
1270
+ function configureDataProcessing(coreConfig, envVars) {
1271
+ coreConfig.types.dataConverterConnector ??= [];
1272
+ coreConfig.types.dataExtractorConnector ??= [];
1273
+ const converterConnectors = envVars.dataConverterConnectors?.split(",") ?? [];
1274
+ for (const converterConnector of converterConnectors) {
1275
+ if (converterConnector === engineTypes.DataConverterConnectorType.Json) {
1276
+ coreConfig.types.dataConverterConnector.push({
1277
+ type: engineTypes.DataConverterConnectorType.Json
1278
+ });
1279
+ }
1280
+ else if (converterConnector === engineTypes.DataConverterConnectorType.Xml) {
1281
+ coreConfig.types.dataConverterConnector.push({
1282
+ type: engineTypes.DataConverterConnectorType.Xml
1283
+ });
1284
+ }
1285
+ }
1286
+ const extractorConnectors = envVars.dataExtractorConnectors?.split(",") ?? [];
1287
+ for (const extractorConnector of extractorConnectors) {
1288
+ if (extractorConnector === engineTypes.DataExtractorConnectorType.JsonPath) {
1289
+ coreConfig.types.dataExtractorConnector.push({
1290
+ type: engineTypes.DataExtractorConnectorType.JsonPath
1291
+ });
1292
+ }
1293
+ }
1294
+ if (coreConfig.types.dataConverterConnector.length > 0 ||
1295
+ coreConfig.types.dataExtractorConnector.length > 0) {
1296
+ coreConfig.types.dataProcessingComponent ??= [];
1297
+ coreConfig.types.dataProcessingComponent.push({ type: engineTypes.DataProcessingComponentType.Service });
1298
+ }
1299
+ }
1300
+ /**
1301
+ * Configures the document management.
1302
+ * @param coreConfig The core config.
1303
+ * @param envVars The environment variables.
1304
+ */
1305
+ function configureDocumentManagement(coreConfig, envVars) {
1306
+ if (core.Is.arrayValue(coreConfig.types.auditableItemGraphComponent) &&
1307
+ core.Is.arrayValue(coreConfig.types.blobStorageComponent) &&
1308
+ core.Is.arrayValue(coreConfig.types.attestationComponent)) {
1309
+ coreConfig.types.documentManagementComponent ??= [];
1310
+ coreConfig.types.documentManagementComponent.push({
1311
+ type: engineTypes.DocumentManagementComponentType.Service
1312
+ });
1313
+ }
1314
+ }
1315
+ /**
1316
+ * Configures the federated catalogue.
1317
+ * @param coreConfig The core config.
1318
+ * @param envVars The environment variables.
1319
+ */
1320
+ function configureFederatedCatalogue(coreConfig, envVars) {
1321
+ if (core.Is.arrayValue(coreConfig.types.identityResolverComponent)) {
1322
+ coreConfig.types.federatedCatalogueComponent ??= [];
1323
+ coreConfig.types.federatedCatalogueComponent.push({
1324
+ type: engineTypes.FederatedCatalogueComponentType.Service,
1325
+ options: {
1326
+ config: {
1327
+ subResourceCacheTtlMs: core.Coerce.number(envVars.federatedCatalogueCacheTtlMs),
1328
+ clearingHouseApproverList: core.Coerce.object(envVars.federatedCatalogueClearingHouseApproverList) ?? []
1329
+ }
1330
+ }
1331
+ });
1332
+ }
1333
+ }
1334
+ /**
1335
+ * Configures the rights management.
1336
+ * @param coreConfig The core config.
1337
+ * @param envVars The environment variables.
1338
+ */
1339
+ function configureRightsManagement(coreConfig, envVars) {
1340
+ if (core.Coerce.boolean(envVars.rightsManagementEnabled) ?? false) {
1341
+ coreConfig.types.rightsManagementPapComponent ??= [];
1342
+ coreConfig.types.rightsManagementPapComponent.push({
1343
+ type: engineTypes.RightsManagementPapComponentType.Service
1344
+ });
1345
+ coreConfig.types.rightsManagementComponent ??= [];
1346
+ coreConfig.types.rightsManagementComponent.push({
1347
+ type: engineTypes.RightsManagementComponentType.Service
1348
+ });
1349
+ }
1350
+ }
1351
+ /**
1352
+ * Configures the task scheduler.
1353
+ * @param coreConfig The core config.
1354
+ * @param envVars The environment variables.
1355
+ */
1356
+ function configureTaskScheduler(coreConfig, envVars) {
1357
+ if (core.Coerce.boolean(envVars.taskSchedulerEnabled) ?? true) {
1358
+ coreConfig.types.taskSchedulerComponent ??= [];
1359
+ coreConfig.types.taskSchedulerComponent.push({
1360
+ type: engineTypes.TaskSchedulerComponentType.Default
1361
+ });
1362
+ }
1363
+ }
1364
+ /**
1365
+ * Configures the DLT.
1366
+ * @param coreConfig The core config.
1367
+ * @param envVars The environment variables.
1368
+ */
1369
+ function configureDlt(coreConfig, envVars) {
1370
+ // Create centralized DLT configuration for IOTA if essential IOTA variables are set
1371
+ if (core.Is.stringValue(envVars.iotaNodeEndpoint) && core.Is.stringValue(envVars.iotaNetwork)) {
1372
+ coreConfig.types.dltConfig ??= [];
1373
+ const gasStationConfig = core.Is.stringValue(envVars.iotaGasStationEndpoint) &&
1374
+ core.Is.stringValue(envVars.iotaGasStationAuthToken)
1375
+ ? {
1376
+ gasStationUrl: envVars.iotaGasStationEndpoint,
1377
+ gasStationAuthToken: envVars.iotaGasStationAuthToken
1378
+ }
1379
+ : undefined;
1380
+ coreConfig.types.dltConfig.push({
1381
+ type: engineTypes.DltConfigType.Iota,
1382
+ isDefault: true,
1383
+ options: {
1384
+ config: {
1385
+ clientOptions: {
1386
+ url: envVars.iotaNodeEndpoint ?? ""
1387
+ },
1388
+ network: envVars.iotaNetwork ?? "",
1389
+ coinType: core.Coerce.number(envVars.iotaCoinType),
1390
+ gasStation: gasStationConfig
1391
+ }
1392
+ }
1393
+ });
1394
+ }
1395
+ }
1396
+
1397
+ /**
1398
+ * Handles the configuration of the server.
1399
+ * @param envVars The environment variables for the engine server.
1400
+ * @param coreEngineConfig The core engine config.
513
1401
  * @param serverInfo The server information.
514
- * @param envVarsPrefix The prefix for the environment variables.
1402
+ * @param openApiSpecPath The path to the open api spec.
1403
+ * @returns The the config for the core and the server.
1404
+ */
1405
+ function buildEngineServerConfiguration(envVars, coreEngineConfig, serverInfo, openApiSpecPath) {
1406
+ envVars.authSigningKeyId ??= "auth-signing";
1407
+ const webServerOptions = {
1408
+ port: core.Coerce.number(envVars.port),
1409
+ host: core.Coerce.string(envVars.host),
1410
+ methods: core.Is.stringValue(envVars.httpMethods)
1411
+ ? envVars.httpMethods.split(",")
1412
+ : undefined,
1413
+ allowedHeaders: core.Is.stringValue(envVars.httpAllowedHeaders)
1414
+ ? envVars.httpAllowedHeaders.split(",")
1415
+ : undefined,
1416
+ exposedHeaders: core.Is.stringValue(envVars.httpExposedHeaders)
1417
+ ? envVars.httpExposedHeaders.split(",")
1418
+ : undefined,
1419
+ corsOrigins: core.Is.stringValue(envVars.corsOrigins) ? envVars.corsOrigins.split(",") : undefined
1420
+ };
1421
+ const serverConfig = {
1422
+ ...coreEngineConfig,
1423
+ web: webServerOptions,
1424
+ types: {
1425
+ ...coreEngineConfig.types,
1426
+ informationComponent: [
1427
+ {
1428
+ type: engineServerTypes.InformationComponentType.Service,
1429
+ options: {
1430
+ config: {
1431
+ serverInfo,
1432
+ openApiSpecPath
1433
+ }
1434
+ }
1435
+ }
1436
+ ]
1437
+ }
1438
+ };
1439
+ if (core.Is.stringValue(envVars.mimeTypeProcessors)) {
1440
+ const mimeTypeProcessors = envVars.mimeTypeProcessors.split(",");
1441
+ if (core.Is.arrayValue(mimeTypeProcessors)) {
1442
+ serverConfig.types.mimeTypeProcessor ??= [];
1443
+ for (const mimeTypeProcessor of mimeTypeProcessors) {
1444
+ serverConfig.types.mimeTypeProcessor.push({
1445
+ type: mimeTypeProcessor
1446
+ });
1447
+ }
1448
+ }
1449
+ }
1450
+ serverConfig.types.restRouteProcessor ??= [];
1451
+ serverConfig.types.socketRouteProcessor ??= [];
1452
+ const disableNodeIdentity = core.Coerce.boolean(envVars.disableNodeIdentity);
1453
+ if (!disableNodeIdentity) {
1454
+ serverConfig.types.restRouteProcessor.push({
1455
+ type: engineServerTypes.RestRouteProcessorType.NodeIdentity
1456
+ });
1457
+ serverConfig.types.socketRouteProcessor.push({
1458
+ type: engineServerTypes.SocketRouteProcessorType.NodeIdentity
1459
+ });
1460
+ }
1461
+ if (!coreEngineConfig.silent) {
1462
+ serverConfig.types.restRouteProcessor.push({
1463
+ type: engineServerTypes.RestRouteProcessorType.Logging,
1464
+ options: {
1465
+ config: {
1466
+ includeBody: coreEngineConfig.debug
1467
+ }
1468
+ }
1469
+ });
1470
+ serverConfig.types.socketRouteProcessor.push({
1471
+ type: engineServerTypes.SocketRouteProcessorType.Logging,
1472
+ options: {
1473
+ config: {
1474
+ includeBody: coreEngineConfig.debug
1475
+ }
1476
+ }
1477
+ });
1478
+ }
1479
+ serverConfig.types.restRouteProcessor.push({
1480
+ type: engineServerTypes.RestRouteProcessorType.RestRoute,
1481
+ options: {
1482
+ config: {
1483
+ includeErrorStack: coreEngineConfig.debug
1484
+ }
1485
+ }
1486
+ });
1487
+ serverConfig.types.socketRouteProcessor.push({
1488
+ type: engineServerTypes.SocketRouteProcessorType.SocketRoute,
1489
+ options: {
1490
+ config: {
1491
+ includeErrorStack: coreEngineConfig.debug
1492
+ }
1493
+ }
1494
+ });
1495
+ const authAdminProcessorType = envVars.authAdminProcessorType;
1496
+ if (authAdminProcessorType === engineServerTypes.AuthenticationAdminComponentType.EntityStorage) {
1497
+ serverConfig.types.authenticationAdminComponent ??= [];
1498
+ serverConfig.types.authenticationAdminComponent.push({
1499
+ type: engineServerTypes.AuthenticationAdminComponentType.EntityStorage,
1500
+ options: {
1501
+ config: {}
1502
+ }
1503
+ });
1504
+ }
1505
+ const authProcessorType = envVars.authProcessorType;
1506
+ if (authProcessorType === engineServerTypes.AuthenticationComponentType.EntityStorage) {
1507
+ serverConfig.types.authenticationComponent ??= [];
1508
+ serverConfig.types.authenticationComponent.push({
1509
+ type: engineServerTypes.AuthenticationComponentType.EntityStorage,
1510
+ options: {
1511
+ config: {
1512
+ signingKeyName: envVars.authSigningKeyId
1513
+ }
1514
+ }
1515
+ });
1516
+ serverConfig.types.restRouteProcessor.push({
1517
+ type: engineServerTypes.RestRouteProcessorType.AuthHeader,
1518
+ options: {
1519
+ config: {
1520
+ signingKeyName: envVars.authSigningKeyId
1521
+ }
1522
+ }
1523
+ });
1524
+ serverConfig.types.socketRouteProcessor.push({
1525
+ type: engineServerTypes.SocketRouteProcessorType.AuthHeader,
1526
+ options: {
1527
+ config: {
1528
+ signingKeyName: envVars.authSigningKeyId
1529
+ }
1530
+ }
1531
+ });
1532
+ }
1533
+ engineServer.addDefaultRestPaths(serverConfig);
1534
+ engineServer.addDefaultSocketPaths(serverConfig);
1535
+ return serverConfig;
1536
+ }
1537
+
1538
+ // Copyright 2024 IOTA Stiftung.
1539
+ // SPDX-License-Identifier: Apache-2.0.
1540
+ /* eslint-disable no-console */
1541
+ /**
1542
+ * Start the engine server.
1543
+ * @param nodeOptions Optional run options for the engine server.
1544
+ * @param engineServerConfig The configuration for the engine server.
515
1545
  * @param envVars The environment variables.
516
- * @param openApiSpecFile Path to the OpenAPI spec file.
517
- * @param stateStorage The state storage.
518
- * @param extendConfig Extends the engine configuration with any additional custom configuration.
519
- * @param extendEngine Extends the engine with any additional options.
520
- * @param extendEngineServer Extends the engine server with any additional options.
521
1546
  * @returns The engine server.
522
1547
  */
523
- async function start(serverInfo, envVarsPrefix, envVars, openApiSpecFile, stateStorage, extendConfig, extendEngine, extendEngineServer) {
1548
+ async function start(nodeOptions, engineServerConfig, envVars) {
524
1549
  envVars.storageFileRoot ??= "";
525
1550
  if ((envVars.entityStorageConnectorType === engineTypes.EntityStorageConnectorType.File ||
526
1551
  envVars.blobStorageConnectorType === engineTypes.BlobStorageConnectorType.File ||
527
- core.Is.empty(stateStorage)) &&
1552
+ core.Is.empty(nodeOptions?.stateStorage)) &&
528
1553
  !core.Is.stringValue(envVars.storageFileRoot)) {
529
1554
  throw new core.GeneralError("node", "storageFileRootNotSet", {
530
- storageFileRoot: `${envVarsPrefix}_STORAGE_FILE_ROOT`
1555
+ storageFileRoot: `${nodeOptions?.envPrefix ?? ""}_STORAGE_FILE_ROOT`
531
1556
  });
532
1557
  }
533
- // Build the engine configuration from the environment variables.
534
- const engineConfig = engine.buildEngineConfiguration(envVars);
535
- // Extend the engine configuration with a custom type.
536
- if (core.Is.function(extendConfig)) {
537
- await extendConfig(engineConfig);
538
- }
539
- // Build the server configuration from the environment variables.
540
- const serverConfig = engineServer.buildEngineServerConfiguration(envVars, engineConfig, serverInfo, openApiSpecFile);
541
1558
  // Create the engine instance using file state storage and custom bootstrap.
542
1559
  const engine$1 = new engine.Engine({
543
- config: { ...engineConfig, ...serverConfig },
544
- stateStorage: stateStorage ?? new engineCore.FileStateStorage(envVars.stateFilename ?? ""),
1560
+ config: engineServerConfig,
1561
+ stateStorage: nodeOptions?.stateStorage ?? new engineCore.FileStateStorage(envVars.stateFilename ?? ""),
545
1562
  customBootstrap: async (core, engineContext) => bootstrap(core, engineContext, envVars)
546
1563
  });
547
1564
  // Extend the engine.
548
- if (core.Is.function(extendEngine)) {
549
- await extendEngine(engine$1);
1565
+ if (core.Is.function(nodeOptions?.extendEngine)) {
1566
+ console.info("Extending Engine");
1567
+ await nodeOptions.extendEngine(engine$1);
550
1568
  }
551
1569
  // Construct the server with the engine.
552
1570
  const server = new engineServer.EngineServer({ engineCore: engine$1 });
553
1571
  // Extend the engine server.
554
- if (core.Is.function(extendEngineServer)) {
555
- await extendEngineServer(server);
1572
+ if (core.Is.function(nodeOptions?.extendEngineServer)) {
1573
+ console.info("Extending Engine Server");
1574
+ await nodeOptions?.extendEngineServer(server);
556
1575
  }
557
1576
  // Need to register the engine with the factory so that background tasks
558
1577
  // can clone it to spawn new instances.
@@ -572,44 +1591,39 @@ async function start(serverInfo, envVarsPrefix, envVars, openApiSpecFile, stateS
572
1591
  /* eslint-disable no-console */
573
1592
  /**
574
1593
  * Run the TWIN Node server.
575
- * @param options Optional configuration options for running the server.
1594
+ * @param nodeOptions Optional configuration options for running the server.
576
1595
  * @returns A promise that resolves when the server is started.
577
1596
  */
578
- async function run(options) {
1597
+ async function run(nodeOptions) {
579
1598
  try {
1599
+ nodeOptions ??= {};
580
1600
  const serverInfo = {
581
- name: options?.serverName ?? "TWIN Node Server",
582
- version: options?.serverVersion ?? "0.0.1-next.9" // x-release-please-version
1601
+ name: nodeOptions?.serverName ?? "TWIN Node Server",
1602
+ version: nodeOptions?.serverVersion ?? "0.0.1-next.11" // x-release-please-version
583
1603
  };
584
1604
  console.log(`\u001B[4m🌩️ ${serverInfo.name} v${serverInfo.version}\u001B[24m\n`);
585
- const executionDirectory = options?.executionDirectory ?? getExecutionDirectory();
586
- console.info("Execution Directory:", process.cwd());
587
- await initialiseLocales(options?.localesDirectory ?? path.resolve(path.join(executionDirectory, "dist", "locales")));
588
- if (core.Is.empty(options?.openApiSpecFile)) {
589
- const specFile = path.resolve(path.join(executionDirectory, "docs", "open-api", "spec.json"));
1605
+ if (!core.Is.stringValue(nodeOptions?.executionDirectory)) {
1606
+ nodeOptions.executionDirectory = getExecutionDirectory();
1607
+ }
1608
+ console.info("Execution Directory:", nodeOptions.executionDirectory);
1609
+ nodeOptions.localesDirectory =
1610
+ nodeOptions?.localesDirectory ??
1611
+ path.resolve(path.join(nodeOptions.executionDirectory, "dist", "locales"));
1612
+ console.info("Locales Directory:", nodeOptions.localesDirectory);
1613
+ await initialiseLocales(nodeOptions.localesDirectory);
1614
+ if (core.Is.empty(nodeOptions?.openApiSpecFile)) {
1615
+ const specFile = path.resolve(path.join(nodeOptions.executionDirectory, "docs", "open-api", "spec.json"));
590
1616
  console.info("Default OpenAPI Spec File:", specFile);
591
1617
  if (await fileExists(specFile)) {
592
- options ??= {};
593
- options.openApiSpecFile = specFile;
1618
+ nodeOptions ??= {};
1619
+ nodeOptions.openApiSpecFile = specFile;
594
1620
  }
595
1621
  }
596
- if (core.Is.empty(options?.envFilenames)) {
597
- const envFile = path.resolve(path.join(executionDirectory, ".env"));
598
- console.info("Default Environment File:", envFile);
599
- options ??= {};
600
- options.envFilenames = [envFile];
601
- }
602
- dotenv__namespace.config({
603
- path: options?.envFilenames
604
- });
605
- const envPrefix = options?.envPrefix ?? "TWIN_NODE_";
606
- console.info("Environment Prefix:", envPrefix);
607
- const envVars = core.EnvHelper.envToJson(process.env, envPrefix);
608
- if (Object.keys(envVars).length === 0) {
609
- throw new core.GeneralError("node", "noEnvVars", { prefix: envPrefix });
610
- }
1622
+ nodeOptions.envPrefix ??= "TWIN_NODE_";
1623
+ console.info("Environment Prefix:", nodeOptions.envPrefix);
1624
+ const { engineServerConfig, nodeEnvVars: envVars } = await buildConfiguration(process.env, nodeOptions, serverInfo);
611
1625
  console.info();
612
- const startResult = await start(serverInfo, envPrefix, envVars, options?.openApiSpecFile, options.stateStorage, options.extendConfig, options.extendEngine, options.extendEngineServer);
1626
+ const startResult = await start(nodeOptions, engineServerConfig, envVars);
613
1627
  if (!core.Is.empty(startResult)) {
614
1628
  for (const signal of ["SIGHUP", "SIGINT", "SIGTERM"]) {
615
1629
  process.on(signal, async () => {
@@ -624,6 +1638,76 @@ async function run(options) {
624
1638
  process.exit(1);
625
1639
  }
626
1640
  }
1641
+ /**
1642
+ * Build the configuration for the TWIN Node server.
1643
+ * @param processEnv The environment variables from the process.
1644
+ * @param options The options for running the server.
1645
+ * @param serverInfo The server information.
1646
+ * @returns A promise that resolves to the engine server configuration, environment prefix, environment variables,
1647
+ * and options.
1648
+ */
1649
+ async function buildConfiguration(processEnv, options, serverInfo) {
1650
+ let defaultEnvOnly = false;
1651
+ if (core.Is.empty(options?.envFilenames)) {
1652
+ const envFile = path.resolve(path.join(options.executionDirectory ?? "", ".env"));
1653
+ console.info("Default Environment File:", envFile);
1654
+ options ??= {};
1655
+ options.envFilenames = [envFile];
1656
+ defaultEnvOnly = true;
1657
+ }
1658
+ if (core.Is.arrayValue(options?.envFilenames)) {
1659
+ const output = dotenv__namespace.config({
1660
+ path: options?.envFilenames
1661
+ });
1662
+ // We don't want to throw an error if the default environment file is not found.
1663
+ // Only if we have custom environment files.
1664
+ if (!defaultEnvOnly && output.error) {
1665
+ throw output.error;
1666
+ }
1667
+ if (core.Is.objectValue(output.parsed)) {
1668
+ Object.assign(processEnv, output.parsed);
1669
+ }
1670
+ }
1671
+ const envVars = core.EnvHelper.envToJson(processEnv, options.envPrefix ?? "");
1672
+ // Expand any environment variables that use the @file: syntax
1673
+ const keys = Object.keys(envVars);
1674
+ for (const key of keys) {
1675
+ if (core.Is.stringValue(envVars[key]) && envVars[key].startsWith("@file:")) {
1676
+ const filePath = envVars[key].slice(6).trim();
1677
+ const embeddedFile = path.resolve(path.join(options.executionDirectory ?? "", filePath));
1678
+ console.info(`Expanding Environment Variable: ${key} from file: ${embeddedFile}`);
1679
+ const fileContent = await loadJsonFile(embeddedFile);
1680
+ envVars[key] = fileContent;
1681
+ }
1682
+ }
1683
+ // Extend the environment variables with any additional custom configuration.
1684
+ if (core.Is.function(options?.extendEnvVars)) {
1685
+ console.info("Extending Environment Variables");
1686
+ await options.extendEnvVars(envVars);
1687
+ }
1688
+ // Build the engine configuration from the environment variables.
1689
+ const coreConfig = buildEngineConfiguration(envVars);
1690
+ const engineServerConfig = buildEngineServerConfiguration(envVars, coreConfig, serverInfo, options?.openApiSpecFile);
1691
+ // Merge any custom configuration provided in the options.
1692
+ if (core.Is.arrayValue(options?.configFilenames)) {
1693
+ for (const configFile of options.configFilenames) {
1694
+ console.info("Loading Configuration File:", configFile);
1695
+ const configFilePath = path.resolve(path.join(options.executionDirectory ?? "", configFile));
1696
+ const config = await loadJsonFile(configFilePath);
1697
+ Object.assign(engineServerConfig, config);
1698
+ }
1699
+ }
1700
+ if (core.Is.objectValue(options?.config)) {
1701
+ console.info("Merging Custom Configuration");
1702
+ Object.assign(engineServerConfig, options.config);
1703
+ }
1704
+ // Merge any custom configuration provided in the options.
1705
+ if (core.Is.function(options?.extendConfig)) {
1706
+ console.info("Extending Configuration");
1707
+ await options.extendConfig(engineServerConfig);
1708
+ }
1709
+ return { engineServerConfig, nodeEnvVars: envVars };
1710
+ }
627
1711
 
628
1712
  exports.NodeFeatures = NodeFeatures;
629
1713
  exports.bootstrap = bootstrap;
@@ -633,9 +1717,12 @@ exports.bootstrapBlobEncryption = bootstrapBlobEncryption;
633
1717
  exports.bootstrapImmutableProofMethod = bootstrapImmutableProofMethod;
634
1718
  exports.bootstrapNodeIdentity = bootstrapNodeIdentity;
635
1719
  exports.bootstrapNodeUser = bootstrapNodeUser;
1720
+ exports.buildConfiguration = buildConfiguration;
1721
+ exports.buildEngineConfiguration = buildEngineConfiguration;
636
1722
  exports.fileExists = fileExists;
637
1723
  exports.getExecutionDirectory = getExecutionDirectory;
638
1724
  exports.getFeatures = getFeatures;
639
1725
  exports.initialiseLocales = initialiseLocales;
1726
+ exports.loadJsonFile = loadJsonFile;
640
1727
  exports.run = run;
641
1728
  exports.start = start;