config-loader: collect schemas from each package version

Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
This commit is contained in:
Patrik Oldsberg
2021-09-27 23:09:58 +02:00
parent 732a09b9da
commit e68bd978e2
3 changed files with 89 additions and 13 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/config-loader': patch
---
Allow collection of configuration schemas from multiple versions of the same package.
@@ -231,6 +231,74 @@ describe('collectConfigSchemas', () => {
]);
});
it('should load schema from different package versions', async () => {
mockFs({
node_modules: {
a: {
'package.json': JSON.stringify({
name: 'a',
dependencies: {
b: '1',
c: '1',
},
configSchema: mockSchema,
}),
},
b: {
'package.json': JSON.stringify({
name: 'b',
version: '1',
dependencies: {
c: '2',
},
configSchema: { ...mockSchema, title: 'b' },
}),
node_modules: {
c: {
'package.json': JSON.stringify({
name: 'c',
version: '2',
configSchema: { ...mockSchema, title: 'c2' },
}),
},
},
},
c: {
'package.json': JSON.stringify({
name: 'c',
version: '1',
configSchema: { ...mockSchema, title: 'c1' },
}),
},
},
});
await expect(collectConfigSchemas(['a'], [])).resolves.toEqual([
{
path: path.join('node_modules', 'a', 'package.json'),
value: mockSchema,
},
{
path: path.join('node_modules', 'b', 'package.json'),
value: { ...mockSchema, title: 'b' },
},
{
path: path.join('node_modules', 'c', 'package.json'),
value: { ...mockSchema, title: 'c1' },
},
{
path: path.join(
'node_modules',
'b',
'node_modules',
'c',
'package.json',
),
value: { ...mockSchema, title: 'c2' },
},
]);
});
it('should not allow unknown schema file types', async () => {
mockFs({
node_modules: {
@@ -43,9 +43,10 @@ export async function collectConfigSchemas(
packageNames: string[],
packagePaths: string[],
): Promise<ConfigSchemaPackageEntry[]> {
const visitedPackages = new Set<string>();
const schemas = Array<ConfigSchemaPackageEntry>();
const tsSchemaPaths = Array<string>();
const schemas = new Array<ConfigSchemaPackageEntry>();
const tsSchemaPaths = new Array<string>();
const visitedPackageVersions = new Map<string, Set<string>>(); // pkgName: [versions...]
const currentDir = await fs.realpath(process.cwd());
async function processItem(item: Item) {
@@ -59,16 +60,6 @@ export async function collectConfigSchemas(
} else if (item.name) {
const { name, parentPath } = item;
// Ensures that we only process each package once. We don't bother with
// loading in schemas from duplicates of different versions, as that's not
// supported by Backstage right now anyway. We may want to change that in
// the future though, if it for example becomes possible to load in two
// different versions of e.g. @backstage/core at once.
if (visitedPackages.has(name)) {
return;
}
visitedPackages.add(name);
try {
pkgPath = req.resolve(
`${name}/package.json`,
@@ -86,6 +77,18 @@ export async function collectConfigSchemas(
}
const pkg = await fs.readJson(pkgPath);
// Ensures that we only process the same version of each package once.
let versions = visitedPackageVersions.get(pkg.name);
if (versions?.has(pkg.version)) {
return;
}
if (!versions) {
versions = new Set();
visitedPackageVersions.set(pkg.name, versions);
}
versions.add(pkg.version);
const depNames = [
...Object.keys(pkg.dependencies ?? {}),
...Object.keys(pkg.devDependencies ?? {}),