@backstage/plugin-catalog-backend 1.32.0 → 1.32.1-next.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,48 @@
|
|
|
1
1
|
# @backstage/plugin-catalog-backend
|
|
2
2
|
|
|
3
|
+
## 1.32.1-next.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 7cc4995: Fix for duplicate results in `queryEntities` when providing an `orderField` parameter
|
|
8
|
+
- Updated dependencies
|
|
9
|
+
- @backstage/plugin-catalog-node@1.16.3-next.0
|
|
10
|
+
- @backstage/plugin-search-backend-module-catalog@0.3.3-next.0
|
|
11
|
+
- @backstage/backend-openapi-utils@0.5.1
|
|
12
|
+
- @backstage/backend-plugin-api@1.2.1
|
|
13
|
+
- @backstage/catalog-client@1.9.1
|
|
14
|
+
- @backstage/catalog-model@1.7.3
|
|
15
|
+
- @backstage/config@1.3.2
|
|
16
|
+
- @backstage/errors@1.2.7
|
|
17
|
+
- @backstage/integration@1.16.3-next.0
|
|
18
|
+
- @backstage/types@1.2.1
|
|
19
|
+
- @backstage/plugin-catalog-common@1.1.3
|
|
20
|
+
- @backstage/plugin-events-node@0.4.9
|
|
21
|
+
- @backstage/plugin-permission-common@0.8.4
|
|
22
|
+
- @backstage/plugin-permission-node@0.9.0
|
|
23
|
+
- @backstage/plugin-search-common@1.2.17
|
|
24
|
+
|
|
25
|
+
## 1.32.1-next.0
|
|
26
|
+
|
|
27
|
+
### Patch Changes
|
|
28
|
+
|
|
29
|
+
- Updated dependencies
|
|
30
|
+
- @backstage/integration@1.16.3-next.0
|
|
31
|
+
- @backstage/plugin-permission-node@0.9.0
|
|
32
|
+
- @backstage/backend-openapi-utils@0.5.1
|
|
33
|
+
- @backstage/backend-plugin-api@1.2.1
|
|
34
|
+
- @backstage/catalog-client@1.9.1
|
|
35
|
+
- @backstage/catalog-model@1.7.3
|
|
36
|
+
- @backstage/config@1.3.2
|
|
37
|
+
- @backstage/errors@1.2.7
|
|
38
|
+
- @backstage/types@1.2.1
|
|
39
|
+
- @backstage/plugin-catalog-common@1.1.3
|
|
40
|
+
- @backstage/plugin-catalog-node@1.16.1
|
|
41
|
+
- @backstage/plugin-events-node@0.4.9
|
|
42
|
+
- @backstage/plugin-permission-common@0.8.4
|
|
43
|
+
- @backstage/plugin-search-backend-module-catalog@0.3.2
|
|
44
|
+
- @backstage/plugin-search-common@1.2.17
|
|
45
|
+
|
|
3
46
|
## 1.32.0
|
|
4
47
|
|
|
5
48
|
### Minor Changes
|
|
@@ -171,7 +171,7 @@ class DefaultEntitiesCatalog {
|
|
|
171
171
|
(inner) => {
|
|
172
172
|
inner.from("final_entities").whereNotNull("final_entity");
|
|
173
173
|
if (sortField) {
|
|
174
|
-
inner.leftOuterJoin(
|
|
174
|
+
inner.distinct().leftOuterJoin(
|
|
175
175
|
"search",
|
|
176
176
|
(qb) => qb.on("search.entity_id", "final_entities.entity_id").andOnVal("search.key", sortField.field)
|
|
177
177
|
).select({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DefaultEntitiesCatalog.cjs.js","sources":["../../src/service/DefaultEntitiesCatalog.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 { Entity, stringifyEntityRef } from '@backstage/catalog-model';\nimport { InputError, NotFoundError } from '@backstage/errors';\nimport { Knex } from 'knex';\nimport { chunk as lodashChunk, isEqual } from 'lodash';\nimport { z } from 'zod';\nimport {\n Cursor,\n EntitiesBatchRequest,\n EntitiesBatchResponse,\n EntitiesCatalog,\n EntitiesRequest,\n EntitiesResponse,\n EntityAncestryResponse,\n EntityFacetsRequest,\n EntityFacetsResponse,\n EntityOrder,\n EntityPagination,\n QueryEntitiesRequest,\n QueryEntitiesResponse,\n} from '../catalog/types';\nimport {\n DbFinalEntitiesRow,\n DbPageInfo,\n DbRefreshStateReferencesRow,\n DbRefreshStateRow,\n DbRelationsRow,\n DbSearchRow,\n} from '../database/tables';\nimport { Stitcher } from '../stitching/types';\n\nimport {\n expandLegacyCompoundRelationsInEntity,\n isQueryEntitiesCursorRequest,\n isQueryEntitiesInitialRequest,\n} from './util';\nimport { EntityFilter } from '@backstage/plugin-catalog-node';\nimport { LoggerService } from '@backstage/backend-plugin-api';\nimport { applyEntityFilterToQuery } from './request/applyEntityFilterToQuery';\nimport { processRawEntitiesResult } from './response';\n\nconst DEFAULT_LIMIT = 200;\n\nfunction parsePagination(input?: EntityPagination): EntityPagination {\n if (!input) {\n return {};\n }\n\n let { limit, offset } = input;\n\n if (input.after === undefined) {\n return { limit, offset };\n }\n\n let cursor;\n try {\n const json = Buffer.from(input.after, 'base64').toString('utf8');\n cursor = JSON.parse(json);\n } catch {\n throw new InputError('Malformed after cursor, could not be parsed');\n }\n\n if (cursor.limit !== undefined) {\n if (!Number.isInteger(cursor.limit)) {\n throw new InputError('Malformed after cursor, limit was not an number');\n }\n limit = cursor.limit;\n }\n\n if (cursor.offset !== undefined) {\n if (!Number.isInteger(cursor.offset)) {\n throw new InputError('Malformed after cursor, offset was not a number');\n }\n offset = cursor.offset;\n }\n\n return { limit, offset };\n}\n\nfunction stringifyPagination(\n input: Required<Omit<EntityPagination, 'after'>>,\n): string {\n const { limit, offset } = input;\n const json = JSON.stringify({ limit, offset });\n const base64 = Buffer.from(json, 'utf8').toString('base64');\n return base64;\n}\n\nexport class DefaultEntitiesCatalog implements EntitiesCatalog {\n private readonly database: Knex;\n private readonly logger: LoggerService;\n private readonly stitcher: Stitcher;\n private readonly disableRelationsCompatibility: boolean;\n\n constructor(options: {\n database: Knex;\n logger: LoggerService;\n stitcher: Stitcher;\n disableRelationsCompatibility?: boolean;\n }) {\n this.database = options.database;\n this.logger = options.logger;\n this.stitcher = options.stitcher;\n this.disableRelationsCompatibility = Boolean(\n options.disableRelationsCompatibility,\n );\n }\n\n async entities(request?: EntitiesRequest): Promise<EntitiesResponse> {\n const db = this.database;\n const { limit, offset } = parsePagination(request?.pagination);\n\n let entitiesQuery =\n db<DbFinalEntitiesRow>('final_entities').select('final_entities.*');\n\n request?.order?.forEach(({ field }, index) => {\n const alias = `order_${index}`;\n entitiesQuery = entitiesQuery.leftOuterJoin(\n { [alias]: 'search' },\n function search(inner) {\n inner\n .on(`${alias}.entity_id`, 'final_entities.entity_id')\n .andOn(`${alias}.key`, db.raw('?', [field]));\n },\n );\n });\n\n entitiesQuery = entitiesQuery.whereNotNull('final_entities.final_entity');\n\n if (request?.filter) {\n entitiesQuery = applyEntityFilterToQuery({\n filter: request.filter,\n targetQuery: entitiesQuery,\n onEntityIdField: 'final_entities.entity_id',\n knex: db,\n });\n }\n\n request?.order?.forEach(({ order }, index) => {\n if (db.client.config.client === 'pg') {\n // pg correctly orders by the column value and handling nulls in one go\n entitiesQuery = entitiesQuery.orderBy([\n { column: `order_${index}.value`, order, nulls: 'last' },\n ]);\n } else {\n // sqlite and mysql translate the above statement ONLY into \"order by (value is null) asc\"\n // no matter what the order is, for some reason, so we have to manually add back the statement\n // that translates to \"order by value <order>\" while avoiding to give an order\n entitiesQuery = entitiesQuery.orderBy([\n { column: `order_${index}.value`, order: undefined, nulls: 'last' },\n { column: `order_${index}.value`, order },\n ]);\n }\n });\n\n if (!request?.order) {\n entitiesQuery = entitiesQuery.orderBy('final_entities.entity_ref', 'asc'); // default sort\n } else {\n entitiesQuery.orderBy('final_entities.entity_id', 'asc'); // stable sort\n }\n\n if (limit !== undefined) {\n entitiesQuery = entitiesQuery.limit(limit + 1);\n }\n if (offset !== undefined) {\n entitiesQuery = entitiesQuery.offset(offset);\n }\n\n let rows = await entitiesQuery;\n let pageInfo: DbPageInfo;\n if (limit === undefined || rows.length <= limit) {\n pageInfo = { hasNextPage: false };\n } else {\n rows = rows.slice(0, -1);\n pageInfo = {\n hasNextPage: true,\n endCursor: stringifyPagination({\n limit,\n offset: (offset ?? 0) + limit,\n }),\n };\n }\n\n return {\n entities: processRawEntitiesResult(\n rows.map(r => r.final_entity!),\n this.disableRelationsCompatibility\n ? request?.fields\n : e => {\n expandLegacyCompoundRelationsInEntity(e);\n if (request?.fields) {\n return request.fields(e);\n }\n return e;\n },\n ),\n pageInfo,\n };\n }\n\n async entitiesBatch(\n request: EntitiesBatchRequest,\n ): Promise<EntitiesBatchResponse> {\n const lookup = new Map<string, string>();\n\n for (const chunk of lodashChunk(request.entityRefs, 200)) {\n let query = this.database<DbFinalEntitiesRow>('final_entities')\n .select({\n entityRef: 'final_entities.entity_ref',\n entity: 'final_entities.final_entity',\n })\n .whereIn('final_entities.entity_ref', chunk);\n\n if (request?.filter) {\n query = applyEntityFilterToQuery({\n filter: request.filter,\n targetQuery: query,\n onEntityIdField: 'final_entities.entity_id',\n knex: this.database,\n });\n }\n\n for (const row of await query) {\n lookup.set(row.entityRef, row.entity ? row.entity : null);\n }\n }\n\n const items = request.entityRefs.map(ref => lookup.get(ref) ?? null);\n\n return { items: processRawEntitiesResult(items, request.fields) };\n }\n\n async queryEntities(\n request: QueryEntitiesRequest,\n ): Promise<QueryEntitiesResponse> {\n const limit = request.limit ?? DEFAULT_LIMIT;\n\n const cursor: Omit<Cursor, 'orderFieldValues'> & {\n orderFieldValues?: (string | null)[];\n skipTotalItems: boolean;\n } = {\n orderFields: [],\n isPrevious: false,\n ...parseCursorFromRequest(request),\n };\n\n // For performance reasons we invoke the count query only on the first\n // request. The result is then embedded into the cursor for subsequent\n // requests. Threfore this can be undefined here, but will then get\n // populated further down.\n const shouldComputeTotalItems =\n cursor.totalItems === undefined && !cursor.skipTotalItems;\n const isFetchingBackwards = cursor.isPrevious;\n\n if (cursor.orderFields.length > 1) {\n this.logger.warn(`Only one sort field is supported, ignoring the rest`);\n }\n\n const sortField = cursor.orderFields.at(0);\n\n // The first part of the query builder is a subquery that applies all of the\n // filtering.\n const dbQuery = this.database.with(\n 'filtered',\n ['entity_id', 'final_entity', ...(sortField ? ['value'] : [])],\n inner => {\n inner\n .from<DbFinalEntitiesRow>('final_entities')\n .whereNotNull('final_entity');\n\n if (sortField) {\n inner\n .leftOuterJoin('search', qb =>\n qb\n .on('search.entity_id', 'final_entities.entity_id')\n .andOnVal('search.key', sortField.field),\n )\n .select({\n entity_id: 'final_entities.entity_id',\n final_entity: 'final_entities.final_entity',\n value: 'search.value',\n });\n } else {\n inner.select({\n entity_id: 'final_entities.entity_id',\n final_entity: 'final_entities.final_entity',\n });\n }\n\n // Add regular filters, if given\n if (cursor.filter) {\n applyEntityFilterToQuery({\n filter: cursor.filter,\n targetQuery: inner,\n onEntityIdField: 'final_entities.entity_id',\n knex: this.database,\n });\n }\n\n // Add full text search filters, if given\n const normalizedFullTextFilterTerm =\n cursor.fullTextFilter?.term?.trim();\n const textFilterFields = cursor.fullTextFilter?.fields ?? [\n sortField?.field || 'metadata.uid',\n ];\n if (normalizedFullTextFilterTerm) {\n if (\n textFilterFields.length === 1 &&\n textFilterFields[0] === sortField?.field\n ) {\n // If there is one item, apply the like query to the top level query which is already\n // filtered based on the singular sortField.\n inner.andWhereRaw(\n 'search.value like ?',\n `%${normalizedFullTextFilterTerm.toLocaleLowerCase('en-US')}%`,\n );\n } else {\n const matchQuery = this.database<DbSearchRow>('search')\n .select('search.entity_id')\n // textFilterFields must be lowercased to match searchable keys in database, i.e. spec.profile.displayName -> spec.profile.displayname\n .whereIn(\n 'search.key',\n textFilterFields.map(field => field.toLocaleLowerCase('en-US')),\n )\n .andWhere(function keyFilter() {\n this.andWhereRaw(\n 'search.value like ?',\n `%${normalizedFullTextFilterTerm.toLocaleLowerCase(\n 'en-US',\n )}%`,\n );\n });\n inner.andWhere('final_entities.entity_id', 'in', matchQuery);\n }\n }\n },\n );\n\n // Only pay the cost of counting the number of items if needed\n if (shouldComputeTotalItems) {\n // Note the intentional cross join here. The filtered_count dataset is\n // always exactly one row, so it won't grow the result unnecessarily. But\n // it's also important that there IS at least one row, because even if the\n // filtered dataset is empty, we still want to know the total number of\n // items.\n dbQuery\n .with('filtered_count', ['count'], inner =>\n inner.from('filtered').count('*', { as: 'count' }),\n )\n .fromRaw('filtered_count, filtered')\n .select('count', 'filtered.*');\n } else {\n dbQuery.from('filtered').select('*');\n }\n\n const isOrderingDescending = sortField?.order === 'desc';\n\n // Move forward (or backward) in the set to the correct cursor position\n if (cursor.orderFieldValues) {\n if (cursor.orderFieldValues.length === 2) {\n // The first will be the sortField value, the second the entity_id\n const [first, second] = cursor.orderFieldValues;\n dbQuery.andWhere(function nested() {\n this.where(\n 'filtered.value',\n isFetchingBackwards !== isOrderingDescending ? '<' : '>',\n first,\n )\n .orWhere('filtered.value', '=', first)\n .andWhere(\n 'filtered.entity_id',\n isFetchingBackwards !== isOrderingDescending ? '<' : '>',\n second,\n );\n });\n } else if (cursor.orderFieldValues.length === 1) {\n // This will be the entity_id\n const [first] = cursor.orderFieldValues;\n dbQuery.andWhere('entity_id', isFetchingBackwards ? '<' : '>', first);\n }\n }\n\n // Add the ordering\n let order = sortField?.order ?? 'asc';\n if (isFetchingBackwards) {\n order = invertOrder(order);\n }\n if (this.database.client.config.client === 'pg') {\n // pg correctly orders by the column value and handling nulls in one go\n dbQuery.orderBy([\n ...(sortField\n ? [\n {\n column: 'filtered.value',\n order,\n nulls: 'last',\n },\n ]\n : []),\n {\n column: 'filtered.entity_id',\n order,\n },\n ]);\n } else {\n // sqlite and mysql translate the above statement ONLY into \"order by (value is null) asc\"\n // no matter what the order is, for some reason, so we have to manually add back the statement\n // that translates to \"order by value <order>\" while avoiding to give an order\n dbQuery.orderBy([\n ...(sortField\n ? [\n {\n column: 'filtered.value',\n order: undefined,\n nulls: 'last',\n },\n {\n column: 'filtered.value',\n order,\n },\n ]\n : []),\n {\n column: 'filtered.entity_id',\n order,\n },\n ]);\n }\n\n // Apply a manually set initial offset\n if (\n isQueryEntitiesInitialRequest(request) &&\n request.offset !== undefined\n ) {\n dbQuery.offset(request.offset);\n }\n // fetch an extra item to check if there are more items.\n dbQuery.limit(isFetchingBackwards ? limit : limit + 1);\n\n const rows = shouldComputeTotalItems || limit > 0 ? await dbQuery : [];\n\n let totalItems: number;\n if (cursor.totalItems !== undefined) {\n totalItems = cursor.totalItems;\n } else if (cursor.skipTotalItems) {\n totalItems = 0;\n } else if (rows.length) {\n totalItems = Number(rows[0].count);\n } else {\n totalItems = 0;\n }\n\n if (isFetchingBackwards) {\n rows.reverse();\n }\n const hasMoreResults =\n limit > 0 && (isFetchingBackwards || rows.length > limit);\n\n // discard the extra item only when fetching forward.\n if (rows.length > limit) {\n rows.length -= 1;\n }\n\n const isInitialRequest = cursor.firstSortFieldValues === undefined;\n\n const firstRow = rows[0];\n const lastRow = rows[rows.length - 1];\n\n const firstSortFieldValues =\n cursor.firstSortFieldValues || sortFieldsFromRow(firstRow, sortField);\n\n const nextCursor: Cursor | undefined = hasMoreResults\n ? {\n ...cursor,\n orderFieldValues: sortFieldsFromRow(lastRow, sortField),\n firstSortFieldValues,\n isPrevious: false,\n totalItems,\n }\n : undefined;\n\n const prevCursor: Cursor | undefined =\n !isInitialRequest &&\n rows.length > 0 &&\n !isEqual(\n sortFieldsFromRow(firstRow, sortField),\n cursor.firstSortFieldValues,\n )\n ? {\n ...cursor,\n orderFieldValues: sortFieldsFromRow(firstRow, sortField),\n firstSortFieldValues: cursor.firstSortFieldValues,\n isPrevious: true,\n totalItems,\n }\n : undefined;\n\n return {\n items: processRawEntitiesResult(\n rows.map(r => r.final_entity!),\n request.fields,\n ),\n pageInfo: {\n ...(!!prevCursor && { prevCursor }),\n ...(!!nextCursor && { nextCursor }),\n },\n totalItems,\n };\n }\n\n async removeEntityByUid(uid: string): Promise<void> {\n const dbConfig = this.database.client.config;\n\n // Clear the hashed state of the immediate parents of the deleted entity.\n // This makes sure that when they get reprocessed, their output is written\n // down again. The reason for wanting to do this, is that if the user\n // deletes entities that ARE still emitted by the parent, the parent\n // processing will still generate the same output hash as always, which\n // means it'll never try to write down the children again (it assumes that\n // they already exist). This means that without the code below, the database\n // never \"heals\" from accidental deletes.\n if (dbConfig.client.includes('mysql')) {\n // MySQL doesn't support the syntax we need to do this in a single query,\n // http://dev.mysql.com/doc/refman/5.6/en/update.html\n const results = await this.database<DbRefreshStateRow>('refresh_state')\n .select('entity_id')\n .whereIn('entity_ref', function parents(builder) {\n return builder\n .from<DbRefreshStateRow>('refresh_state')\n .innerJoin<DbRefreshStateReferencesRow>(\n 'refresh_state_references',\n {\n 'refresh_state_references.target_entity_ref':\n 'refresh_state.entity_ref',\n },\n )\n .where('refresh_state.entity_id', '=', uid)\n .select('refresh_state_references.source_entity_ref');\n });\n await this.database<DbRefreshStateRow>('refresh_state')\n .update({\n result_hash: 'child-was-deleted',\n next_update_at: this.database.fn.now(),\n })\n .whereIn(\n 'entity_id',\n results.map(key => key.entity_id),\n );\n } else {\n await this.database<DbRefreshStateRow>('refresh_state')\n .update({\n result_hash: 'child-was-deleted',\n next_update_at: this.database.fn.now(),\n })\n .whereIn('entity_ref', function parents(builder) {\n return builder\n .from<DbRefreshStateRow>('refresh_state')\n .innerJoin<DbRefreshStateReferencesRow>(\n 'refresh_state_references',\n {\n 'refresh_state_references.target_entity_ref':\n 'refresh_state.entity_ref',\n },\n )\n .where('refresh_state.entity_id', '=', uid)\n .select('refresh_state_references.source_entity_ref');\n });\n }\n\n // Stitch the entities that the deleted one had relations to. If we do not\n // do this, the entities in the other end of the relations will still look\n // like they have a relation to the entity that was deleted, despite not\n // having any corresponding rows in the relations table.\n const relationPeers = await this.database\n .from<DbRelationsRow>('relations')\n .innerJoin<DbRefreshStateReferencesRow>('refresh_state', {\n 'refresh_state.entity_ref': 'relations.target_entity_ref',\n })\n .where('relations.originating_entity_id', '=', uid)\n .andWhere('refresh_state.entity_id', '!=', uid)\n .select({ ref: 'relations.target_entity_ref' })\n .union(other =>\n other\n .from<DbRelationsRow>('relations')\n .innerJoin<DbRefreshStateReferencesRow>('refresh_state', {\n 'refresh_state.entity_ref': 'relations.source_entity_ref',\n })\n .where('relations.originating_entity_id', '=', uid)\n .andWhere('refresh_state.entity_id', '!=', uid)\n .select({ ref: 'relations.source_entity_ref' }),\n );\n\n await this.database<DbRefreshStateRow>('refresh_state')\n .where('entity_id', uid)\n .delete();\n\n await this.stitcher.stitch({\n entityRefs: new Set(relationPeers.map(p => p.ref)),\n });\n }\n\n async entityAncestry(rootRef: string): Promise<EntityAncestryResponse> {\n const [rootRow] = await this.database<DbFinalEntitiesRow>('final_entities')\n .where('final_entities.entity_ref', '=', rootRef)\n .select({\n entityJson: 'final_entities.final_entity',\n });\n\n if (!rootRow) {\n throw new NotFoundError(`No such entity ${rootRef}`);\n }\n\n const rootEntity = JSON.parse(rootRow.entityJson) as Entity;\n const seenEntityRefs = new Set<string>();\n const todo = new Array<Entity>();\n const items = new Array<{ entity: Entity; parentEntityRefs: string[] }>();\n\n for (\n let current: Entity | undefined = rootEntity;\n current;\n current = todo.pop()\n ) {\n const currentRef = stringifyEntityRef(current);\n seenEntityRefs.add(currentRef);\n\n const parentRows = await this.database<DbRefreshStateReferencesRow>(\n 'refresh_state_references',\n )\n .innerJoin<DbFinalEntitiesRow>('final_entities', {\n 'refresh_state_references.source_entity_ref':\n 'final_entities.entity_ref',\n })\n .where('refresh_state_references.target_entity_ref', '=', currentRef)\n .select({\n parentEntityRef: 'final_entities.entity_ref',\n parentEntityJson: 'final_entities.final_entity',\n });\n\n const parentRefs: string[] = [];\n for (const { parentEntityRef, parentEntityJson } of parentRows) {\n parentRefs.push(parentEntityRef);\n if (!seenEntityRefs.has(parentEntityRef)) {\n seenEntityRefs.add(parentEntityRef);\n todo.push(JSON.parse(parentEntityJson));\n }\n }\n\n items.push({\n entity: current,\n parentEntityRefs: parentRefs,\n });\n }\n\n return {\n rootEntityRef: stringifyEntityRef(rootEntity),\n items,\n };\n }\n\n async facets(request: EntityFacetsRequest): Promise<EntityFacetsResponse> {\n const query = this.database<DbSearchRow>('search')\n .whereIn(\n 'search.key',\n request.facets.map(f => f.toLocaleLowerCase('en-US')),\n )\n .whereNotNull('search.original_value')\n .select({\n facet: 'search.key',\n value: 'search.original_value',\n count: this.database.raw('count(*)'),\n })\n .groupBy(['search.key', 'search.original_value']);\n\n if (request.filter) {\n applyEntityFilterToQuery({\n filter: request.filter,\n targetQuery: query,\n onEntityIdField: 'search.entity_id',\n knex: this.database,\n });\n }\n\n const rows = await query;\n\n const facets: EntityFacetsResponse['facets'] = {};\n for (const facet of request.facets) {\n const facetLowercase = facet.toLocaleLowerCase('en-US');\n facets[facet] = rows\n .filter(row => row.facet === facetLowercase)\n .map(row => ({\n value: String(row.value),\n count: Number(row.count),\n }));\n }\n\n return { facets };\n }\n}\n\nconst entityFilterParser: z.ZodSchema<EntityFilter> = z.lazy(() =>\n z\n .object({\n key: z.string(),\n values: z.array(z.string()).optional(),\n })\n .or(z.object({ not: entityFilterParser }))\n .or(z.object({ anyOf: z.array(entityFilterParser) }))\n .or(z.object({ allOf: z.array(entityFilterParser) })),\n);\n\nexport const cursorParser: z.ZodSchema<Cursor> = z.object({\n orderFields: z.array(\n z.object({ field: z.string(), order: z.enum(['asc', 'desc']) }),\n ),\n orderFieldValues: z.array(z.string().or(z.null())),\n filter: entityFilterParser.optional(),\n isPrevious: z.boolean(),\n query: z.string().optional(),\n firstSortFieldValues: z.array(z.string().or(z.null())).optional(),\n totalItems: z.number().optional(),\n});\n\nfunction parseCursorFromRequest(\n request?: QueryEntitiesRequest,\n): Partial<Cursor> & { skipTotalItems: boolean } {\n if (isQueryEntitiesInitialRequest(request)) {\n const {\n filter,\n orderFields: sortFields = [],\n fullTextFilter,\n skipTotalItems = false,\n } = request;\n return { filter, orderFields: sortFields, fullTextFilter, skipTotalItems };\n }\n if (isQueryEntitiesCursorRequest(request)) {\n return {\n ...request.cursor,\n // Doesn't matter here\n skipTotalItems: false,\n };\n }\n return {\n skipTotalItems: false,\n };\n}\n\nfunction invertOrder(order: EntityOrder['order']) {\n return order === 'asc' ? 'desc' : 'asc';\n}\n\nfunction sortFieldsFromRow(\n row: DbSearchRow & DbFinalEntitiesRow,\n sortField?: EntityOrder | undefined,\n) {\n return sortField ? [row?.value, row?.entity_id] : [row?.entity_id];\n}\n"],"names":["InputError","applyEntityFilterToQuery","processRawEntitiesResult","expandLegacyCompoundRelationsInEntity","lodashChunk","isQueryEntitiesInitialRequest","isEqual","NotFoundError","stringifyEntityRef","z","isQueryEntitiesCursorRequest"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"DefaultEntitiesCatalog.cjs.js","sources":["../../src/service/DefaultEntitiesCatalog.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 { Entity, stringifyEntityRef } from '@backstage/catalog-model';\nimport { InputError, NotFoundError } from '@backstage/errors';\nimport { Knex } from 'knex';\nimport { chunk as lodashChunk, isEqual } from 'lodash';\nimport { z } from 'zod';\nimport {\n Cursor,\n EntitiesBatchRequest,\n EntitiesBatchResponse,\n EntitiesCatalog,\n EntitiesRequest,\n EntitiesResponse,\n EntityAncestryResponse,\n EntityFacetsRequest,\n EntityFacetsResponse,\n EntityOrder,\n EntityPagination,\n QueryEntitiesRequest,\n QueryEntitiesResponse,\n} from '../catalog/types';\nimport {\n DbFinalEntitiesRow,\n DbPageInfo,\n DbRefreshStateReferencesRow,\n DbRefreshStateRow,\n DbRelationsRow,\n DbSearchRow,\n} from '../database/tables';\nimport { Stitcher } from '../stitching/types';\n\nimport {\n expandLegacyCompoundRelationsInEntity,\n isQueryEntitiesCursorRequest,\n isQueryEntitiesInitialRequest,\n} from './util';\nimport { EntityFilter } from '@backstage/plugin-catalog-node';\nimport { LoggerService } from '@backstage/backend-plugin-api';\nimport { applyEntityFilterToQuery } from './request/applyEntityFilterToQuery';\nimport { processRawEntitiesResult } from './response';\n\nconst DEFAULT_LIMIT = 200;\n\nfunction parsePagination(input?: EntityPagination): EntityPagination {\n if (!input) {\n return {};\n }\n\n let { limit, offset } = input;\n\n if (input.after === undefined) {\n return { limit, offset };\n }\n\n let cursor;\n try {\n const json = Buffer.from(input.after, 'base64').toString('utf8');\n cursor = JSON.parse(json);\n } catch {\n throw new InputError('Malformed after cursor, could not be parsed');\n }\n\n if (cursor.limit !== undefined) {\n if (!Number.isInteger(cursor.limit)) {\n throw new InputError('Malformed after cursor, limit was not an number');\n }\n limit = cursor.limit;\n }\n\n if (cursor.offset !== undefined) {\n if (!Number.isInteger(cursor.offset)) {\n throw new InputError('Malformed after cursor, offset was not a number');\n }\n offset = cursor.offset;\n }\n\n return { limit, offset };\n}\n\nfunction stringifyPagination(\n input: Required<Omit<EntityPagination, 'after'>>,\n): string {\n const { limit, offset } = input;\n const json = JSON.stringify({ limit, offset });\n const base64 = Buffer.from(json, 'utf8').toString('base64');\n return base64;\n}\n\nexport class DefaultEntitiesCatalog implements EntitiesCatalog {\n private readonly database: Knex;\n private readonly logger: LoggerService;\n private readonly stitcher: Stitcher;\n private readonly disableRelationsCompatibility: boolean;\n\n constructor(options: {\n database: Knex;\n logger: LoggerService;\n stitcher: Stitcher;\n disableRelationsCompatibility?: boolean;\n }) {\n this.database = options.database;\n this.logger = options.logger;\n this.stitcher = options.stitcher;\n this.disableRelationsCompatibility = Boolean(\n options.disableRelationsCompatibility,\n );\n }\n\n async entities(request?: EntitiesRequest): Promise<EntitiesResponse> {\n const db = this.database;\n const { limit, offset } = parsePagination(request?.pagination);\n\n let entitiesQuery =\n db<DbFinalEntitiesRow>('final_entities').select('final_entities.*');\n\n request?.order?.forEach(({ field }, index) => {\n const alias = `order_${index}`;\n entitiesQuery = entitiesQuery.leftOuterJoin(\n { [alias]: 'search' },\n function search(inner) {\n inner\n .on(`${alias}.entity_id`, 'final_entities.entity_id')\n .andOn(`${alias}.key`, db.raw('?', [field]));\n },\n );\n });\n\n entitiesQuery = entitiesQuery.whereNotNull('final_entities.final_entity');\n\n if (request?.filter) {\n entitiesQuery = applyEntityFilterToQuery({\n filter: request.filter,\n targetQuery: entitiesQuery,\n onEntityIdField: 'final_entities.entity_id',\n knex: db,\n });\n }\n\n request?.order?.forEach(({ order }, index) => {\n if (db.client.config.client === 'pg') {\n // pg correctly orders by the column value and handling nulls in one go\n entitiesQuery = entitiesQuery.orderBy([\n { column: `order_${index}.value`, order, nulls: 'last' },\n ]);\n } else {\n // sqlite and mysql translate the above statement ONLY into \"order by (value is null) asc\"\n // no matter what the order is, for some reason, so we have to manually add back the statement\n // that translates to \"order by value <order>\" while avoiding to give an order\n entitiesQuery = entitiesQuery.orderBy([\n { column: `order_${index}.value`, order: undefined, nulls: 'last' },\n { column: `order_${index}.value`, order },\n ]);\n }\n });\n\n if (!request?.order) {\n entitiesQuery = entitiesQuery.orderBy('final_entities.entity_ref', 'asc'); // default sort\n } else {\n entitiesQuery.orderBy('final_entities.entity_id', 'asc'); // stable sort\n }\n\n if (limit !== undefined) {\n entitiesQuery = entitiesQuery.limit(limit + 1);\n }\n if (offset !== undefined) {\n entitiesQuery = entitiesQuery.offset(offset);\n }\n\n let rows = await entitiesQuery;\n let pageInfo: DbPageInfo;\n if (limit === undefined || rows.length <= limit) {\n pageInfo = { hasNextPage: false };\n } else {\n rows = rows.slice(0, -1);\n pageInfo = {\n hasNextPage: true,\n endCursor: stringifyPagination({\n limit,\n offset: (offset ?? 0) + limit,\n }),\n };\n }\n\n return {\n entities: processRawEntitiesResult(\n rows.map(r => r.final_entity!),\n this.disableRelationsCompatibility\n ? request?.fields\n : e => {\n expandLegacyCompoundRelationsInEntity(e);\n if (request?.fields) {\n return request.fields(e);\n }\n return e;\n },\n ),\n pageInfo,\n };\n }\n\n async entitiesBatch(\n request: EntitiesBatchRequest,\n ): Promise<EntitiesBatchResponse> {\n const lookup = new Map<string, string>();\n\n for (const chunk of lodashChunk(request.entityRefs, 200)) {\n let query = this.database<DbFinalEntitiesRow>('final_entities')\n .select({\n entityRef: 'final_entities.entity_ref',\n entity: 'final_entities.final_entity',\n })\n .whereIn('final_entities.entity_ref', chunk);\n\n if (request?.filter) {\n query = applyEntityFilterToQuery({\n filter: request.filter,\n targetQuery: query,\n onEntityIdField: 'final_entities.entity_id',\n knex: this.database,\n });\n }\n\n for (const row of await query) {\n lookup.set(row.entityRef, row.entity ? row.entity : null);\n }\n }\n\n const items = request.entityRefs.map(ref => lookup.get(ref) ?? null);\n\n return { items: processRawEntitiesResult(items, request.fields) };\n }\n\n async queryEntities(\n request: QueryEntitiesRequest,\n ): Promise<QueryEntitiesResponse> {\n const limit = request.limit ?? DEFAULT_LIMIT;\n\n const cursor: Omit<Cursor, 'orderFieldValues'> & {\n orderFieldValues?: (string | null)[];\n skipTotalItems: boolean;\n } = {\n orderFields: [],\n isPrevious: false,\n ...parseCursorFromRequest(request),\n };\n\n // For performance reasons we invoke the count query only on the first\n // request. The result is then embedded into the cursor for subsequent\n // requests. Threfore this can be undefined here, but will then get\n // populated further down.\n const shouldComputeTotalItems =\n cursor.totalItems === undefined && !cursor.skipTotalItems;\n const isFetchingBackwards = cursor.isPrevious;\n\n if (cursor.orderFields.length > 1) {\n this.logger.warn(`Only one sort field is supported, ignoring the rest`);\n }\n\n const sortField = cursor.orderFields.at(0);\n\n // The first part of the query builder is a subquery that applies all of the\n // filtering.\n const dbQuery = this.database.with(\n 'filtered',\n ['entity_id', 'final_entity', ...(sortField ? ['value'] : [])],\n inner => {\n inner\n .from<DbFinalEntitiesRow>('final_entities')\n .whereNotNull('final_entity');\n\n if (sortField) {\n inner\n .distinct()\n .leftOuterJoin('search', qb =>\n qb\n .on('search.entity_id', 'final_entities.entity_id')\n .andOnVal('search.key', sortField.field),\n )\n .select({\n entity_id: 'final_entities.entity_id',\n final_entity: 'final_entities.final_entity',\n value: 'search.value',\n });\n } else {\n inner.select({\n entity_id: 'final_entities.entity_id',\n final_entity: 'final_entities.final_entity',\n });\n }\n\n // Add regular filters, if given\n if (cursor.filter) {\n applyEntityFilterToQuery({\n filter: cursor.filter,\n targetQuery: inner,\n onEntityIdField: 'final_entities.entity_id',\n knex: this.database,\n });\n }\n\n // Add full text search filters, if given\n const normalizedFullTextFilterTerm =\n cursor.fullTextFilter?.term?.trim();\n const textFilterFields = cursor.fullTextFilter?.fields ?? [\n sortField?.field || 'metadata.uid',\n ];\n if (normalizedFullTextFilterTerm) {\n if (\n textFilterFields.length === 1 &&\n textFilterFields[0] === sortField?.field\n ) {\n // If there is one item, apply the like query to the top level query which is already\n // filtered based on the singular sortField.\n inner.andWhereRaw(\n 'search.value like ?',\n `%${normalizedFullTextFilterTerm.toLocaleLowerCase('en-US')}%`,\n );\n } else {\n const matchQuery = this.database<DbSearchRow>('search')\n .select('search.entity_id')\n // textFilterFields must be lowercased to match searchable keys in database, i.e. spec.profile.displayName -> spec.profile.displayname\n .whereIn(\n 'search.key',\n textFilterFields.map(field => field.toLocaleLowerCase('en-US')),\n )\n .andWhere(function keyFilter() {\n this.andWhereRaw(\n 'search.value like ?',\n `%${normalizedFullTextFilterTerm.toLocaleLowerCase(\n 'en-US',\n )}%`,\n );\n });\n inner.andWhere('final_entities.entity_id', 'in', matchQuery);\n }\n }\n },\n );\n\n // Only pay the cost of counting the number of items if needed\n if (shouldComputeTotalItems) {\n // Note the intentional cross join here. The filtered_count dataset is\n // always exactly one row, so it won't grow the result unnecessarily. But\n // it's also important that there IS at least one row, because even if the\n // filtered dataset is empty, we still want to know the total number of\n // items.\n dbQuery\n .with('filtered_count', ['count'], inner =>\n inner.from('filtered').count('*', { as: 'count' }),\n )\n .fromRaw('filtered_count, filtered')\n .select('count', 'filtered.*');\n } else {\n dbQuery.from('filtered').select('*');\n }\n\n const isOrderingDescending = sortField?.order === 'desc';\n\n // Move forward (or backward) in the set to the correct cursor position\n if (cursor.orderFieldValues) {\n if (cursor.orderFieldValues.length === 2) {\n // The first will be the sortField value, the second the entity_id\n const [first, second] = cursor.orderFieldValues;\n dbQuery.andWhere(function nested() {\n this.where(\n 'filtered.value',\n isFetchingBackwards !== isOrderingDescending ? '<' : '>',\n first,\n )\n .orWhere('filtered.value', '=', first)\n .andWhere(\n 'filtered.entity_id',\n isFetchingBackwards !== isOrderingDescending ? '<' : '>',\n second,\n );\n });\n } else if (cursor.orderFieldValues.length === 1) {\n // This will be the entity_id\n const [first] = cursor.orderFieldValues;\n dbQuery.andWhere('entity_id', isFetchingBackwards ? '<' : '>', first);\n }\n }\n\n // Add the ordering\n let order = sortField?.order ?? 'asc';\n if (isFetchingBackwards) {\n order = invertOrder(order);\n }\n if (this.database.client.config.client === 'pg') {\n // pg correctly orders by the column value and handling nulls in one go\n dbQuery.orderBy([\n ...(sortField\n ? [\n {\n column: 'filtered.value',\n order,\n nulls: 'last',\n },\n ]\n : []),\n {\n column: 'filtered.entity_id',\n order,\n },\n ]);\n } else {\n // sqlite and mysql translate the above statement ONLY into \"order by (value is null) asc\"\n // no matter what the order is, for some reason, so we have to manually add back the statement\n // that translates to \"order by value <order>\" while avoiding to give an order\n dbQuery.orderBy([\n ...(sortField\n ? [\n {\n column: 'filtered.value',\n order: undefined,\n nulls: 'last',\n },\n {\n column: 'filtered.value',\n order,\n },\n ]\n : []),\n {\n column: 'filtered.entity_id',\n order,\n },\n ]);\n }\n\n // Apply a manually set initial offset\n if (\n isQueryEntitiesInitialRequest(request) &&\n request.offset !== undefined\n ) {\n dbQuery.offset(request.offset);\n }\n // fetch an extra item to check if there are more items.\n dbQuery.limit(isFetchingBackwards ? limit : limit + 1);\n\n const rows = shouldComputeTotalItems || limit > 0 ? await dbQuery : [];\n\n let totalItems: number;\n if (cursor.totalItems !== undefined) {\n totalItems = cursor.totalItems;\n } else if (cursor.skipTotalItems) {\n totalItems = 0;\n } else if (rows.length) {\n totalItems = Number(rows[0].count);\n } else {\n totalItems = 0;\n }\n\n if (isFetchingBackwards) {\n rows.reverse();\n }\n const hasMoreResults =\n limit > 0 && (isFetchingBackwards || rows.length > limit);\n\n // discard the extra item only when fetching forward.\n if (rows.length > limit) {\n rows.length -= 1;\n }\n\n const isInitialRequest = cursor.firstSortFieldValues === undefined;\n\n const firstRow = rows[0];\n const lastRow = rows[rows.length - 1];\n\n const firstSortFieldValues =\n cursor.firstSortFieldValues || sortFieldsFromRow(firstRow, sortField);\n\n const nextCursor: Cursor | undefined = hasMoreResults\n ? {\n ...cursor,\n orderFieldValues: sortFieldsFromRow(lastRow, sortField),\n firstSortFieldValues,\n isPrevious: false,\n totalItems,\n }\n : undefined;\n\n const prevCursor: Cursor | undefined =\n !isInitialRequest &&\n rows.length > 0 &&\n !isEqual(\n sortFieldsFromRow(firstRow, sortField),\n cursor.firstSortFieldValues,\n )\n ? {\n ...cursor,\n orderFieldValues: sortFieldsFromRow(firstRow, sortField),\n firstSortFieldValues: cursor.firstSortFieldValues,\n isPrevious: true,\n totalItems,\n }\n : undefined;\n\n return {\n items: processRawEntitiesResult(\n rows.map(r => r.final_entity!),\n request.fields,\n ),\n pageInfo: {\n ...(!!prevCursor && { prevCursor }),\n ...(!!nextCursor && { nextCursor }),\n },\n totalItems,\n };\n }\n\n async removeEntityByUid(uid: string): Promise<void> {\n const dbConfig = this.database.client.config;\n\n // Clear the hashed state of the immediate parents of the deleted entity.\n // This makes sure that when they get reprocessed, their output is written\n // down again. The reason for wanting to do this, is that if the user\n // deletes entities that ARE still emitted by the parent, the parent\n // processing will still generate the same output hash as always, which\n // means it'll never try to write down the children again (it assumes that\n // they already exist). This means that without the code below, the database\n // never \"heals\" from accidental deletes.\n if (dbConfig.client.includes('mysql')) {\n // MySQL doesn't support the syntax we need to do this in a single query,\n // http://dev.mysql.com/doc/refman/5.6/en/update.html\n const results = await this.database<DbRefreshStateRow>('refresh_state')\n .select('entity_id')\n .whereIn('entity_ref', function parents(builder) {\n return builder\n .from<DbRefreshStateRow>('refresh_state')\n .innerJoin<DbRefreshStateReferencesRow>(\n 'refresh_state_references',\n {\n 'refresh_state_references.target_entity_ref':\n 'refresh_state.entity_ref',\n },\n )\n .where('refresh_state.entity_id', '=', uid)\n .select('refresh_state_references.source_entity_ref');\n });\n await this.database<DbRefreshStateRow>('refresh_state')\n .update({\n result_hash: 'child-was-deleted',\n next_update_at: this.database.fn.now(),\n })\n .whereIn(\n 'entity_id',\n results.map(key => key.entity_id),\n );\n } else {\n await this.database<DbRefreshStateRow>('refresh_state')\n .update({\n result_hash: 'child-was-deleted',\n next_update_at: this.database.fn.now(),\n })\n .whereIn('entity_ref', function parents(builder) {\n return builder\n .from<DbRefreshStateRow>('refresh_state')\n .innerJoin<DbRefreshStateReferencesRow>(\n 'refresh_state_references',\n {\n 'refresh_state_references.target_entity_ref':\n 'refresh_state.entity_ref',\n },\n )\n .where('refresh_state.entity_id', '=', uid)\n .select('refresh_state_references.source_entity_ref');\n });\n }\n\n // Stitch the entities that the deleted one had relations to. If we do not\n // do this, the entities in the other end of the relations will still look\n // like they have a relation to the entity that was deleted, despite not\n // having any corresponding rows in the relations table.\n const relationPeers = await this.database\n .from<DbRelationsRow>('relations')\n .innerJoin<DbRefreshStateReferencesRow>('refresh_state', {\n 'refresh_state.entity_ref': 'relations.target_entity_ref',\n })\n .where('relations.originating_entity_id', '=', uid)\n .andWhere('refresh_state.entity_id', '!=', uid)\n .select({ ref: 'relations.target_entity_ref' })\n .union(other =>\n other\n .from<DbRelationsRow>('relations')\n .innerJoin<DbRefreshStateReferencesRow>('refresh_state', {\n 'refresh_state.entity_ref': 'relations.source_entity_ref',\n })\n .where('relations.originating_entity_id', '=', uid)\n .andWhere('refresh_state.entity_id', '!=', uid)\n .select({ ref: 'relations.source_entity_ref' }),\n );\n\n await this.database<DbRefreshStateRow>('refresh_state')\n .where('entity_id', uid)\n .delete();\n\n await this.stitcher.stitch({\n entityRefs: new Set(relationPeers.map(p => p.ref)),\n });\n }\n\n async entityAncestry(rootRef: string): Promise<EntityAncestryResponse> {\n const [rootRow] = await this.database<DbFinalEntitiesRow>('final_entities')\n .where('final_entities.entity_ref', '=', rootRef)\n .select({\n entityJson: 'final_entities.final_entity',\n });\n\n if (!rootRow) {\n throw new NotFoundError(`No such entity ${rootRef}`);\n }\n\n const rootEntity = JSON.parse(rootRow.entityJson) as Entity;\n const seenEntityRefs = new Set<string>();\n const todo = new Array<Entity>();\n const items = new Array<{ entity: Entity; parentEntityRefs: string[] }>();\n\n for (\n let current: Entity | undefined = rootEntity;\n current;\n current = todo.pop()\n ) {\n const currentRef = stringifyEntityRef(current);\n seenEntityRefs.add(currentRef);\n\n const parentRows = await this.database<DbRefreshStateReferencesRow>(\n 'refresh_state_references',\n )\n .innerJoin<DbFinalEntitiesRow>('final_entities', {\n 'refresh_state_references.source_entity_ref':\n 'final_entities.entity_ref',\n })\n .where('refresh_state_references.target_entity_ref', '=', currentRef)\n .select({\n parentEntityRef: 'final_entities.entity_ref',\n parentEntityJson: 'final_entities.final_entity',\n });\n\n const parentRefs: string[] = [];\n for (const { parentEntityRef, parentEntityJson } of parentRows) {\n parentRefs.push(parentEntityRef);\n if (!seenEntityRefs.has(parentEntityRef)) {\n seenEntityRefs.add(parentEntityRef);\n todo.push(JSON.parse(parentEntityJson));\n }\n }\n\n items.push({\n entity: current,\n parentEntityRefs: parentRefs,\n });\n }\n\n return {\n rootEntityRef: stringifyEntityRef(rootEntity),\n items,\n };\n }\n\n async facets(request: EntityFacetsRequest): Promise<EntityFacetsResponse> {\n const query = this.database<DbSearchRow>('search')\n .whereIn(\n 'search.key',\n request.facets.map(f => f.toLocaleLowerCase('en-US')),\n )\n .whereNotNull('search.original_value')\n .select({\n facet: 'search.key',\n value: 'search.original_value',\n count: this.database.raw('count(*)'),\n })\n .groupBy(['search.key', 'search.original_value']);\n\n if (request.filter) {\n applyEntityFilterToQuery({\n filter: request.filter,\n targetQuery: query,\n onEntityIdField: 'search.entity_id',\n knex: this.database,\n });\n }\n\n const rows = await query;\n\n const facets: EntityFacetsResponse['facets'] = {};\n for (const facet of request.facets) {\n const facetLowercase = facet.toLocaleLowerCase('en-US');\n facets[facet] = rows\n .filter(row => row.facet === facetLowercase)\n .map(row => ({\n value: String(row.value),\n count: Number(row.count),\n }));\n }\n\n return { facets };\n }\n}\n\nconst entityFilterParser: z.ZodSchema<EntityFilter> = z.lazy(() =>\n z\n .object({\n key: z.string(),\n values: z.array(z.string()).optional(),\n })\n .or(z.object({ not: entityFilterParser }))\n .or(z.object({ anyOf: z.array(entityFilterParser) }))\n .or(z.object({ allOf: z.array(entityFilterParser) })),\n);\n\nexport const cursorParser: z.ZodSchema<Cursor> = z.object({\n orderFields: z.array(\n z.object({ field: z.string(), order: z.enum(['asc', 'desc']) }),\n ),\n orderFieldValues: z.array(z.string().or(z.null())),\n filter: entityFilterParser.optional(),\n isPrevious: z.boolean(),\n query: z.string().optional(),\n firstSortFieldValues: z.array(z.string().or(z.null())).optional(),\n totalItems: z.number().optional(),\n});\n\nfunction parseCursorFromRequest(\n request?: QueryEntitiesRequest,\n): Partial<Cursor> & { skipTotalItems: boolean } {\n if (isQueryEntitiesInitialRequest(request)) {\n const {\n filter,\n orderFields: sortFields = [],\n fullTextFilter,\n skipTotalItems = false,\n } = request;\n return { filter, orderFields: sortFields, fullTextFilter, skipTotalItems };\n }\n if (isQueryEntitiesCursorRequest(request)) {\n return {\n ...request.cursor,\n // Doesn't matter here\n skipTotalItems: false,\n };\n }\n return {\n skipTotalItems: false,\n };\n}\n\nfunction invertOrder(order: EntityOrder['order']) {\n return order === 'asc' ? 'desc' : 'asc';\n}\n\nfunction sortFieldsFromRow(\n row: DbSearchRow & DbFinalEntitiesRow,\n sortField?: EntityOrder | undefined,\n) {\n return sortField ? [row?.value, row?.entity_id] : [row?.entity_id];\n}\n"],"names":["InputError","applyEntityFilterToQuery","processRawEntitiesResult","expandLegacyCompoundRelationsInEntity","lodashChunk","isQueryEntitiesInitialRequest","isEqual","NotFoundError","stringifyEntityRef","z","isQueryEntitiesCursorRequest"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@backstage/plugin-catalog-backend",
|
|
3
|
-
"version": "1.32.
|
|
3
|
+
"version": "1.32.1-next.1",
|
|
4
4
|
"description": "The Backstage backend plugin that provides the Backstage catalog",
|
|
5
5
|
"backstage": {
|
|
6
6
|
"role": "backend-plugin",
|
|
@@ -49,11 +49,11 @@
|
|
|
49
49
|
"types": "./dist/index.d.ts",
|
|
50
50
|
"typesVersions": {
|
|
51
51
|
"*": {
|
|
52
|
-
"*": [
|
|
53
|
-
"dist/index.d.ts"
|
|
54
|
-
],
|
|
55
52
|
"alpha": [
|
|
56
53
|
"dist/alpha.d.ts"
|
|
54
|
+
],
|
|
55
|
+
"package.json": [
|
|
56
|
+
"package.json"
|
|
57
57
|
]
|
|
58
58
|
}
|
|
59
59
|
},
|
|
@@ -76,21 +76,21 @@
|
|
|
76
76
|
},
|
|
77
77
|
"dependencies": {
|
|
78
78
|
"@backstage/backend-common": "^0.25.0",
|
|
79
|
-
"@backstage/backend-openapi-utils": "
|
|
80
|
-
"@backstage/backend-plugin-api": "
|
|
81
|
-
"@backstage/catalog-client": "
|
|
82
|
-
"@backstage/catalog-model": "
|
|
83
|
-
"@backstage/config": "
|
|
84
|
-
"@backstage/errors": "
|
|
85
|
-
"@backstage/integration": "
|
|
86
|
-
"@backstage/plugin-catalog-common": "
|
|
87
|
-
"@backstage/plugin-catalog-node": "
|
|
88
|
-
"@backstage/plugin-events-node": "
|
|
89
|
-
"@backstage/plugin-permission-common": "
|
|
90
|
-
"@backstage/plugin-permission-node": "
|
|
91
|
-
"@backstage/plugin-search-backend-module-catalog": "
|
|
92
|
-
"@backstage/plugin-search-common": "
|
|
93
|
-
"@backstage/types": "
|
|
79
|
+
"@backstage/backend-openapi-utils": "0.5.1",
|
|
80
|
+
"@backstage/backend-plugin-api": "1.2.1",
|
|
81
|
+
"@backstage/catalog-client": "1.9.1",
|
|
82
|
+
"@backstage/catalog-model": "1.7.3",
|
|
83
|
+
"@backstage/config": "1.3.2",
|
|
84
|
+
"@backstage/errors": "1.2.7",
|
|
85
|
+
"@backstage/integration": "1.16.3-next.0",
|
|
86
|
+
"@backstage/plugin-catalog-common": "1.1.3",
|
|
87
|
+
"@backstage/plugin-catalog-node": "1.16.3-next.0",
|
|
88
|
+
"@backstage/plugin-events-node": "0.4.9",
|
|
89
|
+
"@backstage/plugin-permission-common": "0.8.4",
|
|
90
|
+
"@backstage/plugin-permission-node": "0.9.0",
|
|
91
|
+
"@backstage/plugin-search-backend-module-catalog": "0.3.3-next.0",
|
|
92
|
+
"@backstage/plugin-search-common": "1.2.17",
|
|
93
|
+
"@backstage/types": "1.2.1",
|
|
94
94
|
"@opentelemetry/api": "^1.9.0",
|
|
95
95
|
"@types/express": "^4.17.6",
|
|
96
96
|
"codeowners-utils": "^1.0.2",
|
|
@@ -112,12 +112,12 @@
|
|
|
112
112
|
"zod": "^3.22.4"
|
|
113
113
|
},
|
|
114
114
|
"devDependencies": {
|
|
115
|
-
"@backstage/backend-defaults": "
|
|
116
|
-
"@backstage/backend-test-utils": "
|
|
117
|
-
"@backstage/cli": "
|
|
118
|
-
"@backstage/plugin-permission-common": "
|
|
119
|
-
"@backstage/repo-tools": "
|
|
120
|
-
"@backstage/test-utils": "
|
|
115
|
+
"@backstage/backend-defaults": "0.9.0-next.2",
|
|
116
|
+
"@backstage/backend-test-utils": "1.3.2-next.2",
|
|
117
|
+
"@backstage/cli": "0.32.0-next.2",
|
|
118
|
+
"@backstage/plugin-permission-common": "0.8.4",
|
|
119
|
+
"@backstage/repo-tools": "0.13.1",
|
|
120
|
+
"@backstage/test-utils": "1.7.7-next.0",
|
|
121
121
|
"@types/core-js": "^2.5.4",
|
|
122
122
|
"@types/git-url-parse": "^9.0.0",
|
|
123
123
|
"@types/glob": "^8.0.0",
|