From 72af784816ffcd943a7843a3b28587cffc28b32f Mon Sep 17 00:00:00 2001 From: Bas Meeuwissen Date: Wed, 31 Jan 2024 06:30:48 +0100 Subject: [PATCH 1/6] #450: replace env variables with values --- .../src/errors/EnvironmentVariableNotFound.ts | 8 +++++++ .../src/utils/RuntimeConfigurationLoader.ts | 22 ++++++++++++++++++- 2 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 packages/server-nodejs/src/errors/EnvironmentVariableNotFound.ts diff --git a/packages/server-nodejs/src/errors/EnvironmentVariableNotFound.ts b/packages/server-nodejs/src/errors/EnvironmentVariableNotFound.ts new file mode 100644 index 00000000..cc289708 --- /dev/null +++ b/packages/server-nodejs/src/errors/EnvironmentVariableNotFound.ts @@ -0,0 +1,8 @@ + +export default class EnvironmentVariableNotFound extends Error +{ + constructor(name: string) + { + super(`The environment variable '${name}' is not found`); + } +} diff --git a/packages/server-nodejs/src/utils/RuntimeConfigurationLoader.ts b/packages/server-nodejs/src/utils/RuntimeConfigurationLoader.ts index 9d36fe41..bce242a6 100644 --- a/packages/server-nodejs/src/utils/RuntimeConfigurationLoader.ts +++ b/packages/server-nodejs/src/utils/RuntimeConfigurationLoader.ts @@ -3,15 +3,35 @@ import { readFileSync } from 'fs'; import RuntimeConfiguration, { runtimeSchema } from '../configuration/RuntimeConfiguration.js'; +import EnvironmentVariableNotFound from '../errors/EnvironmentVariableNotFound.js'; + import DataConverter from './DataConverter.js'; +const ENVIRONMENT_VARIABLE_REGEX = /\${([^}]*)}/g; + export default class RuntimeConfigurationLoader { static load(filename: string): RuntimeConfiguration { const plainContents = readFileSync(filename, 'utf-8'); - const parsedContents = JSON.parse(plainContents); + const replacedContents = this.#replaceEnvValues(plainContents); + const parsedContents = JSON.parse(replacedContents); return DataConverter.convert(runtimeSchema, parsedContents); } + + static #replaceEnvValues(contents: string): string + { + return contents.replace(ENVIRONMENT_VARIABLE_REGEX, (match, group) => + { + const value = process.env[group]; + + if (value === undefined) + { + throw new EnvironmentVariableNotFound(group); + } + + return value; + }); + } } From 086e699d693cf15e301184e94cd380e050cb65a9 Mon Sep 17 00:00:00 2001 From: Bas Meeuwissen Date: Wed, 31 Jan 2024 06:31:50 +0100 Subject: [PATCH 2/6] #450: removed node version 18 and 19 The .env variables are not supported in these versions --- .github/workflows/nodejsci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/nodejsci.yml b/.github/workflows/nodejsci.yml index 6614f968..ca1345b9 100644 --- a/.github/workflows/nodejsci.yml +++ b/.github/workflows/nodejsci.yml @@ -17,7 +17,7 @@ jobs: strategy: matrix: - node-version: [18.x, 19.x, 20.x, 21.x] + node-version: [20.x, 21.x] steps: - uses: actions/checkout@v4 From ea4b453acc61c7a6348089e9dcd11d738b049786 Mon Sep 17 00:00:00 2001 From: Bas Meeuwissen Date: Wed, 31 Jan 2024 06:35:49 +0100 Subject: [PATCH 3/6] #450: updated docs --- .../docs/fundamentals/runtime-services.md | 15 ++++++++++++--- .../guides/add-jitar-to-an-existing-project.md | 2 +- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/documentation/docs/fundamentals/runtime-services.md b/documentation/docs/fundamentals/runtime-services.md index 4207b926..f9f3366b 100644 --- a/documentation/docs/fundamentals/runtime-services.md +++ b/documentation/docs/fundamentals/runtime-services.md @@ -37,6 +37,15 @@ Configurations are placed in JSON files. The basic structure looks like this. } ``` +::: tip NOTE +The configuration also supports environment variables. They can be used by wrapping the variable name in `${}`. For example, `${ENVIRONMENT_VARIABLE_1}`. +```json +{ + "PROPERTY_3": "${ENVIRONMENT_VARIABLE_3}" +} +``` +::: + There are four properties at root level: * url - service url containing protocol, address and port (e.g. `http://service.example.com:3000`). @@ -128,7 +137,7 @@ A full configuration example looks like this: "repository": "http://repository.example.com:3000", "segments": ["segment1", "segment2"], "middlewares": ["./middleware1", "./middleware2"], - "trustKey": "MY_TRUST_KEY" + "trustKey": "${MY_TRUST_KEY}" } } ``` @@ -176,7 +185,7 @@ A full configuration example looks like this: "repository": "http://repository.example.com:3000", "monitor": 5000, "middlewares": ["./middleware1", "./middleware2"], - "trustKey": "MY_TRUST_KEY" + "trustKey": "${MY_TRUST_KEY}" } } ``` @@ -252,7 +261,7 @@ A full configuration example looks like this: "assets": ["*.html", "*.js", "*.css", "assets/**/*"], "middlewares": ["./middleware1", "./middleware2"], "overrides": { "./my-module": "./alternative-module" }, - "trustKey": "MY_TRUST_KEY" + "trustKey": "${MY_TRUST_KEY}" } } ``` diff --git a/documentation/docs/guides/add-jitar-to-an-existing-project.md b/documentation/docs/guides/add-jitar-to-an-existing-project.md index f2c9b84e..3d7f6b7d 100644 --- a/documentation/docs/guides/add-jitar-to-an-existing-project.md +++ b/documentation/docs/guides/add-jitar-to-an-existing-project.md @@ -19,7 +19,7 @@ In this guide we will explain what needs to be done to add Jitar to your project A Jitar project has a few requirements to function properly. Before adding Jitar make sure the the following conditions are (or can be) met: -* Node version 18.17.1 or higher +* Node version 20.0 or higher * TypeScript 4.7 or higher * Use of ESM (CommonJS is not supported) * Vite, if a frontend needs to be hooked in From 5e667ea107f36545d1368b1fbd5a5f1122417468 Mon Sep 17 00:00:00 2001 From: Bas Meeuwissen Date: Wed, 31 Jan 2024 06:36:03 +0100 Subject: [PATCH 4/6] #450 updated example --- examples/concepts/access-protection/.env | 1 + examples/concepts/access-protection/package.json | 8 ++++---- examples/concepts/access-protection/services/game.json | 2 +- examples/concepts/access-protection/services/gateway.json | 2 +- .../concepts/access-protection/services/standalone.json | 2 +- examples/concepts/access-protection/services/web.json | 2 +- 6 files changed, 9 insertions(+), 8 deletions(-) create mode 100644 examples/concepts/access-protection/.env diff --git a/examples/concepts/access-protection/.env b/examples/concepts/access-protection/.env new file mode 100644 index 00000000..976d3558 --- /dev/null +++ b/examples/concepts/access-protection/.env @@ -0,0 +1 @@ +TRUST_KEY="MY_VERY_SECRET_KEY" \ No newline at end of file diff --git a/examples/concepts/access-protection/package.json b/examples/concepts/access-protection/package.json index c8a17d3b..d08b3f87 100644 --- a/examples/concepts/access-protection/package.json +++ b/examples/concepts/access-protection/package.json @@ -4,11 +4,11 @@ "private": true, "scripts": { "build": "tsc", - "standalone": "node --experimental-network-imports dist/jitar.js --config=services/standalone.json", + "standalone": "node --experimental-network-imports --env-file=.env dist/jitar.js --config=services/standalone.json", "repo": "node --experimental-network-imports dist/jitar.js --config=services/repository.json", - "gateway": "node --experimental-network-imports dist/jitar.js --config=services/gateway.json", - "node-web": "node --experimental-network-imports dist/jitar.js --config=services/web.json", - "node-game": "node --experimental-network-imports dist/jitar.js --config=services/game.json" + "gateway": "node --experimental-network-imports --env-file=.env dist/jitar.js --config=services/gateway.json", + "node-web": "node --experimental-network-imports --env-file=.env dist/jitar.js --config=services/web.json", + "node-game": "node --experimental-network-imports --env-file=.env dist/jitar.js --config=services/game.json" }, "dependencies": { "jitar": "^0.6.0" diff --git a/examples/concepts/access-protection/services/game.json b/examples/concepts/access-protection/services/game.json index f0a112dc..0569b862 100644 --- a/examples/concepts/access-protection/services/game.json +++ b/examples/concepts/access-protection/services/game.json @@ -5,6 +5,6 @@ "gateway": "http://127.0.0.1:3000", "repository": "http://127.0.0.1:2999", "segments": [ "protected" ], - "trustKey": "VERY_SECRET_KEY" + "trustKey": "${TRUST_KEY}" } } \ No newline at end of file diff --git a/examples/concepts/access-protection/services/gateway.json b/examples/concepts/access-protection/services/gateway.json index d3a0a998..76118495 100644 --- a/examples/concepts/access-protection/services/gateway.json +++ b/examples/concepts/access-protection/services/gateway.json @@ -2,6 +2,6 @@ "url": "http://127.0.0.1:3000", "gateway": { "repository": "http://127.0.0.1:2999", - "trustKey": "VERY_SECRET_KEY" + "trustKey": "${TRUST_KEY}" } } \ No newline at end of file diff --git a/examples/concepts/access-protection/services/standalone.json b/examples/concepts/access-protection/services/standalone.json index d48e7e32..85564881 100644 --- a/examples/concepts/access-protection/services/standalone.json +++ b/examples/concepts/access-protection/services/standalone.json @@ -2,6 +2,6 @@ "url": "http://127.0.0.1:3000", "standalone": { - "trustKey": "VERY_SECRET_KEY" + "trustKey": "${TRUST_KEY}" } } \ No newline at end of file diff --git a/examples/concepts/access-protection/services/web.json b/examples/concepts/access-protection/services/web.json index 97e30f1d..af103c41 100644 --- a/examples/concepts/access-protection/services/web.json +++ b/examples/concepts/access-protection/services/web.json @@ -5,6 +5,6 @@ "gateway": "http://127.0.0.1:3000", "repository": "http://127.0.0.1:2999", "segments": [ "public" ], - "trustKey": "VERY_SECRET_KEY" + "trustKey": "${TRUST_KEY}" } } \ No newline at end of file From e3a770972838b1c14e395aa3ec3a3b5f5f8a1db0 Mon Sep 17 00:00:00 2001 From: Bas Meeuwissen Date: Wed, 31 Jan 2024 08:38:34 +0100 Subject: [PATCH 5/6] #450: processed feedback --- .../server-nodejs/src/utils/RuntimeConfigurationLoader.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/server-nodejs/src/utils/RuntimeConfigurationLoader.ts b/packages/server-nodejs/src/utils/RuntimeConfigurationLoader.ts index bce242a6..bc29694f 100644 --- a/packages/server-nodejs/src/utils/RuntimeConfigurationLoader.ts +++ b/packages/server-nodejs/src/utils/RuntimeConfigurationLoader.ts @@ -14,13 +14,13 @@ export default class RuntimeConfigurationLoader static load(filename: string): RuntimeConfiguration { const plainContents = readFileSync(filename, 'utf-8'); - const replacedContents = this.#replaceEnvValues(plainContents); + const replacedContents = this.#replaceEnvironmentVariables(plainContents); const parsedContents = JSON.parse(replacedContents); return DataConverter.convert(runtimeSchema, parsedContents); } - static #replaceEnvValues(contents: string): string + static #replaceEnvironmentVariables(contents: string): string { return contents.replace(ENVIRONMENT_VARIABLE_REGEX, (match, group) => { From a82395c959bd6b21075902a0f70b60e13ef2b6a2 Mon Sep 17 00:00:00 2001 From: Bas Meeuwissen Date: Wed, 31 Jan 2024 08:49:58 +0100 Subject: [PATCH 6/6] #450: added breaking change information --- migrations/migrate-from-0.6.x-to-0.7.x.md | 7 +++++++ packages/jitar/package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 migrations/migrate-from-0.6.x-to-0.7.x.md diff --git a/migrations/migrate-from-0.6.x-to-0.7.x.md b/migrations/migrate-from-0.6.x-to-0.7.x.md new file mode 100644 index 00000000..755da92c --- /dev/null +++ b/migrations/migrate-from-0.6.x-to-0.7.x.md @@ -0,0 +1,7 @@ +# Migrate from 0.6.x to 0.7.0 + +The 0.7 version of Jitar introduces breaking changes. All changes are described here, with instructions how to adopt them. + +## Removed support for Node 18 and 19 + +The configuration now works with environment variables. This makes it easier and safer to configure the runtime services. But for reading the values in Node, the out-of-the-box .env capability of Node is used. Node 20 is the first version of Node that supports this. We've removed the support for the older versions of Node. diff --git a/packages/jitar/package.json b/packages/jitar/package.json index 78aa09d0..30062786 100644 --- a/packages/jitar/package.json +++ b/packages/jitar/package.json @@ -40,7 +40,7 @@ "@jitar/server-nodejs": "^0.6.0" }, "engines": { - "node": ">=18.7" + "node": ">=20.0" }, "repository": { "type": "git",