@twin.org/node-core 0.0.2-next.16 → 0.0.2-next.17

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 (36) hide show
  1. package/dist/cjs/index.cjs +182 -53
  2. package/dist/esm/index.mjs +173 -54
  3. package/dist/types/builders/engineServerEnvBuilder.d.ts +1 -1
  4. package/dist/types/builders/extensionsBuilder.d.ts +31 -0
  5. package/dist/types/defaults.d.ts +6 -0
  6. package/dist/types/index.d.ts +4 -0
  7. package/dist/types/models/IEngineEnvironmentVariables.d.ts +35 -14
  8. package/dist/types/models/INodeEngineConfig.d.ts +6 -0
  9. package/dist/types/models/INodeOptions.d.ts +2 -1
  10. package/dist/types/models/nodeExtensionMethods.d.ts +22 -0
  11. package/dist/types/node.d.ts +2 -2
  12. package/dist/types/server.d.ts +4 -2
  13. package/docs/changelog.md +8 -0
  14. package/docs/reference/functions/buildConfiguration.md +2 -2
  15. package/docs/reference/functions/buildEngineServerConfiguration.md +1 -1
  16. package/docs/reference/functions/extensionsConfiguration.md +25 -0
  17. package/docs/reference/functions/extensionsInitialiseEngine.md +25 -0
  18. package/docs/reference/functions/extensionsInitialiseEngineServer.md +31 -0
  19. package/docs/reference/functions/shutdownExtensions.md +19 -0
  20. package/docs/reference/functions/start.md +4 -4
  21. package/docs/reference/index.md +14 -0
  22. package/docs/reference/interfaces/IEngineEnvironmentVariables.md +73 -22
  23. package/docs/reference/interfaces/IEngineServerEnvironmentVariables.md +101 -30
  24. package/docs/reference/interfaces/INodeEngineConfig.md +7 -0
  25. package/docs/reference/interfaces/INodeEnvironmentVariables.md +101 -30
  26. package/docs/reference/interfaces/INodeOptions.md +6 -2
  27. package/docs/reference/type-aliases/NodeExtensionInitialiseEngineMethod.md +18 -0
  28. package/docs/reference/type-aliases/NodeExtensionInitialiseEngineServerMethod.md +24 -0
  29. package/docs/reference/type-aliases/NodeExtensionInitialiseMethod.md +23 -0
  30. package/docs/reference/variables/ATTESTATION_VERIFICATION_METHOD_ID.md +3 -0
  31. package/docs/reference/variables/AUTH_SIGNING_KEY_ID.md +3 -0
  32. package/docs/reference/variables/BLOB_STORAGE_ENCRYPTION_KEY_ID.md +3 -0
  33. package/docs/reference/variables/IMMUTABLE_PROOF_VERIFICATION_METHOD_ID.md +3 -0
  34. package/docs/reference/variables/SYNCHRONISED_STORAGE_BLOB_STORAGE_ENCRYPTION_KEY_ID.md +3 -0
  35. package/docs/reference/variables/VC_AUTHENTICATION_VERIFICATION_METHOD_ID.md +3 -0
  36. package/package.json +12 -1
@@ -17,6 +17,15 @@ import { Engine } from '@twin.org/engine';
17
17
  import { FileStateStorage } from '@twin.org/engine-core';
18
18
  import { EngineCoreFactory } from '@twin.org/engine-models';
19
19
 
20
+ // Copyright 2024 IOTA Stiftung.
21
+ // SPDX-License-Identifier: Apache-2.0.
22
+ const ATTESTATION_VERIFICATION_METHOD_ID = "attestation-assertion";
23
+ const IMMUTABLE_PROOF_VERIFICATION_METHOD_ID = "immutable-proof-assertion";
24
+ const BLOB_STORAGE_ENCRYPTION_KEY_ID = "blob-encryption";
25
+ const SYNCHRONISED_STORAGE_BLOB_STORAGE_ENCRYPTION_KEY_ID = "synchronised-storage-blob-encryption";
26
+ const VC_AUTHENTICATION_VERIFICATION_METHOD_ID = "node-authentication-assertion";
27
+ const AUTH_SIGNING_KEY_ID = "auth-signing";
28
+
20
29
  // Copyright 2024 IOTA Stiftung.
21
30
  // SPDX-License-Identifier: Apache-2.0.
