config-loader: automatically flatten merged config sources
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
This commit is contained in:
@@ -17,8 +17,9 @@
|
||||
import { MergedConfigSource } from './MergedConfigSource';
|
||||
import { MutableConfigSource } from './MutableConfigSource';
|
||||
import { isResolved, readAll, simpleSource } from './__testUtils__/testUtils';
|
||||
import { ConfigSource } from './types';
|
||||
|
||||
describe('MergeConfigSource', () => {
|
||||
describe('MergedConfigSource', () => {
|
||||
it('should forward from a single source', async () => {
|
||||
const source = simpleSource([{ a: 1 }, { a: 2 }, { a: 3 }]);
|
||||
const merged = MergedConfigSource.from([source]);
|
||||
@@ -104,4 +105,47 @@ describe('MergeConfigSource', () => {
|
||||
done: true,
|
||||
});
|
||||
});
|
||||
|
||||
it('should be flattened', async () => {
|
||||
const sym = Symbol.for(
|
||||
'@backstage/config-loader#MergedConfigSource.sources',
|
||||
);
|
||||
const sourceA: ConfigSource = {
|
||||
async *readConfigData() {
|
||||
yield { data: [] };
|
||||
},
|
||||
};
|
||||
const sourceD: ConfigSource = {
|
||||
async *readConfigData() {
|
||||
yield { data: [] };
|
||||
},
|
||||
};
|
||||
const sourceB: ConfigSource = {
|
||||
async *readConfigData() {
|
||||
yield { data: [] };
|
||||
},
|
||||
};
|
||||
const sourceC: ConfigSource = {
|
||||
async *readConfigData() {
|
||||
yield { data: [] };
|
||||
},
|
||||
};
|
||||
|
||||
const sourceAB = MergedConfigSource.from([sourceA, sourceB]);
|
||||
const sourceABC = MergedConfigSource.from([sourceAB, sourceC]);
|
||||
const sourceABCD = MergedConfigSource.from([sourceABC, sourceD]);
|
||||
|
||||
expect((sourceAB as any)[sym]).toEqual([sourceA, sourceB]);
|
||||
expect((sourceABC as any)[sym]).toEqual([sourceA, sourceB, sourceC]);
|
||||
expect((sourceABCD as any)[sym]).toEqual([
|
||||
sourceA,
|
||||
sourceB,
|
||||
sourceC,
|
||||
sourceD,
|
||||
]);
|
||||
|
||||
await expect(readAll(sourceAB)).resolves.toEqual([[]]);
|
||||
await expect(readAll(sourceABC)).resolves.toEqual([[]]);
|
||||
await expect(readAll(sourceABCD)).resolves.toEqual([[]]);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -21,13 +21,29 @@ import {
|
||||
ReadConfigDataOptions,
|
||||
} from './types';
|
||||
|
||||
const sourcesSymbol = Symbol.for(
|
||||
'@backstage/config-loader#MergedConfigSource.sources',
|
||||
);
|
||||
|
||||
export class MergedConfigSource implements ConfigSource {
|
||||
// An optimization to flatten nested merged sources to avid unnecessary microtasks
|
||||
static #flattenSources(sources: ConfigSource[]): ConfigSource[] {
|
||||
return sources.flatMap(source => {
|
||||
if (sourcesSymbol in source) {
|
||||
return this.#flattenSources(source[sourcesSymbol] as ConfigSource[]);
|
||||
}
|
||||
return source;
|
||||
});
|
||||
}
|
||||
|
||||
static from(sources: ConfigSource[]): ConfigSource {
|
||||
return new MergedConfigSource(sources);
|
||||
return new MergedConfigSource(this.#flattenSources(sources));
|
||||
}
|
||||
|
||||
private constructor(private readonly sources: ConfigSource[]) {}
|
||||
|
||||
[sourcesSymbol] = this.sources;
|
||||
|
||||
async *readConfigData(
|
||||
options?: ReadConfigDataOptions,
|
||||
): AsyncConfigSourceIterator {
|
||||
|
||||
Reference in New Issue
Block a user