Problem: Adapt Configuration Sources

Medium
30 min
Unify environment, file-based, and remote configuration providers under a single .get(key) interface.

Problem statement

Your system reads configuration values from different sources depending on the deployment environment:

  • Environment variables via process.env.

  • JSON config file for local development.

  • Remote config service in production, which fetches values asynchronously.

Each source has a different interface:

  • The env provider reads synchronously via property access.

  • The file provider loads from an object in memory.

  • The remote provider exposes an async .fetch(key) method.

To simplify configuration access across your codebase, you need an adapter that makes all three sources behave uniformly.

Goal

Implement a ConfigAdapter class exposing an async method:

async get(key)

It should:

  • Return the correct value from the underlying provider.

  • Normalize sync and async differences.

  • Always resolve to null if the key doesn’t exist.

Constraints

  • You cannot modify the original providers.

  • The adapter must support all three data sources.

  • All calls to .get() should be awaitable.

  • Avoid environment conditionals (if (env === 'prod')); use capability detection instead.

Sample output

The examples below illustrate what the output should look like:

(async () => {
const envConfig = new ConfigAdapter(envProvider);
const fileConfig = new ConfigAdapter(fileProvider);
const remoteConfig = new ConfigAdapter(remoteProvider);
console.log(await envConfig.get('PATH'));
console.log(await fileConfig.get('apiUrl'));
console.log(await remoteConfig.get('apiUrl'));
})();
/* Expected output:
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
http://localhost:3000
https://api.prod.com
*/

Good luck trying the problem! If you’re unsure how to proceed, check the “Solution” tab above.

Problem: Adapt Configuration Sources

Medium
30 min
Unify environment, file-based, and remote configuration providers under a single .get(key) interface.

Problem statement

Your system reads configuration values from different sources depending on the deployment environment:

  • Environment variables via process.env.

  • JSON config file for local development.

  • Remote config service in production, which fetches values asynchronously.

Each source has a different interface:

  • The env provider reads synchronously via property access.

  • The file provider loads from an object in memory.

  • The remote provider exposes an async .fetch(key) method.

To simplify configuration access across your codebase, you need an adapter that makes all three sources behave uniformly.

Goal

Implement a ConfigAdapter class exposing an async method:

async get(key)

It should:

  • Return the correct value from the underlying provider.

  • Normalize sync and async differences.

  • Always resolve to null if the key doesn’t exist.

Constraints

  • You cannot modify the original providers.

  • The adapter must support all three data sources.

  • All calls to .get() should be awaitable.

  • Avoid environment conditionals (if (env === 'prod')); use capability detection instead.

Sample output

The examples below illustrate what the output should look like:

(async () => {
const envConfig = new ConfigAdapter(envProvider);
const fileConfig = new ConfigAdapter(fileProvider);
const remoteConfig = new ConfigAdapter(remoteProvider);
console.log(await envConfig.get('PATH'));
console.log(await fileConfig.get('apiUrl'));
console.log(await remoteConfig.get('apiUrl'));
})();
/* Expected output:
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
http://localhost:3000
https://api.prod.com
*/

Good luck trying the problem! If you’re unsure how to proceed, check the “Solution” tab above.

Node.js
// Simulated environment variable provider
const envProvider = {
getValue(key) {
return process.env[key] ?? null;
}
};
// Simulated JSON config provider
const fileProvider = {
config: { apiUrl: 'http://localhost:3000', debug: true },
read(key) {
return this.config[key] ?? null;
}
};
// Simulated remote config provider
const remoteProvider = {
async fetch(key) {
return new Promise(resolve => {
setTimeout(() => {
const remoteConfig = { apiUrl: 'https://api.prod.com', debug: false };
resolve(remoteConfig[key] ?? null);
}, 100);
});
}
};
// Your code here
// Example usage
(async () => {
const envConfig = new ConfigAdapter(envProvider);
const fileConfig = new ConfigAdapter(fileProvider);
const remoteConfig = new ConfigAdapter(remoteProvider);
console.log(await envConfig.get('PATH'));
console.log(await fileConfig.get('apiUrl'));
console.log(await remoteConfig.get('apiUrl'));
})();
/* Expected output:
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
http://localhost:3000
https://api.prod.com
*/