fix: runtime environment config

This commit is contained in:
cha0s 2024-02-12 06:27:24 -06:00
parent 5bfaf5a77f
commit 4d55e5524c
4 changed files with 60 additions and 42 deletions

View File

@ -86,40 +86,6 @@ module.exports = class Build extends Flecks {
await this.invokeSequentialAsync('@flecks/build.config.alter', config, env, argv); await this.invokeSequentialAsync('@flecks/build.config.alter', config, env, argv);
} }
static environmentalize(path) {
return path
// - `@flecks/core` -> `flecks_core`
.replace(/[^a-zA-Z0-9]/g, '_')
.replace(/_*(.*)_*/, '$1');
}
static environmentConfiguration(config) {
const keys = Object.keys(process.env);
Object.keys(config)
.sort((l, r) => (l < r ? 1 : -1))
.forEach((fleck) => {
const prefix = `FLECKS_ENV__${this.environmentalize(fleck)}`;
keys
.filter((key) => key.startsWith(`${prefix}__`))
.map((key) => {
debug('reading environment from %s...', key);
return [key.slice(prefix.length + 2), process.env[key]];
})
.map(([subkey, value]) => [subkey.split('_'), value])
.forEach(([path, jsonOrString]) => {
try {
Flecks.set(config, [fleck, ...path], JSON.parse(jsonOrString));
debug('read (%s) as JSON', jsonOrString);
}
catch (error) {
Flecks.set(config, [fleck, ...path], jsonOrString);
debug('read (%s) as string', jsonOrString);
}
});
});
return config;
}
static async from( static async from(
{ {
config: configParameter, config: configParameter,

View File

@ -219,6 +219,52 @@ class Flecks {
this.flecks = {}; this.flecks = {};
} }
/**
* Sanitize a fleck configuration path to an environment variable-friendly name.
*
* @param {string} path The path to sanitize.
* @returns {string}
*/
static environmentalize(path) {
return path
// - `@flecks/core` -> `flecks_core`
.replace(/[^a-zA-Z0-9]/g, '_')
.replace(/_*(.*)_*/, '$1');
}
/**
* Override configuration through environment variables.
*
* @param {Object} config The configuration to override.
* @returns {Object}
*/
static environmentConfiguration(config) {
const keys = Object.keys(process.env);
Object.keys(config)
.sort((l, r) => (l < r ? 1 : -1))
.forEach((fleck) => {
const prefix = `FLECKS_ENV__${this.environmentalize(fleck)}`;
keys
.filter((key) => key.startsWith(`${prefix}__`))
.map((key) => {
debug('reading environment from %s...', key);
return [key.slice(prefix.length + 2), process.env[key]];
})
.map(([subkey, value]) => [subkey.split('_'), value])
.forEach(([path, jsonOrString]) => {
try {
Flecks.set(config, [fleck, ...path], JSON.parse(jsonOrString));
debug('read (%s) as JSON', jsonOrString);
}
catch (error) {
Flecks.set(config, [fleck, ...path], jsonOrString);
debug('read (%s) as string', jsonOrString);
}
});
});
return config;
}
/** /**
* Lists all flecks implementing a hook, including platform-specific and elided variants. * Lists all flecks implementing a hook, including platform-specific and elided variants.
* *

View File

@ -16,11 +16,13 @@ async function runtimeModule(compilation, flecks) {
/* eslint-disable indent */ /* eslint-disable indent */
bootstrappedConfig: JSON.stringify(flecks.invoke('@flecks/core.config')), bootstrappedConfig: JSON.stringify(flecks.invoke('@flecks/core.config')),
config: (` config: (`
dealiasedConfig(${ Flecks.environmentConfiguration(
'production' === compiler.options.mode Flecks.dealiasedConfig(${
? JSON.stringify(flecks.originalConfig) 'production' === compiler.options.mode
: `require('${ymlPath}').default` ? JSON.stringify(flecks.originalConfig)
}) : `require('${ymlPath}').default`
})
)
`), `),
/* eslint-enable indent */ /* eslint-enable indent */
loadFlecks: [ loadFlecks: [
@ -54,7 +56,7 @@ async function runtimeModule(compilation, flecks) {
.map(([key, value]) => `"${key}": ${value}`).join(', ') .map(([key, value]) => `"${key}": ${value}`).join(', ')
}}`; }}`;
const source = [ const source = [
`const {dealiasedConfig} = {${flecks.constructor.dealiasedConfig.toString()}};`, "const {Flecks} = require('@flecks/core');",
"process.env.FLECKS_CORE_BUILD_TARGET = 'server';", "process.env.FLECKS_CORE_BUILD_TARGET = 'server';",
`module.exports = (async () => (${runtimeString}))();`, `module.exports = (async () => (${runtimeString}))();`,
]; ];

View File

@ -7,7 +7,7 @@ import {D, Flecks} from '@flecks/core';
(async () => { (async () => {
const runtime = await import('@flecks/server/runtime'); const runtime = await import('@flecks/server/runtime');
const {loadFlecks, version} = runtime; const {config, loadFlecks, version} = runtime;
// eslint-disable-next-line no-console // eslint-disable-next-line no-console
console.log(`flecks server v${version}`); console.log(`flecks server v${version}`);
try { try {
@ -20,7 +20,11 @@ import {D, Flecks} from '@flecks/core';
} }
const debug = D('@flecks/server/entry'); const debug = D('@flecks/server/entry');
debug('starting server...'); debug('starting server...');
global.flecks = await Flecks.from({...runtime, flecks: await loadFlecks()}); global.flecks = await Flecks.from({
...runtime,
config: Flecks.environmentConfiguration(config),
flecks: await loadFlecks(),
});
await global.flecks.invokeSequentialAsync('@flecks/server.up'); await global.flecks.invokeSequentialAsync('@flecks/server.up');
debug('up!'); debug('up!');
})(); })();