@twin.org/node-core 0.0.3-next.2 → 0.0.3-next.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  // Copyright 2024 IOTA Stiftung.
2
2
  // SPDX-License-Identifier: Apache-2.0.
3
- import { Converter, I18n, Is, RandomHelper, Urn } from "@twin.org/core";
3
+ import { Converter, I18n, Is, RandomHelper, StringHelper, Urn } from "@twin.org/core";
4
4
  import { Bip39 } from "@twin.org/crypto";
5
5
  import { IdentityConnectorType, WalletConnectorType } from "@twin.org/engine-types";
6
6
  import { EntityStorageConnectorFactory } from "@twin.org/entity-storage-models";
@@ -27,9 +27,12 @@ export async function createIdentity(engineCore, envVars, configIdentity, config
27
27
  const vaultConnector = VaultConnectorFactory.get(defaultVaultConnectorType);
28
28
  const workingIdentity = configIdentity ?? `bootstrap-temp-${Converter.bytesToHex(RandomHelper.generate(16))}`;
29
29
  const workingController = controller ?? workingIdentity;
30
- await bootstrapMnemonic(engineCore, vaultConnector, workingIdentity, configMnemonic);
30
+ const mnemonicStored = await bootstrapMnemonic(engineCore, vaultConnector, workingIdentity, configMnemonic);
31
31
  const addresses = addWallet ? await generateWallet(engineCore, envVars, workingIdentity) : [];
32
32
  const finalIdentity = await generateIdentity(engineCore, envVars, workingController, workingIdentity, identityType);
33
+ if (mnemonicStored) {
34
+ engineCore.logInfo(I18n.formatMessage("node.finalMnemonic", { vaultKey: `${finalIdentity}/mnemonic` }));
35
+ }
33
36
  await finaliseWallet(engineCore, envVars, finalIdentity, addresses);
34
37
  await finaliseMnemonic(vaultConnector, workingIdentity, finalIdentity);
35
38
  return finalIdentity;
@@ -40,14 +43,21 @@ export async function createIdentity(engineCore, envVars, configIdentity, config
40
43
  * @param vaultConnector The vault connector to use.
41
44
  * @param identity The identity of the node.
42
45
  * @param existingMnemonic An existing mnemonic to use.
46
+ * @returns Whether the mnemonic was stored.
43
47
  */
44
48
  async function bootstrapMnemonic(engineCore, vaultConnector, identity, existingMnemonic) {
45
49
  let mnemonic = existingMnemonic;
46
50
  let storeMnemonic = false;
51
+ const mnemonicKey = `${identity}/mnemonic`;
47
52
  try {
48
- const storedMnemonic = await vaultConnector.getSecret(`${identity}/mnemonic`);
49
- storeMnemonic = storedMnemonic !== mnemonic;
50
- mnemonic = storedMnemonic;
53
+ const storedMnemonic = await vaultConnector.getSecret(mnemonicKey);
54
+ if (Is.stringValue(storedMnemonic)) {
55
+ storeMnemonic = storedMnemonic !== mnemonic && !Is.empty(mnemonic);
56
+ mnemonic = storedMnemonic;
57
+ }
58
+ else {
59
+ storeMnemonic = true;
60
+ }
51
61
  }
52
62
  catch {
53
63
  storeMnemonic = true;
@@ -56,16 +66,16 @@ async function bootstrapMnemonic(engineCore, vaultConnector, identity, existingM
56
66
  if (Is.empty(mnemonic)) {
57
67
  mnemonic = Bip39.randomMnemonic();
58
68
  storeMnemonic = true;
59
- engineCore.logInfo(I18n.formatMessage("node.generatingMnemonic", { mnemonic }));
60
69
  }
61
70
  // If there is no mnemonic stored in the vault then we need to store it
62
71
  if (storeMnemonic) {
63
72
  engineCore.logInfo(I18n.formatMessage("node.storingMnemonic"));
64
- await vaultConnector.setSecret(`${identity}/mnemonic`, mnemonic);
73
+ await vaultConnector.setSecret(mnemonicKey, mnemonic);
65
74
  }
66
75
  else {
67
76
  engineCore.logInfo(I18n.formatMessage("node.existingMnemonic"));
68
77
  }
78
+ return storeMnemonic;
69
79
  }
70
80
  /**
71
81
  * Finalise the mnemonic for the node identity.
@@ -118,8 +128,9 @@ async function generateWallet(engineCore, envVars, identity) {
118
128
  const balance = await walletConnector.getBalance(identity, addresses[0]);
119
129
  if (balance === 0n) {
120
130
  let address0 = addresses[0];
121
- if (defaultWalletConnectorType.startsWith(WalletConnectorType.Iota)) {
122
- address0 = `${envVars.iotaExplorerEndpoint}address/${address0}?network=${envVars.iotaNetwork}`;
131
+ if (defaultWalletConnectorType.startsWith(WalletConnectorType.Iota) &&
132
+ Is.stringValue(envVars.iotaExplorerEndpoint)) {
133
+ address0 = `${StringHelper.trimTrailingSlashes(envVars.iotaExplorerEndpoint)}/address/${address0}?network=${envVars.iotaNetwork}`;
123
134
  }
124
135
  engineCore.logInfo(I18n.formatMessage("node.fundingWallet", { address: address0 }));
125
136
  // Add some funds to the wallet from the faucet
@@ -160,9 +171,11 @@ async function generateIdentity(engineCore, envVars, controller, identity, ident
160
171
  const didUrn = Urn.fromValidString(identityDocument.id);
161
172
  const didParts = didUrn.parts();
162
173
  const objectId = didParts[3];
163
- engineCore.logInfo(I18n.formatMessage("node.identityExplorer", {
164
- url: `${envVars.iotaExplorerEndpoint}object/${objectId}?network=${envVars.iotaNetwork}`
165
- }));
174
+ if (Is.stringValue(envVars.iotaExplorerEndpoint)) {
175
+ engineCore.logInfo(I18n.formatMessage("node.identityExplorer", {
176
+ url: `${StringHelper.trimTrailingSlashes(envVars.iotaExplorerEndpoint)}/object/${objectId}?network=${envVars.iotaNetwork}`
177
+ }));
178
+ }
166
179
  }
167
180
  return identityDocument.id;
168
181
  }
@@ -1 +1 @@
1
- {"version":3,"file":"identity.js","sourceRoot":"","sources":["../../src/identity.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport { Converter, I18n, Is, RandomHelper, Urn } from \"@twin.org/core\";\nimport { Bip39 } from \"@twin.org/crypto\";\nimport type { IEngineCore } from \"@twin.org/engine-models\";\nimport { IdentityConnectorType, WalletConnectorType } from \"@twin.org/engine-types\";\nimport {\n\tEntityStorageConnectorFactory,\n\ttype IEntityStorageConnector\n} from \"@twin.org/entity-storage-models\";\nimport {\n\tIdentityConnectorFactory,\n\tIdentityResolverConnectorFactory\n} from \"@twin.org/identity-models\";\nimport { nameofKebabCase } from \"@twin.org/nameof\";\nimport { type IVaultConnector, VaultConnectorFactory } from \"@twin.org/vault-models\";\nimport type { WalletAddress } from \"@twin.org/wallet-connector-entity-storage\";\nimport { WalletConnectorFactory } from \"@twin.org/wallet-models\";\nimport type { INodeEnvironmentVariables } from \"./models/INodeEnvironmentVariables.js\";\n\n/**\n * Generate an identity and fund it.\n * @param engineCore The engine core for the node.\n * @param envVars The environment variables for the node.\n * @param configIdentity A identity from config to use.\n * @param configMnemonic A mnemonic from config to use.\n * @param controller The controller for the identity.\n * @param identityType The type of identity.\n * @param addWallet Whether to add a wallet for the identity.\n * @returns The identity that was generated.\n */\nexport async function createIdentity(\n\tengineCore: IEngineCore,\n\tenvVars: INodeEnvironmentVariables,\n\tconfigIdentity: string | undefined,\n\tconfigMnemonic: string | undefined,\n\tcontroller: string | undefined,\n\tidentityType: \"node\" | \"organization\" | \"user\",\n\taddWallet: boolean\n): Promise<string> {\n\tengineCore.logInfo(I18n.formatMessage(\"node.processingIdentity\", { identityType }));\n\n\t// We have a chicken and egg problem in that we can't create the identity\n\t// to store the mnemonic in the vault without an identity. We use a temporary identity\n\t// and then replace it with the new identity later in the process.\n\tconst defaultVaultConnectorType = engineCore.getRegisteredInstanceType(\"vaultConnector\");\n\tconst vaultConnector = VaultConnectorFactory.get(defaultVaultConnectorType);\n\n\tconst workingIdentity =\n\t\tconfigIdentity ?? `bootstrap-temp-${Converter.bytesToHex(RandomHelper.generate(16))}`;\n\tconst workingController = controller ?? workingIdentity;\n\n\tawait bootstrapMnemonic(engineCore, vaultConnector, workingIdentity, configMnemonic);\n\n\tconst addresses = addWallet ? await generateWallet(engineCore, envVars, workingIdentity) : [];\n\n\tconst finalIdentity = await generateIdentity(\n\t\tengineCore,\n\t\tenvVars,\n\t\tworkingController,\n\t\tworkingIdentity,\n\t\tidentityType\n\t);\n\n\tawait finaliseWallet(engineCore, envVars, finalIdentity, addresses);\n\n\tawait finaliseMnemonic(vaultConnector, workingIdentity, finalIdentity);\n\n\treturn finalIdentity;\n}\n\n/**\n * Generate a mnemonic for the node identity.\n * @param engineCore The engine core for the node.\n * @param vaultConnector The vault connector to use.\n * @param identity The identity of the node.\n * @param existingMnemonic An existing mnemonic to use.\n */\nasync function bootstrapMnemonic(\n\tengineCore: IEngineCore,\n\tvaultConnector: IVaultConnector,\n\tidentity: string,\n\texistingMnemonic?: string\n): Promise<void> {\n\tlet mnemonic = existingMnemonic;\n\tlet storeMnemonic = false;\n\n\ttry {\n\t\tconst storedMnemonic = await vaultConnector.getSecret<string>(`${identity}/mnemonic`);\n\t\tstoreMnemonic = storedMnemonic !== mnemonic;\n\t\tmnemonic = storedMnemonic;\n\t} catch {\n\t\tstoreMnemonic = true;\n\t}\n\n\t// If there is no mnemonic then we need to generate one\n\tif (Is.empty(mnemonic)) {\n\t\tmnemonic = Bip39.randomMnemonic();\n\t\tstoreMnemonic = true;\n\t\tengineCore.logInfo(I18n.formatMessage(\"node.generatingMnemonic\", { mnemonic }));\n\t}\n\n\t// If there is no mnemonic stored in the vault then we need to store it\n\tif (storeMnemonic) {\n\t\tengineCore.logInfo(I18n.formatMessage(\"node.storingMnemonic\"));\n\t\tawait vaultConnector.setSecret(`${identity}/mnemonic`, mnemonic);\n\t} else {\n\t\tengineCore.logInfo(I18n.formatMessage(\"node.existingMnemonic\"));\n\t}\n}\n\n/**\n * Finalise the mnemonic for the node identity.\n * @param vaultConnector The vault connector to use.\n * @param workingIdentity The identity of the node.\n * @param finalIdentity The final identity for the node.\n */\nasync function finaliseMnemonic(\n\tvaultConnector: IVaultConnector,\n\tworkingIdentity: string,\n\tfinalIdentity: string\n): Promise<void> {\n\t// Now that we have an identity we can remove the temporary one\n\t// and store the mnemonic with the new identity\n\tif (workingIdentity.startsWith(\"bootstrap-temp-\") && workingIdentity !== finalIdentity) {\n\t\tconst mnemonic = await vaultConnector.getSecret(`${workingIdentity}/mnemonic`);\n\t\tawait vaultConnector.setSecret(`${finalIdentity}/mnemonic`, mnemonic);\n\t\tawait vaultConnector.removeSecret(`${workingIdentity}/mnemonic`);\n\t}\n}\n\n/**\n * Bootstrap the identity for the node.\n * @param engineCore The engine core for the node.\n * @param envVars The environment variables for the node.\n * @param finalIdentity The identity of the node.\n * @param addresses The addresses for the wallet.\n */\nasync function finaliseWallet(\n\tengineCore: IEngineCore,\n\tenvVars: INodeEnvironmentVariables,\n\tfinalIdentity: string,\n\taddresses: string[]\n): Promise<void> {\n\tif (Is.arrayValue(addresses)) {\n\t\tconst defaultWalletConnectorType = engineCore.getRegisteredInstanceType(\"walletConnector\");\n\n\t\t// If we are using entity storage for wallet the identity associated with the\n\t\t// address will be wrong, so fix it\n\t\tif (defaultWalletConnectorType.startsWith(WalletConnectorType.EntityStorage)) {\n\t\t\tconst walletAddress =\n\t\t\t\tEntityStorageConnectorFactory.get<IEntityStorageConnector<WalletAddress>>(\n\t\t\t\t\tnameofKebabCase<WalletAddress>()\n\t\t\t\t);\n\t\t\tconst addr = await walletAddress.get(addresses[0]);\n\t\t\tif (!Is.empty(addr)) {\n\t\t\t\taddr.identity = finalIdentity;\n\t\t\t\tawait walletAddress.set(addr);\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Bootstrap the wallet for the node.\n * @param engineCore The engine core for the node.\n * @param envVars The environment variables for the node.\n * @param identity The identity to create the wallet for.\n * @returns The addresses for the wallet.\n */\nasync function generateWallet(\n\tengineCore: IEngineCore,\n\tenvVars: INodeEnvironmentVariables,\n\tidentity: string\n): Promise<string[]> {\n\tconst defaultWalletConnectorType = engineCore.getRegisteredInstanceType(\"walletConnector\");\n\n\tconst walletConnector = WalletConnectorFactory.get(defaultWalletConnectorType);\n\tconst addresses = await walletConnector.getAddresses(identity, 0, 0, 5);\n\n\tconst balance = await walletConnector.getBalance(identity, addresses[0]);\n\tif (balance === 0n) {\n\t\tlet address0 = addresses[0];\n\n\t\tif (defaultWalletConnectorType.startsWith(WalletConnectorType.Iota)) {\n\t\t\taddress0 = `${envVars.iotaExplorerEndpoint}address/${address0}?network=${envVars.iotaNetwork}`;\n\t\t}\n\n\t\tengineCore.logInfo(I18n.formatMessage(\"node.fundingWallet\", { address: address0 }));\n\n\t\t// Add some funds to the wallet from the faucet\n\t\tawait walletConnector.ensureBalance(identity, addresses[0], 1000000000n);\n\t} else {\n\t\tengineCore.logInfo(I18n.formatMessage(\"node.fundedWallet\"));\n\t}\n\treturn addresses;\n}\n\n/**\n * Bootstrap the identity for the node.\n * @param engineCore The engine core for the node.\n * @param envVars The environment variables for the node.\n * @param controller The controller for the identity.\n * @param identity The existing identity if there is one.\n * @param identityType The type of identity.\n * @returns The addresses for the wallet.\n */\nasync function generateIdentity(\n\tengineCore: IEngineCore,\n\tenvVars: INodeEnvironmentVariables,\n\tcontroller: string,\n\tidentity: string,\n\tidentityType: \"node\" | \"organization\" | \"user\"\n): Promise<string> {\n\tconst defaultIdentityConnectorType = engineCore.getRegisteredInstanceType(\"identityConnector\");\n\n\t// Now create an identity for the node controlled by the address we just funded\n\tconst identityConnector = IdentityConnectorFactory.get(defaultIdentityConnectorType);\n\n\tlet identityDocument;\n\n\ttry {\n\t\tconst defaultIdentityResolverConnectorType = engineCore.getRegisteredInstanceType(\n\t\t\t\"identityResolverConnector\"\n\t\t);\n\n\t\tconst identityResolverConnector = IdentityResolverConnectorFactory.get(\n\t\t\tdefaultIdentityResolverConnectorType\n\t\t);\n\t\tidentityDocument = await identityResolverConnector.resolveDocument(identity);\n\t\tengineCore.logInfo(I18n.formatMessage(\"node.existingIdentity\", { identity }));\n\t} catch {}\n\n\tif (Is.empty(identityDocument)) {\n\t\tengineCore.logInfo(I18n.formatMessage(\"node.generatingIdentity\", { identityType }));\n\n\t\tidentityDocument = await identityConnector.createDocument(controller);\n\n\t\tengineCore.logInfo(\n\t\t\tI18n.formatMessage(\"node.createdIdentity\", { identity: identityDocument.id })\n\t\t);\n\t}\n\n\tif (defaultIdentityConnectorType.startsWith(IdentityConnectorType.Iota)) {\n\t\tconst didUrn = Urn.fromValidString(identityDocument.id);\n\t\tconst didParts = didUrn.parts();\n\t\tconst objectId = didParts[3];\n\n\t\tengineCore.logInfo(\n\t\t\tI18n.formatMessage(\"node.identityExplorer\", {\n\t\t\t\turl: `${envVars.iotaExplorerEndpoint}object/${objectId}?network=${envVars.iotaNetwork}`\n\t\t\t})\n\t\t);\n\t}\n\treturn identityDocument.id;\n}\n"]}
1
+ {"version":3,"file":"identity.js","sourceRoot":"","sources":["../../src/identity.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport { Converter, I18n, Is, RandomHelper, StringHelper, Urn } from \"@twin.org/core\";\nimport { Bip39 } from \"@twin.org/crypto\";\nimport type { IEngineCore } from \"@twin.org/engine-models\";\nimport { IdentityConnectorType, WalletConnectorType } from \"@twin.org/engine-types\";\nimport {\n\tEntityStorageConnectorFactory,\n\ttype IEntityStorageConnector\n} from \"@twin.org/entity-storage-models\";\nimport {\n\tIdentityConnectorFactory,\n\tIdentityResolverConnectorFactory\n} from \"@twin.org/identity-models\";\nimport { nameofKebabCase } from \"@twin.org/nameof\";\nimport { type IVaultConnector, VaultConnectorFactory } from \"@twin.org/vault-models\";\nimport type { WalletAddress } from \"@twin.org/wallet-connector-entity-storage\";\nimport { WalletConnectorFactory } from \"@twin.org/wallet-models\";\nimport type { INodeEnvironmentVariables } from \"./models/INodeEnvironmentVariables.js\";\n\n/**\n * Generate an identity and fund it.\n * @param engineCore The engine core for the node.\n * @param envVars The environment variables for the node.\n * @param configIdentity A identity from config to use.\n * @param configMnemonic A mnemonic from config to use.\n * @param controller The controller for the identity.\n * @param identityType The type of identity.\n * @param addWallet Whether to add a wallet for the identity.\n * @returns The identity that was generated.\n */\nexport async function createIdentity(\n\tengineCore: IEngineCore,\n\tenvVars: INodeEnvironmentVariables,\n\tconfigIdentity: string | undefined,\n\tconfigMnemonic: string | undefined,\n\tcontroller: string | undefined,\n\tidentityType: \"node\" | \"organization\" | \"user\",\n\taddWallet: boolean\n): Promise<string> {\n\tengineCore.logInfo(I18n.formatMessage(\"node.processingIdentity\", { identityType }));\n\n\t// We have a chicken and egg problem in that we can't create the identity\n\t// to store the mnemonic in the vault without an identity. We use a temporary identity\n\t// and then replace it with the new identity later in the process.\n\tconst defaultVaultConnectorType = engineCore.getRegisteredInstanceType(\"vaultConnector\");\n\tconst vaultConnector = VaultConnectorFactory.get(defaultVaultConnectorType);\n\n\tconst workingIdentity =\n\t\tconfigIdentity ?? `bootstrap-temp-${Converter.bytesToHex(RandomHelper.generate(16))}`;\n\tconst workingController = controller ?? workingIdentity;\n\n\tconst mnemonicStored = await bootstrapMnemonic(\n\t\tengineCore,\n\t\tvaultConnector,\n\t\tworkingIdentity,\n\t\tconfigMnemonic\n\t);\n\n\tconst addresses = addWallet ? await generateWallet(engineCore, envVars, workingIdentity) : [];\n\n\tconst finalIdentity = await generateIdentity(\n\t\tengineCore,\n\t\tenvVars,\n\t\tworkingController,\n\t\tworkingIdentity,\n\t\tidentityType\n\t);\n\n\tif (mnemonicStored) {\n\t\tengineCore.logInfo(\n\t\t\tI18n.formatMessage(\"node.finalMnemonic\", { vaultKey: `${finalIdentity}/mnemonic` })\n\t\t);\n\t}\n\n\tawait finaliseWallet(engineCore, envVars, finalIdentity, addresses);\n\n\tawait finaliseMnemonic(vaultConnector, workingIdentity, finalIdentity);\n\n\treturn finalIdentity;\n}\n\n/**\n * Generate a mnemonic for the node identity.\n * @param engineCore The engine core for the node.\n * @param vaultConnector The vault connector to use.\n * @param identity The identity of the node.\n * @param existingMnemonic An existing mnemonic to use.\n * @returns Whether the mnemonic was stored.\n */\nasync function bootstrapMnemonic(\n\tengineCore: IEngineCore,\n\tvaultConnector: IVaultConnector,\n\tidentity: string,\n\texistingMnemonic?: string\n): Promise<boolean> {\n\tlet mnemonic = existingMnemonic;\n\tlet storeMnemonic = false;\n\n\tconst mnemonicKey = `${identity}/mnemonic`;\n\n\ttry {\n\t\tconst storedMnemonic = await vaultConnector.getSecret<string>(mnemonicKey);\n\t\tif (Is.stringValue(storedMnemonic)) {\n\t\t\tstoreMnemonic = storedMnemonic !== mnemonic && !Is.empty(mnemonic);\n\t\t\tmnemonic = storedMnemonic;\n\t\t} else {\n\t\t\tstoreMnemonic = true;\n\t\t}\n\t} catch {\n\t\tstoreMnemonic = true;\n\t}\n\n\t// If there is no mnemonic then we need to generate one\n\tif (Is.empty(mnemonic)) {\n\t\tmnemonic = Bip39.randomMnemonic();\n\t\tstoreMnemonic = true;\n\t}\n\n\t// If there is no mnemonic stored in the vault then we need to store it\n\tif (storeMnemonic) {\n\t\tengineCore.logInfo(I18n.formatMessage(\"node.storingMnemonic\"));\n\t\tawait vaultConnector.setSecret(mnemonicKey, mnemonic);\n\t} else {\n\t\tengineCore.logInfo(I18n.formatMessage(\"node.existingMnemonic\"));\n\t}\n\n\treturn storeMnemonic;\n}\n\n/**\n * Finalise the mnemonic for the node identity.\n * @param vaultConnector The vault connector to use.\n * @param workingIdentity The identity of the node.\n * @param finalIdentity The final identity for the node.\n */\nasync function finaliseMnemonic(\n\tvaultConnector: IVaultConnector,\n\tworkingIdentity: string,\n\tfinalIdentity: string\n): Promise<void> {\n\t// Now that we have an identity we can remove the temporary one\n\t// and store the mnemonic with the new identity\n\tif (workingIdentity.startsWith(\"bootstrap-temp-\") && workingIdentity !== finalIdentity) {\n\t\tconst mnemonic = await vaultConnector.getSecret(`${workingIdentity}/mnemonic`);\n\t\tawait vaultConnector.setSecret(`${finalIdentity}/mnemonic`, mnemonic);\n\t\tawait vaultConnector.removeSecret(`${workingIdentity}/mnemonic`);\n\t}\n}\n\n/**\n * Bootstrap the identity for the node.\n * @param engineCore The engine core for the node.\n * @param envVars The environment variables for the node.\n * @param finalIdentity The identity of the node.\n * @param addresses The addresses for the wallet.\n */\nasync function finaliseWallet(\n\tengineCore: IEngineCore,\n\tenvVars: INodeEnvironmentVariables,\n\tfinalIdentity: string,\n\taddresses: string[]\n): Promise<void> {\n\tif (Is.arrayValue(addresses)) {\n\t\tconst defaultWalletConnectorType = engineCore.getRegisteredInstanceType(\"walletConnector\");\n\n\t\t// If we are using entity storage for wallet the identity associated with the\n\t\t// address will be wrong, so fix it\n\t\tif (defaultWalletConnectorType.startsWith(WalletConnectorType.EntityStorage)) {\n\t\t\tconst walletAddress =\n\t\t\t\tEntityStorageConnectorFactory.get<IEntityStorageConnector<WalletAddress>>(\n\t\t\t\t\tnameofKebabCase<WalletAddress>()\n\t\t\t\t);\n\t\t\tconst addr = await walletAddress.get(addresses[0]);\n\t\t\tif (!Is.empty(addr)) {\n\t\t\t\taddr.identity = finalIdentity;\n\t\t\t\tawait walletAddress.set(addr);\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Bootstrap the wallet for the node.\n * @param engineCore The engine core for the node.\n * @param envVars The environment variables for the node.\n * @param identity The identity to create the wallet for.\n * @returns The addresses for the wallet.\n */\nasync function generateWallet(\n\tengineCore: IEngineCore,\n\tenvVars: INodeEnvironmentVariables,\n\tidentity: string\n): Promise<string[]> {\n\tconst defaultWalletConnectorType = engineCore.getRegisteredInstanceType(\"walletConnector\");\n\n\tconst walletConnector = WalletConnectorFactory.get(defaultWalletConnectorType);\n\tconst addresses = await walletConnector.getAddresses(identity, 0, 0, 5);\n\n\tconst balance = await walletConnector.getBalance(identity, addresses[0]);\n\tif (balance === 0n) {\n\t\tlet address0 = addresses[0];\n\n\t\tif (\n\t\t\tdefaultWalletConnectorType.startsWith(WalletConnectorType.Iota) &&\n\t\t\tIs.stringValue(envVars.iotaExplorerEndpoint)\n\t\t) {\n\t\t\taddress0 = `${StringHelper.trimTrailingSlashes(envVars.iotaExplorerEndpoint)}/address/${address0}?network=${envVars.iotaNetwork}`;\n\t\t}\n\n\t\tengineCore.logInfo(I18n.formatMessage(\"node.fundingWallet\", { address: address0 }));\n\n\t\t// Add some funds to the wallet from the faucet\n\t\tawait walletConnector.ensureBalance(identity, addresses[0], 1000000000n);\n\t} else {\n\t\tengineCore.logInfo(I18n.formatMessage(\"node.fundedWallet\"));\n\t}\n\treturn addresses;\n}\n\n/**\n * Bootstrap the identity for the node.\n * @param engineCore The engine core for the node.\n * @param envVars The environment variables for the node.\n * @param controller The controller for the identity.\n * @param identity The existing identity if there is one.\n * @param identityType The type of identity.\n * @returns The addresses for the wallet.\n */\nasync function generateIdentity(\n\tengineCore: IEngineCore,\n\tenvVars: INodeEnvironmentVariables,\n\tcontroller: string,\n\tidentity: string,\n\tidentityType: \"node\" | \"organization\" | \"user\"\n): Promise<string> {\n\tconst defaultIdentityConnectorType = engineCore.getRegisteredInstanceType(\"identityConnector\");\n\n\t// Now create an identity for the node controlled by the address we just funded\n\tconst identityConnector = IdentityConnectorFactory.get(defaultIdentityConnectorType);\n\n\tlet identityDocument;\n\n\ttry {\n\t\tconst defaultIdentityResolverConnectorType = engineCore.getRegisteredInstanceType(\n\t\t\t\"identityResolverConnector\"\n\t\t);\n\n\t\tconst identityResolverConnector = IdentityResolverConnectorFactory.get(\n\t\t\tdefaultIdentityResolverConnectorType\n\t\t);\n\t\tidentityDocument = await identityResolverConnector.resolveDocument(identity);\n\t\tengineCore.logInfo(I18n.formatMessage(\"node.existingIdentity\", { identity }));\n\t} catch {}\n\n\tif (Is.empty(identityDocument)) {\n\t\tengineCore.logInfo(I18n.formatMessage(\"node.generatingIdentity\", { identityType }));\n\n\t\tidentityDocument = await identityConnector.createDocument(controller);\n\n\t\tengineCore.logInfo(\n\t\t\tI18n.formatMessage(\"node.createdIdentity\", { identity: identityDocument.id })\n\t\t);\n\t}\n\n\tif (defaultIdentityConnectorType.startsWith(IdentityConnectorType.Iota)) {\n\t\tconst didUrn = Urn.fromValidString(identityDocument.id);\n\t\tconst didParts = didUrn.parts();\n\t\tconst objectId = didParts[3];\n\n\t\tif (Is.stringValue(envVars.iotaExplorerEndpoint)) {\n\t\t\tengineCore.logInfo(\n\t\t\t\tI18n.formatMessage(\"node.identityExplorer\", {\n\t\t\t\t\turl: `${StringHelper.trimTrailingSlashes(envVars.iotaExplorerEndpoint)}/object/${objectId}?network=${envVars.iotaNetwork}`\n\t\t\t\t})\n\t\t\t);\n\t\t}\n\t}\n\treturn identityDocument.id;\n}\n"]}
package/dist/es/node.js CHANGED
@@ -23,7 +23,7 @@ export async function run(nodeOptions) {
23
23
  nodeOptions ??= {};
24
24
  const serverInfo = {
25
25
  name: nodeOptions?.serverName ?? "TWIN Node Server",
26
- version: nodeOptions?.serverVersion ?? "0.0.3-next.0" // x-release-please-version
26
+ version: nodeOptions?.serverVersion ?? "0.0.3-next.4" // x-release-please-version
27
27
  };
28
28
  CLIDisplay.header(serverInfo.name, serverInfo.version, "🌩️ ");
29
29
  if (!Is.stringValue(nodeOptions?.executionDirectory)) {
@@ -71,9 +71,9 @@ export async function run(nodeOptions) {
71
71
  ...nodeOptions.envVars
72
72
  };
73
73
  }
74
- const { nodeEngineConfig, nodeEnvVars: envVars, contextIdKeys } = await buildConfiguration(finalEnvVars, nodeOptions, serverInfo);
74
+ const { nodeEngineConfig, nodeEnvVars: envVars, availableContextIdKeys } = await buildConfiguration(finalEnvVars, nodeOptions, serverInfo);
75
75
  CLIDisplay.break();
76
- const startResult = await start(nodeOptions, nodeEngineConfig, envVars, contextIdKeys);
76
+ const startResult = await start(nodeOptions, nodeEngineConfig, envVars, availableContextIdKeys);
77
77
  if (!Is.empty(startResult)) {
78
78
  for (const signal of ["SIGHUP", "SIGINT", "SIGTERM"]) {
79
79
  process.on(signal, async () => {
@@ -102,7 +102,7 @@ export async function run(nodeOptions) {
102
102
  * and options.
103
103
  */
104
104
  export async function buildConfiguration(processEnv, options, serverInfo) {
105
- const contextIdKeys = [];
105
+ const availableContextIdKeys = [];
106
106
  let defaultEnvOnly = false;
107
107
  if (Is.empty(options?.envFilenames)) {
108
108
  const envFile = path.resolve(path.join(options.executionDirectory ?? "", ".env"));
@@ -149,8 +149,8 @@ export async function buildConfiguration(processEnv, options, serverInfo) {
149
149
  await options.extendEnvVars(envVars);
150
150
  }
151
151
  // Build the engine configuration from the environment variables.
152
- const coreConfig = await buildEngineConfiguration(envVars, contextIdKeys);
153
- const engineServerConfig = await buildEngineServerConfiguration(envVars, contextIdKeys, coreConfig, serverInfo, options?.openApiSpecFile, options?.favIconFile);
152
+ const coreConfig = await buildEngineConfiguration(envVars, availableContextIdKeys);
153
+ const engineServerConfig = await buildEngineServerConfiguration(envVars, availableContextIdKeys, coreConfig, serverInfo, options?.openApiSpecFile, options?.favIconFile);
154
154
  // Merge any custom configuration provided in the options.
155
155
  if (Is.arrayValue(options?.configFilenames)) {
156
156
  for (const configFile of options.configFilenames) {
@@ -170,7 +170,7 @@ export async function buildConfiguration(processEnv, options, serverInfo) {
170
170
  await options.extendConfig(envVars, engineServerConfig);
171
171
  }
172
172
  const nodeEngineConfig = await extensionsConfiguration(envVars, engineServerConfig);
173
- return { nodeEngineConfig, nodeEnvVars: envVars, contextIdKeys };
173
+ return { nodeEngineConfig, nodeEnvVars: envVars, availableContextIdKeys };
174
174
  }
175
175
  /**
176
176
  * Override module imports to support protocol-based loading (npm:, https:) and local files.
@@ -1 +1 @@
1
- {"version":3,"file":"node.js","sourceRoot":"","sources":["../../src/node.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport { execSync } from \"node:child_process\";\nimport path from \"node:path\";\nimport type { IServerInfo } from \"@twin.org/api-models\";\nimport { CLIDisplay } from \"@twin.org/cli-core\";\nimport { Coerce, EnvHelper, GeneralError, Is } from \"@twin.org/core\";\nimport type { Engine } from \"@twin.org/engine\";\nimport type { EngineServer } from \"@twin.org/engine-server\";\nimport type { IEngineServerConfig } from \"@twin.org/engine-server-types\";\nimport { ModuleHelper } from \"@twin.org/modules\";\nimport * as dotenv from \"dotenv\";\nimport { buildEngineConfiguration } from \"./builders/engineEnvBuilder.js\";\nimport { buildEngineServerConfiguration } from \"./builders/engineServerEnvBuilder.js\";\nimport { extensionsConfiguration } from \"./builders/extensionsBuilder.js\";\nimport type { INodeEngineConfig } from \"./models/INodeEngineConfig.js\";\nimport type { INodeEngineState } from \"./models/INodeEngineState.js\";\nimport type { INodeEnvironmentVariables } from \"./models/INodeEnvironmentVariables.js\";\nimport type { INodeOptions } from \"./models/INodeOptions.js\";\nimport { ModuleProtocol } from \"./models/moduleProtocol.js\";\nimport { start } from \"./server.js\";\nimport {\n\tcreateModuleImportUrl,\n\tfileExists,\n\tgetExecutionDirectory,\n\tgetExtensionsCacheDir,\n\thandleHttpsProtocol,\n\thandleNpmProtocol,\n\tinitialiseLocales,\n\tloadJsonFile,\n\tloadTextFile,\n\tparseModuleProtocol,\n\tresolvePackageEntryPoint\n} from \"./utils.js\";\n\nconst moduleCache: { [id: string]: unknown } = {};\n\n/**\n * Run the TWIN Node server.\n * @param nodeOptions Optional configuration options for running the server.\n * @returns A promise that resolves when the server is started containing a shutdown method.\n */\nexport async function run(nodeOptions?: INodeOptions): Promise<\n\t| {\n\t\t\tengine: Engine<IEngineServerConfig, INodeEngineState>;\n\t\t\tserver: EngineServer;\n\t\t\tshutdown: () => Promise<void>;\n\t }\n\t| undefined\n> {\n\ttry {\n\t\tnodeOptions ??= {};\n\n\t\tconst serverInfo: IServerInfo = {\n\t\t\tname: nodeOptions?.serverName ?? \"TWIN Node Server\",\n\t\t\tversion: nodeOptions?.serverVersion ?? \"0.0.3-next.0\" // x-release-please-version\n\t\t};\n\n\t\tCLIDisplay.header(serverInfo.name, serverInfo.version, \"🌩️ \");\n\n\t\tif (!Is.stringValue(nodeOptions?.executionDirectory)) {\n\t\t\tnodeOptions.executionDirectory = getExecutionDirectory();\n\t\t}\n\t\tCLIDisplay.value(\"Execution Directory\", nodeOptions.executionDirectory);\n\n\t\tnodeOptions.localesDirectory =\n\t\t\tnodeOptions?.localesDirectory ??\n\t\t\tpath.resolve(path.join(nodeOptions.executionDirectory, \"dist\", \"locales\"));\n\t\tCLIDisplay.value(\"Locales Directory\", nodeOptions.localesDirectory);\n\n\t\tawait initialiseLocales(nodeOptions.localesDirectory);\n\n\t\tif (Is.empty(nodeOptions?.openApiSpecFile)) {\n\t\t\tconst specFile = path.resolve(\n\t\t\t\tpath.join(nodeOptions.executionDirectory ?? \"\", \"docs\", \"open-api\", \"spec.json\")\n\t\t\t);\n\t\t\tCLIDisplay.value(\"Default OpenAPI Spec File\", specFile);\n\t\t\tif (await fileExists(specFile)) {\n\t\t\t\tnodeOptions ??= {};\n\t\t\t\tnodeOptions.openApiSpecFile = specFile;\n\t\t\t}\n\t\t} else {\n\t\t\tCLIDisplay.value(\"OpenAPI Spec File\", nodeOptions.openApiSpecFile);\n\t\t}\n\n\t\tif (Is.empty(nodeOptions?.favIconFile)) {\n\t\t\tconst favIconFile = path.resolve(\n\t\t\t\tpath.join(nodeOptions.executionDirectory ?? \"\", \"static\", \"favicon.png\")\n\t\t\t);\n\t\t\tCLIDisplay.value(\"Default Favicon File\", favIconFile);\n\t\t\tif (await fileExists(favIconFile)) {\n\t\t\t\tnodeOptions ??= {};\n\t\t\t\tnodeOptions.favIconFile = favIconFile;\n\t\t\t}\n\t\t} else {\n\t\t\tCLIDisplay.value(\"Favicon File\", nodeOptions.favIconFile);\n\t\t}\n\n\t\tnodeOptions.envPrefix ??= \"TWIN_\";\n\t\tCLIDisplay.value(\"Environment Variable Prefix\", nodeOptions.envPrefix);\n\n\t\toverrideModuleImport(nodeOptions.executionDirectory ?? \"\");\n\n\t\t// This is the only location in the code base that should access process.env directly\n\t\t// So we can safely disable the linting rule here.\n\t\tlet finalEnvVars =\n\t\t\t// eslint-disable-next-line no-restricted-syntax\n\t\t\tprocess.env as {\n\t\t\t\t[id: string]: string;\n\t\t\t};\n\n\t\tif (Is.objectValue(nodeOptions?.envVars)) {\n\t\t\tfinalEnvVars = {\n\t\t\t\t...finalEnvVars,\n\t\t\t\t...nodeOptions.envVars\n\t\t\t};\n\t\t}\n\n\t\tconst {\n\t\t\tnodeEngineConfig,\n\t\t\tnodeEnvVars: envVars,\n\t\t\tcontextIdKeys\n\t\t} = await buildConfiguration(finalEnvVars, nodeOptions, serverInfo);\n\n\t\tCLIDisplay.break();\n\t\tconst startResult = await start(nodeOptions, nodeEngineConfig, envVars, contextIdKeys);\n\n\t\tif (!Is.empty(startResult)) {\n\t\t\tfor (const signal of [\"SIGHUP\", \"SIGINT\", \"SIGTERM\"]) {\n\t\t\t\tprocess.on(signal, async () => {\n\t\t\t\t\tCLIDisplay.value(\"Terminate Signal\", signal);\n\t\t\t\t\tawait startResult.shutdown();\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\treturn startResult;\n\t} catch (err) {\n\t\tif (nodeOptions?.disableProcessExitOnFailure ?? false) {\n\t\t\tthrow err;\n\t\t}\n\t\tCLIDisplay.error(err);\n\t\t// eslint-disable-next-line unicorn/no-process-exit\n\t\tprocess.exit(1);\n\t}\n}\n\n/**\n * Build the configuration for the TWIN Node server.\n * @param processEnv The environment variables from the process.\n * @param options The options for running the server.\n * @param serverInfo The server information.\n * @returns A promise that resolves to the engine server configuration, environment prefix, environment variables,\n * and options.\n */\nexport async function buildConfiguration(\n\tprocessEnv: {\n\t\t[id: string]: string;\n\t},\n\toptions: INodeOptions,\n\tserverInfo: IServerInfo\n): Promise<{\n\tnodeEnvVars: INodeEnvironmentVariables & { [id: string]: string | unknown };\n\tnodeEngineConfig: INodeEngineConfig;\n\tcontextIdKeys: string[];\n}> {\n\tconst contextIdKeys: string[] = [];\n\n\tlet defaultEnvOnly = false;\n\tif (Is.empty(options?.envFilenames)) {\n\t\tconst envFile = path.resolve(path.join(options.executionDirectory ?? \"\", \".env\"));\n\t\tCLIDisplay.value(\"Default Environment File\", envFile);\n\t\toptions ??= {};\n\t\toptions.envFilenames = [envFile];\n\t\tdefaultEnvOnly = true;\n\t}\n\n\tif (Is.arrayValue(options?.envFilenames)) {\n\t\tconst output = dotenv.config({\n\t\t\tpath: options?.envFilenames,\n\t\t\tquiet: true\n\t\t});\n\n\t\t// We don't want to throw an error if the default environment file is not found.\n\t\t// Only if we have custom environment files.\n\t\tif (!defaultEnvOnly && output.error) {\n\t\t\tthrow output.error;\n\t\t}\n\n\t\tif (Is.objectValue(output.parsed)) {\n\t\t\tObject.assign(processEnv, output.parsed);\n\t\t}\n\t}\n\n\tconst envVars = EnvHelper.envToJson<{ [id: string]: string | unknown }>(\n\t\tprocessEnv,\n\t\toptions.envPrefix ?? \"\"\n\t);\n\n\t// Expand any environment variables that use the @file: syntax\n\tconst keys = Object.keys(envVars);\n\tfor (const key of keys) {\n\t\tif (\n\t\t\tIs.stringValue(envVars[key]) &&\n\t\t\t(envVars[key].startsWith(\"@text:\") || envVars[key].startsWith(\"@json:\"))\n\t\t) {\n\t\t\tconst filePath = envVars[key].slice(6).trim();\n\t\t\tconst embeddedFile = path.resolve(path.join(options.executionDirectory ?? \"\", filePath));\n\n\t\t\tif (envVars[key].startsWith(\"@text:\")) {\n\t\t\t\tCLIDisplay.value(`Expanding Environment Variable: ${key} from text file`, embeddedFile);\n\t\t\t\tenvVars[key] = await loadTextFile(embeddedFile);\n\t\t\t} else if (envVars[key].startsWith(\"@json:\")) {\n\t\t\t\tCLIDisplay.value(`Expanding Environment Variable: ${key} from JSON file`, embeddedFile);\n\t\t\t\tenvVars[key] = await loadJsonFile(embeddedFile);\n\t\t\t}\n\t\t}\n\t}\n\n\t// Extend the environment variables with any additional custom configuration.\n\tif (Is.function(options?.extendEnvVars)) {\n\t\tCLIDisplay.task(\"Extending Environment Variables\");\n\t\tawait options.extendEnvVars(envVars);\n\t}\n\n\t// Build the engine configuration from the environment variables.\n\tconst coreConfig = await buildEngineConfiguration(envVars, contextIdKeys);\n\tconst engineServerConfig = await buildEngineServerConfiguration(\n\t\tenvVars,\n\t\tcontextIdKeys,\n\t\tcoreConfig,\n\t\tserverInfo,\n\t\toptions?.openApiSpecFile,\n\t\toptions?.favIconFile\n\t);\n\n\t// Merge any custom configuration provided in the options.\n\tif (Is.arrayValue(options?.configFilenames)) {\n\t\tfor (const configFile of options.configFilenames) {\n\t\t\tCLIDisplay.value(\"Loading Configuration File\", configFile);\n\t\t\tconst configFilePath = path.resolve(path.join(options.executionDirectory ?? \"\", configFile));\n\t\t\tconst config = await loadJsonFile(configFilePath);\n\t\t\tObject.assign(engineServerConfig, config);\n\t\t}\n\t}\n\n\tif (Is.objectValue(options?.config)) {\n\t\tCLIDisplay.task(\"Merging Custom Configuration\");\n\t\tObject.assign(engineServerConfig, options.config);\n\t}\n\n\t// Merge any custom configuration provided in the options.\n\tif (Is.function(options?.extendConfig)) {\n\t\tCLIDisplay.task(\"Extending Configuration\");\n\t\tawait options.extendConfig(envVars, engineServerConfig);\n\t}\n\n\tconst nodeEngineConfig = await extensionsConfiguration(envVars, engineServerConfig);\n\n\treturn { nodeEngineConfig, nodeEnvVars: envVars, contextIdKeys };\n}\n\n/**\n * Override module imports to support protocol-based loading (npm:, https:) and local files.\n * @param executionDirectory The execution directory for resolving local module paths.\n * @param envVars The environment variables containing extension configuration (optional, uses defaults if not provided).\n */\nexport function overrideModuleImport(\n\texecutionDirectory: string,\n\tenvVars?: INodeEnvironmentVariables\n): void {\n\tconst maxSizeMb = Coerce.number(envVars?.extensionsMaxSizeMb) ?? 10;\n\tconst cacheDirectory = envVars?.extensionsCacheDirectory;\n\n\tModuleHelper.overrideImport(async moduleName => {\n\t\tif (moduleCache[moduleName]) {\n\t\t\treturn {\n\t\t\t\tmodule: moduleCache[moduleName],\n\t\t\t\tuseDefault: false\n\t\t\t};\n\t\t}\n\n\t\tconst parsed = parseModuleProtocol(moduleName);\n\t\tlet resolvedPath: string | undefined;\n\n\t\tswitch (parsed.protocol) {\n\t\t\tcase ModuleProtocol.Npm: {\n\t\t\t\tconst result = await handleNpmProtocol(\n\t\t\t\t\tparsed.identifier,\n\t\t\t\t\texecutionDirectory,\n\t\t\t\t\tcacheDirectory\n\t\t\t\t);\n\t\t\t\tresolvedPath = result.resolvedPath;\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase ModuleProtocol.Https: {\n\t\t\t\tconst result = await handleHttpsProtocol(\n\t\t\t\t\tparsed.identifier,\n\t\t\t\t\texecutionDirectory,\n\t\t\t\t\tmaxSizeMb,\n\t\t\t\t\tcacheDirectory,\n\t\t\t\t\tenvVars?.extensionsCacheTtlHours,\n\t\t\t\t\tenvVars?.extensionsForceRefresh\n\t\t\t\t);\n\t\t\t\tresolvedPath = result.resolvedPath;\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase ModuleProtocol.Http: {\n\t\t\t\tthrow new GeneralError(\"node\", \"insecureProtocol\", { protocol: ModuleProtocol.Http });\n\t\t\t}\n\n\t\t\tcase ModuleProtocol.Local: {\n\t\t\t\tlet localFilename = path.resolve(moduleName);\n\n\t\t\t\tlet exists = await fileExists(localFilename);\n\t\t\t\tif (!exists) {\n\t\t\t\t\tlocalFilename = path.resolve(executionDirectory, moduleName);\n\t\t\t\t\texists = await fileExists(localFilename);\n\t\t\t\t}\n\n\t\t\t\tif (exists) {\n\t\t\t\t\tresolvedPath = localFilename;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase ModuleProtocol.Default: {\n\t\t\t\ttry {\n\t\t\t\t\tconst npmRoot = execSync(\"npm root\").toString().trim().replace(/\\\\/g, \"/\");\n\t\t\t\t\tconst packagePath = path.resolve(npmRoot, moduleName);\n\t\t\t\t\tconst mainFile = await resolvePackageEntryPoint(packagePath, moduleName);\n\t\t\t\t\tconst modulePath = path.resolve(packagePath, mainFile);\n\t\t\t\t\tconst exists = await fileExists(modulePath);\n\t\t\t\t\tif (exists) {\n\t\t\t\t\t\tresolvedPath = modulePath;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t} catch {\n\t\t\t\t\t// Continue to fallback resolution\n\t\t\t\t}\n\n\t\t\t\t// Fallback: resolve from npm protocol cache directory (installed via handleNpmProtocol)\n\t\t\t\ttry {\n\t\t\t\t\tconst cacheNpmRoot = path.resolve(\n\t\t\t\t\t\tgetExtensionsCacheDir(executionDirectory, ModuleProtocol.Npm, cacheDirectory),\n\t\t\t\t\t\t\"node_modules\"\n\t\t\t\t\t);\n\n\t\t\t\t\tconst packagePath = path.resolve(cacheNpmRoot, moduleName);\n\t\t\t\t\tconst mainFile = await resolvePackageEntryPoint(packagePath, moduleName);\n\t\t\t\t\tconst modulePath = path.resolve(packagePath, mainFile);\n\t\t\t\t\tconst exists = await fileExists(modulePath);\n\t\t\t\t\tif (exists) {\n\t\t\t\t\t\tresolvedPath = modulePath;\n\t\t\t\t\t}\n\t\t\t\t} catch {\n\t\t\t\t\t// No cached resolution either; fall through\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t// Common module loading and caching logic\n\t\tif (resolvedPath) {\n\t\t\tconst module = await import(createModuleImportUrl(resolvedPath));\n\t\t\tmoduleCache[moduleName] = module;\n\t\t\treturn {\n\t\t\t\tmodule,\n\t\t\t\tuseDefault: false\n\t\t\t};\n\t\t}\n\n\t\treturn {\n\t\t\tmodule: undefined,\n\t\t\tuseDefault: true\n\t\t};\n\t});\n}\n"]}
1
+ {"version":3,"file":"node.js","sourceRoot":"","sources":["../../src/node.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport { execSync } from \"node:child_process\";\nimport path from \"node:path\";\nimport type { IServerInfo } from \"@twin.org/api-models\";\nimport { CLIDisplay } from \"@twin.org/cli-core\";\nimport { Coerce, EnvHelper, GeneralError, Is } from \"@twin.org/core\";\nimport type { Engine } from \"@twin.org/engine\";\nimport type { EngineServer } from \"@twin.org/engine-server\";\nimport type { IEngineServerConfig } from \"@twin.org/engine-server-types\";\nimport { ModuleHelper } from \"@twin.org/modules\";\nimport * as dotenv from \"dotenv\";\nimport { buildEngineConfiguration } from \"./builders/engineEnvBuilder.js\";\nimport { buildEngineServerConfiguration } from \"./builders/engineServerEnvBuilder.js\";\nimport { extensionsConfiguration } from \"./builders/extensionsBuilder.js\";\nimport type { INodeEngineConfig } from \"./models/INodeEngineConfig.js\";\nimport type { INodeEngineState } from \"./models/INodeEngineState.js\";\nimport type { INodeEnvironmentVariables } from \"./models/INodeEnvironmentVariables.js\";\nimport type { INodeOptions } from \"./models/INodeOptions.js\";\nimport { ModuleProtocol } from \"./models/moduleProtocol.js\";\nimport { start } from \"./server.js\";\nimport {\n\tcreateModuleImportUrl,\n\tfileExists,\n\tgetExecutionDirectory,\n\tgetExtensionsCacheDir,\n\thandleHttpsProtocol,\n\thandleNpmProtocol,\n\tinitialiseLocales,\n\tloadJsonFile,\n\tloadTextFile,\n\tparseModuleProtocol,\n\tresolvePackageEntryPoint\n} from \"./utils.js\";\n\nconst moduleCache: { [id: string]: unknown } = {};\n\n/**\n * Run the TWIN Node server.\n * @param nodeOptions Optional configuration options for running the server.\n * @returns A promise that resolves when the server is started containing a shutdown method.\n */\nexport async function run(nodeOptions?: INodeOptions): Promise<\n\t| {\n\t\t\tengine: Engine<IEngineServerConfig, INodeEngineState>;\n\t\t\tserver: EngineServer;\n\t\t\tshutdown: () => Promise<void>;\n\t }\n\t| undefined\n> {\n\ttry {\n\t\tnodeOptions ??= {};\n\n\t\tconst serverInfo: IServerInfo = {\n\t\t\tname: nodeOptions?.serverName ?? \"TWIN Node Server\",\n\t\t\tversion: nodeOptions?.serverVersion ?? \"0.0.3-next.4\" // x-release-please-version\n\t\t};\n\n\t\tCLIDisplay.header(serverInfo.name, serverInfo.version, \"🌩️ \");\n\n\t\tif (!Is.stringValue(nodeOptions?.executionDirectory)) {\n\t\t\tnodeOptions.executionDirectory = getExecutionDirectory();\n\t\t}\n\t\tCLIDisplay.value(\"Execution Directory\", nodeOptions.executionDirectory);\n\n\t\tnodeOptions.localesDirectory =\n\t\t\tnodeOptions?.localesDirectory ??\n\t\t\tpath.resolve(path.join(nodeOptions.executionDirectory, \"dist\", \"locales\"));\n\t\tCLIDisplay.value(\"Locales Directory\", nodeOptions.localesDirectory);\n\n\t\tawait initialiseLocales(nodeOptions.localesDirectory);\n\n\t\tif (Is.empty(nodeOptions?.openApiSpecFile)) {\n\t\t\tconst specFile = path.resolve(\n\t\t\t\tpath.join(nodeOptions.executionDirectory ?? \"\", \"docs\", \"open-api\", \"spec.json\")\n\t\t\t);\n\t\t\tCLIDisplay.value(\"Default OpenAPI Spec File\", specFile);\n\t\t\tif (await fileExists(specFile)) {\n\t\t\t\tnodeOptions ??= {};\n\t\t\t\tnodeOptions.openApiSpecFile = specFile;\n\t\t\t}\n\t\t} else {\n\t\t\tCLIDisplay.value(\"OpenAPI Spec File\", nodeOptions.openApiSpecFile);\n\t\t}\n\n\t\tif (Is.empty(nodeOptions?.favIconFile)) {\n\t\t\tconst favIconFile = path.resolve(\n\t\t\t\tpath.join(nodeOptions.executionDirectory ?? \"\", \"static\", \"favicon.png\")\n\t\t\t);\n\t\t\tCLIDisplay.value(\"Default Favicon File\", favIconFile);\n\t\t\tif (await fileExists(favIconFile)) {\n\t\t\t\tnodeOptions ??= {};\n\t\t\t\tnodeOptions.favIconFile = favIconFile;\n\t\t\t}\n\t\t} else {\n\t\t\tCLIDisplay.value(\"Favicon File\", nodeOptions.favIconFile);\n\t\t}\n\n\t\tnodeOptions.envPrefix ??= \"TWIN_\";\n\t\tCLIDisplay.value(\"Environment Variable Prefix\", nodeOptions.envPrefix);\n\n\t\toverrideModuleImport(nodeOptions.executionDirectory ?? \"\");\n\n\t\t// This is the only location in the code base that should access process.env directly\n\t\t// So we can safely disable the linting rule here.\n\t\tlet finalEnvVars =\n\t\t\t// eslint-disable-next-line no-restricted-syntax\n\t\t\tprocess.env as {\n\t\t\t\t[id: string]: string;\n\t\t\t};\n\n\t\tif (Is.objectValue(nodeOptions?.envVars)) {\n\t\t\tfinalEnvVars = {\n\t\t\t\t...finalEnvVars,\n\t\t\t\t...nodeOptions.envVars\n\t\t\t};\n\t\t}\n\n\t\tconst {\n\t\t\tnodeEngineConfig,\n\t\t\tnodeEnvVars: envVars,\n\t\t\tavailableContextIdKeys\n\t\t} = await buildConfiguration(finalEnvVars, nodeOptions, serverInfo);\n\n\t\tCLIDisplay.break();\n\t\tconst startResult = await start(nodeOptions, nodeEngineConfig, envVars, availableContextIdKeys);\n\n\t\tif (!Is.empty(startResult)) {\n\t\t\tfor (const signal of [\"SIGHUP\", \"SIGINT\", \"SIGTERM\"]) {\n\t\t\t\tprocess.on(signal, async () => {\n\t\t\t\t\tCLIDisplay.value(\"Terminate Signal\", signal);\n\t\t\t\t\tawait startResult.shutdown();\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\treturn startResult;\n\t} catch (err) {\n\t\tif (nodeOptions?.disableProcessExitOnFailure ?? false) {\n\t\t\tthrow err;\n\t\t}\n\t\tCLIDisplay.error(err);\n\t\t// eslint-disable-next-line unicorn/no-process-exit\n\t\tprocess.exit(1);\n\t}\n}\n\n/**\n * Build the configuration for the TWIN Node server.\n * @param processEnv The environment variables from the process.\n * @param options The options for running the server.\n * @param serverInfo The server information.\n * @returns A promise that resolves to the engine server configuration, environment prefix, environment variables,\n * and options.\n */\nexport async function buildConfiguration(\n\tprocessEnv: {\n\t\t[id: string]: string;\n\t},\n\toptions: INodeOptions,\n\tserverInfo: IServerInfo\n): Promise<{\n\tnodeEnvVars: INodeEnvironmentVariables & { [id: string]: string | unknown };\n\tnodeEngineConfig: INodeEngineConfig;\n\tavailableContextIdKeys: { key: string; componentFeatures: string[] }[];\n}> {\n\tconst availableContextIdKeys: { key: string; componentFeatures: string[] }[] = [];\n\n\tlet defaultEnvOnly = false;\n\tif (Is.empty(options?.envFilenames)) {\n\t\tconst envFile = path.resolve(path.join(options.executionDirectory ?? \"\", \".env\"));\n\t\tCLIDisplay.value(\"Default Environment File\", envFile);\n\t\toptions ??= {};\n\t\toptions.envFilenames = [envFile];\n\t\tdefaultEnvOnly = true;\n\t}\n\n\tif (Is.arrayValue(options?.envFilenames)) {\n\t\tconst output = dotenv.config({\n\t\t\tpath: options?.envFilenames,\n\t\t\tquiet: true\n\t\t});\n\n\t\t// We don't want to throw an error if the default environment file is not found.\n\t\t// Only if we have custom environment files.\n\t\tif (!defaultEnvOnly && output.error) {\n\t\t\tthrow output.error;\n\t\t}\n\n\t\tif (Is.objectValue(output.parsed)) {\n\t\t\tObject.assign(processEnv, output.parsed);\n\t\t}\n\t}\n\n\tconst envVars = EnvHelper.envToJson<{ [id: string]: string | unknown }>(\n\t\tprocessEnv,\n\t\toptions.envPrefix ?? \"\"\n\t);\n\n\t// Expand any environment variables that use the @file: syntax\n\tconst keys = Object.keys(envVars);\n\tfor (const key of keys) {\n\t\tif (\n\t\t\tIs.stringValue(envVars[key]) &&\n\t\t\t(envVars[key].startsWith(\"@text:\") || envVars[key].startsWith(\"@json:\"))\n\t\t) {\n\t\t\tconst filePath = envVars[key].slice(6).trim();\n\t\t\tconst embeddedFile = path.resolve(path.join(options.executionDirectory ?? \"\", filePath));\n\n\t\t\tif (envVars[key].startsWith(\"@text:\")) {\n\t\t\t\tCLIDisplay.value(`Expanding Environment Variable: ${key} from text file`, embeddedFile);\n\t\t\t\tenvVars[key] = await loadTextFile(embeddedFile);\n\t\t\t} else if (envVars[key].startsWith(\"@json:\")) {\n\t\t\t\tCLIDisplay.value(`Expanding Environment Variable: ${key} from JSON file`, embeddedFile);\n\t\t\t\tenvVars[key] = await loadJsonFile(embeddedFile);\n\t\t\t}\n\t\t}\n\t}\n\n\t// Extend the environment variables with any additional custom configuration.\n\tif (Is.function(options?.extendEnvVars)) {\n\t\tCLIDisplay.task(\"Extending Environment Variables\");\n\t\tawait options.extendEnvVars(envVars);\n\t}\n\n\t// Build the engine configuration from the environment variables.\n\tconst coreConfig = await buildEngineConfiguration(envVars, availableContextIdKeys);\n\tconst engineServerConfig = await buildEngineServerConfiguration(\n\t\tenvVars,\n\t\tavailableContextIdKeys,\n\t\tcoreConfig,\n\t\tserverInfo,\n\t\toptions?.openApiSpecFile,\n\t\toptions?.favIconFile\n\t);\n\n\t// Merge any custom configuration provided in the options.\n\tif (Is.arrayValue(options?.configFilenames)) {\n\t\tfor (const configFile of options.configFilenames) {\n\t\t\tCLIDisplay.value(\"Loading Configuration File\", configFile);\n\t\t\tconst configFilePath = path.resolve(path.join(options.executionDirectory ?? \"\", configFile));\n\t\t\tconst config = await loadJsonFile(configFilePath);\n\t\t\tObject.assign(engineServerConfig, config);\n\t\t}\n\t}\n\n\tif (Is.objectValue(options?.config)) {\n\t\tCLIDisplay.task(\"Merging Custom Configuration\");\n\t\tObject.assign(engineServerConfig, options.config);\n\t}\n\n\t// Merge any custom configuration provided in the options.\n\tif (Is.function(options?.extendConfig)) {\n\t\tCLIDisplay.task(\"Extending Configuration\");\n\t\tawait options.extendConfig(envVars, engineServerConfig);\n\t}\n\n\tconst nodeEngineConfig = await extensionsConfiguration(envVars, engineServerConfig);\n\n\treturn { nodeEngineConfig, nodeEnvVars: envVars, availableContextIdKeys };\n}\n\n/**\n * Override module imports to support protocol-based loading (npm:, https:) and local files.\n * @param executionDirectory The execution directory for resolving local module paths.\n * @param envVars The environment variables containing extension configuration (optional, uses defaults if not provided).\n */\nexport function overrideModuleImport(\n\texecutionDirectory: string,\n\tenvVars?: INodeEnvironmentVariables\n): void {\n\tconst maxSizeMb = Coerce.number(envVars?.extensionsMaxSizeMb) ?? 10;\n\tconst cacheDirectory = envVars?.extensionsCacheDirectory;\n\n\tModuleHelper.overrideImport(async moduleName => {\n\t\tif (moduleCache[moduleName]) {\n\t\t\treturn {\n\t\t\t\tmodule: moduleCache[moduleName],\n\t\t\t\tuseDefault: false\n\t\t\t};\n\t\t}\n\n\t\tconst parsed = parseModuleProtocol(moduleName);\n\t\tlet resolvedPath: string | undefined;\n\n\t\tswitch (parsed.protocol) {\n\t\t\tcase ModuleProtocol.Npm: {\n\t\t\t\tconst result = await handleNpmProtocol(\n\t\t\t\t\tparsed.identifier,\n\t\t\t\t\texecutionDirectory,\n\t\t\t\t\tcacheDirectory\n\t\t\t\t);\n\t\t\t\tresolvedPath = result.resolvedPath;\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase ModuleProtocol.Https: {\n\t\t\t\tconst result = await handleHttpsProtocol(\n\t\t\t\t\tparsed.identifier,\n\t\t\t\t\texecutionDirectory,\n\t\t\t\t\tmaxSizeMb,\n\t\t\t\t\tcacheDirectory,\n\t\t\t\t\tenvVars?.extensionsCacheTtlHours,\n\t\t\t\t\tenvVars?.extensionsForceRefresh\n\t\t\t\t);\n\t\t\t\tresolvedPath = result.resolvedPath;\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase ModuleProtocol.Http: {\n\t\t\t\tthrow new GeneralError(\"node\", \"insecureProtocol\", { protocol: ModuleProtocol.Http });\n\t\t\t}\n\n\t\t\tcase ModuleProtocol.Local: {\n\t\t\t\tlet localFilename = path.resolve(moduleName);\n\n\t\t\t\tlet exists = await fileExists(localFilename);\n\t\t\t\tif (!exists) {\n\t\t\t\t\tlocalFilename = path.resolve(executionDirectory, moduleName);\n\t\t\t\t\texists = await fileExists(localFilename);\n\t\t\t\t}\n\n\t\t\t\tif (exists) {\n\t\t\t\t\tresolvedPath = localFilename;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase ModuleProtocol.Default: {\n\t\t\t\ttry {\n\t\t\t\t\tconst npmRoot = execSync(\"npm root\").toString().trim().replace(/\\\\/g, \"/\");\n\t\t\t\t\tconst packagePath = path.resolve(npmRoot, moduleName);\n\t\t\t\t\tconst mainFile = await resolvePackageEntryPoint(packagePath, moduleName);\n\t\t\t\t\tconst modulePath = path.resolve(packagePath, mainFile);\n\t\t\t\t\tconst exists = await fileExists(modulePath);\n\t\t\t\t\tif (exists) {\n\t\t\t\t\t\tresolvedPath = modulePath;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t} catch {\n\t\t\t\t\t// Continue to fallback resolution\n\t\t\t\t}\n\n\t\t\t\t// Fallback: resolve from npm protocol cache directory (installed via handleNpmProtocol)\n\t\t\t\ttry {\n\t\t\t\t\tconst cacheNpmRoot = path.resolve(\n\t\t\t\t\t\tgetExtensionsCacheDir(executionDirectory, ModuleProtocol.Npm, cacheDirectory),\n\t\t\t\t\t\t\"node_modules\"\n\t\t\t\t\t);\n\n\t\t\t\t\tconst packagePath = path.resolve(cacheNpmRoot, moduleName);\n\t\t\t\t\tconst mainFile = await resolvePackageEntryPoint(packagePath, moduleName);\n\t\t\t\t\tconst modulePath = path.resolve(packagePath, mainFile);\n\t\t\t\t\tconst exists = await fileExists(modulePath);\n\t\t\t\t\tif (exists) {\n\t\t\t\t\t\tresolvedPath = modulePath;\n\t\t\t\t\t}\n\t\t\t\t} catch {\n\t\t\t\t\t// No cached resolution either; fall through\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t// Common module loading and caching logic\n\t\tif (resolvedPath) {\n\t\t\tconst module = await import(createModuleImportUrl(resolvedPath));\n\t\t\tmoduleCache[moduleName] = module;\n\t\t\treturn {\n\t\t\t\tmodule,\n\t\t\t\tuseDefault: false\n\t\t\t};\n\t\t}\n\n\t\treturn {\n\t\t\tmodule: undefined,\n\t\t\tuseDefault: true\n\t\t};\n\t});\n}\n"]}
package/dist/es/server.js CHANGED
@@ -14,10 +14,10 @@ let isStarted = false;
14
14
  * @param nodeOptions Optional run options for the engine server.
15
15
  * @param nodeEngineConfig The configuration for the engine server.
16
16
  * @param envVars The environment variables.
17
- * @param contextIdKeys The context ID keys.
17
+ * @param availableContextIdKeys The context ID keys available for operation.
18
18
  * @returns The engine server.
19
19
  */
20
- export async function start(nodeOptions, nodeEngineConfig, envVars, contextIdKeys) {
20
+ export async function start(nodeOptions, nodeEngineConfig, envVars, availableContextIdKeys) {
21
21
  const entityStorageConnectorType = envVars.entityStorageConnectorType?.split(",") ?? [];
22
22
  const blobStorageConnectorType = envVars.blobStorageConnectorType?.split(",") ?? [];
23
23
  // If the blob storage or entity storage is configured with file connectors
@@ -36,10 +36,13 @@ export async function start(nodeOptions, nodeEngineConfig, envVars, contextIdKey
36
36
  stateStorage: nodeOptions?.stateStorage ?? new FileStateStorage(envVars.stateFilename ?? ""),
37
37
  customBootstrap: async (core, engineContext) => bootstrap(core, engineContext, envVars)
38
38
  });
39
- if (Is.arrayValue(contextIdKeys)) {
40
- const uniqueContextIdKeys = Array.from(new Set(contextIdKeys));
41
- for (const contextIdKey of uniqueContextIdKeys) {
42
- engine.addContextIdKey(contextIdKey);
39
+ if (Is.arrayValue(availableContextIdKeys)) {
40
+ const added = [];
41
+ for (const availableContextIdKey of availableContextIdKeys) {
42
+ if (!added.includes(availableContextIdKey.key)) {
43
+ engine.addContextIdKey(availableContextIdKey.key, availableContextIdKey.componentFeatures);
44
+ added.push(availableContextIdKey.key);
45
+ }
43
46
  }
44
47
  }
45
48
  // Construct the server with the engine.
@@ -1 +1 @@
1
- {"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/server.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport { GeneralError, I18n, Is } from \"@twin.org/core\";\nimport { Engine } from \"@twin.org/engine\";\nimport { FileStateStorage } from \"@twin.org/engine-core\";\nimport { EngineCoreFactory } from \"@twin.org/engine-models\";\nimport { EngineServer } from \"@twin.org/engine-server\";\nimport type { IEngineServerConfig } from \"@twin.org/engine-server-types\";\nimport { BlobStorageConnectorType, EntityStorageConnectorType } from \"@twin.org/engine-types\";\nimport { bootstrap } from \"./bootstrap.js\";\nimport {\n\textensionsInitialiseEngine,\n\textensionsInitialiseEngineServer,\n\tshutdownExtensions\n} from \"./builders/extensionsBuilder.js\";\nimport type { INodeEngineConfig } from \"./models/INodeEngineConfig.js\";\nimport type { INodeEngineState } from \"./models/INodeEngineState.js\";\nimport type { INodeEnvironmentVariables } from \"./models/INodeEnvironmentVariables.js\";\nimport type { INodeOptions } from \"./models/INodeOptions.js\";\n\nlet isStarted = false;\n\n/**\n * Start the engine server.\n * @param nodeOptions Optional run options for the engine server.\n * @param nodeEngineConfig The configuration for the engine server.\n * @param envVars The environment variables.\n * @param contextIdKeys The context ID keys.\n * @returns The engine server.\n */\nexport async function start(\n\tnodeOptions: INodeOptions | undefined,\n\tnodeEngineConfig: INodeEngineConfig,\n\tenvVars: INodeEnvironmentVariables,\n\tcontextIdKeys?: string[]\n): Promise<\n\t| {\n\t\t\tengine: Engine<IEngineServerConfig, INodeEngineState>;\n\t\t\tserver: EngineServer;\n\t\t\tshutdown: () => Promise<void>;\n\t }\n\t| undefined\n> {\n\tconst entityStorageConnectorType = envVars.entityStorageConnectorType?.split(\",\") ?? [];\n\tconst blobStorageConnectorType = envVars.blobStorageConnectorType?.split(\",\") ?? [];\n\n\t// If the blob storage or entity storage is configured with file connectors\n\t// then we need to make sure the storageFileRoot is set\n\tif (\n\t\t(entityStorageConnectorType.includes(EntityStorageConnectorType.File) ||\n\t\t\tblobStorageConnectorType.includes(BlobStorageConnectorType.File) ||\n\t\t\tIs.empty(nodeOptions?.stateStorage)) &&\n\t\t!Is.stringValue(envVars.storageFileRoot)\n\t) {\n\t\tthrow new GeneralError(\"node\", \"storageFileRootNotSet\", {\n\t\t\tstorageFileRoot: `${nodeOptions?.envPrefix ?? \"\"}STORAGE_FILE_ROOT`\n\t\t});\n\t}\n\n\t// Create the engine instance using file state storage unless one is configured in options\n\tconst engine = new Engine<IEngineServerConfig, INodeEngineState>({\n\t\tconfig: nodeEngineConfig,\n\t\tstateStorage: nodeOptions?.stateStorage ?? new FileStateStorage(envVars.stateFilename ?? \"\"),\n\t\tcustomBootstrap: async (core, engineContext) => bootstrap(core, engineContext, envVars)\n\t});\n\n\tif (Is.arrayValue(contextIdKeys)) {\n\t\tconst uniqueContextIdKeys = Array.from(new Set(contextIdKeys));\n\t\tfor (const contextIdKey of uniqueContextIdKeys) {\n\t\t\tengine.addContextIdKey(contextIdKey);\n\t\t}\n\t}\n\n\t// Construct the server with the engine.\n\tconst server = new EngineServer({ engineCore: engine });\n\n\t// Extend the engine.\n\tif (Is.function(nodeOptions?.extendEngine)) {\n\t\tawait engine.logInfo(I18n.formatMessage(\"node.extendingEngine\"));\n\t\tawait nodeOptions.extendEngine(engine);\n\t}\n\n\tawait extensionsInitialiseEngine(envVars, engine);\n\n\t// Extend the engine server.\n\tif (Is.function(nodeOptions?.extendEngineServer)) {\n\t\tawait engine.logInfo(I18n.formatMessage(\"node.extendingEngineServer\"));\n\t\tawait nodeOptions?.extendEngineServer(server);\n\t}\n\n\tawait extensionsInitialiseEngineServer(envVars, engine, server);\n\n\t// Need to register the engine with the factory so that background tasks\n\t// can clone it to spawn new instances.\n\tEngineCoreFactory.register(\"engine\", () => engine);\n\n\t// Start the server, which also starts the engine.\n\tisStarted = await server.start();\n\n\tif (isStarted) {\n\t\treturn {\n\t\t\tengine,\n\t\t\tserver,\n\t\t\tshutdown: async () => {\n\t\t\t\tif (isStarted) {\n\t\t\t\t\tisStarted = false;\n\t\t\t\t\tawait shutdownExtensions(envVars, engine);\n\t\t\t\t\tawait server.stop();\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t}\n}\n"]}
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/server.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport { GeneralError, I18n, Is } from \"@twin.org/core\";\nimport { Engine } from \"@twin.org/engine\";\nimport { FileStateStorage } from \"@twin.org/engine-core\";\nimport { EngineCoreFactory } from \"@twin.org/engine-models\";\nimport { EngineServer } from \"@twin.org/engine-server\";\nimport type { IEngineServerConfig } from \"@twin.org/engine-server-types\";\nimport { BlobStorageConnectorType, EntityStorageConnectorType } from \"@twin.org/engine-types\";\nimport { bootstrap } from \"./bootstrap.js\";\nimport {\n\textensionsInitialiseEngine,\n\textensionsInitialiseEngineServer,\n\tshutdownExtensions\n} from \"./builders/extensionsBuilder.js\";\nimport type { INodeEngineConfig } from \"./models/INodeEngineConfig.js\";\nimport type { INodeEngineState } from \"./models/INodeEngineState.js\";\nimport type { INodeEnvironmentVariables } from \"./models/INodeEnvironmentVariables.js\";\nimport type { INodeOptions } from \"./models/INodeOptions.js\";\n\nlet isStarted = false;\n\n/**\n * Start the engine server.\n * @param nodeOptions Optional run options for the engine server.\n * @param nodeEngineConfig The configuration for the engine server.\n * @param envVars The environment variables.\n * @param availableContextIdKeys The context ID keys available for operation.\n * @returns The engine server.\n */\nexport async function start(\n\tnodeOptions: INodeOptions | undefined,\n\tnodeEngineConfig: INodeEngineConfig,\n\tenvVars: INodeEnvironmentVariables,\n\tavailableContextIdKeys?: { key: string; componentFeatures: string[] }[]\n): Promise<\n\t| {\n\t\t\tengine: Engine<IEngineServerConfig, INodeEngineState>;\n\t\t\tserver: EngineServer;\n\t\t\tshutdown: () => Promise<void>;\n\t }\n\t| undefined\n> {\n\tconst entityStorageConnectorType = envVars.entityStorageConnectorType?.split(\",\") ?? [];\n\tconst blobStorageConnectorType = envVars.blobStorageConnectorType?.split(\",\") ?? [];\n\n\t// If the blob storage or entity storage is configured with file connectors\n\t// then we need to make sure the storageFileRoot is set\n\tif (\n\t\t(entityStorageConnectorType.includes(EntityStorageConnectorType.File) ||\n\t\t\tblobStorageConnectorType.includes(BlobStorageConnectorType.File) ||\n\t\t\tIs.empty(nodeOptions?.stateStorage)) &&\n\t\t!Is.stringValue(envVars.storageFileRoot)\n\t) {\n\t\tthrow new GeneralError(\"node\", \"storageFileRootNotSet\", {\n\t\t\tstorageFileRoot: `${nodeOptions?.envPrefix ?? \"\"}STORAGE_FILE_ROOT`\n\t\t});\n\t}\n\n\t// Create the engine instance using file state storage unless one is configured in options\n\tconst engine = new Engine<IEngineServerConfig, INodeEngineState>({\n\t\tconfig: nodeEngineConfig,\n\t\tstateStorage: nodeOptions?.stateStorage ?? new FileStateStorage(envVars.stateFilename ?? \"\"),\n\t\tcustomBootstrap: async (core, engineContext) => bootstrap(core, engineContext, envVars)\n\t});\n\n\tif (Is.arrayValue(availableContextIdKeys)) {\n\t\tconst added: string[] = [];\n\t\tfor (const availableContextIdKey of availableContextIdKeys) {\n\t\t\tif (!added.includes(availableContextIdKey.key)) {\n\t\t\t\tengine.addContextIdKey(availableContextIdKey.key, availableContextIdKey.componentFeatures);\n\t\t\t\tadded.push(availableContextIdKey.key);\n\t\t\t}\n\t\t}\n\t}\n\n\t// Construct the server with the engine.\n\tconst server = new EngineServer({ engineCore: engine });\n\n\t// Extend the engine.\n\tif (Is.function(nodeOptions?.extendEngine)) {\n\t\tawait engine.logInfo(I18n.formatMessage(\"node.extendingEngine\"));\n\t\tawait nodeOptions.extendEngine(engine);\n\t}\n\n\tawait extensionsInitialiseEngine(envVars, engine);\n\n\t// Extend the engine server.\n\tif (Is.function(nodeOptions?.extendEngineServer)) {\n\t\tawait engine.logInfo(I18n.formatMessage(\"node.extendingEngineServer\"));\n\t\tawait nodeOptions?.extendEngineServer(server);\n\t}\n\n\tawait extensionsInitialiseEngineServer(envVars, engine, server);\n\n\t// Need to register the engine with the factory so that background tasks\n\t// can clone it to spawn new instances.\n\tEngineCoreFactory.register(\"engine\", () => engine);\n\n\t// Start the server, which also starts the engine.\n\tisStarted = await server.start();\n\n\tif (isStarted) {\n\t\treturn {\n\t\t\tengine,\n\t\t\tserver,\n\t\t\tshutdown: async () => {\n\t\t\t\tif (isStarted) {\n\t\t\t\t\tisStarted = false;\n\t\t\t\t\tawait shutdownExtensions(envVars, engine);\n\t\t\t\t\tawait server.stop();\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t}\n}\n"]}
@@ -10,14 +10,6 @@ import { NodeFeatures } from "./models/nodeFeatures.js";
10
10
  * @param envVars The environment variables for the node.
11
11
  */
12
12
  export declare function bootstrap(engineCore: IEngineCore, context: IEngineCoreContext<IEngineServerConfig, INodeEngineState>, envVars: INodeEnvironmentVariables): Promise<void>;
13
- /**
14
- * Bootstrap the context id handlers creating any necessary resources.
15
- * @param engineCore The engine core for the node.
16
- * @param context The context for the node.
17
- * @param envVars The environment variables for the node.
18
- * @param features The features that are enabled on the node. The features that are enabled on the node.
19
- */
20
- export declare function bootstrapContextIdHandlers(engineCore: IEngineCore, context: IEngineCoreContext<IEngineServerConfig, INodeEngineState>, envVars: INodeEnvironmentVariables, features: NodeFeatures[]): Promise<void>;
21
13
  /**
22
14
  * Bootstrap the node creating any necessary resources.
23
15
  * @param engineCore The engine core for the node.
@@ -6,4 +6,7 @@ import type { IEngineEnvironmentVariables } from "../models/IEngineEnvironmentVa
6
6
  * @param contextIdKeys The context ID keys.
7
7
  * @returns The config for the core.
8
8
  */
9
- export declare function buildEngineConfiguration(envVars: IEngineEnvironmentVariables, contextIdKeys: string[]): Promise<IEngineConfig>;
9
+ export declare function buildEngineConfiguration(envVars: IEngineEnvironmentVariables, contextIdKeys: {
10
+ key: string;
11
+ componentFeatures: string[];
12
+ }[]): Promise<IEngineConfig>;
@@ -5,11 +5,14 @@ import type { IEngineServerEnvironmentVariables } from "../models/IEngineServerE
5
5
  /**
6
6
  * Handles the configuration of the server.
7
7
  * @param envVars The environment variables for the engine server.
8
- * @param contextIdKeys The context ID keys.
8
+ * @param availableContextIdKeys The context ID keys.
9
9
  * @param coreEngineConfig The core engine config.
10
10
  * @param serverInfo The server information.
11
11
  * @param openApiSpecPath The path to the open api spec.
12
12
  * @param favIconPath The path to the favicon.
13
13
  * @returns The config for the core and the server.
14
14
  */
15
- export declare function buildEngineServerConfiguration(envVars: IEngineServerEnvironmentVariables, contextIdKeys: string[], coreEngineConfig: IEngineCoreConfig, serverInfo: IServerInfo, openApiSpecPath?: string, favIconPath?: string): Promise<IEngineServerConfig>;
15
+ export declare function buildEngineServerConfiguration(envVars: IEngineServerEnvironmentVariables, availableContextIdKeys: {
16
+ key: string;
17
+ componentFeatures: string[];
18
+ }[], coreEngineConfig: IEngineCoreConfig, serverInfo: IServerInfo, openApiSpecPath?: string, favIconPath?: string): Promise<IEngineServerConfig>;
@@ -4,3 +4,5 @@ export declare const BLOB_STORAGE_ENCRYPTION_KEY_ID = "blob-encryption";
4
4
  export declare const SYNCHRONISED_STORAGE_BLOB_STORAGE_ENCRYPTION_KEY_ID = "synchronised-storage-blob-encryption";
5
5
  export declare const VC_AUTHENTICATION_VERIFICATION_METHOD_ID = "node-authentication-assertion";
6
6
  export declare const AUTH_SIGNING_KEY_ID = "auth-signing";
7
+ export declare const CONTEXT_ID_HANDLER_FEATURE_DID = "did";
8
+ export declare const CONTEXT_ID_HANDLER_FEATURE_TENANT = "tenant";
@@ -31,7 +31,10 @@ export declare function buildConfiguration(processEnv: {
31
31
  [id: string]: string | unknown;
32
32
  };
33
33
  nodeEngineConfig: INodeEngineConfig;
34
- contextIdKeys: string[];
34
+ availableContextIdKeys: {
35
+ key: string;
36
+ componentFeatures: string[];
37
+ }[];
35
38
  }>;
36
39
  /**
37
40
  * Override module imports to support protocol-based loading (npm:, https:) and local files.
@@ -10,10 +10,13 @@ import type { INodeOptions } from "./models/INodeOptions.js";
10
10
  * @param nodeOptions Optional run options for the engine server.
11
11
  * @param nodeEngineConfig The configuration for the engine server.
12
12
  * @param envVars The environment variables.
13
- * @param contextIdKeys The context ID keys.
13
+ * @param availableContextIdKeys The context ID keys available for operation.
14
14
  * @returns The engine server.
15
15
  */
16
- export declare function start(nodeOptions: INodeOptions | undefined, nodeEngineConfig: INodeEngineConfig, envVars: INodeEnvironmentVariables, contextIdKeys?: string[]): Promise<{
16
+ export declare function start(nodeOptions: INodeOptions | undefined, nodeEngineConfig: INodeEngineConfig, envVars: INodeEnvironmentVariables, availableContextIdKeys?: {
17
+ key: string;
18
+ componentFeatures: string[];
19
+ }[]): Promise<{
17
20
  engine: Engine<IEngineServerConfig, INodeEngineState>;
18
21
  server: EngineServer;
19
22
  shutdown: () => Promise<void>;
package/docs/changelog.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # @twin.org/node-core - Changelog
2
2
 
3
+ ## [0.0.3-next.4](https://github.com/twinfoundation/node/compare/node-core-v0.0.3-next.3...node-core-v0.0.3-next.4) (2025-11-24)
4
+
5
+
6
+ ### Bug Fixes
7
+
8
+ * org identity verification methods ([18f158b](https://github.com/twinfoundation/node/commit/18f158b2f63930e20e94437c17ed43421771a458))
9
+
10
+ ## [0.0.3-next.3](https://github.com/twinfoundation/node/compare/node-core-v0.0.3-next.2...node-core-v0.0.3-next.3) (2025-11-20)
11
+
12
+
13
+ ### Features
14
+
15
+ * updated context id features ([ef7be07](https://github.com/twinfoundation/node/commit/ef7be07d44dccdeacf10f90cb4ffde0303faa6fa))
16
+
3
17
  ## [0.0.3-next.2](https://github.com/twinfoundation/node/compare/node-core-v0.0.3-next.1...node-core-v0.0.3-next.2) (2025-11-14)
4
18
 
5
19
 
@@ -1,6 +1,6 @@
1
1
  # Function: buildConfiguration()
2
2
 
3
- > **buildConfiguration**(`processEnv`, `options`, `serverInfo`): `Promise`\<\{ `nodeEnvVars`: [`INodeEnvironmentVariables`](../interfaces/INodeEnvironmentVariables.md) & `object`; `nodeEngineConfig`: [`INodeEngineConfig`](../interfaces/INodeEngineConfig.md); `contextIdKeys`: `string`[]; \}\>
3
+ > **buildConfiguration**(`processEnv`, `options`, `serverInfo`): `Promise`\<\{ `nodeEnvVars`: [`INodeEnvironmentVariables`](../interfaces/INodeEnvironmentVariables.md) & `object`; `nodeEngineConfig`: [`INodeEngineConfig`](../interfaces/INodeEngineConfig.md); `availableContextIdKeys`: `object`[]; \}\>
4
4
 
5
5
  Build the configuration for the TWIN Node server.
6
6
 
@@ -24,7 +24,7 @@ The server information.
24
24
 
25
25
  ## Returns
26
26
 
27
- `Promise`\<\{ `nodeEnvVars`: [`INodeEnvironmentVariables`](../interfaces/INodeEnvironmentVariables.md) & `object`; `nodeEngineConfig`: [`INodeEngineConfig`](../interfaces/INodeEngineConfig.md); `contextIdKeys`: `string`[]; \}\>
27
+ `Promise`\<\{ `nodeEnvVars`: [`INodeEnvironmentVariables`](../interfaces/INodeEnvironmentVariables.md) & `object`; `nodeEngineConfig`: [`INodeEngineConfig`](../interfaces/INodeEngineConfig.md); `availableContextIdKeys`: `object`[]; \}\>
28
28
 
29
29
  A promise that resolves to the engine server configuration, environment prefix, environment variables,
30
30
  and options.
@@ -14,7 +14,7 @@ The environment variables.
14
14
 
15
15
  ### contextIdKeys
16
16
 
17
- `string`[]
17
+ `object`[]
18
18
 
19
19
  The context ID keys.
20
20
 
@@ -1,6 +1,6 @@
1
1
  # Function: buildEngineServerConfiguration()
2
2
 
3
- > **buildEngineServerConfiguration**(`envVars`, `contextIdKeys`, `coreEngineConfig`, `serverInfo`, `openApiSpecPath?`, `favIconPath?`): `Promise`\<`IEngineServerConfig`\>
3
+ > **buildEngineServerConfiguration**(`envVars`, `availableContextIdKeys`, `coreEngineConfig`, `serverInfo`, `openApiSpecPath?`, `favIconPath?`): `Promise`\<`IEngineServerConfig`\>
4
4
 
5
5
  Handles the configuration of the server.
6
6
 
@@ -12,9 +12,9 @@ Handles the configuration of the server.
12
12
 
13
13
  The environment variables for the engine server.
14
14
 
15
- ### contextIdKeys
15
+ ### availableContextIdKeys
16
16
 
17
- `string`[]
17
+ `object`[]
18
18
 
19
19
  The context ID keys.
20
20
 
@@ -1,6 +1,6 @@
1
1
  # Function: start()
2
2
 
3
- > **start**(`nodeOptions`, `nodeEngineConfig`, `envVars`, `contextIdKeys?`): `Promise`\<\{ `engine`: `Engine`\<`IEngineServerConfig`, [`INodeEngineState`](../interfaces/INodeEngineState.md)\>; `server`: `EngineServer`; `shutdown`: () => `Promise`\<`void`\>; \} \| `undefined`\>
3
+ > **start**(`nodeOptions`, `nodeEngineConfig`, `envVars`, `availableContextIdKeys?`): `Promise`\<\{ `engine`: `Engine`\<`IEngineServerConfig`, [`INodeEngineState`](../interfaces/INodeEngineState.md)\>; `server`: `EngineServer`; `shutdown`: () => `Promise`\<`void`\>; \} \| `undefined`\>
4
4
 
5
5
  Start the engine server.
6
6
 
@@ -24,11 +24,11 @@ The configuration for the engine server.
24
24
 
25
25
  The environment variables.
26
26
 
27
- ### contextIdKeys?
27
+ ### availableContextIdKeys?
28
28
 
29
- `string`[]
29
+ `object`[]
30
30
 
31
- The context ID keys.
31
+ The context ID keys available for operation.
32
32
 
33
33
  ## Returns
34
34
 
@@ -29,13 +29,14 @@
29
29
  - [SYNCHRONISED\_STORAGE\_BLOB\_STORAGE\_ENCRYPTION\_KEY\_ID](variables/SYNCHRONISED_STORAGE_BLOB_STORAGE_ENCRYPTION_KEY_ID.md)
30
30
  - [VC\_AUTHENTICATION\_VERIFICATION\_METHOD\_ID](variables/VC_AUTHENTICATION_VERIFICATION_METHOD_ID.md)
31
31
  - [AUTH\_SIGNING\_KEY\_ID](variables/AUTH_SIGNING_KEY_ID.md)
32
+ - [CONTEXT\_ID\_HANDLER\_FEATURE\_DID](variables/CONTEXT_ID_HANDLER_FEATURE_DID.md)
33
+ - [CONTEXT\_ID\_HANDLER\_FEATURE\_TENANT](variables/CONTEXT_ID_HANDLER_FEATURE_TENANT.md)
32
34
  - [ModuleProtocol](variables/ModuleProtocol.md)
33
35
  - [NodeFeatures](variables/NodeFeatures.md)
34
36
 
35
37
  ## Functions
36
38
 
37
39
  - [bootstrap](functions/bootstrap.md)
38
- - [bootstrapContextIdHandlers](functions/bootstrapContextIdHandlers.md)
39
40
  - [bootstrapNodeId](functions/bootstrapNodeId.md)
40
41
  - [bootstrapTenantId](functions/bootstrapTenantId.md)
41
42
  - [bootstrapNodeAdminUser](functions/bootstrapNodeAdminUser.md)
@@ -0,0 +1,3 @@
1
+ # Variable: CONTEXT\_ID\_HANDLER\_FEATURE\_DID
2
+
3
+ > `const` **CONTEXT\_ID\_HANDLER\_FEATURE\_DID**: `"did"` = `"did"`
@@ -0,0 +1,3 @@
1
+ # Variable: CONTEXT\_ID\_HANDLER\_FEATURE\_TENANT
2
+
3
+ > `const` **CONTEXT\_ID\_HANDLER\_FEATURE\_TENANT**: `"tenant"` = `"tenant"`