fix: omit collecting backend-common package if backend-defaults is included
Signed-off-by: blam <ben@blam.sh>
This commit is contained in:
@@ -93,6 +93,61 @@ describe('collectConfigSchemas', () => {
|
||||
]);
|
||||
});
|
||||
|
||||
it('should not include schemas for backend-common if theres a backend-defaults package', async () => {
|
||||
mockDir.setContent({
|
||||
root: {
|
||||
'package.json': JSON.stringify({
|
||||
name: 'root',
|
||||
configSchema: mockSchema,
|
||||
dependencies: {},
|
||||
}),
|
||||
node_modules: {
|
||||
a: {
|
||||
'package.json': JSON.stringify({
|
||||
name: 'a',
|
||||
dependencies: {
|
||||
b: '0.0.0',
|
||||
},
|
||||
}),
|
||||
},
|
||||
b: {
|
||||
'package.json': JSON.stringify({
|
||||
name: 'a',
|
||||
dependencies: {
|
||||
b: '0.0.0',
|
||||
},
|
||||
}),
|
||||
},
|
||||
'@backstage': {
|
||||
'backend-common': {
|
||||
'package.json': JSON.stringify({
|
||||
name: '@backstage/backend-common',
|
||||
configSchema: { ...mockSchema, title: 'backend-common' },
|
||||
}),
|
||||
},
|
||||
'backend-defaults': {
|
||||
'package.json': JSON.stringify({
|
||||
name: '@backstage/backend-defaults',
|
||||
configSchema: { ...mockSchema, title: 'backend-defaults' },
|
||||
}),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
process.chdir(mockDir.path);
|
||||
|
||||
await expect(
|
||||
collectConfigSchemas([], [path.join('root', 'package.json')]),
|
||||
).resolves.toEqual([
|
||||
{
|
||||
path: path.join('root', 'package.json'),
|
||||
value: mockSchema,
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('should find schema in transitive dependencies and explicit path', async () => {
|
||||
mockDir.setContent({
|
||||
root: {
|
||||
|
||||
@@ -45,7 +45,7 @@ export async function collectConfigSchemas(
|
||||
packagePaths: string[],
|
||||
): Promise<ConfigSchemaPackageEntry[]> {
|
||||
const schemas = new Array<ConfigSchemaPackageEntry>();
|
||||
const tsSchemaPaths = new Array<string>();
|
||||
const tsSchemaPaths = new Array<{ packageName: string; path: string }>();
|
||||
const visitedPackageVersions = new Map<string, Set<string>>(); // pkgName: [versions...]
|
||||
|
||||
const currentDir = await fs.realpath(process.cwd());
|
||||
@@ -115,22 +115,25 @@ export async function collectConfigSchemas(
|
||||
);
|
||||
}
|
||||
if (isDts) {
|
||||
tsSchemaPaths.push(
|
||||
relativePath(
|
||||
tsSchemaPaths.push({
|
||||
path: relativePath(
|
||||
currentDir,
|
||||
resolvePath(dirname(pkgPath), pkg.configSchema),
|
||||
),
|
||||
);
|
||||
packageName: pkg.name,
|
||||
});
|
||||
} else {
|
||||
const path = resolvePath(dirname(pkgPath), pkg.configSchema);
|
||||
const value = await fs.readJson(path);
|
||||
schemas.push({
|
||||
packageName: pkg.name,
|
||||
value,
|
||||
path: relativePath(currentDir, path),
|
||||
});
|
||||
}
|
||||
} else {
|
||||
schemas.push({
|
||||
packageName: pkg.name,
|
||||
value: pkg.configSchema,
|
||||
path: relativePath(currentDir, pkgPath),
|
||||
});
|
||||
@@ -151,14 +154,27 @@ export async function collectConfigSchemas(
|
||||
|
||||
const tsSchemas = await compileTsSchemas(tsSchemaPaths);
|
||||
|
||||
return schemas.concat(tsSchemas);
|
||||
return schemas
|
||||
.concat(tsSchemas)
|
||||
.filter(
|
||||
({ packageName }, _, original) =>
|
||||
true ||
|
||||
!(
|
||||
packageName === '@backstage/backend-common' &&
|
||||
original.some(
|
||||
({ packageName: p }) => p === '@backstage/backend-defaults',
|
||||
)
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// This handles the support of TypeScript .d.ts config schema declarations.
|
||||
// We collect all typescript schema definition and compile them all in one go.
|
||||
// This is much faster than compiling them separately.
|
||||
async function compileTsSchemas(paths: string[]) {
|
||||
if (paths.length === 0) {
|
||||
async function compileTsSchemas(
|
||||
entries: { path: string; packageName: string }[],
|
||||
) {
|
||||
if (entries.length === 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
@@ -168,20 +184,23 @@ async function compileTsSchemas(paths: string[]) {
|
||||
'typescript-json-schema'
|
||||
);
|
||||
|
||||
const program = getProgramFromFiles(paths, {
|
||||
incremental: false,
|
||||
isolatedModules: true,
|
||||
lib: ['ES5'], // Skipping most libs speeds processing up a lot, we just need the primitive types anyway
|
||||
noEmit: true,
|
||||
noResolve: true,
|
||||
skipLibCheck: true, // Skipping lib checks speeds things up
|
||||
skipDefaultLibCheck: true,
|
||||
strict: true,
|
||||
typeRoots: [], // Do not include any additional types
|
||||
types: [],
|
||||
});
|
||||
const program = getProgramFromFiles(
|
||||
entries.map(({ path }) => path),
|
||||
{
|
||||
incremental: false,
|
||||
isolatedModules: true,
|
||||
lib: ['ES5'], // Skipping most libs speeds processing up a lot, we just need the primitive types anyway
|
||||
noEmit: true,
|
||||
noResolve: true,
|
||||
skipLibCheck: true, // Skipping lib checks speeds things up
|
||||
skipDefaultLibCheck: true,
|
||||
strict: true,
|
||||
typeRoots: [], // Do not include any additional types
|
||||
types: [],
|
||||
},
|
||||
);
|
||||
|
||||
const tsSchemas = paths.map(path => {
|
||||
const tsSchemas = entries.map(({ path, packageName }) => {
|
||||
let value;
|
||||
try {
|
||||
const generator = buildGenerator(
|
||||
@@ -228,7 +247,7 @@ async function compileTsSchemas(paths: string[]) {
|
||||
if (!value) {
|
||||
throw new Error(`Invalid schema in ${path}, missing Config export`);
|
||||
}
|
||||
return { path, value };
|
||||
return { path, value, packageName };
|
||||
});
|
||||
|
||||
return tsSchemas;
|
||||
|
||||
@@ -21,10 +21,12 @@ describe('compileConfigSchemas', () => {
|
||||
const validate = compileConfigSchemas([
|
||||
{
|
||||
path: 'a',
|
||||
packageName: 'a',
|
||||
value: { type: 'object', properties: { a: { type: 'string' } } },
|
||||
},
|
||||
{
|
||||
path: 'b',
|
||||
packageName: 'b',
|
||||
value: { type: 'object', properties: { b: { type: 'number' } } },
|
||||
},
|
||||
]);
|
||||
@@ -64,6 +66,7 @@ describe('compileConfigSchemas', () => {
|
||||
const validate = compileConfigSchemas([
|
||||
{
|
||||
path: 'a1',
|
||||
packageName: 'a1',
|
||||
value: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
@@ -80,6 +83,7 @@ describe('compileConfigSchemas', () => {
|
||||
},
|
||||
{
|
||||
path: 'a2',
|
||||
packageName: 'a2',
|
||||
value: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
@@ -126,6 +130,7 @@ describe('compileConfigSchemas', () => {
|
||||
compileConfigSchemas([
|
||||
{
|
||||
path: 'a1',
|
||||
packageName: 'a1',
|
||||
value: {
|
||||
type: 'object',
|
||||
properties: { a: { type: 'string', visibility: 'frontend' } },
|
||||
@@ -133,6 +138,7 @@ describe('compileConfigSchemas', () => {
|
||||
},
|
||||
{
|
||||
path: 'a2',
|
||||
packageName: 'a2',
|
||||
value: {
|
||||
type: 'object',
|
||||
properties: { a: { type: 'string', visibility: 'secret' } },
|
||||
@@ -148,6 +154,7 @@ describe('compileConfigSchemas', () => {
|
||||
const validate = compileConfigSchemas([
|
||||
{
|
||||
path: 'a1',
|
||||
packageName: 'a1',
|
||||
value: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
@@ -179,6 +186,7 @@ describe('compileConfigSchemas', () => {
|
||||
const validate = compileConfigSchemas([
|
||||
{
|
||||
path: 'a1',
|
||||
packageName: 'a1',
|
||||
value: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
@@ -242,6 +250,7 @@ describe('deepVisibility', () => {
|
||||
const validate = compileConfigSchemas([
|
||||
{
|
||||
path: 'a1',
|
||||
packageName: 'a1',
|
||||
value: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
@@ -257,6 +266,7 @@ describe('deepVisibility', () => {
|
||||
},
|
||||
{
|
||||
path: 'a2',
|
||||
packageName: 'a2',
|
||||
value: {
|
||||
type: 'object',
|
||||
deepVisibility: 'secret',
|
||||
@@ -305,6 +315,7 @@ describe('deepVisibility', () => {
|
||||
compileConfigSchemas([
|
||||
{
|
||||
path: 'a1',
|
||||
packageName: 'a1',
|
||||
value: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
@@ -320,6 +331,7 @@ describe('deepVisibility', () => {
|
||||
},
|
||||
{
|
||||
path: 'a2',
|
||||
packageName: 'a2',
|
||||
value: {
|
||||
type: 'object',
|
||||
deepVisibility: 'secret',
|
||||
@@ -346,6 +358,7 @@ describe('deepVisibility', () => {
|
||||
compileConfigSchemas([
|
||||
{
|
||||
path: 'a2',
|
||||
packageName: 'a2',
|
||||
value: {
|
||||
type: 'object',
|
||||
deepVisibility: 'secret',
|
||||
@@ -376,6 +389,7 @@ describe('deepVisibility', () => {
|
||||
compileConfigSchemas([
|
||||
{
|
||||
path: 'a2',
|
||||
packageName: 'a2',
|
||||
value: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
@@ -398,6 +412,7 @@ describe('deepVisibility', () => {
|
||||
compileConfigSchemas([
|
||||
{
|
||||
path: 'a1',
|
||||
packageName: 'a1',
|
||||
value: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
@@ -418,6 +433,7 @@ describe('deepVisibility', () => {
|
||||
},
|
||||
{
|
||||
path: 'a2',
|
||||
packageName: 'a2',
|
||||
value: {
|
||||
type: 'object',
|
||||
deepVisibility: 'secret',
|
||||
|
||||
@@ -29,6 +29,10 @@ export type ConfigSchemaPackageEntry = {
|
||||
* The relative path that the configuration schema was discovered at.
|
||||
*/
|
||||
path: string;
|
||||
/**
|
||||
* The package name for the package this belongs to
|
||||
*/
|
||||
packageName: string;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user