@twin.org/node-core 0.0.2-next.17 → 0.0.2-next.19
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 +38 -30
- package/dist/esm/index.mjs +39 -31
- package/dist/types/builders/extensionsBuilder.d.ts +2 -1
- package/dist/types/models/IEngineServerEnvironmentVariables.d.ts +0 -4
- package/dist/types/models/nodeExtensionMethods.d.ts +5 -0
- package/docs/changelog.md +14 -0
- package/docs/reference/functions/shutdownExtensions.md +7 -1
- package/docs/reference/index.md +1 -0
- package/docs/reference/interfaces/IEngineServerEnvironmentVariables.md +0 -8
- package/docs/reference/interfaces/INodeEnvironmentVariables.md +0 -12
- package/docs/reference/type-aliases/NodeExtensionShutdownMethod.md +10 -0
- package/locales/en.json +9 -2
- package/package.json +2 -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');
|
|
@@ -70,20 +71,19 @@ const NodeFeatures = {
|
|
|
70
71
|
|
|
71
72
|
// Copyright 2024 IOTA Stiftung.
|
|
72
73
|
// SPDX-License-Identifier: Apache-2.0.
|
|
73
|
-
/* eslint-disable no-console */
|
|
74
74
|
/**
|
|
75
75
|
* Initialise the locales for the application.
|
|
76
76
|
* @param localesDirectory The directory containing the locales.
|
|
77
77
|
*/
|
|
78
78
|
async function initialiseLocales(localesDirectory) {
|
|
79
79
|
const localesFile = path.resolve(path.join(localesDirectory, "en.json"));
|
|
80
|
-
|
|
80
|
+
cliCore.CLIDisplay.value("Locales File", localesFile);
|
|
81
81
|
if (await fileExists(localesFile)) {
|
|
82
82
|
const enLangContent = await promises.readFile(localesFile, "utf8");
|
|
83
83
|
core.I18n.addDictionary("en", JSON.parse(enLangContent));
|
|
84
84
|
}
|
|
85
85
|
else {
|
|
86
|
-
|
|
86
|
+
cliCore.CLIDisplay.error(`Locales file not found: ${localesFile}`);
|
|
87
87
|
}
|
|
88
88
|
}
|
|
89
89
|
/**
|
|
@@ -1710,8 +1710,9 @@ async function buildEngineServerConfiguration(envVars, coreEngineConfig, serverI
|
|
|
1710
1710
|
}
|
|
1711
1711
|
serverConfig.types.restRouteProcessor ??= [];
|
|
1712
1712
|
serverConfig.types.socketRouteProcessor ??= [];
|
|
1713
|
-
const
|
|
1714
|
-
|
|
1713
|
+
const features = getFeatures(envVars);
|
|
1714
|
+
const hasNodeIdentity = features.includes(NodeFeatures.NodeIdentity);
|
|
1715
|
+
if (hasNodeIdentity) {
|
|
1715
1716
|
serverConfig.types.restRouteProcessor.push({
|
|
1716
1717
|
type: engineServerTypes.RestRouteProcessorType.NodeIdentity
|
|
1717
1718
|
});
|
|
@@ -1815,7 +1816,6 @@ async function buildEngineServerConfiguration(envVars, coreEngineConfig, serverI
|
|
|
1815
1816
|
|
|
1816
1817
|
// Copyright 2024 IOTA Stiftung.
|
|
1817
1818
|
// SPDX-License-Identifier: Apache-2.0.
|
|
1818
|
-
/* eslint-disable no-console */
|
|
1819
1819
|
/**
|
|
1820
1820
|
* Handles the configuration of the extensions.
|
|
1821
1821
|
* @param envVars The environment variables for the node.
|
|
@@ -1828,11 +1828,11 @@ async function extensionsConfiguration(envVars, nodeEngineConfig) {
|
|
|
1828
1828
|
for (const extension of extensions) {
|
|
1829
1829
|
let initialiseConfigMethod;
|
|
1830
1830
|
try {
|
|
1831
|
-
|
|
1831
|
+
cliCore.CLIDisplay.value(core.I18n.formatMessage("node.extensionLoading"), extension);
|
|
1832
1832
|
initialiseConfigMethod = await modules.ModuleHelper.getModuleMethod(extension, "extensionInitialise");
|
|
1833
1833
|
}
|
|
1834
1834
|
catch (err) {
|
|
1835
|
-
|
|
1835
|
+
throw new core.GeneralError("node", "extensionLoadingError", { extension }, err);
|
|
1836
1836
|
}
|
|
1837
1837
|
if (core.Is.function(initialiseConfigMethod)) {
|
|
1838
1838
|
await initialiseConfigMethod(envVars, nodeEngineConfig);
|
|
@@ -1853,6 +1853,7 @@ async function extensionsInitialiseEngine(envVars, engineCore) {
|
|
|
1853
1853
|
for (const extension of extensions) {
|
|
1854
1854
|
let initialiseEngineMethod;
|
|
1855
1855
|
try {
|
|
1856
|
+
engineCore.logInfo(core.I18n.formatMessage("node.extensionInitialisingEngine", { extension }));
|
|
1856
1857
|
initialiseEngineMethod =
|
|
1857
1858
|
await modules.ModuleHelper.getModuleMethod(extension, "extensionInitialiseEngine");
|
|
1858
1859
|
}
|
|
@@ -1876,6 +1877,7 @@ async function extensionsInitialiseEngineServer(envVars, engineCore, engineServe
|
|
|
1876
1877
|
for (const extension of extensions) {
|
|
1877
1878
|
let initialiseEngineServerMethod;
|
|
1878
1879
|
try {
|
|
1880
|
+
engineCore.logInfo(core.I18n.formatMessage("node.extensionInitialisingEngineServer", { extension }));
|
|
1879
1881
|
initialiseEngineServerMethod =
|
|
1880
1882
|
await modules.ModuleHelper.getModuleMethod(extension, "extensionInitialiseEngineServer");
|
|
1881
1883
|
}
|
|
@@ -1889,14 +1891,16 @@ async function extensionsInitialiseEngineServer(envVars, engineCore, engineServe
|
|
|
1889
1891
|
/**
|
|
1890
1892
|
* Handles the shutdown of the extensions.
|
|
1891
1893
|
* @param envVars The environment variables for the node.
|
|
1894
|
+
* @param engineCore The engine core instance.
|
|
1892
1895
|
* @returns Nothing.
|
|
1893
1896
|
*/
|
|
1894
|
-
async function shutdownExtensions(envVars) {
|
|
1897
|
+
async function shutdownExtensions(envVars, engineCore) {
|
|
1895
1898
|
if (core.Is.stringValue(envVars.extensions)) {
|
|
1896
1899
|
const extensions = envVars.extensions.split(",");
|
|
1897
1900
|
for (const extension of extensions) {
|
|
1898
1901
|
let shutdownMethod;
|
|
1899
1902
|
try {
|
|
1903
|
+
engineCore.logInfo(core.I18n.formatMessage("node.extensionShutdown", { extension }));
|
|
1900
1904
|
shutdownMethod = await modules.ModuleHelper.getModuleMethod(extension, "extensionShutdown");
|
|
1901
1905
|
}
|
|
1902
1906
|
catch { }
|
|
@@ -1909,7 +1913,6 @@ async function shutdownExtensions(envVars) {
|
|
|
1909
1913
|
|
|
1910
1914
|
// Copyright 2024 IOTA Stiftung.
|
|
1911
1915
|
// SPDX-License-Identifier: Apache-2.0.
|
|
1912
|
-
/* eslint-disable no-console */
|
|
1913
1916
|
/**
|
|
1914
1917
|
* Start the engine server.
|
|
1915
1918
|
* @param nodeOptions Optional run options for the engine server.
|
|
@@ -1940,13 +1943,13 @@ async function start(nodeOptions, nodeEngineConfig, envVars) {
|
|
|
1940
1943
|
const server = new engineServer.EngineServer({ engineCore: engine$1 });
|
|
1941
1944
|
// Extend the engine.
|
|
1942
1945
|
if (core.Is.function(nodeOptions?.extendEngine)) {
|
|
1943
|
-
|
|
1946
|
+
engine$1.logInfo(core.I18n.formatMessage("node.extendingEngine"));
|
|
1944
1947
|
await nodeOptions.extendEngine(engine$1);
|
|
1945
1948
|
}
|
|
1946
1949
|
await extensionsInitialiseEngine(envVars, engine$1);
|
|
1947
1950
|
// Extend the engine server.
|
|
1948
1951
|
if (core.Is.function(nodeOptions?.extendEngineServer)) {
|
|
1949
|
-
|
|
1952
|
+
engine$1.logInfo(core.I18n.formatMessage("node.extendingEngineServer"));
|
|
1950
1953
|
await nodeOptions?.extendEngineServer(server);
|
|
1951
1954
|
}
|
|
1952
1955
|
await extensionsInitialiseEngineServer(envVars, engine$1, server);
|
|
@@ -1961,7 +1964,7 @@ async function start(nodeOptions, nodeEngineConfig, envVars) {
|
|
|
1961
1964
|
server,
|
|
1962
1965
|
shutdown: async () => {
|
|
1963
1966
|
await server.stop();
|
|
1964
|
-
await shutdownExtensions(envVars);
|
|
1967
|
+
await shutdownExtensions(envVars, engine$1);
|
|
1965
1968
|
}
|
|
1966
1969
|
};
|
|
1967
1970
|
}
|
|
@@ -1969,7 +1972,6 @@ async function start(nodeOptions, nodeEngineConfig, envVars) {
|
|
|
1969
1972
|
|
|
1970
1973
|
// Copyright 2024 IOTA Stiftung.
|
|
1971
1974
|
// SPDX-License-Identifier: Apache-2.0.
|
|
1972
|
-
/* eslint-disable no-console */
|
|
1973
1975
|
/**
|
|
1974
1976
|
* Run the TWIN Node server.
|
|
1975
1977
|
* @param nodeOptions Optional configuration options for running the server.
|
|
@@ -1980,42 +1982,48 @@ async function run(nodeOptions) {
|
|
|
1980
1982
|
nodeOptions ??= {};
|
|
1981
1983
|
const serverInfo = {
|
|
1982
1984
|
name: nodeOptions?.serverName ?? "TWIN Node Server",
|
|
1983
|
-
version: nodeOptions?.serverVersion ?? "0.0.2-next.
|
|
1985
|
+
version: nodeOptions?.serverVersion ?? "0.0.2-next.19" // x-release-please-version
|
|
1984
1986
|
};
|
|
1985
|
-
|
|
1987
|
+
cliCore.CLIDisplay.header(serverInfo.name, serverInfo.version, "🌩️ ");
|
|
1986
1988
|
if (!core.Is.stringValue(nodeOptions?.executionDirectory)) {
|
|
1987
1989
|
nodeOptions.executionDirectory = getExecutionDirectory();
|
|
1988
1990
|
}
|
|
1989
|
-
|
|
1991
|
+
cliCore.CLIDisplay.value("Execution Directory", nodeOptions.executionDirectory);
|
|
1990
1992
|
nodeOptions.localesDirectory =
|
|
1991
1993
|
nodeOptions?.localesDirectory ??
|
|
1992
1994
|
path.resolve(path.join(nodeOptions.executionDirectory, "dist", "locales"));
|
|
1993
|
-
|
|
1995
|
+
cliCore.CLIDisplay.value("Locales Directory", nodeOptions.localesDirectory);
|
|
1994
1996
|
await initialiseLocales(nodeOptions.localesDirectory);
|
|
1995
1997
|
if (core.Is.empty(nodeOptions?.openApiSpecFile)) {
|
|
1996
1998
|
const specFile = path.resolve(path.join(nodeOptions.executionDirectory ?? "", "docs", "open-api", "spec.json"));
|
|
1997
|
-
|
|
1999
|
+
cliCore.CLIDisplay.value("Default OpenAPI Spec File", specFile);
|
|
1998
2000
|
if (await fileExists(specFile)) {
|
|
1999
2001
|
nodeOptions ??= {};
|
|
2000
2002
|
nodeOptions.openApiSpecFile = specFile;
|
|
2001
2003
|
}
|
|
2002
2004
|
}
|
|
2005
|
+
else {
|
|
2006
|
+
cliCore.CLIDisplay.value("OpenAPI Spec File", nodeOptions.openApiSpecFile);
|
|
2007
|
+
}
|
|
2003
2008
|
if (core.Is.empty(nodeOptions?.favIconFile)) {
|
|
2004
2009
|
const favIconFile = path.resolve(path.join(nodeOptions.executionDirectory ?? "", "static", "favicon.png"));
|
|
2005
|
-
|
|
2010
|
+
cliCore.CLIDisplay.value("Default Favicon File", favIconFile);
|
|
2006
2011
|
if (await fileExists(favIconFile)) {
|
|
2007
2012
|
nodeOptions ??= {};
|
|
2008
2013
|
nodeOptions.favIconFile = favIconFile;
|
|
2009
2014
|
}
|
|
2010
2015
|
}
|
|
2016
|
+
else {
|
|
2017
|
+
cliCore.CLIDisplay.value("Favicon File", nodeOptions.favIconFile);
|
|
2018
|
+
}
|
|
2011
2019
|
nodeOptions.envPrefix ??= "TWIN_NODE_";
|
|
2012
|
-
|
|
2020
|
+
cliCore.CLIDisplay.value("Environment Variable Prefix", nodeOptions.envPrefix);
|
|
2013
2021
|
overrideModuleImport(nodeOptions.executionDirectory ?? "");
|
|
2014
2022
|
const { nodeEngineConfig, nodeEnvVars: envVars } = await buildConfiguration(
|
|
2015
2023
|
// This is the only location in the code base that should access process.env directly
|
|
2016
2024
|
// eslint-disable-next-line no-restricted-syntax
|
|
2017
2025
|
process.env, nodeOptions, serverInfo);
|
|
2018
|
-
|
|
2026
|
+
cliCore.CLIDisplay.break();
|
|
2019
2027
|
const startResult = await start(nodeOptions, nodeEngineConfig, envVars);
|
|
2020
2028
|
if (!core.Is.empty(startResult)) {
|
|
2021
2029
|
for (const signal of ["SIGHUP", "SIGINT", "SIGTERM"]) {
|
|
@@ -2026,7 +2034,7 @@ async function run(nodeOptions) {
|
|
|
2026
2034
|
}
|
|
2027
2035
|
}
|
|
2028
2036
|
catch (err) {
|
|
2029
|
-
|
|
2037
|
+
cliCore.CLIDisplay.error(err);
|
|
2030
2038
|
// eslint-disable-next-line unicorn/no-process-exit
|
|
2031
2039
|
process.exit(1);
|
|
2032
2040
|
}
|
|
@@ -2043,7 +2051,7 @@ async function buildConfiguration(processEnv, options, serverInfo) {
|
|
|
2043
2051
|
let defaultEnvOnly = false;
|
|
2044
2052
|
if (core.Is.empty(options?.envFilenames)) {
|
|
2045
2053
|
const envFile = path.resolve(path.join(options.executionDirectory ?? "", ".env"));
|
|
2046
|
-
|
|
2054
|
+
cliCore.CLIDisplay.value("Default Environment File", envFile);
|
|
2047
2055
|
options ??= {};
|
|
2048
2056
|
options.envFilenames = [envFile];
|
|
2049
2057
|
defaultEnvOnly = true;
|
|
@@ -2071,18 +2079,18 @@ async function buildConfiguration(processEnv, options, serverInfo) {
|
|
|
2071
2079
|
const filePath = envVars[key].slice(6).trim();
|
|
2072
2080
|
const embeddedFile = path.resolve(path.join(options.executionDirectory ?? "", filePath));
|
|
2073
2081
|
if (envVars[key].startsWith("@text:")) {
|
|
2074
|
-
|
|
2082
|
+
cliCore.CLIDisplay.value(`Expanding Environment Variable: ${key} from text file`, embeddedFile);
|
|
2075
2083
|
envVars[key] = await loadTextFile(embeddedFile);
|
|
2076
2084
|
}
|
|
2077
2085
|
else if (envVars[key].startsWith("@json:")) {
|
|
2078
|
-
|
|
2086
|
+
cliCore.CLIDisplay.value(`Expanding Environment Variable: ${key} from JSON file`, embeddedFile);
|
|
2079
2087
|
envVars[key] = await loadJsonFile(embeddedFile);
|
|
2080
2088
|
}
|
|
2081
2089
|
}
|
|
2082
2090
|
}
|
|
2083
2091
|
// Extend the environment variables with any additional custom configuration.
|
|
2084
2092
|
if (core.Is.function(options?.extendEnvVars)) {
|
|
2085
|
-
|
|
2093
|
+
cliCore.CLIDisplay.task("Extending Environment Variables");
|
|
2086
2094
|
await options.extendEnvVars(envVars);
|
|
2087
2095
|
}
|
|
2088
2096
|
// Build the engine configuration from the environment variables.
|
|
@@ -2091,19 +2099,19 @@ async function buildConfiguration(processEnv, options, serverInfo) {
|
|
|
2091
2099
|
// Merge any custom configuration provided in the options.
|
|
2092
2100
|
if (core.Is.arrayValue(options?.configFilenames)) {
|
|
2093
2101
|
for (const configFile of options.configFilenames) {
|
|
2094
|
-
|
|
2102
|
+
cliCore.CLIDisplay.value("Loading Configuration File", configFile);
|
|
2095
2103
|
const configFilePath = path.resolve(path.join(options.executionDirectory ?? "", configFile));
|
|
2096
2104
|
const config = await loadJsonFile(configFilePath);
|
|
2097
2105
|
Object.assign(engineServerConfig, config);
|
|
2098
2106
|
}
|
|
2099
2107
|
}
|
|
2100
2108
|
if (core.Is.objectValue(options?.config)) {
|
|
2101
|
-
|
|
2109
|
+
cliCore.CLIDisplay.task("Merging Custom Configuration");
|
|
2102
2110
|
Object.assign(engineServerConfig, options.config);
|
|
2103
2111
|
}
|
|
2104
2112
|
// Merge any custom configuration provided in the options.
|
|
2105
2113
|
if (core.Is.function(options?.extendConfig)) {
|
|
2106
|
-
|
|
2114
|
+
cliCore.CLIDisplay.task("Extending Configuration");
|
|
2107
2115
|
await options.extendConfig(envVars, engineServerConfig);
|
|
2108
2116
|
}
|
|
2109
2117
|
const nodeEngineConfig = await extensionsConfiguration(envVars, engineServerConfig);
|
package/dist/esm/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { PasswordHelper } from '@twin.org/api-auth-entity-storage-service';
|
|
2
|
-
import { I18n, Is, Coerce, Converter, RandomHelper, Urn, GeneralError,
|
|
2
|
+
import { I18n, Is, Coerce, Converter, RandomHelper, Urn, GeneralError, EnvHelper } from '@twin.org/core';
|
|
3
3
|
import { PasswordGenerator, Bip39 } from '@twin.org/crypto';
|
|
4
4
|
import { AuthenticationComponentType, InformationComponentType, RestRouteProcessorType, SocketRouteProcessorType, AuthenticationAdminComponentType } from '@twin.org/engine-server-types';
|
|
5
5
|
import { WalletConnectorType, IdentityConnectorType, EntityStorageConnectorType, BlobStorageConnectorType, BlobStorageComponentType, VaultConnectorType, DltConfigType, LoggingConnectorType, LoggingComponentType, BackgroundTaskConnectorType, TaskSchedulerComponentType, EventBusConnectorType, EventBusComponentType, TelemetryConnectorType, TelemetryComponentType, MessagingEmailConnectorType, MessagingSmsConnectorType, MessagingPushNotificationConnectorType, MessagingAdminComponentType, MessagingComponentType, FaucetConnectorType, EngineTypeHelper, NftConnectorType, NftComponentType, VerifiableStorageConnectorType, VerifiableStorageComponentType, ImmutableProofComponentType, IdentityComponentType, IdentityResolverConnectorType, IdentityResolverComponentType, IdentityProfileConnectorType, IdentityProfileComponentType, AttestationConnectorType, AttestationComponentType, DataProcessingComponentType, DataConverterConnectorType, DataExtractorConnectorType, AuditableItemGraphComponentType, AuditableItemStreamComponentType, DocumentManagementComponentType, AuthenticationGeneratorComponentType, RightsManagementPapComponentType, RightsManagementPmpComponentType, RightsManagementPipComponentType, RightsManagementPxpComponentType, RightsManagementPdpComponentType, RightsManagementPepComponentType, RightsManagementPnpComponentType, RightsManagementPnapComponentType, RightsManagementDapComponentType, RightsManagementDarpComponentType, SynchronisedStorageComponentType, FederatedCatalogueComponentType, DataSpaceConnectorComponentType } from '@twin.org/engine-types';
|
|
@@ -9,6 +9,7 @@ import { VaultConnectorFactory, VaultKeyType } from '@twin.org/vault-models';
|
|
|
9
9
|
import { WalletConnectorFactory } from '@twin.org/wallet-models';
|
|
10
10
|
import { readFile, stat, readdir } from 'node:fs/promises';
|
|
11
11
|
import path from 'node:path';
|
|
12
|
+
import { CLIDisplay } from '@twin.org/cli-core';
|
|
12
13
|
import { PolicyNegotiationPointClient, DataAccessPointClient } from '@twin.org/rights-management-rest-client';
|
|
13
14
|
import { addDefaultRestPaths, addDefaultSocketPaths, EngineServer } from '@twin.org/engine-server';
|
|
14
15
|
import { ModuleHelper } from '@twin.org/modules';
|
|
@@ -49,20 +50,19 @@ const NodeFeatures = {
|
|
|
49
50
|
|
|
50
51
|
// Copyright 2024 IOTA Stiftung.
|
|
51
52
|
// SPDX-License-Identifier: Apache-2.0.
|
|
52
|
-
/* eslint-disable no-console */
|
|
53
53
|
/**
|
|
54
54
|
* Initialise the locales for the application.
|
|
55
55
|
* @param localesDirectory The directory containing the locales.
|
|
56
56
|
*/
|
|
57
57
|
async function initialiseLocales(localesDirectory) {
|
|
58
58
|
const localesFile = path.resolve(path.join(localesDirectory, "en.json"));
|
|
59
|
-
|
|
59
|
+
CLIDisplay.value("Locales File", localesFile);
|
|
60
60
|
if (await fileExists(localesFile)) {
|
|
61
61
|
const enLangContent = await readFile(localesFile, "utf8");
|
|
62
62
|
I18n.addDictionary("en", JSON.parse(enLangContent));
|
|
63
63
|
}
|
|
64
64
|
else {
|
|
65
|
-
|
|
65
|
+
CLIDisplay.error(`Locales file not found: ${localesFile}`);
|
|
66
66
|
}
|
|
67
67
|
}
|
|
68
68
|
/**
|
|
@@ -1689,8 +1689,9 @@ async function buildEngineServerConfiguration(envVars, coreEngineConfig, serverI
|
|
|
1689
1689
|
}
|
|
1690
1690
|
serverConfig.types.restRouteProcessor ??= [];
|
|
1691
1691
|
serverConfig.types.socketRouteProcessor ??= [];
|
|
1692
|
-
const
|
|
1693
|
-
|
|
1692
|
+
const features = getFeatures(envVars);
|
|
1693
|
+
const hasNodeIdentity = features.includes(NodeFeatures.NodeIdentity);
|
|
1694
|
+
if (hasNodeIdentity) {
|
|
1694
1695
|
serverConfig.types.restRouteProcessor.push({
|
|
1695
1696
|
type: RestRouteProcessorType.NodeIdentity
|
|
1696
1697
|
});
|
|
@@ -1794,7 +1795,6 @@ async function buildEngineServerConfiguration(envVars, coreEngineConfig, serverI
|
|
|
1794
1795
|
|
|
1795
1796
|
// Copyright 2024 IOTA Stiftung.
|
|
1796
1797
|
// SPDX-License-Identifier: Apache-2.0.
|
|
1797
|
-
/* eslint-disable no-console */
|
|
1798
1798
|
/**
|
|
1799
1799
|
* Handles the configuration of the extensions.
|
|
1800
1800
|
* @param envVars The environment variables for the node.
|
|
@@ -1807,11 +1807,11 @@ async function extensionsConfiguration(envVars, nodeEngineConfig) {
|
|
|
1807
1807
|
for (const extension of extensions) {
|
|
1808
1808
|
let initialiseConfigMethod;
|
|
1809
1809
|
try {
|
|
1810
|
-
|
|
1810
|
+
CLIDisplay.value(I18n.formatMessage("node.extensionLoading"), extension);
|
|
1811
1811
|
initialiseConfigMethod = await ModuleHelper.getModuleMethod(extension, "extensionInitialise");
|
|
1812
1812
|
}
|
|
1813
1813
|
catch (err) {
|
|
1814
|
-
|
|
1814
|
+
throw new GeneralError("node", "extensionLoadingError", { extension }, err);
|
|
1815
1815
|
}
|
|
1816
1816
|
if (Is.function(initialiseConfigMethod)) {
|
|
1817
1817
|
await initialiseConfigMethod(envVars, nodeEngineConfig);
|
|
@@ -1832,6 +1832,7 @@ async function extensionsInitialiseEngine(envVars, engineCore) {
|
|
|
1832
1832
|
for (const extension of extensions) {
|
|
1833
1833
|
let initialiseEngineMethod;
|
|
1834
1834
|
try {
|
|
1835
|
+
engineCore.logInfo(I18n.formatMessage("node.extensionInitialisingEngine", { extension }));
|
|
1835
1836
|
initialiseEngineMethod =
|
|
1836
1837
|
await ModuleHelper.getModuleMethod(extension, "extensionInitialiseEngine");
|
|
1837
1838
|
}
|
|
@@ -1855,6 +1856,7 @@ async function extensionsInitialiseEngineServer(envVars, engineCore, engineServe
|
|
|
1855
1856
|
for (const extension of extensions) {
|
|
1856
1857
|
let initialiseEngineServerMethod;
|
|
1857
1858
|
try {
|
|
1859
|
+
engineCore.logInfo(I18n.formatMessage("node.extensionInitialisingEngineServer", { extension }));
|
|
1858
1860
|
initialiseEngineServerMethod =
|
|
1859
1861
|
await ModuleHelper.getModuleMethod(extension, "extensionInitialiseEngineServer");
|
|
1860
1862
|
}
|
|
@@ -1868,14 +1870,16 @@ async function extensionsInitialiseEngineServer(envVars, engineCore, engineServe
|
|
|
1868
1870
|
/**
|
|
1869
1871
|
* Handles the shutdown of the extensions.
|
|
1870
1872
|
* @param envVars The environment variables for the node.
|
|
1873
|
+
* @param engineCore The engine core instance.
|
|
1871
1874
|
* @returns Nothing.
|
|
1872
1875
|
*/
|
|
1873
|
-
async function shutdownExtensions(envVars) {
|
|
1876
|
+
async function shutdownExtensions(envVars, engineCore) {
|
|
1874
1877
|
if (Is.stringValue(envVars.extensions)) {
|
|
1875
1878
|
const extensions = envVars.extensions.split(",");
|
|
1876
1879
|
for (const extension of extensions) {
|
|
1877
1880
|
let shutdownMethod;
|
|
1878
1881
|
try {
|
|
1882
|
+
engineCore.logInfo(I18n.formatMessage("node.extensionShutdown", { extension }));
|
|
1879
1883
|
shutdownMethod = await ModuleHelper.getModuleMethod(extension, "extensionShutdown");
|
|
1880
1884
|
}
|
|
1881
1885
|
catch { }
|
|
@@ -1888,7 +1892,6 @@ async function shutdownExtensions(envVars) {
|
|
|
1888
1892
|
|
|
1889
1893
|
// Copyright 2024 IOTA Stiftung.
|
|
1890
1894
|
// SPDX-License-Identifier: Apache-2.0.
|
|
1891
|
-
/* eslint-disable no-console */
|
|
1892
1895
|
/**
|
|
1893
1896
|
* Start the engine server.
|
|
1894
1897
|
* @param nodeOptions Optional run options for the engine server.
|
|
@@ -1919,13 +1922,13 @@ async function start(nodeOptions, nodeEngineConfig, envVars) {
|
|
|
1919
1922
|
const server = new EngineServer({ engineCore: engine });
|
|
1920
1923
|
// Extend the engine.
|
|
1921
1924
|
if (Is.function(nodeOptions?.extendEngine)) {
|
|
1922
|
-
|
|
1925
|
+
engine.logInfo(I18n.formatMessage("node.extendingEngine"));
|
|
1923
1926
|
await nodeOptions.extendEngine(engine);
|
|
1924
1927
|
}
|
|
1925
1928
|
await extensionsInitialiseEngine(envVars, engine);
|
|
1926
1929
|
// Extend the engine server.
|
|
1927
1930
|
if (Is.function(nodeOptions?.extendEngineServer)) {
|
|
1928
|
-
|
|
1931
|
+
engine.logInfo(I18n.formatMessage("node.extendingEngineServer"));
|
|
1929
1932
|
await nodeOptions?.extendEngineServer(server);
|
|
1930
1933
|
}
|
|
1931
1934
|
await extensionsInitialiseEngineServer(envVars, engine, server);
|
|
@@ -1940,7 +1943,7 @@ async function start(nodeOptions, nodeEngineConfig, envVars) {
|
|
|
1940
1943
|
server,
|
|
1941
1944
|
shutdown: async () => {
|
|
1942
1945
|
await server.stop();
|
|
1943
|
-
await shutdownExtensions(envVars);
|
|
1946
|
+
await shutdownExtensions(envVars, engine);
|
|
1944
1947
|
}
|
|
1945
1948
|
};
|
|
1946
1949
|
}
|
|
@@ -1948,7 +1951,6 @@ async function start(nodeOptions, nodeEngineConfig, envVars) {
|
|
|
1948
1951
|
|
|
1949
1952
|
// Copyright 2024 IOTA Stiftung.
|
|
1950
1953
|
// SPDX-License-Identifier: Apache-2.0.
|
|
1951
|
-
/* eslint-disable no-console */
|
|
1952
1954
|
/**
|
|
1953
1955
|
* Run the TWIN Node server.
|
|
1954
1956
|
* @param nodeOptions Optional configuration options for running the server.
|
|
@@ -1959,42 +1961,48 @@ async function run(nodeOptions) {
|
|
|
1959
1961
|
nodeOptions ??= {};
|
|
1960
1962
|
const serverInfo = {
|
|
1961
1963
|
name: nodeOptions?.serverName ?? "TWIN Node Server",
|
|
1962
|
-
version: nodeOptions?.serverVersion ?? "0.0.2-next.
|
|
1964
|
+
version: nodeOptions?.serverVersion ?? "0.0.2-next.19" // x-release-please-version
|
|
1963
1965
|
};
|
|
1964
|
-
|
|
1966
|
+
CLIDisplay.header(serverInfo.name, serverInfo.version, "🌩️ ");
|
|
1965
1967
|
if (!Is.stringValue(nodeOptions?.executionDirectory)) {
|
|
1966
1968
|
nodeOptions.executionDirectory = getExecutionDirectory();
|
|
1967
1969
|
}
|
|
1968
|
-
|
|
1970
|
+
CLIDisplay.value("Execution Directory", nodeOptions.executionDirectory);
|
|
1969
1971
|
nodeOptions.localesDirectory =
|
|
1970
1972
|
nodeOptions?.localesDirectory ??
|
|
1971
1973
|
path.resolve(path.join(nodeOptions.executionDirectory, "dist", "locales"));
|
|
1972
|
-
|
|
1974
|
+
CLIDisplay.value("Locales Directory", nodeOptions.localesDirectory);
|
|
1973
1975
|
await initialiseLocales(nodeOptions.localesDirectory);
|
|
1974
1976
|
if (Is.empty(nodeOptions?.openApiSpecFile)) {
|
|
1975
1977
|
const specFile = path.resolve(path.join(nodeOptions.executionDirectory ?? "", "docs", "open-api", "spec.json"));
|
|
1976
|
-
|
|
1978
|
+
CLIDisplay.value("Default OpenAPI Spec File", specFile);
|
|
1977
1979
|
if (await fileExists(specFile)) {
|
|
1978
1980
|
nodeOptions ??= {};
|
|
1979
1981
|
nodeOptions.openApiSpecFile = specFile;
|
|
1980
1982
|
}
|
|
1981
1983
|
}
|
|
1984
|
+
else {
|
|
1985
|
+
CLIDisplay.value("OpenAPI Spec File", nodeOptions.openApiSpecFile);
|
|
1986
|
+
}
|
|
1982
1987
|
if (Is.empty(nodeOptions?.favIconFile)) {
|
|
1983
1988
|
const favIconFile = path.resolve(path.join(nodeOptions.executionDirectory ?? "", "static", "favicon.png"));
|
|
1984
|
-
|
|
1989
|
+
CLIDisplay.value("Default Favicon File", favIconFile);
|
|
1985
1990
|
if (await fileExists(favIconFile)) {
|
|
1986
1991
|
nodeOptions ??= {};
|
|
1987
1992
|
nodeOptions.favIconFile = favIconFile;
|
|
1988
1993
|
}
|
|
1989
1994
|
}
|
|
1995
|
+
else {
|
|
1996
|
+
CLIDisplay.value("Favicon File", nodeOptions.favIconFile);
|
|
1997
|
+
}
|
|
1990
1998
|
nodeOptions.envPrefix ??= "TWIN_NODE_";
|
|
1991
|
-
|
|
1999
|
+
CLIDisplay.value("Environment Variable Prefix", nodeOptions.envPrefix);
|
|
1992
2000
|
overrideModuleImport(nodeOptions.executionDirectory ?? "");
|
|
1993
2001
|
const { nodeEngineConfig, nodeEnvVars: envVars } = await buildConfiguration(
|
|
1994
2002
|
// This is the only location in the code base that should access process.env directly
|
|
1995
2003
|
// eslint-disable-next-line no-restricted-syntax
|
|
1996
2004
|
process.env, nodeOptions, serverInfo);
|
|
1997
|
-
|
|
2005
|
+
CLIDisplay.break();
|
|
1998
2006
|
const startResult = await start(nodeOptions, nodeEngineConfig, envVars);
|
|
1999
2007
|
if (!Is.empty(startResult)) {
|
|
2000
2008
|
for (const signal of ["SIGHUP", "SIGINT", "SIGTERM"]) {
|
|
@@ -2005,7 +2013,7 @@ async function run(nodeOptions) {
|
|
|
2005
2013
|
}
|
|
2006
2014
|
}
|
|
2007
2015
|
catch (err) {
|
|
2008
|
-
|
|
2016
|
+
CLIDisplay.error(err);
|
|
2009
2017
|
// eslint-disable-next-line unicorn/no-process-exit
|
|
2010
2018
|
process.exit(1);
|
|
2011
2019
|
}
|
|
@@ -2022,7 +2030,7 @@ async function buildConfiguration(processEnv, options, serverInfo) {
|
|
|
2022
2030
|
let defaultEnvOnly = false;
|
|
2023
2031
|
if (Is.empty(options?.envFilenames)) {
|
|
2024
2032
|
const envFile = path.resolve(path.join(options.executionDirectory ?? "", ".env"));
|
|
2025
|
-
|
|
2033
|
+
CLIDisplay.value("Default Environment File", envFile);
|
|
2026
2034
|
options ??= {};
|
|
2027
2035
|
options.envFilenames = [envFile];
|
|
2028
2036
|
defaultEnvOnly = true;
|
|
@@ -2050,18 +2058,18 @@ async function buildConfiguration(processEnv, options, serverInfo) {
|
|
|
2050
2058
|
const filePath = envVars[key].slice(6).trim();
|
|
2051
2059
|
const embeddedFile = path.resolve(path.join(options.executionDirectory ?? "", filePath));
|
|
2052
2060
|
if (envVars[key].startsWith("@text:")) {
|
|
2053
|
-
|
|
2061
|
+
CLIDisplay.value(`Expanding Environment Variable: ${key} from text file`, embeddedFile);
|
|
2054
2062
|
envVars[key] = await loadTextFile(embeddedFile);
|
|
2055
2063
|
}
|
|
2056
2064
|
else if (envVars[key].startsWith("@json:")) {
|
|
2057
|
-
|
|
2065
|
+
CLIDisplay.value(`Expanding Environment Variable: ${key} from JSON file`, embeddedFile);
|
|
2058
2066
|
envVars[key] = await loadJsonFile(embeddedFile);
|
|
2059
2067
|
}
|
|
2060
2068
|
}
|
|
2061
2069
|
}
|
|
2062
2070
|
// Extend the environment variables with any additional custom configuration.
|
|
2063
2071
|
if (Is.function(options?.extendEnvVars)) {
|
|
2064
|
-
|
|
2072
|
+
CLIDisplay.task("Extending Environment Variables");
|
|
2065
2073
|
await options.extendEnvVars(envVars);
|
|
2066
2074
|
}
|
|
2067
2075
|
// Build the engine configuration from the environment variables.
|
|
@@ -2070,19 +2078,19 @@ async function buildConfiguration(processEnv, options, serverInfo) {
|
|
|
2070
2078
|
// Merge any custom configuration provided in the options.
|
|
2071
2079
|
if (Is.arrayValue(options?.configFilenames)) {
|
|
2072
2080
|
for (const configFile of options.configFilenames) {
|
|
2073
|
-
|
|
2081
|
+
CLIDisplay.value("Loading Configuration File", configFile);
|
|
2074
2082
|
const configFilePath = path.resolve(path.join(options.executionDirectory ?? "", configFile));
|
|
2075
2083
|
const config = await loadJsonFile(configFilePath);
|
|
2076
2084
|
Object.assign(engineServerConfig, config);
|
|
2077
2085
|
}
|
|
2078
2086
|
}
|
|
2079
2087
|
if (Is.objectValue(options?.config)) {
|
|
2080
|
-
|
|
2088
|
+
CLIDisplay.task("Merging Custom Configuration");
|
|
2081
2089
|
Object.assign(engineServerConfig, options.config);
|
|
2082
2090
|
}
|
|
2083
2091
|
// Merge any custom configuration provided in the options.
|
|
2084
2092
|
if (Is.function(options?.extendConfig)) {
|
|
2085
|
-
|
|
2093
|
+
CLIDisplay.task("Extending Configuration");
|
|
2086
2094
|
await options.extendConfig(envVars, engineServerConfig);
|
|
2087
2095
|
}
|
|
2088
2096
|
const nodeEngineConfig = await extensionsConfiguration(envVars, engineServerConfig);
|
|
@@ -26,6 +26,7 @@ export declare function extensionsInitialiseEngineServer(envVars: INodeEnvironme
|
|
|
26
26
|
/**
|
|
27
27
|
* Handles the shutdown of the extensions.
|
|
28
28
|
* @param envVars The environment variables for the node.
|
|
29
|
+
* @param engineCore The engine core instance.
|
|
29
30
|
* @returns Nothing.
|
|
30
31
|
*/
|
|
31
|
-
export declare function shutdownExtensions(envVars: INodeEnvironmentVariables): Promise<void>;
|
|
32
|
+
export declare function shutdownExtensions(envVars: INodeEnvironmentVariables, engineCore: IEngineCore): Promise<void>;
|
|
@@ -43,10 +43,6 @@ export interface IEngineServerEnvironmentVariables extends IEngineEnvironmentVar
|
|
|
43
43
|
* Additional MIME type processors to include, comma separated.
|
|
44
44
|
*/
|
|
45
45
|
mimeTypeProcessors?: string;
|
|
46
|
-
/**
|
|
47
|
-
* Disable Node Identity route processors.
|
|
48
|
-
*/
|
|
49
|
-
disableNodeIdentity?: string;
|
|
50
46
|
/**
|
|
51
47
|
* Include the body in the REST logging output, useful for debugging.
|
|
52
48
|
*/
|
|
@@ -20,3 +20,8 @@ export type NodeExtensionInitialiseEngineMethod = (engineCore: IEngineCore) => P
|
|
|
20
20
|
* @param engineServer The engine server instance.
|
|
21
21
|
*/
|
|
22
22
|
export type NodeExtensionInitialiseEngineServerMethod = (engineCore: IEngineCore, engineServer: IEngineServer) => Promise<void>;
|
|
23
|
+
/**
|
|
24
|
+
* The type for the shutdown method of an extension module.
|
|
25
|
+
* This is called when the engine is shutting down.
|
|
26
|
+
*/
|
|
27
|
+
export type NodeExtensionShutdownMethod = () => Promise<void>;
|
package/docs/changelog.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# @twin.org/node-core - Changelog
|
|
2
2
|
|
|
3
|
+
## [0.0.2-next.19](https://github.com/twinfoundation/node/compare/node-core-v0.0.2-next.18...node-core-v0.0.2-next.19) (2025-10-03)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* use features instead of disableNodeIdentity ([2e6109b](https://github.com/twinfoundation/node/commit/2e6109bd1de825e0f5396fc120d99ad7b3929852))
|
|
9
|
+
|
|
10
|
+
## [0.0.2-next.18](https://github.com/twinfoundation/node/compare/node-core-v0.0.2-next.17...node-core-v0.0.2-next.18) (2025-10-03)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
### Features
|
|
14
|
+
|
|
15
|
+
* improve error handling for extensions and logging ([bd84fde](https://github.com/twinfoundation/node/commit/bd84fde67e5a9db6ac66730397992401ca52e88c))
|
|
16
|
+
|
|
3
17
|
## [0.0.2-next.17](https://github.com/twinfoundation/node/compare/node-core-v0.0.2-next.16...node-core-v0.0.2-next.17) (2025-10-02)
|
|
4
18
|
|
|
5
19
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Function: shutdownExtensions()
|
|
2
2
|
|
|
3
|
-
> **shutdownExtensions**(`envVars`): `Promise`\<`void`\>
|
|
3
|
+
> **shutdownExtensions**(`envVars`, `engineCore`): `Promise`\<`void`\>
|
|
4
4
|
|
|
5
5
|
Handles the shutdown of the extensions.
|
|
6
6
|
|
|
@@ -12,6 +12,12 @@ Handles the shutdown of the extensions.
|
|
|
12
12
|
|
|
13
13
|
The environment variables for the node.
|
|
14
14
|
|
|
15
|
+
### engineCore
|
|
16
|
+
|
|
17
|
+
`IEngineCore`
|
|
18
|
+
|
|
19
|
+
The engine core instance.
|
|
20
|
+
|
|
15
21
|
## Returns
|
|
16
22
|
|
|
17
23
|
`Promise`\<`void`\>
|
package/docs/reference/index.md
CHANGED
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
- [NodeExtensionInitialiseMethod](type-aliases/NodeExtensionInitialiseMethod.md)
|
|
14
14
|
- [NodeExtensionInitialiseEngineMethod](type-aliases/NodeExtensionInitialiseEngineMethod.md)
|
|
15
15
|
- [NodeExtensionInitialiseEngineServerMethod](type-aliases/NodeExtensionInitialiseEngineServerMethod.md)
|
|
16
|
+
- [NodeExtensionShutdownMethod](type-aliases/NodeExtensionShutdownMethod.md)
|
|
16
17
|
- [NodeFeatures](type-aliases/NodeFeatures.md)
|
|
17
18
|
|
|
18
19
|
## Variables
|
|
@@ -1740,14 +1740,6 @@ Additional MIME type processors to include, comma separated.
|
|
|
1740
1740
|
|
|
1741
1741
|
***
|
|
1742
1742
|
|
|
1743
|
-
### disableNodeIdentity?
|
|
1744
|
-
|
|
1745
|
-
> `optional` **disableNodeIdentity**: `string`
|
|
1746
|
-
|
|
1747
|
-
Disable Node Identity route processors.
|
|
1748
|
-
|
|
1749
|
-
***
|
|
1750
|
-
|
|
1751
1743
|
### routeLoggingIncludeBody?
|
|
1752
1744
|
|
|
1753
1745
|
> `optional` **routeLoggingIncludeBody**: `string`
|
|
@@ -1776,18 +1776,6 @@ Additional MIME type processors to include, comma separated.
|
|
|
1776
1776
|
|
|
1777
1777
|
***
|
|
1778
1778
|
|
|
1779
|
-
### disableNodeIdentity?
|
|
1780
|
-
|
|
1781
|
-
> `optional` **disableNodeIdentity**: `string`
|
|
1782
|
-
|
|
1783
|
-
Disable Node Identity route processors.
|
|
1784
|
-
|
|
1785
|
-
#### Inherited from
|
|
1786
|
-
|
|
1787
|
-
[`IEngineServerEnvironmentVariables`](IEngineServerEnvironmentVariables.md).[`disableNodeIdentity`](IEngineServerEnvironmentVariables.md#disablenodeidentity)
|
|
1788
|
-
|
|
1789
|
-
***
|
|
1790
|
-
|
|
1791
1779
|
### routeLoggingIncludeBody?
|
|
1792
1780
|
|
|
1793
1781
|
> `optional` **routeLoggingIncludeBody**: `string`
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# Type Alias: NodeExtensionShutdownMethod()
|
|
2
|
+
|
|
3
|
+
> **NodeExtensionShutdownMethod** = () => `Promise`\<`void`\>
|
|
4
|
+
|
|
5
|
+
The type for the shutdown method of an extension module.
|
|
6
|
+
This is called when the engine is shutting down.
|
|
7
|
+
|
|
8
|
+
## Returns
|
|
9
|
+
|
|
10
|
+
`Promise`\<`void`\>
|
package/locales/en.json
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"error": {
|
|
3
3
|
"node": {
|
|
4
|
-
"storageFileRootNotSet": "{storageFileRoot} is not set, the server will not start without it, please set it in the shell or create a .env file"
|
|
4
|
+
"storageFileRootNotSet": "{storageFileRoot} is not set, the server will not start without it, please set it in the shell or create a .env file",
|
|
5
|
+
"extensionLoadingError": "Failed to load extension \"{extension}\""
|
|
5
6
|
}
|
|
6
7
|
},
|
|
7
8
|
"node": {
|
|
@@ -31,6 +32,12 @@
|
|
|
31
32
|
"existingUserProfile": "User profile already exists \"{identity}\"",
|
|
32
33
|
"nodeIdentity": "Node identity \"{identity}\"",
|
|
33
34
|
"nodeAdminUserEmail": "Node Admin User Email \"{email}\"",
|
|
34
|
-
"nodeAdminUserPassword": "Node Admin User Password \"{password}\""
|
|
35
|
+
"nodeAdminUserPassword": "Node Admin User Password \"{password}\"",
|
|
36
|
+
"extensionLoading": "Loading Extension",
|
|
37
|
+
"extensionInitialisingEngine": "Initialising engine for extension \"{extension}\"",
|
|
38
|
+
"extensionInitialisingEngineServer": "Initialising engine server for extension \"{extension}\"",
|
|
39
|
+
"extensionShutdown": "Shutdown extension \"{extension}\"",
|
|
40
|
+
"extendingEngine": "Extending Engine",
|
|
41
|
+
"extendingEngineServer": "Extending Engine Server"
|
|
35
42
|
}
|
|
36
43
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@twin.org/node-core",
|
|
3
|
-
"version": "0.0.2-next.
|
|
3
|
+
"version": "0.0.2-next.19",
|
|
4
4
|
"description": "TWIN Node Core for serving APIs using the specified configuration",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
},
|
|
16
16
|
"dependencies": {
|
|
17
17
|
"@twin.org/api-auth-entity-storage-service": "next",
|
|
18
|
+
"@twin.org/cli-core": "next",
|
|
18
19
|
"@twin.org/core": "next",
|
|
19
20
|
"@twin.org/crypto": "next",
|
|
20
21
|
"@twin.org/data-space-connector-models": "next",
|