22
31
  /**
@@ -188,10 +197,16 @@ async function bootstrap(engineCore, context, envVars) {
188
197
  await bootstrapNodeUser(engineCore, context, envVars, features);
189
198
  await bootstrapAuth(engineCore, context, envVars);
190
199
  await bootstrapBlobEncryption(engineCore, context, envVars);
191
- await addVerificationMethod(engineCore, context, "attestation", envVars.attestationVerificationMethodId);
192
- await addVerificationMethod(engineCore, context, "immutable proof", envVars.immutableProofVerificationMethodId);
200
+ const defaultAttestationConnectorType = engineCore.getRegisteredInstanceTypeOptional("attestationConnector");
201
+ if (!Is.empty(defaultAttestationConnectorType)) {
202
+ await addVerificationMethod(engineCore, context, "attestation", envVars.attestationVerificationMethodId ?? ATTESTATION_VERIFICATION_METHOD_ID);
203
+ }
204
+ const defaultImmutableProofComponentType = engineCore.getRegisteredInstanceTypeOptional("immutableProofComponent");
205
+ if (!Is.empty(defaultImmutableProofComponentType)) {
206
+ await addVerificationMethod(engineCore, context, "immutable proof", envVars.immutableProofVerificationMethodId ?? IMMUTABLE_PROOF_VERIFICATION_METHOD_ID);
207
+ }
193
208
  if (Coerce.boolean(envVars.vcAuthenticationEnabled) ?? false) {
194
- await addVerificationMethod(engineCore, context, "verifiable credential authentication", envVars.vcAuthenticationVerificationMethodId);
209
+ await addVerificationMethod(engineCore, context, "verifiable credential authentication", envVars.vcAuthenticationVerificationMethodId ?? VC_AUTHENTICATION_VERIFICATION_METHOD_ID);
195
210
  }
196
211
  await bootstrapSynchronisedStorage(engineCore, context, envVars);
197
212
  }
@@ -467,7 +482,7 @@ async function bootstrapBlobEncryption(engineCore, context, envVars, features) {
467
482
  // Create a new key for encrypting blobs
468
483
  const defaultVaultConnectorType = engineCore.getRegisteredInstanceType("vaultConnector");
469
484
  const vaultConnector = VaultConnectorFactory.get(defaultVaultConnectorType);
470
- const keyName = `${context.state.nodeIdentity}/${envVars.blobStorageEncryptionKeyId}`;
485
+ const keyName = `${context.state.nodeIdentity}/${envVars.blobStorageEncryptionKeyId ?? BLOB_STORAGE_ENCRYPTION_KEY_ID}`;
471
486
  let existingKey;
472
487
  try {
473
488
  existingKey = await vaultConnector.getKey(keyName);
@@ -507,7 +522,7 @@ async function bootstrapAuth(engineCore, context, envVars, features) {
507
522
  // Create a new JWT signing key and a user login for the node
508
523
  const defaultVaultConnectorType = engineCore.getRegisteredInstanceType("vaultConnector");
509
524
  const vaultConnector = VaultConnectorFactory.get(defaultVaultConnectorType);
510
- const keyName = `${context.state.nodeIdentity}/${envVars.authSigningKeyId}`;
525
+ const keyName = `${context.state.nodeIdentity}/${envVars.authSigningKeyId ?? AUTH_SIGNING_KEY_ID}`;
511
526
  let existingKey;
512
527
  try {
513
528
  existingKey = await vaultConnector.getKey(keyName);
@@ -532,11 +547,11 @@ async function bootstrapAuth(engineCore, context, envVars, features) {
532
547
  async function bootstrapSynchronisedStorage(engineCore, context, envVars, features) {
533
548
  if (Coerce.boolean(envVars.synchronisedStorageEnabled) ?? false) {
534
549
  // If this is a trusted node we need to add the blob encryption key pair
535
- if (Is.stringValue(envVars.synchronisedStorageBlobStorageEncryptionKeyId) &&
536
- Is.stringBase64(envVars.synchronisedStorageBlobStorageKey)) {
550
+ if (Is.stringBase64(envVars.synchronisedStorageBlobStorageKey)) {
537
551
  const defaultVaultConnectorType = engineCore.getRegisteredInstanceType("vaultConnector");
538
552
  const vaultConnector = VaultConnectorFactory.get(defaultVaultConnectorType);
539
- const keyName = envVars.synchronisedStorageBlobStorageEncryptionKeyId;
553
+ const keyName = envVars.synchronisedStorageBlobStorageEncryptionKeyId ??
554
+ SYNCHRONISED_STORAGE_BLOB_STORAGE_ENCRYPTION_KEY_ID;
540
555
  let existingKey;
541
556
  try {
542
557
  existingKey = await vaultConnector.getKey(keyName);
@@ -604,12 +619,6 @@ async function buildEngineConfiguration(envVars) {
604
619
  envVars.storageFileRoot = path.resolve(envVars.storageFileRoot);
605
620
  envVars.stateFilename = path.join(envVars.storageFileRoot, envVars.stateFilename);
606
621
  }
607
- envVars.attestationVerificationMethodId ??= "attestation-assertion";
608
- envVars.immutableProofVerificationMethodId ??= "immutable-proof-assertion";
609
- envVars.blobStorageEnableEncryption ??= "false";
610
- envVars.blobStorageEncryptionKeyId ??= "blob-encryption";
611
- envVars.synchronisedStorageBlobStorageEncryptionKeyId ??= "synchronised-storage-blob-encryption";
612
- envVars.vcAuthenticationVerificationMethodId ??= "node-authentication-assertion";
613
622
  const coreConfig = {
614
623
  debug: Coerce.boolean(envVars.debug) ?? false,
615
624
  types: {}
@@ -672,9 +681,10 @@ async function configureEntityStorage(coreConfig, envVars) {
672
681
  options: {
673
682
  config: {
674
683
  region: envVars.awsDynamodbRegion ?? "",
675
- accessKeyId: envVars.awsDynamodbAccessKeyId ?? "",
676
- secretAccessKey: envVars.awsDynamodbSecretAccessKey ?? "",
677
- endpoint: envVars.awsDynamodbEndpoint ?? ""
684
+ authMode: envVars.awsDynamodbAuthMode,
685
+ accessKeyId: envVars.awsDynamodbAccessKeyId,
686
+ secretAccessKey: envVars.awsDynamodbSecretAccessKey,
687
+ endpoint: envVars.awsDynamodbEndpoint
678
688
  },
679
689
  tablePrefix: envVars.entityStorageTablePrefix
680
690
  }
@@ -831,9 +841,10 @@ async function configureBlobStorage(coreConfig, envVars) {
831
841
  config: {
832
842
  region: envVars.awsS3Region ?? "",
833
843
  bucketName: envVars.awsS3BucketName ?? "",
834
- accessKeyId: envVars.awsS3AccessKeyId ?? "",
835
- secretAccessKey: envVars.awsS3SecretAccessKey ?? "",
836
- endpoint: envVars.awsS3Endpoint ?? ""
844
+ authMode: envVars.awsS3AuthMode,
845
+ accessKeyId: envVars.awsS3AccessKeyId,
846
+ secretAccessKey: envVars.awsS3SecretAccessKey,
847
+ endpoint: envVars.awsS3Endpoint
837
848
  },
838
849
  storagePrefix: envVars.blobStoragePrefix
839
850
  }
@@ -890,7 +901,7 @@ async function configureBlobStorage(coreConfig, envVars) {
890
901
  options: {
891
902
  config: {
892
903
  vaultKeyId: (envVars.blobStorageEnableEncryption ?? false)
893
- ? envVars.blobStorageEncryptionKeyId
904
+ ? (envVars.blobStorageEncryptionKeyId ?? BLOB_STORAGE_ENCRYPTION_KEY_ID)
894
905
  : undefined
895
906
  }
896
907
  }
@@ -1030,10 +1041,11 @@ async function configureMessaging(coreConfig, envVars) {
1030
1041
  type: MessagingEmailConnectorType.Aws,
1031
1042
  options: {
1032
1043
  config: {
1033
- region: envVars.awsS3Region ?? "",
1034
- accessKeyId: envVars.awsS3AccessKeyId ?? "",
1035
- secretAccessKey: envVars.awsS3SecretAccessKey ?? "",
1036
- endpoint: envVars.awsS3Endpoint ?? ""
1044
+ region: envVars.awsSesRegion ?? "",
1045
+ authMode: envVars.awsSesAuthMode,
1046
+ accessKeyId: envVars.awsSesAccessKeyId,
1047
+ secretAccessKey: envVars.awsSesSecretAccessKey,
1048
+ endpoint: envVars.awsSesEndpoint
1037
1049
  }
1038
1050
  }
1039
1051
  });
@@ -1048,10 +1060,11 @@ async function configureMessaging(coreConfig, envVars) {
1048
1060
  type: MessagingSmsConnectorType.Aws,
1049
1061
  options: {
1050
1062
  config: {
1051
- region: envVars.awsS3Region ?? "",
1052
- accessKeyId: envVars.awsS3AccessKeyId ?? "",
1053
- secretAccessKey: envVars.awsS3SecretAccessKey ?? "",
1054
- endpoint: envVars.awsS3Endpoint ?? ""
1063
+ region: envVars.awsSesRegion ?? "",
1064
+ authMode: envVars.awsSesAuthMode,
1065
+ accessKeyId: envVars.awsSesAccessKeyId,
1066
+ secretAccessKey: envVars.awsSesSecretAccessKey,
1067
+ endpoint: envVars.awsSesEndpoint
1055
1068
  }
1056
1069
  }
1057
1070
  });
@@ -1068,8 +1081,9 @@ async function configureMessaging(coreConfig, envVars) {
1068
1081
  options: {
1069
1082
  config: {
1070
1083
  region: envVars.awsSesRegion ?? "",
1071
- accessKeyId: envVars.awsSesAccessKeyId ?? "",
1072
- secretAccessKey: envVars.awsSesSecretAccessKey ?? "",
1084
+ authMode: envVars.awsSesAuthMode,
1085
+ accessKeyId: envVars.awsSesAccessKeyId,
1086
+ secretAccessKey: envVars.awsSesSecretAccessKey,
1073
1087
  endpoint: envVars.awsSesEndpoint,
1074
1088
  applicationsSettings: Is.json(envVars.awsMessagingPushNotificationApplications)
1075
1089
  ? JSON.parse(envVars.awsMessagingPushNotificationApplications)
@@ -1199,7 +1213,7 @@ async function configureVerifiableStorage(coreConfig, envVars) {
1199
1213
  type: ImmutableProofComponentType.Service,
1200
1214
  options: {
1201
1215
  config: {
1202
- verificationMethodId: envVars.immutableProofVerificationMethodId
1216
+ verificationMethodId: envVars.immutableProofVerificationMethodId ?? IMMUTABLE_PROOF_VERIFICATION_METHOD_ID
1203
1217
  }
1204
1218
  }
1205
1219
  });
@@ -1304,7 +1318,7 @@ async function configureAttestation(coreConfig, envVars) {
1304
1318
  type: AttestationComponentType.Service,
1305
1319
  options: {
1306
1320
  config: {
1307
- verificationMethodId: envVars.attestationVerificationMethodId
1321
+ verificationMethodId: envVars.attestationVerificationMethodId ?? ATTESTATION_VERIFICATION_METHOD_ID
1308
1322
  }
1309
1323
  }
1310
1324
  });
@@ -1395,7 +1409,9 @@ async function configureVerifiableCredentialAuthentication(coreConfig, envVars)
1395
1409
  coreConfig.types.authenticationGeneratorComponent.push({
1396
1410
  type: AuthenticationGeneratorComponentType.VerifiableCredential,
1397
1411
  options: {
1398
- config: { verificationMethodId: envVars.vcAuthenticationVerificationMethodId ?? "" }
1412
+ config: {
1413
+ verificationMethodId: envVars.vcAuthenticationVerificationMethodId ?? VC_AUTHENTICATION_VERIFICATION_METHOD_ID
1414
+ }
1399
1415
  },
1400
1416
  features: ["verifiable-credential"]
1401
1417
  });
@@ -1523,7 +1539,8 @@ async function configureSynchronisedStorage(coreConfig, envVars) {
1523
1539
  options: {
1524
1540
  config: {
1525
1541
  verifiableStorageKeyId: verifiableStorageKeyId ?? "",
1526
- blobStorageEncryptionKeyId: envVars.synchronisedStorageBlobStorageEncryptionKeyId,
1542
+ blobStorageEncryptionKeyId: envVars.synchronisedStorageBlobStorageEncryptionKeyId ??
1543
+ SYNCHRONISED_STORAGE_BLOB_STORAGE_ENCRYPTION_KEY_ID,
1527
1544
  entityUpdateIntervalMinutes: Coerce.number(envVars.synchronisedStorageEntityUpdateIntervalMinutes),
1528
1545
  consolidationIntervalMinutes: Coerce.number(envVars.synchronisedStorageConsolidationIntervalMinutes),
1529
1546
  consolidationBatchSize: Coerce.number(envVars.synchronisedStorageConsolidationBatchSize),
@@ -1576,9 +1593,8 @@ async function configureDataSpaceConnector(coreConfig, envVars) {
1576
1593
  type: DataSpaceConnectorComponentType.Service,
1577
1594
  options: {
1578
1595
  config: {
1579
- dataSpaceConnectorAppDescriptors: Is.arrayValue(envVars.dataSpaceConnectorApps)
1580
- ? envVars.dataSpaceConnectorApps
1581
- : undefined
1596
+ retainActivityLogsFor: Coerce.number(envVars.dataSpaceConnectorRetainActivityLogsFor),
1597
+ activityLogsCleanUpInterval: Coerce.number(envVars.dataSpaceConnectorActivityLogsCleanUpInterval)
1582
1598
  }
1583
1599
  }
1584
1600
  });
@@ -1624,10 +1640,9 @@ async function configureDlt(coreConfig, envVars) {
1624
1640
  * @param serverInfo The server information.
1625
1641
  * @param openApiSpecPath The path to the open api spec.
1626
1642
  * @param favIconPath The path to the favicon.
1627
- * @returns The the config for the core and the server.
1643
+ * @returns The config for the core and the server.
1628
1644
  */
