@backstage/plugin-catalog 1.20.0 → 1.20.1-next.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/alpha/package.json +1 -1
  3. package/dist/alpha/createCatalogFilterExtension.esm.js +1 -2
  4. package/dist/alpha/createCatalogFilterExtension.esm.js.map +1 -1
  5. package/dist/alpha/filter/matrchers/createHasMatcher.esm.js +2 -4
  6. package/dist/alpha/filter/matrchers/createHasMatcher.esm.js.map +1 -1
  7. package/dist/alpha/filter/matrchers/createIsMatcher.esm.js +1 -4
  8. package/dist/alpha/filter/matrchers/createIsMatcher.esm.js.map +1 -1
  9. package/dist/alpha/filter/matrchers/createTypeMatcher.esm.js +1 -2
  10. package/dist/alpha/filter/matrchers/createTypeMatcher.esm.js.map +1 -1
  11. package/dist/apis/EntityPresentationApi/DefaultEntityPresentationApi.esm.js +100 -137
  12. package/dist/apis/EntityPresentationApi/DefaultEntityPresentationApi.esm.js.map +1 -1
  13. package/dist/apis/StarredEntitiesApi/DefaultStarredEntitiesApi.esm.js +12 -20
  14. package/dist/apis/StarredEntitiesApi/DefaultStarredEntitiesApi.esm.js.map +1 -1
  15. package/dist/apis/StarredEntitiesApi/migration.esm.js +1 -2
  16. package/dist/apis/StarredEntitiesApi/migration.esm.js.map +1 -1
  17. package/dist/components/AboutCard/AboutCard.esm.js +10 -11
  18. package/dist/components/AboutCard/AboutCard.esm.js.map +1 -1
  19. package/dist/components/AboutCard/AboutContent.esm.js +15 -19
  20. package/dist/components/AboutCard/AboutContent.esm.js.map +1 -1
  21. package/dist/components/AboutCard/hooks.esm.js +1 -2
  22. package/dist/components/AboutCard/hooks.esm.js.map +1 -1
  23. package/dist/components/CatalogKindHeader/CatalogKindHeader.esm.js +3 -5
  24. package/dist/components/CatalogKindHeader/CatalogKindHeader.esm.js.map +1 -1
  25. package/dist/components/CatalogKindHeader/kindFilterUtils.esm.js +2 -5
  26. package/dist/components/CatalogKindHeader/kindFilterUtils.esm.js.map +1 -1
  27. package/dist/components/CatalogPage/DefaultCatalogPage.esm.js +2 -3
  28. package/dist/components/CatalogPage/DefaultCatalogPage.esm.js.map +1 -1
  29. package/dist/components/CatalogSearchResultListItem/CatalogSearchResultListItem.esm.js +2 -2
  30. package/dist/components/CatalogSearchResultListItem/CatalogSearchResultListItem.esm.js.map +1 -1
  31. package/dist/components/CatalogTable/CatalogTable.esm.js +5 -8
  32. package/dist/components/CatalogTable/CatalogTable.esm.js.map +1 -1
  33. package/dist/components/CatalogTable/PaginatedCatalogTable.esm.js +2 -2
  34. package/dist/components/CatalogTable/PaginatedCatalogTable.esm.js.map +1 -1
  35. package/dist/components/CatalogTable/columns.esm.js +19 -26
  36. package/dist/components/CatalogTable/columns.esm.js.map +1 -1
  37. package/dist/components/CatalogTable/defaultCatalogTableColumnsFunc.esm.js +2 -4
  38. package/dist/components/CatalogTable/defaultCatalogTableColumnsFunc.esm.js.map +1 -1
  39. package/dist/components/EntityContextMenu/UnregisterEntity.esm.js +3 -4
  40. package/dist/components/EntityContextMenu/UnregisterEntity.esm.js.map +1 -1
  41. package/dist/components/EntityLabelsCard/EntityLabelsCard.esm.js +1 -2
  42. package/dist/components/EntityLabelsCard/EntityLabelsCard.esm.js.map +1 -1
  43. package/dist/components/EntityLabelsCard/conditions.esm.js +1 -2
  44. package/dist/components/EntityLabelsCard/conditions.esm.js.map +1 -1
  45. package/dist/components/EntityLayout/EntityLayout.esm.js +6 -9
  46. package/dist/components/EntityLayout/EntityLayout.esm.js.map +1 -1
  47. package/dist/components/EntityLinksCard/EntityLinksCard.esm.js +3 -7
  48. package/dist/components/EntityLinksCard/EntityLinksCard.esm.js.map +1 -1
  49. package/dist/components/EntityLinksCard/LinksGridList.esm.js +1 -1
  50. package/dist/components/EntityLinksCard/LinksGridList.esm.js.map +1 -1
  51. package/dist/components/EntityLinksCard/useDynamicColumns.esm.js +2 -3
  52. package/dist/components/EntityLinksCard/useDynamicColumns.esm.js.map +1 -1
  53. package/dist/components/EntityOrphanWarning/EntityOrphanWarning.esm.js +1 -2
  54. package/dist/components/EntityOrphanWarning/EntityOrphanWarning.esm.js.map +1 -1
  55. package/dist/components/EntityProcessingErrorsPanel/EntityProcessingErrorsPanel.esm.js +1 -2
  56. package/dist/components/EntityProcessingErrorsPanel/EntityProcessingErrorsPanel.esm.js.map +1 -1
  57. package/dist/components/EntityRelationWarning/EntityRelationWarning.esm.js +2 -3
  58. package/dist/components/EntityRelationWarning/EntityRelationWarning.esm.js.map +1 -1
  59. package/dist/components/EntitySwitch/EntitySwitch.esm.js +4 -7
  60. package/dist/components/EntitySwitch/EntitySwitch.esm.js.map +1 -1
  61. package/dist/components/EntitySwitch/conditions.esm.js +3 -7
  62. package/dist/components/EntitySwitch/conditions.esm.js.map +1 -1
  63. package/package.json +9 -9
package/CHANGELOG.md CHANGED
@@ -1,5 +1,26 @@
1
1
  # @backstage/plugin-catalog
2
2
 
3
+ ## 1.20.1-next.0
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies
8
+ - @backstage/core-components@0.14.8-next.0
9
+ - @backstage/plugin-search-react@1.7.12-next.0
10
+ - @backstage/catalog-client@1.6.5
11
+ - @backstage/catalog-model@1.5.0
12
+ - @backstage/core-compat-api@0.2.6-next.0
13
+ - @backstage/core-plugin-api@1.9.2
14
+ - @backstage/errors@1.2.4
15
+ - @backstage/frontend-plugin-api@0.6.6-next.0
16
+ - @backstage/integration-react@1.1.27
17
+ - @backstage/types@1.1.1
18
+ - @backstage/plugin-catalog-common@1.0.23
19
+ - @backstage/plugin-catalog-react@1.12.1-next.0
20
+ - @backstage/plugin-permission-react@0.4.22
21
+ - @backstage/plugin-scaffolder-common@1.5.2
22
+ - @backstage/plugin-search-common@1.2.11
23
+
3
24
  ## 1.20.0
4
25
 
5
26
  ### Minor Changes
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@backstage/plugin-catalog",
3
- "version": "1.20.0",
3
+ "version": "1.20.1-next.0",
4
4
  "main": "../dist/alpha.esm.js",
5
5
  "module": "../dist/alpha.esm.js",
6
6
  "types": "../dist/alpha.d.ts"
@@ -2,13 +2,12 @@ import React, { lazy } from 'react';
2
2
  import { createExtension, coreExtensionData, ExtensionBoundary } from '@backstage/frontend-plugin-api';
3
3
 
