@backstage/plugin-catalog-backend 1.3.1 → 1.4.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 +51 -0
- package/alpha/package.json +1 -1
- package/dist/index.alpha.d.ts +9 -2
- package/dist/index.beta.d.ts +8 -1
- package/dist/index.cjs.js +60 -16
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +8 -1
- package/package.json +18 -19
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,56 @@
|
|
|
1
1
|
# @backstage/plugin-catalog-backend
|
|
2
2
|
|
|
3
|
+
## 1.4.0-next.2
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- eadf56bbbf: Bump `git-url-parse` version to `^13.0.0`
|
|
8
|
+
- 667d917488: Updated dependency `msw` to `^0.47.0`.
|
|
9
|
+
- 87ec2ba4d6: Updated dependency `msw` to `^0.46.0`.
|
|
10
|
+
- 06e2b077a1: Limit the length of error messages that get written to the database and logs - to prevent performance issues
|
|
11
|
+
- Updated dependencies
|
|
12
|
+
- @backstage/backend-plugin-api@0.1.2-next.1
|
|
13
|
+
- @backstage/plugin-catalog-node@1.0.2-next.1
|
|
14
|
+
- @backstage/backend-common@0.15.1-next.2
|
|
15
|
+
- @backstage/integration@1.3.1-next.1
|
|
16
|
+
- @backstage/catalog-client@1.0.5-next.1
|
|
17
|
+
- @backstage/plugin-permission-common@0.6.4-next.1
|
|
18
|
+
- @backstage/plugin-permission-node@0.6.5-next.2
|
|
19
|
+
|
|
20
|
+
## 1.4.0-next.1
|
|
21
|
+
|
|
22
|
+
### Minor Changes
|
|
23
|
+
|
|
24
|
+
- dd395335bc: Allow unknown typed location from being registered via the location service by configuration settings
|
|
25
|
+
- 651c9d6800: The search index now does retain fields that have a very long value, but in the form of just a null. This makes it possible to at least filter for their existence.
|
|
26
|
+
|
|
27
|
+
### Patch Changes
|
|
28
|
+
|
|
29
|
+
- ce77e78c93: Fixes a bug to be able to utilize refresh keys after the entity is loaded from cache
|
|
30
|
+
- 679f7c5e95: Include entity ref into error message when catalog policies fail
|
|
31
|
+
- Updated dependencies
|
|
32
|
+
- @backstage/plugin-permission-node@0.6.5-next.1
|
|
33
|
+
- @backstage/backend-common@0.15.1-next.1
|
|
34
|
+
|
|
35
|
+
## 1.3.2-next.0
|
|
36
|
+
|
|
37
|
+
### Patch Changes
|
|
38
|
+
|
|
39
|
+
- 243533ecdc: Added support to mysql on some raw queries
|
|
40
|
+
- bf5e9030eb: Updated dependency `msw` to `^0.45.0`.
|
|
41
|
+
- 62788b2ee8: The experimental `CatalogProcessingExtensionPoint` now accepts multiple providers and processors at once.
|
|
42
|
+
- Updated dependencies
|
|
43
|
+
- @backstage/backend-common@0.15.1-next.0
|
|
44
|
+
- @backstage/backend-plugin-api@0.1.2-next.0
|
|
45
|
+
- @backstage/catalog-client@1.0.5-next.0
|
|
46
|
+
- @backstage/integration@1.3.1-next.0
|
|
47
|
+
- @backstage/plugin-permission-common@0.6.4-next.0
|
|
48
|
+
- @backstage/plugin-permission-node@0.6.5-next.0
|
|
49
|
+
- @backstage/plugin-scaffolder-common@1.2.0-next.0
|
|
50
|
+
- @backstage/plugin-catalog-node@1.0.2-next.0
|
|
51
|
+
- @backstage/plugin-catalog-common@1.0.6-next.0
|
|
52
|
+
- @backstage/plugin-search-common@1.0.1-next.0
|
|
53
|
+
|
|
3
54
|
## 1.3.1
|
|
4
55
|
|
|
5
56
|
### Patch Changes
|
package/alpha/package.json
CHANGED
package/dist/index.alpha.d.ts
CHANGED
|
@@ -171,7 +171,8 @@ export declare class CatalogBuilder {
|
|
|
171
171
|
private onProcessingError?;
|
|
172
172
|
private processingInterval;
|
|
173
173
|
private locationAnalyzer;
|
|
174
|
-
private permissionRules;
|
|
174
|
+
private readonly permissionRules;
|
|
175
|
+
private allowedLocationType;
|
|
175
176
|
/**
|
|
176
177
|
* Creates a catalog builder.
|
|
177
178
|
*/
|
|
@@ -293,6 +294,12 @@ export declare class CatalogBuilder {
|
|
|
293
294
|
* @alpha
|
|
294
295
|
*/
|
|
295
296
|
addPermissionRules(...permissionRules: Array<CatalogPermissionRule | Array<CatalogPermissionRule>>): void;
|
|
297
|
+
/**
|
|
298
|
+
* Sets up the allowed location types from being registered via the location service.
|
|
299
|
+
*
|
|
300
|
+
* @param allowedLocationTypes - the allowed location types
|
|
301
|
+
*/
|
|
302
|
+
setAllowedLocationTypes(allowedLocationTypes: string[]): CatalogBuilder;
|
|
296
303
|
/**
|
|
297
304
|
* Wires up and returns all of the component parts of the catalog
|
|
298
305
|
*/
|
|
@@ -349,7 +356,7 @@ export declare type CatalogPermissionRule<TParams extends unknown[] = unknown[]>
|
|
|
349
356
|
* Catalog plugin
|
|
350
357
|
* @alpha
|
|
351
358
|
*/
|
|
352
|
-
export declare const catalogPlugin: (options?:
|
|
359
|
+
export declare const catalogPlugin: (options?: undefined) => BackendFeature;
|
|
353
360
|
|
|
354
361
|
/** @public */
|
|
355
362
|
export declare interface CatalogProcessingEngine {
|
package/dist/index.beta.d.ts
CHANGED
|
@@ -171,7 +171,8 @@ export declare class CatalogBuilder {
|
|
|
171
171
|
private onProcessingError?;
|
|
172
172
|
private processingInterval;
|
|
173
173
|
private locationAnalyzer;
|
|
174
|
-
private permissionRules;
|
|
174
|
+
private readonly permissionRules;
|
|
175
|
+
private allowedLocationType;
|
|
175
176
|
/**
|
|
176
177
|
* Creates a catalog builder.
|
|
177
178
|
*/
|
|
@@ -285,6 +286,12 @@ export declare class CatalogBuilder {
|
|
|
285
286
|
*/
|
|
286
287
|
setEntityDataParser(parser: CatalogProcessorParser): CatalogBuilder;
|
|
287
288
|
/* Excluded from this release type: addPermissionRules */
|
|
289
|
+
/**
|
|
290
|
+
* Sets up the allowed location types from being registered via the location service.
|
|
291
|
+
*
|
|
292
|
+
* @param allowedLocationTypes - the allowed location types
|
|
293
|
+
*/
|
|
294
|
+
setAllowedLocationTypes(allowedLocationTypes: string[]): CatalogBuilder;
|
|
288
295
|
/**
|
|
289
296
|
* Wires up and returns all of the component parts of the catalog
|
|
290
297
|
*/
|
package/dist/index.cjs.js
CHANGED
|
@@ -749,11 +749,15 @@ class UrlReaderProcessor {
|
|
|
749
749
|
emit(pluginCatalogNode.processingResult.refresh(`${location.type}:${location.target}`));
|
|
750
750
|
} catch (error) {
|
|
751
751
|
errors.assertError(error);
|
|
752
|
-
const message = `Unable to read ${location.type}, ${error}
|
|
752
|
+
const message = `Unable to read ${location.type}, ${error}`.substring(
|
|
753
|
+
0,
|
|
754
|
+
5e3
|
|
755
|
+
);
|
|
753
756
|
if (error.name === "NotModifiedError" && cacheItem) {
|
|
754
757
|
for (const parseResult of cacheItem.value) {
|
|
755
758
|
emit(parseResult);
|
|
756
759
|
}
|
|
760
|
+
emit(pluginCatalogNode.processingResult.refresh(`${location.type}:${location.target}`));
|
|
757
761
|
} else if (error.name === "NotFoundError") {
|
|
758
762
|
if (!optional) {
|
|
759
763
|
emit(pluginCatalogNode.processingResult.notFoundError(location, message));
|
|
@@ -1506,7 +1510,7 @@ class DefaultProcessingDatabase {
|
|
|
1506
1510
|
sourceEntityRef
|
|
1507
1511
|
});
|
|
1508
1512
|
let previousRelationRows;
|
|
1509
|
-
if (tx.client.config.client.includes("sqlite3")) {
|
|
1513
|
+
if (tx.client.config.client.includes("sqlite3") || tx.client.config.client.includes("mysql")) {
|
|
1510
1514
|
previousRelationRows = await tx("relations").select("*").where({ originating_entity_id: id });
|
|
1511
1515
|
await tx("relations").where({ originating_entity_id: id }).delete();
|
|
1512
1516
|
} else {
|
|
@@ -1558,6 +1562,12 @@ class DefaultProcessingDatabase {
|
|
|
1558
1562
|
const { toAdd, toUpsert, toRemove } = await this.createDelta(tx, options);
|
|
1559
1563
|
if (toRemove.length) {
|
|
1560
1564
|
let removedCount = 0;
|
|
1565
|
+
const rootId = () => {
|
|
1566
|
+
if (tx.client.config.client.includes("mysql")) {
|
|
1567
|
+
return tx.raw("CAST(NULL as UNSIGNED INT)", []);
|
|
1568
|
+
}
|
|
1569
|
+
return tx.raw("CAST(NULL as INT)", []);
|
|
1570
|
+
};
|
|
1561
1571
|
for (const refs of lodash__default["default"].chunk(toRemove, 1e3)) {
|
|
1562
1572
|
removedCount += await tx("refresh_state").whereIn("entity_ref", function orphanedEntityRefs(orphans) {
|
|
1563
1573
|
return orphans.withRecursive("descendants", function descendants(outer) {
|
|
@@ -1571,7 +1581,7 @@ class DefaultProcessingDatabase {
|
|
|
1571
1581
|
});
|
|
1572
1582
|
}).withRecursive("ancestors", function ancestors(outer) {
|
|
1573
1583
|
return outer.select({
|
|
1574
|
-
root_id:
|
|
1584
|
+
root_id: rootId(),
|
|
1575
1585
|
via_entity_ref: "entity_ref",
|
|
1576
1586
|
to_entity_ref: "entity_ref"
|
|
1577
1587
|
}).from("descendants").union(function recursive(inner) {
|
|
@@ -1695,11 +1705,20 @@ class DefaultProcessingDatabase {
|
|
|
1695
1705
|
}
|
|
1696
1706
|
const items = await itemsQuery.where("next_update_at", "<=", tx.fn.now()).limit(request.processBatchSize).orderBy("next_update_at", "asc");
|
|
1697
1707
|
const interval = this.options.refreshInterval();
|
|
1708
|
+
const nextUpdateAt = (refreshInterval) => {
|
|
1709
|
+
if (tx.client.config.client.includes("sqlite3")) {
|
|
1710
|
+
return tx.raw(`datetime('now', ?)`, [`${refreshInterval} seconds`]);
|
|
1711
|
+
}
|
|
1712
|
+
if (tx.client.config.client.includes("mysql")) {
|
|
1713
|
+
return tx.raw(`now() + interval ${refreshInterval} second`);
|
|
1714
|
+
}
|
|
1715
|
+
return tx.raw(`now() + interval '${refreshInterval} seconds'`);
|
|
1716
|
+
};
|
|
1698
1717
|
await tx("refresh_state").whereIn(
|
|
1699
1718
|
"entity_ref",
|
|
1700
1719
|
items.map((i) => i.entity_ref)
|
|
1701
1720
|
).update({
|
|
1702
|
-
next_update_at:
|
|
1721
|
+
next_update_at: nextUpdateAt(interval)
|
|
1703
1722
|
});
|
|
1704
1723
|
return {
|
|
1705
1724
|
items: items.map(
|
|
@@ -2246,13 +2265,20 @@ function progressTracker() {
|
|
|
2246
2265
|
}
|
|
2247
2266
|
|
|
2248
2267
|
class DefaultLocationService {
|
|
2249
|
-
constructor(store, orchestrator
|
|
2268
|
+
constructor(store, orchestrator, options = {
|
|
2269
|
+
allowedLocationTypes: ["url"]
|
|
2270
|
+
}) {
|
|
2250
2271
|
this.store = store;
|
|
2251
2272
|
this.orchestrator = orchestrator;
|
|
2273
|
+
this.options = options;
|
|
2252
2274
|
}
|
|
2253
2275
|
async createLocation(input, dryRun) {
|
|
2254
|
-
if (input.type
|
|
2255
|
-
throw new errors.InputError(
|
|
2276
|
+
if (!this.options.allowedLocationTypes.includes(input.type)) {
|
|
2277
|
+
throw new errors.InputError(
|
|
2278
|
+
`Registered locations must be of an allowed type ${JSON.stringify(
|
|
2279
|
+
this.options.allowedLocationTypes
|
|
2280
|
+
)}`
|
|
2281
|
+
);
|
|
2256
2282
|
}
|
|
2257
2283
|
if (dryRun) {
|
|
2258
2284
|
return this.dryRunCreateLocation(input);
|
|
@@ -2808,10 +2834,17 @@ class DefaultCatalogProcessingOrchestrator {
|
|
|
2808
2834
|
try {
|
|
2809
2835
|
policyEnforcedEntity = await this.options.policy.enforce(entity);
|
|
2810
2836
|
} catch (e) {
|
|
2811
|
-
throw new errors.InputError(
|
|
2837
|
+
throw new errors.InputError(
|
|
2838
|
+
`Policy check failed for ${catalogModel.stringifyEntityRef(entity)}`,
|
|
2839
|
+
e
|
|
2840
|
+
);
|
|
2812
2841
|
}
|
|
2813
2842
|
if (!policyEnforcedEntity) {
|
|
2814
|
-
throw new Error(
|
|
2843
|
+
throw new Error(
|
|
2844
|
+
`Policy unexpectedly returned no data for ${catalogModel.stringifyEntityRef(
|
|
2845
|
+
entity
|
|
2846
|
+
)}`
|
|
2847
|
+
);
|
|
2815
2848
|
}
|
|
2816
2849
|
return policyEnforcedEntity;
|
|
2817
2850
|
}
|
|
@@ -2981,8 +3014,12 @@ function mapToRows(input, entityId) {
|
|
|
2981
3014
|
result.push({ entity_id: entityId, key, value: null });
|
|
2982
3015
|
} else {
|
|
2983
3016
|
const value = String(rawValue).toLocaleLowerCase("en-US");
|
|
2984
|
-
if (key.length <= MAX_KEY_LENGTH
|
|
2985
|
-
result.push({
|
|
3017
|
+
if (key.length <= MAX_KEY_LENGTH) {
|
|
3018
|
+
result.push({
|
|
3019
|
+
entity_id: entityId,
|
|
3020
|
+
key,
|
|
3021
|
+
value: value.length <= MAX_VALUE_LENGTH ? value : null
|
|
3022
|
+
});
|
|
2986
3023
|
}
|
|
2987
3024
|
}
|
|
2988
3025
|
}
|
|
@@ -3905,6 +3942,7 @@ class CatalogBuilder {
|
|
|
3905
3942
|
this.processorsReplace = false;
|
|
3906
3943
|
this.parser = void 0;
|
|
3907
3944
|
this.permissionRules = Object.values(permissionRules);
|
|
3945
|
+
this.allowedLocationType = ["url"];
|
|
3908
3946
|
}
|
|
3909
3947
|
static create(env) {
|
|
3910
3948
|
return new CatalogBuilder(env);
|
|
@@ -3971,6 +4009,10 @@ class CatalogBuilder {
|
|
|
3971
4009
|
addPermissionRules(...permissionRules) {
|
|
3972
4010
|
this.permissionRules.push(...permissionRules.flat());
|
|
3973
4011
|
}
|
|
4012
|
+
setAllowedLocationTypes(allowedLocationTypes) {
|
|
4013
|
+
this.allowedLocationType = allowedLocationTypes;
|
|
4014
|
+
return this;
|
|
4015
|
+
}
|
|
3974
4016
|
async build() {
|
|
3975
4017
|
var _a, _b;
|
|
3976
4018
|
const { config, database, logger, permissions } = this.env;
|
|
@@ -4056,7 +4098,9 @@ class CatalogBuilder {
|
|
|
4056
4098
|
);
|
|
4057
4099
|
const locationAnalyzer = (_b = this.locationAnalyzer) != null ? _b : new RepoLocationAnalyzer(logger, integrations);
|
|
4058
4100
|
const locationService = new AuthorizedLocationService(
|
|
4059
|
-
new DefaultLocationService(locationStore, orchestrator
|
|
4101
|
+
new DefaultLocationService(locationStore, orchestrator, {
|
|
4102
|
+
allowedLocationTypes: this.allowedLocationType
|
|
4103
|
+
}),
|
|
4060
4104
|
permissionEvaluator
|
|
4061
4105
|
);
|
|
4062
4106
|
const refreshService = new AuthorizedRefreshService(
|
|
@@ -4234,11 +4278,11 @@ class CatalogExtensionPointImpl {
|
|
|
4234
4278
|
__privateAdd(this, _processors, new Array());
|
|
4235
4279
|
__privateAdd(this, _entityProviders, new Array());
|
|
4236
4280
|
}
|
|
4237
|
-
addProcessor(
|
|
4238
|
-
__privateGet(this, _processors).push(
|
|
4281
|
+
addProcessor(...processors) {
|
|
4282
|
+
__privateGet(this, _processors).push(...processors.flat());
|
|
4239
4283
|
}
|
|
4240
|
-
addEntityProvider(
|
|
4241
|
-
__privateGet(this, _entityProviders).push(
|
|
4284
|
+
addEntityProvider(...providers) {
|
|
4285
|
+
__privateGet(this, _entityProviders).push(...providers.flat());
|
|
4242
4286
|
}
|
|
4243
4287
|
get processors() {
|
|
4244
4288
|
return __privateGet(this, _processors);
|