1629
1645
  async function buildEngineServerConfiguration(envVars, coreEngineConfig, serverInfo, openApiSpecPath, favIconPath) {
1630
- envVars.authSigningKeyId ??= "auth-signing";
1631
1646
  const webServerOptions = {
1632
1647
  port: Coerce.number(envVars.port),
1633
1648
  host: Coerce.string(envVars.host),
@@ -1743,7 +1758,7 @@ async function buildEngineServerConfiguration(envVars, coreEngineConfig, serverI
1743
1758
  type: AuthenticationComponentType.EntityStorage,
1744
1759
  options: {
1745
1760
  config: {
1746
- signingKeyName: envVars.authSigningKeyId
1761
+ signingKeyName: envVars.authSigningKeyId ?? AUTH_SIGNING_KEY_ID
1747
1762
  }
1748
1763
  }
1749
1764
  });
@@ -1751,7 +1766,7 @@ async function buildEngineServerConfiguration(envVars, coreEngineConfig, serverI
1751
1766
  type: RestRouteProcessorType.AuthHeader,
1752
1767
  options: {
1753
1768
  config: {
1754
- signingKeyName: envVars.authSigningKeyId
1769
+ signingKeyName: envVars.authSigningKeyId ?? AUTH_SIGNING_KEY_ID
1755
1770
  }
1756
1771
  }
1757
1772
  });