4
4
  function createCatalogFilterExtension(options) {
5
- var _a;
6
5
  return createExtension({
7
6
  kind: "catalog-filter",
8
7
  namespace: options.namespace,
9
8
  name: options.name,
10
9
  attachTo: { id: "page:catalog", input: "filters" },
11
- inputs: (_a = options.inputs) != null ? _a : {},
10
+ inputs: options.inputs ?? {},
12
11
  configSchema: options.configSchema,
13
12
  output: {
14
13
  element: coreExtensionData.reactElement
@@ -1 +1 @@
1
- {"version":3,"file":"createCatalogFilterExtension.esm.js","sources":["../../src/alpha/createCatalogFilterExtension.tsx"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React, { lazy } from 'react';\nimport {\n AnyExtensionInputMap,\n ExtensionBoundary,\n PortableSchema,\n coreExtensionData,\n createExtension,\n} from '@backstage/frontend-plugin-api';\n\n/** @alpha */\nexport function createCatalogFilterExtension<\n TInputs extends AnyExtensionInputMap,\n TConfig = never,\n>(options: {\n namespace?: string;\n name?: string;\n inputs?: TInputs;\n configSchema?: PortableSchema<TConfig>;\n loader: (options: { config: TConfig }) => Promise<JSX.Element>;\n}) {\n return createExtension({\n kind: 'catalog-filter',\n namespace: options.namespace,\n name: options.name,\n attachTo: { id: 'page:catalog', input: 'filters' },\n inputs: options.inputs ?? {},\n configSchema: options.configSchema,\n output: {\n element: coreExtensionData.reactElement,\n },\n factory({ config, node }) {\n const ExtensionComponent = lazy(() =>\n options\n .loader({ config })\n .then(element => ({ default: () => element })),\n );\n\n return {\n element: (\n <ExtensionBoundary node={node}>\n <ExtensionComponent />\n </ExtensionBoundary>\n ),\n };\n },\n });\n}\n"],"names":[],"mappings":";;;AA0BO,SAAS,6BAGd,OAMC,EAAA;AAnCH,EAAA,IAAA,EAAA,CAAA;AAoCE,EAAA,OAAO,eAAgB,CAAA;AAAA,IACrB,IAAM,EAAA,gBAAA;AAAA,IACN,WAAW,OAAQ,CAAA,SAAA;AAAA,IACnB,MAAM,OAAQ,CAAA,IAAA;AAAA,IACd,QAAU,EAAA,EAAE,EAAI,EAAA,cAAA,EAAgB,OAAO,SAAU,EAAA;AAAA,IACjD,MAAQ,EAAA,CAAA,EAAA,GAAA,OAAA,CAAQ,MAAR,KAAA,IAAA,GAAA,EAAA,GAAkB,EAAC;AAAA,IAC3B,cAAc,OAAQ,CAAA,YAAA;AAAA,IACtB,MAAQ,EAAA;AAAA,MACN,SAAS,iBAAkB,CAAA,YAAA;AAAA,KAC7B;AAAA,IACA,OAAQ,CAAA,EAAE,MAAQ,EAAA,IAAA,EAAQ,EAAA;AACxB,MAAA,MAAM,kBAAqB,GAAA,IAAA;AAAA,QAAK,MAC9B,OAAA,CACG,MAAO,CAAA,EAAE,MAAO,EAAC,CACjB,CAAA,IAAA,CAAK,CAAY,OAAA,MAAA,EAAE,OAAS,EAAA,MAAM,SAAU,CAAA,CAAA;AAAA,OACjD,CAAA;AAEA,MAAO,OAAA;AAAA,QACL,yBACG,KAAA,CAAA,aAAA,CAAA,iBAAA,EAAA,EAAkB,IACjB,EAAA,kBAAA,KAAA,CAAA,aAAA,CAAC,wBAAmB,CACtB,CAAA;AAAA,OAEJ,CAAA;AAAA,KACF;AAAA,GACD,CAAA,CAAA;AACH;;;;"}
1
+ {"version":3,"file":"createCatalogFilterExtension.esm.js","sources":["../../src/alpha/createCatalogFilterExtension.tsx"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React, { lazy } from 'react';\nimport {\n AnyExtensionInputMap,\n ExtensionBoundary,\n PortableSchema,\n coreExtensionData,\n createExtension,\n} from '@backstage/frontend-plugin-api';\n\n/** @alpha */\nexport function createCatalogFilterExtension<\n TInputs extends AnyExtensionInputMap,\n TConfig = never,\n>(options: {\n namespace?: string;\n name?: string;\n inputs?: TInputs;\n configSchema?: PortableSchema<TConfig>;\n loader: (options: { config: TConfig }) => Promise<JSX.Element>;\n}) {\n return createExtension({\n kind: 'catalog-filter',\n namespace: options.namespace,\n name: options.name,\n attachTo: { id: 'page:catalog', input: 'filters' },\n inputs: options.inputs ?? {},\n configSchema: options.configSchema,\n output: {\n element: coreExtensionData.reactElement,\n },\n factory({ config, node }) {\n const ExtensionComponent = lazy(() =>\n options\n .loader({ config })\n .then(element => ({ default: () => element })),\n );\n\n return {\n element: (\n <ExtensionBoundary node={node}>\n <ExtensionComponent />\n </ExtensionBoundary>\n ),\n };\n },\n });\n}\n"],"names":[],"mappings":";;;AA0BO,SAAS,6BAGd,OAMC,EAAA;AACD,EAAA,OAAO,eAAgB,CAAA;AAAA,IACrB,IAAM,EAAA,gBAAA;AAAA,IACN,WAAW,OAAQ,CAAA,SAAA;AAAA,IACnB,MAAM,OAAQ,CAAA,IAAA;AAAA,IACd,QAAU,EAAA,EAAE,EAAI,EAAA,cAAA,EAAgB,OAAO,SAAU,EAAA;AAAA,IACjD,MAAA,EAAQ,OAAQ,CAAA,MAAA,IAAU,EAAC;AAAA,IAC3B,cAAc,OAAQ,CAAA,YAAA;AAAA,IACtB,MAAQ,EAAA;AAAA,MACN,SAAS,iBAAkB,CAAA,YAAA;AAAA,KAC7B;AAAA,IACA,OAAQ,CAAA,EAAE,MAAQ,EAAA,IAAA,EAAQ,EAAA;AACxB,MAAA,MAAM,kBAAqB,GAAA,IAAA;AAAA,QAAK,MAC9B,OAAA,CACG,MAAO,CAAA,EAAE,MAAO,EAAC,CACjB,CAAA,IAAA,CAAK,CAAY,OAAA,MAAA,EAAE,OAAS,EAAA,MAAM,SAAU,CAAA,CAAA;AAAA,OACjD,CAAA;AAEA,MAAO,OAAA;AAAA,QACL,yBACG,KAAA,CAAA,aAAA,CAAA,iBAAA,EAAA,EAAkB,IACjB,EAAA,kBAAA,KAAA,CAAA,aAAA,CAAC,wBAAmB,CACtB,CAAA;AAAA,OAEJ,CAAA;AAAA,KACF;AAAA,GACD,CAAA,CAAA;AACH;;;;"}
@@ -2,12 +2,10 @@ import { InputError } from '@backstage/errors';
2
2
 
3
3
  const allowedMatchers = {
4
4
  labels: (entity) => {
5
- var _a;
6
- return Object.keys((_a = entity.metadata.labels) != null ? _a : {}).length > 0;
5
+ return Object.keys(entity.metadata.labels ?? {}).length > 0;
7
6
  },
8
7
  links: (entity) => {
9
- var _a;
10
- return ((_a = entity.metadata.links) != null ? _a : []).length > 0;
8
+ return (entity.metadata.links ?? []).length > 0;
11
9
  }
12
10
  };
13
11
  function createHasMatcher(parameters, onParseError) {
@@ -1 +1 @@
1
- {"version":3,"file":"createHasMatcher.esm.js","sources":["../../../../src/alpha/filter/matrchers/createHasMatcher.ts"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { InputError } from '@backstage/errors';\nimport { EntityMatcherFn } from './types';\n\nconst allowedMatchers: Record<string, EntityMatcherFn> = {\n labels: entity => {\n return Object.keys(entity.metadata.labels ?? {}).length > 0;\n },\n links: entity => {\n return (entity.metadata.links ?? []).length > 0;\n },\n};\n\n/**\n * Matches on the non-empty presence of different parts of the entity\n */\nexport function createHasMatcher(\n parameters: string[],\n onParseError: (error: Error) => void,\n): EntityMatcherFn {\n const matchers = parameters.flatMap(parameter => {\n const matcher = allowedMatchers[parameter.toLocaleLowerCase('en-US')];\n if (!matcher) {\n const known = Object.keys(allowedMatchers).map(m => `'${m}'`);\n onParseError(\n new InputError(\n `'${parameter}' is not a valid parameter for 'has' filter expressions, expected one of ${known}`,\n ),\n );\n return [];\n }\n return [matcher];\n });\n\n return entity =>\n matchers.length ? matchers.some(matcher => matcher(entity)) : true;\n}\n"],"names":[],"mappings":";;AAmBA,MAAM,eAAmD,GAAA;AAAA,EACvD,QAAQ,CAAU,MAAA,KAAA;AApBpB,IAAA,IAAA,EAAA,CAAA;AAqBI,IAAO,OAAA,MAAA,CAAO,MAAK,EAAO,GAAA,MAAA,CAAA,QAAA,CAAS,WAAhB,IAA0B,GAAA,EAAA,GAAA,EAAE,CAAA,CAAE,MAAS,GAAA,CAAA,CAAA;AAAA,GAC5D;AAAA,EACA,OAAO,CAAU,MAAA,KAAA;AAvBnB,IAAA,IAAA,EAAA,CAAA;AAwBI,IAAA,OAAA,CAAA,CAAQ,YAAO,QAAS,CAAA,KAAA,KAAhB,IAAyB,GAAA,EAAA,GAAA,IAAI,MAAS,GAAA,CAAA,CAAA;AAAA,GAChD;AACF,CAAA,CAAA;AAKgB,SAAA,gBAAA,CACd,YACA,YACiB,EAAA;AACjB,EAAM,MAAA,QAAA,GAAW,UAAW,CAAA,OAAA,CAAQ,CAAa,SAAA,KAAA;AAC/C,IAAA,MAAM,OAAU,GAAA,eAAA,CAAgB,SAAU,CAAA,iBAAA,CAAkB,OAAO,CAAC,CAAA,CAAA;AACpE,IAAA,IAAI,CAAC,OAAS,EAAA;AACZ,MAAM,MAAA,KAAA,GAAQ,OAAO,IAAK,CAAA,eAAe,EAAE,GAAI,CAAA,CAAA,CAAA,KAAK,CAAI,CAAA,EAAA,CAAC,CAAG,CAAA,CAAA,CAAA,CAAA;AAC5D,MAAA,YAAA;AAAA,QACE,IAAI,UAAA;AAAA,UACF,CAAA,CAAA,EAAI,SAAS,CAAA,yEAAA,EAA4E,KAAK,CAAA,CAAA;AAAA,SAChG;AAAA,OACF,CAAA;AACA,MAAA,OAAO,EAAC,CAAA;AAAA,KACV;AACA,IAAA,OAAO,CAAC,OAAO,CAAA,CAAA;AAAA,GAChB,CAAA,CAAA;AAED,EAAO,OAAA,CAAA,MAAA,KACL,SAAS,MAAS,GAAA,QAAA,CAAS,KAAK,CAAW,OAAA,KAAA,OAAA,CAAQ,MAAM,CAAC,CAAI,GAAA,IAAA,CAAA;AAClE;;;;"}
1
+ {"version":3,"file":"createHasMatcher.esm.js","sources":["../../../../src/alpha/filter/matrchers/createHasMatcher.ts"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { InputError } from '@backstage/errors';\nimport { EntityMatcherFn } from './types';\n\nconst allowedMatchers: Record<string, EntityMatcherFn> = {\n labels: entity => {\n return Object.keys(entity.metadata.labels ?? {}).length > 0;\n },\n links: entity => {\n return (entity.metadata.links ?? []).length > 0;\n },\n};\n\n/**\n * Matches on the non-empty presence of different parts of the entity\n */\nexport function createHasMatcher(\n parameters: string[],\n onParseError: (error: Error) => void,\n): EntityMatcherFn {\n const matchers = parameters.flatMap(parameter => {\n const matcher = allowedMatchers[parameter.toLocaleLowerCase('en-US')];\n if (!matcher) {\n const known = Object.keys(allowedMatchers).map(m => `'${m}'`);\n onParseError(\n new InputError(\n `'${parameter}' is not a valid parameter for 'has' filter expressions, expected one of ${known}`,\n ),\n );\n return [];\n }\n return [matcher];\n });\n\n return entity =>\n matchers.length ? matchers.some(matcher => matcher(entity)) : true;\n}\n"],"names":[],"mappings":";;AAmBA,MAAM,eAAmD,GAAA;AAAA,EACvD,QAAQ,CAAU,MAAA,KAAA;AAChB,IAAO,OAAA,MAAA,CAAO,KAAK,MAAO,CAAA,QAAA,CAAS,UAAU,EAAE,EAAE,MAAS,GAAA,CAAA,CAAA;AAAA,GAC5D;AAAA,EACA,OAAO,CAAU,MAAA,KAAA;AACf,IAAA,OAAA,CAAQ,MAAO,CAAA,QAAA,CAAS,KAAS,IAAA,IAAI,MAAS,GAAA,CAAA,CAAA;AAAA,GAChD;AACF,CAAA,CAAA;AAKgB,SAAA,gBAAA,CACd,YACA,YACiB,EAAA;AACjB,EAAM,MAAA,QAAA,GAAW,UAAW,CAAA,OAAA,CAAQ,CAAa,SAAA,KAAA;AAC/C,IAAA,MAAM,OAAU,GAAA,eAAA,CAAgB,SAAU,CAAA,iBAAA,CAAkB,OAAO,CAAC,CAAA,CAAA;AACpE,IAAA,IAAI,CAAC,OAAS,EAAA;AACZ,MAAM,MAAA,KAAA,GAAQ,OAAO,IAAK,CAAA,eAAe,EAAE,GAAI,CAAA,CAAA,CAAA,KAAK,CAAI,CAAA,EAAA,CAAC,CAAG,CAAA,CAAA,CAAA,CAAA;AAC5D,MAAA,YAAA;AAAA,QACE,IAAI,UAAA;AAAA,UACF,CAAA,CAAA,EAAI,SAAS,CAAA,yEAAA,EAA4E,KAAK,CAAA,CAAA;AAAA,SAChG;AAAA,OACF,CAAA;AACA,MAAA,OAAO,EAAC,CAAA;AAAA,KACV;AACA,IAAA,OAAO,CAAC,OAAO,CAAA,CAAA;AAAA,GAChB,CAAA,CAAA;AAED,EAAO,OAAA,CAAA,MAAA,KACL,SAAS,MAAS,GAAA,QAAA,CAAS,KAAK,CAAW,OAAA,KAAA,OAAA,CAAQ,MAAM,CAAC,CAAI,GAAA,IAAA,CAAA;AAClE;;;;"}
@@ -1,10 +1,7 @@
1
1
  import { InputError } from '@backstage/errors';
2
2
 
3
3
  const allowedMatchers = {
4
- orphan: (entity) => {
5
- var _a;
6
- return Boolean((_a = entity.metadata.annotations) == null ? void 0 : _a["backstage.io/orphan"]);
7
- }
4
+ orphan: (entity) => Boolean(entity.metadata.annotations?.["backstage.io/orphan"])
8
5
  };
9
6
  function createIsMatcher(parameters, onParseError) {
10
7
  const matchers = parameters.flatMap((parameter) => {
@@ -1 +1 @@
1
- {"version":3,"file":"createIsMatcher.esm.js","sources":["../../../../src/alpha/filter/matrchers/createIsMatcher.ts"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { InputError } from '@backstage/errors';\nimport { EntityMatcherFn } from './types';\n\nconst allowedMatchers: Record<string, EntityMatcherFn> = {\n orphan: entity =>\n Boolean(entity.metadata.annotations?.['backstage.io/orphan']),\n};\n\n/**\n * Matches on different semantic properties of the entity\n */\nexport function createIsMatcher(\n parameters: string[],\n onParseError: (error: Error) => void,\n): EntityMatcherFn {\n const matchers = parameters.flatMap(parameter => {\n const matcher = allowedMatchers[parameter.toLocaleLowerCase('en-US')];\n if (!matcher) {\n const known = Object.keys(allowedMatchers).map(m => `'${m}'`);\n onParseError(\n new InputError(\n `'${parameter}' is not a valid parameter for 'is' filter expressions, expected one of ${known}`,\n ),\n );\n return [];\n }\n return [matcher];\n });\n\n return entity =>\n matchers.length ? matchers.some(matcher => matcher(entity)) : true;\n}\n"],"names":[],"mappings":";;AAmBA,MAAM,eAAmD,GAAA;AAAA,EACvD,QAAQ,CAAO,MAAA,KAAA;AApBjB,IAAA,IAAA,EAAA,CAAA;AAqBI,IAAA,OAAA,OAAA,CAAA,CAAQ,EAAO,GAAA,MAAA,CAAA,QAAA,CAAS,WAAhB,KAAA,IAAA,GAAA,KAAA,CAAA,GAAA,EAAA,CAA8B,qBAAsB,CAAA,CAAA,CAAA;AAAA,GAAA;AAChE,CAAA,CAAA;AAKgB,SAAA,eAAA,CACd,YACA,YACiB,EAAA;AACjB,EAAM,MAAA,QAAA,GAAW,UAAW,CAAA,OAAA,CAAQ,CAAa,SAAA,KAAA;AAC/C,IAAA,MAAM,OAAU,GAAA,eAAA,CAAgB,SAAU,CAAA,iBAAA,CAAkB,OAAO,CAAC,CAAA,CAAA;AACpE,IAAA,IAAI,CAAC,OAAS,EAAA;AACZ,MAAM,MAAA,KAAA,GAAQ,OAAO,IAAK,CAAA,eAAe,EAAE,GAAI,CAAA,CAAA,CAAA,KAAK,CAAI,CAAA,EAAA,CAAC,CAAG,CAAA,CAAA,CAAA,CAAA;AAC5D,MAAA,YAAA;AAAA,QACE,IAAI,UAAA;AAAA,UACF,CAAA,CAAA,EAAI,SAAS,CAAA,wEAAA,EAA2E,KAAK,CAAA,CAAA;AAAA,SAC/F;AAAA,OACF,CAAA;AACA,MAAA,OAAO,EAAC,CAAA;AAAA,KACV;AACA,IAAA,OAAO,CAAC,OAAO,CAAA,CAAA;AAAA,GAChB,CAAA,CAAA;AAED,EAAO,OAAA,CAAA,MAAA,KACL,SAAS,MAAS,GAAA,QAAA,CAAS,KAAK,CAAW,OAAA,KAAA,OAAA,CAAQ,MAAM,CAAC,CAAI,GAAA,IAAA,CAAA;AAClE;;;;"}
1
+ {"version":3,"file":"createIsMatcher.esm.js","sources":["../../../../src/alpha/filter/matrchers/createIsMatcher.ts"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { InputError } from '@backstage/errors';\nimport { EntityMatcherFn } from './types';\n\nconst allowedMatchers: Record<string, EntityMatcherFn> = {\n orphan: entity =>\n Boolean(entity.metadata.annotations?.['backstage.io/orphan']),\n};\n\n/**\n * Matches on different semantic properties of the entity\n */\nexport function createIsMatcher(\n parameters: string[],\n onParseError: (error: Error) => void,\n): EntityMatcherFn {\n const matchers = parameters.flatMap(parameter => {\n const matcher = allowedMatchers[parameter.toLocaleLowerCase('en-US')];\n if (!matcher) {\n const known = Object.keys(allowedMatchers).map(m => `'${m}'`);\n onParseError(\n new InputError(\n `'${parameter}' is not a valid parameter for 'is' filter expressions, expected one of ${known}`,\n ),\n );\n return [];\n }\n return [matcher];\n });\n\n return entity =>\n matchers.length ? matchers.some(matcher => matcher(entity)) : true;\n}\n"],"names":[],"mappings":";;AAmBA,MAAM,eAAmD,GAAA;AAAA,EACvD,QAAQ,CACN,MAAA,KAAA,OAAA,CAAQ,OAAO,QAAS,CAAA,WAAA,GAAc,qBAAqB,CAAC,CAAA;AAChE,CAAA,CAAA;AAKgB,SAAA,eAAA,CACd,YACA,YACiB,EAAA;AACjB,EAAM,MAAA,QAAA,GAAW,UAAW,CAAA,OAAA,CAAQ,CAAa,SAAA,KAAA;AAC/C,IAAA,MAAM,OAAU,GAAA,eAAA,CAAgB,SAAU,CAAA,iBAAA,CAAkB,OAAO,CAAC,CAAA,CAAA;AACpE,IAAA,IAAI,CAAC,OAAS,EAAA;AACZ,MAAM,MAAA,KAAA,GAAQ,OAAO,IAAK,CAAA,eAAe,EAAE,GAAI,CAAA,CAAA,CAAA,KAAK,CAAI,CAAA,EAAA,CAAC,CAAG,CAAA,CAAA,CAAA,CAAA;AAC5D,MAAA,YAAA;AAAA,QACE,IAAI,UAAA;AAAA,UACF,CAAA,CAAA,EAAI,SAAS,CAAA,wEAAA,EAA2E,KAAK,CAAA,CAAA;AAAA,SAC/F;AAAA,OACF,CAAA;AACA,MAAA,OAAO,EAAC,CAAA;AAAA,KACV;AACA,IAAA,OAAO,CAAC,OAAO,CAAA,CAAA;AAAA,GAChB,CAAA,CAAA;AAED,EAAO,OAAA,CAAA,MAAA,KACL,SAAS,MAAS,GAAA,QAAA,CAAS,KAAK,CAAW,OAAA,KAAA,OAAA,CAAQ,MAAM,CAAC,CAAI,GAAA,IAAA,CAAA;AAClE;;;;"}
@@ -1,8 +1,7 @@
1
1
  function createTypeMatcher(parameters, _onParseError) {
2
2
  const items = parameters.map((p) => p.toLocaleLowerCase("en-US"));
3
3
  return (entity) => {
4
- var _a;
5
- const value = (_a = entity.spec) == null ? void 0 : _a.type;
4
+ const value = entity.spec?.type;
6
5
  return typeof value === "string" && items.includes(value.toLocaleLowerCase("en-US"));
7
6
  };
8
7
  }
@@ -1 +1 @@
1
- {"version":3,"file":"createTypeMatcher.esm.js","sources":["../../../../src/alpha/filter/matrchers/createTypeMatcher.ts"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { EntityMatcherFn } from './types';\n\n/**\n * Matches on spec.type\n */\nexport function createTypeMatcher(\n parameters: string[],\n _onParseError: (error: Error) => void,\n): EntityMatcherFn {\n const items = parameters.map(p => p.toLocaleLowerCase('en-US'));\n return entity => {\n const value = entity.spec?.type;\n return (\n typeof value === 'string' &&\n items.includes(value.toLocaleLowerCase('en-US'))\n );\n };\n}\n"],"names":[],"mappings":"AAqBgB,SAAA,iBAAA,CACd,YACA,aACiB,EAAA;AACjB,EAAA,MAAM,QAAQ,UAAW,CAAA,GAAA,CAAI,OAAK,CAAE,CAAA,iBAAA,CAAkB,OAAO,CAAC,CAAA,CAAA;AAC9D,EAAA,OAAO,CAAU,MAAA,KAAA;AA1BnB,IAAA,IAAA,EAAA,CAAA;AA2BI,IAAM,MAAA,KAAA,GAAA,CAAQ,EAAO,GAAA,MAAA,CAAA,IAAA,KAAP,IAAa,GAAA,KAAA,CAAA,GAAA,EAAA,CAAA,IAAA,CAAA;AAC3B,IACE,OAAA,OAAO,UAAU,QACjB,IAAA,KAAA,CAAM,SAAS,KAAM,CAAA,iBAAA,CAAkB,OAAO,CAAC,CAAA,CAAA;AAAA,GAEnD,CAAA;AACF;;;;"}
1
+ {"version":3,"file":"createTypeMatcher.esm.js","sources":["../../../../src/alpha/filter/matrchers/createTypeMatcher.ts"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { EntityMatcherFn } from './types';\n\n/**\n * Matches on spec.type\n */\nexport function createTypeMatcher(\n parameters: string[],\n _onParseError: (error: Error) => void,\n): EntityMatcherFn {\n const items = parameters.map(p => p.toLocaleLowerCase('en-US'));\n return entity => {\n const value = entity.spec?.type;\n return (\n typeof value === 'string' &&\n items.includes(value.toLocaleLowerCase('en-US'))\n );\n };\n}\n"],"names":[],"mappings":"AAqBgB,SAAA,iBAAA,CACd,YACA,aACiB,EAAA;AACjB,EAAA,MAAM,QAAQ,UAAW,CAAA,GAAA,CAAI,OAAK,CAAE,CAAA,iBAAA,CAAkB,OAAO,CAAC,CAAA,CAAA;AAC9D,EAAA,OAAO,CAAU,MAAA,KAAA;AACf,IAAM,MAAA,KAAA,GAAQ,OAAO,IAAM,EAAA,IAAA,CAAA;AAC3B,IACE,OAAA,OAAO,UAAU,QACjB,IAAA,KAAA,CAAM,SAAS,KAAM,CAAA,iBAAA,CAAkB,OAAO,CAAC,CAAA,CAAA;AAAA,GAEnD,CAAA;AACF;;;;"}
@@ -3,94 +3,67 @@ import { durationToMilliseconds } from '@backstage/types';
3
3
  import DataLoader from 'dataloader';
4
4
  import ExpiryMap from 'expiry-map';
5
5
  import ObservableImpl from 'zen-observable';
6
- import { DEFAULT_CACHE_TTL, DEFAULT_BATCH_DELAY, createDefaultRenderer, DEFAULT_ICONS } from './defaults.esm.js';
6
+ import { createDefaultRenderer, DEFAULT_CACHE_TTL, DEFAULT_BATCH_DELAY, DEFAULT_ICONS } from './defaults.esm.js';
7
7
 
8
- var __accessCheck = (obj, member, msg) => {
9
- if (!member.has(obj))
10
- throw TypeError("Cannot " + msg);
11
- };
12
- var __privateGet = (obj, member, getter) => {
13
- __accessCheck(obj, member, "read from private field");
14
- return member.get(obj);
15
- };
16
- var __privateAdd = (obj, member, value) => {
17
- if (member.has(obj))
18
- throw TypeError("Cannot add the same private member more than once");
19
- member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
20
- };
21
- var __privateSet = (obj, member, value, setter) => {
22
- __accessCheck(obj, member, "write to private field");
23
- member.set(obj, value);
24
- return value;
25
- };
26
- var __privateMethod = (obj, member, method) => {
27
- __accessCheck(obj, member, "access private method");
28
- return method;
29
- };
30
- var _cache, _cacheTtlMs, _loader, _kindIcons, _renderer, _getEntityForInitialRender, getEntityForInitialRender_fn, _createLoader, createLoader_fn, _maybeFallbackIcon, maybeFallbackIcon_fn;
31
- const _DefaultEntityPresentationApi = class _DefaultEntityPresentationApi {
8
+ class DefaultEntityPresentationApi {
9
+ /**
10
+ * Creates a new presentation API that does not reach out to the catalog.
11
+ */
12
+ static createLocal() {
13
+ return new DefaultEntityPresentationApi({
14
+ renderer: createDefaultRenderer({ async: false })
15
+ });
16
+ }
17
+ /**
18
+ * Creates a new presentation API that calls out to the catalog as needed to
19
+ * get additional information about entities.
20
+ */
21
+ static create(options) {
22
+ return new DefaultEntityPresentationApi(options);
23
+ }
24
+ // This cache holds on to all entity data ever loaded, no matter how old. Each
25
+ // entry is tagged with a timestamp of when it was inserted. We use this map
26
+ // to be able to always render SOME data even though the information is old.
27
+ // Entities change very rarely, so it's likely that the rendered information
28
+ // was perfectly fine in the first place.
29
+ #cache;
30
+ #cacheTtlMs;
31
+ #loader;
32
+ #kindIcons;
33
+ // lowercased kinds
34
+ #renderer;
32
35
  constructor(options) {
33
- __privateAdd(this, _getEntityForInitialRender);
34
- __privateAdd(this, _createLoader);
35
- __privateAdd(this, _maybeFallbackIcon);
36
- // This cache holds on to all entity data ever loaded, no matter how old. Each
37
- // entry is tagged with a timestamp of when it was inserted. We use this map
38
- // to be able to always render SOME data even though the information is old.
39
- // Entities change very rarely, so it's likely that the rendered information
40
- // was perfectly fine in the first place.
41
- __privateAdd(this, _cache, void 0);
42
- __privateAdd(this, _cacheTtlMs, void 0);
43
- __privateAdd(this, _loader, void 0);
44
- __privateAdd(this, _kindIcons, void 0);
45
- // lowercased kinds
46
- __privateAdd(this, _renderer, void 0);
47
- var _a, _b, _c, _d;
48
- const cacheTtl = (_a = options.cacheTtl) != null ? _a : DEFAULT_CACHE_TTL;
49
- const batchDelay = (_b = options.batchDelay) != null ? _b : DEFAULT_BATCH_DELAY;
50
- const renderer = (_c = options.renderer) != null ? _c : createDefaultRenderer({ async: true });
36
+ const cacheTtl = options.cacheTtl ?? DEFAULT_CACHE_TTL;
37
+ const batchDelay = options.batchDelay ?? DEFAULT_BATCH_DELAY;
38
+ const renderer = options.renderer ?? createDefaultRenderer({ async: true });
51
39
  const kindIcons = {};
52
40
  Object.entries(DEFAULT_ICONS).forEach(([kind, icon]) => {
53
41
  kindIcons[kind.toLocaleLowerCase("en-US")] = icon;
54
42
  });
55
- Object.entries((_d = options.kindIcons) != null ? _d : {}).forEach(([kind, icon]) => {
43
+ Object.entries(options.kindIcons ?? {}).forEach(([kind, icon]) => {
56
44
  kindIcons[kind.toLocaleLowerCase("en-US")] = icon;
57
45
  });
58
46
  if (renderer.async) {
59
47
  if (!options.catalogApi) {
60
48
  throw new TypeError(`Asynchronous rendering requires a catalog API`);
61
49
  }
62
- __privateSet(this, _loader, __privateMethod(this, _createLoader, createLoader_fn).call(this, {
50
+ this.#loader = this.#createLoader({
63
51
  cacheTtl,
64
52
  batchDelay,
65
53
  renderer,
66
54
  catalogApi: options.catalogApi
67
- }));
55
+ });
68
56
  }
69
- __privateSet(this, _cacheTtlMs, durationToMilliseconds(cacheTtl));
70
- __privateSet(this, _cache, /* @__PURE__ */ new Map());
71
- __privateSet(this, _kindIcons, kindIcons);
72
- __privateSet(this, _renderer, renderer);
73
- }
74
- /**
75
- * Creates a new presentation API that does not reach out to the catalog.
76
- */
77
- static createLocal() {
78
- return new _DefaultEntityPresentationApi({
79
- renderer: createDefaultRenderer({ async: false })
80
- });
81
- }
82
- /**
83
- * Creates a new presentation API that calls out to the catalog as needed to
84
- * get additional information about entities.
85
- */
86
- static create(options) {
87
- return new _DefaultEntityPresentationApi(options);
57
+ this.#cacheTtlMs = durationToMilliseconds(cacheTtl);
58
+ this.#cache = /* @__PURE__ */ new Map();
59
+ this.#kindIcons = kindIcons;
60
+ this.#renderer = renderer;
88
61
  }
89
62
  /** {@inheritdoc @backstage/plugin-catalog-react#EntityPresentationApi.forEntity} */
90
63
  forEntity(entityOrRef, context) {
91
- const { entityRef, kind, entity, needsLoad } = __privateMethod(this, _getEntityForInitialRender, getEntityForInitialRender_fn).call(this, entityOrRef);
64
+ const { entityRef, kind, entity, needsLoad } = this.#getEntityForInitialRender(entityOrRef);
92
65
  const render = (options) => {
93
- const { snapshot } = __privateGet(this, _renderer).render({
66
+ const { snapshot } = this.#renderer.render({
94
67
  entityRef,
95
68
  loading: options.loading,
96
69
  entity: options.entity,
@@ -99,7 +72,7 @@ const _DefaultEntityPresentationApi = class _DefaultEntityPresentationApi {
99
72
  return {
100
73
  ...snapshot,
101
74
  entityRef,
102
- Icon: __privateMethod(this, _maybeFallbackIcon, maybeFallbackIcon_fn).call(this, snapshot.Icon, kind)
75
+ Icon: this.#maybeFallbackIcon(snapshot.Icon, kind)
103
76
  };
104
77
  };
105
78
  let initialSnapshot;
@@ -121,12 +94,11 @@ const _DefaultEntityPresentationApi = class _DefaultEntityPresentationApi {
121
94
  };
122
95
  }
123
96
  const maybeUpdatedSnapshot = Promise.resolve().then(() => {
124
- var _a;
125
- return (_a = __privateGet(this, _loader)) == null ? void 0 : _a.load(entityRef);
97
+ return this.#loader?.load(entityRef);
126
98
  }).then((newEntity) => {
127
99
  return render({
128
100
  loading: false,
129
- entity: newEntity != null ? newEntity : entity
101
+ entity: newEntity ?? entity
130
102
  });
131
103
  }).catch(() => {
132
104
  return void 0;
@@ -149,7 +121,7 @@ const _DefaultEntityPresentationApi = class _DefaultEntityPresentationApi {
149
121
  }
150
122
  );
151
123
  const promise = maybeUpdatedSnapshot.then((updatedSnapshot) => {
152
- return updatedSnapshot != null ? updatedSnapshot : initialSnapshot;
124
+ return updatedSnapshot ?? initialSnapshot;
153
125
  });
154
126
  return {
155
127
  snapshot: initialSnapshot,
@@ -157,77 +129,68 @@ const _DefaultEntityPresentationApi = class _DefaultEntityPresentationApi {
157
129
  promise
158
130
  };
159
131
  }
160
- };
161
- _cache = new WeakMap();
162
- _cacheTtlMs = new WeakMap();
163
- _loader = new WeakMap();
164
- _kindIcons = new WeakMap();
165
- _renderer = new WeakMap();
166
- _getEntityForInitialRender = new WeakSet();
167
- getEntityForInitialRender_fn = function(entityOrRef) {
168
- if (typeof entityOrRef !== "string") {
132
+ #getEntityForInitialRender(entityOrRef) {
133
+ if (typeof entityOrRef !== "string") {
134
+ return {
135
+ entity: entityOrRef,
136
+ kind: entityOrRef.kind,
137
+ entityRef: stringifyEntityRef(entityOrRef),
138
+ needsLoad: false
139
+ };
140
+ }
141
+ const cached = this.#cache.get(entityOrRef);
142
+ const cachedEntity = cached?.entity;
143
+ const cacheNeedsUpdate = !cached || Date.now() - cached.updatedAt > this.#cacheTtlMs;
144
+ const needsLoad = cacheNeedsUpdate && this.#renderer.async !== false && this.#loader !== void 0;
169
145
  return {
170
- entity: entityOrRef,
171
- kind: entityOrRef.kind,
172
- entityRef: stringifyEntityRef(entityOrRef),
173
- needsLoad: false
146
+ entity: cachedEntity,
147
+ kind: parseEntityRef(entityOrRef).kind,
148
+ entityRef: entityOrRef,
149
+ needsLoad
174
150
  };
175
151
  }
176
- const cached = __privateGet(this, _cache).get(entityOrRef);
177
- const cachedEntity = cached == null ? void 0 : cached.entity;
178
- const cacheNeedsUpdate = !cached || Date.now() - cached.updatedAt > __privateGet(this, _cacheTtlMs);
179
- const needsLoad = cacheNeedsUpdate && __privateGet(this, _renderer).async !== false && __privateGet(this, _loader) !== void 0;
180
- return {
181
- entity: cachedEntity,
182
- kind: parseEntityRef(entityOrRef).kind,
183
- entityRef: entityOrRef,
184
- needsLoad
185
- };
186
- };
187
- _createLoader = new WeakSet();
188
- createLoader_fn = function(options) {
189
- const cacheTtlMs = durationToMilliseconds(options.cacheTtl);
190
- const batchDelayMs = durationToMilliseconds(options.batchDelay);
191
- return new DataLoader(
192
- async (entityRefs) => {
193
- const { items } = await options.catalogApi.getEntitiesByRefs({
194
- entityRefs
195
- });
196
- const now = Date.now();
197
- entityRefs.forEach((entityRef, index) => {
198
- __privateGet(this, _cache).set(entityRef, {
199
- updatedAt: now,
200
- entity: items[index]
152
+ #createLoader(options) {
153
+ const cacheTtlMs = durationToMilliseconds(options.cacheTtl);
154
+ const batchDelayMs = durationToMilliseconds(options.batchDelay);
155
+ return new DataLoader(
156
+ async (entityRefs) => {
157
+ const { items } = await options.catalogApi.getEntitiesByRefs({
158
+ entityRefs
201
159
  });
202
- });
203
- return items;
204
- },
205
- {
206
- name: "DefaultEntityPresentationApi",
207
- // This cache is the one that the data loader uses internally for
208
- // memoizing requests; essentially what it achieves is that multiple
209
- // requests for the same entity ref will be batched up into a single
210
- // request and then the resulting promises are held on to. We put an
211
- // expiring map here, which makes it so that it re-fetches data with the
212
- // expiry cadence of that map. Otherwise it would only fetch a given ref
213
- // once and then never try again. This cache does therefore not fulfill
214
- // the same purpose as the one that is in the root of the class.
215
- cacheMap: new ExpiryMap(cacheTtlMs),
216
- maxBatchSize: 100,
217
- batchScheduleFn: batchDelayMs ? (cb) => setTimeout(cb, batchDelayMs) : void 0
160
+ const now = Date.now();
161
+ entityRefs.forEach((entityRef, index) => {
162
+ this.#cache.set(entityRef, {
163
+ updatedAt: now,
164
+ entity: items[index]
165
+ });
166
+ });
167
+ return items;
168
+ },
169
+ {
170
+ name: "DefaultEntityPresentationApi",
171
+ // This cache is the one that the data loader uses internally for
172
+ // memoizing requests; essentially what it achieves is that multiple
173
+ // requests for the same entity ref will be batched up into a single
174
+ // request and then the resulting promises are held on to. We put an
175
+ // expiring map here, which makes it so that it re-fetches data with the
176
+ // expiry cadence of that map. Otherwise it would only fetch a given ref
177
+ // once and then never try again. This cache does therefore not fulfill
178
+ // the same purpose as the one that is in the root of the class.
179
+ cacheMap: new ExpiryMap(cacheTtlMs),
180
+ maxBatchSize: 100,
181
+ batchScheduleFn: batchDelayMs ? (cb) => setTimeout(cb, batchDelayMs) : void 0
182
+ }
183
+ );
184
+ }
185
+ #maybeFallbackIcon(renderedIcon, kind) {
186
+ if (renderedIcon) {
187
+ return renderedIcon;
188
+ } else if (renderedIcon === false) {
189
+ return false;
218
190
  }
219
- );
220
- };
221
- _maybeFallbackIcon = new WeakSet();
222
- maybeFallbackIcon_fn = function(renderedIcon, kind) {
223
- if (renderedIcon) {
224
- return renderedIcon;
225
- } else if (renderedIcon === false) {
226
- return false;
191
+ return this.#kindIcons[kind.toLocaleLowerCase("en-US")];
227
192
  }
228
- return __privateGet(this, _kindIcons)[kind.toLocaleLowerCase("en-US")];
229
- };
230
- let DefaultEntityPresentationApi = _DefaultEntityPresentationApi;
193
+ }
231
194
 
232
195
  export { DefaultEntityPresentationApi };
233
196
  //# sourceMappingURL=DefaultEntityPresentationApi.esm.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"DefaultEntityPresentationApi.esm.js","sources":["../../../src/apis/EntityPresentationApi/DefaultEntityPresentationApi.ts"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n Entity,\n parseEntityRef,\n stringifyEntityRef,\n} from '@backstage/catalog-model';\nimport { IconComponent } from '@backstage/core-plugin-api';\nimport {\n CatalogApi,\n EntityPresentationApi,\n EntityRefPresentation,\n EntityRefPresentationSnapshot,\n} from '@backstage/plugin-catalog-react';\nimport { HumanDuration, durationToMilliseconds } from '@backstage/types';\nimport DataLoader from 'dataloader';\nimport ExpiryMap from 'expiry-map';\nimport ObservableImpl from 'zen-observable';\nimport {\n DEFAULT_BATCH_DELAY,\n DEFAULT_CACHE_TTL,\n DEFAULT_ICONS,\n createDefaultRenderer,\n} from './defaults';\n\n/**\n * A custom renderer for the {@link DefaultEntityPresentationApi}.\n *\n * @public\n */\nexport interface DefaultEntityPresentationApiRenderer {\n /**\n * Whether to request the entity from the catalog API asynchronously.\n *\n * @remarks\n *\n * If this is set to true, entity data will be streamed in from the catalog\n * whenever needed, and the render function may be called more than once:\n * first when no entity data existed (or with old cached data), and then again\n * at a later point when data is loaded from the catalog that proved to be\n * different from the old one.\n *\n * @defaultValue true\n */\n async?: boolean;\n\n /**\n * The actual render function.\n *\n * @remarks\n *\n * This function may be called multiple times.\n *\n * The loading flag signals that the framework MAY be trying to load more\n * entity data from the catalog and call the render function again, if it\n * succeeds. In some cases you may want to render a loading state in that\n * case.\n *\n * The entity may or may not be given. If the caller of the presentation API\n * did present an entity upfront, then that's what will be passed in here.\n * Otherwise, it may be a server-side entity that either comes from a local\n * cache or directly from the server.\n *\n * In either case, the renderer should return a presentation that is the most\n * useful possible for the end user, given the data that is available.\n */\n render: (options: {\n entityRef: string;\n loading: boolean;\n entity: Entity | undefined;\n context: {\n defaultKind?: string;\n defaultNamespace?: string;\n };\n }) => {\n snapshot: Omit<EntityRefPresentationSnapshot, 'entityRef'>;\n };\n}\n\n/**\n * Options for the {@link DefaultEntityPresentationApi}.\n *\n * @public\n */\nexport interface DefaultEntityPresentationApiOptions {\n /**\n * The catalog API to use. If you want to use any asynchronous features, you\n * must supply one.\n */\n catalogApi?: CatalogApi;\n\n /**\n * When to expire entities that have been loaded from the catalog API and\n * cached for a while.\n *\n * @defaultValue 10 seconds\n * @remarks\n *\n * The higher this value, the lower the load on the catalog API, but also the\n * higher the risk of users seeing stale data.\n */\n cacheTtl?: HumanDuration;\n\n /**\n * For how long to wait before sending a batch of entity references to the\n * catalog API.\n *\n * @defaultValue 50 milliseconds\n * @remarks\n *\n * The higher this value, the greater the chance of batching up requests from\n * across a page, but also the longer the lag time before displaying accurate\n * information.\n */\n batchDelay?: HumanDuration;\n\n /**\n * A mapping from kinds to icons.\n *\n * @remarks\n *\n * The keys are kinds (case insensitive) that map to icon values to represent\n * kinds by. These are merged with the default set of icons.\n */\n kindIcons?: Record<string, IconComponent>;\n\n /**\n * A custom renderer, if any.\n */\n renderer?: DefaultEntityPresentationApiRenderer;\n}\n\ninterface CacheEntry {\n updatedAt: number;\n entity: Entity | undefined;\n}\n\n/**\n * Default implementation of the {@link @backstage/plugin-catalog-react#EntityPresentationApi}.\n *\n * @public\n */\nexport class DefaultEntityPresentationApi implements EntityPresentationApi {\n /**\n * Creates a new presentation API that does not reach out to the catalog.\n */\n static createLocal(): EntityPresentationApi {\n return new DefaultEntityPresentationApi({\n renderer: createDefaultRenderer({ async: false }),\n });\n }\n\n /**\n * Creates a new presentation API that calls out to the catalog as needed to\n * get additional information about entities.\n */\n static create(\n options: DefaultEntityPresentationApiOptions,\n ): EntityPresentationApi {\n return new DefaultEntityPresentationApi(options);\n }\n\n // This cache holds on to all entity data ever loaded, no matter how old. Each\n // entry is tagged with a timestamp of when it was inserted. We use this map\n // to be able to always render SOME data even though the information is old.\n // Entities change very rarely, so it's likely that the rendered information\n // was perfectly fine in the first place.\n readonly #cache: Map<string, CacheEntry>;\n readonly #cacheTtlMs: number;\n readonly #loader: DataLoader<string, Entity | undefined> | undefined;\n readonly #kindIcons: Record<string, IconComponent>; // lowercased kinds\n readonly #renderer: DefaultEntityPresentationApiRenderer;\n\n private constructor(options: DefaultEntityPresentationApiOptions) {\n const cacheTtl = options.cacheTtl ?? DEFAULT_CACHE_TTL;\n const batchDelay = options.batchDelay ?? DEFAULT_BATCH_DELAY;\n const renderer = options.renderer ?? createDefaultRenderer({ async: true });\n\n const kindIcons: Record<string, IconComponent> = {};\n Object.entries(DEFAULT_ICONS).forEach(([kind, icon]) => {\n kindIcons[kind.toLocaleLowerCase('en-US')] = icon;\n });\n Object.entries(options.kindIcons ?? {}).forEach(([kind, icon]) => {\n kindIcons[kind.toLocaleLowerCase('en-US')] = icon;\n });\n\n if (renderer.async) {\n if (!options.catalogApi) {\n throw new TypeError(`Asynchronous rendering requires a catalog API`);\n }\n this.#loader = this.#createLoader({\n cacheTtl,\n batchDelay,\n renderer,\n catalogApi: options.catalogApi,\n });\n }\n\n this.#cacheTtlMs = durationToMilliseconds(cacheTtl);\n this.#cache = new Map();\n this.#kindIcons = kindIcons;\n this.#renderer = renderer;\n }\n\n /** {@inheritdoc @backstage/plugin-catalog-react#EntityPresentationApi.forEntity} */\n forEntity(\n entityOrRef: Entity | string,\n context?: {\n defaultKind?: string;\n defaultNamespace?: string;\n },\n ): EntityRefPresentation {\n const { entityRef, kind, entity, needsLoad } =\n this.#getEntityForInitialRender(entityOrRef);\n\n // Make a wrapping helper for rendering\n const render = (options: {\n loading: boolean;\n entity?: Entity;\n }): EntityRefPresentationSnapshot => {\n const { snapshot } = this.#renderer.render({\n entityRef: entityRef,\n loading: options.loading,\n entity: options.entity,\n context: context || {},\n });\n return {\n ...snapshot,\n entityRef: entityRef,\n Icon: this.#maybeFallbackIcon(snapshot.Icon, kind),\n };\n };\n\n // First the initial render\n let initialSnapshot: EntityRefPresentationSnapshot;\n try {\n initialSnapshot = render({\n loading: needsLoad,\n entity: entity,\n });\n } catch {\n // This is what gets presented if the renderer throws an error\n initialSnapshot = {\n primaryTitle: entityRef,\n entityRef: entityRef,\n };\n }\n\n if (!needsLoad) {\n return {\n snapshot: initialSnapshot,\n promise: Promise.resolve(initialSnapshot),\n };\n }\n\n // Load the entity and render it\n const maybeUpdatedSnapshot = Promise.resolve()\n .then(() => {\n return this.#loader?.load(entityRef);\n })\n .then(newEntity => {\n // We re-render no matter if we get back a new entity or the old\n // one or nothing, because of the now false loading state - in\n // case the renderer outputs different data depending on that\n return render({\n loading: false,\n entity: newEntity ?? entity,\n });\n })\n .catch(() => {\n // Intentionally ignored - we do not propagate errors to the\n // caller here. The presentation API should be error free and\n // always return SOMETHING that makes sense to render, and we have\n // already ensured above that the initial snapshot was that.\n return undefined;\n });\n\n const observable = new ObservableImpl<EntityRefPresentationSnapshot>(\n subscriber => {\n let aborted = false;\n\n maybeUpdatedSnapshot\n .then(updatedSnapshot => {\n if (updatedSnapshot) {\n subscriber.next(updatedSnapshot);\n }\n })\n .finally(() => {\n if (!aborted) {\n subscriber.complete();\n }\n });\n\n return () => {\n aborted = true;\n };\n },\n );\n\n const promise = maybeUpdatedSnapshot.then(updatedSnapshot => {\n return updatedSnapshot ?? initialSnapshot;\n });\n\n return {\n snapshot: initialSnapshot,\n update$: observable,\n promise: promise,\n };\n }\n\n #getEntityForInitialRender(entityOrRef: Entity | string): {\n entity: Entity | undefined;\n kind: string;\n entityRef: string;\n needsLoad: boolean;\n } {\n // If we were given an entity in the first place, we use it for a single\n // pass of rendering and assume that it's up to date and not partial (i.e.\n // we expect that it wasn't fetched in such a way that the required fields\n // of the renderer were excluded)\n if (typeof entityOrRef !== 'string') {\n return {\n entity: entityOrRef,\n kind: entityOrRef.kind,\n entityRef: stringifyEntityRef(entityOrRef),\n needsLoad: false,\n };\n }\n\n const cached = this.#cache.get(entityOrRef);\n const cachedEntity: Entity | undefined = cached?.entity;\n const cacheNeedsUpdate =\n !cached || Date.now() - cached.updatedAt > this.#cacheTtlMs;\n const needsLoad =\n cacheNeedsUpdate &&\n this.#renderer.async !== false &&\n this.#loader !== undefined;\n\n return {\n entity: cachedEntity,\n kind: parseEntityRef(entityOrRef).kind,\n entityRef: entityOrRef,\n needsLoad,\n };\n }\n\n #createLoader(options: {\n catalogApi: CatalogApi;\n cacheTtl: HumanDuration;\n batchDelay: HumanDuration;\n renderer: DefaultEntityPresentationApiRenderer;\n }): DataLoader<string, Entity | undefined> {\n const cacheTtlMs = durationToMilliseconds(options.cacheTtl);\n const batchDelayMs = durationToMilliseconds(options.batchDelay);\n\n return new DataLoader(\n async (entityRefs: readonly string[]) => {\n const { items } = await options.catalogApi!.getEntitiesByRefs({\n entityRefs: entityRefs as string[],\n });\n\n const now = Date.now();\n entityRefs.forEach((entityRef, index) => {\n this.#cache.set(entityRef, {\n updatedAt: now,\n entity: items[index],\n });\n });\n\n return items;\n },\n {\n name: 'DefaultEntityPresentationApi',\n // This cache is the one that the data loader uses internally for\n // memoizing requests; essentially what it achieves is that multiple\n // requests for the same entity ref will be batched up into a single\n // request and then the resulting promises are held on to. We put an\n // expiring map here, which makes it so that it re-fetches data with the\n // expiry cadence of that map. Otherwise it would only fetch a given ref\n // once and then never try again. This cache does therefore not fulfill\n // the same purpose as the one that is in the root of the class.\n cacheMap: new ExpiryMap(cacheTtlMs),\n maxBatchSize: 100,\n batchScheduleFn: batchDelayMs\n ? cb => setTimeout(cb, batchDelayMs)\n : undefined,\n },\n );\n }\n\n #maybeFallbackIcon(\n renderedIcon: IconComponent | false | undefined,\n kind: string,\n ): IconComponent | false | undefined {\n if (renderedIcon) {\n return renderedIcon;\n } else if (renderedIcon === false) {\n return false;\n }\n\n return this.#kindIcons[kind.toLocaleLowerCase('en-US')];\n }\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,IAAA,MAAA,EAAA,WAAA,EAAA,OAAA,EAAA,UAAA,EAAA,SAAA,EAAA,0BAAA,EAAA,4BAAA,EAAA,aAAA,EAAA,eAAA,EAAA,kBAAA,EAAA,oBAAA,CAAA;AA4JO,MAAM,6BAAA,GAAN,MAAM,6BAA8D,CAAA;AAAA,EA+BjE,YAAY,OAA8C,EAAA;AAyIlE,IAAA,YAAA,CAAA,IAAA,EAAA,0BAAA,CAAA,CAAA;AAoCA,IAAA,YAAA,CAAA,IAAA,EAAA,aAAA,CAAA,CAAA;AA4CA,IAAA,YAAA,CAAA,IAAA,EAAA,kBAAA,CAAA,CAAA;AA/NA;AAAA;AAAA;AAAA;AAAA;AAAA,IAAA,YAAA,CAAA,IAAA,EAAS,MAAT,EAAA,KAAA,CAAA,CAAA,CAAA;AACA,IAAA,YAAA,CAAA,IAAA,EAAS,WAAT,EAAA,KAAA,CAAA,CAAA,CAAA;AACA,IAAA,YAAA,CAAA,IAAA,EAAS,OAAT,EAAA,KAAA,CAAA,CAAA,CAAA;AACA,IAAA,YAAA,CAAA,IAAA,EAAS,UAAT,EAAA,KAAA,CAAA,CAAA,CAAA;AACA;AAAA,IAAA,YAAA,CAAA,IAAA,EAAS,SAAT,EAAA,KAAA,CAAA,CAAA,CAAA;AAzLF,IAAA,IAAA,EAAA,EAAA,EAAA,EAAA,EAAA,EAAA,EAAA,CAAA;AA4LI,IAAM,MAAA,QAAA,GAAA,CAAW,EAAQ,GAAA,OAAA,CAAA,QAAA,KAAR,IAAoB,GAAA,EAAA,GAAA,iBAAA,CAAA;AACrC,IAAM,MAAA,UAAA,GAAA,CAAa,EAAQ,GAAA,OAAA,CAAA,UAAA,KAAR,IAAsB,GAAA,EAAA,GAAA,mBAAA,CAAA;AACzC,IAAM,MAAA,QAAA,GAAA,CAAW,aAAQ,QAAR,KAAA,IAAA,GAAA,EAAA,GAAoB,sBAAsB,EAAE,KAAA,EAAO,MAAM,CAAA,CAAA;AAE1E,IAAA,MAAM,YAA2C,EAAC,CAAA;AAClD,IAAO,MAAA,CAAA,OAAA,CAAQ,aAAa,CAAE,CAAA,OAAA,CAAQ,CAAC,CAAC,IAAA,EAAM,IAAI,CAAM,KAAA;AACtD,MAAA,SAAA,CAAU,IAAK,CAAA,iBAAA,CAAkB,OAAO,CAAC,CAAI,GAAA,IAAA,CAAA;AAAA,KAC9C,CAAA,CAAA;AACD,IAAA,MAAA,CAAO,OAAQ,CAAA,CAAA,EAAA,GAAA,OAAA,CAAQ,SAAR,KAAA,IAAA,GAAA,EAAA,GAAqB,EAAE,CAAE,CAAA,OAAA,CAAQ,CAAC,CAAC,IAAM,EAAA,IAAI,CAAM,KAAA;AAChE,MAAA,SAAA,CAAU,IAAK,CAAA,iBAAA,CAAkB,OAAO,CAAC,CAAI,GAAA,IAAA,CAAA;AAAA,KAC9C,CAAA,CAAA;AAED,IAAA,IAAI,SAAS,KAAO,EAAA;AAClB,MAAI,IAAA,CAAC,QAAQ,UAAY,EAAA;AACvB,QAAM,MAAA,IAAI,UAAU,CAA+C,6CAAA,CAAA,CAAA,CAAA;AAAA,OACrE;AACA,MAAK,YAAA,CAAA,IAAA,EAAA,OAAA,EAAU,eAAK,CAAA,IAAA,EAAA,aAAA,EAAA,eAAA,CAAA,CAAL,IAAmB,CAAA,IAAA,EAAA;AAAA,QAChC,QAAA;AAAA,QACA,UAAA;AAAA,QACA,QAAA;AAAA,QACA,YAAY,OAAQ,CAAA,UAAA;AAAA,OACtB,CAAA,CAAA,CAAA;AAAA,KACF;AAEA,IAAK,YAAA,CAAA,IAAA,EAAA,WAAA,EAAc,uBAAuB,QAAQ,CAAA,CAAA,CAAA;AAClD,IAAK,YAAA,CAAA,IAAA,EAAA,MAAA,sBAAa,GAAI,EAAA,CAAA,CAAA;AACtB,IAAA,YAAA,CAAA,IAAA,EAAK,UAAa,EAAA,SAAA,CAAA,CAAA;AAClB,IAAA,YAAA,CAAA,IAAA,EAAK,SAAY,EAAA,QAAA,CAAA,CAAA;AAAA,GACnB;AAAA;AAAA;AAAA;AAAA,EAxDA,OAAO,WAAqC,GAAA;AAC1C,IAAA,OAAO,IAAI,6BAA6B,CAAA;AAAA,MACtC,QAAU,EAAA,qBAAA,CAAsB,EAAE,KAAA,EAAO,OAAO,CAAA;AAAA,KACjD,CAAA,CAAA;AAAA,GACH;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAO,OACL,OACuB,EAAA;AACvB,IAAO,OAAA,IAAI,8BAA6B,OAAO,CAAA,CAAA;AAAA,GACjD;AAAA;AAAA,EA6CA,SAAA,CACE,aACA,OAIuB,EAAA;AACvB,IAAM,MAAA,EAAE,WAAW,IAAM,EAAA,MAAA,EAAQ,WAC/B,GAAA,eAAA,CAAA,IAAA,EAAK,0DAAL,IAAgC,CAAA,IAAA,EAAA,WAAA,CAAA,CAAA;AAGlC,IAAM,MAAA,MAAA,GAAS,CAAC,OAGqB,KAAA;AACnC,MAAA,MAAM,EAAE,QAAA,EAAa,GAAA,YAAA,CAAA,IAAA,EAAK,WAAU,MAAO,CAAA;AAAA,QACzC,SAAA;AAAA,QACA,SAAS,OAAQ,CAAA,OAAA;AAAA,QACjB,QAAQ,OAAQ,CAAA,MAAA;AAAA,QAChB,OAAA,EAAS,WAAW,EAAC;AAAA,OACtB,CAAA,CAAA;AACD,MAAO,OAAA;AAAA,QACL,GAAG,QAAA;AAAA,QACH,SAAA;AAAA,QACA,IAAM,EAAA,eAAA,CAAA,IAAA,EAAK,kBAAL,EAAA,oBAAA,CAAA,CAAA,IAAA,CAAA,IAAA,EAAwB,SAAS,IAAM,EAAA,IAAA,CAAA;AAAA,OAC/C,CAAA;AAAA,KACF,CAAA;AAGA,IAAI,IAAA,eAAA,CAAA;AACJ,IAAI,IAAA;AACF,MAAA,eAAA,GAAkB,MAAO,CAAA;AAAA,QACvB,OAAS,EAAA,SAAA;AAAA,QACT,MAAA;AAAA,OACD,CAAA,CAAA;AAAA,KACK,CAAA,MAAA;AAEN,MAAkB,eAAA,GAAA;AAAA,QAChB,YAAc,EAAA,SAAA;AAAA,QACd,SAAA;AAAA,OACF,CAAA;AAAA,KACF;AAEA,IAAA,IAAI,CAAC,SAAW,EAAA;AACd,MAAO,OAAA;AAAA,QACL,QAAU,EAAA,eAAA;AAAA,QACV,OAAA,EAAS,OAAQ,CAAA,OAAA,CAAQ,eAAe,CAAA;AAAA,OAC1C,CAAA;AAAA,KACF;AAGA,IAAA,MAAM,oBAAuB,GAAA,OAAA,CAAQ,OAAQ,EAAA,CAC1C,KAAK,MAAM;AA/QlB,MAAA,IAAA,EAAA,CAAA;AAgRQ,MAAO,OAAA,CAAA,EAAA,GAAA,YAAA,CAAA,IAAA,EAAK,OAAL,CAAA,KAAA,IAAA,GAAA,KAAA,CAAA,GAAA,EAAA,CAAc,IAAK,CAAA,SAAA,CAAA,CAAA;AAAA,KAC3B,CACA,CAAA,IAAA,CAAK,CAAa,SAAA,KAAA;AAIjB,MAAA,OAAO,MAAO,CAAA;AAAA,QACZ,OAAS,EAAA,KAAA;AAAA,QACT,QAAQ,SAAa,IAAA,IAAA,GAAA,SAAA,GAAA,MAAA;AAAA,OACtB,CAAA,CAAA;AAAA,KACF,CACA,CAAA,KAAA,CAAM,MAAM;AAKX,MAAO,OAAA,KAAA,CAAA,CAAA;AAAA,KACR,CAAA,CAAA;AAEH,IAAA,MAAM,aAAa,IAAI,cAAA;AAAA,MACrB,CAAc,UAAA,KAAA;AACZ,QAAA,IAAI,OAAU,GAAA,KAAA,CAAA;AAEd,QAAA,oBAAA,CACG,KAAK,CAAmB,eAAA,KAAA;AACvB,UAAA,IAAI,eAAiB,EAAA;AACnB,YAAA,UAAA,CAAW,KAAK,eAAe,CAAA,CAAA;AAAA,WACjC;AAAA,SACD,CACA,CAAA,OAAA,CAAQ,MAAM;AACb,UAAA,IAAI,CAAC,OAAS,EAAA;AACZ,YAAA,UAAA,CAAW,QAAS,EAAA,CAAA;AAAA,WACtB;AAAA,SACD,CAAA,CAAA;AAEH,QAAA,OAAO,MAAM;AACX,UAAU,OAAA,GAAA,IAAA,CAAA;AAAA,SACZ,CAAA;AAAA,OACF;AAAA,KACF,CAAA;AAEA,IAAM,MAAA,OAAA,GAAU,oBAAqB,CAAA,IAAA,CAAK,CAAmB,eAAA,KAAA;AAC3D,MAAA,OAAO,eAAmB,IAAA,IAAA,GAAA,eAAA,GAAA,eAAA,CAAA;AAAA,KAC3B,CAAA,CAAA;AAED,IAAO,OAAA;AAAA,MACL,QAAU,EAAA,eAAA;AAAA,MACV,OAAS,EAAA,UAAA;AAAA,MACT,OAAA;AAAA,KACF,CAAA;AAAA,GACF;AA8FF,CAAA,CAAA;AA3OW,MAAA,GAAA,IAAA,OAAA,EAAA,CAAA;AACA,WAAA,GAAA,IAAA,OAAA,EAAA,CAAA;AACA,OAAA,GAAA,IAAA,OAAA,EAAA,CAAA;AACA,UAAA,GAAA,IAAA,OAAA,EAAA,CAAA;AACA,SAAA,GAAA,IAAA,OAAA,EAAA,CAAA;AA2IT,0BAAA,GAAA,IAAA,OAAA,EAAA,CAAA;AAAA,4BAAA,GAA0B,SAAC,WAKzB,EAAA;AAKA,EAAI,IAAA,OAAO,gBAAgB,QAAU,EAAA;AACnC,IAAO,OAAA;AAAA,MACL,MAAQ,EAAA,WAAA;AAAA,MACR,MAAM,WAAY,CAAA,IAAA;AAAA,MAClB,SAAA,EAAW,mBAAmB,WAAW,CAAA;AAAA,MACzC,SAAW,EAAA,KAAA;AAAA,KACb,CAAA;AAAA,GACF;AAEA,EAAA,MAAM,MAAS,GAAA,YAAA,CAAA,IAAA,EAAK,MAAO,CAAA,CAAA,GAAA,CAAI,WAAW,CAAA,CAAA;AAC1C,EAAA,MAAM,eAAmC,MAAQ,IAAA,IAAA,GAAA,KAAA,CAAA,GAAA,MAAA,CAAA,MAAA,CAAA;AACjD,EAAM,MAAA,gBAAA,GACJ,CAAC,MAAU,IAAA,IAAA,CAAK,KAAQ,GAAA,MAAA,CAAO,YAAY,YAAK,CAAA,IAAA,EAAA,WAAA,CAAA,CAAA;AAClD,EAAA,MAAM,YACJ,gBACA,IAAA,YAAA,CAAA,IAAA,EAAK,WAAU,KAAU,KAAA,KAAA,IACzB,mBAAK,OAAY,CAAA,KAAA,KAAA,CAAA,CAAA;AAEnB,EAAO,OAAA;AAAA,IACL,MAAQ,EAAA,YAAA;AAAA,IACR,IAAA,EAAM,cAAe,CAAA,WAAW,CAAE,CAAA,IAAA;AAAA,IAClC,SAAW,EAAA,WAAA;AAAA,IACX,SAAA;AAAA,GACF,CAAA;AACF,CAAA,CAAA;AAEA,aAAA,GAAA,IAAA,OAAA,EAAA,CAAA;AAAA,eAAA,GAAa,SAAC,OAK6B,EAAA;AACzC,EAAM,MAAA,UAAA,GAAa,sBAAuB,CAAA,OAAA,CAAQ,QAAQ,CAAA,CAAA;AAC1D,EAAM,MAAA,YAAA,GAAe,sBAAuB,CAAA,OAAA,CAAQ,UAAU,CAAA,CAAA;AAE9D,EAAA,OAAO,IAAI,UAAA;AAAA,IACT,OAAO,UAAkC,KAAA;AACvC,MAAA,MAAM,EAAE,KAAM,EAAA,GAAI,MAAM,OAAA,CAAQ,WAAY,iBAAkB,CAAA;AAAA,QAC5D,UAAA;AAAA,OACD,CAAA,CAAA;AAED,MAAM,MAAA,GAAA,GAAM,KAAK,GAAI,EAAA,CAAA;AACrB,MAAW,UAAA,CAAA,OAAA,CAAQ,CAAC,SAAA,EAAW,KAAU,KAAA;AACvC,QAAK,YAAA,CAAA,IAAA,EAAA,MAAA,CAAA,CAAO,IAAI,SAAW,EAAA;AAAA,UACzB,SAAW,EAAA,GAAA;AAAA,UACX,MAAA,EAAQ,MAAM,KAAK,CAAA;AAAA,SACpB,CAAA,CAAA;AAAA,OACF,CAAA,CAAA;AAED,MAAO,OAAA,KAAA,CAAA;AAAA,KACT;AAAA,IACA;AAAA,MACE,IAAM,EAAA,8BAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MASN,QAAA,EAAU,IAAI,SAAA,CAAU,UAAU,CAAA;AAAA,MAClC,YAAc,EAAA,GAAA;AAAA,MACd,iBAAiB,YACb,GAAA,CAAA,EAAA,KAAM,UAAW,CAAA,EAAA,EAAI,YAAY,CACjC,GAAA,KAAA,CAAA;AAAA,KACN;AAAA,GACF,CAAA;AACF,CAAA,CAAA;AAEA,kBAAA,GAAA,IAAA,OAAA,EAAA,CAAA;AAAA,oBAAkB,GAAA,SAChB,cACA,IACmC,EAAA;AACnC,EAAA,IAAI,YAAc,EAAA;AAChB,IAAO,OAAA,YAAA,CAAA;AAAA,GACT,MAAA,IAAW,iBAAiB,KAAO,EAAA;AACjC,IAAO,OAAA,KAAA,CAAA;AAAA,GACT;AAEA,EAAA,OAAO,YAAK,CAAA,IAAA,EAAA,UAAA,CAAA,CAAW,IAAK,CAAA,iBAAA,CAAkB,OAAO,CAAC,CAAA,CAAA;AACxD,CAAA,CAAA;AAnQK,IAAM,4BAAN,GAAA;;;;"}
1
+ {"version":3,"file":"DefaultEntityPresentationApi.esm.js","sources":["../../../src/apis/EntityPresentationApi/DefaultEntityPresentationApi.ts"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n Entity,\n parseEntityRef,\n stringifyEntityRef,\n} from '@backstage/catalog-model';\nimport { IconComponent } from '@backstage/core-plugin-api';\nimport {\n CatalogApi,\n EntityPresentationApi,\n EntityRefPresentation,\n EntityRefPresentationSnapshot,\n} from '@backstage/plugin-catalog-react';\nimport { HumanDuration, durationToMilliseconds } from '@backstage/types';\nimport DataLoader from 'dataloader';\nimport ExpiryMap from 'expiry-map';\nimport ObservableImpl from 'zen-observable';\nimport {\n DEFAULT_BATCH_DELAY,\n DEFAULT_CACHE_TTL,\n DEFAULT_ICONS,\n createDefaultRenderer,\n} from './defaults';\n\n/**\n * A custom renderer for the {@link DefaultEntityPresentationApi}.\n *\n * @public\n */\nexport interface DefaultEntityPresentationApiRenderer {\n /**\n * Whether to request the entity from the catalog API asynchronously.\n *\n * @remarks\n *\n * If this is set to true, entity data will be streamed in from the catalog\n * whenever needed, and the render function may be called more than once:\n * first when no entity data existed (or with old cached data), and then again\n * at a later point when data is loaded from the catalog that proved to be\n * different from the old one.\n *\n * @defaultValue true\n */\n async?: boolean;\n\n /**\n * The actual render function.\n *\n * @remarks\n *\n * This function may be called multiple times.\n *\n * The loading flag signals that the framework MAY be trying to load more\n * entity data from the catalog and call the render function again, if it\n * succeeds. In some cases you may want to render a loading state in that\n * case.\n *\n * The entity may or may not be given. If the caller of the presentation API\n * did present an entity upfront, then that's what will be passed in here.\n * Otherwise, it may be a server-side entity that either comes from a local\n * cache or directly from the server.\n *\n * In either case, the renderer should return a presentation that is the most\n * useful possible for the end user, given the data that is available.\n */\n render: (options: {\n entityRef: string;\n loading: boolean;\n entity: Entity | undefined;\n context: {\n defaultKind?: string;\n defaultNamespace?: string;\n };\n }) => {\n snapshot: Omit<EntityRefPresentationSnapshot, 'entityRef'>;\n };\n}\n\n/**\n * Options for the {@link DefaultEntityPresentationApi}.\n *\n * @public\n */\nexport interface DefaultEntityPresentationApiOptions {\n /**\n * The catalog API to use. If you want to use any asynchronous features, you\n * must supply one.\n */\n catalogApi?: CatalogApi;\n\n /**\n * When to expire entities that have been loaded from the catalog API and\n * cached for a while.\n *\n * @defaultValue 10 seconds\n * @remarks\n *\n * The higher this value, the lower the load on the catalog API, but also the\n * higher the risk of users seeing stale data.\n */\n cacheTtl?: HumanDuration;\n\n /**\n * For how long to wait before sending a batch of entity references to the\n * catalog API.\n *\n * @defaultValue 50 milliseconds\n * @remarks\n *\n * The higher this value, the greater the chance of batching up requests from\n * across a page, but also the longer the lag time before displaying accurate\n * information.\n */\n batchDelay?: HumanDuration;\n\n /**\n * A mapping from kinds to icons.\n *\n * @remarks\n *\n * The keys are kinds (case insensitive) that map to icon values to represent\n * kinds by. These are merged with the default set of icons.\n */\n kindIcons?: Record<string, IconComponent>;\n\n /**\n * A custom renderer, if any.\n */\n renderer?: DefaultEntityPresentationApiRenderer;\n}\n\ninterface CacheEntry {\n updatedAt: number;\n entity: Entity | undefined;\n}\n\n/**\n * Default implementation of the {@link @backstage/plugin-catalog-react#EntityPresentationApi}.\n *\n * @public\n */\nexport class DefaultEntityPresentationApi implements EntityPresentationApi {\n /**\n * Creates a new presentation API that does not reach out to the catalog.\n */\n static createLocal(): EntityPresentationApi {\n return new DefaultEntityPresentationApi({\n renderer: createDefaultRenderer({ async: false }),\n });\n }\n\n /**\n * Creates a new presentation API that calls out to the catalog as needed to\n * get additional information about entities.\n */\n static create(\n options: DefaultEntityPresentationApiOptions,\n ): EntityPresentationApi {\n return new DefaultEntityPresentationApi(options);\n }\n\n // This cache holds on to all entity data ever loaded, no matter how old. Each\n // entry is tagged with a timestamp of when it was inserted. We use this map\n // to be able to always render SOME data even though the information is old.\n // Entities change very rarely, so it's likely that the rendered information\n // was perfectly fine in the first place.\n readonly #cache: Map<string, CacheEntry>;\n readonly #cacheTtlMs: number;\n readonly #loader: DataLoader<string, Entity | undefined> | undefined;\n readonly #kindIcons: Record<string, IconComponent>; // lowercased kinds\n readonly #renderer: DefaultEntityPresentationApiRenderer;\n\n private constructor(options: DefaultEntityPresentationApiOptions) {\n const cacheTtl = options.cacheTtl ?? DEFAULT_CACHE_TTL;\n const batchDelay = options.batchDelay ?? DEFAULT_BATCH_DELAY;\n const renderer = options.renderer ?? createDefaultRenderer({ async: true });\n\n const kindIcons: Record<string, IconComponent> = {};\n Object.entries(DEFAULT_ICONS).forEach(([kind, icon]) => {\n kindIcons[kind.toLocaleLowerCase('en-US')] = icon;\n });\n Object.entries(options.kindIcons ?? {}).forEach(([kind, icon]) => {\n kindIcons[kind.toLocaleLowerCase('en-US')] = icon;\n });\n\n if (renderer.async) {\n if (!options.catalogApi) {\n throw new TypeError(`Asynchronous rendering requires a catalog API`);\n }\n this.#loader = this.#createLoader({\n cacheTtl,\n batchDelay,\n renderer,\n catalogApi: options.catalogApi,\n });\n }\n\n this.#cacheTtlMs = durationToMilliseconds(cacheTtl);\n this.#cache = new Map();\n this.#kindIcons = kindIcons;\n this.#renderer = renderer;\n }\n\n /** {@inheritdoc @backstage/plugin-catalog-react#EntityPresentationApi.forEntity} */\n forEntity(\n entityOrRef: Entity | string,\n context?: {\n defaultKind?: string;\n defaultNamespace?: string;\n },\n ): EntityRefPresentation {\n const { entityRef, kind, entity, needsLoad } =\n this.#getEntityForInitialRender(entityOrRef);\n\n // Make a wrapping helper for rendering\n const render = (options: {\n loading: boolean;\n entity?: Entity;\n }): EntityRefPresentationSnapshot => {\n const { snapshot } = this.#renderer.render({\n entityRef: entityRef,\n loading: options.loading,\n entity: options.entity,\n context: context || {},\n });\n return {\n ...snapshot,\n entityRef: entityRef,\n Icon: this.#maybeFallbackIcon(snapshot.Icon, kind),\n };\n };\n\n // First the initial render\n let initialSnapshot: EntityRefPresentationSnapshot;\n try {\n initialSnapshot = render({\n loading: needsLoad,\n entity: entity,\n });\n } catch {\n // This is what gets presented if the renderer throws an error\n initialSnapshot = {\n primaryTitle: entityRef,\n entityRef: entityRef,\n };\n }\n\n if (!needsLoad) {\n return {\n snapshot: initialSnapshot,\n promise: Promise.resolve(initialSnapshot),\n };\n }\n\n // Load the entity and render it\n const maybeUpdatedSnapshot = Promise.resolve()\n .then(() => {\n return this.#loader?.load(entityRef);\n })\n .then(newEntity => {\n // We re-render no matter if we get back a new entity or the old\n // one or nothing, because of the now false loading state - in\n // case the renderer outputs different data depending on that\n return render({\n loading: false,\n entity: newEntity ?? entity,\n });\n })\n .catch(() => {\n // Intentionally ignored - we do not propagate errors to the\n // caller here. The presentation API should be error free and\n // always return SOMETHING that makes sense to render, and we have\n // already ensured above that the initial snapshot was that.\n return undefined;\n });\n\n const observable = new ObservableImpl<EntityRefPresentationSnapshot>(\n subscriber => {\n let aborted = false;\n\n maybeUpdatedSnapshot\n .then(updatedSnapshot => {\n if (updatedSnapshot) {\n subscriber.next(updatedSnapshot);\n }\n })\n .finally(() => {\n if (!aborted) {\n subscriber.complete();\n }\n });\n\n return () => {\n aborted = true;\n };\n },\n );\n\n const promise = maybeUpdatedSnapshot.then(updatedSnapshot => {\n return updatedSnapshot ?? initialSnapshot;\n });\n\n return {\n snapshot: initialSnapshot,\n update$: observable,\n promise: promise,\n };\n }\n\n #getEntityForInitialRender(entityOrRef: Entity | string): {\n entity: Entity | undefined;\n kind: string;\n entityRef: string;\n needsLoad: boolean;\n } {\n // If we were given an entity in the first place, we use it for a single\n // pass of rendering and assume that it's up to date and not partial (i.e.\n // we expect that it wasn't fetched in such a way that the required fields\n // of the renderer were excluded)\n if (typeof entityOrRef !== 'string') {\n return {\n entity: entityOrRef,\n kind: entityOrRef.kind,\n entityRef: stringifyEntityRef(entityOrRef),\n needsLoad: false,\n };\n }\n\n const cached = this.#cache.get(entityOrRef);\n const cachedEntity: Entity | undefined = cached?.entity;\n const cacheNeedsUpdate =\n !cached || Date.now() - cached.updatedAt > this.#cacheTtlMs;\n const needsLoad =\n cacheNeedsUpdate &&\n this.#renderer.async !== false &&\n this.#loader !== undefined;\n\n return {\n entity: cachedEntity,\n kind: parseEntityRef(entityOrRef).kind,\n entityRef: entityOrRef,\n needsLoad,\n };\n }\n\n #createLoader(options: {\n catalogApi: CatalogApi;\n cacheTtl: HumanDuration;\n batchDelay: HumanDuration;\n renderer: DefaultEntityPresentationApiRenderer;\n }): DataLoader<string, Entity | undefined> {\n const cacheTtlMs = durationToMilliseconds(options.cacheTtl);\n const batchDelayMs = durationToMilliseconds(options.batchDelay);\n\n return new DataLoader(\n async (entityRefs: readonly string[]) => {\n const { items } = await options.catalogApi!.getEntitiesByRefs({\n entityRefs: entityRefs as string[],\n });\n\n const now = Date.now();\n entityRefs.forEach((entityRef, index) => {\n this.#cache.set(entityRef, {\n updatedAt: now,\n entity: items[index],\n });\n });\n\n return items;\n },\n {\n name: 'DefaultEntityPresentationApi',\n // This cache is the one that the data loader uses internally for\n // memoizing requests; essentially what it achieves is that multiple\n // requests for the same entity ref will be batched up into a single\n // request and then the resulting promises are held on to. We put an\n // expiring map here, which makes it so that it re-fetches data with the\n // expiry cadence of that map. Otherwise it would only fetch a given ref\n // once and then never try again. This cache does therefore not fulfill\n // the same purpose as the one that is in the root of the class.\n cacheMap: new ExpiryMap(cacheTtlMs),\n maxBatchSize: 100,\n batchScheduleFn: batchDelayMs\n ? cb => setTimeout(cb, batchDelayMs)\n : undefined,\n },\n );\n }\n\n #maybeFallbackIcon(\n renderedIcon: IconComponent | false | undefined,\n kind: string,\n ): IconComponent | false | undefined {\n if (renderedIcon) {\n return renderedIcon;\n } else if (renderedIcon === false) {\n return false;\n }\n\n return this.#kindIcons[kind.toLocaleLowerCase('en-US')];\n }\n}\n"],"names":[],"mappings":"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"}
@@ -1,34 +1,18 @@
1
1
  import ObservableImpl from 'zen-observable';
2
2
  import { performMigrationToTheNewBucket } from './migration.esm.js';
3
3
 
4
- var __defProp = Object.defineProperty;
5
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
6
- var __publicField = (obj, key, value) => {
7
- __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
8
- return value;
9
- };
10
4
  class DefaultStarredEntitiesApi {
5
+ settingsStore;
6
+ starredEntities;
11
7
  constructor(opts) {
12
- __publicField(this, "settingsStore");
13
- __publicField(this, "starredEntities");
14
- __publicField(this, "subscribers", /* @__PURE__ */ new Set());
15
- __publicField(this, "observable", new ObservableImpl((subscriber) => {
16
- subscriber.next(new Set(this.starredEntities));
17
- this.subscribers.add(subscriber);
18
- return () => {
19
- this.subscribers.delete(subscriber);
20
- };
21
- }));
22
- var _a;
23
8
  performMigrationToTheNewBucket(opts).then();
24
9
  this.settingsStore = opts.storageApi.forBucket("starredEntities");
25
10
  this.starredEntities = new Set(
26
- (_a = this.settingsStore.snapshot("entityRefs").value) != null ? _a : []
11
+ this.settingsStore.snapshot("entityRefs").value ?? []
27
12
  );
28
13
  this.settingsStore.observe$("entityRefs").subscribe({
29
14
  next: (next) => {
30
- var _a2;
31
- this.starredEntities = new Set((_a2 = next.value) != null ? _a2 : []);
15
+ this.starredEntities = new Set(next.value ?? []);
32
16
  this.notifyChanges();
33
17
  }
34
18
  });
@@ -47,6 +31,14 @@ class DefaultStarredEntitiesApi {
47
31
  starredEntitie$() {
48
32
  return this.observable;
49
33
  }
34
+ subscribers = /* @__PURE__ */ new Set();
35
+ observable = new ObservableImpl((subscriber) => {
36
+ subscriber.next(new Set(this.starredEntities));
37
+ this.subscribers.add(subscriber);
38
+ return () => {
39
+ this.subscribers.delete(subscriber);
40
+ };
41
+ });
50
42
  notifyChanges() {
51
43
  for (const subscription of this.subscribers) {
52
44
  subscription.next(new Set(this.starredEntities));