diff --git a/packages/backend-common/src/config.ts b/packages/backend-common/src/config.ts index 2295a8f943..6f7500bb86 100644 --- a/packages/backend-common/src/config.ts +++ b/packages/backend-common/src/config.ts @@ -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; diff --git a/packages/cli/src/commands/app/build.ts b/packages/cli/src/commands/app/build.ts index 12ea362063..21d6924b15 100644 --- a/packages/cli/src/commands/app/build.ts +++ b/packages/cli/src/commands/app/build.ts @@ -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', diff --git a/packages/cli/src/commands/app/serve.ts b/packages/cli/src/commands/app/serve.ts index b372663f09..a04e73dceb 100644 --- a/packages/cli/src/commands/app/serve.ts +++ b/packages/cli/src/commands/app/serve.ts @@ -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', diff --git a/packages/cli/src/commands/backend/dev.ts b/packages/cli/src/commands/backend/dev.ts index cbea2c60cc..91c08af201 100644 --- a/packages/cli/src/commands/backend/dev.ts +++ b/packages/cli/src/commands/backend/dev.ts @@ -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', diff --git a/packages/cli/src/commands/plugin/export.ts b/packages/cli/src/commands/plugin/export.ts index 6de3e14c59..8f3c132285 100644 --- a/packages/cli/src/commands/plugin/export.ts +++ b/packages/cli/src/commands/plugin/export.ts @@ -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', diff --git a/packages/cli/src/commands/plugin/serve.ts b/packages/cli/src/commands/plugin/serve.ts index c23ae060aa..a677bec918 100644 --- a/packages/cli/src/commands/plugin/serve.ts +++ b/packages/cli/src/commands/plugin/serve.ts @@ -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', diff --git a/packages/config-loader/src/lib/resolver.test.ts b/packages/config-loader/src/lib/resolver.test.ts index 78e869e612..c804a6cef3 100644 --- a/packages/config-loader/src/lib/resolver.test.ts +++ b/packages/config-loader/src/lib/resolver.test.ts @@ -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); }); diff --git a/packages/config-loader/src/lib/resolver.ts b/packages/config-loader/src/lib/resolver.ts index 2ee200fbd0..44f0f6ea9e 100644 --- a/packages/config-loader/src/lib/resolver.ts +++ b/packages/config-loader/src/lib/resolver.ts @@ -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 { 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 = []; diff --git a/packages/config-loader/src/loader.ts b/packages/config-loader/src/loader.ts index 27df7ac831..0cc8ac29f5 100644 --- a/packages/config-loader/src/loader.ts +++ b/packages/config-loader/src/loader.ts @@ -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 { 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; } diff --git a/packages/config/src/reader.test.ts b/packages/config/src/reader.test.ts index 9d06e0b025..9cfc1d7f34 100644 --- a/packages/config/src/reader.test.ts +++ b/packages/config/src/reader.test.ts @@ -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']); diff --git a/packages/config/src/reader.ts b/packages/config/src/reader.ts index 0669bcb6d8..86fb125a47 100644 --- a/packages/config/src/reader.ts +++ b/packages/config/src/reader.ts @@ -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( - (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((previousReader, { data, context }) => { + return new ConfigReader(data, context, previousReader); + }, undefined!); } constructor( diff --git a/packages/core/src/api-wrappers/createApp.test.tsx b/packages/core/src/api-wrappers/createApp.test.tsx index 0a3756ad92..33623b4869 100644 --- a/packages/core/src/api-wrappers/createApp.test.tsx +++ b/packages/core/src/api-wrappers/createApp.test.tsx @@ -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' }, ]); }); diff --git a/packages/core/src/api-wrappers/createApp.tsx b/packages/core/src/api-wrappers/createApp.tsx index 60c69d01c5..9d2096cfff 100644 --- a/packages/core/src/api-wrappers/createApp.tsx +++ b/packages/core/src/api-wrappers/createApp.tsx @@ -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}`); }