Oh boy, this is exciting!
Tags: webdev, javascript, programming, react
Published: 2022-12-19 15:54:55

So last Saturday and Sunday I took the time to finally complete the set of features I wanted to deliver in **v2.0.0** of [wj-config](https://www.npmjs.com/package/wj-config).

So I did that on Saturday and started re-working the React v18.2.0 example I have in the repository to make sure all was working as expected.  While doing this and updating the project's  README, I realized of a few things that led me to work on higher API to help comply with **DRY**.  This took the Sunday evening.

#### Quick Screenshot of the React Sample

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lj6nix2is2ndwaxvrefi.png)

---

Anyway, the end result is quite interesting.  Let me put it like this:  Have you ever had the need to have configuration values vary depending on things like the browser the user is using? (Honest question, I am no backend developer).  Well, now you'll be able to!

One new feature, **conditional inclusion of data sources** allows  you to run abritrary checks, including things like checking for browser capabilities.  I'll give you a preview of the example code I wrote for the README:

```javascript
import wjConfig, { Environment } from "wj-config";
import mainConfig from './config.json';

// Chromium-based browsers.
var isChromium = !!window.chrome && (!!window.chrome.webstore || !!window.chrome.runtime);

export default await wjConfig()
    .addObject(mainConfig)
    .name('Main')
    .addFetchedConfig('/config.chromium.json')
    .when(e => isChromium, 'Chromium')
    .build();
```

## Per-Region Or Per-Tenant Configuration

>This was the original feature I wanted to complete before releasing **v2.0.0** as a production package.

Have you ever had this need to have different production configuration files per region or per tenant, and maybe even for pre-production environments too?  Have you done this combination of files yourself, producing stuff like `config.prod.tenantA.json`, `config.prod.tenantB.json`, `config.pre-prod.tenantA.json` and `config.prod.tenantB.json`?  And so on for other environments?

Well, with **Per-Trait Configuration** this multiple configuration file creation will no longer be needed.  Here's an example preview taken from the upcomming README.  It basically computes the combination you need on the spot:

```javascript
import wjConfig, { Environment, EnvironmentDefinition } from "wj-config";
import myTraits from './myTraits.js';

// Easiest to show with NodeJS as we already have an environment object with all variables ready.
// The ENV_TRAITS environment variable would contain the desired trait value assigned when deploying.
const currentEnvDef = new EnvironmentDefinition(process.env.NODE_ENV, process.env.ENV_TRAITS);
const env = new Environment(currentEnvDef, ['MyList', 'OfPossible', 'Environments']);
// Main configuration file.  Boolean argument defines if the file must exist.
const mainConfig = loadJsonFile('./config.json', true);
// Classic per-environment configuration.
const perEnvConfig = loadJsonFile(`config.${env.current.name}.json`, false);
export default await wjConfig()
    .addObject(mainConfig)
    .name('Main')
    .addObject(perEnvConfig)
    .name(env.current.name)
    .addComputed(() => loadJsonFile('config.amr.json', false))
    // The second parameter is just the data source name.
    .whenAllTraits(myTraits.Americas, 'Americas') // <-- It conditions the recently added data source.
    .addComputed(() => loadJsonFile('config.eur.json', false))
    .whenAllTraits(myTraits.Europe, 'Europe')
    .addComputed(() => loadJsonFile('config.asa.json', false))
    .whenAllTraits(myTraits.Asia, 'Asia')
    .includeEnvironment(env)
    .build();
```

Oh, if you don't know, **wj-config** works for **React** and **NodeJS** the same way.  The only differences you see is things like fetching config files in React, but loading files in NodeJS.

Still working on the final details of the documentation and making sure the TypeScript types are all updated and reflecting the new API properly.  Maybe by next weekend we'll have a commit and a new NPM package upload.  Fingers crossed!