@@ -1759,7 +1774,7 @@ async function buildEngineServerConfiguration(envVars, coreEngineConfig, serverI
1759
1774
  type: SocketRouteProcessorType.AuthHeader,
1760
1775
  options: {
1761
1776
  config: {
1762
- signingKeyName: envVars.authSigningKeyId
1777
+ signingKeyName: envVars.authSigningKeyId ?? AUTH_SIGNING_KEY_ID
1763
1778
  }
1764
1779
  }
1765
1780
  });
@@ -1777,17 +1792,111 @@ async function buildEngineServerConfiguration(envVars, coreEngineConfig, serverI
1777
1792
  return serverConfig;
1778
1793
  }
1779
1794
 
1795
+ // Copyright 2024 IOTA Stiftung.
1796
+ // SPDX-License-Identifier: Apache-2.0.
1797
+ /* eslint-disable no-console */
1798
+ /**
1799
+ * Handles the configuration of the extensions.
1800
+ * @param envVars The environment variables for the node.
1801
+ * @param nodeEngineConfig The node engine config.
1802
+ * @returns The config for the core and the server.
1803
+ */
1804
+ async function extensionsConfiguration(envVars, nodeEngineConfig) {
1805
+ if (Is.stringValue(envVars.extensions)) {
1806
+ const extensions = envVars.extensions.split(",");
1807
+ for (const extension of extensions) {
1808
+ let initialiseConfigMethod;
1809
+ try {
1810
+ console.info(`Loading extension "${extension}"`);
1811
+ initialiseConfigMethod = await ModuleHelper.getModuleMethod(extension, "extensionInitialise");
1812
+ }
1813
+ catch (err) {
1814
+ console.error(`Failed to load extension "${extension}":`, err);
1815
+ }
1816
+ if (Is.function(initialiseConfigMethod)) {
1817
+ await initialiseConfigMethod(envVars, nodeEngineConfig);
1818
+ }
1819
+ }
1820
+ }
1821
+ return nodeEngineConfig;
1822
+ }
1823
+ /**
1824
+ * Handles the initialisation of the extensions when the engine has been constructed.
1825
+ * @param envVars The environment variables for the node.
1826
+ * @param engineCore The engine core instance.
1827
+ * @returns Nothing.
1828
+ */
1829
+ async function extensionsInitialiseEngine(envVars, engineCore) {
1830
+ if (Is.stringValue(envVars.extensions)) {
1831
+ const extensions = envVars.extensions.split(",");
1832
+ for (const extension of extensions) {
1833
+ let initialiseEngineMethod;
1834
+ try {
1835
+ initialiseEngineMethod =
1836
+ await ModuleHelper.getModuleMethod(extension, "extensionInitialiseEngine");
1837
+ }
1838
+ catch { }
1839
+ if (Is.function(initialiseEngineMethod)) {
1840
+ await initialiseEngineMethod(engineCore);
1841
+ }
1842
+ }
1843
+ }
1844
+ }
1845
+ /**
1846
+ * Handles the initialisation of the extensions when the engine server has been constructed.
1847
+ * @param envVars The environment variables for the node.
1848
+ * @param engineCore The engine core instance.
1849
+ * @param engineServer The engine server instance.
1850
+ * @returns Nothing.
1851
+ */
1852
+ async function extensionsInitialiseEngineServer(envVars, engineCore, engineServer) {
1853
+ if (Is.stringValue(envVars.extensions)) {
1854
+ const extensions = envVars.extensions.split(",");
1855
+ for (const extension of extensions) {
1856
+ let initialiseEngineServerMethod;
1857
+ try {
1858
+ initialiseEngineServerMethod =
1859
+ await ModuleHelper.getModuleMethod(extension, "extensionInitialiseEngineServer");
1860
+ }
1861
+ catch { }
1862
+ if (Is.function(initialiseEngineServerMethod)) {
1863
+ await initialiseEngineServerMethod(engineCore, engineServer);
1864
+ }
1865
+ }
1866
+ }
1867
+ }
1868
+ /**
1869
+ * Handles the shutdown of the extensions.
1870
+ * @param envVars The environment variables for the node.
1871
+ * @returns Nothing.
1872
+ */
1873
+ async function shutdownExtensions(envVars) {
1874
+ if (Is.stringValue(envVars.extensions)) {
1875
+ const extensions = envVars.extensions.split(",");
1876
+ for (const extension of extensions) {
1877
+ let shutdownMethod;
1878
+ try {
1879
+ shutdownMethod = await ModuleHelper.getModuleMethod(extension, "extensionShutdown");
1880
+ }
1881
+ catch { }
1882
+ if (Is.function(shutdownMethod)) {
1883
+ await shutdownMethod();
1884
+ }
1885
+ }
1886
+ }
1887
+ }
1888
+
1780
1889
  // Copyright 2024 IOTA Stiftung.
