move parseEntityYaml to the node package

Signed-off-by: Fredrik Adelöw <freben@gmail.com>
This commit is contained in:
Fredrik Adelöw
2025-04-25 16:43:49 +02:00
parent 90ab044afe
commit a459f17b2a
12 changed files with 95 additions and 67 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-catalog-node': minor
---
Added `parseEntityYaml` from `@backstage/plugin-catalog-backend`, to make it more easily usable by custom plugins and modules
+1
View File
@@ -33,6 +33,7 @@ The following removed exports are available from `@backstage/plugin-catalog-node
- `PlaceholderResolverParams`
- `PlaceholderResolverRead`
- `PlaceholderResolverResolveUrl`
- `parseEntityYaml`
The following removed exports are available from `@backstage/plugin-catalog-common`:
-7
View File
@@ -10,7 +10,6 @@ import { CatalogProcessor } from '@backstage/plugin-catalog-node';
import { CatalogProcessorCache } from '@backstage/plugin-catalog-node';
import { CatalogProcessorEmit } from '@backstage/plugin-catalog-node';
import { CatalogProcessorParser } from '@backstage/plugin-catalog-node';
import { CatalogProcessorResult } from '@backstage/plugin-catalog-node';
import { Config } from '@backstage/config';
import { DatabaseService } from '@backstage/backend-plugin-api';
import { DiscoveryService } from '@backstage/backend-plugin-api';
@@ -215,12 +214,6 @@ export class FileReaderProcessor implements CatalogProcessor {
): Promise<boolean>;
}
// @public (undocumented)
export function parseEntityYaml(
data: Buffer,
location: LocationSpec,
): Iterable<CatalogProcessorResult>;
// @public
export class PlaceholderProcessor implements CatalogProcessor {
constructor(options: PlaceholderProcessorOptions);
-1
View File
@@ -25,4 +25,3 @@ export * from './processors';
export * from './processing';
export * from './service';
export * from './constants';
export * from './util';
-17
View File
@@ -1,17 +0,0 @@
/*
* Copyright 2024 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export { parseEntityYaml } from './parse';
+1 -41
View File
@@ -14,51 +14,11 @@
* limitations under the License.
*/
import { Entity, stringifyLocationRef } from '@backstage/catalog-model';
import lodash from 'lodash';
import yaml from 'yaml';
import { LocationSpec } from '@backstage/plugin-catalog-common';
import {
CatalogProcessorParser,
CatalogProcessorResult,
processingResult,
parseEntityYaml,
} from '@backstage/plugin-catalog-node';
/** @public */
export function* parseEntityYaml(
data: Buffer,
location: LocationSpec,
): Iterable<CatalogProcessorResult> {
let documents: yaml.Document.Parsed[];
try {
documents = yaml.parseAllDocuments(data.toString('utf8')).filter(d => d);
} catch (e) {
const loc = stringifyLocationRef(location);
const message = `Failed to parse YAML at ${loc}, ${e}`;
yield processingResult.generalError(location, message);
return;
}
for (const document of documents) {
if (document.errors?.length) {
const loc = stringifyLocationRef(location);
const message = `YAML error at ${loc}, ${document.errors[0]}`;
yield processingResult.generalError(location, message);
} else {
const json = document.toJSON();
if (lodash.isPlainObject(json)) {
yield processingResult.entity(location, json as Entity);
} else if (json === null) {
// Ignore null values, these happen if there is an empty document in the
// YAML file, for example if --- is added to the end of the file.
} else {
const message = `Expected object at root, got ${typeof json}`;
yield processingResult.generalError(location, message);
}
}
}
}
export const defaultEntityDataParser: CatalogProcessorParser =
async function* defaultEntityDataParser({ data, location }) {
for (const e of parseEntityYaml(data, location)) {
+3 -1
View File
@@ -67,7 +67,9 @@
"@backstage/plugin-catalog-common": "workspace:^",
"@backstage/plugin-permission-common": "workspace:^",
"@backstage/plugin-permission-node": "workspace:^",
"@backstage/types": "workspace:^"
"@backstage/types": "workspace:^",
"lodash": "^4.17.21",
"yaml": "^2.0.0"
},
"devDependencies": {
"@backstage/backend-test-utils": "workspace:^",
+6
View File
@@ -297,6 +297,12 @@ export function locationSpecToLocationEntity(opts: {
// @public
export function locationSpecToMetadataName(location: LocationSpec_2): string;
// @public
export function parseEntityYaml(
data: string | Buffer,
location: LocationSpec_2,
): Iterable<CatalogProcessorResult>;
// @public (undocumented)
export type PlaceholderResolver = (
params: PlaceholderResolverParams,
@@ -24,3 +24,4 @@ export type {
LocationAnalyzer,
ScmLocationAnalyzer,
} from './types';
export { parseEntityYaml } from './parse';
@@ -0,0 +1,76 @@
/*
* Copyright 2020 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { Entity, stringifyLocationRef } from '@backstage/catalog-model';
import lodash from 'lodash';
import yaml from 'yaml';
import { LocationSpec } from '@backstage/plugin-catalog-common';
import { CatalogProcessorResult } from '../api/processor';
import { processingResult } from '../api/processingResult';
/**
* A helper function that parses a YAML file, properly handling multiple
* documents in a single file.
*
* @public
* @remarks
*
* Each document is expected to be a valid Backstage entity. Each item in the
* iterable is in the form of an entity result if the document seemed like a
* valid object, or in the form of an error result if it seemed incorrect. This
* way, you can choose to retain a partial result if you want.
*
* Note that this function does NOT perform any validation of the entities. No
* assumptions whatsoever can be made on the emnitted entities except that they
* are valid JSON objects.
*/
export function* parseEntityYaml(
data: string | Buffer,
location: LocationSpec,
): Iterable<CatalogProcessorResult> {
let documents: yaml.Document.Parsed[];
try {
documents = yaml
.parseAllDocuments(
typeof data === 'string' ? data : data.toString('utf8'),
)
.filter(d => d);
} catch (e) {
const loc = stringifyLocationRef(location);
const message = `Failed to parse YAML at ${loc}, ${e}`;
yield processingResult.generalError(location, message);
return;
}
for (const document of documents) {
if (document.errors?.length) {
const loc = stringifyLocationRef(location);
const message = `YAML error at ${loc}, ${document.errors[0]}`;
yield processingResult.generalError(location, message);
} else {
const json = document.toJSON();
if (lodash.isPlainObject(json)) {
yield processingResult.entity(location, json as Entity);
} else if (json === null) {
// Ignore null values, these happen if there is an empty document in the
// YAML file, for example if --- is added to the end of the file.
} else {
const message = `Expected object at root, got ${typeof json}`;
yield processingResult.generalError(location, message);
}
}
}
}
+2
View File
@@ -6187,7 +6187,9 @@ __metadata:
"@backstage/plugin-permission-common": "workspace:^"
"@backstage/plugin-permission-node": "workspace:^"
"@backstage/types": "workspace:^"
lodash: "npm:^4.17.21"
msw: "npm:^1.0.0"
yaml: "npm:^2.0.0"
languageName: unknown
linkType: soft