config: flip priority order of ConfigReader.fromConfigs

This commit is contained in:
Patrik Oldsberg
2020-08-07 11:27:46 +02:00
parent f7532bcf1c
commit 1f2216fd77
13 changed files with 68 additions and 71 deletions
+1 -1
View File
@@ -24,7 +24,7 @@ export async function loadBackendConfig() {
const paths = findPaths(__dirname);
const configs = await loadConfig({
env: process.env.NODE_ENV,
rootPaths: [paths.targetDir, paths.targetRoot],
rootPaths: [paths.targetRoot, paths.targetDir],
shouldReadSecrets: true,
});
return configs;
+1 -1
View File
@@ -23,7 +23,7 @@ import { buildBundle } from '../../lib/bundler';
export default async (cmd: Command) => {
const appConfigs = await loadConfig({
env: 'production',
rootPaths: [paths.targetDir, paths.targetRoot],
rootPaths: [paths.targetRoot, paths.targetDir],
});
await buildBundle({
entry: 'src/index',
+1 -1
View File
@@ -23,7 +23,7 @@ import { serveBundle } from '../../lib/bundler';
export default async (cmd: Command) => {
const appConfigs = await loadConfig({
env: 'development',
rootPaths: [paths.targetDir, paths.targetRoot],
rootPaths: [paths.targetRoot, paths.targetDir],
});
const waitForExit = await serveBundle({
entry: 'src/index',
+1 -1
View File
@@ -23,7 +23,7 @@ import { serveBackend } from '../../lib/bundler/backend';
export default async (cmd: Command) => {
const appConfigs = await loadConfig({
env: 'development',
rootPaths: [paths.targetDir, paths.targetRoot],
rootPaths: [paths.targetRoot, paths.targetDir],
});
const waitForExit = await serveBackend({
entry: 'src/index',
+1 -1
View File
@@ -23,7 +23,7 @@ import { buildBundle } from '../../lib/bundler';
export default async (cmd: Command) => {
const appConfigs = await loadConfig({
env: 'production',
rootPaths: [paths.targetDir, paths.targetRoot],
rootPaths: [paths.targetRoot, paths.targetDir],
});
await buildBundle({
entry: 'dev/index',
+1 -1
View File
@@ -23,7 +23,7 @@ import { serveBundle } from '../../lib/bundler';
export default async (cmd: Command) => {
const appConfigs = await loadConfig({
env: 'development',
rootPaths: [paths.targetDir, paths.targetRoot],
rootPaths: [paths.targetRoot, paths.targetDir],
});
const waitForExit = await serveBundle({
entry: 'dev/index',
+11 -11
View File
@@ -57,16 +57,16 @@ describe('resolveStaticConfig', () => {
const resolved = await resolveStaticConfig({
env: 'development',
rootPaths: [
'/repo',
'/other-repo',
'/repo/packages/a',
'/repo/packages/b',
'/other-repo',
'/repo',
],
});
expect(resolved).toEqual([
'/repo/packages/a/app-config.yaml',
'/repo/app-config.yaml',
'/repo/packages/a/app-config.yaml',
]);
expect(pathExists).toHaveBeenCalledTimes(16);
});
@@ -85,15 +85,15 @@ describe('resolveStaticConfig', () => {
);
const resolved = await resolveStaticConfig({
env: 'development',
rootPaths: ['/repo/packages/a', '/repo'],
rootPaths: ['/repo', '/repo/packages/a'],
});
expect(resolved).toEqual([
'/repo/packages/a/app-config.development.yaml',
'/repo/packages/a/app-config.local.yaml',
'/repo/app-config.development.local.yaml',
'/repo/app-config.local.yaml',
'/repo/app-config.yaml',
'/repo/app-config.local.yaml',
'/repo/app-config.development.local.yaml',
'/repo/packages/a/app-config.local.yaml',
'/repo/packages/a/app-config.development.yaml',
]);
expect(pathExists).toHaveBeenCalledTimes(8);
});
@@ -106,10 +106,10 @@ describe('resolveStaticConfig', () => {
});
expect(resolved).toEqual([
'/repo/app-config.production.local.yaml',
'/repo/app-config.production.yaml',
'/repo/app-config.local.yaml',
'/repo/app-config.yaml',
'/repo/app-config.local.yaml',
'/repo/app-config.production.yaml',
'/repo/app-config.production.local.yaml',
]);
expect(pathExists).toHaveBeenCalledTimes(4);
});
+4 -4
View File
@@ -18,7 +18,7 @@ import { resolve as resolvePath } from 'path';
import { pathExists } from 'fs-extra';
type ResolveOptions = {
// Root paths to search for config files. Config from earlier paths has higher priority.
// Root paths to search for config files. Config from earlier paths has lower priority.
rootPaths: string[];
// The environment that we're loading config for, e.g. 'development', 'production'.
env: string;
@@ -38,10 +38,10 @@ export async function resolveStaticConfig(
options: ResolveOptions,
): Promise<string[]> {
const filePaths = [
`app-config.${options.env}.local.yaml`,
`app-config.${options.env}.yaml`,
`app-config.local.yaml`,
`app-config.yaml`,
`app-config.local.yaml`,
`app-config.${options.env}.yaml`,
`app-config.${options.env}.local.yaml`,
];
const resolvedPaths = [];
+3 -3
View File
@@ -25,7 +25,7 @@ import {
} from './lib';
export type LoadConfigOptions = {
// Root paths to search for config files. Config from earlier paths has higher priority.
// Root paths to search for config files. Config from earlier paths has lower priority.
rootPaths: string[];
// The environment that we're loading config for, e.g. 'development', 'production'.
@@ -66,8 +66,6 @@ export async function loadConfig(
): Promise<AppConfig[]> {
const configs = [];
configs.push(...readEnv(process.env));
const configPaths = await resolveStaticConfig(options);
try {
@@ -89,5 +87,7 @@ export async function loadConfig(
);
}
configs.push(...readEnv(process.env));
return configs;
}
+37 -37
View File
@@ -214,9 +214,19 @@ describe('ConfigReader with fallback', () => {
const config = ConfigReader.fromConfigs([
{
data: {
a: true,
b: true,
c: true,
nested1: {
a: true,
b: true,
},
badBefore: {
a: true,
},
badAfter: true,
},
context: 'x',
context: 'z',
},
{
data: {
@@ -234,19 +244,9 @@ describe('ConfigReader with fallback', () => {
},
{
data: {
a: true,
b: true,
c: true,
nested1: {
a: true,
b: true,
},
badBefore: {
a: true,
},
badAfter: true,
},
context: 'z',
context: 'x',
},
]);
@@ -427,42 +427,42 @@ describe('ConfigReader.get()', () => {
});
it('should merge in fallback configs', () => {
expect(ConfigReader.fromConfigs([configs[0], configs[1]]).get('a')).toEqual(
expect(ConfigReader.fromConfigs([configs[1], configs[0]]).get('a')).toEqual(
{
x: 'x1',
y: ['y11', 'y12', 'y13'],
z: false,
},
);
expect(ConfigReader.fromConfigs([configs[0], configs[1]]).get('b')).toEqual(
expect(ConfigReader.fromConfigs([configs[1], configs[0]]).get('b')).toEqual(
{
x: 'x1',
y: ['y11'],
z: 'z2',
},
);
expect(ConfigReader.fromConfigs([configs[0], configs[1]]).get('c')).toEqual(
expect(ConfigReader.fromConfigs([configs[1], configs[0]]).get('c')).toEqual(
{
c1: {
c2: 'c2',
},
},
);
expect(ConfigReader.fromConfigs([configs[0], configs[1]]).get('a')).toEqual(
expect(ConfigReader.fromConfigs([configs[1], configs[0]]).get('a')).toEqual(
{
x: 'x1',
y: ['y11', 'y12', 'y13'],
z: false,
},
);
expect(ConfigReader.fromConfigs([configs[0], configs[1]]).get('b')).toEqual(
expect(ConfigReader.fromConfigs([configs[1], configs[0]]).get('b')).toEqual(
{
x: 'x1',
y: ['y11'],
z: 'z2',
},
);
expect(ConfigReader.fromConfigs([configs[0], configs[1]]).get('c')).toEqual(
expect(ConfigReader.fromConfigs([configs[1], configs[0]]).get('c')).toEqual(
{
c1: {
c2: 'c2',
@@ -471,14 +471,14 @@ describe('ConfigReader.get()', () => {
);
expect(
ConfigReader.fromConfigs([configs[2], configs[1]]).getOptional('b'),
ConfigReader.fromConfigs([configs[1], configs[2]]).getOptional('b'),
).toEqual({
x: 'x2',
y: ['y21', 'y22'],
z: 'z2',
});
expect(
ConfigReader.fromConfigs([configs[2], configs[1]]).getOptional('c'),
ConfigReader.fromConfigs([configs[1], configs[2]]).getOptional('c'),
).toEqual({
c1: 'c1',
});
@@ -486,23 +486,6 @@ describe('ConfigReader.get()', () => {
it('should not merge non-objects', () => {
const config = ConfigReader.fromConfigs([
{
data: {
a: ['1', '2'],
c: [],
d: {
x: 'x',
},
e: ['3'],
f: 'foo',
g: { z: 'z' },
h: {
a: 'a1',
c: 'c1',
},
},
context: '1',
},
{
data: {
a: ['x', 'y', 'z'],
@@ -521,6 +504,23 @@ describe('ConfigReader.get()', () => {
},
context: '2',
},
{
data: {
a: ['1', '2'],
c: [],
d: {
x: 'x',
},
e: ['3'],
f: 'foo',
g: { z: 'z' },
h: {
a: 'a1',
c: 'c1',
},
},
context: '1',
},
]);
expect(config.get('a')).toEqual(['1', '2']);
expect(config.get('b')).toEqual(['1']);
+5 -8
View File
@@ -57,14 +57,11 @@ export class ConfigReader implements Config {
return new ConfigReader(undefined);
}
// Merge together all configs info a single config with recursive fallback
// readers, giving the first config object in the array the highest priority.
return configs.reduceRight<ConfigReader>(
(previousReader, { data, context }) => {
return new ConfigReader(data, context, previousReader);
},
undefined!,
);
// Merge together all configs into a single config with recursive fallback
// readers, giving the first config object in the array the lowest priority.
return configs.reduce<ConfigReader>((previousReader, { data, context }) => {
return new ConfigReader(data, context, previousReader);
}, undefined!);
}
constructor(
@@ -49,9 +49,9 @@ describe('defaultConfigLoader', () => {
'{"my":"runtime-config"}',
);
expect(configs).toEqual([
{ data: { my: 'runtime-config' }, context: 'env' },
{ data: { my: 'override-config' }, context: 'a' },
{ data: { my: 'config' }, context: 'b' },
{ data: { my: 'runtime-config' }, context: 'env' },
]);
});
+1 -1
View File
@@ -60,7 +60,7 @@ export const defaultConfigLoader: AppConfigLoader = async (
if (runtimeConfigJson !== '__app_injected_runtime_config__'.toUpperCase()) {
try {
const data = JSON.parse(runtimeConfigJson) as JsonObject;
configs.unshift({ data, context: 'env' });
configs.push({ data, context: 'env' });
} catch (error) {
throw new Error(`Failed to load runtime configuration, ${error}`);
}