@backstage/plugin-catalog-backend 1.29.0-next.2 → 1.30.0-next.0

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 CHANGED
@@ -1,5 +1,74 @@
1
1
  # @backstage/plugin-catalog-backend
2
2
 
3
+ ## 1.30.0-next.0
4
+
5
+ ### Minor Changes
6
+
7
+ - dd515e3: Removed the long-deprecated `DefaultCatalogCollatorFactory` and `DefaultCatalogCollatorFactoryOptions` exports, which now no longer exist in the search plugin's offerings. If you were using these, you want to migrate to [the new backend system](https://backstage.io/docs/backend-system/) and use the [catalog collator](https://backstage.io/docs/features/search/collators#catalog) directly.
8
+
9
+ ### Patch Changes
10
+
11
+ - d9d62ef: Remove some internal usages of the backend-common package
12
+ - 8379bf4: Remove usages of `PluginDatabaseManager` and `PluginEndpointDiscovery` and replace with their equivalent service types
13
+ - be0aae7: Improved concurrency of the `entities` endpoint when using the streamed query mode behind the `catalog.disableRelationsCompatibility` flag.
14
+ - 3d475a0: Updated condition in `resolveCodeOwner` to fix a bug where `normalizeCodeOwner` could potentially be called with an invalid argument causing an error in `CodeOwnersProcessor`
15
+ - Updated dependencies
16
+ - @backstage/plugin-search-backend-module-catalog@0.3.0-next.0
17
+ - @backstage/plugin-permission-node@0.8.7-next.0
18
+ - @backstage/backend-openapi-utils@0.4.1-next.0
19
+ - @backstage/backend-plugin-api@1.1.1-next.0
20
+ - @backstage/catalog-client@1.9.0
21
+ - @backstage/catalog-model@1.7.2
22
+ - @backstage/config@1.3.1
23
+ - @backstage/errors@1.2.6
24
+ - @backstage/integration@1.16.0
25
+ - @backstage/types@1.2.0
26
+ - @backstage/plugin-catalog-common@1.1.2
27
+ - @backstage/plugin-catalog-node@1.15.1-next.0
28
+ - @backstage/plugin-events-node@0.4.7-next.0
29
+ - @backstage/plugin-permission-common@0.8.3
30
+
31
+ ## 1.29.0
32
+
33
+ ### Minor Changes
34
+
35
+ - 02bd2cb: Added a new `catalog.disableRelationsCompatibility` configuration option that avoids JSON deserialization and serialization if possible when reading entities. This significantly reduces the memory usage of the catalog, and slightly increases performance, but it removes the backwards compatibility processing that ensures that both `entity.relation[].target` and `entity.relation[].targetRef` are present in returned entities.
36
+ - c1307b4: Implement `/entities` in terms of `queryEntities` to not run into memory and performance problems on large catalogs
37
+ - 384e494: Internal updates to generated code.
38
+ - 1d0bc11: Fetch all facets in a single database query
39
+
40
+ ### Patch Changes
41
+
42
+ - dfc8b41: Updated dependency `@opentelemetry/api` to `^1.9.0`.
43
+ - 8013c9c: Perform the by-query count inlined with the main query
44
+ - feba9ee: Internal refactor of filter parsing logic.
45
+ - 1fdb48e: Use a faster count method on pg when computing some metrics
46
+ - e4aab10: Fix a bug where sometimes the `by-query` endpoint could return nulls for entities that were not yet stitched.
47
+ - f159b25: Compute deltas more efficiently, which generally leads to less wasted processing cycles
48
+ - 0c33465: Implement `/entities/by-name/:kind/:namespace/:name` using `getEntitiesByRefs`
49
+ - 56511ba: Be more aggressive in dequeueing entities for stitching
50
+ - 71152e3: Correctly report stitching queue length
51
+ - 5c9cc05: Use native fetch instead of node-fetch
52
+ - d93390d: When parsing filters, do not make redundant `anyOf` and `allOf` nodes when there's only a single entry within them
53
+ - 3ab57c6: Support changing location keys on existing entities, in delta mutations
54
+ - 24ecea8: Avoid extra ordering in by-query when the user doesn't ask for it
55
+ - 2924ffe: Compute some metrics using search table facet aggregations instead of reading the full refresh state
56
+ - Updated dependencies
57
+ - @backstage/integration@1.16.0
58
+ - @backstage/backend-plugin-api@1.1.0
59
+ - @backstage/plugin-search-backend-module-catalog@0.2.6
60
+ - @backstage/plugin-catalog-node@1.15.0
61
+ - @backstage/plugin-events-node@0.4.6
62
+ - @backstage/catalog-client@1.9.0
63
+ - @backstage/plugin-permission-node@0.8.6
64
+ - @backstage/backend-openapi-utils@0.4.0
65
+ - @backstage/errors@1.2.6
66
+ - @backstage/catalog-model@1.7.2
67
+ - @backstage/config@1.3.1
68
+ - @backstage/types@1.2.0
69
+ - @backstage/plugin-catalog-common@1.1.2
70
+ - @backstage/plugin-permission-common@0.8.3
71
+
3
72
  ## 1.29.0-next.2
4
73
 
5
74
  ### Minor Changes
package/config.d.ts CHANGED
@@ -138,6 +138,16 @@ export interface Config {
138
138
  }>;
139
139
  }>;
140
140
 
