@techdocs/cli 1.11.5-next.2 → 1.12.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 +20 -0
- package/dist/commands/generate/generate.cjs.js +32 -2
- package/dist/commands/generate/generate.cjs.js.map +1 -1
- package/dist/commands/index.cjs.js +9 -1
- package/dist/commands/index.cjs.js.map +1 -1
- package/dist/commands/publish/publish.cjs.js +47 -0
- package/dist/commands/publish/publish.cjs.js.map +1 -1
- package/dist/embedded-app/.config-schema.json +97 -92
- package/dist/embedded-app/index.html +1 -1
- package/dist/embedded-app/index.html.tmpl +1 -1
- package/dist/embedded-app/static/123.91ba1b809deb.chunk.js +2 -0
- package/dist/embedded-app/static/123.91ba1b809deb.chunk.js.map +1 -0
- package/dist/embedded-app/static/1659.a99e4eb674e0.chunk.js +2 -0
- package/dist/embedded-app/static/1659.a99e4eb674e0.chunk.js.map +1 -0
- package/dist/embedded-app/static/1749.99ba95728e00.chunk.js +2 -0
- package/dist/embedded-app/static/1749.99ba95728e00.chunk.js.map +1 -0
- package/dist/embedded-app/static/1994.7736057c2e9f.chunk.js +2 -0
- package/dist/embedded-app/static/1994.7736057c2e9f.chunk.js.map +1 -0
- package/dist/embedded-app/static/{2295.0f797d8c2780.chunk.js → 2295.aaedbca4c1c5.chunk.js} +3 -3
- package/dist/embedded-app/static/2295.aaedbca4c1c5.chunk.js.map +1 -0
- package/dist/embedded-app/static/2360.806f2e1ab212.chunk.js +2 -0
- package/dist/embedded-app/static/2360.806f2e1ab212.chunk.js.map +1 -0
- package/dist/embedded-app/static/3554.78dd0c182f6c.chunk.js +2 -0
- package/dist/embedded-app/static/3554.78dd0c182f6c.chunk.js.map +1 -0
- package/dist/embedded-app/static/4587.d1220800a7d6.chunk.js +2 -0
- package/dist/embedded-app/static/4587.d1220800a7d6.chunk.js.map +1 -0
- package/dist/embedded-app/static/4591.d741c025cb8a.chunk.js +2 -0
- package/dist/embedded-app/static/4591.d741c025cb8a.chunk.js.map +1 -0
- package/dist/embedded-app/static/4609.b1c67dc7cac2.chunk.js +531 -0
- package/dist/embedded-app/static/4609.b1c67dc7cac2.chunk.js.map +1 -0
- package/dist/embedded-app/static/4648.cd5b8df48435.chunk.js +2 -0
- package/dist/embedded-app/static/4648.cd5b8df48435.chunk.js.map +1 -0
- package/dist/embedded-app/static/6138.f15d6245c80d.chunk.js +2 -0
- package/dist/embedded-app/static/6138.f15d6245c80d.chunk.js.map +1 -0
- package/dist/embedded-app/static/6206.3e7f13e11c59.chunk.js +2 -0
- package/dist/embedded-app/static/6206.3e7f13e11c59.chunk.js.map +1 -0
- package/dist/embedded-app/static/6949.beeb90ede97f.chunk.js +4 -0
- package/dist/embedded-app/static/6949.beeb90ede97f.chunk.js.map +1 -0
- package/dist/embedded-app/static/7203.8b3d94b34b16.chunk.js +2 -0
- package/dist/embedded-app/static/7203.8b3d94b34b16.chunk.js.map +1 -0
- package/dist/embedded-app/static/8877.ab3d98868650.chunk.js +2 -0
- package/dist/embedded-app/static/8877.ab3d98868650.chunk.js.map +1 -0
- package/dist/embedded-app/static/9050.bd63e0a33f06.chunk.js +2 -0
- package/dist/embedded-app/static/9050.bd63e0a33f06.chunk.js.map +1 -0
- package/dist/embedded-app/static/9230.422824f655e0.chunk.js +2 -0
- package/dist/embedded-app/static/9230.422824f655e0.chunk.js.map +1 -0
- package/dist/embedded-app/static/main.9b48363c4ffa.js +2 -0
- package/dist/embedded-app/static/main.9b48363c4ffa.js.map +1 -0
- package/dist/embedded-app/static/module-remix-run.32d1d7665115.js +2 -0
- package/dist/embedded-app/static/module-remix-run.32d1d7665115.js.map +1 -0
- package/dist/embedded-app/static/{runtime.304ce6fa8de1.js → runtime.720cb48cd7ae.js} +2 -2
- package/dist/embedded-app/static/{runtime.304ce6fa8de1.js.map → runtime.720cb48cd7ae.js.map} +1 -1
- package/dist/embedded-app/static/vendor.470d3e8ecef1.js +2 -0
- package/dist/embedded-app/static/vendor.470d3e8ecef1.js.map +1 -0
- package/dist/lib/etag.cjs.js +40 -0
- package/dist/lib/etag.cjs.js.map +1 -0
- package/dist/package.json.cjs.js +1 -1
- package/package.json +8 -7
- package/dist/embedded-app/static/123.580aa7a9bfda.chunk.js +0 -2
- package/dist/embedded-app/static/123.580aa7a9bfda.chunk.js.map +0 -1
- package/dist/embedded-app/static/1659.4dc5ef343178.chunk.js +0 -2
- package/dist/embedded-app/static/1659.4dc5ef343178.chunk.js.map +0 -1
- package/dist/embedded-app/static/1749.fcf12bbab446.chunk.js +0 -2
- package/dist/embedded-app/static/1749.fcf12bbab446.chunk.js.map +0 -1
- package/dist/embedded-app/static/1994.9de2967d46a1.chunk.js +0 -2
- package/dist/embedded-app/static/1994.9de2967d46a1.chunk.js.map +0 -1
- package/dist/embedded-app/static/2295.0f797d8c2780.chunk.js.map +0 -1
- package/dist/embedded-app/static/2360.c56e85f47e34.chunk.js +0 -2
- package/dist/embedded-app/static/2360.c56e85f47e34.chunk.js.map +0 -1
- package/dist/embedded-app/static/3554.bb882f8e4aea.chunk.js +0 -2
- package/dist/embedded-app/static/3554.bb882f8e4aea.chunk.js.map +0 -1
- package/dist/embedded-app/static/4587.96f03715ec4f.chunk.js +0 -2
- package/dist/embedded-app/static/4587.96f03715ec4f.chunk.js.map +0 -1
- package/dist/embedded-app/static/4591.5563e3a7aea4.chunk.js +0 -2
- package/dist/embedded-app/static/4591.5563e3a7aea4.chunk.js.map +0 -1
- package/dist/embedded-app/static/4609.152f14ef4904.chunk.js +0 -531
- package/dist/embedded-app/static/4609.152f14ef4904.chunk.js.map +0 -1
- package/dist/embedded-app/static/4648.8a54a9ce4e70.chunk.js +0 -2
- package/dist/embedded-app/static/4648.8a54a9ce4e70.chunk.js.map +0 -1
- package/dist/embedded-app/static/6138.a55572f5ecc5.chunk.js +0 -2
- package/dist/embedded-app/static/6138.a55572f5ecc5.chunk.js.map +0 -1
- package/dist/embedded-app/static/6206.b2713857572e.chunk.js +0 -2
- package/dist/embedded-app/static/6206.b2713857572e.chunk.js.map +0 -1
- package/dist/embedded-app/static/6949.62c7fa0aab7f.chunk.js +0 -4
- package/dist/embedded-app/static/6949.62c7fa0aab7f.chunk.js.map +0 -1
- package/dist/embedded-app/static/7203.16b8799346fa.chunk.js +0 -2
- package/dist/embedded-app/static/7203.16b8799346fa.chunk.js.map +0 -1
- package/dist/embedded-app/static/8877.58093d2c2ba0.chunk.js +0 -2
- package/dist/embedded-app/static/8877.58093d2c2ba0.chunk.js.map +0 -1
- package/dist/embedded-app/static/9050.093f683d75b8.chunk.js +0 -2
- package/dist/embedded-app/static/9050.093f683d75b8.chunk.js.map +0 -1
- package/dist/embedded-app/static/9230.1a571175884d.chunk.js +0 -2
- package/dist/embedded-app/static/9230.1a571175884d.chunk.js.map +0 -1
- package/dist/embedded-app/static/main.3b7e5948ec11.js +0 -2
- package/dist/embedded-app/static/main.3b7e5948ec11.js.map +0 -1
- package/dist/embedded-app/static/module-remix-run.0c80eb31316a.js +0 -2
- package/dist/embedded-app/static/module-remix-run.0c80eb31316a.js.map +0 -1
- package/dist/embedded-app/static/vendor.3bc2778face5.js +0 -2
- package/dist/embedded-app/static/vendor.3bc2778face5.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"static/3554.78dd0c182f6c.chunk.js","sources":["webpack://techdocs-cli-embedded-app/../../node_modules/@material-ui/icons/Share.js","webpack://techdocs-cli-embedded-app/../catalog-model/src/model/jsonSchema/getAjv.ts","webpack://techdocs-cli-embedded-app/../catalog-model/src/model/createCatalogModelLayer.ts","webpack://techdocs-cli-embedded-app/../catalog-model/src/model/jsonSchema/util.ts","webpack://techdocs-cli-embedded-app/../catalog-model/src/model/jsonSchema/validateMetaSchema.ts","webpack://techdocs-cli-embedded-app/../catalog-model/src/model/jsonSchema/zod.ts","webpack://techdocs-cli-embedded-app/../catalog-model/src/model/operations/declareAnnotation.ts","webpack://techdocs-cli-embedded-app/../catalog-model/src/model/operations/declareKind.ts","webpack://techdocs-cli-embedded-app/../catalog-model/src/model/jsonSchema/reduceKindSchema.ts","webpack://techdocs-cli-embedded-app/../catalog-model/src/model/jsonSchema/validateKindRootSchemaSemantics.ts","webpack://techdocs-cli-embedded-app/../catalog-model/src/model/operations/declareKindVersion.ts","webpack://techdocs-cli-embedded-app/../catalog-model/src/model/modelActions/addKindVersion.ts","webpack://techdocs-cli-embedded-app/../catalog-model/src/model/operations/declareLabel.ts","webpack://techdocs-cli-embedded-app/../catalog-model/src/model/operations/declareRelation.ts","webpack://techdocs-cli-embedded-app/../catalog-model/src/model/operations/removeAnnotation.ts","webpack://techdocs-cli-embedded-app/../catalog-model/src/model/operations/removeKind.ts","webpack://techdocs-cli-embedded-app/../catalog-model/src/model/operations/removeLabel.ts","webpack://techdocs-cli-embedded-app/../catalog-model/src/model/operations/removeTag.ts","webpack://techdocs-cli-embedded-app/../catalog-model/src/model/operations/declareTag.ts","webpack://techdocs-cli-embedded-app/../catalog-model/src/model/operations/updateAnnotation.ts","webpack://techdocs-cli-embedded-app/../catalog-model/src/model/operations/updateKind.ts","webpack://techdocs-cli-embedded-app/../catalog-model/src/model/operations/updateKindVersion.ts","webpack://techdocs-cli-embedded-app/../catalog-model/src/model/operations/updateLabel.ts","webpack://techdocs-cli-embedded-app/../catalog-model/src/model/operations/updateRelation.ts","webpack://techdocs-cli-embedded-app/../catalog-model/src/model/operations/updateTag.ts","webpack://techdocs-cli-embedded-app/../catalog-model/src/model/types.ts","webpack://techdocs-cli-embedded-app/../catalog-model/src/model/createCatalogModelLayerBuilder.ts","webpack://techdocs-cli-embedded-app/../catalog-model/src/model/modelActions/addKind.ts","webpack://techdocs-cli-embedded-app/../catalog-model/src/model/modelActions/updateKind.ts","webpack://techdocs-cli-embedded-app/../catalog-model/src/model/modelActions/removeKind.ts","webpack://techdocs-cli-embedded-app/../catalog-model/src/model/modelActions/addRelationPair.ts","webpack://techdocs-cli-embedded-app/../catalog-model/src/model/modelActions/updateRelationPair.ts","webpack://techdocs-cli-embedded-app/../catalog-model/src/model/modelActions/addAnnotation.ts","webpack://techdocs-cli-embedded-app/../catalog-model/src/model/modelActions/updateAnnotation.ts","webpack://techdocs-cli-embedded-app/../catalog-model/src/model/modelActions/removeAnnotation.ts","webpack://techdocs-cli-embedded-app/../catalog-model/src/model/modelActions/addLabel.ts","webpack://techdocs-cli-embedded-app/../catalog-model/src/model/modelActions/updateLabel.ts","webpack://techdocs-cli-embedded-app/../catalog-model/src/model/modelActions/removeLabel.ts","webpack://techdocs-cli-embedded-app/../catalog-model/src/model/modelActions/addTag.ts","webpack://techdocs-cli-embedded-app/../catalog-model/src/model/modelActions/updateTag.ts","webpack://techdocs-cli-embedded-app/../catalog-model/src/model/modelActions/removeTag.ts","webpack://techdocs-cli-embedded-app/../catalog-model/src/kinds/relations.ts","webpack://techdocs-cli-embedded-app/../core-components/src/components/EmptyState/EmptyStateImage.tsx","webpack://techdocs-cli-embedded-app/../core-components/src/components/EmptyState/EmptyState.tsx","webpack://techdocs-cli-embedded-app/../core-components/src/components/FavoriteToggle/FavoriteToggle.tsx","webpack://techdocs-cli-embedded-app/../core-components/src/components/LinkButton/LinkButton.tsx","webpack://techdocs-cli-embedded-app/../core-components/src/components/Select/static/ClosedDropdown.tsx","webpack://techdocs-cli-embedded-app/../core-components/src/components/Select/static/OpenedDropdown.tsx","webpack://techdocs-cli-embedded-app/../core-components/src/components/Select/Select.tsx","webpack://techdocs-cli-embedded-app/../core-components/src/components/Table/Filters.tsx","webpack://techdocs-cli-embedded-app/../core-components/src/components/Table/TableLoadingBody.tsx","webpack://techdocs-cli-embedded-app/../core-components/src/components/Table/Table.tsx","webpack://techdocs-cli-embedded-app/../ui/src/components/Container/definition.ts","webpack://techdocs-cli-embedded-app/../ui/src/components/Container/Container.module.css?2792","webpack://techdocs-cli-embedded-app/../ui/src/components/Container/Container.tsx","webpack://techdocs-cli-embedded-app/../../plugins/catalog-react/src/apis/EntityPresentationApi/entityPresentationSnapshot.ts","webpack://techdocs-cli-embedded-app/../../plugins/catalog-react/src/components/CatalogAutocomplete/CatalogAutocomplete.tsx","webpack://techdocs-cli-embedded-app/../../plugins/catalog-react/src/components/CatalogFilterLayout/CatalogFilterLayout.tsx","webpack://techdocs-cli-embedded-app/../../plugins/catalog-react/src/components/EntityAutocompletePicker/EntityAutocompletePickerOption.tsx","webpack://techdocs-cli-embedded-app/../../plugins/catalog-react/src/components/EntityAutocompletePicker/EntityAutocompletePicker.tsx","webpack://techdocs-cli-embedded-app/../../plugins/catalog-react/src/components/EntityOwnerPicker/VirtualizedListbox.tsx","webpack://techdocs-cli-embedded-app/../../plugins/catalog-react/src/components/EntityOwnerPicker/EntityOwnerPicker.tsx","webpack://techdocs-cli-embedded-app/../../plugins/catalog-react/src/components/EntityOwnerPicker/useFetchEntities.ts","webpack://techdocs-cli-embedded-app/../../plugins/catalog-react/src/components/EntityOwnerPicker/useQueryEntities.ts","webpack://techdocs-cli-embedded-app/../../plugins/catalog-react/src/components/EntityOwnerPicker/useFacetsEntities.ts","webpack://techdocs-cli-embedded-app/../../plugins/catalog-react/src/components/EntityRefLink/EntityRefLinks.tsx","webpack://techdocs-cli-embedded-app/../../plugins/catalog-react/src/components/EntityTagPicker/EntityTagPicker.tsx","webpack://techdocs-cli-embedded-app/../../plugins/catalog-react/src/components/UserListPicker/UserListPicker.tsx","webpack://techdocs-cli-embedded-app/../../plugins/catalog-react/src/components/UserListPicker/useOwnedEntitiesCount.ts","webpack://techdocs-cli-embedded-app/../../plugins/catalog-react/src/components/UserListPicker/useAllEntitiesCount.ts","webpack://techdocs-cli-embedded-app/../../plugins/catalog-react/src/components/UserListPicker/useStarredEntitiesCount.ts","webpack://techdocs-cli-embedded-app/../../plugins/catalog-react/src/filters.ts","webpack://techdocs-cli-embedded-app/../../plugins/catalog-react/src/hooks/useEntityListProvider.tsx","webpack://techdocs-cli-embedded-app/../../plugins/catalog-react/src/hooks/useStarredEntities.ts","webpack://techdocs-cli-embedded-app/../../plugins/catalog-react/src/utils/filters.ts","webpack://techdocs-cli-embedded-app/../../plugins/catalog-react/src/utils/getEntityRelations.ts","webpack://techdocs-cli-embedded-app/../../plugins/techdocs/src/alpha/components/TechDocsIndexPageContent.tsx","webpack://techdocs-cli-embedded-app/../../plugins/techdocs/src/helpers.ts","webpack://techdocs-cli-embedded-app/../../plugins/techdocs/src/home/components/Tables/DocsTable.tsx","webpack://techdocs-cli-embedded-app/../../plugins/techdocs/src/home/components/Tables/OffsetPaginatedDocsTable.tsx","webpack://techdocs-cli-embedded-app/../../plugins/techdocs/src/home/components/Tables/CursorPaginatedDocsTable.tsx","webpack://techdocs-cli-embedded-app/../../plugins/techdocs/src/home/components/Tables/EntityListDocsTable.tsx","webpack://techdocs-cli-embedded-app/../../plugins/techdocs/src/home/components/Tables/actions.tsx","webpack://techdocs-cli-embedded-app/../core-components/src/components/Table/SubvalueCell.tsx","webpack://techdocs-cli-embedded-app/../../plugins/techdocs/src/home/components/Tables/columns.tsx","webpack://techdocs-cli-embedded-app/../../plugins/techdocs/src/home/components/Tables/helpers.ts","webpack://techdocs-cli-embedded-app/../../plugins/techdocs/src/home/components/TechDocsPicker.tsx"],"sourcesContent":["\"use strict\";\n\nvar _interopRequireDefault = require(\"@babel/runtime/helpers/interopRequireDefault\");\n\nvar _interopRequireWildcard = require(\"@babel/runtime/helpers/interopRequireWildcard\");\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.default = void 0;\n\nvar React = _interopRequireWildcard(require(\"react\"));\n\nvar _createSvgIcon = _interopRequireDefault(require(\"./utils/createSvgIcon\"));\n\nvar _default = (0, _createSvgIcon.default)( /*#__PURE__*/React.createElement(\"path\", {\n d: \"M18 16.08c-.76 0-1.44.3-1.96.77L8.91 12.7c.05-.23.09-.46.09-.7s-.04-.47-.09-.7l7.05-4.11c.54.5 1.25.81 2.04.81 1.66 0 3-1.34 3-3s-1.34-3-3-3-3 1.34-3 3c0 .24.04.47.09.7L8.04 9.81C7.5 9.31 6.79 9 6 9c-1.66 0-3 1.34-3 3s1.34 3 3 3c.79 0 1.5-.31 2.04-.81l7.12 4.16c-.05.21-.08.43-.08.65 0 1.61 1.31 2.92 2.92 2.92 1.61 0 2.92-1.31 2.92-2.92s-1.31-2.92-2.92-2.92z\"\n}), 'Share');\n\nexports.default = _default;","/*\n * Copyright 2026 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 Ajv from 'ajv';\nimport ajvErrors from 'ajv-errors';\n\n/**\n * Gets a singleton instance of Ajv.\n */\nexport const getAjv = (() => {\n let instance: Ajv | undefined = undefined;\n\n return () => {\n if (!instance) {\n instance = new Ajv({\n allowUnionTypes: true,\n allErrors: true,\n validateSchema: true,\n });\n ajvErrors(instance);\n }\n return instance;\n };\n})();\n","/*\n * Copyright 2026 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 CatalogModelLayerBuilder,\n createCatalogModelLayerBuilder,\n} from './createCatalogModelLayerBuilder';\nimport { CatalogModelLayer } from './types';\n\n/**\n * Creates a catalog model layer using a builder pattern.\n *\n * @alpha\n * @remarks\n *\n * Plugins can create such catalog model layers to declare various\n * contributions to the overall catalog model, and registering them with the\n * catalog which then forms a complete picture out of them.\n */\nexport function createCatalogModelLayer(options: {\n /**\n * The unique ID of the model layer.\n *\n * @remarks\n * @example `example.com/MyCustomKind`\n *\n * This identifier is used for purposes of deduplication and tracking. It is\n * expected to be stable and descriptive. Prefer prefixing the ID with a\n * matching domain name. The backstage.io domain name is reserved for use by\n * the Backstage project itself.\n */\n layerId: string;\n builder: (model: CatalogModelLayerBuilder) => void;\n}): CatalogModelLayer {\n const b = createCatalogModelLayerBuilder({\n layerId: options.layerId,\n });\n options.builder(b);\n return b.build();\n}\n","/*\n * Copyright 2026 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 { JsonObject } from '@backstage/types';\n\n/**\n * Asserts that the value is a JSON object shallowly.\n */\nexport function isJsonObject(value?: unknown): value is JsonObject {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\n/**\n * Asserts that the value is a JSON object recursively containing only JSON safe\n * values and no circular references.\n */\nexport function isJsonObjectDeep(value: unknown): value is JsonObject {\n if (!isJsonObject(value)) {\n return false;\n }\n const seen = new Set<unknown>([value]);\n return Object.values(value).every(v => isJsonValueDeep(v, seen));\n}\n\nfunction isJsonValueDeep(value: unknown, seen: Set<unknown>): boolean {\n if (\n value === null ||\n typeof value === 'string' ||\n typeof value === 'number' ||\n typeof value === 'boolean'\n ) {\n return true;\n }\n if (typeof value !== 'object') {\n return false;\n }\n if (seen.has(value)) {\n return false;\n }\n seen.add(value);\n const result = Array.isArray(value)\n ? value.every(v => isJsonValueDeep(v, seen))\n : Object.values(value).every(v => isJsonValueDeep(v, seen));\n seen.delete(value);\n return result;\n}\n","/*\n * Copyright 2026 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 { type SchemaObject } from 'ajv';\nimport { isJsonObject } from './util';\nimport { InputError } from '@backstage/errors';\nimport { getAjv } from './getAjv';\n\n/**\n * Validates that the schema is valid according to known JSON Schema meta\n * schemas - does not perform any semantic validation beyond that.\n */\nexport function validateMetaSchema(schema: unknown): schema is SchemaObject {\n if (!isJsonObject(schema) || typeof schema.then === 'function') {\n throw new InputError('Invalid JSON schema: must be an object');\n }\n\n const ajv = getAjv();\n try {\n const result = ajv.validateSchema(schema);\n if (typeof result !== 'boolean') {\n // Should not happen; the function is expected to return a promise only\n // for async schemas, but since that's not enforced at the typescript\n // level we add the extra check just to be sure\n throw new InputError('Expected synchronous validation result');\n }\n } catch (error) {\n throw new InputError(`Invalid JSON schema: ${error}`);\n }\n\n // The full set of errors is typically too complex to report; just pick the\n // first one.\n const error = ajv.errors?.[0];\n if (error) {\n let message = error.message;\n if (Array.isArray(error?.params?.allowedValues)) {\n message += `, expected one of: ${error.params.allowedValues.join(', ')}`;\n }\n throw new InputError(\n `Invalid JSON schema, error at path ${error.instancePath}: ${message}`,\n );\n }\n\n return true;\n}\n","/*\n * Copyright 2026 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 { isError } from '@backstage/errors';\nimport { JsonObject } from '@backstage/types';\nimport { z } from 'zod/v3';\nimport { isJsonObjectDeep } from './util';\nimport { validateMetaSchema } from './validateMetaSchema';\n\nexport const jsonObjectSchema = z\n .record(z.string(), z.unknown())\n .refine((x): x is JsonObject => isJsonObjectDeep(x), {\n message: 'Invalid JSON schema',\n });\n\nexport const jsonSchemaSchema = z\n .record(z.string(), z.unknown())\n .superRefine((x, ctx): x is JsonObject => {\n try {\n return validateMetaSchema(x);\n } catch (error) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: isError(error) ? error.message : 'Invalid JSON schema',\n });\n return false;\n }\n });\n","/*\n * Copyright 2026 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 { z } from 'zod/v3';\nimport { jsonSchemaSchema } from '../jsonSchema/zod';\n\n/**\n * Declare the existence of a well-known annotation and its properties.\n */\nexport const opDeclareAnnotationV1Schema = z.strictObject({\n op: z.literal('declareAnnotation.v1'),\n /**\n * The name of the annotation, e.g. \"backstage.io/techdocs-ref\".\n */\n name: z.string(),\n\n /**\n * The properties that apply to this annotation.\n */\n properties: z.strictObject({\n /**\n * A human-readable title that can be used for display purposes instead of\n * the technical name.\n */\n title: z.string().optional(),\n /**\n * A human-readable description of the annotation.\n */\n description: z.string(),\n /**\n * The JSON schema that values of this annotation must conform to.\n *\n * @remarks\n *\n * If not provided, the annotation is assumed to be a simple string with no\n * particular schema.\n */\n schema: z\n .strictObject({\n jsonSchema: jsonSchemaSchema,\n })\n .optional(),\n }),\n});\n\n/** {@inheritDoc opDeclareAnnotationV1Schema} */\nexport type OpDeclareAnnotationV1 = z.infer<typeof opDeclareAnnotationV1Schema>;\n\n/**\n * Creates a validated {@link OpDeclareAnnotationV1} operation instance.\n *\n * @remarks\n *\n * The `op` field is filled in automatically. The input is verified against the\n * schema before returning, ensuring that the resulting op is reliably valid.\n *\n * @param input - All fields of the op except `op` itself.\n * @returns A fully validated {@link OpDeclareAnnotationV1}.\n */\nexport function createDeclareAnnotationOp(\n input: Omit<OpDeclareAnnotationV1, 'op'> & { op?: never },\n): OpDeclareAnnotationV1 {\n return opDeclareAnnotationV1Schema.parse({\n ...input,\n op: 'declareAnnotation.v1',\n });\n}\n","/*\n * Copyright 2026 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 { z } from 'zod/v3';\n\n/**\n * Make a declaration about the properties of a certain kind.\n */\nexport const opDeclareKindV1Schema = z.strictObject({\n op: z.literal('declareKind.v1'),\n\n /**\n * The kind to declare, e.g. \"Component\".\n */\n kind: z.string(),\n /**\n * The apiVersion group of the kind, e.g. \"backstage.io\".\n */\n group: z.string(),\n\n /**\n * Properties that apply for this kind\n */\n properties: z.strictObject({\n /**\n * The singular form of the human-readable kind, e.g. \"component\".\n */\n singular: z.string(),\n /**\n * The plural form of the human-readable kind, e.g. \"components\".\n */\n plural: z.string(),\n /**\n * Short description of the kind.\n */\n description: z.string(),\n }),\n});\n\n/** {@inheritDoc opDeclareKindV1Schema} */\nexport type OpDeclareKindV1 = z.infer<typeof opDeclareKindV1Schema>;\n\n/**\n * Creates a validated {@link OpDeclareKindV1} operation instance.\n *\n * @remarks\n *\n * The `op` field is filled in automatically. The input is verified against the\n * schema before returning, ensuring that the resulting op is reliably valid.\n *\n * @param input - All fields of the op except `op` itself.\n * @returns A fully validated {@link OpDeclareKindV1}.\n */\nexport function createDeclareKindOp(\n input: Omit<OpDeclareKindV1, 'op'> & { op?: never },\n): OpDeclareKindV1 {\n return opDeclareKindV1Schema.parse({ ...input, op: 'declareKind.v1' });\n}\n","/*\n * Copyright 2026 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 { JsonObject } from '@backstage/types';\nimport { z } from 'zod/v3';\nimport { CatalogModelKindRootSchema } from './validateKindRootSchemaSemantics';\n\n/**\n * The expected shape of the standard full kind schemas, which use an allOf\n * with a $ref to Entity and a second element with the kind-specific schema.\n */\nconst fullKindSchema = z\n .object({\n allOf: z.tuple([\n z.object({ $ref: z.literal('Entity') }),\n z\n .object({\n type: z.literal('object'),\n properties: z\n .object({\n apiVersion: z.record(z.string(), z.unknown()).optional(),\n kind: z.record(z.string(), z.unknown()).optional(),\n })\n .passthrough(),\n })\n .passthrough(),\n ]),\n })\n .passthrough();\n\n/**\n * Reduces a full kind JSON schema to the form expected by the catalog model\n * layer system. The full schemas use an allOf with a $ref to Entity and\n * kind/apiVersion constraints that are not needed in the reduced form.\n *\n * If the schema does not match the expected shape, it is returned unchanged.\n */\nexport function reduceKindSchema(\n schema: JsonObject,\n): CatalogModelKindRootSchema {\n const parsed = fullKindSchema.safeParse(schema);\n if (!parsed.success) {\n return schema as CatalogModelKindRootSchema;\n }\n\n const { allOf, ...rest } = parsed.data;\n const { type, properties: allProperties, ...kindRest } = allOf[1];\n const { apiVersion, kind, ...properties } = allProperties;\n\n return {\n ...rest,\n type,\n ...kindRest,\n properties,\n } as CatalogModelKindRootSchema;\n}\n","/*\n * Copyright 2026 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 { InputError } from '@backstage/errors';\nimport { JsonObject, JsonValue } from '@backstage/types';\nimport { isJsonObject, isJsonObjectDeep } from './util';\n\nconst FORBIDDEN_SCHEMA_ROOT_FIELDS = [\n 'kind',\n 'apiVersion',\n 'metadata',\n '$ref',\n] as const;\nconst FORBIDDEN_SCHEMA_STRUCTURAL_FIELDS = [\n 'allOf',\n 'oneOf',\n 'anyOf',\n 'if',\n 'else',\n 'then',\n 'not',\n '$ref',\n] as const;\n\n/**\n * When declaring the JSON schema model for a kind, this is the type that you\n * should abide by.\n *\n * @alpha\n * @remarks\n *\n * It forbids some patterns that would make the schema hard or impossible to\n * inspect / merge properly.\n */\nexport interface CatalogModelKindRootSchema extends JsonObject {\n type: 'object';\n\n // NOTE: These should match the FORBIDDEN_SCHEMA_STRUCTURAL_FIELDS list above\n allOf?: never;\n anyOf?: never;\n oneOf?: never;\n if?: never;\n then?: never;\n else?: never;\n not?: never;\n $ref?: never;\n\n properties?:\n | undefined\n | {\n // NOTE: These should match the FORBIDDEN_SCHEMA_ROOT_FIELDS list above\n kind?: never;\n apiVersion?: never;\n metadata?: never;\n $ref?: never;\n\n [key: string]:\n | undefined\n | {\n // NOTE: These should match the FORBIDDEN_SCHEMA_STRUCTURAL_FIELDS list above\n allOf?: never;\n anyOf?: never;\n oneOf?: never;\n if?: never;\n then?: never;\n else?: never;\n not?: never;\n $ref?: never;\n\n [key: string]: JsonValue | undefined;\n };\n };\n\n [key: string]: JsonValue | undefined;\n}\n\n/**\n * Validates that the semantics of a schema describing a kind follows semantic\n * rules.\n *\n * @remarks\n *\n * It's expected that the input is a valid JSON Schema, as in having been\n * validated by `validateMetaSchema` already.\n *\n * The schema must not try to explicitly declare certain readonly root fields,\n * and neither the root nor the top level keys of fields may use certain\n * structural keywords that makes the schema hard or impossible to inspect /\n * merge properly.\n *\n * @param schema - The schema to validate.\n */\nexport function validateKindRootSchemaSemantics(\n schema: unknown,\n): schema is CatalogModelKindRootSchema {\n if (!isJsonObjectDeep(schema)) {\n throw new InputError('Schema must be an object');\n }\n\n if (schema.type !== undefined && schema.type !== 'object') {\n throw new InputError('Schema root type must be \"object\"');\n }\n\n for (const field of FORBIDDEN_SCHEMA_STRUCTURAL_FIELDS) {\n if (field in schema) {\n throw new InputError(\n `Schema must not use \"${field}\" keyword in the root`,\n );\n }\n }\n\n const rootProperties = schema.properties;\n if (!isJsonObject(rootProperties)) {\n throw new InputError(\n 'Schema must have a \"properties\" field that is an object',\n );\n }\n\n for (const field of FORBIDDEN_SCHEMA_ROOT_FIELDS) {\n if (field in rootProperties) {\n throw new InputError(\n `Schema must not try to declare the reserved root field \"${field}\"`,\n );\n }\n }\n\n for (const [fieldName, fieldSchema] of Object.entries(rootProperties)) {\n if (!isJsonObject(fieldSchema)) {\n throw new InputError(\n `Schema for root field \"${fieldName}\" must be an object`,\n );\n }\n for (const field of FORBIDDEN_SCHEMA_STRUCTURAL_FIELDS) {\n if (field in fieldSchema) {\n throw new InputError(\n `Schema for root field \"${fieldName}\" must not use \"${field}\" keyword`,\n );\n }\n }\n }\n\n return true;\n}\n","/*\n * Copyright 2026 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 { z } from 'zod/v3';\nimport { jsonSchemaSchema } from '../jsonSchema/zod';\n\nconst relationFieldSchema = z.strictObject({\n /**\n * What field that shall be used to generate relations.\n *\n * @remarks\n *\n * The field value is expected to be a string or string array at runtime.\n */\n selector: z.strictObject({\n /**\n * A dot separated path on the common catalog form, e.g. `spec.owner`.\n */\n path: z.string(),\n }),\n /**\n * The relation type that this field generates, e.g. \"ownedBy\".\n */\n relation: z.string(),\n /**\n * If the given shorthand ref did not have a kind, use this kind as the\n * default. If no default kind is specified, the ref must contain a kind.\n */\n defaultKind: z.string().optional(),\n /**\n * If the given shorthand ref did not have a namespace, either inherit the\n * namespace of the entity itself, or choose the default namespace.\n */\n defaultNamespace: z.enum(['default', 'inherit']).optional(),\n /**\n * Only allow relations to be specified to the given kinds. This list must\n * include the default kind, if any. If no allowed kinds are specified,\n * all kinds are allowed.\n */\n allowedKinds: z.array(z.string()).optional(),\n});\n\n/**\n * Make a declaration about the version of a certain kind.\n */\nexport const opDeclareKindVersionV1Schema = z.strictObject({\n op: z.literal('declareKindVersion.v1'),\n\n /**\n * The kind that this version belongs to.\n */\n kind: z.string(),\n /**\n * The specific version name, e.g. \"v1alpha1\". This and the kind group form\n * the full apiVersion.\n */\n name: z.string(),\n /**\n * The spec type that this version applies to, if any.\n *\n * @remarks\n *\n * This can be used to make kinds whose spec effectively are discriminated\n * unions. If you don't specify this, the schema will apply to a spec that has\n * no type given at all, or to those where the type is not among the set of\n * any other known declared spec types.\n */\n specType: z.string().optional(),\n\n /**\n * The properties that apply to this version.\n */\n properties: z.strictObject({\n /**\n * A short description of this particular version (and type, where applicable).\n */\n description: z.string().optional(),\n\n /**\n * The fields that shall be used to generate relations, if any.\n */\n relationFields: z.array(relationFieldSchema).optional(),\n\n /**\n * The JSON schema of the version.\n */\n schema: z.strictObject({\n jsonSchema: jsonSchemaSchema,\n }),\n }),\n});\n\n/** {@inheritDoc opDeclareKindVersionV1Schema} */\nexport type OpDeclareKindVersionV1 = z.infer<\n typeof opDeclareKindVersionV1Schema\n>;\n\n/**\n * Creates a validated {@link OpDeclareKindVersionV1} operation instance.\n *\n * @remarks\n *\n * The `op` field is filled in automatically. The input is verified against the\n * schema before returning, ensuring that the resulting op is reliably valid.\n *\n * @param input - All fields of the op except `op` itself.\n * @returns A fully validated {@link OpDeclareKindVersionV1}.\n */\nexport function createDeclareKindVersionOp(\n input: Omit<OpDeclareKindVersionV1, 'op'> & { op?: never },\n): OpDeclareKindVersionV1 {\n return opDeclareKindVersionV1Schema.parse({\n ...input,\n op: 'declareKindVersion.v1',\n });\n}\n","/*\n * Copyright 2026 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 { reduceKindSchema } from '../jsonSchema/reduceKindSchema';\nimport { validateKindRootSchemaSemantics } from '../jsonSchema/validateKindRootSchemaSemantics';\nimport { validateMetaSchema } from '../jsonSchema/validateMetaSchema';\nimport { CatalogModelOp } from '../operations';\nimport { createDeclareKindVersionOp } from '../operations/declareKindVersion';\nimport type { CatalogModelKindVersionDefinition } from './addKind';\n\n/**\n * The definition for adding one or more versions to an already-declared kind.\n *\n * @alpha\n */\nexport interface CatalogModelAddKindVersionDefinition {\n /**\n * The kind to add versions to, e.g. \"API\".\n */\n kind: string;\n\n /**\n * The versions to add.\n */\n versions: CatalogModelKindVersionDefinition[];\n}\n\nexport function opsFromCatalogModelAddKindVersion(\n definition: CatalogModelAddKindVersionDefinition,\n): CatalogModelOp[] {\n const ops: CatalogModelOp[] = [];\n\n for (const version of definition.versions) {\n const jsonSchema = reduceKindSchema(version.schema.jsonSchema);\n validateMetaSchema(jsonSchema);\n validateKindRootSchemaSemantics(jsonSchema);\n const names = Array.isArray(version.name) ? version.name : [version.name];\n for (const name of names) {\n const specTypes = version.specType\n ? [version.specType].flat()\n : [undefined];\n for (const specType of specTypes) {\n ops.push(\n createDeclareKindVersionOp({\n kind: definition.kind,\n name,\n specType: specType,\n properties: {\n description: version.description,\n relationFields: version.relationFields,\n schema: {\n jsonSchema: jsonSchema as any,\n },\n },\n }),\n );\n }\n }\n }\n\n return ops;\n}\n","/*\n * Copyright 2026 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 { z } from 'zod/v3';\nimport { jsonSchemaSchema } from '../jsonSchema/zod';\n\n/**\n * Declare the existence of a well-known label and its properties.\n */\nexport const opDeclareLabelV1Schema = z.strictObject({\n op: z.literal('declareLabel.v1'),\n /**\n * The name of the label, e.g. \"backstage.io/source-location\".\n */\n name: z.string(),\n\n /**\n * The properties that apply to this label.\n */\n properties: z.strictObject({\n /**\n * A human-readable title that can be used for display purposes instead of\n * the technical name.\n */\n title: z.string().optional(),\n /**\n * A human-readable description of the label.\n */\n description: z.string(),\n /**\n * The JSON schema that values of this label must conform to.\n *\n * @remarks\n *\n * If not provided, the label is assumed to be a simple string with no\n * particular schema.\n */\n schema: z\n .strictObject({\n jsonSchema: jsonSchemaSchema,\n })\n .optional(),\n }),\n});\n\n/** {@inheritDoc opDeclareLabelV1Schema} */\nexport type OpDeclareLabelV1 = z.infer<typeof opDeclareLabelV1Schema>;\n\n/**\n * Creates a validated {@link OpDeclareLabelV1} operation instance.\n *\n * @remarks\n *\n * The `op` field is filled in automatically. The input is verified against the\n * schema before returning, ensuring that the resulting op is reliably valid.\n *\n * @param input - All fields of the op except `op` itself.\n * @returns A fully validated {@link OpDeclareLabelV1}.\n */\nexport function createDeclareLabelOp(\n input: Omit<OpDeclareLabelV1, 'op'> & { op?: never },\n): OpDeclareLabelV1 {\n return opDeclareLabelV1Schema.parse({\n ...input,\n op: 'declareLabel.v1',\n });\n}\n","/*\n * Copyright 2026 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 { z } from 'zod/v3';\n\n/**\n * Make a declaration about the properties of a certain relation type between a\n * given pair of kinds.\n *\n * @remarks\n *\n * Note that this is NOT the same as declaring that a certain field is a\n * relation type - it declares that IF a relation was generated between two\n * kinds for any reason, then these properties apply to it.\n */\nexport const opDeclareRelationV1Schema = z.strictObject({\n op: z.literal('declareRelation.v1'),\n /**\n * The kind that this relation originates from, e.g. \"Component\".\n */\n fromKind: z.string(),\n /**\n * The technical type of the relation, e.g. \"ownedBy\".\n */\n type: z.string(),\n /**\n * The kind that this relation points to, e.g. \"Group\".\n */\n toKind: z.string(),\n\n /**\n * The properties that apply to this relation.\n */\n properties: z.strictObject({\n /**\n * The technical type of the reverse relation, e.g. \"ownerOf\".\n */\n reverseType: z.string(),\n /**\n * A human-readable title for the relation type, e.g. \"owned by\".\n */\n title: z.string(),\n /**\n * A human-readable description of the relation.\n */\n description: z.string(),\n }),\n});\n\n/** {@inheritDoc opDeclareRelationV1Schema} */\nexport type OpDeclareRelationV1 = z.infer<typeof opDeclareRelationV1Schema>;\n\n/**\n * Creates a validated {@link OpDeclareRelationV1} operation instance.\n *\n * @remarks\n *\n * The `op` field is filled in automatically. The input is verified against the\n * schema before returning, ensuring that the resulting op is reliably valid.\n *\n * @param input - All fields of the op except `op` itself.\n * @returns A fully validated {@link OpDeclareRelationV1}.\n */\nexport function createDeclareRelationOp(\n input: Omit<OpDeclareRelationV1, 'op'> & { op?: never },\n): OpDeclareRelationV1 {\n return opDeclareRelationV1Schema.parse({\n ...input,\n op: 'declareRelation.v1',\n });\n}\n","/*\n * Copyright 2026 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 { z } from 'zod/v3';\n\n/**\n * Remove an annotation from the model.\n */\nexport const opRemoveAnnotationV1Schema = z.strictObject({\n op: z.literal('removeAnnotation.v1'),\n\n /**\n * The name of the annotation to remove, e.g. \"backstage.io/techdocs-ref\".\n */\n name: z.string(),\n});\n\n/** {@inheritDoc opRemoveAnnotationV1Schema} */\nexport type OpRemoveAnnotationV1 = z.infer<typeof opRemoveAnnotationV1Schema>;\n\n/**\n * Creates a validated {@link OpRemoveAnnotationV1} operation instance.\n *\n * @remarks\n *\n * The `op` field is filled in automatically. The input is verified against the\n * schema before returning, ensuring that the resulting op is reliably valid.\n *\n * @param input - All fields of the op except `op` itself.\n * @returns A fully validated {@link OpRemoveAnnotationV1}.\n */\nexport function createRemoveAnnotationOp(\n input: Omit<OpRemoveAnnotationV1, 'op'> & { op?: never },\n): OpRemoveAnnotationV1 {\n return opRemoveAnnotationV1Schema.parse({\n ...input,\n op: 'removeAnnotation.v1',\n });\n}\n","/*\n * Copyright 2026 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 { z } from 'zod/v3';\n\n/**\n * Remove a kind entirely from the model.\n */\nexport const opRemoveKindV1Schema = z.strictObject({\n op: z.literal('removeKind.v1'),\n\n /**\n * The kind to remove, e.g. \"Component\".\n */\n kind: z.string(),\n});\n\n/** {@inheritDoc opRemoveKindV1Schema} */\nexport type OpRemoveKindV1 = z.infer<typeof opRemoveKindV1Schema>;\n\n/**\n * Creates a validated {@link OpRemoveKindV1} operation instance.\n *\n * @remarks\n *\n * The `op` field is filled in automatically. The input is verified against the\n * schema before returning, ensuring that the resulting op is reliably valid.\n *\n * @param input - All fields of the op except `op` itself.\n * @returns A fully validated {@link OpRemoveKindV1}.\n */\nexport function createRemoveKindOp(\n input: Omit<OpRemoveKindV1, 'op'> & { op?: never },\n): OpRemoveKindV1 {\n return opRemoveKindV1Schema.parse({ ...input, op: 'removeKind.v1' });\n}\n","/*\n * Copyright 2026 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 { z } from 'zod/v3';\n\n/**\n * Remove a label from the model.\n */\nexport const opRemoveLabelV1Schema = z.strictObject({\n op: z.literal('removeLabel.v1'),\n\n /**\n * The name of the label to remove, e.g. \"backstage.io/source-location\".\n */\n name: z.string(),\n});\n\n/** {@inheritDoc opRemoveLabelV1Schema} */\nexport type OpRemoveLabelV1 = z.infer<typeof opRemoveLabelV1Schema>;\n\n/**\n * Creates a validated {@link OpRemoveLabelV1} operation instance.\n *\n * @remarks\n *\n * The `op` field is filled in automatically. The input is verified against the\n * schema before returning, ensuring that the resulting op is reliably valid.\n *\n * @param input - All fields of the op except `op` itself.\n * @returns A fully validated {@link OpRemoveLabelV1}.\n */\nexport function createRemoveLabelOp(\n input: Omit<OpRemoveLabelV1, 'op'> & { op?: never },\n): OpRemoveLabelV1 {\n return opRemoveLabelV1Schema.parse({ ...input, op: 'removeLabel.v1' });\n}\n","/*\n * Copyright 2026 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 { z } from 'zod/v3';\n\n/**\n * Remove a tag from the model.\n */\nexport const opRemoveTagV1Schema = z.strictObject({\n op: z.literal('removeTag.v1'),\n\n /**\n * The name of the tag to remove, e.g. \"java\".\n */\n name: z.string(),\n});\n\n/** {@inheritDoc opRemoveTagV1Schema} */\nexport type OpRemoveTagV1 = z.infer<typeof opRemoveTagV1Schema>;\n\n/**\n * Creates a validated {@link OpRemoveTagV1} operation instance.\n *\n * @remarks\n *\n * The `op` field is filled in automatically. The input is verified against the\n * schema before returning, ensuring that the resulting op is reliably valid.\n *\n * @param input - All fields of the op except `op` itself.\n * @returns A fully validated {@link OpRemoveTagV1}.\n */\nexport function createRemoveTagOp(\n input: Omit<OpRemoveTagV1, 'op'> & { op?: never },\n): OpRemoveTagV1 {\n return opRemoveTagV1Schema.parse({ ...input, op: 'removeTag.v1' });\n}\n","/*\n * Copyright 2026 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 { z } from 'zod/v3';\n\n/**\n * Declare the existence of a well-known tag and its properties.\n */\nexport const opDeclareTagV1Schema = z.strictObject({\n op: z.literal('declareTag.v1'),\n /**\n * The name of the tag, e.g. \"java\".\n */\n name: z.string(),\n\n /**\n * The properties that apply to this tag.\n */\n properties: z.strictObject({\n /**\n * A human-readable title that can be used for display purposes instead of\n * the technical name.\n */\n title: z.string().optional(),\n /**\n * A human-readable description of the tag.\n */\n description: z.string(),\n }),\n});\n\n/** {@inheritDoc opDeclareTagV1Schema} */\nexport type OpDeclareTagV1 = z.infer<typeof opDeclareTagV1Schema>;\n\n/**\n * Creates a validated {@link OpDeclareTagV1} operation instance.\n *\n * @remarks\n *\n * The `op` field is filled in automatically. The input is verified against the\n * schema before returning, ensuring that the resulting op is reliably valid.\n *\n * @param input - All fields of the op except `op` itself.\n * @returns A fully validated {@link OpDeclareTagV1}.\n */\nexport function createDeclareTagOp(\n input: Omit<OpDeclareTagV1, 'op'> & { op?: never },\n): OpDeclareTagV1 {\n return opDeclareTagV1Schema.parse({\n ...input,\n op: 'declareTag.v1',\n });\n}\n","/*\n * Copyright 2026 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 { z } from 'zod/v3';\nimport { jsonSchemaSchema } from '../jsonSchema/zod';\n\n/**\n * Update the properties of an existing annotation.\n */\nexport const opUpdateAnnotationV1Schema = z.strictObject({\n op: z.literal('updateAnnotation.v1'),\n\n /**\n * The name of the annotation, e.g. \"backstage.io/techdocs-ref\".\n */\n name: z.string(),\n\n /**\n * The properties that apply to this annotation.\n */\n properties: z.strictObject({\n /**\n * A human-readable title that can be used for display purposes instead of\n * the technical name.\n */\n title: z.string().optional(),\n /**\n * A human-readable description of the annotation.\n */\n description: z.string().optional(),\n /**\n * The JSON schema that values of this annotation must conform to.\n *\n * @remarks\n *\n * If not provided, the annotation is assumed to be a simple string with no\n * particular schema.\n */\n schema: z\n .strictObject({\n jsonSchema: jsonSchemaSchema,\n })\n .optional(),\n }),\n});\n\n/** {@inheritDoc opUpdateAnnotationV1Schema} */\nexport type OpUpdateAnnotationV1 = z.infer<typeof opUpdateAnnotationV1Schema>;\n\n/**\n * Creates a validated {@link OpUpdateAnnotationV1} operation instance.\n *\n * @remarks\n *\n * The `op` field is filled in automatically. The input is verified against the\n * schema before returning, ensuring that the resulting op is reliably valid.\n *\n * @param input - All fields of the op except `op` itself.\n * @returns A fully validated {@link OpUpdateAnnotationV1}.\n */\nexport function createUpdateAnnotationOp(\n input: Omit<OpUpdateAnnotationV1, 'op'> & { op?: never },\n): OpUpdateAnnotationV1 {\n return opUpdateAnnotationV1Schema.parse({\n ...input,\n op: 'updateAnnotation.v1',\n });\n}\n","/*\n * Copyright 2026 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 { z } from 'zod/v3';\n\n/**\n * Make a declaration about the properties of a certain kind.\n */\nexport const opUpdateKindV1Schema = z.strictObject({\n op: z.literal('updateKind.v1'),\n\n /**\n * The kind to update, e.g. \"Component\".\n */\n kind: z.string(),\n\n /**\n * Updated properties that apply for this kind\n */\n properties: z.strictObject({\n /**\n * The singular form of the human-readable kind, e.g. \"component\".\n */\n singular: z.string().optional(),\n /**\n * The plural form of the human-readable kind, e.g. \"components\".\n */\n plural: z.string().optional(),\n /**\n * Short description of the kind.\n */\n description: z.string().optional(),\n }),\n});\n\n/** {@inheritDoc opUpdateKindV1Schema} */\nexport type OpUpdateKindV1 = z.infer<typeof opUpdateKindV1Schema>;\n\n/**\n * Creates a validated {@link OpUpdateKindV1} operation instance.\n *\n * @remarks\n *\n * The `op` field is filled in automatically. The input is verified against the\n * schema before returning, ensuring that the resulting op is reliably valid.\n *\n * @param input - All fields of the op except `op` itself.\n * @returns A fully validated {@link OpUpdateKindV1}.\n */\nexport function createUpdateKindOp(\n input: Omit<OpUpdateKindV1, 'op'> & { op?: never },\n): OpUpdateKindV1 {\n return opUpdateKindV1Schema.parse({ ...input, op: 'updateKind.v1' });\n}\n","/*\n * Copyright 2026 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 { z } from 'zod/v3';\nimport { jsonObjectSchema } from '../jsonSchema/zod';\n\nconst relationFieldSchema = z.strictObject({\n /**\n * What field that shall be used to generate relations.\n *\n * @remarks\n *\n * The field value is expected to be a string or string array at runtime.\n */\n selector: z.strictObject({\n /**\n * A dot separated path on the common catalog form, e.g. `spec.owner`.\n */\n path: z.string(),\n }),\n /**\n * The relation type that this field generates, e.g. \"ownedBy\".\n */\n relation: z.string(),\n /**\n * If the given shorthand ref did not have a kind, use this kind as the\n * default. If no default kind is specified, the ref must contain a kind.\n */\n defaultKind: z.string().optional(),\n /**\n * If the given shorthand ref did not have a namespace, either inherit the\n * namespace of the entity itself, or choose the default namespace.\n */\n defaultNamespace: z.enum(['default', 'inherit']).optional(),\n /**\n * Only allow relations to be specified to the given kinds. This list must\n * include the default kind, if any. If no allowed kinds are specified,\n * all kinds are allowed.\n */\n allowedKinds: z.array(z.string()).optional(),\n});\n\n/**\n * Make an update to a pre-existing version of a certain kind.\n */\nexport const opUpdateKindVersionV1Schema = z.strictObject({\n op: z.literal('updateKindVersion.v1'),\n\n /**\n * The kind that this version belongs to.\n */\n kind: z.string(),\n /**\n * The specific version name, e.g. \"v1alpha1\". This and the kind group form\n * the full apiVersion.\n */\n name: z.string(),\n /**\n * The spec type that this version applies to, if any.\n *\n * @remarks\n *\n * This can be used to make kinds whose spec effectively are discriminated\n * unions. If you don't specify this, the schema will apply to a spec that has\n * no type given at all, or to those where the type is not among the set of\n * any other known declared spec types.\n */\n specType: z.string().optional(),\n\n /**\n * The properties that apply to this version update.\n */\n properties: z.strictObject({\n /**\n * A short description of this particular version (and type, where\n * applicable). Specify this if you want to override the default value.\n */\n description: z.string().optional(),\n\n /**\n * The fields that shall be used to generate relations, if any. Specify this\n * if you want to override the default value.\n */\n relationFields: z.array(relationFieldSchema).optional(),\n\n /**\n * The JSON schema of the version. Specify this if you want to override the\n * default value.\n *\n * @remarks\n *\n * This schema gets deep merged with the default one for this version. It\n * can therefore be used for both amending and changing existing fields.\n * Null-valued object fields delete inherited fields. Validation of the\n * resulting JSON schema takes place during model compilation.\n */\n schema: z\n .strictObject({\n jsonSchema: jsonObjectSchema,\n })\n .optional(),\n }),\n});\n\n/** {@inheritDoc opUpdateKindVersionV1Schema} */\nexport type OpUpdateKindVersionV1 = z.infer<typeof opUpdateKindVersionV1Schema>;\n\n/**\n * Creates a validated {@link OpUpdateKindVersionV1} operation instance.\n *\n * @remarks\n *\n * The `op` field is filled in automatically. The input is verified against the\n * schema before returning, ensuring that the resulting op is reliably valid.\n *\n * @param input - All fields of the op except `op` itself.\n * @returns A fully validated {@link OpUpdateKindVersionV1}.\n */\nexport function createUpdateKindVersionOp(\n input: Omit<OpUpdateKindVersionV1, 'op'> & { op?: never },\n): OpUpdateKindVersionV1 {\n return opUpdateKindVersionV1Schema.parse({\n ...input,\n op: 'updateKindVersion.v1',\n });\n}\n","/*\n * Copyright 2026 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 { z } from 'zod/v3';\nimport { jsonSchemaSchema } from '../jsonSchema/zod';\n\n/**\n * Update the properties of an existing label.\n */\nexport const opUpdateLabelV1Schema = z.strictObject({\n op: z.literal('updateLabel.v1'),\n\n /**\n * The name of the label, e.g. \"backstage.io/source-location\".\n */\n name: z.string(),\n\n /**\n * The properties that apply to this label.\n */\n properties: z.strictObject({\n /**\n * A human-readable title that can be used for display purposes instead of\n * the technical name.\n */\n title: z.string().optional(),\n /**\n * A human-readable description of the label.\n */\n description: z.string().optional(),\n /**\n * The JSON schema that values of this label must conform to.\n *\n * @remarks\n *\n * If not provided, the label is assumed to be a simple string with no\n * particular schema.\n */\n schema: z\n .strictObject({\n jsonSchema: jsonSchemaSchema,\n })\n .optional(),\n }),\n});\n\n/** {@inheritDoc opUpdateLabelV1Schema} */\nexport type OpUpdateLabelV1 = z.infer<typeof opUpdateLabelV1Schema>;\n\n/**\n * Creates a validated {@link OpUpdateLabelV1} operation instance.\n *\n * @remarks\n *\n * The `op` field is filled in automatically. The input is verified against the\n * schema before returning, ensuring that the resulting op is reliably valid.\n *\n * @param input - All fields of the op except `op` itself.\n * @returns A fully validated {@link OpUpdateLabelV1}.\n */\nexport function createUpdateLabelOp(\n input: Omit<OpUpdateLabelV1, 'op'> & { op?: never },\n): OpUpdateLabelV1 {\n return opUpdateLabelV1Schema.parse({\n ...input,\n op: 'updateLabel.v1',\n });\n}\n","/*\n * Copyright 2026 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 { z } from 'zod/v3';\n\n/**\n * Update the properties of a certain relation type between a given pair of\n * kinds.\n *\n * @remarks\n *\n * Note that this is NOT the same as updating the properties of a certain field\n * that is a relation type - it updates the properties of a relation that was\n * generated between two kinds for any reason.\n */\nexport const opUpdateRelationV1Schema = z.strictObject({\n op: z.literal('updateRelation.v1'),\n\n /**\n * The kind that this relation originates from, e.g. \"Component\".\n */\n fromKind: z.string(),\n /**\n * The technical type of the relation, e.g. \"ownedBy\".\n */\n type: z.string(),\n /**\n * The kind that this relation points to, e.g. \"Group\".\n */\n toKind: z.string(),\n\n /**\n * The properties that apply to this relation.\n */\n properties: z.strictObject({\n /**\n * The technical type of the reverse relation, e.g. \"ownerOf\".\n */\n reverseType: z.string().optional(),\n /**\n * A human-readable title for the currently declared reverse relation.\n */\n reverseTitle: z.string().optional(),\n /**\n * A human-readable title for the relation type, e.g. \"owned by\".\n */\n title: z.string().optional(),\n /**\n * A human-readable description of the relation.\n */\n description: z.string().optional(),\n }),\n});\n\n/** {@inheritDoc opUpdateRelationV1Schema} */\nexport type OpUpdateRelationV1 = z.infer<typeof opUpdateRelationV1Schema>;\n\n/**\n * Creates a validated {@link OpUpdateRelationV1} operation instance.\n *\n * @remarks\n *\n * The `op` field is filled in automatically. The input is verified against the\n * schema before returning, ensuring that the resulting op is reliably valid.\n *\n * @param input - All fields of the op except `op` itself.\n * @returns A fully validated {@link OpUpdateRelationV1}.\n */\nexport function createUpdateRelationOp(\n input: Omit<OpUpdateRelationV1, 'op'> & { op?: never },\n): OpUpdateRelationV1 {\n return opUpdateRelationV1Schema.parse({\n ...input,\n op: 'updateRelation.v1',\n });\n}\n","/*\n * Copyright 2026 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 { z } from 'zod/v3';\n\n/**\n * Update the properties of an existing tag.\n */\nexport const opUpdateTagV1Schema = z.strictObject({\n op: z.literal('updateTag.v1'),\n\n /**\n * The name of the tag, e.g. \"java\".\n */\n name: z.string(),\n\n /**\n * The properties that apply to this tag.\n */\n properties: z.strictObject({\n /**\n * A human-readable title that can be used for display purposes instead of\n * the technical name.\n */\n title: z.string().optional(),\n /**\n * A human-readable description of the tag.\n */\n description: z.string().optional(),\n }),\n});\n\n/** {@inheritDoc opUpdateTagV1Schema} */\nexport type OpUpdateTagV1 = z.infer<typeof opUpdateTagV1Schema>;\n\n/**\n * Creates a validated {@link OpUpdateTagV1} operation instance.\n *\n * @remarks\n *\n * The `op` field is filled in automatically. The input is verified against the\n * schema before returning, ensuring that the resulting op is reliably valid.\n *\n * @param input - All fields of the op except `op` itself.\n * @returns A fully validated {@link OpUpdateTagV1}.\n */\nexport function createUpdateTagOp(\n input: Omit<OpUpdateTagV1, 'op'> & { op?: never },\n): OpUpdateTagV1 {\n return opUpdateTagV1Schema.parse({ ...input, op: 'updateTag.v1' });\n}\n","/*\n * Copyright 2026 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 { OpaqueType } from '@internal/opaque';\nimport { CatalogModelOp } from './operations';\nimport { JsonObject } from '@backstage/types';\n\n// #region CatalogModelLayer\n\n/**\n * An opaque type that represents a set of catalog model layers.\n *\n * @alpha\n */\nexport interface CatalogModelLayer {\n readonly $$type: '@backstage/CatalogModelLayer';\n /**\n * The unique ID of the model layer.\n *\n * @remarks\n * @example `catalog.backstage.io/kind-api`\n *\n * This identifier is used for purposes of deduplication and tracking. It is\n * expected to be stable and descriptive. Prefer prefixing the ID with a\n * matching domain name. The backstage.io domain name is reserved for use by\n * the Backstage project itself.\n */\n readonly layerId: string;\n}\n\n/**\n * The opaque type that represents a catalog model layer.\n *\n * @internal\n * @remarks\n *\n * Model layers are essentially an array of operations. Several such model\n * layers are merged together to form a final outcome.\n */\nexport const OpaqueCatalogModelLayer = OpaqueType.create<{\n public: CatalogModelLayer;\n versions: {\n readonly version: 'v1';\n readonly layerId: string;\n readonly ops: Array<CatalogModelOp>;\n };\n}>({\n type: '@backstage/CatalogModelLayer',\n versions: ['v1'],\n});\n\n// #endregion\n\n// #region CatalogModel\n\n/**\n * A compiled catalog model.\n *\n * @alpha\n */\nexport interface CatalogModel {\n /**\n * Lists all kinds in the model.\n */\n listKinds(): CatalogModelKindSummary[];\n\n /**\n * Lists all relations in the model.\n */\n listRelations(): CatalogModelRelationSummary[];\n\n /**\n * Returns summaries of the shared metadata fields in the model, including\n * all declared annotations, labels, and tags.\n */\n getMetadata(): {\n annotations: CatalogModelAnnotationSummary[];\n labels: CatalogModelLabelSummary[];\n tags: CatalogModelTagSummary[];\n };\n\n /**\n * Look up a kind in the model.\n *\n * @returns The kind if found, or `undefined` if no matching kind exists.\n * @throws TypeError if the kind exists in the model, but not for this apiVersion or type.\n */\n getKind(options: {\n kind: string;\n apiVersion: string;\n spec?: { type?: string };\n }): CatalogModelKind | undefined;\n\n /**\n * Look up all relations that originate from a given kind.\n *\n * @param kind - The kind name, e.g. \"Component\".\n * @returns The relations originating from the kind, or `undefined` if the\n * kind is not known.\n */\n getRelations(options: { kind: string }): CatalogModelRelation[] | undefined;\n}\n\n// #endregion\n\n// #region CatalogModelKind\n\n/**\n * A compiled catalog model kind.\n *\n * @alpha\n */\nexport interface CatalogModelKind {\n /**\n * A human-readable description of the kind.\n */\n description: string;\n\n /**\n * The API version(s) of the kind that this schema applies to, e.g.\n * \"backstage.io/v1alpha1\".\n */\n apiVersions: string[];\n\n /**\n * The names used for this kind.\n */\n names: {\n /**\n * The name of the kind with proper casing, e.g. \"Component\".\n */\n kind: string;\n\n /**\n * The singular form of the kind name, e.g. \"component\".\n */\n singular: string;\n\n /**\n * The plural form of the kind name, e.g. \"components\".\n */\n plural: string;\n };\n\n /**\n * The relation fields declared for this kind, with full dot-separated paths\n * into the entity (e.g. \"spec.owner\").\n */\n relationFields: Array<{\n /**\n * The full dot-separated path to the field in the entity, e.g. \"spec.owner\".\n */\n path: string;\n /**\n * The relation type that this field generates, e.g. \"ownedBy\".\n */\n relation: string;\n /**\n * The default kind for parsing shorthand entity refs.\n */\n defaultKind?: string;\n /**\n * The default namespace for parsing shorthand entity refs.\n */\n defaultNamespace?: 'inherit' | 'default';\n /**\n * The kinds that are allowed as targets for this relation field.\n */\n allowedKinds?: string[];\n }>;\n\n /**\n * The JSON schema of the kind.\n *\n * @remarks\n *\n * This can be used for validation of entities. Note that it is up to the\n * caller to ensure that the kind and apiVersion match what you are validating\n * against.\n */\n jsonSchema: JsonObject;\n}\n\n// #endregion\n\n// #region CatalogModelKindSummary\n\n/**\n * A summary of a catalog model kind, without version-specific details such as\n * schemas and relation fields.\n *\n * @alpha\n */\nexport interface CatalogModelKindSummary {\n /**\n * A human-readable description of the kind.\n */\n description: string;\n\n /**\n * The names used for this kind.\n */\n names: {\n /**\n * The name of the kind with proper casing, e.g. \"Component\".\n */\n kind: string;\n\n /**\n * The singular form of the kind name, e.g. \"component\".\n */\n singular: string;\n\n /**\n * The plural form of the kind name, e.g. \"components\".\n */\n plural: string;\n };\n\n /**\n * The available versions and spec types for this kind.\n *\n * @remarks\n *\n * Each entry represents a unique apiVersion/specType combination that can be\n * passed to {@link CatalogModel.getKind} to retrieve the full kind details.\n */\n versions: Array<{\n /**\n * The API version, e.g. \"backstage.io/v1alpha1\".\n */\n apiVersion: string;\n /**\n * The spec type, if any, e.g. \"service\". Undefined means the default\n * (untyped) version.\n */\n specType?: string;\n }>;\n}\n\n// #endregion\n\n// #region CatalogModelRelation\n\n/**\n * A compiled catalog model relation.\n *\n * @alpha\n */\nexport interface CatalogModelRelation {\n /**\n * The kinds that this relation can originate from.\n */\n fromKind: string[];\n /**\n * The kinds that this relation can point to.\n */\n toKind: string[];\n /**\n * A human-readable description of the relation.\n */\n description: string;\n /**\n * The forward direction of this relation.\n */\n forward: {\n type: string;\n title: string;\n };\n /**\n * The reverse direction of this relation.\n */\n reverse: {\n type: string;\n title: string;\n };\n}\n\n// #endregion\n\n// #region CatalogModelAnnotationSummary\n\n/**\n * A summary of a catalog model annotation.\n *\n * @alpha\n */\nexport interface CatalogModelAnnotationSummary {\n /**\n * The annotation key, e.g. \"backstage.io/managed-by-location\".\n */\n name: string;\n /**\n * A short human-readable title for the annotation.\n */\n title?: string;\n /**\n * A human-readable description of the annotation.\n */\n description: string;\n}\n\n// #endregion\n\n// #region CatalogModelLabelSummary\n\n/**\n * A summary of a catalog model label.\n *\n * @alpha\n */\nexport interface CatalogModelLabelSummary {\n /**\n * The label key, e.g. \"backstage.io/orphan\".\n */\n name: string;\n /**\n * A short human-readable title for the label.\n */\n title?: string;\n /**\n * A human-readable description of the label.\n */\n description: string;\n}\n\n// #endregion\n\n// #region CatalogModelTagSummary\n\n/**\n * A summary of a catalog model tag.\n *\n * @alpha\n */\nexport interface CatalogModelTagSummary {\n /**\n * The tag value, e.g. \"java\".\n */\n name: string;\n /**\n * A short human-readable title for the tag.\n */\n title?: string;\n /**\n * A human-readable description of the tag.\n */\n description: string;\n}\n\n// #endregion\n\n// #region CatalogModelRelationSummary\n\n/**\n * A summary of a catalog model relation.\n *\n * @alpha\n */\nexport interface CatalogModelRelationSummary {\n /**\n * The kinds that this relation can originate from.\n */\n fromKind: string[];\n /**\n * The kinds that this relation can point to.\n */\n toKind: string[];\n /**\n * A human-readable description of the relation.\n */\n description: string;\n /**\n * The forward direction of this relation.\n */\n forward: {\n type: string;\n title: string;\n };\n /**\n * The reverse direction of this relation.\n */\n reverse: {\n type: string;\n title: string;\n };\n}\n\n// #endregion\n","/*\n * Copyright 2026 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n type CatalogModelAnnotationDefinition,\n opsFromCatalogModelAnnotation,\n} from './modelActions/addAnnotation';\nimport {\n type CatalogModelKindDefinition,\n opsFromCatalogModelKind,\n} from './modelActions/addKind';\nimport {\n type CatalogModelAddKindVersionDefinition,\n opsFromCatalogModelAddKindVersion,\n} from './modelActions/addKindVersion';\nimport {\n type CatalogModelLabelDefinition,\n opsFromCatalogModelLabel,\n} from './modelActions/addLabel';\nimport {\n type CatalogModelRelationPairDefinition,\n opsFromCatalogModelRelationPair,\n} from './modelActions/addRelationPair';\nimport {\n type CatalogModelRemoveAnnotationDefinition,\n opsFromCatalogModelRemoveAnnotation,\n} from './modelActions/removeAnnotation';\nimport {\n type CatalogModelRemoveKindDefinition,\n opsFromCatalogModelRemoveKind,\n} from './modelActions/removeKind';\nimport {\n type CatalogModelRemoveLabelDefinition,\n opsFromCatalogModelRemoveLabel,\n} from './modelActions/removeLabel';\nimport {\n type CatalogModelRemoveTagDefinition,\n opsFromCatalogModelRemoveTag,\n} from './modelActions/removeTag';\nimport {\n type CatalogModelTagDefinition,\n opsFromCatalogModelTag,\n} from './modelActions/addTag';\nimport {\n type CatalogModelUpdateAnnotationDefinition,\n opsFromCatalogModelUpdateAnnotation,\n} from './modelActions/updateAnnotation';\nimport {\n CatalogModelUpdateKindDefinition,\n opsFromCatalogModelUpdateKind,\n} from './modelActions/updateKind';\nimport {\n type CatalogModelUpdateLabelDefinition,\n opsFromCatalogModelUpdateLabel,\n} from './modelActions/updateLabel';\nimport {\n CatalogModelUpdateRelationPairDefinition,\n opsFromCatalogModelUpdateRelationPair,\n} from './modelActions/updateRelationPair';\nimport {\n type CatalogModelUpdateTagDefinition,\n opsFromCatalogModelUpdateTag,\n} from './modelActions/updateTag';\nimport { CatalogModelOp } from './operations';\nimport { CatalogModelLayer, OpaqueCatalogModelLayer } from './types';\n\n/**\n * A builder for catalog model layers.\n *\n * @alpha\n *\n * Plugins can use this builder to declare various contributions to the overall\n * catalog model, and registering the outcome with the catalog which then forms\n * a complete picture out of them.\n */\nexport interface CatalogModelLayerBuilder {\n /**\n * Adds a new kind to the model.\n */\n addKind(kind: CatalogModelKindDefinition): void;\n /**\n * Adds one or more versions to an already-declared kind.\n */\n addKindVersion(definition: CatalogModelAddKindVersionDefinition): void;\n /**\n * Updates an existing kind in the model.\n */\n updateKind(kind: CatalogModelUpdateKindDefinition): void;\n /**\n * Removes a kind entirely from the model.\n */\n removeKind(kind: CatalogModelRemoveKindDefinition): void;\n\n /**\n * Adds a new relation pair to the model.\n */\n addRelationPair(relation: CatalogModelRelationPairDefinition): void;\n /**\n * Updates an existing relation pair in the model.\n */\n updateRelationPair(relation: CatalogModelUpdateRelationPairDefinition): void;\n\n /**\n * Adds a new annotation to the model.\n */\n addAnnotation(annotation: CatalogModelAnnotationDefinition): void;\n /**\n * Updates an existing annotation in the model.\n */\n updateAnnotation(annotation: CatalogModelUpdateAnnotationDefinition): void;\n /**\n * Removes an annotation from the model.\n */\n removeAnnotation(annotation: CatalogModelRemoveAnnotationDefinition): void;\n\n /**\n * Adds a new label to the model.\n */\n addLabel(label: CatalogModelLabelDefinition): void;\n /**\n * Updates an existing label in the model.\n */\n updateLabel(label: CatalogModelUpdateLabelDefinition): void;\n /**\n * Removes a label from the model.\n */\n removeLabel(label: CatalogModelRemoveLabelDefinition): void;\n\n /**\n * Adds a new tag to the model.\n */\n addTag(tag: CatalogModelTagDefinition): void;\n /**\n * Updates an existing tag in the model.\n */\n updateTag(tag: CatalogModelUpdateTagDefinition): void;\n /**\n * Removes a tag from the model.\n */\n removeTag(tag: CatalogModelRemoveTagDefinition): void;\n\n /**\n * Imports all operations from another catalog model layer into this one.\n */\n import(layer: CatalogModelLayer): void;\n}\n\n/**\n * The default implementation of the catalog model layer builder.\n */\nexport class DefaultCatalogModelLayerBuilder\n implements CatalogModelLayerBuilder\n{\n readonly #layerId: string;\n readonly #ops: CatalogModelOp[];\n\n constructor(options: { layerId: string }) {\n this.#layerId = options.layerId;\n this.#ops = [];\n }\n\n addKind(kind: CatalogModelKindDefinition): void {\n const ops = opsFromCatalogModelKind(kind);\n this.#ops.push(...ops);\n }\n\n addKindVersion(definition: CatalogModelAddKindVersionDefinition): void {\n const ops = opsFromCatalogModelAddKindVersion(definition);\n this.#ops.push(...ops);\n }\n\n updateKind(kind: CatalogModelUpdateKindDefinition): void {\n const ops = opsFromCatalogModelUpdateKind(kind);\n this.#ops.push(...ops);\n }\n\n removeKind(kind: CatalogModelRemoveKindDefinition): void {\n const ops = opsFromCatalogModelRemoveKind(kind);\n this.#ops.push(...ops);\n }\n\n addRelationPair(relation: CatalogModelRelationPairDefinition): void {\n const ops = opsFromCatalogModelRelationPair(relation);\n this.#ops.push(...ops);\n }\n\n updateRelationPair(relation: CatalogModelUpdateRelationPairDefinition): void {\n const ops = opsFromCatalogModelUpdateRelationPair(relation);\n this.#ops.push(...ops);\n }\n\n addAnnotation(annotation: CatalogModelAnnotationDefinition): void {\n const ops = opsFromCatalogModelAnnotation(annotation);\n this.#ops.push(...ops);\n }\n\n updateAnnotation(annotation: CatalogModelUpdateAnnotationDefinition): void {\n const ops = opsFromCatalogModelUpdateAnnotation(annotation);\n this.#ops.push(...ops);\n }\n\n removeAnnotation(annotation: CatalogModelRemoveAnnotationDefinition): void {\n const ops = opsFromCatalogModelRemoveAnnotation(annotation);\n this.#ops.push(...ops);\n }\n\n addLabel(label: CatalogModelLabelDefinition): void {\n const ops = opsFromCatalogModelLabel(label);\n this.#ops.push(...ops);\n }\n\n updateLabel(label: CatalogModelUpdateLabelDefinition): void {\n const ops = opsFromCatalogModelUpdateLabel(label);\n this.#ops.push(...ops);\n }\n\n removeLabel(label: CatalogModelRemoveLabelDefinition): void {\n const ops = opsFromCatalogModelRemoveLabel(label);\n this.#ops.push(...ops);\n }\n\n addTag(tag: CatalogModelTagDefinition): void {\n const ops = opsFromCatalogModelTag(tag);\n this.#ops.push(...ops);\n }\n\n updateTag(tag: CatalogModelUpdateTagDefinition): void {\n const ops = opsFromCatalogModelUpdateTag(tag);\n this.#ops.push(...ops);\n }\n\n removeTag(tag: CatalogModelRemoveTagDefinition): void {\n const ops = opsFromCatalogModelRemoveTag(tag);\n this.#ops.push(...ops);\n }\n\n import(layer: CatalogModelLayer): void {\n const internal = OpaqueCatalogModelLayer.toInternal(layer);\n this.#ops.push(...internal.ops);\n }\n\n build(): CatalogModelLayer {\n return OpaqueCatalogModelLayer.createInstance('v1', {\n layerId: this.#layerId,\n ops: this.#ops.slice(),\n });\n }\n}\n\n/**\n * Creates a builder for a catalog model layer.\n *\n * @alpha\n * @remarks\n *\n * Plugins can use the resulting builder to declare various contributions to the\n * overall catalog model, and registering it with the catalog which then forms a\n * complete picture out of them.\n */\nexport function createCatalogModelLayerBuilder(options: {\n layerId: string;\n}): CatalogModelLayerBuilder & { build(): CatalogModelLayer } {\n return new DefaultCatalogModelLayerBuilder(options);\n}\n","/*\n * Copyright 2026 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 { JsonObject } from '@backstage/types';\nimport { CatalogModelOp } from '../operations';\nimport { createDeclareKindOp } from '../operations/declareKind';\nimport { opsFromCatalogModelAddKindVersion } from './addKindVersion';\n\n/**\n * The definition of a catalog model kind, roughly resembling a JSON Schema.\n *\n * @alpha\n */\nexport interface CatalogModelKindDefinition {\n /**\n * The apiVersion group of the kind, e.g. \"backstage.io\".\n */\n group: string;\n\n /**\n * The names used for this kind.\n */\n names: {\n /**\n * The name of the kind with proper casing, e.g. \"Component\".\n */\n kind: string;\n\n /**\n * The singular form of the kind name, e.g. \"component\".\n */\n singular: string;\n\n /**\n * The plural form of the kind name, e.g. \"components\".\n */\n plural: string;\n };\n\n /**\n * A short description of the kind.\n *\n * @remarks\n *\n * For kinds that have wide applicability over for example several different\n * spec types, this description should be a generic one and the types\n * themselves can be more precise.\n */\n description: string;\n\n /**\n * Declare one or more versions of the kind's actual schema shape.\n */\n versions?: CatalogModelKindVersionDefinition[];\n}\n\n/**\n * The definition of one or more specific versions of a catalog model kind.\n *\n * @alpha\n */\nexport interface CatalogModelKindVersionDefinition {\n /**\n * The specific version name or names, e.g. \"v1alpha1\" or\n * [\"v1alpha1\", \"v1beta1\"]. The kind group and the version name form the\n * full apiVersion, e.g. \"backstage.io/v1alpha1\".\n */\n name: string | string[];\n\n /**\n * The spec type or types that this version applies to.\n *\n * @remarks\n *\n * This can be used to make kinds whose spec effectively are discriminated\n * unions. If you don't specify this, the schema will apply to a spec that\n * has no type given at all, or to those where the type is not among the set\n * of any other known declared spec types.\n *\n * TODO: Should this be more like `matcher: { [path: string]: string }`, or\n * even a full JSON Schema that can be used in an \"if\"?\n */\n specType?: string | string[];\n\n /**\n * A short description of this particular version (and type, where applicable).\n */\n description?: string;\n\n /**\n * The fields that shall be used to generate relations, if any.\n *\n * TODO: Should this be not an array, to be more easily mergeable? Or should\n * we just have a custom merge strategy for them\n */\n relationFields?: CatalogModelKindRelationFieldDefinition[];\n\n /**\n * The entity schema, excluding the generated kind, apiVersion, and metadata\n * fields. Its root type must be `object` or omitted; an omitted root type is\n * supplied during compilation.\n */\n schema: {\n jsonSchema: JsonObject;\n };\n}\n\n/**\n * @alpha\n */\nexport interface CatalogModelKindRelationFieldDefinition {\n /**\n * What field that shall be used to generate relations.\n *\n * @remarks\n *\n * The field value is expected to be a string or string array at runtime.\n */\n selector: { path: string };\n /**\n * The relation type that this field generates, e.g. \"ownedBy\".\n */\n relation: string;\n /**\n * If the given shorthand ref did not have a kind, use this kind as the\n * default. If no default kind is specified, the ref must contain a kind.\n */\n defaultKind?: string;\n /**\n * If the given shorthand ref did not have a namespace, either inherit the\n * namespace of the entity itself, or choose the default namespace. If no\n * default namespace is specified, the namespace of the entity itself is used.\n */\n defaultNamespace?: 'default' | 'inherit';\n /**\n * Only allow relations to be specified to the given kinds. This list must\n * include the default kind, if any. If no allowed kinds are specified, all\n * kinds are.\n */\n allowedKinds?: string[];\n}\n\nexport function opsFromCatalogModelKind(\n kind: CatalogModelKindDefinition,\n): CatalogModelOp[] {\n const ops: CatalogModelOp[] = [];\n\n ops.push(\n createDeclareKindOp({\n kind: kind.names.kind,\n group: kind.group,\n properties: {\n singular: kind.names.singular,\n plural: kind.names.plural,\n description: kind.description,\n },\n }),\n );\n\n ops.push(\n ...opsFromCatalogModelAddKindVersion({\n kind: kind.names.kind,\n versions: kind.versions ?? [],\n }),\n );\n\n return ops;\n}\n","/*\n * Copyright 2026 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 { JsonObject } from '@backstage/types';\nimport { reduceKindSchema } from '../jsonSchema/reduceKindSchema';\nimport { CatalogModelOp } from '../operations';\nimport { createUpdateKindOp } from '../operations/updateKind';\nimport { createUpdateKindVersionOp } from '../operations/updateKindVersion';\nimport { CatalogModelKindRelationFieldDefinition } from './addKind';\n\n/**\n * The definition of updates to a catalog model kind.\n *\n * @alpha\n */\nexport interface CatalogModelUpdateKindDefinition {\n /**\n * The names used for this kind.\n */\n names: {\n /**\n * The name of the kind with proper casing, e.g. \"Component\".\n */\n kind: string;\n\n /**\n * The singular form of the kind name, e.g. \"component\". Specify this if you\n * want to override the default value.\n */\n singular?: string;\n\n /**\n * The plural form of the kind name, e.g. \"components\". Specify this if you\n * want to override the default value.\n */\n plural?: string;\n };\n\n /**\n * A short description of the kind. Specify this if you want to override the\n * default value.\n */\n description?: string;\n\n /**\n * Update one or more versions of the kind's actual schema shape.\n */\n versions?: CatalogModelUpdateKindVersionDefinition[];\n}\n\n/**\n * The definition of updates to a specific version of a catalog model kind.\n *\n * @alpha\n */\nexport interface CatalogModelUpdateKindVersionDefinition {\n /**\n * The specific version name or names to update, e.g. \"v1alpha1\" or\n * [\"v1alpha1\", \"v1beta1\"].\n */\n name: string | string[];\n\n /**\n * The spec type or types that this version update applies to.\n */\n specType?: string | string[];\n\n /**\n * A short description of this particular version (and type, where\n * applicable). Specify this if you want to override the default value.\n */\n description?: string;\n\n /**\n * The fields that shall be used to generate relations, if any. Specify this\n * if you want to override the default value.\n */\n relationFields?: CatalogModelKindRelationFieldDefinition[];\n\n /**\n * The JSON schema to deep merge with the existing schema for this version.\n * Object fields set to `null` delete the corresponding inherited field.\n * Values of `const` and `default` are literal JSON data, so `null` is\n * retained for those keywords rather than interpreted as a deletion.\n * Arrays replace the inherited array in full. The resulting schema is\n * validated when the model is compiled.\n */\n schema?: {\n jsonSchema: JsonObject;\n };\n}\n\nexport function opsFromCatalogModelUpdateKind(\n kind: CatalogModelUpdateKindDefinition,\n): CatalogModelOp[] {\n const ops: CatalogModelOp[] = [];\n\n if (\n kind.names.singular !== undefined ||\n kind.names.plural !== undefined ||\n kind.description !== undefined\n ) {\n ops.push(\n createUpdateKindOp({\n kind: kind.names.kind,\n properties: {\n singular: kind.names.singular,\n plural: kind.names.plural,\n description: kind.description,\n },\n }),\n );\n }\n\n for (const version of kind.versions ?? []) {\n const jsonSchema = version.schema\n ? reduceKindSchema(version.schema.jsonSchema)\n : undefined;\n const names = Array.isArray(version.name) ? version.name : [version.name];\n for (const name of names) {\n const specTypes = version.specType?.length\n ? [version.specType].flat()\n : [undefined];\n for (const specType of specTypes) {\n ops.push(\n createUpdateKindVersionOp({\n kind: kind.names.kind,\n name,\n specType: specType,\n properties: {\n description: version.description,\n relationFields: version.relationFields,\n schema: jsonSchema\n ? { jsonSchema: jsonSchema as any }\n : undefined,\n },\n }),\n );\n }\n }\n }\n\n return ops;\n}\n","/*\n * Copyright 2026 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 { CatalogModelOp } from '../operations';\nimport { createRemoveKindOp } from '../operations/removeKind';\n\n/**\n * The definition of a kind removal from the catalog model.\n *\n * @alpha\n */\nexport interface CatalogModelRemoveKindDefinition {\n /**\n * The kind to remove, e.g. \"Component\".\n */\n kind: string;\n}\n\nexport function opsFromCatalogModelRemoveKind(\n definition: CatalogModelRemoveKindDefinition,\n): CatalogModelOp[] {\n return [createRemoveKindOp({ kind: definition.kind })];\n}\n","/*\n * Copyright 2026 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 { CatalogModelOp } from '../operations';\nimport { createDeclareRelationOp } from '../operations/declareRelation';\n\n/**\n * The definition of a catalog model relation.\n *\n * @alpha\n */\nexport interface CatalogModelRelationPairDefinition {\n /**\n * The kind(s) that this relation originates from, e.g. \"Component\" or\n * [\"Component\", \"Resource\"].\n */\n fromKind: string | string[];\n\n /**\n * The kind(s) that this relation points to, e.g. \"Group\" or\n * [\"Group\", \"User\"].\n */\n toKind: string | string[];\n\n /**\n * A human-readable description of the relation.\n */\n description: string;\n\n /**\n * The names for the forward direction (from the current entity toward\n * the one being referenced).\n */\n forward: {\n /**\n * The technical type of the relation, e.g. \"ownedBy\"\n */\n type: string;\n /**\n * A human-readable title for the relation type, e.g. \"owned by\".\n */\n title: string;\n };\n\n /**\n * The names for the reverse direction (from the one being referenced\n * toward the current entity).\n */\n reverse: {\n /**\n * The technical type of the relation, e.g. \"ownerOf\"\n */\n type: string;\n /**\n * A human-readable title for the relation type, e.g. \"owner of\".\n */\n title: string;\n };\n}\n\nexport function opsFromCatalogModelRelationPair(\n relationPair: CatalogModelRelationPairDefinition,\n): CatalogModelOp[] {\n const ops: CatalogModelOp[] = [];\n\n // Duplicate across kinds, and both directions\n for (const firstKind of [relationPair.fromKind].flat()) {\n for (const secondKind of [relationPair.toKind].flat()) {\n ops.push(\n createDeclareRelationOp({\n fromKind: firstKind,\n type: relationPair.forward.type,\n toKind: secondKind,\n properties: {\n reverseType: relationPair.reverse.type,\n title: relationPair.forward.title,\n description: relationPair.description,\n },\n }),\n );\n ops.push(\n createDeclareRelationOp({\n fromKind: secondKind,\n type: relationPair.reverse.type,\n toKind: firstKind,\n properties: {\n reverseType: relationPair.forward.type,\n title: relationPair.reverse.title,\n description: relationPair.description,\n },\n }),\n );\n }\n }\n\n return ops;\n}\n","/*\n * Copyright 2026 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 { CatalogModelOp } from '../operations';\nimport { createUpdateRelationOp } from '../operations/updateRelation';\n\n/**\n * The definition of a catalog model relation.\n *\n * @alpha\n */\nexport interface CatalogModelUpdateRelationPairDefinition {\n /**\n * The kind(s) that this relation originates from, e.g. \"Component\" or\n * [\"Component\", \"Resource\"].\n */\n fromKind: string | string[];\n\n /**\n * The kind(s) that this relation points to, e.g. \"Group\" or\n * [\"Group\", \"User\"].\n */\n toKind: string | string[];\n\n /**\n * A human-readable description of the relation. Specify this if you want\n * to override the default value.\n */\n description?: string;\n\n /**\n * The names for the forward direction (from the current entity toward the one\n * being referenced).\n */\n forward: {\n /**\n * The technical type of the relation, e.g. \"ownedBy\"\n */\n type: string;\n /**\n * A human-readable title for the relation type, e.g. \"owned by\".\n * Specify this if you want to override the default value.\n */\n title?: string;\n };\n\n /**\n * The names for the reverse direction (from the one being referenced toward\n * the current entity).\n */\n reverse: {\n /**\n * The technical type of an existing reverse relation, e.g. \"ownerOf\".\n * If omitted, title updates apply to the currently declared reverse\n * relation.\n */\n type?: string;\n /**\n * A human-readable title for the relation type, e.g. \"owner of\".\n * Specify this if you want to override the default value.\n */\n title?: string;\n };\n}\n\nexport function opsFromCatalogModelUpdateRelationPair(\n relationPair: CatalogModelUpdateRelationPairDefinition,\n): CatalogModelOp[] {\n const ops: CatalogModelOp[] = [];\n\n // Duplicate across kinds, and both directions\n for (const firstKind of [relationPair.fromKind].flat()) {\n for (const secondKind of [relationPair.toKind].flat()) {\n ops.push(\n createUpdateRelationOp({\n fromKind: firstKind,\n type: relationPair.forward.type,\n toKind: secondKind,\n properties: {\n reverseType: relationPair.reverse.type,\n reverseTitle: relationPair.reverse.type\n ? undefined\n : relationPair.reverse.title,\n title: relationPair.forward.title,\n description: relationPair.description,\n },\n }),\n );\n if (relationPair.reverse.type) {\n ops.push(\n createUpdateRelationOp({\n fromKind: secondKind,\n type: relationPair.reverse.type,\n toKind: firstKind,\n properties: {\n reverseType: relationPair.forward.type,\n title: relationPair.reverse.title,\n description: relationPair.description,\n },\n }),\n );\n }\n }\n }\n\n return ops;\n}\n","/*\n * Copyright 2026 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 { InputError } from '@backstage/errors';\nimport { validateMetaSchema } from '../jsonSchema/validateMetaSchema';\nimport { CatalogModelOp } from '../operations';\nimport { createDeclareAnnotationOp } from '../operations/declareAnnotation';\nimport { JsonObject } from '@backstage/types';\n\n/**\n * The definition of a catalog model annotation.\n *\n * @alpha\n */\nexport interface CatalogModelAnnotationDefinition {\n /**\n * The name of the annotation, e.g. \"backstage.io/techdocs-ref\".\n */\n name: string;\n\n /**\n * A human-readable title that can be used for display purposes instead of\n * the technical name.\n */\n title?: string;\n\n /**\n * A human-readable description of the annotation.\n */\n description: string;\n\n /**\n * The JSON schema that values of this annotation must conform to.\n *\n * @remarks\n *\n * If not provided, the annotation is assumed to be a simple string with no\n * particular schema.\n */\n schema?: {\n jsonSchema: JsonObject;\n };\n}\n\nexport function opsFromCatalogModelAnnotation(\n annotation: CatalogModelAnnotationDefinition,\n): CatalogModelOp[] {\n if (annotation.schema?.jsonSchema) {\n validateMetaSchema(annotation.schema.jsonSchema);\n if (annotation.schema.jsonSchema.type !== 'string') {\n throw new InputError(\n `Annotation \"${annotation.name}\" schema must have \"type\": \"string\" at the root, only string values are supported`,\n );\n }\n }\n return [\n createDeclareAnnotationOp({\n name: annotation.name,\n properties: {\n title: annotation.title,\n description: annotation.description,\n schema: annotation.schema,\n },\n }),\n ];\n}\n","/*\n * Copyright 2026 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 { InputError } from '@backstage/errors';\nimport { validateMetaSchema } from '../jsonSchema/validateMetaSchema';\nimport { CatalogModelOp } from '../operations';\nimport { createUpdateAnnotationOp } from '../operations/updateAnnotation';\nimport { JsonObject } from '@backstage/types';\n\n/**\n * The definition of updates to a catalog model annotation.\n *\n * @alpha\n */\nexport interface CatalogModelUpdateAnnotationDefinition {\n /**\n * The name of the annotation, e.g. \"backstage.io/techdocs-ref\".\n */\n name: string;\n\n /**\n * A human-readable title that can be used for display purposes instead of\n * the technical name.\n */\n title?: string;\n\n /**\n * A human-readable description of the annotation.\n */\n description?: string;\n\n /**\n * The JSON schema that values of this annotation must conform to.\n *\n * @remarks\n *\n * If not provided, the annotation is assumed to be a simple string with no\n * particular schema.\n */\n schema?: {\n jsonSchema: JsonObject;\n };\n}\n\nexport function opsFromCatalogModelUpdateAnnotation(\n annotation: CatalogModelUpdateAnnotationDefinition,\n): CatalogModelOp[] {\n if (annotation.schema) {\n validateMetaSchema(annotation.schema.jsonSchema);\n if (annotation.schema.jsonSchema.type !== 'string') {\n throw new InputError(\n `Annotation \"${annotation.name}\" schema must have \"type\": \"string\" at the root, only string values are supported`,\n );\n }\n }\n return [\n createUpdateAnnotationOp({\n name: annotation.name,\n properties: {\n title: annotation.title,\n description: annotation.description,\n schema: annotation.schema,\n },\n }),\n ];\n}\n","/*\n * Copyright 2026 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 { CatalogModelOp } from '../operations';\nimport { createRemoveAnnotationOp } from '../operations/removeAnnotation';\n\n/**\n * The definition of an annotation removal from the catalog model.\n *\n * @alpha\n */\nexport interface CatalogModelRemoveAnnotationDefinition {\n /**\n * The name of the annotation to remove, e.g. \"backstage.io/techdocs-ref\".\n */\n name: string;\n}\n\nexport function opsFromCatalogModelRemoveAnnotation(\n definition: CatalogModelRemoveAnnotationDefinition,\n): CatalogModelOp[] {\n return [createRemoveAnnotationOp({ name: definition.name })];\n}\n","/*\n * Copyright 2026 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 { InputError } from '@backstage/errors';\nimport { validateMetaSchema } from '../jsonSchema/validateMetaSchema';\nimport { CatalogModelOp } from '../operations';\nimport { createDeclareLabelOp } from '../operations/declareLabel';\nimport { JsonObject } from '@backstage/types';\n\n/**\n * The definition of a catalog model label.\n *\n * @alpha\n */\nexport interface CatalogModelLabelDefinition {\n /**\n * The name of the label, e.g. \"backstage.io/source-location\".\n */\n name: string;\n\n /**\n * A human-readable title that can be used for display purposes instead of\n * the technical name.\n */\n title?: string;\n\n /**\n * A human-readable description of the label.\n */\n description: string;\n\n /**\n * The JSON schema that values of this label must conform to.\n *\n * @remarks\n *\n * If not provided, the label is assumed to be a simple string with no\n * particular schema.\n */\n schema?: {\n jsonSchema: JsonObject;\n };\n}\n\nexport function opsFromCatalogModelLabel(\n label: CatalogModelLabelDefinition,\n): CatalogModelOp[] {\n if (label.schema?.jsonSchema) {\n validateMetaSchema(label.schema.jsonSchema);\n if (label.schema.jsonSchema.type !== 'string') {\n throw new InputError(\n `Label \"${label.name}\" schema must have \"type\": \"string\" at the root, only string values are supported`,\n );\n }\n }\n return [\n createDeclareLabelOp({\n name: label.name,\n properties: {\n title: label.title,\n description: label.description,\n schema: label.schema,\n },\n }),\n ];\n}\n","/*\n * Copyright 2026 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 { InputError } from '@backstage/errors';\nimport { validateMetaSchema } from '../jsonSchema/validateMetaSchema';\nimport { CatalogModelOp } from '../operations';\nimport { createUpdateLabelOp } from '../operations/updateLabel';\nimport { JsonObject } from '@backstage/types';\n\n/**\n * The definition of updates to a catalog model label.\n *\n * @alpha\n */\nexport interface CatalogModelUpdateLabelDefinition {\n /**\n * The name of the label, e.g. \"backstage.io/source-location\".\n */\n name: string;\n\n /**\n * A human-readable title that can be used for display purposes instead of\n * the technical name.\n */\n title?: string;\n\n /**\n * A human-readable description of the label.\n */\n description?: string;\n\n /**\n * The JSON schema that values of this label must conform to.\n *\n * @remarks\n *\n * If not provided, the label is assumed to be a simple string with no\n * particular schema.\n */\n schema?: {\n jsonSchema: JsonObject;\n };\n}\n\nexport function opsFromCatalogModelUpdateLabel(\n label: CatalogModelUpdateLabelDefinition,\n): CatalogModelOp[] {\n if (label.schema) {\n validateMetaSchema(label.schema.jsonSchema);\n if (label.schema.jsonSchema.type !== 'string') {\n throw new InputError(\n `Label \"${label.name}\" schema must have \"type\": \"string\" at the root, only string values are supported`,\n );\n }\n }\n return [\n createUpdateLabelOp({\n name: label.name,\n properties: {\n title: label.title,\n description: label.description,\n schema: label.schema,\n },\n }),\n ];\n}\n","/*\n * Copyright 2026 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 { CatalogModelOp } from '../operations';\nimport { createRemoveLabelOp } from '../operations/removeLabel';\n\n/**\n * The definition of a label removal from the catalog model.\n *\n * @alpha\n */\nexport interface CatalogModelRemoveLabelDefinition {\n /**\n * The name of the label to remove, e.g. \"backstage.io/source-location\".\n */\n name: string;\n}\n\nexport function opsFromCatalogModelRemoveLabel(\n definition: CatalogModelRemoveLabelDefinition,\n): CatalogModelOp[] {\n return [createRemoveLabelOp({ name: definition.name })];\n}\n","/*\n * Copyright 2026 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 { CatalogModelOp } from '../operations';\nimport { createDeclareTagOp } from '../operations/declareTag';\n\n/**\n * The definition of a catalog model tag.\n *\n * @alpha\n */\nexport interface CatalogModelTagDefinition {\n /**\n * The name of the tag, e.g. \"java\".\n */\n name: string;\n\n /**\n * A human-readable title that can be used for display purposes instead of\n * the technical name.\n */\n title?: string;\n\n /**\n * A human-readable description of the tag.\n */\n description: string;\n}\n\nexport function opsFromCatalogModelTag(\n tag: CatalogModelTagDefinition,\n): CatalogModelOp[] {\n return [\n createDeclareTagOp({\n name: tag.name,\n properties: {\n title: tag.title,\n description: tag.description,\n },\n }),\n ];\n}\n","/*\n * Copyright 2026 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 { CatalogModelOp } from '../operations';\nimport { createUpdateTagOp } from '../operations/updateTag';\n\n/**\n * The definition of updates to a catalog model tag.\n *\n * @alpha\n */\nexport interface CatalogModelUpdateTagDefinition {\n /**\n * The name of the tag, e.g. \"java\".\n */\n name: string;\n\n /**\n * A human-readable title that can be used for display purposes instead of\n * the technical name.\n */\n title?: string;\n\n /**\n * A human-readable description of the tag.\n */\n description?: string;\n}\n\nexport function opsFromCatalogModelUpdateTag(\n tag: CatalogModelUpdateTagDefinition,\n): CatalogModelOp[] {\n return [\n createUpdateTagOp({\n name: tag.name,\n properties: {\n title: tag.title,\n description: tag.description,\n },\n }),\n ];\n}\n","/*\n * Copyright 2026 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 { CatalogModelOp } from '../operations';\nimport { createRemoveTagOp } from '../operations/removeTag';\n\n/**\n * The definition of a tag removal from the catalog model.\n *\n * @alpha\n */\nexport interface CatalogModelRemoveTagDefinition {\n /**\n * The name of the tag to remove, e.g. \"java\".\n */\n name: string;\n}\n\nexport function opsFromCatalogModelRemoveTag(\n definition: CatalogModelRemoveTagDefinition,\n): CatalogModelOp[] {\n return [createRemoveTagOp({ name: definition.name })];\n}\n","/*\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 { createCatalogModelLayer } from '../model/createCatalogModelLayer';\n\n/*\nNaming rules for relations in priority order:\n\n1. Use at most two words. One main verb and a specifier, e.g. \"ownerOf\"\n2. Reading out \"<source-kind> <type> <target-kind>\" should make sense in English.\n3. Maintain symmetry between pairs, e.g. \"ownedBy\" and \"ownerOf\" rather than \"owns\".\n*/\n\n/**\n * An ownership relation where the owner is usually an organizational\n * entity (user or group), and the other entity can be anything. Reversed\n * direction of {@link RELATION_OWNER_OF}.\n *\n * @public\n */\nexport const RELATION_OWNED_BY = 'ownedBy';\n\n/**\n * A relationship from an owner to the owned entity. Reversed direction of\n * {@link RELATION_OWNED_BY}.\n *\n * @public\n */\nexport const RELATION_OWNER_OF = 'ownerOf';\n\n/**\n * A relation with an API entity, typically from a component. Reversed direction of\n * {@link RELATION_API_CONSUMED_BY}.\n *\n * @public\n */\nexport const RELATION_CONSUMES_API = 'consumesApi';\n\n/**\n * A relation of an API being consumed, typically by a component. Reversed direction of\n * {@link RELATION_CONSUMES_API}.\n *\n * @public\n */\nexport const RELATION_API_CONSUMED_BY = 'apiConsumedBy';\n\n/**\n * A relation from an API provider entity (typically a component) to the API. Reversed direction of\n * {@link RELATION_API_PROVIDED_BY}.\n *\n * @public\n */\nexport const RELATION_PROVIDES_API = 'providesApi';\n\n/**\n * A relation from an API to its provider entity (typically a component). Reversed direction of\n * {@link RELATION_PROVIDES_API}.\n *\n * @public\n */\nexport const RELATION_API_PROVIDED_BY = 'apiProvidedBy';\n\n/**\n * A relation denoting a dependency on another entity. Reversed direction of\n * {@link RELATION_DEPENDENCY_OF}.\n *\n * @public\n */\nexport const RELATION_DEPENDS_ON = 'dependsOn';\n\n/**\n * A relation denoting a reverse dependency by another entity. Reversed direction of\n * {@link RELATION_DEPENDS_ON}.\n *\n * @public\n */\nexport const RELATION_DEPENDENCY_OF = 'dependencyOf';\n\n/**\n * A parent/child relation to build up a tree, used for example to describe\n * the organizational structure between groups. Reversed direction of\n * {@link RELATION_CHILD_OF}.\n *\n * @public\n */\nexport const RELATION_PARENT_OF = 'parentOf';\n\n/**\n * A relation from a child to a parent entity, used for example to describe\n * the organizational structure between groups. Reversed direction of\n * {@link RELATION_PARENT_OF}.\n *\n * @public\n */\nexport const RELATION_CHILD_OF = 'childOf';\n\n/**\n * A membership relation, typically for users in a group. Reversed direction of\n * {@link RELATION_HAS_MEMBER}.\n *\n * @public\n */\nexport const RELATION_MEMBER_OF = 'memberOf';\n\n/**\n * A relation from a group to its member, typically a user in a group. Reversed direction of\n * {@link RELATION_MEMBER_OF}.\n *\n * @public\n */\nexport const RELATION_HAS_MEMBER = 'hasMember';\n\n/**\n * A part/whole relation, typically for components in a system and systems\n * in a domain. Reversed direction of {@link RELATION_HAS_PART}.\n *\n * @public\n */\nexport const RELATION_PART_OF = 'partOf';\n\n/**\n * A relation from a containing entity to a contained entity. Reversed direction of\n * {@link RELATION_PART_OF}.\n *\n * @public\n */\nexport const RELATION_HAS_PART = 'hasPart';\n\n/**\n * Extends the catalog model with the well-known Backstage relation pairs.\n */\nexport const wellKnownRelationsModel = createCatalogModelLayer({\n layerId: 'catalog.backstage.io/well-known-relations',\n builder: model => {\n model.addRelationPair({\n fromKind: [\n 'API',\n 'Component',\n 'Domain',\n 'Group',\n 'Location',\n 'Resource',\n 'System',\n 'User',\n ],\n toKind: ['Group', 'User'],\n description:\n 'An ownership relation where the owner is usually an organizational entity (user or group), and the other entity can be anything.',\n forward: { type: 'ownedBy', title: 'owned by' },\n reverse: { type: 'ownerOf', title: 'owner of' },\n });\n\n model.addRelationPair({\n fromKind: 'Component',\n toKind: 'API',\n description:\n 'A relation from a component to an API it provides for consumption by others.',\n forward: { type: 'providesApi', title: 'provides API' },\n reverse: { type: 'apiProvidedBy', title: 'API provided by' },\n });\n\n model.addRelationPair({\n fromKind: 'Component',\n toKind: 'API',\n description: 'A relation from a component to an API it consumes.',\n forward: { type: 'consumesApi', title: 'consumes API' },\n reverse: { type: 'apiConsumedBy', title: 'API consumed by' },\n });\n\n model.addRelationPair({\n fromKind: ['Component', 'Resource'],\n toKind: ['Component', 'Resource'],\n description:\n 'A dependency relation expressing that an entity needs another entity to function.',\n forward: { type: 'dependsOn', title: 'depends on' },\n reverse: { type: 'dependencyOf', title: 'dependency of' },\n });\n\n model.addRelationPair({\n fromKind: 'Group',\n toKind: 'Group',\n description:\n 'A parent/child relation to build up a tree, used for example to describe the organizational structure between groups.',\n forward: { type: 'parentOf', title: 'parent of' },\n reverse: { type: 'childOf', title: 'child of' },\n });\n\n model.addRelationPair({\n fromKind: 'User',\n toKind: 'Group',\n description: 'A membership relation, typically for users in a group.',\n forward: { type: 'memberOf', title: 'member of' },\n reverse: { type: 'hasMember', title: 'has member' },\n });\n\n model.addRelationPair({\n fromKind: ['Component', 'API', 'Resource'],\n toKind: ['Component', 'System'],\n description:\n 'A part/whole relation where a component, API, or resource belongs to a system or a component is a subcomponent of another.',\n forward: { type: 'partOf', title: 'part of' },\n reverse: { type: 'hasPart', title: 'has part' },\n });\n\n model.addRelationPair({\n fromKind: 'System',\n toKind: 'Domain',\n description: 'A part/whole relation where a system belongs to a domain.',\n forward: { type: 'partOf', title: 'part of' },\n reverse: { type: 'hasPart', title: 'has part' },\n });\n\n model.addRelationPair({\n fromKind: 'Domain',\n toKind: 'Domain',\n description:\n 'A part/whole relation where a domain is a subdomain of another domain.',\n forward: { type: 'partOf', title: 'part of' },\n reverse: { type: 'hasPart', title: 'has part' },\n });\n },\n});\n","/*\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 missingAnnotation from './assets/missingAnnotation.svg';\nimport noInformation from './assets/noInformation.svg';\nimport createComponent from './assets/createComponent.svg';\nimport noBuild from './assets/noBuild.svg';\nimport { makeStyles } from '@material-ui/core/styles';\n\ntype Props = {\n missing: 'field' | 'info' | 'content' | 'data';\n};\n\n/** @public */\nexport type EmptyStateImageClassKey = 'generalImg';\n\nconst useStyles = makeStyles(\n {\n generalImg: {\n width: '95%',\n zIndex: 2,\n position: 'relative',\n left: '50%',\n top: '50%',\n transform: 'translate(-50%, 15%)',\n },\n },\n { name: 'BackstageEmptyStateImage' },\n);\n\n/** @public */\nexport const EmptyStateImage = ({ missing }: Props) => {\n const classes = useStyles();\n switch (missing) {\n case 'field':\n return (\n <img\n src={missingAnnotation}\n className={classes.generalImg}\n alt=\"annotation is missing\"\n />\n );\n case 'info':\n return (\n <img\n src={noInformation}\n alt=\"no Information\"\n className={classes.generalImg}\n />\n );\n case 'content':\n return (\n <img\n src={createComponent}\n alt=\"create Component\"\n className={classes.generalImg}\n />\n );\n case 'data':\n return (\n <img src={noBuild} alt=\"no Build\" className={classes.generalImg} />\n );\n default:\n return null;\n }\n};\n","/*\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 Grid from '@material-ui/core/Grid';\nimport { makeStyles } from '@material-ui/core/styles';\nimport Typography from '@material-ui/core/Typography';\nimport { EmptyStateImage } from './EmptyStateImage';\n\n/** @public */\nexport type EmptyStateClassKey = 'root' | 'action' | 'imageContainer';\n\nconst useStyles = makeStyles(\n theme => ({\n root: {\n backgroundColor: theme.palette.background.default,\n padding: theme.spacing(2, 0, 0, 0),\n },\n action: {\n marginTop: theme.spacing(2),\n },\n imageContainer: {\n position: 'relative',\n },\n }),\n { name: 'BackstageEmptyState' },\n);\n\ntype Props = {\n title: string;\n description?: string | JSX.Element;\n missing: 'field' | 'info' | 'content' | 'data' | { customImage: JSX.Element };\n action?: JSX.Element;\n};\n\n/**\n * Various placeholder views for empty state pages\n *\n * @public\n *\n */\nexport function EmptyState(props: Props) {\n const { title, description, missing, action } = props;\n const classes = useStyles();\n return (\n <Grid\n container\n direction=\"row\"\n justifyContent=\"space-around\"\n alignItems=\"flex-start\"\n className={classes.root}\n spacing={2}\n >\n <Grid item xs={12} md={6}>\n <Grid container direction=\"column\">\n <Grid item xs>\n <Typography variant=\"h5\">{title}</Typography>\n </Grid>\n <Grid item xs>\n <Typography variant=\"body1\">{description}</Typography>\n </Grid>\n <Grid item xs className={classes.action}>\n {action}\n </Grid>\n </Grid>\n </Grid>\n <Grid item xs={12} md={6} className={classes.imageContainer}>\n {typeof missing === 'string' ? (\n <EmptyStateImage missing={missing} />\n ) : (\n missing.customImage\n )}\n </Grid>\n </Grid>\n );\n}\n","/*\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 */\nimport { ComponentProps } from 'react';\nimport IconButton from '@material-ui/core/IconButton';\nimport Tooltip from '@material-ui/core/Tooltip';\nimport Typography from '@material-ui/core/Typography';\nimport { Theme, makeStyles } from '@material-ui/core/styles';\nimport { StarIcon, UnstarredIcon } from '../../icons';\n\nconst useStyles = makeStyles<Theme>(\n () => ({\n icon: {\n color: '#f3ba37',\n cursor: 'pointer',\n display: 'inline-flex',\n },\n iconBorder: {\n color: 'inherit',\n cursor: 'pointer',\n display: 'inline-flex',\n },\n }),\n { name: 'BackstageFavoriteToggleIcon' },\n);\n\n/**\n * @public\n */\nexport type FavoriteToggleIconClassKey = 'icon' | 'iconBorder';\n\n/**\n * Icon used in FavoriteToggle component.\n *\n * Can be used independently, useful when used as {@link @material-table/core#MaterialTableProps.actions} in {@link @material-table/core#MaterialTable}\n *\n * @public\n */\nexport function FavoriteToggleIcon(props: { isFavorite: boolean }) {\n const { isFavorite } = props;\n const classes = useStyles();\n\n return (\n <Typography\n component=\"span\"\n className={isFavorite ? classes.icon : classes.iconBorder}\n >\n {isFavorite ? <StarIcon /> : <UnstarredIcon />}\n </Typography>\n );\n}\n\n/**\n * Props for the {@link FavoriteToggle} component.\n *\n * @public\n */\nexport type FavoriteToggleProps = ComponentProps<typeof IconButton> & {\n id: string;\n title: string;\n isFavorite: boolean;\n onToggle: (value: boolean) => void;\n};\n\n/**\n * Toggle encapsulating logic for marking something as favorite,\n * primarily used in various instances of entity lists and cards but can be used elsewhere.\n *\n * This component can only be used in as a controlled toggle and does not keep internal state.\n *\n * @public\n */\nexport function FavoriteToggle(props: FavoriteToggleProps) {\n const {\n id,\n title,\n isFavorite: value,\n onToggle: onChange,\n ...iconButtonProps\n } = props;\n return (\n <Tooltip id={id} title={title}>\n <IconButton\n aria-label={title}\n id={id}\n onClick={() => onChange(!value)}\n color=\"inherit\"\n {...iconButtonProps}\n >\n <FavoriteToggleIcon isFavorite={value} />\n </IconButton>\n </Tooltip>\n );\n}\n","/*\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 MaterialButton, {\n ButtonProps as MaterialButtonProps,\n} from '@material-ui/core/Button';\nimport { forwardRef } from 'react';\nimport { UnstyledLink, LinkProps } from '../Link/Link';\n\n/**\n * Properties for {@link LinkButton}\n *\n * @public\n * @remarks\n *\n * See {@link https://v4.mui.com/api/button/#props | Material UI Button Props} for all properties\n */\nexport type LinkButtonProps = MaterialButtonProps &\n Omit<LinkProps, 'variant' | 'color'>;\n\n/**\n * This wrapper is here to reset the color of the Link and make typescript happy.\n */\nconst LinkWrapper = forwardRef<any, LinkProps>((props, ref) => (\n <UnstyledLink ref={ref} {...props} color=\"initial\" />\n));\n\n/**\n * Thin wrapper on top of material-ui's {@link https://v4.mui.com/components/buttons/ | Button} component\n *\n * @public\n * @remarks\n */\nexport const LinkButton = forwardRef<any, LinkButtonProps>((props, ref) => (\n <MaterialButton ref={ref} component={LinkWrapper} {...props} />\n)) as (props: LinkButtonProps) => JSX.Element;\n\n/**\n * @public\n * @deprecated use LinkButton instead\n */\nexport const Button = LinkButton;\n\n/**\n * @public\n * @deprecated use LinkButtonProps instead\n */\nexport type ButtonProps = LinkButtonProps;\n","/*\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 */\nimport { makeStyles, createStyles } from '@material-ui/core/styles';\nimport SvgIcon from '@material-ui/core/SvgIcon';\n\n/** @public */\nexport type ClosedDropdownClassKey = 'icon';\n\nconst useStyles = makeStyles(\n theme =>\n createStyles({\n icon: {\n position: 'absolute',\n right: theme.spacing(0.5),\n pointerEvents: 'none',\n color: '#616161',\n },\n }),\n { name: 'BackstageClosedDropdown' },\n);\n\nconst ClosedDropdown = () => {\n const classes = useStyles();\n return (\n <SvgIcon\n className={classes.icon}\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n d=\"M7.5 8L6 9.5L12.0703 15.5703L18.1406 9.5L16.6406 8L12.0703 12.5703L7.5 8Z\"\n fill=\"currentColor\"\n />\n </SvgIcon>\n );\n};\n\nexport default ClosedDropdown;\n","/*\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 */\nimport { makeStyles, createStyles } from '@material-ui/core/styles';\nimport SvgIcon from '@material-ui/core/SvgIcon';\n\nexport type OpenedDropdownClassKey = 'icon';\n\nconst useStyles = makeStyles(\n theme =>\n createStyles({\n icon: {\n position: 'absolute',\n right: theme.spacing(0.5),\n pointerEvents: 'none',\n color: '#616161',\n },\n }),\n { name: 'BackstageOpenedDropdown' },\n);\n\nconst OpenedDropdown = () => {\n const classes = useStyles();\n return (\n <SvgIcon\n className={classes.icon}\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n d=\"M16.5 16L18 14.5L11.9297 8.42969L5.85938 14.5L7.35938 16L11.9297 11.4297L16.5 16Z\"\n fill=\"currentColor\"\n />\n </SvgIcon>\n );\n};\n\nexport default OpenedDropdown;\n","/*\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 */\nimport Box from '@material-ui/core/Box';\nimport Checkbox from '@material-ui/core/Checkbox';\nimport Chip from '@material-ui/core/Chip';\nimport FormControl from '@material-ui/core/FormControl';\nimport InputBase from '@material-ui/core/InputBase';\nimport InputLabel from '@material-ui/core/InputLabel';\nimport MenuItem from '@material-ui/core/MenuItem';\nimport Select from '@material-ui/core/Select';\nimport {\n createStyles,\n makeStyles,\n Theme,\n withStyles,\n} from '@material-ui/core/styles';\nimport Typography from '@material-ui/core/Typography';\nimport CancelIcon from '@material-ui/icons/Cancel';\nimport { ChangeEvent, useEffect, useState } from 'react';\n\nimport ClosedDropdown from './static/ClosedDropdown';\nimport OpenedDropdown from './static/OpenedDropdown';\n\n/** @public */\nexport type SelectInputBaseClassKey = 'root' | 'input';\n\nconst BootstrapInput = withStyles(\n (theme: Theme) =>\n createStyles({\n root: {\n 'label + &': {\n marginTop: theme.spacing(3),\n },\n '&.Mui-focused > div[role=button]': {\n borderColor: theme.palette.primary.main,\n },\n },\n input: {\n borderRadius: theme.shape.borderRadius,\n position: 'relative',\n backgroundColor: theme.palette.background.paper,\n border: '1px solid #ced4da',\n fontSize: theme.typography.body1.fontSize,\n padding: theme.spacing(1.25, 3.25, 1.25, 1.5),\n transition: theme.transitions.create(['border-color', 'box-shadow']),\n '&:focus': {\n background: theme.palette.background.paper,\n borderRadius: theme.shape.borderRadius,\n },\n },\n }),\n { name: 'BackstageSelectInputBase' },\n)(InputBase);\n\n/** @public */\nexport type SelectClassKey =\n | 'formControl'\n | 'label'\n | 'chips'\n | 'chip'\n | 'checkbox'\n | 'root';\n\nconst useStyles = makeStyles(\n (theme: Theme) =>\n createStyles({\n formControl: {\n margin: theme.spacing(1, 0),\n },\n label: {\n transform: 'initial',\n fontWeight: 'bold',\n fontSize: theme.typography.body2.fontSize,\n fontFamily: theme.typography.fontFamily,\n color: theme.palette.text.primary,\n '&.Mui-focused': {\n color: theme.palette.text.primary,\n },\n },\n formLabel: {\n transform: 'initial',\n fontWeight: 'bold',\n fontSize: theme.typography.body2.fontSize,\n fontFamily: theme.typography.fontFamily,\n color: theme.palette.text.primary,\n '&.Mui-focused': {\n color: theme.palette.text.primary,\n },\n },\n chips: {\n display: 'flex',\n flexWrap: 'wrap',\n },\n chip: {\n margin: 2,\n },\n checkbox: {},\n\n root: {\n display: 'flex',\n flexDirection: 'column',\n },\n }),\n { name: 'BackstageSelect' },\n);\n\n/** @public */\nexport type SelectItem = {\n label: string;\n value: string | number;\n};\n\n/** @public */\nexport type SelectedItems = string | string[] | number | number[];\n\nexport type SelectProps = {\n multiple?: boolean;\n items: SelectItem[];\n label: string;\n placeholder?: string;\n selected?: SelectedItems;\n onChange: (arg: SelectedItems) => void;\n triggerReset?: boolean;\n native?: boolean;\n disabled?: boolean;\n margin?: 'dense' | 'none';\n 'data-testid'?: string;\n};\n\n/** @public */\nexport function SelectComponent(props: SelectProps) {\n const {\n multiple,\n items,\n label,\n placeholder,\n selected,\n onChange,\n triggerReset,\n native = false,\n disabled = false,\n margin,\n 'data-testid': dataTestId = 'select',\n } = props;\n const classes = useStyles();\n const [value, setValue] = useState<SelectedItems>(\n selected || (multiple ? [] : ''),\n );\n const [isOpen, setOpen] = useState(false);\n\n useEffect(() => {\n setValue(multiple ? [] : '');\n }, [triggerReset, multiple]);\n\n useEffect(() => {\n setValue(selected || (multiple ? [] : ''));\n }, [selected, multiple]);\n\n const handleChange = (event: ChangeEvent<{ value: unknown }>) => {\n setValue(event.target.value as SelectedItems);\n onChange(event.target.value as SelectedItems);\n };\n\n const handleOpen = (event: ChangeEvent<any>) => {\n if (disabled) {\n event.preventDefault();\n return;\n }\n setOpen(previous => {\n if (multiple && !(event.target instanceof HTMLElement)) {\n return true;\n }\n return !previous;\n });\n };\n\n const handleClose = () => {\n setOpen(false);\n };\n\n const handleDelete = (selectedValue: string | number) => () => {\n const newValue = (value as any[]).filter(chip => chip !== selectedValue);\n setValue(newValue);\n onChange(newValue);\n };\n\n return (\n <Box className={classes.root}>\n <FormControl className={classes.formControl}>\n <InputLabel className={classes.formLabel}>{label}</InputLabel>\n <Select\n aria-label={label}\n value={value}\n native={native}\n disabled={disabled}\n data-testid={dataTestId}\n displayEmpty\n multiple={multiple}\n margin={margin}\n onChange={handleChange}\n open={isOpen}\n onOpen={handleOpen}\n onClose={handleClose}\n input={<BootstrapInput />}\n label={label}\n renderValue={s =>\n multiple && (value as any[]).length !== 0 ? (\n <Box className={classes.chips}>\n {(s as string[]).map(selectedValue => {\n const item = items.find(el => el.value === selectedValue);\n return item ? (\n <Chip\n data-testid=\"chip\"\n key={item?.value}\n label={item?.label}\n clickable\n deleteIcon={\n <CancelIcon\n data-testid=\"cancel-icon\"\n onMouseDown={event => event.stopPropagation()}\n />\n }\n onDelete={handleDelete(selectedValue)}\n className={classes.chip}\n />\n ) : (\n false\n );\n })}\n </Box>\n ) : (\n <Typography>\n {(value as any[]).length === 0\n ? placeholder || ''\n : items.find(el => el.value === s)?.label}\n </Typography>\n )\n }\n IconComponent={() =>\n !isOpen ? <ClosedDropdown /> : <OpenedDropdown />\n }\n MenuProps={{\n anchorOrigin: {\n vertical: 'bottom',\n horizontal: 'left',\n },\n transformOrigin: {\n vertical: 'top',\n horizontal: 'left',\n },\n getContentAnchorEl: null,\n }}\n >\n {!!placeholder && !multiple && (\n <MenuItem value={[]}>{placeholder}</MenuItem>\n )}\n {native\n ? items &&\n items.map(item => (\n <option value={item.value} key={item.value}>\n {item.label}\n </option>\n ))\n : items &&\n items.map(item => (\n <MenuItem key={item.value} value={item.value}>\n {multiple && (\n <Checkbox\n color=\"primary\"\n checked={(value as any[]).includes(item.value) || false}\n className={classes.checkbox}\n />\n )}\n {item.label}\n </MenuItem>\n ))}\n </Select>\n </FormControl>\n </Box>\n );\n}\n","/*\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 Box from '@material-ui/core/Box';\nimport Button from '@material-ui/core/Button';\nimport { makeStyles } from '@material-ui/core/styles';\nimport { useEffect, useState } from 'react';\n\nimport { Select } from '../Select';\nimport { SelectProps } from '../Select/Select';\nimport { coreComponentsTranslationRef } from '../../translation';\nimport { useTranslationRef } from '@backstage/core-plugin-api/alpha';\n\nexport type TableFiltersClassKey =\n | 'root'\n | 'value'\n | 'header'\n /**\n * @deprecated Use `'header'` instead. This was a typo in the original class key.\n */\n | 'heder'\n | 'filters';\n\nconst useFilterStyles = makeStyles(\n theme => ({\n root: {\n height: '100%',\n width: '315px',\n display: 'flex',\n flexDirection: 'column',\n marginRight: theme.spacing(3),\n },\n value: {\n fontWeight: 'bold',\n fontSize: 18,\n },\n header: {\n display: 'flex',\n alignItems: 'center',\n height: theme.spacing(7.5),\n justifyContent: 'space-between',\n borderBottom: `1px solid ${theme.palette.grey[500]}`,\n },\n // Intentionally empty: the deprecated `heder` class is still applied to\n // the same element as `header` so legacy theme overrides on\n // `BackstageTableFilters.heder` continue to work. Keeping this rule empty\n // (rather than duplicating `header`'s styles) avoids clobbering overrides\n // on the canonical `header` key — JSS injects rules in key order, so an\n // empty `heder` defined after `header` has no properties to override.\n heder: {},\n filters: {\n display: 'flex',\n flexDirection: 'column',\n '& > *': {\n marginTop: theme.spacing(2),\n },\n },\n }),\n { name: 'BackstageTableFilters' },\n);\n\nexport type Without<T, K> = Pick<T, Exclude<keyof T, K>>;\n\nexport type Filter = {\n type: 'select' | 'multiple-select';\n element: Without<SelectProps, 'onChange'>;\n};\n\nexport type SelectedFilters = {\n [key: string]: string | string[];\n};\n\ntype Props = {\n filters: Filter[];\n selectedFilters?: SelectedFilters;\n onChangeFilters: (arg: any) => any;\n};\n\nexport const Filters = (props: Props) => {\n const classes = useFilterStyles();\n\n const { onChangeFilters } = props;\n const { t } = useTranslationRef(coreComponentsTranslationRef);\n\n const [selectedFilters, setSelectedFilters] = useState<SelectedFilters>({\n ...props.selectedFilters,\n });\n const [reset, triggerReset] = useState(false);\n\n // Trigger re-rendering\n const handleClick = () => {\n setSelectedFilters({});\n triggerReset(el => !el);\n };\n\n useEffect(() => {\n onChangeFilters(selectedFilters);\n }, [selectedFilters, onChangeFilters]);\n\n // As material table doesn't provide a way to add a column filter tab we will make our own filter logic\n return (\n <Box className={classes.root}>\n <Box className={`${classes.header} ${classes.heder}`}>\n <Box className={classes.value}>{t('table.filter.title')}</Box>\n <Button color=\"primary\" onClick={handleClick}>\n {t('table.filter.clearAll')}\n </Button>\n </Box>\n <Box className={classes.filters}>\n {!!props.filters?.length &&\n props.filters.map(filter => (\n <Select\n triggerReset={reset}\n key={filter.element.label}\n {...(filter.element as SelectProps)}\n selected={selectedFilters[filter.element.label]}\n onChange={el =>\n setSelectedFilters({\n ...selectedFilters,\n [filter.element.label]: el as any,\n })\n }\n />\n ))}\n </Box>\n </Box>\n );\n};\n","/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport Box from '@material-ui/core/Box';\nimport CircularProgress from '@material-ui/core/CircularProgress';\n\n/**\n * @internal\n */\nexport function TableLoadingBody(props: { colSpan?: number }) {\n return (\n <tbody data-testid=\"loading-indicator\">\n <tr>\n <td colSpan={props.colSpan}>\n <Box\n sx={{\n display: 'flex',\n justifyContent: 'center',\n alignItems: 'center',\n width: '100%',\n minHeight: '15rem',\n }}\n >\n <CircularProgress size=\"5rem\" />\n </Box>\n </td>\n </tr>\n </tbody>\n );\n}\n","/*\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 TranslationFunction,\n useTranslationRef,\n} from '@backstage/core-plugin-api/alpha';\nimport MTable, {\n Column,\n Icons,\n MaterialTableProps,\n MTableBody,\n MTableHeader,\n MTableToolbar,\n Options,\n} from '@material-table/core';\nimport Box from '@material-ui/core/Box';\nimport IconButton from '@material-ui/core/IconButton';\nimport {\n makeStyles,\n Theme,\n useTheme,\n withStyles,\n} from '@material-ui/core/styles';\nimport Typography from '@material-ui/core/Typography';\nimport AddBox from '@material-ui/icons/AddBox';\nimport ArrowUpward from '@material-ui/icons/ArrowUpward';\nimport Check from '@material-ui/icons/Check';\nimport ChevronLeft from '@material-ui/icons/ChevronLeft';\nimport ChevronRight from '@material-ui/icons/ChevronRight';\nimport Clear from '@material-ui/icons/Clear';\nimport DeleteOutline from '@material-ui/icons/DeleteOutline';\nimport Edit from '@material-ui/icons/Edit';\nimport FilterList from '@material-ui/icons/FilterList';\nimport Search from '@material-ui/icons/Search';\nimport FirstPage from '@material-ui/icons/FirstPage';\nimport LastPage from '@material-ui/icons/LastPage';\nimport Remove from '@material-ui/icons/Remove';\nimport SaveAlt from '@material-ui/icons/SaveAlt';\nimport ViewColumn from '@material-ui/icons/ViewColumn';\nimport { isEqual, transform } from 'lodash';\nimport {\n CSSProperties,\n forwardRef,\n MutableRefObject,\n ReactNode,\n useCallback,\n useEffect,\n useMemo,\n useState,\n} from 'react';\n\nimport { coreComponentsTranslationRef } from '../../translation';\nimport { SelectProps } from '../Select/Select';\nimport { Filter, Filters, SelectedFilters, Without } from './Filters';\nimport { TableLoadingBody } from './TableLoadingBody';\n\n// Material-table is not using the standard icons available in in material-ui. https://github.com/mbrn/material-table/issues/51\nconst tableIcons: Icons = {\n Add: forwardRef<SVGSVGElement>((props, ref) => (\n <AddBox {...props} ref={ref} />\n )),\n Check: forwardRef<SVGSVGElement>((props, ref) => (\n <Check {...props} ref={ref} />\n )),\n Clear: forwardRef<SVGSVGElement>((props, ref) => (\n <Clear {...props} ref={ref} />\n )),\n Delete: forwardRef<SVGSVGElement>((props, ref) => (\n <DeleteOutline {...props} ref={ref} />\n )),\n DetailPanel: forwardRef<SVGSVGElement>((props, ref) => (\n <ChevronRight {...props} ref={ref} />\n )),\n Edit: forwardRef<SVGSVGElement>((props, ref) => (\n <Edit {...props} ref={ref} />\n )),\n Export: forwardRef<SVGSVGElement>((props, ref) => (\n <SaveAlt {...props} ref={ref} />\n )),\n Filter: forwardRef<SVGSVGElement>((props, ref) => (\n <FilterList {...props} ref={ref} />\n )),\n FirstPage: forwardRef<SVGSVGElement>((props, ref) => (\n <FirstPage {...props} ref={ref} />\n )),\n LastPage: forwardRef<SVGSVGElement>((props, ref) => (\n <LastPage {...props} ref={ref} />\n )),\n NextPage: forwardRef<SVGSVGElement>((props, ref) => (\n <ChevronRight {...props} ref={ref} />\n )),\n PreviousPage: forwardRef<SVGSVGElement>((props, ref) => (\n <ChevronLeft {...props} ref={ref} />\n )),\n ResetSearch: forwardRef<SVGSVGElement>((props, ref) => (\n <Clear {...props} ref={ref} />\n )),\n Search: forwardRef<SVGSVGElement>((props, ref) => (\n <Search {...props} ref={ref} />\n )),\n SortArrow: forwardRef<SVGSVGElement>((props, ref) => (\n <ArrowUpward {...props} ref={ref} />\n )),\n ThirdStateCheck: forwardRef<SVGSVGElement>((props, ref) => (\n <Remove {...props} ref={ref} />\n )),\n ViewColumn: forwardRef<SVGSVGElement>((props, ref) => (\n <ViewColumn {...props} ref={ref} />\n )),\n};\n\n// TODO: Material table might already have such a function internally that we can use?\nfunction extractValueByField(data: any, field: string): any | undefined {\n const path = field.split('.');\n let value = data[path[0]];\n\n for (let i = 1; i < path.length; ++i) {\n if (value === undefined) {\n return value;\n }\n\n const f = path[i];\n value = value[f];\n }\n\n return value;\n}\n\nexport type TableHeaderClassKey = 'header';\n\nconst StyledMTableHeader = withStyles(\n theme => ({\n header: {\n padding: theme.spacing(1, 2, 1, 2.5),\n borderTop: `1px solid ${theme.palette.grey.A100}`,\n borderBottom: `1px solid ${theme.palette.grey.A100}`,\n // withStyles hasn't a generic overload for theme\n fontWeight: theme.typography.fontWeightBold,\n position: 'static',\n wordBreak: 'normal',\n textTransform: 'uppercase',\n },\n }),\n { name: 'BackstageTableHeader' },\n)(MTableHeader);\n\nexport type TableToolbarClassKey = 'root' | 'title' | 'searchField';\n\nconst StyledMTableToolbar = withStyles(\n theme => ({\n root: {\n padding: theme.spacing(3, 0, 2.5, 2.5),\n },\n title: {\n '& > h6': {\n fontWeight: theme.typography.fontWeightBold,\n },\n },\n searchField: {\n paddingRight: theme.spacing(2),\n },\n }),\n { name: 'BackstageTableToolbar' },\n)(MTableToolbar);\n\n/** @public */\nexport type FiltersContainerClassKey = 'root' | 'filterControls' | 'title';\n\nconst useFilterStyles = makeStyles(\n theme => ({\n root: {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n flexWrap: 'wrap',\n },\n filterControls: {\n display: 'flex',\n alignItems: 'center',\n },\n title: {\n fontWeight: theme.typography.fontWeightBold,\n fontSize: 18,\n whiteSpace: 'nowrap',\n },\n }),\n { name: 'BackstageTableFiltersContainer' },\n);\n\nexport type TableClassKey = 'root';\n\nconst useTableStyles = makeStyles(\n () => ({\n root: {\n display: 'flex',\n alignItems: 'start',\n },\n }),\n { name: 'BackstageTable' },\n);\n\nfunction convertColumns<T extends object>(\n columns: TableColumn<T>[],\n theme: Theme,\n): TableColumn<T>[] {\n return columns.map(column => {\n const headerStyle: CSSProperties = column.headerStyle ?? {};\n\n let cellStyle = column.cellStyle || {};\n\n if (column.highlight) {\n headerStyle.color = theme.palette.textContrast;\n\n if (typeof cellStyle === 'object') {\n (cellStyle as CSSProperties).fontWeight =\n theme.typography.fontWeightBold;\n } else {\n const cellStyleFn = cellStyle as (\n data: any,\n rowData: T,\n column?: Column<T>,\n ) => CSSProperties;\n cellStyle = (data, rowData, rowColumn) => {\n const style = cellStyleFn(data, rowData, rowColumn);\n return { ...style, fontWeight: theme.typography.fontWeightBold };\n };\n }\n }\n\n return {\n ...column,\n headerStyle,\n cellStyle,\n };\n });\n}\n\nfunction removeDefaultValues(state: any, defaultState: any): any {\n return transform(state, (result, value, key) => {\n if (!isEqual(value, defaultState[key])) {\n result[key] = value;\n }\n });\n}\n\nconst defaultInitialState = {\n search: '',\n filtersOpen: false,\n filters: {},\n};\n\nexport interface TableColumn<T extends object = {}> extends Column<T> {\n highlight?: boolean;\n width?: string;\n}\n\nexport type TableFilter = {\n column: string;\n type: 'select' | 'multiple-select';\n};\n\nexport type TableState = {\n search?: string;\n filtersOpen?: boolean;\n filters?: SelectedFilters;\n};\n\nexport interface TableProps<T extends object = {}>\n extends MaterialTableProps<T> {\n columns: TableColumn<T>[];\n subtitle?: string;\n filters?: TableFilter[];\n initialState?: TableState;\n emptyContent?: ReactNode;\n isLoading?: boolean;\n onStateChange?: (state: TableState) => any;\n}\n\nexport interface TableOptions<T extends object = {}> extends Options<T> {}\n\nexport function TableToolbar(toolbarProps: {\n toolbarRef: MutableRefObject<any>;\n setSearch: (value: string) => void;\n onSearchChanged: (value: string) => void;\n toggleFilters: () => void;\n hasFilters: boolean;\n selectedFiltersLength: number;\n}) {\n const {\n toolbarRef,\n setSearch,\n hasFilters,\n selectedFiltersLength,\n toggleFilters,\n } = toolbarProps;\n const { t } = useTranslationRef(coreComponentsTranslationRef);\n const filtersClasses = useFilterStyles();\n const onSearchChanged = useCallback(\n (searchText: string) => {\n toolbarProps.onSearchChanged(searchText);\n setSearch(searchText);\n },\n [toolbarProps, setSearch],\n );\n\n if (hasFilters) {\n return (\n <Box className={filtersClasses.root}>\n <Box className={filtersClasses.filterControls}>\n <IconButton onClick={toggleFilters} aria-label=\"filter list\">\n <FilterList />\n </IconButton>\n <Typography className={filtersClasses.title}>\n {t('table.filter.title')} ({selectedFiltersLength})\n </Typography>\n </Box>\n <StyledMTableToolbar\n {...toolbarProps}\n ref={toolbarRef}\n onSearchChanged={onSearchChanged}\n />\n </Box>\n );\n }\n\n return (\n <StyledMTableToolbar\n {...toolbarProps}\n ref={toolbarRef}\n onSearchChanged={onSearchChanged}\n />\n );\n}\n\n/**\n * @public\n */\nexport function Table<T extends object = {}>(props: TableProps<T>) {\n const {\n data,\n columns,\n emptyContent,\n options,\n title,\n subtitle,\n localization,\n filters,\n initialState,\n onStateChange,\n components,\n isLoading: loading,\n style,\n ...restProps\n } = props;\n const { t } = useTranslationRef(coreComponentsTranslationRef);\n const tableClasses = useTableStyles();\n\n const theme = useTheme();\n\n const calculatedInitialState = { ...defaultInitialState, ...initialState };\n\n const [filtersOpen, setFiltersOpen] = useState(\n calculatedInitialState.filtersOpen,\n );\n const toggleFilters = useCallback(\n () => setFiltersOpen(v => !v),\n [setFiltersOpen],\n );\n\n const [selectedFilters, setSelectedFilters] = useState(\n calculatedInitialState.filters,\n );\n\n const [search, setSearch] = useState(calculatedInitialState.search);\n\n useEffect(() => {\n if (onStateChange) {\n const state = removeDefaultValues(\n {\n search,\n filtersOpen,\n filters: selectedFilters,\n },\n defaultInitialState,\n );\n\n onStateChange(state);\n }\n }, [search, filtersOpen, selectedFilters, onStateChange]);\n\n const getFieldByTitle = useCallback(\n (titleValue: string | keyof T) =>\n columns.find(el => el.title === titleValue)?.field,\n [columns],\n );\n\n const tableData = useMemo(() => {\n if (typeof data === 'function' || !selectedFilters) {\n return data;\n }\n\n const selectedFiltersArray = Object.values(selectedFilters);\n if (data && selectedFiltersArray.flat().length) {\n const newData = (data as any[]).filter(\n el =>\n !!Object.entries(selectedFilters)\n .filter(([, value]) => !!(value as { length?: number }).length)\n .every(([key, filterValue]) => {\n const fieldValue = extractValueByField(\n el,\n getFieldByTitle(key) as string,\n );\n\n if (Array.isArray(fieldValue) && Array.isArray(filterValue)) {\n return fieldValue.some(v => filterValue.includes(v));\n } else if (Array.isArray(fieldValue)) {\n return fieldValue.includes(filterValue);\n } else if (Array.isArray(filterValue)) {\n return filterValue.includes(fieldValue);\n }\n\n return fieldValue === filterValue;\n }),\n );\n return newData;\n }\n return data;\n }, [data, selectedFilters, getFieldByTitle]);\n\n const selectedFiltersLength = Object.values(selectedFilters).flat().length;\n\n const hasFilters = !!filters?.length;\n const Toolbar = useCallback(\n (toolbarProps: any /* no type for this in material-table */) => {\n return (\n <TableToolbar\n setSearch={setSearch}\n hasFilters={hasFilters}\n selectedFiltersLength={selectedFiltersLength}\n toggleFilters={toggleFilters}\n {...toolbarProps}\n />\n );\n },\n [toggleFilters, hasFilters, selectedFiltersLength, setSearch],\n );\n\n const hasNoRows = typeof data !== 'function' && data.length === 0;\n const columnCount = columns.length;\n const Body = useMemo(\n () => makeBody({ hasNoRows, emptyContent, columnCount, loading }),\n [hasNoRows, emptyContent, columnCount, loading],\n );\n\n return (\n <Box className={tableClasses.root}>\n {filtersOpen && data && typeof data !== 'function' && filters?.length && (\n <Filters\n filters={constructFilters(filters, data as any[], columns, t)}\n selectedFilters={selectedFilters}\n onChangeFilters={setSelectedFilters}\n />\n )}\n <MTable<T>\n components={{\n Header: StyledMTableHeader,\n Body,\n Toolbar,\n ...components,\n }}\n options={options}\n columns={convertColumns(columns, theme)}\n icons={tableIcons}\n title={\n <>\n <Typography variant=\"h5\" component=\"h2\">\n {title}\n </Typography>\n {subtitle && (\n <Typography color=\"textSecondary\" variant=\"body1\">\n {subtitle}\n </Typography>\n )}\n </>\n }\n data={tableData}\n style={{ width: '100%', ...style }}\n localization={{\n ...localization,\n body: {\n emptyDataSourceMessage: t('table.body.emptyDataSourceMessage'),\n ...localization?.body,\n },\n pagination: {\n firstTooltip: t('table.pagination.firstTooltip'),\n labelDisplayedRows: t('table.pagination.labelDisplayedRows'),\n labelRowsSelect: t('table.pagination.labelRowsSelect'),\n lastTooltip: t('table.pagination.lastTooltip'),\n nextTooltip: t('table.pagination.nextTooltip'),\n previousTooltip: t('table.pagination.previousTooltip'),\n ...localization?.pagination,\n },\n header: {\n actions: t('table.header.actions'),\n ...localization?.header,\n },\n toolbar: {\n searchPlaceholder: t('table.toolbar.search'),\n searchTooltip: t('table.toolbar.search'),\n ...localization?.toolbar,\n },\n }}\n {...restProps}\n />\n </Box>\n );\n}\n\nTable.icons = Object.freeze(tableIcons);\n\nfunction makeBody({\n columnCount,\n emptyContent,\n hasNoRows,\n loading,\n}: {\n hasNoRows: boolean;\n emptyContent: ReactNode;\n columnCount: number;\n loading?: boolean;\n}) {\n return (bodyProps: any /* no type for this in material-table */) => {\n if (loading) {\n return <TableLoadingBody colSpan={columnCount} />;\n }\n\n if (emptyContent && hasNoRows) {\n return (\n <tbody>\n <tr>\n <td colSpan={columnCount}>{emptyContent}</td>\n </tr>\n </tbody>\n );\n }\n\n return <MTableBody {...bodyProps} />;\n };\n}\n\nfunction constructFilters<T extends object>(\n filterConfig: TableFilter[],\n dataValue: any[] | undefined,\n columns: TableColumn<T>[],\n t: TranslationFunction<typeof coreComponentsTranslationRef.T>,\n): Filter[] {\n const extractDistinctValues = (field: string | keyof T): Set<any> => {\n const distinctValues = new Set<any>();\n const addValue = (value: any) => {\n if (value !== undefined && value !== null) {\n distinctValues.add(value);\n }\n };\n\n if (dataValue) {\n dataValue.forEach(el => {\n const value = extractValueByField(\n el,\n columns.find(c => c.title === field)?.field as string,\n );\n\n if (Array.isArray(value)) {\n (value as []).forEach(addValue);\n } else {\n addValue(value);\n }\n });\n }\n\n return distinctValues;\n };\n\n const constructSelect = (\n filter: TableFilter,\n ): Without<SelectProps, 'onChange'> => {\n return {\n placeholder: t('table.filter.placeholder'),\n label: filter.column,\n multiple: filter.type === 'multiple-select',\n items: [...extractDistinctValues(filter.column)].sort().map(value => ({\n label: value,\n value,\n })),\n };\n };\n\n return filterConfig.map(filter => ({\n type: filter.type,\n element: constructSelect(filter),\n }));\n}\n","/*\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 { defineComponent } from '../../hooks/useDefinition';\nimport type { ContainerOwnProps } from './types';\nimport styles from './Container.module.css';\n\n/**\n * Component definition for Container\n * @public\n */\nexport const ContainerDefinition = defineComponent<ContainerOwnProps>()({\n styles,\n classNames: {\n root: 'bui-Container',\n },\n propDefs: {\n children: {},\n className: {},\n style: {},\n },\n utilityProps: ['my', 'mt', 'mb', 'py', 'pt', 'pb', 'display'],\n});\n","// extracted by css-extract-rspack-plugin\nexport default {\"bui-Container\":\"j9YF9y0JMsI4PdI6\"};","/*\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 { forwardRef } from 'react';\nimport type { ContainerProps } from './types';\nimport { useDefinition } from '../../hooks/useDefinition';\nimport { ContainerDefinition } from './definition';\n\n/**\n * A centered layout wrapper that constrains content to a maximum width and provides consistent page-level padding.\n *\n * @public\n */\nexport const Container = forwardRef<HTMLDivElement, ContainerProps>(\n (props, ref) => {\n const { ownProps, restProps, utilityStyle } = useDefinition(\n ContainerDefinition,\n props,\n );\n const { classes, children, style } = ownProps;\n\n return (\n <div\n ref={ref}\n className={classes.root}\n style={{ ...utilityStyle, ...style }}\n {...restProps}\n >\n {children}\n </div>\n );\n },\n);\n\nContainer.displayName = 'Container';\n","/*\n * Copyright 2026 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 stringifyEntityRef,\n} from '@backstage/catalog-model';\nimport {\n EntityPresentationApi,\n EntityRefPresentationSnapshot,\n} from './EntityPresentationApi';\nimport { defaultEntityPresentation } from './defaultEntityPresentation';\n\n/**\n * Returns a synchronous presentation snapshot for an entity in non-React\n * contexts.\n *\n * @remarks\n *\n * This is the synchronous, non-React counterpart to\n * {@link useEntityPresentation}. It handles `Entity`, `CompoundEntityRef`,\n * and string ref inputs uniformly, using the provided\n * {@link EntityPresentationApi} when available and falling back to\n * {@link defaultEntityPresentation} otherwise.\n *\n * Because this function is synchronous, it uses cached data from the\n * presentation API (via `.snapshot`). If the entity has been seen before,\n * the snapshot will contain the full resolved title; otherwise it falls\n * back to what can be extracted from the ref alone. This is the correct\n * trade-off for sort comparators, column factories, filter callbacks, and\n * data mappers where a synchronous return value is required.\n *\n * In async contexts such as data loaders where you can `await`, prefer\n * using the {@link EntityPresentationApi} directly via\n * `forEntity().promise` for the richest possible presentation.\n *\n * @public\n * @param entityOrRef - An entity, a compound entity ref, or a string entity ref.\n * @param context - Optional context that may affect the presentation.\n * @param entityPresentationApi - Optional presentation API instance. When not\n * provided, falls back to {@link defaultEntityPresentation}.\n */\nexport function entityPresentationSnapshot(\n entityOrRef: Entity | CompoundEntityRef | string,\n context?: { defaultKind?: string; defaultNamespace?: string },\n entityPresentationApi?: EntityPresentationApi,\n): EntityRefPresentationSnapshot {\n if (entityPresentationApi) {\n const ref =\n typeof entityOrRef === 'string' || 'metadata' in entityOrRef\n ? entityOrRef\n : stringifyEntityRef(entityOrRef);\n return entityPresentationApi.forEntity(ref, context).snapshot;\n }\n return defaultEntityPresentation(entityOrRef, context);\n}\n","/*\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 Box from '@material-ui/core/Box';\nimport Typography, { TypographyProps } from '@material-ui/core/Typography';\nimport Paper, { PaperProps } from '@material-ui/core/Paper';\nimport Popper, { PopperProps } from '@material-ui/core/Popper';\nimport TextField, { OutlinedTextFieldProps } from '@material-ui/core/TextField';\nimport Grow from '@material-ui/core/Grow';\nimport {\n createStyles,\n makeStyles,\n Theme,\n withStyles,\n} from '@material-ui/core/styles';\nimport ExpandMoreIcon from '@material-ui/icons/ExpandMore';\nimport Autocomplete, {\n AutocompleteProps,\n AutocompleteRenderInputParams,\n} from '@material-ui/lab/Autocomplete';\nimport { ReactNode, useCallback } from 'react';\nimport { merge } from 'lodash';\nimport classNames from 'classnames';\n\nconst useStyles = makeStyles(\n theme => ({\n root: {\n margin: theme.spacing(1, 0),\n },\n label: {\n position: 'relative',\n fontWeight: 'bold',\n fontSize: theme.typography.body2.fontSize,\n fontFamily: theme.typography.fontFamily,\n color: theme.palette.text.primary,\n '& > span': {\n top: 0,\n left: 0,\n position: 'absolute',\n },\n },\n }),\n { name: 'BackstageAutocomplete' },\n);\n\nconst BootstrapAutocomplete = withStyles(\n (theme: Theme) =>\n createStyles({\n root: {},\n paper: {\n margin: 0,\n },\n hasClearIcon: {},\n hasPopupIcon: {},\n focused: {},\n inputRoot: {\n marginTop: 24,\n backgroundColor: theme.palette.background.paper,\n '$root$hasClearIcon$hasPopupIcon &': {\n paddingBlock: theme.spacing(0.75),\n paddingInlineStart: theme.spacing(0.75),\n },\n '$root$focused &': {\n outline: 'none',\n },\n '$root &:hover > fieldset': {\n borderColor: '#ced4da',\n },\n '$root$focused & > fieldset': {\n borderWidth: 1,\n borderColor: theme.palette.primary.main,\n },\n },\n popupIndicator: {\n padding: 0,\n margin: 0,\n color: '#616161',\n '&:hover': {\n backgroundColor: 'unset',\n },\n '& [class*=\"MuiTouchRipple-root\"]': {\n display: 'none',\n },\n },\n endAdornment: {\n '$root$hasClearIcon$hasPopupIcon &': {\n right: 4,\n },\n },\n input: {\n '$root$hasClearIcon$hasPopupIcon &': {\n fontSize: theme.typography.body1.fontSize,\n paddingBlock: theme.spacing(0.8125),\n },\n },\n }),\n { name: 'BackstageAutocompleteBase' },\n)(Autocomplete) as typeof Autocomplete;\n\nconst PopperComponent = (props: PopperProps) => (\n <Popper {...props} transition placement=\"bottom-start\">\n {({ TransitionProps }) => (\n <Grow {...TransitionProps} style={{ transformOrigin: '0 0 0' }}>\n <Box>{props.children as ReactNode}</Box>\n </Grow>\n )}\n </Popper>\n);\n\nconst PaperComponent = (props: PaperProps) => (\n <Paper {...props} elevation={8} />\n);\n\n/**\n * Props for {@link CatalogAutocomplete}\n *\n * @public\n */\nexport type CatalogAutocompleteProps<\n T,\n Multiple extends boolean | undefined = undefined,\n DisableClearable extends boolean | undefined = undefined,\n FreeSolo extends boolean | undefined = undefined,\n> = Omit<\n AutocompleteProps<T, Multiple, DisableClearable, FreeSolo>,\n 'PopperComponent' | 'PaperComponent' | 'popupIcon' | 'renderInput'\n> & {\n name: string;\n label?: string;\n LabelProps?: TypographyProps<'label'>;\n TextFieldProps?: Omit<OutlinedTextFieldProps, 'variant'>;\n renderInput?: AutocompleteProps<\n T,\n Multiple,\n DisableClearable,\n FreeSolo\n >['renderInput'];\n};\n\n/** @public */\nexport function CatalogAutocomplete<\n T,\n Multiple extends boolean | undefined = undefined,\n DisableClearable extends boolean | undefined = undefined,\n FreeSolo extends boolean | undefined = undefined,\n>(props: CatalogAutocompleteProps<T, Multiple, DisableClearable, FreeSolo>) {\n const { label, name, LabelProps, TextFieldProps, ...rest } = props;\n const classes = useStyles();\n const renderInput = useCallback(\n (params: AutocompleteRenderInputParams) => (\n <TextField {...merge(params, TextFieldProps)} variant=\"outlined\" />\n ),\n [TextFieldProps],\n );\n const autocomplete = (\n <BootstrapAutocomplete\n size=\"small\"\n {...rest}\n renderInput={rest.renderInput ?? renderInput}\n popupIcon={<ExpandMoreIcon data-testid={`${name}-expand`} />}\n PaperComponent={PaperComponent}\n PopperComponent={PopperComponent}\n />\n );\n\n return (\n <Box className={classes.root}>\n {label ? (\n <Typography\n {...LabelProps}\n className={classNames(classes.label, LabelProps?.className)}\n component=\"label\"\n >\n <Box component=\"span\">{label}</Box>\n {autocomplete}\n </Typography>\n ) : (\n autocomplete\n )}\n </Box>\n );\n}\n","/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { ReactNode, useState } from 'react';\nimport Box from '@material-ui/core/Box';\nimport Button from '@material-ui/core/Button';\nimport Drawer from '@material-ui/core/Drawer';\nimport Grid from '@material-ui/core/Grid';\nimport Typography from '@material-ui/core/Typography';\nimport useMediaQuery from '@material-ui/core/useMediaQuery';\nimport { Theme, useTheme } from '@material-ui/core/styles';\nimport FilterListIcon from '@material-ui/icons/FilterList';\nimport { catalogReactTranslationRef } from '../../translation';\nimport { useTranslationRef } from '@backstage/core-plugin-api/alpha';\n\n/** @public */\nexport const Filters = (props: {\n children: ReactNode;\n options?: {\n drawerBreakpoint?: 'xs' | 'sm' | 'md' | 'lg' | 'xl' | number;\n drawerAnchor?: 'left' | 'right' | 'top' | 'bottom';\n };\n}) => {\n const isScreenSmallerThanBreakpoint = useMediaQuery(\n (theme: Theme) =>\n theme.breakpoints.down(props.options?.drawerBreakpoint ?? 'md'),\n { noSsr: true },\n );\n const theme = useTheme();\n const [filterDrawerOpen, setFilterDrawerOpen] = useState<boolean>(false);\n const { t } = useTranslationRef(catalogReactTranslationRef);\n\n return isScreenSmallerThanBreakpoint ? (\n <>\n <Button\n style={{ marginTop: theme.spacing(1), marginLeft: theme.spacing(1) }}\n onClick={() => setFilterDrawerOpen(true)}\n startIcon={<FilterListIcon />}\n >\n {t('catalogFilter.buttonTitle')}\n </Button>\n <Drawer\n open={filterDrawerOpen}\n onClose={() => setFilterDrawerOpen(false)}\n anchor={props.options?.drawerAnchor ?? 'left'}\n disableAutoFocus\n keepMounted\n variant=\"temporary\"\n >\n <Box m={2}>\n <Typography\n variant=\"h6\"\n component=\"h2\"\n style={{ marginBottom: theme.spacing(1) }}\n >\n {t('catalogFilter.title')}\n </Typography>\n {props.children}\n </Box>\n </Drawer>\n </>\n ) : (\n <Grid item lg={2}>\n {props.children}\n </Grid>\n );\n};\n\n/** @public */\nexport const Content = (props: { children: ReactNode }) => {\n return (\n <Grid item xs={12} lg={10}>\n {props.children}\n </Grid>\n );\n};\n\n/** @public */\nexport const CatalogFilterLayout = (props: { children: ReactNode }) => {\n return (\n <Grid container style={{ position: 'relative' }}>\n {props.children}\n </Grid>\n );\n};\n\nCatalogFilterLayout.Filters = Filters;\nCatalogFilterLayout.Content = Content;\n","/*\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 */\nimport Checkbox from '@material-ui/core/Checkbox';\nimport FormControlLabel from '@material-ui/core/FormControlLabel';\nimport CheckBoxIcon from '@material-ui/icons/CheckBox';\nimport CheckBoxOutlineBlankIcon from '@material-ui/icons/CheckBoxOutlineBlank';\nimport { memo } from 'react';\n\ninterface Props {\n selected: boolean;\n value: string;\n availableOptions?: Record<string, number>;\n showCounts: boolean;\n}\n\nconst icon = <CheckBoxOutlineBlankIcon fontSize=\"small\" />;\nconst checkedIcon = <CheckBoxIcon fontSize=\"small\" />;\n\nfunction OptionCheckbox({ selected }: { selected: boolean }) {\n return <Checkbox icon={icon} checkedIcon={checkedIcon} checked={selected} />;\n}\n\nexport const EntityAutocompletePickerOption = memo((props: Props) => {\n const { selected, value, availableOptions, showCounts } = props;\n const label = showCounts ? `${value} (${availableOptions?.[value]})` : value;\n\n return (\n <FormControlLabel\n control={<OptionCheckbox selected={selected} />}\n label={label}\n onClick={event => event.preventDefault()}\n />\n );\n});\n","/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport Box from '@material-ui/core/Box';\nimport { TextFieldProps } from '@material-ui/core/TextField';\nimport { makeStyles } from '@material-ui/core/styles';\nimport { ReactNode, useEffect, useMemo, useState } from 'react';\nimport { useApi } from '@backstage/core-plugin-api';\nimport useAsync from 'react-use/esm/useAsync';\nimport { catalogApiRef } from '../../api';\nimport { EntityAutocompletePickerOption } from './EntityAutocompletePickerOption';\nimport {\n DefaultEntityFilters,\n useEntityList,\n} from '../../hooks/useEntityListProvider';\nimport { EntityFilter } from '../../types';\nimport { reduceBackendCatalogFilters } from '../../utils/filters';\nimport { CatalogAutocomplete } from '../CatalogAutocomplete';\nimport { AutocompleteRenderOptionState } from '@material-ui/lab/Autocomplete';\nimport { isEqual } from 'lodash';\n\n/** @public */\nexport type AllowedEntityFilters<T extends DefaultEntityFilters> = {\n [K in keyof T]-?: NonNullable<T[K]> extends EntityFilter & {\n values: string[];\n }\n ? K\n : never;\n}[keyof T];\n\n/** @public */\nexport type EntityAutocompletePickerProps<\n T extends DefaultEntityFilters = DefaultEntityFilters,\n Name extends AllowedEntityFilters<T> = AllowedEntityFilters<T>,\n> = {\n label: string;\n name: Name;\n path: string;\n showCounts?: boolean;\n Filter: { new (values: string[]): NonNullable<T[Name]> };\n InputProps?: TextFieldProps;\n initialSelectedOptions?: string[];\n filtersForAvailableValues?: Array<keyof T>;\n hidden?: boolean;\n getOptionLabel?: (option: string) => string;\n renderOption?: (\n option: string,\n state: AutocompleteRenderOptionState,\n ) => ReactNode;\n};\n\n/** @public */\nexport type CatalogReactEntityAutocompletePickerClassKey = 'root' | 'label';\n\nconst useStyles = makeStyles(\n {\n root: {},\n label: {\n textTransform: 'none',\n fontWeight: 'bold',\n },\n },\n { name: 'CatalogReactEntityAutocompletePicker' },\n);\n\n/** @public */\nexport function EntityAutocompletePicker<\n T extends DefaultEntityFilters = DefaultEntityFilters,\n Name extends AllowedEntityFilters<T> = AllowedEntityFilters<T>,\n>(props: EntityAutocompletePickerProps<T, Name>) {\n const {\n label,\n name,\n path,\n showCounts,\n Filter,\n InputProps,\n initialSelectedOptions = [],\n filtersForAvailableValues = ['kind'],\n hidden,\n getOptionLabel,\n renderOption,\n } = props;\n const classes = useStyles();\n\n const {\n updateFilters,\n filters,\n queryParameters: { [name]: queryParameter },\n } = useEntityList<T>();\n\n const catalogApi = useApi(catalogApiRef);\n const availableValuesFilters = filtersForAvailableValues.map(\n f => filters[f] as EntityFilter | undefined,\n );\n const { value: availableValues } = useAsync(async () => {\n const facet = path;\n const { facets } = await catalogApi.getEntityFacets({\n facets: [facet],\n filter: reduceBackendCatalogFilters(\n availableValuesFilters.filter(Boolean) as EntityFilter[],\n ),\n });\n\n return Object.fromEntries(\n facets[facet].map(({ value, count }) => [value, count]),\n );\n }, [...availableValuesFilters]);\n\n const queryParameters = useMemo(\n () => [queryParameter].flat().filter(Boolean) as string[],\n [queryParameter],\n );\n\n const filteredOptions = (filters[name] as unknown as { values: string[] })\n ?.values;\n\n const [selectedOptions, setSelectedOptions] = useState(\n queryParameters.length\n ? queryParameters\n : filteredOptions ?? initialSelectedOptions,\n );\n\n // Set selected options on query parameter updates; this happens at initial page load and from\n // external updates to the page location\n useEffect(() => {\n if (queryParameters.length) {\n setSelectedOptions(queryParameters);\n }\n }, [queryParameters]);\n\n const availableOptions = Object.keys(availableValues ?? {});\n const shouldAddFilter = selectedOptions.length && availableOptions.length;\n\n // Update filter value when selectedOptions change\n useEffect(() => {\n updateFilters({\n [name]: shouldAddFilter ? new Filter(selectedOptions) : undefined,\n } as Partial<T>);\n }, [name, shouldAddFilter, selectedOptions, Filter, updateFilters]);\n\n // Update selected options when filter value changes\n useEffect(() => {\n if (!shouldAddFilter) return;\n\n const newSelectedOptions = filteredOptions ?? [];\n\n // Check value is actually different (not just a different reference) to prevent selectedOptions <> filters loop\n if (!isEqual(newSelectedOptions, selectedOptions)) {\n setSelectedOptions(newSelectedOptions);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps -- Don't re-set filter value when selectedOptions changes\n }, [filteredOptions]);\n\n const filter = filters[name];\n if (\n (filter && typeof filter === 'object' && !('values' in filter)) ||\n !availableOptions.length\n ) {\n return null;\n }\n\n return hidden ? null : (\n <Box className={classes.root} pb={1} pt={1}>\n <CatalogAutocomplete<string, true>\n multiple\n disableCloseOnSelect\n label={label}\n name={`${String(name)}-picker`}\n options={availableOptions}\n value={selectedOptions}\n TextFieldProps={InputProps}\n onChange={(_event: object, options: string[]) =>\n setSelectedOptions(options)\n }\n {...(getOptionLabel && { getOptionLabel })}\n renderOption={\n renderOption ??\n ((option, { selected }) => (\n <EntityAutocompletePickerOption\n selected={selected}\n value={option}\n availableOptions={availableValues}\n showCounts={!!showCounts}\n />\n ))\n }\n />\n </Box>\n );\n}\n","/*\n * Copyright 2026 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 HTMLAttributes,\n UIEvent,\n cloneElement,\n createContext,\n forwardRef,\n useContext,\n Children,\n} from 'react';\nimport { FixedSizeList, ListChildComponentProps } from 'react-window';\n\n// MUI Autocomplete's ListboxComponent prop is typed as ComponentType<HTMLAttributes<HTMLElement>>,\n// so we use HTMLElement here to avoid a cast at the usage site.\ntype ListboxProps = HTMLAttributes<HTMLElement>;\n\nconst ITEM_SIZE = 36;\n\nconst renderRow = (props: ListChildComponentProps) => {\n const { data, index, style } = props;\n return cloneElement(data[index], { style });\n};\n\n// Passes Autocomplete listbox props (onScroll, data-testid, etc.) through to the\n// outer scroll container so MUI Autocomplete keeps working correctly.\n// See https://v4.mui.com/components/autocomplete/#Virtualize.tsx\nconst OuterElementContext = createContext<ListboxProps>({});\n\nconst OuterElementType = forwardRef<HTMLDivElement, ListboxProps>(\n ({ onScroll: rrOnScroll, ...props }, ref) => {\n const { onScroll: outerOnScroll, ...outerProps } =\n useContext(OuterElementContext);\n // Compose both handlers: spreading outerProps last would silently overwrite\n // react-window's onScroll, breaking virtualization.\n const handleScroll = (e: UIEvent<HTMLDivElement>) => {\n rrOnScroll?.(e);\n outerOnScroll?.(e);\n };\n return <div ref={ref} onScroll={handleScroll} {...props} {...outerProps} />;\n },\n);\n\nexport const VirtualizedListbox = forwardRef<HTMLDivElement, ListboxProps>(\n (props, ref) => {\n const { children, ...other } = props;\n const itemData = Children.toArray(children);\n const itemCount = itemData.length;\n\n const itemsToShow = Math.min(10, itemCount) + 0.5;\n const height = itemsToShow * ITEM_SIZE;\n\n return (\n <div ref={ref}>\n <OuterElementContext.Provider value={other}>\n <FixedSizeList\n height={height}\n itemData={itemData}\n itemCount={itemCount}\n itemSize={ITEM_SIZE}\n outerElementType={OuterElementType}\n width=\"100%\"\n >\n {renderRow}\n </FixedSizeList>\n </OuterElementContext.Provider>\n </div>\n );\n },\n);\n","/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n Entity,\n parseEntityRef,\n stringifyEntityRef,\n} from '@backstage/catalog-model';\nimport Box from '@material-ui/core/Box';\nimport Checkbox from '@material-ui/core/Checkbox';\nimport FormControlLabel from '@material-ui/core/FormControlLabel';\nimport Typography from '@material-ui/core/Typography';\nimport Tooltip from '@material-ui/core/Tooltip';\nimport { makeStyles } from '@material-ui/core/styles';\nimport CheckBoxIcon from '@material-ui/icons/CheckBox';\nimport CheckBoxOutlineBlankIcon from '@material-ui/icons/CheckBoxOutlineBlank';\nimport { MouseEvent, useEffect, useMemo, useState } from 'react';\nimport { useEntityList } from '../../hooks/useEntityListProvider';\nimport { EntityOwnerFilter } from '../../filters';\nimport { useDebouncedEffect } from '@react-hookz/web';\nimport PersonIcon from '@material-ui/icons/Person';\nimport GroupIcon from '@material-ui/icons/Group';\nimport {\n entityPresentationApiRef,\n entityPresentationSnapshot,\n} from '../../apis';\nimport { useFetchEntities } from './useFetchEntities';\nimport { VirtualizedListbox } from './VirtualizedListbox';\nimport { withStyles } from '@material-ui/core/styles';\nimport { useEntityPresentation } from '../../apis';\nimport { catalogReactTranslationRef } from '../../translation';\nimport { useApiHolder } from '@backstage/core-plugin-api';\nimport { useTranslationRef } from '@backstage/core-plugin-api/alpha';\nimport { CatalogAutocomplete } from '../CatalogAutocomplete';\n\n/** @public */\nexport type CatalogReactEntityOwnerPickerClassKey = 'input';\n\nconst useStyles = makeStyles(\n {\n root: {},\n label: {},\n input: {},\n fullWidth: { width: '100%' },\n boxLabel: {\n width: '100%',\n textOverflow: 'ellipsis',\n overflow: 'hidden',\n },\n },\n { name: 'CatalogReactEntityOwnerPicker' },\n);\n\n/** @public */\nexport type FixedWidthFormControlLabelClassKey = 'label' | 'root';\n\nconst FixedWidthFormControlLabel = withStyles(\n _theme => ({\n label: {\n width: '100%',\n },\n root: {\n width: '90%',\n },\n }),\n { name: 'FixedWidthFormControlLabel' },\n)(FormControlLabel);\n\nconst icon = <CheckBoxOutlineBlankIcon fontSize=\"small\" />;\nconst checkedIcon = <CheckBoxIcon fontSize=\"small\" />;\n\n/**\n * @public\n */\nexport type EntityOwnerPickerProps = {\n mode?: 'owners-only' | 'all';\n};\n\nfunction RenderOptionLabel(props: {\n entity: Entity;\n isSelected: boolean;\n mode: 'owners-only' | 'all';\n}) {\n const classes = useStyles();\n const isGroup = props.entity.kind.toLowerCase() === 'group';\n // owners-only stubs lack title/displayName; pass ref string so the presentation API fetches the full entity.\n const entityOrRef: Entity | string =\n props.mode === 'owners-only'\n ? stringifyEntityRef(props.entity)\n : props.entity;\n const { primaryTitle: title } = useEntityPresentation(entityOrRef);\n return (\n <Box className={classes.fullWidth}>\n <FixedWidthFormControlLabel\n className={classes.fullWidth}\n control={\n <Checkbox\n icon={icon}\n checkedIcon={checkedIcon}\n checked={props.isSelected}\n />\n }\n onClick={event => event.preventDefault()}\n label={\n <Tooltip title={title}>\n <Box display=\"flex\" alignItems=\"center\">\n {isGroup ? (\n <GroupIcon fontSize=\"small\" />\n ) : (\n <PersonIcon fontSize=\"small\" />\n )}\n \n <Box className={classes.boxLabel}>\n <Typography noWrap>{title}</Typography>\n </Box>\n </Box>\n </Tooltip>\n }\n />\n </Box>\n );\n}\n\n/** @public */\nexport const EntityOwnerPicker = (props?: EntityOwnerPickerProps) => {\n const classes = useStyles();\n const { mode = 'owners-only' } = props || {};\n const apis = useApiHolder();\n const entityPresentationApi = apis.get(entityPresentationApiRef);\n const {\n updateFilters,\n filters,\n queryParameters: { owners: ownersParameter },\n } = useEntityList();\n\n const [text, setText] = useState('');\n const { t } = useTranslationRef(catalogReactTranslationRef);\n\n const queryParamOwners = useMemo(\n () => [ownersParameter].flat().filter(Boolean) as string[],\n [ownersParameter],\n );\n\n // Query parameters may contain humanized refs (e.g. `guests` rather than\n // `group:default/guests`), so they are normalized before being stored.\n const [selectedOwners, setSelectedOwners] = useState<string[]>(\n queryParamOwners.length\n ? new EntityOwnerFilter(queryParamOwners).values\n : filters.owners?.values ?? [],\n );\n\n const [{ value, loading }, handleFetch, cache] = useFetchEntities({\n mode,\n initialSelectedOwnersRefs: selectedOwners,\n });\n useDebouncedEffect(\n () => handleFetch({ text: text.toLowerCase() }),\n [text, handleFetch],\n 250,\n );\n\n const availableOwners = value?.items || [];\n\n // Set selected owners on query parameter updates; this happens at initial page load and from\n // external updates to the page location.\n useEffect(() => {\n if (queryParamOwners.length) {\n const filter = new EntityOwnerFilter(queryParamOwners);\n setSelectedOwners(filter.values);\n }\n }, [queryParamOwners]);\n\n useEffect(() => {\n updateFilters({\n owners: selectedOwners.length\n ? new EntityOwnerFilter(selectedOwners)\n : undefined,\n });\n }, [selectedOwners, updateFilters]);\n\n if (['user', 'group'].includes(filters.kind?.value.toLowerCase() || '')) {\n return null;\n }\n\n return (\n <Box className={classes.root} pb={1} pt={1}>\n <CatalogAutocomplete<Entity, true>\n label={t('entityOwnerPicker.title')}\n multiple\n disableCloseOnSelect\n loading={loading}\n options={availableOwners}\n value={selectedOwners as unknown as Entity[]}\n getOptionSelected={(o, v) => {\n if (typeof v === 'string') {\n return stringifyEntityRef(o) === v;\n }\n return o === v;\n }}\n getOptionLabel={o => {\n if (mode === 'owners-only') {\n // Stubs have no title; use string ref so entityPresentationSnapshot hits the API cache.\n const ref = typeof o === 'string' ? o : stringifyEntityRef(o);\n return entityPresentationSnapshot(\n ref,\n undefined,\n entityPresentationApi,\n ).primaryTitle;\n }\n const entity =\n typeof o === 'string'\n ? cache.getEntity(o) ||\n parseEntityRef(o, {\n defaultKind: 'group',\n defaultNamespace: 'default',\n })\n : o;\n return entityPresentationSnapshot(\n entity,\n undefined,\n entityPresentationApi,\n ).primaryTitle;\n }}\n onChange={(_: object, owners) => {\n setText('');\n setSelectedOwners(\n owners.map(e => {\n const entityRef =\n typeof e === 'string' ? e : stringifyEntityRef(e);\n\n if (typeof e !== 'string') {\n cache.setEntity(e);\n }\n return entityRef;\n }),\n );\n }}\n filterOptions={x => x}\n renderOption={(entity, { selected }) => {\n return (\n <RenderOptionLabel\n entity={entity}\n isSelected={selected}\n mode={mode}\n />\n );\n }}\n name=\"owner-picker\"\n onInputChange={(_e, inputValue) => {\n setText(inputValue);\n }}\n ListboxComponent={VirtualizedListbox}\n ListboxProps={{\n onScroll: (e: MouseEvent) => {\n const element = e.currentTarget;\n const hasReachedEnd =\n Math.abs(\n element.scrollHeight - element.clientHeight - element.scrollTop,\n ) < 1;\n\n if (hasReachedEnd && value?.cursor) {\n handleFetch({ items: value.items, cursor: value.cursor });\n }\n },\n 'data-testid': 'owner-picker-listbox',\n }}\n LabelProps={{ className: classes.label }}\n TextFieldProps={{ className: classes.input }}\n />\n </Box>\n );\n};\n","/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { useRef } from 'react';\nimport { useFacetsEntities } from './useFacetsEntities';\nimport { useQueryEntities } from './useQueryEntities';\nimport { Entity, stringifyEntityRef } from '@backstage/catalog-model';\nimport { useApi } from '@backstage/core-plugin-api';\nimport { catalogApiRef } from '../../api';\nimport useAsyncFn from 'react-use/esm/useAsyncFn';\nimport { useMountEffect } from '@react-hookz/web';\n\nexport function useFetchEntities({\n mode,\n initialSelectedOwnersRefs,\n}: {\n mode: 'owners-only' | 'all';\n initialSelectedOwnersRefs: string[];\n}) {\n const isOwnersOnlyMode = mode === 'owners-only';\n const queryEntitiesResponse = useQueryEntities();\n const facetsEntitiesResponse = useFacetsEntities({\n enabled: isOwnersOnlyMode,\n });\n\n const [state, handleFetch] = isOwnersOnlyMode\n ? facetsEntitiesResponse\n : queryEntitiesResponse;\n\n return [\n state,\n handleFetch,\n useSelectedOwners({\n enabled: !isOwnersOnlyMode,\n initialSelectedOwnersRefs,\n }),\n ] as const;\n}\n\n/**\n * Hook used for storing the full entity of the specified owners\n * in order to display users and group using the information contained on each entity.\n * When a component is rendered for the first time, it loads the content of the entities\n * specified by `initialSelectedOwnersRefs` and export the `getEntity` and `setEntity`\n * utilities, used to retrieve and modify the owners.\n */\nfunction useSelectedOwners({\n enabled,\n initialSelectedOwnersRefs,\n}: {\n enabled: boolean;\n initialSelectedOwnersRefs: string[];\n}) {\n const allEntities = useRef<Record<string, Entity>>({});\n const catalogApi = useApi(catalogApiRef);\n\n const [, handleFetch] = useAsyncFn(async () => {\n const initialSelectedEntities = await catalogApi.getEntitiesByRefs({\n entityRefs: initialSelectedOwnersRefs,\n });\n initialSelectedEntities.items.forEach(e => {\n if (e) {\n allEntities.current[stringifyEntityRef(e)] = e;\n }\n });\n }, []);\n\n useMountEffect(() => {\n if (enabled && initialSelectedOwnersRefs.length > 0) {\n handleFetch();\n }\n });\n\n return {\n getEntity: (entityRef: string) => allEntities.current[entityRef],\n setEntity: (entity: Entity) => {\n allEntities.current[stringifyEntityRef(entity)] = entity;\n },\n };\n}\n","/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { useApi } from '@backstage/core-plugin-api';\nimport { catalogApiRef } from '../../api';\nimport useAsyncFn from 'react-use/esm/useAsyncFn';\nimport { Entity } from '@backstage/catalog-model';\n\ntype QueryEntitiesResponse = {\n items: Entity[];\n cursor?: string;\n};\n\nexport function useQueryEntities() {\n const catalogApi = useApi(catalogApiRef);\n return useAsyncFn(\n async (\n request: { text: string } | QueryEntitiesResponse,\n options?: { limit: number },\n ): Promise<QueryEntitiesResponse> => {\n const initialRequest = request as { text: string };\n const cursorRequest = request as QueryEntitiesResponse;\n const limit = options?.limit ?? 20;\n\n if (cursorRequest.cursor) {\n const response = await catalogApi.queryEntities({\n cursor: cursorRequest.cursor,\n limit,\n });\n return {\n cursor: response.pageInfo.nextCursor,\n items: [...cursorRequest.items, ...response.items],\n };\n }\n\n const response = await catalogApi.queryEntities({\n fullTextFilter: {\n term: initialRequest.text || '',\n fields: [\n 'metadata.name',\n 'kind',\n 'spec.profile.displayname',\n 'metadata.title',\n ],\n },\n filter: { kind: ['User', 'Group'] },\n orderFields: [{ field: 'metadata.name', order: 'asc' }],\n limit,\n });\n\n return {\n cursor: response.pageInfo.nextCursor,\n items: response.items,\n };\n },\n [],\n { loading: true },\n );\n}\n","/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { useApi } from '@backstage/core-plugin-api';\nimport useAsyncFn from 'react-use/esm/useAsyncFn';\nimport { catalogApiRef } from '../../api';\nimport { useState } from 'react';\nimport { Entity, parseEntityRef } from '@backstage/catalog-model';\n\ntype FacetsCursor = {\n start: number;\n text: string;\n};\n\ntype FacetsEntitiesResponse = {\n items: Entity[];\n cursor?: string;\n};\n\ntype FacetsInitialRequest = {\n text: string;\n};\n\n/**\n * This hook asynchronously loads the entity owners using the facets endpoint.\n * EntityOwnerPicker uses this hook when mode=\"owners-only\" is passed as prop.\n * All the owners are kept internally in memory and rendered in batches once requested\n * by the frontend. The values returned by this hook are compatible with `useQueryEntities`\n * hook, which is also used by EntityOwnerPicker.\n * In this mode, the EntityOwnerPicker won't show detailed information of the owners.\n */\nexport function useFacetsEntities({ enabled }: { enabled: boolean }) {\n const catalogApi = useApi(catalogApiRef);\n\n const [facetsPromise] = useState(async () => {\n if (!enabled) {\n return [];\n }\n const facet = 'relations.ownedBy';\n\n return catalogApi\n .getEntityFacets({ facets: [facet] })\n .then(response =>\n response.facets[facet]\n .map(e => e.value)\n .map(ref => {\n const { kind, name, namespace } = parseEntityRef(ref);\n return {\n apiVersion: 'backstage.io/v1beta1',\n kind,\n metadata: { name, namespace },\n };\n })\n .sort(\n (a, b) =>\n a.kind.localeCompare(b.kind, 'en-US') ||\n a.metadata.namespace.localeCompare(\n b.metadata.namespace,\n 'en-US',\n ) ||\n a.metadata.name.localeCompare(b.metadata.name, 'en-US'),\n ),\n )\n .catch(() => []);\n });\n\n return useAsyncFn<\n (\n request: FacetsInitialRequest | FacetsEntitiesResponse,\n options?: { limit?: number },\n ) => Promise<FacetsEntitiesResponse>\n >(\n async (request, options) => {\n const facets = await facetsPromise;\n\n if (!facets) {\n return {\n items: [],\n };\n }\n\n const limit = options?.limit ?? 20;\n\n const { text, start } = decodeCursor(request);\n const filteredRefs = facets.filter(e => filterEntity(text, e));\n const end = start + limit;\n return {\n items: filteredRefs.slice(0, end),\n ...encodeCursor({\n entities: filteredRefs,\n limit: end,\n payload: {\n text,\n start: end,\n },\n }),\n };\n },\n [facetsPromise],\n { loading: true, value: { items: [] } },\n );\n}\n\nfunction decodeCursor(\n request: FacetsInitialRequest | FacetsEntitiesResponse,\n): FacetsCursor {\n if (isFacetsResponse(request) && request.cursor) {\n return JSON.parse(atob(request.cursor));\n }\n return {\n text: (request as FacetsInitialRequest).text || '',\n start: 0,\n };\n}\n\nfunction isFacetsResponse(\n request: FacetsInitialRequest | FacetsEntitiesResponse,\n): request is FacetsEntitiesResponse {\n return !!(request as FacetsEntitiesResponse).cursor;\n}\n\nfunction encodeCursor({\n entities,\n limit,\n payload,\n}: {\n entities: Entity[];\n limit: number;\n payload: { text: string; start: number };\n}) {\n if (entities.length > limit) {\n return { cursor: btoa(JSON.stringify(payload)) };\n }\n return {};\n}\n\nfunction filterEntity(text: string, entity: Entity) {\n const normalizedText = text.trim();\n return (\n entity.kind.includes(normalizedText) ||\n entity.metadata.namespace?.includes(normalizedText) ||\n entity.metadata.name.includes(normalizedText)\n );\n}\n","/*\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 */\nimport {\n Entity,\n CompoundEntityRef,\n stringifyEntityRef,\n} from '@backstage/catalog-model';\nimport { Fragment } from 'react';\nimport { EntityRefLink } from './EntityRefLink';\nimport { LinkProps } from '@backstage/core-components';\n\n/**\n * Props for {@link EntityRefLink}.\n *\n * @public\n */\nexport type EntityRefLinksProps<\n TRef extends string | CompoundEntityRef | Entity,\n> = {\n defaultKind?: string;\n entityRefs: TRef[];\n hideIcons?: boolean;\n /** @deprecated This option is no longer used; presentation is handled by entityPresentationApiRef instead */\n fetchEntities?: boolean;\n /** @deprecated This option is no longer used; presentation is handled by entityPresentationApiRef instead */\n getTitle?(entity: TRef): string | undefined;\n} & Omit<LinkProps, 'to'>;\n\n/**\n * Shows a list of clickable links to entities.\n *\n * @public\n */\nexport function EntityRefLinks<\n TRef extends string | CompoundEntityRef | Entity,\n>(props: EntityRefLinksProps<TRef>) {\n const { entityRefs, hideIcons, ...linkProps } = props;\n\n return (\n <>\n {entityRefs.map((r: TRef, i: number) => {\n const entityRefString =\n typeof r === 'string' ? r : stringifyEntityRef(r);\n return (\n <Fragment key={`${i}.${entityRefString}`}>\n {i > 0 && ', '}\n <EntityRefLink {...linkProps} entityRef={r} hideIcon={hideIcons} />\n </Fragment>\n );\n })}\n </>\n );\n}\n","/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { makeStyles } from '@material-ui/core/styles';\nimport { EntityTagFilter } from '../../filters';\nimport { EntityAutocompletePicker } from '../EntityAutocompletePicker/EntityAutocompletePicker';\nimport { catalogReactTranslationRef } from '../../translation';\nimport { useTranslationRef } from '@backstage/core-plugin-api/alpha';\n\n/** @public */\nexport type CatalogReactEntityTagPickerClassKey = 'input';\n\n/** @public */\nexport type EntityTagPickerProps = {\n showCounts?: boolean;\n initialFilter?: string[];\n hidden?: boolean;\n};\n\nconst useStyles = makeStyles(\n { input: {} },\n { name: 'CatalogReactEntityTagPicker' },\n);\n\n/** @public */\nexport const EntityTagPicker = (props: EntityTagPickerProps) => {\n const classes = useStyles();\n const { t } = useTranslationRef(catalogReactTranslationRef);\n\n return (\n <EntityAutocompletePicker\n label={t('entityTagPicker.title')}\n name=\"tags\"\n path=\"metadata.tags\"\n Filter={EntityTagFilter}\n showCounts={props.showCounts}\n InputProps={{ className: classes.input }}\n initialSelectedOptions={props.initialFilter ? props.initialFilter : []}\n hidden={props.hidden}\n />\n );\n};\n","/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n configApiRef,\n IconComponent,\n useApi,\n} from '@backstage/core-plugin-api';\nimport Card from '@material-ui/core/Card';\nimport List from '@material-ui/core/List';\nimport ListItemIcon from '@material-ui/core/ListItemIcon';\nimport ListItemSecondaryAction from '@material-ui/core/ListItemSecondaryAction';\nimport ListItemText from '@material-ui/core/ListItemText';\nimport MenuItem from '@material-ui/core/MenuItem';\nimport Typography from '@material-ui/core/Typography';\nimport { makeStyles } from '@material-ui/core/styles';\nimport SettingsIcon from '@material-ui/icons/Settings';\nimport { StarIcon } from '@backstage/core-components';\nimport { Fragment, useEffect, useMemo, useState } from 'react';\nimport { EntityUserFilter } from '../../filters';\nimport { useEntityList } from '../../hooks';\nimport { UserListFilterKind } from '../../types';\nimport { useOwnedEntitiesCount } from './useOwnedEntitiesCount';\nimport { useAllEntitiesCount } from './useAllEntitiesCount';\nimport { useStarredEntitiesCount } from './useStarredEntitiesCount';\nimport {\n TranslationFunction,\n useTranslationRef,\n} from '@backstage/core-plugin-api/alpha';\nimport { catalogReactTranslationRef } from '../../translation';\n\n/** @public */\nexport type CatalogReactUserListPickerClassKey =\n | 'root'\n | 'title'\n | 'listIcon'\n | 'menuItem'\n | 'groupWrapper';\n\nconst useStyles = makeStyles(\n theme => ({\n root: {\n backgroundColor: 'rgba(0, 0, 0, .11)',\n boxShadow: 'none',\n margin: theme.spacing(1, 0, 1, 0),\n },\n title: {\n margin: theme.spacing(1, 0, 0, 1),\n textTransform: 'uppercase',\n fontSize: 12,\n fontWeight: 'bold',\n },\n listIcon: {\n minWidth: 30,\n color: theme.palette.text.primary,\n },\n menuItem: {\n minHeight: theme.spacing(6),\n },\n groupWrapper: {\n margin: theme.spacing(1, 1, 2, 1),\n },\n }),\n { name: 'CatalogReactUserListPicker' },\n);\n\nexport type ButtonGroup = {\n name: string;\n items: {\n id: 'owned' | 'starred' | 'all';\n label: string;\n icon?: IconComponent;\n }[];\n};\n\nfunction getFilterGroups(\n orgName: string,\n t: TranslationFunction<typeof catalogReactTranslationRef.T>,\n): ButtonGroup[] {\n return [\n {\n name: t('userListPicker.personalFilter.title'),\n items: [\n {\n id: 'owned',\n label: t('userListPicker.personalFilter.ownedLabel'),\n icon: SettingsIcon,\n },\n {\n id: 'starred',\n label: t('userListPicker.personalFilter.starredLabel'),\n icon: StarIcon,\n },\n ],\n },\n {\n name: orgName,\n items: [\n {\n id: 'all',\n label: t('userListPicker.orgFilterAllLabel'),\n },\n ],\n },\n ];\n}\n\n/** @public */\nexport type UserListPickerProps = {\n initialFilter?: UserListFilterKind;\n availableFilters?: UserListFilterKind[];\n hidden?: boolean;\n alwaysKeepFilters?: boolean;\n};\n\n/** @public */\nexport const UserListPicker = (props: UserListPickerProps) => {\n const { initialFilter, availableFilters, hidden, alwaysKeepFilters } = props;\n const classes = useStyles();\n const configApi = useApi(configApiRef);\n const { t } = useTranslationRef(catalogReactTranslationRef);\n const orgName =\n configApi.getOptionalString('organization.name') ??\n t('userListPicker.defaultOrgName');\n const {\n filters,\n updateFilters,\n queryParameters: { user: userParameter },\n } = useEntityList();\n const kindParameter = filters.kind?.value?.toLowerCase();\n\n // Remove group items that aren't in availableFilters and exclude\n // any now-empty groups.\n const userAndGroupFilterIds = ['starred', 'all'];\n const filterGroups = getFilterGroups(orgName, t)\n .map(filterGroup => ({\n ...filterGroup,\n items: filterGroup.items.filter(({ id }) =>\n // TODO: avoid hardcoding kinds here\n ['group', 'user'].some(kind => kind === kindParameter)\n ? userAndGroupFilterIds.includes(id)\n : !availableFilters || availableFilters.includes(id),\n ),\n }))\n .filter(({ items }) => !!items.length);\n\n const {\n count: ownedEntitiesCount,\n loading: loadingOwnedEntities,\n filter: ownedEntitiesFilter,\n } = useOwnedEntitiesCount();\n const { count: allCount } = useAllEntitiesCount();\n const {\n count: starredEntitiesCount,\n filter: starredEntitiesFilter,\n loading: loadingStarredEntities,\n } = useStarredEntitiesCount();\n\n const queryParamUserFilter = useMemo(\n () => [userParameter].flat()[0],\n [userParameter],\n );\n\n const [selectedUserFilter, setSelectedUserFilter] = useState(\n (queryParamUserFilter as UserListFilterKind) ?? initialFilter,\n );\n\n const filterCounts = useMemo(() => {\n return {\n all: allCount,\n starred: starredEntitiesCount,\n owned: ownedEntitiesCount,\n };\n }, [starredEntitiesCount, ownedEntitiesCount, allCount]);\n\n // Set selected user filter on query parameter updates; this happens at initial page load and from\n // external updates to the page location.\n useEffect(() => {\n if (queryParamUserFilter) {\n setSelectedUserFilter(queryParamUserFilter as UserListFilterKind);\n }\n }, [queryParamUserFilter]);\n\n const loading = loadingOwnedEntities || loadingStarredEntities;\n\n useEffect(() => {\n if (\n !loading &&\n !!selectedUserFilter &&\n selectedUserFilter !== 'all' &&\n filterCounts[selectedUserFilter] === 0 &&\n !alwaysKeepFilters\n ) {\n setSelectedUserFilter('all');\n }\n }, [\n loading,\n filterCounts,\n selectedUserFilter,\n setSelectedUserFilter,\n alwaysKeepFilters,\n ]);\n\n useEffect(() => {\n if (!selectedUserFilter) {\n return;\n }\n if (loading) {\n return;\n }\n\n const getFilter = () => {\n if (selectedUserFilter === 'owned') {\n return ownedEntitiesFilter;\n }\n if (selectedUserFilter === 'starred') {\n return starredEntitiesFilter;\n }\n return EntityUserFilter.all();\n };\n\n updateFilters({ user: getFilter() });\n }, [\n selectedUserFilter,\n starredEntitiesFilter,\n ownedEntitiesFilter,\n updateFilters,\n\n loading,\n ]);\n\n return hidden ? null : (\n <Card className={classes.root}>\n {filterGroups.map(group => (\n <Fragment key={group.name}>\n <Typography\n variant=\"subtitle2\"\n component=\"span\"\n className={classes.title}\n >\n {group.name}\n </Typography>\n <Card className={classes.groupWrapper}>\n <List disablePadding dense role=\"menu\" aria-label={group.name}>\n {group.items.map((item, index) => (\n <MenuItem\n role=\"none presentation\"\n key={item.id}\n divider={index !== group.items.length - 1}\n onClick={() => setSelectedUserFilter(item.id)}\n selected={item.id === filters.user?.value}\n className={classes.menuItem}\n disabled={filterCounts[item.id] === 0}\n data-testid={`user-picker-${item.id}`}\n tabIndex={0}\n ContainerProps={{ role: 'menuitem' }}\n >\n {item.icon && (\n <ListItemIcon className={classes.listIcon}>\n <item.icon fontSize=\"small\" />\n </ListItemIcon>\n )}\n <ListItemText>\n <Typography variant=\"body1\">{item.label} </Typography>\n </ListItemText>\n <ListItemSecondaryAction>\n {filterCounts[item.id] ?? '-'}\n </ListItemSecondaryAction>\n </MenuItem>\n ))}\n </List>\n </Card>\n </Fragment>\n ))}\n </Card>\n );\n};\n","/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { identityApiRef, useApi } from '@backstage/core-plugin-api';\nimport { compact, intersection } from 'lodash';\nimport { useMemo } from 'react';\nimport useAsync from 'react-use/esm/useAsync';\nimport { catalogApiRef } from '../../api';\nimport { EntityOwnerFilter, EntityUserFilter } from '../../filters';\nimport { useEntityList } from '../../hooks';\nimport { CatalogFilters, reduceCatalogFilters } from '../../utils/filters';\nimport useAsyncFn from 'react-use/esm/useAsyncFn';\nimport useDeepCompareEffect from 'react-use/esm/useDeepCompareEffect';\n\nexport function useOwnedEntitiesCount() {\n const identityApi = useApi(identityApiRef);\n const catalogApi = useApi(catalogApiRef);\n\n const { filters } = useEntityList();\n\n const { value: ownershipEntityRefs, loading: loadingEntityRefs } = useAsync(\n async () => (await identityApi.getBackstageIdentity()).ownershipEntityRefs,\n // load only on mount\n [],\n );\n\n const { user, owners, ...allFilters } = filters;\n const { orderFields, ...catalogFilters } = reduceCatalogFilters(\n compact(Object.values(allFilters)),\n );\n\n const [{ value: count, loading: loadingEntityOwnership }, fetchEntities] =\n useAsyncFn(\n async (req: {\n ownershipEntityRefs: string[];\n owners: EntityOwnerFilter | undefined;\n filter: CatalogFilters;\n }) => {\n const ownedClaims = getOwnedCountClaims(\n req.owners,\n req.ownershipEntityRefs,\n );\n if (ownedClaims === undefined) {\n // this implicitly means that there aren't claims in common with\n // the logged in users, so avoid invoking the queryEntities endpoint\n // which will implicitly returns 0\n return 0;\n }\n\n const { ['metadata.name']: metadata, ...filter } = req.filter.filter;\n\n const { totalItems } = await catalogApi.queryEntities({\n ...req.filter,\n filter: {\n ...filter,\n 'relations.ownedBy': ownedClaims,\n },\n limit: 0,\n });\n return totalItems;\n },\n [],\n { loading: true },\n );\n\n useDeepCompareEffect(() => {\n // context contains no filter, wait\n if (Object.keys(catalogFilters.filter).length === 0) {\n return;\n }\n // ownershipEntityRefs is loading, wait\n if (ownershipEntityRefs === undefined) {\n return;\n }\n fetchEntities({\n ownershipEntityRefs,\n owners,\n filter: catalogFilters,\n });\n }, [ownershipEntityRefs, owners, catalogFilters]);\n\n const loading = loadingEntityRefs || loadingEntityOwnership;\n\n return {\n count,\n loading,\n filter: useMemo(\n () => EntityUserFilter.owned(ownershipEntityRefs ?? []),\n [ownershipEntityRefs],\n ),\n ownershipEntityRefs,\n };\n}\n\nfunction getOwnedCountClaims(\n owners: EntityOwnerFilter | undefined,\n ownershipEntityRefs: string[] | undefined,\n) {\n if (!ownershipEntityRefs?.length) {\n return undefined;\n }\n const ownersRefs = owners?.values ?? [];\n if (ownersRefs.length) {\n const commonOwnedBy = intersection(ownersRefs, ownershipEntityRefs);\n if (commonOwnedBy.length === 0) {\n return undefined;\n }\n return commonOwnedBy;\n }\n return ownershipEntityRefs;\n}\n","/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { QueryEntitiesInitialRequest } from '@backstage/catalog-client';\nimport { useApi } from '@backstage/core-plugin-api';\nimport { compact, isEqual } from 'lodash';\nimport { useMemo, useRef } from 'react';\nimport useAsync from 'react-use/esm/useAsync';\nimport { catalogApiRef } from '../../api';\nimport { useEntityList } from '../../hooks';\nimport { reduceCatalogFilters } from '../../utils/filters';\n\nexport function useAllEntitiesCount() {\n const catalogApi = useApi(catalogApiRef);\n const { filters } = useEntityList();\n\n const prevRequest = useRef<QueryEntitiesInitialRequest>();\n const request = useMemo(() => {\n const { user, ...allFilters } = filters;\n const compacted = compact(Object.values(allFilters));\n const { orderFields, ...catalogFilters } = reduceCatalogFilters(compacted);\n const newRequest: QueryEntitiesInitialRequest = {\n ...catalogFilters,\n limit: 0,\n };\n\n if (Object.keys(catalogFilters.filter).length === 0) {\n prevRequest.current = undefined;\n return prevRequest.current;\n }\n\n if (isEqual(newRequest, prevRequest.current)) {\n return prevRequest.current;\n }\n prevRequest.current = newRequest;\n return newRequest;\n }, [filters]);\n\n const { value: count, loading } = useAsync(async () => {\n if (request === undefined) {\n return 0;\n }\n const { totalItems } = await catalogApi.queryEntities(request);\n\n return totalItems;\n }, [request]);\n\n return { count, loading };\n}\n","/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { QueryEntitiesInitialRequest } from '@backstage/catalog-client';\nimport { parseEntityRef, stringifyEntityRef } from '@backstage/catalog-model';\nimport { useApi } from '@backstage/core-plugin-api';\nimport { compact, isEqual } from 'lodash';\nimport { useMemo, useRef } from 'react';\nimport useAsync from 'react-use/esm/useAsync';\nimport { catalogApiRef } from '../../api';\nimport { EntityUserFilter } from '../../filters';\nimport { useEntityList, useStarredEntities } from '../../hooks';\nimport { reduceCatalogFilters } from '../../utils/filters';\n\nexport function useStarredEntitiesCount() {\n const catalogApi = useApi(catalogApiRef);\n const { filters } = useEntityList();\n const { starredEntities } = useStarredEntities();\n\n const prevRequest = useRef<QueryEntitiesInitialRequest>();\n const request = useMemo(() => {\n const { user, ...allFilters } = filters;\n const compacted = compact(Object.values(allFilters));\n const { orderFields, ...catalogFilters } = reduceCatalogFilters(compacted);\n\n const facet = 'metadata.name';\n\n const newRequest: QueryEntitiesInitialRequest = {\n ...catalogFilters,\n filter: {\n ...catalogFilters.filter,\n /**\n * here we are filtering entities by `name`. Given this filter,\n * the response might contain more entities than expected, in case multiple entities\n * of different kind or namespace share the same name. Those extra entities are filtered out\n * client side by `EntityUserFilter`, so they won't be visible to the user.\n */\n [facet]: Array.from(starredEntities).map(e => parseEntityRef(e).name),\n },\n /**\n * limit is set to a high value as we are not expecting many starred entities\n */\n limit: 1000,\n };\n if (isEqual(newRequest, prevRequest.current)) {\n return prevRequest.current;\n }\n prevRequest.current = newRequest;\n\n return newRequest;\n }, [filters, starredEntities]);\n\n const { value: count, loading } = useAsync(async () => {\n if (!starredEntities.size) {\n return 0;\n }\n\n /**\n * given a list of starred entity refs and some filters coming from CatalogPage,\n * it reduces the list of starred entities, to a list of entities that matches the\n * provided filters. It won't be possible to getEntitiesByRefs\n * as the method doesn't accept any filter.\n */\n const response = await catalogApi.queryEntities(request);\n\n return response.items\n .map(e =>\n stringifyEntityRef({\n kind: e.kind,\n namespace: e.metadata.namespace,\n name: e.metadata.name,\n }),\n )\n .filter(e => starredEntities.has(e)).length;\n }, [request, starredEntities]);\n\n const filter = useMemo(\n () => EntityUserFilter.starred(Array.from(starredEntities)),\n [starredEntities],\n );\n\n return { count, loading, filter };\n}\n","/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n Entity,\n parseEntityRef,\n RELATION_OWNED_BY,\n stringifyEntityRef,\n} from '@backstage/catalog-model';\nimport { AlphaEntity } from '@backstage/catalog-model/alpha';\nimport { EntityFilter, UserListFilterKind } from './types';\nimport { getEntityRelations } from './utils/getEntityRelations';\nimport { EntityOrderQuery } from '@backstage/catalog-client';\n\n/**\n * Filter entities based on Kind.\n * @public\n */\nexport class EntityKindFilter implements EntityFilter {\n readonly value: string;\n readonly label: string;\n\n constructor(value: string, label: string) {\n this.value = value;\n this.label = label;\n }\n\n getCatalogFilters(): Record<string, string | string[]> {\n return { kind: this.value };\n }\n\n toQueryValue(): string {\n return this.value;\n }\n}\n\n/**\n * Filters entities based on type\n * @public\n */\nexport class EntityTypeFilter implements EntityFilter {\n readonly value: string | string[];\n\n constructor(value: string | string[]) {\n this.value = value;\n }\n\n // Simplify `string | string[]` for consumers, always returns an array\n getTypes(): string[] {\n return Array.isArray(this.value) ? this.value : [this.value];\n }\n\n getCatalogFilters(): Record<string, string | string[]> {\n return { 'spec.type': this.getTypes() };\n }\n\n toQueryValue(): string[] {\n return this.getTypes();\n }\n}\n\n/**\n * Filters entities based on tag.\n * @public\n */\nexport class EntityTagFilter implements EntityFilter {\n readonly values: string[];\n\n constructor(values: string[]) {\n this.values = values;\n }\n\n filterEntity(entity: Entity): boolean {\n return this.values.every(v => (entity.metadata.tags ?? []).includes(v));\n }\n\n getCatalogFilters(): Record<string, string | string[]> {\n return { 'metadata.tags': this.values };\n }\n\n toQueryValue(): string[] {\n return this.values;\n }\n}\n\n/**\n * Filters entities where the text matches spec, title or tags.\n * @public\n */\nexport class EntityTextFilter implements EntityFilter {\n readonly value: string;\n\n constructor(value: string) {\n this.value = value;\n }\n\n filterEntity(entity: Entity): boolean {\n const words = this.toUpperArray(this.value.split(/\\s/));\n const exactMatch = this.toUpperArray([entity.metadata.tags]);\n const targets = (entity.spec as { targets?: unknown })?.targets;\n const partialMatch = this.toUpperArray([\n entity.metadata.name,\n entity.metadata.title,\n (entity.spec?.profile as { displayName?: string })?.displayName,\n (entity.spec as { target?: string })?.target,\n ...(Array.isArray(targets) ? targets : []),\n ]);\n\n for (const word of words) {\n if (\n exactMatch.every(m => m !== word) &&\n partialMatch.every(m => !m.includes(word))\n ) {\n return false;\n }\n }\n\n return true;\n }\n\n getFullTextFilters() {\n return {\n term: this.value,\n // Update this to be more dynamic based on table columns.\n fields: [\n 'metadata.name',\n 'metadata.title',\n 'spec.profile.displayName',\n 'spec.target',\n 'spec.targets',\n ],\n };\n }\n\n toQueryValue() {\n return this.value;\n }\n\n private toUpperArray(\n value: Array<string | string[] | undefined>,\n ): Array<string> {\n return value\n .flat()\n .filter((m): m is string => Boolean(m) && typeof m === 'string')\n .map(m => m.toUpperCase());\n }\n}\n\n/**\n * Filter matching entities that are owned by group.\n * @public\n *\n * CAUTION: This class may contain both full and partial entity refs.\n */\nexport class EntityOwnerFilter implements EntityFilter {\n readonly values: string[];\n constructor(values: string[]) {\n this.values = values.reduce((fullRefs, ref) => {\n // Attempt to remove bad entity references here.\n try {\n fullRefs.push(\n stringifyEntityRef(parseEntityRef(ref, { defaultKind: 'Group' })),\n );\n return fullRefs;\n } catch (err) {\n return fullRefs;\n }\n }, [] as string[]);\n }\n\n getCatalogFilters(): Record<string, string | string[]> {\n return { 'relations.ownedBy': this.values };\n }\n\n filterEntity(entity: Entity): boolean {\n return this.values.some(v =>\n getEntityRelations(entity, RELATION_OWNED_BY).some(\n o => stringifyEntityRef(o) === v,\n ),\n );\n }\n\n /**\n * Get the URL query parameter value. May be a mix of full and humanized entity refs.\n * @returns list of entity refs.\n */\n toQueryValue(): string[] {\n return this.values;\n }\n}\n\n/**\n * Filters entities on lifecycle.\n * @public\n */\nexport class EntityLifecycleFilter implements EntityFilter {\n readonly values: string[];\n\n constructor(values: string[]) {\n this.values = values;\n }\n\n getCatalogFilters(): Record<string, string | string[]> {\n return { 'spec.lifecycle': this.values };\n }\n\n filterEntity(entity: Entity): boolean {\n return this.values.some(v => entity.spec?.lifecycle === v);\n }\n\n toQueryValue(): string[] {\n return this.values;\n }\n}\n\n/**\n * Filters entities to those within the given namespace(s).\n * @public\n */\nexport class EntityNamespaceFilter implements EntityFilter {\n readonly values: string[];\n\n constructor(values: string[]) {\n this.values = values;\n }\n\n getCatalogFilters(): Record<string, string | string[]> {\n return { 'metadata.namespace': this.values };\n }\n filterEntity(entity: Entity): boolean {\n return this.values.some(v => entity.metadata.namespace === v);\n }\n\n toQueryValue(): string[] {\n return this.values;\n }\n}\n\n/**\n * @public\n */\nexport class EntityUserFilter implements EntityFilter {\n readonly value: UserListFilterKind;\n readonly refs?: string[];\n\n private constructor(value: UserListFilterKind, refs?: string[]) {\n this.value = value;\n this.refs = refs;\n }\n\n static owned(ownershipEntityRefs: string[]) {\n return new EntityUserFilter('owned', ownershipEntityRefs);\n }\n\n static all() {\n return new EntityUserFilter('all');\n }\n\n static starred(starredEntityRefs: string[]) {\n return new EntityUserFilter('starred', starredEntityRefs);\n }\n\n getCatalogFilters(): Record<string, string[]> {\n if (this.value === 'owned') {\n return { 'relations.ownedBy': this.refs ?? [] };\n }\n if (this.value === 'starred') {\n return {\n 'metadata.name': this.refs?.map(e => parseEntityRef(e).name) ?? [],\n };\n }\n return {};\n }\n\n filterEntity(entity: Entity) {\n if (this.value === 'starred') {\n return this.refs?.includes(stringifyEntityRef(entity)) ?? true;\n }\n // used only for retro-compatibility with non paginated data.\n // This is supposed to return always true for paginated\n // owned entities, since the filters are applied server side.\n if (this.value === 'owned') {\n const relations = getEntityRelations(entity, RELATION_OWNED_BY);\n\n return (\n this.refs?.some(v =>\n relations.some(o => stringifyEntityRef(o) === v),\n ) ?? false\n );\n }\n return true;\n }\n\n toQueryValue(): string {\n return this.value;\n }\n}\n\n/**\n * Filters entities based on whatever the user has starred or owns them.\n * @deprecated use EntityUserFilter\n * @public\n */\nexport class UserListFilter implements EntityFilter {\n readonly value: UserListFilterKind;\n readonly isOwnedEntity: (entity: Entity) => boolean;\n readonly isStarredEntity: (entity: Entity) => boolean;\n\n constructor(\n value: UserListFilterKind,\n isOwnedEntity: (entity: Entity) => boolean,\n isStarredEntity: (entity: Entity) => boolean,\n ) {\n this.value = value;\n this.isOwnedEntity = isOwnedEntity;\n this.isStarredEntity = isStarredEntity;\n }\n\n filterEntity(entity: Entity): boolean {\n switch (this.value) {\n case 'owned':\n return this.isOwnedEntity(entity);\n case 'starred':\n return this.isStarredEntity(entity);\n default:\n return true;\n }\n }\n\n toQueryValue(): string {\n return this.value;\n }\n}\n\n/**\n * Filters entities based if it is an orphan or not.\n * @public\n */\nexport class EntityOrphanFilter implements EntityFilter {\n readonly value: boolean;\n\n constructor(value: boolean) {\n this.value = value;\n }\n\n getCatalogFilters(): Record<string, string | string[]> {\n if (this.value) {\n return { 'metadata.annotations.backstage.io/orphan': String(this.value) };\n }\n return {};\n }\n\n filterEntity(entity: Entity): boolean {\n const orphan = entity.metadata.annotations?.['backstage.io/orphan'];\n return orphan !== undefined && this.value.toString() === orphan;\n }\n}\n\n/**\n * Filters entities based on if it has errors or not.\n * @public\n */\nexport class EntityErrorFilter implements EntityFilter {\n readonly value: boolean;\n\n constructor(value: boolean) {\n this.value = value;\n }\n\n filterEntity(entity: Entity): boolean {\n const error =\n ((entity as AlphaEntity)?.status?.items?.length as number) > 0;\n return error !== undefined && this.value === error;\n }\n}\n\n/**\n * Sort entities by a given field/column.\n * @public\n */\nexport class EntityOrderFilter implements EntityFilter {\n readonly values: [string, 'asc' | 'desc'][];\n\n constructor(values: [string, 'asc' | 'desc'][]) {\n this.values = values;\n }\n\n getOrderFilters(): EntityOrderQuery {\n return this.values.map(([field, order]) => ({ field, order }));\n }\n\n toQueryValue(): string[] {\n return this.values.flat();\n }\n}\n","/*\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 { QueryEntitiesResponse } from '@backstage/catalog-client';\nimport { Entity } from '@backstage/catalog-model';\nimport { useApi } from '@backstage/core-plugin-api';\nimport {\n createVersionedContext,\n createVersionedValueMap,\n useVersionedContext,\n} from '@backstage/version-bridge';\nimport { compact, isEqual } from 'lodash';\nimport qs from 'qs';\nimport {\n createContext,\n PropsWithChildren,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { useLocation } from 'react-router-dom';\nimport useAsyncFn from 'react-use/esm/useAsyncFn';\nimport useDebounce from 'react-use/esm/useDebounce';\nimport useMountedState from 'react-use/esm/useMountedState';\nimport { catalogApiRef } from '../api';\nimport {\n EntityErrorFilter,\n EntityKindFilter,\n EntityLifecycleFilter,\n EntityNamespaceFilter,\n EntityOrderFilter,\n EntityOrphanFilter,\n EntityOwnerFilter,\n EntityTagFilter,\n EntityTextFilter,\n EntityTypeFilter,\n EntityUserFilter,\n UserListFilter,\n} from '../filters';\nimport { EntityFilter, EntityListPagination } from '../types';\nimport {\n reduceBackendCatalogFilters,\n reduceCatalogFilters,\n reduceEntityFilters,\n} from '../utils/filters';\n\n/** @public */\nexport type DefaultEntityFilters = {\n kind?: EntityKindFilter;\n type?: EntityTypeFilter;\n user?: UserListFilter | EntityUserFilter;\n owners?: EntityOwnerFilter;\n lifecycles?: EntityLifecycleFilter;\n tags?: EntityTagFilter;\n text?: EntityTextFilter;\n orphan?: EntityOrphanFilter;\n error?: EntityErrorFilter;\n namespace?: EntityNamespaceFilter;\n order?: EntityOrderFilter;\n};\n\n/** @public */\nexport type PaginationMode = 'cursor' | 'offset' | 'none';\n\n/** @public */\nexport type EntityListContextProps<\n EntityFilters extends DefaultEntityFilters = DefaultEntityFilters,\n> = {\n /**\n * The currently registered filters, adhering to the shape of DefaultEntityFilters or an extension\n * of that default (to add custom filter types).\n */\n filters: EntityFilters;\n\n /**\n * The resolved list of catalog entities, after all filters are applied.\n */\n entities: Entity[];\n\n /**\n * The resolved list of catalog entities, after _only catalog-backend_ filters are applied.\n */\n backendEntities: Entity[];\n\n /**\n * Update one or more of the registered filters. Optional filters can be set to `undefined` to\n * reset the filter.\n */\n updateFilters: (\n filters:\n | Partial<EntityFilters>\n | ((prevFilters: EntityFilters) => Partial<EntityFilters>),\n ) => void;\n\n /**\n * Filter values from query parameters.\n */\n queryParameters: Partial<Record<keyof EntityFilters, string | string[]>>;\n\n loading: boolean;\n error?: Error;\n\n pageInfo?: {\n next?: () => void;\n prev?: () => void;\n };\n totalItems?: number;\n totalItemsLoading: boolean;\n limit: number;\n offset?: number;\n setLimit: (limit: number) => void;\n setOffset?: (offset: number) => void;\n paginationMode: PaginationMode;\n\n /**\n * Trigger refresh of entities and entity totals.\n */\n refresh?: () => void;\n};\n\n// This context has support for multiple concurrent versions of this package.\n// It is currently used in parallel with the old context in order to provide\n// a smooth transition, but will eventually be the only context we use.\nexport const NewEntityListContext = createVersionedContext<{\n 1: EntityListContextProps<any>;\n}>('entity-list-context');\n\n/**\n * Creates new context for entity listing and filtering.\n */\nexport const OldEntityListContext = createContext<\n EntityListContextProps<any> | undefined\n>(undefined);\n\ntype BackendState = {\n backendEntities: Entity[];\n pageInfo?: QueryEntitiesResponse['pageInfo'];\n totalItems?: number;\n};\n\n/**\n * @public\n */\nexport type EntityListProviderProps = PropsWithChildren<{\n pagination?: EntityListPagination;\n}>;\n\n/**\n * Provides entities and filters for a catalog listing.\n * @public\n */\nexport const EntityListProvider = <EntityFilters extends DefaultEntityFilters>(\n props: EntityListProviderProps,\n) => {\n const isMounted = useMountedState();\n const catalogApi = useApi(catalogApiRef);\n const [requestedFilters, setRequestedFilters] = useState<EntityFilters>(\n {} as EntityFilters,\n );\n\n // We use react-router's useLocation hook so updates from external sources trigger an update to\n // the queryParameters in outputState. Updates from this hook use replaceState below and won't\n // trigger a useLocation change; this would instead come from an external source, such as a manual\n // update of the URL or two catalog sidebar links with different catalog filters.\n const location = useLocation();\n\n let paginationMode: PaginationMode = 'none';\n if (props.pagination === true) {\n paginationMode = 'cursor';\n } else if (typeof props.pagination === 'object') {\n paginationMode = props.pagination.mode ?? 'cursor';\n }\n const paginationLimit =\n typeof props.pagination === 'object' ? props.pagination.limit ?? 20 : 20;\n\n const {\n queryParameters,\n cursor: initialCursor,\n offset: initialOffset,\n limit: initialLimit,\n } = useMemo(() => {\n const parsed = qs.parse(location.search, {\n ignoreQueryPrefix: true,\n arrayLimit: 10000,\n });\n\n let limit = paginationLimit;\n if (typeof parsed.limit === 'string') {\n const queryLimit = Number.parseInt(parsed.limit, 10);\n if (!isNaN(queryLimit)) {\n limit = queryLimit;\n }\n }\n\n const offset =\n typeof parsed.offset === 'string' && paginationMode === 'offset'\n ? Number.parseInt(parsed.offset, 10)\n : undefined;\n\n return {\n queryParameters: (parsed.filters ?? {}) as Record<\n string,\n string | string[]\n >,\n cursor:\n typeof parsed.cursor === 'string' && paginationMode === 'cursor'\n ? parsed.cursor\n : undefined,\n offset:\n paginationMode === 'offset' && offset && !isNaN(offset)\n ? offset\n : undefined,\n limit,\n };\n }, [paginationMode, location.search, paginationLimit]);\n\n const [cursor, setCursor] = useState(initialCursor);\n const [offset, setOffset] = useState<number | undefined>(initialOffset);\n const [limit, setLimit] = useState(initialLimit);\n\n const [backendState, setBackendState] = useState<BackendState>({\n backendEntities: [],\n });\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<Error | undefined>();\n const [refreshToken, setRefreshToken] = useState(0);\n\n // Tracks the params of the last API call so identical requests are\n // skipped even when requestedFilters changes (e.g. a label change\n // or a frontend-only filter addition).\n const lastFetchParamsRef = useRef<unknown>(undefined);\n // Generation counter — only the most recent fetch updates state,\n // so out-of-order responses from overlapping requests are discarded.\n const fetchGenRef = useRef(0);\n\n // Adjusted filters remove the owners filter for user/group kinds,\n // since ownership is not meaningful for those entity types.\n const adjustedFilters = useMemo(() => {\n const kindValue = requestedFilters.kind?.value?.toLowerCase();\n return kindValue === 'user' || kindValue === 'group'\n ? { ...requestedFilters, owners: undefined }\n : requestedFilters;\n }, [requestedFilters]);\n\n const refresh = async () => {\n const compacted = compact(Object.values(adjustedFilters));\n\n let fetchParams: unknown;\n let doFetch: () => Promise<BackendState>;\n\n if (paginationMode !== 'none') {\n if (cursor) {\n fetchParams = { cursor, limit };\n doFetch = async () => {\n const response = await catalogApi.queryEntities({\n cursor,\n limit,\n totalItems: 'exclude',\n });\n return {\n backendEntities: response.items,\n pageInfo: response.pageInfo,\n };\n };\n } else {\n const backendFilter = reduceCatalogFilters(compacted);\n fetchParams = { ...backendFilter, limit, offset };\n doFetch = async () => {\n const response = await catalogApi.queryEntities({\n ...backendFilter,\n limit,\n offset,\n totalItems: 'exclude',\n });\n return {\n backendEntities: response.items,\n pageInfo: response.pageInfo,\n };\n };\n }\n } else {\n const backendFilter = reduceBackendCatalogFilters(compacted);\n const { orderFields } = reduceCatalogFilters(compacted);\n fetchParams = { filter: backendFilter, order: orderFields };\n doFetch = async () => {\n const response = await catalogApi.getEntities({\n filter: backendFilter,\n order: orderFields,\n });\n return { backendEntities: response.items };\n };\n }\n\n // No filters registered yet — wait for filter components to\n // call updateFilters before making the first request.\n // Exception: a cursor in the URL is a self-contained page reference\n // that doesn't need filter state to be valid.\n if (\n compacted.length === 0 &&\n lastFetchParamsRef.current === undefined &&\n !cursor\n ) {\n setLoading(false);\n return;\n }\n\n if (isEqual(fetchParams, lastFetchParamsRef.current)) {\n return;\n }\n lastFetchParamsRef.current = fetchParams;\n\n const gen = ++fetchGenRef.current;\n setLoading(true);\n setError(undefined);\n\n try {\n const result = await doFetch();\n if (gen === fetchGenRef.current) {\n setBackendState(result);\n }\n } catch (e) {\n if (gen === fetchGenRef.current) {\n // Clear the ref so the same params can be retried, and so\n // a response discarded due to a concurrent request (gen mismatch)\n // doesn't permanently block fetching those params again.\n lastFetchParamsRef.current = undefined;\n setError(e as Error);\n }\n } finally {\n if (gen === fetchGenRef.current) {\n setLoading(false);\n }\n }\n };\n\n // Slight debounce on the refresh, since (especially on page load)\n // several filters will be calling updateFilters in rapid succession.\n useDebounce(refresh, 10, [\n adjustedFilters,\n cursor,\n limit,\n offset,\n refreshToken,\n ]);\n\n // Fetch the total count separately, only when filters change. This is\n // decoupled from the main list fetch so that page navigation doesn't\n // re-run the expensive count query, and so that the count can arrive\n // asynchronously without blocking the list response.\n const [{ value: totalItems, loading: totalItemsLoading }, refreshCount] =\n useAsyncFn(async () => {\n if (paginationMode === 'none') {\n return undefined;\n }\n const compacted = compact(Object.values(adjustedFilters));\n if (compacted.length === 0) {\n return undefined;\n }\n const backendFilter = reduceCatalogFilters(compacted);\n try {\n const response = await catalogApi.queryEntities({\n ...backendFilter,\n limit: 0,\n });\n return response.totalItems;\n } catch {\n return undefined;\n }\n }, [catalogApi, paginationMode, adjustedFilters]);\n\n useDebounce(refreshCount, 10, [adjustedFilters, refreshToken]);\n\n // Frontend filtering — synchronous, no debounce needed. Updates\n // instantly when requestedFilters or backendEntities change.\n const entities = useMemo(() => {\n const compacted = compact(Object.values(adjustedFilters));\n const entityFilter = reduceEntityFilters(compacted);\n return backendState.backendEntities.filter(entityFilter);\n }, [adjustedFilters, backendState.backendEntities]);\n\n // Sync filter state to URL query parameters. We use direct history\n // manipulation since useSearchParams and useNavigate in\n // react-router-dom cause unnecessary extra rerenders. Also make sure\n // to replace the state rather than pushing, since we don't want\n // there to be back/forward slots for every single filter change.\n useEffect(() => {\n if (!isMounted() || Object.keys(requestedFilters).length === 0) {\n return;\n }\n const queryParams = Object.keys(requestedFilters).reduce((params, key) => {\n const filter = requestedFilters[key as keyof EntityFilters] as\n | EntityFilter\n | undefined;\n if (filter?.toQueryValue) {\n params[key] = filter.toQueryValue();\n }\n return params;\n }, {} as Record<string, string | string[]>);\n\n const oldParams = qs.parse(location.search, {\n ignoreQueryPrefix: true,\n arrayLimit: 10000,\n });\n const newParams = qs.stringify(\n {\n ...oldParams,\n filters: queryParams,\n ...(paginationMode === 'none' ? {} : { cursor, limit, offset }),\n },\n { addQueryPrefix: true, arrayFormat: 'repeat' },\n );\n const newUrl = `${window.location.pathname}${newParams}`;\n window.history?.replaceState(null, document.title, newUrl);\n }, [\n cursor,\n isMounted,\n limit,\n location.search,\n offset,\n requestedFilters,\n paginationMode,\n ]);\n\n const updateFilters = useCallback(\n (\n update:\n | Partial<EntityFilter>\n | ((prevFilters: EntityFilters) => Partial<EntityFilters>),\n ) => {\n // changing filters will affect pagination, so we need to reset\n // the cursor and start from the first page.\n // TODO(vinzscam): this is currently causing issues at page reload\n // where the state is not kept. Unfortunately we need to rethink\n // the way filters work in order to fix this.\n if (paginationMode === 'cursor') {\n setCursor(undefined);\n } else if (paginationMode === 'offset') {\n // Same thing with offset\n setOffset(0);\n }\n setRequestedFilters(prevFilters => {\n const newFilters =\n typeof update === 'function' ? update(prevFilters) : update;\n return { ...prevFilters, ...newFilters };\n });\n },\n [paginationMode],\n );\n\n const triggerRefresh = useCallback(() => {\n // Clear the ref to allow refetching with the same params.\n lastFetchParamsRef.current = undefined;\n setRefreshToken(t => t + 1);\n }, []);\n\n const pageInfo = useMemo(() => {\n if (paginationMode !== 'cursor') {\n return undefined;\n }\n\n const prevCursor = backendState.pageInfo?.prevCursor;\n const nextCursor = backendState.pageInfo?.nextCursor;\n return {\n prev: prevCursor ? () => setCursor(prevCursor) : undefined,\n next: nextCursor ? () => setCursor(nextCursor) : undefined,\n };\n }, [paginationMode, backendState.pageInfo]);\n\n const value = useMemo(\n () => ({\n filters: requestedFilters,\n entities,\n backendEntities: backendState.backendEntities,\n updateFilters,\n queryParameters,\n loading,\n error,\n pageInfo,\n totalItems:\n paginationMode === 'none'\n ? entities.length\n : totalItems ?? backendState.totalItems,\n totalItemsLoading: paginationMode !== 'none' && totalItemsLoading,\n limit,\n offset,\n setLimit,\n setOffset,\n paginationMode,\n refresh: triggerRefresh,\n }),\n [\n requestedFilters,\n entities,\n backendState,\n totalItems,\n totalItemsLoading,\n updateFilters,\n queryParameters,\n loading,\n error,\n pageInfo,\n paginationMode,\n limit,\n offset,\n setLimit,\n setOffset,\n triggerRefresh,\n ],\n );\n\n return (\n <OldEntityListContext.Provider value={value}>\n <NewEntityListContext.Provider\n value={createVersionedValueMap({ 1: value })}\n >\n {props.children}\n </NewEntityListContext.Provider>\n </OldEntityListContext.Provider>\n );\n};\n\n/**\n * Hook for interacting with the entity list context provided by the {@link EntityListProvider}.\n * @public\n */\nexport function useEntityList<\n EntityFilters extends DefaultEntityFilters = DefaultEntityFilters,\n>(): EntityListContextProps<EntityFilters> {\n const versionedHolder = useVersionedContext<{\n 1: EntityListContextProps<any>;\n }>('entity-list-context');\n const oldContext = useContext(OldEntityListContext);\n\n if (versionedHolder) {\n const value = versionedHolder.atVersion(1);\n if (!value) {\n throw new Error('EntityListContext v1 not available');\n }\n return value;\n }\n\n if (oldContext) {\n return oldContext;\n }\n\n throw new Error('useEntityList must be used within EntityListProvider');\n}\n","/*\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 Entity,\n CompoundEntityRef,\n stringifyEntityRef,\n} from '@backstage/catalog-model';\nimport { useApi } from '@backstage/core-plugin-api';\nimport { useCallback, useMemo } from 'react';\nimport useObservable from 'react-use/esm/useObservable';\nimport { starredEntitiesApiRef } from '../apis';\n\nfunction getEntityRef(\n entityOrRef: Entity | CompoundEntityRef | string,\n): string {\n return typeof entityOrRef === 'string'\n ? entityOrRef\n : stringifyEntityRef(entityOrRef);\n}\n\n/** @public */\nexport function useStarredEntities(): {\n starredEntities: Set<string>;\n toggleStarredEntity: (\n entityOrRef: Entity | CompoundEntityRef | string,\n ) => void;\n isStarredEntity: (\n entityOrRef: Entity | CompoundEntityRef | string,\n ) => boolean;\n} {\n const starredEntitiesApi = useApi(starredEntitiesApiRef);\n\n const starredEntities = useObservable(\n useMemo(() => starredEntitiesApi.starredEntitie$(), [starredEntitiesApi]),\n new Set<string>(),\n );\n\n const isStarredEntity = useCallback(\n (entityOrRef: Entity | CompoundEntityRef | string) =>\n starredEntities.has(getEntityRef(entityOrRef)),\n [starredEntities],\n );\n\n const toggleStarredEntity = useCallback(\n (entityOrRef: Entity | CompoundEntityRef | string) =>\n starredEntitiesApi.toggleStarred(getEntityRef(entityOrRef)).then(),\n [starredEntitiesApi],\n );\n\n return {\n starredEntities,\n toggleStarredEntity,\n isStarredEntity,\n };\n}\n","/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Entity } from '@backstage/catalog-model';\nimport { EntityFilter } from '../types';\nimport {\n EntityLifecycleFilter,\n EntityNamespaceFilter,\n EntityOrderFilter,\n EntityOrphanFilter,\n EntityOwnerFilter,\n EntityTagFilter,\n EntityTextFilter,\n EntityUserFilter,\n UserListFilter,\n} from '../filters';\nimport { EntityOrderQuery } from '@backstage/catalog-client';\n\nexport interface CatalogFilters {\n filter: Record<string, string | symbol | (string | symbol)[]>;\n fullTextFilter?: {\n term: string;\n };\n orderFields?: EntityOrderQuery;\n}\n\nfunction isEntityTextFilter(t: EntityFilter): t is EntityTextFilter {\n return !!(t as EntityTextFilter).getFullTextFilters;\n}\n\nfunction isEntityOrderFilter(t: EntityFilter): t is EntityOrderFilter {\n return !!(t as EntityOrderFilter).getOrderFilters;\n}\n\nexport function reduceCatalogFilters(filters: EntityFilter[]): CatalogFilters {\n const condensedFilters = filters.reduce<CatalogFilters['filter']>(\n (compoundFilter, filter) => {\n return {\n ...compoundFilter,\n ...(filter.getCatalogFilters ? filter.getCatalogFilters() : {}),\n };\n },\n {},\n );\n\n const fullTextFilter = filters.find(isEntityTextFilter)?.getFullTextFilters();\n\n const orderFields = filters.find(isEntityOrderFilter)?.getOrderFilters() || [\n {\n field: 'metadata.name',\n order: 'asc',\n },\n ];\n return { filter: condensedFilters, fullTextFilter, orderFields };\n}\n\n/**\n * This function computes and returns an object containing the filters to be sent\n * to the backend. Any filter coming from `EntityKindFilter` and `EntityTypeFilter`, together\n * with custom filter set by the adopters is allowed. This function is used by `EntityListProvider`\n * and it won't be needed anymore in the future once pagination is implemented, as all the filters\n * will be applied backend-side.\n */\nexport function reduceBackendCatalogFilters(filters: EntityFilter[]) {\n const backendCatalogFilters: Record<\n string,\n string | symbol | (string | symbol)[]\n > = {};\n\n filters.forEach(filter => {\n if (\n filter instanceof EntityTagFilter ||\n filter instanceof EntityOwnerFilter ||\n filter instanceof EntityLifecycleFilter ||\n filter instanceof EntityNamespaceFilter ||\n filter instanceof EntityUserFilter ||\n filter instanceof EntityOrphanFilter ||\n filter instanceof EntityTextFilter ||\n filter instanceof UserListFilter\n ) {\n return;\n }\n Object.assign(backendCatalogFilters, filter.getCatalogFilters?.() || {});\n });\n\n return backendCatalogFilters;\n}\n\nexport function reduceEntityFilters(\n filters: EntityFilter[],\n): (entity: Entity) => boolean {\n return (entity: Entity) =>\n filters.every(\n filter => !filter.filterEntity || filter.filterEntity(entity),\n );\n}\n","/*\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 Entity,\n CompoundEntityRef,\n parseEntityRef,\n} from '@backstage/catalog-model';\n\n// TODO(freben): This should be returning entity refs instead\n/**\n * Get the related entity references.\n *\n * @public\n */\nexport function getEntityRelations(\n entity: Entity | undefined,\n relationType: string,\n filter?: { kind: string },\n): CompoundEntityRef[] {\n let entityNames =\n entity?.relations\n ?.filter(r => r.type === relationType)\n .map(r => parseEntityRef(r.targetRef)) || [];\n\n if (filter?.kind) {\n entityNames = entityNames.filter(\n e => e.kind.toLowerCase() === filter.kind.toLowerCase(),\n );\n }\n\n return entityNames;\n}\n","/*\n * Copyright 2026 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 { Container } from '@backstage/ui';\nimport {\n CatalogFilterLayout,\n EntityListProvider,\n EntityOwnerPicker,\n EntityTagPicker,\n UserListPicker,\n} from '@backstage/plugin-catalog-react';\nimport { TechDocsPicker } from '../../home/components/TechDocsPicker';\nimport { EntityListDocsTable } from '../../home/components/Tables';\nimport type { TechDocsIndexPageProps } from '../../home/components/TechDocsIndexPage';\n\nexport const TechDocsIndexPageContent = (props: TechDocsIndexPageProps) => {\n const {\n initialFilter = 'owned',\n columns,\n actions,\n ownerPickerMode,\n pagination,\n options,\n } = props;\n\n return (\n <Container mt=\"6\">\n <EntityListProvider pagination={pagination}>\n <CatalogFilterLayout>\n <CatalogFilterLayout.Filters>\n <TechDocsPicker />\n <UserListPicker initialFilter={initialFilter} />\n <EntityOwnerPicker mode={ownerPickerMode} />\n <EntityTagPicker />\n </CatalogFilterLayout.Filters>\n <CatalogFilterLayout.Content>\n <EntityListDocsTable\n actions={actions}\n columns={columns}\n options={options}\n />\n </CatalogFilterLayout.Content>\n </CatalogFilterLayout>\n </EntityListProvider>\n </Container>\n );\n};\n","/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Config } from '@backstage/config';\n\n// Lower-case entity triplets by default, but allow override.\nexport function toLowerMaybe(str: string, config: Config) {\n return config.getOptionalBoolean(\n 'techdocs.legacyUseCaseSensitiveTripletPaths',\n )\n ? str\n : str.toLowerCase();\n}\n","/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport useCopyToClipboard from 'react-use/esm/useCopyToClipboard';\n\nimport {\n configApiRef,\n useApi,\n useApiHolder,\n useRouteRef,\n} from '@backstage/core-plugin-api';\nimport { useTranslationRef } from '@backstage/core-plugin-api/alpha';\nimport { Entity } from '@backstage/catalog-model';\nimport { rootDocsRouteRef } from '../../../routes';\nimport { entityPresentationApiRef } from '@backstage/plugin-catalog-react';\nimport {\n EmptyState,\n LinkButton,\n Table,\n TableColumn,\n TableOptions,\n TableProps,\n} from '@backstage/core-components';\nimport { techdocsTranslationRef } from '../../../translation';\nimport { actionFactories } from './actions';\nimport { columnFactories } from './columns';\nimport {\n DocsTableRow,\n DocsTableColumnFactories,\n DocsTableActionFactories,\n} from './types';\nimport { entitiesToDocsMapper } from './helpers';\n\n/**\n * Props for {@link DocsTable}.\n *\n * @public\n */\nexport type DocsTableProps = {\n entities: Entity[] | undefined;\n title?: string | undefined;\n loading?: boolean | undefined;\n columns?: TableColumn<DocsTableRow>[];\n actions?: TableProps<DocsTableRow>['actions'];\n options?: TableOptions<DocsTableRow>;\n};\n\n/**\n * Component which renders a table documents\n *\n * @public\n */\nconst DocsTableComponent = (props: DocsTableProps): JSX.Element | null => {\n const { entities, title, loading, columns, actions, options } = props;\n const [, copyToClipboard] = useCopyToClipboard();\n const getRouteToReaderPageFor = useRouteRef(rootDocsRouteRef);\n const config = useApi(configApiRef);\n const apiHolder = useApiHolder();\n\n const { t } = useTranslationRef(techdocsTranslationRef);\n if (!entities) return null;\n\n const documents = entitiesToDocsMapper(\n entities,\n getRouteToReaderPageFor,\n config,\n apiHolder.get(entityPresentationApiRef),\n );\n\n const tableColumns = columns || [\n columnFactories.createTitleColumn({\n hidden: true,\n entityPresentationApi: apiHolder.get(entityPresentationApiRef),\n }),\n columnFactories.createNameColumn({\n entityPresentationApi: apiHolder.get(entityPresentationApiRef),\n }),\n columnFactories.createOwnerColumn(),\n columnFactories.createKindColumn(),\n columnFactories.createTypeColumn(),\n ];\n\n const defaultActions: TableProps<DocsTableRow>['actions'] = [\n actionFactories.createCopyDocsUrlAction(copyToClipboard, t),\n ];\n\n const pageSize = 20;\n const paging = documents && documents.length > pageSize;\n\n return (\n <>\n {loading || (documents && documents.length > 0) ? (\n <Table<DocsTableRow>\n isLoading={loading}\n options={{\n paging,\n pageSize,\n search: true,\n actionsColumnIndex: -1,\n ...options,\n }}\n data={documents}\n columns={tableColumns}\n actions={actions || defaultActions}\n title={\n title\n ? `${title} (${documents.length})`\n : `${t('table.title.all')} (${documents.length})`\n }\n localization={{\n header: {\n actions: t('table.header.actions'),\n },\n toolbar: {\n searchPlaceholder: t('table.toolbar.searchPlaceholder'),\n },\n pagination: {\n labelRowsSelect: t('table.pagination.labelRowsSelect'),\n },\n body: {\n emptyDataSourceMessage: t('table.body.emptyDataSourceMessage'),\n },\n }}\n />\n ) : (\n <EmptyState\n missing=\"data\"\n title={t('table.emptyState.title')}\n description={t('table.emptyState.description')}\n action={\n <LinkButton\n color=\"primary\"\n to=\"https://backstage.io/docs/features/techdocs/getting-started\"\n variant=\"contained\"\n >\n {t('table.emptyState.docsButton')}\n </LinkButton>\n }\n />\n )}\n </>\n );\n};\n\n/**\n * @public\n */\nexport const DocsTable = DocsTableComponent as {\n (props: DocsTableProps): JSX.Element | null;\n columns: DocsTableColumnFactories;\n actions: DocsTableActionFactories;\n};\n\nDocsTable.columns = columnFactories;\nDocsTable.actions = actionFactories;\n","/*\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 { useState, useEffect } from 'react';\n\nimport { Table, TableProps } from '@backstage/core-components';\nimport { useTranslationRef } from '@backstage/core-plugin-api/alpha';\nimport { techdocsTranslationRef } from '../../../translation';\nimport { DocsTableRow } from './types';\nimport {\n EntityTextFilter,\n useEntityList,\n} from '@backstage/plugin-catalog-react';\n\n/**\n * @internal\n */\nexport function OffsetPaginatedDocsTable(props: TableProps<DocsTableRow>) {\n const { actions, columns, data, isLoading, options, title } = props;\n const { updateFilters, setLimit, setOffset, limit, totalItems, offset } =\n useEntityList();\n const { t } = useTranslationRef(techdocsTranslationRef);\n const [page, setPage] = useState(\n offset && limit ? Math.floor(offset / limit) : 0,\n );\n\n useEffect(() => {\n if (totalItems && page * limit >= totalItems) {\n setOffset!(Math.max(0, totalItems - limit));\n } else {\n setOffset!(Math.max(0, page * limit));\n }\n }, [setOffset, page, limit, totalItems]);\n\n return (\n <Table<DocsTableRow>\n title={title}\n columns={columns}\n data={data}\n options={{\n paginationPosition: 'both',\n pageSizeOptions: [5, 10, 20, 50, 100],\n pageSize: limit,\n emptyRowsWhenPaging: false,\n actionsColumnIndex: -1,\n ...options,\n }}\n actions={actions}\n onSearchChange={(searchText: string) =>\n updateFilters({\n text: searchText ? new EntityTextFilter(searchText) : undefined,\n })\n }\n page={page}\n onPageChange={newPage => {\n setPage(newPage);\n }}\n onRowsPerPageChange={pageSize => {\n setLimit(pageSize);\n }}\n totalCount={totalItems}\n localization={{\n header: {\n actions: t('table.header.actions'),\n },\n toolbar: {\n searchPlaceholder: t('table.toolbar.searchPlaceholder'),\n },\n pagination: {\n labelDisplayedRows: '',\n labelRowsSelect: t('table.pagination.labelRowsSelect'),\n },\n body: {\n emptyDataSourceMessage: t('table.body.emptyDataSourceMessage'),\n },\n }}\n isLoading={isLoading}\n />\n );\n}\n","/*\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 { Table, TableProps } from '@backstage/core-components';\nimport { useTranslationRef } from '@backstage/core-plugin-api/alpha';\nimport { techdocsTranslationRef } from '../../../translation';\nimport { DocsTableRow } from './types';\n\ntype PaginatedDocsTableProps = {\n prev?(): void;\n next?(): void;\n} & TableProps<DocsTableRow>;\n\n/**\n * @internal\n */\n\nexport function CursorPaginatedDocsTable(props: PaginatedDocsTableProps) {\n const {\n actions,\n columns,\n data,\n next,\n prev,\n title,\n isLoading,\n options,\n ...restProps\n } = props;\n const { t } = useTranslationRef(techdocsTranslationRef);\n\n return (\n <Table\n title={isLoading ? '' : title}\n columns={columns}\n data={data}\n options={{\n paginationPosition: 'both',\n ...options,\n // These settings are configured to force server side pagination\n pageSizeOptions: [],\n showFirstLastPageButtons: false,\n pageSize: Number.MAX_SAFE_INTEGER,\n emptyRowsWhenPaging: false,\n actionsColumnIndex: -1,\n }}\n onPageChange={page => {\n if (page > 0) {\n next?.();\n } else {\n prev?.();\n }\n }}\n /* this will enable the prev button accordingly */\n page={prev ? 1 : 0}\n /* this will enable the next button accordingly */\n totalCount={next ? Number.MAX_VALUE : Number.MAX_SAFE_INTEGER}\n localization={{\n header: {\n actions: t('table.header.actions'),\n },\n toolbar: {\n searchPlaceholder: t('table.toolbar.searchPlaceholder'),\n },\n pagination: {\n labelDisplayedRows: '',\n labelRowsSelect: t('table.pagination.labelRowsSelect'),\n },\n body: {\n emptyDataSourceMessage: t('table.body.emptyDataSourceMessage'),\n },\n }}\n isLoading={isLoading}\n {...restProps}\n />\n );\n}\n","/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport useCopyToClipboard from 'react-use/esm/useCopyToClipboard';\nimport { capitalize } from 'lodash';\nimport {\n CodeSnippet,\n TableColumn,\n TableOptions,\n TableProps,\n WarningPanel,\n} from '@backstage/core-components';\nimport {\n configApiRef,\n useApi,\n useApiHolder,\n useRouteRef,\n} from '@backstage/core-plugin-api';\nimport { useTranslationRef } from '@backstage/core-plugin-api/alpha';\nimport {\n useEntityList,\n useStarredEntities,\n entityPresentationApiRef,\n} from '@backstage/plugin-catalog-react';\nimport { techdocsTranslationRef } from '../../../translation';\nimport { DocsTable } from './DocsTable';\nimport { OffsetPaginatedDocsTable } from './OffsetPaginatedDocsTable';\nimport { CursorPaginatedDocsTable } from './CursorPaginatedDocsTable';\nimport { actionFactories } from './actions';\nimport { columnFactories } from './columns';\nimport {\n DocsTableRow,\n DocsTableColumnFactories,\n DocsTableActionFactories,\n} from './types';\nimport { rootDocsRouteRef } from '../../../routes';\nimport { entitiesToDocsMapper } from './helpers';\n\n/**\n * Props for {@link EntityListDocsTable}.\n *\n * @public\n */\nexport type EntityListDocsTableProps = {\n columns?: TableColumn<DocsTableRow>[];\n actions?: TableProps<DocsTableRow>['actions'];\n options?: TableOptions<DocsTableRow>;\n};\n\n/**\n * Component which renders a table with entities from catalog.\n *\n * @public\n */\nconst EntityListDocsTableComponent = (\n props: EntityListDocsTableProps,\n): JSX.Element | null => {\n const { columns, actions, options } = props;\n const { loading, error, entities, filters, paginationMode, pageInfo } =\n useEntityList();\n const { isStarredEntity, toggleStarredEntity } = useStarredEntities();\n const [, copyToClipboard] = useCopyToClipboard();\n const getRouteToReaderPageFor = useRouteRef(rootDocsRouteRef);\n const config = useApi(configApiRef);\n const apiHolder = useApiHolder();\n const { t } = useTranslationRef(techdocsTranslationRef);\n\n const title = capitalize(filters.user?.value ?? 'all');\n\n const defaultActions = [\n actionFactories.createCopyDocsUrlAction(copyToClipboard, t),\n actionFactories.createStarEntityAction(\n isStarredEntity,\n toggleStarredEntity,\n t,\n ),\n ];\n\n const documents = entitiesToDocsMapper(\n entities,\n getRouteToReaderPageFor,\n config,\n apiHolder.get(entityPresentationApiRef),\n );\n\n const tableColumns = columns || [\n columnFactories.createTitleColumn({\n hidden: true,\n entityPresentationApi: apiHolder.get(entityPresentationApiRef),\n }),\n columnFactories.createNameColumn({\n entityPresentationApi: apiHolder.get(entityPresentationApiRef),\n }),\n columnFactories.createOwnerColumn(),\n columnFactories.createKindColumn(),\n columnFactories.createTypeColumn(),\n ];\n\n if (paginationMode === 'cursor') {\n return (\n <CursorPaginatedDocsTable\n columns={tableColumns}\n isLoading={loading}\n title={title}\n actions={actions || defaultActions}\n options={options}\n data={documents}\n next={pageInfo?.next}\n prev={pageInfo?.prev}\n />\n );\n } else if (paginationMode === 'offset') {\n return (\n <OffsetPaginatedDocsTable\n columns={tableColumns}\n isLoading={loading}\n title={title}\n actions={actions || defaultActions}\n options={options}\n data={documents}\n />\n );\n }\n\n if (error) {\n return (\n <WarningPanel severity=\"error\" title={t('error.couldNotLoad')}>\n <CodeSnippet language=\"text\" text={error.toString()} />\n </WarningPanel>\n );\n }\n\n return (\n <DocsTable\n title={title}\n entities={entities}\n loading={loading}\n actions={actions || defaultActions}\n columns={tableColumns}\n options={options}\n />\n );\n};\n\n/**\n * @public\n */\nexport const EntityListDocsTable = EntityListDocsTableComponent as {\n (props: EntityListDocsTableProps): JSX.Element | null;\n columns: DocsTableColumnFactories;\n actions: DocsTableActionFactories;\n};\n\nEntityListDocsTable.columns = columnFactories;\nEntityListDocsTable.actions = actionFactories;\n","/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport ShareIcon from '@material-ui/icons/Share';\nimport { DocsTableRow } from './types';\nimport { FavoriteToggleIcon } from '@backstage/core-components';\nimport type { TranslationFunction } from '@backstage/core-plugin-api/alpha';\nimport type { techdocsTranslationRef } from '../../../translation';\n\ntype InternalTranslationFunctionType = TranslationFunction<\n typeof techdocsTranslationRef extends { T: infer T } ? T : never\n>;\n\n/**\n * Not directly exported, but through DocsTable.actions and EntityListDocsTable.actions\n *\n * @public\n */\nexport const actionFactories = {\n createCopyDocsUrlAction(\n copyToClipboard: Function,\n t?: InternalTranslationFunctionType,\n ) {\n return (row: DocsTableRow) => {\n return {\n icon: () => <ShareIcon fontSize=\"small\" />,\n tooltip:\n t?.('table.actions.copyDocsUrl', {}) ??\n 'Click to copy documentation link to clipboard',\n onClick: () =>\n copyToClipboard(`${window.location.origin}${row.resolved.docsUrl}`),\n };\n };\n },\n createStarEntityAction(\n isStarredEntity: Function,\n toggleStarredEntity: Function,\n t?: InternalTranslationFunctionType,\n ) {\n return (row: DocsTableRow) => {\n const entity = row.entity;\n const isStarred = isStarredEntity(entity);\n const tooltip = isStarred\n ? t?.('table.actions.removeFromFavorites', {}) ??\n 'Remove from favorites'\n : t?.('table.actions.addToFavorites', {}) ?? 'Add to favorites';\n return {\n cellStyle: { paddingLeft: '1em' },\n icon: () => <FavoriteToggleIcon isFavorite={isStarred} />,\n tooltip,\n onClick: () => toggleStarredEntity(entity),\n };\n };\n },\n};\n","/*\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 Box from '@material-ui/core/Box';\nimport { makeStyles } from '@material-ui/core/styles';\nimport { ReactNode } from 'react';\n\nexport type SubvalueCellClassKey = 'value' | 'subvalue';\n\nconst useSubvalueCellStyles = makeStyles(\n theme => ({\n value: {\n marginBottom: theme.spacing(0.75),\n },\n subvalue: {\n color: theme.palette.textSubtle,\n fontWeight: 'normal',\n },\n }),\n { name: 'BackstageSubvalueCell' },\n);\n\ntype SubvalueCellProps = {\n value: ReactNode;\n subvalue: ReactNode;\n};\n\nexport function SubvalueCell(props: SubvalueCellProps) {\n const { value, subvalue } = props;\n const classes = useSubvalueCellStyles();\n\n return (\n <>\n <Box className={classes.value}>{value}</Box>\n <Box className={classes.subvalue}>{subvalue}</Box>\n </>\n );\n}\n","/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n Link,\n SubvalueCell,\n type TableColumn,\n} from '@backstage/core-components';\nimport {\n EntityDisplayName,\n type EntityPresentationApi,\n entityPresentationSnapshot,\n EntityRefLinks,\n} from '@backstage/plugin-catalog-react';\nimport { Entity } from '@backstage/catalog-model';\nimport { useTranslationRef } from '@backstage/core-plugin-api/alpha';\nimport { techdocsTranslationRef } from '../../../translation';\nimport { DocsTableRow } from './types';\n\nfunction customTitle(\n entity: Entity,\n presentationApi?: EntityPresentationApi,\n): string {\n return entityPresentationSnapshot(entity, undefined, presentationApi)\n .primaryTitle;\n}\n\n/**\n * Component for translating table column titles\n * @alpha\n */\nconst TableColumnTitle = ({\n translationKey,\n}: {\n translationKey: 'document' | 'owner' | 'kind' | 'type';\n}) => {\n const { t } = useTranslationRef(techdocsTranslationRef);\n return <>{t(`table.columns.${translationKey}`)}</>;\n};\n\n/**\n * Not directly exported, but through DocsTable.columns and EntityListDocsTable.columns\n *\n * @public\n */\nexport const columnFactories = {\n createTitleColumn(options?: {\n hidden?: boolean;\n entityPresentationApi?: EntityPresentationApi;\n }): TableColumn<DocsTableRow> {\n const nameCol = columnFactories.createNameColumn({\n entityPresentationApi: options?.entityPresentationApi,\n });\n return {\n ...nameCol,\n field: 'entity.metadata.title',\n hidden: options?.hidden,\n };\n },\n\n createNameColumn(options?: {\n entityPresentationApi?: EntityPresentationApi;\n }): TableColumn<DocsTableRow> {\n const presentationApi = options?.entityPresentationApi;\n return {\n title: <TableColumnTitle translationKey=\"document\" />,\n field: 'entity.metadata.name',\n highlight: true,\n searchable: true,\n defaultSort: 'asc',\n customSort: (row1, row2) => {\n const title1 = customTitle(row1.entity, presentationApi).toLowerCase();\n const title2 = customTitle(row2.entity, presentationApi).toLowerCase();\n return title1.localeCompare(title2);\n },\n customFilterAndSearch: (filter, row) =>\n customTitle(row.entity, presentationApi)\n .toLowerCase()\n .includes(filter.toLowerCase()),\n render: (row: DocsTableRow) => (\n <SubvalueCell\n value={\n <Link to={row.resolved.docsUrl}>\n {presentationApi ? (\n <EntityDisplayName entityRef={row.entity} />\n ) : (\n customTitle(row.entity)\n )}\n </Link>\n }\n subvalue={row.entity.metadata.description}\n />\n ),\n };\n },\n createOwnerColumn(): TableColumn<DocsTableRow> {\n return {\n title: <TableColumnTitle translationKey=\"owner\" />,\n field: 'resolved.ownedByRelationsTitle',\n render: ({ resolved }) => (\n <EntityRefLinks\n entityRefs={resolved.ownedByRelations}\n defaultKind=\"group\"\n />\n ),\n };\n },\n createKindColumn(): TableColumn<DocsTableRow> {\n return {\n title: <TableColumnTitle translationKey=\"kind\" />,\n field: 'entity.kind',\n };\n },\n createTypeColumn(): TableColumn<DocsTableRow> {\n return {\n title: <TableColumnTitle translationKey=\"type\" />,\n field: 'entity.spec.type',\n };\n },\n};\n\nexport const defaultColumns: TableColumn<DocsTableRow>[] = [\n columnFactories.createTitleColumn({ hidden: true }),\n columnFactories.createNameColumn(),\n columnFactories.createOwnerColumn(),\n columnFactories.createKindColumn(),\n columnFactories.createTypeColumn(),\n];\n","/*\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 { RELATION_OWNED_BY, Entity } from '@backstage/catalog-model';\nimport {\n entityPresentationSnapshot,\n getEntityRelations,\n type EntityPresentationApi,\n} from '@backstage/plugin-catalog-react';\nimport { toLowerMaybe } from '../../../helpers';\nimport { ConfigApi, RouteFunc } from '@backstage/core-plugin-api';\n\ntype getRouteFunc = RouteFunc<{\n namespace: string;\n kind: string;\n name: string;\n}>;\n\nexport function entitiesToDocsMapper(\n entities: Entity[],\n getRouteToReaderPageFor: getRouteFunc,\n config: ConfigApi,\n entityPresentationApi?: EntityPresentationApi,\n) {\n return entities.map(entity => {\n const ownedByRelations = getEntityRelations(entity, RELATION_OWNED_BY);\n return {\n entity,\n resolved: {\n docsUrl: getRouteToReaderPageFor({\n namespace: toLowerMaybe(\n entity.metadata.namespace ?? 'default',\n config,\n ),\n kind: toLowerMaybe(entity.kind, config),\n name: toLowerMaybe(entity.metadata.name, config),\n }),\n ownedByRelations,\n ownedByRelationsTitle: ownedByRelations\n .map(\n r =>\n entityPresentationSnapshot(\n r,\n { defaultKind: 'group' },\n entityPresentationApi,\n ).primaryTitle,\n )\n .join(', '),\n },\n };\n });\n}\n","/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { useEffect } from 'react';\nimport {\n CATALOG_FILTER_EXISTS,\n DefaultEntityFilters,\n EntityFilter,\n useEntityList,\n} from '@backstage/plugin-catalog-react';\nimport { TECHDOCS_ANNOTATION } from '@backstage/plugin-techdocs-common';\n\nclass TechDocsFilter implements EntityFilter {\n getCatalogFilters(): Record<string, string | symbol | (string | symbol)[]> {\n return {\n [`metadata.annotations.${TECHDOCS_ANNOTATION}`]: CATALOG_FILTER_EXISTS,\n };\n }\n}\n\ntype CustomFilters = DefaultEntityFilters & {\n techdocs?: TechDocsFilter;\n};\n\n/**\n * Component responsible for updating TechDocs filters\n *\n * @public\n */\nexport const TechDocsPicker = () => {\n const { updateFilters } = useEntityList<CustomFilters>();\n\n useEffect(() => {\n updateFilters({\n techdocs: new TechDocsFilter(),\n });\n }, [updateFilters]);\n\n return null;\n};\n"],"names":["instance","b","options","isJsonObject","value","Array","isJsonObjectDeep","seen","Set","Object","v","isJsonValueDeep","result","validateMetaSchema","schema","InputError","ajv","Ajv","ajvErrors","error","message","jsonObjectSchema","z","x","jsonSchemaSchema","ctx","isError","opDeclareAnnotationV1Schema","opDeclareKindV1Schema","fullKindSchema","reduceKindSchema","parsed","allOf","rest","type","allProperties","kindRest","apiVersion","kind","properties","FORBIDDEN_SCHEMA_ROOT_FIELDS","FORBIDDEN_SCHEMA_STRUCTURAL_FIELDS","relationFieldSchema","opDeclareKindVersionV1Schema","opsFromCatalogModelAddKindVersion","definition","ops","version","jsonSchema","name","validateKindRootSchemaSemantics","undefined","field","rootProperties","fieldName","fieldSchema","specType","input","opDeclareLabelV1Schema","opDeclareRelationV1Schema","createDeclareRelationOp","opRemoveAnnotationV1Schema","opRemoveKindV1Schema","opRemoveLabelV1Schema","opRemoveTagV1Schema","opDeclareTagV1Schema","opUpdateAnnotationV1Schema","opUpdateKindV1Schema","opUpdateKindVersionV1Schema","opUpdateLabelV1Schema","opUpdateRelationV1Schema","createUpdateRelationOp","opUpdateTagV1Schema","OpaqueCatalogModelLayer","OpaqueType","DefaultCatalogModelLayerBuilder","opsFromCatalogModelUpdateKind","relation","opsFromCatalogModelRelationPair","relationPair","firstKind","secondKind","opsFromCatalogModelUpdateRelationPair","annotation","opsFromCatalogModelAnnotation","opsFromCatalogModelUpdateAnnotation","label","opsFromCatalogModelLabel","opsFromCatalogModelUpdateLabel","tag","layer","internal","RELATION_OWNED_BY","RELATION_DEPENDS_ON","RELATION_PART_OF","RELATION_HAS_PART","model","useStyles","makeStyles","EmptyStateImage","missing","classes","missingAnnotation","noInformation","createComponent","noBuild","theme","EmptyState","props","title","description","action","Grid","Typography","FavoriteToggleIcon","isFavorite","StarIcon","UnstarredIcon","FavoriteToggle","id","onChange","iconButtonProps","Tooltip","IconButton","LinkWrapper","forwardRef","ref","UnstyledLink","LinkButton","MaterialButton","createStyles","SvgIcon","BootstrapInput","withStyles","InputBase","SelectComponent","multiple","items","placeholder","selected","triggerReset","native","disabled","margin","dataTestId","setValue","useState","isOpen","setOpen","useEffect","Box","FormControl","InputLabel","Select","event","previous","HTMLElement","s","selectedValue","item","el","Chip","CancelIcon","newValue","chip","OpenedDropdown","ClosedDropdown","MenuItem","Checkbox","useFilterStyles","Filters","onChangeFilters","t","useTranslationRef","coreComponentsTranslationRef","selectedFilters","setSelectedFilters","reset","Button","filter","TableLoadingBody","CircularProgress","tableIcons","AddBox","Check","Clear","DeleteOutline","ChevronRight","Edit","SaveAlt","FilterList","FirstPage","LastPage","ChevronLeft","Search","ArrowUpward","Remove","ViewColumn","extractValueByField","data","path","i","StyledMTableHeader","MTableHeader","StyledMTableToolbar","MTableToolbar","useTableStyles","defaultInitialState","TableToolbar","toolbarProps","toolbarRef","setSearch","hasFilters","selectedFiltersLength","toggleFilters","filtersClasses","onSearchChanged","useCallback","searchText","Table","filterConfig","dataValue","columns","emptyContent","subtitle","localization","filters","initialState","onStateChange","components","loading","style","restProps","tableClasses","useTheme","calculatedInitialState","filtersOpen","setFiltersOpen","search","state","transform","key","isEqual","defaultState","getFieldByTitle","titleValue","tableData","useMemo","selectedFiltersArray","filterValue","fieldValue","Toolbar","hasNoRows","columnCount","Body","makeBody","bodyProps","MTableBody","distinctValues","addValue","c","MTable","column","headerStyle","cellStyle","cellStyleFn","rowData","rowColumn","ContainerDefinition","defineComponent","styles","Container","ownProps","utilityStyle","useDefinition","children","entityPresentationSnapshot","entityOrRef","context","entityPresentationApi","stringifyEntityRef","defaultEntityPresentation","BootstrapAutocomplete","Autocomplete","PopperComponent","Popper","TransitionProps","Grow","PaperComponent","Paper","CatalogAutocomplete","LabelProps","TextFieldProps","renderInput","params","TextField","merge","autocomplete","ExpandMoreIcon","classNames","CatalogFilterLayout","isScreenSmallerThanBreakpoint","useMediaQuery","filterDrawerOpen","setFilterDrawerOpen","catalogReactTranslationRef","FilterListIcon","Drawer","icon","CheckBoxOutlineBlankIcon","checkedIcon","CheckBoxIcon","OptionCheckbox","EntityAutocompletePickerOption","memo","availableOptions","showCounts","FormControlLabel","EntityAutocompletePicker","Filter","InputProps","initialSelectedOptions","filtersForAvailableValues","hidden","getOptionLabel","renderOption","updateFilters","queryParameter","useEntityList","catalogApi","useApi","catalogApiRef","availableValuesFilters","f","availableValues","useAsync","facets","reduceBackendCatalogFilters","Boolean","count","queryParameters","filteredOptions","selectedOptions","setSelectedOptions","shouldAddFilter","newSelectedOptions","String","_event","option","renderRow","index","cloneElement","OuterElementContext","createContext","OuterElementType","rrOnScroll","outerOnScroll","outerProps","useContext","e","VirtualizedListbox","other","itemData","Children","itemCount","itemsToShow","Math","FixedSizeList","FixedWidthFormControlLabel","_theme","RenderOptionLabel","isGroup","useEntityPresentation","GroupIcon","PersonIcon","EntityOwnerPicker","mode","apis","useApiHolder","entityPresentationApiRef","ownersParameter","text","setText","queryParamOwners","selectedOwners","setSelectedOwners","EntityOwnerFilter","handleFetch","cache","useFetchEntities","initialSelectedOwnersRefs","isOwnersOnlyMode","queryEntitiesResponse","useAsyncFn","request","limit","cursorRequest","response","initialRequest","facetsEntitiesResponse","useFacetsEntities","enabled","facetsPromise","facet","namespace","parseEntityRef","a","start","isFacetsResponse","JSON","atob","filteredRefs","entity","normalizedText","end","encodeCursor","entities","payload","btoa","useSelectedOwners","allEntities","useRef","initialSelectedEntities","useMountEffect","entityRef","useDebouncedEffect","availableOwners","o","_","owners","_e","inputValue","element","hasReachedEnd","EntityRefLinks","entityRefs","hideIcons","linkProps","r","entityRefString","Fragment","EntityRefLink","EntityTagPicker","EntityTagFilter","UserListPicker","initialFilter","availableFilters","alwaysKeepFilters","configApi","configApiRef","orgName","userParameter","kindParameter","userAndGroupFilterIds","filterGroups","getFilterGroups","SettingsIcon","filterGroup","ownedEntitiesCount","loadingOwnedEntities","ownedEntitiesFilter","useOwnedEntitiesCount","identityApi","identityApiRef","ownershipEntityRefs","loadingEntityRefs","user","allFilters","orderFields","catalogFilters","reduceCatalogFilters","compact","loadingEntityOwnership","fetchEntities","req","ownedClaims","getOwnedCountClaims","ownersRefs","commonOwnedBy","intersection","metadata","totalItems","useDeepCompareEffect","EntityUserFilter","allCount","useAllEntitiesCount","prevRequest","compacted","newRequest","starredEntitiesCount","starredEntitiesFilter","loadingStarredEntities","useStarredEntitiesCount","starredEntities","useStarredEntities","queryParamUserFilter","selectedUserFilter","setSelectedUserFilter","filterCounts","Card","group","List","ListItemIcon","ListItemText","ListItemSecondaryAction","EntityKindFilter","EntityTypeFilter","values","EntityTextFilter","words","exactMatch","targets","partialMatch","word","m","fullRefs","err","getEntityRelations","EntityLifecycleFilter","EntityNamespaceFilter","refs","starredEntityRefs","relations","UserListFilter","isOwnedEntity","isStarredEntity","EntityOrphanFilter","orphan","EntityErrorFilter","NewEntityListContext","createVersionedContext","OldEntityListContext","EntityListProvider","isMounted","useMountedState","requestedFilters","setRequestedFilters","location","useLocation","paginationMode","paginationLimit","initialCursor","initialOffset","initialLimit","qs","queryLimit","Number","isNaN","offset","cursor","setCursor","setOffset","setLimit","backendState","setBackendState","setLoading","setError","refreshToken","setRefreshToken","lastFetchParamsRef","fetchGenRef","adjustedFilters","kindValue","refresh","fetchParams","doFetch","backendFilter","gen","useDebounce","totalItemsLoading","refreshCount","entityFilter","reduceEntityFilters","queryParams","oldParams","newParams","newUrl","window","document","update","prevFilters","newFilters","triggerRefresh","pageInfo","prevCursor","nextCursor","createVersionedValueMap","versionedHolder","useVersionedContext","oldContext","Error","getEntityRef","starredEntitiesApi","starredEntitiesApiRef","useObservable","toggleStarredEntity","isEntityTextFilter","isEntityOrderFilter","condensedFilters","compoundFilter","fullTextFilter","backendCatalogFilters","relationType","entityNames","TechDocsIndexPageContent","actions","ownerPickerMode","pagination","TechDocsPicker","EntityListDocsTable","toLowerMaybe","str","config","DocsTable","copyToClipboard","useCopyToClipboard","getRouteToReaderPageFor","useRouteRef","rootDocsRouteRef","apiHolder","techdocsTranslationRef","documents","entitiesToDocsMapper","tableColumns","columnFactories","defaultActions","actionFactories","paging","pageSize","OffsetPaginatedDocsTable","isLoading","page","setPage","newPage","CursorPaginatedDocsTable","next","prev","capitalize","WarningPanel","CodeSnippet","row","ShareIcon","isStarred","tooltip","useSubvalueCellStyles","SubvalueCell","subvalue","customTitle","presentationApi","TableColumnTitle","translationKey","row1","row2","title1","title2","Link","EntityDisplayName","resolved","ownedByRelations","TechDocsFilter","TECHDOCS_ANNOTATION","CATALOG_FILTER_EXISTS"],"mappings":"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"}
|