@twin.org/node-core 0.0.2-next.16 → 0.0.2-next.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/index.cjs +211 -75
- package/dist/esm/index.mjs +203 -77
- package/dist/types/builders/engineServerEnvBuilder.d.ts +1 -1
- package/dist/types/builders/extensionsBuilder.d.ts +32 -0
- package/dist/types/defaults.d.ts +6 -0
- package/dist/types/index.d.ts +4 -0
- package/dist/types/models/IEngineEnvironmentVariables.d.ts +35 -14
- package/dist/types/models/INodeEngineConfig.d.ts +6 -0
- package/dist/types/models/INodeOptions.d.ts +2 -1
- package/dist/types/models/nodeExtensionMethods.d.ts +27 -0
- package/dist/types/node.d.ts +2 -2
- package/dist/types/server.d.ts +4 -2
- package/docs/changelog.md +15 -0
- package/docs/reference/functions/buildConfiguration.md +2 -2
- package/docs/reference/functions/buildEngineServerConfiguration.md +1 -1
- package/docs/reference/functions/extensionsConfiguration.md +25 -0
- package/docs/reference/functions/extensionsInitialiseEngine.md +25 -0
- package/docs/reference/functions/extensionsInitialiseEngineServer.md +31 -0
- package/docs/reference/functions/shutdownExtensions.md +25 -0
- package/docs/reference/functions/start.md +4 -4
- package/docs/reference/index.md +15 -0
- package/docs/reference/interfaces/IEngineEnvironmentVariables.md +73 -22
- package/docs/reference/interfaces/IEngineServerEnvironmentVariables.md +101 -30
- package/docs/reference/interfaces/INodeEngineConfig.md +7 -0
- package/docs/reference/interfaces/INodeEnvironmentVariables.md +101 -30
- package/docs/reference/interfaces/INodeOptions.md +6 -2
- package/docs/reference/type-aliases/NodeExtensionInitialiseEngineMethod.md +18 -0
- package/docs/reference/type-aliases/NodeExtensionInitialiseEngineServerMethod.md +24 -0
- package/docs/reference/type-aliases/NodeExtensionInitialiseMethod.md +23 -0
- package/docs/reference/type-aliases/NodeExtensionShutdownMethod.md +10 -0
- package/docs/reference/variables/ATTESTATION_VERIFICATION_METHOD_ID.md +3 -0
- package/docs/reference/variables/AUTH_SIGNING_KEY_ID.md +3 -0
- package/docs/reference/variables/BLOB_STORAGE_ENCRYPTION_KEY_ID.md +3 -0
- package/docs/reference/variables/IMMUTABLE_PROOF_VERIFICATION_METHOD_ID.md +3 -0
- package/docs/reference/variables/SYNCHRONISED_STORAGE_BLOB_STORAGE_ENCRYPTION_KEY_ID.md +3 -0
- package/docs/reference/variables/VC_AUTHENTICATION_VERIFICATION_METHOD_ID.md +3 -0
- package/locales/en.json +9 -2
- package/package.json +13 -1
package/dist/cjs/index.cjs
CHANGED
|
@@ -11,6 +11,7 @@ var vaultModels = require('@twin.org/vault-models');
|
|
|
11
11
|
var walletModels = require('@twin.org/wallet-models');
|
|
12
12
|
var promises = require('node:fs/promises');
|
|
13
13
|
var path = require('node:path');
|
|
14
|
+
var cliCore = require('@twin.org/cli-core');
|
|
14
15
|
var rightsManagementRestClient = require('@twin.org/rights-management-rest-client');
|
|
15
16
|
var engineServer = require('@twin.org/engine-server');
|
|
16
17
|
var modules = require('@twin.org/modules');
|
|
@@ -38,6 +39,15 @@ function _interopNamespaceDefault(e) {
|
|
|
38
39
|
|
|
39
40
|
var dotenv__namespace = /*#__PURE__*/_interopNamespaceDefault(dotenv);
|
|
40
41
|
|
|
42
|
+
// Copyright 2024 IOTA Stiftung.
|
|
43
|
+
// SPDX-License-Identifier: Apache-2.0.
|
|
44
|
+
const ATTESTATION_VERIFICATION_METHOD_ID = "attestation-assertion";
|
|
45
|
+
const IMMUTABLE_PROOF_VERIFICATION_METHOD_ID = "immutable-proof-assertion";
|
|
46
|
+
const BLOB_STORAGE_ENCRYPTION_KEY_ID = "blob-encryption";
|
|
47
|
+
const SYNCHRONISED_STORAGE_BLOB_STORAGE_ENCRYPTION_KEY_ID = "synchronised-storage-blob-encryption";
|
|
48
|
+
const VC_AUTHENTICATION_VERIFICATION_METHOD_ID = "node-authentication-assertion";
|
|
49
|
+
const AUTH_SIGNING_KEY_ID = "auth-signing";
|
|
50
|
+
|
|
41
51
|
// Copyright 2024 IOTA Stiftung.
|
|
42
52
|
// SPDX-License-Identifier: Apache-2.0.
|
|
43
53
|
/**
|
|
@@ -61,20 +71,19 @@ const NodeFeatures = {
|
|
|
61
71
|
|
|
62
72
|
// Copyright 2024 IOTA Stiftung.
|
|
63
73
|
// SPDX-License-Identifier: Apache-2.0.
|
|
64
|
-
/* eslint-disable no-console */
|
|
65
74
|
/**
|
|
66
75
|
* Initialise the locales for the application.
|
|
67
76
|
* @param localesDirectory The directory containing the locales.
|
|
68
77
|
*/
|
|
69
78
|
async function initialiseLocales(localesDirectory) {
|
|
70
79
|
const localesFile = path.resolve(path.join(localesDirectory, "en.json"));
|
|
71
|
-
|
|
80
|
+
cliCore.CLIDisplay.value("Locales File", localesFile);
|
|
72
81
|
if (await fileExists(localesFile)) {
|
|
73
82
|
const enLangContent = await promises.readFile(localesFile, "utf8");
|
|
74
83
|
core.I18n.addDictionary("en", JSON.parse(enLangContent));
|
|
75
84
|
}
|
|
76
85
|
else {
|
|
77
|
-
|
|
86
|
+
cliCore.CLIDisplay.error(`Locales file not found: ${localesFile}`);
|
|
78
87
|
}
|
|
79
88
|
}
|
|
80
89
|
/**
|
|
@@ -209,10 +218,16 @@ async function bootstrap(engineCore, context, envVars) {
|
|
|
209
218
|
await bootstrapNodeUser(engineCore, context, envVars, features);
|
|
210
219
|
await bootstrapAuth(engineCore, context, envVars);
|
|
211
220
|
await bootstrapBlobEncryption(engineCore, context, envVars);
|
|
212
|
-
|
|
213
|
-
|
|
221
|
+
const defaultAttestationConnectorType = engineCore.getRegisteredInstanceTypeOptional("attestationConnector");
|
|
222
|
+
if (!core.Is.empty(defaultAttestationConnectorType)) {
|
|
223
|
+
await addVerificationMethod(engineCore, context, "attestation", envVars.attestationVerificationMethodId ?? ATTESTATION_VERIFICATION_METHOD_ID);
|
|
224
|
+
}
|
|
225
|
+
const defaultImmutableProofComponentType = engineCore.getRegisteredInstanceTypeOptional("immutableProofComponent");
|
|
226
|
+
if (!core.Is.empty(defaultImmutableProofComponentType)) {
|
|
227
|
+
await addVerificationMethod(engineCore, context, "immutable proof", envVars.immutableProofVerificationMethodId ?? IMMUTABLE_PROOF_VERIFICATION_METHOD_ID);
|
|
228
|
+
}
|
|
214
229
|
if (core.Coerce.boolean(envVars.vcAuthenticationEnabled) ?? false) {
|
|
215
|
-
await addVerificationMethod(engineCore, context, "verifiable credential authentication", envVars.vcAuthenticationVerificationMethodId);
|
|
230
|
+
await addVerificationMethod(engineCore, context, "verifiable credential authentication", envVars.vcAuthenticationVerificationMethodId ?? VC_AUTHENTICATION_VERIFICATION_METHOD_ID);
|
|
216
231
|
}
|
|
217
232
|
await bootstrapSynchronisedStorage(engineCore, context, envVars);
|
|
218
233
|
}
|
|
@@ -488,7 +503,7 @@ async function bootstrapBlobEncryption(engineCore, context, envVars, features) {
|
|
|
488
503
|
// Create a new key for encrypting blobs
|
|
489
504
|
const defaultVaultConnectorType = engineCore.getRegisteredInstanceType("vaultConnector");
|
|
490
505
|
const vaultConnector = vaultModels.VaultConnectorFactory.get(defaultVaultConnectorType);
|
|
491
|
-
const keyName = `${context.state.nodeIdentity}/${envVars.blobStorageEncryptionKeyId}`;
|
|
506
|
+
const keyName = `${context.state.nodeIdentity}/${envVars.blobStorageEncryptionKeyId ?? BLOB_STORAGE_ENCRYPTION_KEY_ID}`;
|
|
492
507
|
let existingKey;
|
|
493
508
|
try {
|
|
494
509
|
existingKey = await vaultConnector.getKey(keyName);
|
|
@@ -528,7 +543,7 @@ async function bootstrapAuth(engineCore, context, envVars, features) {
|
|
|
528
543
|
// Create a new JWT signing key and a user login for the node
|
|
529
544
|
const defaultVaultConnectorType = engineCore.getRegisteredInstanceType("vaultConnector");
|
|
530
545
|
const vaultConnector = vaultModels.VaultConnectorFactory.get(defaultVaultConnectorType);
|
|
531
|
-
const keyName = `${context.state.nodeIdentity}/${envVars.authSigningKeyId}`;
|
|
546
|
+
const keyName = `${context.state.nodeIdentity}/${envVars.authSigningKeyId ?? AUTH_SIGNING_KEY_ID}`;
|
|
532
547
|
let existingKey;
|
|
533
548
|
try {
|
|
534
549
|
existingKey = await vaultConnector.getKey(keyName);
|
|
@@ -553,11 +568,11 @@ async function bootstrapAuth(engineCore, context, envVars, features) {
|
|
|
553
568
|
async function bootstrapSynchronisedStorage(engineCore, context, envVars, features) {
|
|
554
569
|
if (core.Coerce.boolean(envVars.synchronisedStorageEnabled) ?? false) {
|
|
555
570
|
// If this is a trusted node we need to add the blob encryption key pair
|
|
556
|
-
if (core.Is.
|
|
557
|
-
core.Is.stringBase64(envVars.synchronisedStorageBlobStorageKey)) {
|
|
571
|
+
if (core.Is.stringBase64(envVars.synchronisedStorageBlobStorageKey)) {
|
|
558
572
|
const defaultVaultConnectorType = engineCore.getRegisteredInstanceType("vaultConnector");
|
|
559
573
|
const vaultConnector = vaultModels.VaultConnectorFactory.get(defaultVaultConnectorType);
|
|
560
|
-
const keyName = envVars.synchronisedStorageBlobStorageEncryptionKeyId
|
|
574
|
+
const keyName = envVars.synchronisedStorageBlobStorageEncryptionKeyId ??
|
|
575
|
+
SYNCHRONISED_STORAGE_BLOB_STORAGE_ENCRYPTION_KEY_ID;
|
|
561
576
|
let existingKey;
|
|
562
577
|
try {
|
|
563
578
|
existingKey = await vaultConnector.getKey(keyName);
|
|
@@ -625,12 +640,6 @@ async function buildEngineConfiguration(envVars) {
|
|
|
625
640
|
envVars.storageFileRoot = path.resolve(envVars.storageFileRoot);
|
|
626
641
|
envVars.stateFilename = path.join(envVars.storageFileRoot, envVars.stateFilename);
|
|
627
642
|
}
|
|
628
|
-
envVars.attestationVerificationMethodId ??= "attestation-assertion";
|
|
629
|
-
envVars.immutableProofVerificationMethodId ??= "immutable-proof-assertion";
|
|
630
|
-
envVars.blobStorageEnableEncryption ??= "false";
|
|
631
|
-
envVars.blobStorageEncryptionKeyId ??= "blob-encryption";
|
|
632
|
-
envVars.synchronisedStorageBlobStorageEncryptionKeyId ??= "synchronised-storage-blob-encryption";
|
|
633
|
-
envVars.vcAuthenticationVerificationMethodId ??= "node-authentication-assertion";
|
|
634
643
|
const coreConfig = {
|
|
635
644
|
debug: core.Coerce.boolean(envVars.debug) ?? false,
|
|
636
645
|
types: {}
|
|
@@ -693,9 +702,10 @@ async function configureEntityStorage(coreConfig, envVars) {
|
|
|
693
702
|
options: {
|
|
694
703
|
config: {
|
|
695
704
|
region: envVars.awsDynamodbRegion ?? "",
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
705
|
+
authMode: envVars.awsDynamodbAuthMode,
|
|
706
|
+
accessKeyId: envVars.awsDynamodbAccessKeyId,
|
|
707
|
+
secretAccessKey: envVars.awsDynamodbSecretAccessKey,
|
|
708
|
+
endpoint: envVars.awsDynamodbEndpoint
|
|
699
709
|
},
|
|
700
710
|
tablePrefix: envVars.entityStorageTablePrefix
|
|
701
711
|
}
|
|
@@ -852,9 +862,10 @@ async function configureBlobStorage(coreConfig, envVars) {
|
|
|
852
862
|
config: {
|
|
853
863
|
region: envVars.awsS3Region ?? "",
|
|
854
864
|
bucketName: envVars.awsS3BucketName ?? "",
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
865
|
+
authMode: envVars.awsS3AuthMode,
|
|
866
|
+
accessKeyId: envVars.awsS3AccessKeyId,
|
|
867
|
+
secretAccessKey: envVars.awsS3SecretAccessKey,
|
|
868
|
+
endpoint: envVars.awsS3Endpoint
|
|
858
869
|
},
|
|
859
870
|
storagePrefix: envVars.blobStoragePrefix
|
|
860
871
|
}
|
|
@@ -911,7 +922,7 @@ async function configureBlobStorage(coreConfig, envVars) {
|
|
|
911
922
|
options: {
|
|
912
923
|
config: {
|
|
913
924
|
vaultKeyId: (envVars.blobStorageEnableEncryption ?? false)
|
|
914
|
-
? envVars.blobStorageEncryptionKeyId
|
|
925
|
+
? (envVars.blobStorageEncryptionKeyId ?? BLOB_STORAGE_ENCRYPTION_KEY_ID)
|
|
915
926
|
: undefined
|
|
916
927
|
}
|
|
917
928
|
}
|
|
@@ -1051,10 +1062,11 @@ async function configureMessaging(coreConfig, envVars) {
|
|
|
1051
1062
|
type: engineTypes.MessagingEmailConnectorType.Aws,
|
|
1052
1063
|
options: {
|
|
1053
1064
|
config: {
|
|
1054
|
-
region: envVars.
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1065
|
+
region: envVars.awsSesRegion ?? "",
|
|
1066
|
+
authMode: envVars.awsSesAuthMode,
|
|
1067
|
+
accessKeyId: envVars.awsSesAccessKeyId,
|
|
1068
|
+
secretAccessKey: envVars.awsSesSecretAccessKey,
|
|
1069
|
+
endpoint: envVars.awsSesEndpoint
|
|
1058
1070
|
}
|
|
1059
1071
|
}
|
|
1060
1072
|
});
|
|
@@ -1069,10 +1081,11 @@ async function configureMessaging(coreConfig, envVars) {
|
|
|
1069
1081
|
type: engineTypes.MessagingSmsConnectorType.Aws,
|
|
1070
1082
|
options: {
|
|
1071
1083
|
config: {
|
|
1072
|
-
region: envVars.
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1084
|
+
region: envVars.awsSesRegion ?? "",
|
|
1085
|
+
authMode: envVars.awsSesAuthMode,
|
|
1086
|
+
accessKeyId: envVars.awsSesAccessKeyId,
|
|
1087
|
+
secretAccessKey: envVars.awsSesSecretAccessKey,
|
|
1088
|
+
endpoint: envVars.awsSesEndpoint
|
|
1076
1089
|
}
|
|
1077
1090
|
}
|
|
1078
1091
|
});
|
|
@@ -1089,8 +1102,9 @@ async function configureMessaging(coreConfig, envVars) {
|
|
|
1089
1102
|
options: {
|
|
1090
1103
|
config: {
|
|
1091
1104
|
region: envVars.awsSesRegion ?? "",
|
|
1092
|
-
|
|
1093
|
-
|
|
1105
|
+
authMode: envVars.awsSesAuthMode,
|
|
1106
|
+
accessKeyId: envVars.awsSesAccessKeyId,
|
|
1107
|
+
secretAccessKey: envVars.awsSesSecretAccessKey,
|
|
1094
1108
|
endpoint: envVars.awsSesEndpoint,
|
|
1095
1109
|
applicationsSettings: core.Is.json(envVars.awsMessagingPushNotificationApplications)
|
|
1096
1110
|
? JSON.parse(envVars.awsMessagingPushNotificationApplications)
|
|
@@ -1220,7 +1234,7 @@ async function configureVerifiableStorage(coreConfig, envVars) {
|
|
|
1220
1234
|
type: engineTypes.ImmutableProofComponentType.Service,
|
|
1221
1235
|
options: {
|
|
1222
1236
|
config: {
|
|
1223
|
-
verificationMethodId: envVars.immutableProofVerificationMethodId
|
|
1237
|
+
verificationMethodId: envVars.immutableProofVerificationMethodId ?? IMMUTABLE_PROOF_VERIFICATION_METHOD_ID
|
|
1224
1238
|
}
|
|
1225
1239
|
}
|
|
1226
1240
|
});
|
|
@@ -1325,7 +1339,7 @@ async function configureAttestation(coreConfig, envVars) {
|
|
|
1325
1339
|
type: engineTypes.AttestationComponentType.Service,
|
|
1326
1340
|
options: {
|
|
1327
1341
|
config: {
|
|
1328
|
-
verificationMethodId: envVars.attestationVerificationMethodId
|
|
1342
|
+
verificationMethodId: envVars.attestationVerificationMethodId ?? ATTESTATION_VERIFICATION_METHOD_ID
|
|
1329
1343
|
}
|
|
1330
1344
|
}
|
|
1331
1345
|
});
|
|
@@ -1416,7 +1430,9 @@ async function configureVerifiableCredentialAuthentication(coreConfig, envVars)
|
|
|
1416
1430
|
coreConfig.types.authenticationGeneratorComponent.push({
|
|
1417
1431
|
type: engineTypes.AuthenticationGeneratorComponentType.VerifiableCredential,
|
|
1418
1432
|
options: {
|
|
1419
|
-
config: {
|
|
1433
|
+
config: {
|
|
1434
|
+
verificationMethodId: envVars.vcAuthenticationVerificationMethodId ?? VC_AUTHENTICATION_VERIFICATION_METHOD_ID
|
|
1435
|
+
}
|
|
1420
1436
|
},
|
|
1421
1437
|
features: ["verifiable-credential"]
|
|
1422
1438
|
});
|
|
@@ -1544,7 +1560,8 @@ async function configureSynchronisedStorage(coreConfig, envVars) {
|
|
|
1544
1560
|
options: {
|
|
1545
1561
|
config: {
|
|
1546
1562
|
verifiableStorageKeyId: verifiableStorageKeyId ?? "",
|
|
1547
|
-
blobStorageEncryptionKeyId: envVars.synchronisedStorageBlobStorageEncryptionKeyId
|
|
1563
|
+
blobStorageEncryptionKeyId: envVars.synchronisedStorageBlobStorageEncryptionKeyId ??
|
|
1564
|
+
SYNCHRONISED_STORAGE_BLOB_STORAGE_ENCRYPTION_KEY_ID,
|
|
1548
1565
|
entityUpdateIntervalMinutes: core.Coerce.number(envVars.synchronisedStorageEntityUpdateIntervalMinutes),
|
|
1549
1566
|
consolidationIntervalMinutes: core.Coerce.number(envVars.synchronisedStorageConsolidationIntervalMinutes),
|
|
1550
1567
|
consolidationBatchSize: core.Coerce.number(envVars.synchronisedStorageConsolidationBatchSize),
|
|
@@ -1597,9 +1614,8 @@ async function configureDataSpaceConnector(coreConfig, envVars) {
|
|
|
1597
1614
|
type: engineTypes.DataSpaceConnectorComponentType.Service,
|
|
1598
1615
|
options: {
|
|
1599
1616
|
config: {
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
: undefined
|
|
1617
|
+
retainActivityLogsFor: core.Coerce.number(envVars.dataSpaceConnectorRetainActivityLogsFor),
|
|
1618
|
+
activityLogsCleanUpInterval: core.Coerce.number(envVars.dataSpaceConnectorActivityLogsCleanUpInterval)
|
|
1603
1619
|
}
|
|
1604
1620
|
}
|
|
1605
1621
|
});
|
|
@@ -1645,10 +1661,9 @@ async function configureDlt(coreConfig, envVars) {
|
|
|
1645
1661
|
* @param serverInfo The server information.
|
|
1646
1662
|
* @param openApiSpecPath The path to the open api spec.
|
|
1647
1663
|
* @param favIconPath The path to the favicon.
|
|
1648
|
-
* @returns The
|
|
1664
|
+
* @returns The config for the core and the server.
|
|
1649
1665
|
*/
|
|
1650
1666
|
async function buildEngineServerConfiguration(envVars, coreEngineConfig, serverInfo, openApiSpecPath, favIconPath) {
|
|
1651
|
-
envVars.authSigningKeyId ??= "auth-signing";
|
|
1652
1667
|
const webServerOptions = {
|
|
1653
1668
|
port: core.Coerce.number(envVars.port),
|
|
1654
1669
|
host: core.Coerce.string(envVars.host),
|
|
@@ -1764,7 +1779,7 @@ async function buildEngineServerConfiguration(envVars, coreEngineConfig, serverI
|
|
|
1764
1779
|
type: engineServerTypes.AuthenticationComponentType.EntityStorage,
|
|
1765
1780
|
options: {
|
|
1766
1781
|
config: {
|
|
1767
|
-
signingKeyName: envVars.authSigningKeyId
|
|
1782
|
+
signingKeyName: envVars.authSigningKeyId ?? AUTH_SIGNING_KEY_ID
|
|
1768
1783
|
}
|
|
1769
1784
|
}
|
|
1770
1785
|
});
|
|
@@ -1772,7 +1787,7 @@ async function buildEngineServerConfiguration(envVars, coreEngineConfig, serverI
|
|
|
1772
1787
|
type: engineServerTypes.RestRouteProcessorType.AuthHeader,
|
|
1773
1788
|
options: {
|
|
1774
1789
|
config: {
|
|
1775
|
-
signingKeyName: envVars.authSigningKeyId
|
|
1790
|
+
signingKeyName: envVars.authSigningKeyId ?? AUTH_SIGNING_KEY_ID
|
|
1776
1791
|
}
|
|
1777
1792
|
}
|
|
1778
1793
|
});
|
|
@@ -1780,7 +1795,7 @@ async function buildEngineServerConfiguration(envVars, coreEngineConfig, serverI
|
|
|
1780
1795
|
type: engineServerTypes.SocketRouteProcessorType.AuthHeader,
|
|
1781
1796
|
options: {
|
|
1782
1797
|
config: {
|
|
1783
|
-
signingKeyName: envVars.authSigningKeyId
|
|
1798
|
+
signingKeyName: envVars.authSigningKeyId ?? AUTH_SIGNING_KEY_ID
|
|
1784
1799
|
}
|
|
1785
1800
|
}
|
|
1786
1801
|
});
|
|
@@ -1800,15 +1815,111 @@ async function buildEngineServerConfiguration(envVars, coreEngineConfig, serverI
|
|
|
1800
1815
|
|
|
1801
1816
|
// Copyright 2024 IOTA Stiftung.
|
|
1802
1817
|
// SPDX-License-Identifier: Apache-2.0.
|
|
1803
|
-
|
|
1818
|
+
/**
|
|
1819
|
+
* Handles the configuration of the extensions.
|
|
1820
|
+
* @param envVars The environment variables for the node.
|
|
1821
|
+
* @param nodeEngineConfig The node engine config.
|
|
1822
|
+
* @returns The config for the core and the server.
|
|
1823
|
+
*/
|
|
1824
|
+
async function extensionsConfiguration(envVars, nodeEngineConfig) {
|
|
1825
|
+
if (core.Is.stringValue(envVars.extensions)) {
|
|
1826
|
+
const extensions = envVars.extensions.split(",");
|
|
1827
|
+
for (const extension of extensions) {
|
|
1828
|
+
let initialiseConfigMethod;
|
|
1829
|
+
try {
|
|
1830
|
+
cliCore.CLIDisplay.value(core.I18n.formatMessage("node.extensionLoading"), extension);
|
|
1831
|
+
initialiseConfigMethod = await modules.ModuleHelper.getModuleMethod(extension, "extensionInitialise");
|
|
1832
|
+
}
|
|
1833
|
+
catch (err) {
|
|
1834
|
+
throw new core.GeneralError("node", "extensionLoadingError", { extension }, err);
|
|
1835
|
+
}
|
|
1836
|
+
if (core.Is.function(initialiseConfigMethod)) {
|
|
1837
|
+
await initialiseConfigMethod(envVars, nodeEngineConfig);
|
|
1838
|
+
}
|
|
1839
|
+
}
|
|
1840
|
+
}
|
|
1841
|
+
return nodeEngineConfig;
|
|
1842
|
+
}
|
|
1843
|
+
/**
|
|
1844
|
+
* Handles the initialisation of the extensions when the engine has been constructed.
|
|
1845
|
+
* @param envVars The environment variables for the node.
|
|
1846
|
+
* @param engineCore The engine core instance.
|
|
1847
|
+
* @returns Nothing.
|
|
1848
|
+
*/
|
|
1849
|
+
async function extensionsInitialiseEngine(envVars, engineCore) {
|
|
1850
|
+
if (core.Is.stringValue(envVars.extensions)) {
|
|
1851
|
+
const extensions = envVars.extensions.split(",");
|
|
1852
|
+
for (const extension of extensions) {
|
|
1853
|
+
let initialiseEngineMethod;
|
|
1854
|
+
try {
|
|
1855
|
+
engineCore.logInfo(core.I18n.formatMessage("node.extensionInitialisingEngine", { extension }));
|
|
1856
|
+
initialiseEngineMethod =
|
|
1857
|
+
await modules.ModuleHelper.getModuleMethod(extension, "extensionInitialiseEngine");
|
|
1858
|
+
}
|
|
1859
|
+
catch { }
|
|
1860
|
+
if (core.Is.function(initialiseEngineMethod)) {
|
|
1861
|
+
await initialiseEngineMethod(engineCore);
|
|
1862
|
+
}
|
|
1863
|
+
}
|
|
1864
|
+
}
|
|
1865
|
+
}
|
|
1866
|
+
/**
|
|
1867
|
+
* Handles the initialisation of the extensions when the engine server has been constructed.
|
|
1868
|
+
* @param envVars The environment variables for the node.
|
|
1869
|
+
* @param engineCore The engine core instance.
|
|
1870
|
+
* @param engineServer The engine server instance.
|
|
1871
|
+
* @returns Nothing.
|
|
1872
|
+
*/
|
|
1873
|
+
async function extensionsInitialiseEngineServer(envVars, engineCore, engineServer) {
|
|
1874
|
+
if (core.Is.stringValue(envVars.extensions)) {
|
|
1875
|
+
const extensions = envVars.extensions.split(",");
|
|
1876
|
+
for (const extension of extensions) {
|
|
1877
|
+
let initialiseEngineServerMethod;
|
|
1878
|
+
try {
|
|
1879
|
+
engineCore.logInfo(core.I18n.formatMessage("node.extensionInitialisingEngineServer", { extension }));
|
|
1880
|
+
initialiseEngineServerMethod =
|
|
1881
|
+
await modules.ModuleHelper.getModuleMethod(extension, "extensionInitialiseEngineServer");
|
|
1882
|
+
}
|
|
1883
|
+
catch { }
|
|
1884
|
+
if (core.Is.function(initialiseEngineServerMethod)) {
|
|
1885
|
+
await initialiseEngineServerMethod(engineCore, engineServer);
|
|
1886
|
+
}
|
|
1887
|
+
}
|
|
1888
|
+
}
|
|
1889
|
+
}
|
|
1890
|
+
/**
|
|
1891
|
+
* Handles the shutdown of the extensions.
|
|
1892
|
+
* @param envVars The environment variables for the node.
|
|
1893
|
+
* @param engineCore The engine core instance.
|
|
1894
|
+
* @returns Nothing.
|
|
1895
|
+
*/
|
|
1896
|
+
async function shutdownExtensions(envVars, engineCore) {
|
|
1897
|
+
if (core.Is.stringValue(envVars.extensions)) {
|
|
1898
|
+
const extensions = envVars.extensions.split(",");
|
|
1899
|
+
for (const extension of extensions) {
|
|
1900
|
+
let shutdownMethod;
|
|
1901
|
+
try {
|
|
1902
|
+
engineCore.logInfo(core.I18n.formatMessage("node.extensionShutdown", { extension }));
|
|
1903
|
+
shutdownMethod = await modules.ModuleHelper.getModuleMethod(extension, "extensionShutdown");
|
|
1904
|
+
}
|
|
1905
|
+
catch { }
|
|
1906
|
+
if (core.Is.function(shutdownMethod)) {
|
|
1907
|
+
await shutdownMethod();
|
|
1908
|
+
}
|
|
1909
|
+
}
|
|
1910
|
+
}
|
|
1911
|
+
}
|
|
1912
|
+
|
|
1913
|
+
// Copyright 2024 IOTA Stiftung.
|
|
1914
|
+
// SPDX-License-Identifier: Apache-2.0.
|
|
1804
1915
|
/**
|
|
1805
1916
|
* Start the engine server.
|
|
1806
1917
|
* @param nodeOptions Optional run options for the engine server.
|
|
1807
|
-
* @param
|
|
1918
|
+
* @param nodeEngineConfig The configuration for the engine server.
|
|
1808
1919
|
* @param envVars The environment variables.
|
|
1809
1920
|
* @returns The engine server.
|
|
1810
1921
|
*/
|
|
1811
|
-
async function start(nodeOptions,
|
|
1922
|
+
async function start(nodeOptions, nodeEngineConfig, envVars) {
|
|
1812
1923
|
const entityStorageConnectorType = envVars.entityStorageConnectorType?.split(",") ?? [];
|
|
1813
1924
|
const blobStorageConnectorType = envVars.blobStorageConnectorType?.split(",") ?? [];
|
|
1814
1925
|
// If the blob storage or entity storage is configured with file connectors
|
|
@@ -1823,7 +1934,7 @@ async function start(nodeOptions, engineServerConfig, envVars) {
|
|
|
1823
1934
|
}
|
|
1824
1935
|
// Create the engine instance using file state storage unless one is configured in options
|
|
1825
1936
|
const engine$1 = new engine.Engine({
|
|
1826
|
-
config:
|
|
1937
|
+
config: nodeEngineConfig,
|
|
1827
1938
|
stateStorage: nodeOptions?.stateStorage ?? new engineCore.FileStateStorage(envVars.stateFilename ?? ""),
|
|
1828
1939
|
customBootstrap: async (core, engineContext) => bootstrap(core, engineContext, envVars)
|
|
1829
1940
|
});
|
|
@@ -1831,14 +1942,16 @@ async function start(nodeOptions, engineServerConfig, envVars) {
|
|
|
1831
1942
|
const server = new engineServer.EngineServer({ engineCore: engine$1 });
|
|
1832
1943
|
// Extend the engine.
|
|
1833
1944
|
if (core.Is.function(nodeOptions?.extendEngine)) {
|
|
1834
|
-
|
|
1945
|
+
engine$1.logInfo(core.I18n.formatMessage("node.extendingEngine"));
|
|
1835
1946
|
await nodeOptions.extendEngine(engine$1);
|
|
1836
1947
|
}
|
|
1948
|
+
await extensionsInitialiseEngine(envVars, engine$1);
|
|
1837
1949
|
// Extend the engine server.
|
|
1838
1950
|
if (core.Is.function(nodeOptions?.extendEngineServer)) {
|
|
1839
|
-
|
|
1951
|
+
engine$1.logInfo(core.I18n.formatMessage("node.extendingEngineServer"));
|
|
1840
1952
|
await nodeOptions?.extendEngineServer(server);
|
|
1841
1953
|
}
|
|
1954
|
+
await extensionsInitialiseEngineServer(envVars, engine$1, server);
|
|
1842
1955
|
// Need to register the engine with the factory so that background tasks
|
|
1843
1956
|
// can clone it to spawn new instances.
|
|
1844
1957
|
engineModels.EngineCoreFactory.register("engine", () => engine$1);
|
|
@@ -1847,14 +1960,17 @@ async function start(nodeOptions, engineServerConfig, envVars) {
|
|
|
1847
1960
|
if (canContinue) {
|
|
1848
1961
|
return {
|
|
1849
1962
|
engine: engine$1,
|
|
1850
|
-
server
|
|
1963
|
+
server,
|
|
1964
|
+
shutdown: async () => {
|
|
1965
|
+
await server.stop();
|
|
1966
|
+
await shutdownExtensions(envVars, engine$1);
|
|
1967
|
+
}
|
|
1851
1968
|
};
|
|
1852
1969
|
}
|
|
1853
1970
|
}
|
|
1854
1971
|
|
|
1855
1972
|
// Copyright 2024 IOTA Stiftung.
|
|
1856
1973
|
// SPDX-License-Identifier: Apache-2.0.
|
|
1857
|
-
/* eslint-disable no-console */
|
|
1858
1974
|
/**
|
|
1859
1975
|
* Run the TWIN Node server.
|
|
1860
1976
|
* @param nodeOptions Optional configuration options for running the server.
|
|
@@ -1865,50 +1981,59 @@ async function run(nodeOptions) {
|
|
|
1865
1981
|
nodeOptions ??= {};
|
|
1866
1982
|
const serverInfo = {
|
|
1867
1983
|
name: nodeOptions?.serverName ?? "TWIN Node Server",
|
|
1868
|
-
version: nodeOptions?.serverVersion ?? "0.0.2-next.
|
|
1984
|
+
version: nodeOptions?.serverVersion ?? "0.0.2-next.18" // x-release-please-version
|
|
1869
1985
|
};
|
|
1870
|
-
|
|
1986
|
+
cliCore.CLIDisplay.header(serverInfo.name, serverInfo.version, "🌩️ ");
|
|
1871
1987
|
if (!core.Is.stringValue(nodeOptions?.executionDirectory)) {
|
|
1872
1988
|
nodeOptions.executionDirectory = getExecutionDirectory();
|
|
1873
1989
|
}
|
|
1874
|
-
|
|
1990
|
+
cliCore.CLIDisplay.value("Execution Directory", nodeOptions.executionDirectory);
|
|
1875
1991
|
nodeOptions.localesDirectory =
|
|
1876
1992
|
nodeOptions?.localesDirectory ??
|
|
1877
1993
|
path.resolve(path.join(nodeOptions.executionDirectory, "dist", "locales"));
|
|
1878
|
-
|
|
1994
|
+
cliCore.CLIDisplay.value("Locales Directory", nodeOptions.localesDirectory);
|
|
1879
1995
|
await initialiseLocales(nodeOptions.localesDirectory);
|
|
1880
1996
|
if (core.Is.empty(nodeOptions?.openApiSpecFile)) {
|
|
1881
1997
|
const specFile = path.resolve(path.join(nodeOptions.executionDirectory ?? "", "docs", "open-api", "spec.json"));
|
|
1882
|
-
|
|
1998
|
+
cliCore.CLIDisplay.value("Default OpenAPI Spec File", specFile);
|
|
1883
1999
|
if (await fileExists(specFile)) {
|
|
1884
2000
|
nodeOptions ??= {};
|
|
1885
2001
|
nodeOptions.openApiSpecFile = specFile;
|
|
1886
2002
|
}
|
|
1887
2003
|
}
|
|
2004
|
+
else {
|
|
2005
|
+
cliCore.CLIDisplay.value("OpenAPI Spec File", nodeOptions.openApiSpecFile);
|
|
2006
|
+
}
|
|
1888
2007
|
if (core.Is.empty(nodeOptions?.favIconFile)) {
|
|
1889
2008
|
const favIconFile = path.resolve(path.join(nodeOptions.executionDirectory ?? "", "static", "favicon.png"));
|
|
1890
|
-
|
|
2009
|
+
cliCore.CLIDisplay.value("Default Favicon File", favIconFile);
|
|
1891
2010
|
if (await fileExists(favIconFile)) {
|
|
1892
2011
|
nodeOptions ??= {};
|
|
1893
2012
|
nodeOptions.favIconFile = favIconFile;
|
|
1894
2013
|
}
|
|
1895
2014
|
}
|
|
2015
|
+
else {
|
|
2016
|
+
cliCore.CLIDisplay.value("Favicon File", nodeOptions.favIconFile);
|
|
2017
|
+
}
|
|
1896
2018
|
nodeOptions.envPrefix ??= "TWIN_NODE_";
|
|
1897
|
-
|
|
2019
|
+
cliCore.CLIDisplay.value("Environment Variable Prefix", nodeOptions.envPrefix);
|
|
1898
2020
|
overrideModuleImport(nodeOptions.executionDirectory ?? "");
|
|
1899
|
-
const {
|
|
1900
|
-
|
|
1901
|
-
|
|
2021
|
+
const { nodeEngineConfig, nodeEnvVars: envVars } = await buildConfiguration(
|
|
2022
|
+
// This is the only location in the code base that should access process.env directly
|
|
2023
|
+
// eslint-disable-next-line no-restricted-syntax
|
|
2024
|
+
process.env, nodeOptions, serverInfo);
|
|
2025
|
+
cliCore.CLIDisplay.break();
|
|
2026
|
+
const startResult = await start(nodeOptions, nodeEngineConfig, envVars);
|
|
1902
2027
|
if (!core.Is.empty(startResult)) {
|
|
1903
2028
|
for (const signal of ["SIGHUP", "SIGINT", "SIGTERM"]) {
|
|
1904
2029
|
process.on(signal, async () => {
|
|
1905
|
-
await startResult.
|
|
2030
|
+
await startResult.shutdown();
|
|
1906
2031
|
});
|
|
1907
2032
|
}
|
|
1908
2033
|
}
|
|
1909
2034
|
}
|
|
1910
2035
|
catch (err) {
|
|
1911
|
-
|
|
2036
|
+
cliCore.CLIDisplay.error(err);
|
|
1912
2037
|
// eslint-disable-next-line unicorn/no-process-exit
|
|
1913
2038
|
process.exit(1);
|
|
1914
2039
|
}
|
|
@@ -1925,7 +2050,7 @@ async function buildConfiguration(processEnv, options, serverInfo) {
|
|
|
1925
2050
|
let defaultEnvOnly = false;
|
|
1926
2051
|
if (core.Is.empty(options?.envFilenames)) {
|
|
1927
2052
|
const envFile = path.resolve(path.join(options.executionDirectory ?? "", ".env"));
|
|
1928
|
-
|
|
2053
|
+
cliCore.CLIDisplay.value("Default Environment File", envFile);
|
|
1929
2054
|
options ??= {};
|
|
1930
2055
|
options.envFilenames = [envFile];
|
|
1931
2056
|
defaultEnvOnly = true;
|
|
@@ -1953,18 +2078,18 @@ async function buildConfiguration(processEnv, options, serverInfo) {
|
|
|
1953
2078
|
const filePath = envVars[key].slice(6).trim();
|
|
1954
2079
|
const embeddedFile = path.resolve(path.join(options.executionDirectory ?? "", filePath));
|
|
1955
2080
|
if (envVars[key].startsWith("@text:")) {
|
|
1956
|
-
|
|
2081
|
+
cliCore.CLIDisplay.value(`Expanding Environment Variable: ${key} from text file`, embeddedFile);
|
|
1957
2082
|
envVars[key] = await loadTextFile(embeddedFile);
|
|
1958
2083
|
}
|
|
1959
2084
|
else if (envVars[key].startsWith("@json:")) {
|
|
1960
|
-
|
|
2085
|
+
cliCore.CLIDisplay.value(`Expanding Environment Variable: ${key} from JSON file`, embeddedFile);
|
|
1961
2086
|
envVars[key] = await loadJsonFile(embeddedFile);
|
|
1962
2087
|
}
|
|
1963
2088
|
}
|
|
1964
2089
|
}
|
|
1965
2090
|
// Extend the environment variables with any additional custom configuration.
|
|
1966
2091
|
if (core.Is.function(options?.extendEnvVars)) {
|
|
1967
|
-
|
|
2092
|
+
cliCore.CLIDisplay.task("Extending Environment Variables");
|
|
1968
2093
|
await options.extendEnvVars(envVars);
|
|
1969
2094
|
}
|
|
1970
2095
|
// Build the engine configuration from the environment variables.
|
|
@@ -1973,22 +2098,23 @@ async function buildConfiguration(processEnv, options, serverInfo) {
|
|
|
1973
2098
|
// Merge any custom configuration provided in the options.
|
|
1974
2099
|
if (core.Is.arrayValue(options?.configFilenames)) {
|
|
1975
2100
|
for (const configFile of options.configFilenames) {
|
|
1976
|
-
|
|
2101
|
+
cliCore.CLIDisplay.value("Loading Configuration File", configFile);
|
|
1977
2102
|
const configFilePath = path.resolve(path.join(options.executionDirectory ?? "", configFile));
|
|
1978
2103
|
const config = await loadJsonFile(configFilePath);
|
|
1979
2104
|
Object.assign(engineServerConfig, config);
|
|
1980
2105
|
}
|
|
1981
2106
|
}
|
|
1982
2107
|
if (core.Is.objectValue(options?.config)) {
|
|
1983
|
-
|
|
2108
|
+
cliCore.CLIDisplay.task("Merging Custom Configuration");
|
|
1984
2109
|
Object.assign(engineServerConfig, options.config);
|
|
1985
2110
|
}
|
|
1986
2111
|
// Merge any custom configuration provided in the options.
|
|
1987
2112
|
if (core.Is.function(options?.extendConfig)) {
|
|
1988
|
-
|
|
1989
|
-
await options.extendConfig(engineServerConfig);
|
|
2113
|
+
cliCore.CLIDisplay.task("Extending Configuration");
|
|
2114
|
+
await options.extendConfig(envVars, engineServerConfig);
|
|
1990
2115
|
}
|
|
1991
|
-
|
|
2116
|
+
const nodeEngineConfig = await extensionsConfiguration(envVars, engineServerConfig);
|
|
2117
|
+
return { nodeEngineConfig, nodeEnvVars: envVars };
|
|
1992
2118
|
}
|
|
1993
2119
|
/**
|
|
1994
2120
|
* Override module imports to use local files where possible.
|
|
@@ -2025,7 +2151,13 @@ function overrideModuleImport(executionDirectory) {
|
|
|
2025
2151
|
});
|
|
2026
2152
|
}
|
|
2027
2153
|
|
|
2154
|
+
exports.ATTESTATION_VERIFICATION_METHOD_ID = ATTESTATION_VERIFICATION_METHOD_ID;
|
|
2155
|
+
exports.AUTH_SIGNING_KEY_ID = AUTH_SIGNING_KEY_ID;
|
|
2156
|
+
exports.BLOB_STORAGE_ENCRYPTION_KEY_ID = BLOB_STORAGE_ENCRYPTION_KEY_ID;
|
|
2157
|
+
exports.IMMUTABLE_PROOF_VERIFICATION_METHOD_ID = IMMUTABLE_PROOF_VERIFICATION_METHOD_ID;
|
|
2028
2158
|
exports.NodeFeatures = NodeFeatures;
|
|
2159
|
+
exports.SYNCHRONISED_STORAGE_BLOB_STORAGE_ENCRYPTION_KEY_ID = SYNCHRONISED_STORAGE_BLOB_STORAGE_ENCRYPTION_KEY_ID;
|
|
2160
|
+
exports.VC_AUTHENTICATION_VERIFICATION_METHOD_ID = VC_AUTHENTICATION_VERIFICATION_METHOD_ID;
|
|
2029
2161
|
exports.bootstrap = bootstrap;
|
|
2030
2162
|
exports.bootstrapAuth = bootstrapAuth;
|
|
2031
2163
|
exports.bootstrapBlobEncryption = bootstrapBlobEncryption;
|
|
@@ -2037,6 +2169,9 @@ exports.buildConfiguration = buildConfiguration;
|
|
|
2037
2169
|
exports.buildEngineConfiguration = buildEngineConfiguration;
|
|
2038
2170
|
exports.buildEngineServerConfiguration = buildEngineServerConfiguration;
|
|
2039
2171
|
exports.directoryExists = directoryExists;
|
|
2172
|
+
exports.extensionsConfiguration = extensionsConfiguration;
|
|
2173
|
+
exports.extensionsInitialiseEngine = extensionsInitialiseEngine;
|
|
2174
|
+
exports.extensionsInitialiseEngineServer = extensionsInitialiseEngineServer;
|
|
2040
2175
|
exports.fileExists = fileExists;
|
|
2041
2176
|
exports.getExecutionDirectory = getExecutionDirectory;
|
|
2042
2177
|
exports.getFeatures = getFeatures;
|
|
@@ -2047,4 +2182,5 @@ exports.loadJsonFile = loadJsonFile;
|
|
|
2047
2182
|
exports.loadTextFile = loadTextFile;
|
|
2048
2183
|
exports.overrideModuleImport = overrideModuleImport;
|
|
2049
2184
|
exports.run = run;
|
|
2185
|
+
exports.shutdownExtensions = shutdownExtensions;
|
|
2050
2186
|
exports.start = start;
|