141
+ /**
142
+ * Disables the compatibility layer for relations in returned entities that
143
+ * ensures that all relations objects have both `target` and `targetRef`.
144
+ *
145
+ * Enabling this option significantly reduces the memory usage of the
146
+ * catalog, and slightly increases performance, but may break consumers that
147
+ * rely on the existence of `target` in the relations objects.
148
+ */
149
+ disableRelationsCompatibility?: boolean;
150
+
141
151
  /**
142
152
  * The strategy to use for entities that are orphaned, i.e. no longer have
143
153
  * any other entities or providers referencing them. The default value is
@@ -6,10 +6,8 @@ var pluginSearchBackendModuleCatalog = require('@backstage/plugin-search-backend
6
6
  const locationSpecToMetadataName = pluginCatalogNode.locationSpecToMetadataName;
7
7
  const locationSpecToLocationEntity = pluginCatalogNode.locationSpecToLocationEntity;
8
8
  const processingResult = pluginCatalogNode.processingResult;
9
- const DefaultCatalogCollatorFactory = pluginSearchBackendModuleCatalog.DefaultCatalogCollatorFactory;
10
9
  const defaultCatalogCollatorEntityTransformer = pluginSearchBackendModuleCatalog.defaultCatalogCollatorEntityTransformer;
11
10
 
12
- exports.DefaultCatalogCollatorFactory = DefaultCatalogCollatorFactory;
13
11
  exports.defaultCatalogCollatorEntityTransformer = defaultCatalogCollatorEntityTransformer;
14
12
  exports.locationSpecToLocationEntity = locationSpecToLocationEntity;
15
13
  exports.locationSpecToMetadataName = locationSpecToMetadataName;
@@ -1 +1 @@
1
- {"version":3,"file":"deprecated.cjs.js","sources":["../src/deprecated.ts"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n type AnalyzeLocationEntityField as _AnalyzeLocationEntityField,\n type AnalyzeLocationExistingEntity as _AnalyzeLocationExistingEntity,\n type AnalyzeLocationGenerateEntity as _AnalyzeLocationGenerateEntity,\n type AnalyzeLocationRequest as _AnalyzeLocationRequest,\n type AnalyzeLocationResponse as _AnalyzeLocationResponse,\n type LocationSpec as _LocationSpec,\n} from '@backstage/plugin-catalog-common';\nimport {\n locationSpecToMetadataName as _locationSpecToMetadataName,\n locationSpecToLocationEntity as _locationSpecToLocationEntity,\n processingResult as _processingResult,\n type EntitiesSearchFilter as _EntitiesSearchFilter,\n type EntityFilter as _EntityFilter,\n type DeferredEntity as _DeferredEntity,\n type EntityRelationSpec as _EntityRelationSpec,\n type CatalogProcessor as _CatalogProcessor,\n type CatalogProcessorParser as _CatalogProcessorParser,\n type CatalogProcessorCache as _CatalogProcessorCache,\n type CatalogProcessorEmit as _CatalogProcessorEmit,\n type CatalogProcessorLocationResult as _CatalogProcessorLocationResult,\n type CatalogProcessorEntityResult as _CatalogProcessorEntityResult,\n type CatalogProcessorRelationResult as _CatalogProcessorRelationResult,\n type CatalogProcessorErrorResult as _CatalogProcessorErrorResult,\n type CatalogProcessorRefreshKeysResult as _CatalogProcessorRefreshKeysResult,\n type CatalogProcessorResult as _CatalogProcessorResult,\n type EntityProvider as _EntityProvider,\n type EntityProviderConnection as _EntityProviderConnection,\n type EntityProviderMutation as _EntityProviderMutation,\n type AnalyzeOptions as _AnalyzeOptions,\n type PlaceholderResolver as _PlaceholderResolver,\n type PlaceholderResolverParams as _PlaceholderResolverParams,\n type PlaceholderResolverRead as _PlaceholderResolverRead,\n type PlaceholderResolverResolveUrl as _PlaceholderResolverResolveUrl,\n type LocationAnalyzer as _LocationAnalyzer,\n type ScmLocationAnalyzer as _ScmLocationAnalyzer,\n} from '@backstage/plugin-catalog-node';\nimport {\n defaultCatalogCollatorEntityTransformer as _defaultCatalogCollatorEntityTransformer,\n DefaultCatalogCollatorFactory as _DefaultCatalogCollatorFactory,\n type CatalogCollatorEntityTransformer as _CatalogCollatorEntityTransformer,\n type DefaultCatalogCollatorFactoryOptions as _DefaultCatalogCollatorFactoryOptions,\n} from '@backstage/plugin-search-backend-module-catalog';\n\n/**\n * @public\n * @deprecated import from `@backstage/plugin-catalog-node` instead\n */\nexport const locationSpecToMetadataName = _locationSpecToMetadataName;\n/**\n * @public\n * @deprecated import from `@backstage/plugin-catalog-node` instead\n */\nexport const locationSpecToLocationEntity = _locationSpecToLocationEntity;\n/**\n * @public\n * @deprecated import from `@backstage/plugin-catalog-node` instead\n */\nexport const processingResult = _processingResult;\n/**\n * @public\n * @deprecated import from `@backstage/plugin-catalog-node` instead\n */\nexport type EntitiesSearchFilter = _EntitiesSearchFilter;\n/**\n * @public\n * @deprecated import from `@backstage/plugin-catalog-node` instead\n */\nexport type EntityFilter = _EntityFilter;\n/**\n * @public\n * @deprecated import from `@backstage/plugin-catalog-node` instead\n */\nexport type DeferredEntity = _DeferredEntity;\n/**\n * @public\n * @deprecated import from `@backstage/plugin-catalog-node` instead\n */\nexport type EntityRelationSpec = _EntityRelationSpec;\n/**\n * @public\n * @deprecated import from `@backstage/plugin-catalog-node` instead\n */\nexport type CatalogProcessor = _CatalogProcessor;\n/**\n * @public\n * @deprecated import from `@backstage/plugin-catalog-node` instead\n */\nexport type CatalogProcessorParser = _CatalogProcessorParser;\n/**\n * @public\n * @deprecated import from `@backstage/plugin-catalog-node` instead\n */\nexport type CatalogProcessorCache = _CatalogProcessorCache;\n/**\n * @public\n * @deprecated import from `@backstage/plugin-catalog-node` instead\n */\nexport type CatalogProcessorEmit = _CatalogProcessorEmit;\n/**\n * @public\n * @deprecated import from `@backstage/plugin-catalog-node` instead\n */\nexport type CatalogProcessorLocationResult = _CatalogProcessorLocationResult;\n/**\n * @public\n * @deprecated import from `@backstage/plugin-catalog-node` instead\n */\nexport type CatalogProcessorEntityResult = _CatalogProcessorEntityResult;\n/**\n * @public\n * @deprecated import from `@backstage/plugin-catalog-node` instead\n */\nexport type CatalogProcessorRelationResult = _CatalogProcessorRelationResult;\n/**\n * @public\n * @deprecated import from `@backstage/plugin-catalog-node` instead\n */\nexport type CatalogProcessorErrorResult = _CatalogProcessorErrorResult;\n/**\n * @public\n * @deprecated import from `@backstage/plugin-catalog-node` instead\n */\nexport type CatalogProcessorRefreshKeysResult =\n _CatalogProcessorRefreshKeysResult;\n/**\n * @public\n * @deprecated import from `@backstage/plugin-catalog-node` instead\n */\nexport type CatalogProcessorResult = _CatalogProcessorResult;\n/**\n * @public\n * @deprecated import from `@backstage/plugin-catalog-node` instead\n */\nexport type EntityProvider = _EntityProvider;\n/**\n * @public\n * @deprecated import from `@backstage/plugin-catalog-node` instead\n */\nexport type EntityProviderConnection = _EntityProviderConnection;\n/**\n * @public\n * @deprecated import from `@backstage/plugin-catalog-node` instead\n */\nexport type EntityProviderMutation = _EntityProviderMutation;\n\n/**\n * Holds the entity location information.\n *\n * @remarks\n *\n * `presence` flag: when using repo importer plugin, location is being created before the component yaml file is merged to the main branch.\n * This flag is then set to indicate that the file can be not present.\n * default value: 'required'.\n *\n * @public\n * @deprecated use the same type from `@backstage/plugin-catalog-common` instead\n */\nexport type LocationSpec = _LocationSpec;\n/**\n * @public\n * @deprecated import from `@backstage/plugin-catalog-node` instead\n */\nexport type AnalyzeOptions = _AnalyzeOptions;\n/**\n * @public\n * @deprecated import from `@backstage/plugin-catalog-node` instead\n */\nexport type LocationAnalyzer = _LocationAnalyzer;\n/**\n * @public\n * @deprecated import from `@backstage/plugin-catalog-node` instead\n */\nexport type ScmLocationAnalyzer = _ScmLocationAnalyzer;\n\n/**\n * @public\n * @deprecated import from `@backstage/plugin-catalog-node` instead\n */\nexport type PlaceholderResolver = _PlaceholderResolver;\n\n/**\n * @public\n * @deprecated import from `@backstage/plugin-catalog-node` instead\n */\nexport type PlaceholderResolverParams = _PlaceholderResolverParams;\n\n/**\n * @public\n * @deprecated import from `@backstage/plugin-catalog-node` instead\n */\nexport type PlaceholderResolverRead = _PlaceholderResolverRead;\n\n/**\n * @public\n * @deprecated import from `@backstage/plugin-catalog-node` instead\n */\nexport type PlaceholderResolverResolveUrl = _PlaceholderResolverResolveUrl;\n\n/**\n * @public\n * @deprecated use the same type from `@backstage/plugin-catalog-common` instead\n */\nexport type AnalyzeLocationRequest = _AnalyzeLocationRequest;\n/**\n * @public\n * @deprecated use the same type from `@backstage/plugin-catalog-common` instead\n */\nexport type AnalyzeLocationResponse = _AnalyzeLocationResponse;\n\n/**\n * If the folder pointed to already contained catalog info yaml files, they are\n * read and emitted like this so that the frontend can inform the user that it\n * located them and can make sure to register them as well if they weren't\n * already\n * @public\n * @deprecated use the same type from `@backstage/plugin-catalog-common` instead\n */\nexport type AnalyzeLocationExistingEntity = _AnalyzeLocationExistingEntity;\n/**\n * This is some form of representation of what the analyzer could deduce.\n * We should probably have a chat about how this can best be conveyed to\n * the frontend. It'll probably contain a (possibly incomplete) entity, plus\n * enough info for the frontend to know what form data to show to the user\n * for overriding/completing the info.\n * @public\n * @deprecated use the same type from `@backstage/plugin-catalog-common` instead\n */\nexport type AnalyzeLocationGenerateEntity = _AnalyzeLocationGenerateEntity;\n\n/**\n *\n * This is where I get really vague. Something like this perhaps? Or it could be\n * something like a json-schema that contains enough info for the frontend to\n * be able to present a form and explanations\n * @public\n * @deprecated use the same type from `@backstage/plugin-catalog-common` instead\n */\nexport type AnalyzeLocationEntityField = _AnalyzeLocationEntityField;\n\n/**\n * @public\n * @deprecated import from `@backstage/plugin-search-backend-module-catalog` instead\n */\nexport const DefaultCatalogCollatorFactory = _DefaultCatalogCollatorFactory;\n\n/**\n * @public\n * @deprecated import from `@backstage/plugin-search-backend-module-catalog` instead\n */\nexport const defaultCatalogCollatorEntityTransformer =\n _defaultCatalogCollatorEntityTransformer;\n\n/**\n * @public\n * @deprecated import from `@backstage/plugin-search-backend-module-catalog` instead\n */\nexport type DefaultCatalogCollatorFactoryOptions =\n _DefaultCatalogCollatorFactoryOptions;\n\n/**\n * @public\n * @deprecated import from `@backstage/plugin-search-backend-module-catalog` instead\n */\nexport type CatalogCollatorEntityTransformer =\n _CatalogCollatorEntityTransformer;\n"],"names":["_locationSpecToMetadataName","_locationSpecToLocationEntity","_processingResult","_DefaultCatalogCollatorFactory","_defaultCatalogCollatorEntityTransformer"],"mappings":";;;;;AAgEO,MAAM,0BAA6B,GAAAA;AAKnC,MAAM,4BAA+B,GAAAC;AAKrC,MAAM,gBAAmB,GAAAC;AA0LzB,MAAM,6BAAgC,GAAAC;AAMtC,MAAM,uCACX,GAAAC;;;;;;;;"}
1
+ {"version":3,"file":"deprecated.cjs.js","sources":["../src/deprecated.ts"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n type AnalyzeLocationEntityField as _AnalyzeLocationEntityField,\n type AnalyzeLocationExistingEntity as _AnalyzeLocationExistingEntity,\n type AnalyzeLocationGenerateEntity as _AnalyzeLocationGenerateEntity,\n type AnalyzeLocationRequest as _AnalyzeLocationRequest,\n type AnalyzeLocationResponse as _AnalyzeLocationResponse,\n type LocationSpec as _LocationSpec,\n} from '@backstage/plugin-catalog-common';\nimport {\n locationSpecToMetadataName as _locationSpecToMetadataName,\n locationSpecToLocationEntity as _locationSpecToLocationEntity,\n processingResult as _processingResult,\n type EntitiesSearchFilter as _EntitiesSearchFilter,\n type EntityFilter as _EntityFilter,\n type DeferredEntity as _DeferredEntity,\n type EntityRelationSpec as _EntityRelationSpec,\n type CatalogProcessor as _CatalogProcessor,\n type CatalogProcessorParser as _CatalogProcessorParser,\n type CatalogProcessorCache as _CatalogProcessorCache,\n type CatalogProcessorEmit as _CatalogProcessorEmit,\n type CatalogProcessorLocationResult as _CatalogProcessorLocationResult,\n type CatalogProcessorEntityResult as _CatalogProcessorEntityResult,\n type CatalogProcessorRelationResult as _CatalogProcessorRelationResult,\n type CatalogProcessorErrorResult as _CatalogProcessorErrorResult,\n type CatalogProcessorRefreshKeysResult as _CatalogProcessorRefreshKeysResult,\n type CatalogProcessorResult as _CatalogProcessorResult,\n type EntityProvider as _EntityProvider,\n type EntityProviderConnection as _EntityProviderConnection,\n type EntityProviderMutation as _EntityProviderMutation,\n type AnalyzeOptions as _AnalyzeOptions,\n type PlaceholderResolver as _PlaceholderResolver,\n type PlaceholderResolverParams as _PlaceholderResolverParams,\n type PlaceholderResolverRead as _PlaceholderResolverRead,\n type PlaceholderResolverResolveUrl as _PlaceholderResolverResolveUrl,\n type LocationAnalyzer as _LocationAnalyzer,\n type ScmLocationAnalyzer as _ScmLocationAnalyzer,\n} from '@backstage/plugin-catalog-node';\nimport {\n defaultCatalogCollatorEntityTransformer as _defaultCatalogCollatorEntityTransformer,\n type CatalogCollatorEntityTransformer as _CatalogCollatorEntityTransformer,\n} from '@backstage/plugin-search-backend-module-catalog';\n\n/**\n * @public\n * @deprecated import from `@backstage/plugin-catalog-node` instead\n */\nexport const locationSpecToMetadataName = _locationSpecToMetadataName;\n/**\n * @public\n * @deprecated import from `@backstage/plugin-catalog-node` instead\n */\nexport const locationSpecToLocationEntity = _locationSpecToLocationEntity;\n/**\n * @public\n * @deprecated import from `@backstage/plugin-catalog-node` instead\n */\nexport const processingResult = _processingResult;\n/**\n * @public\n * @deprecated import from `@backstage/plugin-catalog-node` instead\n */\nexport type EntitiesSearchFilter = _EntitiesSearchFilter;\n/**\n * @public\n * @deprecated import from `@backstage/plugin-catalog-node` instead\n */\nexport type EntityFilter = _EntityFilter;\n/**\n * @public\n * @deprecated import from `@backstage/plugin-catalog-node` instead\n */\nexport type DeferredEntity = _DeferredEntity;\n/**\n * @public\n * @deprecated import from `@backstage/plugin-catalog-node` instead\n */\nexport type EntityRelationSpec = _EntityRelationSpec;\n/**\n * @public\n * @deprecated import from `@backstage/plugin-catalog-node` instead\n */\nexport type CatalogProcessor = _CatalogProcessor;\n/**\n * @public\n * @deprecated import from `@backstage/plugin-catalog-node` instead\n */\nexport type CatalogProcessorParser = _CatalogProcessorParser;\n/**\n * @public\n * @deprecated import from `@backstage/plugin-catalog-node` instead\n */\nexport type CatalogProcessorCache = _CatalogProcessorCache;\n/**\n * @public\n * @deprecated import from `@backstage/plugin-catalog-node` instead\n */\nexport type CatalogProcessorEmit = _CatalogProcessorEmit;\n/**\n * @public\n * @deprecated import from `@backstage/plugin-catalog-node` instead\n */\nexport type CatalogProcessorLocationResult = _CatalogProcessorLocationResult;\n/**\n * @public\n * @deprecated import from `@backstage/plugin-catalog-node` instead\n */\nexport type CatalogProcessorEntityResult = _CatalogProcessorEntityResult;\n/**\n * @public\n * @deprecated import from `@backstage/plugin-catalog-node` instead\n */\nexport type CatalogProcessorRelationResult = _CatalogProcessorRelationResult;\n/**\n * @public\n * @deprecated import from `@backstage/plugin-catalog-node` instead\n */\nexport type CatalogProcessorErrorResult = _CatalogProcessorErrorResult;\n/**\n * @public\n * @deprecated import from `@backstage/plugin-catalog-node` instead\n */\nexport type CatalogProcessorRefreshKeysResult =\n _CatalogProcessorRefreshKeysResult;\n/**\n * @public\n * @deprecated import from `@backstage/plugin-catalog-node` instead\n */\nexport type CatalogProcessorResult = _CatalogProcessorResult;\n/**\n * @public\n * @deprecated import from `@backstage/plugin-catalog-node` instead\n */\nexport type EntityProvider = _EntityProvider;\n/**\n * @public\n * @deprecated import from `@backstage/plugin-catalog-node` instead\n */\nexport type EntityProviderConnection = _EntityProviderConnection;\n/**\n * @public\n * @deprecated import from `@backstage/plugin-catalog-node` instead\n */\nexport type EntityProviderMutation = _EntityProviderMutation;\n\n/**\n * Holds the entity location information.\n *\n * @remarks\n *\n * `presence` flag: when using repo importer plugin, location is being created before the component yaml file is merged to the main branch.\n * This flag is then set to indicate that the file can be not present.\n * default value: 'required'.\n *\n * @public\n * @deprecated use the same type from `@backstage/plugin-catalog-common` instead\n */\nexport type LocationSpec = _LocationSpec;\n/**\n * @public\n * @deprecated import from `@backstage/plugin-catalog-node` instead\n */\nexport type AnalyzeOptions = _AnalyzeOptions;\n/**\n * @public\n * @deprecated import from `@backstage/plugin-catalog-node` instead\n */\nexport type LocationAnalyzer = _LocationAnalyzer;\n/**\n * @public\n * @deprecated import from `@backstage/plugin-catalog-node` instead\n */\nexport type ScmLocationAnalyzer = _ScmLocationAnalyzer;\n\n/**\n * @public\n * @deprecated import from `@backstage/plugin-catalog-node` instead\n */\nexport type PlaceholderResolver = _PlaceholderResolver;\n\n/**\n * @public\n * @deprecated import from `@backstage/plugin-catalog-node` instead\n */\nexport type PlaceholderResolverParams = _PlaceholderResolverParams;\n\n/**\n * @public\n * @deprecated import from `@backstage/plugin-catalog-node` instead\n */\nexport type PlaceholderResolverRead = _PlaceholderResolverRead;\n\n/**\n * @public\n * @deprecated import from `@backstage/plugin-catalog-node` instead\n */\nexport type PlaceholderResolverResolveUrl = _PlaceholderResolverResolveUrl;\n\n/**\n * @public\n * @deprecated use the same type from `@backstage/plugin-catalog-common` instead\n */\nexport type AnalyzeLocationRequest = _AnalyzeLocationRequest;\n/**\n * @public\n * @deprecated use the same type from `@backstage/plugin-catalog-common` instead\n */\nexport type AnalyzeLocationResponse = _AnalyzeLocationResponse;\n\n/**\n * If the folder pointed to already contained catalog info yaml files, they are\n * read and emitted like this so that the frontend can inform the user that it\n * located them and can make sure to register them as well if they weren't\n * already\n * @public\n * @deprecated use the same type from `@backstage/plugin-catalog-common` instead\n */\nexport type AnalyzeLocationExistingEntity = _AnalyzeLocationExistingEntity;\n/**\n * This is some form of representation of what the analyzer could deduce.\n * We should probably have a chat about how this can best be conveyed to\n * the frontend. It'll probably contain a (possibly incomplete) entity, plus\n * enough info for the frontend to know what form data to show to the user\n * for overriding/completing the info.\n * @public\n * @deprecated use the same type from `@backstage/plugin-catalog-common` instead\n */\nexport type AnalyzeLocationGenerateEntity = _AnalyzeLocationGenerateEntity;\n\n/**\n *\n * This is where I get really vague. Something like this perhaps? Or it could be\n * something like a json-schema that contains enough info for the frontend to\n * be able to present a form and explanations\n * @public\n * @deprecated use the same type from `@backstage/plugin-catalog-common` instead\n */\nexport type AnalyzeLocationEntityField = _AnalyzeLocationEntityField;\n\n/**\n * @public\n * @deprecated import from `@backstage/plugin-search-backend-module-catalog` instead\n */\nexport const defaultCatalogCollatorEntityTransformer =\n _defaultCatalogCollatorEntityTransformer;\n\n/**\n * @public\n * @deprecated import from `@backstage/plugin-search-backend-module-catalog` instead\n */\nexport type CatalogCollatorEntityTransformer =\n _CatalogCollatorEntityTransformer;\n"],"names":["_locationSpecToMetadataName","_locationSpecToLocationEntity","_processingResult","_defaultCatalogCollatorEntityTransformer"],"mappings":";;;;;AA8DO,MAAM,0BAA6B,GAAAA;AAKnC,MAAM,4BAA+B,GAAAC;AAKrC,MAAM,gBAAmB,GAAAC;AA0LzB,MAAM,uCACX,GAAAC;;;;;;;"}
package/dist/index.cjs.js CHANGED
@@ -34,7 +34,6 @@ exports.transformLegacyPolicyToProcessor = transformLegacyPolicyToProcessor.tran
34
34
  exports.createRandomProcessingInterval = refresh.createRandomProcessingInterval;
35
35
  exports.DefaultCatalogCollator = DefaultCatalogCollator.DefaultCatalogCollator;
36
36
  exports.CatalogBuilder = CatalogBuilder.CatalogBuilder;
37
- exports.DefaultCatalogCollatorFactory = deprecated.DefaultCatalogCollatorFactory;
38
37
  exports.defaultCatalogCollatorEntityTransformer = deprecated.defaultCatalogCollatorEntityTransformer;
39
38
  exports.locationSpecToLocationEntity = deprecated.locationSpecToLocationEntity;
40
39
  exports.locationSpecToMetadataName = deprecated.locationSpecToMetadataName;
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.cjs.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
package/dist/index.d.ts CHANGED
@@ -1,19 +1,19 @@
1
1
  /// <reference types="node" />
2
2
  import * as _backstage_backend_plugin_api from '@backstage/backend-plugin-api';
3
- import { LoggerService, UrlReaderService, DatabaseService, RootConfigService, PermissionsService, SchedulerService, DiscoveryService, AuthService, HttpAuthService } from '@backstage/backend-plugin-api';
3
+ import { LoggerService, UrlReaderService, DiscoveryService, DatabaseService, RootConfigService, PermissionsService, SchedulerService, AuthService, HttpAuthService } from '@backstage/backend-plugin-api';
4
4
  import * as _backstage_catalog_model from '@backstage/catalog-model';
5
5
  import { Entity, EntityPolicy, Validators } from '@backstage/catalog-model';
6
6
  import { ScmIntegrationRegistry } from '@backstage/integration';
7
7
  import { LocationSpec as LocationSpec$1, CatalogEntityDocument, AnalyzeLocationRequest as AnalyzeLocationRequest$1, AnalyzeLocationResponse as AnalyzeLocationResponse$1, AnalyzeLocationExistingEntity as AnalyzeLocationExistingEntity$1, AnalyzeLocationGenerateEntity as AnalyzeLocationGenerateEntity$1, AnalyzeLocationEntityField as AnalyzeLocationEntityField$1 } from '@backstage/plugin-catalog-common';
8
8
  import { CatalogProcessor as CatalogProcessor$1, CatalogProcessorEmit as CatalogProcessorEmit$1, CatalogProcessorParser as CatalogProcessorParser$1, PlaceholderResolver as PlaceholderResolver$1, CatalogProcessorCache as CatalogProcessorCache$1, EntitiesSearchFilter as EntitiesSearchFilter$1, LocationAnalyzer as LocationAnalyzer$1, EntityProvider as EntityProvider$1, ScmLocationAnalyzer as ScmLocationAnalyzer$1, locationSpecToMetadataName as locationSpecToMetadataName$1, locationSpecToLocationEntity as locationSpecToLocationEntity$1, CatalogProcessorResult as CatalogProcessorResult$1, EntityRelationSpec as EntityRelationSpec$1, EntityFilter as EntityFilter$1, DeferredEntity as DeferredEntity$1, CatalogProcessorLocationResult as CatalogProcessorLocationResult$1, CatalogProcessorEntityResult as CatalogProcessorEntityResult$1, CatalogProcessorRelationResult as CatalogProcessorRelationResult$1, CatalogProcessorErrorResult as CatalogProcessorErrorResult$1, CatalogProcessorRefreshKeysResult as CatalogProcessorRefreshKeysResult$1, EntityProviderConnection as EntityProviderConnection$1, EntityProviderMutation as EntityProviderMutation$1, AnalyzeOptions as AnalyzeOptions$1, PlaceholderResolverParams as PlaceholderResolverParams$1, PlaceholderResolverRead as PlaceholderResolverRead$1, PlaceholderResolverResolveUrl as PlaceholderResolverResolveUrl$1 } from '@backstage/plugin-catalog-node';
9
9
  import { Config } from '@backstage/config';
10
- import { PluginEndpointDiscovery, TokenManager } from '@backstage/backend-common';
10
+ import { TokenManager } from '@backstage/backend-common';
11
11
  import { GetEntitiesRequest, CatalogApi } from '@backstage/catalog-client';
12
12
  import { Permission, PermissionRuleParams, PermissionAuthorizer } from '@backstage/plugin-permission-common';
13
13
  import { Router } from 'express';
14
14
  import { PermissionRule } from '@backstage/plugin-permission-node';
15
15
  import { EventBroker, EventsService } from '@backstage/plugin-events-node';
16
- import { DefaultCatalogCollatorFactory as DefaultCatalogCollatorFactory$1, CatalogCollatorEntityTransformer as CatalogCollatorEntityTransformer$1, DefaultCatalogCollatorFactoryOptions as DefaultCatalogCollatorFactoryOptions$1 } from '@backstage/plugin-search-backend-module-catalog';
16
+ import { CatalogCollatorEntityTransformer as CatalogCollatorEntityTransformer$1 } from '@backstage/plugin-search-backend-module-catalog';
17
17
 
18
18
  /**
19
19
  * Catalog plugin
@@ -175,7 +175,7 @@ declare function createRandomProcessingInterval(options: {
175
175
  * use `DefaultCatalogCollatorFactory` instead.
176
176
  */
177
177
  declare class DefaultCatalogCollator {
178
- protected discovery: PluginEndpointDiscovery;
178
+ protected discovery: DiscoveryService;
179
179
  protected locationTemplate: string;
180
180
  protected filter?: GetEntitiesRequest['filter'];
181
181
  protected readonly catalogClient: CatalogApi;
@@ -183,12 +183,12 @@ declare class DefaultCatalogCollator {
183
183
  readonly visibilityPermission: Permission;
184
184
  protected tokenManager: TokenManager;
185
185
  static fromConfig(_config: Config, options: {
186
- discovery: PluginEndpointDiscovery;
186
+ discovery: DiscoveryService;
187
187
  tokenManager: TokenManager;
188
188
  filter?: GetEntitiesRequest['filter'];
189
189
  }): DefaultCatalogCollator;
190
190
  constructor(options: {
191
- discovery: PluginEndpointDiscovery;
191
+ discovery: DiscoveryService;
192
192
  tokenManager: TokenManager;
193
193
  locationTemplate?: string;
194
194
  filter?: GetEntitiesRequest['filter'];
@@ -630,21 +630,11 @@ type AnalyzeLocationGenerateEntity = AnalyzeLocationGenerateEntity$1;
630
630
  * @deprecated use the same type from `@backstage/plugin-catalog-common` instead
631
631
  */
632
632
  type AnalyzeLocationEntityField = AnalyzeLocationEntityField$1;
633
- /**
634
- * @public
635
- * @deprecated import from `@backstage/plugin-search-backend-module-catalog` instead
636
- */
637
- declare const DefaultCatalogCollatorFactory: typeof DefaultCatalogCollatorFactory$1;
638
633
  /**
639
634
  * @public
640
635
  * @deprecated import from `@backstage/plugin-search-backend-module-catalog` instead
641
636
  */
642
637
  declare const defaultCatalogCollatorEntityTransformer: CatalogCollatorEntityTransformer$1;
643
- /**
644
- * @public
645
- * @deprecated import from `@backstage/plugin-search-backend-module-catalog` instead
646
- */
647
- type DefaultCatalogCollatorFactoryOptions = DefaultCatalogCollatorFactoryOptions$1;
648
638
  /**
649
639
  * @public
650
640
  * @deprecated import from `@backstage/plugin-search-backend-module-catalog` instead
@@ -659,4 +649,4 @@ declare const CATALOG_ERRORS_TOPIC = "experimental.catalog.errors";
659
649
  /** @public */
660
650
  declare function parseEntityYaml(data: Buffer, location: LocationSpec$1): Iterable<CatalogProcessorResult$1>;
661
651
 
662
- export { type AnalyzeLocationEntityField, type AnalyzeLocationExistingEntity, type AnalyzeLocationGenerateEntity, type AnalyzeLocationRequest, type AnalyzeLocationResponse, type AnalyzeOptions, AnnotateLocationEntityProcessor, AnnotateScmSlugEntityProcessor, BuiltinKindsEntityProcessor, CATALOG_CONFLICTS_TOPIC, CATALOG_ERRORS_TOPIC, CatalogBuilder, type CatalogCollatorEntityTransformer, type CatalogEnvironment, type CatalogPermissionRuleInput, type CatalogProcessingEngine, type CatalogProcessor, type CatalogProcessorCache, type CatalogProcessorEmit, type CatalogProcessorEntityResult, type CatalogProcessorErrorResult, type CatalogProcessorLocationResult, type CatalogProcessorParser, type CatalogProcessorRefreshKeysResult, type CatalogProcessorRelationResult, type CatalogProcessorResult, CodeOwnersProcessor, DefaultCatalogCollator, DefaultCatalogCollatorFactory, type DefaultCatalogCollatorFactoryOptions, type DeferredEntity, type EntitiesSearchFilter, type EntityFilter, type EntityProvider, type EntityProviderConnection, type EntityProviderMutation, type EntityRelationSpec, FileReaderProcessor, type LocationAnalyzer, LocationEntityProcessor, type LocationEntityProcessorOptions, type LocationSpec, PlaceholderProcessor, type PlaceholderProcessorOptions, type PlaceholderResolver, type PlaceholderResolverParams, type PlaceholderResolverRead, type PlaceholderResolverResolveUrl, type ProcessingIntervalFunction, type ScmLocationAnalyzer, UrlReaderProcessor, createRandomProcessingInterval, catalogPlugin as default, defaultCatalogCollatorEntityTransformer, locationSpecToLocationEntity, locationSpecToMetadataName, parseEntityYaml, processingResult, transformLegacyPolicyToProcessor };
652
+ export { type AnalyzeLocationEntityField, type AnalyzeLocationExistingEntity, type AnalyzeLocationGenerateEntity, type AnalyzeLocationRequest, type AnalyzeLocationResponse, type AnalyzeOptions, AnnotateLocationEntityProcessor, AnnotateScmSlugEntityProcessor, BuiltinKindsEntityProcessor, CATALOG_CONFLICTS_TOPIC, CATALOG_ERRORS_TOPIC, CatalogBuilder, type CatalogCollatorEntityTransformer, type CatalogEnvironment, type CatalogPermissionRuleInput, type CatalogProcessingEngine, type CatalogProcessor, type CatalogProcessorCache, type CatalogProcessorEmit, type CatalogProcessorEntityResult, type CatalogProcessorErrorResult, type CatalogProcessorLocationResult, type CatalogProcessorParser, type CatalogProcessorRefreshKeysResult, type CatalogProcessorRelationResult, type CatalogProcessorResult, CodeOwnersProcessor, DefaultCatalogCollator, type DeferredEntity, type EntitiesSearchFilter, type EntityFilter, type EntityProvider, type EntityProviderConnection, type EntityProviderMutation, type EntityRelationSpec, FileReaderProcessor, type LocationAnalyzer, LocationEntityProcessor, type LocationEntityProcessorOptions, type LocationSpec, PlaceholderProcessor, type PlaceholderProcessorOptions, type PlaceholderResolver, type PlaceholderResolverParams, type PlaceholderResolverRead, type PlaceholderResolverResolveUrl, type ProcessingIntervalFunction, type ScmLocationAnalyzer, UrlReaderProcessor, createRandomProcessingInterval, catalogPlugin as default, defaultCatalogCollatorEntityTransformer, locationSpecToLocationEntity, locationSpecToMetadataName, parseEntityYaml, processingResult, transformLegacyPolicyToProcessor };
@@ -33,7 +33,7 @@ function resolveCodeOwner(contents, catalogInfoFileUrl) {
33
33
  const codeOwnerEntries = codeowners__namespace.parse(contents);
34
34
  const { filepath } = parseGitUrl__default.default(catalogInfoFileUrl);
35
35
  const match = codeowners__namespace.matchFile(filepath, codeOwnerEntries);
36
- return match ? normalizeCodeOwner(match.owners[0]) : void 0;
36
+ return match?.owners?.length ? normalizeCodeOwner(match.owners[0]) : void 0;
37
37
  }
38
38
  function normalizeCodeOwner(owner) {
39
39
  if (owner.match(GROUP_PATTERN)) {
@@ -1 +1 @@
1
- {"version":3,"file":"resolve.cjs.js","sources":["../../../src/processors/codeowners/resolve.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport * as codeowners from 'codeowners-utils';\nimport parseGitUrl from 'git-url-parse';\n\nconst USER_PATTERN = /^@.*/;\nconst GROUP_PATTERN = /^@.*\\/.*/;\nconst EMAIL_PATTERN = /^.*@.*\\..*$/;\n\nexport function resolveCodeOwner(\n contents: string,\n catalogInfoFileUrl: string,\n): string | undefined {\n const codeOwnerEntries = codeowners.parse(contents);\n\n const { filepath } = parseGitUrl(catalogInfoFileUrl);\n const match = codeowners.matchFile(filepath, codeOwnerEntries);\n\n return match ? normalizeCodeOwner(match.owners[0]) : undefined;\n}\n\nexport function normalizeCodeOwner(owner: string) {\n if (owner.match(GROUP_PATTERN)) {\n return owner.split('/')[1];\n } else if (owner.match(USER_PATTERN)) {\n return `User:${owner.substring(1)}`;\n } else if (owner.match(EMAIL_PATTERN)) {\n return owner.split('@')[0];\n }\n\n return owner;\n}\n"],"names":["codeowners","parseGitUrl"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmBA,MAAM,YAAe,GAAA,MAAA;AACrB,MAAM,aAAgB,GAAA,UAAA;AACtB,MAAM,aAAgB,GAAA,aAAA;AAEN,SAAA,gBAAA,CACd,UACA,kBACoB,EAAA;AACpB,EAAM,MAAA,gBAAA,GAAmBA,qBAAW,CAAA,KAAA,CAAM,QAAQ,CAAA;AAElD,EAAA,MAAM,EAAE,QAAA,EAAa,GAAAC,4BAAA,CAAY,kBAAkB,CAAA;AACnD,EAAA,MAAM,KAAQ,GAAAD,qBAAA,CAAW,SAAU,CAAA,QAAA,EAAU,gBAAgB,CAAA;AAE7D,EAAA,OAAO,QAAQ,kBAAmB,CAAA,KAAA,CAAM,MAAO,CAAA,CAAC,CAAC,CAAI,GAAA,KAAA,CAAA;AACvD;AAEO,SAAS,mBAAmB,KAAe,EAAA;AAChD,EAAI,IAAA,KAAA,CAAM,KAAM,CAAA,aAAa,CAAG,EAAA;AAC9B,IAAA,OAAO,KAAM,CAAA,KAAA,CAAM,GAAG,CAAA,CAAE,CAAC,CAAA;AAAA,GAChB,MAAA,IAAA,KAAA,CAAM,KAAM,CAAA,YAAY,CAAG,EAAA;AACpC,IAAA,OAAO,CAAQ,KAAA,EAAA,KAAA,CAAM,SAAU,CAAA,CAAC,CAAC,CAAA,CAAA;AAAA,GACxB,MAAA,IAAA,KAAA,CAAM,KAAM,CAAA,aAAa,CAAG,EAAA;AACrC,IAAA,OAAO,KAAM,CAAA,KAAA,CAAM,GAAG,CAAA,CAAE,CAAC,CAAA;AAAA;AAG3B,EAAO,OAAA,KAAA;AACT;;;;;"}
1
+ {"version":3,"file":"resolve.cjs.js","sources":["../../../src/processors/codeowners/resolve.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport * as codeowners from 'codeowners-utils';\nimport parseGitUrl from 'git-url-parse';\n\nconst USER_PATTERN = /^@.*/;\nconst GROUP_PATTERN = /^@.*\\/.*/;\nconst EMAIL_PATTERN = /^.*@.*\\..*$/;\n\nexport function resolveCodeOwner(\n contents: string,\n catalogInfoFileUrl: string,\n): string | undefined {\n const codeOwnerEntries = codeowners.parse(contents);\n\n const { filepath } = parseGitUrl(catalogInfoFileUrl);\n const match = codeowners.matchFile(filepath, codeOwnerEntries);\n\n return match?.owners?.length\n ? normalizeCodeOwner(match.owners[0])\n : undefined;\n}\n\nexport function normalizeCodeOwner(owner: string) {\n if (owner.match(GROUP_PATTERN)) {\n return owner.split('/')[1];\n } else if (owner.match(USER_PATTERN)) {\n return `User:${owner.substring(1)}`;\n } else if (owner.match(EMAIL_PATTERN)) {\n return owner.split('@')[0];\n }\n\n return owner;\n}\n"],"names":["codeowners","parseGitUrl"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmBA,MAAM,YAAe,GAAA,MAAA;AACrB,MAAM,aAAgB,GAAA,UAAA;AACtB,MAAM,aAAgB,GAAA,aAAA;AAEN,SAAA,gBAAA,CACd,UACA,kBACoB,EAAA;AACpB,EAAM,MAAA,gBAAA,GAAmBA,qBAAW,CAAA,KAAA,CAAM,QAAQ,CAAA;AAElD,EAAA,MAAM,EAAE,QAAA,EAAa,GAAAC,4BAAA,CAAY,kBAAkB,CAAA;AACnD,EAAA,MAAM,KAAQ,GAAAD,qBAAA,CAAW,SAAU,CAAA,QAAA,EAAU,gBAAgB,CAAA;AAE7D,EAAO,OAAA,KAAA,EAAO,QAAQ,MAClB,GAAA,kBAAA,CAAmB,MAAM,MAAO,CAAA,CAAC,CAAC,CAClC,GAAA,KAAA,CAAA;AACN;AAEO,SAAS,mBAAmB,KAAe,EAAA;AAChD,EAAI,IAAA,KAAA,CAAM,KAAM,CAAA,aAAa,CAAG,EAAA;AAC9B,IAAA,OAAO,KAAM,CAAA,KAAA,CAAM,GAAG,CAAA,CAAE,CAAC,CAAA;AAAA,GAChB,MAAA,IAAA,KAAA,CAAM,KAAM,CAAA,YAAY,CAAG,EAAA;AACpC,IAAA,OAAO,CAAQ,KAAA,EAAA,KAAA,CAAM,SAAU,CAAA,CAAC,CAAC,CAAA,CAAA;AAAA,GACxB,MAAA,IAAA,KAAA,CAAM,KAAM,CAAA,aAAa,CAAG,EAAA;AACrC,IAAA,OAAO,KAAM,CAAA,KAAA,CAAM,GAAG,CAAA,CAAE,CAAC,CAAA;AAAA;AAG3B,EAAO,OAAA,KAAA;AACT;;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"DefaultCatalogCollator.cjs.js","sources":["../../src/search/DefaultCatalogCollator.ts"],"sourcesContent":["/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n PluginEndpointDiscovery,\n TokenManager,\n} from '@backstage/backend-common';\nimport {\n Entity,\n isUserEntity,\n stringifyEntityRef,\n} from '@backstage/catalog-model';\nimport { Config } from '@backstage/config';\nimport {\n CatalogApi,\n CatalogClient,\n GetEntitiesRequest,\n} from '@backstage/catalog-client';\nimport { catalogEntityReadPermission } from '@backstage/plugin-catalog-common/alpha';\nimport { CatalogEntityDocument } from '@backstage/plugin-catalog-common';\nimport { Permission } from '@backstage/plugin-permission-common';\n\n/**\n * @public\n * @deprecated Upgrade to a more recent `@backstage/plugin-search-backend-node` and\n * use `DefaultCatalogCollatorFactory` instead.\n */\nexport class DefaultCatalogCollator {\n protected discovery: PluginEndpointDiscovery;\n protected locationTemplate: string;\n protected filter?: GetEntitiesRequest['filter'];\n protected readonly catalogClient: CatalogApi;\n public readonly type: string = 'software-catalog';\n public readonly visibilityPermission: Permission =\n catalogEntityReadPermission;\n protected tokenManager: TokenManager;\n\n static fromConfig(\n _config: Config,\n options: {\n discovery: PluginEndpointDiscovery;\n tokenManager: TokenManager;\n filter?: GetEntitiesRequest['filter'];\n },\n ) {\n return new DefaultCatalogCollator({\n ...options,\n });\n }\n\n constructor(options: {\n discovery: PluginEndpointDiscovery;\n tokenManager: TokenManager;\n locationTemplate?: string;\n filter?: GetEntitiesRequest['filter'];\n catalogClient?: CatalogApi;\n }) {\n const { discovery, locationTemplate, filter, catalogClient, tokenManager } =\n options;\n\n this.discovery = discovery;\n this.locationTemplate =\n locationTemplate || '/catalog/:namespace/:kind/:name';\n this.filter = filter;\n this.catalogClient =\n catalogClient || new CatalogClient({ discoveryApi: discovery });\n this.tokenManager = tokenManager;\n }\n\n protected applyArgsToFormat(\n format: string,\n args: Record<string, string>,\n ): string {\n let formatted = format;\n for (const [key, value] of Object.entries(args)) {\n formatted = formatted.replace(`:${key}`, value);\n }\n return formatted.toLowerCase();\n }\n\n private getDocumentText(entity: Entity): string {\n let documentText = entity.metadata.description || '';\n if (isUserEntity(entity)) {\n if (entity.spec?.profile?.displayName && documentText) {\n // combine displayName and description\n const displayName = entity.spec?.profile?.displayName;\n documentText = displayName.concat(' : ', documentText);\n } else {\n documentText = entity.spec?.profile?.displayName || documentText;\n }\n }\n return documentText;\n }\n\n async execute() {\n const { token } = await this.tokenManager.getToken();\n const response = await this.catalogClient.getEntities(\n {\n filter: this.filter,\n },\n { token },\n );\n return response.items.map((entity: Entity): CatalogEntityDocument => {\n return {\n title: entity.metadata.title\n ? `${entity.metadata.title} (${entity.metadata.name})`\n : entity.metadata.name,\n location: this.applyArgsToFormat(this.locationTemplate, {\n namespace: entity.metadata.namespace || 'default',\n kind: entity.kind,\n name: entity.metadata.name,\n }),\n text: this.getDocumentText(entity),\n componentType: entity.spec?.type?.toString() || 'other',\n type: entity.spec?.type?.toString() || 'other',\n namespace: entity.metadata.namespace || 'default',\n kind: entity.kind,\n lifecycle: (entity.spec?.lifecycle as string) || '',\n owner: (entity.spec?.owner as string) || '',\n authorization: {\n resourceRef: stringifyEntityRef(entity),\n },\n };\n });\n }\n}\n"],"names":["catalogEntityReadPermission","catalogClient","CatalogClient","isUserEntity","stringifyEntityRef"],"mappings":"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"}
1
+ {"version":3,"file":"DefaultCatalogCollator.cjs.js","sources":["../../src/search/DefaultCatalogCollator.ts"],"sourcesContent":["/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { TokenManager } from '@backstage/backend-common';\nimport {\n Entity,\n isUserEntity,\n stringifyEntityRef,\n} from '@backstage/catalog-model';\nimport { Config } from '@backstage/config';\nimport {\n CatalogApi,\n CatalogClient,\n GetEntitiesRequest,\n} from '@backstage/catalog-client';\nimport { catalogEntityReadPermission } from '@backstage/plugin-catalog-common/alpha';\nimport { CatalogEntityDocument } from '@backstage/plugin-catalog-common';\nimport { Permission } from '@backstage/plugin-permission-common';\nimport { DiscoveryService } from '@backstage/backend-plugin-api';\n\n/**\n * @public\n * @deprecated Upgrade to a more recent `@backstage/plugin-search-backend-node` and\n * use `DefaultCatalogCollatorFactory` instead.\n */\nexport class DefaultCatalogCollator {\n protected discovery: DiscoveryService;\n protected locationTemplate: string;\n protected filter?: GetEntitiesRequest['filter'];\n protected readonly catalogClient: CatalogApi;\n public readonly type: string = 'software-catalog';\n public readonly visibilityPermission: Permission =\n catalogEntityReadPermission;\n protected tokenManager: TokenManager;\n\n static fromConfig(\n _config: Config,\n options: {\n discovery: DiscoveryService;\n tokenManager: TokenManager;\n filter?: GetEntitiesRequest['filter'];\n },\n ) {\n return new DefaultCatalogCollator({\n ...options,\n });\n }\n\n constructor(options: {\n discovery: DiscoveryService;\n tokenManager: TokenManager;\n locationTemplate?: string;\n filter?: GetEntitiesRequest['filter'];\n catalogClient?: CatalogApi;\n }) {\n const { discovery, locationTemplate, filter, catalogClient, tokenManager } =\n options;\n\n this.discovery = discovery;\n this.locationTemplate =\n locationTemplate || '/catalog/:namespace/:kind/:name';\n this.filter = filter;\n this.catalogClient =\n catalogClient || new CatalogClient({ discoveryApi: discovery });\n this.tokenManager = tokenManager;\n }\n\n protected applyArgsToFormat(\n format: string,\n args: Record<string, string>,\n ): string {\n let formatted = format;\n for (const [key, value] of Object.entries(args)) {\n formatted = formatted.replace(`:${key}`, value);\n }\n return formatted.toLowerCase();\n }\n\n private getDocumentText(entity: Entity): string {\n let documentText = entity.metadata.description || '';\n if (isUserEntity(entity)) {\n if (entity.spec?.profile?.displayName && documentText) {\n // combine displayName and description\n const displayName = entity.spec?.profile?.displayName;\n documentText = displayName.concat(' : ', documentText);\n } else {\n documentText = entity.spec?.profile?.displayName || documentText;\n }\n }\n return documentText;\n }\n\n async execute() {\n const { token } = await this.tokenManager.getToken();\n const response = await this.catalogClient.getEntities(\n {\n filter: this.filter,\n },\n { token },\n );\n return response.items.map((entity: Entity): CatalogEntityDocument => {\n return {\n title: entity.metadata.title\n ? `${entity.metadata.title} (${entity.metadata.name})`\n : entity.metadata.name,\n location: this.applyArgsToFormat(this.locationTemplate, {\n namespace: entity.metadata.namespace || 'default',\n kind: entity.kind,\n name: entity.metadata.name,\n }),\n text: this.getDocumentText(entity),\n componentType: entity.spec?.type?.toString() || 'other',\n type: entity.spec?.type?.toString() || 'other',\n namespace: entity.metadata.namespace || 'default',\n kind: entity.kind,\n lifecycle: (entity.spec?.lifecycle as string) || '',\n owner: (entity.spec?.owner as string) || '',\n authorization: {\n resourceRef: stringifyEntityRef(entity),\n },\n };\n });\n }\n}\n"],"names":["catalogEntityReadPermission","catalogClient","CatalogClient","isUserEntity","stringifyEntityRef"],"mappings":"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"}
@@ -22,7 +22,7 @@ class AuthorizedEntitiesCatalog {
22
22
  ))[0];
23
23
  if (authorizeDecision.result === pluginPermissionCommon.AuthorizeResult.DENY) {
24
24
  return {
25
- entities: [],
25
+ entities: { type: "object", entities: [] },
26
26
  pageInfo: { hasNextPage: false }
27
27
  };
28
28
  }
@@ -44,7 +44,10 @@ class AuthorizedEntitiesCatalog {
44
44
  ))[0];
45
45
  if (authorizeDecision.result === pluginPermissionCommon.AuthorizeResult.DENY) {
46
46
  return {
47
- items: new Array(request.entityRefs.length).fill(null)
47
+ items: {
48
+ type: "object",
49
+ entities: new Array(request.entityRefs.length).fill(null)
50
+ }
48
51
  };
49
52
  }
50
53
  if (authorizeDecision.result === pluginPermissionCommon.AuthorizeResult.CONDITIONAL) {
@@ -65,7 +68,7 @@ class AuthorizedEntitiesCatalog {
65
68
  ))[0];
66
69
  if (authorizeDecision.result === pluginPermissionCommon.AuthorizeResult.DENY) {
67
70
  return {
68
- items: [],
71
+ items: { type: "object", entities: [] },
69
72
  pageInfo: {},
70
73
  totalItems: 0
71
74
  };
@@ -131,7 +134,7 @@ class AuthorizedEntitiesCatalog {
131
134
  allOf: [permissionFilter, basicEntityFilter.basicEntityFilter({ "metadata.uid": uid })]
132
135
  }
133
136
  });
134
- if (entities.length === 0) {
137
+ if (entities.entities.length === 0) {
135
138
  throw new errors.NotAllowedError();
136
139
  }
137
140
  }
@@ -1 +1 @@
1
- {"version":3,"file":"AuthorizedEntitiesCatalog.cjs.js","sources":["../../src/service/AuthorizedEntitiesCatalog.ts"],"sourcesContent":["/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { NotAllowedError } from '@backstage/errors';\nimport {\n catalogEntityDeletePermission,\n catalogEntityReadPermission,\n} from '@backstage/plugin-catalog-common/alpha';\nimport { Entity, stringifyEntityRef } from '@backstage/catalog-model';\nimport { AuthorizeResult } from '@backstage/plugin-permission-common';\nimport { ConditionTransformer } from '@backstage/plugin-permission-node';\nimport {\n Cursor,\n EntitiesBatchRequest,\n EntitiesBatchResponse,\n EntitiesCatalog,\n EntitiesRequest,\n EntitiesResponse,\n EntityAncestryResponse,\n EntityFacetsRequest,\n EntityFacetsResponse,\n QueryEntitiesRequest,\n QueryEntitiesResponse,\n} from '../catalog/types';\nimport { basicEntityFilter } from './request';\nimport { isQueryEntitiesCursorRequest } from './util';\nimport { EntityFilter } from '@backstage/plugin-catalog-node';\nimport {\n BackstageCredentials,\n PermissionsService,\n} from '@backstage/backend-plugin-api';\n\nexport class AuthorizedEntitiesCatalog implements EntitiesCatalog {\n constructor(\n private readonly entitiesCatalog: EntitiesCatalog,\n private readonly permissionApi: PermissionsService,\n private readonly transformConditions: ConditionTransformer<EntityFilter>,\n ) {}\n\n async entities(request: EntitiesRequest): Promise<EntitiesResponse> {\n const authorizeDecision = (\n await this.permissionApi.authorizeConditional(\n [{ permission: catalogEntityReadPermission }],\n { credentials: request.credentials },\n )\n )[0];\n\n if (authorizeDecision.result === AuthorizeResult.DENY) {\n return {\n entities: [],\n pageInfo: { hasNextPage: false },\n };\n }\n\n if (authorizeDecision.result === AuthorizeResult.CONDITIONAL) {\n const permissionFilter: EntityFilter = this.transformConditions(\n authorizeDecision.conditions,\n );\n return this.entitiesCatalog.entities({\n ...request,\n filter: request?.filter\n ? { allOf: [permissionFilter, request.filter] }\n : permissionFilter,\n });\n }\n\n return this.entitiesCatalog.entities(request);\n }\n\n async entitiesBatch(\n request: EntitiesBatchRequest,\n ): Promise<EntitiesBatchResponse> {\n const authorizeDecision = (\n await this.permissionApi.authorizeConditional(\n [{ permission: catalogEntityReadPermission }],\n { credentials: request.credentials },\n )\n )[0];\n\n if (authorizeDecision.result === AuthorizeResult.DENY) {\n return {\n items: new Array(request.entityRefs.length).fill(null),\n };\n }\n\n if (authorizeDecision.result === AuthorizeResult.CONDITIONAL) {\n const permissionFilter: EntityFilter = this.transformConditions(\n authorizeDecision.conditions,\n );\n return this.entitiesCatalog.entitiesBatch({\n ...request,\n filter: request?.filter\n ? { allOf: [permissionFilter, request.filter] }\n : permissionFilter,\n });\n }\n\n return this.entitiesCatalog.entitiesBatch(request);\n }\n\n async queryEntities(\n request: QueryEntitiesRequest,\n ): Promise<QueryEntitiesResponse> {\n const authorizeDecision = (\n await this.permissionApi.authorizeConditional(\n [{ permission: catalogEntityReadPermission }],\n { credentials: request.credentials },\n )\n )[0];\n\n if (authorizeDecision.result === AuthorizeResult.DENY) {\n return {\n items: [],\n pageInfo: {},\n totalItems: 0,\n };\n }\n\n if (authorizeDecision.result === AuthorizeResult.CONDITIONAL) {\n const permissionFilter: EntityFilter = this.transformConditions(\n authorizeDecision.conditions,\n );\n\n let permissionedRequest: QueryEntitiesRequest;\n let requestFilter: EntityFilter | undefined;\n\n if (isQueryEntitiesCursorRequest(request)) {\n requestFilter = request.cursor.filter;\n\n permissionedRequest = {\n ...request,\n cursor: {\n ...request.cursor,\n filter: request.cursor.filter\n ? { allOf: [permissionFilter, request.cursor.filter] }\n : permissionFilter,\n },\n };\n } else {\n permissionedRequest = {\n ...request,\n filter: request.filter\n ? { allOf: [permissionFilter, request.filter] }\n : permissionFilter,\n };\n requestFilter = request.filter;\n }\n\n const response = await this.entitiesCatalog.queryEntities(\n permissionedRequest,\n );\n\n const prevCursor: Cursor | undefined = response.pageInfo.prevCursor && {\n ...response.pageInfo.prevCursor,\n filter: requestFilter,\n };\n\n const nextCursor: Cursor | undefined = response.pageInfo.nextCursor && {\n ...response.pageInfo.nextCursor,\n filter: requestFilter,\n };\n\n return {\n ...response,\n pageInfo: {\n prevCursor,\n nextCursor,\n },\n };\n }\n\n return this.entitiesCatalog.queryEntities(request);\n }\n\n async removeEntityByUid(\n uid: string,\n options: { credentials: BackstageCredentials },\n ): Promise<void> {\n const authorizeResponse = (\n await this.permissionApi.authorizeConditional(\n [{ permission: catalogEntityDeletePermission }],\n { credentials: options.credentials },\n )\n )[0];\n if (authorizeResponse.result === AuthorizeResult.DENY) {\n throw new NotAllowedError();\n }\n if (authorizeResponse.result === AuthorizeResult.CONDITIONAL) {\n const permissionFilter: EntityFilter = this.transformConditions(\n authorizeResponse.conditions,\n );\n const { entities } = await this.entitiesCatalog.entities({\n credentials: options.credentials,\n filter: {\n allOf: [permissionFilter, basicEntityFilter({ 'metadata.uid': uid })],\n },\n });\n if (entities.length === 0) {\n throw new NotAllowedError();\n }\n }\n return this.entitiesCatalog.removeEntityByUid(uid, {\n credentials: options.credentials,\n });\n }\n\n async entityAncestry(\n entityRef: string,\n options: { credentials: BackstageCredentials },\n ): Promise<EntityAncestryResponse> {\n const rootEntityAuthorizeResponse = (\n await this.permissionApi.authorize(\n [{ permission: catalogEntityReadPermission, resourceRef: entityRef }],\n { credentials: options.credentials },\n )\n )[0];\n if (rootEntityAuthorizeResponse.result === AuthorizeResult.DENY) {\n throw new NotAllowedError();\n }\n\n const ancestryResult = await this.entitiesCatalog.entityAncestry(\n entityRef,\n { credentials: options.credentials },\n );\n const authorizeResponse = await this.permissionApi.authorize(\n ancestryResult.items.map(item => ({\n permission: catalogEntityReadPermission,\n resourceRef: stringifyEntityRef(item.entity),\n })),\n { credentials: options.credentials },\n );\n const unauthorizedAncestryItems = ancestryResult.items.filter(\n (_, index) => authorizeResponse[index].result === AuthorizeResult.DENY,\n );\n if (unauthorizedAncestryItems.length === 0) {\n return ancestryResult;\n }\n const rootUnauthorizedEntityRefs = unauthorizedAncestryItems.map(\n ancestryItem => stringifyEntityRef(ancestryItem.entity),\n );\n const allUnauthorizedEntityRefs = new Set(\n rootUnauthorizedEntityRefs.flatMap(rootEntityRef =>\n this.findParents(\n rootEntityRef,\n ancestryResult.items,\n new Set(rootUnauthorizedEntityRefs),\n ),\n ),\n );\n return {\n rootEntityRef: ancestryResult.rootEntityRef,\n items: ancestryResult.items.filter(\n ancestryItem =>\n !allUnauthorizedEntityRefs.has(\n stringifyEntityRef(ancestryItem.entity),\n ),\n ),\n };\n }\n\n async facets(request: EntityFacetsRequest): Promise<EntityFacetsResponse> {\n const authorizeDecision = (\n await this.permissionApi.authorizeConditional(\n [{ permission: catalogEntityReadPermission }],\n { credentials: request.credentials },\n )\n )[0];\n\n if (authorizeDecision.result === AuthorizeResult.DENY) {\n return {\n facets: Object.fromEntries(request.facets.map(f => [f, []])),\n };\n }\n\n if (authorizeDecision.result === AuthorizeResult.CONDITIONAL) {\n const permissionFilter: EntityFilter = this.transformConditions(\n authorizeDecision.conditions,\n );\n return this.entitiesCatalog.facets({\n ...request,\n filter: request?.filter\n ? { allOf: [permissionFilter, request.filter] }\n : permissionFilter,\n });\n }\n\n return this.entitiesCatalog.facets(request);\n }\n\n private findParents(\n entityRef: string,\n allAncestryItems: { entity: Entity; parentEntityRefs: string[] }[],\n seenEntityRefs: Set<string>,\n ): string[] {\n const entity = allAncestryItems.find(\n ancestryItem => stringifyEntityRef(ancestryItem.entity) === entityRef,\n );\n if (!entity) return [];\n\n const newSeenEntityRefs = new Set(seenEntityRefs);\n entity.parentEntityRefs.forEach(parentRef =>\n newSeenEntityRefs.add(parentRef),\n );\n\n return [\n entityRef,\n ...entity.parentEntityRefs.flatMap(parentRef =>\n seenEntityRefs.has(parentRef)\n ? []\n : this.findParents(parentRef, allAncestryItems, newSeenEntityRefs),\n ),\n ];\n }\n}\n"],"names":["catalogEntityReadPermission","AuthorizeResult","isQueryEntitiesCursorRequest","catalogEntityDeletePermission","NotAllowedError","basicEntityFilter","stringifyEntityRef"],"mappings":"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"}
1
+ {"version":3,"file":"AuthorizedEntitiesCatalog.cjs.js","sources":["../../src/service/AuthorizedEntitiesCatalog.ts"],"sourcesContent":["/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { NotAllowedError } from '@backstage/errors';\nimport {\n catalogEntityDeletePermission,\n catalogEntityReadPermission,\n} from '@backstage/plugin-catalog-common/alpha';\nimport { Entity, stringifyEntityRef } from '@backstage/catalog-model';\nimport { AuthorizeResult } from '@backstage/plugin-permission-common';\nimport { ConditionTransformer } from '@backstage/plugin-permission-node';\nimport {\n Cursor,\n EntitiesBatchRequest,\n EntitiesBatchResponse,\n EntitiesCatalog,\n EntitiesRequest,\n EntitiesResponse,\n EntityAncestryResponse,\n EntityFacetsRequest,\n EntityFacetsResponse,\n QueryEntitiesRequest,\n QueryEntitiesResponse,\n} from '../catalog/types';\nimport { basicEntityFilter } from './request';\nimport { isQueryEntitiesCursorRequest } from './util';\nimport { EntityFilter } from '@backstage/plugin-catalog-node';\nimport {\n BackstageCredentials,\n PermissionsService,\n} from '@backstage/backend-plugin-api';\n\nexport class AuthorizedEntitiesCatalog implements EntitiesCatalog {\n constructor(\n private readonly entitiesCatalog: EntitiesCatalog,\n private readonly permissionApi: PermissionsService,\n private readonly transformConditions: ConditionTransformer<EntityFilter>,\n ) {}\n\n async entities(request: EntitiesRequest): Promise<EntitiesResponse> {\n const authorizeDecision = (\n await this.permissionApi.authorizeConditional(\n [{ permission: catalogEntityReadPermission }],\n { credentials: request.credentials },\n )\n )[0];\n\n if (authorizeDecision.result === AuthorizeResult.DENY) {\n return {\n entities: { type: 'object', entities: [] },\n pageInfo: { hasNextPage: false },\n };\n }\n\n if (authorizeDecision.result === AuthorizeResult.CONDITIONAL) {\n const permissionFilter: EntityFilter = this.transformConditions(\n authorizeDecision.conditions,\n );\n return this.entitiesCatalog.entities({\n ...request,\n filter: request?.filter\n ? { allOf: [permissionFilter, request.filter] }\n : permissionFilter,\n });\n }\n\n return this.entitiesCatalog.entities(request);\n }\n\n async entitiesBatch(\n request: EntitiesBatchRequest,\n ): Promise<EntitiesBatchResponse> {\n const authorizeDecision = (\n await this.permissionApi.authorizeConditional(\n [{ permission: catalogEntityReadPermission }],\n { credentials: request.credentials },\n )\n )[0];\n\n if (authorizeDecision.result === AuthorizeResult.DENY) {\n return {\n items: {\n type: 'object',\n entities: new Array(request.entityRefs.length).fill(null),\n },\n };\n }\n\n if (authorizeDecision.result === AuthorizeResult.CONDITIONAL) {\n const permissionFilter: EntityFilter = this.transformConditions(\n authorizeDecision.conditions,\n );\n return this.entitiesCatalog.entitiesBatch({\n ...request,\n filter: request?.filter\n ? { allOf: [permissionFilter, request.filter] }\n : permissionFilter,\n });\n }\n\n return this.entitiesCatalog.entitiesBatch(request);\n }\n\n async queryEntities(\n request: QueryEntitiesRequest,\n ): Promise<QueryEntitiesResponse> {\n const authorizeDecision = (\n await this.permissionApi.authorizeConditional(\n [{ permission: catalogEntityReadPermission }],\n { credentials: request.credentials },\n )\n )[0];\n\n if (authorizeDecision.result === AuthorizeResult.DENY) {\n return {\n items: { type: 'object', entities: [] },\n pageInfo: {},\n totalItems: 0,\n };\n }\n\n if (authorizeDecision.result === AuthorizeResult.CONDITIONAL) {\n const permissionFilter: EntityFilter = this.transformConditions(\n authorizeDecision.conditions,\n );\n\n let permissionedRequest: QueryEntitiesRequest;\n let requestFilter: EntityFilter | undefined;\n\n if (isQueryEntitiesCursorRequest(request)) {\n requestFilter = request.cursor.filter;\n\n permissionedRequest = {\n ...request,\n cursor: {\n ...request.cursor,\n filter: request.cursor.filter\n ? { allOf: [permissionFilter, request.cursor.filter] }\n : permissionFilter,\n },\n };\n } else {\n permissionedRequest = {\n ...request,\n filter: request.filter\n ? { allOf: [permissionFilter, request.filter] }\n : permissionFilter,\n };\n requestFilter = request.filter;\n }\n\n const response = await this.entitiesCatalog.queryEntities(\n permissionedRequest,\n );\n\n const prevCursor: Cursor | undefined = response.pageInfo.prevCursor && {\n ...response.pageInfo.prevCursor,\n filter: requestFilter,\n };\n\n const nextCursor: Cursor | undefined = response.pageInfo.nextCursor && {\n ...response.pageInfo.nextCursor,\n filter: requestFilter,\n };\n\n return {\n ...response,\n pageInfo: {\n prevCursor,\n nextCursor,\n },\n };\n }\n\n return this.entitiesCatalog.queryEntities(request);\n }\n\n async removeEntityByUid(\n uid: string,\n options: { credentials: BackstageCredentials },\n ): Promise<void> {\n const authorizeResponse = (\n await this.permissionApi.authorizeConditional(\n [{ permission: catalogEntityDeletePermission }],\n { credentials: options.credentials },\n )\n )[0];\n if (authorizeResponse.result === AuthorizeResult.DENY) {\n throw new NotAllowedError();\n }\n if (authorizeResponse.result === AuthorizeResult.CONDITIONAL) {\n const permissionFilter: EntityFilter = this.transformConditions(\n authorizeResponse.conditions,\n );\n const { entities } = await this.entitiesCatalog.entities({\n credentials: options.credentials,\n filter: {\n allOf: [permissionFilter, basicEntityFilter({ 'metadata.uid': uid })],\n },\n });\n if (entities.entities.length === 0) {\n throw new NotAllowedError();\n }\n }\n return this.entitiesCatalog.removeEntityByUid(uid, {\n credentials: options.credentials,\n });\n }\n\n async entityAncestry(\n entityRef: string,\n options: { credentials: BackstageCredentials },\n ): Promise<EntityAncestryResponse> {\n const rootEntityAuthorizeResponse = (\n await this.permissionApi.authorize(\n [{ permission: catalogEntityReadPermission, resourceRef: entityRef }],\n { credentials: options.credentials },\n )\n )[0];\n if (rootEntityAuthorizeResponse.result === AuthorizeResult.DENY) {\n throw new NotAllowedError();\n }\n\n const ancestryResult = await this.entitiesCatalog.entityAncestry(\n entityRef,\n { credentials: options.credentials },\n );\n const authorizeResponse = await this.permissionApi.authorize(\n ancestryResult.items.map(item => ({\n permission: catalogEntityReadPermission,\n resourceRef: stringifyEntityRef(item.entity),\n })),\n { credentials: options.credentials },\n );\n const unauthorizedAncestryItems = ancestryResult.items.filter(\n (_, index) => authorizeResponse[index].result === AuthorizeResult.DENY,\n );\n if (unauthorizedAncestryItems.length === 0) {\n return ancestryResult;\n }\n const rootUnauthorizedEntityRefs = unauthorizedAncestryItems.map(\n ancestryItem => stringifyEntityRef(ancestryItem.entity),\n );\n const allUnauthorizedEntityRefs = new Set(\n rootUnauthorizedEntityRefs.flatMap(rootEntityRef =>\n this.findParents(\n rootEntityRef,\n ancestryResult.items,\n new Set(rootUnauthorizedEntityRefs),\n ),\n ),\n );\n return {\n rootEntityRef: ancestryResult.rootEntityRef,\n items: ancestryResult.items.filter(\n ancestryItem =>\n !allUnauthorizedEntityRefs.has(\n stringifyEntityRef(ancestryItem.entity),\n ),\n ),\n };\n }\n\n async facets(request: EntityFacetsRequest): Promise<EntityFacetsResponse> {\n const authorizeDecision = (\n await this.permissionApi.authorizeConditional(\n [{ permission: catalogEntityReadPermission }],\n { credentials: request.credentials },\n )\n )[0];\n\n if (authorizeDecision.result === AuthorizeResult.DENY) {\n return {\n facets: Object.fromEntries(request.facets.map(f => [f, []])),\n };\n }\n\n if (authorizeDecision.result === AuthorizeResult.CONDITIONAL) {\n const permissionFilter: EntityFilter = this.transformConditions(\n authorizeDecision.conditions,\n );\n return this.entitiesCatalog.facets({\n ...request,\n filter: request?.filter\n ? { allOf: [permissionFilter, request.filter] }\n : permissionFilter,\n });\n }\n\n return this.entitiesCatalog.facets(request);\n }\n\n private findParents(\n entityRef: string,\n allAncestryItems: { entity: Entity; parentEntityRefs: string[] }[],\n seenEntityRefs: Set<string>,\n ): string[] {\n const entity = allAncestryItems.find(\n ancestryItem => stringifyEntityRef(ancestryItem.entity) === entityRef,\n );\n if (!entity) return [];\n\n const newSeenEntityRefs = new Set(seenEntityRefs);\n entity.parentEntityRefs.forEach(parentRef =>\n newSeenEntityRefs.add(parentRef),\n );\n\n return [\n entityRef,\n ...entity.parentEntityRefs.flatMap(parentRef =>\n seenEntityRefs.has(parentRef)\n ? []\n : this.findParents(parentRef, allAncestryItems, newSeenEntityRefs),\n ),\n ];\n }\n}\n"],"names":["catalogEntityReadPermission","AuthorizeResult","isQueryEntitiesCursorRequest","catalogEntityDeletePermission","NotAllowedError","basicEntityFilter","stringifyEntityRef"],"mappings":"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"}
@@ -46,6 +46,7 @@ var AuthorizedLocationService = require('./AuthorizedLocationService.cjs.js');
46
46
  var DefaultProviderDatabase = require('../database/DefaultProviderDatabase.cjs.js');
47
47
  var DefaultCatalogDatabase = require('../database/DefaultCatalogDatabase.cjs.js');
48
48
  var types = require('@backstage/types');
49
+ var process$1 = require('./response/process.cjs.js');
49
50
 
50
51
  function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
51
52
 
@@ -321,6 +322,9 @@ class CatalogBuilder {
321
322
  ...this.env,
322
323
  discovery
323
324
  });
325
+ const disableRelationsCompatibility = config.getOptionalBoolean(
326
+ "catalog.disableRelationsCompatibility"
327
+ );
324
328
  const policy = this.buildEntityPolicy();
325
329
  const processors = this.buildProcessors();
326
330
  const parser = this.parser || parse.defaultEntityDataParser;
@@ -352,7 +356,8 @@ class CatalogBuilder {
352
356
  const unauthorizedEntitiesCatalog = new DefaultEntitiesCatalog.DefaultEntitiesCatalog({
353
357
  database: dbClient,
354
358
  logger,
355
- stitcher
359
+ stitcher,
360
+ disableRelationsCompatibility
356
361
  });
357
362
  let permissionsService;
358
363
  if ("authorizeConditional" in permissions) {
@@ -393,7 +398,10 @@ class CatalogBuilder {
393
398
  })
394
399
  }
395
400
  });
396
- const entitiesByRef = lodash.keyBy(entities, catalogModel.stringifyEntityRef);
401
+ const entitiesByRef = lodash.keyBy(
402
+ process$1.entitiesResponseToObjects(entities),
403
+ catalogModel.stringifyEntityRef
404
+ );
397
405
  return resourceRefs.map(
398
406
  (resourceRef) => entitiesByRef[catalogModel.stringifyEntityRef(catalogModel.parseEntityRef(resourceRef))]
399
407
  );
@@ -447,7 +455,8 @@ class CatalogBuilder {
447
455
  permissionIntegrationRouter,
448
456
  auth,
449
457
  httpAuth,
450
- permissionsService
458
+ permissionsService,
459
+ disableRelationsCompatibility
451
460
  });
452
461
  await connectEntityProviders.connectEntityProviders(providerDatabase, entityProviders);
453
462
  return {