Skip to content

Commit

Permalink
make it possible to use root .env with FLAT env variables
Browse files Browse the repository at this point in the history
  • Loading branch information
JeromeBu committed Mar 20, 2024
1 parent 0f23403 commit dae46a3
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 30 deletions.
3 changes: 2 additions & 1 deletion api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"test": "vitest --watch=false",
"dev": "yarn build && yarn start",
"build": "tsc",
"start": "./.env.local.sh forever dist/main.js",
"start": "dotenv -e ../.env -- forever dist/main.js",
"_format": "prettier \"**/*.{ts,tsx,json,md}\"",
"format": "yarn run _format --write",
"format:check": "yarn run _format --list-different",
Expand Down Expand Up @@ -51,6 +51,7 @@
"cors": "^2.8.5",
"csv-parse": "^5.0.4",
"deepmerge": "^4.2.2",
"dotenv-cli": "^7.4.1",
"evt": "^2.5.7",
"express": "^4.17.2",
"forever": "^4.0.3",
Expand Down
72 changes: 43 additions & 29 deletions api/src/env.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
import { symToStr } from "tsafe/symToStr";
import { assert } from "tsafe/assert";
import * as JSONC from "comment-json";
import { z } from "zod";
import { zLocalizedString } from "./core/ports/GetSoftwareExternalData";
import { is } from "tsafe/is";

const zParsedCONFIGURATION = z.object({
const zConfiguration = z.object({
"keycloakParams": z
.object({
"url": z.string().nonempty(), //Example: https://auth.code.gouv.fr/auth (with the /auth at the end)
Expand Down Expand Up @@ -33,42 +30,59 @@ const zParsedCONFIGURATION = z.object({
// we use the GitHub API for pre filling the version when adding a software
"githubPersonalAccessTokenForApiRateLimit": z.string().nonempty(),
//Port we listen to, default 8080
"port": z.number().optional(),
"port": z.coerce.number().optional(),
"isDevEnvironnement": z.boolean().optional(),
// Completely disable this instance and redirect to another url
"redirectUrl": z.string().optional(),
"externalSoftwareDataOrigin": z.enum(["wikidata", "HAL"]).optional()
});

const { parsedCONFIGURATION } = (() => {
const getJsonConfiguration = () => {
const { CONFIGURATION } = process.env;

if (CONFIGURATION === undefined) {
throw new Error(
`We need a ${symToStr({
CONFIGURATION
})} environnement variable`
);
}

let parsedCONFIGURATION: unknown;

try {
parsedCONFIGURATION = JSONC.parse(CONFIGURATION) as any;
} catch (error) {
throw new Error(
`The CONFIGURATION environnement variable is not a valid JSONC string (JSONC = JSON + Comment support)\n${CONFIGURATION}: ${String(
error
)}`
);
if (CONFIGURATION) {
try {
return JSONC.parse(CONFIGURATION) as any;
} catch (error) {
throw new Error(
`The CONFIGURATION environnement variable is not a valid JSONC string (JSONC = JSON + Comment support)\n${CONFIGURATION}: ${String(
error
)}`
);
}
}

zParsedCONFIGURATION.parse(parsedCONFIGURATION);
return {
"keycloakParams": {
"url": process.env.SILL_KEYCLOAK_URL,
"realm": process.env.SILL_KEYCLOAK_REALM,
"clientId": process.env.SILL_KEYCLOAK_CLIENT_ID,
"adminPassword": process.env.SILL_KEYCLOAK_ADMIN_PASSWORD,
"organizationUserProfileAttributeName": process.env.SILL_KEYCLOAK_ORGANIZATION_USER_PROFILE_ATTRIBUTE_NAME
},
"readmeUrl": process.env.SILL_README_URL,
"termsOfServiceUrl": process.env.SILL_TERMS_OF_SERVICE_URL,
"jwtClaimByUserKey": {
"id": process.env.SILL_JWT_ID,
"email": process.env.SILL_JWT_EMAIL,
"organization": process.env.SILL_JWT_ORGANIZATION
},
"dataRepoSshUrl": process.env.SILL_DATA_REPO_SSH_URL,
"sshPrivateKeyForGitName": process.env.SILL_SSH_NAME,
"sshPrivateKeyForGit": process.env.SILL_SSH_PRIVATE_KEY,
"githubPersonalAccessTokenForApiRateLimit": process.env.SILL_GITHUB_TOKEN,
"githubWebhookSecret": process.env.SILL_WEBHOOK_SECRET,
"port": parseInt(process.env.SILL_API_PORT ?? ""),
"isDevEnvironnement": process.env.SILL_IS_DEV_ENVIRONNEMENT?.toLowerCase() === "true",
"externalSoftwareDataOrigin": process.env.SILL_EXTERNAL_SOFTWARE_DATA_ORIGIN
};
};

assert(is<ReturnType<(typeof zParsedCONFIGURATION)["parse"]>>(parsedCONFIGURATION));
const getValidConfiguration = (): z.infer<typeof zConfiguration> => {
const configuration = getJsonConfiguration();
return zConfiguration.parse(configuration);
};

return { parsedCONFIGURATION };
})();
const parsedCONFIGURATION = getValidConfiguration();

export const env = {
...parsedCONFIGURATION,
Expand Down
20 changes: 20 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -7642,6 +7642,21 @@ dot-prop@^4.1.0:
dependencies:
is-obj "^1.0.0"

dotenv-cli@^7.4.1:
version "7.4.1"
resolved "https://registry.yarnpkg.com/dotenv-cli/-/dotenv-cli-7.4.1.tgz#be3895878775c257e9864e5e57ff801d7492dcf8"
integrity sha512-fE1aywjRrWGxV3miaiUr3d2zC/VAiuzEGghi+QzgIA9fEf/M5hLMaRSXb4IxbUAwGmaLi0IozdZddnVU96acag==
dependencies:
cross-spawn "^7.0.3"
dotenv "^16.3.0"
dotenv-expand "^10.0.0"
minimist "^1.2.6"

dotenv-expand@^10.0.0:
version "10.0.0"
resolved "https://registry.yarnpkg.com/dotenv-expand/-/dotenv-expand-10.0.0.tgz#12605d00fb0af6d0a592e6558585784032e4ef37"
integrity sha512-GopVGCpVS1UKH75VKHGuQFqS1Gusej0z4FyQkPdwjil2gNIv+LNsqBlboOzpJFZKVT95GkCyWJbBSdFEFUWI2A==

dotenv-expand@^5.1.0:
version "5.1.0"
resolved "https://registry.yarnpkg.com/dotenv-expand/-/dotenv-expand-5.1.0.tgz#3fbaf020bfd794884072ea26b1e9791d45a629f0"
Expand All @@ -7652,6 +7667,11 @@ dotenv@^10.0.0:
resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-10.0.0.tgz#3d4227b8fb95f81096cdd2b66653fb2c7085ba81"
integrity sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==

dotenv@^16.3.0:
version "16.4.5"
resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.4.5.tgz#cdd3b3b604cb327e286b4762e13502f717cb099f"
integrity sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==

dotenv@^8.0.0:
version "8.6.0"
resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-8.6.0.tgz#061af664d19f7f4d8fc6e4ff9b584ce237adcb8b"
Expand Down

0 comments on commit dae46a3

Please sign in to comment.