@backstage/catalog-client 1.7.1 → 1.8.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 +13 -0
- package/dist/CatalogClient.cjs.js +22 -15
- package/dist/CatalogClient.cjs.js.map +1 -1
- package/dist/CatalogClient.esm.js +23 -16
- package/dist/CatalogClient.esm.js.map +1 -1
- package/dist/testUtils/InMemoryCatalogClient.cjs.js +14 -5
- package/dist/testUtils/InMemoryCatalogClient.cjs.js.map +1 -1
- package/dist/testUtils/InMemoryCatalogClient.esm.js +14 -5
- package/dist/testUtils/InMemoryCatalogClient.esm.js.map +1 -1
- package/dist/utils.cjs.js +30 -0
- package/dist/utils.cjs.js.map +1 -1
- package/dist/utils.esm.js +30 -1
- package/dist/utils.esm.js.map +1 -1
- package/package.json +4 -4
- package/testUtils/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# @backstage/catalog-client
|
|
2
2
|
|
|
3
|
+
## 1.8.0-next.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 31c4fe0: The client now automatically splits up very large `getEntitiesByRefs` calls into several smaller requests behind the scenes when needed. This ensures that each individual request does not exceed common Express.js request body limits or overload the server.
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- 873f89a: Fix for certain filter fields in the `catalogApiMock` being case sensitive.
|
|
12
|
+
- Updated dependencies
|
|
13
|
+
- @backstage/catalog-model@1.7.0
|
|
14
|
+
- @backstage/errors@1.2.4
|
|
15
|
+
|
|
3
16
|
## 1.7.1
|
|
4
17
|
|
|
5
18
|
### Patch Changes
|
|
@@ -82,23 +82,30 @@ class CatalogClient {
|
|
|
82
82
|
* {@inheritdoc CatalogApi.getEntitiesByRefs}
|
|
83
83
|
*/
|
|
84
84
|
async getEntitiesByRefs(request, options) {
|
|
85
|
-
const
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
entityRefs: request.
|
|
89
|
-
|
|
85
|
+
const getOneChunk = async (refs) => {
|
|
86
|
+
const response = await this.apiClient.getEntitiesByRefs(
|
|
87
|
+
{
|
|
88
|
+
body: { entityRefs: refs, fields: request.fields },
|
|
89
|
+
query: { filter: this.getFilterValue(request.filter) }
|
|
90
90
|
},
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
91
|
+
options
|
|
92
|
+
);
|
|
93
|
+
if (!response.ok) {
|
|
94
|
+
throw await errors.ResponseError.fromResponse(response);
|
|
95
|
+
}
|
|
96
|
+
const body = await response.json();
|
|
97
|
+
return body.items.map((i) => i ?? void 0);
|
|
98
|
+
};
|
|
99
|
+
let result;
|
|
100
|
+
for (const refs of utils.splitRefsIntoChunks(request.entityRefs)) {
|
|
101
|
+
const entities = await getOneChunk(refs);
|
|
102
|
+
if (!result) {
|
|
103
|
+
result = entities;
|
|
104
|
+
} else {
|
|
105
|
+
result.push(...entities);
|
|
106
|
+
}
|
|
99
107
|
}
|
|
100
|
-
|
|
101
|
-
return { items: items.map((i) => i ?? void 0) };
|
|
108
|
+
return { items: result ?? [] };
|
|
102
109
|
}
|
|
103
110
|
/**
|
|
104
111
|
* {@inheritdoc CatalogApi.queryEntities}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CatalogClient.cjs.js","sources":["../src/CatalogClient.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 {\n CompoundEntityRef,\n Entity,\n parseEntityRef,\n stringifyLocationRef,\n} from '@backstage/catalog-model';\nimport { ResponseError } from '@backstage/errors';\nimport {\n AddLocationRequest,\n AddLocationResponse,\n CATALOG_FILTER_EXISTS,\n CatalogApi,\n CatalogRequestOptions,\n EntityFilterQuery,\n GetEntitiesByRefsRequest,\n GetEntitiesByRefsResponse,\n GetEntitiesRequest,\n GetEntitiesResponse,\n GetEntityAncestorsRequest,\n GetEntityAncestorsResponse,\n GetEntityFacetsRequest,\n GetEntityFacetsResponse,\n Location,\n QueryEntitiesRequest,\n QueryEntitiesResponse,\n ValidateEntityResponse,\n} from './types/api';\nimport { isQueryEntitiesInitialRequest } from './utils';\nimport { DefaultApiClient, TypedResponse } from './generated';\n\n/**\n * A frontend and backend compatible client for communicating with the Backstage\n * software catalog.\n *\n * @public\n */\nexport class CatalogClient implements CatalogApi {\n private readonly apiClient: DefaultApiClient;\n\n constructor(options: {\n discoveryApi: { getBaseUrl(pluginId: string): Promise<string> };\n fetchApi?: { fetch: typeof fetch };\n }) {\n this.apiClient = new DefaultApiClient(options);\n }\n\n /**\n * {@inheritdoc CatalogApi.getEntityAncestors}\n */\n async getEntityAncestors(\n request: GetEntityAncestorsRequest,\n options?: CatalogRequestOptions,\n ): Promise<GetEntityAncestorsResponse> {\n return await this.requestRequired(\n await this.apiClient.getEntityAncestryByName(\n { path: parseEntityRef(request.entityRef) },\n options,\n ),\n );\n }\n\n /**\n * {@inheritdoc CatalogApi.getLocationById}\n */\n async getLocationById(\n id: string,\n options?: CatalogRequestOptions,\n ): Promise<Location | undefined> {\n return await this.requestOptional(\n await this.apiClient.getLocation({ path: { id } }, options),\n );\n }\n\n /**\n * {@inheritdoc CatalogApi.getLocationByEntity}\n */\n async getLocationByEntity(\n entityRef: CompoundEntityRef | string,\n options?: CatalogRequestOptions,\n ): Promise<Location | undefined> {\n return await this.requestOptional(\n await this.apiClient.getLocationByEntity(\n { path: parseEntityRef(entityRef) },\n options,\n ),\n );\n }\n\n /**\n * {@inheritdoc CatalogApi.getEntities}\n */\n async getEntities(\n request?: GetEntitiesRequest,\n options?: CatalogRequestOptions,\n ): Promise<GetEntitiesResponse> {\n const {\n filter = [],\n fields = [],\n order,\n offset,\n limit,\n after,\n } = request ?? {};\n const encodedOrder = [];\n if (order) {\n for (const directive of [order].flat()) {\n if (directive) {\n encodedOrder.push(`${directive.order}:${directive.field}`);\n }\n }\n }\n\n const entities = await this.requestRequired(\n await this.apiClient.getEntities(\n {\n query: {\n fields,\n limit,\n filter: this.getFilterValue(filter),\n offset,\n after,\n order: order ? encodedOrder : undefined,\n },\n },\n options,\n ),\n );\n return { items: entities };\n }\n\n /**\n * {@inheritdoc CatalogApi.getEntitiesByRefs}\n */\n async getEntitiesByRefs(\n request: GetEntitiesByRefsRequest,\n options?: CatalogRequestOptions,\n ): Promise<GetEntitiesByRefsResponse> {\n const response = await this.apiClient.getEntitiesByRefs(\n {\n body: {\n entityRefs: request.entityRefs,\n fields: request.fields,\n },\n query: {\n filter: this.getFilterValue(request.filter),\n },\n },\n options,\n );\n\n if (!response.ok) {\n throw await ResponseError.fromResponse(response);\n }\n\n const { items } = (await response.json()) as {\n items: Array<Entity | null>;\n };\n\n return { items: items.map(i => i ?? undefined) };\n }\n\n /**\n * {@inheritdoc CatalogApi.queryEntities}\n */\n async queryEntities(\n request: QueryEntitiesRequest = {},\n options?: CatalogRequestOptions,\n ): Promise<QueryEntitiesResponse> {\n const params: Partial<\n Parameters<typeof this.apiClient.getEntitiesByQuery>[0]['query']\n > = {};\n\n if (isQueryEntitiesInitialRequest(request)) {\n const {\n fields = [],\n filter,\n limit,\n offset,\n orderFields,\n fullTextFilter,\n } = request;\n params.filter = this.getFilterValue(filter);\n\n if (limit !== undefined) {\n params.limit = limit;\n }\n if (offset !== undefined) {\n params.offset = offset;\n }\n if (orderFields !== undefined) {\n params.orderField = (\n Array.isArray(orderFields) ? orderFields : [orderFields]\n ).map(({ field, order }) => `${field},${order}`);\n }\n if (fields.length) {\n params.fields = fields;\n }\n\n const normalizedFullTextFilterTerm = fullTextFilter?.term?.trim();\n if (normalizedFullTextFilterTerm) {\n params.fullTextFilterTerm = normalizedFullTextFilterTerm;\n }\n if (fullTextFilter?.fields?.length) {\n params.fullTextFilterFields = fullTextFilter.fields;\n }\n } else {\n const { fields = [], limit, cursor } = request;\n\n params.cursor = cursor;\n if (limit !== undefined) {\n params.limit = limit;\n }\n if (fields.length) {\n params.fields = fields;\n }\n }\n\n return this.apiClient\n .getEntitiesByQuery({ query: params }, options)\n .then(r => r.json());\n }\n\n /**\n * {@inheritdoc CatalogApi.getEntityByRef}\n */\n async getEntityByRef(\n entityRef: string | CompoundEntityRef,\n options?: CatalogRequestOptions,\n ): Promise<Entity | undefined> {\n return this.requestOptional(\n await this.apiClient.getEntityByName(\n {\n path: parseEntityRef(entityRef),\n },\n options,\n ),\n );\n }\n\n // NOTE(freben): When we deprecate getEntityByName from the interface, we may\n // still want to leave this implementation in place for quite some time\n // longer, to minimize the risk for breakages. Suggested date for removal:\n // August 2022\n /**\n * @deprecated Use getEntityByRef instead\n */\n async getEntityByName(\n compoundName: CompoundEntityRef,\n options?: CatalogRequestOptions,\n ): Promise<Entity | undefined> {\n const { kind, namespace = 'default', name } = compoundName;\n return this.requestOptional(\n await this.apiClient.getEntityByName(\n { path: { kind, namespace, name } },\n options,\n ),\n );\n }\n\n /**\n * {@inheritdoc CatalogApi.refreshEntity}\n */\n async refreshEntity(entityRef: string, options?: CatalogRequestOptions) {\n const response = await this.apiClient.refreshEntity(\n { body: { entityRef } },\n options,\n );\n\n if (response.status !== 200) {\n throw new Error(await response.text());\n }\n }\n\n /**\n * {@inheritdoc CatalogApi.getEntityFacets}\n */\n async getEntityFacets(\n request: GetEntityFacetsRequest,\n options?: CatalogRequestOptions,\n ): Promise<GetEntityFacetsResponse> {\n const { filter = [], facets } = request;\n return await this.requestOptional(\n await this.apiClient.getEntityFacets(\n {\n query: { facet: facets, filter: this.getFilterValue(filter) },\n },\n options,\n ),\n );\n }\n\n /**\n * {@inheritdoc CatalogApi.addLocation}\n */\n async addLocation(\n request: AddLocationRequest,\n options?: CatalogRequestOptions,\n ): Promise<AddLocationResponse> {\n const { type = 'url', target, dryRun } = request;\n\n const response = await this.apiClient.createLocation(\n {\n body: { type, target },\n query: { dryRun: dryRun ? 'true' : undefined },\n },\n options,\n );\n\n if (response.status !== 201) {\n throw new Error(await response.text());\n }\n\n const { location, entities, exists } = await response.json();\n\n if (!location) {\n throw new Error(`Location wasn't added: ${target}`);\n }\n\n return {\n location,\n entities,\n exists,\n };\n }\n\n /**\n * {@inheritdoc CatalogApi.getLocationByRef}\n */\n async getLocationByRef(\n locationRef: string,\n options?: CatalogRequestOptions,\n ): Promise<Location | undefined> {\n const all = await this.requestRequired(\n await this.apiClient.getLocations({}, options),\n );\n return all\n .map(r => r.data)\n .find(l => locationRef === stringifyLocationRef(l));\n }\n\n /**\n * {@inheritdoc CatalogApi.removeLocationById}\n */\n async removeLocationById(\n id: string,\n options?: CatalogRequestOptions,\n ): Promise<void> {\n await this.requestIgnored(\n await this.apiClient.deleteLocation({ path: { id } }, options),\n );\n }\n\n /**\n * {@inheritdoc CatalogApi.removeEntityByUid}\n */\n async removeEntityByUid(\n uid: string,\n options?: CatalogRequestOptions,\n ): Promise<void> {\n await this.requestIgnored(\n await this.apiClient.deleteEntityByUid({ path: { uid } }, options),\n );\n }\n\n /**\n * {@inheritdoc CatalogApi.validateEntity}\n */\n async validateEntity(\n entity: Entity,\n locationRef: string,\n options?: CatalogRequestOptions,\n ): Promise<ValidateEntityResponse> {\n const response = await this.apiClient.validateEntity(\n { body: { entity, location: locationRef } },\n options,\n );\n\n if (response.ok) {\n return {\n valid: true,\n };\n }\n\n if (response.status !== 400) {\n throw await ResponseError.fromResponse(response);\n }\n\n const { errors = [] } = (await response.json()) as any;\n\n return {\n valid: false,\n errors,\n };\n }\n\n //\n // Private methods\n //\n\n private async requestIgnored(response: Response): Promise<void> {\n if (!response.ok) {\n throw await ResponseError.fromResponse(response);\n }\n }\n\n private async requestRequired<T>(response: TypedResponse<T>): Promise<T> {\n if (!response.ok) {\n throw await ResponseError.fromResponse(response);\n }\n\n return response.json();\n }\n\n private async requestOptional(response: Response): Promise<any | undefined> {\n if (!response.ok) {\n if (response.status === 404) {\n return undefined;\n }\n throw await ResponseError.fromResponse(response);\n }\n\n return await response.json();\n }\n\n private getFilterValue(filter: EntityFilterQuery = []) {\n const filters: string[] = [];\n // filter param can occur multiple times, for example\n // /api/catalog/entities?filter=metadata.name=wayback-search,kind=component&filter=metadata.name=www-artist,kind=component'\n // the \"outer array\" defined by `filter` occurrences corresponds to \"anyOf\" filters\n // the \"inner array\" defined within a `filter` param corresponds to \"allOf\" filters\n for (const filterItem of [filter].flat()) {\n const filterParts: string[] = [];\n for (const [key, value] of Object.entries(filterItem)) {\n for (const v of [value].flat()) {\n if (v === CATALOG_FILTER_EXISTS) {\n filterParts.push(key);\n } else if (typeof v === 'string') {\n filterParts.push(`${key}=${v}`);\n }\n }\n }\n\n if (filterParts.length) {\n filters.push(filterParts.join(','));\n }\n }\n return filters;\n }\n}\n"],"names":["DefaultApiClient","parseEntityRef","ResponseError","isQueryEntitiesInitialRequest","stringifyLocationRef","errors","CATALOG_FILTER_EXISTS"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"CatalogClient.cjs.js","sources":["../src/CatalogClient.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 {\n CompoundEntityRef,\n Entity,\n parseEntityRef,\n stringifyLocationRef,\n} from '@backstage/catalog-model';\nimport { ResponseError } from '@backstage/errors';\nimport {\n AddLocationRequest,\n AddLocationResponse,\n CATALOG_FILTER_EXISTS,\n CatalogApi,\n CatalogRequestOptions,\n EntityFilterQuery,\n GetEntitiesByRefsRequest,\n GetEntitiesByRefsResponse,\n GetEntitiesRequest,\n GetEntitiesResponse,\n GetEntityAncestorsRequest,\n GetEntityAncestorsResponse,\n GetEntityFacetsRequest,\n GetEntityFacetsResponse,\n Location,\n QueryEntitiesRequest,\n QueryEntitiesResponse,\n ValidateEntityResponse,\n} from './types/api';\nimport { isQueryEntitiesInitialRequest, splitRefsIntoChunks } from './utils';\nimport { DefaultApiClient, TypedResponse } from './generated';\n\n/**\n * A frontend and backend compatible client for communicating with the Backstage\n * software catalog.\n *\n * @public\n */\nexport class CatalogClient implements CatalogApi {\n private readonly apiClient: DefaultApiClient;\n\n constructor(options: {\n discoveryApi: { getBaseUrl(pluginId: string): Promise<string> };\n fetchApi?: { fetch: typeof fetch };\n }) {\n this.apiClient = new DefaultApiClient(options);\n }\n\n /**\n * {@inheritdoc CatalogApi.getEntityAncestors}\n */\n async getEntityAncestors(\n request: GetEntityAncestorsRequest,\n options?: CatalogRequestOptions,\n ): Promise<GetEntityAncestorsResponse> {\n return await this.requestRequired(\n await this.apiClient.getEntityAncestryByName(\n { path: parseEntityRef(request.entityRef) },\n options,\n ),\n );\n }\n\n /**\n * {@inheritdoc CatalogApi.getLocationById}\n */\n async getLocationById(\n id: string,\n options?: CatalogRequestOptions,\n ): Promise<Location | undefined> {\n return await this.requestOptional(\n await this.apiClient.getLocation({ path: { id } }, options),\n );\n }\n\n /**\n * {@inheritdoc CatalogApi.getLocationByEntity}\n */\n async getLocationByEntity(\n entityRef: CompoundEntityRef | string,\n options?: CatalogRequestOptions,\n ): Promise<Location | undefined> {\n return await this.requestOptional(\n await this.apiClient.getLocationByEntity(\n { path: parseEntityRef(entityRef) },\n options,\n ),\n );\n }\n\n /**\n * {@inheritdoc CatalogApi.getEntities}\n */\n async getEntities(\n request?: GetEntitiesRequest,\n options?: CatalogRequestOptions,\n ): Promise<GetEntitiesResponse> {\n const {\n filter = [],\n fields = [],\n order,\n offset,\n limit,\n after,\n } = request ?? {};\n const encodedOrder = [];\n if (order) {\n for (const directive of [order].flat()) {\n if (directive) {\n encodedOrder.push(`${directive.order}:${directive.field}`);\n }\n }\n }\n\n const entities = await this.requestRequired(\n await this.apiClient.getEntities(\n {\n query: {\n fields,\n limit,\n filter: this.getFilterValue(filter),\n offset,\n after,\n order: order ? encodedOrder : undefined,\n },\n },\n options,\n ),\n );\n return { items: entities };\n }\n\n /**\n * {@inheritdoc CatalogApi.getEntitiesByRefs}\n */\n async getEntitiesByRefs(\n request: GetEntitiesByRefsRequest,\n options?: CatalogRequestOptions,\n ): Promise<GetEntitiesByRefsResponse> {\n const getOneChunk = async (refs: string[]) => {\n const response = await this.apiClient.getEntitiesByRefs(\n {\n body: { entityRefs: refs, fields: request.fields },\n query: { filter: this.getFilterValue(request.filter) },\n },\n options,\n );\n if (!response.ok) {\n throw await ResponseError.fromResponse(response);\n }\n const body = (await response.json()) as {\n items: Array<Entity | null>;\n };\n return body.items.map(i => i ?? undefined);\n };\n\n let result: Array<Entity | undefined> | undefined;\n for (const refs of splitRefsIntoChunks(request.entityRefs)) {\n const entities = await getOneChunk(refs);\n if (!result) {\n result = entities;\n } else {\n result.push(...entities);\n }\n }\n\n return { items: result ?? [] };\n }\n\n /**\n * {@inheritdoc CatalogApi.queryEntities}\n */\n async queryEntities(\n request: QueryEntitiesRequest = {},\n options?: CatalogRequestOptions,\n ): Promise<QueryEntitiesResponse> {\n const params: Partial<\n Parameters<typeof this.apiClient.getEntitiesByQuery>[0]['query']\n > = {};\n\n if (isQueryEntitiesInitialRequest(request)) {\n const {\n fields = [],\n filter,\n limit,\n offset,\n orderFields,\n fullTextFilter,\n } = request;\n params.filter = this.getFilterValue(filter);\n\n if (limit !== undefined) {\n params.limit = limit;\n }\n if (offset !== undefined) {\n params.offset = offset;\n }\n if (orderFields !== undefined) {\n params.orderField = (\n Array.isArray(orderFields) ? orderFields : [orderFields]\n ).map(({ field, order }) => `${field},${order}`);\n }\n if (fields.length) {\n params.fields = fields;\n }\n\n const normalizedFullTextFilterTerm = fullTextFilter?.term?.trim();\n if (normalizedFullTextFilterTerm) {\n params.fullTextFilterTerm = normalizedFullTextFilterTerm;\n }\n if (fullTextFilter?.fields?.length) {\n params.fullTextFilterFields = fullTextFilter.fields;\n }\n } else {\n const { fields = [], limit, cursor } = request;\n\n params.cursor = cursor;\n if (limit !== undefined) {\n params.limit = limit;\n }\n if (fields.length) {\n params.fields = fields;\n }\n }\n\n return this.apiClient\n .getEntitiesByQuery({ query: params }, options)\n .then(r => r.json());\n }\n\n /**\n * {@inheritdoc CatalogApi.getEntityByRef}\n */\n async getEntityByRef(\n entityRef: string | CompoundEntityRef,\n options?: CatalogRequestOptions,\n ): Promise<Entity | undefined> {\n return this.requestOptional(\n await this.apiClient.getEntityByName(\n {\n path: parseEntityRef(entityRef),\n },\n options,\n ),\n );\n }\n\n // NOTE(freben): When we deprecate getEntityByName from the interface, we may\n // still want to leave this implementation in place for quite some time\n // longer, to minimize the risk for breakages. Suggested date for removal:\n // August 2022\n /**\n * @deprecated Use getEntityByRef instead\n */\n async getEntityByName(\n compoundName: CompoundEntityRef,\n options?: CatalogRequestOptions,\n ): Promise<Entity | undefined> {\n const { kind, namespace = 'default', name } = compoundName;\n return this.requestOptional(\n await this.apiClient.getEntityByName(\n { path: { kind, namespace, name } },\n options,\n ),\n );\n }\n\n /**\n * {@inheritdoc CatalogApi.refreshEntity}\n */\n async refreshEntity(entityRef: string, options?: CatalogRequestOptions) {\n const response = await this.apiClient.refreshEntity(\n { body: { entityRef } },\n options,\n );\n\n if (response.status !== 200) {\n throw new Error(await response.text());\n }\n }\n\n /**\n * {@inheritdoc CatalogApi.getEntityFacets}\n */\n async getEntityFacets(\n request: GetEntityFacetsRequest,\n options?: CatalogRequestOptions,\n ): Promise<GetEntityFacetsResponse> {\n const { filter = [], facets } = request;\n return await this.requestOptional(\n await this.apiClient.getEntityFacets(\n {\n query: { facet: facets, filter: this.getFilterValue(filter) },\n },\n options,\n ),\n );\n }\n\n /**\n * {@inheritdoc CatalogApi.addLocation}\n */\n async addLocation(\n request: AddLocationRequest,\n options?: CatalogRequestOptions,\n ): Promise<AddLocationResponse> {\n const { type = 'url', target, dryRun } = request;\n\n const response = await this.apiClient.createLocation(\n {\n body: { type, target },\n query: { dryRun: dryRun ? 'true' : undefined },\n },\n options,\n );\n\n if (response.status !== 201) {\n throw new Error(await response.text());\n }\n\n const { location, entities, exists } = await response.json();\n\n if (!location) {\n throw new Error(`Location wasn't added: ${target}`);\n }\n\n return {\n location,\n entities,\n exists,\n };\n }\n\n /**\n * {@inheritdoc CatalogApi.getLocationByRef}\n */\n async getLocationByRef(\n locationRef: string,\n options?: CatalogRequestOptions,\n ): Promise<Location | undefined> {\n const all = await this.requestRequired(\n await this.apiClient.getLocations({}, options),\n );\n return all\n .map(r => r.data)\n .find(l => locationRef === stringifyLocationRef(l));\n }\n\n /**\n * {@inheritdoc CatalogApi.removeLocationById}\n */\n async removeLocationById(\n id: string,\n options?: CatalogRequestOptions,\n ): Promise<void> {\n await this.requestIgnored(\n await this.apiClient.deleteLocation({ path: { id } }, options),\n );\n }\n\n /**\n * {@inheritdoc CatalogApi.removeEntityByUid}\n */\n async removeEntityByUid(\n uid: string,\n options?: CatalogRequestOptions,\n ): Promise<void> {\n await this.requestIgnored(\n await this.apiClient.deleteEntityByUid({ path: { uid } }, options),\n );\n }\n\n /**\n * {@inheritdoc CatalogApi.validateEntity}\n */\n async validateEntity(\n entity: Entity,\n locationRef: string,\n options?: CatalogRequestOptions,\n ): Promise<ValidateEntityResponse> {\n const response = await this.apiClient.validateEntity(\n { body: { entity, location: locationRef } },\n options,\n );\n\n if (response.ok) {\n return {\n valid: true,\n };\n }\n\n if (response.status !== 400) {\n throw await ResponseError.fromResponse(response);\n }\n\n const { errors = [] } = (await response.json()) as any;\n\n return {\n valid: false,\n errors,\n };\n }\n\n //\n // Private methods\n //\n\n private async requestIgnored(response: Response): Promise<void> {\n if (!response.ok) {\n throw await ResponseError.fromResponse(response);\n }\n }\n\n private async requestRequired<T>(response: TypedResponse<T>): Promise<T> {\n if (!response.ok) {\n throw await ResponseError.fromResponse(response);\n }\n\n return response.json();\n }\n\n private async requestOptional(response: Response): Promise<any | undefined> {\n if (!response.ok) {\n if (response.status === 404) {\n return undefined;\n }\n throw await ResponseError.fromResponse(response);\n }\n\n return await response.json();\n }\n\n private getFilterValue(filter: EntityFilterQuery = []) {\n const filters: string[] = [];\n // filter param can occur multiple times, for example\n // /api/catalog/entities?filter=metadata.name=wayback-search,kind=component&filter=metadata.name=www-artist,kind=component'\n // the \"outer array\" defined by `filter` occurrences corresponds to \"anyOf\" filters\n // the \"inner array\" defined within a `filter` param corresponds to \"allOf\" filters\n for (const filterItem of [filter].flat()) {\n const filterParts: string[] = [];\n for (const [key, value] of Object.entries(filterItem)) {\n for (const v of [value].flat()) {\n if (v === CATALOG_FILTER_EXISTS) {\n filterParts.push(key);\n } else if (typeof v === 'string') {\n filterParts.push(`${key}=${v}`);\n }\n }\n }\n\n if (filterParts.length) {\n filters.push(filterParts.join(','));\n }\n }\n return filters;\n }\n}\n"],"names":["DefaultApiClient","parseEntityRef","ResponseError","splitRefsIntoChunks","isQueryEntitiesInitialRequest","stringifyLocationRef","errors","CATALOG_FILTER_EXISTS"],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { parseEntityRef, stringifyLocationRef } from '@backstage/catalog-model';
|
|
2
2
|
import { ResponseError } from '@backstage/errors';
|
|
3
3
|
import { CATALOG_FILTER_EXISTS } from './types/api.esm.js';
|
|
4
|
-
import { isQueryEntitiesInitialRequest } from './utils.esm.js';
|
|
4
|
+
import { splitRefsIntoChunks, isQueryEntitiesInitialRequest } from './utils.esm.js';
|
|
5
5
|
import { DefaultApiClient } from './generated/apis/DefaultApi.client.esm.js';
|
|
6
6
|
|
|
7
7
|
class CatalogClient {
|
|
@@ -80,23 +80,30 @@ class CatalogClient {
|
|
|
80
80
|
* {@inheritdoc CatalogApi.getEntitiesByRefs}
|
|
81
81
|
*/
|
|
82
82
|
async getEntitiesByRefs(request, options) {
|
|
83
|
-
const
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
entityRefs: request.
|
|
87
|
-
|
|
83
|
+
const getOneChunk = async (refs) => {
|
|
84
|
+
const response = await this.apiClient.getEntitiesByRefs(
|
|
85
|
+
{
|
|
86
|
+
body: { entityRefs: refs, fields: request.fields },
|
|
87
|
+
query: { filter: this.getFilterValue(request.filter) }
|
|
88
88
|
},
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
89
|
+
options
|
|
90
|
+
);
|
|
91
|
+
if (!response.ok) {
|
|
92
|
+
throw await ResponseError.fromResponse(response);
|
|
93
|
+
}
|
|
94
|
+
const body = await response.json();
|
|
95
|
+
return body.items.map((i) => i ?? void 0);
|
|
96
|
+
};
|
|
97
|
+
let result;
|
|
98
|
+
for (const refs of splitRefsIntoChunks(request.entityRefs)) {
|
|
99
|
+
const entities = await getOneChunk(refs);
|
|
100
|
+
if (!result) {
|
|
101
|
+
result = entities;
|
|
102
|
+
} else {
|
|
103
|
+
result.push(...entities);
|
|
104
|
+
}
|
|
97
105
|
}
|
|
98
|
-
|
|
99
|
-
return { items: items.map((i) => i ?? void 0) };
|
|
106
|
+
return { items: result ?? [] };
|
|
100
107
|
}
|
|
101
108
|
/**
|
|
102
109
|
* {@inheritdoc CatalogApi.queryEntities}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CatalogClient.esm.js","sources":["../src/CatalogClient.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 {\n CompoundEntityRef,\n Entity,\n parseEntityRef,\n stringifyLocationRef,\n} from '@backstage/catalog-model';\nimport { ResponseError } from '@backstage/errors';\nimport {\n AddLocationRequest,\n AddLocationResponse,\n CATALOG_FILTER_EXISTS,\n CatalogApi,\n CatalogRequestOptions,\n EntityFilterQuery,\n GetEntitiesByRefsRequest,\n GetEntitiesByRefsResponse,\n GetEntitiesRequest,\n GetEntitiesResponse,\n GetEntityAncestorsRequest,\n GetEntityAncestorsResponse,\n GetEntityFacetsRequest,\n GetEntityFacetsResponse,\n Location,\n QueryEntitiesRequest,\n QueryEntitiesResponse,\n ValidateEntityResponse,\n} from './types/api';\nimport { isQueryEntitiesInitialRequest } from './utils';\nimport { DefaultApiClient, TypedResponse } from './generated';\n\n/**\n * A frontend and backend compatible client for communicating with the Backstage\n * software catalog.\n *\n * @public\n */\nexport class CatalogClient implements CatalogApi {\n private readonly apiClient: DefaultApiClient;\n\n constructor(options: {\n discoveryApi: { getBaseUrl(pluginId: string): Promise<string> };\n fetchApi?: { fetch: typeof fetch };\n }) {\n this.apiClient = new DefaultApiClient(options);\n }\n\n /**\n * {@inheritdoc CatalogApi.getEntityAncestors}\n */\n async getEntityAncestors(\n request: GetEntityAncestorsRequest,\n options?: CatalogRequestOptions,\n ): Promise<GetEntityAncestorsResponse> {\n return await this.requestRequired(\n await this.apiClient.getEntityAncestryByName(\n { path: parseEntityRef(request.entityRef) },\n options,\n ),\n );\n }\n\n /**\n * {@inheritdoc CatalogApi.getLocationById}\n */\n async getLocationById(\n id: string,\n options?: CatalogRequestOptions,\n ): Promise<Location | undefined> {\n return await this.requestOptional(\n await this.apiClient.getLocation({ path: { id } }, options),\n );\n }\n\n /**\n * {@inheritdoc CatalogApi.getLocationByEntity}\n */\n async getLocationByEntity(\n entityRef: CompoundEntityRef | string,\n options?: CatalogRequestOptions,\n ): Promise<Location | undefined> {\n return await this.requestOptional(\n await this.apiClient.getLocationByEntity(\n { path: parseEntityRef(entityRef) },\n options,\n ),\n );\n }\n\n /**\n * {@inheritdoc CatalogApi.getEntities}\n */\n async getEntities(\n request?: GetEntitiesRequest,\n options?: CatalogRequestOptions,\n ): Promise<GetEntitiesResponse> {\n const {\n filter = [],\n fields = [],\n order,\n offset,\n limit,\n after,\n } = request ?? {};\n const encodedOrder = [];\n if (order) {\n for (const directive of [order].flat()) {\n if (directive) {\n encodedOrder.push(`${directive.order}:${directive.field}`);\n }\n }\n }\n\n const entities = await this.requestRequired(\n await this.apiClient.getEntities(\n {\n query: {\n fields,\n limit,\n filter: this.getFilterValue(filter),\n offset,\n after,\n order: order ? encodedOrder : undefined,\n },\n },\n options,\n ),\n );\n return { items: entities };\n }\n\n /**\n * {@inheritdoc CatalogApi.getEntitiesByRefs}\n */\n async getEntitiesByRefs(\n request: GetEntitiesByRefsRequest,\n options?: CatalogRequestOptions,\n ): Promise<GetEntitiesByRefsResponse> {\n const response = await this.apiClient.getEntitiesByRefs(\n {\n body: {\n entityRefs: request.entityRefs,\n fields: request.fields,\n },\n query: {\n filter: this.getFilterValue(request.filter),\n },\n },\n options,\n );\n\n if (!response.ok) {\n throw await ResponseError.fromResponse(response);\n }\n\n const { items } = (await response.json()) as {\n items: Array<Entity | null>;\n };\n\n return { items: items.map(i => i ?? undefined) };\n }\n\n /**\n * {@inheritdoc CatalogApi.queryEntities}\n */\n async queryEntities(\n request: QueryEntitiesRequest = {},\n options?: CatalogRequestOptions,\n ): Promise<QueryEntitiesResponse> {\n const params: Partial<\n Parameters<typeof this.apiClient.getEntitiesByQuery>[0]['query']\n > = {};\n\n if (isQueryEntitiesInitialRequest(request)) {\n const {\n fields = [],\n filter,\n limit,\n offset,\n orderFields,\n fullTextFilter,\n } = request;\n params.filter = this.getFilterValue(filter);\n\n if (limit !== undefined) {\n params.limit = limit;\n }\n if (offset !== undefined) {\n params.offset = offset;\n }\n if (orderFields !== undefined) {\n params.orderField = (\n Array.isArray(orderFields) ? orderFields : [orderFields]\n ).map(({ field, order }) => `${field},${order}`);\n }\n if (fields.length) {\n params.fields = fields;\n }\n\n const normalizedFullTextFilterTerm = fullTextFilter?.term?.trim();\n if (normalizedFullTextFilterTerm) {\n params.fullTextFilterTerm = normalizedFullTextFilterTerm;\n }\n if (fullTextFilter?.fields?.length) {\n params.fullTextFilterFields = fullTextFilter.fields;\n }\n } else {\n const { fields = [], limit, cursor } = request;\n\n params.cursor = cursor;\n if (limit !== undefined) {\n params.limit = limit;\n }\n if (fields.length) {\n params.fields = fields;\n }\n }\n\n return this.apiClient\n .getEntitiesByQuery({ query: params }, options)\n .then(r => r.json());\n }\n\n /**\n * {@inheritdoc CatalogApi.getEntityByRef}\n */\n async getEntityByRef(\n entityRef: string | CompoundEntityRef,\n options?: CatalogRequestOptions,\n ): Promise<Entity | undefined> {\n return this.requestOptional(\n await this.apiClient.getEntityByName(\n {\n path: parseEntityRef(entityRef),\n },\n options,\n ),\n );\n }\n\n // NOTE(freben): When we deprecate getEntityByName from the interface, we may\n // still want to leave this implementation in place for quite some time\n // longer, to minimize the risk for breakages. Suggested date for removal:\n // August 2022\n /**\n * @deprecated Use getEntityByRef instead\n */\n async getEntityByName(\n compoundName: CompoundEntityRef,\n options?: CatalogRequestOptions,\n ): Promise<Entity | undefined> {\n const { kind, namespace = 'default', name } = compoundName;\n return this.requestOptional(\n await this.apiClient.getEntityByName(\n { path: { kind, namespace, name } },\n options,\n ),\n );\n }\n\n /**\n * {@inheritdoc CatalogApi.refreshEntity}\n */\n async refreshEntity(entityRef: string, options?: CatalogRequestOptions) {\n const response = await this.apiClient.refreshEntity(\n { body: { entityRef } },\n options,\n );\n\n if (response.status !== 200) {\n throw new Error(await response.text());\n }\n }\n\n /**\n * {@inheritdoc CatalogApi.getEntityFacets}\n */\n async getEntityFacets(\n request: GetEntityFacetsRequest,\n options?: CatalogRequestOptions,\n ): Promise<GetEntityFacetsResponse> {\n const { filter = [], facets } = request;\n return await this.requestOptional(\n await this.apiClient.getEntityFacets(\n {\n query: { facet: facets, filter: this.getFilterValue(filter) },\n },\n options,\n ),\n );\n }\n\n /**\n * {@inheritdoc CatalogApi.addLocation}\n */\n async addLocation(\n request: AddLocationRequest,\n options?: CatalogRequestOptions,\n ): Promise<AddLocationResponse> {\n const { type = 'url', target, dryRun } = request;\n\n const response = await this.apiClient.createLocation(\n {\n body: { type, target },\n query: { dryRun: dryRun ? 'true' : undefined },\n },\n options,\n );\n\n if (response.status !== 201) {\n throw new Error(await response.text());\n }\n\n const { location, entities, exists } = await response.json();\n\n if (!location) {\n throw new Error(`Location wasn't added: ${target}`);\n }\n\n return {\n location,\n entities,\n exists,\n };\n }\n\n /**\n * {@inheritdoc CatalogApi.getLocationByRef}\n */\n async getLocationByRef(\n locationRef: string,\n options?: CatalogRequestOptions,\n ): Promise<Location | undefined> {\n const all = await this.requestRequired(\n await this.apiClient.getLocations({}, options),\n );\n return all\n .map(r => r.data)\n .find(l => locationRef === stringifyLocationRef(l));\n }\n\n /**\n * {@inheritdoc CatalogApi.removeLocationById}\n */\n async removeLocationById(\n id: string,\n options?: CatalogRequestOptions,\n ): Promise<void> {\n await this.requestIgnored(\n await this.apiClient.deleteLocation({ path: { id } }, options),\n );\n }\n\n /**\n * {@inheritdoc CatalogApi.removeEntityByUid}\n */\n async removeEntityByUid(\n uid: string,\n options?: CatalogRequestOptions,\n ): Promise<void> {\n await this.requestIgnored(\n await this.apiClient.deleteEntityByUid({ path: { uid } }, options),\n );\n }\n\n /**\n * {@inheritdoc CatalogApi.validateEntity}\n */\n async validateEntity(\n entity: Entity,\n locationRef: string,\n options?: CatalogRequestOptions,\n ): Promise<ValidateEntityResponse> {\n const response = await this.apiClient.validateEntity(\n { body: { entity, location: locationRef } },\n options,\n );\n\n if (response.ok) {\n return {\n valid: true,\n };\n }\n\n if (response.status !== 400) {\n throw await ResponseError.fromResponse(response);\n }\n\n const { errors = [] } = (await response.json()) as any;\n\n return {\n valid: false,\n errors,\n };\n }\n\n //\n // Private methods\n //\n\n private async requestIgnored(response: Response): Promise<void> {\n if (!response.ok) {\n throw await ResponseError.fromResponse(response);\n }\n }\n\n private async requestRequired<T>(response: TypedResponse<T>): Promise<T> {\n if (!response.ok) {\n throw await ResponseError.fromResponse(response);\n }\n\n return response.json();\n }\n\n private async requestOptional(response: Response): Promise<any | undefined> {\n if (!response.ok) {\n if (response.status === 404) {\n return undefined;\n }\n throw await ResponseError.fromResponse(response);\n }\n\n return await response.json();\n }\n\n private getFilterValue(filter: EntityFilterQuery = []) {\n const filters: string[] = [];\n // filter param can occur multiple times, for example\n // /api/catalog/entities?filter=metadata.name=wayback-search,kind=component&filter=metadata.name=www-artist,kind=component'\n // the \"outer array\" defined by `filter` occurrences corresponds to \"anyOf\" filters\n // the \"inner array\" defined within a `filter` param corresponds to \"allOf\" filters\n for (const filterItem of [filter].flat()) {\n const filterParts: string[] = [];\n for (const [key, value] of Object.entries(filterItem)) {\n for (const v of [value].flat()) {\n if (v === CATALOG_FILTER_EXISTS) {\n filterParts.push(key);\n } else if (typeof v === 'string') {\n filterParts.push(`${key}=${v}`);\n }\n }\n }\n\n if (filterParts.length) {\n filters.push(filterParts.join(','));\n }\n }\n return filters;\n }\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"CatalogClient.esm.js","sources":["../src/CatalogClient.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 {\n CompoundEntityRef,\n Entity,\n parseEntityRef,\n stringifyLocationRef,\n} from '@backstage/catalog-model';\nimport { ResponseError } from '@backstage/errors';\nimport {\n AddLocationRequest,\n AddLocationResponse,\n CATALOG_FILTER_EXISTS,\n CatalogApi,\n CatalogRequestOptions,\n EntityFilterQuery,\n GetEntitiesByRefsRequest,\n GetEntitiesByRefsResponse,\n GetEntitiesRequest,\n GetEntitiesResponse,\n GetEntityAncestorsRequest,\n GetEntityAncestorsResponse,\n GetEntityFacetsRequest,\n GetEntityFacetsResponse,\n Location,\n QueryEntitiesRequest,\n QueryEntitiesResponse,\n ValidateEntityResponse,\n} from './types/api';\nimport { isQueryEntitiesInitialRequest, splitRefsIntoChunks } from './utils';\nimport { DefaultApiClient, TypedResponse } from './generated';\n\n/**\n * A frontend and backend compatible client for communicating with the Backstage\n * software catalog.\n *\n * @public\n */\nexport class CatalogClient implements CatalogApi {\n private readonly apiClient: DefaultApiClient;\n\n constructor(options: {\n discoveryApi: { getBaseUrl(pluginId: string): Promise<string> };\n fetchApi?: { fetch: typeof fetch };\n }) {\n this.apiClient = new DefaultApiClient(options);\n }\n\n /**\n * {@inheritdoc CatalogApi.getEntityAncestors}\n */\n async getEntityAncestors(\n request: GetEntityAncestorsRequest,\n options?: CatalogRequestOptions,\n ): Promise<GetEntityAncestorsResponse> {\n return await this.requestRequired(\n await this.apiClient.getEntityAncestryByName(\n { path: parseEntityRef(request.entityRef) },\n options,\n ),\n );\n }\n\n /**\n * {@inheritdoc CatalogApi.getLocationById}\n */\n async getLocationById(\n id: string,\n options?: CatalogRequestOptions,\n ): Promise<Location | undefined> {\n return await this.requestOptional(\n await this.apiClient.getLocation({ path: { id } }, options),\n );\n }\n\n /**\n * {@inheritdoc CatalogApi.getLocationByEntity}\n */\n async getLocationByEntity(\n entityRef: CompoundEntityRef | string,\n options?: CatalogRequestOptions,\n ): Promise<Location | undefined> {\n return await this.requestOptional(\n await this.apiClient.getLocationByEntity(\n { path: parseEntityRef(entityRef) },\n options,\n ),\n );\n }\n\n /**\n * {@inheritdoc CatalogApi.getEntities}\n */\n async getEntities(\n request?: GetEntitiesRequest,\n options?: CatalogRequestOptions,\n ): Promise<GetEntitiesResponse> {\n const {\n filter = [],\n fields = [],\n order,\n offset,\n limit,\n after,\n } = request ?? {};\n const encodedOrder = [];\n if (order) {\n for (const directive of [order].flat()) {\n if (directive) {\n encodedOrder.push(`${directive.order}:${directive.field}`);\n }\n }\n }\n\n const entities = await this.requestRequired(\n await this.apiClient.getEntities(\n {\n query: {\n fields,\n limit,\n filter: this.getFilterValue(filter),\n offset,\n after,\n order: order ? encodedOrder : undefined,\n },\n },\n options,\n ),\n );\n return { items: entities };\n }\n\n /**\n * {@inheritdoc CatalogApi.getEntitiesByRefs}\n */\n async getEntitiesByRefs(\n request: GetEntitiesByRefsRequest,\n options?: CatalogRequestOptions,\n ): Promise<GetEntitiesByRefsResponse> {\n const getOneChunk = async (refs: string[]) => {\n const response = await this.apiClient.getEntitiesByRefs(\n {\n body: { entityRefs: refs, fields: request.fields },\n query: { filter: this.getFilterValue(request.filter) },\n },\n options,\n );\n if (!response.ok) {\n throw await ResponseError.fromResponse(response);\n }\n const body = (await response.json()) as {\n items: Array<Entity | null>;\n };\n return body.items.map(i => i ?? undefined);\n };\n\n let result: Array<Entity | undefined> | undefined;\n for (const refs of splitRefsIntoChunks(request.entityRefs)) {\n const entities = await getOneChunk(refs);\n if (!result) {\n result = entities;\n } else {\n result.push(...entities);\n }\n }\n\n return { items: result ?? [] };\n }\n\n /**\n * {@inheritdoc CatalogApi.queryEntities}\n */\n async queryEntities(\n request: QueryEntitiesRequest = {},\n options?: CatalogRequestOptions,\n ): Promise<QueryEntitiesResponse> {\n const params: Partial<\n Parameters<typeof this.apiClient.getEntitiesByQuery>[0]['query']\n > = {};\n\n if (isQueryEntitiesInitialRequest(request)) {\n const {\n fields = [],\n filter,\n limit,\n offset,\n orderFields,\n fullTextFilter,\n } = request;\n params.filter = this.getFilterValue(filter);\n\n if (limit !== undefined) {\n params.limit = limit;\n }\n if (offset !== undefined) {\n params.offset = offset;\n }\n if (orderFields !== undefined) {\n params.orderField = (\n Array.isArray(orderFields) ? orderFields : [orderFields]\n ).map(({ field, order }) => `${field},${order}`);\n }\n if (fields.length) {\n params.fields = fields;\n }\n\n const normalizedFullTextFilterTerm = fullTextFilter?.term?.trim();\n if (normalizedFullTextFilterTerm) {\n params.fullTextFilterTerm = normalizedFullTextFilterTerm;\n }\n if (fullTextFilter?.fields?.length) {\n params.fullTextFilterFields = fullTextFilter.fields;\n }\n } else {\n const { fields = [], limit, cursor } = request;\n\n params.cursor = cursor;\n if (limit !== undefined) {\n params.limit = limit;\n }\n if (fields.length) {\n params.fields = fields;\n }\n }\n\n return this.apiClient\n .getEntitiesByQuery({ query: params }, options)\n .then(r => r.json());\n }\n\n /**\n * {@inheritdoc CatalogApi.getEntityByRef}\n */\n async getEntityByRef(\n entityRef: string | CompoundEntityRef,\n options?: CatalogRequestOptions,\n ): Promise<Entity | undefined> {\n return this.requestOptional(\n await this.apiClient.getEntityByName(\n {\n path: parseEntityRef(entityRef),\n },\n options,\n ),\n );\n }\n\n // NOTE(freben): When we deprecate getEntityByName from the interface, we may\n // still want to leave this implementation in place for quite some time\n // longer, to minimize the risk for breakages. Suggested date for removal:\n // August 2022\n /**\n * @deprecated Use getEntityByRef instead\n */\n async getEntityByName(\n compoundName: CompoundEntityRef,\n options?: CatalogRequestOptions,\n ): Promise<Entity | undefined> {\n const { kind, namespace = 'default', name } = compoundName;\n return this.requestOptional(\n await this.apiClient.getEntityByName(\n { path: { kind, namespace, name } },\n options,\n ),\n );\n }\n\n /**\n * {@inheritdoc CatalogApi.refreshEntity}\n */\n async refreshEntity(entityRef: string, options?: CatalogRequestOptions) {\n const response = await this.apiClient.refreshEntity(\n { body: { entityRef } },\n options,\n );\n\n if (response.status !== 200) {\n throw new Error(await response.text());\n }\n }\n\n /**\n * {@inheritdoc CatalogApi.getEntityFacets}\n */\n async getEntityFacets(\n request: GetEntityFacetsRequest,\n options?: CatalogRequestOptions,\n ): Promise<GetEntityFacetsResponse> {\n const { filter = [], facets } = request;\n return await this.requestOptional(\n await this.apiClient.getEntityFacets(\n {\n query: { facet: facets, filter: this.getFilterValue(filter) },\n },\n options,\n ),\n );\n }\n\n /**\n * {@inheritdoc CatalogApi.addLocation}\n */\n async addLocation(\n request: AddLocationRequest,\n options?: CatalogRequestOptions,\n ): Promise<AddLocationResponse> {\n const { type = 'url', target, dryRun } = request;\n\n const response = await this.apiClient.createLocation(\n {\n body: { type, target },\n query: { dryRun: dryRun ? 'true' : undefined },\n },\n options,\n );\n\n if (response.status !== 201) {\n throw new Error(await response.text());\n }\n\n const { location, entities, exists } = await response.json();\n\n if (!location) {\n throw new Error(`Location wasn't added: ${target}`);\n }\n\n return {\n location,\n entities,\n exists,\n };\n }\n\n /**\n * {@inheritdoc CatalogApi.getLocationByRef}\n */\n async getLocationByRef(\n locationRef: string,\n options?: CatalogRequestOptions,\n ): Promise<Location | undefined> {\n const all = await this.requestRequired(\n await this.apiClient.getLocations({}, options),\n );\n return all\n .map(r => r.data)\n .find(l => locationRef === stringifyLocationRef(l));\n }\n\n /**\n * {@inheritdoc CatalogApi.removeLocationById}\n */\n async removeLocationById(\n id: string,\n options?: CatalogRequestOptions,\n ): Promise<void> {\n await this.requestIgnored(\n await this.apiClient.deleteLocation({ path: { id } }, options),\n );\n }\n\n /**\n * {@inheritdoc CatalogApi.removeEntityByUid}\n */\n async removeEntityByUid(\n uid: string,\n options?: CatalogRequestOptions,\n ): Promise<void> {\n await this.requestIgnored(\n await this.apiClient.deleteEntityByUid({ path: { uid } }, options),\n );\n }\n\n /**\n * {@inheritdoc CatalogApi.validateEntity}\n */\n async validateEntity(\n entity: Entity,\n locationRef: string,\n options?: CatalogRequestOptions,\n ): Promise<ValidateEntityResponse> {\n const response = await this.apiClient.validateEntity(\n { body: { entity, location: locationRef } },\n options,\n );\n\n if (response.ok) {\n return {\n valid: true,\n };\n }\n\n if (response.status !== 400) {\n throw await ResponseError.fromResponse(response);\n }\n\n const { errors = [] } = (await response.json()) as any;\n\n return {\n valid: false,\n errors,\n };\n }\n\n //\n // Private methods\n //\n\n private async requestIgnored(response: Response): Promise<void> {\n if (!response.ok) {\n throw await ResponseError.fromResponse(response);\n }\n }\n\n private async requestRequired<T>(response: TypedResponse<T>): Promise<T> {\n if (!response.ok) {\n throw await ResponseError.fromResponse(response);\n }\n\n return response.json();\n }\n\n private async requestOptional(response: Response): Promise<any | undefined> {\n if (!response.ok) {\n if (response.status === 404) {\n return undefined;\n }\n throw await ResponseError.fromResponse(response);\n }\n\n return await response.json();\n }\n\n private getFilterValue(filter: EntityFilterQuery = []) {\n const filters: string[] = [];\n // filter param can occur multiple times, for example\n // /api/catalog/entities?filter=metadata.name=wayback-search,kind=component&filter=metadata.name=www-artist,kind=component'\n // the \"outer array\" defined by `filter` occurrences corresponds to \"anyOf\" filters\n // the \"inner array\" defined within a `filter` param corresponds to \"allOf\" filters\n for (const filterItem of [filter].flat()) {\n const filterParts: string[] = [];\n for (const [key, value] of Object.entries(filterItem)) {\n for (const v of [value].flat()) {\n if (v === CATALOG_FILTER_EXISTS) {\n filterParts.push(key);\n } else if (typeof v === 'string') {\n filterParts.push(`${key}=${v}`);\n }\n }\n }\n\n if (filterParts.length) {\n filters.push(filterParts.join(','));\n }\n }\n return filters;\n }\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -8,21 +8,30 @@ var buildEntitySearch$1 = require('../plugins/catalog-backend/src/database/opera
|
|
|
8
8
|
function buildEntitySearch(entity) {
|
|
9
9
|
const rows = buildEntitySearch$1.traverse(entity);
|
|
10
10
|
if (entity.metadata?.name) {
|
|
11
|
-
rows.push({
|
|
11
|
+
rows.push({
|
|
12
|
+
key: "metadata.name",
|
|
13
|
+
value: entity.metadata.name.toLocaleLowerCase("en-US")
|
|
14
|
+
});
|
|
12
15
|
}
|
|
13
16
|
if (entity.metadata?.namespace) {
|
|
14
|
-
rows.push({
|
|
17
|
+
rows.push({
|
|
18
|
+
key: "metadata.namespace",
|
|
19
|
+
value: entity.metadata.namespace.toLocaleLowerCase("en-US")
|
|
20
|
+
});
|
|
15
21
|
}
|
|
16
22
|
if (entity.metadata?.uid) {
|
|
17
|
-
rows.push({
|
|
23
|
+
rows.push({
|
|
24
|
+
key: "metadata.uid",
|
|
25
|
+
value: entity.metadata.uid.toLocaleLowerCase("en-US")
|
|
26
|
+
});
|
|
18
27
|
}
|
|
19
28
|
if (!entity.metadata.namespace) {
|
|
20
29
|
rows.push({ key: "metadata.namespace", value: catalogModel.DEFAULT_NAMESPACE });
|
|
21
30
|
}
|
|
22
31
|
for (const relation of entity.relations ?? []) {
|
|
23
32
|
rows.push({
|
|
24
|
-
key: `relations.${relation.type}`,
|
|
25
|
-
value: relation.targetRef
|
|
33
|
+
key: `relations.${relation.type.toLocaleLowerCase("en-US")}`,
|
|
34
|
+
value: relation.targetRef.toLocaleLowerCase("en-US")
|
|
26
35
|
});
|
|
27
36
|
}
|
|
28
37
|
return rows;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InMemoryCatalogClient.cjs.js","sources":["../../src/testUtils/InMemoryCatalogClient.ts"],"sourcesContent":["/*\n * Copyright 2024 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 AddLocationRequest,\n AddLocationResponse,\n CATALOG_FILTER_EXISTS,\n CatalogApi,\n EntityFilterQuery,\n GetEntitiesByRefsRequest,\n GetEntitiesByRefsResponse,\n GetEntitiesRequest,\n GetEntitiesResponse,\n GetEntityAncestorsRequest,\n GetEntityAncestorsResponse,\n GetEntityFacetsRequest,\n GetEntityFacetsResponse,\n Location,\n QueryEntitiesRequest,\n QueryEntitiesResponse,\n ValidateEntityResponse,\n} from '@backstage/catalog-client';\nimport {\n CompoundEntityRef,\n DEFAULT_NAMESPACE,\n Entity,\n parseEntityRef,\n stringifyEntityRef,\n} from '@backstage/catalog-model';\nimport { NotFoundError, NotImplementedError } from '@backstage/errors';\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport { traverse } from '../../../../plugins/catalog-backend/src/database/operations/stitcher/buildEntitySearch';\n\nfunction buildEntitySearch(entity: Entity) {\n const rows = traverse(entity);\n\n if (entity.metadata?.name) {\n rows.push({ key: 'metadata.name', value: entity.metadata.name });\n }\n if (entity.metadata?.namespace) {\n rows.push({ key: 'metadata.namespace', value: entity.metadata.namespace });\n }\n if (entity.metadata?.uid) {\n rows.push({ key: 'metadata.uid', value: entity.metadata.uid });\n }\n\n if (!entity.metadata.namespace) {\n rows.push({ key: 'metadata.namespace', value: DEFAULT_NAMESPACE });\n }\n\n // Visit relations\n for (const relation of entity.relations ?? []) {\n rows.push({\n key: `relations.${relation.type}`,\n value: relation.targetRef,\n });\n }\n\n return rows;\n}\n\nfunction createFilter(\n filterOrFilters?: EntityFilterQuery,\n): (entity: Entity) => boolean {\n if (!filterOrFilters) {\n return () => true;\n }\n\n const filters = [filterOrFilters].flat();\n\n return entity => {\n const rows = buildEntitySearch(entity);\n\n return filters.some(filter => {\n for (const [key, expectedValue] of Object.entries(filter)) {\n const searchValues = rows\n .filter(row => row.key === key.toLocaleLowerCase('en-US'))\n .map(row => row.value?.toString().toLocaleLowerCase('en-US'));\n\n if (searchValues.length === 0) {\n return false;\n }\n if (expectedValue === CATALOG_FILTER_EXISTS) {\n continue;\n }\n if (\n !searchValues?.includes(\n String(expectedValue).toLocaleLowerCase('en-US'),\n )\n ) {\n return false;\n }\n }\n return true;\n });\n };\n}\n\n/**\n * Implements a VERY basic fake catalog client that stores entities in memory.\n * It has severely limited functionality, and is only useful under certain\n * circumstances in tests.\n *\n * @public\n */\nexport class InMemoryCatalogClient implements CatalogApi {\n #entities: Entity[];\n\n constructor(options?: { entities?: Entity[] }) {\n this.#entities = options?.entities?.slice() ?? [];\n }\n\n async getEntities(\n request?: GetEntitiesRequest,\n ): Promise<GetEntitiesResponse> {\n const filter = createFilter(request?.filter);\n return { items: this.#entities.filter(filter) };\n }\n\n async getEntitiesByRefs(\n request: GetEntitiesByRefsRequest,\n ): Promise<GetEntitiesByRefsResponse> {\n const filter = createFilter(request.filter);\n const refMap = this.#createEntityRefMap();\n return {\n items: request.entityRefs\n .map(ref => refMap.get(ref))\n .map(e => (e && filter(e) ? e : undefined)),\n };\n }\n\n async queryEntities(\n request?: QueryEntitiesRequest,\n ): Promise<QueryEntitiesResponse> {\n if (request && 'cursor' in request) {\n return { items: [], pageInfo: {}, totalItems: 0 };\n }\n const filter = createFilter(request?.filter);\n const items = this.#entities.filter(filter);\n // TODO(Rugvip): Pagination\n return {\n items,\n pageInfo: {},\n totalItems: items.length,\n };\n }\n\n async getEntityAncestors(\n request: GetEntityAncestorsRequest,\n ): Promise<GetEntityAncestorsResponse> {\n const entity = this.#createEntityRefMap().get(request.entityRef);\n if (!entity) {\n throw new NotFoundError(`Entity with ref ${request.entityRef} not found`);\n }\n return {\n items: [{ entity, parentEntityRefs: [] }],\n rootEntityRef: request.entityRef,\n };\n }\n\n async getEntityByRef(\n entityRef: string | CompoundEntityRef,\n ): Promise<Entity | undefined> {\n return this.#createEntityRefMap().get(\n stringifyEntityRef(parseEntityRef(entityRef)),\n );\n }\n\n async removeEntityByUid(uid: string): Promise<void> {\n const index = this.#entities.findIndex(e => e.metadata.uid === uid);\n if (index !== -1) {\n this.#entities.splice(index, 1);\n }\n }\n\n async refreshEntity(_entityRef: string): Promise<void> {}\n\n async getEntityFacets(\n request: GetEntityFacetsRequest,\n ): Promise<GetEntityFacetsResponse> {\n const filter = createFilter(request.filter);\n const filteredEntities = this.#entities.filter(filter);\n const facets = Object.fromEntries(\n request.facets.map(facet => {\n const facetValues = new Map<string, number>();\n for (const entity of filteredEntities) {\n const rows = buildEntitySearch(entity);\n const value = rows.find(\n row => row.key === facet.toLocaleLowerCase('en-US'),\n )?.value;\n if (value) {\n facetValues.set(\n String(value),\n (facetValues.get(String(value)) ?? 0) + 1,\n );\n }\n }\n const counts = Array.from(facetValues.entries()).map(\n ([value, count]) => ({ value, count }),\n );\n return [facet, counts];\n }),\n );\n return {\n facets,\n };\n }\n\n async getLocationById(_id: string): Promise<Location | undefined> {\n throw new NotImplementedError('Method not implemented.');\n }\n\n async getLocationByRef(_locationRef: string): Promise<Location | undefined> {\n throw new NotImplementedError('Method not implemented.');\n }\n\n async addLocation(\n _location: AddLocationRequest,\n ): Promise<AddLocationResponse> {\n throw new NotImplementedError('Method not implemented.');\n }\n\n async removeLocationById(_id: string): Promise<void> {\n throw new NotImplementedError('Method not implemented.');\n }\n\n async getLocationByEntity(\n _entityRef: string | CompoundEntityRef,\n ): Promise<Location | undefined> {\n throw new NotImplementedError('Method not implemented.');\n }\n\n async validateEntity(\n _entity: Entity,\n _locationRef: string,\n ): Promise<ValidateEntityResponse> {\n throw new NotImplementedError('Method not implemented.');\n }\n\n #createEntityRefMap() {\n return new Map(this.#entities.map(e => [stringifyEntityRef(e), e]));\n }\n}\n"],"names":["traverse","DEFAULT_NAMESPACE","CATALOG_FILTER_EXISTS","NotFoundError","stringifyEntityRef","parseEntityRef","NotImplementedError"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"InMemoryCatalogClient.cjs.js","sources":["../../src/testUtils/InMemoryCatalogClient.ts"],"sourcesContent":["/*\n * Copyright 2024 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 AddLocationRequest,\n AddLocationResponse,\n CATALOG_FILTER_EXISTS,\n CatalogApi,\n EntityFilterQuery,\n GetEntitiesByRefsRequest,\n GetEntitiesByRefsResponse,\n GetEntitiesRequest,\n GetEntitiesResponse,\n GetEntityAncestorsRequest,\n GetEntityAncestorsResponse,\n GetEntityFacetsRequest,\n GetEntityFacetsResponse,\n Location,\n QueryEntitiesRequest,\n QueryEntitiesResponse,\n ValidateEntityResponse,\n} from '@backstage/catalog-client';\nimport {\n CompoundEntityRef,\n DEFAULT_NAMESPACE,\n Entity,\n parseEntityRef,\n stringifyEntityRef,\n} from '@backstage/catalog-model';\nimport { NotFoundError, NotImplementedError } from '@backstage/errors';\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport { traverse } from '../../../../plugins/catalog-backend/src/database/operations/stitcher/buildEntitySearch';\n\nfunction buildEntitySearch(entity: Entity) {\n const rows = traverse(entity);\n\n if (entity.metadata?.name) {\n rows.push({\n key: 'metadata.name',\n value: entity.metadata.name.toLocaleLowerCase('en-US'),\n });\n }\n if (entity.metadata?.namespace) {\n rows.push({\n key: 'metadata.namespace',\n value: entity.metadata.namespace.toLocaleLowerCase('en-US'),\n });\n }\n if (entity.metadata?.uid) {\n rows.push({\n key: 'metadata.uid',\n value: entity.metadata.uid.toLocaleLowerCase('en-US'),\n });\n }\n\n if (!entity.metadata.namespace) {\n rows.push({ key: 'metadata.namespace', value: DEFAULT_NAMESPACE });\n }\n\n // Visit relations\n for (const relation of entity.relations ?? []) {\n rows.push({\n key: `relations.${relation.type.toLocaleLowerCase('en-US')}`,\n value: relation.targetRef.toLocaleLowerCase('en-US'),\n });\n }\n\n return rows;\n}\n\nfunction createFilter(\n filterOrFilters?: EntityFilterQuery,\n): (entity: Entity) => boolean {\n if (!filterOrFilters) {\n return () => true;\n }\n\n const filters = [filterOrFilters].flat();\n\n return entity => {\n const rows = buildEntitySearch(entity);\n\n return filters.some(filter => {\n for (const [key, expectedValue] of Object.entries(filter)) {\n const searchValues = rows\n .filter(row => row.key === key.toLocaleLowerCase('en-US'))\n .map(row => row.value?.toString().toLocaleLowerCase('en-US'));\n\n if (searchValues.length === 0) {\n return false;\n }\n if (expectedValue === CATALOG_FILTER_EXISTS) {\n continue;\n }\n if (\n !searchValues?.includes(\n String(expectedValue).toLocaleLowerCase('en-US'),\n )\n ) {\n return false;\n }\n }\n return true;\n });\n };\n}\n\n/**\n * Implements a VERY basic fake catalog client that stores entities in memory.\n * It has severely limited functionality, and is only useful under certain\n * circumstances in tests.\n *\n * @public\n */\nexport class InMemoryCatalogClient implements CatalogApi {\n #entities: Entity[];\n\n constructor(options?: { entities?: Entity[] }) {\n this.#entities = options?.entities?.slice() ?? [];\n }\n\n async getEntities(\n request?: GetEntitiesRequest,\n ): Promise<GetEntitiesResponse> {\n const filter = createFilter(request?.filter);\n return { items: this.#entities.filter(filter) };\n }\n\n async getEntitiesByRefs(\n request: GetEntitiesByRefsRequest,\n ): Promise<GetEntitiesByRefsResponse> {\n const filter = createFilter(request.filter);\n const refMap = this.#createEntityRefMap();\n return {\n items: request.entityRefs\n .map(ref => refMap.get(ref))\n .map(e => (e && filter(e) ? e : undefined)),\n };\n }\n\n async queryEntities(\n request?: QueryEntitiesRequest,\n ): Promise<QueryEntitiesResponse> {\n if (request && 'cursor' in request) {\n return { items: [], pageInfo: {}, totalItems: 0 };\n }\n const filter = createFilter(request?.filter);\n const items = this.#entities.filter(filter);\n // TODO(Rugvip): Pagination\n return {\n items,\n pageInfo: {},\n totalItems: items.length,\n };\n }\n\n async getEntityAncestors(\n request: GetEntityAncestorsRequest,\n ): Promise<GetEntityAncestorsResponse> {\n const entity = this.#createEntityRefMap().get(request.entityRef);\n if (!entity) {\n throw new NotFoundError(`Entity with ref ${request.entityRef} not found`);\n }\n return {\n items: [{ entity, parentEntityRefs: [] }],\n rootEntityRef: request.entityRef,\n };\n }\n\n async getEntityByRef(\n entityRef: string | CompoundEntityRef,\n ): Promise<Entity | undefined> {\n return this.#createEntityRefMap().get(\n stringifyEntityRef(parseEntityRef(entityRef)),\n );\n }\n\n async removeEntityByUid(uid: string): Promise<void> {\n const index = this.#entities.findIndex(e => e.metadata.uid === uid);\n if (index !== -1) {\n this.#entities.splice(index, 1);\n }\n }\n\n async refreshEntity(_entityRef: string): Promise<void> {}\n\n async getEntityFacets(\n request: GetEntityFacetsRequest,\n ): Promise<GetEntityFacetsResponse> {\n const filter = createFilter(request.filter);\n const filteredEntities = this.#entities.filter(filter);\n const facets = Object.fromEntries(\n request.facets.map(facet => {\n const facetValues = new Map<string, number>();\n for (const entity of filteredEntities) {\n const rows = buildEntitySearch(entity);\n const value = rows.find(\n row => row.key === facet.toLocaleLowerCase('en-US'),\n )?.value;\n if (value) {\n facetValues.set(\n String(value),\n (facetValues.get(String(value)) ?? 0) + 1,\n );\n }\n }\n const counts = Array.from(facetValues.entries()).map(\n ([value, count]) => ({ value, count }),\n );\n return [facet, counts];\n }),\n );\n return {\n facets,\n };\n }\n\n async getLocationById(_id: string): Promise<Location | undefined> {\n throw new NotImplementedError('Method not implemented.');\n }\n\n async getLocationByRef(_locationRef: string): Promise<Location | undefined> {\n throw new NotImplementedError('Method not implemented.');\n }\n\n async addLocation(\n _location: AddLocationRequest,\n ): Promise<AddLocationResponse> {\n throw new NotImplementedError('Method not implemented.');\n }\n\n async removeLocationById(_id: string): Promise<void> {\n throw new NotImplementedError('Method not implemented.');\n }\n\n async getLocationByEntity(\n _entityRef: string | CompoundEntityRef,\n ): Promise<Location | undefined> {\n throw new NotImplementedError('Method not implemented.');\n }\n\n async validateEntity(\n _entity: Entity,\n _locationRef: string,\n ): Promise<ValidateEntityResponse> {\n throw new NotImplementedError('Method not implemented.');\n }\n\n #createEntityRefMap() {\n return new Map(this.#entities.map(e => [stringifyEntityRef(e), e]));\n }\n}\n"],"names":["traverse","DEFAULT_NAMESPACE","CATALOG_FILTER_EXISTS","NotFoundError","stringifyEntityRef","parseEntityRef","NotImplementedError"],"mappings":";;;;;;;AA8CA,SAAS,kBAAkB,MAAgB,EAAA;AACzC,EAAM,MAAA,IAAA,GAAOA,6BAAS,MAAM,CAAA,CAAA;AAE5B,EAAI,IAAA,MAAA,CAAO,UAAU,IAAM,EAAA;AACzB,IAAA,IAAA,CAAK,IAAK,CAAA;AAAA,MACR,GAAK,EAAA,eAAA;AAAA,MACL,KAAO,EAAA,MAAA,CAAO,QAAS,CAAA,IAAA,CAAK,kBAAkB,OAAO,CAAA;AAAA,KACtD,CAAA,CAAA;AAAA,GACH;AACA,EAAI,IAAA,MAAA,CAAO,UAAU,SAAW,EAAA;AAC9B,IAAA,IAAA,CAAK,IAAK,CAAA;AAAA,MACR,GAAK,EAAA,oBAAA;AAAA,MACL,KAAO,EAAA,MAAA,CAAO,QAAS,CAAA,SAAA,CAAU,kBAAkB,OAAO,CAAA;AAAA,KAC3D,CAAA,CAAA;AAAA,GACH;AACA,EAAI,IAAA,MAAA,CAAO,UAAU,GAAK,EAAA;AACxB,IAAA,IAAA,CAAK,IAAK,CAAA;AAAA,MACR,GAAK,EAAA,cAAA;AAAA,MACL,KAAO,EAAA,MAAA,CAAO,QAAS,CAAA,GAAA,CAAI,kBAAkB,OAAO,CAAA;AAAA,KACrD,CAAA,CAAA;AAAA,GACH;AAEA,EAAI,IAAA,CAAC,MAAO,CAAA,QAAA,CAAS,SAAW,EAAA;AAC9B,IAAA,IAAA,CAAK,KAAK,EAAE,GAAA,EAAK,oBAAsB,EAAA,KAAA,EAAOC,gCAAmB,CAAA,CAAA;AAAA,GACnE;AAGA,EAAA,KAAA,MAAW,QAAY,IAAA,MAAA,CAAO,SAAa,IAAA,EAAI,EAAA;AAC7C,IAAA,IAAA,CAAK,IAAK,CAAA;AAAA,MACR,KAAK,CAAa,UAAA,EAAA,QAAA,CAAS,IAAK,CAAA,iBAAA,CAAkB,OAAO,CAAC,CAAA,CAAA;AAAA,MAC1D,KAAO,EAAA,QAAA,CAAS,SAAU,CAAA,iBAAA,CAAkB,OAAO,CAAA;AAAA,KACpD,CAAA,CAAA;AAAA,GACH;AAEA,EAAO,OAAA,IAAA,CAAA;AACT,CAAA;AAEA,SAAS,aACP,eAC6B,EAAA;AAC7B,EAAA,IAAI,CAAC,eAAiB,EAAA;AACpB,IAAA,OAAO,MAAM,IAAA,CAAA;AAAA,GACf;AAEA,EAAA,MAAM,OAAU,GAAA,CAAC,eAAe,CAAA,CAAE,IAAK,EAAA,CAAA;AAEvC,EAAA,OAAO,CAAU,MAAA,KAAA;AACf,IAAM,MAAA,IAAA,GAAO,kBAAkB,MAAM,CAAA,CAAA;AAErC,IAAO,OAAA,OAAA,CAAQ,KAAK,CAAU,MAAA,KAAA;AAC5B,MAAA,KAAA,MAAW,CAAC,GAAK,EAAA,aAAa,KAAK,MAAO,CAAA,OAAA,CAAQ,MAAM,CAAG,EAAA;AACzD,QAAA,MAAM,eAAe,IAClB,CAAA,MAAA,CAAO,SAAO,GAAI,CAAA,GAAA,KAAQ,IAAI,iBAAkB,CAAA,OAAO,CAAC,CACxD,CAAA,GAAA,CAAI,SAAO,GAAI,CAAA,KAAA,EAAO,UAAW,CAAA,iBAAA,CAAkB,OAAO,CAAC,CAAA,CAAA;AAE9D,QAAI,IAAA,YAAA,CAAa,WAAW,CAAG,EAAA;AAC7B,UAAO,OAAA,KAAA,CAAA;AAAA,SACT;AACA,QAAA,IAAI,kBAAkBC,mCAAuB,EAAA;AAC3C,UAAA,SAAA;AAAA,SACF;AACA,QAAA,IACE,CAAC,YAAc,EAAA,QAAA;AAAA,UACb,MAAO,CAAA,aAAa,CAAE,CAAA,iBAAA,CAAkB,OAAO,CAAA;AAAA,SAEjD,EAAA;AACA,UAAO,OAAA,KAAA,CAAA;AAAA,SACT;AAAA,OACF;AACA,MAAO,OAAA,IAAA,CAAA;AAAA,KACR,CAAA,CAAA;AAAA,GACH,CAAA;AACF,CAAA;AASO,MAAM,qBAA4C,CAAA;AAAA,EACvD,SAAA,CAAA;AAAA,EAEA,YAAY,OAAmC,EAAA;AAC7C,IAAA,IAAA,CAAK,SAAY,GAAA,OAAA,EAAS,QAAU,EAAA,KAAA,MAAW,EAAC,CAAA;AAAA,GAClD;AAAA,EAEA,MAAM,YACJ,OAC8B,EAAA;AAC9B,IAAM,MAAA,MAAA,GAAS,YAAa,CAAA,OAAA,EAAS,MAAM,CAAA,CAAA;AAC3C,IAAA,OAAO,EAAE,KAAO,EAAA,IAAA,CAAK,SAAU,CAAA,MAAA,CAAO,MAAM,CAAE,EAAA,CAAA;AAAA,GAChD;AAAA,EAEA,MAAM,kBACJ,OACoC,EAAA;AACpC,IAAM,MAAA,MAAA,GAAS,YAAa,CAAA,OAAA,CAAQ,MAAM,CAAA,CAAA;AAC1C,IAAM,MAAA,MAAA,GAAS,KAAK,mBAAoB,EAAA,CAAA;AACxC,IAAO,OAAA;AAAA,MACL,OAAO,OAAQ,CAAA,UAAA,CACZ,GAAI,CAAA,CAAA,GAAA,KAAO,OAAO,GAAI,CAAA,GAAG,CAAC,CAAA,CAC1B,IAAI,CAAM,CAAA,KAAA,CAAA,IAAK,OAAO,CAAC,CAAA,GAAI,IAAI,KAAU,CAAA,CAAA;AAAA,KAC9C,CAAA;AAAA,GACF;AAAA,EAEA,MAAM,cACJ,OACgC,EAAA;AAChC,IAAI,IAAA,OAAA,IAAW,YAAY,OAAS,EAAA;AAClC,MAAO,OAAA,EAAE,OAAO,EAAC,EAAG,UAAU,EAAC,EAAG,YAAY,CAAE,EAAA,CAAA;AAAA,KAClD;AACA,IAAM,MAAA,MAAA,GAAS,YAAa,CAAA,OAAA,EAAS,MAAM,CAAA,CAAA;AAC3C,IAAA,MAAM,KAAQ,GAAA,IAAA,CAAK,SAAU,CAAA,MAAA,CAAO,MAAM,CAAA,CAAA;AAE1C,IAAO,OAAA;AAAA,MACL,KAAA;AAAA,MACA,UAAU,EAAC;AAAA,MACX,YAAY,KAAM,CAAA,MAAA;AAAA,KACpB,CAAA;AAAA,GACF;AAAA,EAEA,MAAM,mBACJ,OACqC,EAAA;AACrC,IAAA,MAAM,SAAS,IAAK,CAAA,mBAAA,EAAsB,CAAA,GAAA,CAAI,QAAQ,SAAS,CAAA,CAAA;AAC/D,IAAA,IAAI,CAAC,MAAQ,EAAA;AACX,MAAA,MAAM,IAAIC,oBAAA,CAAc,CAAmB,gBAAA,EAAA,OAAA,CAAQ,SAAS,CAAY,UAAA,CAAA,CAAA,CAAA;AAAA,KAC1E;AACA,IAAO,OAAA;AAAA,MACL,OAAO,CAAC,EAAE,QAAQ,gBAAkB,EAAA,IAAI,CAAA;AAAA,MACxC,eAAe,OAAQ,CAAA,SAAA;AAAA,KACzB,CAAA;AAAA,GACF;AAAA,EAEA,MAAM,eACJ,SAC6B,EAAA;AAC7B,IAAO,OAAA,IAAA,CAAK,qBAAsB,CAAA,GAAA;AAAA,MAChCC,+BAAA,CAAmBC,2BAAe,CAAA,SAAS,CAAC,CAAA;AAAA,KAC9C,CAAA;AAAA,GACF;AAAA,EAEA,MAAM,kBAAkB,GAA4B,EAAA;AAClD,IAAM,MAAA,KAAA,GAAQ,KAAK,SAAU,CAAA,SAAA,CAAU,OAAK,CAAE,CAAA,QAAA,CAAS,QAAQ,GAAG,CAAA,CAAA;AAClE,IAAA,IAAI,UAAU,CAAI,CAAA,EAAA;AAChB,MAAK,IAAA,CAAA,SAAA,CAAU,MAAO,CAAA,KAAA,EAAO,CAAC,CAAA,CAAA;AAAA,KAChC;AAAA,GACF;AAAA,EAEA,MAAM,cAAc,UAAmC,EAAA;AAAA,GAAC;AAAA,EAExD,MAAM,gBACJ,OACkC,EAAA;AAClC,IAAM,MAAA,MAAA,GAAS,YAAa,CAAA,OAAA,CAAQ,MAAM,CAAA,CAAA;AAC1C,IAAA,MAAM,gBAAmB,GAAA,IAAA,CAAK,SAAU,CAAA,MAAA,CAAO,MAAM,CAAA,CAAA;AACrD,IAAA,MAAM,SAAS,MAAO,CAAA,WAAA;AAAA,MACpB,OAAA,CAAQ,MAAO,CAAA,GAAA,CAAI,CAAS,KAAA,KAAA;AAC1B,QAAM,MAAA,WAAA,uBAAkB,GAAoB,EAAA,CAAA;AAC5C,QAAA,KAAA,MAAW,UAAU,gBAAkB,EAAA;AACrC,UAAM,MAAA,IAAA,GAAO,kBAAkB,MAAM,CAAA,CAAA;AACrC,UAAA,MAAM,QAAQ,IAAK,CAAA,IAAA;AAAA,YACjB,CAAO,GAAA,KAAA,GAAA,CAAI,GAAQ,KAAA,KAAA,CAAM,kBAAkB,OAAO,CAAA;AAAA,WACjD,EAAA,KAAA,CAAA;AACH,UAAA,IAAI,KAAO,EAAA;AACT,YAAY,WAAA,CAAA,GAAA;AAAA,cACV,OAAO,KAAK,CAAA;AAAA,cAAA,CACX,YAAY,GAAI,CAAA,MAAA,CAAO,KAAK,CAAC,KAAK,CAAK,IAAA,CAAA;AAAA,aAC1C,CAAA;AAAA,WACF;AAAA,SACF;AACA,QAAA,MAAM,SAAS,KAAM,CAAA,IAAA,CAAK,WAAY,CAAA,OAAA,EAAS,CAAE,CAAA,GAAA;AAAA,UAC/C,CAAC,CAAC,KAAA,EAAO,KAAK,CAAO,MAAA,EAAE,OAAO,KAAM,EAAA,CAAA;AAAA,SACtC,CAAA;AACA,QAAO,OAAA,CAAC,OAAO,MAAM,CAAA,CAAA;AAAA,OACtB,CAAA;AAAA,KACH,CAAA;AACA,IAAO,OAAA;AAAA,MACL,MAAA;AAAA,KACF,CAAA;AAAA,GACF;AAAA,EAEA,MAAM,gBAAgB,GAA4C,EAAA;AAChE,IAAM,MAAA,IAAIC,2BAAoB,yBAAyB,CAAA,CAAA;AAAA,GACzD;AAAA,EAEA,MAAM,iBAAiB,YAAqD,EAAA;AAC1E,IAAM,MAAA,IAAIA,2BAAoB,yBAAyB,CAAA,CAAA;AAAA,GACzD;AAAA,EAEA,MAAM,YACJ,SAC8B,EAAA;AAC9B,IAAM,MAAA,IAAIA,2BAAoB,yBAAyB,CAAA,CAAA;AAAA,GACzD;AAAA,EAEA,MAAM,mBAAmB,GAA4B,EAAA;AACnD,IAAM,MAAA,IAAIA,2BAAoB,yBAAyB,CAAA,CAAA;AAAA,GACzD;AAAA,EAEA,MAAM,oBACJ,UAC+B,EAAA;AAC/B,IAAM,MAAA,IAAIA,2BAAoB,yBAAyB,CAAA,CAAA;AAAA,GACzD;AAAA,EAEA,MAAM,cACJ,CAAA,OAAA,EACA,YACiC,EAAA;AACjC,IAAM,MAAA,IAAIA,2BAAoB,yBAAyB,CAAA,CAAA;AAAA,GACzD;AAAA,EAEA,mBAAsB,GAAA;AACpB,IAAA,OAAO,IAAI,GAAA,CAAI,IAAK,CAAA,SAAA,CAAU,GAAI,CAAA,CAAA,CAAA,KAAK,CAACF,+BAAA,CAAmB,CAAC,CAAA,EAAG,CAAC,CAAC,CAAC,CAAA,CAAA;AAAA,GACpE;AACF;;;;"}
|
|
@@ -6,21 +6,30 @@ import { traverse } from '../plugins/catalog-backend/src/database/operations/sti
|
|
|
6
6
|
function buildEntitySearch(entity) {
|
|
7
7
|
const rows = traverse(entity);
|
|
8
8
|
if (entity.metadata?.name) {
|
|
9
|
-
rows.push({
|
|
9
|
+
rows.push({
|
|
10
|
+
key: "metadata.name",
|
|
11
|
+
value: entity.metadata.name.toLocaleLowerCase("en-US")
|
|
12
|
+
});
|
|
10
13
|
}
|
|
11
14
|
if (entity.metadata?.namespace) {
|
|
12
|
-
rows.push({
|
|
15
|
+
rows.push({
|
|
16
|
+
key: "metadata.namespace",
|
|
17
|
+
value: entity.metadata.namespace.toLocaleLowerCase("en-US")
|
|
18
|
+
});
|
|
13
19
|
}
|
|
14
20
|
if (entity.metadata?.uid) {
|
|
15
|
-
rows.push({
|
|
21
|
+
rows.push({
|
|
22
|
+
key: "metadata.uid",
|
|
23
|
+
value: entity.metadata.uid.toLocaleLowerCase("en-US")
|
|
24
|
+
});
|
|
16
25
|
}
|
|
17
26
|
if (!entity.metadata.namespace) {
|
|
18
27
|
rows.push({ key: "metadata.namespace", value: DEFAULT_NAMESPACE });
|
|
19
28
|
}
|
|
20
29
|
for (const relation of entity.relations ?? []) {
|
|
21
30
|
rows.push({
|
|
22
|
-
key: `relations.${relation.type}`,
|
|
23
|
-
value: relation.targetRef
|
|
31
|
+
key: `relations.${relation.type.toLocaleLowerCase("en-US")}`,
|
|
32
|
+
value: relation.targetRef.toLocaleLowerCase("en-US")
|
|
24
33
|
});
|
|
25
34
|
}
|
|
26
35
|
return rows;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InMemoryCatalogClient.esm.js","sources":["../../src/testUtils/InMemoryCatalogClient.ts"],"sourcesContent":["/*\n * Copyright 2024 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 AddLocationRequest,\n AddLocationResponse,\n CATALOG_FILTER_EXISTS,\n CatalogApi,\n EntityFilterQuery,\n GetEntitiesByRefsRequest,\n GetEntitiesByRefsResponse,\n GetEntitiesRequest,\n GetEntitiesResponse,\n GetEntityAncestorsRequest,\n GetEntityAncestorsResponse,\n GetEntityFacetsRequest,\n GetEntityFacetsResponse,\n Location,\n QueryEntitiesRequest,\n QueryEntitiesResponse,\n ValidateEntityResponse,\n} from '@backstage/catalog-client';\nimport {\n CompoundEntityRef,\n DEFAULT_NAMESPACE,\n Entity,\n parseEntityRef,\n stringifyEntityRef,\n} from '@backstage/catalog-model';\nimport { NotFoundError, NotImplementedError } from '@backstage/errors';\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport { traverse } from '../../../../plugins/catalog-backend/src/database/operations/stitcher/buildEntitySearch';\n\nfunction buildEntitySearch(entity: Entity) {\n const rows = traverse(entity);\n\n if (entity.metadata?.name) {\n rows.push({ key: 'metadata.name', value: entity.metadata.name });\n }\n if (entity.metadata?.namespace) {\n rows.push({ key: 'metadata.namespace', value: entity.metadata.namespace });\n }\n if (entity.metadata?.uid) {\n rows.push({ key: 'metadata.uid', value: entity.metadata.uid });\n }\n\n if (!entity.metadata.namespace) {\n rows.push({ key: 'metadata.namespace', value: DEFAULT_NAMESPACE });\n }\n\n // Visit relations\n for (const relation of entity.relations ?? []) {\n rows.push({\n key: `relations.${relation.type}`,\n value: relation.targetRef,\n });\n }\n\n return rows;\n}\n\nfunction createFilter(\n filterOrFilters?: EntityFilterQuery,\n): (entity: Entity) => boolean {\n if (!filterOrFilters) {\n return () => true;\n }\n\n const filters = [filterOrFilters].flat();\n\n return entity => {\n const rows = buildEntitySearch(entity);\n\n return filters.some(filter => {\n for (const [key, expectedValue] of Object.entries(filter)) {\n const searchValues = rows\n .filter(row => row.key === key.toLocaleLowerCase('en-US'))\n .map(row => row.value?.toString().toLocaleLowerCase('en-US'));\n\n if (searchValues.length === 0) {\n return false;\n }\n if (expectedValue === CATALOG_FILTER_EXISTS) {\n continue;\n }\n if (\n !searchValues?.includes(\n String(expectedValue).toLocaleLowerCase('en-US'),\n )\n ) {\n return false;\n }\n }\n return true;\n });\n };\n}\n\n/**\n * Implements a VERY basic fake catalog client that stores entities in memory.\n * It has severely limited functionality, and is only useful under certain\n * circumstances in tests.\n *\n * @public\n */\nexport class InMemoryCatalogClient implements CatalogApi {\n #entities: Entity[];\n\n constructor(options?: { entities?: Entity[] }) {\n this.#entities = options?.entities?.slice() ?? [];\n }\n\n async getEntities(\n request?: GetEntitiesRequest,\n ): Promise<GetEntitiesResponse> {\n const filter = createFilter(request?.filter);\n return { items: this.#entities.filter(filter) };\n }\n\n async getEntitiesByRefs(\n request: GetEntitiesByRefsRequest,\n ): Promise<GetEntitiesByRefsResponse> {\n const filter = createFilter(request.filter);\n const refMap = this.#createEntityRefMap();\n return {\n items: request.entityRefs\n .map(ref => refMap.get(ref))\n .map(e => (e && filter(e) ? e : undefined)),\n };\n }\n\n async queryEntities(\n request?: QueryEntitiesRequest,\n ): Promise<QueryEntitiesResponse> {\n if (request && 'cursor' in request) {\n return { items: [], pageInfo: {}, totalItems: 0 };\n }\n const filter = createFilter(request?.filter);\n const items = this.#entities.filter(filter);\n // TODO(Rugvip): Pagination\n return {\n items,\n pageInfo: {},\n totalItems: items.length,\n };\n }\n\n async getEntityAncestors(\n request: GetEntityAncestorsRequest,\n ): Promise<GetEntityAncestorsResponse> {\n const entity = this.#createEntityRefMap().get(request.entityRef);\n if (!entity) {\n throw new NotFoundError(`Entity with ref ${request.entityRef} not found`);\n }\n return {\n items: [{ entity, parentEntityRefs: [] }],\n rootEntityRef: request.entityRef,\n };\n }\n\n async getEntityByRef(\n entityRef: string | CompoundEntityRef,\n ): Promise<Entity | undefined> {\n return this.#createEntityRefMap().get(\n stringifyEntityRef(parseEntityRef(entityRef)),\n );\n }\n\n async removeEntityByUid(uid: string): Promise<void> {\n const index = this.#entities.findIndex(e => e.metadata.uid === uid);\n if (index !== -1) {\n this.#entities.splice(index, 1);\n }\n }\n\n async refreshEntity(_entityRef: string): Promise<void> {}\n\n async getEntityFacets(\n request: GetEntityFacetsRequest,\n ): Promise<GetEntityFacetsResponse> {\n const filter = createFilter(request.filter);\n const filteredEntities = this.#entities.filter(filter);\n const facets = Object.fromEntries(\n request.facets.map(facet => {\n const facetValues = new Map<string, number>();\n for (const entity of filteredEntities) {\n const rows = buildEntitySearch(entity);\n const value = rows.find(\n row => row.key === facet.toLocaleLowerCase('en-US'),\n )?.value;\n if (value) {\n facetValues.set(\n String(value),\n (facetValues.get(String(value)) ?? 0) + 1,\n );\n }\n }\n const counts = Array.from(facetValues.entries()).map(\n ([value, count]) => ({ value, count }),\n );\n return [facet, counts];\n }),\n );\n return {\n facets,\n };\n }\n\n async getLocationById(_id: string): Promise<Location | undefined> {\n throw new NotImplementedError('Method not implemented.');\n }\n\n async getLocationByRef(_locationRef: string): Promise<Location | undefined> {\n throw new NotImplementedError('Method not implemented.');\n }\n\n async addLocation(\n _location: AddLocationRequest,\n ): Promise<AddLocationResponse> {\n throw new NotImplementedError('Method not implemented.');\n }\n\n async removeLocationById(_id: string): Promise<void> {\n throw new NotImplementedError('Method not implemented.');\n }\n\n async getLocationByEntity(\n _entityRef: string | CompoundEntityRef,\n ): Promise<Location | undefined> {\n throw new NotImplementedError('Method not implemented.');\n }\n\n async validateEntity(\n _entity: Entity,\n _locationRef: string,\n ): Promise<ValidateEntityResponse> {\n throw new NotImplementedError('Method not implemented.');\n }\n\n #createEntityRefMap() {\n return new Map(this.#entities.map(e => [stringifyEntityRef(e), e]));\n }\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"InMemoryCatalogClient.esm.js","sources":["../../src/testUtils/InMemoryCatalogClient.ts"],"sourcesContent":["/*\n * Copyright 2024 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 AddLocationRequest,\n AddLocationResponse,\n CATALOG_FILTER_EXISTS,\n CatalogApi,\n EntityFilterQuery,\n GetEntitiesByRefsRequest,\n GetEntitiesByRefsResponse,\n GetEntitiesRequest,\n GetEntitiesResponse,\n GetEntityAncestorsRequest,\n GetEntityAncestorsResponse,\n GetEntityFacetsRequest,\n GetEntityFacetsResponse,\n Location,\n QueryEntitiesRequest,\n QueryEntitiesResponse,\n ValidateEntityResponse,\n} from '@backstage/catalog-client';\nimport {\n CompoundEntityRef,\n DEFAULT_NAMESPACE,\n Entity,\n parseEntityRef,\n stringifyEntityRef,\n} from '@backstage/catalog-model';\nimport { NotFoundError, NotImplementedError } from '@backstage/errors';\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport { traverse } from '../../../../plugins/catalog-backend/src/database/operations/stitcher/buildEntitySearch';\n\nfunction buildEntitySearch(entity: Entity) {\n const rows = traverse(entity);\n\n if (entity.metadata?.name) {\n rows.push({\n key: 'metadata.name',\n value: entity.metadata.name.toLocaleLowerCase('en-US'),\n });\n }\n if (entity.metadata?.namespace) {\n rows.push({\n key: 'metadata.namespace',\n value: entity.metadata.namespace.toLocaleLowerCase('en-US'),\n });\n }\n if (entity.metadata?.uid) {\n rows.push({\n key: 'metadata.uid',\n value: entity.metadata.uid.toLocaleLowerCase('en-US'),\n });\n }\n\n if (!entity.metadata.namespace) {\n rows.push({ key: 'metadata.namespace', value: DEFAULT_NAMESPACE });\n }\n\n // Visit relations\n for (const relation of entity.relations ?? []) {\n rows.push({\n key: `relations.${relation.type.toLocaleLowerCase('en-US')}`,\n value: relation.targetRef.toLocaleLowerCase('en-US'),\n });\n }\n\n return rows;\n}\n\nfunction createFilter(\n filterOrFilters?: EntityFilterQuery,\n): (entity: Entity) => boolean {\n if (!filterOrFilters) {\n return () => true;\n }\n\n const filters = [filterOrFilters].flat();\n\n return entity => {\n const rows = buildEntitySearch(entity);\n\n return filters.some(filter => {\n for (const [key, expectedValue] of Object.entries(filter)) {\n const searchValues = rows\n .filter(row => row.key === key.toLocaleLowerCase('en-US'))\n .map(row => row.value?.toString().toLocaleLowerCase('en-US'));\n\n if (searchValues.length === 0) {\n return false;\n }\n if (expectedValue === CATALOG_FILTER_EXISTS) {\n continue;\n }\n if (\n !searchValues?.includes(\n String(expectedValue).toLocaleLowerCase('en-US'),\n )\n ) {\n return false;\n }\n }\n return true;\n });\n };\n}\n\n/**\n * Implements a VERY basic fake catalog client that stores entities in memory.\n * It has severely limited functionality, and is only useful under certain\n * circumstances in tests.\n *\n * @public\n */\nexport class InMemoryCatalogClient implements CatalogApi {\n #entities: Entity[];\n\n constructor(options?: { entities?: Entity[] }) {\n this.#entities = options?.entities?.slice() ?? [];\n }\n\n async getEntities(\n request?: GetEntitiesRequest,\n ): Promise<GetEntitiesResponse> {\n const filter = createFilter(request?.filter);\n return { items: this.#entities.filter(filter) };\n }\n\n async getEntitiesByRefs(\n request: GetEntitiesByRefsRequest,\n ): Promise<GetEntitiesByRefsResponse> {\n const filter = createFilter(request.filter);\n const refMap = this.#createEntityRefMap();\n return {\n items: request.entityRefs\n .map(ref => refMap.get(ref))\n .map(e => (e && filter(e) ? e : undefined)),\n };\n }\n\n async queryEntities(\n request?: QueryEntitiesRequest,\n ): Promise<QueryEntitiesResponse> {\n if (request && 'cursor' in request) {\n return { items: [], pageInfo: {}, totalItems: 0 };\n }\n const filter = createFilter(request?.filter);\n const items = this.#entities.filter(filter);\n // TODO(Rugvip): Pagination\n return {\n items,\n pageInfo: {},\n totalItems: items.length,\n };\n }\n\n async getEntityAncestors(\n request: GetEntityAncestorsRequest,\n ): Promise<GetEntityAncestorsResponse> {\n const entity = this.#createEntityRefMap().get(request.entityRef);\n if (!entity) {\n throw new NotFoundError(`Entity with ref ${request.entityRef} not found`);\n }\n return {\n items: [{ entity, parentEntityRefs: [] }],\n rootEntityRef: request.entityRef,\n };\n }\n\n async getEntityByRef(\n entityRef: string | CompoundEntityRef,\n ): Promise<Entity | undefined> {\n return this.#createEntityRefMap().get(\n stringifyEntityRef(parseEntityRef(entityRef)),\n );\n }\n\n async removeEntityByUid(uid: string): Promise<void> {\n const index = this.#entities.findIndex(e => e.metadata.uid === uid);\n if (index !== -1) {\n this.#entities.splice(index, 1);\n }\n }\n\n async refreshEntity(_entityRef: string): Promise<void> {}\n\n async getEntityFacets(\n request: GetEntityFacetsRequest,\n ): Promise<GetEntityFacetsResponse> {\n const filter = createFilter(request.filter);\n const filteredEntities = this.#entities.filter(filter);\n const facets = Object.fromEntries(\n request.facets.map(facet => {\n const facetValues = new Map<string, number>();\n for (const entity of filteredEntities) {\n const rows = buildEntitySearch(entity);\n const value = rows.find(\n row => row.key === facet.toLocaleLowerCase('en-US'),\n )?.value;\n if (value) {\n facetValues.set(\n String(value),\n (facetValues.get(String(value)) ?? 0) + 1,\n );\n }\n }\n const counts = Array.from(facetValues.entries()).map(\n ([value, count]) => ({ value, count }),\n );\n return [facet, counts];\n }),\n );\n return {\n facets,\n };\n }\n\n async getLocationById(_id: string): Promise<Location | undefined> {\n throw new NotImplementedError('Method not implemented.');\n }\n\n async getLocationByRef(_locationRef: string): Promise<Location | undefined> {\n throw new NotImplementedError('Method not implemented.');\n }\n\n async addLocation(\n _location: AddLocationRequest,\n ): Promise<AddLocationResponse> {\n throw new NotImplementedError('Method not implemented.');\n }\n\n async removeLocationById(_id: string): Promise<void> {\n throw new NotImplementedError('Method not implemented.');\n }\n\n async getLocationByEntity(\n _entityRef: string | CompoundEntityRef,\n ): Promise<Location | undefined> {\n throw new NotImplementedError('Method not implemented.');\n }\n\n async validateEntity(\n _entity: Entity,\n _locationRef: string,\n ): Promise<ValidateEntityResponse> {\n throw new NotImplementedError('Method not implemented.');\n }\n\n #createEntityRefMap() {\n return new Map(this.#entities.map(e => [stringifyEntityRef(e), e]));\n }\n}\n"],"names":[],"mappings":"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"}
|
package/dist/utils.cjs.js
CHANGED
|
@@ -3,6 +3,36 @@
|
|
|
3
3
|
function isQueryEntitiesInitialRequest(request) {
|
|
4
4
|
return !request.cursor;
|
|
5
5
|
}
|
|
6
|
+
function splitRefsIntoChunks(refs, options) {
|
|
7
|
+
if (!refs.length) {
|
|
8
|
+
return [];
|
|
9
|
+
}
|
|
10
|
+
const {
|
|
11
|
+
maxCountPerChunk = 1e3,
|
|
12
|
+
maxStringLengthPerChunk = 90 * 2 ** 10,
|
|
13
|
+
extraStringLengthPerRef = 3
|
|
14
|
+
} = {};
|
|
15
|
+
const chunks = [];
|
|
16
|
+
let currentChunkStart = 0;
|
|
17
|
+
let currentChunkStringLength = 0;
|
|
18
|
+
let currentChunkSize = 0;
|
|
19
|
+
for (let i = 0; i < refs.length; ++i) {
|
|
20
|
+
const refLength = refs[i].length + extraStringLengthPerRef;
|
|
21
|
+
if (currentChunkSize > 0) {
|
|
22
|
+
if (currentChunkStringLength + refLength > maxStringLengthPerChunk || currentChunkSize + 1 > maxCountPerChunk) {
|
|
23
|
+
chunks.push(refs.slice(currentChunkStart, i));
|
|
24
|
+
currentChunkStart = i;
|
|
25
|
+
currentChunkStringLength = 0;
|
|
26
|
+
currentChunkSize = 0;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
currentChunkStringLength += refLength;
|
|
30
|
+
currentChunkSize += 1;
|
|
31
|
+
}
|
|
32
|
+
chunks.push(refs.slice(currentChunkStart, refs.length));
|
|
33
|
+
return chunks;
|
|
34
|
+
}
|
|
6
35
|
|
|
7
36
|
exports.isQueryEntitiesInitialRequest = isQueryEntitiesInitialRequest;
|
|
37
|
+
exports.splitRefsIntoChunks = splitRefsIntoChunks;
|
|
8
38
|
//# sourceMappingURL=utils.cjs.js.map
|
package/dist/utils.cjs.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.cjs.js","sources":["../src/utils.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 {\n QueryEntitiesCursorRequest,\n QueryEntitiesInitialRequest,\n} from './types/api';\n\nexport function isQueryEntitiesInitialRequest(\n request: QueryEntitiesInitialRequest,\n): request is QueryEntitiesInitialRequest {\n return !(request as QueryEntitiesCursorRequest).cursor;\n}\n"],"names":[],"mappings":";;AAqBO,SAAS,8BACd,OACwC,EAAA;AACxC,EAAA,OAAO,CAAE,OAAuC,CAAA,MAAA,CAAA;AAClD
|
|
1
|
+
{"version":3,"file":"utils.cjs.js","sources":["../src/utils.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 {\n QueryEntitiesCursorRequest,\n QueryEntitiesInitialRequest,\n} from './types/api';\n\nexport function isQueryEntitiesInitialRequest(\n request: QueryEntitiesInitialRequest,\n): request is QueryEntitiesInitialRequest {\n return !(request as QueryEntitiesCursorRequest).cursor;\n}\n\n/**\n * Takes a set of entity refs, and splits them into chunks (groups) such that\n * the total string length in each chunk does not exceed the default Express.js\n * request body limit of 100 kB (with some margin) when JSON encoded as an\n * array.\n */\nexport function splitRefsIntoChunks(\n refs: string[],\n options?: {\n // No chunk has more than this many refs, no matter what\n maxCountPerChunk?: number;\n // The total string length (taking the extraStringLengthPerRef into account)\n // of each chunk never exceeds this many characters, no matter what\n maxStringLengthPerChunk?: number;\n // Add this many characters to the length of each ref when calculating\n // (default is 3, since eacn array entry is surrounded by quotes and a\n // comma)\n extraStringLengthPerRef?: number;\n },\n): string[][] {\n if (!refs.length) {\n return [];\n }\n\n const {\n maxCountPerChunk = 1000,\n maxStringLengthPerChunk = 90 * 2 ** 10,\n extraStringLengthPerRef = 3,\n } = options ?? {};\n\n const chunks: string[][] = [];\n\n let currentChunkStart = 0;\n let currentChunkStringLength = 0;\n let currentChunkSize = 0;\n\n for (let i = 0; i < refs.length; ++i) {\n const refLength = refs[i].length + extraStringLengthPerRef;\n\n // always allow at least one element per chunk even in abnormal situations\n if (currentChunkSize > 0) {\n // emit chunk and start over if either the string length or the count\n // limit would be reached\n if (\n currentChunkStringLength + refLength > maxStringLengthPerChunk ||\n currentChunkSize + 1 > maxCountPerChunk\n ) {\n chunks.push(refs.slice(currentChunkStart, i));\n currentChunkStart = i;\n currentChunkStringLength = 0;\n currentChunkSize = 0;\n }\n }\n\n currentChunkStringLength += refLength;\n currentChunkSize += 1;\n }\n\n // emit whatever is left as the last chunk\n chunks.push(refs.slice(currentChunkStart, refs.length));\n\n return chunks;\n}\n"],"names":[],"mappings":";;AAqBO,SAAS,8BACd,OACwC,EAAA;AACxC,EAAA,OAAO,CAAE,OAAuC,CAAA,MAAA,CAAA;AAClD,CAAA;AAQgB,SAAA,mBAAA,CACd,MACA,OAWY,EAAA;AACZ,EAAI,IAAA,CAAC,KAAK,MAAQ,EAAA;AAChB,IAAA,OAAO,EAAC,CAAA;AAAA,GACV;AAEA,EAAM,MAAA;AAAA,IACJ,gBAAmB,GAAA,GAAA;AAAA,IACnB,uBAAA,GAA0B,KAAK,CAAK,IAAA,EAAA;AAAA,IACpC,uBAA0B,GAAA,CAAA;AAAA,GAC5B,GAAe,EAAC,CAAA;AAEhB,EAAA,MAAM,SAAqB,EAAC,CAAA;AAE5B,EAAA,IAAI,iBAAoB,GAAA,CAAA,CAAA;AACxB,EAAA,IAAI,wBAA2B,GAAA,CAAA,CAAA;AAC/B,EAAA,IAAI,gBAAmB,GAAA,CAAA,CAAA;AAEvB,EAAA,KAAA,IAAS,IAAI,CAAG,EAAA,CAAA,GAAI,IAAK,CAAA,MAAA,EAAQ,EAAE,CAAG,EAAA;AACpC,IAAA,MAAM,SAAY,GAAA,IAAA,CAAK,CAAC,CAAA,CAAE,MAAS,GAAA,uBAAA,CAAA;AAGnC,IAAA,IAAI,mBAAmB,CAAG,EAAA;AAGxB,MAAA,IACE,wBAA2B,GAAA,SAAA,GAAY,uBACvC,IAAA,gBAAA,GAAmB,IAAI,gBACvB,EAAA;AACA,QAAA,MAAA,CAAO,IAAK,CAAA,IAAA,CAAK,KAAM,CAAA,iBAAA,EAAmB,CAAC,CAAC,CAAA,CAAA;AAC5C,QAAoB,iBAAA,GAAA,CAAA,CAAA;AACpB,QAA2B,wBAAA,GAAA,CAAA,CAAA;AAC3B,QAAmB,gBAAA,GAAA,CAAA,CAAA;AAAA,OACrB;AAAA,KACF;AAEA,IAA4B,wBAAA,IAAA,SAAA,CAAA;AAC5B,IAAoB,gBAAA,IAAA,CAAA,CAAA;AAAA,GACtB;AAGA,EAAA,MAAA,CAAO,KAAK,IAAK,CAAA,KAAA,CAAM,iBAAmB,EAAA,IAAA,CAAK,MAAM,CAAC,CAAA,CAAA;AAEtD,EAAO,OAAA,MAAA,CAAA;AACT;;;;;"}
|
package/dist/utils.esm.js
CHANGED
|
@@ -1,6 +1,35 @@
|
|
|
1
1
|
function isQueryEntitiesInitialRequest(request) {
|
|
2
2
|
return !request.cursor;
|
|
3
3
|
}
|
|
4
|
+
function splitRefsIntoChunks(refs, options) {
|
|
5
|
+
if (!refs.length) {
|
|
6
|
+
return [];
|
|
7
|
+
}
|
|
8
|
+
const {
|
|
9
|
+
maxCountPerChunk = 1e3,
|
|
10
|
+
maxStringLengthPerChunk = 90 * 2 ** 10,
|
|
11
|
+
extraStringLengthPerRef = 3
|
|
12
|
+
} = {};
|
|
13
|
+
const chunks = [];
|
|
14
|
+
let currentChunkStart = 0;
|
|
15
|
+
let currentChunkStringLength = 0;
|
|
16
|
+
let currentChunkSize = 0;
|
|
17
|
+
for (let i = 0; i < refs.length; ++i) {
|
|
18
|
+
const refLength = refs[i].length + extraStringLengthPerRef;
|
|
19
|
+
if (currentChunkSize > 0) {
|
|
20
|
+
if (currentChunkStringLength + refLength > maxStringLengthPerChunk || currentChunkSize + 1 > maxCountPerChunk) {
|
|
21
|
+
chunks.push(refs.slice(currentChunkStart, i));
|
|
22
|
+
currentChunkStart = i;
|
|
23
|
+
currentChunkStringLength = 0;
|
|
24
|
+
currentChunkSize = 0;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
currentChunkStringLength += refLength;
|
|
28
|
+
currentChunkSize += 1;
|
|
29
|
+
}
|
|
30
|
+
chunks.push(refs.slice(currentChunkStart, refs.length));
|
|
31
|
+
return chunks;
|
|
32
|
+
}
|
|
4
33
|
|
|
5
|
-
export { isQueryEntitiesInitialRequest };
|
|
34
|
+
export { isQueryEntitiesInitialRequest, splitRefsIntoChunks };
|
|
6
35
|
//# sourceMappingURL=utils.esm.js.map
|
package/dist/utils.esm.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.esm.js","sources":["../src/utils.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 {\n QueryEntitiesCursorRequest,\n QueryEntitiesInitialRequest,\n} from './types/api';\n\nexport function isQueryEntitiesInitialRequest(\n request: QueryEntitiesInitialRequest,\n): request is QueryEntitiesInitialRequest {\n return !(request as QueryEntitiesCursorRequest).cursor;\n}\n"],"names":[],"mappings":"AAqBO,SAAS,8BACd,OACwC,EAAA;AACxC,EAAA,OAAO,CAAE,OAAuC,CAAA,MAAA,CAAA;AAClD;;;;"}
|
|
1
|
+
{"version":3,"file":"utils.esm.js","sources":["../src/utils.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 {\n QueryEntitiesCursorRequest,\n QueryEntitiesInitialRequest,\n} from './types/api';\n\nexport function isQueryEntitiesInitialRequest(\n request: QueryEntitiesInitialRequest,\n): request is QueryEntitiesInitialRequest {\n return !(request as QueryEntitiesCursorRequest).cursor;\n}\n\n/**\n * Takes a set of entity refs, and splits them into chunks (groups) such that\n * the total string length in each chunk does not exceed the default Express.js\n * request body limit of 100 kB (with some margin) when JSON encoded as an\n * array.\n */\nexport function splitRefsIntoChunks(\n refs: string[],\n options?: {\n // No chunk has more than this many refs, no matter what\n maxCountPerChunk?: number;\n // The total string length (taking the extraStringLengthPerRef into account)\n // of each chunk never exceeds this many characters, no matter what\n maxStringLengthPerChunk?: number;\n // Add this many characters to the length of each ref when calculating\n // (default is 3, since eacn array entry is surrounded by quotes and a\n // comma)\n extraStringLengthPerRef?: number;\n },\n): string[][] {\n if (!refs.length) {\n return [];\n }\n\n const {\n maxCountPerChunk = 1000,\n maxStringLengthPerChunk = 90 * 2 ** 10,\n extraStringLengthPerRef = 3,\n } = options ?? {};\n\n const chunks: string[][] = [];\n\n let currentChunkStart = 0;\n let currentChunkStringLength = 0;\n let currentChunkSize = 0;\n\n for (let i = 0; i < refs.length; ++i) {\n const refLength = refs[i].length + extraStringLengthPerRef;\n\n // always allow at least one element per chunk even in abnormal situations\n if (currentChunkSize > 0) {\n // emit chunk and start over if either the string length or the count\n // limit would be reached\n if (\n currentChunkStringLength + refLength > maxStringLengthPerChunk ||\n currentChunkSize + 1 > maxCountPerChunk\n ) {\n chunks.push(refs.slice(currentChunkStart, i));\n currentChunkStart = i;\n currentChunkStringLength = 0;\n currentChunkSize = 0;\n }\n }\n\n currentChunkStringLength += refLength;\n currentChunkSize += 1;\n }\n\n // emit whatever is left as the last chunk\n chunks.push(refs.slice(currentChunkStart, refs.length));\n\n return chunks;\n}\n"],"names":[],"mappings":"AAqBO,SAAS,8BACd,OACwC,EAAA;AACxC,EAAA,OAAO,CAAE,OAAuC,CAAA,MAAA,CAAA;AAClD,CAAA;AAQgB,SAAA,mBAAA,CACd,MACA,OAWY,EAAA;AACZ,EAAI,IAAA,CAAC,KAAK,MAAQ,EAAA;AAChB,IAAA,OAAO,EAAC,CAAA;AAAA,GACV;AAEA,EAAM,MAAA;AAAA,IACJ,gBAAmB,GAAA,GAAA;AAAA,IACnB,uBAAA,GAA0B,KAAK,CAAK,IAAA,EAAA;AAAA,IACpC,uBAA0B,GAAA,CAAA;AAAA,GAC5B,GAAe,EAAC,CAAA;AAEhB,EAAA,MAAM,SAAqB,EAAC,CAAA;AAE5B,EAAA,IAAI,iBAAoB,GAAA,CAAA,CAAA;AACxB,EAAA,IAAI,wBAA2B,GAAA,CAAA,CAAA;AAC/B,EAAA,IAAI,gBAAmB,GAAA,CAAA,CAAA;AAEvB,EAAA,KAAA,IAAS,IAAI,CAAG,EAAA,CAAA,GAAI,IAAK,CAAA,MAAA,EAAQ,EAAE,CAAG,EAAA;AACpC,IAAA,MAAM,SAAY,GAAA,IAAA,CAAK,CAAC,CAAA,CAAE,MAAS,GAAA,uBAAA,CAAA;AAGnC,IAAA,IAAI,mBAAmB,CAAG,EAAA;AAGxB,MAAA,IACE,wBAA2B,GAAA,SAAA,GAAY,uBACvC,IAAA,gBAAA,GAAmB,IAAI,gBACvB,EAAA;AACA,QAAA,MAAA,CAAO,IAAK,CAAA,IAAA,CAAK,KAAM,CAAA,iBAAA,EAAmB,CAAC,CAAC,CAAA,CAAA;AAC5C,QAAoB,iBAAA,GAAA,CAAA,CAAA;AACpB,QAA2B,wBAAA,GAAA,CAAA,CAAA;AAC3B,QAAmB,gBAAA,GAAA,CAAA,CAAA;AAAA,OACrB;AAAA,KACF;AAEA,IAA4B,wBAAA,IAAA,SAAA,CAAA;AAC5B,IAAoB,gBAAA,IAAA,CAAA,CAAA;AAAA,GACtB;AAGA,EAAA,MAAA,CAAO,KAAK,IAAK,CAAA,KAAA,CAAM,iBAAmB,EAAA,IAAA,CAAK,MAAM,CAAC,CAAA,CAAA;AAEtD,EAAO,OAAA,MAAA,CAAA;AACT;;;;"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@backstage/catalog-client",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.8.0-next.0",
|
|
4
4
|
"description": "An isomorphic client for the catalog backend",
|
|
5
5
|
"backstage": {
|
|
6
6
|
"role": "common-library"
|
|
@@ -49,13 +49,13 @@
|
|
|
49
49
|
"test": "backstage-cli package test"
|
|
50
50
|
},
|
|
51
51
|
"dependencies": {
|
|
52
|
-
"@backstage/catalog-model": "
|
|
53
|
-
"@backstage/errors": "
|
|
52
|
+
"@backstage/catalog-model": "1.7.0",
|
|
53
|
+
"@backstage/errors": "1.2.4",
|
|
54
54
|
"cross-fetch": "^4.0.0",
|
|
55
55
|
"uri-template": "^2.0.0"
|
|
56
56
|
},
|
|
57
57
|
"devDependencies": {
|
|
58
|
-
"@backstage/cli": "
|
|
58
|
+
"@backstage/cli": "0.29.0-next.0",
|
|
59
59
|
"msw": "^1.0.0"
|
|
60
60
|
},
|
|
61
61
|
"module": "./dist/index.esm.js"
|