1781
1890
  // SPDX-License-Identifier: Apache-2.0.
1782
1891
  /* eslint-disable no-console */
1783
1892
  /**
1784
1893
  * Start the engine server.
1785
1894
  * @param nodeOptions Optional run options for the engine server.
1786
- * @param engineServerConfig The configuration for the engine server.
1895
+ * @param nodeEngineConfig The configuration for the engine server.
1787
1896
  * @param envVars The environment variables.
1788
1897
  * @returns The engine server.
1789
1898
  */
1790
- async function start(nodeOptions, engineServerConfig, envVars) {
1899
+ async function start(nodeOptions, nodeEngineConfig, envVars) {
1791
1900
  const entityStorageConnectorType = envVars.entityStorageConnectorType?.split(",") ?? [];
1792
1901
  const blobStorageConnectorType = envVars.blobStorageConnectorType?.split(",") ?? [];
1793
1902
  // If the blob storage or entity storage is configured with file connectors
@@ -1802,7 +1911,7 @@ async function start(nodeOptions, engineServerConfig, envVars) {
1802
1911
  }
1803
1912
  // Create the engine instance using file state storage unless one is configured in options
1804
1913
  const engine = new Engine({
1805
- config: engineServerConfig,
1914
+ config: nodeEngineConfig,
1806
1915
  stateStorage: nodeOptions?.stateStorage ?? new FileStateStorage(envVars.stateFilename ?? ""),
1807
1916
  customBootstrap: async (core, engineContext) => bootstrap(core, engineContext, envVars)
1808
1917
  });
@@ -1813,11 +1922,13 @@ async function start(nodeOptions, engineServerConfig, envVars) {
1813
1922
  console.info("Extending Engine");
1814
1923
  await nodeOptions.extendEngine(engine);
1815
1924
  }
1925
+ await extensionsInitialiseEngine(envVars, engine);
1816
1926
  // Extend the engine server.
1817
1927
  if (Is.function(nodeOptions?.extendEngineServer)) {
1818
1928
  console.info("Extending Engine Server");
1819
1929
  await nodeOptions?.extendEngineServer(server);
1820
1930
  }
1931
+ await extensionsInitialiseEngineServer(envVars, engine, server);
1821
1932
  // Need to register the engine with the factory so that background tasks
1822
1933
  // can clone it to spawn new instances.
1823
1934
  EngineCoreFactory.register("engine", () => engine);
@@ -1826,7 +1937,11 @@ async function start(nodeOptions, engineServerConfig, envVars) {
1826
1937
  if (canContinue) {
1827
1938
  return {
1828
1939
  engine,
1829
- server
1940
+ server,
1941
+ shutdown: async () => {
1942
+ await server.stop();
1943
+ await shutdownExtensions(envVars);
1944
+ }
1830
1945
  };
1831
1946
  }
1832
1947
  }
@@ -1844,7 +1959,7 @@ async function run(nodeOptions) {
1844
1959
  nodeOptions ??= {};
1845
1960
  const serverInfo = {
1846
1961
  name: nodeOptions?.serverName ?? "TWIN Node Server",
1847
- version: nodeOptions?.serverVersion ?? "0.0.2-next.16" // x-release-please-version
1962
+ version: nodeOptions?.serverVersion ?? "0.0.2-next.17" // x-release-please-version
1848
1963
  };
1849
1964
  console.log(`\u001B[4m🌩️ ${serverInfo.name} v${serverInfo.version}\u001B[24m\n`);
1850
1965
  if (!Is.stringValue(nodeOptions?.executionDirectory)) {
@@ -1875,13 +1990,16 @@ async function run(nodeOptions) {
1875
1990
  nodeOptions.envPrefix ??= "TWIN_NODE_";
1876
1991
  console.info("Environment Prefix:", nodeOptions.envPrefix);
1877
1992
  overrideModuleImport(nodeOptions.executionDirectory ?? "");
1878
- const { engineServerConfig, nodeEnvVars: envVars } = await buildConfiguration(process.env, nodeOptions, serverInfo);
1993
+ const { nodeEngineConfig, nodeEnvVars: envVars } = await buildConfiguration(
1994
+ // This is the only location in the code base that should access process.env directly
1995
+ // eslint-disable-next-line no-restricted-syntax
1996
+ process.env, nodeOptions, serverInfo);
1879
1997
  console.info();
1880
- const startResult = await start(nodeOptions, engineServerConfig, envVars);
1998
+ const startResult = await start(nodeOptions, nodeEngineConfig, envVars);
1881
1999
  if (!Is.empty(startResult)) {
1882
2000
  for (const signal of ["SIGHUP", "SIGINT", "SIGTERM"]) {
1883
2001
  process.on(signal, async () => {
1884
- await startResult.server.stop();
2002
+ await startResult.shutdown();
1885
2003
  });
1886
2004
  }
1887
2005
  }
@@ -1965,9 +2083,10 @@ async function buildConfiguration(processEnv, options, serverInfo) {
1965
2083
  // Merge any custom configuration provided in the options.
1966
2084
  if (Is.function(options?.extendConfig)) {
1967
2085
  console.info("Extending Configuration");
1968
- await options.extendConfig(engineServerConfig);
2086
+ await options.extendConfig(envVars, engineServerConfig);
1969
2087
  }
1970
- return { engineServerConfig, nodeEnvVars: envVars };
2088
+ const nodeEngineConfig = await extensionsConfiguration(envVars, engineServerConfig);
2089
+ return { nodeEngineConfig, nodeEnvVars: envVars };
1971
2090
  }
1972
2091
  /**
1973
2092
  * Override module imports to use local files where possible.
@@ -2004,4 +2123,4 @@ function overrideModuleImport(executionDirectory) {
2004
2123
  });
2005
2124
  }
2006
2125
 
2007
- export { NodeFeatures, bootstrap, bootstrapAuth, bootstrapBlobEncryption, bootstrapImmutableProofMethod, bootstrapNodeIdentity, bootstrapNodeUser, bootstrapSynchronisedStorage, buildConfiguration, buildEngineConfiguration, buildEngineServerConfiguration, directoryExists, fileExists, getExecutionDirectory, getFeatures, getFiles, getSubFolders, initialiseLocales, loadJsonFile, loadTextFile, overrideModuleImport, run, start };
2126
+ export { ATTESTATION_VERIFICATION_METHOD_ID, AUTH_SIGNING_KEY_ID, BLOB_STORAGE_ENCRYPTION_KEY_ID, IMMUTABLE_PROOF_VERIFICATION_METHOD_ID, NodeFeatures, SYNCHRONISED_STORAGE_BLOB_STORAGE_ENCRYPTION_KEY_ID, VC_AUTHENTICATION_VERIFICATION_METHOD_ID, bootstrap, bootstrapAuth, bootstrapBlobEncryption, bootstrapImmutableProofMethod, bootstrapNodeIdentity, bootstrapNodeUser, bootstrapSynchronisedStorage, buildConfiguration, buildEngineConfiguration, buildEngineServerConfiguration, directoryExists, extensionsConfiguration, extensionsInitialiseEngine, extensionsInitialiseEngineServer, fileExists, getExecutionDirectory, getFeatures, getFiles, getSubFolders, initialiseLocales, loadJsonFile, loadTextFile, overrideModuleImport, run, shutdownExtensions, start };
@@ -9,6 +9,6 @@ import type { IEngineServerEnvironmentVariables } from "../models/IEngineServerE
9
9
  * @param serverInfo The server information.
10
10
  * @param openApiSpecPath The path to the open api spec.
11
11
  * @param favIconPath The path to the favicon.
12
- * @returns The the config for the core and the server.
12
+ * @returns The config for the core and the server.
13
13
  */
14
14
  export declare function buildEngineServerConfiguration(envVars: IEngineServerEnvironmentVariables, coreEngineConfig: IEngineCoreConfig, serverInfo: IServerInfo, openApiSpecPath?: string, favIconPath?: string): Promise<IEngineServerConfig>;
@@ -0,0 +1,31 @@
1
+ import type { IEngineCore, IEngineServer } from "@twin.org/engine-models";
2
+ import type { INodeEngineConfig } from "../models/INodeEngineConfig";
3
+ import type { INodeEnvironmentVariables } from "../models/INodeEnvironmentVariables";
4
+ /**
5
+ * Handles the configuration of the extensions.
6
+ * @param envVars The environment variables for the node.
7
+ * @param nodeEngineConfig The node engine config.
8
+ * @returns The config for the core and the server.
9
+ */
10
+ export declare function extensionsConfiguration(envVars: INodeEnvironmentVariables, nodeEngineConfig: INodeEngineConfig): Promise<INodeEngineConfig>;
11
+ /**
12
+ * Handles the initialisation of the extensions when the engine has been constructed.
13
+ * @param envVars The environment variables for the node.
14
+ * @param engineCore The engine core instance.
15
+ * @returns Nothing.
16
+ */
17
+ export declare function extensionsInitialiseEngine(envVars: INodeEnvironmentVariables, engineCore: IEngineCore): Promise<void>;
18
+ /**
19
+ * Handles the initialisation of the extensions when the engine server has been constructed.
20
+ * @param envVars The environment variables for the node.
21
+ * @param engineCore The engine core instance.
22
+ * @param engineServer The engine server instance.
23
+ * @returns Nothing.
24
+ */
25
+ export declare function extensionsInitialiseEngineServer(envVars: INodeEnvironmentVariables, engineCore: IEngineCore, engineServer: IEngineServer): Promise<void>;
26
+ /**
27
+ * Handles the shutdown of the extensions.
28
+ * @param envVars The environment variables for the node.
29
+ * @returns Nothing.
30
+ */
31
+ export declare function shutdownExtensions(envVars: INodeEnvironmentVariables): Promise<void>;
@@ -0,0 +1,6 @@
1
+ export declare const ATTESTATION_VERIFICATION_METHOD_ID = "attestation-assertion";
2
+ export declare const IMMUTABLE_PROOF_VERIFICATION_METHOD_ID = "immutable-proof-assertion";
3
+ export declare const BLOB_STORAGE_ENCRYPTION_KEY_ID = "blob-encryption";
4
+ export declare const SYNCHRONISED_STORAGE_BLOB_STORAGE_ENCRYPTION_KEY_ID = "synchronised-storage-blob-encryption";
5
+ export declare const VC_AUTHENTICATION_VERIFICATION_METHOD_ID = "node-authentication-assertion";
6
+ export declare const AUTH_SIGNING_KEY_ID = "auth-signing";
@@ -1,10 +1,14 @@
1
1
  export * from "./bootstrap";
2
2
  export * from "./builders/engineEnvBuilder";
3
3
  export * from "./builders/engineServerEnvBuilder";
4
+ export * from "./builders/extensionsBuilder";
5
+ export * from "./defaults";
4
6
  export * from "./models/IEngineEnvironmentVariables";
5
7
  export * from "./models/IEngineServerEnvironmentVariables";
8
+ export * from "./models/INodeEngineConfig";
6
9
  export * from "./models/INodeEnvironmentVariables";
7
10
  export * from "./models/INodeOptions";
11
+ export * from "./models/nodeExtensionMethods";
8
12
  export * from "./models/nodeFeatures";
9
13
  export * from "./node";
10
14
  export * from "./server";
@@ -27,6 +27,10 @@ export interface IEngineEnvironmentVariables {
27
27
  * A prefix for all the table in entity-storage, can be empty.
28
28
  */
29
29
  entityStorageTablePrefix?: string;
30
+ /**
31
+ * AWS DynamoDB auth mode, either credentials or pod.
32
+ */
33
+ awsDynamodbAuthMode?: string;
30
34
  /**
31
35
  * AWS Dynamo DB access key id.
32
36
  */
@@ -194,25 +198,29 @@ export interface IEngineEnvironmentVariables {
194
198
  */
195
199
  blobStoragePrefix?: string;
196
200
  /**
197
- * AWS S3 access key id.
201
+ * AWS S3 region.
198
202
  */
199
- awsS3AccessKeyId?: string;
203
+ awsS3Region?: string;
200
204
  /**
201
205
  * AWS S3 bucket name.
202
206
  */
203
207
  awsS3BucketName?: string;
204
208
  /**
205
- * AWS S3 endpoint.
209
+ * AWS S3 auth mode, either credentials or pod, defaults to credentials.
206
210
  */
207
- awsS3Endpoint?: string;
211
+ awsS3AuthMode?: string;
208
212
  /**
209
- * AWS S3 region.
213
+ * AWS S3 access key id.
210
214
  */
211
- awsS3Region?: string;
215
+ awsS3AccessKeyId?: string;
212
216
  /**
213
217
  * AWS S3 secret access key.
214
218
  */
215
219
  awsS3SecretAccessKey?: string;
220
+ /**
221
+ * AWS S3 endpoint.
222
+ */
223
+ awsS3Endpoint?: string;
216
224
  /**
217
225
  * Azure Storage account key.
218
226
  */
@@ -282,6 +290,14 @@ export interface IEngineEnvironmentVariables {
282
290
  * Use the @json: prefix to specify the path to the JSON file.
283
291
  */
284
292
  messagingTemplates?: string;
293
+ /**
294
+ * AWS SES region.
295
+ */
296
+ awsSesRegion?: string;
297
+ /**
298
+ * AWS SES auth mode, either credentials or pod, defaults to credentials.
299
+ */
300
+ awsSesAuthMode?: string;
285
301
  /**
286
302
  * AWS SES secret access key.
287
303
  */
@@ -290,10 +306,6 @@ export interface IEngineEnvironmentVariables {
290
306
  * AWS SES access key id.
291
307
  */
292
308
  awsSesAccessKeyId?: string;
293
- /**
294
- * AWS SES region.
295
- */
296
- awsSesRegion?: string;
297
309
  /**
298
310
  * AWS SES endpoint.
299
311
  */
@@ -424,7 +436,7 @@ export interface IEngineEnvironmentVariables {
424
436
  synchronisedStorageTrustedUrl?: string;
425
437
  /**
426
438
  * The key for the smart contract which contains the verifiable storage pointer store for synchronised storage.
427
- * This only required if using a custom verifiable storage item, otherwise it will default the the network name.
439
+ * This only required if using a custom verifiable storage item, otherwise it will default to the network name.
428
440
  */
429
441
  synchronisedStorageVerifiableStorageKeyId?: string;
430
442
  /**
@@ -522,10 +534,15 @@ export interface IEngineEnvironmentVariables {
522
534
  */
523
535
  dataSpaceConnectorEnabled?: string;
524
536
  /**
525
- * The application configuration for the data space connector.
526
- * Use the @json: prefix to specify the path to the JSON configuration file.
537
+ * The length of time to retain the activity logs for in minutes, set to -1 to keep forever.
538
+ * @default 10
539
+ */
540
+ dataSpaceConnectorRetainActivityLogsFor?: string;
541
+ /**
542
+ * The interval for cleaning up the activity logs.
543
+ * @default 60
527
544
  */
528
- dataSpaceConnectorApps?: string;
545
+ dataSpaceConnectorActivityLogsCleanUpInterval?: string;
529
546
  /**
530
547
  * Enable verifiable credential authentication for the API.
531
548
  */
@@ -535,4 +552,8 @@ export interface IEngineEnvironmentVariables {
535
552
  * Defaults to node-authentication-assertion.
536
553
  */
537
554
  vcAuthenticationVerificationMethodId?: string;
555
+ /**
556
+ * A comma separated list of additional node extensions to load, the initialiseExtension method will be called for each extension.
557
+ */
558
+ extensions?: string;
538
559
  }
@@ -0,0 +1,6 @@
1
+ import type { IEngineServerConfig } from "@twin.org/engine-server-types";
2
+ /**
3
+ * The config for the node.
4
+ */
5
+ export interface INodeEngineConfig extends IEngineServerConfig {
6
+ }
@@ -1,5 +1,6 @@
1
1
  import type { IEngineCore, IEngineServer, IEngineStateStorage } from "@twin.org/engine-models";
2
2
  import type { IEngineConfig } from "@twin.org/engine-types";
3
+ import type { INodeEngineConfig } from "./INodeEngineConfig";
3
4
  import type { INodeEnvironmentVariables } from "./INodeEnvironmentVariables";
4
5
  /**
5
6
  * The options when running the node.
@@ -56,7 +57,7 @@ export interface INodeOptions {
56
57
  /**
57
58
  * Method to extend the engine configuration with any additional custom configuration.
58
59
  */
59
- extendConfig?: (config: IEngineConfig) => Promise<void>;
60
+ extendConfig?: (envVars: INodeEnvironmentVariables, config: INodeEngineConfig) => Promise<void>;
60
61
  /**
61
62
  * Method to extend the engine with any additional options.
62
63
  */