@backstage/plugin-catalog-backend 1.1.0-next.1 → 1.1.0-next.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/README.md +1 -2
- package/alpha/package.json +1 -1
- package/dist/index.cjs.js +69 -4
- package/dist/index.cjs.js.map +1 -1
- package/package.json +4 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# @backstage/plugin-catalog-backend
|
|
2
2
|
|
|
3
|
+
## 1.1.0-next.2
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- bf82edf4c9: Added `/validate-entity` endpoint
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- 8592cacfd3: Fixed an issue where sometimes entities would have stale relations "stuck" and
|
|
12
|
+
not getting removed as expected, after the other end of the relation had stopped
|
|
13
|
+
referring to them.
|
|
14
|
+
- Updated dependencies
|
|
15
|
+
- @backstage/catalog-model@1.0.1-next.1
|
|
16
|
+
|
|
3
17
|
## 1.1.0-next.1
|
|
4
18
|
|
|
5
19
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -27,8 +27,7 @@ restoring the plugin, if you previously removed it.
|
|
|
27
27
|
|
|
28
28
|
```bash
|
|
29
29
|
# From your Backstage root directory
|
|
30
|
-
|
|
31
|
-
yarn add @backstage/plugin-catalog-backend
|
|
30
|
+
yarn add --cwd packages/backend @backstage/plugin-catalog-backend
|
|
32
31
|
```
|
|
33
32
|
|
|
34
33
|
### Adding the plugin to your `packages/backend`
|
package/alpha/package.json
CHANGED
package/dist/index.cjs.js
CHANGED
|
@@ -1318,7 +1318,13 @@ class DefaultProcessingDatabase {
|
|
|
1318
1318
|
entities: deferredEntities,
|
|
1319
1319
|
sourceEntityRef: catalogModel.stringifyEntityRef(processedEntity)
|
|
1320
1320
|
});
|
|
1321
|
-
|
|
1321
|
+
let previousRelationRows;
|
|
1322
|
+
if (tx.client.config.client.includes("sqlite3")) {
|
|
1323
|
+
previousRelationRows = await tx("relations").select("*").where({ originating_entity_id: id });
|
|
1324
|
+
await tx("relations").where({ originating_entity_id: id }).delete();
|
|
1325
|
+
} else {
|
|
1326
|
+
previousRelationRows = await tx("relations").where({ originating_entity_id: id }).delete().returning("*");
|
|
1327
|
+
}
|
|
1322
1328
|
const relationRows = relations.map(({ source, target, type }) => ({
|
|
1323
1329
|
originating_entity_id: id,
|
|
1324
1330
|
source_entity_ref: catalogModel.stringifyEntityRef(source),
|
|
@@ -1326,6 +1332,11 @@ class DefaultProcessingDatabase {
|
|
|
1326
1332
|
type
|
|
1327
1333
|
}));
|
|
1328
1334
|
await tx.batchInsert("relations", this.deduplicateRelations(relationRows), BATCH_SIZE$1);
|
|
1335
|
+
return {
|
|
1336
|
+
previous: {
|
|
1337
|
+
relations: previousRelationRows
|
|
1338
|
+
}
|
|
1339
|
+
};
|
|
1329
1340
|
}
|
|
1330
1341
|
async updateProcessedEntityErrors(txOpaque, options) {
|
|
1331
1342
|
const tx = txOpaque;
|
|
@@ -1802,8 +1813,9 @@ class DefaultCatalogProcessingEngine {
|
|
|
1802
1813
|
return;
|
|
1803
1814
|
}
|
|
1804
1815
|
result.completedEntity.metadata.uid = id;
|
|
1816
|
+
let oldRelationSources;
|
|
1805
1817
|
await this.processingDatabase.transaction(async (tx) => {
|
|
1806
|
-
await this.processingDatabase.updateProcessedEntity(tx, {
|
|
1818
|
+
const { previous } = await this.processingDatabase.updateProcessedEntity(tx, {
|
|
1807
1819
|
id,
|
|
1808
1820
|
processedEntity: result.completedEntity,
|
|
1809
1821
|
resultHash,
|
|
@@ -1812,11 +1824,22 @@ class DefaultCatalogProcessingEngine {
|
|
|
1812
1824
|
deferredEntities: result.deferredEntities,
|
|
1813
1825
|
locationKey
|
|
1814
1826
|
});
|
|
1827
|
+
oldRelationSources = new Set(previous.relations.map((r) => r.source_entity_ref));
|
|
1815
1828
|
});
|
|
1829
|
+
const newRelationSources = new Set(result.relations.map((relation) => catalogModel.stringifyEntityRef(relation.source)));
|
|
1816
1830
|
const setOfThingsToStitch = /* @__PURE__ */ new Set([
|
|
1817
|
-
catalogModel.stringifyEntityRef(result.completedEntity)
|
|
1818
|
-
...result.relations.map((relation) => catalogModel.stringifyEntityRef(relation.source))
|
|
1831
|
+
catalogModel.stringifyEntityRef(result.completedEntity)
|
|
1819
1832
|
]);
|
|
1833
|
+
newRelationSources.forEach((r) => {
|
|
1834
|
+
if (!oldRelationSources.has(r)) {
|
|
1835
|
+
setOfThingsToStitch.add(r);
|
|
1836
|
+
}
|
|
1837
|
+
});
|
|
1838
|
+
oldRelationSources.forEach((r) => {
|
|
1839
|
+
if (!newRelationSources.has(r)) {
|
|
1840
|
+
setOfThingsToStitch.add(r);
|
|
1841
|
+
}
|
|
1842
|
+
});
|
|
1820
1843
|
await this.stitcher.stitch(setOfThingsToStitch);
|
|
1821
1844
|
track.markSuccessfulWithChanges(setOfThingsToStitch.size);
|
|
1822
1845
|
} catch (error) {
|
|
@@ -2866,6 +2889,7 @@ async function createRouter(options) {
|
|
|
2866
2889
|
entitiesCatalog,
|
|
2867
2890
|
locationAnalyzer,
|
|
2868
2891
|
locationService,
|
|
2892
|
+
orchestrator,
|
|
2869
2893
|
refreshService,
|
|
2870
2894
|
config,
|
|
2871
2895
|
logger,
|
|
@@ -2988,6 +3012,46 @@ async function createRouter(options) {
|
|
|
2988
3012
|
res.status(200).json(output);
|
|
2989
3013
|
});
|
|
2990
3014
|
}
|
|
3015
|
+
if (orchestrator) {
|
|
3016
|
+
router.post("/validate-entity", async (req, res) => {
|
|
3017
|
+
const bodySchema = zod.z.object({
|
|
3018
|
+
entity: zod.z.unknown(),
|
|
3019
|
+
location: zod.z.string()
|
|
3020
|
+
});
|
|
3021
|
+
let body;
|
|
3022
|
+
let entity;
|
|
3023
|
+
let location;
|
|
3024
|
+
try {
|
|
3025
|
+
body = await validateRequestBody(req, bodySchema);
|
|
3026
|
+
entity = validateEntityEnvelope(body.entity);
|
|
3027
|
+
location = catalogModel.parseLocationRef(body.location);
|
|
3028
|
+
if (location.type !== "url")
|
|
3029
|
+
throw new TypeError(`Invalid location ref ${body.location}, only 'url:<target>' is supported, e.g. url:https://host/path`);
|
|
3030
|
+
} catch (err) {
|
|
3031
|
+
return res.status(400).json({
|
|
3032
|
+
errors: [errors.serializeError(err)]
|
|
3033
|
+
});
|
|
3034
|
+
}
|
|
3035
|
+
const processingResult = await orchestrator.process({
|
|
3036
|
+
entity: {
|
|
3037
|
+
...entity,
|
|
3038
|
+
metadata: {
|
|
3039
|
+
...entity.metadata,
|
|
3040
|
+
annotations: {
|
|
3041
|
+
[catalogModel.ANNOTATION_LOCATION]: body.location,
|
|
3042
|
+
[catalogModel.ANNOTATION_ORIGIN_LOCATION]: body.location,
|
|
3043
|
+
...entity.metadata.annotations
|
|
3044
|
+
}
|
|
3045
|
+
}
|
|
3046
|
+
}
|
|
3047
|
+
});
|
|
3048
|
+
if (!processingResult.ok)
|
|
3049
|
+
res.status(400).json({
|
|
3050
|
+
errors: processingResult.errors.map((e) => errors.serializeError(e))
|
|
3051
|
+
});
|
|
3052
|
+
return res.status(200).end();
|
|
3053
|
+
});
|
|
3054
|
+
}
|
|
2991
3055
|
router.use(backendCommon.errorHandler());
|
|
2992
3056
|
return router;
|
|
2993
3057
|
}
|
|
@@ -3441,6 +3505,7 @@ class CatalogBuilder {
|
|
|
3441
3505
|
entitiesCatalog,
|
|
3442
3506
|
locationAnalyzer,
|
|
3443
3507
|
locationService,
|
|
3508
|
+
orchestrator,
|
|
3444
3509
|
refreshService,
|
|
3445
3510
|
logger,
|
|
3446
3511
|
config,
|